summaryrefslogtreecommitdiff
path: root/nsswitch
diff options
context:
space:
mode:
authorVolker Lendecke <vl@samba.org>2011-01-10 17:25:00 +0100
committerVolker Lendecke <vlendec@samba.org>2011-01-19 08:40:28 +0100
commit7f87d58900c2adf4d79f4dc7859a96f1d00d819b (patch)
treeadd63dc353d4026745f7ffb3c4fcbf8473737e56 /nsswitch
parent1b439960224cb97e328204cdf79654f565043679 (diff)
downloadsamba-7f87d58900c2adf4d79f4dc7859a96f1d00d819b.tar.gz
s3: Add wbinfo --dc-info
wbinfo --dc-info prints the current DC name and IP address. This helps diagnosing problems that might happen when a later wbinfo --ping-dc fails. This patch started out by using the SAF and NBT cache entires, but those are relatively short-lived. So I decided to invent a new gencache entry with a very long timeout. We need to go via the gencache because when for some reason a winbind child process is stuck, we can't query it for the current DC it's connected to. This must eventually go away again when we have a fully async winbind. Autobuild-User: Volker Lendecke <vlendec@samba.org> Autobuild-Date: Wed Jan 19 08:40:28 CET 2011 on sn-devel-104
Diffstat (limited to 'nsswitch')
-rw-r--r--nsswitch/libwbclient/wbc_util.c86
-rw-r--r--nsswitch/libwbclient/wbclient.h15
-rw-r--r--nsswitch/wbinfo.c33
-rw-r--r--nsswitch/winbind_struct_protocol.h4
4 files changed, 136 insertions, 2 deletions
diff --git a/nsswitch/libwbclient/wbc_util.c b/nsswitch/libwbclient/wbc_util.c
index e2e657a903..d2783f30d2 100644
--- a/nsswitch/libwbclient/wbc_util.c
+++ b/nsswitch/libwbclient/wbc_util.c
@@ -203,6 +203,92 @@ wbcErr wbcDomainInfo(const char *domain, struct wbcDomainInfo **dinfo)
return wbc_status;
}
+/* Get the list of current DCs */
+wbcErr wbcDcInfo(const char *domain, size_t *num_dcs,
+ const char ***dc_names, const char ***dc_ips)
+{
+ struct winbindd_request request;
+ struct winbindd_response response;
+ const char **names = NULL;
+ const char **ips = NULL;
+ wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
+ size_t extra_len;
+ int i;
+ char *p;
+
+ /* Initialise request */
+
+ ZERO_STRUCT(request);
+ ZERO_STRUCT(response);
+
+ if (domain != NULL) {
+ strncpy(request.domain_name, domain,
+ sizeof(request.domain_name) - 1);
+ }
+
+ wbc_status = wbcRequestResponse(WINBINDD_DC_INFO,
+ &request, &response);
+ BAIL_ON_WBC_ERROR(wbc_status);
+
+ names = wbcAllocateStringArray(response.data.num_entries);
+ BAIL_ON_PTR_ERROR(names, wbc_status);
+
+ ips = wbcAllocateStringArray(response.data.num_entries);
+ BAIL_ON_PTR_ERROR(names, wbc_status);
+
+ wbc_status = WBC_ERR_INVALID_RESPONSE;
+
+ p = (char *)response.extra_data.data;
+
+ if (response.length < (sizeof(struct winbindd_response)+1)) {
+ goto done;
+ }
+
+ extra_len = response.length - sizeof(struct winbindd_response);
+
+ if (p[extra_len-1] != '\0') {
+ goto done;
+ }
+
+ for (i=0; i<response.data.num_entries; i++) {
+ char *q;
+
+ q = strchr(p, '\n');
+ if (q == NULL) {
+ goto done;
+ }
+ names[i] = strndup(p, q-p);
+ BAIL_ON_PTR_ERROR(names[i], wbc_status);
+ p = q+1;
+
+ q = strchr(p, '\n');
+ if (q == NULL) {
+ goto done;
+ }
+ ips[i] = strndup(p, q-p);
+ BAIL_ON_PTR_ERROR(ips[i], wbc_status);
+ p = q+1;
+ }
+ if (p[0] != '\0') {
+ goto done;
+ }
+
+ wbc_status = WBC_ERR_SUCCESS;
+done:
+ if (response.extra_data.data)
+ free(response.extra_data.data);
+
+ if (WBC_ERROR_IS_OK(wbc_status)) {
+ *num_dcs = response.data.num_entries;
+ *dc_names = names;
+ names = NULL;
+ *dc_ips = ips;
+ ips = NULL;
+ }
+ wbcFreeMemory(names);
+ wbcFreeMemory(ips);
+ return wbc_status;
+}
/* Resolve a NetbiosName via WINS */
wbcErr wbcResolveWinsByName(const char *name, char **ip)
diff --git a/nsswitch/libwbclient/wbclient.h b/nsswitch/libwbclient/wbclient.h
index e2f989094a..39670ab6ed 100644
--- a/nsswitch/libwbclient/wbclient.h
+++ b/nsswitch/libwbclient/wbclient.h
@@ -192,7 +192,6 @@ struct wbcDomainInfo {
#define WBC_DOMINFO_TRUSTTYPE_IN_FOREST 0x00000002
#define WBC_DOMINFO_TRUSTTYPE_EXTERNAL 0x00000003
-
/**
* @brief Auth User Parameters
**/
@@ -992,6 +991,20 @@ wbcErr wbcDomainInfo(const char *domain,
struct wbcDomainInfo **dinfo);
/**
+ * @brief Lookup the currently contacted DCs
+ *
+ * @param domain The domain to query
+ *
+ * @param num_dcs Number of DCs currently known
+ * @param dc_names Names of the currently known DCs
+ * @param dc_ips IP addresses of the currently known DCs
+ *
+ * @return #wbcErr
+ **/
+wbcErr wbcDcInfo(const char *domain, size_t *num_dcs,
+ const char ***dc_names, const char ***dc_ips);
+
+/**
* @brief Enumerate the domain trusts known by Winbind
*
* @param **domains Pointer to the allocated domain list array
diff --git a/nsswitch/wbinfo.c b/nsswitch/wbinfo.c
index 6ff66f8f3c..caa37f3c9e 100644
--- a/nsswitch/wbinfo.c
+++ b/nsswitch/wbinfo.c
@@ -787,6 +787,31 @@ static bool wbinfo_check_secret(const char *domain)
return true;
}
+/* Find the currently connected DCs */
+
+static bool wbinfo_dc_info(const char *domain_name)
+{
+ wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
+ size_t i, num_dcs;
+ const char **dc_names, **dc_ips;
+
+ wbc_status = wbcDcInfo(domain_name, &num_dcs,
+ &dc_names, &dc_ips);
+ if (!WBC_ERROR_IS_OK(wbc_status)) {
+ printf("Could not find dc info %s\n",
+ domain_name ? domain_name : "our domain");
+ return false;
+ }
+
+ for (i=0; i<num_dcs; i++) {
+ printf("%s (%s)\n", dc_names[i], dc_ips[i]);
+ }
+ wbcFreeMemory(dc_names);
+ wbcFreeMemory(dc_ips);
+
+ return true;
+}
+
/* Change trust account password */
static bool wbinfo_change_secret(const char *domain)
@@ -1921,6 +1946,7 @@ enum {
OPT_SEQUENCE,
OPT_GETDCNAME,
OPT_DSGETDCNAME,
+ OPT_DC_INFO,
OPT_USERDOMGROUPS,
OPT_SIDALIASES,
OPT_USERSIDS,
@@ -2030,6 +2056,8 @@ int main(int argc, char **argv, char **envp)
{ "getdcname", 0, POPT_ARG_STRING, &string_arg, OPT_GETDCNAME,
"Get a DC name for a foreign domain", "domainname" },
{ "dsgetdcname", 0, POPT_ARG_STRING, &string_arg, OPT_DSGETDCNAME, "Find a DC for a domain", "domainname" },
+ { "dc-info", 0, POPT_ARG_STRING, &string_arg, OPT_DC_INFO,
+ "Find the currently known DCs", "domainname" },
{ "get-auth-user", 0, POPT_ARG_NONE, NULL, OPT_GET_AUTH_USER, "Retrieve user and password used by winbindd (root only)", NULL },
{ "ping", 'p', POPT_ARG_NONE, 0, 'p', "Ping winbindd to see if it is alive" },
{ "domain", 0, POPT_ARG_STRING, &opt_domain_name, OPT_DOMAIN_NAME, "Define to the domain to restrict operation", "domain" },
@@ -2443,6 +2471,11 @@ int main(int argc, char **argv, char **envp)
goto done;
}
break;
+ case OPT_DC_INFO:
+ if (!wbinfo_dc_info(string_arg)) {
+ goto done;
+ }
+ break;
case OPT_SEPARATOR: {
const char sep = winbind_separator();
if ( !sep ) {
diff --git a/nsswitch/winbind_struct_protocol.h b/nsswitch/winbind_struct_protocol.h
index 537754f688..9304702fa0 100644
--- a/nsswitch/winbind_struct_protocol.h
+++ b/nsswitch/winbind_struct_protocol.h
@@ -54,8 +54,9 @@ typedef char fstring[FSTRING_LEN];
* 25: removed WINBINDD_SET_HWM
* removed WINBINDD_SET_MAPPING
* removed WINBINDD_REMOVE_MAPPING
+ * 26: added WINBINDD_DC_INFO
*/
-#define WINBIND_INTERFACE_VERSION 25
+#define WINBIND_INTERFACE_VERSION 26
/* Have to deal with time_t being 4 or 8 bytes due to structure alignment.
On a 64bit Linux box, we have to support a constant structure size
@@ -132,6 +133,7 @@ enum winbindd_cmd {
struct winbindd_domain */
WINBINDD_GETDCNAME, /* Issue a GetDCName Request */
WINBINDD_DSGETDCNAME, /* Issue a DsGetDCName Request */
+ WINBINDD_DC_INFO, /* Which DC are we connected to? */
WINBINDD_SHOW_SEQUENCE, /* display sequence numbers of domains */