* fix to display correct form information in REG_BINARY information
[Samba.git] / source / libsmb / namequery.c
blobe2ddfd828098847868385fabad3b47f61a432614
1 /*
2 Unix SMB/CIFS implementation.
3 name query routines
4 Copyright (C) Andrew Tridgell 1994-1998
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.
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.
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.
22 #include "includes.h"
24 /* nmbd.c sets this to True. */
25 BOOL global_in_nmbd = False;
27 /****************************************************************************
28 generate a random trn_id
29 ****************************************************************************/
30 static int generate_trn_id(void)
32 static int trn_id;
34 if (trn_id == 0) {
35 sys_srandom(sys_getpid());
38 trn_id = sys_random();
40 return trn_id % (unsigned)0x7FFF;
44 /****************************************************************************
45 parse a node status response into an array of structures
46 ****************************************************************************/
47 static struct node_status *parse_node_status(char *p, int *num_names)
49 struct node_status *ret;
50 int i;
52 *num_names = CVAL(p,0);
54 if (*num_names == 0) return NULL;
56 ret = (struct node_status *)malloc(sizeof(struct node_status)* (*num_names));
57 if (!ret) return NULL;
59 p++;
60 for (i=0;i< *num_names;i++) {
61 StrnCpy(ret[i].name,p,15);
62 trim_string(ret[i].name,NULL," ");
63 ret[i].type = CVAL(p,15);
64 ret[i].flags = p[16];
65 p += 18;
66 DEBUG(10, ("%s#%02x: flags = 0x%02x\n", ret[i].name,
67 ret[i].type, ret[i].flags));
69 return ret;
73 /****************************************************************************
74 do a NBT node status query on an open socket and return an array of
75 structures holding the returned names or NULL if the query failed
76 **************************************************************************/
77 struct node_status *node_status_query(int fd,struct nmb_name *name,
78 struct in_addr to_ip, int *num_names)
80 BOOL found=False;
81 int retries = 2;
82 int retry_time = 2000;
83 struct timeval tval;
84 struct packet_struct p;
85 struct packet_struct *p2;
86 struct nmb_packet *nmb = &p.packet.nmb;
87 struct node_status *ret;
89 ZERO_STRUCT(p);
91 nmb->header.name_trn_id = generate_trn_id();
92 nmb->header.opcode = 0;
93 nmb->header.response = False;
94 nmb->header.nm_flags.bcast = False;
95 nmb->header.nm_flags.recursion_available = False;
96 nmb->header.nm_flags.recursion_desired = False;
97 nmb->header.nm_flags.trunc = False;
98 nmb->header.nm_flags.authoritative = False;
99 nmb->header.rcode = 0;
100 nmb->header.qdcount = 1;
101 nmb->header.ancount = 0;
102 nmb->header.nscount = 0;
103 nmb->header.arcount = 0;
104 nmb->question.question_name = *name;
105 nmb->question.question_type = 0x21;
106 nmb->question.question_class = 0x1;
108 p.ip = to_ip;
109 p.port = NMB_PORT;
110 p.fd = fd;
111 p.timestamp = time(NULL);
112 p.packet_type = NMB_PACKET;
114 GetTimeOfDay(&tval);
116 if (!send_packet(&p))
117 return NULL;
119 retries--;
121 while (1) {
122 struct timeval tval2;
123 GetTimeOfDay(&tval2);
124 if (TvalDiff(&tval,&tval2) > retry_time) {
125 if (!retries)
126 break;
127 if (!found && !send_packet(&p))
128 return NULL;
129 GetTimeOfDay(&tval);
130 retries--;
133 if ((p2=receive_nmb_packet(fd,90,nmb->header.name_trn_id))) {
134 struct nmb_packet *nmb2 = &p2->packet.nmb;
135 debug_nmb_packet(p2);
137 if (nmb2->header.opcode != 0 ||
138 nmb2->header.nm_flags.bcast ||
139 nmb2->header.rcode ||
140 !nmb2->header.ancount ||
141 nmb2->answers->rr_type != 0x21) {
142 /* XXXX what do we do with this? could be a
143 redirect, but we'll discard it for the
144 moment */
145 free_packet(p2);
146 continue;
149 ret = parse_node_status(&nmb2->answers->rdata[0], num_names);
150 free_packet(p2);
151 return ret;
155 return NULL;
159 /****************************************************************************
160 find the first type XX name in a node status reply - used for finding
161 a servers name given its IP
162 return the matched name in *name
163 **************************************************************************/
165 BOOL name_status_find(const char *q_name, int q_type, int type, struct in_addr to_ip, char *name)
167 struct node_status *status = NULL;
168 struct nmb_name nname;
169 int count, i;
170 int sock;
171 BOOL result = False;
173 DEBUG(10, ("name_status_find: looking up %s#%02x at %s\n", q_name,
174 q_type, inet_ntoa(to_ip)));
176 sock = open_socket_in(SOCK_DGRAM, 0, 3, interpret_addr(lp_socket_address()), True);
177 if (sock == -1)
178 goto done;
180 /* W2K PDC's seem not to respond to '*'#0. JRA */
181 make_nmb_name(&nname, q_name, q_type);
182 status = node_status_query(sock, &nname, to_ip, &count);
183 close(sock);
184 if (!status)
185 goto done;
187 for (i=0;i<count;i++) {
188 if (status[i].type == type)
189 break;
191 if (i == count)
192 goto done;
194 pull_ascii(name, status[i].name, 15, -1, STR_TERMINATE);
195 result = True;
197 done:
198 SAFE_FREE(status);
200 DEBUG(10, ("name_status_find: name %sfound", result ? "" : "not "));
202 if (result)
203 DEBUGADD(10, (", ip address is %s", inet_ntoa(to_ip)));
205 DEBUG(10, ("\n"));
207 return result;
212 comparison function used by sort_ip_list
214 static int ip_compare(struct in_addr *ip1, struct in_addr *ip2)
216 int max_bits1=0, max_bits2=0;
217 int num_interfaces = iface_count();
218 int i;
220 for (i=0;i<num_interfaces;i++) {
221 struct in_addr ip;
222 int bits1, bits2;
223 ip = *iface_n_bcast(i);
224 bits1 = matching_quad_bits((uchar *)&ip1->s_addr, (uchar *)&ip.s_addr);
225 bits2 = matching_quad_bits((uchar *)&ip2->s_addr, (uchar *)&ip.s_addr);
226 max_bits1 = MAX(bits1, max_bits1);
227 max_bits2 = MAX(bits2, max_bits2);
230 /* bias towards directly reachable IPs */
231 if (iface_local(*ip1)) {
232 max_bits1 += 32;
234 if (iface_local(*ip2)) {
235 max_bits2 += 32;
238 return max_bits2 - max_bits1;
242 sort an IP list so that names that are close to one of our interfaces
243 are at the top. This prevents the problem where a WINS server returns an IP that
244 is not reachable from our subnet as the first match
246 static void sort_ip_list(struct in_addr *iplist, int count)
248 if (count <= 1) {
249 return;
252 qsort(iplist, count, sizeof(struct in_addr), QSORT_CAST ip_compare);
256 /****************************************************************************
257 Do a netbios name query to find someones IP.
258 Returns an array of IP addresses or NULL if none.
259 *count will be set to the number of addresses returned.
260 *timed_out is set if we failed by timing out
261 ****************************************************************************/
262 struct in_addr *name_query(int fd,const char *name,int name_type,
263 BOOL bcast,BOOL recurse,
264 struct in_addr to_ip, int *count, int *flags,
265 BOOL *timed_out)
267 BOOL found=False;
268 int i, retries = 3;
269 int retry_time = bcast?250:2000;
270 struct timeval tval;
271 struct packet_struct p;
272 struct packet_struct *p2;
273 struct nmb_packet *nmb = &p.packet.nmb;
274 struct in_addr *ip_list = NULL;
276 if (timed_out) {
277 *timed_out = False;
280 memset((char *)&p,'\0',sizeof(p));
281 (*count) = 0;
282 (*flags) = 0;
284 nmb->header.name_trn_id = generate_trn_id();
285 nmb->header.opcode = 0;
286 nmb->header.response = False;
287 nmb->header.nm_flags.bcast = bcast;
288 nmb->header.nm_flags.recursion_available = False;
289 nmb->header.nm_flags.recursion_desired = recurse;
290 nmb->header.nm_flags.trunc = False;
291 nmb->header.nm_flags.authoritative = False;
292 nmb->header.rcode = 0;
293 nmb->header.qdcount = 1;
294 nmb->header.ancount = 0;
295 nmb->header.nscount = 0;
296 nmb->header.arcount = 0;
298 make_nmb_name(&nmb->question.question_name,name,name_type);
300 nmb->question.question_type = 0x20;
301 nmb->question.question_class = 0x1;
303 p.ip = to_ip;
304 p.port = NMB_PORT;
305 p.fd = fd;
306 p.timestamp = time(NULL);
307 p.packet_type = NMB_PACKET;
309 GetTimeOfDay(&tval);
311 if (!send_packet(&p))
312 return NULL;
314 retries--;
316 while (1) {
317 struct timeval tval2;
318 struct in_addr *tmp_ip_list;
320 GetTimeOfDay(&tval2);
321 if (TvalDiff(&tval,&tval2) > retry_time) {
322 if (!retries)
323 break;
324 if (!found && !send_packet(&p))
325 return NULL;
326 GetTimeOfDay(&tval);
327 retries--;
330 if ((p2=receive_nmb_packet(fd,90,nmb->header.name_trn_id))) {
331 struct nmb_packet *nmb2 = &p2->packet.nmb;
332 debug_nmb_packet(p2);
334 /* If we get a Negative Name Query Response from a WINS
335 * server, we should report it and give up.
337 if( 0 == nmb2->header.opcode /* A query response */
338 && !(bcast) /* from a WINS server */
339 && nmb2->header.rcode /* Error returned */
342 if( DEBUGLVL( 3 ) ) {
343 /* Only executed if DEBUGLEVEL >= 3 */
344 dbgtext( "Negative name query response, rcode 0x%02x: ", nmb2->header.rcode );
345 switch( nmb2->header.rcode ) {
346 case 0x01:
347 dbgtext( "Request was invalidly formatted.\n" );
348 break;
349 case 0x02:
350 dbgtext( "Problem with NBNS, cannot process name.\n");
351 break;
352 case 0x03:
353 dbgtext( "The name requested does not exist.\n" );
354 break;
355 case 0x04:
356 dbgtext( "Unsupported request error.\n" );
357 break;
358 case 0x05:
359 dbgtext( "Query refused error.\n" );
360 break;
361 default:
362 dbgtext( "Unrecognized error code.\n" );
363 break;
366 free_packet(p2);
367 return( NULL );
370 if (nmb2->header.opcode != 0 ||
371 nmb2->header.nm_flags.bcast ||
372 nmb2->header.rcode ||
373 !nmb2->header.ancount) {
375 * XXXX what do we do with this? Could be a
376 * redirect, but we'll discard it for the
377 * moment.
379 free_packet(p2);
380 continue;
383 tmp_ip_list = (struct in_addr *)Realloc( ip_list, sizeof( ip_list[0] )
384 * ( (*count) + nmb2->answers->rdlength/6 ) );
386 if (!tmp_ip_list) {
387 DEBUG(0,("name_query: Realloc failed.\n"));
388 SAFE_FREE(ip_list);
391 ip_list = tmp_ip_list;
393 if (ip_list) {
394 DEBUG(2,("Got a positive name query response from %s ( ", inet_ntoa(p2->ip)));
395 for (i=0;i<nmb2->answers->rdlength/6;i++) {
396 putip((char *)&ip_list[(*count)],&nmb2->answers->rdata[2+i*6]);
397 DEBUGADD(2,("%s ",inet_ntoa(ip_list[(*count)])));
398 (*count)++;
400 DEBUGADD(2,(")\n"));
403 found=True;
404 retries=0;
405 /* We add the flags back ... */
406 if (nmb2->header.response)
407 (*flags) |= NM_FLAGS_RS;
408 if (nmb2->header.nm_flags.authoritative)
409 (*flags) |= NM_FLAGS_AA;
410 if (nmb2->header.nm_flags.trunc)
411 (*flags) |= NM_FLAGS_TC;
412 if (nmb2->header.nm_flags.recursion_desired)
413 (*flags) |= NM_FLAGS_RD;
414 if (nmb2->header.nm_flags.recursion_available)
415 (*flags) |= NM_FLAGS_RA;
416 if (nmb2->header.nm_flags.bcast)
417 (*flags) |= NM_FLAGS_B;
418 free_packet(p2);
420 * If we're doing a unicast lookup we only
421 * expect one reply. Don't wait the full 2
422 * seconds if we got one. JRA.
424 if(!bcast && found)
425 break;
429 if (timed_out) {
430 *timed_out = True;
433 /* sort the ip list so we choose close servers first if possible */
434 sort_ip_list(ip_list, *count);
436 return ip_list;
439 /********************************************************
440 Start parsing the lmhosts file.
441 *********************************************************/
443 XFILE *startlmhosts(char *fname)
445 XFILE *fp = x_fopen(fname,O_RDONLY, 0);
446 if (!fp) {
447 DEBUG(4,("startlmhosts: Can't open lmhosts file %s. Error was %s\n",
448 fname, strerror(errno)));
449 return NULL;
451 return fp;
454 /********************************************************
455 Parse the next line in the lmhosts file.
456 *********************************************************/
458 BOOL getlmhostsent( XFILE *fp, pstring name, int *name_type, struct in_addr *ipaddr)
460 pstring line;
462 while(!x_feof(fp) && !x_ferror(fp)) {
463 pstring ip,flags,extra;
464 char *ptr;
465 int count = 0;
467 *name_type = -1;
469 if (!fgets_slash(line,sizeof(pstring),fp))
470 continue;
472 if (*line == '#')
473 continue;
475 pstrcpy(ip,"");
476 pstrcpy(name,"");
477 pstrcpy(flags,"");
479 ptr = line;
481 if (next_token(&ptr,ip ,NULL,sizeof(ip)))
482 ++count;
483 if (next_token(&ptr,name ,NULL, sizeof(pstring)))
484 ++count;
485 if (next_token(&ptr,flags,NULL, sizeof(flags)))
486 ++count;
487 if (next_token(&ptr,extra,NULL, sizeof(extra)))
488 ++count;
490 if (count <= 0)
491 continue;
493 if (count > 0 && count < 2)
495 DEBUG(0,("getlmhostsent: Ill formed hosts line [%s]\n",line));
496 continue;
499 if (count >= 4)
501 DEBUG(0,("getlmhostsent: too many columns in lmhosts file (obsolete syntax)\n"));
502 continue;
505 DEBUG(4, ("getlmhostsent: lmhost entry: %s %s %s\n", ip, name, flags));
507 if (strchr_m(flags,'G') || strchr_m(flags,'S'))
509 DEBUG(0,("getlmhostsent: group flag in lmhosts ignored (obsolete)\n"));
510 continue;
513 *ipaddr = *interpret_addr2(ip);
515 /* Extra feature. If the name ends in '#XX', where XX is a hex number,
516 then only add that name type. */
517 if((ptr = strchr_m(name, '#')) != NULL)
519 char *endptr;
521 ptr++;
522 *name_type = (int)strtol(ptr, &endptr, 16);
524 if(!*ptr || (endptr == ptr))
526 DEBUG(0,("getlmhostsent: invalid name %s containing '#'.\n", name));
527 continue;
530 *(--ptr) = '\0'; /* Truncate at the '#' */
533 return True;
536 return False;
539 /********************************************************
540 Finish parsing the lmhosts file.
541 *********************************************************/
543 void endlmhosts(XFILE *fp)
545 x_fclose(fp);
549 /********************************************************
550 Resolve via "bcast" method.
551 *********************************************************/
553 BOOL name_resolve_bcast(const char *name, int name_type,
554 struct in_addr **return_ip_list, int *return_count)
556 int sock, i;
557 int num_interfaces = iface_count();
559 *return_ip_list = NULL;
560 *return_count = 0;
563 * "bcast" means do a broadcast lookup on all the local interfaces.
566 DEBUG(3,("name_resolve_bcast: Attempting broadcast lookup for name %s<0x%x>\n", name, name_type));
568 sock = open_socket_in( SOCK_DGRAM, 0, 3,
569 interpret_addr(lp_socket_address()), True );
571 if (sock == -1) return False;
573 set_socket_options(sock,"SO_BROADCAST");
575 * Lookup the name on all the interfaces, return on
576 * the first successful match.
578 for( i = num_interfaces-1; i >= 0; i--) {
579 struct in_addr sendto_ip;
580 int flags;
581 /* Done this way to fix compiler error on IRIX 5.x */
582 sendto_ip = *iface_n_bcast(i);
583 *return_ip_list = name_query(sock, name, name_type, True,
584 True, sendto_ip, return_count, &flags, NULL);
585 if(*return_ip_list != NULL) {
586 close(sock);
587 return True;
591 close(sock);
592 return False;
595 /********************************************************
596 Resolve via "wins" method.
597 *********************************************************/
598 BOOL resolve_wins(const char *name, int name_type,
599 struct in_addr **return_iplist, int *return_count)
601 int sock, t, i;
602 char **wins_tags;
603 struct in_addr src_ip;
605 *return_iplist = NULL;
606 *return_count = 0;
608 DEBUG(3,("resolve_wins: Attempting wins lookup for name %s<0x%x>\n", name, name_type));
610 if (wins_srv_count() < 1) {
611 DEBUG(3,("resolve_wins: WINS server resolution selected and no WINS servers listed.\n"));
612 return False;
615 /* we try a lookup on each of the WINS tags in turn */
616 wins_tags = wins_srv_tags();
618 if (!wins_tags) {
619 /* huh? no tags?? give up in disgust */
620 return False;
623 /* the address we will be sending from */
624 src_ip = *interpret_addr2(lp_socket_address());
626 /* in the worst case we will try every wins server with every
627 tag! */
628 for (t=0; wins_tags && wins_tags[t]; t++) {
629 int srv_count = wins_srv_count_tag(wins_tags[t]);
630 for (i=0; i<srv_count; i++) {
631 struct in_addr wins_ip;
632 int flags;
633 BOOL timed_out;
635 wins_ip = wins_srv_ip_tag(wins_tags[t], src_ip);
637 if (global_in_nmbd && ismyip(wins_ip)) {
638 /* yikes! we'll loop forever */
639 continue;
642 /* skip any that have been unresponsive lately */
643 if (wins_srv_is_dead(wins_ip, src_ip)) {
644 continue;
647 DEBUG(3,("resolve_wins: using WINS server %s and tag '%s'\n", inet_ntoa(wins_ip), wins_tags[t]));
649 sock = open_socket_in(SOCK_DGRAM, 0, 3, src_ip.s_addr, True);
650 if (sock == -1) {
651 continue;
654 *return_iplist = name_query(sock,name,name_type, False,
655 True, wins_ip, return_count, &flags,
656 &timed_out);
657 if (*return_iplist != NULL) {
658 goto success;
660 close(sock);
662 if (timed_out) {
663 /* Timed out wating for WINS server to respond. Mark it dead. */
664 wins_srv_died(wins_ip, src_ip);
665 } else {
666 /* The name definately isn't in this
667 group of WINS servers. goto the next group */
668 break;
673 wins_srv_tags_free(wins_tags);
674 return False;
676 success:
677 wins_srv_tags_free(wins_tags);
678 close(sock);
679 return True;
682 /********************************************************
683 Resolve via "lmhosts" method.
684 *********************************************************/
686 static BOOL resolve_lmhosts(const char *name, int name_type,
687 struct in_addr **return_iplist, int *return_count)
690 * "lmhosts" means parse the local lmhosts file.
693 XFILE *fp;
694 pstring lmhost_name;
695 int name_type2;
696 struct in_addr return_ip;
698 *return_iplist = NULL;
699 *return_count = 0;
701 DEBUG(3,("resolve_lmhosts: Attempting lmhosts lookup for name %s<0x%x>\n", name, name_type));
703 fp = startlmhosts(dyn_LMHOSTSFILE);
704 if(fp) {
705 while (getlmhostsent(fp, lmhost_name, &name_type2, &return_ip)) {
706 if (strequal(name, lmhost_name) &&
707 ((name_type2 == -1) || (name_type == name_type2))
709 endlmhosts(fp);
710 *return_iplist = (struct in_addr *)malloc(sizeof(struct in_addr));
711 if(*return_iplist == NULL) {
712 DEBUG(3,("resolve_lmhosts: malloc fail !\n"));
713 return False;
715 **return_iplist = return_ip;
716 *return_count = 1;
717 return True;
720 endlmhosts(fp);
722 return False;
726 /********************************************************
727 Resolve via "hosts" method.
728 *********************************************************/
730 static BOOL resolve_hosts(const char *name,
731 struct in_addr **return_iplist, int *return_count)
734 * "host" means do a localhost, or dns lookup.
736 struct hostent *hp;
738 *return_iplist = NULL;
739 *return_count = 0;
741 DEBUG(3,("resolve_hosts: Attempting host lookup for name %s<0x20>\n", name));
743 if (((hp = sys_gethostbyname(name)) != NULL) && (hp->h_addr != NULL)) {
744 struct in_addr return_ip;
745 putip((char *)&return_ip,(char *)hp->h_addr);
746 *return_iplist = (struct in_addr *)malloc(sizeof(struct in_addr));
747 if(*return_iplist == NULL) {
748 DEBUG(3,("resolve_hosts: malloc fail !\n"));
749 return False;
751 **return_iplist = return_ip;
752 *return_count = 1;
753 return True;
755 return False;
758 /********************************************************
759 Internal interface to resolve a name into an IP address.
760 Use this function if the string is either an IP address, DNS
761 or host name or NetBIOS name. This uses the name switch in the
762 smb.conf to determine the order of name resolution.
763 *********************************************************/
765 static BOOL internal_resolve_name(const char *name, int name_type,
766 struct in_addr **return_iplist, int *return_count)
768 pstring name_resolve_list;
769 fstring tok;
770 char *ptr;
771 BOOL allones = (strcmp(name,"255.255.255.255") == 0);
772 BOOL allzeros = (strcmp(name,"0.0.0.0") == 0);
773 BOOL is_address = is_ipaddress(name);
774 BOOL result = False;
775 struct in_addr *nodupes_iplist;
776 int i;
778 *return_iplist = NULL;
779 *return_count = 0;
781 DEBUG(10, ("internal_resolve_name: looking up %s#%x\n", name, name_type));
783 if (allzeros || allones || is_address) {
784 *return_iplist = (struct in_addr *)malloc(sizeof(struct in_addr));
785 if(*return_iplist == NULL) {
786 DEBUG(3,("internal_resolve_name: malloc fail !\n"));
787 return False;
789 if(is_address) {
790 /* if it's in the form of an IP address then get the lib to interpret it */
791 (*return_iplist)->s_addr = inet_addr(name);
792 } else {
793 (*return_iplist)->s_addr = allones ? 0xFFFFFFFF : 0;
794 *return_count = 1;
796 return True;
799 pstrcpy(name_resolve_list, lp_name_resolve_order());
800 ptr = name_resolve_list;
801 if (!ptr || !*ptr)
802 ptr = "host";
804 while (next_token(&ptr, tok, LIST_SEP, sizeof(tok))) {
805 if((strequal(tok, "host") || strequal(tok, "hosts"))) {
806 if (name_type == 0x20 && resolve_hosts(name, return_iplist, return_count)) {
807 result = True;
808 goto done;
810 } else if(strequal( tok, "lmhosts")) {
811 if (resolve_lmhosts(name, name_type, return_iplist, return_count)) {
812 result = True;
813 goto done;
815 } else if(strequal( tok, "wins")) {
816 /* don't resolve 1D via WINS */
817 if (name_type != 0x1D &&
818 resolve_wins(name, name_type, return_iplist, return_count)) {
819 result = True;
820 goto done;
822 } else if(strequal( tok, "bcast")) {
823 if (name_resolve_bcast(name, name_type, return_iplist, return_count)) {
824 result = True;
825 goto done;
827 } else {
828 DEBUG(0,("resolve_name: unknown name switch type %s\n", tok));
832 /* All of the resolve_* functions above have returned false. */
834 SAFE_FREE(*return_iplist);
835 *return_count = 0;
837 return False;
839 done:
841 /* Remove duplicate entries. Some queries, notably #1c (domain
842 controllers) return the PDC in iplist[0] and then all domain
843 controllers including the PDC in iplist[1..n]. Iterating over
844 the iplist when the PDC is down will cause two sets of timeouts. */
846 if (*return_count && (nodupes_iplist = (struct in_addr *)
847 malloc(sizeof(struct in_addr) * (*return_count)))) {
848 int nodupes_count = 0;
850 /* Iterate over return_iplist looking for duplicates */
852 for (i = 0; i < *return_count; i++) {
853 BOOL is_dupe = False;
854 int j;
856 for (j = i + 1; j < *return_count; j++) {
857 if (ip_equal((*return_iplist)[i],
858 (*return_iplist)[j])) {
859 is_dupe = True;
860 break;
864 if (!is_dupe) {
866 /* This one not a duplicate */
868 nodupes_iplist[nodupes_count] = (*return_iplist)[i];
869 nodupes_count++;
873 /* Switcheroo with original list */
875 free(*return_iplist);
877 *return_iplist = nodupes_iplist;
878 *return_count = nodupes_count;
881 /* Display some debugging info */
883 DEBUG(10, ("internal_resolve_name: returning %d addresses: ",
884 *return_count));
886 for (i = 0; i < *return_count; i++)
887 DEBUGADD(10, ("%s ", inet_ntoa((*return_iplist)[i])));
889 DEBUG(10, ("\n"));
891 return result;
894 /********************************************************
895 Internal interface to resolve a name into one IP address.
896 Use this function if the string is either an IP address, DNS
897 or host name or NetBIOS name. This uses the name switch in the
898 smb.conf to determine the order of name resolution.
899 *********************************************************/
901 BOOL resolve_name(const char *name, struct in_addr *return_ip, int name_type)
903 struct in_addr *ip_list = NULL;
904 int count = 0;
906 if (is_ipaddress(name)) {
907 *return_ip = *interpret_addr2(name);
908 return True;
911 if (internal_resolve_name(name, name_type, &ip_list, &count)) {
912 int i;
913 /* only return valid addresses for TCP connections */
914 for (i=0; i<count; i++) {
915 char *ip_str = inet_ntoa(ip_list[i]);
916 if (ip_str &&
917 strcmp(ip_str, "255.255.255.255") != 0 &&
918 strcmp(ip_str, "0.0.0.0") != 0) {
919 *return_ip = ip_list[i];
920 SAFE_FREE(ip_list);
921 return True;
925 SAFE_FREE(ip_list);
926 return False;
929 /********************************************************
930 Find the IP address of the master browser or DMB for a workgroup.
931 *********************************************************/
933 BOOL find_master_ip(const char *group, struct in_addr *master_ip)
935 struct in_addr *ip_list = NULL;
936 int count = 0;
938 if (internal_resolve_name(group, 0x1D, &ip_list, &count)) {
939 *master_ip = ip_list[0];
940 SAFE_FREE(ip_list);
941 return True;
943 if(internal_resolve_name(group, 0x1B, &ip_list, &count)) {
944 *master_ip = ip_list[0];
945 SAFE_FREE(ip_list);
946 return True;
949 SAFE_FREE(ip_list);
950 return False;
953 /********************************************************
954 Lookup a DC name given a Domain name and IP address.
955 *********************************************************/
957 BOOL lookup_dc_name(const char *srcname, const char *domain,
958 struct in_addr *dc_ip, char *ret_name)
960 #if !defined(I_HATE_WINDOWS_REPLY_CODE)
962 fstring dc_name;
963 BOOL ret;
966 * Due to the fact win WinNT *sucks* we must do a node status
967 * query here... JRA.
970 *dc_name = '\0';
972 ret = name_status_find(domain, 0x1c, 0x20, *dc_ip, dc_name);
974 if(ret && *dc_name) {
975 fstrcpy(ret_name, dc_name);
976 return True;
979 return False;
981 #else /* defined(I_HATE_WINDOWS_REPLY_CODE) */
983 JRA - This code is broken with BDC rollover - we need to do a full
984 NT GETDC call, UNICODE, NT domain SID and uncle tom cobbley and all...
986 int retries = 3;
987 int retry_time = 2000;
988 struct timeval tval;
989 struct packet_struct p;
990 struct dgram_packet *dgram = &p.packet.dgram;
991 char *ptr,*p2;
992 char tmp[4];
993 int len;
994 struct sockaddr_in sock_name;
995 int sock_len = sizeof(sock_name);
996 const char *mailslot = NET_LOGON_MAILSLOT;
997 char *mailslot_name;
998 char buffer[1024];
999 char *bufp;
1000 int dgm_id = generate_trn_id();
1001 int sock = open_socket_in(SOCK_DGRAM, 0, 3, interpret_addr(lp_socket_address()), True );
1003 if(sock == -1)
1004 return False;
1006 /* Find out the transient UDP port we have been allocated. */
1007 if(getsockname(sock, (struct sockaddr *)&sock_name, &sock_len)<0) {
1008 DEBUG(0,("lookup_pdc_name: Failed to get local UDP port. Error was %s\n",
1009 strerror(errno)));
1010 close(sock);
1011 return False;
1015 * Create the request data.
1018 memset(buffer,'\0',sizeof(buffer));
1019 bufp = buffer;
1020 SSVAL(bufp,0,QUERYFORPDC);
1021 bufp += 2;
1022 fstrcpy(bufp,srcname);
1023 bufp += (strlen(bufp) + 1);
1024 slprintf(bufp, sizeof(fstring)-1, "\\MAILSLOT\\NET\\GETDC%d", dgm_id);
1025 mailslot_name = bufp;
1026 bufp += (strlen(bufp) + 1);
1027 bufp = ALIGN2(bufp, buffer);
1028 bufp += push_ucs2(NULL, bufp, srcname, sizeof(buffer) - (bufp - buffer), STR_TERMINATE);
1030 SIVAL(bufp,0,1);
1031 SSVAL(bufp,4,0xFFFF);
1032 SSVAL(bufp,6,0xFFFF);
1033 bufp += 8;
1034 len = PTR_DIFF(bufp,buffer);
1036 memset((char *)&p,'\0',sizeof(p));
1038 /* DIRECT GROUP or UNIQUE datagram. */
1039 dgram->header.msg_type = 0x10;
1040 dgram->header.flags.node_type = M_NODE;
1041 dgram->header.flags.first = True;
1042 dgram->header.flags.more = False;
1043 dgram->header.dgm_id = dgm_id;
1044 dgram->header.source_ip = *iface_ip(*pdc_ip);
1045 dgram->header.source_port = ntohs(sock_name.sin_port);
1046 dgram->header.dgm_length = 0; /* Let build_dgram() handle this. */
1047 dgram->header.packet_offset = 0;
1049 make_nmb_name(&dgram->source_name,srcname,0);
1050 make_nmb_name(&dgram->dest_name,domain,0x1C);
1052 ptr = &dgram->data[0];
1054 /* Setup the smb part. */
1055 ptr -= 4; /* XXX Ugliness because of handling of tcp SMB length. */
1056 memcpy(tmp,ptr,4);
1057 set_message(ptr,17,17 + len,True);
1058 memcpy(ptr,tmp,4);
1060 CVAL(ptr,smb_com) = SMBtrans;
1061 SSVAL(ptr,smb_vwv1,len);
1062 SSVAL(ptr,smb_vwv11,len);
1063 SSVAL(ptr,smb_vwv12,70 + strlen(mailslot));
1064 SSVAL(ptr,smb_vwv13,3);
1065 SSVAL(ptr,smb_vwv14,1);
1066 SSVAL(ptr,smb_vwv15,1);
1067 SSVAL(ptr,smb_vwv16,2);
1068 p2 = smb_buf(ptr);
1069 pstrcpy(p2,mailslot);
1070 p2 = skip_string(p2,1);
1072 memcpy(p2,buffer,len);
1073 p2 += len;
1075 dgram->datasize = PTR_DIFF(p2,ptr+4); /* +4 for tcp length. */
1077 p.ip = *pdc_ip;
1078 p.port = DGRAM_PORT;
1079 p.fd = sock;
1080 p.timestamp = time(NULL);
1081 p.packet_type = DGRAM_PACKET;
1083 GetTimeOfDay(&tval);
1085 if (!send_packet(&p)) {
1086 DEBUG(0,("lookup_pdc_name: send_packet failed.\n"));
1087 close(sock);
1088 return False;
1091 retries--;
1093 while (1) {
1094 struct timeval tval2;
1095 struct packet_struct *p_ret;
1097 GetTimeOfDay(&tval2);
1098 if (TvalDiff(&tval,&tval2) > retry_time) {
1099 if (!retries)
1100 break;
1101 if (!send_packet(&p)) {
1102 DEBUG(0,("lookup_pdc_name: send_packet failed.\n"));
1103 close(sock);
1104 return False;
1106 GetTimeOfDay(&tval);
1107 retries--;
1110 if ((p_ret = receive_dgram_packet(sock,90,mailslot_name))) {
1111 struct dgram_packet *dgram2 = &p_ret->packet.dgram;
1112 char *buf;
1113 char *buf2;
1115 buf = &dgram2->data[0];
1116 buf -= 4;
1118 if (CVAL(buf,smb_com) != SMBtrans) {
1119 DEBUG(0,("lookup_pdc_name: datagram type %u != SMBtrans(%u)\n", (unsigned int)
1120 CVAL(buf,smb_com), (unsigned int)SMBtrans ));
1121 free_packet(p_ret);
1122 continue;
1125 len = SVAL(buf,smb_vwv11);
1126 buf2 = smb_base(buf) + SVAL(buf,smb_vwv12);
1128 if (len <= 0) {
1129 DEBUG(0,("lookup_pdc_name: datagram len < 0 (%d)\n", len ));
1130 free_packet(p_ret);
1131 continue;
1134 DEBUG(4,("lookup_pdc_name: datagram reply from %s to %s IP %s for %s of type %d len=%d\n",
1135 nmb_namestr(&dgram2->source_name),nmb_namestr(&dgram2->dest_name),
1136 inet_ntoa(p_ret->ip), smb_buf(buf),SVAL(buf2,0),len));
1138 if(SVAL(buf2,0) != QUERYFORPDC_R) {
1139 DEBUG(0,("lookup_pdc_name: datagram type (%u) != QUERYFORPDC_R(%u)\n",
1140 (unsigned int)SVAL(buf,0), (unsigned int)QUERYFORPDC_R ));
1141 free_packet(p_ret);
1142 continue;
1145 buf2 += 2;
1146 /* Note this is safe as it is a bounded strcpy. */
1147 fstrcpy(ret_name, buf2);
1148 ret_name[sizeof(fstring)-1] = '\0';
1149 close(sock);
1150 free_packet(p_ret);
1151 return True;
1155 close(sock);
1156 return False;
1157 #endif /* defined(I_HATE_WINDOWS_REPLY_CODE) */
1161 /********************************************************
1162 Get the IP address list of the PDC/BDC's of a Domain.
1163 *********************************************************/
1165 BOOL get_dc_list(BOOL pdc_only, const char *group, struct in_addr **ip_list, int *count)
1167 int name_type = pdc_only ? 0x1B : 0x1C;
1170 * If it's our domain then
1171 * use the 'password server' parameter.
1174 if (strequal(group, lp_workgroup())) {
1175 char *p;
1176 char *pserver = lp_passwordserver();
1177 fstring name;
1178 int num_adresses = 0;
1179 struct in_addr *return_iplist = NULL;
1181 if (! *pserver)
1182 return internal_resolve_name(group, name_type, ip_list, count);
1184 p = pserver;
1185 while (next_token(&p,name,LIST_SEP,sizeof(name))) {
1186 if (strequal(name, "*"))
1187 return internal_resolve_name(group, name_type, ip_list, count);
1188 num_adresses++;
1190 if (num_adresses == 0)
1191 return internal_resolve_name(group, name_type, ip_list, count);
1193 return_iplist = (struct in_addr *)malloc(num_adresses * sizeof(struct in_addr));
1194 if(return_iplist == NULL) {
1195 DEBUG(3,("get_dc_list: malloc fail !\n"));
1196 return False;
1198 p = pserver;
1199 *count = 0;
1200 while (next_token(&p,name,LIST_SEP,sizeof(name))) {
1201 struct in_addr name_ip;
1202 if (resolve_name( name, &name_ip, 0x20) == False)
1203 continue;
1204 return_iplist[(*count)++] = name_ip;
1206 *ip_list = return_iplist;
1207 return (*count != 0);
1208 } else
1209 return internal_resolve_name(group, name_type, ip_list, count);