summaryrefslogtreecommitdiff
path: root/source3/winbindd
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 /source3/winbindd
parent1b439960224cb97e328204cdf79654f565043679 (diff)
downloadsamba-7f87d58900c2adf4d79f4dc7859a96f1d00d819b.tar.gz
samba-7f87d58900c2adf4d79f4dc7859a96f1d00d819b.tar.bz2
samba-7f87d58900c2adf4d79f4dc7859a96f1d00d819b.zip
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 'source3/winbindd')
-rw-r--r--source3/winbindd/winbindd.c1
-rw-r--r--source3/winbindd/winbindd_cm.c93
-rw-r--r--source3/winbindd/winbindd_misc.c50
-rw-r--r--source3/winbindd/winbindd_proto.h4
4 files changed, 148 insertions, 0 deletions
diff --git a/source3/winbindd/winbindd.c b/source3/winbindd/winbindd.c
index e5aeca6830..8f4a205db5 100644
--- a/source3/winbindd/winbindd.c
+++ b/source3/winbindd/winbindd.c
@@ -442,6 +442,7 @@ static struct winbindd_dispatch_table {
"INTERFACE_VERSION" },
{ WINBINDD_DOMAIN_NAME, winbindd_domain_name, "DOMAIN_NAME" },
{ WINBINDD_DOMAIN_INFO, winbindd_domain_info, "DOMAIN_INFO" },
+ { WINBINDD_DC_INFO, winbindd_dc_info, "DC_INFO" },
{ WINBINDD_NETBIOS_NAME, winbindd_netbios_name, "NETBIOS_NAME" },
{ WINBINDD_PRIV_PIPE_DIR, winbindd_priv_pipe_dir,
"WINBINDD_PRIV_PIPE_DIR" },
diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c
index b36f79fb3c..8e29b7d584 100644
--- a/source3/winbindd/winbindd_cm.c
+++ b/source3/winbindd/winbindd_cm.c
@@ -1419,6 +1419,88 @@ static bool find_new_dc(TALLOC_CTX *mem_ctx,
goto again;
}
+static char *current_dc_key(TALLOC_CTX *mem_ctx, const char *domain_name)
+{
+ return talloc_asprintf_strupper_m(mem_ctx, "CURRENT_DCNAME/%s",
+ domain_name);
+}
+
+static void store_current_dc_in_gencache(const char *domain_name,
+ const char *dc_name,
+ struct cli_state *cli)
+{
+ char addr[INET6_ADDRSTRLEN];
+ char *key, *value;
+
+ if (cli == NULL) {
+ return;
+ }
+ if (cli->fd == -1) {
+ return;
+ }
+ get_peer_addr(cli->fd, addr, sizeof(addr));
+
+ key = current_dc_key(talloc_tos(), domain_name);
+ if (key == NULL) {
+ goto done;
+ }
+
+ value = talloc_asprintf(talloc_tos(), "%s %s", addr, dc_name);
+ if (value == NULL) {
+ goto done;
+ }
+
+ gencache_set(key, value, 0x7ffffffff);
+done:
+ TALLOC_FREE(value);
+ TALLOC_FREE(key);
+}
+
+bool fetch_current_dc_from_gencache(TALLOC_CTX *mem_ctx,
+ const char *domain_name,
+ char **p_dc_name, char **p_dc_ip)
+{
+ char *key, *value, *p;
+ bool ret = false;
+ char *dc_name = NULL;
+ char *dc_ip = NULL;
+
+ key = current_dc_key(talloc_tos(), domain_name);
+ if (key == NULL) {
+ goto done;
+ }
+ if (!gencache_get(key, &value, NULL)) {
+ goto done;
+ }
+ p = strchr(value, ' ');
+ if (p == NULL) {
+ goto done;
+ }
+ dc_ip = talloc_strndup(mem_ctx, value, p - value);
+ if (dc_ip == NULL) {
+ goto done;
+ }
+ dc_name = talloc_strdup(mem_ctx, p+1);
+ if (dc_name == NULL) {
+ goto done;
+ }
+
+ if (p_dc_ip != NULL) {
+ *p_dc_ip = dc_ip;
+ dc_ip = NULL;
+ }
+ if (p_dc_name != NULL) {
+ *p_dc_name = dc_name;
+ dc_name = NULL;
+ }
+ ret = true;
+done:
+ TALLOC_FREE(dc_name);
+ TALLOC_FREE(dc_ip);
+ TALLOC_FREE(key);
+ return ret;
+}
+
static NTSTATUS cm_open_connection(struct winbindd_domain *domain,
struct winbindd_cm_conn *new_conn)
{
@@ -1520,6 +1602,17 @@ static NTSTATUS cm_open_connection(struct winbindd_domain *domain,
set_global_winbindd_state_online();
}
set_domain_online(domain);
+
+ /*
+ * Much as I hate global state, this seems to be the point
+ * where we can be certain that we have a proper connection to
+ * a DC. wbinfo --dc-info needs that information, store it in
+ * gencache with a looong timeout. This will need revisiting
+ * once we start to connect to multiple DCs, wbcDcInfo is
+ * already prepared for that.
+ */
+ store_current_dc_in_gencache(domain->name, domain->dcname,
+ new_conn->cli);
} else {
/* Ensure we setup the retry handler. */
set_domain_offline(domain);
diff --git a/source3/winbindd/winbindd_misc.c b/source3/winbindd/winbindd_misc.c
index caf213b551..42ecea2aad 100644
--- a/source3/winbindd/winbindd_misc.c
+++ b/source3/winbindd/winbindd_misc.c
@@ -314,6 +314,56 @@ static void domain_info_done(struct tevent_req *req)
request_ok(state->cli);
}
+void winbindd_dc_info(struct winbindd_cli_state *cli)
+{
+ struct winbindd_domain *domain;
+ char *dc_name, *dc_ip;
+
+ cli->request->domain_name[sizeof(cli->request->domain_name-1)] = '\0';
+
+ DEBUG(3, ("[%5lu]: domain_info [%s]\n", (unsigned long)cli->pid,
+ cli->request->domain_name));
+
+ if (cli->request->domain_name[0] != '\0') {
+ domain = find_domain_from_name_noinit(
+ cli->request->domain_name);
+ DEBUG(10, ("Could not find domain %s\n",
+ cli->request->domain_name));
+ if (domain == NULL) {
+ request_error(cli);
+ return;
+ }
+ } else {
+ domain = find_our_domain();
+ }
+
+ if (!fetch_current_dc_from_gencache(
+ talloc_tos(), domain->name, &dc_name, &dc_ip)) {
+ DEBUG(10, ("fetch_current_dc_from_gencache(%s) failed\n",
+ domain->name));
+ request_error(cli);
+ return;
+ }
+
+ cli->response->data.num_entries = 1;
+ cli->response->extra_data.data = talloc_asprintf(
+ cli->mem_ctx, "%s\n%s\n", dc_name, dc_ip);
+
+ TALLOC_FREE(dc_name);
+ TALLOC_FREE(dc_ip);
+
+ if (cli->response->extra_data.data == NULL) {
+ request_error(cli);
+ return;
+ }
+
+ /* must add one to length to copy the 0 for string termination */
+ cli->response->length +=
+ strlen((char *)cli->response->extra_data.data) + 1;
+
+ request_ok(cli);
+}
+
/* List various tidbits of information */
void winbindd_info(struct winbindd_cli_state *state)
diff --git a/source3/winbindd/winbindd_proto.h b/source3/winbindd/winbindd_proto.h
index dc563c9dac..5cb6c4c155 100644
--- a/source3/winbindd/winbindd_proto.h
+++ b/source3/winbindd/winbindd_proto.h
@@ -170,6 +170,9 @@ NTSTATUS cm_connect_lsa_tcp(struct winbindd_domain *domain,
struct rpc_pipe_client **cli);
NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain,
struct rpc_pipe_client **cli);
+bool fetch_current_dc_from_gencache(TALLOC_CTX *mem_ctx,
+ const char *domain_name,
+ char **p_dc_name, char **p_dc_ip);
/* The following definitions come from winbindd/winbindd_cred_cache.c */
@@ -322,6 +325,7 @@ enum winbindd_result winbindd_dual_list_trusted_domains(struct winbindd_domain *
struct winbindd_cli_state *state);
void winbindd_show_sequence(struct winbindd_cli_state *state);
void winbindd_domain_info(struct winbindd_cli_state *state);
+void winbindd_dc_info(struct winbindd_cli_state *state);
void winbindd_ping(struct winbindd_cli_state *state);
void winbindd_info(struct winbindd_cli_state *state);
void winbindd_interface_version(struct winbindd_cli_state *state);