Initial version imported to CVS
[ira/wip.git] / source3 / libsmb / nmblib.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    NBT netbios library routines
5    Copyright (C) Andrew Tridgell 1994-1995
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 #include "nameserv.h"
25
26 extern int DEBUGLEVEL;
27
28 int num_good_sends=0;
29 int  num_good_receives=0;
30 static uint16 name_trn_id = 0;
31 BOOL CanRecurse = True;
32 extern pstring scope;
33
34 /*******************************************************************
35   handle "compressed" name pointers
36   ******************************************************************/
37 static BOOL handle_name_ptrs(unsigned char *ubuf,int *offset,int length,
38                              BOOL *got_pointer,int *ret)
39 {
40   int loop_count=0;
41
42   while ((ubuf[*offset] & 0xC0) == 0xC0) {
43     if (!*got_pointer) (*ret) += 2;
44     (*got_pointer)=True;
45     (*offset) = ((ubuf[*offset] & ~0xC0)<<8) | ubuf[(*offset)+1];
46     if (loop_count++ == 10 || (*offset) < 0 || (*offset)>(length-2)) {
47       return(False);
48     }
49   }
50   return(True);
51 }
52
53 /*******************************************************************
54   parse a nmb name from "compressed" format to something readable
55   return the space taken by the name, or 0 if the name is invalid
56   ******************************************************************/
57 static int parse_nmb_name(char *inbuf,int offset,int length,
58                           struct nmb_name *name)
59 {
60   int m,n=0;
61   unsigned char *ubuf = (unsigned char *)inbuf;
62   int ret = 0;
63   BOOL got_pointer=False;
64
65   if (length - offset < 2) return(0);  
66
67   /* handle initial name pointers */
68   if (!handle_name_ptrs(ubuf,&offset,length,&got_pointer,&ret)) return(0);
69   
70   m = ubuf[offset];
71
72   if (!m) return(0);
73   if ((m & 0xC0) || offset+m+2 > length) return(0);
74
75   bzero((char *)name,sizeof(*name));
76
77   /* the "compressed" part */
78   if (!got_pointer) ret += m + 2;
79   offset++;
80   while (m) {
81     unsigned char c1,c2;
82     c1 = ubuf[offset++]-'A';
83     c2 = ubuf[offset++]-'A';
84     if ((c1 & 0xF0) || (c2 & 0xF0)) return(0);
85     name->name[n++] = (c1<<4) | c2;
86     m -= 2;
87   }
88   name->name[n] = 0;
89
90   if (n==16) {
91     /* parse out the name type, 
92        its always in the 16th byte of the name */
93     name->name_type = name->name[15];
94   
95     /* remove trailing spaces */
96     name->name[15] = 0;
97     n = 14;
98     while (n && name->name[n]==' ') name->name[n--] = 0;  
99   }
100
101   /* now the domain parts (if any) */
102   n = 0;
103   while ((m=ubuf[offset])) {
104     /* we can have pointers within the domain part as well */
105     if (!handle_name_ptrs(ubuf,&offset,length,&got_pointer,&ret)) return(0);
106
107     if (!got_pointer) ret += m+1;
108     if (n) name->scope[n++] = '.';
109     if (m+2+offset>length || n+m+1>sizeof(name->scope)) return(0);
110     offset++;
111     while (m--) name->scope[n++] = (char)ubuf[offset++];
112   }
113   name->scope[n++] = 0;  
114
115   return(ret);
116 }
117
118
119 /*******************************************************************
120   put a compressed nmb name into a buffer. return the length of the
121   compressed name
122
123   compressed names are really weird. The "compression" doubles the
124   size. The idea is that it also means that compressed names conform
125   to the doman name system. See RFC1002.
126   ******************************************************************/
127 static int put_nmb_name(char *buf,int offset,struct nmb_name *name)
128 {
129   int ret,m;
130   fstring buf1;
131   char *p;
132
133   if (name->name[0] == '*') {
134     /* special case for wildcard name */
135     bzero(buf1,20);
136     buf1[0] = '*';
137   } else {
138     sprintf(buf1,"%-15.15s%c",name->name,name->name_type);
139   }
140
141   buf[offset] = 0x20;
142
143   ret = 34;
144
145   for (m=0;m<16;m++) {
146     buf[offset+1+2*m] = 'A' + ((buf1[m]>>4)&0xF);
147     buf[offset+2+2*m] = 'A' + (buf1[m]&0xF);
148   }
149   offset += 33;
150
151   buf[offset] = 0;
152
153   if (name->scope[0]) {
154     /* XXXX this scope handling needs testing */
155     ret += strlen(name->scope) + 1;
156     strcpy(&buf[offset+1],name->scope);  
157   
158     p = &buf[offset+1];
159     while ((p = strchr(p,'.'))) {
160       buf[offset] = PTR_DIFF(p,&buf[offset]);
161       offset += buf[offset];
162       p = &buf[offset+1];
163     }
164     buf[offset] = strlen(&buf[offset+1]);
165   }
166
167   return(ret);
168 }
169
170 /*******************************************************************
171   useful for debugging messages
172   ******************************************************************/
173 char *namestr(struct nmb_name *n)
174 {
175   static int i=0;
176   static fstring ret[4];
177   char *p = ret[i];
178
179   if (!n->scope[0])
180     sprintf(p,"%s(%x)",n->name,n->name_type);
181   else
182     sprintf(p,"%s(%x).%s",n->name,n->name_type,n->scope);
183
184   i = (i+1)%4;
185   return(p);
186 }
187
188 /*******************************************************************
189   allocate are parse some resource records
190   ******************************************************************/
191 static BOOL parse_alloc_res_rec(char *inbuf,int *offset,int length,
192                                 struct res_rec **recs,
193                                 int count)
194 {
195   int i;
196   *recs = (struct res_rec *)malloc(sizeof(**recs)*count);
197   if (!*recs) return(False);
198
199   bzero(*recs,sizeof(**recs)*count);
200
201   for (i=0;i<count;i++) {
202     int l = parse_nmb_name(inbuf,*offset,length,&(*recs)[i].rr_name);
203     (*offset) += l;
204     if (!l || (*offset)+10 > length) {
205       free(*recs);
206       return(False);
207     }
208     (*recs)[i].rr_type = RSVAL(inbuf,(*offset));
209     (*recs)[i].rr_class = RSVAL(inbuf,(*offset)+2);
210     (*recs)[i].ttl = RIVAL(inbuf,(*offset)+4);
211     (*recs)[i].rdlength = RSVAL(inbuf,(*offset)+8);
212     (*offset) += 10;
213     if ((*recs)[i].rdlength>sizeof((*recs)[i].rdata) || 
214         (*offset)+(*recs)[i].rdlength > length) {
215       free(*recs);
216       return(False);
217     }
218     memcpy((*recs)[i].rdata,inbuf+(*offset),(*recs)[i].rdlength);
219     (*offset) += (*recs)[i].rdlength;    
220   }
221   return(True);
222 }
223
224 /*******************************************************************
225   put a resource record into a packet
226   ******************************************************************/
227 static int put_res_rec(char *buf,int offset,struct res_rec *recs,int count)
228 {
229   int ret=0;
230   int i;
231
232   for (i=0;i<count;i++) {
233     int l = put_nmb_name(buf,offset,&recs[i].rr_name);
234     offset += l;
235     ret += l;
236     RSSVAL(buf,offset,recs[i].rr_type);
237     RSSVAL(buf,offset+2,recs[i].rr_class);
238     RSIVAL(buf,offset+4,recs[i].ttl);
239     RSSVAL(buf,offset+8,recs[i].rdlength);
240     memcpy(buf+offset+10,recs[i].rdata,recs[i].rdlength);
241     offset += 10+recs[i].rdlength;
242     ret += 10+recs[i].rdlength;
243   }
244
245   return(ret);
246 }
247
248 /*******************************************************************
249   parse a dgram packet. Return False if the packet can't be parsed 
250   or is invalid for some reason, True otherwise 
251
252   this is documented in section 4.4.1 of RFC1002
253   ******************************************************************/
254 static BOOL parse_dgram(char *inbuf,int length,struct dgram_packet *dgram)
255 {
256   int offset;
257   int flags;
258
259   bzero((char *)dgram,sizeof(*dgram));
260
261   if (length < 14) return(False);
262
263   dgram->header.msg_type = CVAL(inbuf,0);
264   flags = CVAL(inbuf,1);
265   dgram->header.flags.node_type = (enum node_type)((flags>>2)&3);
266   if (flags & 1) dgram->header.flags.more = True;
267   if (flags & 2) dgram->header.flags.first = True;
268   dgram->header.dgm_id = RSVAL(inbuf,2);
269   putip((char *)&dgram->header.source_ip,inbuf+4);
270   dgram->header.source_port = RSVAL(inbuf,8);
271   dgram->header.dgm_length = RSVAL(inbuf,10);
272   dgram->header.packet_offset = RSVAL(inbuf,12);
273
274   offset = 14;
275
276   if (dgram->header.msg_type == 0x10 ||
277       dgram->header.msg_type == 0x11 ||
278       dgram->header.msg_type == 0x12) {      
279     offset += parse_nmb_name(inbuf,offset,length,&dgram->source_name);
280     offset += parse_nmb_name(inbuf,offset,length,&dgram->dest_name);
281   }
282
283   if (offset >= length || (length-offset > sizeof(dgram->data))) 
284     return(False);
285
286   dgram->datasize = length-offset;
287   memcpy(dgram->data,inbuf+offset,dgram->datasize);
288
289   return(True);
290 }
291
292
293 /*******************************************************************
294   parse a nmb packet. Return False if the packet can't be parsed 
295   or is invalid for some reason, True otherwise 
296   ******************************************************************/
297 static BOOL parse_nmb(char *inbuf,int length,struct nmb_packet *nmb)
298 {
299   int nm_flags,offset;
300
301   bzero((char *)nmb,sizeof(*nmb));
302
303   if (length < 12) return(False);
304
305   /* parse the header */
306   nmb->header.name_trn_id = RSVAL(inbuf,0);
307   nmb->header.opcode = (CVAL(inbuf,2) >> 3) & 0xF;
308   nmb->header.response = ((CVAL(inbuf,2)>>7)&1)?True:False;
309   nm_flags = ((CVAL(inbuf,2) & 0x7) << 4) + (CVAL(inbuf,3)>>4);
310   nmb->header.nm_flags.bcast = (nm_flags&1)?True:False;
311   nmb->header.nm_flags.recursion_available = (nm_flags&8)?True:False;
312   nmb->header.nm_flags.recursion_desired = (nm_flags&0x10)?True:False;
313   nmb->header.nm_flags.trunc = (nm_flags&0x20)?True:False;
314   nmb->header.nm_flags.authoritative = (nm_flags&0x40)?True:False;
315   nmb->header.rcode = CVAL(inbuf,3) & 0xF;
316   nmb->header.qdcount = RSVAL(inbuf,4);
317   nmb->header.ancount = RSVAL(inbuf,6);
318   nmb->header.nscount = RSVAL(inbuf,8);
319   nmb->header.arcount = RSVAL(inbuf,10);
320   
321   if (nmb->header.qdcount) {
322     offset = parse_nmb_name(inbuf,12,length,&nmb->question.question_name);
323     if (!offset) return(False);
324
325     if (length - (12+offset) < 4) return(False);
326     nmb->question.question_type = RSVAL(inbuf,12+offset);
327     nmb->question.question_class = RSVAL(inbuf,12+offset+2);
328
329     offset += 12+4;
330   } else {
331     offset = 12;
332   }
333
334   /* and any resource records */
335   if (nmb->header.ancount && 
336       !parse_alloc_res_rec(inbuf,&offset,length,&nmb->answers,
337                            nmb->header.ancount))
338     return(False);
339
340   if (nmb->header.nscount && 
341       !parse_alloc_res_rec(inbuf,&offset,length,&nmb->nsrecs,
342                            nmb->header.nscount))
343     return(False);
344   
345   if (nmb->header.arcount && 
346       !parse_alloc_res_rec(inbuf,&offset,length,&nmb->additional,
347                            nmb->header.arcount))
348     return(False);
349
350   return(True);
351 }
352
353 /*******************************************************************
354   free up any resources associated with an nmb packet
355   ******************************************************************/
356 void free_nmb_packet(struct nmb_packet *nmb)
357 {  
358   if (nmb->answers) free(nmb->answers);
359   if (nmb->nsrecs) free(nmb->nsrecs);
360   if (nmb->additional) free(nmb->additional);
361 }
362
363 /*******************************************************************
364   free up any resources associated with a packet
365   ******************************************************************/
366 void free_packet(struct packet_struct *packet)
367 {  
368   if (packet->packet_type == NMB_PACKET)
369     free_nmb_packet(&packet->packet.nmb);
370   free(packet);
371 }
372
373 /*******************************************************************
374   read a packet from a socket and parse it, returning a packet ready
375   to be used or put on the queue. This assumes a UDP socket
376   ******************************************************************/
377 struct packet_struct *read_packet(int fd,enum packet_type packet_type)
378 {
379   extern struct in_addr lastip;
380   extern int lastport;
381   struct packet_struct *packet;
382   char buf[MAX_DGRAM_SIZE];
383   int length;
384   BOOL ok=False;
385
386   length = read_udp_socket(fd,buf,sizeof(buf));
387   if (length < MIN_DGRAM_SIZE) return(NULL);
388
389   packet = (struct packet_struct *)malloc(sizeof(*packet));
390   if (!packet) return(NULL);
391
392   packet->next = NULL;
393   packet->prev = NULL;
394   packet->ip = lastip;
395   packet->port = lastport;
396   packet->fd = fd;
397   packet->timestamp = time(NULL);
398   packet->packet_type = packet_type;
399   switch (packet_type) 
400     {
401     case NMB_PACKET:
402       ok = parse_nmb(buf,length,&packet->packet.nmb);
403       break;
404
405     case DGRAM_PACKET:
406       ok = parse_dgram(buf,length,&packet->packet.dgram);
407       break;
408     }
409   if (!ok) {
410     free(packet);
411     return(NULL);
412   }
413
414   num_good_receives++;
415
416   DEBUG(4,("%s received a packet of len %d from (%s) port %d\n",
417            timestring(),length,inet_ntoa(packet->ip),packet->port));
418
419   return(packet);
420 }
421                                          
422
423 /*******************************************************************
424   send a udp packet on a already open socket
425   ******************************************************************/
426 static BOOL send_udp(int fd,char *buf,int len,struct in_addr ip,int port)
427 {
428   BOOL ret;
429   struct sockaddr_in sock_out;
430
431   /* set the address and port */
432   bzero((char *)&sock_out,sizeof(sock_out));
433   putip((char *)&sock_out.sin_addr,(char *)&ip);
434   sock_out.sin_port = htons( port );
435   sock_out.sin_family = AF_INET;
436   
437   DEBUG(4,("%s sending a packet of len %d to (%s) on port %d\n",
438            timestring(),len,inet_ntoa(ip),port));
439         
440   ret = (sendto(fd,buf,len,0,(struct sockaddr *)&sock_out,
441                 sizeof(sock_out)) >= 0);
442
443   if (!ret)
444     DEBUG(0,("Packet send failed to %s(%d) ERRNO=%s\n",
445              inet_ntoa(ip),port,strerror(errno)));
446
447   if (ret)
448     num_good_sends++;
449
450   return(ret);
451 }
452
453 /*******************************************************************
454   build a dgram packet ready for sending
455
456   XXXX This currently doesn't handle packets too big for one
457   datagram. It should split them and use the packet_offset, more and
458   first flags to handle the fragmentation. Yuck.
459   ******************************************************************/
460 static int build_dgram(char *buf,struct packet_struct *p)
461 {
462   struct dgram_packet *dgram = &p->packet.dgram;
463   unsigned char *ubuf = (unsigned char *)buf;
464   int offset=0;
465
466   /* put in the header */
467   ubuf[0] = dgram->header.msg_type;
468   ubuf[1] = (((int)dgram->header.flags.node_type)<<2);
469   if (dgram->header.flags.more) ubuf[1] |= 1;
470   if (dgram->header.flags.first) ubuf[1] |= 2;
471   RSSVAL(ubuf,2,dgram->header.dgm_id);
472   putip(ubuf+4,(char *)&dgram->header.source_ip);
473   RSSVAL(ubuf,8,dgram->header.source_port);
474   RSSVAL(ubuf,12,dgram->header.packet_offset);
475
476   offset = 14;
477
478   if (dgram->header.msg_type == 0x10 ||
479       dgram->header.msg_type == 0x11 ||
480       dgram->header.msg_type == 0x12) {      
481     offset += put_nmb_name((char *)ubuf,offset,&dgram->source_name);
482     offset += put_nmb_name((char *)ubuf,offset,&dgram->dest_name);
483   }
484
485   memcpy(ubuf+offset,dgram->data,dgram->datasize);
486   offset += dgram->datasize;
487
488   /* automatically set the dgm_length */
489   dgram->header.dgm_length = offset;
490   RSSVAL(ubuf,10,dgram->header.dgm_length); 
491
492   return(offset);
493 }
494
495 /*******************************************************************
496   build a nmb name
497   ******************************************************************/
498 void make_nmb_name(struct nmb_name *n,char *name,int type,char *this_scope)
499 {
500   strcpy(n->name,name);
501   strupper(n->name);
502   n->name_type = type;
503   strcpy(n->scope,this_scope);
504 }
505
506
507 /*******************************************************************
508   build a nmb packet ready for sending
509
510   XXXX this currently relies on not being passed something that expands
511   to a packet too big for the buffer. Eventually this should be
512   changed to set the trunc bit so the receiver can request the rest
513   via tcp (when that becomes supported)
514   ******************************************************************/
515 static int build_nmb(char *buf,struct packet_struct *p)
516 {
517   struct nmb_packet *nmb = &p->packet.nmb;
518   unsigned char *ubuf = (unsigned char *)buf;
519   int offset=0;
520
521   /* put in the header */
522   RSSVAL(ubuf,offset,nmb->header.name_trn_id);
523   ubuf[offset+2] = (nmb->header.opcode & 0xF) << 3;
524   if (nmb->header.response) ubuf[offset+2] |= (1<<7);
525   if (nmb->header.nm_flags.authoritative) ubuf[offset+2] |= 0x4;
526   if (nmb->header.nm_flags.trunc) ubuf[offset+2] |= 0x2;
527   if (nmb->header.nm_flags.recursion_desired) ubuf[offset+2] |= 0x1;
528   if (nmb->header.nm_flags.recursion_available) ubuf[offset+3] |= 0x80;
529   if (nmb->header.nm_flags.bcast) ubuf[offset+3] |= 0x10;
530   ubuf[offset+3] |= (nmb->header.rcode & 0xF);
531   RSSVAL(ubuf,offset+4,nmb->header.qdcount);
532   RSSVAL(ubuf,offset+6,nmb->header.ancount);
533   RSSVAL(ubuf,offset+8,nmb->header.nscount);
534   RSSVAL(ubuf,offset+10,nmb->header.arcount);
535   
536   offset += 12;
537   if (nmb->header.qdcount) {
538     /* XXXX this doesn't handle a qdcount of > 1 */
539     offset += put_nmb_name((char *)ubuf,offset,&nmb->question.question_name);
540     RSSVAL(ubuf,offset,nmb->question.question_type);
541     RSSVAL(ubuf,offset+2,nmb->question.question_class);
542     offset += 4;
543   }
544
545   if (nmb->header.ancount)
546     offset += put_res_rec((char *)ubuf,offset,nmb->answers,
547                           nmb->header.ancount);
548
549   if (nmb->header.nscount)
550     offset += put_res_rec((char *)ubuf,offset,nmb->nsrecs,
551                           nmb->header.nscount);
552
553   if (nmb->header.arcount)
554     offset += put_res_rec((char *)ubuf,offset,nmb->additional,
555                           nmb->header.arcount);  
556
557   return(offset);
558 }
559
560
561 /*******************************************************************
562   send a packet_struct
563   ******************************************************************/
564 BOOL send_packet(struct packet_struct *p)
565 {
566   char buf[1024];
567   int len=0;
568
569   bzero(buf,sizeof(buf));
570
571   switch (p->packet_type) 
572     {
573     case NMB_PACKET:
574       len = build_nmb(buf,p);
575       break;
576
577     case DGRAM_PACKET:
578       len = build_dgram(buf,p);
579       break;
580     }
581
582   if (!len) return(False);
583
584   return(send_udp(p->fd,buf,len,p->ip,p->port));
585 }
586
587 /****************************************************************************
588   receive a packet with timeout on a open UDP filedescriptor
589   The timeout is in milliseconds
590   ***************************************************************************/
591 struct packet_struct *receive_packet(int fd,enum packet_type type,int t)
592 {
593   fd_set fds;
594   struct timeval timeout;
595
596   FD_ZERO(&fds);
597   FD_SET(fd,&fds);
598   timeout.tv_sec = t/1000;
599   timeout.tv_usec = 1000*(t%1000);
600
601   sys_select(&fds,&timeout);
602
603   if (FD_ISSET(fd,&fds)) 
604     return(read_packet(fd,type));
605
606   return(NULL);
607 }
608
609
610 /****************************************************************************
611 interpret a node status response
612 ****************************************************************************/
613 static void interpret_node_status(char *p, char *master,char *rname)
614 {
615   int level = (master||rname)?4:0;
616   int numnames = CVAL(p,0);
617   DEBUG(level,("received %d names\n",numnames));
618
619   if (rname) *rname = 0;
620   if (master) *master = 0;
621
622   p += 1;
623   while (numnames--)
624     {
625       char qname[17];
626       int type;
627       fstring flags;
628       *flags = 0;
629       StrnCpy(qname,p,15);
630       type = CVAL(p,15);
631       p += 16;
632
633       if (p[0] & 0x80) strcat(flags,"<GROUP> ");
634       if ((p[0] & 0x60) == 0) strcat(flags,"B ");
635       if ((p[0] & 0x60) == 1) strcat(flags,"P ");
636       if ((p[0] & 0x60) == 2) strcat(flags,"M ");
637       if ((p[0] & 0x60) == 3) strcat(flags,"_ ");
638       if (p[0] & 0x10) strcat(flags,"<DEREGISTERING> ");
639       if (p[0] & 0x08) strcat(flags,"<CONFLICT> ");
640       if (p[0] & 0x04) strcat(flags,"<ACTIVE> ");
641       if (p[0] & 0x02) strcat(flags,"<PERMANENT> ");
642
643       if (master && !*master && type == 0x1d) {
644         StrnCpy(master,qname,15);
645         trim_string(master,NULL," ");
646       }
647
648       if (rname && !*rname && type == 0x20 && !(p[0]&0x80)) {
649         StrnCpy(rname,qname,15);
650         trim_string(rname,NULL," ");
651       }
652       
653       DEBUG(level,("\t%s (type=0x%x)\t%s\n",qname,type,flags));
654       p+=2;
655     }
656   DEBUG(level,("num_good_sends=%d num_good_receives=%d\n",
657                IVAL(p,20),IVAL(p,24)));
658 }
659
660
661 /****************************************************************************
662   do a netbios name status query on a host
663
664   the "master" parameter is a hack used for finding workgroups.
665   **************************************************************************/
666 BOOL name_status(int fd,char *name,int name_type,BOOL recurse,
667                  struct in_addr to_ip,char *master,char *rname,
668                  void (*fn)())
669 {
670   BOOL found=False;
671   int retries = 2;
672   int retry_time = 5000;
673   struct timeval tval;
674   struct packet_struct p;
675   struct packet_struct *p2;
676   struct nmb_packet *nmb = &p.packet.nmb;
677
678   bzero((char *)&p,sizeof(p));
679
680   if (!name_trn_id) name_trn_id = (time(NULL)%(unsigned)0x7FFF) + 
681     (getpid()%(unsigned)100);
682   name_trn_id = (name_trn_id+1) % (unsigned)0x7FFF;
683
684   nmb->header.name_trn_id = name_trn_id;
685   nmb->header.opcode = 0;
686   nmb->header.response = False;
687   nmb->header.nm_flags.bcast = False;
688   nmb->header.nm_flags.recursion_available = CanRecurse;
689   nmb->header.nm_flags.recursion_desired = recurse;
690   nmb->header.nm_flags.trunc = False;
691   nmb->header.nm_flags.authoritative = False;
692   nmb->header.rcode = 0;
693   nmb->header.qdcount = 1;
694   nmb->header.ancount = 0;
695   nmb->header.nscount = 0;
696   nmb->header.arcount = 0;
697
698   make_nmb_name(&nmb->question.question_name,name,name_type,scope);
699
700   nmb->question.question_type = 0x21;
701   nmb->question.question_class = 0x1;
702
703   p.ip = to_ip;
704   p.port = NMB_PORT;
705   p.fd = fd;
706   p.timestamp = time(NULL);
707   p.packet_type = NMB_PACKET;
708
709   GetTimeOfDay(&tval);
710
711   if (!send_packet(&p)) 
712     return(False);
713
714   retries--;
715
716   while (1)
717     {
718       struct timeval tval2;
719       GetTimeOfDay(&tval2);
720       if (TvalDiff(&tval,&tval2) > retry_time) {
721         if (!retries) break;
722         if (!found && !send_packet(&p))
723           return False;
724         GetTimeOfDay(&tval);
725         retries--;
726       }
727
728       if ((p2=receive_packet(fd,NMB_PACKET,90)))
729         {     
730           struct nmb_packet *nmb2 = &p2->packet.nmb;
731           if (nmb->header.name_trn_id != nmb2->header.name_trn_id ||
732               !nmb2->header.response) {
733             /* its not for us - maybe deal with it later */
734             if (fn) 
735               fn(p2);
736             else
737               free_packet(p2);
738             continue;
739           }
740           
741           if (nmb2->header.opcode != 0 ||
742               nmb2->header.nm_flags.bcast ||
743               nmb2->header.rcode ||
744               !nmb2->header.ancount ||
745               nmb2->answers->rr_type != 0x21) {
746             /* XXXX what do we do with this? could be a redirect, but
747                we'll discard it for the moment */
748             free_packet(p2);
749             continue;
750           }
751
752           interpret_node_status(&nmb2->answers->rdata[0], master,rname);
753           free_packet(p2);
754           return(True);
755         }
756     }
757   
758
759   DEBUG(0,("No status response (this is not unusual)\n"));
760
761   return(False);
762 }
763
764
765 /****************************************************************************
766   do a netbios name query to find someones IP
767   ****************************************************************************/
768 BOOL name_query(int fd,char *name,int name_type, 
769                 BOOL bcast,BOOL recurse,
770                 struct in_addr to_ip, struct in_addr *ip,void (*fn)())
771 {
772   BOOL found=False;
773   int retries = 3;
774   int retry_time = bcast?250:2000;
775   struct timeval tval;
776   struct packet_struct p;
777   struct packet_struct *p2;
778   struct nmb_packet *nmb = &p.packet.nmb;
779
780   bzero((char *)&p,sizeof(p));
781
782   if (!name_trn_id) name_trn_id = (time(NULL)%(unsigned)0x7FFF) + 
783     (getpid()%(unsigned)100);
784   name_trn_id = (name_trn_id+1) % (unsigned)0x7FFF;
785
786   nmb->header.name_trn_id = name_trn_id;
787   nmb->header.opcode = 0;
788   nmb->header.response = False;
789   nmb->header.nm_flags.bcast = bcast;
790   nmb->header.nm_flags.recursion_available = CanRecurse;
791   nmb->header.nm_flags.recursion_desired = recurse;
792   nmb->header.nm_flags.trunc = False;
793   nmb->header.nm_flags.authoritative = False;
794   nmb->header.rcode = 0;
795   nmb->header.qdcount = 1;
796   nmb->header.ancount = 0;
797   nmb->header.nscount = 0;
798   nmb->header.arcount = 0;
799
800   make_nmb_name(&nmb->question.question_name,name,name_type,scope);
801
802   nmb->question.question_type = 0x20;
803   nmb->question.question_class = 0x1;
804
805   p.ip = to_ip;
806   p.port = NMB_PORT;
807   p.fd = fd;
808   p.timestamp = time(NULL);
809   p.packet_type = NMB_PACKET;
810
811   GetTimeOfDay(&tval);
812
813   if (!send_packet(&p)) 
814     return(False);
815
816   retries--;
817
818   while (1)
819     {
820       struct timeval tval2;
821       GetTimeOfDay(&tval2);
822       if (TvalDiff(&tval,&tval2) > retry_time) {
823         if (!retries) break;
824         if (!found && !send_packet(&p))
825           return False;
826         GetTimeOfDay(&tval);
827         retries--;
828       }
829
830       if ((p2=receive_packet(fd,NMB_PACKET,90)))
831         {     
832           struct nmb_packet *nmb2 = &p2->packet.nmb;
833           if (nmb->header.name_trn_id != nmb2->header.name_trn_id ||
834               !nmb2->header.response) {
835             /* its not for us - maybe deal with it later 
836                (put it on the queue?) */
837             if (fn) 
838               fn(p2);
839             else
840               free_packet(p2);
841             continue;
842           }
843           
844           if (nmb2->header.opcode != 0 ||
845               nmb2->header.nm_flags.bcast ||
846               nmb2->header.rcode ||
847               !nmb2->header.ancount) {
848             /* XXXX what do we do with this? could be a redirect, but
849                we'll discard it for the moment */
850             free_packet(p2);
851             continue;
852           }
853
854           if (ip) {
855             putip((char *)ip,&nmb2->answers->rdata[2]);
856             DEBUG(fn?3:2,("Got a positive name query response from %s",
857                           inet_ntoa(p2->ip)));
858             DEBUG(fn?3:2,(" (%s)\n",inet_ntoa(*ip)));
859           }
860           found=True; retries=0;
861           free_packet(p2);
862           if (fn) break;
863         }
864     }
865
866   return(found);
867 }
868
869
870 /****************************************************************************
871   construct and send a netbios DGRAM
872
873   Note that this currently sends all answers to port 138. thats the
874   wrong things to do! I should send to the requestors port. XXX
875   **************************************************************************/
876 BOOL send_mailslot_reply(char *mailslot,int fd,char *buf,int len,
877                          char *srcname,char *dstname,
878                          int src_type,int dest_type,
879                          struct in_addr dest_ip,
880                          struct in_addr src_ip)
881 {
882   struct packet_struct p;
883   struct dgram_packet *dgram = &p.packet.dgram;
884   char *ptr,*p2;
885   char tmp[4];
886
887   bzero((char *)&p,sizeof(p));
888
889   dgram->header.msg_type = 0x11; /* DIRECT GROUP DATAGRAM */
890   dgram->header.flags.node_type = M_NODE;
891   dgram->header.flags.first = True;
892   dgram->header.flags.more = False;
893   dgram->header.dgm_id = name_trn_id++;
894   dgram->header.source_ip = src_ip;
895   dgram->header.source_port = DGRAM_PORT;
896   dgram->header.dgm_length = 0; /* let build_dgram() handle this */
897   dgram->header.packet_offset = 0;
898   
899   make_nmb_name(&dgram->source_name,srcname,src_type,scope);
900   make_nmb_name(&dgram->dest_name,dstname,dest_type,scope);
901
902   ptr = &dgram->data[0];
903
904   /* now setup the smb part */
905   ptr -= 4; /* XXX ugliness because of handling of tcp SMB length */
906   memcpy(tmp,ptr,4);
907   set_message(ptr,17,17 + len,True);
908   memcpy(ptr,tmp,4);
909
910   CVAL(ptr,smb_com) = SMBtrans;
911   SSVAL(ptr,smb_vwv1,len);
912   SSVAL(ptr,smb_vwv11,len);
913   SSVAL(ptr,smb_vwv12,70 + strlen(mailslot));
914   SSVAL(ptr,smb_vwv13,3);
915   SSVAL(ptr,smb_vwv14,1);
916   SSVAL(ptr,smb_vwv15,1);
917   SSVAL(ptr,smb_vwv16,2);
918   p2 = smb_buf(ptr);
919   strcpy(p2,mailslot);
920   p2 = skip_string(p2,1);
921
922   memcpy(p2,buf,len);
923   p2 += len;
924
925   dgram->datasize = PTR_DIFF(p2,ptr+4); /* +4 for tcp length */
926
927   p.ip = dest_ip;
928   p.port = DGRAM_PORT;
929   p.fd = fd;
930   p.timestamp = time(NULL);
931   p.packet_type = DGRAM_PACKET;
932
933   return(send_packet(&p));
934 }
935
936