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