void run_events(void)
{
- struct timeval now;
-
- if (timed_events == NULL) {
- /* No syscall if there are no events */
- DEBUG(11, ("run_events: No events\n"));
- return;
- }
+ /* Run all events that are pending, not just one (as we
+ did previously. */
- GetTimeOfDay(&now);
+ while (timed_events) {
+ struct timeval now;
+ GetTimeOfDay(&now);
- if (timeval_compare(&now, &timed_events->when) < 0) {
- /* Nothing to do yet */
- DEBUG(11, ("run_events: Nothing to do\n"));
- return;
- }
+ if (timeval_compare(&now, &timed_events->when) < 0) {
+ /* Nothing to do yet */
+ DEBUG(11, ("run_events: Nothing to do\n"));
+ return;
+ }
- DEBUG(10, ("Running event \"%s\" %lx\n", timed_events->event_name,
- (unsigned long)timed_events));
+ DEBUG(10, ("Running event \"%s\" %lx\n", timed_events->event_name,
+ (unsigned long)timed_events));
- timed_events->handler(timed_events, &now, timed_events->private_data);
- return;
+ timed_events->handler(timed_events, &now, timed_events->private_data);
+ }
}
struct timeval *get_timed_events_timeout(struct timeval *to_ret)
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_WINBIND
+static NTSTATUS init_dc_connection(struct winbindd_domain *domain);
+
+/****************************************************************
+ Handler triggered if we're offline to try and detect a DC.
+****************************************************************/
+
+static void check_domain_online_handler(struct timed_event *te,
+ const struct timeval *now,
+ void *private_data)
+{
+ struct winbindd_domain *domain =
+ (struct winbindd_domain *)private_data;
+
+ DEBUG(10,("check_domain_online_handler: called for domain %s\n",
+ domain->name ));
+
+ if (domain->check_online_event) {
+ TALLOC_FREE(domain->check_online_event);
+ }
+
+ /* We've been told to stay offline, so stay
+ that way. */
+
+ if (get_global_winbindd_state_offline()) {
+ DEBUG(10,("check_domain_online_handler: domain %s remaining globally offline\n",
+ domain->name ));
+ return;
+ }
+
+ /* This call takes care of setting the online
+ flag to true if we connected, or re-adding
+ the offline handler if false. */
+ init_dc_connection(domain);
+}
+
+/****************************************************************
+ Set domain offline and also add handler to put us back online
+ if we detect a DC.
+****************************************************************/
+
+void set_domain_offline(struct winbindd_domain *domain)
+{
+ DEBUG(10,("set_domain_offline: called for domain %s\n",
+ domain->name ));
+
+ if (domain->check_online_event) {
+ TALLOC_FREE(domain->check_online_event);
+ }
+
+ domain->online = False;
+
+ /* We only add the timeout handler that checks and
+ allows us to go back online when we've not
+ been told to remain offline. */
+
+ if (get_global_winbindd_state_offline()) {
+ DEBUG(10,("set_domain_offline: domain %s remaining globally offline\n",
+ domain->name ));
+ return;
+ }
+
+ domain->check_online_event = add_timed_event( NULL,
+ timeval_current_ofs(lp_winbind_cache_time(), 0),
+ "check_domain_online_handler",
+ check_domain_online_handler,
+ domain);
+
+ /* The above *has* to succeed for winbindd to work. */
+ if (!domain->check_online_event) {
+ smb_panic("set_domain_offline: failed to add online handler.\n");
+ }
+
+ DEBUG(10,("set_domain_offline: added event handler for domain %s\n",
+ domain->name ));
+}
+
+/****************************************************************
+ Set domain online - if allowed.
+****************************************************************/
+
+void set_domain_online(struct winbindd_domain *domain)
+{
+ DEBUG(10,("set_domain_offline: called for domain %s\n",
+ domain->name ));
+
+ if (get_global_winbindd_state_offline()) {
+ DEBUG(10,("set_domain_online: domain %s remaining globally offline\n",
+ domain->name ));
+ return;
+ }
+
+ domain->online = True;
+}
+
+/****************************************************************
+ Add -ve connection cache entries for domain and realm.
+****************************************************************/
+
+void winbind_add_failed_connection_entry(const struct winbindd_domain *domain,
+ const char *server,
+ NTSTATUS result)
+{
+ add_failed_connection_entry(domain->name, server, result);
+ if (*domain->alt_name) {
+ add_failed_connection_entry(domain->alt_name, server, result);
+ }
+}
/* Choose between anonymous or authenticated connections. We need to use
an authenticated connection if DCs have the RestrictAnonymous registry
SAFE_FREE(ipc_password);
if (!NT_STATUS_IS_OK(result)) {
- add_failed_connection_entry(domain->name, controller, result);
+ winbind_add_failed_connection_entry(domain, controller, result);
if ((*cli) != NULL) {
cli_shutdown(*cli);
*cli = NULL;
if ( !open_any_socket_out(addrs, num_addrs, 5000, &fd_index, fd) )
{
for (i=0; i<num_dcs; i++) {
- add_failed_connection_entry(domain->name,
+ winbind_add_failed_connection_entry(domain,
dcs[i].name, NT_STATUS_UNSUCCESSFUL);
}
return False;
}
/* We can not continue without the DC's name */
- add_failed_connection_entry(domain->name, dcs[fd_index].name,
+ winbind_add_failed_connection_entry(domain, dcs[fd_index].name,
NT_STATUS_UNSUCCESSFUL);
goto again;
}
if ((mem_ctx = talloc_init("cm_open_connection")) == NULL) {
SAFE_FREE(saf_servername);
+ set_domain_offline(domain);
return NT_STATUS_NO_MEMORY;
}
&domain->sid, ip, saf_name )) {
fstrcpy( domain->dcname, saf_name );
} else {
- add_failed_connection_entry(
- domain->name, saf_servername,
+ winbind_add_failed_connection_entry(
+ domain, saf_servername,
NT_STATUS_UNSUCCESSFUL);
}
} else {
/* 5 second timeout. */
if (!open_any_socket_out(addrs, num_addrs, 5000, &dummy, &fd)) {
- domain->online = False;
fd = -1;
}
}
to true, if a "WINBINDD_OFFLINE" entry
is found in the winbindd cache. */
set_global_winbindd_state_offline();
- domain->online = False;
break;
}
/* We're changing state from offline to online. */
set_global_winbindd_state_online();
}
- domain->online = True;
+ set_domain_online(domain);
+ } else {
+ /* Ensure we setup the retry handler. */
+ set_domain_offline(domain);
}
talloc_destroy(mem_ctx);
for (domain = domain_list(); domain; domain = domain->next) {
DEBUG(5,("child_msg_offline: marking %s offline.\n", domain->name));
- domain->online = False;
+ set_domain_offline(domain);
+ }
+}
+
+/* Ensure any negative cache entries with the netbios or realm names are removed. */
+
+static void winbindd_flush_negative_conn_cache(struct winbindd_domain *domain)
+{
+ check_negative_conn_cache_timeout(domain->name, domain->dcname, 0);
+ if (*domain->alt_name) {
+ check_negative_conn_cache_timeout(domain->alt_name, domain->dcname, 0);
}
}
winbindd_flush_nscd_cache();
/* Mark everything online - delete any negative cache entries
- to force an immediate reconnect. */
+ to force a reconnect on the next query from the parent to this child. */
for (domain = domain_list(); domain; domain = domain->next) {
DEBUG(5,("child_msg_online: marking %s online.\n", domain->name));
- domain->online = True;
- check_negative_conn_cache_timeout(domain->name, domain->dcname, 0);
+ set_domain_online(domain);
+ winbindd_flush_negative_conn_cache(domain);
}
}
char *buf = NULL;
if ((buf = talloc_asprintf(mem_ctx, "global:%s ",
- get_global_winbindd_state_online() ?
+ get_global_winbindd_state_offline() ?
"Offline":"Online")) == NULL) {
return NULL;
}
/**********************************************************************
Get the sequence number for a Windows AD native mode domain using
- LDAP queries
+ LDAP queries.
**********************************************************************/
-static int get_ldap_sequence_number( const char* domain, uint32 *seq)
+static int get_ldap_sequence_number(struct winbindd_domain *domain, uint32 *seq)
{
int ret = -1;
int i, port = LDAP_PORT;
struct ip_service *ip_list = NULL;
int count;
- if ( !NT_STATUS_IS_OK(get_sorted_dc_list(domain, &ip_list, &count,
+ if ( !NT_STATUS_IS_OK(get_sorted_dc_list(domain->name, &ip_list, &count,
False)) ) {
- DEBUG(3, ("Could not look up dc's for domain %s\n", domain));
+ DEBUG(3, ("Could not look up dc's for domain %s\n", domain->name));
return False;
}
goto done;
/* add to failed connection cache */
- add_failed_connection_entry( domain, ipstr,
+ winbind_add_failed_connection_entry( domain, ipstr,
NT_STATUS_UNSUCCESSFUL );
}
if ( ret == 0 ) {
DEBUG(3, ("get_ldap_sequence_number: Retrieved sequence "
"number for Domain (%s) from DC (%s:%d)\n",
- domain, inet_ntoa(ip_list[i].ip), port));
+ domain->name, inet_ntoa(ip_list[i].ip), port));
}
SAFE_FREE(ip_list);