preparing for release of 3.0-alpha11
[Samba/ekacnet.git] / source / libsmb / namequery.c
blob2c235417a80ef469c11fc018fe69ee0fede76062
1 /*
2 Unix SMB/Netbios implementation.
3 Version 1.9.
4 name query routines
5 Copyright (C) Andrew Tridgell 1994-1998
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 2 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, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 #include "includes.h"
25 /* nmbd.c sets this to True. */
26 BOOL global_in_nmbd = False;
28 /****************************************************************************
29 generate a random trn_id
30 ****************************************************************************/
31 static int generate_trn_id(void)
33 static int trn_id;
35 if (trn_id == 0) {
36 sys_srandom(sys_getpid());
39 trn_id = sys_random();
41 return trn_id % (unsigned)0x7FFF;
45 /****************************************************************************
46 parse a node status response into an array of structures
47 ****************************************************************************/
48 static struct node_status *parse_node_status(char *p, int *num_names)
50 struct node_status *ret;
51 int i;
53 *num_names = CVAL(p,0);
55 if (*num_names == 0) return NULL;
57 ret = (struct node_status *)malloc(sizeof(struct node_status)* (*num_names));
58 if (!ret) return NULL;
60 p++;
61 for (i=0;i< *num_names;i++) {
62 StrnCpy(ret[i].name,p,15);
63 trim_string(ret[i].name,NULL," ");
64 ret[i].type = CVAL(p,15);
65 ret[i].flags = p[16];
66 p += 18;
68 return ret;
72 /****************************************************************************
73 do a NBT node status query on an open socket and return an array of
74 structures holding the returned names or NULL if the query failed
75 **************************************************************************/
76 struct node_status *node_status_query(int fd,struct nmb_name *name,
77 struct in_addr to_ip, int *num_names)
79 BOOL found=False;
80 int retries = 2;
81 int retry_time = 2000;
82 struct timeval tval;
83 struct packet_struct p;
84 struct packet_struct *p2;
85 struct nmb_packet *nmb = &p.packet.nmb;
86 struct node_status *ret;
88 ZERO_STRUCT(p);
90 nmb->header.name_trn_id = generate_trn_id();
91 nmb->header.opcode = 0;
92 nmb->header.response = False;
93 nmb->header.nm_flags.bcast = False;
94 nmb->header.nm_flags.recursion_available = False;
95 nmb->header.nm_flags.recursion_desired = False;
96 nmb->header.nm_flags.trunc = False;
97 nmb->header.nm_flags.authoritative = False;
98 nmb->header.rcode = 0;
99 nmb->header.qdcount = 1;
100 nmb->header.ancount = 0;
101 nmb->header.nscount = 0;
102 nmb->header.arcount = 0;
103 nmb->question.question_name = *name;
104 nmb->question.question_type = 0x21;
105 nmb->question.question_class = 0x1;
107 p.ip = to_ip;
108 p.port = NMB_PORT;
109 p.fd = fd;
110 p.timestamp = time(NULL);
111 p.packet_type = NMB_PACKET;
113 GetTimeOfDay(&tval);
115 if (!send_packet(&p))
116 return NULL;
118 retries--;
120 while (1) {
121 struct timeval tval2;
122 GetTimeOfDay(&tval2);
123 if (TvalDiff(&tval,&tval2) > retry_time) {
124 if (!retries)
125 break;
126 if (!found && !send_packet(&p))
127 return NULL;
128 GetTimeOfDay(&tval);
129 retries--;
132 if ((p2=receive_nmb_packet(fd,90,nmb->header.name_trn_id))) {
133 struct nmb_packet *nmb2 = &p2->packet.nmb;
134 debug_nmb_packet(p2);
136 if (nmb2->header.opcode != 0 ||
137 nmb2->header.nm_flags.bcast ||
138 nmb2->header.rcode ||
139 !nmb2->header.ancount ||
140 nmb2->answers->rr_type != 0x21) {
141 /* XXXX what do we do with this? could be a
142 redirect, but we'll discard it for the
143 moment */
144 free_packet(p2);
145 continue;
148 ret = parse_node_status(&nmb2->answers->rdata[0], num_names);
149 free_packet(p2);
150 return ret;
154 return NULL;
158 /****************************************************************************
159 find the first type XX name in a node status reply - used for finding
160 a servers name given its IP
161 return the matched name in *name
162 **************************************************************************/
164 BOOL name_status_find(const char *q_name, int q_type, int type, struct in_addr to_ip, char *name)
166 struct node_status *status;
167 struct nmb_name nname;
168 int count, i;
169 int sock;
171 sock = open_socket_in(SOCK_DGRAM, 0, 3, interpret_addr(lp_socket_address()), True);
172 if (sock == -1)
173 return False;
175 /* W2K PDC's seem not to respond to '*'#0. JRA */
176 make_nmb_name(&nname, q_name, q_type);
177 status = node_status_query(sock, &nname, to_ip, &count);
178 close(sock);
179 if (!status)
180 return False;
182 for (i=0;i<count;i++) {
183 if (status[i].type == type)
184 break;
186 if (i == count)
187 return False;
189 pull_ascii(name, status[i].name, 15, 0, STR_TERMINATE);
191 SAFE_FREE(status);
192 return True;
195 /****************************************************************************
196 Do a NetBIOS name registation to try to claim a name ...
197 ***************************************************************************/
198 BOOL name_register(int fd, const char *name, int name_type,
199 struct in_addr name_ip, int opcode,
200 BOOL bcast,
201 struct in_addr to_ip, int *count)
203 int retries = 3;
204 struct timeval tval;
205 struct packet_struct p;
206 struct packet_struct *p2;
207 struct nmb_packet *nmb = &p.packet.nmb;
208 struct in_addr register_ip;
210 DEBUG(4, ("name_register: %s as %s on %s\n", name, inet_ntoa(name_ip), inet_ntoa(to_ip)));
212 register_ip.s_addr = name_ip.s_addr; /* Fix this ... */
214 memset((char *)&p, '\0', sizeof(p));
216 *count = 0;
218 nmb->header.name_trn_id = generate_trn_id();
219 nmb->header.opcode = opcode;
220 nmb->header.response = False;
221 nmb->header.nm_flags.bcast = False;
222 nmb->header.nm_flags.recursion_available = False;
223 nmb->header.nm_flags.recursion_desired = True; /* ? */
224 nmb->header.nm_flags.trunc = False;
225 nmb->header.nm_flags.authoritative = True;
227 nmb->header.qdcount = 1;
228 nmb->header.ancount = 0;
229 nmb->header.nscount = 0;
230 nmb->header.arcount = 1;
232 make_nmb_name(&nmb->question.question_name, name, name_type);
234 nmb->question.question_type = 0x20;
235 nmb->question.question_class = 0x1;
237 /* Now, create the additional stuff for a registration request */
239 if ((nmb->additional = (struct res_rec *)malloc(sizeof(struct res_rec))) == NULL) {
241 DEBUG(0, ("name_register: malloc fail for additional record.\n"));
242 return False;
246 memset((char *)nmb->additional, '\0', sizeof(struct res_rec));
248 nmb->additional->rr_name = nmb->question.question_name;
249 nmb->additional->rr_type = RR_TYPE_NB;
250 nmb->additional->rr_class = RR_CLASS_IN;
252 /* See RFC 1002, sections 5.1.1.1, 5.1.1.2 and 5.1.1.3 */
253 if (nmb->header.nm_flags.bcast)
254 nmb->additional->ttl = PERMANENT_TTL;
255 else
256 nmb->additional->ttl = lp_max_ttl();
258 nmb->additional->rdlength = 6;
260 nmb->additional->rdata[0] = NB_MFLAG & 0xFF;
262 /* Set the address for the name we are registering. */
263 putip(&nmb->additional->rdata[2], &register_ip);
265 p.ip = to_ip;
266 p.port = NMB_PORT;
267 p.fd = fd;
268 p.timestamp = time(NULL);
269 p.packet_type = NMB_PACKET;
271 GetTimeOfDay(&tval);
273 if (!send_packet(&p))
274 return False;
276 retries--;
278 if ((p2 = receive_nmb_packet(fd, 10, nmb->header.name_trn_id))) {
279 debug_nmb_packet(p2);
280 SAFE_FREE(p2); /* No memory leaks ... */
283 return True;
286 /****************************************************************************
287 Do a netbios name query to find someones IP.
288 Returns an array of IP addresses or NULL if none.
289 *count will be set to the number of addresses returned.
290 ****************************************************************************/
291 struct in_addr *name_query(int fd,const char *name,int name_type,
292 BOOL bcast,BOOL recurse,
293 struct in_addr to_ip, int *count)
295 BOOL found=False;
296 int i, retries = 3;
297 int retry_time = bcast?250:2000;
298 struct timeval tval;
299 struct packet_struct p;
300 struct packet_struct *p2;
301 struct nmb_packet *nmb = &p.packet.nmb;
302 struct in_addr *ip_list = NULL;
304 memset((char *)&p,'\0',sizeof(p));
305 (*count) = 0;
307 nmb->header.name_trn_id = generate_trn_id();
308 nmb->header.opcode = 0;
309 nmb->header.response = False;
310 nmb->header.nm_flags.bcast = bcast;
311 nmb->header.nm_flags.recursion_available = False;
312 nmb->header.nm_flags.recursion_desired = recurse;
313 nmb->header.nm_flags.trunc = False;
314 nmb->header.nm_flags.authoritative = False;
315 nmb->header.rcode = 0;
316 nmb->header.qdcount = 1;
317 nmb->header.ancount = 0;
318 nmb->header.nscount = 0;
319 nmb->header.arcount = 0;
321 make_nmb_name(&nmb->question.question_name,name,name_type);
323 nmb->question.question_type = 0x20;
324 nmb->question.question_class = 0x1;
326 p.ip = to_ip;
327 p.port = NMB_PORT;
328 p.fd = fd;
329 p.timestamp = time(NULL);
330 p.packet_type = NMB_PACKET;
332 GetTimeOfDay(&tval);
334 if (!send_packet(&p))
335 return NULL;
337 retries--;
339 while (1) {
340 struct timeval tval2;
341 struct in_addr *tmp_ip_list;
343 GetTimeOfDay(&tval2);
344 if (TvalDiff(&tval,&tval2) > retry_time) {
345 if (!retries)
346 break;
347 if (!found && !send_packet(&p))
348 return NULL;
349 GetTimeOfDay(&tval);
350 retries--;
353 if ((p2=receive_nmb_packet(fd,90,nmb->header.name_trn_id))) {
354 struct nmb_packet *nmb2 = &p2->packet.nmb;
355 debug_nmb_packet(p2);
357 /* If we get a Negative Name Query Response from a WINS
358 * server, we should report it and give up.
360 if( 0 == nmb2->header.opcode /* A query response */
361 && !(bcast) /* from a WINS server */
362 && nmb2->header.rcode /* Error returned */
365 if( DEBUGLVL( 3 ) ) {
366 /* Only executed if DEBUGLEVEL >= 3 */
367 dbgtext( "Negative name query response, rcode 0x%02x: ", nmb2->header.rcode );
368 switch( nmb2->header.rcode ) {
369 case 0x01:
370 dbgtext( "Request was invalidly formatted.\n" );
371 break;
372 case 0x02:
373 dbgtext( "Problem with NBNS, cannot process name.\n");
374 break;
375 case 0x03:
376 dbgtext( "The name requested does not exist.\n" );
377 break;
378 case 0x04:
379 dbgtext( "Unsupported request error.\n" );
380 break;
381 case 0x05:
382 dbgtext( "Query refused error.\n" );
383 break;
384 default:
385 dbgtext( "Unrecognized error code.\n" );
386 break;
389 free_packet(p2);
390 return( NULL );
393 if (nmb2->header.opcode != 0 ||
394 nmb2->header.nm_flags.bcast ||
395 nmb2->header.rcode ||
396 !nmb2->header.ancount) {
398 * XXXX what do we do with this? Could be a
399 * redirect, but we'll discard it for the
400 * moment.
402 free_packet(p2);
403 continue;
406 tmp_ip_list = (struct in_addr *)Realloc( ip_list, sizeof( ip_list[0] )
407 * ( (*count) + nmb2->answers->rdlength/6 ) );
409 if (!tmp_ip_list) {
410 DEBUG(0,("name_query: Realloc failed.\n"));
411 SAFE_FREE(ip_list);
414 ip_list = tmp_ip_list;
416 if (ip_list) {
417 DEBUG(2,("Got a positive name query response from %s ( ", inet_ntoa(p2->ip)));
418 for (i=0;i<nmb2->answers->rdlength/6;i++) {
419 putip((char *)&ip_list[(*count)],&nmb2->answers->rdata[2+i*6]);
420 DEBUGADD(2,("%s ",inet_ntoa(ip_list[(*count)])));
421 (*count)++;
423 DEBUGADD(2,(")\n"));
426 found=True;
427 retries=0;
428 free_packet(p2);
430 * If we're doing a unicast lookup we only
431 * expect one reply. Don't wait the full 2
432 * seconds if we got one. JRA.
434 if(!bcast && found)
435 break;
439 /* Reach here if we've timed out waiting for replies.. */
440 if( !bcast && !found ) {
441 /* Timed out wating for WINS server to respond. Mark it dead. */
442 wins_srv_died( to_ip );
445 return ip_list;
448 /********************************************************
449 Start parsing the lmhosts file.
450 *********************************************************/
452 XFILE *startlmhosts(char *fname)
454 XFILE *fp = x_fopen(fname,O_RDONLY, 0);
455 if (!fp) {
456 DEBUG(4,("startlmhosts: Can't open lmhosts file %s. Error was %s\n",
457 fname, strerror(errno)));
458 return NULL;
460 return fp;
463 /********************************************************
464 Parse the next line in the lmhosts file.
465 *********************************************************/
467 BOOL getlmhostsent( XFILE *fp, pstring name, int *name_type, struct in_addr *ipaddr)
469 pstring line;
471 while(!x_feof(fp) && !x_ferror(fp)) {
472 pstring ip,flags,extra;
473 char *ptr;
474 int count = 0;
476 *name_type = -1;
478 if (!fgets_slash(line,sizeof(pstring),fp))
479 continue;
481 if (*line == '#')
482 continue;
484 pstrcpy(ip,"");
485 pstrcpy(name,"");
486 pstrcpy(flags,"");
488 ptr = line;
490 if (next_token(&ptr,ip ,NULL,sizeof(ip)))
491 ++count;
492 if (next_token(&ptr,name ,NULL, sizeof(pstring)))
493 ++count;
494 if (next_token(&ptr,flags,NULL, sizeof(flags)))
495 ++count;
496 if (next_token(&ptr,extra,NULL, sizeof(extra)))
497 ++count;
499 if (count <= 0)
500 continue;
502 if (count > 0 && count < 2)
504 DEBUG(0,("getlmhostsent: Ill formed hosts line [%s]\n",line));
505 continue;
508 if (count >= 4)
510 DEBUG(0,("getlmhostsent: too many columns in lmhosts file (obsolete syntax)\n"));
511 continue;
514 DEBUG(4, ("getlmhostsent: lmhost entry: %s %s %s\n", ip, name, flags));
516 if (strchr_m(flags,'G') || strchr_m(flags,'S'))
518 DEBUG(0,("getlmhostsent: group flag in lmhosts ignored (obsolete)\n"));
519 continue;
522 *ipaddr = *interpret_addr2(ip);
524 /* Extra feature. If the name ends in '#XX', where XX is a hex number,
525 then only add that name type. */
526 if((ptr = strchr_m(name, '#')) != NULL)
528 char *endptr;
530 ptr++;
531 *name_type = (int)strtol(ptr, &endptr, 16);
533 if(!*ptr || (endptr == ptr))
535 DEBUG(0,("getlmhostsent: invalid name %s containing '#'.\n", name));
536 continue;
539 *(--ptr) = '\0'; /* Truncate at the '#' */
542 return True;
545 return False;
548 /********************************************************
549 Finish parsing the lmhosts file.
550 *********************************************************/
552 void endlmhosts(XFILE *fp)
554 x_fclose(fp);
557 BOOL name_register_wins(const char *name, int name_type)
559 int sock, i, return_count;
560 int num_interfaces = iface_count();
561 struct in_addr sendto_ip;
564 * Check if we have any interfaces, prevents a segfault later
567 if (num_interfaces <= 0)
568 return False; /* Should return some indication of the problem */
571 * Do a broadcast register ...
574 if (0 == wins_srv_count())
575 return False;
577 if( DEBUGLVL( 4 ) )
579 dbgtext( "name_register_wins: Registering my name %s ", name );
580 dbgtext( "with WINS server %s.\n", wins_srv_name() );
583 sock = open_socket_in( SOCK_DGRAM, 0, 3,
584 interpret_addr("0.0.0.0"), True );
586 if (sock == -1) return False;
588 set_socket_options(sock, "SO_BROADCAST"); /* ????! crh */
590 sendto_ip = wins_srv_ip();
592 if (num_interfaces > 1) {
594 for (i = 0; i < num_interfaces; i++) {
596 if (!name_register(sock, name, name_type, *iface_n_ip(i),
597 NMB_NAME_MULTIHOMED_REG_OPCODE,
598 True, sendto_ip, &return_count)) {
600 close(sock);
601 return False;
608 else {
610 if (!name_register(sock, name, name_type, *iface_n_ip(0),
611 NMB_NAME_REG_OPCODE,
612 True, sendto_ip, &return_count)) {
614 close(sock);
615 return False;
621 close(sock);
623 return True;
627 /********************************************************
628 Resolve via "bcast" method.
629 *********************************************************/
631 BOOL name_resolve_bcast(const char *name, int name_type,
632 struct in_addr **return_ip_list, int *return_count)
634 int sock, i;
635 int num_interfaces = iface_count();
637 *return_ip_list = NULL;
638 *return_count = 0;
641 * "bcast" means do a broadcast lookup on all the local interfaces.
644 DEBUG(3,("name_resolve_bcast: Attempting broadcast lookup for name %s<0x%x>\n", name, name_type));
646 sock = open_socket_in( SOCK_DGRAM, 0, 3,
647 interpret_addr(lp_socket_address()), True );
649 if (sock == -1) return False;
651 set_socket_options(sock,"SO_BROADCAST");
653 * Lookup the name on all the interfaces, return on
654 * the first successful match.
656 for( i = num_interfaces-1; i >= 0; i--) {
657 struct in_addr sendto_ip;
658 /* Done this way to fix compiler error on IRIX 5.x */
659 sendto_ip = *iface_bcast(*iface_n_ip(i));
660 *return_ip_list = name_query(sock, name, name_type, True,
661 True, sendto_ip, return_count);
662 if(*return_ip_list != NULL) {
663 close(sock);
664 return True;
668 close(sock);
669 return False;
672 /********************************************************
673 Resolve via "wins" method.
674 *********************************************************/
676 static BOOL resolve_wins(const char *name, int name_type,
677 struct in_addr **return_iplist, int *return_count)
679 int sock;
680 struct in_addr wins_ip;
681 BOOL wins_ismyip;
683 *return_iplist = NULL;
684 *return_count = 0;
687 * "wins" means do a unicast lookup to the WINS server.
688 * Ignore if there is no WINS server specified or if the
689 * WINS server is one of our interfaces (if we're being
690 * called from within nmbd - we can't do this call as we
691 * would then block).
694 DEBUG(3,("resolve_wins: Attempting wins lookup for name %s<0x%x>\n", name, name_type));
696 if (lp_wins_support()) {
698 * We're providing WINS support. Call ourselves so
699 * long as we're not nmbd.
701 extern struct in_addr loopback_ip;
702 wins_ip = loopback_ip;
703 wins_ismyip = True;
704 } else if( wins_srv_count() < 1 ) {
705 DEBUG(3,("resolve_wins: WINS server resolution selected and no WINS servers listed.\n"));
706 return False;
707 } else {
708 wins_ip = wins_srv_ip();
709 wins_ismyip = ismyip(wins_ip);
712 DEBUG(3, ("resolve_wins: WINS server == <%s>\n", inet_ntoa(wins_ip)) );
713 if((wins_ismyip && !global_in_nmbd) || !wins_ismyip) {
714 sock = open_socket_in( SOCK_DGRAM, 0, 3,
715 interpret_addr(lp_socket_address()),
716 True );
717 if (sock != -1) {
718 *return_iplist = name_query( sock, name,
719 name_type, False,
720 True, wins_ip,
721 return_count);
722 if(*return_iplist != NULL) {
723 close(sock);
724 return True;
726 close(sock);
730 return False;
733 /********************************************************
734 Resolve via "lmhosts" method.
735 *********************************************************/
737 static BOOL resolve_lmhosts(const char *name, int name_type,
738 struct in_addr **return_iplist, int *return_count)
741 * "lmhosts" means parse the local lmhosts file.
744 XFILE *fp;
745 pstring lmhost_name;
746 int name_type2;
747 struct in_addr return_ip;
749 *return_iplist = NULL;
750 *return_count = 0;
752 DEBUG(3,("resolve_lmhosts: Attempting lmhosts lookup for name %s<0x%x>\n", name, name_type));
754 fp = startlmhosts(dyn_LMHOSTSFILE);
755 if(fp) {
756 while (getlmhostsent(fp, lmhost_name, &name_type2, &return_ip)) {
757 if (strequal(name, lmhost_name) &&
758 ((name_type2 == -1) || (name_type == name_type2))
760 endlmhosts(fp);
761 *return_iplist = (struct in_addr *)malloc(sizeof(struct in_addr));
762 if(*return_iplist == NULL) {
763 DEBUG(3,("resolve_lmhosts: malloc fail !\n"));
764 return False;
766 **return_iplist = return_ip;
767 *return_count = 1;
768 return True;
771 endlmhosts(fp);
773 return False;
777 /********************************************************
778 Resolve via "hosts" method.
779 *********************************************************/
781 static BOOL resolve_hosts(const char *name,
782 struct in_addr **return_iplist, int *return_count)
785 * "host" means do a localhost, or dns lookup.
787 struct hostent *hp;
789 *return_iplist = NULL;
790 *return_count = 0;
792 DEBUG(3,("resolve_hosts: Attempting host lookup for name %s<0x20>\n", name));
794 if (((hp = sys_gethostbyname(name)) != NULL) && (hp->h_addr != NULL)) {
795 struct in_addr return_ip;
796 putip((char *)&return_ip,(char *)hp->h_addr);
797 *return_iplist = (struct in_addr *)malloc(sizeof(struct in_addr));
798 if(*return_iplist == NULL) {
799 DEBUG(3,("resolve_hosts: malloc fail !\n"));
800 return False;
802 **return_iplist = return_ip;
803 *return_count = 1;
804 return True;
806 return False;
809 /********************************************************
810 Internal interface to resolve a name into an IP address.
811 Use this function if the string is either an IP address, DNS
812 or host name or NetBIOS name. This uses the name switch in the
813 smb.conf to determine the order of name resolution.
814 *********************************************************/
816 static BOOL internal_resolve_name(const char *name, int name_type,
817 struct in_addr **return_iplist, int *return_count)
819 pstring name_resolve_list;
820 fstring tok;
821 char *ptr;
822 BOOL allones = (strcmp(name,"255.255.255.255") == 0);
823 BOOL allzeros = (strcmp(name,"0.0.0.0") == 0);
824 BOOL is_address = is_ipaddress(name);
825 *return_iplist = NULL;
826 *return_count = 0;
828 if (allzeros || allones || is_address) {
829 *return_iplist = (struct in_addr *)malloc(sizeof(struct in_addr));
830 if(*return_iplist == NULL) {
831 DEBUG(3,("internal_resolve_name: malloc fail !\n"));
832 return False;
834 if(is_address) {
835 /* if it's in the form of an IP address then get the lib to interpret it */
836 (*return_iplist)->s_addr = inet_addr(name);
837 } else {
838 (*return_iplist)->s_addr = allones ? 0xFFFFFFFF : 0;
839 *return_count = 1;
841 return True;
844 pstrcpy(name_resolve_list, lp_name_resolve_order());
845 ptr = name_resolve_list;
846 if (!ptr || !*ptr)
847 ptr = "host";
849 while (next_token(&ptr, tok, LIST_SEP, sizeof(tok))) {
850 if((strequal(tok, "host") || strequal(tok, "hosts"))) {
851 if (name_type == 0x20 && resolve_hosts(name, return_iplist, return_count)) {
852 return True;
854 } else if(strequal( tok, "lmhosts")) {
855 if (resolve_lmhosts(name, name_type, return_iplist, return_count)) {
856 return True;
858 } else if(strequal( tok, "wins")) {
859 /* don't resolve 1D via WINS */
860 if (name_type != 0x1D &&
861 resolve_wins(name, name_type, return_iplist, return_count)) {
862 return True;
864 } else if(strequal( tok, "bcast")) {
865 if (name_resolve_bcast(name, name_type, return_iplist, return_count)) {
866 return True;
868 } else {
869 DEBUG(0,("resolve_name: unknown name switch type %s\n", tok));
873 SAFE_FREE(*return_iplist);
874 return False;
877 /********************************************************
878 Internal interface to resolve a name into one IP address.
879 Use this function if the string is either an IP address, DNS
880 or host name or NetBIOS name. This uses the name switch in the
881 smb.conf to determine the order of name resolution.
882 *********************************************************/
884 BOOL resolve_name(const char *name, struct in_addr *return_ip, int name_type)
886 struct in_addr *ip_list = NULL;
887 int count = 0;
889 if(internal_resolve_name(name, name_type, &ip_list, &count)) {
890 *return_ip = ip_list[0];
891 SAFE_FREE(ip_list);
892 return True;
894 SAFE_FREE(ip_list);
895 return False;
899 /********************************************************
900 resolve a name of format \\server_name or \\ipaddress
901 into a name. also, cut the \\ from the front for us.
902 *********************************************************/
904 BOOL resolve_srv_name(const char* srv_name, fstring dest_host,
905 struct in_addr *ip)
907 BOOL ret;
908 const char *sv_name = srv_name;
910 DEBUG(10,("resolve_srv_name: %s\n", srv_name));
912 if (srv_name == NULL || strequal("\\\\.", srv_name))
914 extern pstring global_myname;
915 fstrcpy(dest_host, global_myname);
916 ip = interpret_addr2("127.0.0.1");
917 return True;
920 if (strnequal("\\\\", srv_name, 2))
922 sv_name = &srv_name[2];
925 fstrcpy(dest_host, sv_name);
926 /* treat the '*' name specially - it is a magic name for the PDC */
927 if (strcmp(dest_host,"*") == 0) {
928 extern pstring global_myname;
929 ret = resolve_name(lp_workgroup(), ip, 0x1B);
930 lookup_dc_name(global_myname, lp_workgroup(), ip, dest_host);
931 } else {
932 ret = resolve_name(dest_host, ip, 0x20);
935 if (is_ipaddress(dest_host))
937 fstrcpy(dest_host, "*SMBSERVER");
940 return ret;
944 /********************************************************
945 Find the IP address of the master browser or DMB for a workgroup.
946 *********************************************************/
948 BOOL find_master_ip(char *group, struct in_addr *master_ip)
950 struct in_addr *ip_list = NULL;
951 int count = 0;
953 if (internal_resolve_name(group, 0x1D, &ip_list, &count)) {
954 *master_ip = ip_list[0];
955 SAFE_FREE(ip_list);
956 return True;
958 if(internal_resolve_name(group, 0x1B, &ip_list, &count)) {
959 *master_ip = ip_list[0];
960 SAFE_FREE(ip_list);
961 return True;
964 SAFE_FREE(ip_list);
965 return False;
968 /********************************************************
969 Lookup a DC name given a Domain name and IP address.
970 *********************************************************/
972 BOOL lookup_dc_name(const char *srcname, const char *domain,
973 struct in_addr *dc_ip, char *ret_name)
975 #if !defined(I_HATE_WINDOWS_REPLY_CODE)
977 fstring dc_name;
978 BOOL ret;
981 * Due to the fact win WinNT *sucks* we must do a node status
982 * query here... JRA.
985 *dc_name = '\0';
987 ret = name_status_find(domain, 0x1c, 0x20, *dc_ip, dc_name);
989 if(ret && *dc_name) {
990 fstrcpy(ret_name, dc_name);
991 return True;
994 return False;
996 #else /* defined(I_HATE_WINDOWS_REPLY_CODE) */
998 JRA - This code is broken with BDC rollover - we need to do a full
999 NT GETDC call, UNICODE, NT domain SID and uncle tom cobbley and all...
1001 int retries = 3;
1002 int retry_time = 2000;
1003 struct timeval tval;
1004 struct packet_struct p;
1005 struct dgram_packet *dgram = &p.packet.dgram;
1006 char *ptr,*p2;
1007 char tmp[4];
1008 int len;
1009 struct sockaddr_in sock_name;
1010 int sock_len = sizeof(sock_name);
1011 const char *mailslot = NET_LOGON_MAILSLOT;
1012 char *mailslot_name;
1013 char buffer[1024];
1014 char *bufp;
1015 int dgm_id = generate_trn_id();
1016 int sock = open_socket_in(SOCK_DGRAM, 0, 3, interpret_addr(lp_socket_address()), True );
1018 if(sock == -1)
1019 return False;
1021 /* Find out the transient UDP port we have been allocated. */
1022 if(getsockname(sock, (struct sockaddr *)&sock_name, &sock_len)<0) {
1023 DEBUG(0,("lookup_pdc_name: Failed to get local UDP port. Error was %s\n",
1024 strerror(errno)));
1025 close(sock);
1026 return False;
1030 * Create the request data.
1033 memset(buffer,'\0',sizeof(buffer));
1034 bufp = buffer;
1035 SSVAL(bufp,0,QUERYFORPDC);
1036 bufp += 2;
1037 fstrcpy(bufp,srcname);
1038 bufp += (strlen(bufp) + 1);
1039 slprintf(bufp, sizeof(fstring)-1, "\\MAILSLOT\\NET\\GETDC%d", dgm_id);
1040 mailslot_name = bufp;
1041 bufp += (strlen(bufp) + 1);
1042 bufp = ALIGN2(bufp, buffer);
1043 bufp += push_ucs2(NULL, bufp, srcname, sizeof(buffer) - (bufp - buffer), STR_TERMINATE);
1045 SIVAL(bufp,0,1);
1046 SSVAL(bufp,4,0xFFFF);
1047 SSVAL(bufp,6,0xFFFF);
1048 bufp += 8;
1049 len = PTR_DIFF(bufp,buffer);
1051 memset((char *)&p,'\0',sizeof(p));
1053 /* DIRECT GROUP or UNIQUE datagram. */
1054 dgram->header.msg_type = 0x10;
1055 dgram->header.flags.node_type = M_NODE;
1056 dgram->header.flags.first = True;
1057 dgram->header.flags.more = False;
1058 dgram->header.dgm_id = dgm_id;
1059 dgram->header.source_ip = *iface_ip(*pdc_ip);
1060 dgram->header.source_port = ntohs(sock_name.sin_port);
1061 dgram->header.dgm_length = 0; /* Let build_dgram() handle this. */
1062 dgram->header.packet_offset = 0;
1064 make_nmb_name(&dgram->source_name,srcname,0);
1065 make_nmb_name(&dgram->dest_name,domain,0x1C);
1067 ptr = &dgram->data[0];
1069 /* Setup the smb part. */
1070 ptr -= 4; /* XXX Ugliness because of handling of tcp SMB length. */
1071 memcpy(tmp,ptr,4);
1072 set_message(ptr,17,17 + len,True);
1073 memcpy(ptr,tmp,4);
1075 CVAL(ptr,smb_com) = SMBtrans;
1076 SSVAL(ptr,smb_vwv1,len);
1077 SSVAL(ptr,smb_vwv11,len);
1078 SSVAL(ptr,smb_vwv12,70 + strlen(mailslot));
1079 SSVAL(ptr,smb_vwv13,3);
1080 SSVAL(ptr,smb_vwv14,1);
1081 SSVAL(ptr,smb_vwv15,1);
1082 SSVAL(ptr,smb_vwv16,2);
1083 p2 = smb_buf(ptr);
1084 pstrcpy(p2,mailslot);
1085 p2 = skip_string(p2,1);
1087 memcpy(p2,buffer,len);
1088 p2 += len;
1090 dgram->datasize = PTR_DIFF(p2,ptr+4); /* +4 for tcp length. */
1092 p.ip = *pdc_ip;
1093 p.port = DGRAM_PORT;
1094 p.fd = sock;
1095 p.timestamp = time(NULL);
1096 p.packet_type = DGRAM_PACKET;
1098 GetTimeOfDay(&tval);
1100 if (!send_packet(&p)) {
1101 DEBUG(0,("lookup_pdc_name: send_packet failed.\n"));
1102 close(sock);
1103 return False;
1106 retries--;
1108 while (1) {
1109 struct timeval tval2;
1110 struct packet_struct *p_ret;
1112 GetTimeOfDay(&tval2);
1113 if (TvalDiff(&tval,&tval2) > retry_time) {
1114 if (!retries)
1115 break;
1116 if (!send_packet(&p)) {
1117 DEBUG(0,("lookup_pdc_name: send_packet failed.\n"));
1118 close(sock);
1119 return False;
1121 GetTimeOfDay(&tval);
1122 retries--;
1125 if ((p_ret = receive_dgram_packet(sock,90,mailslot_name))) {
1126 struct dgram_packet *dgram2 = &p_ret->packet.dgram;
1127 char *buf;
1128 char *buf2;
1130 buf = &dgram2->data[0];
1131 buf -= 4;
1133 if (CVAL(buf,smb_com) != SMBtrans) {
1134 DEBUG(0,("lookup_pdc_name: datagram type %u != SMBtrans(%u)\n", (unsigned int)
1135 CVAL(buf,smb_com), (unsigned int)SMBtrans ));
1136 free_packet(p_ret);
1137 continue;
1140 len = SVAL(buf,smb_vwv11);
1141 buf2 = smb_base(buf) + SVAL(buf,smb_vwv12);
1143 if (len <= 0) {
1144 DEBUG(0,("lookup_pdc_name: datagram len < 0 (%d)\n", len ));
1145 free_packet(p_ret);
1146 continue;
1149 DEBUG(4,("lookup_pdc_name: datagram reply from %s to %s IP %s for %s of type %d len=%d\n",
1150 nmb_namestr(&dgram2->source_name),nmb_namestr(&dgram2->dest_name),
1151 inet_ntoa(p_ret->ip), smb_buf(buf),SVAL(buf2,0),len));
1153 if(SVAL(buf2,0) != QUERYFORPDC_R) {
1154 DEBUG(0,("lookup_pdc_name: datagram type (%u) != QUERYFORPDC_R(%u)\n",
1155 (unsigned int)SVAL(buf,0), (unsigned int)QUERYFORPDC_R ));
1156 free_packet(p_ret);
1157 continue;
1160 buf2 += 2;
1161 /* Note this is safe as it is a bounded strcpy. */
1162 fstrcpy(ret_name, buf2);
1163 ret_name[sizeof(fstring)-1] = '\0';
1164 close(sock);
1165 free_packet(p_ret);
1166 return True;
1170 close(sock);
1171 return False;
1172 #endif /* defined(I_HATE_WINDOWS_REPLY_CODE) */
1176 /********************************************************
1177 Get the IP address list of the PDC/BDC's of a Domain.
1178 *********************************************************/
1180 BOOL get_dc_list(BOOL pdc_only, char *group, struct in_addr **ip_list, int *count)
1182 int name_type = pdc_only ? 0x1B : 0x1C;
1185 * If it's our domain then
1186 * use the 'password server' parameter.
1189 if (strequal(group, lp_workgroup())) {
1190 char *p;
1191 char *pserver = lp_passwordserver();
1192 fstring name;
1193 int num_adresses = 0;
1194 struct in_addr *return_iplist = NULL;
1196 if (! *pserver)
1197 return internal_resolve_name(group, name_type, ip_list, count);
1199 p = pserver;
1200 while (next_token(&p,name,LIST_SEP,sizeof(name))) {
1201 if (strequal(name, "*"))
1202 return internal_resolve_name(group, name_type, ip_list, count);
1203 num_adresses++;
1205 if (num_adresses == 0)
1206 return internal_resolve_name(group, name_type, ip_list, count);
1208 return_iplist = (struct in_addr *)malloc(num_adresses * sizeof(struct in_addr));
1209 if(return_iplist == NULL) {
1210 DEBUG(3,("get_dc_list: malloc fail !\n"));
1211 return False;
1213 p = pserver;
1214 *count = 0;
1215 while (next_token(&p,name,LIST_SEP,sizeof(name))) {
1216 struct in_addr name_ip;
1217 if (resolve_name( name, &name_ip, 0x20) == False)
1218 continue;
1219 return_iplist[(*count)++] = name_ip;
1221 *ip_list = return_iplist;
1222 return (*count != 0);
1223 } else
1224 return internal_resolve_name(group, name_type, ip_list, count);
1227 /********************************************************
1228 Get the IP address list of the Local Master Browsers
1229 ********************************************************/
1230 BOOL get_lmb_list(struct in_addr **ip_list, int *count)
1232 return internal_resolve_name( MSBROWSE, 0x1, ip_list, count);