mount.cifs: check access of credential files before opening
[Samba.git] / source / libsmb / namequery.c
blob62cb1bad24b41cae243b7dd530c105dac8ab9730
1 /*
2 Unix SMB/CIFS implementation.
3 name query routines
4 Copyright (C) Andrew Tridgell 1994-1998
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 #include "includes.h"
23 /* nmbd.c sets this to True. */
24 BOOL global_in_nmbd = False;
26 /****************************
27 * SERVER AFFINITY ROUTINES *
28 ****************************/
30 /* Server affinity is the concept of preferring the last domain
31 controller with whom you had a successful conversation */
33 /****************************************************************************
34 ****************************************************************************/
35 #define SAFKEY_FMT "SAF/DOMAIN/%s"
36 #define SAF_TTL 900
37 #define SAFJOINKEY_FMT "SAFJOIN/DOMAIN/%s"
38 #define SAFJOIN_TTL 3600
40 static char *saf_key(const char *domain)
42 char *keystr;
44 asprintf( &keystr, SAFKEY_FMT, strupper_static(domain) );
46 return keystr;
49 static char *saf_join_key(const char *domain)
51 char *keystr;
53 asprintf( &keystr, SAFJOINKEY_FMT, strupper_static(domain) );
55 return keystr;
58 /****************************************************************************
59 ****************************************************************************/
61 BOOL saf_store( const char *domain, const char *servername )
63 char *key;
64 time_t expire;
65 BOOL ret = False;
67 if ( !domain || !servername ) {
68 DEBUG(2,("saf_store: Refusing to store empty domain or servername!\n"));
69 return False;
72 if ( (strlen(domain) == 0) || (strlen(servername) == 0) ) {
73 DEBUG(0,("saf_store: refusing to store 0 length domain or servername!\n"));
74 return False;
77 if ( !gencache_init() )
78 return False;
80 key = saf_key( domain );
81 expire = time( NULL ) + lp_parm_int(-1, "saf","ttl", SAF_TTL);
84 DEBUG(10,("saf_store: domain = [%s], server = [%s], expire = [%u]\n",
85 domain, servername, (unsigned int)expire ));
87 ret = gencache_set( key, servername, expire );
89 SAFE_FREE( key );
91 return ret;
94 BOOL saf_join_store( const char *domain, const char *servername )
96 char *key;
97 time_t expire;
98 BOOL ret = False;
100 if ( !domain || !servername ) {
101 DEBUG(2,("saf_join_store: Refusing to store empty domain or servername!\n"));
102 return False;
105 if ( (strlen(domain) == 0) || (strlen(servername) == 0) ) {
106 DEBUG(0,("saf_join_store: refusing to store 0 length domain or servername!\n"));
107 return False;
110 if ( !gencache_init() )
111 return False;
113 key = saf_join_key( domain );
114 expire = time( NULL ) + lp_parm_int(-1, "saf","join ttl", SAFJOIN_TTL);
116 DEBUG(10,("saf_join_store: domain = [%s], server = [%s], expire = [%u]\n",
117 domain, servername, (unsigned int)expire ));
119 ret = gencache_set( key, servername, expire );
121 SAFE_FREE( key );
123 return ret;
126 BOOL saf_delete( const char *domain )
128 char *key;
129 BOOL ret = False;
131 if ( !domain ) {
132 DEBUG(2,("saf_delete: Refusing to delete empty domain\n"));
133 return False;
136 if ( !gencache_init() )
137 return False;
139 key = saf_join_key(domain);
140 ret = gencache_del(key);
141 SAFE_FREE(key);
143 if (ret) {
144 DEBUG(10,("saf_delete[join]: domain = [%s]\n", domain ));
147 key = saf_key(domain);
148 ret = gencache_del(key);
149 SAFE_FREE(key);
151 if (ret) {
152 DEBUG(10,("saf_delete: domain = [%s]\n", domain ));
155 return ret;
158 /****************************************************************************
159 ****************************************************************************/
161 char *saf_fetch( const char *domain )
163 char *server = NULL;
164 time_t timeout;
165 BOOL ret = False;
166 char *key = NULL;
168 if ( !domain || strlen(domain) == 0) {
169 DEBUG(2,("saf_fetch: Empty domain name!\n"));
170 return NULL;
173 if ( !gencache_init() )
174 return False;
176 key = saf_join_key( domain );
178 ret = gencache_get( key, &server, &timeout );
180 SAFE_FREE( key );
182 if ( ret ) {
183 DEBUG(5,("saf_fetch[join]: Returning \"%s\" for \"%s\" domain\n",
184 server, domain ));
185 return server;
188 key = saf_key( domain );
190 ret = gencache_get( key, &server, &timeout );
192 SAFE_FREE( key );
194 if ( !ret ) {
195 DEBUG(5,("saf_fetch: failed to find server for \"%s\" domain\n", domain ));
196 } else {
197 DEBUG(5,("saf_fetch: Returning \"%s\" for \"%s\" domain\n",
198 server, domain ));
201 return server;
204 /****************************************************************************
205 Generate a random trn_id.
206 ****************************************************************************/
208 static int generate_trn_id(void)
210 static int trn_id;
212 if (trn_id == 0) {
213 sys_srandom(sys_getpid());
216 trn_id = sys_random();
218 return trn_id % (unsigned)0x7FFF;
221 /****************************************************************************
222 Parse a node status response into an array of structures.
223 ****************************************************************************/
225 static NODE_STATUS_STRUCT *parse_node_status(char *p, int *num_names, struct node_status_extra *extra)
227 NODE_STATUS_STRUCT *ret;
228 int i;
230 *num_names = CVAL(p,0);
232 if (*num_names == 0)
233 return NULL;
235 ret = SMB_MALLOC_ARRAY(NODE_STATUS_STRUCT,*num_names);
236 if (!ret)
237 return NULL;
239 p++;
240 for (i=0;i< *num_names;i++) {
241 StrnCpy(ret[i].name,p,15);
242 trim_char(ret[i].name,'\0',' ');
243 ret[i].type = CVAL(p,15);
244 ret[i].flags = p[16];
245 p += 18;
246 DEBUG(10, ("%s#%02x: flags = 0x%02x\n", ret[i].name,
247 ret[i].type, ret[i].flags));
250 * Also, pick up the MAC address ...
252 if (extra) {
253 memcpy(&extra->mac_addr, p, 6); /* Fill in the mac addr */
255 return ret;
259 /****************************************************************************
260 Do a NBT node status query on an open socket and return an array of
261 structures holding the returned names or NULL if the query failed.
262 **************************************************************************/
264 NODE_STATUS_STRUCT *node_status_query(int fd,struct nmb_name *name,
265 struct in_addr to_ip, int *num_names,
266 struct node_status_extra *extra)
268 BOOL found=False;
269 int retries = 2;
270 int retry_time = 2000;
271 struct timeval tval;
272 struct packet_struct p;
273 struct packet_struct *p2;
274 struct nmb_packet *nmb = &p.packet.nmb;
275 NODE_STATUS_STRUCT *ret;
277 ZERO_STRUCT(p);
279 nmb->header.name_trn_id = generate_trn_id();
280 nmb->header.opcode = 0;
281 nmb->header.response = False;
282 nmb->header.nm_flags.bcast = False;
283 nmb->header.nm_flags.recursion_available = False;
284 nmb->header.nm_flags.recursion_desired = False;
285 nmb->header.nm_flags.trunc = False;
286 nmb->header.nm_flags.authoritative = False;
287 nmb->header.rcode = 0;
288 nmb->header.qdcount = 1;
289 nmb->header.ancount = 0;
290 nmb->header.nscount = 0;
291 nmb->header.arcount = 0;
292 nmb->question.question_name = *name;
293 nmb->question.question_type = 0x21;
294 nmb->question.question_class = 0x1;
296 p.ip = to_ip;
297 p.port = NMB_PORT;
298 p.fd = fd;
299 p.timestamp = time(NULL);
300 p.packet_type = NMB_PACKET;
302 GetTimeOfDay(&tval);
304 if (!send_packet(&p))
305 return NULL;
307 retries--;
309 while (1) {
310 struct timeval tval2;
311 GetTimeOfDay(&tval2);
312 if (TvalDiff(&tval,&tval2) > retry_time) {
313 if (!retries)
314 break;
315 if (!found && !send_packet(&p))
316 return NULL;
317 GetTimeOfDay(&tval);
318 retries--;
321 if ((p2=receive_nmb_packet(fd,90,nmb->header.name_trn_id))) {
322 struct nmb_packet *nmb2 = &p2->packet.nmb;
323 debug_nmb_packet(p2);
325 if (nmb2->header.opcode != 0 ||
326 nmb2->header.nm_flags.bcast ||
327 nmb2->header.rcode ||
328 !nmb2->header.ancount ||
329 nmb2->answers->rr_type != 0x21) {
330 /* XXXX what do we do with this? could be a
331 redirect, but we'll discard it for the
332 moment */
333 free_packet(p2);
334 continue;
337 ret = parse_node_status(&nmb2->answers->rdata[0], num_names, extra);
338 free_packet(p2);
339 return ret;
343 return NULL;
346 /****************************************************************************
347 Find the first type XX name in a node status reply - used for finding
348 a servers name given its IP. Return the matched name in *name.
349 **************************************************************************/
351 BOOL name_status_find(const char *q_name, int q_type, int type, struct in_addr to_ip, fstring name)
353 NODE_STATUS_STRUCT *status = NULL;
354 struct nmb_name nname;
355 int count, i;
356 int sock;
357 BOOL result = False;
359 if (lp_disable_netbios()) {
360 DEBUG(5,("name_status_find(%s#%02x): netbios is disabled\n", q_name, q_type));
361 return False;
364 DEBUG(10, ("name_status_find: looking up %s#%02x at %s\n", q_name,
365 q_type, inet_ntoa(to_ip)));
367 /* Check the cache first. */
369 if (namecache_status_fetch(q_name, q_type, type, to_ip, name))
370 return True;
372 sock = open_socket_in(SOCK_DGRAM, 0, 3, interpret_addr(lp_socket_address()), True);
373 if (sock == -1)
374 goto done;
376 /* W2K PDC's seem not to respond to '*'#0. JRA */
377 make_nmb_name(&nname, q_name, q_type);
378 status = node_status_query(sock, &nname, to_ip, &count, NULL);
379 close(sock);
380 if (!status)
381 goto done;
383 for (i=0;i<count;i++) {
384 if (status[i].type == type)
385 break;
387 if (i == count)
388 goto done;
390 pull_ascii_nstring(name, sizeof(fstring), status[i].name);
392 /* Store the result in the cache. */
393 /* but don't store an entry for 0x1c names here. Here we have
394 a single host and DOMAIN<0x1c> names should be a list of hosts */
396 if ( q_type != 0x1c )
397 namecache_status_store(q_name, q_type, type, to_ip, name);
399 result = True;
401 done:
402 SAFE_FREE(status);
404 DEBUG(10, ("name_status_find: name %sfound", result ? "" : "not "));
406 if (result)
407 DEBUGADD(10, (", name %s ip address is %s", name, inet_ntoa(to_ip)));
409 DEBUG(10, ("\n"));
411 return result;
415 comparison function used by sort_ip_list
418 static int ip_compare(struct in_addr *ip1, struct in_addr *ip2)
420 int max_bits1=0, max_bits2=0;
421 int num_interfaces = iface_count();
422 int i;
424 for (i=0;i<num_interfaces;i++) {
425 struct in_addr ip;
426 int bits1, bits2;
427 ip = *iface_n_bcast(i);
428 bits1 = matching_quad_bits((uchar *)&ip1->s_addr, (uchar *)&ip.s_addr);
429 bits2 = matching_quad_bits((uchar *)&ip2->s_addr, (uchar *)&ip.s_addr);
430 max_bits1 = MAX(bits1, max_bits1);
431 max_bits2 = MAX(bits2, max_bits2);
434 /* bias towards directly reachable IPs */
435 if (iface_local(*ip1)) {
436 max_bits1 += 32;
438 if (iface_local(*ip2)) {
439 max_bits2 += 32;
442 return max_bits2 - max_bits1;
445 /*******************************************************************
446 compare 2 ldap IPs by nearness to our interfaces - used in qsort
447 *******************************************************************/
449 int ip_service_compare(struct ip_service *ip1, struct ip_service *ip2)
451 int result;
453 if ( (result = ip_compare(&ip1->ip, &ip2->ip)) != 0 )
454 return result;
456 if ( ip1->port > ip2->port )
457 return 1;
459 if ( ip1->port < ip2->port )
460 return -1;
462 return 0;
466 sort an IP list so that names that are close to one of our interfaces
467 are at the top. This prevents the problem where a WINS server returns an IP that
468 is not reachable from our subnet as the first match
471 static void sort_ip_list(struct in_addr *iplist, int count)
473 if (count <= 1) {
474 return;
477 qsort(iplist, count, sizeof(struct in_addr), QSORT_CAST ip_compare);
480 static void sort_ip_list2(struct ip_service *iplist, int count)
482 if (count <= 1) {
483 return;
486 qsort(iplist, count, sizeof(struct ip_service), QSORT_CAST ip_service_compare);
489 /**********************************************************************
490 Remove any duplicate address/port pairs in the list
491 *********************************************************************/
493 static int remove_duplicate_addrs2( struct ip_service *iplist, int count )
495 int i, j;
497 DEBUG(10,("remove_duplicate_addrs2: looking for duplicate address/port pairs\n"));
499 /* one loop to remove duplicates */
500 for ( i=0; i<count; i++ ) {
501 if ( is_zero_ip(iplist[i].ip) )
502 continue;
504 for ( j=i+1; j<count; j++ ) {
505 if ( ip_service_equal(iplist[i], iplist[j]) )
506 zero_ip(&iplist[j].ip);
510 /* one loop to clean up any holes we left */
511 /* first ip should never be a zero_ip() */
512 for (i = 0; i<count; ) {
513 if ( is_zero_ip(iplist[i].ip) ) {
514 if (i != count-1 )
515 memmove(&iplist[i], &iplist[i+1], (count - i - 1)*sizeof(iplist[i]));
516 count--;
517 continue;
519 i++;
522 return count;
525 /****************************************************************************
526 Do a netbios name query to find someones IP.
527 Returns an array of IP addresses or NULL if none.
528 *count will be set to the number of addresses returned.
529 *timed_out is set if we failed by timing out
530 ****************************************************************************/
532 struct in_addr *name_query(int fd,const char *name,int name_type,
533 BOOL bcast,BOOL recurse,
534 struct in_addr to_ip, int *count, int *flags,
535 BOOL *timed_out)
537 BOOL found=False;
538 int i, retries = 3;
539 int retry_time = bcast?250:2000;
540 struct timeval tval;
541 struct packet_struct p;
542 struct packet_struct *p2;
543 struct nmb_packet *nmb = &p.packet.nmb;
544 struct in_addr *ip_list = NULL;
546 if (lp_disable_netbios()) {
547 DEBUG(5,("name_query(%s#%02x): netbios is disabled\n", name, name_type));
548 return NULL;
551 if (timed_out) {
552 *timed_out = False;
555 memset((char *)&p,'\0',sizeof(p));
556 (*count) = 0;
557 (*flags) = 0;
559 nmb->header.name_trn_id = generate_trn_id();
560 nmb->header.opcode = 0;
561 nmb->header.response = False;
562 nmb->header.nm_flags.bcast = bcast;
563 nmb->header.nm_flags.recursion_available = False;
564 nmb->header.nm_flags.recursion_desired = recurse;
565 nmb->header.nm_flags.trunc = False;
566 nmb->header.nm_flags.authoritative = False;
567 nmb->header.rcode = 0;
568 nmb->header.qdcount = 1;
569 nmb->header.ancount = 0;
570 nmb->header.nscount = 0;
571 nmb->header.arcount = 0;
573 make_nmb_name(&nmb->question.question_name,name,name_type);
575 nmb->question.question_type = 0x20;
576 nmb->question.question_class = 0x1;
578 p.ip = to_ip;
579 p.port = NMB_PORT;
580 p.fd = fd;
581 p.timestamp = time(NULL);
582 p.packet_type = NMB_PACKET;
584 GetTimeOfDay(&tval);
586 if (!send_packet(&p))
587 return NULL;
589 retries--;
591 while (1) {
592 struct timeval tval2;
594 GetTimeOfDay(&tval2);
595 if (TvalDiff(&tval,&tval2) > retry_time) {
596 if (!retries)
597 break;
598 if (!found && !send_packet(&p))
599 return NULL;
600 GetTimeOfDay(&tval);
601 retries--;
604 if ((p2=receive_nmb_packet(fd,90,nmb->header.name_trn_id))) {
605 struct nmb_packet *nmb2 = &p2->packet.nmb;
606 debug_nmb_packet(p2);
608 /* If we get a Negative Name Query Response from a WINS
609 * server, we should report it and give up.
611 if( 0 == nmb2->header.opcode /* A query response */
612 && !(bcast) /* from a WINS server */
613 && nmb2->header.rcode /* Error returned */
616 if( DEBUGLVL( 3 ) ) {
617 /* Only executed if DEBUGLEVEL >= 3 */
618 dbgtext( "Negative name query response, rcode 0x%02x: ", nmb2->header.rcode );
619 switch( nmb2->header.rcode ) {
620 case 0x01:
621 dbgtext( "Request was invalidly formatted.\n" );
622 break;
623 case 0x02:
624 dbgtext( "Problem with NBNS, cannot process name.\n");
625 break;
626 case 0x03:
627 dbgtext( "The name requested does not exist.\n" );
628 break;
629 case 0x04:
630 dbgtext( "Unsupported request error.\n" );
631 break;
632 case 0x05:
633 dbgtext( "Query refused error.\n" );
634 break;
635 default:
636 dbgtext( "Unrecognized error code.\n" );
637 break;
640 free_packet(p2);
641 return( NULL );
644 if (nmb2->header.opcode != 0 ||
645 nmb2->header.nm_flags.bcast ||
646 nmb2->header.rcode ||
647 !nmb2->header.ancount) {
649 * XXXX what do we do with this? Could be a
650 * redirect, but we'll discard it for the
651 * moment.
653 free_packet(p2);
654 continue;
657 ip_list = SMB_REALLOC_ARRAY( ip_list, struct in_addr,
658 (*count) + nmb2->answers->rdlength/6 );
660 if (!ip_list) {
661 DEBUG(0,("name_query: Realloc failed.\n"));
662 free_packet(p2);
663 return( NULL );
666 DEBUG(2,("Got a positive name query response from %s ( ", inet_ntoa(p2->ip)));
667 for (i=0;i<nmb2->answers->rdlength/6;i++) {
668 putip((char *)&ip_list[(*count)],&nmb2->answers->rdata[2+i*6]);
669 DEBUGADD(2,("%s ",inet_ntoa(ip_list[(*count)])));
670 (*count)++;
672 DEBUGADD(2,(")\n"));
674 found=True;
675 retries=0;
676 /* We add the flags back ... */
677 if (nmb2->header.response)
678 (*flags) |= NM_FLAGS_RS;
679 if (nmb2->header.nm_flags.authoritative)
680 (*flags) |= NM_FLAGS_AA;
681 if (nmb2->header.nm_flags.trunc)
682 (*flags) |= NM_FLAGS_TC;
683 if (nmb2->header.nm_flags.recursion_desired)
684 (*flags) |= NM_FLAGS_RD;
685 if (nmb2->header.nm_flags.recursion_available)
686 (*flags) |= NM_FLAGS_RA;
687 if (nmb2->header.nm_flags.bcast)
688 (*flags) |= NM_FLAGS_B;
689 free_packet(p2);
691 * If we're doing a unicast lookup we only
692 * expect one reply. Don't wait the full 2
693 * seconds if we got one. JRA.
695 if(!bcast && found)
696 break;
700 /* only set timed_out if we didn't fund what we where looking for*/
702 if ( !found && timed_out ) {
703 *timed_out = True;
706 /* sort the ip list so we choose close servers first if possible */
707 sort_ip_list(ip_list, *count);
709 return ip_list;
712 /********************************************************
713 Start parsing the lmhosts file.
714 *********************************************************/
716 XFILE *startlmhosts(char *fname)
718 XFILE *fp = x_fopen(fname,O_RDONLY, 0);
719 if (!fp) {
720 DEBUG(4,("startlmhosts: Can't open lmhosts file %s. Error was %s\n",
721 fname, strerror(errno)));
722 return NULL;
724 return fp;
727 /********************************************************
728 Parse the next line in the lmhosts file.
729 *********************************************************/
731 BOOL getlmhostsent( XFILE *fp, pstring name, int *name_type, struct in_addr *ipaddr)
733 pstring line;
735 while(!x_feof(fp) && !x_ferror(fp)) {
736 pstring ip,flags,extra;
737 const char *ptr;
738 char *ptr1;
739 int count = 0;
741 *name_type = -1;
743 if (!fgets_slash(line,sizeof(pstring),fp)) {
744 continue;
747 if (*line == '#') {
748 continue;
751 pstrcpy(ip,"");
752 pstrcpy(name,"");
753 pstrcpy(flags,"");
755 ptr = line;
757 if (next_token(&ptr,ip ,NULL,sizeof(ip)))
758 ++count;
759 if (next_token(&ptr,name ,NULL, sizeof(pstring)))
760 ++count;
761 if (next_token(&ptr,flags,NULL, sizeof(flags)))
762 ++count;
763 if (next_token(&ptr,extra,NULL, sizeof(extra)))
764 ++count;
766 if (count <= 0)
767 continue;
769 if (count > 0 && count < 2) {
770 DEBUG(0,("getlmhostsent: Ill formed hosts line [%s]\n",line));
771 continue;
774 if (count >= 4) {
775 DEBUG(0,("getlmhostsent: too many columns in lmhosts file (obsolete syntax)\n"));
776 continue;
779 DEBUG(4, ("getlmhostsent: lmhost entry: %s %s %s\n", ip, name, flags));
781 if (strchr_m(flags,'G') || strchr_m(flags,'S')) {
782 DEBUG(0,("getlmhostsent: group flag in lmhosts ignored (obsolete)\n"));
783 continue;
786 *ipaddr = *interpret_addr2(ip);
788 /* Extra feature. If the name ends in '#XX', where XX is a hex number,
789 then only add that name type. */
790 if((ptr1 = strchr_m(name, '#')) != NULL) {
791 char *endptr;
792 ptr1++;
794 *name_type = (int)strtol(ptr1, &endptr, 16);
795 if(!*ptr1 || (endptr == ptr1)) {
796 DEBUG(0,("getlmhostsent: invalid name %s containing '#'.\n", name));
797 continue;
800 *(--ptr1) = '\0'; /* Truncate at the '#' */
803 return True;
806 return False;
809 /********************************************************
810 Finish parsing the lmhosts file.
811 *********************************************************/
813 void endlmhosts(XFILE *fp)
815 x_fclose(fp);
818 /********************************************************
819 convert an array if struct in_addrs to struct ip_service
820 return False on failure. Port is set to PORT_NONE;
821 *********************************************************/
823 static BOOL convert_ip2service( struct ip_service **return_iplist, struct in_addr *ip_list, int count )
825 int i;
827 if ( count==0 || !ip_list )
828 return False;
830 /* copy the ip address; port will be PORT_NONE */
831 if ( (*return_iplist = SMB_MALLOC_ARRAY(struct ip_service, count)) == NULL ) {
832 DEBUG(0,("convert_ip2service: malloc failed for %d enetries!\n", count ));
833 return False;
836 for ( i=0; i<count; i++ ) {
837 (*return_iplist)[i].ip = ip_list[i];
838 (*return_iplist)[i].port = PORT_NONE;
841 return True;
843 /********************************************************
844 Resolve via "bcast" method.
845 *********************************************************/
847 BOOL name_resolve_bcast(const char *name, int name_type,
848 struct ip_service **return_iplist, int *return_count)
850 int sock, i;
851 int num_interfaces = iface_count();
852 struct in_addr *ip_list;
853 BOOL ret;
855 if (lp_disable_netbios()) {
856 DEBUG(5,("name_resolve_bcast(%s#%02x): netbios is disabled\n", name, name_type));
857 return False;
860 *return_iplist = NULL;
861 *return_count = 0;
864 * "bcast" means do a broadcast lookup on all the local interfaces.
867 DEBUG(3,("name_resolve_bcast: Attempting broadcast lookup for name %s<0x%x>\n", name, name_type));
869 sock = open_socket_in( SOCK_DGRAM, 0, 3,
870 interpret_addr(lp_socket_address()), True );
872 if (sock == -1) return False;
874 set_socket_options(sock,"SO_BROADCAST");
876 * Lookup the name on all the interfaces, return on
877 * the first successful match.
879 for( i = num_interfaces-1; i >= 0; i--) {
880 struct in_addr sendto_ip;
881 int flags;
882 /* Done this way to fix compiler error on IRIX 5.x */
883 sendto_ip = *iface_n_bcast(i);
884 ip_list = name_query(sock, name, name_type, True,
885 True, sendto_ip, return_count, &flags, NULL);
886 if( ip_list )
887 goto success;
890 /* failed - no response */
892 close(sock);
893 return False;
895 success:
896 ret = True;
897 if ( !convert_ip2service(return_iplist, ip_list, *return_count) )
898 ret = False;
900 SAFE_FREE( ip_list );
901 close(sock);
902 return ret;
905 /********************************************************
906 Resolve via "wins" method.
907 *********************************************************/
909 BOOL resolve_wins(const char *name, int name_type,
910 struct ip_service **return_iplist, int *return_count)
912 int sock, t, i;
913 char **wins_tags;
914 struct in_addr src_ip, *ip_list = NULL;
915 BOOL ret;
917 if (lp_disable_netbios()) {
918 DEBUG(5,("resolve_wins(%s#%02x): netbios is disabled\n", name, name_type));
919 return False;
922 *return_iplist = NULL;
923 *return_count = 0;
925 DEBUG(3,("resolve_wins: Attempting wins lookup for name %s<0x%x>\n", name, name_type));
927 if (wins_srv_count() < 1) {
928 DEBUG(3,("resolve_wins: WINS server resolution selected and no WINS servers listed.\n"));
929 return False;
932 /* we try a lookup on each of the WINS tags in turn */
933 wins_tags = wins_srv_tags();
935 if (!wins_tags) {
936 /* huh? no tags?? give up in disgust */
937 return False;
940 /* the address we will be sending from */
941 src_ip = *interpret_addr2(lp_socket_address());
943 /* in the worst case we will try every wins server with every
944 tag! */
945 for (t=0; wins_tags && wins_tags[t]; t++) {
946 int srv_count = wins_srv_count_tag(wins_tags[t]);
947 for (i=0; i<srv_count; i++) {
948 struct in_addr wins_ip;
949 int flags;
950 BOOL timed_out;
952 wins_ip = wins_srv_ip_tag(wins_tags[t], src_ip);
954 if (global_in_nmbd && ismyip(wins_ip)) {
955 /* yikes! we'll loop forever */
956 continue;
959 /* skip any that have been unresponsive lately */
960 if (wins_srv_is_dead(wins_ip, src_ip)) {
961 continue;
964 DEBUG(3,("resolve_wins: using WINS server %s and tag '%s'\n", inet_ntoa(wins_ip), wins_tags[t]));
966 sock = open_socket_in(SOCK_DGRAM, 0, 3, src_ip.s_addr, True);
967 if (sock == -1) {
968 continue;
971 ip_list = name_query(sock,name,name_type, False,
972 True, wins_ip, return_count, &flags,
973 &timed_out);
975 /* exit loop if we got a list of addresses */
977 if ( ip_list )
978 goto success;
980 close(sock);
982 if (timed_out) {
983 /* Timed out wating for WINS server to respond. Mark it dead. */
984 wins_srv_died(wins_ip, src_ip);
985 } else {
986 /* The name definately isn't in this
987 group of WINS servers. goto the next group */
988 break;
993 wins_srv_tags_free(wins_tags);
994 return False;
996 success:
997 ret = True;
998 if ( !convert_ip2service( return_iplist, ip_list, *return_count ) )
999 ret = False;
1001 SAFE_FREE( ip_list );
1002 wins_srv_tags_free(wins_tags);
1003 close(sock);
1005 return ret;
1008 /********************************************************
1009 Resolve via "lmhosts" method.
1010 *********************************************************/
1012 static BOOL resolve_lmhosts(const char *name, int name_type,
1013 struct ip_service **return_iplist, int *return_count)
1016 * "lmhosts" means parse the local lmhosts file.
1019 XFILE *fp;
1020 pstring lmhost_name;
1021 int name_type2;
1022 struct in_addr return_ip;
1023 BOOL result = False;
1025 *return_iplist = NULL;
1026 *return_count = 0;
1028 DEBUG(3,("resolve_lmhosts: Attempting lmhosts lookup for name %s<0x%x>\n", name, name_type));
1030 fp = startlmhosts(dyn_LMHOSTSFILE);
1032 if ( fp == NULL )
1033 return False;
1035 while (getlmhostsent(fp, lmhost_name, &name_type2, &return_ip))
1038 if (!strequal(name, lmhost_name))
1039 continue;
1041 if ((name_type2 != -1) && (name_type != name_type2))
1042 continue;
1044 *return_iplist = SMB_REALLOC_ARRAY((*return_iplist), struct ip_service,
1045 (*return_count)+1);
1047 if ((*return_iplist) == NULL) {
1048 endlmhosts(fp);
1049 DEBUG(3,("resolve_lmhosts: malloc fail !\n"));
1050 return False;
1053 (*return_iplist)[*return_count].ip = return_ip;
1054 (*return_iplist)[*return_count].port = PORT_NONE;
1055 *return_count += 1;
1057 /* we found something */
1058 result = True;
1060 /* Multiple names only for DC lookup */
1061 if (name_type != 0x1c)
1062 break;
1065 endlmhosts(fp);
1067 return result;
1071 /********************************************************
1072 Resolve via "hosts" method.
1073 *********************************************************/
1075 static BOOL resolve_hosts(const char *name, int name_type,
1076 struct ip_service **return_iplist, int *return_count)
1079 * "host" means do a localhost, or dns lookup.
1081 struct hostent *hp;
1083 if ( name_type != 0x20 && name_type != 0x0) {
1084 DEBUG(5, ("resolve_hosts: not appropriate for name type <0x%x>\n", name_type));
1085 return False;
1088 *return_iplist = NULL;
1089 *return_count = 0;
1091 DEBUG(3,("resolve_hosts: Attempting host lookup for name %s<0x%x>\n", name, name_type));
1093 if (((hp = sys_gethostbyname(name)) != NULL) && (hp->h_addr != NULL)) {
1094 struct in_addr return_ip;
1095 putip((char *)&return_ip,(char *)hp->h_addr);
1096 *return_iplist = SMB_MALLOC_P(struct ip_service);
1097 if(*return_iplist == NULL) {
1098 DEBUG(3,("resolve_hosts: malloc fail !\n"));
1099 return False;
1101 (*return_iplist)->ip = return_ip;
1102 (*return_iplist)->port = PORT_NONE;
1103 *return_count = 1;
1104 return True;
1106 return False;
1109 /********************************************************
1110 Resolve via "ADS" method.
1111 *********************************************************/
1113 static BOOL resolve_ads(const char *name, int name_type,
1114 const char *sitename,
1115 struct ip_service **return_iplist, int *return_count)
1117 int i, j;
1118 NTSTATUS status;
1119 TALLOC_CTX *ctx;
1120 struct dns_rr_srv *dcs = NULL;
1121 int numdcs = 0;
1122 int numaddrs = 0;
1124 if ((name_type != 0x1c) && (name_type != KDC_NAME_TYPE))
1125 return False;
1127 DEBUG(5,("resolve_ads: Attempting to resolve DC's for %s using DNS\n",
1128 name));
1130 if ( (ctx = talloc_init("resolve_ads")) == NULL ) {
1131 DEBUG(0,("resolve_ads: talloc_init() failed!\n"));
1132 return False;
1135 if (name_type == KDC_NAME_TYPE) {
1136 status = ads_dns_query_kdcs(ctx, name, sitename, &dcs, &numdcs);
1137 } else {
1138 status = ads_dns_query_dcs(ctx, name, sitename, &dcs, &numdcs);
1140 if ( !NT_STATUS_IS_OK( status ) ) {
1141 talloc_destroy(ctx);
1142 return False;
1145 for (i=0;i<numdcs;i++) {
1146 numaddrs += MAX(dcs[i].num_ips,1);
1149 if ( (*return_iplist = SMB_MALLOC_ARRAY(struct ip_service, numaddrs)) == NULL ) {
1150 DEBUG(0,("resolve_ads: malloc failed for %d entries\n", numaddrs ));
1151 talloc_destroy(ctx);
1152 return False;
1155 /* now unroll the list of IP addresses */
1157 *return_count = 0;
1158 i = 0;
1159 j = 0;
1160 while ( i < numdcs && (*return_count<numaddrs) ) {
1161 struct ip_service *r = &(*return_iplist)[*return_count];
1163 r->port = dcs[i].port;
1165 /* If we don't have an IP list for a name, lookup it up */
1167 if ( !dcs[i].ips ) {
1168 r->ip = *interpret_addr2(dcs[i].hostname);
1169 i++;
1170 j = 0;
1171 } else {
1172 /* use the IP addresses from the SRV sresponse */
1174 if ( j >= dcs[i].num_ips ) {
1175 i++;
1176 j = 0;
1177 continue;
1180 r->ip = dcs[i].ips[j];
1181 j++;
1184 /* make sure it is a valid IP. I considered checking the negative
1185 connection cache, but this is the wrong place for it. Maybe only
1186 as a hac. After think about it, if all of the IP addresses retuend
1187 from DNS are dead, what hope does a netbios name lookup have?
1188 The standard reason for falling back to netbios lookups is that
1189 our DNS server doesn't know anything about the DC's -- jerry */
1191 if ( ! is_zero_ip(r->ip) )
1192 (*return_count)++;
1195 talloc_destroy(ctx);
1196 return True;
1199 /*******************************************************************
1200 Internal interface to resolve a name into an IP address.
1201 Use this function if the string is either an IP address, DNS
1202 or host name or NetBIOS name. This uses the name switch in the
1203 smb.conf to determine the order of name resolution.
1205 Added support for ip addr/port to support ADS ldap servers.
1206 the only place we currently care about the port is in the
1207 resolve_hosts() when looking up DC's via SRV RR entries in DNS
1208 **********************************************************************/
1210 BOOL internal_resolve_name(const char *name, int name_type,
1211 const char *sitename,
1212 struct ip_service **return_iplist,
1213 int *return_count, const char *resolve_order)
1215 pstring name_resolve_list;
1216 fstring tok;
1217 const char *ptr;
1218 BOOL allones = (strcmp(name,"255.255.255.255") == 0);
1219 BOOL allzeros = (strcmp(name,"0.0.0.0") == 0);
1220 BOOL is_address = is_ipaddress(name);
1221 BOOL result = False;
1222 int i;
1224 *return_iplist = NULL;
1225 *return_count = 0;
1227 DEBUG(10, ("internal_resolve_name: looking up %s#%x (sitename %s)\n",
1228 name, name_type, sitename ? sitename : "(null)"));
1230 if (allzeros || allones || is_address) {
1232 if ( (*return_iplist = SMB_MALLOC_P(struct ip_service)) == NULL ) {
1233 DEBUG(0,("internal_resolve_name: malloc fail !\n"));
1234 return False;
1237 if(is_address) {
1238 /* ignore the port here */
1239 (*return_iplist)->port = PORT_NONE;
1241 /* if it's in the form of an IP address then get the lib to interpret it */
1242 if (((*return_iplist)->ip.s_addr = inet_addr(name)) == 0xFFFFFFFF ){
1243 DEBUG(1,("internal_resolve_name: inet_addr failed on %s\n", name));
1244 SAFE_FREE(*return_iplist);
1245 return False;
1247 } else {
1248 (*return_iplist)->ip.s_addr = allones ? 0xFFFFFFFF : 0;
1250 *return_count = 1;
1251 return True;
1254 /* Check name cache */
1256 if (namecache_fetch(name, name_type, return_iplist, return_count)) {
1257 /* This could be a negative response */
1258 return (*return_count > 0);
1261 /* set the name resolution order */
1263 if ( strcmp( resolve_order, "NULL") == 0 ) {
1264 DEBUG(8,("internal_resolve_name: all lookups disabled\n"));
1265 return False;
1268 if ( !resolve_order ) {
1269 pstrcpy(name_resolve_list, lp_name_resolve_order());
1270 } else {
1271 pstrcpy(name_resolve_list, resolve_order);
1274 if ( !name_resolve_list[0] ) {
1275 ptr = "host";
1276 } else {
1277 ptr = name_resolve_list;
1280 /* iterate through the name resolution backends */
1282 while (next_token(&ptr, tok, LIST_SEP, sizeof(tok))) {
1283 if((strequal(tok, "host") || strequal(tok, "hosts"))) {
1284 if (resolve_hosts(name, name_type, return_iplist, return_count)) {
1285 result = True;
1286 goto done;
1288 } else if(strequal( tok, "kdc")) {
1289 /* deal with KDC_NAME_TYPE names here. This will result in a
1290 SRV record lookup */
1291 if (resolve_ads(name, KDC_NAME_TYPE, sitename, return_iplist, return_count)) {
1292 result = True;
1293 /* Ensure we don't namecache this with the KDC port. */
1294 name_type = KDC_NAME_TYPE;
1295 goto done;
1297 } else if(strequal( tok, "ads")) {
1298 /* deal with 0x1c names here. This will result in a
1299 SRV record lookup */
1300 if (resolve_ads(name, name_type, sitename, return_iplist, return_count)) {
1301 result = True;
1302 goto done;
1304 } else if(strequal( tok, "lmhosts")) {
1305 if (resolve_lmhosts(name, name_type, return_iplist, return_count)) {
1306 result = True;
1307 goto done;
1309 } else if(strequal( tok, "wins")) {
1310 /* don't resolve 1D via WINS */
1311 if (name_type != 0x1D && resolve_wins(name, name_type, return_iplist, return_count)) {
1312 result = True;
1313 goto done;
1315 } else if(strequal( tok, "bcast")) {
1316 if (name_resolve_bcast(name, name_type, return_iplist, return_count)) {
1317 result = True;
1318 goto done;
1320 } else {
1321 DEBUG(0,("resolve_name: unknown name switch type %s\n", tok));
1325 /* All of the resolve_* functions above have returned false. */
1327 SAFE_FREE(*return_iplist);
1328 *return_count = 0;
1330 return False;
1332 done:
1334 /* Remove duplicate entries. Some queries, notably #1c (domain
1335 controllers) return the PDC in iplist[0] and then all domain
1336 controllers including the PDC in iplist[1..n]. Iterating over
1337 the iplist when the PDC is down will cause two sets of timeouts. */
1339 if ( *return_count ) {
1340 *return_count = remove_duplicate_addrs2( *return_iplist, *return_count );
1343 /* Save in name cache */
1344 if ( DEBUGLEVEL >= 100 ) {
1345 for (i = 0; i < *return_count && DEBUGLEVEL == 100; i++)
1346 DEBUG(100, ("Storing name %s of type %d (%s:%d)\n", name,
1347 name_type, inet_ntoa((*return_iplist)[i].ip), (*return_iplist)[i].port));
1350 namecache_store(name, name_type, *return_count, *return_iplist);
1352 /* Display some debugging info */
1354 if ( DEBUGLEVEL >= 10 ) {
1355 DEBUG(10, ("internal_resolve_name: returning %d addresses: ", *return_count));
1357 for (i = 0; i < *return_count; i++) {
1358 DEBUGADD(10, ("%s:%d ", inet_ntoa((*return_iplist)[i].ip), (*return_iplist)[i].port));
1360 DEBUG(10, ("\n"));
1363 return result;
1366 /********************************************************
1367 Internal interface to resolve a name into one IP address.
1368 Use this function if the string is either an IP address, DNS
1369 or host name or NetBIOS name. This uses the name switch in the
1370 smb.conf to determine the order of name resolution.
1371 *********************************************************/
1373 BOOL resolve_name(const char *name, struct in_addr *return_ip, int name_type)
1375 struct ip_service *ip_list = NULL;
1376 char *sitename = sitename_fetch(lp_realm()); /* wild guess */
1377 int count = 0;
1379 if (is_ipaddress(name)) {
1380 *return_ip = *interpret_addr2(name);
1381 SAFE_FREE(sitename);
1382 return True;
1385 if (internal_resolve_name(name, name_type, sitename, &ip_list, &count, lp_name_resolve_order())) {
1386 int i;
1388 /* only return valid addresses for TCP connections */
1389 for (i=0; i<count; i++) {
1390 char *ip_str = inet_ntoa(ip_list[i].ip);
1391 if (ip_str &&
1392 strcmp(ip_str, "255.255.255.255") != 0 &&
1393 strcmp(ip_str, "0.0.0.0") != 0)
1395 *return_ip = ip_list[i].ip;
1396 SAFE_FREE(ip_list);
1397 SAFE_FREE(sitename);
1398 return True;
1403 SAFE_FREE(ip_list);
1404 SAFE_FREE(sitename);
1405 return False;
1408 /********************************************************
1409 Find the IP address of the master browser or DMB for a workgroup.
1410 *********************************************************/
1412 BOOL find_master_ip(const char *group, struct in_addr *master_ip)
1414 struct ip_service *ip_list = NULL;
1415 int count = 0;
1417 if (lp_disable_netbios()) {
1418 DEBUG(5,("find_master_ip(%s): netbios is disabled\n", group));
1419 return False;
1422 if (internal_resolve_name(group, 0x1D, NULL, &ip_list, &count, lp_name_resolve_order())) {
1423 *master_ip = ip_list[0].ip;
1424 SAFE_FREE(ip_list);
1425 return True;
1427 if(internal_resolve_name(group, 0x1B, NULL, &ip_list, &count, lp_name_resolve_order())) {
1428 *master_ip = ip_list[0].ip;
1429 SAFE_FREE(ip_list);
1430 return True;
1433 SAFE_FREE(ip_list);
1434 return False;
1437 /********************************************************
1438 Get the IP address list of the primary domain controller
1439 for a domain.
1440 *********************************************************/
1442 BOOL get_pdc_ip(const char *domain, struct in_addr *ip)
1444 struct ip_service *ip_list = NULL;
1445 int count = 0;
1447 /* Look up #1B name */
1449 if (!internal_resolve_name(domain, 0x1b, NULL, &ip_list, &count, lp_name_resolve_order())) {
1450 return False;
1453 /* if we get more than 1 IP back we have to assume it is a
1454 multi-homed PDC and not a mess up */
1456 if ( count > 1 ) {
1457 DEBUG(6,("get_pdc_ip: PDC has %d IP addresses!\n", count));
1458 sort_ip_list2( ip_list, count );
1461 *ip = ip_list[0].ip;
1463 SAFE_FREE(ip_list);
1465 return True;
1468 /* Private enum type for lookups. */
1470 enum dc_lookup_type { DC_NORMAL_LOOKUP, DC_ADS_ONLY, DC_KDC_ONLY };
1472 /********************************************************
1473 Get the IP address list of the domain controllers for
1474 a domain.
1475 *********************************************************/
1477 static NTSTATUS get_dc_list(const char *domain, const char *sitename, struct ip_service **ip_list,
1478 int *count, enum dc_lookup_type lookup_type, int *ordered)
1480 fstring resolve_order;
1481 char *saf_servername;
1482 pstring pserver;
1483 const char *p;
1484 char *port_str;
1485 int port;
1486 fstring name;
1487 int num_addresses = 0;
1488 int local_count, i, j;
1489 struct ip_service *return_iplist = NULL;
1490 struct ip_service *auto_ip_list = NULL;
1491 BOOL done_auto_lookup = False;
1492 int auto_count = 0;
1493 NTSTATUS status;
1495 *ip_list = NULL;
1496 *count = 0;
1498 *ordered = False;
1500 /* if we are restricted to solely using DNS for looking
1501 up a domain controller, make sure that host lookups
1502 are enabled for the 'name resolve order'. If host lookups
1503 are disabled and ads_only is True, then set the string to
1504 NULL. */
1506 fstrcpy( resolve_order, lp_name_resolve_order() );
1507 strlower_m( resolve_order );
1508 if ( lookup_type == DC_ADS_ONLY) {
1509 if ( strstr( resolve_order, "host" ) ) {
1510 fstrcpy( resolve_order, "ads" );
1512 /* DNS SRV lookups used by the ads resolver
1513 are already sorted by priority and weight */
1514 *ordered = True;
1515 } else {
1516 fstrcpy( resolve_order, "NULL" );
1518 } else if (lookup_type == DC_KDC_ONLY) {
1519 /* DNS SRV lookups used by the ads/kdc resolver
1520 are already sorted by priority and weight */
1521 *ordered = True;
1522 fstrcpy( resolve_order, "kdc" );
1525 /* fetch the server we have affinity for. Add the
1526 'password server' list to a search for our domain controllers */
1528 saf_servername = saf_fetch( domain);
1530 if ( strequal(domain, lp_workgroup()) || strequal(domain, lp_realm()) ) {
1531 pstr_sprintf( pserver, "%s, %s",
1532 saf_servername ? saf_servername : "",
1533 lp_passwordserver() );
1534 } else {
1535 pstr_sprintf( pserver, "%s, *",
1536 saf_servername ? saf_servername : "" );
1539 SAFE_FREE( saf_servername );
1541 /* if we are starting from scratch, just lookup DOMAIN<0x1c> */
1543 if ( !*pserver ) {
1544 DEBUG(10,("get_dc_list: no preferred domain controllers.\n"));
1545 /* TODO: change return type of internal_resolve_name to
1546 * NTSTATUS */
1547 if (internal_resolve_name(domain, 0x1C, sitename, ip_list, count,
1548 resolve_order)) {
1549 status = NT_STATUS_OK;
1550 goto out;
1551 } else {
1552 status = NT_STATUS_NO_LOGON_SERVERS;
1553 goto out;
1557 DEBUG(3,("get_dc_list: preferred server list: \"%s\"\n", pserver ));
1560 * if '*' appears in the "password server" list then add
1561 * an auto lookup to the list of manually configured
1562 * DC's. If any DC is listed by name, then the list should be
1563 * considered to be ordered
1566 p = pserver;
1567 while (next_token(&p,name,LIST_SEP,sizeof(name))) {
1568 if (!done_auto_lookup && strequal(name, "*")) {
1569 if (internal_resolve_name(domain, 0x1C, sitename, &auto_ip_list,
1570 &auto_count, resolve_order))
1571 num_addresses += auto_count;
1572 done_auto_lookup = True;
1573 DEBUG(8,("Adding %d DC's from auto lookup\n", auto_count));
1574 } else {
1575 num_addresses++;
1579 /* if we have no addresses and haven't done the auto lookup, then
1580 just return the list of DC's. Or maybe we just failed. */
1582 if ( (num_addresses == 0) ) {
1583 if ( done_auto_lookup ) {
1584 DEBUG(4,("get_dc_list: no servers found\n"));
1585 status = NT_STATUS_NO_LOGON_SERVERS;
1586 goto out;
1588 if (internal_resolve_name(domain, 0x1C, sitename, ip_list, count,
1589 resolve_order)) {
1590 status = NT_STATUS_OK;
1591 goto out;
1592 } else {
1593 status = NT_STATUS_NO_LOGON_SERVERS;
1594 goto out;
1598 if ( (return_iplist = SMB_MALLOC_ARRAY(struct ip_service, num_addresses)) == NULL ) {
1599 DEBUG(3,("get_dc_list: malloc fail !\n"));
1600 status = NT_STATUS_NO_MEMORY;
1601 goto out;
1604 p = pserver;
1605 local_count = 0;
1607 /* fill in the return list now with real IP's */
1609 while ( (local_count<num_addresses) && next_token(&p,name,LIST_SEP,sizeof(name)) ) {
1610 struct in_addr name_ip;
1612 /* copy any addersses from the auto lookup */
1614 if ( strequal(name, "*") ) {
1615 for ( j=0; j<auto_count; j++ ) {
1616 /* Check for and don't copy any known bad DC IP's. */
1617 if(!NT_STATUS_IS_OK(check_negative_conn_cache(domain,
1618 inet_ntoa(auto_ip_list[j].ip)))) {
1619 DEBUG(5,("get_dc_list: negative entry %s removed from DC list\n",
1620 inet_ntoa(auto_ip_list[j].ip) ));
1621 continue;
1623 return_iplist[local_count].ip = auto_ip_list[j].ip;
1624 return_iplist[local_count].port = auto_ip_list[j].port;
1625 local_count++;
1627 continue;
1631 /* added support for address:port syntax for ads (not that I think
1632 anyone will ever run the LDAP server in an AD domain on something
1633 other than port 389 */
1635 port = (lp_security() == SEC_ADS) ? LDAP_PORT : PORT_NONE;
1636 if ( (port_str=strchr(name, ':')) != NULL ) {
1637 *port_str = '\0';
1638 port_str++;
1639 port = atoi( port_str );
1642 /* explicit lookup; resolve_name() will handle names & IP addresses */
1643 if ( resolve_name( name, &name_ip, 0x20 ) ) {
1645 /* Check for and don't copy any known bad DC IP's. */
1646 if( !NT_STATUS_IS_OK(check_negative_conn_cache(domain, inet_ntoa(name_ip))) ) {
1647 DEBUG(5,("get_dc_list: negative entry %s removed from DC list\n",name ));
1648 continue;
1651 return_iplist[local_count].ip = name_ip;
1652 return_iplist[local_count].port = port;
1653 local_count++;
1654 *ordered = True;
1658 /* need to remove duplicates in the list if we have any
1659 explicit password servers */
1661 if ( local_count ) {
1662 local_count = remove_duplicate_addrs2( return_iplist, local_count );
1665 if ( DEBUGLEVEL >= 4 ) {
1666 DEBUG(4,("get_dc_list: returning %d ip addresses in an %sordered list\n", local_count,
1667 *ordered ? "":"un"));
1668 DEBUG(4,("get_dc_list: "));
1669 for ( i=0; i<local_count; i++ )
1670 DEBUGADD(4,("%s:%d ", inet_ntoa(return_iplist[i].ip), return_iplist[i].port ));
1671 DEBUGADD(4,("\n"));
1674 *ip_list = return_iplist;
1675 *count = local_count;
1677 status = ( *count != 0 ? NT_STATUS_OK : NT_STATUS_NO_LOGON_SERVERS );
1679 out:
1681 if (!NT_STATUS_IS_OK(status)) {
1682 SAFE_FREE(return_iplist);
1683 *ip_list = NULL;
1684 *count = 0;
1687 SAFE_FREE(auto_ip_list);
1689 return status;
1692 /*********************************************************************
1693 Small wrapper function to get the DC list and sort it if neccessary.
1694 *********************************************************************/
1696 NTSTATUS get_sorted_dc_list( const char *domain, const char *sitename, struct ip_service **ip_list, int *count, BOOL ads_only )
1698 BOOL ordered;
1699 NTSTATUS status;
1700 enum dc_lookup_type lookup_type = DC_NORMAL_LOOKUP;
1702 DEBUG(8,("get_sorted_dc_list: attempting lookup for name %s (sitename %s) "
1703 "using [%s]\n",
1704 domain,
1705 sitename ? sitename : "NULL",
1706 (ads_only ? "ads" : lp_name_resolve_order())));
1708 if (ads_only) {
1709 lookup_type = DC_ADS_ONLY;
1712 status = get_dc_list(domain, sitename, ip_list, count, lookup_type, &ordered);
1713 if (NT_STATUS_EQUAL(status, NT_STATUS_NO_LOGON_SERVERS) && sitename) {
1714 DEBUG(3,("get_sorted_dc_list: no server for name %s available"
1715 " in site %s, fallback to all servers\n",
1716 domain, sitename));
1717 status = get_dc_list(domain, NULL, ip_list, count,
1718 lookup_type, &ordered);
1721 if (!NT_STATUS_IS_OK(status)) {
1722 return status;
1725 /* only sort if we don't already have an ordered list */
1726 if ( !ordered ) {
1727 sort_ip_list2( *ip_list, *count );
1730 return NT_STATUS_OK;
1733 /*********************************************************************
1734 Get the KDC list - re-use all the logic in get_dc_list.
1735 *********************************************************************/
1737 NTSTATUS get_kdc_list( const char *realm, const char *sitename, struct ip_service **ip_list, int *count)
1739 BOOL ordered;
1740 NTSTATUS status;
1742 *count = 0;
1743 *ip_list = NULL;
1745 status = get_dc_list(realm, sitename, ip_list, count, DC_KDC_ONLY, &ordered);
1747 if (!NT_STATUS_IS_OK(status)) {
1748 return status;
1751 /* only sort if we don't already have an ordered list */
1752 if ( !ordered ) {
1753 sort_ip_list2( *ip_list, *count );
1756 return NT_STATUS_OK;