summaryrefslogtreecommitdiffstats
path: root/source/nsswitch/winbindd_cm.c
diff options
context:
space:
mode:
authorGerald Carter <jerry@samba.org>2002-10-09 19:50:33 +0000
committerGerald Carter <jerry@samba.org>2002-10-09 19:50:33 +0000
commit0849906f13deb460b3f897934a1d63374e35a548 (patch)
tree90ce8f67d81fb1aeb1d79bfc3ab0cc2b4162275c /source/nsswitch/winbindd_cm.c
parentd7ae4079e7f8b75064dbf84c0989208c2d0b4674 (diff)
downloadsamba-0849906f13deb460b3f897934a1d63374e35a548.tar.gz
samba-0849906f13deb460b3f897934a1d63374e35a548.tar.xz
samba-0849906f13deb460b3f897934a1d63374e35a548.zip
sync with SAMBA_2_2 for 2.2.6rc1
Diffstat (limited to 'source/nsswitch/winbindd_cm.c')
-rw-r--r--source/nsswitch/winbindd_cm.c183
1 files changed, 95 insertions, 88 deletions
diff --git a/source/nsswitch/winbindd_cm.c b/source/nsswitch/winbindd_cm.c
index 7024592f5b7..fb406adcf7c 100644
--- a/source/nsswitch/winbindd_cm.c
+++ b/source/nsswitch/winbindd_cm.c
@@ -74,85 +74,45 @@ struct winbindd_cm_conn {
static struct winbindd_cm_conn *cm_conns = NULL;
-/* Get a domain controller name. Cache positive and negative lookups so we
- don't go to the network too often when something is badly broken. */
-
-#define GET_DC_NAME_CACHE_TIMEOUT 30 /* Seconds between dc lookups */
-
-struct get_dc_name_cache {
- fstring domain_name;
- fstring srv_name;
- time_t lookup_time;
- struct get_dc_name_cache *prev, *next;
-};
+/* Get a domain controller name */
static BOOL cm_get_dc_name(const char *domain, fstring srv_name, struct in_addr *ip_out)
{
- static struct get_dc_name_cache *get_dc_name_cache;
- struct get_dc_name_cache *dcc;
- struct in_addr *ip_list, dc_ip;
+ struct in_addr *ip_list = NULL, dc_ip, exclude_ip;
int count, i;
- /* Check the cache for previous lookups */
-
- for (dcc = get_dc_name_cache; dcc; dcc = dcc->next) {
-
- if (!strequal(domain, dcc->domain_name))
- continue; /* Not our domain */
-
- if ((time(NULL) - dcc->lookup_time) >
- GET_DC_NAME_CACHE_TIMEOUT) {
-
- /* Cache entry has expired, delete it */
-
- DEBUG(10, ("get_dc_name_cache entry expired for %s\n", domain));
-
- DLIST_REMOVE(get_dc_name_cache, dcc);
- SAFE_FREE(dcc);
-
- break;
- }
-
- /* Return a positive or negative lookup for this domain */
-
- if (dcc->srv_name[0]) {
- DEBUG(10, ("returning positive get_dc_name_cache entry for %s\n", domain));
- fstrcpy(srv_name, dcc->srv_name);
- return True;
- } else {
- DEBUG(10, ("returning negative get_dc_name_cache entry for %s\n", domain));
- return False;
+ zero_ip(&exclude_ip);
+ /* Lookup domain controller name. Try the real PDC first to avoid
+ SAM sync delays */
+ if (get_dc_list(True, domain, &ip_list, &count)) {
+ if (name_status_find(domain, 0x1c, 0x20, ip_list[0], srv_name)) {
+ dc_ip = ip_list[0];
+ goto done;
}
+ /* Didn't get name, remember not to talk to this DC. */
+ exclude_ip = ip_list[0];
+ SAFE_FREE(ip_list);
}
- /* Add cache entry for this lookup. */
-
- DEBUG(10, ("Creating get_dc_name_cache entry for %s\n", domain));
-
- if (!(dcc = (struct get_dc_name_cache *)
- malloc(sizeof(struct get_dc_name_cache))))
+ if (!get_dc_list(False, domain, &ip_list, &count)) {
+ DEBUG(3, ("Could not look up dc's for domain %s\n", domain));
return False;
+ }
- ZERO_STRUCTP(dcc);
-
- fstrcpy(dcc->domain_name, domain);
- dcc->lookup_time = time(NULL);
-
- DLIST_ADD(get_dc_name_cache, dcc);
+ /* Remove the entry we've already failed with (should be the PDC). */
- /* Lookup domain controller name. Try the real PDC first to avoid
- SAM sync delays */
- if (!get_dc_list(True, domain, &ip_list, &count)) {
- if (!get_dc_list(False, domain, &ip_list, &count)) {
- DEBUG(3, ("Could not look up dc's for domain %s\n", domain));
- return False;
- }
+ for (i = 0; i < count; i++) {
+ if (ip_equal( exclude_ip, ip_list[i]))
+ zero_ip(&ip_list[i]);
}
/* Pick a nice close server */
/* Look for DC on local net */
for (i = 0; i < count; i++) {
+ if (is_zero_ip(ip_list[i]))
+ continue;
+
if (!is_local_net(ip_list[i]))
continue;
@@ -189,6 +149,8 @@ static BOOL cm_get_dc_name(const char *domain, fstring srv_name, struct in_addr
}
}
+ SAFE_FREE(ip_list);
+
/* No-one to talk to )-: */
return False; /* Boo-hoo */
@@ -198,10 +160,6 @@ static BOOL cm_get_dc_name(const char *domain, fstring srv_name, struct in_addr
the DC is alive and kicking. If we can catch a dead DC before
performing a cli_connect() we can avoid a 30-second timeout. */
- /* We have a name so make the cache entry positive now */
-
- fstrcpy(dcc->srv_name, srv_name);
-
DEBUG(3, ("cm_get_dc_name: Returning DC %s (%s) for domain %s\n", srv_name,
inet_ntoa(dc_ip), domain));
@@ -258,11 +216,23 @@ static struct failed_connection_cache *failed_connection_cache;
/* Add an entry to the failed conneciton cache */
-static void add_failed_connection_entry(struct winbindd_cm_conn *new_conn, NTSTATUS result) {
+static void add_failed_connection_entry(struct winbindd_cm_conn *new_conn,
+ NTSTATUS result)
+{
struct failed_connection_cache *fcc;
SMB_ASSERT(!NT_STATUS_IS_OK(result));
+ /* Check we already aren't in the cache */
+
+ for (fcc = failed_connection_cache; fcc; fcc = fcc->next) {
+ if (strequal(fcc->domain_name, new_conn->domain)) {
+ DEBUG(10, ("domain %s already tried and failed\n",
+ fcc->domain_name));
+ return;
+ }
+ }
+
/* Create negative lookup cache entry for this domain and controller */
if (!(fcc = (struct failed_connection_cache *)
@@ -284,7 +254,7 @@ static void add_failed_connection_entry(struct winbindd_cm_conn *new_conn, NTSTA
/* Open a connction to the remote server, cache failures for 30 seconds */
static NTSTATUS cm_open_connection(const char *domain,const char *pipe_name,
- struct winbindd_cm_conn *new_conn)
+ struct winbindd_cm_conn *new_conn)
{
struct failed_connection_cache *fcc;
extern pstring global_myname;
@@ -446,7 +416,7 @@ static NTSTATUS get_connection_from_cache(const char *domain, const char *pipe_n
/* Return a LSA policy handle on a domain */
-CLI_POLICY_HND *cm_get_lsa_handle(char *domain)
+NTSTATUS cm_get_lsa_handle(char *domain, CLI_POLICY_HND **return_hnd)
{
struct winbindd_cm_conn *conn;
uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
@@ -455,15 +425,17 @@ CLI_POLICY_HND *cm_get_lsa_handle(char *domain)
/* Look for existing connections */
- if (!NT_STATUS_IS_OK(result = get_connection_from_cache(domain, PIPE_LSARPC, &conn))) {
- return NULL;
- }
+ if (!NT_STATUS_IS_OK(result = get_connection_from_cache(domain, PIPE_LSARPC, &conn)))
+ return result;
/* This *shitty* code needs scrapping ! JRA */
+
if (policy_handle_is_valid(&conn->pol)) {
hnd.pol = conn->pol;
hnd.cli = conn->cli;
- return &hnd;
+ *return_hnd = &hnd;
+
+ return NT_STATUS_OK;
}
result = cli_lsa_open_policy(conn->cli, conn->cli->mem_ctx, False,
@@ -472,9 +444,8 @@ CLI_POLICY_HND *cm_get_lsa_handle(char *domain)
if (!NT_STATUS_IS_OK(result)) {
/* Hit the cache code again. This cleans out the old connection and gets a new one */
if (conn->cli->fd == -1) { /* Try again, if the remote host disapeared */
- if (!NT_STATUS_IS_OK(result = get_connection_from_cache(domain, PIPE_LSARPC, &conn))) {
- return NULL;
- }
+ if (!NT_STATUS_IS_OK(result = get_connection_from_cache(domain, PIPE_LSARPC, &conn)))
+ return result;
result = cli_lsa_open_policy(conn->cli, conn->cli->mem_ctx, False,
des_access, &conn->pol);
@@ -484,19 +455,22 @@ CLI_POLICY_HND *cm_get_lsa_handle(char *domain)
cli_shutdown(conn->cli);
DLIST_REMOVE(cm_conns, conn);
SAFE_FREE(conn);
- return NULL;
+
+ return result;
}
}
hnd.pol = conn->pol;
hnd.cli = conn->cli;
- return &hnd;
+ *return_hnd = &hnd;
+
+ return NT_STATUS_OK;
}
/* Return a SAM policy handle on a domain */
-CLI_POLICY_HND *cm_get_sam_handle(char *domain)
+NTSTATUS cm_get_sam_handle(char *domain, CLI_POLICY_HND **return_hnd)
{
struct winbindd_cm_conn *conn;
uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
@@ -505,42 +479,50 @@ CLI_POLICY_HND *cm_get_sam_handle(char *domain)
/* Look for existing connections */
- if (!NT_STATUS_IS_OK(result = get_connection_from_cache(domain, PIPE_SAMR, &conn))) {
- return NULL;
- }
+ if (!NT_STATUS_IS_OK(result = get_connection_from_cache(domain, PIPE_SAMR, &conn)))
+ return result;
/* This *shitty* code needs scrapping ! JRA */
+
if (policy_handle_is_valid(&conn->pol)) {
hnd.pol = conn->pol;
hnd.cli = conn->cli;
- return &hnd;
+
+ *return_hnd = &hnd;
+
+ return NT_STATUS_OK;
}
+
result = cli_samr_connect(conn->cli, conn->cli->mem_ctx,
des_access, &conn->pol);
if (!NT_STATUS_IS_OK(result)) {
/* Hit the cache code again. This cleans out the old connection and gets a new one */
if (conn->cli->fd == -1) { /* Try again, if the remote host disapeared */
- if (!NT_STATUS_IS_OK(result = get_connection_from_cache(domain, PIPE_SAMR, &conn))) {
- return NULL;
- }
+
+ if (!NT_STATUS_IS_OK(result = get_connection_from_cache(domain, PIPE_SAMR, &conn)))
+ return result;
result = cli_samr_connect(conn->cli, conn->cli->mem_ctx,
des_access, &conn->pol);
}
if (!NT_STATUS_IS_OK(result)) {
+
cli_shutdown(conn->cli);
DLIST_REMOVE(cm_conns, conn);
SAFE_FREE(conn);
- return NULL;
+
+ return result;
}
}
hnd.pol = conn->pol;
hnd.cli = conn->cli;
- return &hnd;
+ *return_hnd = &hnd;
+
+ return NT_STATUS_OK;
}
#if 0 /* This code now *well* out of date */
@@ -853,3 +835,28 @@ void winbindd_cm_status(void)
else
DEBUG(0, ("\tNo active connections\n"));
}
+
+/* Close all cached connections */
+
+void winbindd_cm_flush(void)
+{
+ struct winbindd_cm_conn *conn, tmp;
+
+ for (conn = cm_conns; conn; conn = conn->next) {
+
+ if (!connection_ok(conn))
+ continue;
+
+ DEBUG(10, ("Closing connection to %s on %s\n",
+ conn->pipe_name, conn->controller));
+
+ if (conn->cli)
+ cli_shutdown(conn->cli);
+
+ tmp.next = conn->next;
+
+ DLIST_REMOVE(cm_conns, conn);
+ SAFE_FREE(conn);
+ conn = &tmp;
+ }
+}