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