source: branches/samba-3.0/source/libsmb/namequery.c@ 134

Last change on this file since 134 was 1, checked in by Paul Smedley, 18 years ago

Initial code import

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