555d88fdc83343d30bf422a26cb2c84fbd01a594
[samba.git] / source3 / libsmb / namequery.c
1 /* 
2    Unix SMB/CIFS implementation.
3    name query routines
4    Copyright (C) Andrew Tridgell 1994-1998
5    
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.
10    
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.
15    
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.
19    
20 */
21
22 #include "includes.h"
23
24 /* nmbd.c sets this to True. */
25 BOOL global_in_nmbd = False;
26
27
28 /****************************
29  * SERVER AFFINITY ROUTINES *
30  ****************************/
31  
32  /* Server affinity is the concept of preferring the last domain 
33     controller with whom you had a successful conversation */
34  
35 /****************************************************************************
36 ****************************************************************************/
37 #define SAFKEY_FMT      "SAF/DOMAIN/%s"
38 #define SAF_TTL         900
39
40 static char *saf_key(const char *domain)
41 {
42         char *keystr;
43         
44         asprintf( &keystr, SAFKEY_FMT, strupper_static(domain) );
45
46         return keystr;
47 }
48
49 /****************************************************************************
50 ****************************************************************************/
51
52 BOOL saf_store( const char *domain, const char *servername )
53 {
54         char *key;
55         time_t expire;
56         BOOL ret = False;
57         
58         if ( !domain || !servername ) {
59                 DEBUG(2,("saf_store: Refusing to store empty domain or servername!\n"));
60                 return False;
61         }
62
63         if ( (strlen(domain) == 0) || (strlen(servername) == 0) ) {
64                 DEBUG(0,("saf_store: refusing to store 0 length domain or servername!\n"));
65                 return False;
66         }
67         
68         if ( !gencache_init() ) 
69                 return False;
70         
71         key = saf_key( domain );
72         expire = time( NULL ) + SAF_TTL;
73         
74         
75         DEBUG(10,("saf_store: domain = [%s], server = [%s], expire = [%u]\n",
76                 domain, servername, (unsigned int)expire ));
77                 
78         ret = gencache_set( key, servername, expire );
79         
80         SAFE_FREE( key );
81         
82         return ret;
83 }
84
85 BOOL saf_delete( const char *domain, const char *servername )
86 {
87         char *key;
88         BOOL ret = False;
89         
90         if ( !domain || !servername ) {
91                 DEBUG(2,("saf_delete: Refusing to store empty domain or servername!\n"));
92                 return False;
93         }
94         
95         if ( !gencache_init() ) 
96                 return False;
97         
98         key = saf_key(domain);
99         ret = gencache_del(key);
100         
101         if (ret) {
102                 DEBUG(10,("saf_delete: domain = [%s], server = [%s]\n",
103                         domain, servername));
104         }
105         SAFE_FREE( key );
106         return ret;
107 }
108
109 /****************************************************************************
110 ****************************************************************************/
111
112 char *saf_fetch( const char *domain )
113 {
114         char *server = NULL;
115         time_t timeout;
116         BOOL ret = False;
117         char *key = NULL;
118
119         if ( !domain || strlen(domain) == 0) {
120                 DEBUG(2,("saf_fetch: Empty domain name!\n"));
121                 return NULL;
122         }
123         
124         if ( !gencache_init() ) 
125                 return False;
126         
127         key = saf_key( domain );
128         
129         ret = gencache_get( key, &server, &timeout );
130         
131         SAFE_FREE( key );
132         
133         if ( !ret ) {
134                 DEBUG(5,("saf_fetch: failed to find server for \"%s\" domain\n", domain ));
135         } else {
136                 DEBUG(5,("saf_fetch: Returning \"%s\" for \"%s\" domain\n", 
137                         server, domain ));
138         }
139                 
140         return server;
141 }
142
143 /****************************************************************************
144  Generate a random trn_id.
145 ****************************************************************************/
146
147 static int generate_trn_id(void)
148 {
149         static int trn_id;
150
151         if (trn_id == 0) {
152                 sys_srandom(sys_getpid());
153         }
154
155         trn_id = sys_random();
156
157         return trn_id % (unsigned)0x7FFF;
158 }
159
160 /****************************************************************************
161  Parse a node status response into an array of structures.
162 ****************************************************************************/
163
164 static NODE_STATUS_STRUCT *parse_node_status(char *p, int *num_names, struct node_status_extra *extra)
165 {
166         NODE_STATUS_STRUCT *ret;
167         int i;
168
169         *num_names = CVAL(p,0);
170
171         if (*num_names == 0)
172                 return NULL;
173
174         ret = SMB_MALLOC_ARRAY(NODE_STATUS_STRUCT,*num_names);
175         if (!ret)
176                 return NULL;
177
178         p++;
179         for (i=0;i< *num_names;i++) {
180                 StrnCpy(ret[i].name,p,15);
181                 trim_char(ret[i].name,'\0',' ');
182                 ret[i].type = CVAL(p,15);
183                 ret[i].flags = p[16];
184                 p += 18;
185                 DEBUG(10, ("%s#%02x: flags = 0x%02x\n", ret[i].name, 
186                            ret[i].type, ret[i].flags));
187         }
188         /*
189          * Also, pick up the MAC address ...
190          */
191         if (extra) {
192                 memcpy(&extra->mac_addr, p, 6); /* Fill in the mac addr */
193         }
194         return ret;
195 }
196
197
198 /****************************************************************************
199  Do a NBT node status query on an open socket and return an array of
200  structures holding the returned names or NULL if the query failed.
201 **************************************************************************/
202
203 NODE_STATUS_STRUCT *node_status_query(int fd,struct nmb_name *name,
204                                       struct in_addr to_ip, int *num_names,
205                                       struct node_status_extra *extra)
206 {
207         BOOL found=False;
208         int retries = 2;
209         int retry_time = 2000;
210         struct timeval tval;
211         struct packet_struct p;
212         struct packet_struct *p2;
213         struct nmb_packet *nmb = &p.packet.nmb;
214         NODE_STATUS_STRUCT *ret;
215
216         ZERO_STRUCT(p);
217
218         nmb->header.name_trn_id = generate_trn_id();
219         nmb->header.opcode = 0;
220         nmb->header.response = False;
221         nmb->header.nm_flags.bcast = False;
222         nmb->header.nm_flags.recursion_available = False;
223         nmb->header.nm_flags.recursion_desired = False;
224         nmb->header.nm_flags.trunc = False;
225         nmb->header.nm_flags.authoritative = False;
226         nmb->header.rcode = 0;
227         nmb->header.qdcount = 1;
228         nmb->header.ancount = 0;
229         nmb->header.nscount = 0;
230         nmb->header.arcount = 0;
231         nmb->question.question_name = *name;
232         nmb->question.question_type = 0x21;
233         nmb->question.question_class = 0x1;
234
235         p.ip = to_ip;
236         p.port = NMB_PORT;
237         p.fd = fd;
238         p.timestamp = time(NULL);
239         p.packet_type = NMB_PACKET;
240         
241         GetTimeOfDay(&tval);
242   
243         if (!send_packet(&p)) 
244                 return NULL;
245
246         retries--;
247
248         while (1) {
249                 struct timeval tval2;
250                 GetTimeOfDay(&tval2);
251                 if (TvalDiff(&tval,&tval2) > retry_time) {
252                         if (!retries)
253                                 break;
254                         if (!found && !send_packet(&p))
255                                 return NULL;
256                         GetTimeOfDay(&tval);
257                         retries--;
258                 }
259
260                 if ((p2=receive_nmb_packet(fd,90,nmb->header.name_trn_id))) {     
261                         struct nmb_packet *nmb2 = &p2->packet.nmb;
262                         debug_nmb_packet(p2);
263                         
264                         if (nmb2->header.opcode != 0 ||
265                             nmb2->header.nm_flags.bcast ||
266                             nmb2->header.rcode ||
267                             !nmb2->header.ancount ||
268                             nmb2->answers->rr_type != 0x21) {
269                                 /* XXXX what do we do with this? could be a
270                                    redirect, but we'll discard it for the
271                                    moment */
272                                 free_packet(p2);
273                                 continue;
274                         }
275
276                         ret = parse_node_status(&nmb2->answers->rdata[0], num_names, extra);
277                         free_packet(p2);
278                         return ret;
279                 }
280         }
281         
282         return NULL;
283 }
284
285 /****************************************************************************
286  Find the first type XX name in a node status reply - used for finding
287  a servers name given its IP. Return the matched name in *name.
288 **************************************************************************/
289
290 BOOL name_status_find(const char *q_name, int q_type, int type, struct in_addr to_ip, fstring name)
291 {
292         NODE_STATUS_STRUCT *status = NULL;
293         struct nmb_name nname;
294         int count, i;
295         int sock;
296         BOOL result = False;
297
298         if (lp_disable_netbios()) {
299                 DEBUG(5,("name_status_find(%s#%02x): netbios is disabled\n", q_name, q_type));
300                 return False;
301         }
302
303         DEBUG(10, ("name_status_find: looking up %s#%02x at %s\n", q_name, 
304                    q_type, inet_ntoa(to_ip)));
305
306         /* Check the cache first. */
307
308         if (namecache_status_fetch(q_name, q_type, type, to_ip, name))
309                 return True;
310
311         sock = open_socket_in(SOCK_DGRAM, 0, 3, interpret_addr(lp_socket_address()), True);
312         if (sock == -1)
313                 goto done;
314
315         /* W2K PDC's seem not to respond to '*'#0. JRA */
316         make_nmb_name(&nname, q_name, q_type);
317         status = node_status_query(sock, &nname, to_ip, &count, NULL);
318         close(sock);
319         if (!status)
320                 goto done;
321
322         for (i=0;i<count;i++) {
323                 if (status[i].type == type)
324                         break;
325         }
326         if (i == count)
327                 goto done;
328
329         pull_ascii_nstring(name, sizeof(fstring), status[i].name);
330
331         /* Store the result in the cache. */
332         /* but don't store an entry for 0x1c names here.  Here we have 
333            a single host and DOMAIN<0x1c> names should be a list of hosts */
334            
335         if ( q_type != 0x1c )
336                 namecache_status_store(q_name, q_type, type, to_ip, name);
337
338         result = True;
339
340  done:
341         SAFE_FREE(status);
342
343         DEBUG(10, ("name_status_find: name %sfound", result ? "" : "not "));
344
345         if (result)
346                 DEBUGADD(10, (", name %s ip address is %s", name, inet_ntoa(to_ip)));
347
348         DEBUG(10, ("\n"));      
349
350         return result;
351 }
352
353 /*
354   comparison function used by sort_ip_list
355 */
356
357 static int ip_compare(struct in_addr *ip1, struct in_addr *ip2)
358 {
359         int max_bits1=0, max_bits2=0;
360         int num_interfaces = iface_count();
361         int i;
362
363         for (i=0;i<num_interfaces;i++) {
364                 struct in_addr ip;
365                 int bits1, bits2;
366                 ip = *iface_n_bcast(i);
367                 bits1 = matching_quad_bits((uchar *)&ip1->s_addr, (uchar *)&ip.s_addr);
368                 bits2 = matching_quad_bits((uchar *)&ip2->s_addr, (uchar *)&ip.s_addr);
369                 max_bits1 = MAX(bits1, max_bits1);
370                 max_bits2 = MAX(bits2, max_bits2);
371         }       
372         
373         /* bias towards directly reachable IPs */
374         if (iface_local(*ip1)) {
375                 max_bits1 += 32;
376         }
377         if (iface_local(*ip2)) {
378                 max_bits2 += 32;
379         }
380
381         return max_bits2 - max_bits1;
382 }
383
384 /*******************************************************************
385  compare 2 ldap IPs by nearness to our interfaces - used in qsort
386 *******************************************************************/
387
388 static int ip_service_compare(struct ip_service *ip1, struct ip_service *ip2)
389 {
390         int result;
391         
392         if ( (result = ip_compare(&ip1->ip, &ip2->ip)) != 0 )
393                 return result;
394                 
395         if ( ip1->port > ip2->port )
396                 return 1;
397         
398         if ( ip1->port < ip2->port )
399                 return -1;
400                 
401         return 0;
402 }
403
404 /*
405   sort an IP list so that names that are close to one of our interfaces 
406   are at the top. This prevents the problem where a WINS server returns an IP that
407   is not reachable from our subnet as the first match
408 */
409
410 static void sort_ip_list(struct in_addr *iplist, int count)
411 {
412         if (count <= 1) {
413                 return;
414         }
415
416         qsort(iplist, count, sizeof(struct in_addr), QSORT_CAST ip_compare);    
417 }
418
419 static void sort_ip_list2(struct ip_service *iplist, int count)
420 {
421         if (count <= 1) {
422                 return;
423         }
424
425         qsort(iplist, count, sizeof(struct ip_service), QSORT_CAST ip_service_compare); 
426 }
427
428 /**********************************************************************
429  Remove any duplicate address/port pairs in the list 
430  *********************************************************************/
431
432 static int remove_duplicate_addrs2( struct ip_service *iplist, int count )
433 {
434         int i, j;
435         
436         DEBUG(10,("remove_duplicate_addrs2: looking for duplicate address/port pairs\n"));
437         
438         /* one loop to remove duplicates */
439         for ( i=0; i<count; i++ ) {
440                 if ( is_zero_ip(iplist[i].ip) )
441                         continue;
442                                         
443                 for ( j=i+1; j<count; j++ ) {
444                         if ( ip_service_equal(iplist[i], iplist[j]) )
445                                 zero_ip(&iplist[j].ip);
446                 }
447         }
448                         
449         /* one loop to clean up any holes we left */
450         /* first ip should never be a zero_ip() */
451         for (i = 0; i<count; ) {
452                 if ( is_zero_ip(iplist[i].ip) ) {
453                         if (i != count-1 )
454                                 memmove(&iplist[i], &iplist[i+1], (count - i - 1)*sizeof(iplist[i]));
455                         count--;
456                         continue;
457                 }
458                 i++;
459         }
460
461         return count;
462 }
463
464 /****************************************************************************
465  Do a netbios name query to find someones IP.
466  Returns an array of IP addresses or NULL if none.
467  *count will be set to the number of addresses returned.
468  *timed_out is set if we failed by timing out
469 ****************************************************************************/
470
471 struct in_addr *name_query(int fd,const char *name,int name_type, 
472                            BOOL bcast,BOOL recurse,
473                            struct in_addr to_ip, int *count, int *flags,
474                            BOOL *timed_out)
475 {
476         BOOL found=False;
477         int i, retries = 3;
478         int retry_time = bcast?250:2000;
479         struct timeval tval;
480         struct packet_struct p;
481         struct packet_struct *p2;
482         struct nmb_packet *nmb = &p.packet.nmb;
483         struct in_addr *ip_list = NULL;
484
485         if (lp_disable_netbios()) {
486                 DEBUG(5,("name_query(%s#%02x): netbios is disabled\n", name, name_type));
487                 return NULL;
488         }
489
490         if (timed_out) {
491                 *timed_out = False;
492         }
493         
494         memset((char *)&p,'\0',sizeof(p));
495         (*count) = 0;
496         (*flags) = 0;
497         
498         nmb->header.name_trn_id = generate_trn_id();
499         nmb->header.opcode = 0;
500         nmb->header.response = False;
501         nmb->header.nm_flags.bcast = bcast;
502         nmb->header.nm_flags.recursion_available = False;
503         nmb->header.nm_flags.recursion_desired = recurse;
504         nmb->header.nm_flags.trunc = False;
505         nmb->header.nm_flags.authoritative = False;
506         nmb->header.rcode = 0;
507         nmb->header.qdcount = 1;
508         nmb->header.ancount = 0;
509         nmb->header.nscount = 0;
510         nmb->header.arcount = 0;
511         
512         make_nmb_name(&nmb->question.question_name,name,name_type);
513         
514         nmb->question.question_type = 0x20;
515         nmb->question.question_class = 0x1;
516         
517         p.ip = to_ip;
518         p.port = NMB_PORT;
519         p.fd = fd;
520         p.timestamp = time(NULL);
521         p.packet_type = NMB_PACKET;
522         
523         GetTimeOfDay(&tval);
524         
525         if (!send_packet(&p)) 
526                 return NULL;
527         
528         retries--;
529         
530         while (1) {
531                 struct timeval tval2;
532                 
533                 GetTimeOfDay(&tval2);
534                 if (TvalDiff(&tval,&tval2) > retry_time) {
535                         if (!retries)
536                                 break;
537                         if (!found && !send_packet(&p))
538                                 return NULL;
539                         GetTimeOfDay(&tval);
540                         retries--;
541                 }
542                 
543                 if ((p2=receive_nmb_packet(fd,90,nmb->header.name_trn_id))) {     
544                         struct nmb_packet *nmb2 = &p2->packet.nmb;
545                         debug_nmb_packet(p2);
546                         
547                         /* If we get a Negative Name Query Response from a WINS
548                          * server, we should report it and give up.
549                          */
550                         if( 0 == nmb2->header.opcode            /* A query response   */
551                             && !(bcast)                 /* from a WINS server */
552                             && nmb2->header.rcode               /* Error returned     */
553                                 ) {
554                                 
555                                 if( DEBUGLVL( 3 ) ) {
556                                         /* Only executed if DEBUGLEVEL >= 3 */
557                                         dbgtext( "Negative name query response, rcode 0x%02x: ", nmb2->header.rcode );
558                                         switch( nmb2->header.rcode ) {
559                                         case 0x01:
560                                                 dbgtext( "Request was invalidly formatted.\n" );
561                                                 break;
562                                         case 0x02:
563                                                 dbgtext( "Problem with NBNS, cannot process name.\n");
564                                                 break;
565                                         case 0x03:
566                                                 dbgtext( "The name requested does not exist.\n" );
567                                                 break;
568                                         case 0x04:
569                                                 dbgtext( "Unsupported request error.\n" );
570                                                 break;
571                                         case 0x05:
572                                                 dbgtext( "Query refused error.\n" );
573                                                 break;
574                                         default:
575                                                 dbgtext( "Unrecognized error code.\n" );
576                                                 break;
577                                         }
578                                 }
579                                 free_packet(p2);
580                                 return( NULL );
581                         }
582                         
583                         if (nmb2->header.opcode != 0 ||
584                             nmb2->header.nm_flags.bcast ||
585                             nmb2->header.rcode ||
586                             !nmb2->header.ancount) {
587                                 /* 
588                                  * XXXX what do we do with this? Could be a
589                                  * redirect, but we'll discard it for the
590                                  * moment.
591                                  */
592                                 free_packet(p2);
593                                 continue;
594                         }
595                         
596                         ip_list = SMB_REALLOC_ARRAY( ip_list, struct in_addr,
597                                                 (*count) + nmb2->answers->rdlength/6 );
598                         
599                         if (!ip_list) {
600                                 DEBUG(0,("name_query: Realloc failed.\n"));
601                                 free_packet(p2);
602                                 return( NULL );
603                         }
604                         
605                         DEBUG(2,("Got a positive name query response from %s ( ", inet_ntoa(p2->ip)));
606                         for (i=0;i<nmb2->answers->rdlength/6;i++) {
607                                 putip((char *)&ip_list[(*count)],&nmb2->answers->rdata[2+i*6]);
608                                 DEBUGADD(2,("%s ",inet_ntoa(ip_list[(*count)])));
609                                 (*count)++;
610                         }
611                         DEBUGADD(2,(")\n"));
612                         
613                         found=True;
614                         retries=0;
615                         /* We add the flags back ... */
616                         if (nmb2->header.response)
617                                 (*flags) |= NM_FLAGS_RS;
618                         if (nmb2->header.nm_flags.authoritative)
619                                 (*flags) |= NM_FLAGS_AA;
620                         if (nmb2->header.nm_flags.trunc)
621                                 (*flags) |= NM_FLAGS_TC;
622                         if (nmb2->header.nm_flags.recursion_desired)
623                                 (*flags) |= NM_FLAGS_RD;
624                         if (nmb2->header.nm_flags.recursion_available)
625                                 (*flags) |= NM_FLAGS_RA;
626                         if (nmb2->header.nm_flags.bcast)
627                                 (*flags) |= NM_FLAGS_B;
628                         free_packet(p2);
629                         /*
630                          * If we're doing a unicast lookup we only
631                          * expect one reply. Don't wait the full 2
632                          * seconds if we got one. JRA.
633                          */
634                         if(!bcast && found)
635                                 break;
636                 }
637         }
638
639         /* only set timed_out if we didn't fund what we where looking for*/
640         
641         if ( !found && timed_out ) {
642                 *timed_out = True;
643         }
644
645         /* sort the ip list so we choose close servers first if possible */
646         sort_ip_list(ip_list, *count);
647
648         return ip_list;
649 }
650
651 /********************************************************
652  Start parsing the lmhosts file.
653 *********************************************************/
654
655 XFILE *startlmhosts(char *fname)
656 {
657         XFILE *fp = x_fopen(fname,O_RDONLY, 0);
658         if (!fp) {
659                 DEBUG(4,("startlmhosts: Can't open lmhosts file %s. Error was %s\n",
660                          fname, strerror(errno)));
661                 return NULL;
662         }
663         return fp;
664 }
665
666 /********************************************************
667  Parse the next line in the lmhosts file.
668 *********************************************************/
669
670 BOOL getlmhostsent( XFILE *fp, pstring name, int *name_type, struct in_addr *ipaddr)
671 {
672         pstring line;
673
674         while(!x_feof(fp) && !x_ferror(fp)) {
675                 pstring ip,flags,extra;
676                 const char *ptr;
677                 char *ptr1;
678                 int count = 0;
679
680                 *name_type = -1;
681
682                 if (!fgets_slash(line,sizeof(pstring),fp)) {
683                         continue;
684                 }
685
686                 if (*line == '#') {
687                         continue;
688                 }
689
690                 pstrcpy(ip,"");
691                 pstrcpy(name,"");
692                 pstrcpy(flags,"");
693
694                 ptr = line;
695
696                 if (next_token(&ptr,ip   ,NULL,sizeof(ip)))
697                         ++count;
698                 if (next_token(&ptr,name ,NULL, sizeof(pstring)))
699                         ++count;
700                 if (next_token(&ptr,flags,NULL, sizeof(flags)))
701                         ++count;
702                 if (next_token(&ptr,extra,NULL, sizeof(extra)))
703                         ++count;
704
705                 if (count <= 0)
706                         continue;
707
708                 if (count > 0 && count < 2) {
709                         DEBUG(0,("getlmhostsent: Ill formed hosts line [%s]\n",line));
710                         continue;
711                 }
712
713                 if (count >= 4) {
714                         DEBUG(0,("getlmhostsent: too many columns in lmhosts file (obsolete syntax)\n"));
715                         continue;
716                 }
717
718                 DEBUG(4, ("getlmhostsent: lmhost entry: %s %s %s\n", ip, name, flags));
719
720                 if (strchr_m(flags,'G') || strchr_m(flags,'S')) {
721                         DEBUG(0,("getlmhostsent: group flag in lmhosts ignored (obsolete)\n"));
722                         continue;
723                 }
724
725                 *ipaddr = *interpret_addr2(ip);
726
727                 /* Extra feature. If the name ends in '#XX', where XX is a hex number,
728                         then only add that name type. */
729                 if((ptr1 = strchr_m(name, '#')) != NULL) {
730                         char *endptr;
731                         ptr1++;
732
733                         *name_type = (int)strtol(ptr1, &endptr, 16);
734                         if(!*ptr1 || (endptr == ptr1)) {
735                                 DEBUG(0,("getlmhostsent: invalid name %s containing '#'.\n", name));
736                                 continue;
737                         }
738
739                         *(--ptr1) = '\0'; /* Truncate at the '#' */
740                 }
741
742                 return True;
743         }
744
745         return False;
746 }
747
748 /********************************************************
749  Finish parsing the lmhosts file.
750 *********************************************************/
751
752 void endlmhosts(XFILE *fp)
753 {
754         x_fclose(fp);
755 }
756
757 /********************************************************
758  convert an array if struct in_addrs to struct ip_service
759  return False on failure.  Port is set to PORT_NONE;
760 *********************************************************/
761
762 static BOOL convert_ip2service( struct ip_service **return_iplist, struct in_addr *ip_list, int count )
763 {
764         int i;
765
766         if ( count==0 || !ip_list )
767                 return False;
768                 
769         /* copy the ip address; port will be PORT_NONE */
770         if ( (*return_iplist = SMB_MALLOC_ARRAY(struct ip_service, count)) == NULL ) {
771                 DEBUG(0,("convert_ip2service: malloc failed for %d enetries!\n", count ));
772                 return False;
773         }
774         
775         for ( i=0; i<count; i++ ) {
776                 (*return_iplist)[i].ip   = ip_list[i];
777                 (*return_iplist)[i].port = PORT_NONE;
778         }
779
780         return True;
781 }       
782 /********************************************************
783  Resolve via "bcast" method.
784 *********************************************************/
785
786 BOOL name_resolve_bcast(const char *name, int name_type,
787                         struct ip_service **return_iplist, int *return_count)
788 {
789         int sock, i;
790         int num_interfaces = iface_count();
791         struct in_addr *ip_list;
792         BOOL ret;
793
794         if (lp_disable_netbios()) {
795                 DEBUG(5,("name_resolve_bcast(%s#%02x): netbios is disabled\n", name, name_type));
796                 return False;
797         }
798
799         *return_iplist = NULL;
800         *return_count = 0;
801         
802         /*
803          * "bcast" means do a broadcast lookup on all the local interfaces.
804          */
805
806         DEBUG(3,("name_resolve_bcast: Attempting broadcast lookup for name %s<0x%x>\n", name, name_type));
807
808         sock = open_socket_in( SOCK_DGRAM, 0, 3,
809                                interpret_addr(lp_socket_address()), True );
810
811         if (sock == -1) return False;
812
813         set_socket_options(sock,"SO_BROADCAST");
814         /*
815          * Lookup the name on all the interfaces, return on
816          * the first successful match.
817          */
818         for( i = num_interfaces-1; i >= 0; i--) {
819                 struct in_addr sendto_ip;
820                 int flags;
821                 /* Done this way to fix compiler error on IRIX 5.x */
822                 sendto_ip = *iface_n_bcast(i);
823                 ip_list = name_query(sock, name, name_type, True, 
824                                     True, sendto_ip, return_count, &flags, NULL);
825                 if( ip_list ) 
826                         goto success;
827         }
828         
829         /* failed - no response */
830         
831         close(sock);
832         return False;
833         
834 success:
835         ret = True;
836         if ( !convert_ip2service(return_iplist, ip_list, *return_count) )
837                 ret = False;
838         
839         SAFE_FREE( ip_list );
840         close(sock);
841         return ret;
842 }
843
844 /********************************************************
845  Resolve via "wins" method.
846 *********************************************************/
847
848 BOOL resolve_wins(const char *name, int name_type,
849                   struct ip_service **return_iplist, int *return_count)
850 {
851         int sock, t, i;
852         char **wins_tags;
853         struct in_addr src_ip, *ip_list = NULL;
854         BOOL ret;
855
856         if (lp_disable_netbios()) {
857                 DEBUG(5,("resolve_wins(%s#%02x): netbios is disabled\n", name, name_type));
858                 return False;
859         }
860
861         *return_iplist = NULL;
862         *return_count = 0;
863         
864         DEBUG(3,("resolve_wins: Attempting wins lookup for name %s<0x%x>\n", name, name_type));
865
866         if (wins_srv_count() < 1) {
867                 DEBUG(3,("resolve_wins: WINS server resolution selected and no WINS servers listed.\n"));
868                 return False;
869         }
870
871         /* we try a lookup on each of the WINS tags in turn */
872         wins_tags = wins_srv_tags();
873
874         if (!wins_tags) {
875                 /* huh? no tags?? give up in disgust */
876                 return False;
877         }
878
879         /* the address we will be sending from */
880         src_ip = *interpret_addr2(lp_socket_address());
881
882         /* in the worst case we will try every wins server with every
883            tag! */
884         for (t=0; wins_tags && wins_tags[t]; t++) {
885                 int srv_count = wins_srv_count_tag(wins_tags[t]);
886                 for (i=0; i<srv_count; i++) {
887                         struct in_addr wins_ip;
888                         int flags;
889                         BOOL timed_out;
890
891                         wins_ip = wins_srv_ip_tag(wins_tags[t], src_ip);
892
893                         if (global_in_nmbd && ismyip(wins_ip)) {
894                                 /* yikes! we'll loop forever */
895                                 continue;
896                         }
897
898                         /* skip any that have been unresponsive lately */
899                         if (wins_srv_is_dead(wins_ip, src_ip)) {
900                                 continue;
901                         }
902
903                         DEBUG(3,("resolve_wins: using WINS server %s and tag '%s'\n", inet_ntoa(wins_ip), wins_tags[t]));
904
905                         sock = open_socket_in(SOCK_DGRAM, 0, 3, src_ip.s_addr, True);
906                         if (sock == -1) {
907                                 continue;
908                         }
909
910                         ip_list = name_query(sock,name,name_type, False, 
911                                                     True, wins_ip, return_count, &flags, 
912                                                     &timed_out);
913                                                     
914                         /* exit loop if we got a list of addresses */
915                         
916                         if ( ip_list ) 
917                                 goto success;
918                                 
919                         close(sock);
920
921                         if (timed_out) {
922                                 /* Timed out wating for WINS server to respond.  Mark it dead. */
923                                 wins_srv_died(wins_ip, src_ip);
924                         } else {
925                                 /* The name definately isn't in this
926                                    group of WINS servers. goto the next group  */
927                                 break;
928                         }
929                 }
930         }
931
932         wins_srv_tags_free(wins_tags);
933         return False;
934
935 success:
936         ret = True;
937         if ( !convert_ip2service( return_iplist, ip_list, *return_count ) )
938                 ret = False;
939         
940         SAFE_FREE( ip_list );
941         wins_srv_tags_free(wins_tags);
942         close(sock);
943         
944         return ret;
945 }
946
947 /********************************************************
948  Resolve via "lmhosts" method.
949 *********************************************************/
950
951 static BOOL resolve_lmhosts(const char *name, int name_type,
952                          struct ip_service **return_iplist, int *return_count)
953 {
954         /*
955          * "lmhosts" means parse the local lmhosts file.
956          */
957         
958         XFILE *fp;
959         pstring lmhost_name;
960         int name_type2;
961         struct in_addr return_ip;
962         BOOL result = False;
963
964         *return_iplist = NULL;
965         *return_count = 0;
966
967         DEBUG(3,("resolve_lmhosts: Attempting lmhosts lookup for name %s<0x%x>\n", name, name_type));
968
969         fp = startlmhosts(dyn_LMHOSTSFILE);
970
971         if ( fp == NULL )
972                 return False;
973
974         while (getlmhostsent(fp, lmhost_name, &name_type2, &return_ip)) 
975         {
976
977                 if (!strequal(name, lmhost_name))
978                         continue;
979
980                 if ((name_type2 != -1) && (name_type != name_type2))
981                         continue;
982
983                 *return_iplist = SMB_REALLOC_ARRAY((*return_iplist), struct ip_service,
984                                         (*return_count)+1);
985
986                 if ((*return_iplist) == NULL) {
987                         endlmhosts(fp);
988                         DEBUG(3,("resolve_lmhosts: malloc fail !\n"));
989                         return False;
990                 }
991
992                 (*return_iplist)[*return_count].ip   = return_ip;
993                 (*return_iplist)[*return_count].port = PORT_NONE;
994                 *return_count += 1;
995
996                 /* we found something */
997                 result = True;
998
999                 /* Multiple names only for DC lookup */
1000                 if (name_type != 0x1c)
1001                         break;
1002         }
1003
1004         endlmhosts(fp);
1005
1006         return result;
1007 }
1008
1009
1010 /********************************************************
1011  Resolve via "hosts" method.
1012 *********************************************************/
1013
1014 static BOOL resolve_hosts(const char *name, int name_type,
1015                          struct ip_service **return_iplist, int *return_count)
1016 {
1017         /*
1018          * "host" means do a localhost, or dns lookup.
1019          */
1020         struct hostent *hp;
1021         
1022         if ( name_type != 0x20 && name_type != 0x0) {
1023                 DEBUG(5, ("resolve_hosts: not appropriate for name type <0x%x>\n", name_type));
1024                 return False;
1025         }
1026
1027         *return_iplist = NULL;
1028         *return_count = 0;
1029
1030         DEBUG(3,("resolve_hosts: Attempting host lookup for name %s<0x%x>\n", name, name_type));
1031         
1032         if (((hp = sys_gethostbyname(name)) != NULL) && (hp->h_addr != NULL)) {
1033                 struct in_addr return_ip;
1034                 putip((char *)&return_ip,(char *)hp->h_addr);
1035                 *return_iplist = SMB_MALLOC_P(struct ip_service);
1036                 if(*return_iplist == NULL) {
1037                         DEBUG(3,("resolve_hosts: malloc fail !\n"));
1038                         return False;
1039                 }
1040                 (*return_iplist)->ip   = return_ip;
1041                 (*return_iplist)->port = PORT_NONE;
1042                 *return_count = 1;
1043                 return True;
1044         }
1045         return False;
1046 }
1047
1048 /********************************************************
1049  Resolve via "ADS" method.
1050 *********************************************************/
1051
1052 static BOOL resolve_ads(const char *name, int name_type,
1053                          struct ip_service **return_iplist, int *return_count)
1054 {
1055         int                     i, j;
1056         NTSTATUS                status;
1057         TALLOC_CTX              *ctx;
1058         struct dns_rr_srv       *dcs = NULL;
1059         int                     numdcs = 0;
1060         int                     numaddrs = 0;
1061
1062         if ((name_type != 0x1c) && (name_type != KDC_NAME_TYPE))
1063                 return False;
1064                 
1065         DEBUG(5,("resolve_ads: Attempting to resolve DC's for %s using DNS\n",
1066                 name));
1067                         
1068         if ( (ctx = talloc_init("resolve_ads")) == NULL ) {
1069                 DEBUG(0,("resolve_ads: talloc_init() failed!\n"));
1070                 return False;
1071         }
1072
1073         if (name_type == KDC_NAME_TYPE) {
1074                 status = ads_dns_query_kdcs(ctx, name, &dcs, &numdcs);
1075         } else {
1076                 status = ads_dns_query_dcs(ctx, name, &dcs, &numdcs);
1077         }
1078         if ( !NT_STATUS_IS_OK( status ) ) {
1079                 talloc_destroy(ctx);
1080                 return False;
1081         }
1082
1083         for (i=0;i<numdcs;i++) {
1084                 numaddrs += MAX(dcs[i].num_ips,1);
1085         }
1086                 
1087         if ( (*return_iplist = SMB_MALLOC_ARRAY(struct ip_service, numaddrs)) == NULL ) {
1088                 DEBUG(0,("resolve_ads: malloc failed for %d entries\n", numaddrs ));
1089                 talloc_destroy(ctx);
1090                 return False;
1091         }
1092         
1093         /* now unroll the list of IP addresses */
1094
1095         *return_count = 0;
1096         i = 0;
1097         j = 0;
1098         while ( i < numdcs && (*return_count<numaddrs) ) {
1099                 struct ip_service *r = &(*return_iplist)[*return_count];
1100
1101                 r->port = dcs[i].port;
1102                 
1103                 /* If we don't have an IP list for a name, lookup it up */
1104                 
1105                 if ( !dcs[i].ips ) {
1106                         r->ip = *interpret_addr2(dcs[i].hostname);
1107                         i++;
1108                         j = 0;
1109                 } else {
1110                         /* use the IP addresses from the SRV sresponse */
1111                         
1112                         if ( j >= dcs[i].num_ips ) {
1113                                 i++;
1114                                 j = 0;
1115                                 continue;
1116                         }
1117                         
1118                         r->ip = dcs[i].ips[j];
1119                         j++;
1120                 }
1121                         
1122                 /* make sure it is a valid IP.  I considered checking the negative
1123                    connection cache, but this is the wrong place for it.  Maybe only
1124                    as a hac.  After think about it, if all of the IP addresses retuend
1125                    from DNS are dead, what hope does a netbios name lookup have?
1126                    The standard reason for falling back to netbios lookups is that 
1127                    our DNS server doesn't know anything about the DC's   -- jerry */    
1128                            
1129                 if ( ! is_zero_ip(r->ip) )
1130                         (*return_count)++;
1131         }
1132                 
1133         talloc_destroy(ctx);
1134         return True;
1135 }
1136
1137 /*******************************************************************
1138  Internal interface to resolve a name into an IP address.
1139  Use this function if the string is either an IP address, DNS
1140  or host name or NetBIOS name. This uses the name switch in the
1141  smb.conf to determine the order of name resolution.
1142  
1143  Added support for ip addr/port to support ADS ldap servers.
1144  the only place we currently care about the port is in the 
1145  resolve_hosts() when looking up DC's via SRV RR entries in DNS
1146 **********************************************************************/
1147
1148 BOOL internal_resolve_name(const char *name, int name_type,
1149                            struct ip_service **return_iplist, 
1150                            int *return_count, const char *resolve_order)
1151 {
1152         pstring name_resolve_list;
1153         fstring tok;
1154         const char *ptr;
1155         BOOL allones = (strcmp(name,"255.255.255.255") == 0);
1156         BOOL allzeros = (strcmp(name,"0.0.0.0") == 0);
1157         BOOL is_address = is_ipaddress(name);
1158         BOOL result = False;
1159         int i;
1160
1161         *return_iplist = NULL;
1162         *return_count = 0;
1163
1164         DEBUG(10, ("internal_resolve_name: looking up %s#%x\n", name, name_type));
1165
1166         if (allzeros || allones || is_address) {
1167   
1168                 if ( (*return_iplist = SMB_MALLOC_P(struct ip_service)) == NULL ) {
1169                         DEBUG(0,("internal_resolve_name: malloc fail !\n"));
1170                         return False;
1171                 }
1172         
1173                 if(is_address) { 
1174                         /* ignore the port here */
1175                         (*return_iplist)->port = PORT_NONE;
1176                 
1177                         /* if it's in the form of an IP address then get the lib to interpret it */
1178                         if (((*return_iplist)->ip.s_addr = inet_addr(name)) == 0xFFFFFFFF ){
1179                                 DEBUG(1,("internal_resolve_name: inet_addr failed on %s\n", name));
1180                                 SAFE_FREE(*return_iplist);
1181                                 return False;
1182                         }
1183                 } else {
1184                         (*return_iplist)->ip.s_addr = allones ? 0xFFFFFFFF : 0;
1185                 }
1186                 *return_count = 1;
1187                 return True;
1188         }
1189   
1190         /* Check name cache */
1191
1192         if (namecache_fetch(name, name_type, return_iplist, return_count)) {
1193                 /* This could be a negative response */
1194                 return (*return_count > 0);
1195         }
1196
1197         /* set the name resolution order */
1198
1199         if ( strcmp( resolve_order, "NULL") == 0 ) {
1200                 DEBUG(8,("internal_resolve_name: all lookups disabled\n"));
1201                 return False;
1202         }
1203   
1204         if ( !resolve_order ) {
1205                 pstrcpy(name_resolve_list, lp_name_resolve_order());
1206         } else {
1207                 pstrcpy(name_resolve_list, resolve_order);
1208         }
1209
1210         if ( !name_resolve_list[0] ) {
1211                 ptr = "host";
1212         } else {
1213                 ptr = name_resolve_list;
1214         }
1215
1216         /* iterate through the name resolution backends */
1217   
1218         while (next_token(&ptr, tok, LIST_SEP, sizeof(tok))) {
1219                 if((strequal(tok, "host") || strequal(tok, "hosts"))) {
1220                         if (resolve_hosts(name, name_type, return_iplist, return_count)) {
1221                                 result = True;
1222                                 goto done;
1223                         }
1224                 } else if(strequal( tok, "kdc")) {
1225                         /* deal with KDC_NAME_TYPE names here.  This will result in a
1226                                 SRV record lookup */
1227                         if (resolve_ads(name, KDC_NAME_TYPE, return_iplist, return_count)) {
1228                                 result = True;
1229                                 /* Ensure we don't namecache this with the KDC port. */
1230                                 name_type = KDC_NAME_TYPE;
1231                                 goto done;
1232                         }
1233                 } else if(strequal( tok, "ads")) {
1234                         /* deal with 0x1c names here.  This will result in a
1235                                 SRV record lookup */
1236                         if (resolve_ads(name, name_type, return_iplist, return_count)) {
1237                                 result = True;
1238                                 goto done;
1239                         }
1240                 } else if(strequal( tok, "lmhosts")) {
1241                         if (resolve_lmhosts(name, name_type, return_iplist, return_count)) {
1242                                 result = True;
1243                                 goto done;
1244                         }
1245                 } else if(strequal( tok, "wins")) {
1246                         /* don't resolve 1D via WINS */
1247                         if (name_type != 0x1D && resolve_wins(name, name_type, return_iplist, return_count)) {
1248                                 result = True;
1249                                 goto done;
1250                         }
1251                 } else if(strequal( tok, "bcast")) {
1252                         if (name_resolve_bcast(name, name_type, return_iplist, return_count)) {
1253                                 result = True;
1254                                 goto done;
1255                         }
1256                 } else {
1257                         DEBUG(0,("resolve_name: unknown name switch type %s\n", tok));
1258                 }
1259         }
1260
1261         /* All of the resolve_* functions above have returned false. */
1262
1263         SAFE_FREE(*return_iplist);
1264         *return_count = 0;
1265
1266         return False;
1267
1268   done:
1269
1270         /* Remove duplicate entries.  Some queries, notably #1c (domain
1271         controllers) return the PDC in iplist[0] and then all domain
1272         controllers including the PDC in iplist[1..n].  Iterating over
1273         the iplist when the PDC is down will cause two sets of timeouts. */
1274
1275         if ( *return_count ) {
1276                 *return_count = remove_duplicate_addrs2( *return_iplist, *return_count );
1277         }
1278  
1279         /* Save in name cache */
1280         if ( DEBUGLEVEL >= 100 ) {
1281                 for (i = 0; i < *return_count && DEBUGLEVEL == 100; i++)
1282                         DEBUG(100, ("Storing name %s of type %d (%s:%d)\n", name,
1283                                 name_type, inet_ntoa((*return_iplist)[i].ip), (*return_iplist)[i].port));
1284         }
1285    
1286         namecache_store(name, name_type, *return_count, *return_iplist);
1287
1288         /* Display some debugging info */
1289
1290         if ( DEBUGLEVEL >= 10 ) {
1291                 DEBUG(10, ("internal_resolve_name: returning %d addresses: ", *return_count));
1292
1293                 for (i = 0; i < *return_count; i++) {
1294                         DEBUGADD(10, ("%s:%d ", inet_ntoa((*return_iplist)[i].ip), (*return_iplist)[i].port));
1295                 }
1296                 DEBUG(10, ("\n"));
1297         }
1298   
1299         return result;
1300 }
1301
1302 /********************************************************
1303  Internal interface to resolve a name into one IP address.
1304  Use this function if the string is either an IP address, DNS
1305  or host name or NetBIOS name. This uses the name switch in the
1306  smb.conf to determine the order of name resolution.
1307 *********************************************************/
1308
1309 BOOL resolve_name(const char *name, struct in_addr *return_ip, int name_type)
1310 {
1311         struct ip_service *ip_list = NULL;
1312         int count = 0;
1313
1314         if (is_ipaddress(name)) {
1315                 *return_ip = *interpret_addr2(name);
1316                 return True;
1317         }
1318
1319         if (internal_resolve_name(name, name_type, &ip_list, &count, lp_name_resolve_order())) {
1320                 int i;
1321                 
1322                 /* only return valid addresses for TCP connections */
1323                 for (i=0; i<count; i++) {
1324                         char *ip_str = inet_ntoa(ip_list[i].ip);
1325                         if (ip_str &&
1326                             strcmp(ip_str, "255.255.255.255") != 0 &&
1327                             strcmp(ip_str, "0.0.0.0") != 0) 
1328                         {
1329                                 *return_ip = ip_list[i].ip;
1330                                 SAFE_FREE(ip_list);
1331                                 return True;
1332                         }
1333                 }
1334         }
1335         
1336         SAFE_FREE(ip_list);
1337         return False;
1338 }
1339
1340 /********************************************************
1341  Find the IP address of the master browser or DMB for a workgroup.
1342 *********************************************************/
1343
1344 BOOL find_master_ip(const char *group, struct in_addr *master_ip)
1345 {
1346         struct ip_service *ip_list = NULL;
1347         int count = 0;
1348
1349         if (lp_disable_netbios()) {
1350                 DEBUG(5,("find_master_ip(%s): netbios is disabled\n", group));
1351                 return False;
1352         }
1353
1354         if (internal_resolve_name(group, 0x1D, &ip_list, &count, lp_name_resolve_order())) {
1355                 *master_ip = ip_list[0].ip;
1356                 SAFE_FREE(ip_list);
1357                 return True;
1358         }
1359         if(internal_resolve_name(group, 0x1B, &ip_list, &count, lp_name_resolve_order())) {
1360                 *master_ip = ip_list[0].ip;
1361                 SAFE_FREE(ip_list);
1362                 return True;
1363         }
1364
1365         SAFE_FREE(ip_list);
1366         return False;
1367 }
1368
1369 /********************************************************
1370  Get the IP address list of the primary domain controller
1371  for a domain.
1372 *********************************************************/
1373
1374 BOOL get_pdc_ip(const char *domain, struct in_addr *ip)
1375 {
1376         struct ip_service *ip_list;
1377         int count;
1378
1379         /* Look up #1B name */
1380
1381         if (!internal_resolve_name(domain, 0x1b, &ip_list, &count, lp_name_resolve_order())) {
1382                 return False;
1383         }
1384
1385         /* if we get more than 1 IP back we have to assume it is a
1386            multi-homed PDC and not a mess up */
1387
1388         if ( count > 1 ) {
1389                 DEBUG(6,("get_pdc_ip: PDC has %d IP addresses!\n", count));             
1390                 sort_ip_list2( ip_list, count );
1391         }
1392
1393         *ip = ip_list[0].ip;
1394         
1395         SAFE_FREE(ip_list);
1396
1397         return True;
1398 }
1399
1400 /* Private enum type for lookups. */
1401
1402 enum dc_lookup_type { DC_NORMAL_LOOKUP, DC_ADS_ONLY, DC_KDC_ONLY };
1403
1404 /********************************************************
1405  Get the IP address list of the domain controllers for
1406  a domain.
1407 *********************************************************/
1408
1409 static NTSTATUS get_dc_list(const char *domain, struct ip_service **ip_list, 
1410                             int *count, enum dc_lookup_type lookup_type, int *ordered)
1411 {
1412         fstring resolve_order;
1413         char *saf_servername;
1414         pstring pserver;
1415         const char *p;
1416         char *port_str;
1417         int port;
1418         fstring name;
1419         int num_addresses = 0;
1420         int  local_count, i, j;
1421         struct ip_service *return_iplist = NULL;
1422         struct ip_service *auto_ip_list = NULL;
1423         BOOL done_auto_lookup = False;
1424         int auto_count = 0;
1425
1426         *ordered = False;
1427
1428         /* if we are restricted to solely using DNS for looking
1429            up a domain controller, make sure that host lookups
1430            are enabled for the 'name resolve order'.  If host lookups
1431            are disabled and ads_only is True, then set the string to
1432            NULL. */
1433
1434         fstrcpy( resolve_order, lp_name_resolve_order() );
1435         strlower_m( resolve_order );
1436         if ( lookup_type == DC_ADS_ONLY)  {
1437                 if ( strstr( resolve_order, "host" ) ) {
1438                         fstrcpy( resolve_order, "ads" );
1439
1440                         /* DNS SRV lookups used by the ads resolver
1441                            are already sorted by priority and weight */
1442                         *ordered = True;
1443                 } else {
1444                         fstrcpy( resolve_order, "NULL" );
1445                 }
1446         } else if (lookup_type == DC_KDC_ONLY) {
1447                 /* DNS SRV lookups used by the ads/kdc resolver
1448                    are already sorted by priority and weight */
1449                 *ordered = True;
1450                 fstrcpy( resolve_order, "kdc" );
1451         }
1452
1453         /* fetch the server we have affinity for.  Add the 
1454            'password server' list to a search for our domain controllers */
1455         
1456         saf_servername = saf_fetch( domain );
1457         
1458         if ( strequal(domain, lp_workgroup()) || strequal(domain, lp_realm()) ) {
1459                 pstr_sprintf( pserver, "%s, %s", 
1460                         saf_servername ? saf_servername : "",
1461                         lp_passwordserver() );
1462         } else {
1463                 pstr_sprintf( pserver, "%s, *", 
1464                         saf_servername ? saf_servername : "" );
1465         }
1466
1467         SAFE_FREE( saf_servername );
1468
1469         /* if we are starting from scratch, just lookup DOMAIN<0x1c> */
1470
1471         if ( !*pserver ) {
1472                 DEBUG(10,("get_dc_list: no preferred domain controllers.\n"));
1473                 /* TODO: change return type of internal_resolve_name to
1474                  * NTSTATUS */
1475                 if (internal_resolve_name(domain, 0x1C, ip_list, count,
1476                                           resolve_order)) {
1477                         return NT_STATUS_OK;
1478                 } else {
1479                         return NT_STATUS_NO_LOGON_SERVERS;
1480                 }
1481         }
1482
1483         DEBUG(3,("get_dc_list: preferred server list: \"%s\"\n", pserver ));
1484         
1485         /*
1486          * if '*' appears in the "password server" list then add
1487          * an auto lookup to the list of manually configured
1488          * DC's.  If any DC is listed by name, then the list should be 
1489          * considered to be ordered 
1490          */
1491
1492         p = pserver;
1493         while (next_token(&p,name,LIST_SEP,sizeof(name))) {
1494                 if (strequal(name, "*")) {
1495                         if (internal_resolve_name(domain, 0x1C, &auto_ip_list,
1496                                                   &auto_count, resolve_order))
1497                                 num_addresses += auto_count;
1498                         done_auto_lookup = True;
1499                         DEBUG(8,("Adding %d DC's from auto lookup\n", auto_count));
1500                 } else  {
1501                         num_addresses++;
1502                 }
1503         }
1504
1505         /* if we have no addresses and haven't done the auto lookup, then
1506            just return the list of DC's.  Or maybe we just failed. */
1507                    
1508         if ( (num_addresses == 0) ) {
1509                 if ( !done_auto_lookup ) {
1510                         if (internal_resolve_name(domain, 0x1C, ip_list, count, resolve_order)) {
1511                                 return NT_STATUS_OK;
1512                         } else {
1513                                 return NT_STATUS_NO_LOGON_SERVERS;
1514                         }
1515                 } else {
1516                         DEBUG(4,("get_dc_list: no servers found\n")); 
1517                         return NT_STATUS_NO_LOGON_SERVERS;
1518                 }
1519         }
1520
1521         if ( (return_iplist = SMB_MALLOC_ARRAY(struct ip_service, num_addresses)) == NULL ) {
1522                 DEBUG(3,("get_dc_list: malloc fail !\n"));
1523                 return NT_STATUS_NO_MEMORY;
1524         }
1525
1526         p = pserver;
1527         local_count = 0;
1528
1529         /* fill in the return list now with real IP's */
1530                                 
1531         while ( (local_count<num_addresses) && next_token(&p,name,LIST_SEP,sizeof(name)) ) {
1532                 struct in_addr name_ip;
1533                         
1534                 /* copy any addersses from the auto lookup */
1535                         
1536                 if ( strequal(name, "*") ) {
1537                         for ( j=0; j<auto_count; j++ ) {
1538                                 /* Check for and don't copy any known bad DC IP's. */
1539                                 if(!NT_STATUS_IS_OK(check_negative_conn_cache(domain, 
1540                                                 inet_ntoa(auto_ip_list[j].ip)))) {
1541                                         DEBUG(5,("get_dc_list: negative entry %s removed from DC list\n",
1542                                                 inet_ntoa(auto_ip_list[j].ip) ));
1543                                         continue;
1544                                 }
1545                                 return_iplist[local_count].ip   = auto_ip_list[j].ip;
1546                                 return_iplist[local_count].port = auto_ip_list[j].port;
1547                                 local_count++;
1548                         }
1549                         continue;
1550                 }
1551                         
1552                         
1553                 /* added support for address:port syntax for ads (not that I think 
1554                    anyone will ever run the LDAP server in an AD domain on something 
1555                    other than port 389 */
1556                         
1557                 port = (lp_security() == SEC_ADS) ? LDAP_PORT : PORT_NONE;
1558                 if ( (port_str=strchr(name, ':')) != NULL ) {
1559                         *port_str = '\0';
1560                         port_str++;
1561                         port = atoi( port_str );
1562                 }
1563
1564                 /* explicit lookup; resolve_name() will handle names & IP addresses */
1565                 if ( resolve_name( name, &name_ip, 0x20 ) ) {
1566
1567                         /* Check for and don't copy any known bad DC IP's. */
1568                         if( !NT_STATUS_IS_OK(check_negative_conn_cache(domain, inet_ntoa(name_ip))) ) {
1569                                 DEBUG(5,("get_dc_list: negative entry %s removed from DC list\n",name ));
1570                                 continue;
1571                         }
1572
1573                         return_iplist[local_count].ip   = name_ip;
1574                         return_iplist[local_count].port = port;
1575                         local_count++;
1576                         *ordered = True;
1577                 }
1578         }
1579                                 
1580         SAFE_FREE(auto_ip_list);
1581
1582         /* need to remove duplicates in the list if we have any 
1583            explicit password servers */
1584            
1585         if ( local_count ) {
1586                 local_count = remove_duplicate_addrs2( return_iplist, local_count );
1587         }
1588                 
1589         if ( DEBUGLEVEL >= 4 ) {
1590                 DEBUG(4,("get_dc_list: returning %d ip addresses in an %sordered list\n", local_count, 
1591                         *ordered ? "":"un"));
1592                 DEBUG(4,("get_dc_list: "));
1593                 for ( i=0; i<local_count; i++ )
1594                         DEBUGADD(4,("%s:%d ", inet_ntoa(return_iplist[i].ip), return_iplist[i].port ));
1595                 DEBUGADD(4,("\n"));
1596         }
1597                         
1598         *ip_list = return_iplist;
1599         *count = local_count;
1600
1601         return ( *count != 0 ? NT_STATUS_OK : NT_STATUS_NO_LOGON_SERVERS );
1602 }
1603
1604 /*********************************************************************
1605  Small wrapper function to get the DC list and sort it if neccessary.
1606 *********************************************************************/
1607
1608 NTSTATUS get_sorted_dc_list( const char *domain, struct ip_service **ip_list, int *count, BOOL ads_only )
1609 {
1610         BOOL ordered;
1611         NTSTATUS status;
1612         enum dc_lookup_type lookup_type = DC_NORMAL_LOOKUP;
1613
1614         DEBUG(8,("get_sorted_dc_list: attempting lookup using [%s]\n",
1615                 (ads_only ? "ads" : lp_name_resolve_order())));
1616         
1617         if (ads_only) {
1618                 lookup_type = DC_ADS_ONLY;
1619         }
1620
1621         status = get_dc_list(domain, ip_list, count, lookup_type, &ordered);
1622         if (!NT_STATUS_IS_OK(status)) {
1623                 return status; 
1624         }
1625                 
1626         /* only sort if we don't already have an ordered list */
1627         if ( !ordered ) {
1628                 sort_ip_list2( *ip_list, *count );
1629         }
1630                 
1631         return NT_STATUS_OK;
1632 }
1633
1634 /*********************************************************************
1635  Get the KDC list - re-use all the logic in get_dc_list.
1636 *********************************************************************/
1637
1638 NTSTATUS get_kdc_list( const char *realm, struct ip_service **ip_list, int *count)
1639 {
1640         BOOL ordered;
1641         NTSTATUS status;
1642
1643         *count = 0;
1644         *ip_list = NULL;
1645
1646         status = get_dc_list(realm, ip_list, count, DC_KDC_ONLY, &ordered);
1647
1648         if (!NT_STATUS_IS_OK(status)) {
1649                 return status; 
1650         }
1651
1652         /* only sort if we don't already have an ordered list */
1653         if ( !ordered ) {
1654                 sort_ip_list2( *ip_list, *count );
1655         }
1656
1657         return NT_STATUS_OK;
1658 }