6a91b20ea87fe1cffae34e2e8c670ca268ac55be
[kai/samba.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-1997
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 int num_good_sends = 0;
28 int num_good_receives = 0;
29 extern pstring scope;
30 extern pstring myname;
31 extern struct in_addr ipzero;
32
33 static struct opcode_names {
34         char *nmb_opcode_name;
35         int opcode;
36 } nmb_header_opcode_names[] = {
37       { "Query",           0 },
38       {"Registration",      5 },
39       {"Release",           6 },
40       {"WACK",              7 },
41       {"refresh",           8 },
42       {0, -1 }
43 };
44
45 /****************************************************************************
46  * Lookup a nmb opcode name.
47  ****************************************************************************/
48
49 char *lookup_opcode_name( int opcode )
50 {
51   struct opcode_names *op_namep;
52   int i;
53
54   for(i = 0; nmb_header_opcode_names[i].nmb_opcode_name != 0; i++) {
55     op_namep = &nmb_header_opcode_names[i];
56     if(opcode == op_namep->opcode)
57       return op_namep->nmb_opcode_name;
58   }
59   return "<unknown opcode>";
60 }
61
62 /****************************************************************************
63   print out a res_rec structure
64   ****************************************************************************/
65 static void debug_nmb_res_rec(struct res_rec *res, char *hdr)
66 {
67   int i, j;
68
69   DEBUG(4,("    %s: nmb_name=%s rr_type=%d rr_class=%d ttl=%d\n",
70            hdr,
71            namestr(&res->rr_name),
72            res->rr_type,
73            res->rr_class,
74            res->ttl));
75                 
76   if (res->rdlength == 0 || res->rdata == NULL) return;
77
78   for (i = 0; i < res->rdlength; i+= 16)
79     {
80       DEBUG(4, ("    %s %3x char ", hdr, i));
81
82       for (j = 0; j < 16; j++)
83         {
84           unsigned char x = res->rdata[i+j];
85           if (x < 32 || x > 127) x = '.';
86           
87           if (i+j >= res->rdlength) break;
88           DEBUG(4, ("%c", x));
89         }
90       
91       DEBUG(4, ("   hex ", i));
92
93       for (j = 0; j < 16; j++)
94         {
95           if (i+j >= res->rdlength) break;
96           DEBUG(4, ("%02X", (unsigned char)res->rdata[i+j]));
97         }
98       
99       DEBUG(4, ("\n"));
100     }
101 }
102
103 /****************************************************************************
104   process a nmb packet
105   ****************************************************************************/
106 void debug_nmb_packet(struct packet_struct *p)
107 {
108   struct nmb_packet *nmb = &p->packet.nmb;
109   
110   DEBUG(4,("nmb packet from %s(%d) header: id=%d opcode=%s(%d) response=%s\n",
111            inet_ntoa(p->ip), p->port,
112            nmb->header.name_trn_id,
113            lookup_opcode_name(nmb->header.opcode),
114            nmb->header.opcode,BOOLSTR(nmb->header.response)));
115   DEBUG(4,("    header: flags: bcast=%s rec_avail=%s rec_des=%s trunc=%s auth=%s\n",
116            BOOLSTR(nmb->header.nm_flags.bcast),
117            BOOLSTR(nmb->header.nm_flags.recursion_available),
118            BOOLSTR(nmb->header.nm_flags.recursion_desired),
119            BOOLSTR(nmb->header.nm_flags.trunc),
120            BOOLSTR(nmb->header.nm_flags.authoritative)));
121   DEBUG(4,("    header: rcode=%d qdcount=%d ancount=%d nscount=%d arcount=%d\n",
122            nmb->header.rcode,
123            nmb->header.qdcount,
124            nmb->header.ancount,
125            nmb->header.nscount,
126            nmb->header.arcount));
127
128   if (nmb->header.qdcount)
129     {
130       DEBUG(4,("    question: q_name=%s q_type=%d q_class=%d\n",
131                namestr(&nmb->question.question_name),
132                nmb->question.question_type,
133                nmb->question.question_class));
134     }
135
136   if (nmb->answers && nmb->header.ancount) 
137     {
138       debug_nmb_res_rec(nmb->answers,"answers");
139     }
140   if (nmb->nsrecs && nmb->header.nscount)
141     {
142       debug_nmb_res_rec(nmb->nsrecs,"nsrecs");
143     }
144   if (nmb->additional && nmb->header.arcount)
145     {
146       debug_nmb_res_rec(nmb->additional,"additional");
147     }
148 }
149
150 /*******************************************************************
151   handle "compressed" name pointers
152   ******************************************************************/
153 static BOOL handle_name_ptrs(unsigned char *ubuf,int *offset,int length,
154                              BOOL *got_pointer,int *ret)
155 {
156   int loop_count=0;
157   
158   while ((ubuf[*offset] & 0xC0) == 0xC0) {
159     if (!*got_pointer) (*ret) += 2;
160     (*got_pointer)=True;
161     (*offset) = ((ubuf[*offset] & ~0xC0)<<8) | ubuf[(*offset)+1];
162     if (loop_count++ == 10 || (*offset) < 0 || (*offset)>(length-2)) {
163       return(False);
164     }
165   }
166   return(True);
167 }
168
169 /*******************************************************************
170   parse a nmb name from "compressed" format to something readable
171   return the space taken by the name, or 0 if the name is invalid
172   ******************************************************************/
173 static int parse_nmb_name(char *inbuf,int offset,int length, struct nmb_name *name)
174 {
175   int m,n=0;
176   unsigned char *ubuf = (unsigned char *)inbuf;
177   int ret = 0;
178   BOOL got_pointer=False;
179
180   if (length - offset < 2) return(0);  
181
182   /* handle initial name pointers */
183   if (!handle_name_ptrs(ubuf,&offset,length,&got_pointer,&ret)) return(0);
184   
185   m = ubuf[offset];
186
187   if (!m) return(0);
188   if ((m & 0xC0) || offset+m+2 > length) return(0);
189
190   bzero((char *)name,sizeof(*name));
191
192   /* the "compressed" part */
193   if (!got_pointer) ret += m + 2;
194   offset++;
195   while (m) {
196     unsigned char c1,c2;
197     c1 = ubuf[offset++]-'A';
198     c2 = ubuf[offset++]-'A';
199     if ((c1 & 0xF0) || (c2 & 0xF0)) return(0);
200     name->name[n++] = (c1<<4) | c2;
201     m -= 2;
202   }
203   name->name[n] = 0;
204
205   if (n==16) {
206     /* parse out the name type, 
207        its always in the 16th byte of the name */
208     name->name_type = name->name[15];
209   
210     /* remove trailing spaces */
211     name->name[15] = 0;
212     n = 14;
213     while (n && name->name[n]==' ') name->name[n--] = 0;  
214   }
215
216   /* now the domain parts (if any) */
217   n = 0;
218   while ((m=ubuf[offset])) {
219     /* we can have pointers within the domain part as well */
220     if (!handle_name_ptrs(ubuf,&offset,length,&got_pointer,&ret)) return(0);
221
222     if (!got_pointer) ret += m+1;
223     if (n) name->scope[n++] = '.';
224     if (m+2+offset>length || n+m+1>sizeof(name->scope)) return(0);
225     offset++;
226     while (m--) name->scope[n++] = (char)ubuf[offset++];
227   }
228   name->scope[n++] = 0;  
229
230   return(ret);
231 }
232
233
234 /*******************************************************************
235   put a compressed nmb name into a buffer. return the length of the
236   compressed name
237
238   compressed names are really weird. The "compression" doubles the
239   size. The idea is that it also means that compressed names conform
240   to the doman name system. See RFC1002.
241   ******************************************************************/
242 static int put_nmb_name(char *buf,int offset,struct nmb_name *name)
243 {
244   int ret,m;
245   fstring buf1;
246   char *p;
247
248   if (name->name[0] == '*') {
249     /* special case for wildcard name */
250     bzero(buf1,20);
251     buf1[0] = '*';
252   } else {
253     sprintf(buf1,"%-15.15s%c",name->name,name->name_type);
254   }
255
256   buf[offset] = 0x20;
257
258   ret = 34;
259
260   for (m=0;m<16;m++) {
261     buf[offset+1+2*m] = 'A' + ((buf1[m]>>4)&0xF);
262     buf[offset+2+2*m] = 'A' + (buf1[m]&0xF);
263   }
264   offset += 33;
265
266   buf[offset] = 0;
267
268   if (name->scope[0]) {
269     /* XXXX this scope handling needs testing */
270     ret += strlen(name->scope) + 1;
271     strcpy(&buf[offset+1],name->scope);  
272   
273     p = &buf[offset+1];
274     while ((p = strchr(p,'.'))) {
275       buf[offset] = PTR_DIFF(p,&buf[offset]);
276       offset += buf[offset];
277       p = &buf[offset+1];
278     }
279     buf[offset] = strlen(&buf[offset+1]);
280   }
281
282   return(ret);
283 }
284
285 /*******************************************************************
286   useful for debugging messages
287   ******************************************************************/
288 char *namestr(struct nmb_name *n)
289 {
290   static int i=0;
291   static fstring ret[4];
292   char *p = ret[i];
293
294   if (!n->scope[0])
295     sprintf(p,"%s(%x)",n->name,n->name_type);
296   else
297     sprintf(p,"%s(%x).%s",n->name,n->name_type,n->scope);
298
299   i = (i+1)%4;
300   return(p);
301 }
302
303 /*******************************************************************
304   allocate and parse some resource records
305   ******************************************************************/
306 static BOOL parse_alloc_res_rec(char *inbuf,int *offset,int length,
307                                 struct res_rec **recs, int count)
308 {
309   int i;
310   *recs = (struct res_rec *)malloc(sizeof(**recs)*count);
311   if (!*recs) return(False);
312
313   bzero(*recs,sizeof(**recs)*count);
314
315   for (i=0;i<count;i++) {
316     int l = parse_nmb_name(inbuf,*offset,length,&(*recs)[i].rr_name);
317     (*offset) += l;
318     if (!l || (*offset)+10 > length) {
319       free(*recs);
320       return(False);
321     }
322     (*recs)[i].rr_type = RSVAL(inbuf,(*offset));
323     (*recs)[i].rr_class = RSVAL(inbuf,(*offset)+2);
324     (*recs)[i].ttl = RIVAL(inbuf,(*offset)+4);
325     (*recs)[i].rdlength = RSVAL(inbuf,(*offset)+8);
326     (*offset) += 10;
327     if ((*recs)[i].rdlength>sizeof((*recs)[i].rdata) || 
328         (*offset)+(*recs)[i].rdlength > length) {
329       free(*recs);
330       return(False);
331     }
332     memcpy((*recs)[i].rdata,inbuf+(*offset),(*recs)[i].rdlength);
333     (*offset) += (*recs)[i].rdlength;    
334   }
335   return(True);
336 }
337
338 /*******************************************************************
339   put a resource record into a packet
340   ******************************************************************/
341 static int put_res_rec(char *buf,int offset,struct res_rec *recs,int count)
342 {
343   int ret=0;
344   int i;
345
346   for (i=0;i<count;i++) {
347     int l = put_nmb_name(buf,offset,&recs[i].rr_name);
348     offset += l;
349     ret += l;
350     RSSVAL(buf,offset,recs[i].rr_type);
351     RSSVAL(buf,offset+2,recs[i].rr_class);
352     RSIVAL(buf,offset+4,recs[i].ttl);
353     RSSVAL(buf,offset+8,recs[i].rdlength);
354     memcpy(buf+offset+10,recs[i].rdata,recs[i].rdlength);
355     offset += 10+recs[i].rdlength;
356     ret += 10+recs[i].rdlength;
357   }
358
359   return(ret);
360 }
361
362 /*******************************************************************
363   parse a dgram packet. Return False if the packet can't be parsed 
364   or is invalid for some reason, True otherwise 
365
366   this is documented in section 4.4.1 of RFC1002
367   ******************************************************************/
368 static BOOL parse_dgram(char *inbuf,int length,struct dgram_packet *dgram)
369 {
370   int offset;
371   int flags;
372
373   bzero((char *)dgram,sizeof(*dgram));
374
375   if (length < 14) return(False);
376
377   dgram->header.msg_type = CVAL(inbuf,0);
378   flags = CVAL(inbuf,1);
379   dgram->header.flags.node_type = (enum node_type)((flags>>2)&3);
380   if (flags & 1) dgram->header.flags.more = True;
381   if (flags & 2) dgram->header.flags.first = True;
382   dgram->header.dgm_id = RSVAL(inbuf,2);
383   putip((char *)&dgram->header.source_ip,inbuf+4);
384   dgram->header.source_port = RSVAL(inbuf,8);
385   dgram->header.dgm_length = RSVAL(inbuf,10);
386   dgram->header.packet_offset = RSVAL(inbuf,12);
387
388   offset = 14;
389
390   if (dgram->header.msg_type == 0x10 ||
391       dgram->header.msg_type == 0x11 ||
392       dgram->header.msg_type == 0x12) {      
393     offset += parse_nmb_name(inbuf,offset,length,&dgram->source_name);
394     offset += parse_nmb_name(inbuf,offset,length,&dgram->dest_name);
395   }
396
397   if (offset >= length || (length-offset > sizeof(dgram->data))) 
398     return(False);
399
400   dgram->datasize = length-offset;
401   memcpy(dgram->data,inbuf+offset,dgram->datasize);
402
403   return(True);
404 }
405
406
407 /*******************************************************************
408   parse a nmb packet. Return False if the packet can't be parsed 
409   or is invalid for some reason, True otherwise 
410   ******************************************************************/
411 static BOOL parse_nmb(char *inbuf,int length,struct nmb_packet *nmb)
412 {
413   int nm_flags,offset;
414
415   bzero((char *)nmb,sizeof(*nmb));
416
417   if (length < 12) return(False);
418
419   /* parse the header */
420   nmb->header.name_trn_id = RSVAL(inbuf,0);
421
422   DEBUG(10,("parse_nmb: packet id = %d\n", nmb->header.name_trn_id));
423
424   nmb->header.opcode = (CVAL(inbuf,2) >> 3) & 0xF;
425   nmb->header.response = ((CVAL(inbuf,2)>>7)&1)?True:False;
426   nm_flags = ((CVAL(inbuf,2) & 0x7) << 4) + (CVAL(inbuf,3)>>4);
427   nmb->header.nm_flags.bcast = (nm_flags&1)?True:False;
428   nmb->header.nm_flags.recursion_available = (nm_flags&8)?True:False;
429   nmb->header.nm_flags.recursion_desired = (nm_flags&0x10)?True:False;
430   nmb->header.nm_flags.trunc = (nm_flags&0x20)?True:False;
431   nmb->header.nm_flags.authoritative = (nm_flags&0x40)?True:False;  
432   nmb->header.rcode = CVAL(inbuf,3) & 0xF;
433   nmb->header.qdcount = RSVAL(inbuf,4);
434   nmb->header.ancount = RSVAL(inbuf,6);
435   nmb->header.nscount = RSVAL(inbuf,8);
436   nmb->header.arcount = RSVAL(inbuf,10);
437   
438   if (nmb->header.qdcount) {
439     offset = parse_nmb_name(inbuf,12,length,&nmb->question.question_name);
440     if (!offset) return(False);
441
442     if (length - (12+offset) < 4) return(False);
443     nmb->question.question_type = RSVAL(inbuf,12+offset);
444     nmb->question.question_class = RSVAL(inbuf,12+offset+2);
445
446     offset += 12+4;
447   } else {
448     offset = 12;
449   }
450
451   /* and any resource records */
452   if (nmb->header.ancount && 
453       !parse_alloc_res_rec(inbuf,&offset,length,&nmb->answers,
454                            nmb->header.ancount))
455     return(False);
456
457   if (nmb->header.nscount && 
458       !parse_alloc_res_rec(inbuf,&offset,length,&nmb->nsrecs,
459                            nmb->header.nscount))
460     return(False);
461   
462   if (nmb->header.arcount && 
463       !parse_alloc_res_rec(inbuf,&offset,length,&nmb->additional,
464                            nmb->header.arcount))
465     return(False);
466
467   return(True);
468 }
469
470 /*******************************************************************
471   free up any resources associated with an nmb packet
472   ******************************************************************/
473 void free_nmb_packet(struct nmb_packet *nmb)
474 {  
475   if (nmb->answers) free(nmb->answers);
476   if (nmb->nsrecs) free(nmb->nsrecs);
477   if (nmb->additional) free(nmb->additional);
478 }
479
480 /*******************************************************************
481   free up any resources associated with a packet
482   ******************************************************************/
483 void free_packet(struct packet_struct *packet)
484 {  
485         if (packet->locked) 
486                 return;
487         if (packet->packet_type == NMB_PACKET)
488                 free_nmb_packet(&packet->packet.nmb);
489         free(packet);
490 }
491
492 /*******************************************************************
493   read a packet from a socket and parse it, returning a packet ready
494   to be used or put on the queue. This assumes a UDP socket
495   ******************************************************************/
496 struct packet_struct *read_packet(int fd,enum packet_type packet_type)
497 {
498   extern struct in_addr lastip;
499   extern int lastport;
500   struct packet_struct *packet;
501   char buf[MAX_DGRAM_SIZE];
502   int length;
503   BOOL ok=False;
504   
505   length = read_udp_socket(fd,buf,sizeof(buf));
506   if (length < MIN_DGRAM_SIZE) return(NULL);
507
508   packet = (struct packet_struct *)malloc(sizeof(*packet));
509   if (!packet) return(NULL);
510
511   packet->next = NULL;
512   packet->prev = NULL;
513   packet->ip = lastip;
514   packet->port = lastport;
515   packet->fd = fd;
516   packet->locked = False;
517   packet->timestamp = time(NULL);
518   packet->packet_type = packet_type;
519   switch (packet_type) 
520     {
521     case NMB_PACKET:
522       ok = parse_nmb(buf,length,&packet->packet.nmb);
523       break;
524
525     case DGRAM_PACKET:
526       ok = parse_dgram(buf,length,&packet->packet.dgram);
527       break;
528     }
529   if (!ok) {
530     DEBUG(10,("parse_nmb: discarding packet id = %d\n", 
531                  packet->packet.nmb.header.name_trn_id));
532     free(packet);
533     return(NULL);
534   }
535
536   num_good_receives++;
537
538   DEBUG(5,("%s received a packet of len %d from (%s) port %d\n",
539            timestring(),length,inet_ntoa(packet->ip),packet->port));
540
541   return(packet);
542 }
543                                          
544
545 /*******************************************************************
546   send a udp packet on a already open socket
547   ******************************************************************/
548 static BOOL send_udp(int fd,char *buf,int len,struct in_addr ip,int port)
549 {
550   BOOL ret;
551   struct sockaddr_in sock_out;
552
553   /* set the address and port */
554   bzero((char *)&sock_out,sizeof(sock_out));
555   putip((char *)&sock_out.sin_addr,(char *)&ip);
556   sock_out.sin_port = htons( port );
557   sock_out.sin_family = AF_INET;
558   
559   DEBUG(5,("%s sending a packet of len %d to (%s) on port %d\n",
560            timestring(),len,inet_ntoa(ip),port));
561         
562   ret = (sendto(fd,buf,len,0,(struct sockaddr *)&sock_out,
563                 sizeof(sock_out)) >= 0);
564
565   if (!ret)
566     DEBUG(0,("Packet send failed to %s(%d) ERRNO=%s\n",
567              inet_ntoa(ip),port,strerror(errno)));
568
569   if (ret)
570     num_good_sends++;
571
572   return(ret);
573 }
574
575 /*******************************************************************
576   build a dgram packet ready for sending
577
578   XXXX This currently doesn't handle packets too big for one
579   datagram. It should split them and use the packet_offset, more and
580   first flags to handle the fragmentation. Yuck.
581   ******************************************************************/
582 static int build_dgram(char *buf,struct packet_struct *p)
583 {
584   struct dgram_packet *dgram = &p->packet.dgram;
585   unsigned char *ubuf = (unsigned char *)buf;
586   int offset=0;
587
588   /* put in the header */
589   ubuf[0] = dgram->header.msg_type;
590   ubuf[1] = (((int)dgram->header.flags.node_type)<<2);
591   if (dgram->header.flags.more) ubuf[1] |= 1;
592   if (dgram->header.flags.first) ubuf[1] |= 2;
593   RSSVAL(ubuf,2,dgram->header.dgm_id);
594   putip(ubuf+4,(char *)&dgram->header.source_ip);
595   RSSVAL(ubuf,8,dgram->header.source_port);
596   RSSVAL(ubuf,12,dgram->header.packet_offset);
597
598   offset = 14;
599
600   if (dgram->header.msg_type == 0x10 ||
601       dgram->header.msg_type == 0x11 ||
602       dgram->header.msg_type == 0x12) {      
603     offset += put_nmb_name((char *)ubuf,offset,&dgram->source_name);
604     offset += put_nmb_name((char *)ubuf,offset,&dgram->dest_name);
605   }
606
607   memcpy(ubuf+offset,dgram->data,dgram->datasize);
608   offset += dgram->datasize;
609
610   /* automatically set the dgm_length */
611   dgram->header.dgm_length = offset;
612   RSSVAL(ubuf,10,dgram->header.dgm_length); 
613
614   return(offset);
615 }
616
617 /*******************************************************************
618   build a nmb name
619   ******************************************************************/
620 void make_nmb_name(struct nmb_name *n,char *name,int type,char *this_scope)
621 {
622   fstrcpy(n->name,name);
623   strupper(n->name);
624   n->name_type = type;
625   fstrcpy(n->scope,this_scope);
626 }
627
628
629 /*******************************************************************
630   build a nmb packet ready for sending
631
632   XXXX this currently relies on not being passed something that expands
633   to a packet too big for the buffer. Eventually this should be
634   changed to set the trunc bit so the receiver can request the rest
635   via tcp (when that becomes supported)
636   ******************************************************************/
637 static int build_nmb(char *buf,struct packet_struct *p)
638 {
639   struct nmb_packet *nmb = &p->packet.nmb;
640   unsigned char *ubuf = (unsigned char *)buf;
641   int offset=0;
642
643   /* put in the header */
644   RSSVAL(ubuf,offset,nmb->header.name_trn_id);
645   ubuf[offset+2] = (nmb->header.opcode & 0xF) << 3;
646   if (nmb->header.response) ubuf[offset+2] |= (1<<7);
647   if (nmb->header.nm_flags.authoritative && 
648       nmb->header.response) ubuf[offset+2] |= 0x4;
649   if (nmb->header.nm_flags.trunc) ubuf[offset+2] |= 0x2;
650   if (nmb->header.nm_flags.recursion_desired) ubuf[offset+2] |= 0x1;
651   if (nmb->header.nm_flags.recursion_available &&
652       nmb->header.response) ubuf[offset+3] |= 0x80;
653   if (nmb->header.nm_flags.bcast) ubuf[offset+3] |= 0x10;
654   ubuf[offset+3] |= (nmb->header.rcode & 0xF);
655
656   RSSVAL(ubuf,offset+4,nmb->header.qdcount);
657   RSSVAL(ubuf,offset+6,nmb->header.ancount);
658   RSSVAL(ubuf,offset+8,nmb->header.nscount);
659   RSSVAL(ubuf,offset+10,nmb->header.arcount);
660   
661   offset += 12;
662   if (nmb->header.qdcount) {
663     /* XXXX this doesn't handle a qdcount of > 1 */
664     offset += put_nmb_name((char *)ubuf,offset,&nmb->question.question_name);
665     RSSVAL(ubuf,offset,nmb->question.question_type);
666     RSSVAL(ubuf,offset+2,nmb->question.question_class);
667     offset += 4;
668   }
669
670   if (nmb->header.ancount)
671     offset += put_res_rec((char *)ubuf,offset,nmb->answers,
672                           nmb->header.ancount);
673
674   if (nmb->header.nscount)
675     offset += put_res_rec((char *)ubuf,offset,nmb->nsrecs,
676                           nmb->header.nscount);
677
678   if (nmb->header.arcount)
679     offset += put_res_rec((char *)ubuf,offset,nmb->additional,
680                           nmb->header.arcount);  
681
682   return(offset);
683 }
684
685
686 /*******************************************************************
687   send a packet_struct
688   ******************************************************************/
689 BOOL send_packet(struct packet_struct *p)
690 {
691   char buf[1024];
692   int len=0;
693
694   bzero(buf,sizeof(buf));
695
696   switch (p->packet_type) 
697     {
698     case NMB_PACKET:
699       len = build_nmb(buf,p);
700       debug_nmb_packet(p);
701       break;
702
703     case DGRAM_PACKET:
704       len = build_dgram(buf,p);
705       break;
706     }
707
708   if (!len) return(False);
709
710   return(send_udp(p->fd,buf,len,p->ip,p->port));
711 }
712
713 /****************************************************************************
714   receive a packet with timeout on a open UDP filedescriptor
715   The timeout is in milliseconds
716   ***************************************************************************/
717 struct packet_struct *receive_packet(int fd,enum packet_type type,int t)
718 {
719   fd_set fds;
720   struct timeval timeout;
721
722   FD_ZERO(&fds);
723   FD_SET(fd,&fds);
724   timeout.tv_sec = t/1000;
725   timeout.tv_usec = 1000*(t%1000);
726
727   sys_select(&fds,&timeout);
728
729   if (FD_ISSET(fd,&fds)) 
730     return(read_packet(fd,type));
731
732   return(NULL);
733 }
734
735