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