The next phase in the WINS rewrite!
[samba.git] / source3 / libsmb / namequery.c
1 /* 
2    Unix SMB/CIFS implementation.
3    name query routines
4    Copyright (C) Andrew Tridgell 1994-1998
5    
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2 of the License, or
9    (at your option) any later version.
10    
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15    
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19    
20 */
21
22 #include "includes.h"
23
24 /* nmbd.c sets this to True. */
25 BOOL global_in_nmbd = False;
26
27 /****************************************************************************
28 generate a random trn_id
29 ****************************************************************************/
30 static int generate_trn_id(void)
31 {
32         static int trn_id;
33
34         if (trn_id == 0) {
35                 sys_srandom(sys_getpid());
36         }
37
38         trn_id = sys_random();
39
40         return trn_id % (unsigned)0x7FFF;
41 }
42
43
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)
48 {
49         struct node_status *ret;
50         int i;
51
52         *num_names = CVAL(p,0);
53
54         if (*num_names == 0) return NULL;
55
56         ret = (struct node_status *)malloc(sizeof(struct node_status)* (*num_names));
57         if (!ret) return NULL;
58
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));
68         }
69         return ret;
70 }
71
72
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)
79 {
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;
88
89         ZERO_STRUCT(p);
90
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;
107
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;
113         
114         GetTimeOfDay(&tval);
115   
116         if (!send_packet(&p)) 
117                 return NULL;
118
119         retries--;
120
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--;
131                 }
132
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);
136                         
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;
147                         }
148
149                         ret = parse_node_status(&nmb2->answers->rdata[0], num_names);
150                         free_packet(p2);
151                         return ret;
152                 }
153         }
154         
155         return NULL;
156 }
157
158
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 **************************************************************************/
164
165 BOOL name_status_find(const char *q_name, int q_type, int type, struct in_addr to_ip, char *name)
166 {
167         struct node_status *status = NULL;
168         struct nmb_name nname;
169         int count, i;
170         int sock;
171         BOOL result = False;
172
173         DEBUG(10, ("name_status_find: looking up %s#%02x at %s\n", q_name, 
174                    q_type, inet_ntoa(to_ip)));
175
176         sock = open_socket_in(SOCK_DGRAM, 0, 3, interpret_addr(lp_socket_address()), True);
177         if (sock == -1)
178                 goto done;
179
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;
186
187         for (i=0;i<count;i++) {
188                 if (status[i].type == type)
189                         break;
190         }
191         if (i == count)
192                 goto done;
193
194         pull_ascii(name, status[i].name, 15, -1, STR_TERMINATE);
195         result = True;
196
197  done:
198         SAFE_FREE(status);
199
200         DEBUG(10, ("name_status_find: name %sfound", result ? "" : "not "));
201
202         if (result)
203                 DEBUGADD(10, (", ip address is %s", inet_ntoa(to_ip)));
204
205         DEBUG(10, ("\n"));      
206
207         return result;
208 }
209
210 /****************************************************************************
211  Do a NetBIOS name registation to try to claim a name ...
212 ***************************************************************************/
213 BOOL name_register(int fd, const char *name, int name_type,
214                    struct in_addr name_ip, int opcode,
215                    BOOL bcast, 
216                    struct in_addr to_ip, int *count)
217 {
218   int retries = 3;
219   struct timeval tval;
220   struct packet_struct p;
221   struct packet_struct *p2;
222   struct nmb_packet *nmb = &p.packet.nmb;
223   struct in_addr register_ip;
224
225   DEBUG(4, ("name_register: %s as %s on %s\n", name, inet_ntoa(name_ip), inet_ntoa(to_ip)));
226
227   register_ip.s_addr = name_ip.s_addr;  /* Fix this ... */
228   
229   memset((char *)&p, '\0', sizeof(p));
230
231   *count = 0;
232
233   nmb->header.name_trn_id = generate_trn_id();
234   nmb->header.opcode = opcode;
235   nmb->header.response = False;
236   nmb->header.nm_flags.bcast = False;
237   nmb->header.nm_flags.recursion_available = False;
238   nmb->header.nm_flags.recursion_desired = True;  /* ? */
239   nmb->header.nm_flags.trunc = False;
240   nmb->header.nm_flags.authoritative = True;
241
242   nmb->header.qdcount = 1;
243   nmb->header.ancount = 0;
244   nmb->header.nscount = 0;
245   nmb->header.arcount = 1;
246
247   make_nmb_name(&nmb->question.question_name, name, name_type);
248
249   nmb->question.question_type = 0x20;
250   nmb->question.question_class = 0x1;
251
252   /* Now, create the additional stuff for a registration request */
253
254   if ((nmb->additional = (struct res_rec *)malloc(sizeof(struct res_rec))) == NULL) {
255
256     DEBUG(0, ("name_register: malloc fail for additional record.\n"));
257     return False;
258
259   }
260
261   memset((char *)nmb->additional, '\0', sizeof(struct res_rec));
262
263   nmb->additional->rr_name  = nmb->question.question_name;
264   nmb->additional->rr_type  = RR_TYPE_NB;
265   nmb->additional->rr_class = RR_CLASS_IN;
266
267   /* See RFC 1002, sections 5.1.1.1, 5.1.1.2 and 5.1.1.3 */
268   if (nmb->header.nm_flags.bcast)
269     nmb->additional->ttl = PERMANENT_TTL;
270   else
271     nmb->additional->ttl = lp_max_ttl();
272
273   nmb->additional->rdlength = 6;
274
275   nmb->additional->rdata[0] = NB_MFLAG & 0xFF;
276
277   /* Set the address for the name we are registering. */
278   putip(&nmb->additional->rdata[2], &register_ip);
279
280   p.ip = to_ip;
281   p.port = NMB_PORT;
282   p.fd = fd;
283   p.timestamp = time(NULL);
284   p.packet_type = NMB_PACKET;
285
286   GetTimeOfDay(&tval);
287
288   if (!send_packet(&p))
289     return False;
290
291   retries--;
292
293   if ((p2 = receive_nmb_packet(fd, 10, nmb->header.name_trn_id))) {
294     debug_nmb_packet(p2);
295     SAFE_FREE(p2);  /* No memory leaks ... */
296   }
297
298   return True;
299 }
300
301 /****************************************************************************
302  Do a netbios name query to find someones IP.
303  Returns an array of IP addresses or NULL if none.
304  *count will be set to the number of addresses returned.
305  *timed_out is set if we failed by timing out
306 ****************************************************************************/
307 struct in_addr *name_query(int fd,const char *name,int name_type, 
308                            BOOL bcast,BOOL recurse,
309                            struct in_addr to_ip, int *count, int *flags,
310                            BOOL *timed_out)
311 {
312         BOOL found=False;
313         int i, retries = 3;
314         int retry_time = bcast?250:2000;
315         struct timeval tval;
316         struct packet_struct p;
317         struct packet_struct *p2;
318         struct nmb_packet *nmb = &p.packet.nmb;
319         struct in_addr *ip_list = NULL;
320
321         if (timed_out) {
322                 *timed_out = False;
323         }
324         
325         memset((char *)&p,'\0',sizeof(p));
326         (*count) = 0;
327         (*flags) = 0;
328         
329         nmb->header.name_trn_id = generate_trn_id();
330         nmb->header.opcode = 0;
331         nmb->header.response = False;
332         nmb->header.nm_flags.bcast = bcast;
333         nmb->header.nm_flags.recursion_available = False;
334         nmb->header.nm_flags.recursion_desired = recurse;
335         nmb->header.nm_flags.trunc = False;
336         nmb->header.nm_flags.authoritative = False;
337         nmb->header.rcode = 0;
338         nmb->header.qdcount = 1;
339         nmb->header.ancount = 0;
340         nmb->header.nscount = 0;
341         nmb->header.arcount = 0;
342         
343         make_nmb_name(&nmb->question.question_name,name,name_type);
344         
345         nmb->question.question_type = 0x20;
346         nmb->question.question_class = 0x1;
347         
348         p.ip = to_ip;
349         p.port = NMB_PORT;
350         p.fd = fd;
351         p.timestamp = time(NULL);
352         p.packet_type = NMB_PACKET;
353         
354         GetTimeOfDay(&tval);
355         
356         if (!send_packet(&p)) 
357                 return NULL;
358         
359         retries--;
360         
361         while (1) {
362                 struct timeval tval2;
363                 struct in_addr *tmp_ip_list;
364                 
365                 GetTimeOfDay(&tval2);
366                 if (TvalDiff(&tval,&tval2) > retry_time) {
367                         if (!retries)
368                                 break;
369                         if (!found && !send_packet(&p))
370                                 return NULL;
371                         GetTimeOfDay(&tval);
372                         retries--;
373                 }
374                 
375                 if ((p2=receive_nmb_packet(fd,90,nmb->header.name_trn_id))) {     
376                         struct nmb_packet *nmb2 = &p2->packet.nmb;
377                         debug_nmb_packet(p2);
378                         
379                         /* If we get a Negative Name Query Response from a WINS
380                          * server, we should report it and give up.
381                          */
382                         if( 0 == nmb2->header.opcode            /* A query response   */
383                             && !(bcast)                 /* from a WINS server */
384                             && nmb2->header.rcode               /* Error returned     */
385                                 ) {
386                                 
387                                 if( DEBUGLVL( 3 ) ) {
388                                         /* Only executed if DEBUGLEVEL >= 3 */
389                                         dbgtext( "Negative name query response, rcode 0x%02x: ", nmb2->header.rcode );
390                                         switch( nmb2->header.rcode ) {
391                                         case 0x01:
392                                                 dbgtext( "Request was invalidly formatted.\n" );
393                                                 break;
394                                         case 0x02:
395                                                 dbgtext( "Problem with NBNS, cannot process name.\n");
396                                                 break;
397                                         case 0x03:
398                                                 dbgtext( "The name requested does not exist.\n" );
399                                                 break;
400                                         case 0x04:
401                                                 dbgtext( "Unsupported request error.\n" );
402                                                 break;
403                                         case 0x05:
404                                                 dbgtext( "Query refused error.\n" );
405                                                 break;
406                                         default:
407                                                 dbgtext( "Unrecognized error code.\n" );
408                                                 break;
409                                         }
410                                 }
411                                 free_packet(p2);
412                                 return( NULL );
413                         }
414                         
415                         if (nmb2->header.opcode != 0 ||
416                             nmb2->header.nm_flags.bcast ||
417                             nmb2->header.rcode ||
418                             !nmb2->header.ancount) {
419                                 /* 
420                                  * XXXX what do we do with this? Could be a
421                                  * redirect, but we'll discard it for the
422                                  * moment.
423                                  */
424                                 free_packet(p2);
425                                 continue;
426                         }
427                         
428                         tmp_ip_list = (struct in_addr *)Realloc( ip_list, sizeof( ip_list[0] )
429                                                                  * ( (*count) + nmb2->answers->rdlength/6 ) );
430                         
431                         if (!tmp_ip_list) {
432                                 DEBUG(0,("name_query: Realloc failed.\n"));
433                                 SAFE_FREE(ip_list);
434                         }
435                         
436                         ip_list = tmp_ip_list;
437                         
438                         if (ip_list) {
439                                 DEBUG(2,("Got a positive name query response from %s ( ", inet_ntoa(p2->ip)));
440                                 for (i=0;i<nmb2->answers->rdlength/6;i++) {
441                                         putip((char *)&ip_list[(*count)],&nmb2->answers->rdata[2+i*6]);
442                                         DEBUGADD(2,("%s ",inet_ntoa(ip_list[(*count)])));
443                                         (*count)++;
444                                 }
445                                 DEBUGADD(2,(")\n"));
446                         }
447                         
448                         found=True;
449                         retries=0;
450                         /* We add the flags back ... */
451                         if (nmb2->header.response)
452                                 (*flags) |= NM_FLAGS_RS;
453                         if (nmb2->header.nm_flags.authoritative)
454                                 (*flags) |= NM_FLAGS_AA;
455                         if (nmb2->header.nm_flags.trunc)
456                                 (*flags) |= NM_FLAGS_TC;
457                         if (nmb2->header.nm_flags.recursion_desired)
458                                 (*flags) |= NM_FLAGS_RD;
459                         if (nmb2->header.nm_flags.recursion_available)
460                                 (*flags) |= NM_FLAGS_RA;
461                         if (nmb2->header.nm_flags.bcast)
462                                 (*flags) |= NM_FLAGS_B;
463                         free_packet(p2);
464                         /*
465                          * If we're doing a unicast lookup we only
466                          * expect one reply. Don't wait the full 2
467                          * seconds if we got one. JRA.
468                          */
469                         if(!bcast && found)
470                                 break;
471                 }
472         }
473
474         if (timed_out) {
475                 *timed_out = True;
476         }
477
478         return ip_list;
479 }
480
481 /********************************************************
482  Start parsing the lmhosts file.
483 *********************************************************/
484
485 XFILE *startlmhosts(char *fname)
486 {
487         XFILE *fp = x_fopen(fname,O_RDONLY, 0);
488         if (!fp) {
489                 DEBUG(4,("startlmhosts: Can't open lmhosts file %s. Error was %s\n",
490                          fname, strerror(errno)));
491                 return NULL;
492         }
493         return fp;
494 }
495
496 /********************************************************
497  Parse the next line in the lmhosts file.
498 *********************************************************/
499
500 BOOL getlmhostsent( XFILE *fp, pstring name, int *name_type, struct in_addr *ipaddr)
501 {
502   pstring line;
503
504   while(!x_feof(fp) && !x_ferror(fp)) {
505     pstring ip,flags,extra;
506     char *ptr;
507     int count = 0;
508
509     *name_type = -1;
510
511     if (!fgets_slash(line,sizeof(pstring),fp))
512       continue;
513
514     if (*line == '#')
515       continue;
516
517     pstrcpy(ip,"");
518     pstrcpy(name,"");
519     pstrcpy(flags,"");
520
521     ptr = line;
522
523     if (next_token(&ptr,ip   ,NULL,sizeof(ip)))
524       ++count;
525     if (next_token(&ptr,name ,NULL, sizeof(pstring)))
526       ++count;
527     if (next_token(&ptr,flags,NULL, sizeof(flags)))
528       ++count;
529     if (next_token(&ptr,extra,NULL, sizeof(extra)))
530       ++count;
531
532     if (count <= 0)
533       continue;
534
535     if (count > 0 && count < 2)
536     {
537       DEBUG(0,("getlmhostsent: Ill formed hosts line [%s]\n",line));
538       continue;
539     }
540
541     if (count >= 4)
542     {
543       DEBUG(0,("getlmhostsent: too many columns in lmhosts file (obsolete syntax)\n"));
544       continue;
545     }
546
547     DEBUG(4, ("getlmhostsent: lmhost entry: %s %s %s\n", ip, name, flags));
548
549     if (strchr_m(flags,'G') || strchr_m(flags,'S'))
550     {
551       DEBUG(0,("getlmhostsent: group flag in lmhosts ignored (obsolete)\n"));
552       continue;
553     }
554
555     *ipaddr = *interpret_addr2(ip);
556
557     /* Extra feature. If the name ends in '#XX', where XX is a hex number,
558        then only add that name type. */
559     if((ptr = strchr_m(name, '#')) != NULL)
560     {
561       char *endptr;
562
563       ptr++;
564       *name_type = (int)strtol(ptr, &endptr, 16);
565
566       if(!*ptr || (endptr == ptr))
567       {
568         DEBUG(0,("getlmhostsent: invalid name %s containing '#'.\n", name));
569         continue;
570       }
571
572       *(--ptr) = '\0'; /* Truncate at the '#' */
573     }
574
575     return True;
576   }
577
578   return False;
579 }
580
581 /********************************************************
582  Finish parsing the lmhosts file.
583 *********************************************************/
584
585 void endlmhosts(XFILE *fp)
586 {
587         x_fclose(fp);
588 }
589
590
591 /********************************************************
592  Resolve via "bcast" method.
593 *********************************************************/
594
595 BOOL name_resolve_bcast(const char *name, int name_type,
596                         struct in_addr **return_ip_list, int *return_count)
597 {
598         int sock, i;
599         int num_interfaces = iface_count();
600
601         *return_ip_list = NULL;
602         *return_count = 0;
603         
604         /*
605          * "bcast" means do a broadcast lookup on all the local interfaces.
606          */
607
608         DEBUG(3,("name_resolve_bcast: Attempting broadcast lookup for name %s<0x%x>\n", name, name_type));
609
610         sock = open_socket_in( SOCK_DGRAM, 0, 3,
611                                interpret_addr(lp_socket_address()), True );
612
613         if (sock == -1) return False;
614
615         set_socket_options(sock,"SO_BROADCAST");
616         /*
617          * Lookup the name on all the interfaces, return on
618          * the first successful match.
619          */
620         for( i = num_interfaces-1; i >= 0; i--) {
621                 struct in_addr sendto_ip;
622                 int flags;
623                 /* Done this way to fix compiler error on IRIX 5.x */
624                 sendto_ip = *iface_n_bcast(i);
625                 *return_ip_list = name_query(sock, name, name_type, True, 
626                                     True, sendto_ip, return_count, &flags, NULL);
627                 if(*return_ip_list != NULL) {
628                         close(sock);
629                         return True;
630                 }
631         }
632
633         close(sock);
634         return False;
635 }
636
637 /********************************************************
638  Resolve via "wins" method.
639 *********************************************************/
640 BOOL resolve_wins(const char *name, int name_type,
641                   struct in_addr **return_iplist, int *return_count)
642 {
643         int sock, t, i;
644         char **wins_tags;
645         struct in_addr src_ip;
646
647         *return_iplist = NULL;
648         *return_count = 0;
649         
650         DEBUG(3,("resolve_wins: Attempting wins lookup for name %s<0x%x>\n", name, name_type));
651
652         if (wins_srv_count() < 1) {
653                 DEBUG(3,("resolve_wins: WINS server resolution selected and no WINS servers listed.\n"));
654                 return False;
655         }
656
657         /* we try a lookup on each of the WINS tags in turn */
658         wins_tags = wins_srv_tags();
659
660         if (!wins_tags) {
661                 /* huh? no tags?? give up in disgust */
662                 return False;
663         }
664
665         /* the address we will be sending from */
666         src_ip = *interpret_addr2(lp_socket_address());
667
668         /* in the worst case we will try every wins server with every
669            tag! */
670         for (t=0; wins_tags && wins_tags[t]; t++) {
671                 int srv_count = wins_srv_count_tag(wins_tags[t]);
672                 for (i=0; i<srv_count; i++) {
673                         struct in_addr wins_ip;
674                         int flags;
675                         BOOL timed_out;
676
677                         wins_ip = wins_srv_ip_tag(wins_tags[t], src_ip);
678
679                         if (global_in_nmbd && ismyip(wins_ip)) {
680                                 /* yikes! we'll loop forever */
681                                 continue;
682                         }
683
684                         /* skip any that have been unresponsive lately */
685                         if (wins_srv_is_dead(wins_ip, src_ip)) {
686                                 continue;
687                         }
688
689                         DEBUG(3,("resolve_wins: using WINS server %s and tag '%s'\n", inet_ntoa(wins_ip), wins_tags[t]));
690
691                         sock = open_socket_in(SOCK_DGRAM, 0, 3, src_ip.s_addr, True);
692                         if (sock == -1) {
693                                 continue;
694                         }
695
696                         *return_iplist = name_query(sock,name,name_type, False, 
697                                                     True, wins_ip, return_count, &flags, 
698                                                     &timed_out);
699                         if (*return_iplist != NULL) {
700                                 goto success;
701                         }
702                         close(sock);
703
704                         if (timed_out) {
705                                 /* Timed out wating for WINS server to respond.  Mark it dead. */
706                                 wins_srv_died(wins_ip, src_ip);
707                         } else {
708                                 /* The name definately isn't in this
709                                    group of WINS servers. goto the next group  */
710                                 break;
711                         }
712                 }
713         }
714
715         wins_srv_tags_free(wins_tags);
716         return False;
717
718 success:
719         wins_srv_tags_free(wins_tags);
720         close(sock);
721         return True;
722 }
723
724 /********************************************************
725  Resolve via "lmhosts" method.
726 *********************************************************/
727
728 static BOOL resolve_lmhosts(const char *name, int name_type,
729                          struct in_addr **return_iplist, int *return_count)
730 {
731         /*
732          * "lmhosts" means parse the local lmhosts file.
733          */
734         
735         XFILE *fp;
736         pstring lmhost_name;
737         int name_type2;
738         struct in_addr return_ip;
739
740         *return_iplist = NULL;
741         *return_count = 0;
742
743         DEBUG(3,("resolve_lmhosts: Attempting lmhosts lookup for name %s<0x%x>\n", name, name_type));
744
745         fp = startlmhosts(dyn_LMHOSTSFILE);
746         if(fp) {
747                 while (getlmhostsent(fp, lmhost_name, &name_type2, &return_ip)) {
748                         if (strequal(name, lmhost_name) && 
749                 ((name_type2 == -1) || (name_type == name_type2))
750                ) {
751                                 endlmhosts(fp);
752                                 *return_iplist = (struct in_addr *)malloc(sizeof(struct in_addr));
753                                 if(*return_iplist == NULL) {
754                                         DEBUG(3,("resolve_lmhosts: malloc fail !\n"));
755                                         return False;
756                                 }
757                                 **return_iplist = return_ip;
758                                 *return_count = 1;
759                                 return True; 
760                         }
761                 }
762                 endlmhosts(fp);
763         }
764         return False;
765 }
766
767
768 /********************************************************
769  Resolve via "hosts" method.
770 *********************************************************/
771
772 static BOOL resolve_hosts(const char *name,
773                          struct in_addr **return_iplist, int *return_count)
774 {
775         /*
776          * "host" means do a localhost, or dns lookup.
777          */
778         struct hostent *hp;
779
780         *return_iplist = NULL;
781         *return_count = 0;
782
783         DEBUG(3,("resolve_hosts: Attempting host lookup for name %s<0x20>\n", name));
784         
785         if (((hp = sys_gethostbyname(name)) != NULL) && (hp->h_addr != NULL)) {
786                 struct in_addr return_ip;
787                 putip((char *)&return_ip,(char *)hp->h_addr);
788                 *return_iplist = (struct in_addr *)malloc(sizeof(struct in_addr));
789                 if(*return_iplist == NULL) {
790                         DEBUG(3,("resolve_hosts: malloc fail !\n"));
791                         return False;
792                 }
793                 **return_iplist = return_ip;
794                 *return_count = 1;
795                 return True;
796         }
797         return False;
798 }
799
800 /********************************************************
801  Internal interface to resolve a name into an IP address.
802  Use this function if the string is either an IP address, DNS
803  or host name or NetBIOS name. This uses the name switch in the
804  smb.conf to determine the order of name resolution.
805 *********************************************************/
806
807 static BOOL internal_resolve_name(const char *name, int name_type,
808                                         struct in_addr **return_iplist, int *return_count)
809 {
810   pstring name_resolve_list;
811   fstring tok;
812   char *ptr;
813   BOOL allones = (strcmp(name,"255.255.255.255") == 0);
814   BOOL allzeros = (strcmp(name,"0.0.0.0") == 0);
815   BOOL is_address = is_ipaddress(name);
816   BOOL result = False;
817   struct in_addr *nodupes_iplist;
818   int i;
819
820   *return_iplist = NULL;
821   *return_count = 0;
822
823   DEBUG(10, ("internal_resolve_name: looking up %s#%x\n", name, name_type));
824
825   if (allzeros || allones || is_address) {
826         *return_iplist = (struct in_addr *)malloc(sizeof(struct in_addr));
827         if(*return_iplist == NULL) {
828                 DEBUG(3,("internal_resolve_name: malloc fail !\n"));
829                 return False;
830         }
831         if(is_address) { 
832                 /* if it's in the form of an IP address then get the lib to interpret it */
833                 (*return_iplist)->s_addr = inet_addr(name);
834     } else {
835                 (*return_iplist)->s_addr = allones ? 0xFFFFFFFF : 0;
836                 *return_count = 1;
837         }
838     return True;
839   }
840   
841   pstrcpy(name_resolve_list, lp_name_resolve_order());
842   ptr = name_resolve_list;
843   if (!ptr || !*ptr)
844     ptr = "host";
845
846   while (next_token(&ptr, tok, LIST_SEP, sizeof(tok))) {
847           if((strequal(tok, "host") || strequal(tok, "hosts"))) {
848                   if (name_type == 0x20 && resolve_hosts(name, return_iplist, return_count)) {
849                     result = True;
850                     goto done;
851                   }
852           } else if(strequal( tok, "lmhosts")) {
853                   if (resolve_lmhosts(name, name_type, return_iplist, return_count)) {
854                     result = True;
855                     goto done;
856                   }
857           } else if(strequal( tok, "wins")) {
858                   /* don't resolve 1D via WINS */
859                   if (name_type != 0x1D &&
860                       resolve_wins(name, name_type, return_iplist, return_count)) {
861                     result = True;
862                     goto done;
863                   }
864           } else if(strequal( tok, "bcast")) {
865                   if (name_resolve_bcast(name, name_type, return_iplist, return_count)) {
866                     result = True;
867                     goto done;
868                   }
869           } else {
870                   DEBUG(0,("resolve_name: unknown name switch type %s\n", tok));
871           }
872   }
873
874   /* All of the resolve_* functions above have returned false. */
875
876   SAFE_FREE(*return_iplist);
877   *return_count = 0;
878
879   return False;
880
881  done:
882
883   /* Remove duplicate entries.  Some queries, notably #1c (domain
884      controllers) return the PDC in iplist[0] and then all domain
885      controllers including the PDC in iplist[1..n].  Iterating over
886      the iplist when the PDC is down will cause two sets of timeouts. */
887
888   if (*return_count && (nodupes_iplist = (struct in_addr *)
889        malloc(sizeof(struct in_addr) * (*return_count)))) {
890           int nodupes_count = 0;
891
892           /* Iterate over return_iplist looking for duplicates */
893
894           for (i = 0; i < *return_count; i++) {
895                   BOOL is_dupe = False;
896                   int j;
897
898                   for (j = i + 1; j < *return_count; j++) {
899                           if (ip_equal((*return_iplist)[i], 
900                                        (*return_iplist)[j])) {
901                                   is_dupe = True;
902                                   break;
903                           }
904                   }
905
906                   if (!is_dupe) {
907
908                           /* This one not a duplicate */
909
910                           nodupes_iplist[nodupes_count] = (*return_iplist)[i];
911                           nodupes_count++;
912                   }
913           }
914           
915           /* Switcheroo with original list */
916           
917           free(*return_iplist);
918
919           *return_iplist = nodupes_iplist;
920           *return_count = nodupes_count;
921   }
922
923   /* Display some debugging info */
924
925   DEBUG(10, ("internal_resolve_name: returning %d addresses: ", 
926              *return_count));
927
928   for (i = 0; i < *return_count; i++)
929           DEBUGADD(10, ("%s ", inet_ntoa((*return_iplist)[i])));
930
931   DEBUG(10, ("\n"));
932
933   return result;
934 }
935
936 /********************************************************
937  Internal interface to resolve a name into one IP address.
938  Use this function if the string is either an IP address, DNS
939  or host name or NetBIOS name. This uses the name switch in the
940  smb.conf to determine the order of name resolution.
941 *********************************************************/
942
943 BOOL resolve_name(const char *name, struct in_addr *return_ip, int name_type)
944 {
945         struct in_addr *ip_list = NULL;
946         int count = 0;
947
948         if (is_ipaddress(name)) {
949                 *return_ip = *interpret_addr2(name);
950                 return True;
951         }
952
953         if (internal_resolve_name(name, name_type, &ip_list, &count)) {
954                 int i;
955                 /* only return valid addresses for TCP connections */
956                 for (i=0; i<count; i++) {
957                         char *ip_str = inet_ntoa(ip_list[i]);
958                         if (ip_str &&
959                             strcmp(ip_str, "255.255.255.255") != 0 &&
960                             strcmp(ip_str, "0.0.0.0") != 0) {
961                                 *return_ip = ip_list[i];
962                                 SAFE_FREE(ip_list);
963                                 return True;
964                         }
965                 }
966         }
967         SAFE_FREE(ip_list);
968         return False;
969 }
970
971 /********************************************************
972  Find the IP address of the master browser or DMB for a workgroup.
973 *********************************************************/
974
975 BOOL find_master_ip(char *group, struct in_addr *master_ip)
976 {
977         struct in_addr *ip_list = NULL;
978         int count = 0;
979
980         if (internal_resolve_name(group, 0x1D, &ip_list, &count)) {
981                 *master_ip = ip_list[0];
982                 SAFE_FREE(ip_list);
983                 return True;
984         }
985         if(internal_resolve_name(group, 0x1B, &ip_list, &count)) {
986                 *master_ip = ip_list[0];
987                 SAFE_FREE(ip_list);
988                 return True;
989         }
990
991         SAFE_FREE(ip_list);
992         return False;
993 }
994
995 /********************************************************
996  Lookup a DC name given a Domain name and IP address.
997 *********************************************************/
998
999 BOOL lookup_dc_name(const char *srcname, const char *domain, 
1000                     struct in_addr *dc_ip, char *ret_name)
1001 {
1002 #if !defined(I_HATE_WINDOWS_REPLY_CODE)
1003         
1004         fstring dc_name;
1005         BOOL ret;
1006         
1007         /*
1008          * Due to the fact win WinNT *sucks* we must do a node status
1009          * query here... JRA.
1010          */
1011         
1012         *dc_name = '\0';
1013         
1014         ret = name_status_find(domain, 0x1c, 0x20, *dc_ip, dc_name);
1015
1016         if(ret && *dc_name) {
1017                 fstrcpy(ret_name, dc_name);
1018                 return True;
1019         }
1020         
1021         return False;
1022
1023 #else /* defined(I_HATE_WINDOWS_REPLY_CODE) */
1024
1025 JRA - This code is broken with BDC rollover - we need to do a full
1026 NT GETDC call, UNICODE, NT domain SID and uncle tom cobbley and all...
1027
1028         int retries = 3;
1029         int retry_time = 2000;
1030         struct timeval tval;
1031         struct packet_struct p;
1032         struct dgram_packet *dgram = &p.packet.dgram;
1033         char *ptr,*p2;
1034         char tmp[4];
1035         int len;
1036         struct sockaddr_in sock_name;
1037         int sock_len = sizeof(sock_name);
1038         const char *mailslot = NET_LOGON_MAILSLOT;
1039         char *mailslot_name;
1040         char buffer[1024];
1041         char *bufp;
1042         int dgm_id = generate_trn_id();
1043         int sock = open_socket_in(SOCK_DGRAM, 0, 3, interpret_addr(lp_socket_address()), True );
1044         
1045         if(sock == -1)
1046                 return False;
1047         
1048         /* Find out the transient UDP port we have been allocated. */
1049         if(getsockname(sock, (struct sockaddr *)&sock_name, &sock_len)<0) {
1050                 DEBUG(0,("lookup_pdc_name: Failed to get local UDP port. Error was %s\n",
1051                          strerror(errno)));
1052                 close(sock);
1053                 return False;
1054         }
1055
1056         /*
1057          * Create the request data.
1058          */
1059
1060         memset(buffer,'\0',sizeof(buffer));
1061         bufp = buffer;
1062         SSVAL(bufp,0,QUERYFORPDC);
1063         bufp += 2;
1064         fstrcpy(bufp,srcname);
1065         bufp += (strlen(bufp) + 1);
1066         slprintf(bufp, sizeof(fstring)-1, "\\MAILSLOT\\NET\\GETDC%d", dgm_id);
1067         mailslot_name = bufp;
1068         bufp += (strlen(bufp) + 1);
1069         bufp = ALIGN2(bufp, buffer);
1070         bufp += push_ucs2(NULL, bufp, srcname, sizeof(buffer) - (bufp - buffer), STR_TERMINATE);        
1071         
1072         SIVAL(bufp,0,1);
1073         SSVAL(bufp,4,0xFFFF); 
1074         SSVAL(bufp,6,0xFFFF); 
1075         bufp += 8;
1076         len = PTR_DIFF(bufp,buffer);
1077
1078         memset((char *)&p,'\0',sizeof(p));
1079
1080         /* DIRECT GROUP or UNIQUE datagram. */
1081         dgram->header.msg_type = 0x10;
1082         dgram->header.flags.node_type = M_NODE;
1083         dgram->header.flags.first = True;
1084         dgram->header.flags.more = False;
1085         dgram->header.dgm_id = dgm_id;
1086         dgram->header.source_ip = *iface_ip(*pdc_ip);
1087         dgram->header.source_port = ntohs(sock_name.sin_port);
1088         dgram->header.dgm_length = 0; /* Let build_dgram() handle this. */
1089         dgram->header.packet_offset = 0;
1090         
1091         make_nmb_name(&dgram->source_name,srcname,0);
1092         make_nmb_name(&dgram->dest_name,domain,0x1C);
1093         
1094         ptr = &dgram->data[0];
1095         
1096         /* Setup the smb part. */
1097         ptr -= 4; /* XXX Ugliness because of handling of tcp SMB length. */
1098         memcpy(tmp,ptr,4);
1099         set_message(ptr,17,17 + len,True);
1100         memcpy(ptr,tmp,4);
1101
1102         CVAL(ptr,smb_com) = SMBtrans;
1103         SSVAL(ptr,smb_vwv1,len);
1104         SSVAL(ptr,smb_vwv11,len);
1105         SSVAL(ptr,smb_vwv12,70 + strlen(mailslot));
1106         SSVAL(ptr,smb_vwv13,3);
1107         SSVAL(ptr,smb_vwv14,1);
1108         SSVAL(ptr,smb_vwv15,1);
1109         SSVAL(ptr,smb_vwv16,2);
1110         p2 = smb_buf(ptr);
1111         pstrcpy(p2,mailslot);
1112         p2 = skip_string(p2,1);
1113         
1114         memcpy(p2,buffer,len);
1115         p2 += len;
1116         
1117         dgram->datasize = PTR_DIFF(p2,ptr+4); /* +4 for tcp length. */
1118         
1119         p.ip = *pdc_ip;
1120         p.port = DGRAM_PORT;
1121         p.fd = sock;
1122         p.timestamp = time(NULL);
1123         p.packet_type = DGRAM_PACKET;
1124         
1125         GetTimeOfDay(&tval);
1126         
1127         if (!send_packet(&p)) {
1128                 DEBUG(0,("lookup_pdc_name: send_packet failed.\n"));
1129                 close(sock);
1130                 return False;
1131         }
1132         
1133         retries--;
1134         
1135         while (1) {
1136                 struct timeval tval2;
1137                 struct packet_struct *p_ret;
1138                 
1139                 GetTimeOfDay(&tval2);
1140                 if (TvalDiff(&tval,&tval2) > retry_time) {
1141                         if (!retries)
1142                                 break;
1143                         if (!send_packet(&p)) {
1144                                 DEBUG(0,("lookup_pdc_name: send_packet failed.\n"));
1145                                 close(sock);
1146                                 return False;
1147                         }
1148                         GetTimeOfDay(&tval);
1149                         retries--;
1150                 }
1151
1152                 if ((p_ret = receive_dgram_packet(sock,90,mailslot_name))) {
1153                         struct dgram_packet *dgram2 = &p_ret->packet.dgram;
1154                         char *buf;
1155                         char *buf2;
1156
1157                         buf = &dgram2->data[0];
1158                         buf -= 4;
1159
1160                         if (CVAL(buf,smb_com) != SMBtrans) {
1161                                 DEBUG(0,("lookup_pdc_name: datagram type %u != SMBtrans(%u)\n", (unsigned int)
1162                                          CVAL(buf,smb_com), (unsigned int)SMBtrans ));
1163                                 free_packet(p_ret);
1164                                 continue;
1165                         }
1166                         
1167                         len = SVAL(buf,smb_vwv11);
1168                         buf2 = smb_base(buf) + SVAL(buf,smb_vwv12);
1169                         
1170                         if (len <= 0) {
1171                                 DEBUG(0,("lookup_pdc_name: datagram len < 0 (%d)\n", len ));
1172                                 free_packet(p_ret);
1173                                 continue;
1174                         }
1175
1176                         DEBUG(4,("lookup_pdc_name: datagram reply from %s to %s IP %s for %s of type %d len=%d\n",
1177                                  nmb_namestr(&dgram2->source_name),nmb_namestr(&dgram2->dest_name),
1178                                  inet_ntoa(p_ret->ip), smb_buf(buf),SVAL(buf2,0),len));
1179
1180                         if(SVAL(buf2,0) != QUERYFORPDC_R) {
1181                                 DEBUG(0,("lookup_pdc_name: datagram type (%u) != QUERYFORPDC_R(%u)\n",
1182                                          (unsigned int)SVAL(buf,0), (unsigned int)QUERYFORPDC_R ));
1183                                 free_packet(p_ret);
1184                                 continue;
1185                         }
1186
1187                         buf2 += 2;
1188                         /* Note this is safe as it is a bounded strcpy. */
1189                         fstrcpy(ret_name, buf2);
1190                         ret_name[sizeof(fstring)-1] = '\0';
1191                         close(sock);
1192                         free_packet(p_ret);
1193                         return True;
1194                 }
1195         }
1196         
1197         close(sock);
1198         return False;
1199 #endif /* defined(I_HATE_WINDOWS_REPLY_CODE) */
1200 }
1201
1202 /********************************************************
1203   Get the IP address list of the Local Master Browsers
1204  ********************************************************/ 
1205
1206 BOOL get_lmb_list(struct in_addr **ip_list, int *count)
1207 {
1208     return internal_resolve_name( MSBROWSE, 0x1, ip_list, count);
1209 }
1210
1211 /********************************************************
1212  Get the IP address list of the PDC/BDC's of a Domain.
1213 *********************************************************/
1214
1215 BOOL get_dc_list(BOOL pdc_only, const char *group, struct in_addr **ip_list, int *count)
1216 {
1217         int name_type = pdc_only ? 0x1B : 0x1C;
1218
1219         /*
1220          * If it's our domain then
1221          * use the 'password server' parameter.
1222          */
1223
1224         if (strequal(group, lp_workgroup())) {
1225                 char *p;
1226                 char *pserver = lp_passwordserver();
1227                 fstring name;
1228                 int num_adresses = 0;
1229                 struct in_addr *return_iplist = NULL;
1230
1231                 if (! *pserver)
1232                         return internal_resolve_name(group, name_type, ip_list, count);
1233
1234                 p = pserver;
1235                 while (next_token(&p,name,LIST_SEP,sizeof(name))) {
1236                         if (strequal(name, "*"))
1237                                 return internal_resolve_name(group, name_type, ip_list, count);
1238                         num_adresses++;
1239                 }
1240                 if (num_adresses == 0)
1241                         return internal_resolve_name(group, name_type, ip_list, count);
1242
1243                 return_iplist = (struct in_addr *)malloc(num_adresses * sizeof(struct in_addr));
1244                 if(return_iplist == NULL) {
1245                         DEBUG(3,("get_dc_list: malloc fail !\n"));
1246                         return False;
1247                 }
1248                 p = pserver;
1249                 *count = 0;
1250                 while (next_token(&p,name,LIST_SEP,sizeof(name))) {
1251                         struct in_addr name_ip;
1252                         if (resolve_name( name, &name_ip, 0x20) == False)
1253                                 continue;
1254                         return_iplist[(*count)++] = name_ip;
1255                 }
1256                 *ip_list = return_iplist;
1257                 return (*count != 0);
1258         } else
1259                 return internal_resolve_name(group, name_type, ip_list, count);
1260 }