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