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