Got "medieval on our ass" about adding the -1 to slprintf.
[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         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( wins_srv_count() < 1 ) {
678                 DEBUG(3,("resolve_wins: WINS server resolution selected and no WINS servers listed.\n"));
679                 return False;
680         }
681
682         wins_ip     = wins_srv_ip();
683         wins_ismyip = ismyip(wins_ip);
684
685         DEBUG(3, ("resolve_wins: WINS server == <%s>\n", inet_ntoa(wins_ip)) );
686         if((wins_ismyip && !global_in_nmbd) || !wins_ismyip) {
687                 sock = open_socket_in(  SOCK_DGRAM, 0, 3,
688                                         interpret_addr(lp_socket_address()),
689                                         True );
690                 if (sock != -1) {
691                         *return_iplist = name_query( sock,      name,
692                                                      name_type, False, 
693                                                      True,      wins_ip,
694                                                      return_count);
695                         if(*return_iplist != NULL) {
696                                 close(sock);
697                                 return True;
698                         }
699                         close(sock);
700                 }
701         }
702
703         return False;
704 }
705
706 /********************************************************
707  Resolve via "lmhosts" method.
708 *********************************************************/
709
710 static BOOL resolve_lmhosts(const char *name, int name_type,
711                          struct in_addr **return_iplist, int *return_count)
712 {
713         /*
714          * "lmhosts" means parse the local lmhosts file.
715          */
716         
717         FILE *fp;
718         pstring lmhost_name;
719         int name_type2;
720         struct in_addr return_ip;
721
722         *return_iplist = NULL;
723         *return_count = 0;
724
725         DEBUG(3,("resolve_lmhosts: Attempting lmhosts lookup for name %s<0x%x>\n", name, name_type));
726
727         fp = startlmhosts( LMHOSTSFILE );
728         if(fp) {
729                 while (getlmhostsent(fp, lmhost_name, &name_type2, &return_ip)) {
730                         if (strequal(name, lmhost_name) && 
731                 ((name_type2 == -1) || (name_type == name_type2))
732                ) {
733                                 endlmhosts(fp);
734                                 *return_iplist = (struct in_addr *)malloc(sizeof(struct in_addr));
735                                 if(*return_iplist == NULL) {
736                                         DEBUG(3,("resolve_lmhosts: malloc fail !\n"));
737                                         return False;
738                                 }
739                                 **return_iplist = return_ip;
740                                 *return_count = 1;
741                                 return True; 
742                         }
743                 }
744                 endlmhosts(fp);
745         }
746         return False;
747 }
748
749
750 /********************************************************
751  Resolve via "hosts" method.
752 *********************************************************/
753
754 static BOOL resolve_hosts(const char *name,
755                          struct in_addr **return_iplist, int *return_count)
756 {
757         /*
758          * "host" means do a localhost, or dns lookup.
759          */
760         struct hostent *hp;
761
762         *return_iplist = NULL;
763         *return_count = 0;
764
765         DEBUG(3,("resolve_hosts: Attempting host lookup for name %s<0x20>\n", name));
766         
767         if (((hp = Get_Hostbyname(name)) != NULL) && (hp->h_addr != NULL)) {
768                 struct in_addr return_ip;
769                 putip((char *)&return_ip,(char *)hp->h_addr);
770                 *return_iplist = (struct in_addr *)malloc(sizeof(struct in_addr));
771                 if(*return_iplist == NULL) {
772                         DEBUG(3,("resolve_hosts: malloc fail !\n"));
773                         return False;
774                 }
775                 **return_iplist = return_ip;
776                 *return_count = 1;
777                 return True;
778         }
779         return False;
780 }
781
782 /********************************************************
783  Internal interface to resolve a name into an IP address.
784  Use this function if the string is either an IP address, DNS
785  or host name or NetBIOS name. This uses the name switch in the
786  smb.conf to determine the order of name resolution.
787 *********************************************************/
788
789 static BOOL internal_resolve_name(const char *name, int name_type,
790                                         struct in_addr **return_iplist, int *return_count)
791 {
792   pstring name_resolve_list;
793   fstring tok;
794   char *ptr;
795   BOOL allones = (strcmp(name,"255.255.255.255") == 0);
796   BOOL allzeros = (strcmp(name,"0.0.0.0") == 0);
797   BOOL is_address = is_ipaddress(name);
798   *return_iplist = NULL;
799   *return_count = 0;
800
801   if (allzeros || allones || is_address) {
802         *return_iplist = (struct in_addr *)malloc(sizeof(struct in_addr));
803         if(*return_iplist == NULL) {
804                 DEBUG(3,("internal_resolve_name: malloc fail !\n"));
805                 return False;
806         }
807         if(is_address) { 
808                 /* if it's in the form of an IP address then get the lib to interpret it */
809                 (*return_iplist)->s_addr = inet_addr(name);
810     } else {
811                 (*return_iplist)->s_addr = allones ? 0xFFFFFFFF : 0;
812                 *return_count = 1;
813         }
814     return True;
815   }
816   
817   pstrcpy(name_resolve_list, lp_name_resolve_order());
818   ptr = name_resolve_list;
819   if (!ptr || !*ptr)
820     ptr = "host";
821
822   while (next_token(&ptr, tok, LIST_SEP, sizeof(tok))) {
823           if((strequal(tok, "host") || strequal(tok, "hosts"))) {
824                   if (name_type == 0x20 && resolve_hosts(name, return_iplist, return_count)) {
825                           return True;
826                   }
827           } else if(strequal( tok, "lmhosts")) {
828                   if (resolve_lmhosts(name, name_type, return_iplist, return_count)) {
829                           return True;
830                   }
831           } else if(strequal( tok, "wins")) {
832                   /* don't resolve 1D via WINS */
833                   if (name_type != 0x1D &&
834                       resolve_wins(name, name_type, return_iplist, return_count)) {
835                           return True;
836                   }
837           } else if(strequal( tok, "bcast")) {
838                   if (name_resolve_bcast(name, name_type, return_iplist, return_count)) {
839                           return True;
840                   }
841           } else {
842                   DEBUG(0,("resolve_name: unknown name switch type %s\n", tok));
843           }
844   }
845
846   if((*return_iplist) != NULL) {
847     free((char *)(*return_iplist));
848     *return_iplist = NULL;
849   }
850   return False;
851 }
852
853 /********************************************************
854  Internal interface to resolve a name into one IP address.
855  Use this function if the string is either an IP address, DNS
856  or host name or NetBIOS name. This uses the name switch in the
857  smb.conf to determine the order of name resolution.
858 *********************************************************/
859
860 BOOL resolve_name(const char *name, struct in_addr *return_ip, int name_type)
861 {
862         struct in_addr *ip_list = NULL;
863         int count = 0;
864
865         if(internal_resolve_name(name, name_type, &ip_list, &count)) {
866                 *return_ip = ip_list[0];
867                 free((char *)ip_list);
868                 return True;
869         }
870         if(ip_list != NULL)
871                 free((char *)ip_list);
872         return False;
873 }
874
875
876 /********************************************************
877  resolve a name of format \\server_name or \\ipaddress
878  into a name.  also, cut the \\ from the front for us.
879 *********************************************************/
880
881 BOOL resolve_srv_name(const char* srv_name, fstring dest_host,
882                                 struct in_addr *ip)
883 {
884         BOOL ret;
885         const char *sv_name = srv_name;
886
887         DEBUG(10,("resolve_srv_name: %s\n", srv_name));
888
889         if (srv_name == NULL || strequal("\\\\.", srv_name))
890         {
891                 extern pstring global_myname;
892                 fstrcpy(dest_host, global_myname);
893                 ip = interpret_addr2("127.0.0.1");
894                 return True;
895         }
896
897         if (strnequal("\\\\", srv_name, 2))
898         {
899                 sv_name = &srv_name[2];
900         }
901
902         fstrcpy(dest_host, sv_name);
903         /* treat the '*' name specially - it is a magic name for the PDC */
904         if (strcmp(dest_host,"*") == 0) {
905                 extern pstring global_myname;
906                 ret = resolve_name(lp_workgroup(), ip, 0x1B);
907                 lookup_pdc_name(global_myname, lp_workgroup(), ip, dest_host);
908         } else {
909                 ret = resolve_name(dest_host, ip, 0x20);
910         }
911         
912         if (is_ipaddress(dest_host))
913         {
914                 fstrcpy(dest_host, "*SMBSERVER");
915         }
916         
917         return ret;
918 }
919
920
921 /********************************************************
922  Find the IP address of the master browser or DMB for a workgroup.
923 *********************************************************/
924
925 BOOL find_master_ip(char *group, struct in_addr *master_ip)
926 {
927         struct in_addr *ip_list = NULL;
928         int count = 0;
929
930         if (internal_resolve_name(group, 0x1D, &ip_list, &count)) {
931                 *master_ip = ip_list[0];
932                 free((char *)ip_list);
933                 return True;
934         }
935         if(internal_resolve_name(group, 0x1B, &ip_list, &count)) {
936                 *master_ip = ip_list[0];
937                 free((char *)ip_list);
938                 return True;
939         }
940
941         if(ip_list != NULL)
942                 free((char *)ip_list);
943         return False;
944 }
945
946 /********************************************************
947  Lookup a PDC name given a Domain name and IP address.
948 *********************************************************/
949
950 BOOL lookup_pdc_name(const char *srcname, const char *domain, struct in_addr *pdc_ip, char *ret_name)
951 {
952 #if !defined(I_HATE_WINDOWS_REPLY_CODE)
953
954   fstring pdc_name;
955   BOOL ret;
956
957   /*
958    * Due to the fact win WinNT *sucks* we must do a node status
959    * query here... JRA.
960    */
961
962   *pdc_name = '\0';
963
964   ret = name_status_find(0x20,*pdc_ip,pdc_name);
965
966   if(ret && *pdc_name) {
967     fstrcpy(ret_name, pdc_name);
968     return True;
969   }
970
971   return False;
972
973 #else /* defined(I_HATE_WINDOWS_REPLY_CODE) */
974
975 JRA - This code is broken with BDC rollover - we need to do a full
976 NT GETDC call, UNICODE, NT domain SID and uncle tom cobbley and all...
977
978         int retries = 3;
979         int retry_time = 2000;
980         struct timeval tval;
981         struct packet_struct p;
982         struct dgram_packet *dgram = &p.packet.dgram;
983         char *ptr,*p2;
984         char tmp[4];
985         int len;
986         struct sockaddr_in sock_name;
987         int sock_len = sizeof(sock_name);
988         const char *mailslot = NET_LOGON_MAILSLOT;
989         char *mailslot_name;
990         char buffer[1024];
991         char *bufp;
992         int dgm_id = generate_trn_id();
993         int sock = open_socket_in(SOCK_DGRAM, 0, 3, interpret_addr(lp_socket_address()), True );
994         
995         if(sock == -1)
996                 return False;
997         
998         /* Find out the transient UDP port we have been allocated. */
999         if(getsockname(sock, (struct sockaddr *)&sock_name, &sock_len)<0) {
1000                 DEBUG(0,("lookup_pdc_name: Failed to get local UDP port. Error was %s\n",
1001                          strerror(errno)));
1002                 close(sock);
1003                 return False;
1004         }
1005
1006         /*
1007          * Create the request data.
1008          */
1009
1010         memset(buffer,'\0',sizeof(buffer));
1011         bufp = buffer;
1012         SSVAL(bufp,0,QUERYFORPDC);
1013         bufp += 2;
1014         fstrcpy(bufp,srcname);
1015         bufp += (strlen(bufp) + 1);
1016         slprintf(bufp, sizeof(fstring)-1, "\\MAILSLOT\\NET\\GETDC%d", dgm_id);
1017         mailslot_name = bufp;
1018         bufp += (strlen(bufp) + 1);
1019         bufp = ALIGN2(bufp, buffer);
1020         bufp += dos_PutUniCode(bufp, srcname, sizeof(buffer) - (bufp - buffer) - 1, True);
1021         SIVAL(bufp,0,1);
1022         SSVAL(bufp,4,0xFFFF); 
1023         SSVAL(bufp,6,0xFFFF); 
1024         bufp += 8;
1025         len = PTR_DIFF(bufp,buffer);
1026
1027         memset((char *)&p,'\0',sizeof(p));
1028
1029         /* DIRECT GROUP or UNIQUE datagram. */
1030         dgram->header.msg_type = 0x10;
1031         dgram->header.flags.node_type = M_NODE;
1032         dgram->header.flags.first = True;
1033         dgram->header.flags.more = False;
1034         dgram->header.dgm_id = dgm_id;
1035         dgram->header.source_ip = *iface_ip(*pdc_ip);
1036         dgram->header.source_port = ntohs(sock_name.sin_port);
1037         dgram->header.dgm_length = 0; /* Let build_dgram() handle this. */
1038         dgram->header.packet_offset = 0;
1039         
1040         make_nmb_name(&dgram->source_name,srcname,0);
1041         make_nmb_name(&dgram->dest_name,domain,0x1C);
1042         
1043         ptr = &dgram->data[0];
1044         
1045         /* Setup the smb part. */
1046         ptr -= 4; /* XXX Ugliness because of handling of tcp SMB length. */
1047         memcpy(tmp,ptr,4);
1048         set_message(ptr,17,17 + len,True);
1049         memcpy(ptr,tmp,4);
1050
1051         CVAL(ptr,smb_com) = SMBtrans;
1052         SSVAL(ptr,smb_vwv1,len);
1053         SSVAL(ptr,smb_vwv11,len);
1054         SSVAL(ptr,smb_vwv12,70 + strlen(mailslot));
1055         SSVAL(ptr,smb_vwv13,3);
1056         SSVAL(ptr,smb_vwv14,1);
1057         SSVAL(ptr,smb_vwv15,1);
1058         SSVAL(ptr,smb_vwv16,2);
1059         p2 = smb_buf(ptr);
1060         pstrcpy(p2,mailslot);
1061         p2 = skip_string(p2,1);
1062         
1063         memcpy(p2,buffer,len);
1064         p2 += len;
1065         
1066         dgram->datasize = PTR_DIFF(p2,ptr+4); /* +4 for tcp length. */
1067         
1068         p.ip = *pdc_ip;
1069         p.port = DGRAM_PORT;
1070         p.fd = sock;
1071         p.timestamp = time(NULL);
1072         p.packet_type = DGRAM_PACKET;
1073         
1074         GetTimeOfDay(&tval);
1075         
1076         if (!send_packet(&p)) {
1077                 DEBUG(0,("lookup_pdc_name: send_packet failed.\n"));
1078                 close(sock);
1079                 return False;
1080         }
1081         
1082         retries--;
1083         
1084         while (1) {
1085                 struct timeval tval2;
1086                 struct packet_struct *p_ret;
1087                 
1088                 GetTimeOfDay(&tval2);
1089                 if (TvalDiff(&tval,&tval2) > retry_time) {
1090                         if (!retries)
1091                                 break;
1092                         if (!send_packet(&p)) {
1093                                 DEBUG(0,("lookup_pdc_name: send_packet failed.\n"));
1094                                 close(sock);
1095                                 return False;
1096                         }
1097                         GetTimeOfDay(&tval);
1098                         retries--;
1099                 }
1100
1101                 if ((p_ret = receive_dgram_packet(sock,90,mailslot_name))) {
1102                         struct dgram_packet *dgram2 = &p_ret->packet.dgram;
1103                         char *buf;
1104                         char *buf2;
1105
1106                         buf = &dgram2->data[0];
1107                         buf -= 4;
1108
1109                         if (CVAL(buf,smb_com) != SMBtrans) {
1110                                 DEBUG(0,("lookup_pdc_name: datagram type %u != SMBtrans(%u)\n", (unsigned int)
1111                                          CVAL(buf,smb_com), (unsigned int)SMBtrans ));
1112                                 free_packet(p_ret);
1113                                 continue;
1114                         }
1115                         
1116                         len = SVAL(buf,smb_vwv11);
1117                         buf2 = smb_base(buf) + SVAL(buf,smb_vwv12);
1118                         
1119                         if (len <= 0) {
1120                                 DEBUG(0,("lookup_pdc_name: datagram len < 0 (%d)\n", len ));
1121                                 free_packet(p_ret);
1122                                 continue;
1123                         }
1124
1125                         DEBUG(4,("lookup_pdc_name: datagram reply from %s to %s IP %s for %s of type %d len=%d\n",
1126                                  nmb_namestr(&dgram2->source_name),nmb_namestr(&dgram2->dest_name),
1127                                  inet_ntoa(p_ret->ip), smb_buf(buf),SVAL(buf2,0),len));
1128
1129                         if(SVAL(buf2,0) != QUERYFORPDC_R) {
1130                                 DEBUG(0,("lookup_pdc_name: datagram type (%u) != QUERYFORPDC_R(%u)\n",
1131                                          (unsigned int)SVAL(buf,0), (unsigned int)QUERYFORPDC_R ));
1132                                 free_packet(p_ret);
1133                                 continue;
1134                         }
1135
1136                         buf2 += 2;
1137                         /* Note this is safe as it is a bounded strcpy. */
1138                         fstrcpy(ret_name, buf2);
1139                         ret_name[sizeof(fstring)-1] = '\0';
1140                         close(sock);
1141                         free_packet(p_ret);
1142                         return True;
1143                 }
1144         }
1145         
1146         close(sock);
1147         return False;
1148 #endif /* defined(I_HATE_WINDOWS_REPLY_CODE) */
1149 }
1150
1151
1152 /********************************************************
1153  Get the IP address list of the PDC/BDC's of a Domain.
1154 *********************************************************/
1155 BOOL get_dc_list(BOOL pdc_only, char *group, struct in_addr **ip_list, int *count)
1156 {
1157         return internal_resolve_name(group, pdc_only ? 0x1B : 0x1C, ip_list, count);
1158 }