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