Remove pstring from nmbd.
[Samba.git] / source / libsmb / namequery.c
blobf4f9f84b00026b51601cc24def4a8e264ba0573d
1 /*
2 Unix SMB/CIFS implementation.
3 name query routines
4 Copyright (C) Andrew Tridgell 1994-1998
5 Copyright (C) Jeremy Allison 2007.
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include "includes.h"
23 /* nmbd.c sets this to True. */
24 bool global_in_nmbd = False;
26 /****************************
27 * SERVER AFFINITY ROUTINES *
28 ****************************/
30 /* Server affinity is the concept of preferring the last domain
31 controller with whom you had a successful conversation */
33 /****************************************************************************
34 ****************************************************************************/
35 #define SAFKEY_FMT "SAF/DOMAIN/%s"
36 #define SAF_TTL 900
38 static char *saf_key(const char *domain)
40 char *keystr;
42 asprintf( &keystr, SAFKEY_FMT, strupper_static(domain) );
44 return keystr;
47 /****************************************************************************
48 ****************************************************************************/
50 bool saf_store( const char *domain, const char *servername )
52 char *key;
53 time_t expire;
54 bool ret = False;
56 if ( !domain || !servername ) {
57 DEBUG(2,("saf_store: "
58 "Refusing to store empty domain or servername!\n"));
59 return False;
62 if ( (strlen(domain) == 0) || (strlen(servername) == 0) ) {
63 DEBUG(0,("saf_store: "
64 "refusing to store 0 length domain or servername!\n"));
65 return False;
68 if ( !gencache_init() )
69 return False;
71 key = saf_key( domain );
72 expire = time( NULL ) + SAF_TTL;
74 DEBUG(10,("saf_store: domain = [%s], server = [%s], expire = [%u]\n",
75 domain, servername, (unsigned int)expire ));
77 ret = gencache_set( key, servername, expire );
79 SAFE_FREE( key );
81 return ret;
84 bool saf_delete( const char *domain )
86 char *key;
87 bool ret = False;
89 if ( !domain ) {
90 DEBUG(2,("saf_delete: Refusing to delete empty domain\n"));
91 return False;
94 if ( !gencache_init() )
95 return False;
97 key = saf_key(domain);
98 ret = gencache_del(key);
100 if (ret) {
101 DEBUG(10,("saf_delete: domain = [%s]\n", domain ));
104 SAFE_FREE( key );
106 return ret;
109 /****************************************************************************
110 ****************************************************************************/
112 char *saf_fetch( const char *domain )
114 char *server = NULL;
115 time_t timeout;
116 bool ret = False;
117 char *key = NULL;
119 if ( !domain || strlen(domain) == 0) {
120 DEBUG(2,("saf_fetch: Empty domain name!\n"));
121 return NULL;
124 if ( !gencache_init() )
125 return False;
127 key = saf_key( domain );
129 ret = gencache_get( key, &server, &timeout );
131 SAFE_FREE( key );
133 if ( !ret ) {
134 DEBUG(5,("saf_fetch: failed to find server for \"%s\" domain\n",
135 domain ));
136 } else {
137 DEBUG(5,("saf_fetch: Returning \"%s\" for \"%s\" domain\n",
138 server, domain ));
141 return server;
144 /****************************************************************************
145 Generate a random trn_id.
146 ****************************************************************************/
148 static int generate_trn_id(void)
150 uint16 id;
152 generate_random_buffer((uint8 *)&id, sizeof(id));
154 return id % (unsigned)0x7FFF;
157 /****************************************************************************
158 Parse a node status response into an array of structures.
159 ****************************************************************************/
161 static NODE_STATUS_STRUCT *parse_node_status(char *p,
162 int *num_names,
163 struct node_status_extra *extra)
165 NODE_STATUS_STRUCT *ret;
166 int i;
168 *num_names = CVAL(p,0);
170 if (*num_names == 0)
171 return NULL;
173 ret = SMB_MALLOC_ARRAY(NODE_STATUS_STRUCT,*num_names);
174 if (!ret)
175 return NULL;
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));
188 * Also, pick up the MAC address ...
190 if (extra) {
191 memcpy(&extra->mac_addr, p, 6); /* Fill in the mac addr */
193 return ret;
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 **************************************************************************/
202 NODE_STATUS_STRUCT *node_status_query(int fd,
203 struct nmb_name *name,
204 const struct sockaddr_storage *to_ss,
205 int *num_names,
206 struct node_status_extra *extra)
208 bool found=False;
209 int retries = 2;
210 int retry_time = 2000;
211 struct timeval tval;
212 struct packet_struct p;
213 struct packet_struct *p2;
214 struct nmb_packet *nmb = &p.packet.nmb;
215 NODE_STATUS_STRUCT *ret;
217 ZERO_STRUCT(p);
219 if (to_ss->ss_family != AF_INET) {
220 /* Can't do node status to IPv6 */
221 return NULL;
223 nmb->header.name_trn_id = generate_trn_id();
224 nmb->header.opcode = 0;
225 nmb->header.response = false;
226 nmb->header.nm_flags.bcast = false;
227 nmb->header.nm_flags.recursion_available = false;
228 nmb->header.nm_flags.recursion_desired = false;
229 nmb->header.nm_flags.trunc = false;
230 nmb->header.nm_flags.authoritative = false;
231 nmb->header.rcode = 0;
232 nmb->header.qdcount = 1;
233 nmb->header.ancount = 0;
234 nmb->header.nscount = 0;
235 nmb->header.arcount = 0;
236 nmb->question.question_name = *name;
237 nmb->question.question_type = 0x21;
238 nmb->question.question_class = 0x1;
240 p.ip = ((const struct sockaddr_in *)to_ss)->sin_addr;
241 p.port = NMB_PORT;
242 p.fd = fd;
243 p.timestamp = time(NULL);
244 p.packet_type = NMB_PACKET;
246 GetTimeOfDay(&tval);
248 if (!send_packet(&p))
249 return NULL;
251 retries--;
253 while (1) {
254 struct timeval tval2;
255 GetTimeOfDay(&tval2);
256 if (TvalDiff(&tval,&tval2) > retry_time) {
257 if (!retries)
258 break;
259 if (!found && !send_packet(&p))
260 return NULL;
261 GetTimeOfDay(&tval);
262 retries--;
265 if ((p2=receive_nmb_packet(fd,90,nmb->header.name_trn_id))) {
266 struct nmb_packet *nmb2 = &p2->packet.nmb;
267 debug_nmb_packet(p2);
269 if (nmb2->header.opcode != 0 ||
270 nmb2->header.nm_flags.bcast ||
271 nmb2->header.rcode ||
272 !nmb2->header.ancount ||
273 nmb2->answers->rr_type != 0x21) {
274 /* XXXX what do we do with this? could be a
275 redirect, but we'll discard it for the
276 moment */
277 free_packet(p2);
278 continue;
281 ret = parse_node_status(&nmb2->answers->rdata[0],
282 num_names, extra);
283 free_packet(p2);
284 return ret;
288 return NULL;
291 /****************************************************************************
292 Find the first type XX name in a node status reply - used for finding
293 a servers name given its IP. Return the matched name in *name.
294 **************************************************************************/
296 bool name_status_find(const char *q_name,
297 int q_type,
298 int type,
299 const struct sockaddr_storage *to_ss,
300 fstring name)
302 char addr[INET6_ADDRSTRLEN];
303 struct sockaddr_storage ss;
304 NODE_STATUS_STRUCT *status = NULL;
305 struct nmb_name nname;
306 int count, i;
307 int sock;
308 bool result = false;
310 if (lp_disable_netbios()) {
311 DEBUG(5,("name_status_find(%s#%02x): netbios is disabled\n",
312 q_name, q_type));
313 return False;
316 print_sockaddr(addr, sizeof(addr), to_ss);
318 DEBUG(10, ("name_status_find: looking up %s#%02x at %s\n", q_name,
319 q_type, addr));
321 /* Check the cache first. */
323 if (namecache_status_fetch(q_name, q_type, type, to_ss, name)) {
324 return True;
327 if (to_ss->ss_family != AF_INET) {
328 /* Can't do node status to IPv6 */
329 return false;
332 if (!interpret_string_addr(&ss, lp_socket_address(),
333 AI_NUMERICHOST|AI_PASSIVE)) {
334 zero_addr(&ss);
337 sock = open_socket_in(SOCK_DGRAM, 0, 3, &ss, True);
338 if (sock == -1)
339 goto done;
341 /* W2K PDC's seem not to respond to '*'#0. JRA */
342 make_nmb_name(&nname, q_name, q_type);
343 status = node_status_query(sock, &nname, to_ss, &count, NULL);
344 close(sock);
345 if (!status)
346 goto done;
348 for (i=0;i<count;i++) {
349 if (status[i].type == type)
350 break;
352 if (i == count)
353 goto done;
355 pull_ascii_nstring(name, sizeof(fstring), status[i].name);
357 /* Store the result in the cache. */
358 /* but don't store an entry for 0x1c names here. Here we have
359 a single host and DOMAIN<0x1c> names should be a list of hosts */
361 if ( q_type != 0x1c ) {
362 namecache_status_store(q_name, q_type, type, to_ss, name);
365 result = true;
367 done:
368 SAFE_FREE(status);
370 DEBUG(10, ("name_status_find: name %sfound", result ? "" : "not "));
372 if (result)
373 DEBUGADD(10, (", name %s ip address is %s", name, addr));
375 DEBUG(10, ("\n"));
377 return result;
381 comparison function used by sort_addr_list
384 static int addr_compare(const struct sockaddr_storage *ss1,
385 const struct sockaddr_storage *ss2)
387 int max_bits1=0, max_bits2=0;
388 int num_interfaces = iface_count();
389 int i;
391 /* Sort IPv6 addresses first. */
392 if (ss1->ss_family != ss2->ss_family) {
393 if (ss2->ss_family == AF_INET) {
394 return -1;
395 } else {
396 return 1;
400 /* Here we know both addresses are of the same
401 * family. */
403 for (i=0;i<num_interfaces;i++) {
404 const struct sockaddr_storage *pss = iface_n_bcast(i);
405 unsigned char *p_ss1 = NULL;
406 unsigned char *p_ss2 = NULL;
407 unsigned char *p_if = NULL;
408 size_t len = 0;
409 int bits1, bits2;
411 if (pss->ss_family != ss1->ss_family) {
412 /* Ignore interfaces of the wrong type. */
413 continue;
415 if (pss->ss_family == AF_INET) {
416 p_if = (unsigned char *)
417 &((const struct sockaddr_in *)pss)->sin_addr;
418 p_ss1 = (unsigned char *)
419 &((const struct sockaddr_in *)ss1)->sin_addr;
420 p_ss2 = (unsigned char *)
421 &((const struct sockaddr_in *)ss2)->sin_addr;
422 len = 4;
424 #if defined(HAVE_IPV6)
425 if (pss->ss_family == AF_INET6) {
426 p_if = (unsigned char *)
427 &((const struct sockaddr_in6 *)pss)->sin6_addr;
428 p_ss1 = (unsigned char *)
429 &((const struct sockaddr_in6 *)ss1)->sin6_addr;
430 p_ss2 = (unsigned char *)
431 &((const struct sockaddr_in6 *)ss2)->sin6_addr;
432 len = 16;
434 #endif
435 if (!p_ss1 || !p_ss2 || !p_if || len == 0) {
436 continue;
438 bits1 = matching_len_bits(p_ss1, p_if, len);
439 bits2 = matching_len_bits(p_ss2, p_if, len);
440 max_bits1 = MAX(bits1, max_bits1);
441 max_bits2 = MAX(bits2, max_bits2);
444 /* Bias towards directly reachable IPs */
445 if (iface_local(ss1)) {
446 if (ss1->ss_family == AF_INET) {
447 max_bits1 += 32;
448 } else {
449 max_bits1 += 128;
452 if (iface_local(ss2)) {
453 if (ss2->ss_family == AF_INET) {
454 max_bits2 += 32;
455 } else {
456 max_bits2 += 128;
459 return max_bits2 - max_bits1;
462 /*******************************************************************
463 compare 2 ldap IPs by nearness to our interfaces - used in qsort
464 *******************************************************************/
466 int ip_service_compare(struct ip_service *ss1, struct ip_service *ss2)
468 int result;
470 if ((result = addr_compare(&ss1->ss, &ss2->ss)) != 0) {
471 return result;
474 if (ss1->port > ss2->port) {
475 return 1;
478 if (ss1->port < ss2->port) {
479 return -1;
482 return 0;
486 sort an IP list so that names that are close to one of our interfaces
487 are at the top. This prevents the problem where a WINS server returns an IP
488 that is not reachable from our subnet as the first match
491 static void sort_addr_list(struct sockaddr_storage *sslist, int count)
493 if (count <= 1) {
494 return;
497 qsort(sslist, count, sizeof(struct sockaddr_storage),
498 QSORT_CAST addr_compare);
501 static void sort_service_list(struct ip_service *servlist, int count)
503 if (count <= 1) {
504 return;
507 qsort(servlist, count, sizeof(struct ip_service),
508 QSORT_CAST ip_service_compare);
511 /**********************************************************************
512 Remove any duplicate address/port pairs in the list
513 *********************************************************************/
515 static int remove_duplicate_addrs2(struct ip_service *iplist, int count )
517 int i, j;
519 DEBUG(10,("remove_duplicate_addrs2: "
520 "looking for duplicate address/port pairs\n"));
522 /* one loop to remove duplicates */
523 for ( i=0; i<count; i++ ) {
524 if ( is_zero_addr(&iplist[i].ss)) {
525 continue;
528 for ( j=i+1; j<count; j++ ) {
529 if (addr_equal(&iplist[i].ss, &iplist[j].ss) &&
530 iplist[i].port == iplist[j].port) {
531 zero_addr(&iplist[j].ss);
536 /* one loop to clean up any holes we left */
537 /* first ip should never be a zero_ip() */
538 for (i = 0; i<count; ) {
539 if (is_zero_addr(&iplist[i].ss) ) {
540 if (i != count-1) {
541 memmove(&iplist[i], &iplist[i+1],
542 (count - i - 1)*sizeof(iplist[i]));
544 count--;
545 continue;
547 i++;
550 return count;
553 /****************************************************************************
554 Do a netbios name query to find someones IP.
555 Returns an array of IP addresses or NULL if none.
556 *count will be set to the number of addresses returned.
557 *timed_out is set if we failed by timing out
558 ****************************************************************************/
560 struct sockaddr_storage *name_query(int fd,
561 const char *name,
562 int name_type,
563 bool bcast,
564 bool recurse,
565 const struct sockaddr_storage *to_ss,
566 int *count,
567 int *flags,
568 bool *timed_out)
570 bool found=false;
571 int i, retries = 3;
572 int retry_time = bcast?250:2000;
573 struct timeval tval;
574 struct packet_struct p;
575 struct packet_struct *p2;
576 struct nmb_packet *nmb = &p.packet.nmb;
577 struct sockaddr_storage *ss_list = NULL;
579 if (lp_disable_netbios()) {
580 DEBUG(5,("name_query(%s#%02x): netbios is disabled\n",
581 name, name_type));
582 return NULL;
585 if (to_ss->ss_family != AF_INET) {
586 return NULL;
589 if (timed_out) {
590 *timed_out = false;
593 memset((char *)&p,'\0',sizeof(p));
594 (*count) = 0;
595 (*flags) = 0;
597 nmb->header.name_trn_id = generate_trn_id();
598 nmb->header.opcode = 0;
599 nmb->header.response = false;
600 nmb->header.nm_flags.bcast = bcast;
601 nmb->header.nm_flags.recursion_available = false;
602 nmb->header.nm_flags.recursion_desired = recurse;
603 nmb->header.nm_flags.trunc = false;
604 nmb->header.nm_flags.authoritative = false;
605 nmb->header.rcode = 0;
606 nmb->header.qdcount = 1;
607 nmb->header.ancount = 0;
608 nmb->header.nscount = 0;
609 nmb->header.arcount = 0;
611 make_nmb_name(&nmb->question.question_name,name,name_type);
613 nmb->question.question_type = 0x20;
614 nmb->question.question_class = 0x1;
616 p.ip = ((struct sockaddr_in *)to_ss)->sin_addr;
617 p.port = NMB_PORT;
618 p.fd = fd;
619 p.timestamp = time(NULL);
620 p.packet_type = NMB_PACKET;
622 GetTimeOfDay(&tval);
624 if (!send_packet(&p))
625 return NULL;
627 retries--;
629 while (1) {
630 struct timeval tval2;
632 GetTimeOfDay(&tval2);
633 if (TvalDiff(&tval,&tval2) > retry_time) {
634 if (!retries)
635 break;
636 if (!found && !send_packet(&p))
637 return NULL;
638 GetTimeOfDay(&tval);
639 retries--;
642 if ((p2=receive_nmb_packet(fd,90,nmb->header.name_trn_id))) {
643 struct nmb_packet *nmb2 = &p2->packet.nmb;
644 debug_nmb_packet(p2);
646 /* If we get a Negative Name Query Response from a WINS
647 * server, we should report it and give up.
649 if( 0 == nmb2->header.opcode /* A query response */
650 && !(bcast) /* from a WINS server */
651 && nmb2->header.rcode /* Error returned */
654 if( DEBUGLVL( 3 ) ) {
655 /* Only executed if DEBUGLEVEL >= 3 */
656 dbgtext( "Negative name query "
657 "response, rcode 0x%02x: ",
658 nmb2->header.rcode );
659 switch( nmb2->header.rcode ) {
660 case 0x01:
661 dbgtext( "Request "
662 "was invalidly formatted.\n" );
663 break;
664 case 0x02:
665 dbgtext( "Problem with NBNS, "
666 "cannot process name.\n");
667 break;
668 case 0x03:
669 dbgtext( "The name requested "
670 "does not exist.\n" );
671 break;
672 case 0x04:
673 dbgtext( "Unsupported request "
674 "error.\n" );
675 break;
676 case 0x05:
677 dbgtext( "Query refused "
678 "error.\n" );
679 break;
680 default:
681 dbgtext( "Unrecognized error "
682 "code.\n" );
683 break;
686 free_packet(p2);
687 return( NULL );
690 if (nmb2->header.opcode != 0 ||
691 nmb2->header.nm_flags.bcast ||
692 nmb2->header.rcode ||
693 !nmb2->header.ancount) {
695 * XXXX what do we do with this? Could be a
696 * redirect, but we'll discard it for the
697 * moment.
699 free_packet(p2);
700 continue;
703 ss_list = SMB_REALLOC_ARRAY(ss_list,
704 struct sockaddr_storage,
705 (*count) +
706 nmb2->answers->rdlength/6);
708 if (!ss_list) {
709 DEBUG(0,("name_query: Realloc failed.\n"));
710 free_packet(p2);
711 return NULL;
714 DEBUG(2,("Got a positive name query response "
715 "from %s ( ",
716 inet_ntoa(p2->ip)));
718 for (i=0;i<nmb2->answers->rdlength/6;i++) {
719 struct in_addr ip;
720 putip((char *)&ip,&nmb2->answers->rdata[2+i*6]);
721 in_addr_to_sockaddr_storage(&ss_list[(*count)],
722 ip);
723 DEBUGADD(2,("%s ",inet_ntoa(ip)));
724 (*count)++;
726 DEBUGADD(2,(")\n"));
728 found=true;
729 retries=0;
730 /* We add the flags back ... */
731 if (nmb2->header.response)
732 (*flags) |= NM_FLAGS_RS;
733 if (nmb2->header.nm_flags.authoritative)
734 (*flags) |= NM_FLAGS_AA;
735 if (nmb2->header.nm_flags.trunc)
736 (*flags) |= NM_FLAGS_TC;
737 if (nmb2->header.nm_flags.recursion_desired)
738 (*flags) |= NM_FLAGS_RD;
739 if (nmb2->header.nm_flags.recursion_available)
740 (*flags) |= NM_FLAGS_RA;
741 if (nmb2->header.nm_flags.bcast)
742 (*flags) |= NM_FLAGS_B;
743 free_packet(p2);
745 * If we're doing a unicast lookup we only
746 * expect one reply. Don't wait the full 2
747 * seconds if we got one. JRA.
749 if(!bcast && found)
750 break;
754 /* only set timed_out if we didn't fund what we where looking for*/
756 if ( !found && timed_out ) {
757 *timed_out = true;
760 /* sort the ip list so we choose close servers first if possible */
761 sort_addr_list(ss_list, *count);
763 return ss_list;
766 /********************************************************
767 Start parsing the lmhosts file.
768 *********************************************************/
770 XFILE *startlmhosts(const char *fname)
772 XFILE *fp = x_fopen(fname,O_RDONLY, 0);
773 if (!fp) {
774 DEBUG(4,("startlmhosts: Can't open lmhosts file %s. "
775 "Error was %s\n",
776 fname, strerror(errno)));
777 return NULL;
779 return fp;
782 /********************************************************
783 Parse the next line in the lmhosts file.
784 *********************************************************/
786 bool getlmhostsent(TALLOC_CTX *ctx, XFILE *fp, char **pp_name, int *name_type,
787 struct sockaddr_storage *pss)
789 char line[1024];
791 *pp_name = NULL;
793 while(!x_feof(fp) && !x_ferror(fp)) {
794 char ip[INET6_ADDRSTRLEN];
795 fstring flags;
796 fstring extra;
797 fstring name;
798 const char *ptr;
799 char *ptr1;
800 int count = 0;
802 *name_type = -1;
804 if (!fgets_slash(line,sizeof(line),fp)) {
805 continue;
808 if (*line == '#') {
809 continue;
812 ip[0] = '\0';
813 name[0] = '\0';
814 flags[0] = '\0';
816 ptr = line;
818 if (next_token(&ptr,ip ,NULL,sizeof(ip)))
819 ++count;
820 if (next_token(&ptr,name ,NULL, sizeof(name)))
821 ++count;
822 if (next_token(&ptr,flags,NULL, sizeof(flags)))
823 ++count;
824 if (next_token(&ptr,extra,NULL, sizeof(extra)))
825 ++count;
827 if (count <= 0)
828 continue;
830 if (count > 0 && count < 2) {
831 DEBUG(0,("getlmhostsent: Ill formed hosts line [%s]\n",
832 line));
833 continue;
836 if (count >= 4) {
837 DEBUG(0,("getlmhostsent: too many columns "
838 "in lmhosts file (obsolete syntax)\n"));
839 continue;
842 DEBUG(4, ("getlmhostsent: lmhost entry: %s %s %s\n",
843 ip, name, flags));
845 if (strchr_m(flags,'G') || strchr_m(flags,'S')) {
846 DEBUG(0,("getlmhostsent: group flag "
847 "in lmhosts ignored (obsolete)\n"));
848 continue;
851 if (!interpret_string_addr(pss, ip, AI_NUMERICHOST)) {
852 DEBUG(0,("getlmhostsent: invalid address "
853 "%s.\n", ip));
856 /* Extra feature. If the name ends in '#XX',
857 * where XX is a hex number, then only add that name type. */
858 if((ptr1 = strchr_m(name, '#')) != NULL) {
859 char *endptr;
860 ptr1++;
862 *name_type = (int)strtol(ptr1, &endptr, 16);
863 if(!*ptr1 || (endptr == ptr1)) {
864 DEBUG(0,("getlmhostsent: invalid name "
865 "%s containing '#'.\n", name));
866 continue;
869 *(--ptr1) = '\0'; /* Truncate at the '#' */
872 *pp_name = talloc_strdup(ctx, name);
873 if (!*pp_name) {
874 return false;
876 return true;
879 return false;
882 /********************************************************
883 Finish parsing the lmhosts file.
884 *********************************************************/
886 void endlmhosts(XFILE *fp)
888 x_fclose(fp);
891 /********************************************************
892 convert an array if struct sockaddr_storage to struct ip_service
893 return false on failure. Port is set to PORT_NONE;
894 *********************************************************/
896 static bool convert_ss2service(struct ip_service **return_iplist,
897 const struct sockaddr_storage *ss_list,
898 int count)
900 int i;
902 if ( count==0 || !ss_list )
903 return False;
905 /* copy the ip address; port will be PORT_NONE */
906 if ((*return_iplist = SMB_MALLOC_ARRAY(struct ip_service, count)) ==
907 NULL) {
908 DEBUG(0,("convert_ip2service: malloc failed "
909 "for %d enetries!\n", count ));
910 return False;
913 for ( i=0; i<count; i++ ) {
914 (*return_iplist)[i].ss = ss_list[i];
915 (*return_iplist)[i].port = PORT_NONE;
918 return true;
921 /********************************************************
922 Resolve via "bcast" method.
923 *********************************************************/
925 NTSTATUS name_resolve_bcast(const char *name,
926 int name_type,
927 struct ip_service **return_iplist,
928 int *return_count)
930 int sock, i;
931 int num_interfaces = iface_count();
932 struct sockaddr_storage *ss_list;
933 struct sockaddr_storage ss;
934 NTSTATUS status;
936 if (lp_disable_netbios()) {
937 DEBUG(5,("name_resolve_bcast(%s#%02x): netbios is disabled\n",
938 name, name_type));
939 return NT_STATUS_INVALID_PARAMETER;
942 *return_iplist = NULL;
943 *return_count = 0;
946 * "bcast" means do a broadcast lookup on all the local interfaces.
949 DEBUG(3,("name_resolve_bcast: Attempting broadcast lookup "
950 "for name %s<0x%x>\n", name, name_type));
952 if (!interpret_string_addr(&ss, lp_socket_address(),
953 AI_NUMERICHOST|AI_PASSIVE)) {
954 zero_addr(&ss);
957 sock = open_socket_in( SOCK_DGRAM, 0, 3, &ss, true );
958 if (sock == -1) {
959 return NT_STATUS_UNSUCCESSFUL;
962 set_socket_options(sock,"SO_BROADCAST");
964 * Lookup the name on all the interfaces, return on
965 * the first successful match.
967 for( i = num_interfaces-1; i >= 0; i--) {
968 const struct sockaddr_storage *pss = iface_n_bcast(i);
969 int flags;
971 /* Done this way to fix compiler error on IRIX 5.x */
972 if (!pss) {
973 continue;
975 ss_list = name_query(sock, name, name_type, true,
976 true, pss, return_count, &flags, NULL);
977 if (ss_list) {
978 goto success;
982 /* failed - no response */
984 close(sock);
985 return NT_STATUS_UNSUCCESSFUL;
987 success:
989 status = NT_STATUS_OK;
990 if (!convert_ss2service(return_iplist, ss_list, *return_count) )
991 status = NT_STATUS_INVALID_PARAMETER;
993 SAFE_FREE(ss_list);
994 close(sock);
995 return status;
998 /********************************************************
999 Resolve via "wins" method.
1000 *********************************************************/
1002 NTSTATUS resolve_wins(const char *name,
1003 int name_type,
1004 struct ip_service **return_iplist,
1005 int *return_count)
1007 int sock, t, i;
1008 char **wins_tags;
1009 struct sockaddr_storage src_ss, *ss_list = NULL;
1010 struct in_addr src_ip;
1011 NTSTATUS status;
1013 if (lp_disable_netbios()) {
1014 DEBUG(5,("resolve_wins(%s#%02x): netbios is disabled\n",
1015 name, name_type));
1016 return NT_STATUS_INVALID_PARAMETER;
1019 *return_iplist = NULL;
1020 *return_count = 0;
1022 DEBUG(3,("resolve_wins: Attempting wins lookup for name %s<0x%x>\n",
1023 name, name_type));
1025 if (wins_srv_count() < 1) {
1026 DEBUG(3,("resolve_wins: WINS server resolution selected "
1027 "and no WINS servers listed.\n"));
1028 return NT_STATUS_INVALID_PARAMETER;
1031 /* we try a lookup on each of the WINS tags in turn */
1032 wins_tags = wins_srv_tags();
1034 if (!wins_tags) {
1035 /* huh? no tags?? give up in disgust */
1036 return NT_STATUS_INVALID_PARAMETER;
1039 /* the address we will be sending from */
1040 if (!interpret_string_addr(&src_ss, lp_socket_address(),
1041 AI_NUMERICHOST|AI_PASSIVE)) {
1042 zero_addr(&src_ss);
1045 if (src_ss.ss_family != AF_INET) {
1046 char addr[INET6_ADDRSTRLEN];
1047 print_sockaddr(addr, sizeof(addr), &src_ss);
1048 DEBUG(3,("resolve_wins: cannot receive WINS replies "
1049 "on IPv6 address %s\n",
1050 addr));
1051 return NT_STATUS_INVALID_PARAMETER;
1054 src_ip = ((struct sockaddr_in *)&src_ss)->sin_addr;
1056 /* in the worst case we will try every wins server with every
1057 tag! */
1058 for (t=0; wins_tags && wins_tags[t]; t++) {
1059 int srv_count = wins_srv_count_tag(wins_tags[t]);
1060 for (i=0; i<srv_count; i++) {
1061 struct sockaddr_storage wins_ss;
1062 struct in_addr wins_ip;
1063 int flags;
1064 bool timed_out;
1066 wins_ip = wins_srv_ip_tag(wins_tags[t], src_ip);
1068 if (global_in_nmbd && ismyip_v4(wins_ip)) {
1069 /* yikes! we'll loop forever */
1070 continue;
1073 /* skip any that have been unresponsive lately */
1074 if (wins_srv_is_dead(wins_ip, src_ip)) {
1075 continue;
1078 DEBUG(3,("resolve_wins: using WINS server %s "
1079 "and tag '%s'\n",
1080 inet_ntoa(wins_ip), wins_tags[t]));
1082 sock = open_socket_in(SOCK_DGRAM, 0, 3, &src_ss, true);
1083 if (sock == -1) {
1084 continue;
1087 in_addr_to_sockaddr_storage(&wins_ss, wins_ip);
1088 ss_list = name_query(sock,
1089 name,
1090 name_type,
1091 false,
1092 true,
1093 &wins_ss,
1094 return_count,
1095 &flags,
1096 &timed_out);
1098 /* exit loop if we got a list of addresses */
1100 if (ss_list)
1101 goto success;
1103 close(sock);
1105 if (timed_out) {
1106 /* Timed out wating for WINS server to respond.
1107 * Mark it dead. */
1108 wins_srv_died(wins_ip, src_ip);
1109 } else {
1110 /* The name definately isn't in this
1111 group of WINS servers.
1112 goto the next group */
1113 break;
1118 wins_srv_tags_free(wins_tags);
1119 return NT_STATUS_NO_LOGON_SERVERS;
1121 success:
1123 status = NT_STATUS_OK;
1124 if (!convert_ss2service(return_iplist, ss_list, *return_count))
1125 status = NT_STATUS_INVALID_PARAMETER;
1127 SAFE_FREE(ss_list);
1128 wins_srv_tags_free(wins_tags);
1129 close(sock);
1131 return status;
1134 /********************************************************
1135 Resolve via "lmhosts" method.
1136 *********************************************************/
1138 static NTSTATUS resolve_lmhosts(const char *name, int name_type,
1139 struct ip_service **return_iplist,
1140 int *return_count)
1143 * "lmhosts" means parse the local lmhosts file.
1146 XFILE *fp;
1147 char *lmhost_name = NULL;
1148 int name_type2;
1149 struct sockaddr_storage return_ss;
1150 NTSTATUS status = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1151 TALLOC_CTX *ctx = NULL;
1153 *return_iplist = NULL;
1154 *return_count = 0;
1156 DEBUG(3,("resolve_lmhosts: "
1157 "Attempting lmhosts lookup for name %s<0x%x>\n",
1158 name, name_type));
1160 fp = startlmhosts(dyn_LMHOSTSFILE);
1162 if ( fp == NULL )
1163 return NT_STATUS_NO_SUCH_FILE;
1165 ctx = talloc_init("resolve_lmhosts");
1166 if (!ctx) {
1167 endlmhosts(fp);
1168 return NT_STATUS_NO_MEMORY;
1171 while (getlmhostsent(ctx, fp, &lmhost_name, &name_type2, &return_ss)) {
1173 if (!strequal(name, lmhost_name)) {
1174 TALLOC_FREE(lmhost_name);
1175 continue;
1178 if ((name_type2 != -1) && (name_type != name_type2)) {
1179 TALLOC_FREE(lmhost_name);
1180 continue;
1183 *return_iplist = SMB_REALLOC_ARRAY((*return_iplist),
1184 struct ip_service,
1185 (*return_count)+1);
1187 if ((*return_iplist) == NULL) {
1188 TALLOC_FREE(ctx);
1189 endlmhosts(fp);
1190 DEBUG(3,("resolve_lmhosts: malloc fail !\n"));
1191 return NT_STATUS_NO_MEMORY;
1194 (*return_iplist)[*return_count].ss = return_ss;
1195 (*return_iplist)[*return_count].port = PORT_NONE;
1196 *return_count += 1;
1198 /* we found something */
1199 status = NT_STATUS_OK;
1201 /* Multiple names only for DC lookup */
1202 if (name_type != 0x1c)
1203 break;
1206 TALLOC_FREE(ctx);
1207 endlmhosts(fp);
1208 return status;
1212 /********************************************************
1213 Resolve via "hosts" method.
1214 *********************************************************/
1216 static NTSTATUS resolve_hosts(const char *name, int name_type,
1217 struct ip_service **return_iplist,
1218 int *return_count)
1221 * "host" means do a localhost, or dns lookup.
1223 struct addrinfo hints;
1224 struct addrinfo *ailist = NULL;
1225 struct addrinfo *res = NULL;
1226 int ret = -1;
1227 int i = 0;
1229 if ( name_type != 0x20 && name_type != 0x0) {
1230 DEBUG(5, ("resolve_hosts: not appropriate "
1231 "for name type <0x%x>\n",
1232 name_type));
1233 return NT_STATUS_INVALID_PARAMETER;
1236 *return_iplist = NULL;
1237 *return_count = 0;
1239 DEBUG(3,("resolve_hosts: Attempting host lookup for name %s<0x%x>\n",
1240 name, name_type));
1242 ZERO_STRUCT(hints);
1243 /* By default make sure it supports TCP. */
1244 hints.ai_socktype = SOCK_STREAM;
1245 hints.ai_flags = AI_ADDRCONFIG;
1247 ret = getaddrinfo(name,
1248 NULL,
1249 &hints,
1250 &ailist);
1251 if (ret) {
1252 DEBUG(3,("resolve_hosts: getaddrinfo failed for name %s [%s]\n",
1253 name,
1254 gai_strerror(ret) ));
1257 for (res = ailist; res; res = res->ai_next) {
1258 struct sockaddr_storage ss;
1260 if (!res->ai_addr || res->ai_addrlen == 0) {
1261 continue;
1264 memset(&ss, '\0', sizeof(ss));
1265 memcpy(&ss, res->ai_addr, res->ai_addrlen);
1267 *return_count += 1;
1269 *return_iplist = SMB_REALLOC_ARRAY(*return_iplist,
1270 struct ip_service,
1271 *return_count);
1272 if (!*return_iplist) {
1273 DEBUG(3,("resolve_hosts: malloc fail !\n"));
1274 freeaddrinfo(ailist);
1275 return NT_STATUS_NO_MEMORY;
1277 (*return_iplist)[i].ss = ss;
1278 (*return_iplist)[i].port = PORT_NONE;
1279 i++;
1281 if (ailist) {
1282 freeaddrinfo(ailist);
1284 if (*return_count) {
1285 return NT_STATUS_OK;
1287 return NT_STATUS_UNSUCCESSFUL;
1290 /********************************************************
1291 Resolve via "ADS" method.
1292 *********************************************************/
1294 NTSTATUS resolve_ads(const char *name,
1295 int name_type,
1296 const char *sitename,
1297 struct ip_service **return_iplist,
1298 int *return_count)
1300 int i, j;
1301 NTSTATUS status;
1302 TALLOC_CTX *ctx;
1303 struct dns_rr_srv *dcs = NULL;
1304 int numdcs = 0;
1305 int numaddrs = 0;
1307 if ((name_type != 0x1c) && (name_type != KDC_NAME_TYPE) &&
1308 (name_type != 0x1b)) {
1309 return NT_STATUS_INVALID_PARAMETER;
1312 if ( (ctx = talloc_init("resolve_ads")) == NULL ) {
1313 DEBUG(0,("resolve_ads: talloc_init() failed!\n"));
1314 return NT_STATUS_NO_MEMORY;
1317 /* The DNS code needs fixing to find IPv6 addresses... JRA. */
1319 switch (name_type) {
1320 case 0x1b:
1321 DEBUG(5,("resolve_ads: Attempting to resolve "
1322 "PDC for %s using DNS\n", name));
1323 status = ads_dns_query_pdc(ctx, name, &dcs, &numdcs);
1324 break;
1326 case 0x1c:
1327 DEBUG(5,("resolve_ads: Attempting to resolve "
1328 "DCs for %s using DNS\n", name));
1329 status = ads_dns_query_dcs(ctx, name, sitename, &dcs,
1330 &numdcs);
1331 break;
1332 case KDC_NAME_TYPE:
1333 DEBUG(5,("resolve_ads: Attempting to resolve "
1334 "KDCs for %s using DNS\n", name));
1335 status = ads_dns_query_kdcs(ctx, name, sitename, &dcs,
1336 &numdcs);
1337 break;
1338 default:
1339 status = NT_STATUS_INVALID_PARAMETER;
1340 break;
1343 if ( !NT_STATUS_IS_OK( status ) ) {
1344 talloc_destroy(ctx);
1345 return status;
1348 for (i=0;i<numdcs;i++) {
1349 numaddrs += MAX(dcs[i].num_ips,1);
1352 if ((*return_iplist = SMB_MALLOC_ARRAY(struct ip_service, numaddrs)) ==
1353 NULL ) {
1354 DEBUG(0,("resolve_ads: malloc failed for %d entries\n",
1355 numaddrs ));
1356 talloc_destroy(ctx);
1357 return NT_STATUS_NO_MEMORY;
1360 /* now unroll the list of IP addresses */
1362 *return_count = 0;
1363 i = 0;
1364 j = 0;
1365 while ( i < numdcs && (*return_count<numaddrs) ) {
1366 struct ip_service *r = &(*return_iplist)[*return_count];
1368 r->port = dcs[i].port;
1370 /* If we don't have an IP list for a name, lookup it up */
1372 if (!dcs[i].ss_s) {
1373 interpret_string_addr(&r->ss, dcs[i].hostname, 0);
1374 i++;
1375 j = 0;
1376 } else {
1377 /* use the IP addresses from the SRV sresponse */
1379 if ( j >= dcs[i].num_ips ) {
1380 i++;
1381 j = 0;
1382 continue;
1385 r->ss = dcs[i].ss_s[j];
1386 j++;
1389 /* make sure it is a valid IP. I considered checking the
1390 * negative connection cache, but this is the wrong place
1391 * for it. Maybe only as a hack. After think about it, if
1392 * all of the IP addresses returned from DNS are dead, what
1393 * hope does a netbios name lookup have ? The standard reason
1394 * for falling back to netbios lookups is that our DNS server
1395 * doesn't know anything about the DC's -- jerry */
1397 if (!is_zero_addr(&r->ss)) {
1398 (*return_count)++;
1402 talloc_destroy(ctx);
1403 return NT_STATUS_OK;
1406 /*******************************************************************
1407 Internal interface to resolve a name into an IP address.
1408 Use this function if the string is either an IP address, DNS
1409 or host name or NetBIOS name. This uses the name switch in the
1410 smb.conf to determine the order of name resolution.
1412 Added support for ip addr/port to support ADS ldap servers.
1413 the only place we currently care about the port is in the
1414 resolve_hosts() when looking up DC's via SRV RR entries in DNS
1415 **********************************************************************/
1417 NTSTATUS internal_resolve_name(const char *name,
1418 int name_type,
1419 const char *sitename,
1420 struct ip_service **return_iplist,
1421 int *return_count,
1422 const char *resolve_order)
1424 pstring name_resolve_list;
1425 fstring tok;
1426 const char *ptr;
1427 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
1428 int i;
1430 *return_iplist = NULL;
1431 *return_count = 0;
1433 DEBUG(10, ("internal_resolve_name: looking up %s#%x (sitename %s)\n",
1434 name, name_type, sitename ? sitename : NULL));
1436 if (is_ipaddress(name)) {
1437 if ((*return_iplist = SMB_MALLOC_P(struct ip_service)) ==
1438 NULL) {
1439 DEBUG(0,("internal_resolve_name: malloc fail !\n"));
1440 return NT_STATUS_NO_MEMORY;
1443 /* ignore the port here */
1444 (*return_iplist)->port = PORT_NONE;
1446 /* if it's in the form of an IP address then get the lib to interpret it */
1447 if (!interpret_string_addr(&(*return_iplist)->ss,
1448 name, AI_NUMERICHOST)) {
1449 DEBUG(1,("internal_resolve_name: interpret_string_addr "
1450 "failed on %s\n",
1451 name));
1452 SAFE_FREE(*return_iplist);
1453 return NT_STATUS_INVALID_PARAMETER;
1455 *return_count = 1;
1456 return NT_STATUS_OK;
1459 /* Check name cache */
1461 if (namecache_fetch(name, name_type, return_iplist, return_count)) {
1462 /* This could be a negative response */
1463 if (*return_count > 0) {
1464 return NT_STATUS_OK;
1465 } else {
1466 return NT_STATUS_UNSUCCESSFUL;
1470 /* set the name resolution order */
1472 if (strcmp( resolve_order, "NULL") == 0) {
1473 DEBUG(8,("internal_resolve_name: all lookups disabled\n"));
1474 return NT_STATUS_INVALID_PARAMETER;
1477 if (!resolve_order) {
1478 pstrcpy(name_resolve_list, lp_name_resolve_order());
1479 } else {
1480 pstrcpy(name_resolve_list, resolve_order);
1483 if (!name_resolve_list[0]) {
1484 ptr = "host";
1485 } else {
1486 ptr = name_resolve_list;
1489 /* iterate through the name resolution backends */
1491 while (next_token(&ptr, tok, LIST_SEP, sizeof(tok))) {
1492 if((strequal(tok, "host") || strequal(tok, "hosts"))) {
1493 status = resolve_hosts(name, name_type, return_iplist,
1494 return_count);
1495 if (NT_STATUS_IS_OK(status)) {
1496 goto done;
1498 } else if(strequal( tok, "kdc")) {
1499 /* deal with KDC_NAME_TYPE names here.
1500 * This will result in a SRV record lookup */
1501 status = resolve_ads(name, KDC_NAME_TYPE, sitename,
1502 return_iplist, return_count);
1503 if (NT_STATUS_IS_OK(status)) {
1504 /* Ensure we don't namecache
1505 * this with the KDC port. */
1506 name_type = KDC_NAME_TYPE;
1507 goto done;
1509 } else if(strequal( tok, "ads")) {
1510 /* deal with 0x1c and 0x1b names here.
1511 * This will result in a SRV record lookup */
1512 status = resolve_ads(name, name_type, sitename,
1513 return_iplist, return_count);
1514 if (NT_STATUS_IS_OK(status)) {
1515 goto done;
1517 } else if(strequal( tok, "lmhosts")) {
1518 status = resolve_lmhosts(name, name_type,
1519 return_iplist, return_count);
1520 if (NT_STATUS_IS_OK(status)) {
1521 goto done;
1523 } else if(strequal( tok, "wins")) {
1524 /* don't resolve 1D via WINS */
1525 if (name_type != 0x1D) {
1526 status = resolve_wins(name, name_type,
1527 return_iplist,
1528 return_count);
1529 if (NT_STATUS_IS_OK(status)) {
1530 goto done;
1533 } else if(strequal( tok, "bcast")) {
1534 status = name_resolve_bcast(name, name_type,
1535 return_iplist,
1536 return_count);
1537 if (NT_STATUS_IS_OK(status)) {
1538 goto done;
1540 } else {
1541 DEBUG(0,("resolve_name: unknown name switch type %s\n",
1542 tok));
1546 /* All of the resolve_* functions above have returned false. */
1548 SAFE_FREE(*return_iplist);
1549 *return_count = 0;
1551 return NT_STATUS_UNSUCCESSFUL;
1553 done:
1555 /* Remove duplicate entries. Some queries, notably #1c (domain
1556 controllers) return the PDC in iplist[0] and then all domain
1557 controllers including the PDC in iplist[1..n]. Iterating over
1558 the iplist when the PDC is down will cause two sets of timeouts. */
1560 if ( *return_count ) {
1561 *return_count = remove_duplicate_addrs2(*return_iplist,
1562 *return_count );
1565 /* Save in name cache */
1566 if ( DEBUGLEVEL >= 100 ) {
1567 for (i = 0; i < *return_count && DEBUGLEVEL == 100; i++) {
1568 char addr[INET6_ADDRSTRLEN];
1569 print_sockaddr(addr, sizeof(addr),
1570 &(*return_iplist)[i].ss);
1571 DEBUG(100, ("Storing name %s of type %d (%s:%d)\n",
1572 name,
1573 name_type,
1574 addr,
1575 (*return_iplist)[i].port));
1579 namecache_store(name, name_type, *return_count, *return_iplist);
1581 /* Display some debugging info */
1583 if ( DEBUGLEVEL >= 10 ) {
1584 DEBUG(10, ("internal_resolve_name: returning %d addresses: ",
1585 *return_count));
1587 for (i = 0; i < *return_count; i++) {
1588 char addr[INET6_ADDRSTRLEN];
1589 print_sockaddr(addr, sizeof(addr),
1590 &(*return_iplist)[i].ss);
1591 DEBUGADD(10, ("%s:%d ",
1592 addr,
1593 (*return_iplist)[i].port));
1595 DEBUG(10, ("\n"));
1598 return status;
1601 /********************************************************
1602 Internal interface to resolve a name into one IP address.
1603 Use this function if the string is either an IP address, DNS
1604 or host name or NetBIOS name. This uses the name switch in the
1605 smb.conf to determine the order of name resolution.
1606 *********************************************************/
1608 bool resolve_name(const char *name,
1609 struct sockaddr_storage *return_ss,
1610 int name_type)
1612 struct ip_service *ss_list = NULL;
1613 char *sitename = NULL;
1614 int count = 0;
1616 if (is_ipaddress(name)) {
1617 return interpret_string_addr(return_ss, name, AI_NUMERICHOST);
1620 sitename = sitename_fetch(lp_realm()); /* wild guess */
1622 if (NT_STATUS_IS_OK(internal_resolve_name(name, name_type, sitename,
1623 &ss_list, &count,
1624 lp_name_resolve_order()))) {
1625 int i;
1627 /* only return valid addresses for TCP connections */
1628 for (i=0; i<count; i++) {
1629 if (!is_zero_addr(&ss_list[i].ss) &&
1630 !is_broadcast_addr(&ss_list[i].ss)) {
1631 *return_ss = ss_list[i].ss;
1632 SAFE_FREE(ss_list);
1633 SAFE_FREE(sitename);
1634 return True;
1639 SAFE_FREE(ss_list);
1640 SAFE_FREE(sitename);
1641 return False;
1644 /********************************************************
1645 Find the IP address of the master browser or DMB for a workgroup.
1646 *********************************************************/
1648 bool find_master_ip(const char *group, struct sockaddr_storage *master_ss)
1650 struct ip_service *ip_list = NULL;
1651 int count = 0;
1652 NTSTATUS status;
1654 if (lp_disable_netbios()) {
1655 DEBUG(5,("find_master_ip(%s): netbios is disabled\n", group));
1656 return false;
1659 status = internal_resolve_name(group, 0x1D, NULL, &ip_list, &count,
1660 lp_name_resolve_order());
1661 if (NT_STATUS_IS_OK(status)) {
1662 *master_ss = ip_list[0].ss;
1663 SAFE_FREE(ip_list);
1664 return true;
1667 status = internal_resolve_name(group, 0x1B, NULL, &ip_list, &count,
1668 lp_name_resolve_order());
1669 if (NT_STATUS_IS_OK(status)) {
1670 *master_ss = ip_list[0].ss;
1671 SAFE_FREE(ip_list);
1672 return true;
1675 SAFE_FREE(ip_list);
1676 return false;
1679 /********************************************************
1680 Get the IP address list of the primary domain controller
1681 for a domain.
1682 *********************************************************/
1684 bool get_pdc_ip(const char *domain, struct sockaddr_storage *pss)
1686 struct ip_service *ip_list = NULL;
1687 int count = 0;
1688 NTSTATUS status = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1690 /* Look up #1B name */
1692 if (lp_security() == SEC_ADS) {
1693 status = internal_resolve_name(domain, 0x1b, NULL, &ip_list,
1694 &count, "ads");
1697 if (!NT_STATUS_IS_OK(status) || count == 0) {
1698 status = internal_resolve_name(domain, 0x1b, NULL, &ip_list,
1699 &count,
1700 lp_name_resolve_order());
1701 if (!NT_STATUS_IS_OK(status)) {
1702 return false;
1706 /* if we get more than 1 IP back we have to assume it is a
1707 multi-homed PDC and not a mess up */
1709 if ( count > 1 ) {
1710 DEBUG(6,("get_pdc_ip: PDC has %d IP addresses!\n", count));
1711 sort_service_list(ip_list, count);
1714 *pss = ip_list[0].ss;
1715 SAFE_FREE(ip_list);
1716 return true;
1719 /* Private enum type for lookups. */
1721 enum dc_lookup_type { DC_NORMAL_LOOKUP, DC_ADS_ONLY, DC_KDC_ONLY };
1723 /********************************************************
1724 Get the IP address list of the domain controllers for
1725 a domain.
1726 *********************************************************/
1728 static NTSTATUS get_dc_list(const char *domain,
1729 const char *sitename,
1730 struct ip_service **ip_list,
1731 int *count,
1732 enum dc_lookup_type lookup_type,
1733 bool *ordered)
1735 fstring resolve_order;
1736 char *saf_servername;
1737 pstring pserver;
1738 const char *p;
1739 char *port_str;
1740 int port;
1741 fstring name;
1742 int num_addresses = 0;
1743 int local_count, i, j;
1744 struct ip_service *return_iplist = NULL;
1745 struct ip_service *auto_ip_list = NULL;
1746 bool done_auto_lookup = False;
1747 int auto_count = 0;
1748 NTSTATUS status;
1750 *ordered = False;
1752 /* if we are restricted to solely using DNS for looking
1753 up a domain controller, make sure that host lookups
1754 are enabled for the 'name resolve order'. If host lookups
1755 are disabled and ads_only is True, then set the string to
1756 NULL. */
1758 fstrcpy(resolve_order, lp_name_resolve_order());
1759 strlower_m(resolve_order);
1760 if (lookup_type == DC_ADS_ONLY) {
1761 if (strstr( resolve_order, "host")) {
1762 fstrcpy( resolve_order, "ads");
1764 /* DNS SRV lookups used by the ads resolver
1765 are already sorted by priority and weight */
1766 *ordered = true;
1767 } else {
1768 fstrcpy(resolve_order, "NULL");
1770 } else if (lookup_type == DC_KDC_ONLY) {
1771 /* DNS SRV lookups used by the ads/kdc resolver
1772 are already sorted by priority and weight */
1773 *ordered = true;
1774 fstrcpy(resolve_order, "kdc");
1777 /* fetch the server we have affinity for. Add the
1778 'password server' list to a search for our domain controllers */
1780 saf_servername = saf_fetch( domain);
1782 if (strequal(domain, lp_workgroup()) || strequal(domain, lp_realm())) {
1783 pstr_sprintf(pserver, "%s, %s",
1784 saf_servername ? saf_servername : "",
1785 lp_passwordserver());
1786 } else {
1787 pstr_sprintf(pserver, "%s, *",
1788 saf_servername ? saf_servername : "");
1791 SAFE_FREE( saf_servername );
1793 /* if we are starting from scratch, just lookup DOMAIN<0x1c> */
1795 if (!*pserver ) {
1796 DEBUG(10,("get_dc_list: no preferred domain controllers.\n"));
1797 return internal_resolve_name(domain, 0x1C, sitename, ip_list,
1798 count, resolve_order);
1801 DEBUG(3,("get_dc_list: preferred server list: \"%s\"\n", pserver ));
1804 * if '*' appears in the "password server" list then add
1805 * an auto lookup to the list of manually configured
1806 * DC's. If any DC is listed by name, then the list should be
1807 * considered to be ordered
1810 p = pserver;
1811 while (next_token(&p,name,LIST_SEP,sizeof(name))) {
1812 if (strequal(name, "*")) {
1813 status = internal_resolve_name(domain, 0x1C, sitename,
1814 &auto_ip_list,
1815 &auto_count,
1816 resolve_order);
1817 if (NT_STATUS_IS_OK(status)) {
1818 num_addresses += auto_count;
1820 done_auto_lookup = true;
1821 DEBUG(8,("Adding %d DC's from auto lookup\n",
1822 auto_count));
1823 } else {
1824 num_addresses++;
1828 /* if we have no addresses and haven't done the auto lookup, then
1829 just return the list of DC's. Or maybe we just failed. */
1831 if ((num_addresses == 0)) {
1832 if (done_auto_lookup) {
1833 DEBUG(4,("get_dc_list: no servers found\n"));
1834 SAFE_FREE(auto_ip_list);
1835 return NT_STATUS_NO_LOGON_SERVERS;
1837 return internal_resolve_name(domain, 0x1C, sitename, ip_list,
1838 count, resolve_order);
1841 if ((return_iplist = SMB_MALLOC_ARRAY(struct ip_service,
1842 num_addresses)) == NULL) {
1843 DEBUG(3,("get_dc_list: malloc fail !\n"));
1844 SAFE_FREE(auto_ip_list);
1845 return NT_STATUS_NO_MEMORY;
1848 p = pserver;
1849 local_count = 0;
1851 /* fill in the return list now with real IP's */
1853 while ((local_count<num_addresses) &&
1854 next_token(&p,name,LIST_SEP,sizeof(name))) {
1855 struct sockaddr_storage name_ss;
1857 /* copy any addersses from the auto lookup */
1859 if (strequal(name, "*")) {
1860 for (j=0; j<auto_count; j++) {
1861 char addr[INET6_ADDRSTRLEN];
1862 print_sockaddr(addr,
1863 sizeof(addr),
1864 &auto_ip_list[j].ss);
1865 /* Check for and don't copy any
1866 * known bad DC IP's. */
1867 if(!NT_STATUS_IS_OK(check_negative_conn_cache(
1868 domain,
1869 addr))) {
1870 DEBUG(5,("get_dc_list: "
1871 "negative entry %s removed "
1872 "from DC list\n",
1873 addr));
1874 continue;
1876 return_iplist[local_count].ss =
1877 auto_ip_list[j].ss;
1878 return_iplist[local_count].port =
1879 auto_ip_list[j].port;
1880 local_count++;
1882 continue;
1885 /* added support for address:port syntax for ads
1886 * (not that I think anyone will ever run the LDAP
1887 * server in an AD domain on something other than
1888 * port 389 */
1890 port = (lp_security() == SEC_ADS) ? LDAP_PORT : PORT_NONE;
1891 if ((port_str=strchr(name, ':')) != NULL) {
1892 *port_str = '\0';
1893 port_str++;
1894 port = atoi(port_str);
1897 /* explicit lookup; resolve_name() will
1898 * handle names & IP addresses */
1899 if (resolve_name( name, &name_ss, 0x20 )) {
1900 char addr[INET6_ADDRSTRLEN];
1901 print_sockaddr(addr,
1902 sizeof(addr),
1903 &name_ss);
1905 /* Check for and don't copy any known bad DC IP's. */
1906 if( !NT_STATUS_IS_OK(check_negative_conn_cache(domain,
1907 addr)) ) {
1908 DEBUG(5,("get_dc_list: negative entry %s "
1909 "removed from DC list\n",
1910 name ));
1911 continue;
1914 return_iplist[local_count].ss = name_ss;
1915 return_iplist[local_count].port = port;
1916 local_count++;
1917 *ordered = true;
1921 SAFE_FREE(auto_ip_list);
1923 /* need to remove duplicates in the list if we have any
1924 explicit password servers */
1926 if (local_count) {
1927 local_count = remove_duplicate_addrs2(return_iplist,
1928 local_count );
1931 if ( DEBUGLEVEL >= 4 ) {
1932 DEBUG(4,("get_dc_list: returning %d ip addresses "
1933 "in an %sordered list\n",
1934 local_count,
1935 *ordered ? "":"un"));
1936 DEBUG(4,("get_dc_list: "));
1937 for ( i=0; i<local_count; i++ ) {
1938 char addr[INET6_ADDRSTRLEN];
1939 print_sockaddr(addr,
1940 sizeof(addr),
1941 &return_iplist[i].ss);
1942 DEBUGADD(4,("%s:%d ", addr, return_iplist[i].port ));
1944 DEBUGADD(4,("\n"));
1947 *ip_list = return_iplist;
1948 *count = local_count;
1950 return ( *count != 0 ? NT_STATUS_OK : NT_STATUS_NO_LOGON_SERVERS );
1953 /*********************************************************************
1954 Small wrapper function to get the DC list and sort it if neccessary.
1955 *********************************************************************/
1957 NTSTATUS get_sorted_dc_list( const char *domain,
1958 const char *sitename,
1959 struct ip_service **ip_list,
1960 int *count,
1961 bool ads_only )
1963 bool ordered;
1964 NTSTATUS status;
1965 enum dc_lookup_type lookup_type = DC_NORMAL_LOOKUP;
1967 DEBUG(8,("get_sorted_dc_list: attempting lookup "
1968 "for name %s (sitename %s) using [%s]\n",
1969 domain,
1970 sitename ? sitename : "NULL",
1971 (ads_only ? "ads" : lp_name_resolve_order())));
1973 if (ads_only) {
1974 lookup_type = DC_ADS_ONLY;
1977 status = get_dc_list(domain, sitename, ip_list,
1978 count, lookup_type, &ordered);
1979 if (!NT_STATUS_IS_OK(status)) {
1980 return status;
1983 /* only sort if we don't already have an ordered list */
1984 if (!ordered) {
1985 sort_service_list(*ip_list, *count);
1988 return NT_STATUS_OK;
1991 /*********************************************************************
1992 Get the KDC list - re-use all the logic in get_dc_list.
1993 *********************************************************************/
1995 NTSTATUS get_kdc_list( const char *realm,
1996 const char *sitename,
1997 struct ip_service **ip_list,
1998 int *count)
2000 bool ordered;
2001 NTSTATUS status;
2003 *count = 0;
2004 *ip_list = NULL;
2006 status = get_dc_list(realm, sitename, ip_list,
2007 count, DC_KDC_ONLY, &ordered);
2009 if (!NT_STATUS_IS_OK(status)) {
2010 return status;
2013 /* only sort if we don't already have an ordered list */
2014 if ( !ordered ) {
2015 sort_service_list(*ip_list, *count);
2018 return NT_STATUS_OK;