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