sync with SAMBA_2_2
[Samba/gbeck.git] / source / libsmb / namequery.c
blob7714de760b276505e72eca306249dda2a553fb9e
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 extern int DEBUGLEVEL;
27 /* nmbd.c sets this to True. */
28 BOOL global_in_nmbd = False;
30 /****************************************************************************
31 generate a random trn_id
32 ****************************************************************************/
33 static int generate_trn_id(void)
35 static int trn_id;
37 if (trn_id == 0) {
38 sys_srandom(sys_getpid());
41 trn_id = sys_random();
43 return trn_id % (unsigned)0x7FFF;
47 /****************************************************************************
48 parse a node status response into an array of structures
49 ****************************************************************************/
50 static struct node_status *parse_node_status(char *p, int *num_names)
52 struct node_status *ret;
53 int i;
55 *num_names = CVAL(p,0);
57 if (*num_names == 0) return NULL;
59 ret = (struct node_status *)malloc(sizeof(struct node_status)* (*num_names));
60 if (!ret) return NULL;
62 p++;
63 for (i=0;i< *num_names;i++) {
64 StrnCpy(ret[i].name,p,15);
65 trim_string(ret[i].name,NULL," ");
66 ret[i].type = CVAL(p,15);
67 ret[i].flags = p[16];
68 p += 18;
70 return ret;
74 /****************************************************************************
75 do a NBT node status query on an open socket and return an array of
76 structures holding the returned names or NULL if the query failed
77 **************************************************************************/
78 struct node_status *name_status_query(int fd,struct nmb_name *name,
79 struct in_addr to_ip, int *num_names)
81 BOOL found=False;
82 int retries = 2;
83 int retry_time = 2000;
84 struct timeval tval;
85 struct packet_struct p;
86 struct packet_struct *p2;
87 struct nmb_packet *nmb = &p.packet.nmb;
88 struct node_status *ret;
90 ZERO_STRUCT(p);
92 nmb->header.name_trn_id = generate_trn_id();
93 nmb->header.opcode = 0;
94 nmb->header.response = False;
95 nmb->header.nm_flags.bcast = False;
96 nmb->header.nm_flags.recursion_available = False;
97 nmb->header.nm_flags.recursion_desired = False;
98 nmb->header.nm_flags.trunc = False;
99 nmb->header.nm_flags.authoritative = False;
100 nmb->header.rcode = 0;
101 nmb->header.qdcount = 1;
102 nmb->header.ancount = 0;
103 nmb->header.nscount = 0;
104 nmb->header.arcount = 0;
105 nmb->question.question_name = *name;
106 nmb->question.question_type = 0x21;
107 nmb->question.question_class = 0x1;
109 p.ip = to_ip;
110 p.port = NMB_PORT;
111 p.fd = fd;
112 p.timestamp = time(NULL);
113 p.packet_type = NMB_PACKET;
115 GetTimeOfDay(&tval);
117 if (!send_packet(&p))
118 return NULL;
120 retries--;
122 while (1) {
123 struct timeval tval2;
124 GetTimeOfDay(&tval2);
125 if (TvalDiff(&tval,&tval2) > retry_time) {
126 if (!retries)
127 break;
128 if (!found && !send_packet(&p))
129 return NULL;
130 GetTimeOfDay(&tval);
131 retries--;
134 if ((p2=receive_nmb_packet(fd,90,nmb->header.name_trn_id))) {
135 struct nmb_packet *nmb2 = &p2->packet.nmb;
136 debug_nmb_packet(p2);
138 if (nmb2->header.opcode != 0 ||
139 nmb2->header.nm_flags.bcast ||
140 nmb2->header.rcode ||
141 !nmb2->header.ancount ||
142 nmb2->answers->rr_type != 0x21) {
143 /* XXXX what do we do with this? could be a
144 redirect, but we'll discard it for the
145 moment */
146 free_packet(p2);
147 continue;
150 ret = parse_node_status(&nmb2->answers->rdata[0], num_names);
151 free_packet(p2);
152 return ret;
156 return NULL;
160 /****************************************************************************
161 find the first type XX name in a node status reply - used for finding
162 a servers name given its IP
163 return the matched name in *name
164 **************************************************************************/
165 BOOL name_status_find(int type, struct in_addr to_ip, char *name)
167 struct node_status *status;
168 struct nmb_name nname;
169 int count, i;
170 int sock;
172 sock = open_socket_in(SOCK_DGRAM, 0, 3, interpret_addr(lp_socket_address()), True);
173 if (sock == -1) return False;
175 make_nmb_name(&nname, "*", 0);
176 status = name_status_query(sock, &nname, to_ip, &count);
177 close(sock);
178 if (!status) return False;
180 for (i=0;i<count;i++) {
181 if (status[i].type == type) break;
183 if (i == count) return False;
185 StrnCpy(name, status[i].name, 15);
187 dos_to_unix(name, True);
189 free(status);
190 return True;
193 /****************************************************************************
194 Do a NetBIOS name registation to try to claim a name ...
195 ***************************************************************************/
196 BOOL name_register(int fd, const char *name, int name_type,
197 struct in_addr name_ip, int opcode,
198 BOOL bcast,
199 struct in_addr to_ip, int *count)
201 int retries = 3;
202 struct timeval tval;
203 struct packet_struct p;
204 struct packet_struct *p2;
205 struct nmb_packet *nmb = &p.packet.nmb;
206 struct in_addr register_ip;
208 DEBUG(4, ("name_register: %s as %s on %s\n", name, inet_ntoa(name_ip), inet_ntoa(to_ip)));
210 register_ip.s_addr = name_ip.s_addr; /* Fix this ... */
212 bzero((char *)&p, sizeof(p));
214 *count = 0;
216 nmb->header.name_trn_id = generate_trn_id();
217 nmb->header.opcode = opcode;
218 nmb->header.response = False;
219 nmb->header.nm_flags.bcast = False;
220 nmb->header.nm_flags.recursion_available = False;
221 nmb->header.nm_flags.recursion_desired = True; /* ? */
222 nmb->header.nm_flags.trunc = False;
223 nmb->header.nm_flags.authoritative = True;
225 nmb->header.qdcount = 1;
226 nmb->header.ancount = 0;
227 nmb->header.nscount = 0;
228 nmb->header.arcount = 1;
230 make_nmb_name(&nmb->question.question_name, name, name_type);
232 nmb->question.question_type = 0x20;
233 nmb->question.question_class = 0x1;
235 /* Now, create the additional stuff for a registration request */
237 if ((nmb->additional = (struct res_rec *)malloc(sizeof(struct res_rec))) == NULL) {
239 DEBUG(0, ("name_register: malloc fail for additional record.\n"));
240 return False;
244 bzero((char *)nmb->additional, sizeof(struct res_rec));
246 nmb->additional->rr_name = nmb->question.question_name;
247 nmb->additional->rr_type = RR_TYPE_NB;
248 nmb->additional->rr_class = RR_CLASS_IN;
250 /* See RFC 1002, sections 5.1.1.1, 5.1.1.2 and 5.1.1.3 */
251 if (nmb->header.nm_flags.bcast)
252 nmb->additional->ttl = PERMANENT_TTL;
253 else
254 nmb->additional->ttl = lp_max_ttl();
256 nmb->additional->rdlength = 6;
258 nmb->additional->rdata[0] = NB_MFLAG & 0xFF;
260 /* Set the address for the name we are registering. */
261 putip(&nmb->additional->rdata[2], &register_ip);
263 p.ip = to_ip;
264 p.port = NMB_PORT;
265 p.fd = fd;
266 p.timestamp = time(NULL);
267 p.packet_type = NMB_PACKET;
269 GetTimeOfDay(&tval);
271 if (!send_packet(&p))
272 return False;
274 retries--;
276 if ((p2 = receive_nmb_packet(fd, 10, nmb->header.name_trn_id))) {
277 debug_nmb_packet(p2);
278 free(p2); /* No memory leaks ... */
281 return True;
284 /****************************************************************************
285 Do a netbios name query to find someones IP.
286 Returns an array of IP addresses or NULL if none.
287 *count will be set to the number of addresses returned.
288 ****************************************************************************/
289 struct in_addr *name_query(int fd,const char *name,int name_type,
290 BOOL bcast,BOOL recurse,
291 struct in_addr to_ip, int *count)
293 BOOL found=False;
294 int i, retries = 3;
295 int retry_time = bcast?250:2000;
296 struct timeval tval;
297 struct packet_struct p;
298 struct packet_struct *p2;
299 struct nmb_packet *nmb = &p.packet.nmb;
300 struct in_addr *ip_list = NULL;
302 memset((char *)&p,'\0',sizeof(p));
303 (*count) = 0;
305 nmb->header.name_trn_id = generate_trn_id();
306 nmb->header.opcode = 0;
307 nmb->header.response = False;
308 nmb->header.nm_flags.bcast = bcast;
309 nmb->header.nm_flags.recursion_available = False;
310 nmb->header.nm_flags.recursion_desired = recurse;
311 nmb->header.nm_flags.trunc = False;
312 nmb->header.nm_flags.authoritative = False;
313 nmb->header.rcode = 0;
314 nmb->header.qdcount = 1;
315 nmb->header.ancount = 0;
316 nmb->header.nscount = 0;
317 nmb->header.arcount = 0;
319 make_nmb_name(&nmb->question.question_name,name,name_type);
321 nmb->question.question_type = 0x20;
322 nmb->question.question_class = 0x1;
324 p.ip = to_ip;
325 p.port = NMB_PORT;
326 p.fd = fd;
327 p.timestamp = time(NULL);
328 p.packet_type = NMB_PACKET;
330 GetTimeOfDay(&tval);
332 if (!send_packet(&p))
333 return NULL;
335 retries--;
337 while (1)
339 struct timeval tval2;
340 GetTimeOfDay(&tval2);
341 if (TvalDiff(&tval,&tval2) > retry_time) {
342 if (!retries)
343 break;
344 if (!found && !send_packet(&p))
345 return NULL;
346 GetTimeOfDay(&tval);
347 retries--;
350 if ((p2=receive_nmb_packet(fd,90,nmb->header.name_trn_id))) {
351 struct nmb_packet *nmb2 = &p2->packet.nmb;
352 debug_nmb_packet(p2);
354 /* If we get a Negative Name Query Response from a WINS
355 * server, we should report it and give up.
357 if( 0 == nmb2->header.opcode /* A query response */
358 && !(bcast) /* from a WINS server */
359 && nmb2->header.rcode /* Error returned */
362 if( DEBUGLVL( 3 ) ) {
363 /* Only executed if DEBUGLEVEL >= 3 */
364 dbgtext( "Negative name query response, rcode 0x%02x: ",
365 nmb2->header.rcode );
366 switch( nmb2->header.rcode ) {
367 case 0x01:
368 dbgtext( "Request was invalidly formatted.\n" );
369 break;
370 case 0x02:
371 dbgtext( "Problem with NBNS, cannot process name.\n");
372 break;
373 case 0x03:
374 dbgtext( "The name requested does not exist.\n" );
375 break;
376 case 0x04:
377 dbgtext( "Unsupported request error.\n" );
378 break;
379 case 0x05:
380 dbgtext( "Query refused error.\n" );
381 break;
382 default:
383 dbgtext( "Unrecognized error code.\n" );
384 break;
387 free_packet(p2);
388 return( NULL );
391 if (nmb2->header.opcode != 0 ||
392 nmb2->header.nm_flags.bcast ||
393 nmb2->header.rcode ||
394 !nmb2->header.ancount) {
396 * XXXX what do we do with this? Could be a
397 * redirect, but we'll discard it for the
398 * moment. */
399 free_packet(p2);
400 continue;
403 ip_list = (struct in_addr *)Realloc( ip_list,
404 sizeof( ip_list[0] )
405 * ( (*count) + nmb2->answers->rdlength/6 ) );
406 if (ip_list) {
407 DEBUG(2,("Got a positive name query response from %s ( ",
408 inet_ntoa(p2->ip)));
409 for (i=0;i<nmb2->answers->rdlength/6;i++) {
410 putip((char *)&ip_list[(*count)],&nmb2->answers->rdata[2+i*6]);
411 DEBUGADD(2,("%s ",inet_ntoa(ip_list[(*count)])));
412 (*count)++;
414 DEBUGADD(2,(")\n"));
417 found=True;
418 retries=0;
419 free_packet(p2);
421 * If we're doing a unicast lookup we only
422 * expect one reply. Don't wait the full 2
423 * seconds if we got one. JRA.
425 if(!bcast && found)
426 break;
430 /* Reach here if we've timed out waiting for replies.. */
431 if( !bcast && !found )
433 /* Timed out wating for WINS server to respond. Mark it dead. */
434 wins_srv_died( to_ip );
437 return ip_list;
440 /********************************************************
441 Start parsing the lmhosts file.
442 *********************************************************/
444 FILE *startlmhosts(char *fname)
446 FILE *fp = sys_fopen(fname,"r");
447 if (!fp) {
448 DEBUG(4,("startlmhosts: Can't open lmhosts file %s. Error was %s\n",
449 fname, strerror(errno)));
450 return NULL;
452 return fp;
455 /********************************************************
456 Parse the next line in the lmhosts file.
457 *********************************************************/
459 BOOL getlmhostsent( FILE *fp, pstring name, int *name_type, struct in_addr *ipaddr)
461 pstring line;
463 while(!feof(fp) && !ferror(fp)) {
464 pstring ip,flags,extra;
465 char *ptr;
466 int count = 0;
468 *name_type = -1;
470 if (!fgets_slash(line,sizeof(pstring),fp))
471 continue;
473 if (*line == '#')
474 continue;
476 pstrcpy(ip,"");
477 pstrcpy(name,"");
478 pstrcpy(flags,"");
480 ptr = line;
482 if (next_token(&ptr,ip ,NULL,sizeof(ip)))
483 ++count;
484 if (next_token(&ptr,name ,NULL, sizeof(pstring)))
485 ++count;
486 if (next_token(&ptr,flags,NULL, sizeof(flags)))
487 ++count;
488 if (next_token(&ptr,extra,NULL, sizeof(extra)))
489 ++count;
491 if (count <= 0)
492 continue;
494 if (count > 0 && count < 2)
496 DEBUG(0,("getlmhostsent: Ill formed hosts line [%s]\n",line));
497 continue;
500 if (count >= 4)
502 DEBUG(0,("getlmhostsent: too many columns in lmhosts file (obsolete syntax)\n"));
503 continue;
506 DEBUG(4, ("getlmhostsent: lmhost entry: %s %s %s\n", ip, name, flags));
508 if (strchr(flags,'G') || strchr(flags,'S'))
510 DEBUG(0,("getlmhostsent: group flag in lmhosts ignored (obsolete)\n"));
511 continue;
514 *ipaddr = *interpret_addr2(ip);
516 /* Extra feature. If the name ends in '#XX', where XX is a hex number,
517 then only add that name type. */
518 if((ptr = strchr(name, '#')) != NULL)
520 char *endptr;
522 ptr++;
523 *name_type = (int)strtol(ptr, &endptr, 16);
525 if(!*ptr || (endptr == ptr))
527 DEBUG(0,("getlmhostsent: invalid name %s containing '#'.\n", name));
528 continue;
531 *(--ptr) = '\0'; /* Truncate at the '#' */
534 return True;
537 return False;
540 /********************************************************
541 Finish parsing the lmhosts file.
542 *********************************************************/
544 void endlmhosts(FILE *fp)
546 fclose(fp);
549 BOOL name_register_wins(const char *name, int name_type)
551 int sock, i, return_count;
552 int num_interfaces = iface_count();
553 struct in_addr sendto_ip;
556 * Do a broadcast register ...
559 if (!lp_wins_server())
560 return False;
562 DEBUG(4, ("name_register_wins:Registering my name %s on %s\n", name, lp_wins_server()));
564 sock = open_socket_in(SOCK_DGRAM, 0, 3,
565 interpret_addr("0.0.0.0"), True);
567 if (sock == -1) return False;
569 set_socket_options(sock, "SO_BROADCAST");
571 sendto_ip.s_addr = inet_addr(lp_wins_server());
573 if (num_interfaces > 1) {
575 for (i = 0; i < num_interfaces; i++) {
577 if (!name_register(sock, name, name_type, *iface_n_ip(i),
578 NMB_NAME_MULTIHOMED_REG_OPCODE,
579 True, sendto_ip, &return_count)) {
581 close(sock);
582 return False;
589 else {
591 if (!name_register(sock, name, name_type, *iface_n_ip(0),
592 NMB_NAME_REG_OPCODE,
593 True, sendto_ip, &return_count)) {
595 close(sock);
596 return False;
602 close(sock);
604 return True;
608 /********************************************************
609 Resolve via "bcast" method.
610 *********************************************************/
612 BOOL name_resolve_bcast(const char *name, int name_type,
613 struct in_addr **return_ip_list, int *return_count)
615 int sock, i;
616 int num_interfaces = iface_count();
618 *return_ip_list = NULL;
619 *return_count = 0;
622 * "bcast" means do a broadcast lookup on all the local interfaces.
625 DEBUG(3,("name_resolve_bcast: Attempting broadcast lookup for name %s<0x%x>\n", name, name_type));
627 sock = open_socket_in( SOCK_DGRAM, 0, 3,
628 interpret_addr(lp_socket_address()), True );
630 if (sock == -1) return False;
632 set_socket_options(sock,"SO_BROADCAST");
634 * Lookup the name on all the interfaces, return on
635 * the first successful match.
637 for( i = num_interfaces-1; i >= 0; i--) {
638 struct in_addr sendto_ip;
639 /* Done this way to fix compiler error on IRIX 5.x */
640 sendto_ip = *iface_bcast(*iface_n_ip(i));
641 *return_ip_list = name_query(sock, name, name_type, True,
642 True, sendto_ip, return_count);
643 if(*return_ip_list != NULL) {
644 close(sock);
645 return True;
649 close(sock);
650 return False;
653 /********************************************************
654 Resolve via "wins" method.
655 *********************************************************/
657 static BOOL resolve_wins(const char *name, int name_type,
658 struct in_addr **return_iplist, int *return_count)
660 int sock;
661 struct in_addr wins_ip;
662 BOOL wins_ismyip;
664 *return_iplist = NULL;
665 *return_count = 0;
668 * "wins" means do a unicast lookup to the WINS server.
669 * Ignore if there is no WINS server specified or if the
670 * WINS server is one of our interfaces (if we're being
671 * called from within nmbd - we can't do this call as we
672 * would then block).
675 DEBUG(3,("resolve_wins: Attempting wins lookup for name %s<0x%x>\n", name, name_type));
677 if (lp_wins_support()) {
679 * We're providing WINS support. Call ourselves so
680 * long as we're not nmbd.
682 extern struct in_addr loopback_ip;
683 wins_ip = loopback_ip;
684 wins_ismyip = True;
685 } else if( wins_srv_count() < 1 ) {
686 DEBUG(3,("resolve_wins: WINS server resolution selected and no WINS servers listed.\n"));
687 return False;
688 } else {
689 wins_ip = wins_srv_ip();
690 wins_ismyip = ismyip(wins_ip);
693 DEBUG(3, ("resolve_wins: WINS server == <%s>\n", inet_ntoa(wins_ip)) );
694 if((wins_ismyip && !global_in_nmbd) || !wins_ismyip) {
695 sock = open_socket_in( SOCK_DGRAM, 0, 3,
696 interpret_addr(lp_socket_address()),
697 True );
698 if (sock != -1) {
699 *return_iplist = name_query( sock, name,
700 name_type, False,
701 True, wins_ip,
702 return_count);
703 if(*return_iplist != NULL) {
704 close(sock);
705 return True;
707 close(sock);
711 return False;
714 /********************************************************
715 Resolve via "lmhosts" method.
716 *********************************************************/
718 static BOOL resolve_lmhosts(const char *name, int name_type,
719 struct in_addr **return_iplist, int *return_count)
722 * "lmhosts" means parse the local lmhosts file.
725 FILE *fp;
726 pstring lmhost_name;
727 int name_type2;
728 struct in_addr return_ip;
730 *return_iplist = NULL;
731 *return_count = 0;
733 DEBUG(3,("resolve_lmhosts: Attempting lmhosts lookup for name %s<0x%x>\n", name, name_type));
735 fp = startlmhosts( LMHOSTSFILE );
736 if(fp) {
737 while (getlmhostsent(fp, lmhost_name, &name_type2, &return_ip)) {
738 if (strequal(name, lmhost_name) &&
739 ((name_type2 == -1) || (name_type == name_type2))
741 endlmhosts(fp);
742 *return_iplist = (struct in_addr *)malloc(sizeof(struct in_addr));
743 if(*return_iplist == NULL) {
744 DEBUG(3,("resolve_lmhosts: malloc fail !\n"));
745 return False;
747 **return_iplist = return_ip;
748 *return_count = 1;
749 return True;
752 endlmhosts(fp);
754 return False;
758 /********************************************************
759 Resolve via "hosts" method.
760 *********************************************************/
762 static BOOL resolve_hosts(const char *name,
763 struct in_addr **return_iplist, int *return_count)
766 * "host" means do a localhost, or dns lookup.
768 struct hostent *hp;
770 *return_iplist = NULL;
771 *return_count = 0;
773 DEBUG(3,("resolve_hosts: Attempting host lookup for name %s<0x20>\n", name));
775 if (((hp = Get_Hostbyname(name)) != NULL) && (hp->h_addr != NULL)) {
776 struct in_addr return_ip;
777 putip((char *)&return_ip,(char *)hp->h_addr);
778 *return_iplist = (struct in_addr *)malloc(sizeof(struct in_addr));
779 if(*return_iplist == NULL) {
780 DEBUG(3,("resolve_hosts: malloc fail !\n"));
781 return False;
783 **return_iplist = return_ip;
784 *return_count = 1;
785 return True;
787 return False;
790 /********************************************************
791 Internal interface to resolve a name into an IP address.
792 Use this function if the string is either an IP address, DNS
793 or host name or NetBIOS name. This uses the name switch in the
794 smb.conf to determine the order of name resolution.
795 *********************************************************/
797 static BOOL internal_resolve_name(const char *name, int name_type,
798 struct in_addr **return_iplist, int *return_count)
800 pstring name_resolve_list;
801 fstring tok;
802 char *ptr;
803 BOOL allones = (strcmp(name,"255.255.255.255") == 0);
804 BOOL allzeros = (strcmp(name,"0.0.0.0") == 0);
805 BOOL is_address = is_ipaddress(name);
806 *return_iplist = NULL;
807 *return_count = 0;
809 if (allzeros || allones || is_address) {
810 *return_iplist = (struct in_addr *)malloc(sizeof(struct in_addr));
811 if(*return_iplist == NULL) {
812 DEBUG(3,("internal_resolve_name: malloc fail !\n"));
813 return False;
815 if(is_address) {
816 /* if it's in the form of an IP address then get the lib to interpret it */
817 (*return_iplist)->s_addr = inet_addr(name);
818 } else {
819 (*return_iplist)->s_addr = allones ? 0xFFFFFFFF : 0;
820 *return_count = 1;
822 return True;
825 pstrcpy(name_resolve_list, lp_name_resolve_order());
826 ptr = name_resolve_list;
827 if (!ptr || !*ptr)
828 ptr = "host";
830 while (next_token(&ptr, tok, LIST_SEP, sizeof(tok))) {
831 if((strequal(tok, "host") || strequal(tok, "hosts"))) {
832 if (name_type == 0x20 && resolve_hosts(name, return_iplist, return_count)) {
833 return True;
835 } else if(strequal( tok, "lmhosts")) {
836 if (resolve_lmhosts(name, name_type, return_iplist, return_count)) {
837 return True;
839 } else if(strequal( tok, "wins")) {
840 /* don't resolve 1D via WINS */
841 if (name_type != 0x1D &&
842 resolve_wins(name, name_type, return_iplist, return_count)) {
843 return True;
845 } else if(strequal( tok, "bcast")) {
846 if (name_resolve_bcast(name, name_type, return_iplist, return_count)) {
847 return True;
849 } else {
850 DEBUG(0,("resolve_name: unknown name switch type %s\n", tok));
854 if((*return_iplist) != NULL) {
855 free((char *)(*return_iplist));
856 *return_iplist = NULL;
858 return False;
861 /********************************************************
862 Internal interface to resolve a name into one IP address.
863 Use this function if the string is either an IP address, DNS
864 or host name or NetBIOS name. This uses the name switch in the
865 smb.conf to determine the order of name resolution.
866 *********************************************************/
868 BOOL resolve_name(const char *name, struct in_addr *return_ip, int name_type)
870 struct in_addr *ip_list = NULL;
871 int count = 0;
873 if(internal_resolve_name(name, name_type, &ip_list, &count)) {
874 *return_ip = ip_list[0];
875 free((char *)ip_list);
876 return True;
878 if(ip_list != NULL)
879 free((char *)ip_list);
880 return False;
884 /********************************************************
885 resolve a name of format \\server_name or \\ipaddress
886 into a name. also, cut the \\ from the front for us.
887 *********************************************************/
889 BOOL resolve_srv_name(const char* srv_name, fstring dest_host,
890 struct in_addr *ip)
892 BOOL ret;
893 const char *sv_name = srv_name;
895 DEBUG(10,("resolve_srv_name: %s\n", srv_name));
897 if (srv_name == NULL || strequal("\\\\.", srv_name))
899 extern pstring global_myname;
900 fstrcpy(dest_host, global_myname);
901 ip = interpret_addr2("127.0.0.1");
902 return True;
905 if (strnequal("\\\\", srv_name, 2))
907 sv_name = &srv_name[2];
910 fstrcpy(dest_host, sv_name);
911 /* treat the '*' name specially - it is a magic name for the PDC */
912 if (strcmp(dest_host,"*") == 0) {
913 extern pstring global_myname;
914 ret = resolve_name(lp_workgroup(), ip, 0x1B);
915 lookup_pdc_name(global_myname, lp_workgroup(), ip, dest_host);
916 } else {
917 ret = resolve_name(dest_host, ip, 0x20);
920 if (is_ipaddress(dest_host))
922 fstrcpy(dest_host, "*SMBSERVER");
925 return ret;
929 /********************************************************
930 Find the IP address of the master browser or DMB for a workgroup.
931 *********************************************************/
933 BOOL find_master_ip(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 free((char *)ip_list);
941 return True;
943 if(internal_resolve_name(group, 0x1B, &ip_list, &count)) {
944 *master_ip = ip_list[0];
945 free((char *)ip_list);
946 return True;
949 if(ip_list != NULL)
950 free((char *)ip_list);
951 return False;
954 /********************************************************
955 Lookup a PDC name given a Domain name and IP address.
956 *********************************************************/
958 BOOL lookup_pdc_name(const char *srcname, const char *domain, struct in_addr *pdc_ip, char *ret_name)
960 #if !defined(I_HATE_WINDOWS_REPLY_CODE)
962 fstring pdc_name;
963 BOOL ret;
966 * Due to the fact win WinNT *sucks* we must do a node status
967 * query here... JRA.
970 *pdc_name = '\0';
972 ret = name_status_find(0x20,*pdc_ip,pdc_name);
974 if(ret && *pdc_name) {
975 fstrcpy(ret_name, pdc_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 += dos_PutUniCode(bufp, srcname, sizeof(buffer) - (bufp - buffer) - 1, True);
1029 SIVAL(bufp,0,1);
1030 SSVAL(bufp,4,0xFFFF);
1031 SSVAL(bufp,6,0xFFFF);
1032 bufp += 8;
1033 len = PTR_DIFF(bufp,buffer);
1035 memset((char *)&p,'\0',sizeof(p));
1037 /* DIRECT GROUP or UNIQUE datagram. */
1038 dgram->header.msg_type = 0x10;
1039 dgram->header.flags.node_type = M_NODE;
1040 dgram->header.flags.first = True;
1041 dgram->header.flags.more = False;
1042 dgram->header.dgm_id = dgm_id;
1043 dgram->header.source_ip = *iface_ip(*pdc_ip);
1044 dgram->header.source_port = ntohs(sock_name.sin_port);
1045 dgram->header.dgm_length = 0; /* Let build_dgram() handle this. */
1046 dgram->header.packet_offset = 0;
1048 make_nmb_name(&dgram->source_name,srcname,0);
1049 make_nmb_name(&dgram->dest_name,domain,0x1C);
1051 ptr = &dgram->data[0];
1053 /* Setup the smb part. */
1054 ptr -= 4; /* XXX Ugliness because of handling of tcp SMB length. */
1055 memcpy(tmp,ptr,4);
1056 set_message(ptr,17,17 + len,True);
1057 memcpy(ptr,tmp,4);
1059 CVAL(ptr,smb_com) = SMBtrans;
1060 SSVAL(ptr,smb_vwv1,len);
1061 SSVAL(ptr,smb_vwv11,len);
1062 SSVAL(ptr,smb_vwv12,70 + strlen(mailslot));
1063 SSVAL(ptr,smb_vwv13,3);
1064 SSVAL(ptr,smb_vwv14,1);
1065 SSVAL(ptr,smb_vwv15,1);
1066 SSVAL(ptr,smb_vwv16,2);
1067 p2 = smb_buf(ptr);
1068 pstrcpy(p2,mailslot);
1069 p2 = skip_string(p2,1);
1071 memcpy(p2,buffer,len);
1072 p2 += len;
1074 dgram->datasize = PTR_DIFF(p2,ptr+4); /* +4 for tcp length. */
1076 p.ip = *pdc_ip;
1077 p.port = DGRAM_PORT;
1078 p.fd = sock;
1079 p.timestamp = time(NULL);
1080 p.packet_type = DGRAM_PACKET;
1082 GetTimeOfDay(&tval);
1084 if (!send_packet(&p)) {
1085 DEBUG(0,("lookup_pdc_name: send_packet failed.\n"));
1086 close(sock);
1087 return False;
1090 retries--;
1092 while (1) {
1093 struct timeval tval2;
1094 struct packet_struct *p_ret;
1096 GetTimeOfDay(&tval2);
1097 if (TvalDiff(&tval,&tval2) > retry_time) {
1098 if (!retries)
1099 break;
1100 if (!send_packet(&p)) {
1101 DEBUG(0,("lookup_pdc_name: send_packet failed.\n"));
1102 close(sock);
1103 return False;
1105 GetTimeOfDay(&tval);
1106 retries--;
1109 if ((p_ret = receive_dgram_packet(sock,90,mailslot_name))) {
1110 struct dgram_packet *dgram2 = &p_ret->packet.dgram;
1111 char *buf;
1112 char *buf2;
1114 buf = &dgram2->data[0];
1115 buf -= 4;
1117 if (CVAL(buf,smb_com) != SMBtrans) {
1118 DEBUG(0,("lookup_pdc_name: datagram type %u != SMBtrans(%u)\n", (unsigned int)
1119 CVAL(buf,smb_com), (unsigned int)SMBtrans ));
1120 free_packet(p_ret);
1121 continue;
1124 len = SVAL(buf,smb_vwv11);
1125 buf2 = smb_base(buf) + SVAL(buf,smb_vwv12);
1127 if (len <= 0) {
1128 DEBUG(0,("lookup_pdc_name: datagram len < 0 (%d)\n", len ));
1129 free_packet(p_ret);
1130 continue;
1133 DEBUG(4,("lookup_pdc_name: datagram reply from %s to %s IP %s for %s of type %d len=%d\n",
1134 nmb_namestr(&dgram2->source_name),nmb_namestr(&dgram2->dest_name),
1135 inet_ntoa(p_ret->ip), smb_buf(buf),SVAL(buf2,0),len));
1137 if(SVAL(buf2,0) != QUERYFORPDC_R) {
1138 DEBUG(0,("lookup_pdc_name: datagram type (%u) != QUERYFORPDC_R(%u)\n",
1139 (unsigned int)SVAL(buf,0), (unsigned int)QUERYFORPDC_R ));
1140 free_packet(p_ret);
1141 continue;
1144 buf2 += 2;
1145 /* Note this is safe as it is a bounded strcpy. */
1146 fstrcpy(ret_name, buf2);
1147 ret_name[sizeof(fstring)-1] = '\0';
1148 close(sock);
1149 free_packet(p_ret);
1150 return True;
1154 close(sock);
1155 return False;
1156 #endif /* defined(I_HATE_WINDOWS_REPLY_CODE) */
1160 /********************************************************
1161 Get the IP address list of the PDC/BDC's of a Domain.
1162 *********************************************************/
1163 BOOL get_dc_list(BOOL pdc_only, char *group, struct in_addr **ip_list, int *count)
1165 return internal_resolve_name(group, pdc_only ? 0x1B : 0x1C, ip_list, count);