- completely rewrote the wins_srv.c code. It is now much simpler, and
[nivanova/samba-autobuild/.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 ****************************************************************************/
306 struct in_addr *name_query(int fd,const char *name,int name_type, 
307                            BOOL bcast,BOOL recurse,
308                            struct in_addr to_ip, int *count, int *flags)
309 {
310   BOOL found=False;
311   int i, retries = 3;
312   int retry_time = bcast?250:2000;
313   struct timeval tval;
314   struct packet_struct p;
315   struct packet_struct *p2;
316   struct nmb_packet *nmb = &p.packet.nmb;
317   struct in_addr *ip_list = NULL;
318
319   memset((char *)&p,'\0',sizeof(p));
320   (*count) = 0;
321   (*flags) = 0;
322
323   nmb->header.name_trn_id = generate_trn_id();
324   nmb->header.opcode = 0;
325   nmb->header.response = False;
326   nmb->header.nm_flags.bcast = bcast;
327   nmb->header.nm_flags.recursion_available = False;
328   nmb->header.nm_flags.recursion_desired = recurse;
329   nmb->header.nm_flags.trunc = False;
330   nmb->header.nm_flags.authoritative = False;
331   nmb->header.rcode = 0;
332   nmb->header.qdcount = 1;
333   nmb->header.ancount = 0;
334   nmb->header.nscount = 0;
335   nmb->header.arcount = 0;
336
337   make_nmb_name(&nmb->question.question_name,name,name_type);
338
339   nmb->question.question_type = 0x20;
340   nmb->question.question_class = 0x1;
341
342   p.ip = to_ip;
343   p.port = NMB_PORT;
344   p.fd = fd;
345   p.timestamp = time(NULL);
346   p.packet_type = NMB_PACKET;
347
348   GetTimeOfDay(&tval);
349
350   if (!send_packet(&p)) 
351     return NULL;
352
353   retries--;
354
355         while (1) {
356           struct timeval tval2;
357       struct in_addr *tmp_ip_list;
358
359           GetTimeOfDay(&tval2);
360           if (TvalDiff(&tval,&tval2) > retry_time) {
361                   if (!retries)
362                           break;
363                   if (!found && !send_packet(&p))
364                           return NULL;
365                   GetTimeOfDay(&tval);
366                   retries--;
367           }
368           
369           if ((p2=receive_nmb_packet(fd,90,nmb->header.name_trn_id))) {     
370                   struct nmb_packet *nmb2 = &p2->packet.nmb;
371                   debug_nmb_packet(p2);
372
373                   /* If we get a Negative Name Query Response from a WINS
374                    * server, we should report it and give up.
375                    */
376                   if( 0 == nmb2->header.opcode          /* A query response   */
377                       && !(bcast)                       /* from a WINS server */
378                       && nmb2->header.rcode             /* Error returned     */
379                     ) {
380
381                     if( DEBUGLVL( 3 ) ) {
382                       /* Only executed if DEBUGLEVEL >= 3 */
383                                         dbgtext( "Negative name query response, rcode 0x%02x: ", nmb2->header.rcode );
384                       switch( nmb2->header.rcode ) {
385                         case 0x01:
386                           dbgtext( "Request was invalidly formatted.\n" );
387                           break;
388                         case 0x02:
389                           dbgtext( "Problem with NBNS, cannot process name.\n");
390                           break;
391                         case 0x03:
392                           dbgtext( "The name requested does not exist.\n" );
393                           break;
394                         case 0x04:
395                           dbgtext( "Unsupported request error.\n" );
396                           break;
397                         case 0x05:
398                           dbgtext( "Query refused error.\n" );
399                           break;
400                         default:
401                           dbgtext( "Unrecognized error code.\n" );
402                           break;
403                       }
404                     }
405                     free_packet(p2);
406                     return( NULL );
407                   }
408
409                   if (nmb2->header.opcode != 0 ||
410                       nmb2->header.nm_flags.bcast ||
411                       nmb2->header.rcode ||
412                       !nmb2->header.ancount) {
413                           /* 
414                            * XXXX what do we do with this? Could be a
415                            * redirect, but we'll discard it for the
416                                  * moment.
417                                  */
418                           free_packet(p2);
419                           continue;
420                   }
421
422           tmp_ip_list = (struct in_addr *)Realloc( ip_list, sizeof( ip_list[0] )
423                                                 * ( (*count) + nmb2->answers->rdlength/6 ) );
424  
425           if (!tmp_ip_list) {
426               DEBUG(0,("name_query: Realloc failed.\n"));
427               SAFE_FREE(ip_list);
428           }
429  
430           ip_list = tmp_ip_list;
431
432                   if (ip_list) {
433                                 DEBUG(2,("Got a positive name query response from %s ( ", inet_ntoa(p2->ip)));
434                           for (i=0;i<nmb2->answers->rdlength/6;i++) {
435                                   putip((char *)&ip_list[(*count)],&nmb2->answers->rdata[2+i*6]);
436                                   DEBUGADD(2,("%s ",inet_ntoa(ip_list[(*count)])));
437                                   (*count)++;
438                           }
439                           DEBUGADD(2,(")\n"));
440                   }
441
442                   found=True;
443                   retries=0;
444                   /* We add the flags back ... */
445                   if (nmb2->header.response)
446                     (*flags) |= NM_FLAGS_RS;
447                   if (nmb2->header.nm_flags.authoritative)
448                     (*flags) |= NM_FLAGS_AA;
449                   if (nmb2->header.nm_flags.trunc)
450                     (*flags) |= NM_FLAGS_TC;
451                   if (nmb2->header.nm_flags.recursion_desired)
452                     (*flags) |= NM_FLAGS_RD;
453                   if (nmb2->header.nm_flags.recursion_available)
454                     (*flags) |= NM_FLAGS_RA;
455                   if (nmb2->header.nm_flags.bcast)
456                     (*flags) |= NM_FLAGS_B;
457                   free_packet(p2);
458                   /*
459                    * If we're doing a unicast lookup we only
460                    * expect one reply. Don't wait the full 2
461                    * seconds if we got one. JRA.
462                    */
463                   if(!bcast && found)
464                           break;
465           }
466   }
467
468   /* Reach here if we've timed out waiting for replies.. */
469         if( !bcast && !found ) {
470     /* Timed out wating for WINS server to respond.  Mark it dead. */
471     wins_srv_died( to_ip );
472     }
473
474   return ip_list;
475 }
476
477 /********************************************************
478  Start parsing the lmhosts file.
479 *********************************************************/
480
481 XFILE *startlmhosts(char *fname)
482 {
483         XFILE *fp = x_fopen(fname,O_RDONLY, 0);
484         if (!fp) {
485                 DEBUG(4,("startlmhosts: Can't open lmhosts file %s. Error was %s\n",
486                          fname, strerror(errno)));
487                 return NULL;
488         }
489         return fp;
490 }
491
492 /********************************************************
493  Parse the next line in the lmhosts file.
494 *********************************************************/
495
496 BOOL getlmhostsent( XFILE *fp, pstring name, int *name_type, struct in_addr *ipaddr)
497 {
498   pstring line;
499
500   while(!x_feof(fp) && !x_ferror(fp)) {
501     pstring ip,flags,extra;
502     char *ptr;
503     int count = 0;
504
505     *name_type = -1;
506
507     if (!fgets_slash(line,sizeof(pstring),fp))
508       continue;
509
510     if (*line == '#')
511       continue;
512
513     pstrcpy(ip,"");
514     pstrcpy(name,"");
515     pstrcpy(flags,"");
516
517     ptr = line;
518
519     if (next_token(&ptr,ip   ,NULL,sizeof(ip)))
520       ++count;
521     if (next_token(&ptr,name ,NULL, sizeof(pstring)))
522       ++count;
523     if (next_token(&ptr,flags,NULL, sizeof(flags)))
524       ++count;
525     if (next_token(&ptr,extra,NULL, sizeof(extra)))
526       ++count;
527
528     if (count <= 0)
529       continue;
530
531     if (count > 0 && count < 2)
532     {
533       DEBUG(0,("getlmhostsent: Ill formed hosts line [%s]\n",line));
534       continue;
535     }
536
537     if (count >= 4)
538     {
539       DEBUG(0,("getlmhostsent: too many columns in lmhosts file (obsolete syntax)\n"));
540       continue;
541     }
542
543     DEBUG(4, ("getlmhostsent: lmhost entry: %s %s %s\n", ip, name, flags));
544
545     if (strchr_m(flags,'G') || strchr_m(flags,'S'))
546     {
547       DEBUG(0,("getlmhostsent: group flag in lmhosts ignored (obsolete)\n"));
548       continue;
549     }
550
551     *ipaddr = *interpret_addr2(ip);
552
553     /* Extra feature. If the name ends in '#XX', where XX is a hex number,
554        then only add that name type. */
555     if((ptr = strchr_m(name, '#')) != NULL)
556     {
557       char *endptr;
558
559       ptr++;
560       *name_type = (int)strtol(ptr, &endptr, 16);
561
562       if(!*ptr || (endptr == ptr))
563       {
564         DEBUG(0,("getlmhostsent: invalid name %s containing '#'.\n", name));
565         continue;
566       }
567
568       *(--ptr) = '\0'; /* Truncate at the '#' */
569     }
570
571     return True;
572   }
573
574   return False;
575 }
576
577 /********************************************************
578  Finish parsing the lmhosts file.
579 *********************************************************/
580
581 void endlmhosts(XFILE *fp)
582 {
583         x_fclose(fp);
584 }
585
586 BOOL name_register_wins(const char *name, int name_type)
587 {
588   int sock, i, return_count;
589   int num_interfaces = iface_count();
590   struct in_addr sendto_ip;
591
592   /* 
593    * Check if we have any interfaces, prevents a segfault later
594    */
595
596   if (num_interfaces <= 0)
597     return False;         /* Should return some indication of the problem */
598
599   /*
600    * Do a broadcast register ...
601    */
602
603   if (0 == wins_srv_count())
604     return False;
605
606   sendto_ip = wins_srv_ip();
607
608   if( DEBUGLVL( 4 ) )
609     {
610     dbgtext( "name_register_wins: Registering my name %s ", name );
611     dbgtext( "with WINS server %s.\n", inet_ntoa(sendto_ip));
612     }
613
614   sock = open_socket_in( SOCK_DGRAM, 0, 3, 
615                          interpret_addr("0.0.0.0"), True );
616
617   if (sock == -1) return False;
618
619   set_socket_options(sock, "SO_BROADCAST");     /* ????! crh */
620
621   if (num_interfaces > 1) {
622
623     for (i = 0; i < num_interfaces; i++) {
624       
625       if (!name_register(sock, name, name_type, *iface_n_ip(i), 
626                          NMB_NAME_MULTIHOMED_REG_OPCODE,
627                          True, sendto_ip, &return_count)) {
628
629         close(sock);
630         return False;
631
632       }
633
634     }
635
636   }
637   else {
638
639     if (!name_register(sock, name, name_type, *iface_n_ip(0),
640                        NMB_NAME_REG_OPCODE,
641                        True, sendto_ip, &return_count)) {
642
643       close(sock);
644       return False;
645
646     }
647
648   }
649
650   close(sock);
651
652   return True;
653
654 }
655
656 /********************************************************
657  Resolve via "bcast" method.
658 *********************************************************/
659
660 BOOL name_resolve_bcast(const char *name, int name_type,
661                         struct in_addr **return_ip_list, int *return_count)
662 {
663         int sock, i;
664         int num_interfaces = iface_count();
665
666         *return_ip_list = NULL;
667         *return_count = 0;
668         
669         /*
670          * "bcast" means do a broadcast lookup on all the local interfaces.
671          */
672
673         DEBUG(3,("name_resolve_bcast: Attempting broadcast lookup for name %s<0x%x>\n", name, name_type));
674
675         sock = open_socket_in( SOCK_DGRAM, 0, 3,
676                                interpret_addr(lp_socket_address()), True );
677
678         if (sock == -1) return False;
679
680         set_socket_options(sock,"SO_BROADCAST");
681         /*
682          * Lookup the name on all the interfaces, return on
683          * the first successful match.
684          */
685         for( i = num_interfaces-1; i >= 0; i--) {
686                 struct in_addr sendto_ip;
687                 int flags;
688                 /* Done this way to fix compiler error on IRIX 5.x */
689                 sendto_ip = *iface_n_bcast(i);
690                 *return_ip_list = name_query(sock, name, name_type, True, 
691                                     True, sendto_ip, return_count, &flags);
692                 if(*return_ip_list != NULL) {
693                         close(sock);
694                         return True;
695                 }
696         }
697
698         close(sock);
699         return False;
700 }
701
702 /********************************************************
703  Resolve via "wins" method.
704 *********************************************************/
705
706 static BOOL resolve_wins(const char *name, int name_type,
707                          struct in_addr **return_iplist, int *return_count)
708 {
709         int sock;
710         struct in_addr wins_ip;
711         BOOL wins_ismyip;
712
713         *return_iplist = NULL;
714         *return_count = 0;
715         
716         /*
717          * "wins" means do a unicast lookup to the WINS server.
718          * Ignore if there is no WINS server specified or if the
719          * WINS server is one of our interfaces (if we're being
720          * called from within nmbd - we can't do this call as we
721          * would then block).
722          */
723
724         DEBUG(3,("resolve_wins: Attempting wins lookup for name %s<0x%x>\n", name, name_type));
725
726         if (lp_wins_support()) {
727                 /*
728                  * We're providing WINS support. Call ourselves so
729                  * long as we're not nmbd.
730                  */
731                 extern struct in_addr loopback_ip;
732                 wins_ip = loopback_ip;
733                 wins_ismyip = True;
734         } else if( wins_srv_count() < 1 ) {
735                 DEBUG(3,("resolve_wins: WINS server resolution selected and no WINS servers listed.\n"));
736                 return False;
737         } else {
738                 wins_ip     = wins_srv_ip();
739                 wins_ismyip = ismyip(wins_ip);
740         }
741
742         DEBUG(3, ("resolve_wins: WINS server == <%s>\n", inet_ntoa(wins_ip)) );
743         if((wins_ismyip && !global_in_nmbd) || !wins_ismyip) {
744                 int flags;
745                 sock = open_socket_in(  SOCK_DGRAM, 0, 3,
746                                         interpret_addr(lp_socket_address()),
747                                         True );
748                 if (sock != -1) {
749                         *return_iplist = name_query( sock,      name,
750                                                      name_type, False, 
751                                                      True,      wins_ip,
752                                                      return_count, &flags);
753                         if(*return_iplist != NULL) {
754                                 close(sock);
755                                 return True;
756                         }
757                         close(sock);
758                 }
759         }
760
761         return False;
762 }
763
764 /********************************************************
765  Resolve via "lmhosts" method.
766 *********************************************************/
767
768 static BOOL resolve_lmhosts(const char *name, int name_type,
769                          struct in_addr **return_iplist, int *return_count)
770 {
771         /*
772          * "lmhosts" means parse the local lmhosts file.
773          */
774         
775         XFILE *fp;
776         pstring lmhost_name;
777         int name_type2;
778         struct in_addr return_ip;
779
780         *return_iplist = NULL;
781         *return_count = 0;
782
783         DEBUG(3,("resolve_lmhosts: Attempting lmhosts lookup for name %s<0x%x>\n", name, name_type));
784
785         fp = startlmhosts(dyn_LMHOSTSFILE);
786         if(fp) {
787                 while (getlmhostsent(fp, lmhost_name, &name_type2, &return_ip)) {
788                         if (strequal(name, lmhost_name) && 
789                 ((name_type2 == -1) || (name_type == name_type2))
790                ) {
791                                 endlmhosts(fp);
792                                 *return_iplist = (struct in_addr *)malloc(sizeof(struct in_addr));
793                                 if(*return_iplist == NULL) {
794                                         DEBUG(3,("resolve_lmhosts: malloc fail !\n"));
795                                         return False;
796                                 }
797                                 **return_iplist = return_ip;
798                                 *return_count = 1;
799                                 return True; 
800                         }
801                 }
802                 endlmhosts(fp);
803         }
804         return False;
805 }
806
807
808 /********************************************************
809  Resolve via "hosts" method.
810 *********************************************************/
811
812 static BOOL resolve_hosts(const char *name,
813                          struct in_addr **return_iplist, int *return_count)
814 {
815         /*
816          * "host" means do a localhost, or dns lookup.
817          */
818         struct hostent *hp;
819
820         *return_iplist = NULL;
821         *return_count = 0;
822
823         DEBUG(3,("resolve_hosts: Attempting host lookup for name %s<0x20>\n", name));
824         
825         if (((hp = sys_gethostbyname(name)) != NULL) && (hp->h_addr != NULL)) {
826                 struct in_addr return_ip;
827                 putip((char *)&return_ip,(char *)hp->h_addr);
828                 *return_iplist = (struct in_addr *)malloc(sizeof(struct in_addr));
829                 if(*return_iplist == NULL) {
830                         DEBUG(3,("resolve_hosts: malloc fail !\n"));
831                         return False;
832                 }
833                 **return_iplist = return_ip;
834                 *return_count = 1;
835                 return True;
836         }
837         return False;
838 }
839
840 /********************************************************
841  Internal interface to resolve a name into an IP address.
842  Use this function if the string is either an IP address, DNS
843  or host name or NetBIOS name. This uses the name switch in the
844  smb.conf to determine the order of name resolution.
845 *********************************************************/
846
847 static BOOL internal_resolve_name(const char *name, int name_type,
848                                         struct in_addr **return_iplist, int *return_count)
849 {
850   pstring name_resolve_list;
851   fstring tok;
852   char *ptr;
853   BOOL allones = (strcmp(name,"255.255.255.255") == 0);
854   BOOL allzeros = (strcmp(name,"0.0.0.0") == 0);
855   BOOL is_address = is_ipaddress(name);
856   BOOL result = False;
857   struct in_addr *nodupes_iplist;
858   int i;
859
860   *return_iplist = NULL;
861   *return_count = 0;
862
863   DEBUG(10, ("internal_resolve_name: looking up %s#%x\n", name, name_type));
864
865   if (allzeros || allones || is_address) {
866         *return_iplist = (struct in_addr *)malloc(sizeof(struct in_addr));
867         if(*return_iplist == NULL) {
868                 DEBUG(3,("internal_resolve_name: malloc fail !\n"));
869                 return False;
870         }
871         if(is_address) { 
872                 /* if it's in the form of an IP address then get the lib to interpret it */
873                 (*return_iplist)->s_addr = inet_addr(name);
874     } else {
875                 (*return_iplist)->s_addr = allones ? 0xFFFFFFFF : 0;
876                 *return_count = 1;
877         }
878     return True;
879   }
880   
881   pstrcpy(name_resolve_list, lp_name_resolve_order());
882   ptr = name_resolve_list;
883   if (!ptr || !*ptr)
884     ptr = "host";
885
886   while (next_token(&ptr, tok, LIST_SEP, sizeof(tok))) {
887           if((strequal(tok, "host") || strequal(tok, "hosts"))) {
888                   if (name_type == 0x20 && resolve_hosts(name, return_iplist, return_count)) {
889                     result = True;
890                     goto done;
891                   }
892           } else if(strequal( tok, "lmhosts")) {
893                   if (resolve_lmhosts(name, name_type, return_iplist, return_count)) {
894                     result = True;
895                     goto done;
896                   }
897           } else if(strequal( tok, "wins")) {
898                   /* don't resolve 1D via WINS */
899                   if (name_type != 0x1D &&
900                       resolve_wins(name, name_type, return_iplist, return_count)) {
901                     result = True;
902                     goto done;
903                   }
904           } else if(strequal( tok, "bcast")) {
905                   if (name_resolve_bcast(name, name_type, return_iplist, return_count)) {
906                     result = True;
907                     goto done;
908                   }
909           } else {
910                   DEBUG(0,("resolve_name: unknown name switch type %s\n", tok));
911           }
912   }
913
914   /* All of the resolve_* functions above have returned false. */
915
916   SAFE_FREE(*return_iplist);
917   *return_count = 0;
918
919   return False;
920
921  done:
922
923   /* Remove duplicate entries.  Some queries, notably #1c (domain
924      controllers) return the PDC in iplist[0] and then all domain
925      controllers including the PDC in iplist[1..n].  Iterating over
926      the iplist when the PDC is down will cause two sets of timeouts. */
927
928   if (*return_count && (nodupes_iplist = (struct in_addr *)
929        malloc(sizeof(struct in_addr) * (*return_count)))) {
930           int nodupes_count = 0;
931
932           /* Iterate over return_iplist looking for duplicates */
933
934           for (i = 0; i < *return_count; i++) {
935                   BOOL is_dupe = False;
936                   int j;
937
938                   for (j = i + 1; j < *return_count; j++) {
939                           if (ip_equal((*return_iplist)[i], 
940                                        (*return_iplist)[j])) {
941                                   is_dupe = True;
942                                   break;
943                           }
944                   }
945
946                   if (!is_dupe) {
947
948                           /* This one not a duplicate */
949
950                           nodupes_iplist[nodupes_count] = (*return_iplist)[i];
951                           nodupes_count++;
952                   }
953           }
954           
955           /* Switcheroo with original list */
956           
957           free(*return_iplist);
958
959           *return_iplist = nodupes_iplist;
960           *return_count = nodupes_count;
961   }
962
963   /* Display some debugging info */
964
965   DEBUG(10, ("internal_resolve_name: returning %d addresses: ", 
966              *return_count));
967
968   for (i = 0; i < *return_count; i++)
969           DEBUGADD(10, ("%s ", inet_ntoa((*return_iplist)[i])));
970
971   DEBUG(10, ("\n"));
972
973   return result;
974 }
975
976 /********************************************************
977  Internal interface to resolve a name into one IP address.
978  Use this function if the string is either an IP address, DNS
979  or host name or NetBIOS name. This uses the name switch in the
980  smb.conf to determine the order of name resolution.
981 *********************************************************/
982
983 BOOL resolve_name(const char *name, struct in_addr *return_ip, int name_type)
984 {
985         struct in_addr *ip_list = NULL;
986         int count = 0;
987
988         if (is_ipaddress(name)) {
989                 *return_ip = *interpret_addr2(name);
990                 return True;
991         }
992
993         if (internal_resolve_name(name, name_type, &ip_list, &count)) {
994                 int i;
995                 /* only return valid addresses for TCP connections */
996                 for (i=0; i<count; i++) {
997                         char *ip_str = inet_ntoa(ip_list[i]);
998                         if (ip_str &&
999                             strcmp(ip_str, "255.255.255.255") != 0 &&
1000                             strcmp(ip_str, "0.0.0.0") != 0) {
1001                                 *return_ip = ip_list[i];
1002                                 SAFE_FREE(ip_list);
1003                                 return True;
1004                         }
1005                 }
1006         }
1007         SAFE_FREE(ip_list);
1008         return False;
1009 }
1010
1011 /********************************************************
1012  Find the IP address of the master browser or DMB for a workgroup.
1013 *********************************************************/
1014
1015 BOOL find_master_ip(char *group, struct in_addr *master_ip)
1016 {
1017         struct in_addr *ip_list = NULL;
1018         int count = 0;
1019
1020         if (internal_resolve_name(group, 0x1D, &ip_list, &count)) {
1021                 *master_ip = ip_list[0];
1022                 SAFE_FREE(ip_list);
1023                 return True;
1024         }
1025         if(internal_resolve_name(group, 0x1B, &ip_list, &count)) {
1026                 *master_ip = ip_list[0];
1027                 SAFE_FREE(ip_list);
1028                 return True;
1029         }
1030
1031         SAFE_FREE(ip_list);
1032         return False;
1033 }
1034
1035 /********************************************************
1036  Lookup a DC name given a Domain name and IP address.
1037 *********************************************************/
1038
1039 BOOL lookup_dc_name(const char *srcname, const char *domain, 
1040                     struct in_addr *dc_ip, char *ret_name)
1041 {
1042 #if !defined(I_HATE_WINDOWS_REPLY_CODE)
1043         
1044         fstring dc_name;
1045         BOOL ret;
1046         
1047         /*
1048          * Due to the fact win WinNT *sucks* we must do a node status
1049          * query here... JRA.
1050          */
1051         
1052         *dc_name = '\0';
1053         
1054         ret = name_status_find(domain, 0x1c, 0x20, *dc_ip, dc_name);
1055
1056         if(ret && *dc_name) {
1057                 fstrcpy(ret_name, dc_name);
1058                 return True;
1059         }
1060         
1061         return False;
1062
1063 #else /* defined(I_HATE_WINDOWS_REPLY_CODE) */
1064
1065 JRA - This code is broken with BDC rollover - we need to do a full
1066 NT GETDC call, UNICODE, NT domain SID and uncle tom cobbley and all...
1067
1068         int retries = 3;
1069         int retry_time = 2000;
1070         struct timeval tval;
1071         struct packet_struct p;
1072         struct dgram_packet *dgram = &p.packet.dgram;
1073         char *ptr,*p2;
1074         char tmp[4];
1075         int len;
1076         struct sockaddr_in sock_name;
1077         int sock_len = sizeof(sock_name);
1078         const char *mailslot = NET_LOGON_MAILSLOT;
1079         char *mailslot_name;
1080         char buffer[1024];
1081         char *bufp;
1082         int dgm_id = generate_trn_id();
1083         int sock = open_socket_in(SOCK_DGRAM, 0, 3, interpret_addr(lp_socket_address()), True );
1084         
1085         if(sock == -1)
1086                 return False;
1087         
1088         /* Find out the transient UDP port we have been allocated. */
1089         if(getsockname(sock, (struct sockaddr *)&sock_name, &sock_len)<0) {
1090                 DEBUG(0,("lookup_pdc_name: Failed to get local UDP port. Error was %s\n",
1091                          strerror(errno)));
1092                 close(sock);
1093                 return False;
1094         }
1095
1096         /*
1097          * Create the request data.
1098          */
1099
1100         memset(buffer,'\0',sizeof(buffer));
1101         bufp = buffer;
1102         SSVAL(bufp,0,QUERYFORPDC);
1103         bufp += 2;
1104         fstrcpy(bufp,srcname);
1105         bufp += (strlen(bufp) + 1);
1106         slprintf(bufp, sizeof(fstring)-1, "\\MAILSLOT\\NET\\GETDC%d", dgm_id);
1107         mailslot_name = bufp;
1108         bufp += (strlen(bufp) + 1);
1109         bufp = ALIGN2(bufp, buffer);
1110         bufp += push_ucs2(NULL, bufp, srcname, sizeof(buffer) - (bufp - buffer), STR_TERMINATE);        
1111         
1112         SIVAL(bufp,0,1);
1113         SSVAL(bufp,4,0xFFFF); 
1114         SSVAL(bufp,6,0xFFFF); 
1115         bufp += 8;
1116         len = PTR_DIFF(bufp,buffer);
1117
1118         memset((char *)&p,'\0',sizeof(p));
1119
1120         /* DIRECT GROUP or UNIQUE datagram. */
1121         dgram->header.msg_type = 0x10;
1122         dgram->header.flags.node_type = M_NODE;
1123         dgram->header.flags.first = True;
1124         dgram->header.flags.more = False;
1125         dgram->header.dgm_id = dgm_id;
1126         dgram->header.source_ip = *iface_ip(*pdc_ip);
1127         dgram->header.source_port = ntohs(sock_name.sin_port);
1128         dgram->header.dgm_length = 0; /* Let build_dgram() handle this. */
1129         dgram->header.packet_offset = 0;
1130         
1131         make_nmb_name(&dgram->source_name,srcname,0);
1132         make_nmb_name(&dgram->dest_name,domain,0x1C);
1133         
1134         ptr = &dgram->data[0];
1135         
1136         /* Setup the smb part. */
1137         ptr -= 4; /* XXX Ugliness because of handling of tcp SMB length. */
1138         memcpy(tmp,ptr,4);
1139         set_message(ptr,17,17 + len,True);
1140         memcpy(ptr,tmp,4);
1141
1142         CVAL(ptr,smb_com) = SMBtrans;
1143         SSVAL(ptr,smb_vwv1,len);
1144         SSVAL(ptr,smb_vwv11,len);
1145         SSVAL(ptr,smb_vwv12,70 + strlen(mailslot));
1146         SSVAL(ptr,smb_vwv13,3);
1147         SSVAL(ptr,smb_vwv14,1);
1148         SSVAL(ptr,smb_vwv15,1);
1149         SSVAL(ptr,smb_vwv16,2);
1150         p2 = smb_buf(ptr);
1151         pstrcpy(p2,mailslot);
1152         p2 = skip_string(p2,1);
1153         
1154         memcpy(p2,buffer,len);
1155         p2 += len;
1156         
1157         dgram->datasize = PTR_DIFF(p2,ptr+4); /* +4 for tcp length. */
1158         
1159         p.ip = *pdc_ip;
1160         p.port = DGRAM_PORT;
1161         p.fd = sock;
1162         p.timestamp = time(NULL);
1163         p.packet_type = DGRAM_PACKET;
1164         
1165         GetTimeOfDay(&tval);
1166         
1167         if (!send_packet(&p)) {
1168                 DEBUG(0,("lookup_pdc_name: send_packet failed.\n"));
1169                 close(sock);
1170                 return False;
1171         }
1172         
1173         retries--;
1174         
1175         while (1) {
1176                 struct timeval tval2;
1177                 struct packet_struct *p_ret;
1178                 
1179                 GetTimeOfDay(&tval2);
1180                 if (TvalDiff(&tval,&tval2) > retry_time) {
1181                         if (!retries)
1182                                 break;
1183                         if (!send_packet(&p)) {
1184                                 DEBUG(0,("lookup_pdc_name: send_packet failed.\n"));
1185                                 close(sock);
1186                                 return False;
1187                         }
1188                         GetTimeOfDay(&tval);
1189                         retries--;
1190                 }
1191
1192                 if ((p_ret = receive_dgram_packet(sock,90,mailslot_name))) {
1193                         struct dgram_packet *dgram2 = &p_ret->packet.dgram;
1194                         char *buf;
1195                         char *buf2;
1196
1197                         buf = &dgram2->data[0];
1198                         buf -= 4;
1199
1200                         if (CVAL(buf,smb_com) != SMBtrans) {
1201                                 DEBUG(0,("lookup_pdc_name: datagram type %u != SMBtrans(%u)\n", (unsigned int)
1202                                          CVAL(buf,smb_com), (unsigned int)SMBtrans ));
1203                                 free_packet(p_ret);
1204                                 continue;
1205                         }
1206                         
1207                         len = SVAL(buf,smb_vwv11);
1208                         buf2 = smb_base(buf) + SVAL(buf,smb_vwv12);
1209                         
1210                         if (len <= 0) {
1211                                 DEBUG(0,("lookup_pdc_name: datagram len < 0 (%d)\n", len ));
1212                                 free_packet(p_ret);
1213                                 continue;
1214                         }
1215
1216                         DEBUG(4,("lookup_pdc_name: datagram reply from %s to %s IP %s for %s of type %d len=%d\n",
1217                                  nmb_namestr(&dgram2->source_name),nmb_namestr(&dgram2->dest_name),
1218                                  inet_ntoa(p_ret->ip), smb_buf(buf),SVAL(buf2,0),len));
1219
1220                         if(SVAL(buf2,0) != QUERYFORPDC_R) {
1221                                 DEBUG(0,("lookup_pdc_name: datagram type (%u) != QUERYFORPDC_R(%u)\n",
1222                                          (unsigned int)SVAL(buf,0), (unsigned int)QUERYFORPDC_R ));
1223                                 free_packet(p_ret);
1224                                 continue;
1225                         }
1226
1227                         buf2 += 2;
1228                         /* Note this is safe as it is a bounded strcpy. */
1229                         fstrcpy(ret_name, buf2);
1230                         ret_name[sizeof(fstring)-1] = '\0';
1231                         close(sock);
1232                         free_packet(p_ret);
1233                         return True;
1234                 }
1235         }
1236         
1237         close(sock);
1238         return False;
1239 #endif /* defined(I_HATE_WINDOWS_REPLY_CODE) */
1240 }
1241
1242 /********************************************************
1243   Get the IP address list of the Local Master Browsers
1244  ********************************************************/ 
1245
1246 BOOL get_lmb_list(struct in_addr **ip_list, int *count)
1247 {
1248     return internal_resolve_name( MSBROWSE, 0x1, ip_list, count);
1249 }
1250
1251 /********************************************************
1252  Get the IP address list of the PDC/BDC's of a Domain.
1253 *********************************************************/
1254
1255 BOOL get_dc_list(BOOL pdc_only, const char *group, struct in_addr **ip_list, int *count)
1256 {
1257         int name_type = pdc_only ? 0x1B : 0x1C;
1258
1259         /*
1260          * If it's our domain then
1261          * use the 'password server' parameter.
1262          */
1263
1264         if (strequal(group, lp_workgroup())) {
1265                 char *p;
1266                 char *pserver = lp_passwordserver();
1267                 fstring name;
1268                 int num_adresses = 0;
1269                 struct in_addr *return_iplist = NULL;
1270
1271                 if (! *pserver)
1272                         return internal_resolve_name(group, name_type, ip_list, count);
1273
1274                 p = pserver;
1275                 while (next_token(&p,name,LIST_SEP,sizeof(name))) {
1276                         if (strequal(name, "*"))
1277                                 return internal_resolve_name(group, name_type, ip_list, count);
1278                         num_adresses++;
1279                 }
1280                 if (num_adresses == 0)
1281                         return internal_resolve_name(group, name_type, ip_list, count);
1282
1283                 return_iplist = (struct in_addr *)malloc(num_adresses * sizeof(struct in_addr));
1284                 if(return_iplist == NULL) {
1285                         DEBUG(3,("get_dc_list: malloc fail !\n"));
1286                         return False;
1287                 }
1288                 p = pserver;
1289                 *count = 0;
1290                 while (next_token(&p,name,LIST_SEP,sizeof(name))) {
1291                         struct in_addr name_ip;
1292                         if (resolve_name( name, &name_ip, 0x20) == False)
1293                                 continue;
1294                         return_iplist[(*count)++] = name_ip;
1295                 }
1296                 *ip_list = return_iplist;
1297                 return (*count != 0);
1298         } else
1299                 return internal_resolve_name(group, name_type, ip_list, count);
1300 }