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