0237a9752f8fbc86a637eb875186e805b0f0f918
[tprouty/samba.git] / source / 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  Interpret a node status response.
49 ****************************************************************************/
50
51 static void _interpret_node_status(char *p, char *master,char *rname)
52 {
53   int numnames = CVAL(p,0);
54   DEBUG(1,("received %d names\n",numnames));
55
56   if (rname) *rname = 0;
57   if (master) *master = 0;
58
59   p += 1;
60   while (numnames--) {
61     char qname[17];
62     int type;
63     fstring flags;
64     int i;
65     *flags = 0;
66     StrnCpy(qname,p,15);
67     type = CVAL(p,15);
68     p += 16;
69
70     fstrcat(flags, (p[0] & 0x80) ? "<GROUP> " : "        ");
71     if ((p[0] & 0x60) == 0x00) fstrcat(flags,"B ");
72     if ((p[0] & 0x60) == 0x20) fstrcat(flags,"P ");
73     if ((p[0] & 0x60) == 0x40) fstrcat(flags,"M ");
74     if ((p[0] & 0x60) == 0x60) fstrcat(flags,"H ");
75     if (p[0] & 0x10) fstrcat(flags,"<DEREGISTERING> ");
76     if (p[0] & 0x08) fstrcat(flags,"<CONFLICT> ");
77     if (p[0] & 0x04) fstrcat(flags,"<ACTIVE> ");
78     if (p[0] & 0x02) fstrcat(flags,"<PERMANENT> ");
79
80     if (master && !*master && type == 0x1d) {
81       StrnCpy(master,qname,15);
82       trim_string(master,NULL," ");
83     }
84
85     if (rname && !*rname && type == 0x20 && !(p[0]&0x80)) {
86       StrnCpy(rname,qname,15);
87       trim_string(rname,NULL," ");
88     }
89       
90     for (i = strlen( qname) ; --i >= 0 ; ) {
91       if (!isprint((int)qname[i])) qname[i] = '.';
92     }
93     DEBUG(1,("\t%-15s <%02x> - %s\n",qname,type,flags));
94     p+=2;
95   }
96
97   DEBUG(1,("num_good_sends=%d num_good_receives=%d\n",
98                IVAL(p,20),IVAL(p,24)));
99 }
100
101 /****************************************************************************
102  Internal function handling a netbios name status query on a host.
103 **************************************************************************/
104 static BOOL internal_name_status(int fd,char *name,int name_type,BOOL recurse,
105                                  struct in_addr to_ip,char *master,
106                                  char *rname, BOOL verbose,
107                                  void (*fn_interpret_node_status)(char *, char *,char *))
108 {
109   BOOL found=False;
110   int retries = 2;
111   int retry_time = 5000;
112   struct timeval tval;
113   struct packet_struct p;
114   struct packet_struct *p2;
115   struct nmb_packet *nmb = &p.packet.nmb;
116
117   memset((char *)&p,'\0',sizeof(p));
118
119   nmb->header.name_trn_id = generate_trn_id();
120   nmb->header.opcode = 0;
121   nmb->header.response = False;
122   nmb->header.nm_flags.bcast = False;
123   nmb->header.nm_flags.recursion_available = False;
124   nmb->header.nm_flags.recursion_desired = False;
125   nmb->header.nm_flags.trunc = False;
126   nmb->header.nm_flags.authoritative = False;
127   nmb->header.rcode = 0;
128   nmb->header.qdcount = 1;
129   nmb->header.ancount = 0;
130   nmb->header.nscount = 0;
131   nmb->header.arcount = 0;
132
133   make_nmb_name(&nmb->question.question_name,name,name_type);
134
135   nmb->question.question_type = 0x21;
136   nmb->question.question_class = 0x1;
137
138   p.ip = to_ip;
139   p.port = NMB_PORT;
140   p.fd = fd;
141   p.timestamp = time(NULL);
142   p.packet_type = NMB_PACKET;
143
144   GetTimeOfDay(&tval);
145
146   if (!send_packet(&p)) 
147     return(False);
148
149   retries--;
150
151   while (1) {
152           struct timeval tval2;
153           GetTimeOfDay(&tval2);
154           if (TvalDiff(&tval,&tval2) > retry_time) {
155                   if (!retries)
156                           break;
157                   if (!found && !send_packet(&p))
158                           return False;
159                   GetTimeOfDay(&tval);
160                   retries--;
161           }
162
163           if ((p2=receive_nmb_packet(fd,90,nmb->header.name_trn_id))) {     
164                   struct nmb_packet *nmb2 = &p2->packet.nmb;
165                   debug_nmb_packet(p2);
166
167                   if (nmb2->header.opcode != 0 ||
168                       nmb2->header.nm_flags.bcast ||
169                       nmb2->header.rcode ||
170                       !nmb2->header.ancount ||
171                       nmb2->answers->rr_type != 0x21) {
172                           /* XXXX what do we do with this? could be a
173                              redirect, but we'll discard it for the
174                              moment */
175                           free_packet(p2);
176                           continue;
177                   }
178
179                   if(fn_interpret_node_status)
180                           (*fn_interpret_node_status)(&nmb2->answers->rdata[0],master,rname);
181                   free_packet(p2);
182                   return(True);
183           }
184   }
185
186   if(verbose)
187           DEBUG(0,("No status response (this is not unusual)\n"));
188
189   return(False);
190 }
191
192 /****************************************************************************
193  Do a netbios name status query on a host.
194  The "master" parameter is a hack used for finding workgroups.
195 **************************************************************************/
196 BOOL name_status(int fd,char *name,int name_type,BOOL recurse,
197                  struct in_addr to_ip,char *master,char *rname)
198 {
199         return internal_name_status(fd,name,name_type,recurse,
200                                     to_ip,master,rname,True,
201                                     _interpret_node_status);
202 }
203
204 /****************************************************************************
205  Do a netbios name query to find someones IP.
206  Returns an array of IP addresses or NULL if none.
207  *count will be set to the number of addresses returned.
208 ****************************************************************************/
209
210 struct in_addr *name_query(int fd,const char *name,int name_type, 
211                            BOOL bcast,BOOL recurse,
212                            struct in_addr to_ip, int *count)
213 {
214   BOOL found=False;
215   int i, retries = 3;
216   int retry_time = bcast?250:2000;
217   struct timeval tval;
218   struct packet_struct p;
219   struct packet_struct *p2;
220   struct nmb_packet *nmb = &p.packet.nmb;
221   struct in_addr *ip_list = NULL;
222
223   memset((char *)&p,'\0',sizeof(p));
224   (*count) = 0;
225
226   nmb->header.name_trn_id = generate_trn_id();
227   nmb->header.opcode = 0;
228   nmb->header.response = False;
229   nmb->header.nm_flags.bcast = bcast;
230   nmb->header.nm_flags.recursion_available = False;
231   nmb->header.nm_flags.recursion_desired = recurse;
232   nmb->header.nm_flags.trunc = False;
233   nmb->header.nm_flags.authoritative = False;
234   nmb->header.rcode = 0;
235   nmb->header.qdcount = 1;
236   nmb->header.ancount = 0;
237   nmb->header.nscount = 0;
238   nmb->header.arcount = 0;
239
240   make_nmb_name(&nmb->question.question_name,name,name_type);
241
242   nmb->question.question_type = 0x20;
243   nmb->question.question_class = 0x1;
244
245   p.ip = to_ip;
246   p.port = NMB_PORT;
247   p.fd = fd;
248   p.timestamp = time(NULL);
249   p.packet_type = NMB_PACKET;
250
251   GetTimeOfDay(&tval);
252
253   if (!send_packet(&p)) 
254     return NULL;
255
256   retries--;
257
258   while (1)
259   {
260           struct timeval tval2;
261           GetTimeOfDay(&tval2);
262           if (TvalDiff(&tval,&tval2) > retry_time) {
263                   if (!retries)
264                           break;
265                   if (!found && !send_packet(&p))
266                           return NULL;
267                   GetTimeOfDay(&tval);
268                   retries--;
269           }
270           
271           if ((p2=receive_nmb_packet(fd,90,nmb->header.name_trn_id))) {     
272                   struct nmb_packet *nmb2 = &p2->packet.nmb;
273                   debug_nmb_packet(p2);
274
275                   /* If we get a Negative Name Query Response from a WINS
276                    * server, we should report it and give up.
277                    */
278                   if( 0 == nmb2->header.opcode          /* A query response   */
279                       && !(bcast)                       /* from a WINS server */
280                       && nmb2->header.rcode             /* Error returned     */
281                     ) {
282
283                     if( DEBUGLVL( 3 ) ) {
284                       /* Only executed if DEBUGLEVEL >= 3 */
285                       dbgtext( "Negative name query response, rcode 0x%02x: ",
286                                 nmb2->header.rcode );
287                       switch( nmb2->header.rcode ) {
288                         case 0x01:
289                           dbgtext( "Request was invalidly formatted.\n" );
290                           break;
291                         case 0x02:
292                           dbgtext( "Problem with NBNS, cannot process name.\n");
293                           break;
294                         case 0x03:
295                           dbgtext( "The name requested does not exist.\n" );
296                           break;
297                         case 0x04:
298                           dbgtext( "Unsupported request error.\n" );
299                           break;
300                         case 0x05:
301                           dbgtext( "Refused error.\n" );
302                           break;
303                         default:
304                           dbgtext( "Unrecognized error code.\n" );
305                           break;
306                       }
307                     }
308                     free_packet(p2);
309                     return( NULL );
310                   }
311
312                   if (nmb2->header.opcode != 0 ||
313                       nmb2->header.nm_flags.bcast ||
314                       nmb2->header.rcode ||
315                       !nmb2->header.ancount) {
316                           /* 
317                            * XXXX what do we do with this? Could be a
318                            * redirect, but we'll discard it for the
319                            * moment.  */
320                           free_packet(p2);
321                           continue;
322                   }
323
324                   ip_list = (struct in_addr *)Realloc( ip_list,
325                                 sizeof( ip_list[0] )
326                                 * ( (*count) + nmb2->answers->rdlength/6 ) );
327                   if (ip_list) {
328                           DEBUG(2,("Got a positive name query response from %s ( ",
329                                    inet_ntoa(p2->ip)));
330                           for (i=0;i<nmb2->answers->rdlength/6;i++) {
331                                   putip((char *)&ip_list[(*count)],&nmb2->answers->rdata[2+i*6]);
332                                   DEBUGADD(2,("%s ",inet_ntoa(ip_list[(*count)])));
333                                   (*count)++;
334                           }
335                           DEBUGADD(2,(")\n"));
336                   }
337
338                   found=True;
339                   retries=0;
340                   free_packet(p2);
341                   /*
342                    * If we're doing a unicast lookup we only
343                    * expect one reply. Don't wait the full 2
344                    * seconds if we got one. JRA.
345                    */
346                   if(!bcast && found)
347                           break;
348           }
349   }
350
351   return ip_list;
352 }
353
354 /********************************************************
355  Start parsing the lmhosts file.
356 *********************************************************/
357
358 FILE *startlmhosts(char *fname)
359 {
360   FILE *fp = sys_fopen(fname,"r");
361   if (!fp) {
362     DEBUG(4,("startlmhosts: Can't open lmhosts file %s. Error was %s\n",
363              fname, strerror(errno)));
364     return NULL;
365   }
366   return fp;
367 }
368
369 /********************************************************
370  Parse the next line in the lmhosts file.
371 *********************************************************/
372
373 BOOL getlmhostsent( FILE *fp, pstring name, int *name_type, struct in_addr *ipaddr)
374 {
375   pstring line;
376
377   while(!feof(fp) && !ferror(fp)) {
378     pstring ip,flags,extra;
379     char *ptr;
380     int count = 0;
381
382     *name_type = -1;
383
384     if (!fgets_slash(line,sizeof(pstring),fp))
385       continue;
386
387     if (*line == '#')
388       continue;
389
390     pstrcpy(ip,"");
391     pstrcpy(name,"");
392     pstrcpy(flags,"");
393
394     ptr = line;
395
396     if (next_token(&ptr,ip   ,NULL,sizeof(ip)))
397       ++count;
398     if (next_token(&ptr,name ,NULL, sizeof(pstring)))
399       ++count;
400     if (next_token(&ptr,flags,NULL, sizeof(flags)))
401       ++count;
402     if (next_token(&ptr,extra,NULL, sizeof(extra)))
403       ++count;
404
405     if (count <= 0)
406       continue;
407
408     if (count > 0 && count < 2)
409     {
410       DEBUG(0,("getlmhostsent: Ill formed hosts line [%s]\n",line));
411       continue;
412     }
413
414     if (count >= 4)
415     {
416       DEBUG(0,("getlmhostsent: too many columns in lmhosts file (obsolete syntax)\n"));
417       continue;
418     }
419
420     DEBUG(4, ("getlmhostsent: lmhost entry: %s %s %s\n", ip, name, flags));
421
422     if (strchr(flags,'G') || strchr(flags,'S'))
423     {
424       DEBUG(0,("getlmhostsent: group flag in lmhosts ignored (obsolete)\n"));
425       continue;
426     }
427
428     *ipaddr = *interpret_addr2(ip);
429
430     /* Extra feature. If the name ends in '#XX', where XX is a hex number,
431        then only add that name type. */
432     if((ptr = strchr(name, '#')) != NULL)
433     {
434       char *endptr;
435
436       ptr++;
437       *name_type = (int)strtol(ptr, &endptr, 16);
438
439       if(!*ptr || (endptr == ptr))
440       {
441         DEBUG(0,("getlmhostsent: invalid name %s containing '#'.\n", name));
442         continue;
443       }
444
445       *(--ptr) = '\0'; /* Truncate at the '#' */
446     }
447
448     return True;
449   }
450
451   return False;
452 }
453
454 /********************************************************
455  Finish parsing the lmhosts file.
456 *********************************************************/
457
458 void endlmhosts(FILE *fp)
459 {
460   fclose(fp);
461 }
462
463 /********************************************************
464  Resolve via "bcast" method.
465 *********************************************************/
466
467 static BOOL resolve_bcast(const char *name, int name_type,
468                                 struct in_addr **return_ip_list, int *return_count)
469 {
470         int sock, i;
471         int num_interfaces = iface_count();
472
473         *return_ip_list = NULL;
474         *return_count = 0;
475         
476         /*
477          * "bcast" means do a broadcast lookup on all the local interfaces.
478          */
479
480         DEBUG(3,("resolve_bcast: Attempting broadcast lookup for name %s<0x%x>\n", name, name_type));
481
482         sock = open_socket_in( SOCK_DGRAM, 0, 3,
483                                interpret_addr(lp_socket_address()), True );
484
485         if (sock == -1) return False;
486
487         set_socket_options(sock,"SO_BROADCAST");
488         /*
489          * Lookup the name on all the interfaces, return on
490          * the first successful match.
491          */
492         for( i = num_interfaces-1; i >= 0; i--) {
493                 struct in_addr sendto_ip;
494                 /* Done this way to fix compiler error on IRIX 5.x */
495                 sendto_ip = *iface_bcast(*iface_n_ip(i));
496                 *return_ip_list = name_query(sock, name, name_type, True, 
497                                     True, sendto_ip, return_count);
498                 if(*return_ip_list != NULL) {
499                         close(sock);
500                         return True;
501                 }
502         }
503
504         close(sock);
505         return False;
506 }
507
508 /********************************************************
509  Resolve via "wins" method.
510 *********************************************************/
511
512 static BOOL resolve_wins(const char *name, int name_type,
513                          struct in_addr **return_iplist, int *return_count)
514 {
515         int sock;
516         struct in_addr wins_ip;
517         BOOL wins_ismyip;
518
519         *return_iplist = NULL;
520         *return_count = 0;
521         
522         /*
523          * "wins" means do a unicast lookup to the WINS server.
524          * Ignore if there is no WINS server specified or if the
525          * WINS server is one of our interfaces (if we're being
526          * called from within nmbd - we can't do this call as we
527          * would then block).
528          */
529
530         DEBUG(3,("resolve_wins: Attempting wins lookup for name %s<0x%x>\n", name, name_type));
531
532         if( wins_srv_count() < 1 ) {
533                 DEBUG(3,("resolve_wins: WINS server resolution selected and no WINS servers listed.\n"));
534                 return False;
535         }
536
537         wins_ip = *interpret_addr2( wins_srv() );
538         wins_ismyip = ismyip(wins_ip);
539
540         DEBUG(3, ("resolve_wins: WINS server == <%s>\n", inet_ntoa(wins_ip)) );
541         if((wins_ismyip && !global_in_nmbd) || !wins_ismyip) {
542                 sock = open_socket_in(  SOCK_DGRAM, 0, 3,
543                                         interpret_addr(lp_socket_address()),
544                                         True );
545                 if (sock != -1) {
546                         *return_iplist = name_query( sock,      name,
547                                                      name_type, False, 
548                                                      True,      wins_ip,
549                                                      return_count);
550                         if(*return_iplist != NULL) {
551                                 close(sock);
552                                 return True;
553                         }
554                         close(sock);
555                 }
556         }
557
558         return False;
559 }
560
561 /********************************************************
562  Resolve via "lmhosts" method.
563 *********************************************************/
564
565 static BOOL resolve_lmhosts(const char *name, int name_type,
566                          struct in_addr **return_iplist, int *return_count)
567 {
568         /*
569          * "lmhosts" means parse the local lmhosts file.
570          */
571         
572         FILE *fp;
573         pstring lmhost_name;
574         int name_type2;
575         struct in_addr return_ip;
576
577         *return_iplist = NULL;
578         *return_count = 0;
579
580         DEBUG(3,("resolve_lmhosts: Attempting lmhosts lookup for name %s<0x%x>\n", name, name_type));
581
582         fp = startlmhosts( LMHOSTSFILE );
583         if(fp) {
584                 while (getlmhostsent(fp, lmhost_name, &name_type2, &return_ip)) {
585                         if (strequal(name, lmhost_name) && 
586                 ((name_type2 == -1) || (name_type == name_type2))
587                ) {
588                                 endlmhosts(fp);
589                                 *return_iplist = (struct in_addr *)malloc(sizeof(struct in_addr));
590                                 if(*return_iplist == NULL) {
591                                         DEBUG(3,("resolve_lmhosts: malloc fail !\n"));
592                                         return False;
593                                 }
594                                 **return_iplist = return_ip;
595                                 *return_count = 1;
596                                 return True; 
597                         }
598                 }
599                 endlmhosts(fp);
600         }
601         return False;
602 }
603
604
605 /********************************************************
606  Resolve via "hosts" method.
607 *********************************************************/
608
609 static BOOL resolve_hosts(const char *name,
610                          struct in_addr **return_iplist, int *return_count)
611 {
612         /*
613          * "host" means do a localhost, or dns lookup.
614          */
615         struct hostent *hp;
616
617         *return_iplist = NULL;
618         *return_count = 0;
619
620         DEBUG(3,("resolve_hosts: Attempting host lookup for name %s<0x20>\n", name));
621         
622         if (((hp = Get_Hostbyname(name)) != NULL) && (hp->h_addr != NULL)) {
623                 struct in_addr return_ip;
624                 putip((char *)&return_ip,(char *)hp->h_addr);
625                 *return_iplist = (struct in_addr *)malloc(sizeof(struct in_addr));
626                 if(*return_iplist == NULL) {
627                         DEBUG(3,("resolve_hosts: malloc fail !\n"));
628                         return False;
629                 }
630                 **return_iplist = return_ip;
631                 *return_count = 1;
632                 return True;
633         }
634         return False;
635 }
636
637 /********************************************************
638  Resolve a name into an IP address. Use this function if
639  the string is either an IP address, DNS or host name
640  or NetBIOS name. This uses the name switch in the
641  smb.conf to determine the order of name resolution.
642 *********************************************************/
643 BOOL is_ip_address(const char *name)
644 {
645   int i;
646   for (i=0; name[i]; i++)
647     if (!(isdigit((int)name[i]) || name[i] == '.'))
648         return False;
649
650   return True;
651 }
652
653
654 /********************************************************
655  Internal interface to resolve a name into an IP address.
656  Use this function if the string is either an IP address, DNS
657  or host name or NetBIOS name. This uses the name switch in the
658  smb.conf to determine the order of name resolution.
659 *********************************************************/
660
661 static BOOL internal_resolve_name(const char *name, int name_type,
662                                         struct in_addr **return_iplist, int *return_count)
663 {
664   pstring name_resolve_list;
665   fstring tok;
666   char *ptr;
667   BOOL allones = (strcmp(name,"255.255.255.255") == 0);
668   BOOL allzeros = (strcmp(name,"0.0.0.0") == 0);
669   BOOL is_address = is_ipaddress(name);
670   *return_iplist = NULL;
671   *return_count = 0;
672
673   if (allzeros || allones || is_address) {
674         *return_iplist = (struct in_addr *)malloc(sizeof(struct in_addr));
675         if(*return_iplist == NULL) {
676                 DEBUG(3,("internal_resolve_name: malloc fail !\n"));
677                 return False;
678         }
679         if(is_address) { 
680                 /* if it's in the form of an IP address then get the lib to interpret it */
681                 (*return_iplist)->s_addr = inet_addr(name);
682     } else {
683                 (*return_iplist)->s_addr = allones ? 0xFFFFFFFF : 0;
684                 *return_count = 1;
685         }
686     return True;
687   }
688   
689   pstrcpy(name_resolve_list, lp_name_resolve_order());
690   ptr = name_resolve_list;
691   if (!ptr || !*ptr)
692     ptr = "host";
693
694   while (next_token(&ptr, tok, LIST_SEP, sizeof(tok))) {
695           if((strequal(tok, "host") || strequal(tok, "hosts"))) {
696                   if (name_type == 0x20 && resolve_hosts(name, return_iplist, return_count)) {
697                           return True;
698                   }
699           } else if(strequal( tok, "lmhosts")) {
700                   if (resolve_lmhosts(name, name_type, return_iplist, return_count)) {
701                           return True;
702                   }
703           } else if(strequal( tok, "wins")) {
704                   /* don't resolve 1D via WINS */
705                   if (name_type != 0x1D &&
706                       resolve_wins(name, name_type, return_iplist, return_count)) {
707                           return True;
708                   }
709           } else if(strequal( tok, "bcast")) {
710                   if (resolve_bcast(name, name_type, return_iplist, return_count)) {
711                           return True;
712                   }
713           } else {
714                   DEBUG(0,("resolve_name: unknown name switch type %s\n", tok));
715           }
716   }
717
718   if((*return_iplist) != NULL) {
719     free((char *)(*return_iplist));
720     *return_iplist = NULL;
721   }
722   return False;
723 }
724
725 /********************************************************
726  Internal interface to resolve a name into one IP address.
727  Use this function if the string is either an IP address, DNS
728  or host name or NetBIOS name. This uses the name switch in the
729  smb.conf to determine the order of name resolution.
730 *********************************************************/
731
732 BOOL resolve_name(const char *name, struct in_addr *return_ip, int name_type)
733 {
734         struct in_addr *ip_list = NULL;
735         int count = 0;
736
737         if(internal_resolve_name(name, name_type, &ip_list, &count)) {
738                 *return_ip = ip_list[0];
739                 free((char *)ip_list);
740                 return True;
741         }
742         if(ip_list != NULL)
743                 free((char *)ip_list);
744         return False;
745 }
746
747
748 /********************************************************
749  resolve a name of format \\server_name or \\ipaddress
750  into a name.  also, cut the \\ from the front for us.
751 *********************************************************/
752
753 BOOL resolve_srv_name(const char* srv_name, fstring dest_host,
754                                 struct in_addr *ip)
755 {
756         BOOL ret;
757         const char *sv_name = srv_name;
758
759         DEBUG(10,("resolve_srv_name: %s\n", srv_name));
760
761         if (srv_name == NULL || strequal("\\\\.", srv_name))
762         {
763                 extern pstring global_myname;
764                 fstrcpy(dest_host, global_myname);
765                 ip = interpret_addr2("127.0.0.1");
766                 return True;
767         }
768
769         if (strnequal("\\\\", srv_name, 2))
770         {
771                 sv_name = &srv_name[2];
772         }
773
774         fstrcpy(dest_host, sv_name);
775         /* treat the '*' name specially - it is a magic name for the PDC */
776         if (strcmp(dest_host,"*") == 0) {
777                 extern pstring global_myname;
778                 ret = resolve_name(lp_workgroup(), ip, 0x1B);
779                 lookup_pdc_name(global_myname, lp_workgroup(), ip, dest_host);
780         } else {
781                 ret = resolve_name(dest_host, ip, 0x20);
782         }
783         
784         if (is_ip_address(dest_host))
785         {
786                 fstrcpy(dest_host, "*SMBSERVER");
787         }
788         
789         return ret;
790 }
791
792
793 /********************************************************
794  Find the IP address of the master browser or DMB for a workgroup.
795 *********************************************************/
796
797 BOOL find_master_ip(char *group, struct in_addr *master_ip)
798 {
799         struct in_addr *ip_list = NULL;
800         int count = 0;
801
802         if (internal_resolve_name(group, 0x1D, &ip_list, &count)) {
803                 *master_ip = ip_list[0];
804                 free((char *)ip_list);
805                 return True;
806         }
807         if(internal_resolve_name(group, 0x1B, &ip_list, &count)) {
808                 *master_ip = ip_list[0];
809                 free((char *)ip_list);
810                 return True;
811         }
812
813         if(ip_list != NULL)
814                 free((char *)ip_list);
815         return False;
816 }
817
818
819 /********************************************************
820  Lookup a PDC name given a Domain name and IP address.
821 *********************************************************/
822 BOOL lookup_pdc_name(const char *srcname, const char *domain, struct in_addr *pdc_ip, char *ret_name)
823 {
824         int retries = 3;
825         int retry_time = 2000;
826         struct timeval tval;
827         struct packet_struct p;
828         struct dgram_packet *dgram = &p.packet.dgram;
829         char *ptr,*p2;
830         char tmp[4];
831         int len;
832         struct sockaddr_in sock_name;
833         int sock_len = sizeof(sock_name);
834         const char *mailslot = "\\MAILSLOT\\NET\\NETLOGON";
835         char *mailslot_name;
836         char buffer[1024];
837         char *bufp;
838         int dgm_id = generate_trn_id();
839         int sock = open_socket_in(SOCK_DGRAM, 0, 3, interpret_addr(lp_socket_address()), True );
840         
841         if(sock == -1)
842                 return False;
843         
844         /* Find out the transient UDP port we have been allocated. */
845         if(getsockname(sock, (struct sockaddr *)&sock_name, &sock_len)<0) {
846                 DEBUG(0,("lookup_pdc_name: Failed to get local UDP port. Error was %s\n",
847                          strerror(errno)));
848                 close(sock);
849                 return False;
850         }
851
852         /*
853          * Create the request data.
854          */
855
856         memset(buffer,'\0',sizeof(buffer));
857         bufp = buffer;
858         SSVAL(bufp,0,QUERYFORPDC);
859         bufp += 2;
860         fstrcpy(bufp,srcname);
861         bufp += (strlen(bufp) + 1);
862         slprintf(bufp, sizeof(fstring), "\\MAILSLOT\\NET\\GETDC%d", dgm_id);
863         mailslot_name = bufp;
864         bufp += (strlen(bufp) + 1);
865         bufp = ALIGN2(bufp, buffer);
866         bufp += dos_PutUniCode(bufp, srcname, sizeof(buffer) - (bufp - buffer) - 1, True);
867         SIVAL(bufp,0,1);
868         SSVAL(bufp,4,0xFFFF); 
869         SSVAL(bufp,6,0xFFFF); 
870         bufp += 8;
871         len = PTR_DIFF(bufp,buffer);
872
873         memset((char *)&p,'\0',sizeof(p));
874
875         /* DIRECT GROUP or UNIQUE datagram. */
876         dgram->header.msg_type = 0x10;
877         dgram->header.flags.node_type = M_NODE;
878         dgram->header.flags.first = True;
879         dgram->header.flags.more = False;
880         dgram->header.dgm_id = dgm_id;
881         dgram->header.source_ip = *iface_ip(*pdc_ip);
882         dgram->header.source_port = ntohs(sock_name.sin_port);
883         dgram->header.dgm_length = 0; /* Let build_dgram() handle this. */
884         dgram->header.packet_offset = 0;
885         
886         make_nmb_name(&dgram->source_name,srcname,0);
887         make_nmb_name(&dgram->dest_name,domain,0x1B);
888         
889         ptr = &dgram->data[0];
890         
891         /* Setup the smb part. */
892         ptr -= 4; /* XXX Ugliness because of handling of tcp SMB length. */
893         memcpy(tmp,ptr,4);
894         set_message(ptr,17,17 + len,True);
895         memcpy(ptr,tmp,4);
896
897         CVAL(ptr,smb_com) = SMBtrans;
898         SSVAL(ptr,smb_vwv1,len);
899         SSVAL(ptr,smb_vwv11,len);
900         SSVAL(ptr,smb_vwv12,70 + strlen(mailslot));
901         SSVAL(ptr,smb_vwv13,3);
902         SSVAL(ptr,smb_vwv14,1);
903         SSVAL(ptr,smb_vwv15,1);
904         SSVAL(ptr,smb_vwv16,2);
905         p2 = smb_buf(ptr);
906         pstrcpy(p2,mailslot);
907         p2 = skip_string(p2,1);
908         
909         memcpy(p2,buffer,len);
910         p2 += len;
911         
912         dgram->datasize = PTR_DIFF(p2,ptr+4); /* +4 for tcp length. */
913         
914         p.ip = *pdc_ip;
915         p.port = DGRAM_PORT;
916         p.fd = sock;
917         p.timestamp = time(NULL);
918         p.packet_type = DGRAM_PACKET;
919         
920         GetTimeOfDay(&tval);
921         
922         if (!send_packet(&p)) {
923                 DEBUG(0,("lookup_pdc_name: send_packet failed.\n"));
924                 close(sock);
925                 return False;
926         }
927         
928         retries--;
929         
930         while (1) {
931                 struct timeval tval2;
932                 struct packet_struct *p_ret;
933                 
934                 GetTimeOfDay(&tval2);
935                 if (TvalDiff(&tval,&tval2) > retry_time) {
936                         if (!retries)
937                                 break;
938                         if (!send_packet(&p)) {
939                                 DEBUG(0,("lookup_pdc_name: send_packet failed.\n"));
940                                 close(sock);
941                                 return False;
942                         }
943                         GetTimeOfDay(&tval);
944                         retries--;
945                 }
946
947                 if ((p_ret = receive_dgram_packet(sock,90,mailslot_name))) {
948                         struct dgram_packet *dgram2 = &p_ret->packet.dgram;
949                         char *buf;
950                         char *buf2;
951
952                         buf = &dgram2->data[0];
953                         buf -= 4;
954
955                         if (CVAL(buf,smb_com) != SMBtrans) {
956                                 DEBUG(0,("lookup_pdc_name: datagram type %u != SMBtrans(%u)\n", (unsigned int)
957                                          CVAL(buf,smb_com), (unsigned int)SMBtrans ));
958                                 free_packet(p_ret);
959                                 continue;
960                         }
961                         
962                         len = SVAL(buf,smb_vwv11);
963                         buf2 = smb_base(buf) + SVAL(buf,smb_vwv12);
964                         
965                         if (len <= 0) {
966                                 DEBUG(0,("lookup_pdc_name: datagram len < 0 (%d)\n", len ));
967                                 free_packet(p_ret);
968                                 continue;
969                         }
970
971                         DEBUG(4,("lookup_pdc_name: datagram reply from %s to %s IP %s for %s of type %d len=%d\n",
972                                  nmb_namestr(&dgram2->source_name),nmb_namestr(&dgram2->dest_name),
973                                  inet_ntoa(p_ret->ip), smb_buf(buf),SVAL(buf2,0),len));
974
975                         if(SVAL(buf2,0) != QUERYFORPDC_R) {
976                                 DEBUG(0,("lookup_pdc_name: datagram type (%u) != QUERYFORPDC_R(%u)\n",
977                                          (unsigned int)SVAL(buf,0), (unsigned int)QUERYFORPDC_R ));
978                                 free_packet(p_ret);
979                                 continue;
980                         }
981
982                         buf2 += 2;
983                         /* Note this is safe as it is a bounded strcpy. */
984                         fstrcpy(ret_name, buf2);
985                         ret_name[sizeof(fstring)-1] = '\0';
986                         close(sock);
987                         free_packet(p_ret);
988                         return True;
989                 }
990         }
991         
992         close(sock);
993         return False;
994 }
995
996
997 /********************************************************
998  Get the IP address list of the PDC/BDC's of a Domain.
999 *********************************************************/
1000 BOOL get_dc_list(char *group, struct in_addr **ip_list, int *count)
1001 {
1002         return internal_resolve_name(group, 0x1C, ip_list, count);
1003 }