Fix up 'net ads join' to delete and rejoin if the account already exists.
[ira/wip.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 /* nmbd.c sets this to True. */
26 BOOL global_in_nmbd = False;
27
28 /****************************************************************************
29 generate a random trn_id
30 ****************************************************************************/
31 static int generate_trn_id(void)
32 {
33         static int trn_id;
34
35         if (trn_id == 0) {
36                 sys_srandom(sys_getpid());
37         }
38
39         trn_id = sys_random();
40
41         return trn_id % (unsigned)0x7FFF;
42 }
43
44
45 /****************************************************************************
46  parse a node status response into an array of structures
47 ****************************************************************************/
48 static struct node_status *parse_node_status(char *p, int *num_names)
49 {
50         struct node_status *ret;
51         int i;
52
53         *num_names = CVAL(p,0);
54
55         if (*num_names == 0) return NULL;
56
57         ret = (struct node_status *)malloc(sizeof(struct node_status)* (*num_names));
58         if (!ret) return NULL;
59
60         p++;
61         for (i=0;i< *num_names;i++) {
62                 StrnCpy(ret[i].name,p,15);
63                 trim_string(ret[i].name,NULL," ");
64                 ret[i].type = CVAL(p,15);
65                 ret[i].flags = p[16];
66                 p += 18;
67         }
68         return ret;
69 }
70
71
72 /****************************************************************************
73 do a NBT node status query on an open socket and return an array of
74 structures holding the returned names or NULL if the query failed
75 **************************************************************************/
76 struct node_status *node_status_query(int fd,struct nmb_name *name,
77                                       struct in_addr to_ip, int *num_names)
78 {
79         BOOL found=False;
80         int retries = 2;
81         int retry_time = 2000;
82         struct timeval tval;
83         struct packet_struct p;
84         struct packet_struct *p2;
85         struct nmb_packet *nmb = &p.packet.nmb;
86         struct node_status *ret;
87
88         ZERO_STRUCT(p);
89
90         nmb->header.name_trn_id = generate_trn_id();
91         nmb->header.opcode = 0;
92         nmb->header.response = False;
93         nmb->header.nm_flags.bcast = False;
94         nmb->header.nm_flags.recursion_available = False;
95         nmb->header.nm_flags.recursion_desired = False;
96         nmb->header.nm_flags.trunc = False;
97         nmb->header.nm_flags.authoritative = False;
98         nmb->header.rcode = 0;
99         nmb->header.qdcount = 1;
100         nmb->header.ancount = 0;
101         nmb->header.nscount = 0;
102         nmb->header.arcount = 0;
103         nmb->question.question_name = *name;
104         nmb->question.question_type = 0x21;
105         nmb->question.question_class = 0x1;
106
107         p.ip = to_ip;
108         p.port = NMB_PORT;
109         p.fd = fd;
110         p.timestamp = time(NULL);
111         p.packet_type = NMB_PACKET;
112         
113         GetTimeOfDay(&tval);
114   
115         if (!send_packet(&p)) 
116                 return NULL;
117
118         retries--;
119
120         while (1) {
121                 struct timeval tval2;
122                 GetTimeOfDay(&tval2);
123                 if (TvalDiff(&tval,&tval2) > retry_time) {
124                         if (!retries)
125                                 break;
126                         if (!found && !send_packet(&p))
127                                 return NULL;
128                         GetTimeOfDay(&tval);
129                         retries--;
130                 }
131
132                 if ((p2=receive_nmb_packet(fd,90,nmb->header.name_trn_id))) {     
133                         struct nmb_packet *nmb2 = &p2->packet.nmb;
134                         debug_nmb_packet(p2);
135                         
136                         if (nmb2->header.opcode != 0 ||
137                             nmb2->header.nm_flags.bcast ||
138                             nmb2->header.rcode ||
139                             !nmb2->header.ancount ||
140                             nmb2->answers->rr_type != 0x21) {
141                                 /* XXXX what do we do with this? could be a
142                                    redirect, but we'll discard it for the
143                                    moment */
144                                 free_packet(p2);
145                                 continue;
146                         }
147
148                         ret = parse_node_status(&nmb2->answers->rdata[0], num_names);
149                         free_packet(p2);
150                         return ret;
151                 }
152         }
153         
154         return NULL;
155 }
156
157
158 /****************************************************************************
159 find the first type XX name in a node status reply - used for finding
160 a servers name given its IP
161 return the matched name in *name
162 **************************************************************************/
163
164 BOOL name_status_find(const char *q_name, int q_type, int type, struct in_addr to_ip, char *name)
165 {
166         struct node_status *status;
167         struct nmb_name nname;
168         int count, i;
169         int sock;
170
171         sock = open_socket_in(SOCK_DGRAM, 0, 3, interpret_addr(lp_socket_address()), True);
172         if (sock == -1)
173                 return False;
174
175         /* W2K PDC's seem not to respond to '*'#0. JRA */
176         make_nmb_name(&nname, q_name, q_type);
177         status = node_status_query(sock, &nname, to_ip, &count);
178         close(sock);
179         if (!status)
180                 return False;
181
182         for (i=0;i<count;i++) {
183                 if (status[i].type == type)
184                         break;
185         }
186         if (i == count)
187                 return False;
188
189         pull_ascii(name, status[i].name, 15, 0, STR_TERMINATE);
190
191         SAFE_FREE(status);
192         return True;
193 }
194
195 /****************************************************************************
196  Do a NetBIOS name registation to try to claim a name ...
197 ***************************************************************************/
198 BOOL name_register(int fd, const char *name, int name_type,
199                    struct in_addr name_ip, int opcode,
200                    BOOL bcast, 
201                    struct in_addr to_ip, int *count)
202 {
203   int retries = 3;
204   struct timeval tval;
205   struct packet_struct p;
206   struct packet_struct *p2;
207   struct nmb_packet *nmb = &p.packet.nmb;
208   struct in_addr register_ip;
209
210   DEBUG(4, ("name_register: %s as %s on %s\n", name, inet_ntoa(name_ip), inet_ntoa(to_ip)));
211
212   register_ip.s_addr = name_ip.s_addr;  /* Fix this ... */
213   
214   memset((char *)&p, '\0', sizeof(p));
215
216   *count = 0;
217
218   nmb->header.name_trn_id = generate_trn_id();
219   nmb->header.opcode = opcode;
220   nmb->header.response = False;
221   nmb->header.nm_flags.bcast = False;
222   nmb->header.nm_flags.recursion_available = False;
223   nmb->header.nm_flags.recursion_desired = True;  /* ? */
224   nmb->header.nm_flags.trunc = False;
225   nmb->header.nm_flags.authoritative = True;
226
227   nmb->header.qdcount = 1;
228   nmb->header.ancount = 0;
229   nmb->header.nscount = 0;
230   nmb->header.arcount = 1;
231
232   make_nmb_name(&nmb->question.question_name, name, name_type);
233
234   nmb->question.question_type = 0x20;
235   nmb->question.question_class = 0x1;
236
237   /* Now, create the additional stuff for a registration request */
238
239   if ((nmb->additional = (struct res_rec *)malloc(sizeof(struct res_rec))) == NULL) {
240
241     DEBUG(0, ("name_register: malloc fail for additional record.\n"));
242     return False;
243
244   }
245
246   memset((char *)nmb->additional, '\0', sizeof(struct res_rec));
247
248   nmb->additional->rr_name  = nmb->question.question_name;
249   nmb->additional->rr_type  = RR_TYPE_NB;
250   nmb->additional->rr_class = RR_CLASS_IN;
251
252   /* See RFC 1002, sections 5.1.1.1, 5.1.1.2 and 5.1.1.3 */
253   if (nmb->header.nm_flags.bcast)
254     nmb->additional->ttl = PERMANENT_TTL;
255   else
256     nmb->additional->ttl = lp_max_ttl();
257
258   nmb->additional->rdlength = 6;
259
260   nmb->additional->rdata[0] = NB_MFLAG & 0xFF;
261
262   /* Set the address for the name we are registering. */
263   putip(&nmb->additional->rdata[2], &register_ip);
264
265   p.ip = to_ip;
266   p.port = NMB_PORT;
267   p.fd = fd;
268   p.timestamp = time(NULL);
269   p.packet_type = NMB_PACKET;
270
271   GetTimeOfDay(&tval);
272
273   if (!send_packet(&p))
274     return False;
275
276   retries--;
277
278   if ((p2 = receive_nmb_packet(fd, 10, nmb->header.name_trn_id))) {
279     debug_nmb_packet(p2);
280     SAFE_FREE(p2);  /* No memory leaks ... */
281   }
282
283   return True;
284 }
285
286 /****************************************************************************
287  Do a netbios name query to find someones IP.
288  Returns an array of IP addresses or NULL if none.
289  *count will be set to the number of addresses returned.
290 ****************************************************************************/
291 struct in_addr *name_query(int fd,const char *name,int name_type, 
292                            BOOL bcast,BOOL recurse,
293                            struct in_addr to_ip, int *count)
294 {
295   BOOL found=False;
296   int i, retries = 3;
297   int retry_time = bcast?250:2000;
298   struct timeval tval;
299   struct packet_struct p;
300   struct packet_struct *p2;
301   struct nmb_packet *nmb = &p.packet.nmb;
302   struct in_addr *ip_list = NULL;
303
304   memset((char *)&p,'\0',sizeof(p));
305   (*count) = 0;
306
307   nmb->header.name_trn_id = generate_trn_id();
308   nmb->header.opcode = 0;
309   nmb->header.response = False;
310   nmb->header.nm_flags.bcast = bcast;
311   nmb->header.nm_flags.recursion_available = False;
312   nmb->header.nm_flags.recursion_desired = recurse;
313   nmb->header.nm_flags.trunc = False;
314   nmb->header.nm_flags.authoritative = False;
315   nmb->header.rcode = 0;
316   nmb->header.qdcount = 1;
317   nmb->header.ancount = 0;
318   nmb->header.nscount = 0;
319   nmb->header.arcount = 0;
320
321   make_nmb_name(&nmb->question.question_name,name,name_type);
322
323   nmb->question.question_type = 0x20;
324   nmb->question.question_class = 0x1;
325
326   p.ip = to_ip;
327   p.port = NMB_PORT;
328   p.fd = fd;
329   p.timestamp = time(NULL);
330   p.packet_type = NMB_PACKET;
331
332   GetTimeOfDay(&tval);
333
334   if (!send_packet(&p)) 
335     return NULL;
336
337   retries--;
338
339         while (1) {
340           struct timeval tval2;
341       struct in_addr *tmp_ip_list;
342
343           GetTimeOfDay(&tval2);
344           if (TvalDiff(&tval,&tval2) > retry_time) {
345                   if (!retries)
346                           break;
347                   if (!found && !send_packet(&p))
348                           return NULL;
349                   GetTimeOfDay(&tval);
350                   retries--;
351           }
352           
353           if ((p2=receive_nmb_packet(fd,90,nmb->header.name_trn_id))) {     
354                   struct nmb_packet *nmb2 = &p2->packet.nmb;
355                   debug_nmb_packet(p2);
356
357                   /* If we get a Negative Name Query Response from a WINS
358                    * server, we should report it and give up.
359                    */
360                   if( 0 == nmb2->header.opcode          /* A query response   */
361                       && !(bcast)                       /* from a WINS server */
362                       && nmb2->header.rcode             /* Error returned     */
363                     ) {
364
365                     if( DEBUGLVL( 3 ) ) {
366                       /* Only executed if DEBUGLEVEL >= 3 */
367                                         dbgtext( "Negative name query response, rcode 0x%02x: ", nmb2->header.rcode );
368                       switch( nmb2->header.rcode ) {
369                         case 0x01:
370                           dbgtext( "Request was invalidly formatted.\n" );
371                           break;
372                         case 0x02:
373                           dbgtext( "Problem with NBNS, cannot process name.\n");
374                           break;
375                         case 0x03:
376                           dbgtext( "The name requested does not exist.\n" );
377                           break;
378                         case 0x04:
379                           dbgtext( "Unsupported request error.\n" );
380                           break;
381                         case 0x05:
382                           dbgtext( "Query refused error.\n" );
383                           break;
384                         default:
385                           dbgtext( "Unrecognized error code.\n" );
386                           break;
387                       }
388                     }
389                     free_packet(p2);
390                     return( NULL );
391                   }
392
393                   if (nmb2->header.opcode != 0 ||
394                       nmb2->header.nm_flags.bcast ||
395                       nmb2->header.rcode ||
396                       !nmb2->header.ancount) {
397                           /* 
398                            * XXXX what do we do with this? Could be a
399                            * redirect, but we'll discard it for the
400                                  * moment.
401                                  */
402                           free_packet(p2);
403                           continue;
404                   }
405
406           tmp_ip_list = (struct in_addr *)Realloc( ip_list, sizeof( ip_list[0] )
407                                                 * ( (*count) + nmb2->answers->rdlength/6 ) );
408  
409           if (!tmp_ip_list) {
410               DEBUG(0,("name_query: Realloc failed.\n"));
411               SAFE_FREE(ip_list);
412           }
413  
414           ip_list = tmp_ip_list;
415
416                   if (ip_list) {
417                                 DEBUG(2,("Got a positive name query response from %s ( ", inet_ntoa(p2->ip)));
418                           for (i=0;i<nmb2->answers->rdlength/6;i++) {
419                                   putip((char *)&ip_list[(*count)],&nmb2->answers->rdata[2+i*6]);
420                                   DEBUGADD(2,("%s ",inet_ntoa(ip_list[(*count)])));
421                                   (*count)++;
422                           }
423                           DEBUGADD(2,(")\n"));
424                   }
425
426                   found=True;
427                   retries=0;
428                   free_packet(p2);
429                   /*
430                    * If we're doing a unicast lookup we only
431                    * expect one reply. Don't wait the full 2
432                    * seconds if we got one. JRA.
433                    */
434                   if(!bcast && found)
435                           break;
436           }
437   }
438
439   /* Reach here if we've timed out waiting for replies.. */
440         if( !bcast && !found ) {
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 XFILE *startlmhosts(char *fname)
453 {
454         XFILE *fp = x_fopen(fname,O_RDONLY, 0);
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( XFILE *fp, pstring name, int *name_type, struct in_addr *ipaddr)
468 {
469   pstring line;
470
471   while(!x_feof(fp) && !x_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(XFILE *fp)
553 {
554         x_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         XFILE *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(dyn_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   BOOL result = False;
826   struct in_addr *nodupes_iplist;
827   int i;
828
829   *return_iplist = NULL;
830   *return_count = 0;
831
832   DEBUG(10, ("internal_resolve_name: looking up %s#%x\n", name, name_type));
833
834   if (allzeros || allones || is_address) {
835         *return_iplist = (struct in_addr *)malloc(sizeof(struct in_addr));
836         if(*return_iplist == NULL) {
837                 DEBUG(3,("internal_resolve_name: malloc fail !\n"));
838                 return False;
839         }
840         if(is_address) { 
841                 /* if it's in the form of an IP address then get the lib to interpret it */
842                 (*return_iplist)->s_addr = inet_addr(name);
843     } else {
844                 (*return_iplist)->s_addr = allones ? 0xFFFFFFFF : 0;
845                 *return_count = 1;
846         }
847     return True;
848   }
849   
850   pstrcpy(name_resolve_list, lp_name_resolve_order());
851   ptr = name_resolve_list;
852   if (!ptr || !*ptr)
853     ptr = "host";
854
855   while (next_token(&ptr, tok, LIST_SEP, sizeof(tok))) {
856           if((strequal(tok, "host") || strequal(tok, "hosts"))) {
857                   if (name_type == 0x20 && resolve_hosts(name, return_iplist, return_count)) {
858                     result = True;
859                     goto done;
860                   }
861           } else if(strequal( tok, "lmhosts")) {
862                   if (resolve_lmhosts(name, name_type, return_iplist, return_count)) {
863                     result = True;
864                     goto done;
865                   }
866           } else if(strequal( tok, "wins")) {
867                   /* don't resolve 1D via WINS */
868                   if (name_type != 0x1D &&
869                       resolve_wins(name, name_type, return_iplist, return_count)) {
870                     result = True;
871                     goto done;
872                   }
873           } else if(strequal( tok, "bcast")) {
874                   if (name_resolve_bcast(name, name_type, return_iplist, return_count)) {
875                     result = True;
876                     goto done;
877                   }
878           } else {
879                   DEBUG(0,("resolve_name: unknown name switch type %s\n", tok));
880           }
881   }
882
883   /* All of the resolve_* functions above have returned false. */
884
885   SAFE_FREE(*return_iplist);
886   *return_count = 0;
887
888   return False;
889
890  done:
891
892   /* Remove duplicate entries.  Some queries, notably #1c (domain
893      controllers) return the PDC in iplist[0] and then all domain
894      controllers including the PDC in iplist[1..n].  Iterating over
895      the iplist when the PDC is down will cause two sets of timeouts. */
896
897   if ((nodupes_iplist = (struct in_addr *)
898        malloc(sizeof(struct in_addr) * (*return_count)))) {
899           int nodupes_count = 0;
900
901           /* Iterate over return_iplist looking for duplicates */
902
903           for (i = 0; i < *return_count; i++) {
904                   BOOL is_dupe = False;
905                   int j;
906
907                   for (j = i + 1; j < *return_count; j++) {
908                           if (ip_equal((*return_iplist)[i], 
909                                        (*return_iplist)[j])) {
910                                   is_dupe = True;
911                                   break;
912                           }
913                   }
914
915                   if (!is_dupe) {
916
917                           /* This one not a duplicate */
918
919                           nodupes_iplist[nodupes_count] = (*return_iplist)[i];
920                           nodupes_count++;
921                   }
922           }
923           
924           /* Switcheroo with original list */
925           
926           free(*return_iplist);
927
928           *return_iplist = nodupes_iplist;
929           *return_count = nodupes_count;
930   }
931
932   /* Display some debugging info */
933
934   DEBUG(10, ("internal_resolve_name: returning %d addresses: ", 
935              *return_count));
936
937   for (i = 0; i < *return_count; i++)
938           DEBUGADD(10, ("%s ", inet_ntoa((*return_iplist)[i])));
939
940   DEBUG(10, ("\n"));
941
942   return result;
943 }
944
945 /********************************************************
946  Internal interface to resolve a name into one IP address.
947  Use this function if the string is either an IP address, DNS
948  or host name or NetBIOS name. This uses the name switch in the
949  smb.conf to determine the order of name resolution.
950 *********************************************************/
951
952 BOOL resolve_name(const char *name, struct in_addr *return_ip, int name_type)
953 {
954         struct in_addr *ip_list = NULL;
955         int count = 0;
956
957         if (internal_resolve_name(name, name_type, &ip_list, &count)) {
958                 int i;
959                 /* only return valid addresses for TCP connections */
960                 for (i=0; i<count; i++) {
961                         char *ip_str = inet_ntoa(ip_list[i]);
962                         if (ip_str &&
963                             strcmp(ip_str, "255.255.255.255") != 0 &&
964                             strcmp(ip_str, "0.0.0.0") != 0) {
965                                 *return_ip = ip_list[i];
966                                 SAFE_FREE(ip_list);
967                                 return True;
968                         }
969                 }
970         }
971         SAFE_FREE(ip_list);
972         return False;
973 }
974
975
976 /********************************************************
977  resolve a name of format \\server_name or \\ipaddress
978  into a name.  also, cut the \\ from the front for us.
979 *********************************************************/
980
981 BOOL resolve_srv_name(const char* srv_name, fstring dest_host,
982                                 struct in_addr *ip)
983 {
984         BOOL ret;
985         const char *sv_name = srv_name;
986
987         DEBUG(10,("resolve_srv_name: %s\n", srv_name));
988
989         if (srv_name == NULL || strequal("\\\\.", srv_name))
990         {
991                 extern pstring global_myname;
992                 fstrcpy(dest_host, global_myname);
993                 ip = interpret_addr2("127.0.0.1");
994                 return True;
995         }
996
997         if (strnequal("\\\\", srv_name, 2))
998         {
999                 sv_name = &srv_name[2];
1000         }
1001
1002         fstrcpy(dest_host, sv_name);
1003         /* treat the '*' name specially - it is a magic name for the PDC */
1004         if (strcmp(dest_host,"*") == 0) {
1005                 extern pstring global_myname;
1006                 ret = resolve_name(lp_workgroup(), ip, 0x1B);
1007                 lookup_dc_name(global_myname, lp_workgroup(), ip, dest_host);
1008         } else {
1009                 ret = resolve_name(dest_host, ip, 0x20);
1010         }
1011         
1012         if (is_ipaddress(dest_host))
1013         {
1014                 fstrcpy(dest_host, "*SMBSERVER");
1015         }
1016         
1017         return ret;
1018 }
1019
1020
1021 /********************************************************
1022  Find the IP address of the master browser or DMB for a workgroup.
1023 *********************************************************/
1024
1025 BOOL find_master_ip(char *group, struct in_addr *master_ip)
1026 {
1027         struct in_addr *ip_list = NULL;
1028         int count = 0;
1029
1030         if (internal_resolve_name(group, 0x1D, &ip_list, &count)) {
1031                 *master_ip = ip_list[0];
1032                 SAFE_FREE(ip_list);
1033                 return True;
1034         }
1035         if(internal_resolve_name(group, 0x1B, &ip_list, &count)) {
1036                 *master_ip = ip_list[0];
1037                 SAFE_FREE(ip_list);
1038                 return True;
1039         }
1040
1041         SAFE_FREE(ip_list);
1042         return False;
1043 }
1044
1045 /********************************************************
1046  Lookup a DC name given a Domain name and IP address.
1047 *********************************************************/
1048
1049 BOOL lookup_dc_name(const char *srcname, const char *domain, 
1050                     struct in_addr *dc_ip, char *ret_name)
1051 {
1052 #if !defined(I_HATE_WINDOWS_REPLY_CODE)
1053         
1054         fstring dc_name;
1055         BOOL ret;
1056         
1057         /*
1058          * Due to the fact win WinNT *sucks* we must do a node status
1059          * query here... JRA.
1060          */
1061         
1062         *dc_name = '\0';
1063         
1064         ret = name_status_find(domain, 0x1c, 0x20, *dc_ip, dc_name);
1065
1066         if(ret && *dc_name) {
1067                 fstrcpy(ret_name, dc_name);
1068                 return True;
1069         }
1070         
1071         return False;
1072
1073 #else /* defined(I_HATE_WINDOWS_REPLY_CODE) */
1074
1075 JRA - This code is broken with BDC rollover - we need to do a full
1076 NT GETDC call, UNICODE, NT domain SID and uncle tom cobbley and all...
1077
1078         int retries = 3;
1079         int retry_time = 2000;
1080         struct timeval tval;
1081         struct packet_struct p;
1082         struct dgram_packet *dgram = &p.packet.dgram;
1083         char *ptr,*p2;
1084         char tmp[4];
1085         int len;
1086         struct sockaddr_in sock_name;
1087         int sock_len = sizeof(sock_name);
1088         const char *mailslot = NET_LOGON_MAILSLOT;
1089         char *mailslot_name;
1090         char buffer[1024];
1091         char *bufp;
1092         int dgm_id = generate_trn_id();
1093         int sock = open_socket_in(SOCK_DGRAM, 0, 3, interpret_addr(lp_socket_address()), True );
1094         
1095         if(sock == -1)
1096                 return False;
1097         
1098         /* Find out the transient UDP port we have been allocated. */
1099         if(getsockname(sock, (struct sockaddr *)&sock_name, &sock_len)<0) {
1100                 DEBUG(0,("lookup_pdc_name: Failed to get local UDP port. Error was %s\n",
1101                          strerror(errno)));
1102                 close(sock);
1103                 return False;
1104         }
1105
1106         /*
1107          * Create the request data.
1108          */
1109
1110         memset(buffer,'\0',sizeof(buffer));
1111         bufp = buffer;
1112         SSVAL(bufp,0,QUERYFORPDC);
1113         bufp += 2;
1114         fstrcpy(bufp,srcname);
1115         bufp += (strlen(bufp) + 1);
1116         slprintf(bufp, sizeof(fstring)-1, "\\MAILSLOT\\NET\\GETDC%d", dgm_id);
1117         mailslot_name = bufp;
1118         bufp += (strlen(bufp) + 1);
1119         bufp = ALIGN2(bufp, buffer);
1120         bufp += push_ucs2(NULL, bufp, srcname, sizeof(buffer) - (bufp - buffer), STR_TERMINATE);        
1121         
1122         SIVAL(bufp,0,1);
1123         SSVAL(bufp,4,0xFFFF); 
1124         SSVAL(bufp,6,0xFFFF); 
1125         bufp += 8;
1126         len = PTR_DIFF(bufp,buffer);
1127
1128         memset((char *)&p,'\0',sizeof(p));
1129
1130         /* DIRECT GROUP or UNIQUE datagram. */
1131         dgram->header.msg_type = 0x10;
1132         dgram->header.flags.node_type = M_NODE;
1133         dgram->header.flags.first = True;
1134         dgram->header.flags.more = False;
1135         dgram->header.dgm_id = dgm_id;
1136         dgram->header.source_ip = *iface_ip(*pdc_ip);
1137         dgram->header.source_port = ntohs(sock_name.sin_port);
1138         dgram->header.dgm_length = 0; /* Let build_dgram() handle this. */
1139         dgram->header.packet_offset = 0;
1140         
1141         make_nmb_name(&dgram->source_name,srcname,0);
1142         make_nmb_name(&dgram->dest_name,domain,0x1C);
1143         
1144         ptr = &dgram->data[0];
1145         
1146         /* Setup the smb part. */
1147         ptr -= 4; /* XXX Ugliness because of handling of tcp SMB length. */
1148         memcpy(tmp,ptr,4);
1149         set_message(ptr,17,17 + len,True);
1150         memcpy(ptr,tmp,4);
1151
1152         CVAL(ptr,smb_com) = SMBtrans;
1153         SSVAL(ptr,smb_vwv1,len);
1154         SSVAL(ptr,smb_vwv11,len);
1155         SSVAL(ptr,smb_vwv12,70 + strlen(mailslot));
1156         SSVAL(ptr,smb_vwv13,3);
1157         SSVAL(ptr,smb_vwv14,1);
1158         SSVAL(ptr,smb_vwv15,1);
1159         SSVAL(ptr,smb_vwv16,2);
1160         p2 = smb_buf(ptr);
1161         pstrcpy(p2,mailslot);
1162         p2 = skip_string(p2,1);
1163         
1164         memcpy(p2,buffer,len);
1165         p2 += len;
1166         
1167         dgram->datasize = PTR_DIFF(p2,ptr+4); /* +4 for tcp length. */
1168         
1169         p.ip = *pdc_ip;
1170         p.port = DGRAM_PORT;
1171         p.fd = sock;
1172         p.timestamp = time(NULL);
1173         p.packet_type = DGRAM_PACKET;
1174         
1175         GetTimeOfDay(&tval);
1176         
1177         if (!send_packet(&p)) {
1178                 DEBUG(0,("lookup_pdc_name: send_packet failed.\n"));
1179                 close(sock);
1180                 return False;
1181         }
1182         
1183         retries--;
1184         
1185         while (1) {
1186                 struct timeval tval2;
1187                 struct packet_struct *p_ret;
1188                 
1189                 GetTimeOfDay(&tval2);
1190                 if (TvalDiff(&tval,&tval2) > retry_time) {
1191                         if (!retries)
1192                                 break;
1193                         if (!send_packet(&p)) {
1194                                 DEBUG(0,("lookup_pdc_name: send_packet failed.\n"));
1195                                 close(sock);
1196                                 return False;
1197                         }
1198                         GetTimeOfDay(&tval);
1199                         retries--;
1200                 }
1201
1202                 if ((p_ret = receive_dgram_packet(sock,90,mailslot_name))) {
1203                         struct dgram_packet *dgram2 = &p_ret->packet.dgram;
1204                         char *buf;
1205                         char *buf2;
1206
1207                         buf = &dgram2->data[0];
1208                         buf -= 4;
1209
1210                         if (CVAL(buf,smb_com) != SMBtrans) {
1211                                 DEBUG(0,("lookup_pdc_name: datagram type %u != SMBtrans(%u)\n", (unsigned int)
1212                                          CVAL(buf,smb_com), (unsigned int)SMBtrans ));
1213                                 free_packet(p_ret);
1214                                 continue;
1215                         }
1216                         
1217                         len = SVAL(buf,smb_vwv11);
1218                         buf2 = smb_base(buf) + SVAL(buf,smb_vwv12);
1219                         
1220                         if (len <= 0) {
1221                                 DEBUG(0,("lookup_pdc_name: datagram len < 0 (%d)\n", len ));
1222                                 free_packet(p_ret);
1223                                 continue;
1224                         }
1225
1226                         DEBUG(4,("lookup_pdc_name: datagram reply from %s to %s IP %s for %s of type %d len=%d\n",
1227                                  nmb_namestr(&dgram2->source_name),nmb_namestr(&dgram2->dest_name),
1228                                  inet_ntoa(p_ret->ip), smb_buf(buf),SVAL(buf2,0),len));
1229
1230                         if(SVAL(buf2,0) != QUERYFORPDC_R) {
1231                                 DEBUG(0,("lookup_pdc_name: datagram type (%u) != QUERYFORPDC_R(%u)\n",
1232                                          (unsigned int)SVAL(buf,0), (unsigned int)QUERYFORPDC_R ));
1233                                 free_packet(p_ret);
1234                                 continue;
1235                         }
1236
1237                         buf2 += 2;
1238                         /* Note this is safe as it is a bounded strcpy. */
1239                         fstrcpy(ret_name, buf2);
1240                         ret_name[sizeof(fstring)-1] = '\0';
1241                         close(sock);
1242                         free_packet(p_ret);
1243                         return True;
1244                 }
1245         }
1246         
1247         close(sock);
1248         return False;
1249 #endif /* defined(I_HATE_WINDOWS_REPLY_CODE) */
1250 }
1251
1252
1253 /********************************************************
1254  Get the IP address list of the PDC/BDC's of a Domain.
1255 *********************************************************/
1256
1257 BOOL get_dc_list(BOOL pdc_only, const char *group, struct in_addr **ip_list, int *count)
1258 {
1259         int name_type = pdc_only ? 0x1B : 0x1C;
1260
1261         /*
1262          * If it's our domain then
1263          * use the 'password server' parameter.
1264          */
1265
1266         if (strequal(group, lp_workgroup())) {
1267                 char *p;
1268                 char *pserver = lp_passwordserver();
1269                 fstring name;
1270                 int num_adresses = 0;
1271                 struct in_addr *return_iplist = NULL;
1272
1273                 if (! *pserver)
1274                         return internal_resolve_name(group, name_type, ip_list, count);
1275
1276                 p = pserver;
1277                 while (next_token(&p,name,LIST_SEP,sizeof(name))) {
1278                         if (strequal(name, "*"))
1279                                 return internal_resolve_name(group, name_type, ip_list, count);
1280                         num_adresses++;
1281                 }
1282                 if (num_adresses == 0)
1283                         return internal_resolve_name(group, name_type, ip_list, count);
1284
1285                 return_iplist = (struct in_addr *)malloc(num_adresses * sizeof(struct in_addr));
1286                 if(return_iplist == NULL) {
1287                         DEBUG(3,("get_dc_list: malloc fail !\n"));
1288                         return False;
1289                 }
1290                 p = pserver;
1291                 *count = 0;
1292                 while (next_token(&p,name,LIST_SEP,sizeof(name))) {
1293                         struct in_addr name_ip;
1294                         if (resolve_name( name, &name_ip, 0x20) == False)
1295                                 continue;
1296                         return_iplist[(*count)++] = name_ip;
1297                 }
1298                 *ip_list = return_iplist;
1299                 return (*count != 0);
1300         } else
1301                 return internal_resolve_name(group, name_type, ip_list, count);
1302 }
1303
1304 /********************************************************
1305   Get the IP address list of the Local Master Browsers
1306  ********************************************************/ 
1307 BOOL get_lmb_list(struct in_addr **ip_list, int *count)
1308 {
1309     return internal_resolve_name( MSBROWSE, 0x1, ip_list, count);
1310 }