This commit does 3 main things:
[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-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 header: id=%d opcode=%s(%d) response=%s\n",
111            inet_ntoa(p->ip),
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->packet_type == NMB_PACKET)
486     free_nmb_packet(&packet->packet.nmb);
487   free(packet);
488 }
489
490 /*******************************************************************
491   read a packet from a socket and parse it, returning a packet ready
492   to be used or put on the queue. This assumes a UDP socket
493   ******************************************************************/
494 struct packet_struct *read_packet(int fd,enum packet_type packet_type)
495 {
496   extern struct in_addr lastip;
497   extern int lastport;
498   struct packet_struct *packet;
499   char buf[MAX_DGRAM_SIZE];
500   int length;
501   BOOL ok=False;
502   
503   length = read_udp_socket(fd,buf,sizeof(buf));
504   if (length < MIN_DGRAM_SIZE) return(NULL);
505
506   packet = (struct packet_struct *)malloc(sizeof(*packet));
507   if (!packet) return(NULL);
508
509   packet->next = NULL;
510   packet->prev = NULL;
511   packet->ip = lastip;
512   packet->port = lastport;
513   packet->fd = fd;
514   packet->timestamp = time(NULL);
515   packet->packet_type = packet_type;
516   switch (packet_type) 
517     {
518     case NMB_PACKET:
519       ok = parse_nmb(buf,length,&packet->packet.nmb);
520       break;
521
522     case DGRAM_PACKET:
523       ok = parse_dgram(buf,length,&packet->packet.dgram);
524       break;
525     }
526   if (!ok) {
527     DEBUG(10,("parse_nmb: discarding packet id = %d\n", 
528                  packet->packet.nmb.header.name_trn_id));
529     free(packet);
530     return(NULL);
531   }
532
533   num_good_receives++;
534
535   DEBUG(5,("%s received a packet of len %d from (%s) port %d\n",
536            timestring(),length,inet_ntoa(packet->ip),packet->port));
537
538   return(packet);
539 }
540                                          
541
542 /*******************************************************************
543   send a udp packet on a already open socket
544   ******************************************************************/
545 static BOOL send_udp(int fd,char *buf,int len,struct in_addr ip,int port)
546 {
547   BOOL ret;
548   struct sockaddr_in sock_out;
549
550   /* set the address and port */
551   bzero((char *)&sock_out,sizeof(sock_out));
552   putip((char *)&sock_out.sin_addr,(char *)&ip);
553   sock_out.sin_port = htons( port );
554   sock_out.sin_family = AF_INET;
555   
556   DEBUG(5,("%s sending a packet of len %d to (%s) on port %d\n",
557            timestring(),len,inet_ntoa(ip),port));
558         
559   ret = (sendto(fd,buf,len,0,(struct sockaddr *)&sock_out,
560                 sizeof(sock_out)) >= 0);
561
562   if (!ret)
563     DEBUG(0,("Packet send failed to %s(%d) ERRNO=%s\n",
564              inet_ntoa(ip),port,strerror(errno)));
565
566   if (ret)
567     num_good_sends++;
568
569   return(ret);
570 }
571
572 /*******************************************************************
573   build a dgram packet ready for sending
574
575   XXXX This currently doesn't handle packets too big for one
576   datagram. It should split them and use the packet_offset, more and
577   first flags to handle the fragmentation. Yuck.
578   ******************************************************************/
579 static int build_dgram(char *buf,struct packet_struct *p)
580 {
581   struct dgram_packet *dgram = &p->packet.dgram;
582   unsigned char *ubuf = (unsigned char *)buf;
583   int offset=0;
584
585   /* put in the header */
586   ubuf[0] = dgram->header.msg_type;
587   ubuf[1] = (((int)dgram->header.flags.node_type)<<2);
588   if (dgram->header.flags.more) ubuf[1] |= 1;
589   if (dgram->header.flags.first) ubuf[1] |= 2;
590   RSSVAL(ubuf,2,dgram->header.dgm_id);
591   putip(ubuf+4,(char *)&dgram->header.source_ip);
592   RSSVAL(ubuf,8,dgram->header.source_port);
593   RSSVAL(ubuf,12,dgram->header.packet_offset);
594
595   offset = 14;
596
597   if (dgram->header.msg_type == 0x10 ||
598       dgram->header.msg_type == 0x11 ||
599       dgram->header.msg_type == 0x12) {      
600     offset += put_nmb_name((char *)ubuf,offset,&dgram->source_name);
601     offset += put_nmb_name((char *)ubuf,offset,&dgram->dest_name);
602   }
603
604   memcpy(ubuf+offset,dgram->data,dgram->datasize);
605   offset += dgram->datasize;
606
607   /* automatically set the dgm_length */
608   dgram->header.dgm_length = offset;
609   RSSVAL(ubuf,10,dgram->header.dgm_length); 
610
611   return(offset);
612 }
613
614 /*******************************************************************
615   build a nmb name
616   ******************************************************************/
617 void make_nmb_name(struct nmb_name *n,char *name,int type,char *this_scope)
618 {
619   strcpy(n->name,name);
620   strupper(n->name);
621   n->name_type = type;
622   strcpy(n->scope,this_scope);
623 }
624
625
626 /*******************************************************************
627   build a nmb packet ready for sending
628
629   XXXX this currently relies on not being passed something that expands
630   to a packet too big for the buffer. Eventually this should be
631   changed to set the trunc bit so the receiver can request the rest
632   via tcp (when that becomes supported)
633   ******************************************************************/
634 static int build_nmb(char *buf,struct packet_struct *p)
635 {
636   struct nmb_packet *nmb = &p->packet.nmb;
637   unsigned char *ubuf = (unsigned char *)buf;
638   int offset=0;
639
640   /* put in the header */
641   RSSVAL(ubuf,offset,nmb->header.name_trn_id);
642   ubuf[offset+2] = (nmb->header.opcode & 0xF) << 3;
643   if (nmb->header.response) ubuf[offset+2] |= (1<<7);
644   if (nmb->header.nm_flags.authoritative && 
645       nmb->header.response) ubuf[offset+2] |= 0x4;
646   if (nmb->header.nm_flags.trunc) ubuf[offset+2] |= 0x2;
647   if (nmb->header.nm_flags.recursion_desired) ubuf[offset+2] |= 0x1;
648   if (nmb->header.nm_flags.recursion_available &&
649       nmb->header.response) ubuf[offset+3] |= 0x80;
650   if (nmb->header.nm_flags.bcast) ubuf[offset+3] |= 0x10;
651   ubuf[offset+3] |= (nmb->header.rcode & 0xF);
652
653   RSSVAL(ubuf,offset+4,nmb->header.qdcount);
654   RSSVAL(ubuf,offset+6,nmb->header.ancount);
655   RSSVAL(ubuf,offset+8,nmb->header.nscount);
656   RSSVAL(ubuf,offset+10,nmb->header.arcount);
657   
658   offset += 12;
659   if (nmb->header.qdcount) {
660     /* XXXX this doesn't handle a qdcount of > 1 */
661     offset += put_nmb_name((char *)ubuf,offset,&nmb->question.question_name);
662     RSSVAL(ubuf,offset,nmb->question.question_type);
663     RSSVAL(ubuf,offset+2,nmb->question.question_class);
664     offset += 4;
665   }
666
667   if (nmb->header.ancount)
668     offset += put_res_rec((char *)ubuf,offset,nmb->answers,
669                           nmb->header.ancount);
670
671   if (nmb->header.nscount)
672     offset += put_res_rec((char *)ubuf,offset,nmb->nsrecs,
673                           nmb->header.nscount);
674
675   if (nmb->header.arcount)
676     offset += put_res_rec((char *)ubuf,offset,nmb->additional,
677                           nmb->header.arcount);  
678
679   return(offset);
680 }
681
682
683 /*******************************************************************
684   send a packet_struct
685   ******************************************************************/
686 BOOL send_packet(struct packet_struct *p)
687 {
688   char buf[1024];
689   int len=0;
690
691   bzero(buf,sizeof(buf));
692
693   switch (p->packet_type) 
694     {
695     case NMB_PACKET:
696       len = build_nmb(buf,p);
697       break;
698
699     case DGRAM_PACKET:
700       len = build_dgram(buf,p);
701       break;
702     }
703
704   if (!len) return(False);
705
706   return(send_udp(p->fd,buf,len,p->ip,p->port));
707 }
708
709 /****************************************************************************
710   receive a packet with timeout on a open UDP filedescriptor
711   The timeout is in milliseconds
712   ***************************************************************************/
713 struct packet_struct *receive_packet(int fd,enum packet_type type,int t)
714 {
715   fd_set fds;
716   struct timeval timeout;
717
718   FD_ZERO(&fds);
719   FD_SET(fd,&fds);
720   timeout.tv_sec = t/1000;
721   timeout.tv_usec = 1000*(t%1000);
722
723   sys_select(&fds,&timeout);
724
725   if (FD_ISSET(fd,&fds)) 
726     return(read_packet(fd,type));
727
728   return(NULL);
729 }
730
731