Getting back to a compilable state (not there yet but close).
[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 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 (nmb2->header.opcode != 0 ||
276                       nmb2->header.nm_flags.bcast ||
277                       nmb2->header.rcode ||
278                       !nmb2->header.ancount) {
279                           /* 
280                            * XXXX what do we do with this? Could be a
281                            * redirect, but we'll discard it for the
282                            * moment.  */
283                           free_packet(p2);
284                           continue;
285                   }
286
287                   ip_list = (struct in_addr *)Realloc(ip_list, sizeof(ip_list[0]) * 
288                                                       ((*count)+nmb2->answers->rdlength/6));
289                   if (ip_list) {
290                           DEBUG(2,("Got a positive name query response from %s ( ",
291                                    inet_ntoa(p2->ip)));
292                           for (i=0;i<nmb2->answers->rdlength/6;i++) {
293                                   putip((char *)&ip_list[(*count)],&nmb2->answers->rdata[2+i*6]);
294                                   DEBUG(2,("%s ",inet_ntoa(ip_list[(*count)])));
295                                   (*count)++;
296                           }
297                           DEBUG(2,(")\n"));
298                   }
299
300                   found=True;
301                   retries=0;
302                   free_packet(p2);
303                   /*
304                    * If we're doing a unicast lookup we only
305                    * expect one reply. Don't wait the full 2
306                    * seconds if we got one. JRA.
307                    */
308                   if(!bcast && found)
309                           break;
310           }
311   }
312
313   return ip_list;
314 }
315
316 /********************************************************
317  Start parsing the lmhosts file.
318 *********************************************************/
319
320 FILE *startlmhosts(char *fname)
321 {
322   FILE *fp = sys_fopen(fname,"r");
323   if (!fp) {
324     DEBUG(4,("startlmhosts: Can't open lmhosts file %s. Error was %s\n",
325              fname, strerror(errno)));
326     return NULL;
327   }
328   return fp;
329 }
330
331 /********************************************************
332  Parse the next line in the lmhosts file.
333 *********************************************************/
334
335 BOOL getlmhostsent( FILE *fp, pstring name, int *name_type, struct in_addr *ipaddr)
336 {
337   pstring line;
338
339   while(!feof(fp) && !ferror(fp)) {
340     pstring ip,flags,extra;
341     char *ptr;
342     int count = 0;
343
344     *name_type = -1;
345
346     if (!fgets_slash(line,sizeof(pstring),fp))
347       continue;
348
349     if (*line == '#')
350       continue;
351
352     pstrcpy(ip,"");
353     pstrcpy(name,"");
354     pstrcpy(flags,"");
355
356     ptr = line;
357
358     if (next_token(&ptr,ip   ,NULL,sizeof(ip)))
359       ++count;
360     if (next_token(&ptr,name ,NULL, sizeof(pstring)))
361       ++count;
362     if (next_token(&ptr,flags,NULL, sizeof(flags)))
363       ++count;
364     if (next_token(&ptr,extra,NULL, sizeof(extra)))
365       ++count;
366
367     if (count <= 0)
368       continue;
369
370     if (count > 0 && count < 2)
371     {
372       DEBUG(0,("getlmhostsent: Ill formed hosts line [%s]\n",line));
373       continue;
374     }
375
376     if (count >= 4)
377     {
378       DEBUG(0,("getlmhostsent: too many columns in lmhosts file (obsolete syntax)\n"));
379       continue;
380     }
381
382     DEBUG(4, ("getlmhostsent: lmhost entry: %s %s %s\n", ip, name, flags));
383
384     if (strchr(flags,'G') || strchr(flags,'S'))
385     {
386       DEBUG(0,("getlmhostsent: group flag in lmhosts ignored (obsolete)\n"));
387       continue;
388     }
389
390     *ipaddr = *interpret_addr2(ip);
391
392     /* Extra feature. If the name ends in '#XX', where XX is a hex number,
393        then only add that name type. */
394     if((ptr = strchr(name, '#')) != NULL)
395     {
396       char *endptr;
397
398       ptr++;
399       *name_type = (int)strtol(ptr, &endptr, 16);
400
401       if(!*ptr || (endptr == ptr))
402       {
403         DEBUG(0,("getlmhostsent: invalid name %s containing '#'.\n", name));
404         continue;
405       }
406
407       *(--ptr) = '\0'; /* Truncate at the '#' */
408     }
409
410     return True;
411   }
412
413   return False;
414 }
415
416 /********************************************************
417  Finish parsing the lmhosts file.
418 *********************************************************/
419
420 void endlmhosts(FILE *fp)
421 {
422   fclose(fp);
423 }
424
425 /********************************************************
426  Resolve via "bcast" method.
427 *********************************************************/
428
429 static BOOL resolve_bcast(const char *name, int name_type,
430                                 struct in_addr **return_ip_list, int *return_count)
431 {
432         int sock, i;
433         int num_interfaces = iface_count();
434
435         *return_ip_list = NULL;
436         *return_count = 0;
437         
438         /*
439          * "bcast" means do a broadcast lookup on all the local interfaces.
440          */
441
442         DEBUG(3,("resolve_bcast: Attempting broadcast lookup for name %s<0x%x>\n", name, name_type));
443
444         sock = open_socket_in( SOCK_DGRAM, 0, 3,
445                                interpret_addr(lp_socket_address()), True );
446
447         if (sock == -1) return False;
448
449         set_socket_options(sock,"SO_BROADCAST");
450         /*
451          * Lookup the name on all the interfaces, return on
452          * the first successful match.
453          */
454         for( i = num_interfaces-1; i >= 0; i--) {
455                 struct in_addr sendto_ip;
456                 /* Done this way to fix compiler error on IRIX 5.x */
457                 sendto_ip = *iface_bcast(*iface_n_ip(i));
458                 *return_ip_list = name_query(sock, name, name_type, True, 
459                                     True, sendto_ip, return_count);
460                 if(*return_ip_list != NULL) {
461                         close(sock);
462                         return True;
463                 }
464         }
465
466         close(sock);
467         return False;
468 }
469
470 /********************************************************
471  Resolve via "wins" method.
472 *********************************************************/
473
474 static BOOL resolve_wins(const char *name, int name_type,
475                          struct in_addr **return_iplist, int *return_count)
476 {
477         int sock;
478         struct in_addr wins_ip;
479         BOOL wins_ismyip;
480
481         *return_iplist = NULL;
482         *return_count = 0;
483         
484         /*
485          * "wins" means do a unicast lookup to the WINS server.
486          * Ignore if there is no WINS server specified or if the
487          * WINS server is one of our interfaces (if we're being
488          * called from within nmbd - we can't do this call as we
489          * would then block).
490          */
491
492         DEBUG(3,("resolve_wins: Attempting wins lookup for name %s<0x%x>\n", name, name_type));
493
494         if(!*lp_wins_server()) {
495                 DEBUG(3,("resolve_wins: WINS server resolution selected and no WINS server present.\n"));
496                 return False;
497         }
498
499         wins_ip = *interpret_addr2(lp_wins_server());
500         wins_ismyip = ismyip(wins_ip);
501
502         if((wins_ismyip && !global_in_nmbd) || !wins_ismyip) {
503                 sock = open_socket_in( SOCK_DGRAM, 0, 3,
504                                                         interpret_addr(lp_socket_address()), True );
505               
506                 if (sock != -1) {
507                         *return_iplist = name_query(sock, name, name_type, False, 
508                                                                 True, wins_ip, return_count);
509                         if(*return_iplist != NULL) {
510                                 close(sock);
511                                 return True;
512                         }
513                         close(sock);
514                 }
515         }
516
517         return False;
518 }
519
520 /********************************************************
521  Resolve via "lmhosts" method.
522 *********************************************************/
523
524 static BOOL resolve_lmhosts(const char *name, int name_type,
525                          struct in_addr **return_iplist, int *return_count)
526 {
527         /*
528          * "lmhosts" means parse the local lmhosts file.
529          */
530         
531         FILE *fp;
532         pstring lmhost_name;
533         int name_type2;
534         struct in_addr return_ip;
535
536         *return_iplist = NULL;
537         *return_count = 0;
538
539         DEBUG(3,("resolve_lmhosts: Attempting lmhosts lookup for name %s<0x%x>\n", name, name_type));
540
541         fp = startlmhosts( LMHOSTSFILE );
542         if(fp) {
543                 while (getlmhostsent(fp, lmhost_name, &name_type2, &return_ip)) {
544                         if (strequal(name, lmhost_name) && 
545                 ((name_type2 == -1) || (name_type == name_type2))
546                ) {
547                                 endlmhosts(fp);
548                                 *return_iplist = (struct in_addr *)malloc(sizeof(struct in_addr));
549                                 if(*return_iplist == NULL) {
550                                         DEBUG(3,("resolve_lmhosts: malloc fail !\n"));
551                                         return False;
552                                 }
553                                 **return_iplist = return_ip;
554                                 *return_count = 1;
555                                 return True; 
556                         }
557                 }
558                 endlmhosts(fp);
559         }
560         return False;
561 }
562
563
564 /********************************************************
565  Resolve via "hosts" method.
566 *********************************************************/
567
568 static BOOL resolve_hosts(const char *name,
569                          struct in_addr **return_iplist, int *return_count)
570 {
571         /*
572          * "host" means do a localhost, or dns lookup.
573          */
574         struct hostent *hp;
575
576         *return_iplist = NULL;
577         *return_count = 0;
578
579         DEBUG(3,("resolve_hosts: Attempting host lookup for name %s<0x20>\n", name));
580         
581         if (((hp = Get_Hostbyname(name)) != NULL) && (hp->h_addr != NULL)) {
582                 struct in_addr return_ip;
583                 putip((char *)&return_ip,(char *)hp->h_addr);
584                 *return_iplist = (struct in_addr *)malloc(sizeof(struct in_addr));
585                 if(*return_iplist == NULL) {
586                         DEBUG(3,("resolve_hosts: malloc fail !\n"));
587                         return False;
588                 }
589                 **return_iplist = return_ip;
590                 *return_count = 1;
591                 return True;
592         }
593         return False;
594 }
595
596 /********************************************************
597  Internal interface to resolve a name into an IP address.
598  Use this function if the string is either an IP address, DNS
599  or host name or NetBIOS name. This uses the name switch in the
600  smb.conf to determine the order of name resolution.
601 *********************************************************/
602
603 static BOOL internal_resolve_name(const char *name, int name_type,
604                                         struct in_addr **return_iplist, int *return_count)
605 {
606   pstring name_resolve_list;
607   fstring tok;
608   char *ptr;
609   BOOL allones = (strcmp(name,"255.255.255.255") == 0);
610   BOOL allzeros = (strcmp(name,"0.0.0.0") == 0);
611   BOOL is_address = is_ipaddress(name);
612   *return_iplist = NULL;
613   *return_count = 0;
614
615   if (allzeros || allones || is_address) {
616         *return_iplist = (struct in_addr *)malloc(sizeof(struct in_addr));
617         if(*return_iplist == NULL) {
618                 DEBUG(3,("internal_resolve_name: malloc fail !\n"));
619                 return False;
620         }
621         if(is_address) { 
622                 /* if it's in the form of an IP address then get the lib to interpret it */
623                 (*return_iplist)->s_addr = inet_addr(name);
624     } else {
625                 (*return_iplist)->s_addr = allones ? 0xFFFFFFFF : 0;
626                 *return_count = 1;
627         }
628     return True;
629   }
630   
631   pstrcpy(name_resolve_list, lp_name_resolve_order());
632   ptr = name_resolve_list;
633   if (!ptr || !*ptr)
634     ptr = "host";
635
636   while (next_token(&ptr, tok, LIST_SEP, sizeof(tok))) {
637           if((strequal(tok, "host") || strequal(tok, "hosts"))) {
638                   if (name_type == 0x20 && resolve_hosts(name, return_iplist, return_count)) {
639                           return True;
640                   }
641           } else if(strequal( tok, "lmhosts")) {
642                   if (resolve_lmhosts(name, name_type, return_iplist, return_count)) {
643                           return True;
644                   }
645           } else if(strequal( tok, "wins")) {
646                   /* don't resolve 1D via WINS */
647                   if (name_type != 0x1D &&
648                       resolve_wins(name, name_type, return_iplist, return_count)) {
649                           return True;
650                   }
651           } else if(strequal( tok, "bcast")) {
652                   if (resolve_bcast(name, name_type, return_iplist, return_count)) {
653                           return True;
654                   }
655           } else {
656                   DEBUG(0,("resolve_name: unknown name switch type %s\n", tok));
657           }
658   }
659
660   if((*return_iplist) != NULL) {
661     free((char *)(*return_iplist));
662     *return_iplist = NULL;
663   }
664   return False;
665 }
666
667 /********************************************************
668  Internal interface to resolve a name into one IP address.
669  Use this function if the string is either an IP address, DNS
670  or host name or NetBIOS name. This uses the name switch in the
671  smb.conf to determine the order of name resolution.
672 *********************************************************/
673
674 BOOL resolve_name(const char *name, struct in_addr *return_ip, int name_type)
675 {
676         struct in_addr *ip_list = NULL;
677         int count = 0;
678
679         if(internal_resolve_name(name, name_type, &ip_list, &count)) {
680                 *return_ip = ip_list[0];
681                 free((char *)ip_list);
682                 return True;
683         }
684         if(ip_list != NULL)
685                 free((char *)ip_list);
686         return False;
687 }
688
689 /********************************************************
690  Find the IP address of the master browser or DMB for a workgroup.
691 *********************************************************/
692
693 BOOL find_master_ip(char *group, struct in_addr *master_ip)
694 {
695         struct in_addr *ip_list = NULL;
696         int count = 0;
697
698         if (internal_resolve_name(group, 0x1D, &ip_list, &count)) {
699                 *master_ip = ip_list[0];
700                 free((char *)ip_list);
701                 return True;
702         }
703         if(internal_resolve_name(group, 0x1B, &ip_list, &count)) {
704                 *master_ip = ip_list[0];
705                 free((char *)ip_list);
706                 return True;
707         }
708
709         if(ip_list != NULL)
710                 free((char *)ip_list);
711         return False;
712 }
713
714
715 /********************************************************
716  Lookup a PDC name given a Domain name and IP address.
717 *********************************************************/
718 BOOL lookup_pdc_name(const char *srcname, const char *domain, struct in_addr *pdc_ip, char *ret_name)
719 {
720         int retries = 3;
721         int retry_time = 2000;
722         struct timeval tval;
723         struct packet_struct p;
724         struct dgram_packet *dgram = &p.packet.dgram;
725         char *ptr,*p2;
726         char tmp[4];
727         int len;
728         struct sockaddr_in sock_name;
729         int sock_len = sizeof(sock_name);
730         const char *mailslot = "\\MAILSLOT\\NET\\NETLOGON";
731         char *mailslot_name;
732         char buffer[1024];
733         char *bufp;
734         int dgm_id = generate_trn_id();
735         int sock = open_socket_in(SOCK_DGRAM, 0, 3, interpret_addr(lp_socket_address()), True );
736         
737         if(sock == -1)
738                 return False;
739         
740         /* Find out the transient UDP port we have been allocated. */
741         if(getsockname(sock, (struct sockaddr *)&sock_name, &sock_len)<0) {
742                 DEBUG(0,("lookup_pdc_name: Failed to get local UDP port. Error was %s\n",
743                          strerror(errno)));
744                 close(sock);
745                 return False;
746         }
747
748         /*
749          * Create the request data.
750          */
751
752         memset(buffer,'\0',sizeof(buffer));
753         bufp = buffer;
754         SSVAL(bufp,0,QUERYFORPDC);
755         bufp += 2;
756         fstrcpy(bufp,srcname);
757         bufp += (strlen(bufp) + 1);
758         slprintf(bufp, sizeof(fstring), "\\MAILSLOT\\NET\\GETDC%d", dgm_id);
759         mailslot_name = bufp;
760         bufp += (strlen(bufp) + 1);
761         bufp = ALIGN2(bufp, buffer);
762         bufp += dos_PutUniCode(bufp, srcname, sizeof(buffer) - (bufp - buffer) - 1, True);
763         SIVAL(bufp,0,1);
764         SSVAL(bufp,4,0xFFFF); 
765         SSVAL(bufp,6,0xFFFF); 
766         bufp += 8;
767         len = PTR_DIFF(bufp,buffer);
768
769         memset((char *)&p,'\0',sizeof(p));
770
771         /* DIRECT GROUP or UNIQUE datagram. */
772         dgram->header.msg_type = 0x10;
773         dgram->header.flags.node_type = M_NODE;
774         dgram->header.flags.first = True;
775         dgram->header.flags.more = False;
776         dgram->header.dgm_id = dgm_id;
777         dgram->header.source_ip = *iface_ip(*pdc_ip);
778         dgram->header.source_port = ntohs(sock_name.sin_port);
779         dgram->header.dgm_length = 0; /* Let build_dgram() handle this. */
780         dgram->header.packet_offset = 0;
781         
782         make_nmb_name(&dgram->source_name,srcname,0);
783         make_nmb_name(&dgram->dest_name,domain,0x1B);
784         
785         ptr = &dgram->data[0];
786         
787         /* Setup the smb part. */
788         ptr -= 4; /* XXX Ugliness because of handling of tcp SMB length. */
789         memcpy(tmp,ptr,4);
790         set_message(ptr,17,17 + len,True);
791         memcpy(ptr,tmp,4);
792
793         CVAL(ptr,smb_com) = SMBtrans;
794         SSVAL(ptr,smb_vwv1,len);
795         SSVAL(ptr,smb_vwv11,len);
796         SSVAL(ptr,smb_vwv12,70 + strlen(mailslot));
797         SSVAL(ptr,smb_vwv13,3);
798         SSVAL(ptr,smb_vwv14,1);
799         SSVAL(ptr,smb_vwv15,1);
800         SSVAL(ptr,smb_vwv16,2);
801         p2 = smb_buf(ptr);
802         pstrcpy(p2,mailslot);
803         p2 = skip_string(p2,1);
804         
805         memcpy(p2,buffer,len);
806         p2 += len;
807         
808         dgram->datasize = PTR_DIFF(p2,ptr+4); /* +4 for tcp length. */
809         
810         p.ip = *pdc_ip;
811         p.port = DGRAM_PORT;
812         p.fd = sock;
813         p.timestamp = time(NULL);
814         p.packet_type = DGRAM_PACKET;
815         
816         GetTimeOfDay(&tval);
817         
818         if (!send_packet(&p)) {
819                 DEBUG(0,("lookup_pdc_name: send_packet failed.\n"));
820                 close(sock);
821                 return False;
822         }
823         
824         retries--;
825         
826         while (1) {
827                 struct timeval tval2;
828                 struct packet_struct *p_ret;
829                 
830                 GetTimeOfDay(&tval2);
831                 if (TvalDiff(&tval,&tval2) > retry_time) {
832                         if (!retries)
833                                 break;
834                         if (!send_packet(&p)) {
835                                 DEBUG(0,("lookup_pdc_name: send_packet failed.\n"));
836                                 close(sock);
837                                 return False;
838                         }
839                         GetTimeOfDay(&tval);
840                         retries--;
841                 }
842
843                 if ((p_ret = receive_dgram_packet(sock,90,mailslot_name))) {
844                         struct dgram_packet *dgram2 = &p_ret->packet.dgram;
845                         char *buf;
846                         char *buf2;
847
848                         buf = &dgram2->data[0];
849                         buf -= 4;
850
851                         if (CVAL(buf,smb_com) != SMBtrans) {
852                                 DEBUG(0,("lookup_pdc_name: datagram type %u != SMBtrans(%u)\n", (unsigned int)
853                                          CVAL(buf,smb_com), (unsigned int)SMBtrans ));
854                                 free_packet(p_ret);
855                                 continue;
856                         }
857                         
858                         len = SVAL(buf,smb_vwv11);
859                         buf2 = smb_base(buf) + SVAL(buf,smb_vwv12);
860                         
861                         if (len <= 0) {
862                                 DEBUG(0,("lookup_pdc_name: datagram len < 0 (%d)\n", len ));
863                                 free_packet(p_ret);
864                                 continue;
865                         }
866
867                         DEBUG(4,("lookup_pdc_name: datagram reply from %s to %s IP %s for %s of type %d len=%d\n",
868                                  nmb_namestr(&dgram2->source_name),nmb_namestr(&dgram2->dest_name),
869                                  inet_ntoa(p_ret->ip), smb_buf(buf),SVAL(buf2,0),len));
870
871                         if(SVAL(buf2,0) != QUERYFORPDC_R) {
872                                 DEBUG(0,("lookup_pdc_name: datagram type (%u) != QUERYFORPDC_R(%u)\n",
873                                          (unsigned int)SVAL(buf,0), (unsigned int)QUERYFORPDC_R ));
874                                 free_packet(p_ret);
875                                 continue;
876                         }
877
878                         buf2 += 2;
879                         /* Note this is safe as it is a bounded strcpy. */
880                         fstrcpy(ret_name, buf2);
881                         ret_name[sizeof(fstring)-1] = '\0';
882                         close(sock);
883                         free_packet(p_ret);
884                         return True;
885                 }
886         }
887         
888         close(sock);
889         return False;
890 }
891
892
893 /********************************************************
894  Get the IP address list of the PDC/BDC's of a Domain.
895 *********************************************************/
896 BOOL get_dc_list(char *group, struct in_addr **ip_list, int *count)
897 {
898         return internal_resolve_name(group, 0x1C, ip_list, count);
899 }