2 Unix SMB/CIFS implementation.
4 Winbind daemon connection manager
6 Copyright (C) Tim Potter 2001
7 Copyright (C) Andrew Bartlett 2002
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 We need to manage connections to domain controllers without having to
26 mess up the main winbindd code with other issues. The aim of the
27 connection manager is to:
29 - make connections to domain controllers and cache them
30 - re-establish connections when networks or servers go down
31 - centralise the policy on connection timeouts, domain controller
33 - manage re-entrancy for when winbindd becomes able to handle
34 multiple outstanding rpc requests
36 Why not have connection management as part of the rpc layer like tng?
37 Good question. This code may morph into libsmb/rpc_cache.c or something
38 like that but at the moment it's simply staying as part of winbind. I
39 think the TNG architecture of forcing every user of the rpc layer to use
40 the connection caching system is a bad idea. It should be an optional
41 method of using the routines.
43 The TNG design is quite good but I disagree with some aspects of the
51 - I'm pretty annoyed by all the make_nmb_name() stuff. It should be
52 moved down into another function.
54 - There needs to be a utility function in libsmb/namequery.c that does
57 - Take care when destroying cli_structs as they can be shared between
65 #define DBGC_CLASS DBGC_WINBIND
67 /* Global list of connections. Initially a DLIST but can become a hash
68 table or whatever later. */
70 struct winbindd_cm_conn {
71 struct winbindd_cm_conn *prev, *next;
75 struct cli_state *cli;
79 static struct winbindd_cm_conn *cm_conns = NULL;
81 /* Get a domain controller name. Cache positive and negative lookups so we
82 don't go to the network too often when something is badly broken. */
84 #define GET_DC_NAME_CACHE_TIMEOUT 30 /* Seconds between dc lookups */
86 struct get_dc_name_cache {
90 struct get_dc_name_cache *prev, *next;
95 find the DC for a domain using methods appropriate for a ADS domain
97 static BOOL cm_ads_find_dc(const char *domain, struct in_addr *dc_ip, fstring srv_name)
100 const char *realm = domain;
102 if (strcasecmp(realm, lp_workgroup()) == 0) {
106 ads = ads_init(realm, domain, NULL);
111 /* we don't need to bind, just connect */
112 ads->auth.flags |= ADS_AUTH_NO_BIND;
114 DEBUG(4,("cm_ads_find_dc: domain=%s\n", domain));
117 /* a full ads_connect() is actually overkill, as we don't srictly need
118 to do the SASL auth in order to get the info we need, but libads
119 doesn't offer a better way right now */
123 if (!ads->config.realm) {
127 fstrcpy(srv_name, ads->config.ldap_server_name);
129 *dc_ip = ads->ldap_ip;
132 DEBUG(4,("cm_ads_find_dc: using server='%s' IP=%s\n",
133 srv_name, inet_ntoa(*dc_ip)));
139 find the DC for a domain using methods appropriate for a RPC domain
141 static BOOL cm_rpc_find_dc(const char *domain, struct in_addr *dc_ip, fstring srv_name)
143 struct in_addr *ip_list = NULL, exclude_ip;
146 zero_ip(&exclude_ip);
148 /* Lookup domain controller name. Try the real PDC first to avoid
151 if (get_dc_list(True, domain, &ip_list, &count)) {
152 if (name_status_find(domain, 0x1c, 0x20, ip_list[0], srv_name)) {
157 /* Didn't get name, remember not to talk to this DC. */
158 exclude_ip = ip_list[0];
162 if (!get_dc_list(False, domain, &ip_list, &count)) {
163 DEBUG(3, ("Could not look up dc's for domain %s\n", domain));
167 /* Remove the entry we've already failed with (should be the PDC). */
168 for (i = 0; i < count; i++) {
169 if (ip_equal( exclude_ip, ip_list[i]))
170 zero_ip(&ip_list[i]);
173 /* Pick a nice close server */
174 /* Look for DC on local net */
175 for (i = 0; i < count; i++) {
176 if (is_zero_ip(ip_list[i]))
179 if (!is_local_net(ip_list[i]))
182 if (name_status_find(domain, 0x1c, 0x20, ip_list[i], srv_name)) {
187 zero_ip(&ip_list[i]);
191 * Secondly try and contact a random PDC/BDC.
194 i = (sys_random() % count);
196 if (!is_zero_ip(ip_list[i]) &&
197 name_status_find(domain, 0x1c, 0x20,
198 ip_list[i], srv_name)) {
203 zero_ip(&ip_list[i]); /* Tried and failed. */
205 /* Finally return first DC that we can contact using a node
207 for (i = 0; i < count; i++) {
208 if (is_zero_ip(ip_list[i]))
211 if (name_status_find(domain, 0x1c, 0x20, ip_list[i], srv_name)) {
224 static BOOL cm_get_dc_name(const char *domain, fstring srv_name, struct in_addr *ip_out)
226 static struct get_dc_name_cache *get_dc_name_cache;
227 struct get_dc_name_cache *dcc;
228 struct in_addr dc_ip;
231 /* Check the cache for previous lookups */
233 for (dcc = get_dc_name_cache; dcc; dcc = dcc->next) {
235 if (!strequal(domain, dcc->domain_name))
236 continue; /* Not our domain */
238 if ((time(NULL) - dcc->lookup_time) >
239 GET_DC_NAME_CACHE_TIMEOUT) {
241 /* Cache entry has expired, delete it */
243 DEBUG(10, ("get_dc_name_cache entry expired for %s\n", domain));
245 DLIST_REMOVE(get_dc_name_cache, dcc);
251 /* Return a positive or negative lookup for this domain */
253 if (dcc->srv_name[0]) {
254 DEBUG(10, ("returning positive get_dc_name_cache entry for %s\n", domain));
255 fstrcpy(srv_name, dcc->srv_name);
258 DEBUG(10, ("returning negative get_dc_name_cache entry for %s\n", domain));
263 /* Add cache entry for this lookup. */
265 DEBUG(10, ("Creating get_dc_name_cache entry for %s\n", domain));
267 if (!(dcc = (struct get_dc_name_cache *)
268 malloc(sizeof(struct get_dc_name_cache))))
273 fstrcpy(dcc->domain_name, domain);
274 dcc->lookup_time = time(NULL);
276 DLIST_ADD(get_dc_name_cache, dcc);
281 if (lp_security() == SEC_ADS) {
282 ret = cm_ads_find_dc(domain, &dc_ip, srv_name);
285 /* fall back on rpc methods if the ADS methods fail */
286 ret = cm_rpc_find_dc(domain, &dc_ip, srv_name);
293 /* We have a name so make the cache entry positive now */
294 fstrcpy(dcc->srv_name, srv_name);
296 DEBUG(3, ("cm_get_dc_name: Returning DC %s (%s) for domain %s\n", srv_name,
297 inet_ntoa(dc_ip), domain));
304 /* Choose between anonymous or authenticated connections. We need to use
305 an authenticated connection if DCs have the RestrictAnonymous registry
306 entry set > 0, or the "Additional restrictions for anonymous
307 connections" set in the win2k Local Security Policy.
309 Caller to free() result in domain, username, password
312 static void cm_get_ipc_userpass(char **username, char **domain, char **password)
314 *username = secrets_fetch(SECRETS_AUTH_USER, NULL);
315 *domain = secrets_fetch(SECRETS_AUTH_DOMAIN, NULL);
316 *password = secrets_fetch(SECRETS_AUTH_PASSWORD, NULL);
318 if (*username && **username) {
319 if (!*domain || !**domain) {
320 *domain = smb_xstrdup(lp_workgroup());
323 DEBUG(3, ("IPC$ connections done by user %s\\%s\n", *domain, *username));
325 DEBUG(3, ("IPC$ connections done anonymously\n"));
326 *username = smb_xstrdup("");
327 *domain = smb_xstrdup("");
328 *password = smb_xstrdup("");
332 /* Open a new smb pipe connection to a DC on a given domain. Cache
333 negative creation attempts so we don't try and connect to broken
334 machines too often. */
336 #define FAILED_CONNECTION_CACHE_TIMEOUT 30 /* Seconds between attempts */
338 struct failed_connection_cache {
343 struct failed_connection_cache *prev, *next;
346 static struct failed_connection_cache *failed_connection_cache;
348 /* Add an entry to the failed conneciton cache */
350 static void add_failed_connection_entry(struct winbindd_cm_conn *new_conn,
353 struct failed_connection_cache *fcc;
355 SMB_ASSERT(!NT_STATUS_IS_OK(result));
357 /* Check we already aren't in the cache */
359 for (fcc = failed_connection_cache; fcc; fcc = fcc->next) {
360 if (strequal(fcc->domain_name, new_conn->domain)) {
361 DEBUG(10, ("domain %s already tried and failed\n",
367 /* Create negative lookup cache entry for this domain and controller */
369 if (!(fcc = (struct failed_connection_cache *)
370 malloc(sizeof(struct failed_connection_cache)))) {
371 DEBUG(0, ("malloc failed in add_failed_connection_entry!\n"));
377 fstrcpy(fcc->domain_name, new_conn->domain);
378 fstrcpy(fcc->controller, new_conn->controller);
379 fcc->lookup_time = time(NULL);
380 fcc->nt_status = result;
382 DLIST_ADD(failed_connection_cache, fcc);
385 /* Open a connction to the remote server, cache failures for 30 seconds */
387 static NTSTATUS cm_open_connection(const char *domain, const iont pipe_index,
388 struct winbindd_cm_conn *new_conn)
390 struct failed_connection_cache *fcc;
391 extern pstring global_myname;
393 char *ipc_username, *ipc_domain, *ipc_password;
394 struct in_addr dc_ip;
398 fstrcpy(new_conn->domain, domain);
399 fstrcpy(new_conn->pipe_name, get_pipe_name_from_index(pipe_index));
401 /* Look for a domain controller for this domain. Negative results
402 are cached so don't bother applying the caching for this
403 function just yet. */
405 if (!cm_get_dc_name(domain, new_conn->controller, &dc_ip)) {
406 result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
407 add_failed_connection_entry(new_conn, result);
411 /* Return false if we have tried to look up this domain and netbios
412 name before and failed. */
414 for (fcc = failed_connection_cache; fcc; fcc = fcc->next) {
416 if (!(strequal(domain, fcc->domain_name) &&
417 strequal(new_conn->controller, fcc->controller)))
418 continue; /* Not our domain */
420 if ((time(NULL) - fcc->lookup_time) >
421 FAILED_CONNECTION_CACHE_TIMEOUT) {
423 /* Cache entry has expired, delete it */
425 DEBUG(10, ("cm_open_connection cache entry expired for %s, %s\n", domain, new_conn->controller));
427 DLIST_REMOVE(failed_connection_cache, fcc);
433 /* The timeout hasn't expired yet so return false */
435 DEBUG(10, ("returning negative open_connection_cache entry for %s, %s\n", domain, new_conn->controller));
437 result = fcc->nt_status;
438 SMB_ASSERT(!NT_STATUS_IS_OK(result));
442 /* Initialise SMB connection */
444 cm_get_ipc_userpass(&ipc_username, &ipc_domain, &ipc_password);
446 DEBUG(5, ("connecting to %s from %s with username [%s]\\[%s]\n",
447 new_conn->controller, global_myname, ipc_domain, ipc_username));
449 result = cli_full_connection(&(new_conn->cli), global_myname, new_conn->controller,
451 "IPC", ipc_username, ipc_domain,
454 SAFE_FREE(ipc_username);
455 SAFE_FREE(ipc_domain);
456 SAFE_FREE(ipc_password);
458 if (!NT_STATUS_IS_OK(result)) {
459 add_failed_connection_entry(new_conn, result);
463 if ( !cli_nt_session_open (new_conn->cli, pipe_index) ) {
464 result = NT_STATUS_PIPE_NOT_AVAILABLE;
465 add_failed_connection_entry(new_conn, result);
466 cli_shutdown(new_conn->cli);
473 /* Return true if a connection is still alive */
475 static BOOL connection_ok(struct winbindd_cm_conn *conn)
478 smb_panic("Invalid paramater passed to conneciton_ok(): conn was NULL!\n");
483 DEBUG(0, ("Connection to %s for domain %s (pipe %s) has NULL conn->cli!\n",
484 conn->controller, conn->domain, conn->pipe_name));
485 smb_panic("connection_ok: conn->cli was null!");
489 if (!conn->cli->initialised) {
490 DEBUG(0, ("Connection to %s for domain %s (pipe %s) was never initialised!\n",
491 conn->controller, conn->domain, conn->pipe_name));
492 smb_panic("connection_ok: conn->cli->initialised is False!");
496 if (conn->cli->fd == -1) {
497 DEBUG(3, ("Connection to %s for domain %s (pipe %s) has died or was never started (fd == -1)\n",
498 conn->controller, conn->domain, conn->pipe_name));
505 /* Get a connection to the remote DC and open the pipe. If there is already a connection, use that */
507 static NTSTATUS get_connection_from_cache(const char *domain, const char *pipe_name, struct winbindd_cm_conn **conn_out)
509 struct winbindd_cm_conn *conn, conn_temp;
512 for (conn = cm_conns; conn; conn = conn->next) {
513 if (strequal(conn->domain, domain) &&
514 strequal(conn->pipe_name, pipe_name)) {
515 if (!connection_ok(conn)) {
517 cli_shutdown(conn->cli);
519 ZERO_STRUCT(conn_temp);
520 conn_temp.next = conn->next;
521 DLIST_REMOVE(cm_conns, conn);
523 conn = &conn_temp; /* Just to keep the loop moving */
531 if (!(conn = malloc(sizeof(*conn))))
532 return NT_STATUS_NO_MEMORY;
536 if (!NT_STATUS_IS_OK(result = cm_open_connection(domain, get_pipe_index(pipe_name), conn))) {
537 DEBUG(3, ("Could not open a connection to %s for %s (%s)\n",
538 domain, pipe_name, nt_errstr(result)));
542 DLIST_ADD(cm_conns, conn);
550 /**********************************************************************************
551 **********************************************************************************/
553 BOOL cm_check_for_native_mode_win2k( const char *domain )
556 struct winbindd_cm_conn conn;
564 if ( !NT_STATUS_IS_OK(result = cm_open_connection(domain, PI_LSARPC_DS, &conn)) )
566 DEBUG(3, ("cm_check_for_native_mode_win2k: Could not open a connection to %s for PIPE_LSARPC (%s)\n",
567 domain, nt_errstr(result)));
572 if ( !NT_STATUS_IS_OK(cli_ds_getprimarydominfo( conn.cli,
573 conn.cli->mem_ctx, DsRolePrimaryDomainInfoBasic, &ctr)) )
580 if ( (ctr.basic->flags & DSROLE_PRIMARY_DS_RUNNING)
581 && !(ctr.basic->flags & DSROLE_PRIMARY_DS_MIXED_MODE) )
588 cli_shutdown( conn.cli );
595 /* Return a LSA policy handle on a domain */
597 CLI_POLICY_HND *cm_get_lsa_handle(char *domain)
599 struct winbindd_cm_conn *conn;
600 uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
602 static CLI_POLICY_HND hnd;
604 /* Look for existing connections */
606 if (!NT_STATUS_IS_OK(result = get_connection_from_cache(domain, PIPE_LSARPC, &conn))) {
610 /* This *shitty* code needs scrapping ! JRA */
611 if (policy_handle_is_valid(&conn->pol)) {
617 result = cli_lsa_open_policy(conn->cli, conn->cli->mem_ctx, False,
618 des_access, &conn->pol);
620 if (!NT_STATUS_IS_OK(result)) {
621 /* Hit the cache code again. This cleans out the old connection and gets a new one */
622 if (conn->cli->fd == -1) { /* Try again, if the remote host disapeared */
623 if (!NT_STATUS_IS_OK(result = get_connection_from_cache(domain, PIPE_LSARPC, &conn))) {
627 result = cli_lsa_open_policy(conn->cli, conn->cli->mem_ctx, False,
628 des_access, &conn->pol);
631 if (!NT_STATUS_IS_OK(result)) {
632 cli_shutdown(conn->cli);
633 DLIST_REMOVE(cm_conns, conn);
645 /* Return a SAM policy handle on a domain */
647 CLI_POLICY_HND *cm_get_sam_handle(char *domain)
649 struct winbindd_cm_conn *conn;
650 uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
652 static CLI_POLICY_HND hnd;
654 /* Look for existing connections */
656 if (!NT_STATUS_IS_OK(result = get_connection_from_cache(domain, PIPE_SAMR, &conn))) {
660 /* This *shitty* code needs scrapping ! JRA */
661 if (policy_handle_is_valid(&conn->pol)) {
666 result = cli_samr_connect(conn->cli, conn->cli->mem_ctx,
667 des_access, &conn->pol);
669 if (!NT_STATUS_IS_OK(result)) {
670 /* Hit the cache code again. This cleans out the old connection and gets a new one */
671 if (conn->cli->fd == -1) { /* Try again, if the remote host disapeared */
672 if (!NT_STATUS_IS_OK(result = get_connection_from_cache(domain, PIPE_SAMR, &conn))) {
676 result = cli_samr_connect(conn->cli, conn->cli->mem_ctx,
677 des_access, &conn->pol);
680 if (!NT_STATUS_IS_OK(result)) {
681 cli_shutdown(conn->cli);
682 DLIST_REMOVE(cm_conns, conn);
694 #if 0 /* This code now *well* out of date */
696 /* Return a SAM domain policy handle on a domain */
698 CLI_POLICY_HND *cm_get_sam_dom_handle(char *domain, DOM_SID *domain_sid)
700 struct winbindd_cm_conn *conn, *basic_conn = NULL;
701 static CLI_POLICY_HND hnd;
703 uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
705 /* Look for existing connections */
707 for (conn = cm_conns; conn; conn = conn->next) {
708 if (strequal(conn->domain, domain) &&
709 strequal(conn->pipe_name, PIPE_SAMR) &&
710 conn->pipe_data.samr.pipe_type == SAM_PIPE_DOM) {
712 if (!connection_ok(conn)) {
713 /* Shutdown cli? Free conn? Allow retry of DC? */
714 DLIST_REMOVE(cm_conns, conn);
722 /* Create a basic handle to open a domain handle from */
724 if (!cm_get_sam_handle(domain))
727 for (conn = cm_conns; conn; conn = conn->next) {
728 if (strequal(conn->domain, domain) &&
729 strequal(conn->pipe_name, PIPE_SAMR) &&
730 conn->pipe_data.samr.pipe_type == SAM_PIPE_BASIC)
734 if (!(conn = (struct winbindd_cm_conn *)
735 malloc(sizeof(struct winbindd_cm_conn))))
740 fstrcpy(conn->domain, basic_conn->domain);
741 fstrcpy(conn->controller, basic_conn->controller);
742 fstrcpy(conn->pipe_name, basic_conn->pipe_name);
744 conn->pipe_data.samr.pipe_type = SAM_PIPE_DOM;
745 conn->cli = basic_conn->cli;
747 result = cli_samr_open_domain(conn->cli, conn->cli->mem_ctx,
748 &basic_conn->pol, des_access,
749 domain_sid, &conn->pol);
751 if (!NT_STATUS_IS_OK(result))
756 DLIST_ADD(cm_conns, conn);
765 /* Return a SAM policy handle on a domain user */
767 CLI_POLICY_HND *cm_get_sam_user_handle(char *domain, DOM_SID *domain_sid,
770 struct winbindd_cm_conn *conn, *basic_conn = NULL;
771 static CLI_POLICY_HND hnd;
773 uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
775 /* Look for existing connections */
777 for (conn = cm_conns; conn; conn = conn->next) {
778 if (strequal(conn->domain, domain) &&
779 strequal(conn->pipe_name, PIPE_SAMR) &&
780 conn->pipe_data.samr.pipe_type == SAM_PIPE_USER &&
781 conn->pipe_data.samr.rid == user_rid) {
783 if (!connection_ok(conn)) {
784 /* Shutdown cli? Free conn? Allow retry of DC? */
785 DLIST_REMOVE(cm_conns, conn);
793 /* Create a domain handle to open a user handle from */
795 if (!cm_get_sam_dom_handle(domain, domain_sid))
798 for (conn = cm_conns; conn; conn = conn->next) {
799 if (strequal(conn->domain, domain) &&
800 strequal(conn->pipe_name, PIPE_SAMR) &&
801 conn->pipe_data.samr.pipe_type == SAM_PIPE_DOM)
806 DEBUG(0, ("No domain sam handle was created!\n"));
810 if (!(conn = (struct winbindd_cm_conn *)
811 malloc(sizeof(struct winbindd_cm_conn))))
816 fstrcpy(conn->domain, basic_conn->domain);
817 fstrcpy(conn->controller, basic_conn->controller);
818 fstrcpy(conn->pipe_name, basic_conn->pipe_name);
820 conn->pipe_data.samr.pipe_type = SAM_PIPE_USER;
821 conn->cli = basic_conn->cli;
822 conn->pipe_data.samr.rid = user_rid;
824 result = cli_samr_open_user(conn->cli, conn->cli->mem_ctx,
825 &basic_conn->pol, des_access, user_rid,
828 if (!NT_STATUS_IS_OK(result))
833 DLIST_ADD(cm_conns, conn);
842 /* Return a SAM policy handle on a domain group */
844 CLI_POLICY_HND *cm_get_sam_group_handle(char *domain, DOM_SID *domain_sid,
847 struct winbindd_cm_conn *conn, *basic_conn = NULL;
848 static CLI_POLICY_HND hnd;
850 uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
852 /* Look for existing connections */
854 for (conn = cm_conns; conn; conn = conn->next) {
855 if (strequal(conn->domain, domain) &&
856 strequal(conn->pipe_name, PIPE_SAMR) &&
857 conn->pipe_data.samr.pipe_type == SAM_PIPE_GROUP &&
858 conn->pipe_data.samr.rid == group_rid) {
860 if (!connection_ok(conn)) {
861 /* Shutdown cli? Free conn? Allow retry of DC? */
862 DLIST_REMOVE(cm_conns, conn);
870 /* Create a domain handle to open a user handle from */
872 if (!cm_get_sam_dom_handle(domain, domain_sid))
875 for (conn = cm_conns; conn; conn = conn->next) {
876 if (strequal(conn->domain, domain) &&
877 strequal(conn->pipe_name, PIPE_SAMR) &&
878 conn->pipe_data.samr.pipe_type == SAM_PIPE_DOM)
883 DEBUG(0, ("No domain sam handle was created!\n"));
887 if (!(conn = (struct winbindd_cm_conn *)
888 malloc(sizeof(struct winbindd_cm_conn))))
893 fstrcpy(conn->domain, basic_conn->domain);
894 fstrcpy(conn->controller, basic_conn->controller);
895 fstrcpy(conn->pipe_name, basic_conn->pipe_name);
897 conn->pipe_data.samr.pipe_type = SAM_PIPE_GROUP;
898 conn->cli = basic_conn->cli;
899 conn->pipe_data.samr.rid = group_rid;
901 result = cli_samr_open_group(conn->cli, conn->cli->mem_ctx,
902 &basic_conn->pol, des_access, group_rid,
905 if (!NT_STATUS_IS_OK(result))
910 DLIST_ADD(cm_conns, conn);
921 /* Get a handle on a netlogon pipe. This is a bit of a hack to re-use the
922 netlogon pipe as no handle is returned. */
924 NTSTATUS cm_get_netlogon_cli(char *domain, unsigned char *trust_passwd,
925 struct cli_state **cli)
927 NTSTATUS result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
928 struct winbindd_cm_conn *conn;
929 uint32 neg_flags = 0x000001ff;
932 return NT_STATUS_INVALID_PARAMETER;
935 /* Open an initial conection */
937 if (!NT_STATUS_IS_OK(result = get_connection_from_cache(domain, PIPE_NETLOGON, &conn))) {
941 result = cli_nt_setup_creds(conn->cli, get_sec_chan(), trust_passwd, &neg_flags, 2);
943 if (!NT_STATUS_IS_OK(result)) {
944 DEBUG(0, ("error connecting to domain password server: %s\n",
947 /* Hit the cache code again. This cleans out the old connection and gets a new one */
948 if (conn->cli->fd == -1) {
949 if (!NT_STATUS_IS_OK(result = get_connection_from_cache(domain, PIPE_NETLOGON, &conn))) {
954 result = cli_nt_setup_creds( conn->cli, get_sec_chan(),trust_passwd, &neg_flags, 2);
957 if (!NT_STATUS_IS_OK(result)) {
958 cli_shutdown(conn->cli);
959 DLIST_REMOVE(cm_conns, conn);
970 /* Dump the current connection status */
972 static void dump_conn_list(void)
974 struct winbindd_cm_conn *con;
976 DEBUG(0, ("\tDomain Controller Pipe\n"));
978 for(con = cm_conns; con; con = con->next) {
981 /* Display pipe info */
983 if (asprintf(&msg, "\t%-15s %-15s %-16s", con->domain, con->controller, con->pipe_name) < 0) {
984 DEBUG(0, ("Error: not enough memory!\n"));
986 DEBUG(0, ("%s\n", msg));
992 void winbindd_cm_status(void)
994 /* List open connections */
996 DEBUG(0, ("winbindd connection manager status:\n"));
1001 DEBUG(0, ("\tNo active connections\n"));