r23784: use the GPLv3 boilerplate as recommended by the FSF and the license text
[Samba/bb.git] / source / libsmb / namequery.c
blobf0bef3ef96e20de58c5fb27b286356f32a96c5b2
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 3 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, see <http://www.gnu.org/licenses/>.
20 #include "includes.h"
22 /* nmbd.c sets this to True. */
23 BOOL global_in_nmbd = False;
25 /****************************
26 * SERVER AFFINITY ROUTINES *
27 ****************************/
29 /* Server affinity is the concept of preferring the last domain
30 controller with whom you had a successful conversation */
32 /****************************************************************************
33 ****************************************************************************/
34 #define SAFKEY_FMT "SAF/DOMAIN/%s"
35 #define SAF_TTL 900
37 static char *saf_key(const char *domain)
39 char *keystr;
41 asprintf( &keystr, SAFKEY_FMT, strupper_static(domain) );
43 return keystr;
46 /****************************************************************************
47 ****************************************************************************/
49 BOOL saf_store( const char *domain, const char *servername )
51 char *key;
52 time_t expire;
53 BOOL ret = False;
55 if ( !domain || !servername ) {
56 DEBUG(2,("saf_store: Refusing to store empty domain or servername!\n"));
57 return False;
60 if ( (strlen(domain) == 0) || (strlen(servername) == 0) ) {
61 DEBUG(0,("saf_store: refusing to store 0 length domain or servername!\n"));
62 return False;
65 if ( !gencache_init() )
66 return False;
68 key = saf_key( domain );
69 expire = time( NULL ) + SAF_TTL;
72 DEBUG(10,("saf_store: domain = [%s], server = [%s], expire = [%u]\n",
73 domain, servername, (unsigned int)expire ));
75 ret = gencache_set( key, servername, expire );
77 SAFE_FREE( key );
79 return ret;
82 BOOL saf_delete( const char *domain )
84 char *key;
85 BOOL ret = False;
87 if ( !domain ) {
88 DEBUG(2,("saf_delete: Refusing to delete empty domain\n"));
89 return False;
92 if ( !gencache_init() )
93 return False;
95 key = saf_key(domain);
96 ret = gencache_del(key);
98 if (ret) {
99 DEBUG(10,("saf_delete: domain = [%s]\n", domain ));
102 SAFE_FREE( key );
104 return ret;
107 /****************************************************************************
108 ****************************************************************************/
110 char *saf_fetch( const char *domain )
112 char *server = NULL;
113 time_t timeout;
114 BOOL ret = False;
115 char *key = NULL;
117 if ( !domain || strlen(domain) == 0) {
118 DEBUG(2,("saf_fetch: Empty domain name!\n"));
119 return NULL;
122 if ( !gencache_init() )
123 return False;
125 key = saf_key( domain );
127 ret = gencache_get( key, &server, &timeout );
129 SAFE_FREE( key );
131 if ( !ret ) {
132 DEBUG(5,("saf_fetch: failed to find server for \"%s\" domain\n", domain ));
133 } else {
134 DEBUG(5,("saf_fetch: Returning \"%s\" for \"%s\" domain\n",
135 server, domain ));
138 return server;
141 /****************************************************************************
142 Generate a random trn_id.
143 ****************************************************************************/
145 static int generate_trn_id(void)
147 uint16 id;
149 generate_random_buffer((uint8 *)&id, sizeof(id));
151 return id % (unsigned)0x7FFF;
154 /****************************************************************************
155 Parse a node status response into an array of structures.
156 ****************************************************************************/
158 static NODE_STATUS_STRUCT *parse_node_status(char *p, int *num_names, struct node_status_extra *extra)
160 NODE_STATUS_STRUCT *ret;
161 int i;
163 *num_names = CVAL(p,0);
165 if (*num_names == 0)
166 return NULL;
168 ret = SMB_MALLOC_ARRAY(NODE_STATUS_STRUCT,*num_names);
169 if (!ret)
170 return NULL;
172 p++;
173 for (i=0;i< *num_names;i++) {
174 StrnCpy(ret[i].name,p,15);
175 trim_char(ret[i].name,'\0',' ');
176 ret[i].type = CVAL(p,15);
177 ret[i].flags = p[16];
178 p += 18;
179 DEBUG(10, ("%s#%02x: flags = 0x%02x\n", ret[i].name,
180 ret[i].type, ret[i].flags));
183 * Also, pick up the MAC address ...
185 if (extra) {
186 memcpy(&extra->mac_addr, p, 6); /* Fill in the mac addr */
188 return ret;
192 /****************************************************************************
193 Do a NBT node status query on an open socket and return an array of
194 structures holding the returned names or NULL if the query failed.
195 **************************************************************************/
197 NODE_STATUS_STRUCT *node_status_query(int fd,struct nmb_name *name,
198 struct in_addr to_ip, int *num_names,
199 struct node_status_extra *extra)
201 BOOL found=False;
202 int retries = 2;
203 int retry_time = 2000;
204 struct timeval tval;
205 struct packet_struct p;
206 struct packet_struct *p2;
207 struct nmb_packet *nmb = &p.packet.nmb;
208 NODE_STATUS_STRUCT *ret;
210 ZERO_STRUCT(p);
212 nmb->header.name_trn_id = generate_trn_id();
213 nmb->header.opcode = 0;
214 nmb->header.response = False;
215 nmb->header.nm_flags.bcast = False;
216 nmb->header.nm_flags.recursion_available = False;
217 nmb->header.nm_flags.recursion_desired = False;
218 nmb->header.nm_flags.trunc = False;
219 nmb->header.nm_flags.authoritative = False;
220 nmb->header.rcode = 0;
221 nmb->header.qdcount = 1;
222 nmb->header.ancount = 0;
223 nmb->header.nscount = 0;
224 nmb->header.arcount = 0;
225 nmb->question.question_name = *name;
226 nmb->question.question_type = 0x21;
227 nmb->question.question_class = 0x1;
229 p.ip = to_ip;
230 p.port = NMB_PORT;
231 p.fd = fd;
232 p.timestamp = time(NULL);
233 p.packet_type = NMB_PACKET;
235 GetTimeOfDay(&tval);
237 if (!send_packet(&p))
238 return NULL;
240 retries--;
242 while (1) {
243 struct timeval tval2;
244 GetTimeOfDay(&tval2);
245 if (TvalDiff(&tval,&tval2) > retry_time) {
246 if (!retries)
247 break;
248 if (!found && !send_packet(&p))
249 return NULL;
250 GetTimeOfDay(&tval);
251 retries--;
254 if ((p2=receive_nmb_packet(fd,90,nmb->header.name_trn_id))) {
255 struct nmb_packet *nmb2 = &p2->packet.nmb;
256 debug_nmb_packet(p2);
258 if (nmb2->header.opcode != 0 ||
259 nmb2->header.nm_flags.bcast ||
260 nmb2->header.rcode ||
261 !nmb2->header.ancount ||
262 nmb2->answers->rr_type != 0x21) {
263 /* XXXX what do we do with this? could be a
264 redirect, but we'll discard it for the
265 moment */
266 free_packet(p2);
267 continue;
270 ret = parse_node_status(&nmb2->answers->rdata[0], num_names, extra);
271 free_packet(p2);
272 return ret;
276 return NULL;
279 /****************************************************************************
280 Find the first type XX name in a node status reply - used for finding
281 a servers name given its IP. Return the matched name in *name.
282 **************************************************************************/
284 BOOL name_status_find(const char *q_name, int q_type, int type, struct in_addr to_ip, fstring name)
286 NODE_STATUS_STRUCT *status = NULL;
287 struct nmb_name nname;
288 int count, i;
289 int sock;
290 BOOL result = False;
292 if (lp_disable_netbios()) {
293 DEBUG(5,("name_status_find(%s#%02x): netbios is disabled\n", q_name, q_type));
294 return False;
297 DEBUG(10, ("name_status_find: looking up %s#%02x at %s\n", q_name,
298 q_type, inet_ntoa(to_ip)));
300 /* Check the cache first. */
302 if (namecache_status_fetch(q_name, q_type, type, to_ip, name))
303 return True;
305 sock = open_socket_in(SOCK_DGRAM, 0, 3, interpret_addr(lp_socket_address()), True);
306 if (sock == -1)
307 goto done;
309 /* W2K PDC's seem not to respond to '*'#0. JRA */
310 make_nmb_name(&nname, q_name, q_type);
311 status = node_status_query(sock, &nname, to_ip, &count, NULL);
312 close(sock);
313 if (!status)
314 goto done;
316 for (i=0;i<count;i++) {
317 if (status[i].type == type)
318 break;
320 if (i == count)
321 goto done;
323 pull_ascii_nstring(name, sizeof(fstring), status[i].name);
325 /* Store the result in the cache. */
326 /* but don't store an entry for 0x1c names here. Here we have
327 a single host and DOMAIN<0x1c> names should be a list of hosts */
329 if ( q_type != 0x1c )
330 namecache_status_store(q_name, q_type, type, to_ip, name);
332 result = True;
334 done:
335 SAFE_FREE(status);
337 DEBUG(10, ("name_status_find: name %sfound", result ? "" : "not "));
339 if (result)
340 DEBUGADD(10, (", name %s ip address is %s", name, inet_ntoa(to_ip)));
342 DEBUG(10, ("\n"));
344 return result;
348 comparison function used by sort_ip_list
351 static int ip_compare(struct in_addr *ip1, struct in_addr *ip2)
353 int max_bits1=0, max_bits2=0;
354 int num_interfaces = iface_count();
355 int i;
357 for (i=0;i<num_interfaces;i++) {
358 struct in_addr ip;
359 int bits1, bits2;
360 ip = *iface_n_bcast(i);
361 bits1 = matching_quad_bits((uchar *)&ip1->s_addr, (uchar *)&ip.s_addr);
362 bits2 = matching_quad_bits((uchar *)&ip2->s_addr, (uchar *)&ip.s_addr);
363 max_bits1 = MAX(bits1, max_bits1);
364 max_bits2 = MAX(bits2, max_bits2);
367 /* bias towards directly reachable IPs */
368 if (iface_local(*ip1)) {
369 max_bits1 += 32;
371 if (iface_local(*ip2)) {
372 max_bits2 += 32;
375 return max_bits2 - max_bits1;
378 /*******************************************************************
379 compare 2 ldap IPs by nearness to our interfaces - used in qsort
380 *******************************************************************/
382 int ip_service_compare(struct ip_service *ip1, struct ip_service *ip2)
384 int result;
386 if ( (result = ip_compare(&ip1->ip, &ip2->ip)) != 0 )
387 return result;
389 if ( ip1->port > ip2->port )
390 return 1;
392 if ( ip1->port < ip2->port )
393 return -1;
395 return 0;
399 sort an IP list so that names that are close to one of our interfaces
400 are at the top. This prevents the problem where a WINS server returns an IP that
401 is not reachable from our subnet as the first match
404 static void sort_ip_list(struct in_addr *iplist, int count)
406 if (count <= 1) {
407 return;
410 qsort(iplist, count, sizeof(struct in_addr), QSORT_CAST ip_compare);
413 static void sort_ip_list2(struct ip_service *iplist, int count)
415 if (count <= 1) {
416 return;
419 qsort(iplist, count, sizeof(struct ip_service), QSORT_CAST ip_service_compare);
422 /**********************************************************************
423 Remove any duplicate address/port pairs in the list
424 *********************************************************************/
426 static int remove_duplicate_addrs2( struct ip_service *iplist, int count )
428 int i, j;
430 DEBUG(10,("remove_duplicate_addrs2: looking for duplicate address/port pairs\n"));
432 /* one loop to remove duplicates */
433 for ( i=0; i<count; i++ ) {
434 if ( is_zero_ip(iplist[i].ip) )
435 continue;
437 for ( j=i+1; j<count; j++ ) {
438 if ( ip_service_equal(iplist[i], iplist[j]) )
439 zero_ip(&iplist[j].ip);
443 /* one loop to clean up any holes we left */
444 /* first ip should never be a zero_ip() */
445 for (i = 0; i<count; ) {
446 if ( is_zero_ip(iplist[i].ip) ) {
447 if (i != count-1 )
448 memmove(&iplist[i], &iplist[i+1], (count - i - 1)*sizeof(iplist[i]));
449 count--;
450 continue;
452 i++;
455 return count;
458 /****************************************************************************
459 Do a netbios name query to find someones IP.
460 Returns an array of IP addresses or NULL if none.
461 *count will be set to the number of addresses returned.
462 *timed_out is set if we failed by timing out
463 ****************************************************************************/
465 struct in_addr *name_query(int fd,const char *name,int name_type,
466 BOOL bcast,BOOL recurse,
467 struct in_addr to_ip, int *count, int *flags,
468 BOOL *timed_out)
470 BOOL found=False;
471 int i, retries = 3;
472 int retry_time = bcast?250:2000;
473 struct timeval tval;
474 struct packet_struct p;
475 struct packet_struct *p2;
476 struct nmb_packet *nmb = &p.packet.nmb;
477 struct in_addr *ip_list = NULL;
479 if (lp_disable_netbios()) {
480 DEBUG(5,("name_query(%s#%02x): netbios is disabled\n", name, name_type));
481 return NULL;
484 if (timed_out) {
485 *timed_out = False;
488 memset((char *)&p,'\0',sizeof(p));
489 (*count) = 0;
490 (*flags) = 0;
492 nmb->header.name_trn_id = generate_trn_id();
493 nmb->header.opcode = 0;
494 nmb->header.response = False;
495 nmb->header.nm_flags.bcast = bcast;
496 nmb->header.nm_flags.recursion_available = False;
497 nmb->header.nm_flags.recursion_desired = recurse;
498 nmb->header.nm_flags.trunc = False;
499 nmb->header.nm_flags.authoritative = False;
500 nmb->header.rcode = 0;
501 nmb->header.qdcount = 1;
502 nmb->header.ancount = 0;
503 nmb->header.nscount = 0;
504 nmb->header.arcount = 0;
506 make_nmb_name(&nmb->question.question_name,name,name_type);
508 nmb->question.question_type = 0x20;
509 nmb->question.question_class = 0x1;
511 p.ip = to_ip;
512 p.port = NMB_PORT;
513 p.fd = fd;
514 p.timestamp = time(NULL);
515 p.packet_type = NMB_PACKET;
517 GetTimeOfDay(&tval);
519 if (!send_packet(&p))
520 return NULL;
522 retries--;
524 while (1) {
525 struct timeval tval2;
527 GetTimeOfDay(&tval2);
528 if (TvalDiff(&tval,&tval2) > retry_time) {
529 if (!retries)
530 break;
531 if (!found && !send_packet(&p))
532 return NULL;
533 GetTimeOfDay(&tval);
534 retries--;
537 if ((p2=receive_nmb_packet(fd,90,nmb->header.name_trn_id))) {
538 struct nmb_packet *nmb2 = &p2->packet.nmb;
539 debug_nmb_packet(p2);
541 /* If we get a Negative Name Query Response from a WINS
542 * server, we should report it and give up.
544 if( 0 == nmb2->header.opcode /* A query response */
545 && !(bcast) /* from a WINS server */
546 && nmb2->header.rcode /* Error returned */
549 if( DEBUGLVL( 3 ) ) {
550 /* Only executed if DEBUGLEVEL >= 3 */
551 dbgtext( "Negative name query response, rcode 0x%02x: ", nmb2->header.rcode );
552 switch( nmb2->header.rcode ) {
553 case 0x01:
554 dbgtext( "Request was invalidly formatted.\n" );
555 break;
556 case 0x02:
557 dbgtext( "Problem with NBNS, cannot process name.\n");
558 break;
559 case 0x03:
560 dbgtext( "The name requested does not exist.\n" );
561 break;
562 case 0x04:
563 dbgtext( "Unsupported request error.\n" );
564 break;
565 case 0x05:
566 dbgtext( "Query refused error.\n" );
567 break;
568 default:
569 dbgtext( "Unrecognized error code.\n" );
570 break;
573 free_packet(p2);
574 return( NULL );
577 if (nmb2->header.opcode != 0 ||
578 nmb2->header.nm_flags.bcast ||
579 nmb2->header.rcode ||
580 !nmb2->header.ancount) {
582 * XXXX what do we do with this? Could be a
583 * redirect, but we'll discard it for the
584 * moment.
586 free_packet(p2);
587 continue;
590 ip_list = SMB_REALLOC_ARRAY( ip_list, struct in_addr,
591 (*count) + nmb2->answers->rdlength/6 );
593 if (!ip_list) {
594 DEBUG(0,("name_query: Realloc failed.\n"));
595 free_packet(p2);
596 return( NULL );
599 DEBUG(2,("Got a positive name query response from %s ( ", inet_ntoa(p2->ip)));
600 for (i=0;i<nmb2->answers->rdlength/6;i++) {
601 putip((char *)&ip_list[(*count)],&nmb2->answers->rdata[2+i*6]);
602 DEBUGADD(2,("%s ",inet_ntoa(ip_list[(*count)])));
603 (*count)++;
605 DEBUGADD(2,(")\n"));
607 found=True;
608 retries=0;
609 /* We add the flags back ... */
610 if (nmb2->header.response)
611 (*flags) |= NM_FLAGS_RS;
612 if (nmb2->header.nm_flags.authoritative)
613 (*flags) |= NM_FLAGS_AA;
614 if (nmb2->header.nm_flags.trunc)
615 (*flags) |= NM_FLAGS_TC;
616 if (nmb2->header.nm_flags.recursion_desired)
617 (*flags) |= NM_FLAGS_RD;
618 if (nmb2->header.nm_flags.recursion_available)
619 (*flags) |= NM_FLAGS_RA;
620 if (nmb2->header.nm_flags.bcast)
621 (*flags) |= NM_FLAGS_B;
622 free_packet(p2);
624 * If we're doing a unicast lookup we only
625 * expect one reply. Don't wait the full 2
626 * seconds if we got one. JRA.
628 if(!bcast && found)
629 break;
633 /* only set timed_out if we didn't fund what we where looking for*/
635 if ( !found && timed_out ) {
636 *timed_out = True;
639 /* sort the ip list so we choose close servers first if possible */
640 sort_ip_list(ip_list, *count);
642 return ip_list;
645 /********************************************************
646 Start parsing the lmhosts file.
647 *********************************************************/
649 XFILE *startlmhosts(const char *fname)
651 XFILE *fp = x_fopen(fname,O_RDONLY, 0);
652 if (!fp) {
653 DEBUG(4,("startlmhosts: Can't open lmhosts file %s. Error was %s\n",
654 fname, strerror(errno)));
655 return NULL;
657 return fp;
660 /********************************************************
661 Parse the next line in the lmhosts file.
662 *********************************************************/
664 BOOL getlmhostsent( XFILE *fp, pstring name, int *name_type, struct in_addr *ipaddr)
666 pstring line;
668 while(!x_feof(fp) && !x_ferror(fp)) {
669 pstring ip,flags,extra;
670 const char *ptr;
671 char *ptr1;
672 int count = 0;
674 *name_type = -1;
676 if (!fgets_slash(line,sizeof(pstring),fp)) {
677 continue;
680 if (*line == '#') {
681 continue;
684 pstrcpy(ip,"");
685 pstrcpy(name,"");
686 pstrcpy(flags,"");
688 ptr = line;
690 if (next_token(&ptr,ip ,NULL,sizeof(ip)))
691 ++count;
692 if (next_token(&ptr,name ,NULL, sizeof(pstring)))
693 ++count;
694 if (next_token(&ptr,flags,NULL, sizeof(flags)))
695 ++count;
696 if (next_token(&ptr,extra,NULL, sizeof(extra)))
697 ++count;
699 if (count <= 0)
700 continue;
702 if (count > 0 && count < 2) {
703 DEBUG(0,("getlmhostsent: Ill formed hosts line [%s]\n",line));
704 continue;
707 if (count >= 4) {
708 DEBUG(0,("getlmhostsent: too many columns in lmhosts file (obsolete syntax)\n"));
709 continue;
712 DEBUG(4, ("getlmhostsent: lmhost entry: %s %s %s\n", ip, name, flags));
714 if (strchr_m(flags,'G') || strchr_m(flags,'S')) {
715 DEBUG(0,("getlmhostsent: group flag in lmhosts ignored (obsolete)\n"));
716 continue;
719 *ipaddr = *interpret_addr2(ip);
721 /* Extra feature. If the name ends in '#XX', where XX is a hex number,
722 then only add that name type. */
723 if((ptr1 = strchr_m(name, '#')) != NULL) {
724 char *endptr;
725 ptr1++;
727 *name_type = (int)strtol(ptr1, &endptr, 16);
728 if(!*ptr1 || (endptr == ptr1)) {
729 DEBUG(0,("getlmhostsent: invalid name %s containing '#'.\n", name));
730 continue;
733 *(--ptr1) = '\0'; /* Truncate at the '#' */
736 return True;
739 return False;
742 /********************************************************
743 Finish parsing the lmhosts file.
744 *********************************************************/
746 void endlmhosts(XFILE *fp)
748 x_fclose(fp);
751 /********************************************************
752 convert an array if struct in_addrs to struct ip_service
753 return False on failure. Port is set to PORT_NONE;
754 *********************************************************/
756 static BOOL convert_ip2service( struct ip_service **return_iplist, struct in_addr *ip_list, int count )
758 int i;
760 if ( count==0 || !ip_list )
761 return False;
763 /* copy the ip address; port will be PORT_NONE */
764 if ( (*return_iplist = SMB_MALLOC_ARRAY(struct ip_service, count)) == NULL ) {
765 DEBUG(0,("convert_ip2service: malloc failed for %d enetries!\n", count ));
766 return False;
769 for ( i=0; i<count; i++ ) {
770 (*return_iplist)[i].ip = ip_list[i];
771 (*return_iplist)[i].port = PORT_NONE;
774 return True;
776 /********************************************************
777 Resolve via "bcast" method.
778 *********************************************************/
780 BOOL name_resolve_bcast(const char *name, int name_type,
781 struct ip_service **return_iplist, int *return_count)
783 int sock, i;
784 int num_interfaces = iface_count();
785 struct in_addr *ip_list;
786 BOOL ret;
788 if (lp_disable_netbios()) {
789 DEBUG(5,("name_resolve_bcast(%s#%02x): netbios is disabled\n", name, name_type));
790 return False;
793 *return_iplist = NULL;
794 *return_count = 0;
797 * "bcast" means do a broadcast lookup on all the local interfaces.
800 DEBUG(3,("name_resolve_bcast: Attempting broadcast lookup for name %s<0x%x>\n", name, name_type));
802 sock = open_socket_in( SOCK_DGRAM, 0, 3,
803 interpret_addr(lp_socket_address()), True );
805 if (sock == -1) return False;
807 set_socket_options(sock,"SO_BROADCAST");
809 * Lookup the name on all the interfaces, return on
810 * the first successful match.
812 for( i = num_interfaces-1; i >= 0; i--) {
813 struct in_addr sendto_ip;
814 int flags;
815 /* Done this way to fix compiler error on IRIX 5.x */
816 sendto_ip = *iface_n_bcast(i);
817 ip_list = name_query(sock, name, name_type, True,
818 True, sendto_ip, return_count, &flags, NULL);
819 if( ip_list )
820 goto success;
823 /* failed - no response */
825 close(sock);
826 return False;
828 success:
829 ret = True;
830 if ( !convert_ip2service(return_iplist, ip_list, *return_count) )
831 ret = False;
833 SAFE_FREE( ip_list );
834 close(sock);
835 return ret;
838 /********************************************************
839 Resolve via "wins" method.
840 *********************************************************/
842 BOOL resolve_wins(const char *name, int name_type,
843 struct ip_service **return_iplist, int *return_count)
845 int sock, t, i;
846 char **wins_tags;
847 struct in_addr src_ip, *ip_list = NULL;
848 BOOL ret;
850 if (lp_disable_netbios()) {
851 DEBUG(5,("resolve_wins(%s#%02x): netbios is disabled\n", name, name_type));
852 return False;
855 *return_iplist = NULL;
856 *return_count = 0;
858 DEBUG(3,("resolve_wins: Attempting wins lookup for name %s<0x%x>\n", name, name_type));
860 if (wins_srv_count() < 1) {
861 DEBUG(3,("resolve_wins: WINS server resolution selected and no WINS servers listed.\n"));
862 return False;
865 /* we try a lookup on each of the WINS tags in turn */
866 wins_tags = wins_srv_tags();
868 if (!wins_tags) {
869 /* huh? no tags?? give up in disgust */
870 return False;
873 /* the address we will be sending from */
874 src_ip = *interpret_addr2(lp_socket_address());
876 /* in the worst case we will try every wins server with every
877 tag! */
878 for (t=0; wins_tags && wins_tags[t]; t++) {
879 int srv_count = wins_srv_count_tag(wins_tags[t]);
880 for (i=0; i<srv_count; i++) {
881 struct in_addr wins_ip;
882 int flags;
883 BOOL timed_out;
885 wins_ip = wins_srv_ip_tag(wins_tags[t], src_ip);
887 if (global_in_nmbd && ismyip(wins_ip)) {
888 /* yikes! we'll loop forever */
889 continue;
892 /* skip any that have been unresponsive lately */
893 if (wins_srv_is_dead(wins_ip, src_ip)) {
894 continue;
897 DEBUG(3,("resolve_wins: using WINS server %s and tag '%s'\n", inet_ntoa(wins_ip), wins_tags[t]));
899 sock = open_socket_in(SOCK_DGRAM, 0, 3, src_ip.s_addr, True);
900 if (sock == -1) {
901 continue;
904 ip_list = name_query(sock,name,name_type, False,
905 True, wins_ip, return_count, &flags,
906 &timed_out);
908 /* exit loop if we got a list of addresses */
910 if ( ip_list )
911 goto success;
913 close(sock);
915 if (timed_out) {
916 /* Timed out wating for WINS server to respond. Mark it dead. */
917 wins_srv_died(wins_ip, src_ip);
918 } else {
919 /* The name definately isn't in this
920 group of WINS servers. goto the next group */
921 break;
926 wins_srv_tags_free(wins_tags);
927 return False;
929 success:
930 ret = True;
931 if ( !convert_ip2service( return_iplist, ip_list, *return_count ) )
932 ret = False;
934 SAFE_FREE( ip_list );
935 wins_srv_tags_free(wins_tags);
936 close(sock);
938 return ret;
941 /********************************************************
942 Resolve via "lmhosts" method.
943 *********************************************************/
945 static BOOL resolve_lmhosts(const char *name, int name_type,
946 struct ip_service **return_iplist, int *return_count)
949 * "lmhosts" means parse the local lmhosts file.
952 XFILE *fp;
953 pstring lmhost_name;
954 int name_type2;
955 struct in_addr return_ip;
956 BOOL result = False;
958 *return_iplist = NULL;
959 *return_count = 0;
961 DEBUG(3,("resolve_lmhosts: Attempting lmhosts lookup for name %s<0x%x>\n", name, name_type));
963 fp = startlmhosts(dyn_LMHOSTSFILE);
965 if ( fp == NULL )
966 return False;
968 while (getlmhostsent(fp, lmhost_name, &name_type2, &return_ip))
971 if (!strequal(name, lmhost_name))
972 continue;
974 if ((name_type2 != -1) && (name_type != name_type2))
975 continue;
977 *return_iplist = SMB_REALLOC_ARRAY((*return_iplist), struct ip_service,
978 (*return_count)+1);
980 if ((*return_iplist) == NULL) {
981 endlmhosts(fp);
982 DEBUG(3,("resolve_lmhosts: malloc fail !\n"));
983 return False;
986 (*return_iplist)[*return_count].ip = return_ip;
987 (*return_iplist)[*return_count].port = PORT_NONE;
988 *return_count += 1;
990 /* we found something */
991 result = True;
993 /* Multiple names only for DC lookup */
994 if (name_type != 0x1c)
995 break;
998 endlmhosts(fp);
1000 return result;
1004 /********************************************************
1005 Resolve via "hosts" method.
1006 *********************************************************/
1008 static BOOL resolve_hosts(const char *name, int name_type,
1009 struct ip_service **return_iplist, int *return_count)
1012 * "host" means do a localhost, or dns lookup.
1014 struct hostent *hp;
1016 if ( name_type != 0x20 && name_type != 0x0) {
1017 DEBUG(5, ("resolve_hosts: not appropriate for name type <0x%x>\n", name_type));
1018 return False;
1021 *return_iplist = NULL;
1022 *return_count = 0;
1024 DEBUG(3,("resolve_hosts: Attempting host lookup for name %s<0x%x>\n", name, name_type));
1026 if (((hp = sys_gethostbyname(name)) != NULL) && (hp->h_addr != NULL)) {
1027 struct in_addr return_ip;
1028 putip((char *)&return_ip,(char *)hp->h_addr);
1029 *return_iplist = SMB_MALLOC_P(struct ip_service);
1030 if(*return_iplist == NULL) {
1031 DEBUG(3,("resolve_hosts: malloc fail !\n"));
1032 return False;
1034 (*return_iplist)->ip = return_ip;
1035 (*return_iplist)->port = PORT_NONE;
1036 *return_count = 1;
1037 return True;
1039 return False;
1042 /********************************************************
1043 Resolve via "ADS" method.
1044 *********************************************************/
1046 static BOOL resolve_ads(const char *name, int name_type,
1047 const char *sitename,
1048 struct ip_service **return_iplist, int *return_count)
1050 int i, j;
1051 NTSTATUS status;
1052 TALLOC_CTX *ctx;
1053 struct dns_rr_srv *dcs = NULL;
1054 int numdcs = 0;
1055 int numaddrs = 0;
1057 if ((name_type != 0x1c) && (name_type != KDC_NAME_TYPE))
1058 return False;
1060 DEBUG(5,("resolve_ads: Attempting to resolve DC's for %s using DNS\n",
1061 name));
1063 if ( (ctx = talloc_init("resolve_ads")) == NULL ) {
1064 DEBUG(0,("resolve_ads: talloc_init() failed!\n"));
1065 return False;
1068 if (name_type == KDC_NAME_TYPE) {
1069 status = ads_dns_query_kdcs(ctx, name, sitename, &dcs, &numdcs);
1070 } else {
1071 status = ads_dns_query_dcs(ctx, name, sitename, &dcs, &numdcs);
1073 if ( !NT_STATUS_IS_OK( status ) ) {
1074 talloc_destroy(ctx);
1075 return False;
1078 for (i=0;i<numdcs;i++) {
1079 numaddrs += MAX(dcs[i].num_ips,1);
1082 if ( (*return_iplist = SMB_MALLOC_ARRAY(struct ip_service, numaddrs)) == NULL ) {
1083 DEBUG(0,("resolve_ads: malloc failed for %d entries\n", numaddrs ));
1084 talloc_destroy(ctx);
1085 return False;
1088 /* now unroll the list of IP addresses */
1090 *return_count = 0;
1091 i = 0;
1092 j = 0;
1093 while ( i < numdcs && (*return_count<numaddrs) ) {
1094 struct ip_service *r = &(*return_iplist)[*return_count];
1096 r->port = dcs[i].port;
1098 /* If we don't have an IP list for a name, lookup it up */
1100 if ( !dcs[i].ips ) {
1101 r->ip = *interpret_addr2(dcs[i].hostname);
1102 i++;
1103 j = 0;
1104 } else {
1105 /* use the IP addresses from the SRV sresponse */
1107 if ( j >= dcs[i].num_ips ) {
1108 i++;
1109 j = 0;
1110 continue;
1113 r->ip = dcs[i].ips[j];
1114 j++;
1117 /* make sure it is a valid IP. I considered checking the negative
1118 connection cache, but this is the wrong place for it. Maybe only
1119 as a hac. After think about it, if all of the IP addresses retuend
1120 from DNS are dead, what hope does a netbios name lookup have?
1121 The standard reason for falling back to netbios lookups is that
1122 our DNS server doesn't know anything about the DC's -- jerry */
1124 if ( ! is_zero_ip(r->ip) )
1125 (*return_count)++;
1128 talloc_destroy(ctx);
1129 return True;
1132 /*******************************************************************
1133 Internal interface to resolve a name into an IP address.
1134 Use this function if the string is either an IP address, DNS
1135 or host name or NetBIOS name. This uses the name switch in the
1136 smb.conf to determine the order of name resolution.
1138 Added support for ip addr/port to support ADS ldap servers.
1139 the only place we currently care about the port is in the
1140 resolve_hosts() when looking up DC's via SRV RR entries in DNS
1141 **********************************************************************/
1143 BOOL internal_resolve_name(const char *name, int name_type,
1144 const char *sitename,
1145 struct ip_service **return_iplist,
1146 int *return_count, const char *resolve_order)
1148 pstring name_resolve_list;
1149 fstring tok;
1150 const char *ptr;
1151 BOOL allones = (strcmp(name,"255.255.255.255") == 0);
1152 BOOL allzeros = (strcmp(name,"0.0.0.0") == 0);
1153 BOOL is_address = is_ipaddress(name);
1154 BOOL result = False;
1155 int i;
1157 *return_iplist = NULL;
1158 *return_count = 0;
1160 DEBUG(10, ("internal_resolve_name: looking up %s#%x (sitename %s)\n",
1161 name, name_type, sitename ? sitename : NULL));
1163 if (allzeros || allones || is_address) {
1165 if ( (*return_iplist = SMB_MALLOC_P(struct ip_service)) == NULL ) {
1166 DEBUG(0,("internal_resolve_name: malloc fail !\n"));
1167 return False;
1170 if(is_address) {
1171 /* ignore the port here */
1172 (*return_iplist)->port = PORT_NONE;
1174 /* if it's in the form of an IP address then get the lib to interpret it */
1175 if (((*return_iplist)->ip.s_addr = inet_addr(name)) == 0xFFFFFFFF ){
1176 DEBUG(1,("internal_resolve_name: inet_addr failed on %s\n", name));
1177 SAFE_FREE(*return_iplist);
1178 return False;
1180 } else {
1181 (*return_iplist)->ip.s_addr = allones ? 0xFFFFFFFF : 0;
1183 *return_count = 1;
1184 return True;
1187 /* Check name cache */
1189 if (namecache_fetch(name, name_type, return_iplist, return_count)) {
1190 /* This could be a negative response */
1191 return (*return_count > 0);
1194 /* set the name resolution order */
1196 if ( strcmp( resolve_order, "NULL") == 0 ) {
1197 DEBUG(8,("internal_resolve_name: all lookups disabled\n"));
1198 return False;
1201 if ( !resolve_order ) {
1202 pstrcpy(name_resolve_list, lp_name_resolve_order());
1203 } else {
1204 pstrcpy(name_resolve_list, resolve_order);
1207 if ( !name_resolve_list[0] ) {
1208 ptr = "host";
1209 } else {
1210 ptr = name_resolve_list;
1213 /* iterate through the name resolution backends */
1215 while (next_token(&ptr, tok, LIST_SEP, sizeof(tok))) {
1216 if((strequal(tok, "host") || strequal(tok, "hosts"))) {
1217 if (resolve_hosts(name, name_type, return_iplist, return_count)) {
1218 result = True;
1219 goto done;
1221 } else if(strequal( tok, "kdc")) {
1222 /* deal with KDC_NAME_TYPE names here. This will result in a
1223 SRV record lookup */
1224 if (resolve_ads(name, KDC_NAME_TYPE, sitename, return_iplist, return_count)) {
1225 result = True;
1226 /* Ensure we don't namecache this with the KDC port. */
1227 name_type = KDC_NAME_TYPE;
1228 goto done;
1230 } else if(strequal( tok, "ads")) {
1231 /* deal with 0x1c names here. This will result in a
1232 SRV record lookup */
1233 if (resolve_ads(name, name_type, sitename, return_iplist, return_count)) {
1234 result = True;
1235 goto done;
1237 } else if(strequal( tok, "lmhosts")) {
1238 if (resolve_lmhosts(name, name_type, return_iplist, return_count)) {
1239 result = True;
1240 goto done;
1242 } else if(strequal( tok, "wins")) {
1243 /* don't resolve 1D via WINS */
1244 if (name_type != 0x1D && resolve_wins(name, name_type, return_iplist, return_count)) {
1245 result = True;
1246 goto done;
1248 } else if(strequal( tok, "bcast")) {
1249 if (name_resolve_bcast(name, name_type, return_iplist, return_count)) {
1250 result = True;
1251 goto done;
1253 } else {
1254 DEBUG(0,("resolve_name: unknown name switch type %s\n", tok));
1258 /* All of the resolve_* functions above have returned false. */
1260 SAFE_FREE(*return_iplist);
1261 *return_count = 0;
1263 return False;
1265 done:
1267 /* Remove duplicate entries. Some queries, notably #1c (domain
1268 controllers) return the PDC in iplist[0] and then all domain
1269 controllers including the PDC in iplist[1..n]. Iterating over
1270 the iplist when the PDC is down will cause two sets of timeouts. */
1272 if ( *return_count ) {
1273 *return_count = remove_duplicate_addrs2( *return_iplist, *return_count );
1276 /* Save in name cache */
1277 if ( DEBUGLEVEL >= 100 ) {
1278 for (i = 0; i < *return_count && DEBUGLEVEL == 100; i++)
1279 DEBUG(100, ("Storing name %s of type %d (%s:%d)\n", name,
1280 name_type, inet_ntoa((*return_iplist)[i].ip), (*return_iplist)[i].port));
1283 namecache_store(name, name_type, *return_count, *return_iplist);
1285 /* Display some debugging info */
1287 if ( DEBUGLEVEL >= 10 ) {
1288 DEBUG(10, ("internal_resolve_name: returning %d addresses: ", *return_count));
1290 for (i = 0; i < *return_count; i++) {
1291 DEBUGADD(10, ("%s:%d ", inet_ntoa((*return_iplist)[i].ip), (*return_iplist)[i].port));
1293 DEBUG(10, ("\n"));
1296 return result;
1299 /********************************************************
1300 Internal interface to resolve a name into one IP address.
1301 Use this function if the string is either an IP address, DNS
1302 or host name or NetBIOS name. This uses the name switch in the
1303 smb.conf to determine the order of name resolution.
1304 *********************************************************/
1306 BOOL resolve_name(const char *name, struct in_addr *return_ip, int name_type)
1308 struct ip_service *ip_list = NULL;
1309 char *sitename = sitename_fetch(lp_realm()); /* wild guess */
1310 int count = 0;
1312 if (is_ipaddress(name)) {
1313 *return_ip = *interpret_addr2(name);
1314 SAFE_FREE(sitename);
1315 return True;
1318 if (internal_resolve_name(name, name_type, sitename, &ip_list, &count, lp_name_resolve_order())) {
1319 int i;
1321 /* only return valid addresses for TCP connections */
1322 for (i=0; i<count; i++) {
1323 char *ip_str = inet_ntoa(ip_list[i].ip);
1324 if (ip_str &&
1325 strcmp(ip_str, "255.255.255.255") != 0 &&
1326 strcmp(ip_str, "0.0.0.0") != 0)
1328 *return_ip = ip_list[i].ip;
1329 SAFE_FREE(ip_list);
1330 SAFE_FREE(sitename);
1331 return True;
1336 SAFE_FREE(ip_list);
1337 SAFE_FREE(sitename);
1338 return False;
1341 /********************************************************
1342 Find the IP address of the master browser or DMB for a workgroup.
1343 *********************************************************/
1345 BOOL find_master_ip(const char *group, struct in_addr *master_ip)
1347 struct ip_service *ip_list = NULL;
1348 int count = 0;
1350 if (lp_disable_netbios()) {
1351 DEBUG(5,("find_master_ip(%s): netbios is disabled\n", group));
1352 return False;
1355 if (internal_resolve_name(group, 0x1D, NULL, &ip_list, &count, lp_name_resolve_order())) {
1356 *master_ip = ip_list[0].ip;
1357 SAFE_FREE(ip_list);
1358 return True;
1360 if(internal_resolve_name(group, 0x1B, NULL, &ip_list, &count, lp_name_resolve_order())) {
1361 *master_ip = ip_list[0].ip;
1362 SAFE_FREE(ip_list);
1363 return True;
1366 SAFE_FREE(ip_list);
1367 return False;
1370 /********************************************************
1371 Get the IP address list of the primary domain controller
1372 for a domain.
1373 *********************************************************/
1375 BOOL get_pdc_ip(const char *domain, struct in_addr *ip)
1377 struct ip_service *ip_list = NULL;
1378 int count = 0;
1380 /* Look up #1B name */
1382 if (!internal_resolve_name(domain, 0x1b, NULL, &ip_list, &count, lp_name_resolve_order())) {
1383 return False;
1386 /* if we get more than 1 IP back we have to assume it is a
1387 multi-homed PDC and not a mess up */
1389 if ( count > 1 ) {
1390 DEBUG(6,("get_pdc_ip: PDC has %d IP addresses!\n", count));
1391 sort_ip_list2( ip_list, count );
1394 *ip = ip_list[0].ip;
1396 SAFE_FREE(ip_list);
1398 return True;
1401 /* Private enum type for lookups. */
1403 enum dc_lookup_type { DC_NORMAL_LOOKUP, DC_ADS_ONLY, DC_KDC_ONLY };
1405 /********************************************************
1406 Get the IP address list of the domain controllers for
1407 a domain.
1408 *********************************************************/
1410 static NTSTATUS get_dc_list(const char *domain, const char *sitename, struct ip_service **ip_list,
1411 int *count, enum dc_lookup_type lookup_type, int *ordered)
1413 fstring resolve_order;
1414 char *saf_servername;
1415 pstring pserver;
1416 const char *p;
1417 char *port_str;
1418 int port;
1419 fstring name;
1420 int num_addresses = 0;
1421 int local_count, i, j;
1422 struct ip_service *return_iplist = NULL;
1423 struct ip_service *auto_ip_list = NULL;
1424 BOOL done_auto_lookup = False;
1425 int auto_count = 0;
1427 *ordered = False;
1429 /* if we are restricted to solely using DNS for looking
1430 up a domain controller, make sure that host lookups
1431 are enabled for the 'name resolve order'. If host lookups
1432 are disabled and ads_only is True, then set the string to
1433 NULL. */
1435 fstrcpy( resolve_order, lp_name_resolve_order() );
1436 strlower_m( resolve_order );
1437 if ( lookup_type == DC_ADS_ONLY) {
1438 if ( strstr( resolve_order, "host" ) ) {
1439 fstrcpy( resolve_order, "ads" );
1441 /* DNS SRV lookups used by the ads resolver
1442 are already sorted by priority and weight */
1443 *ordered = True;
1444 } else {
1445 fstrcpy( resolve_order, "NULL" );
1447 } else if (lookup_type == DC_KDC_ONLY) {
1448 /* DNS SRV lookups used by the ads/kdc resolver
1449 are already sorted by priority and weight */
1450 *ordered = True;
1451 fstrcpy( resolve_order, "kdc" );
1454 /* fetch the server we have affinity for. Add the
1455 'password server' list to a search for our domain controllers */
1457 saf_servername = saf_fetch( domain);
1459 if ( strequal(domain, lp_workgroup()) || strequal(domain, lp_realm()) ) {
1460 pstr_sprintf( pserver, "%s, %s",
1461 saf_servername ? saf_servername : "",
1462 lp_passwordserver() );
1463 } else {
1464 pstr_sprintf( pserver, "%s, *",
1465 saf_servername ? saf_servername : "" );
1468 SAFE_FREE( saf_servername );
1470 /* if we are starting from scratch, just lookup DOMAIN<0x1c> */
1472 if ( !*pserver ) {
1473 DEBUG(10,("get_dc_list: no preferred domain controllers.\n"));
1474 /* TODO: change return type of internal_resolve_name to
1475 * NTSTATUS */
1476 if (internal_resolve_name(domain, 0x1C, sitename, ip_list, count,
1477 resolve_order)) {
1478 return NT_STATUS_OK;
1479 } else {
1480 return NT_STATUS_NO_LOGON_SERVERS;
1484 DEBUG(3,("get_dc_list: preferred server list: \"%s\"\n", pserver ));
1487 * if '*' appears in the "password server" list then add
1488 * an auto lookup to the list of manually configured
1489 * DC's. If any DC is listed by name, then the list should be
1490 * considered to be ordered
1493 p = pserver;
1494 while (next_token(&p,name,LIST_SEP,sizeof(name))) {
1495 if (strequal(name, "*")) {
1496 if (internal_resolve_name(domain, 0x1C, sitename, &auto_ip_list,
1497 &auto_count, resolve_order))
1498 num_addresses += auto_count;
1499 done_auto_lookup = True;
1500 DEBUG(8,("Adding %d DC's from auto lookup\n", auto_count));
1501 } else {
1502 num_addresses++;
1506 /* if we have no addresses and haven't done the auto lookup, then
1507 just return the list of DC's. Or maybe we just failed. */
1509 if ( (num_addresses == 0) ) {
1510 if ( done_auto_lookup ) {
1511 DEBUG(4,("get_dc_list: no servers found\n"));
1512 SAFE_FREE(auto_ip_list);
1513 return NT_STATUS_NO_LOGON_SERVERS;
1515 if (internal_resolve_name(domain, 0x1C, sitename, ip_list, count,
1516 resolve_order)) {
1517 return NT_STATUS_OK;
1518 } else {
1519 return NT_STATUS_NO_LOGON_SERVERS;
1523 if ( (return_iplist = SMB_MALLOC_ARRAY(struct ip_service, num_addresses)) == NULL ) {
1524 DEBUG(3,("get_dc_list: malloc fail !\n"));
1525 SAFE_FREE(auto_ip_list);
1526 return NT_STATUS_NO_MEMORY;
1529 p = pserver;
1530 local_count = 0;
1532 /* fill in the return list now with real IP's */
1534 while ( (local_count<num_addresses) && next_token(&p,name,LIST_SEP,sizeof(name)) ) {
1535 struct in_addr name_ip;
1537 /* copy any addersses from the auto lookup */
1539 if ( strequal(name, "*") ) {
1540 for ( j=0; j<auto_count; j++ ) {
1541 /* Check for and don't copy any known bad DC IP's. */
1542 if(!NT_STATUS_IS_OK(check_negative_conn_cache(domain,
1543 inet_ntoa(auto_ip_list[j].ip)))) {
1544 DEBUG(5,("get_dc_list: negative entry %s removed from DC list\n",
1545 inet_ntoa(auto_ip_list[j].ip) ));
1546 continue;
1548 return_iplist[local_count].ip = auto_ip_list[j].ip;
1549 return_iplist[local_count].port = auto_ip_list[j].port;
1550 local_count++;
1552 continue;
1556 /* added support for address:port syntax for ads (not that I think
1557 anyone will ever run the LDAP server in an AD domain on something
1558 other than port 389 */
1560 port = (lp_security() == SEC_ADS) ? LDAP_PORT : PORT_NONE;
1561 if ( (port_str=strchr(name, ':')) != NULL ) {
1562 *port_str = '\0';
1563 port_str++;
1564 port = atoi( port_str );
1567 /* explicit lookup; resolve_name() will handle names & IP addresses */
1568 if ( resolve_name( name, &name_ip, 0x20 ) ) {
1570 /* Check for and don't copy any known bad DC IP's. */
1571 if( !NT_STATUS_IS_OK(check_negative_conn_cache(domain, inet_ntoa(name_ip))) ) {
1572 DEBUG(5,("get_dc_list: negative entry %s removed from DC list\n",name ));
1573 continue;
1576 return_iplist[local_count].ip = name_ip;
1577 return_iplist[local_count].port = port;
1578 local_count++;
1579 *ordered = True;
1583 SAFE_FREE(auto_ip_list);
1585 /* need to remove duplicates in the list if we have any
1586 explicit password servers */
1588 if ( local_count ) {
1589 local_count = remove_duplicate_addrs2( return_iplist, local_count );
1592 if ( DEBUGLEVEL >= 4 ) {
1593 DEBUG(4,("get_dc_list: returning %d ip addresses in an %sordered list\n", local_count,
1594 *ordered ? "":"un"));
1595 DEBUG(4,("get_dc_list: "));
1596 for ( i=0; i<local_count; i++ )
1597 DEBUGADD(4,("%s:%d ", inet_ntoa(return_iplist[i].ip), return_iplist[i].port ));
1598 DEBUGADD(4,("\n"));
1601 *ip_list = return_iplist;
1602 *count = local_count;
1604 return ( *count != 0 ? NT_STATUS_OK : NT_STATUS_NO_LOGON_SERVERS );
1607 /*********************************************************************
1608 Small wrapper function to get the DC list and sort it if neccessary.
1609 *********************************************************************/
1611 NTSTATUS get_sorted_dc_list( const char *domain, const char *sitename, struct ip_service **ip_list, int *count, BOOL ads_only )
1613 BOOL ordered;
1614 NTSTATUS status;
1615 enum dc_lookup_type lookup_type = DC_NORMAL_LOOKUP;
1617 DEBUG(8,("get_sorted_dc_list: attempting lookup for name %s (sitename %s) "
1618 "using [%s]\n",
1619 domain,
1620 sitename ? sitename : "NULL",
1621 (ads_only ? "ads" : lp_name_resolve_order())));
1623 if (ads_only) {
1624 lookup_type = DC_ADS_ONLY;
1627 status = get_dc_list(domain, sitename, ip_list, count, lookup_type, &ordered);
1628 if (!NT_STATUS_IS_OK(status)) {
1629 return status;
1632 /* only sort if we don't already have an ordered list */
1633 if ( !ordered ) {
1634 sort_ip_list2( *ip_list, *count );
1637 return NT_STATUS_OK;
1640 /*********************************************************************
1641 Get the KDC list - re-use all the logic in get_dc_list.
1642 *********************************************************************/
1644 NTSTATUS get_kdc_list( const char *realm, const char *sitename, struct ip_service **ip_list, int *count)
1646 BOOL ordered;
1647 NTSTATUS status;
1649 *count = 0;
1650 *ip_list = NULL;
1652 status = get_dc_list(realm, sitename, ip_list, count, DC_KDC_ONLY, &ordered);
1654 if (!NT_STATUS_IS_OK(status)) {
1655 return status;
1658 /* only sort if we don't already have an ordered list */
1659 if ( !ordered ) {
1660 sort_ip_list2( *ip_list, *count );
1663 return NT_STATUS_OK;