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