d11b1ffd780c5f02cf4e72b0aa66622dba3450fc
[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   *return_iplist = NULL;
826   *return_count = 0;
827
828   if (allzeros || allones || is_address) {
829         *return_iplist = (struct in_addr *)malloc(sizeof(struct in_addr));
830         if(*return_iplist == NULL) {
831                 DEBUG(3,("internal_resolve_name: malloc fail !\n"));
832                 return False;
833         }
834         if(is_address) { 
835                 /* if it's in the form of an IP address then get the lib to interpret it */
836                 (*return_iplist)->s_addr = inet_addr(name);
837     } else {
838                 (*return_iplist)->s_addr = allones ? 0xFFFFFFFF : 0;
839                 *return_count = 1;
840         }
841     return True;
842   }
843   
844   pstrcpy(name_resolve_list, lp_name_resolve_order());
845   ptr = name_resolve_list;
846   if (!ptr || !*ptr)
847     ptr = "host";
848
849   while (next_token(&ptr, tok, LIST_SEP, sizeof(tok))) {
850           if((strequal(tok, "host") || strequal(tok, "hosts"))) {
851                   if (name_type == 0x20 && resolve_hosts(name, return_iplist, return_count)) {
852                           return True;
853                   }
854           } else if(strequal( tok, "lmhosts")) {
855                   if (resolve_lmhosts(name, name_type, return_iplist, return_count)) {
856                           return True;
857                   }
858           } else if(strequal( tok, "wins")) {
859                   /* don't resolve 1D via WINS */
860                   if (name_type != 0x1D &&
861                       resolve_wins(name, name_type, return_iplist, return_count)) {
862                           return True;
863                   }
864           } else if(strequal( tok, "bcast")) {
865                   if (name_resolve_bcast(name, name_type, return_iplist, return_count)) {
866                           return True;
867                   }
868           } else {
869                   DEBUG(0,("resolve_name: unknown name switch type %s\n", tok));
870           }
871   }
872
873   SAFE_FREE(*return_iplist);
874   return False;
875 }
876
877 /********************************************************
878  Internal interface to resolve a name into one IP address.
879  Use this function if the string is either an IP address, DNS
880  or host name or NetBIOS name. This uses the name switch in the
881  smb.conf to determine the order of name resolution.
882 *********************************************************/
883
884 BOOL resolve_name(const char *name, struct in_addr *return_ip, int name_type)
885 {
886         struct in_addr *ip_list = NULL;
887         int count = 0;
888
889         if(internal_resolve_name(name, name_type, &ip_list, &count)) {
890                 *return_ip = ip_list[0];
891                 SAFE_FREE(ip_list);
892                 return True;
893         }
894         SAFE_FREE(ip_list);
895         return False;
896 }
897
898
899 /********************************************************
900  resolve a name of format \\server_name or \\ipaddress
901  into a name.  also, cut the \\ from the front for us.
902 *********************************************************/
903
904 BOOL resolve_srv_name(const char* srv_name, fstring dest_host,
905                                 struct in_addr *ip)
906 {
907         BOOL ret;
908         const char *sv_name = srv_name;
909
910         DEBUG(10,("resolve_srv_name: %s\n", srv_name));
911
912         if (srv_name == NULL || strequal("\\\\.", srv_name))
913         {
914                 extern pstring global_myname;
915                 fstrcpy(dest_host, global_myname);
916                 ip = interpret_addr2("127.0.0.1");
917                 return True;
918         }
919
920         if (strnequal("\\\\", srv_name, 2))
921         {
922                 sv_name = &srv_name[2];
923         }
924
925         fstrcpy(dest_host, sv_name);
926         /* treat the '*' name specially - it is a magic name for the PDC */
927         if (strcmp(dest_host,"*") == 0) {
928                 extern pstring global_myname;
929                 ret = resolve_name(lp_workgroup(), ip, 0x1B);
930                 lookup_dc_name(global_myname, lp_workgroup(), ip, dest_host);
931         } else {
932                 ret = resolve_name(dest_host, ip, 0x20);
933         }
934         
935         if (is_ipaddress(dest_host))
936         {
937                 fstrcpy(dest_host, "*SMBSERVER");
938         }
939         
940         return ret;
941 }
942
943
944 /********************************************************
945  Find the IP address of the master browser or DMB for a workgroup.
946 *********************************************************/
947
948 BOOL find_master_ip(char *group, struct in_addr *master_ip)
949 {
950         struct in_addr *ip_list = NULL;
951         int count = 0;
952
953         if (internal_resolve_name(group, 0x1D, &ip_list, &count)) {
954                 *master_ip = ip_list[0];
955                 SAFE_FREE(ip_list);
956                 return True;
957         }
958         if(internal_resolve_name(group, 0x1B, &ip_list, &count)) {
959                 *master_ip = ip_list[0];
960                 SAFE_FREE(ip_list);
961                 return True;
962         }
963
964         SAFE_FREE(ip_list);
965         return False;
966 }
967
968 /********************************************************
969  Lookup a DC name given a Domain name and IP address.
970 *********************************************************/
971
972 BOOL lookup_dc_name(const char *srcname, const char *domain, 
973                     struct in_addr *dc_ip, char *ret_name)
974 {
975 #if !defined(I_HATE_WINDOWS_REPLY_CODE)
976         
977         fstring dc_name;
978         BOOL ret;
979         
980         /*
981          * Due to the fact win WinNT *sucks* we must do a node status
982          * query here... JRA.
983          */
984         
985         *dc_name = '\0';
986         
987         ret = name_status_find(domain, 0x1c, 0x20, *dc_ip, dc_name);
988
989         if(ret && *dc_name) {
990                 fstrcpy(ret_name, dc_name);
991                 return True;
992         }
993         
994         return False;
995
996 #else /* defined(I_HATE_WINDOWS_REPLY_CODE) */
997
998 JRA - This code is broken with BDC rollover - we need to do a full
999 NT GETDC call, UNICODE, NT domain SID and uncle tom cobbley and all...
1000
1001         int retries = 3;
1002         int retry_time = 2000;
1003         struct timeval tval;
1004         struct packet_struct p;
1005         struct dgram_packet *dgram = &p.packet.dgram;
1006         char *ptr,*p2;
1007         char tmp[4];
1008         int len;
1009         struct sockaddr_in sock_name;
1010         int sock_len = sizeof(sock_name);
1011         const char *mailslot = NET_LOGON_MAILSLOT;
1012         char *mailslot_name;
1013         char buffer[1024];
1014         char *bufp;
1015         int dgm_id = generate_trn_id();
1016         int sock = open_socket_in(SOCK_DGRAM, 0, 3, interpret_addr(lp_socket_address()), True );
1017         
1018         if(sock == -1)
1019                 return False;
1020         
1021         /* Find out the transient UDP port we have been allocated. */
1022         if(getsockname(sock, (struct sockaddr *)&sock_name, &sock_len)<0) {
1023                 DEBUG(0,("lookup_pdc_name: Failed to get local UDP port. Error was %s\n",
1024                          strerror(errno)));
1025                 close(sock);
1026                 return False;
1027         }
1028
1029         /*
1030          * Create the request data.
1031          */
1032
1033         memset(buffer,'\0',sizeof(buffer));
1034         bufp = buffer;
1035         SSVAL(bufp,0,QUERYFORPDC);
1036         bufp += 2;
1037         fstrcpy(bufp,srcname);
1038         bufp += (strlen(bufp) + 1);
1039         slprintf(bufp, sizeof(fstring)-1, "\\MAILSLOT\\NET\\GETDC%d", dgm_id);
1040         mailslot_name = bufp;
1041         bufp += (strlen(bufp) + 1);
1042         bufp = ALIGN2(bufp, buffer);
1043         bufp += push_ucs2(NULL, bufp, srcname, sizeof(buffer) - (bufp - buffer), STR_TERMINATE);        
1044         
1045         SIVAL(bufp,0,1);
1046         SSVAL(bufp,4,0xFFFF); 
1047         SSVAL(bufp,6,0xFFFF); 
1048         bufp += 8;
1049         len = PTR_DIFF(bufp,buffer);
1050
1051         memset((char *)&p,'\0',sizeof(p));
1052
1053         /* DIRECT GROUP or UNIQUE datagram. */
1054         dgram->header.msg_type = 0x10;
1055         dgram->header.flags.node_type = M_NODE;
1056         dgram->header.flags.first = True;
1057         dgram->header.flags.more = False;
1058         dgram->header.dgm_id = dgm_id;
1059         dgram->header.source_ip = *iface_ip(*pdc_ip);
1060         dgram->header.source_port = ntohs(sock_name.sin_port);
1061         dgram->header.dgm_length = 0; /* Let build_dgram() handle this. */
1062         dgram->header.packet_offset = 0;
1063         
1064         make_nmb_name(&dgram->source_name,srcname,0);
1065         make_nmb_name(&dgram->dest_name,domain,0x1C);
1066         
1067         ptr = &dgram->data[0];
1068         
1069         /* Setup the smb part. */
1070         ptr -= 4; /* XXX Ugliness because of handling of tcp SMB length. */
1071         memcpy(tmp,ptr,4);
1072         set_message(ptr,17,17 + len,True);
1073         memcpy(ptr,tmp,4);
1074
1075         CVAL(ptr,smb_com) = SMBtrans;
1076         SSVAL(ptr,smb_vwv1,len);
1077         SSVAL(ptr,smb_vwv11,len);
1078         SSVAL(ptr,smb_vwv12,70 + strlen(mailslot));
1079         SSVAL(ptr,smb_vwv13,3);
1080         SSVAL(ptr,smb_vwv14,1);
1081         SSVAL(ptr,smb_vwv15,1);
1082         SSVAL(ptr,smb_vwv16,2);
1083         p2 = smb_buf(ptr);
1084         pstrcpy(p2,mailslot);
1085         p2 = skip_string(p2,1);
1086         
1087         memcpy(p2,buffer,len);
1088         p2 += len;
1089         
1090         dgram->datasize = PTR_DIFF(p2,ptr+4); /* +4 for tcp length. */
1091         
1092         p.ip = *pdc_ip;
1093         p.port = DGRAM_PORT;
1094         p.fd = sock;
1095         p.timestamp = time(NULL);
1096         p.packet_type = DGRAM_PACKET;
1097         
1098         GetTimeOfDay(&tval);
1099         
1100         if (!send_packet(&p)) {
1101                 DEBUG(0,("lookup_pdc_name: send_packet failed.\n"));
1102                 close(sock);
1103                 return False;
1104         }
1105         
1106         retries--;
1107         
1108         while (1) {
1109                 struct timeval tval2;
1110                 struct packet_struct *p_ret;
1111                 
1112                 GetTimeOfDay(&tval2);
1113                 if (TvalDiff(&tval,&tval2) > retry_time) {
1114                         if (!retries)
1115                                 break;
1116                         if (!send_packet(&p)) {
1117                                 DEBUG(0,("lookup_pdc_name: send_packet failed.\n"));
1118                                 close(sock);
1119                                 return False;
1120                         }
1121                         GetTimeOfDay(&tval);
1122                         retries--;
1123                 }
1124
1125                 if ((p_ret = receive_dgram_packet(sock,90,mailslot_name))) {
1126                         struct dgram_packet *dgram2 = &p_ret->packet.dgram;
1127                         char *buf;
1128                         char *buf2;
1129
1130                         buf = &dgram2->data[0];
1131                         buf -= 4;
1132
1133                         if (CVAL(buf,smb_com) != SMBtrans) {
1134                                 DEBUG(0,("lookup_pdc_name: datagram type %u != SMBtrans(%u)\n", (unsigned int)
1135                                          CVAL(buf,smb_com), (unsigned int)SMBtrans ));
1136                                 free_packet(p_ret);
1137                                 continue;
1138                         }
1139                         
1140                         len = SVAL(buf,smb_vwv11);
1141                         buf2 = smb_base(buf) + SVAL(buf,smb_vwv12);
1142                         
1143                         if (len <= 0) {
1144                                 DEBUG(0,("lookup_pdc_name: datagram len < 0 (%d)\n", len ));
1145                                 free_packet(p_ret);
1146                                 continue;
1147                         }
1148
1149                         DEBUG(4,("lookup_pdc_name: datagram reply from %s to %s IP %s for %s of type %d len=%d\n",
1150                                  nmb_namestr(&dgram2->source_name),nmb_namestr(&dgram2->dest_name),
1151                                  inet_ntoa(p_ret->ip), smb_buf(buf),SVAL(buf2,0),len));
1152
1153                         if(SVAL(buf2,0) != QUERYFORPDC_R) {
1154                                 DEBUG(0,("lookup_pdc_name: datagram type (%u) != QUERYFORPDC_R(%u)\n",
1155                                          (unsigned int)SVAL(buf,0), (unsigned int)QUERYFORPDC_R ));
1156                                 free_packet(p_ret);
1157                                 continue;
1158                         }
1159
1160                         buf2 += 2;
1161                         /* Note this is safe as it is a bounded strcpy. */
1162                         fstrcpy(ret_name, buf2);
1163                         ret_name[sizeof(fstring)-1] = '\0';
1164                         close(sock);
1165                         free_packet(p_ret);
1166                         return True;
1167                 }
1168         }
1169         
1170         close(sock);
1171         return False;
1172 #endif /* defined(I_HATE_WINDOWS_REPLY_CODE) */
1173 }
1174
1175
1176 /********************************************************
1177  Get the IP address list of the PDC/BDC's of a Domain.
1178 *********************************************************/
1179
1180 BOOL get_dc_list(BOOL pdc_only, const char *group, struct in_addr **ip_list, int *count)
1181 {
1182         int name_type = pdc_only ? 0x1B : 0x1C;
1183
1184         /*
1185          * If it's our domain then
1186          * use the 'password server' parameter.
1187          */
1188
1189         if (strequal(group, lp_workgroup())) {
1190                 char *p;
1191                 char *pserver = lp_passwordserver();
1192                 fstring name;
1193                 int num_adresses = 0;
1194                 struct in_addr *return_iplist = NULL;
1195
1196                 if (! *pserver)
1197                         return internal_resolve_name(group, name_type, ip_list, count);
1198
1199                 p = pserver;
1200                 while (next_token(&p,name,LIST_SEP,sizeof(name))) {
1201                         if (strequal(name, "*"))
1202                                 return internal_resolve_name(group, name_type, ip_list, count);
1203                         num_adresses++;
1204                 }
1205                 if (num_adresses == 0)
1206                         return internal_resolve_name(group, name_type, ip_list, count);
1207
1208                 return_iplist = (struct in_addr *)malloc(num_adresses * sizeof(struct in_addr));
1209                 if(return_iplist == NULL) {
1210                         DEBUG(3,("get_dc_list: malloc fail !\n"));
1211                         return False;
1212                 }
1213                 p = pserver;
1214                 *count = 0;
1215                 while (next_token(&p,name,LIST_SEP,sizeof(name))) {
1216                         struct in_addr name_ip;
1217                         if (resolve_name( name, &name_ip, 0x20) == False)
1218                                 continue;
1219                         return_iplist[(*count)++] = name_ip;
1220                 }
1221                 *ip_list = return_iplist;
1222                 return (*count != 0);
1223         } else
1224                 return internal_resolve_name(group, name_type, ip_list, count);
1225 }
1226
1227 /********************************************************
1228   Get the IP address list of the Local Master Browsers
1229  ********************************************************/ 
1230 BOOL get_lmb_list(struct in_addr **ip_list, int *count)
1231 {
1232     return internal_resolve_name( MSBROWSE, 0x1, ip_list, count);
1233 }