automatically uppercase server and share names (win95 won't handle
[Samba/gbeck.git] / source / libsmb / nmblib.c
blob7f3bcc9642ac6fba10e19b9038b530d2425a8bf6
1 /*
2 Unix SMB/Netbios implementation.
3 Version 1.9.
4 NBT netbios library routines
5 Copyright (C) Andrew Tridgell 1994-1998
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.
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.
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.
23 #include "includes.h"
25 extern int DEBUGLEVEL;
27 int num_good_sends = 0;
28 int num_good_receives = 0;
30 static struct opcode_names {
31 char *nmb_opcode_name;
32 int opcode;
33 } nmb_header_opcode_names[] = {
34 {"Query", 0 },
35 {"Registration", 5 },
36 {"Release", 6 },
37 {"WACK", 7 },
38 {"Refresh", 8 },
39 {"Refresh(altcode)", 9 },
40 {"Multi-homed Registration", 15 },
41 {0, -1 }
44 /****************************************************************************
45 * Lookup a nmb opcode name.
46 ****************************************************************************/
47 static char *lookup_opcode_name( int opcode )
49 struct opcode_names *op_namep;
50 int i;
52 for(i = 0; nmb_header_opcode_names[i].nmb_opcode_name != 0; i++) {
53 op_namep = &nmb_header_opcode_names[i];
54 if(opcode == op_namep->opcode)
55 return op_namep->nmb_opcode_name;
57 return "<unknown opcode>";
60 /****************************************************************************
61 print out a res_rec structure
62 ****************************************************************************/
63 static void debug_nmb_res_rec(struct res_rec *res, char *hdr)
65 int i, j;
67 DEBUGADD( 4, ( " %s: nmb_name=%s rr_type=%d rr_class=%d ttl=%d\n",
68 hdr,
69 nmb_namestr(&res->rr_name),
70 res->rr_type,
71 res->rr_class,
72 res->ttl ) );
74 if( res->rdlength == 0 || res->rdata == NULL )
75 return;
77 for (i = 0; i < res->rdlength; i+= 16)
79 DEBUGADD(4, (" %s %3x char ", hdr, i));
81 for (j = 0; j < 16; j++)
83 unsigned char x = res->rdata[i+j];
84 if (x < 32 || x > 127) x = '.';
86 if (i+j >= res->rdlength) break;
87 DEBUGADD(4, ("%c", x));
90 DEBUGADD(4, (" hex "));
92 for (j = 0; j < 16; j++)
94 if (i+j >= res->rdlength) break;
95 DEBUGADD(4, ("%02X", (unsigned char)res->rdata[i+j]));
98 DEBUGADD(4, ("\n"));
102 /****************************************************************************
103 process a nmb packet
104 ****************************************************************************/
105 void debug_nmb_packet(struct packet_struct *p)
107 struct nmb_packet *nmb = &p->packet.nmb;
109 if( DEBUGLVL( 4 ) )
111 dbgtext( "nmb packet from %s(%d) header: id=%d opcode=%s(%d) response=%s\n",
112 inet_ntoa(p->ip), p->port,
113 nmb->header.name_trn_id,
114 lookup_opcode_name(nmb->header.opcode),
115 nmb->header.opcode,
116 BOOLSTR(nmb->header.response) );
117 dbgtext( " 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 dbgtext( " 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 );
131 if (nmb->header.qdcount)
133 DEBUGADD( 4, ( " question: q_name=%s q_type=%d q_class=%d\n",
134 nmb_namestr(&nmb->question.question_name),
135 nmb->question.question_type,
136 nmb->question.question_class) );
139 if (nmb->answers && nmb->header.ancount)
141 debug_nmb_res_rec(nmb->answers,"answers");
143 if (nmb->nsrecs && nmb->header.nscount)
145 debug_nmb_res_rec(nmb->nsrecs,"nsrecs");
147 if (nmb->additional && nmb->header.arcount)
149 debug_nmb_res_rec(nmb->additional,"additional");
153 /*******************************************************************
154 handle "compressed" name pointers
155 ******************************************************************/
156 static BOOL handle_name_ptrs(unsigned char *ubuf,int *offset,int length,
157 BOOL *got_pointer,int *ret)
159 int loop_count=0;
161 while ((ubuf[*offset] & 0xC0) == 0xC0) {
162 if (!*got_pointer) (*ret) += 2;
163 (*got_pointer)=True;
164 (*offset) = ((ubuf[*offset] & ~0xC0)<<8) | ubuf[(*offset)+1];
165 if (loop_count++ == 10 || (*offset) < 0 || (*offset)>(length-2)) {
166 return(False);
169 return(True);
172 /*******************************************************************
173 parse a nmb name from "compressed" format to something readable
174 return the space taken by the name, or 0 if the name is invalid
175 ******************************************************************/
176 static int parse_nmb_name(char *inbuf,int offset,int length, struct nmb_name *name)
178 int m,n=0;
179 unsigned char *ubuf = (unsigned char *)inbuf;
180 int ret = 0;
181 BOOL got_pointer=False;
183 if (length - offset < 2) return(0);
185 /* handle initial name pointers */
186 if (!handle_name_ptrs(ubuf,&offset,length,&got_pointer,&ret)) return(0);
188 m = ubuf[offset];
190 if (!m) return(0);
191 if ((m & 0xC0) || offset+m+2 > length) return(0);
193 bzero((char *)name,sizeof(*name));
195 /* the "compressed" part */
196 if (!got_pointer) ret += m + 2;
197 offset++;
198 while (m) {
199 unsigned char c1,c2;
200 c1 = ubuf[offset++]-'A';
201 c2 = ubuf[offset++]-'A';
202 if ((c1 & 0xF0) || (c2 & 0xF0) || (n > sizeof(name->name)-1)) return(0);
203 name->name[n++] = (c1<<4) | c2;
204 m -= 2;
206 name->name[n] = 0;
208 if (n==16) {
209 /* parse out the name type,
210 its always in the 16th byte of the name */
211 name->name_type = ((unsigned char)name->name[15]) & 0xff;
213 /* remove trailing spaces */
214 name->name[15] = 0;
215 n = 14;
216 while (n && name->name[n]==' ') name->name[n--] = 0;
219 /* now the domain parts (if any) */
220 n = 0;
221 while ((m=ubuf[offset])) {
222 /* we can have pointers within the domain part as well */
223 if (!handle_name_ptrs(ubuf,&offset,length,&got_pointer,&ret)) return(0);
225 if (!got_pointer) ret += m+1;
226 if (n) name->scope[n++] = '.';
227 if (m+2+offset>length || n+m+1>sizeof(name->scope)) return(0);
228 offset++;
229 while (m--) name->scope[n++] = (char)ubuf[offset++];
231 name->scope[n++] = 0;
233 return(ret);
237 /*******************************************************************
238 put a compressed nmb name into a buffer. return the length of the
239 compressed name
241 compressed names are really weird. The "compression" doubles the
242 size. The idea is that it also means that compressed names conform
243 to the doman name system. See RFC1002.
244 ******************************************************************/
245 static int put_nmb_name(char *buf,int offset,struct nmb_name *name)
247 int ret,m;
248 fstring buf1;
249 char *p;
251 if (strcmp(name->name,"*") == 0) {
252 /* special case for wildcard name */
253 bzero(buf1,20);
254 buf1[0] = '*';
255 buf1[15] = name->name_type;
256 } else {
257 slprintf(buf1, sizeof(buf1) - 1,"%-15.15s%c",name->name,name->name_type);
260 buf[offset] = 0x20;
262 ret = 34;
264 for (m=0;m<16;m++) {
265 buf[offset+1+2*m] = 'A' + ((buf1[m]>>4)&0xF);
266 buf[offset+2+2*m] = 'A' + (buf1[m]&0xF);
268 offset += 33;
270 buf[offset] = 0;
272 if (name->scope[0]) {
273 /* XXXX this scope handling needs testing */
274 ret += strlen(name->scope) + 1;
275 pstrcpy(&buf[offset+1],name->scope);
277 p = &buf[offset+1];
278 while ((p = strchr(p,'.'))) {
279 buf[offset] = PTR_DIFF(p,&buf[offset]);
280 offset += buf[offset];
281 p = &buf[offset+1];
283 buf[offset] = strlen(&buf[offset+1]);
286 return(ret);
289 /*******************************************************************
290 useful for debugging messages
291 ******************************************************************/
292 char *nmb_namestr(struct nmb_name *n)
294 static int i=0;
295 static fstring ret[4];
296 char *p = ret[i];
298 if (!n->scope[0])
299 slprintf(p,sizeof(fstring)-1, "%s<%02x>",n->name,n->name_type);
300 else
301 slprintf(p,sizeof(fstring)-1, "%s<%02x>.%s",n->name,n->name_type,n->scope);
303 i = (i+1)%4;
304 return(p);
307 /*******************************************************************
308 allocate and parse some resource records
309 ******************************************************************/
310 static BOOL parse_alloc_res_rec(char *inbuf,int *offset,int length,
311 struct res_rec **recs, int count)
313 int i;
314 *recs = (struct res_rec *)malloc(sizeof(**recs)*count);
315 if (!*recs) return(False);
317 bzero(*recs,sizeof(**recs)*count);
319 for (i=0;i<count;i++) {
320 int l = parse_nmb_name(inbuf,*offset,length,&(*recs)[i].rr_name);
321 (*offset) += l;
322 if (!l || (*offset)+10 > length) {
323 free(*recs);
324 return(False);
326 (*recs)[i].rr_type = RSVAL(inbuf,(*offset));
327 (*recs)[i].rr_class = RSVAL(inbuf,(*offset)+2);
328 (*recs)[i].ttl = RIVAL(inbuf,(*offset)+4);
329 (*recs)[i].rdlength = RSVAL(inbuf,(*offset)+8);
330 (*offset) += 10;
331 if ((*recs)[i].rdlength>sizeof((*recs)[i].rdata) ||
332 (*offset)+(*recs)[i].rdlength > length) {
333 free(*recs);
334 return(False);
336 memcpy((*recs)[i].rdata,inbuf+(*offset),(*recs)[i].rdlength);
337 (*offset) += (*recs)[i].rdlength;
339 return(True);
342 /*******************************************************************
343 put a resource record into a packet
344 ******************************************************************/
345 static int put_res_rec(char *buf,int offset,struct res_rec *recs,int count)
347 int ret=0;
348 int i;
350 for (i=0;i<count;i++) {
351 int l = put_nmb_name(buf,offset,&recs[i].rr_name);
352 offset += l;
353 ret += l;
354 RSSVAL(buf,offset,recs[i].rr_type);
355 RSSVAL(buf,offset+2,recs[i].rr_class);
356 RSIVAL(buf,offset+4,recs[i].ttl);
357 RSSVAL(buf,offset+8,recs[i].rdlength);
358 memcpy(buf+offset+10,recs[i].rdata,recs[i].rdlength);
359 offset += 10+recs[i].rdlength;
360 ret += 10+recs[i].rdlength;
363 return(ret);
366 /*******************************************************************
367 put a compressed name pointer record into a packet
368 ******************************************************************/
369 static int put_compressed_name_ptr(unsigned char *buf,int offset,struct res_rec *rec,int ptr_offset)
371 int ret=0;
372 buf[offset] = (0xC0 | ((ptr_offset >> 8) & 0xFF));
373 buf[offset+1] = (ptr_offset & 0xFF);
374 offset += 2;
375 ret += 2;
376 RSSVAL(buf,offset,rec->rr_type);
377 RSSVAL(buf,offset+2,rec->rr_class);
378 RSIVAL(buf,offset+4,rec->ttl);
379 RSSVAL(buf,offset+8,rec->rdlength);
380 memcpy(buf+offset+10,rec->rdata,rec->rdlength);
381 offset += 10+rec->rdlength;
382 ret += 10+rec->rdlength;
384 return(ret);
387 /*******************************************************************
388 parse a dgram packet. Return False if the packet can't be parsed
389 or is invalid for some reason, True otherwise
391 this is documented in section 4.4.1 of RFC1002
392 ******************************************************************/
393 static BOOL parse_dgram(char *inbuf,int length,struct dgram_packet *dgram)
395 int offset;
396 int flags;
398 bzero((char *)dgram,sizeof(*dgram));
400 if (length < 14) return(False);
402 dgram->header.msg_type = CVAL(inbuf,0);
403 flags = CVAL(inbuf,1);
404 dgram->header.flags.node_type = (enum node_type)((flags>>2)&3);
405 if (flags & 1) dgram->header.flags.more = True;
406 if (flags & 2) dgram->header.flags.first = True;
407 dgram->header.dgm_id = RSVAL(inbuf,2);
408 putip((char *)&dgram->header.source_ip,inbuf+4);
409 dgram->header.source_port = RSVAL(inbuf,8);
410 dgram->header.dgm_length = RSVAL(inbuf,10);
411 dgram->header.packet_offset = RSVAL(inbuf,12);
413 offset = 14;
415 if (dgram->header.msg_type == 0x10 ||
416 dgram->header.msg_type == 0x11 ||
417 dgram->header.msg_type == 0x12) {
418 offset += parse_nmb_name(inbuf,offset,length,&dgram->source_name);
419 offset += parse_nmb_name(inbuf,offset,length,&dgram->dest_name);
422 if (offset >= length || (length-offset > sizeof(dgram->data)))
423 return(False);
425 dgram->datasize = length-offset;
426 memcpy(dgram->data,inbuf+offset,dgram->datasize);
428 return(True);
432 /*******************************************************************
433 parse a nmb packet. Return False if the packet can't be parsed
434 or is invalid for some reason, True otherwise
435 ******************************************************************/
436 static BOOL parse_nmb(char *inbuf,int length,struct nmb_packet *nmb)
438 int nm_flags,offset;
440 bzero((char *)nmb,sizeof(*nmb));
442 if (length < 12) return(False);
444 /* parse the header */
445 nmb->header.name_trn_id = RSVAL(inbuf,0);
447 DEBUG(10,("parse_nmb: packet id = %d\n", nmb->header.name_trn_id));
449 nmb->header.opcode = (CVAL(inbuf,2) >> 3) & 0xF;
450 nmb->header.response = ((CVAL(inbuf,2)>>7)&1)?True:False;
451 nm_flags = ((CVAL(inbuf,2) & 0x7) << 4) + (CVAL(inbuf,3)>>4);
452 nmb->header.nm_flags.bcast = (nm_flags&1)?True:False;
453 nmb->header.nm_flags.recursion_available = (nm_flags&8)?True:False;
454 nmb->header.nm_flags.recursion_desired = (nm_flags&0x10)?True:False;
455 nmb->header.nm_flags.trunc = (nm_flags&0x20)?True:False;
456 nmb->header.nm_flags.authoritative = (nm_flags&0x40)?True:False;
457 nmb->header.rcode = CVAL(inbuf,3) & 0xF;
458 nmb->header.qdcount = RSVAL(inbuf,4);
459 nmb->header.ancount = RSVAL(inbuf,6);
460 nmb->header.nscount = RSVAL(inbuf,8);
461 nmb->header.arcount = RSVAL(inbuf,10);
463 if (nmb->header.qdcount) {
464 offset = parse_nmb_name(inbuf,12,length,&nmb->question.question_name);
465 if (!offset) return(False);
467 if (length - (12+offset) < 4) return(False);
468 nmb->question.question_type = RSVAL(inbuf,12+offset);
469 nmb->question.question_class = RSVAL(inbuf,12+offset+2);
471 offset += 12+4;
472 } else {
473 offset = 12;
476 /* and any resource records */
477 if (nmb->header.ancount &&
478 !parse_alloc_res_rec(inbuf,&offset,length,&nmb->answers,
479 nmb->header.ancount))
480 return(False);
482 if (nmb->header.nscount &&
483 !parse_alloc_res_rec(inbuf,&offset,length,&nmb->nsrecs,
484 nmb->header.nscount))
485 return(False);
487 if (nmb->header.arcount &&
488 !parse_alloc_res_rec(inbuf,&offset,length,&nmb->additional,
489 nmb->header.arcount))
490 return(False);
492 return(True);
495 /*******************************************************************
496 'Copy constructor' for an nmb packet
497 ******************************************************************/
498 static struct packet_struct *copy_nmb_packet(struct packet_struct *packet)
500 struct nmb_packet *nmb;
501 struct nmb_packet *copy_nmb;
502 struct packet_struct *pkt_copy;
504 if(( pkt_copy = (struct packet_struct *)malloc(sizeof(*packet))) == NULL)
506 DEBUG(0,("copy_nmb_packet: malloc fail.\n"));
507 return NULL;
510 /* Structure copy of entire thing. */
512 *pkt_copy = *packet;
514 /* Ensure this copy is not locked. */
515 pkt_copy->locked = False;
517 /* Ensure this copy has no resource records. */
518 nmb = &packet->packet.nmb;
519 copy_nmb = &pkt_copy->packet.nmb;
521 copy_nmb->answers = NULL;
522 copy_nmb->nsrecs = NULL;
523 copy_nmb->additional = NULL;
525 /* Now copy any resource records. */
527 if (nmb->answers)
529 if((copy_nmb->answers = (struct res_rec *)
530 malloc(nmb->header.ancount * sizeof(struct res_rec))) == NULL)
531 goto free_and_exit;
532 memcpy((char *)copy_nmb->answers, (char *)nmb->answers,
533 nmb->header.ancount * sizeof(struct res_rec));
535 if (nmb->nsrecs)
537 if((copy_nmb->nsrecs = (struct res_rec *)
538 malloc(nmb->header.nscount * sizeof(struct res_rec))) == NULL)
539 goto free_and_exit;
540 memcpy((char *)copy_nmb->nsrecs, (char *)nmb->nsrecs,
541 nmb->header.nscount * sizeof(struct res_rec));
543 if (nmb->additional)
545 if((copy_nmb->additional = (struct res_rec *)
546 malloc(nmb->header.arcount * sizeof(struct res_rec))) == NULL)
547 goto free_and_exit;
548 memcpy((char *)copy_nmb->additional, (char *)nmb->additional,
549 nmb->header.arcount * sizeof(struct res_rec));
552 return pkt_copy;
554 free_and_exit:
556 if(copy_nmb->answers)
557 free((char *)copy_nmb->answers);
558 if(copy_nmb->nsrecs)
559 free((char *)copy_nmb->nsrecs);
560 if(copy_nmb->additional)
561 free((char *)copy_nmb->additional);
562 free((char *)pkt_copy);
564 DEBUG(0,("copy_nmb_packet: malloc fail in resource records.\n"));
565 return NULL;
568 /*******************************************************************
569 'Copy constructor' for a dgram packet
570 ******************************************************************/
571 static struct packet_struct *copy_dgram_packet(struct packet_struct *packet)
573 struct packet_struct *pkt_copy;
575 if(( pkt_copy = (struct packet_struct *)malloc(sizeof(*packet))) == NULL)
577 DEBUG(0,("copy_dgram_packet: malloc fail.\n"));
578 return NULL;
581 /* Structure copy of entire thing. */
583 *pkt_copy = *packet;
585 /* Ensure this copy is not locked. */
586 pkt_copy->locked = False;
588 /* There are no additional pointers in a dgram packet,
589 we are finished. */
590 return pkt_copy;
593 /*******************************************************************
594 'Copy constructor' for a generic packet
595 ******************************************************************/
596 struct packet_struct *copy_packet(struct packet_struct *packet)
598 if(packet->packet_type == NMB_PACKET)
599 return copy_nmb_packet(packet);
600 else if (packet->packet_type == DGRAM_PACKET)
601 return copy_dgram_packet(packet);
602 return NULL;
605 /*******************************************************************
606 free up any resources associated with an nmb packet
607 ******************************************************************/
608 static void free_nmb_packet(struct nmb_packet *nmb)
610 if (nmb->answers) free(nmb->answers);
611 if (nmb->nsrecs) free(nmb->nsrecs);
612 if (nmb->additional) free(nmb->additional);
615 /*******************************************************************
616 free up any resources associated with a dgram packet
617 ******************************************************************/
618 static void free_dgram_packet(struct dgram_packet *nmb)
620 /* We have nothing to do for a dgram packet. */
623 /*******************************************************************
624 free up any resources associated with a packet
625 ******************************************************************/
626 void free_packet(struct packet_struct *packet)
628 if (packet->locked)
629 return;
630 if (packet->packet_type == NMB_PACKET)
631 free_nmb_packet(&packet->packet.nmb);
632 else if (packet->packet_type == DGRAM_PACKET)
633 free_dgram_packet(&packet->packet.dgram);
634 free(packet);
637 /*******************************************************************
638 read a packet from a socket and parse it, returning a packet ready
639 to be used or put on the queue. This assumes a UDP socket
640 ******************************************************************/
641 struct packet_struct *read_packet(int fd,enum packet_type packet_type)
643 extern struct in_addr lastip;
644 extern int lastport;
645 struct packet_struct *packet;
646 char buf[MAX_DGRAM_SIZE];
647 int length;
648 BOOL ok=False;
650 length = read_udp_socket(fd,buf,sizeof(buf));
651 if (length < MIN_DGRAM_SIZE) return(NULL);
653 packet = (struct packet_struct *)malloc(sizeof(*packet));
654 if (!packet) return(NULL);
656 packet->next = NULL;
657 packet->prev = NULL;
658 packet->ip = lastip;
659 packet->port = lastport;
660 packet->fd = fd;
661 packet->locked = False;
662 packet->timestamp = time(NULL);
663 packet->packet_type = packet_type;
664 switch (packet_type)
666 case NMB_PACKET:
667 ok = parse_nmb(buf,length,&packet->packet.nmb);
668 break;
670 case DGRAM_PACKET:
671 ok = parse_dgram(buf,length,&packet->packet.dgram);
672 break;
674 if (!ok) {
675 DEBUG(10,("parse_nmb: discarding packet id = %d\n",
676 packet->packet.nmb.header.name_trn_id));
677 free(packet);
678 return(NULL);
681 num_good_receives++;
683 DEBUG(5,("Received a packet of len %d from (%s) port %d\n",
684 length, inet_ntoa(packet->ip), packet->port ) );
686 return(packet);
690 /*******************************************************************
691 send a udp packet on a already open socket
692 ******************************************************************/
693 static BOOL send_udp(int fd,char *buf,int len,struct in_addr ip,int port)
695 BOOL ret;
696 struct sockaddr_in sock_out;
698 /* set the address and port */
699 bzero((char *)&sock_out,sizeof(sock_out));
700 putip((char *)&sock_out.sin_addr,(char *)&ip);
701 sock_out.sin_port = htons( port );
702 sock_out.sin_family = AF_INET;
704 DEBUG( 5, ( "Sending a packet of len %d to (%s) on port %d\n",
705 len, inet_ntoa(ip), port ) );
707 ret = (sendto(fd,buf,len,0,(struct sockaddr *)&sock_out,
708 sizeof(sock_out)) >= 0);
710 if (!ret)
711 DEBUG(0,("Packet send failed to %s(%d) ERRNO=%s\n",
712 inet_ntoa(ip),port,strerror(errno)));
714 if (ret)
715 num_good_sends++;
717 return(ret);
720 /*******************************************************************
721 build a dgram packet ready for sending
723 XXXX This currently doesn't handle packets too big for one
724 datagram. It should split them and use the packet_offset, more and
725 first flags to handle the fragmentation. Yuck.
726 ******************************************************************/
727 static int build_dgram(char *buf,struct packet_struct *p)
729 struct dgram_packet *dgram = &p->packet.dgram;
730 unsigned char *ubuf = (unsigned char *)buf;
731 int offset=0;
733 /* put in the header */
734 ubuf[0] = dgram->header.msg_type;
735 ubuf[1] = (((int)dgram->header.flags.node_type)<<2);
736 if (dgram->header.flags.more) ubuf[1] |= 1;
737 if (dgram->header.flags.first) ubuf[1] |= 2;
738 RSSVAL(ubuf,2,dgram->header.dgm_id);
739 putip(ubuf+4,(char *)&dgram->header.source_ip);
740 RSSVAL(ubuf,8,dgram->header.source_port);
741 RSSVAL(ubuf,12,dgram->header.packet_offset);
743 offset = 14;
745 if (dgram->header.msg_type == 0x10 ||
746 dgram->header.msg_type == 0x11 ||
747 dgram->header.msg_type == 0x12) {
748 offset += put_nmb_name((char *)ubuf,offset,&dgram->source_name);
749 offset += put_nmb_name((char *)ubuf,offset,&dgram->dest_name);
752 memcpy(ubuf+offset,dgram->data,dgram->datasize);
753 offset += dgram->datasize;
755 /* automatically set the dgm_length */
756 dgram->header.dgm_length = offset;
757 RSSVAL(ubuf,10,dgram->header.dgm_length);
759 return(offset);
762 /*******************************************************************
763 build a nmb name
764 *******************************************************************/
765 void make_nmb_name( struct nmb_name *n, const char *name, int type, const char *this_scope )
767 memset( (char *)n, '\0', sizeof(struct nmb_name) );
768 StrnCpy( n->name, name, 15 );
769 strupper( n->name );
770 n->name_type = (unsigned int)type & 0xFF;
771 StrnCpy( n->scope, this_scope, 63 );
772 strupper( n->scope );
775 /*******************************************************************
776 Compare two nmb names
777 ******************************************************************/
779 BOOL nmb_name_equal(struct nmb_name *n1, struct nmb_name *n2)
781 return ((n1->name_type == n2->name_type) &&
782 strequal(n1->name ,n2->name ) &&
783 strequal(n1->scope,n2->scope));
786 /*******************************************************************
787 build a nmb packet ready for sending
789 XXXX this currently relies on not being passed something that expands
790 to a packet too big for the buffer. Eventually this should be
791 changed to set the trunc bit so the receiver can request the rest
792 via tcp (when that becomes supported)
793 ******************************************************************/
794 static int build_nmb(char *buf,struct packet_struct *p)
796 struct nmb_packet *nmb = &p->packet.nmb;
797 unsigned char *ubuf = (unsigned char *)buf;
798 int offset=0;
800 /* put in the header */
801 RSSVAL(ubuf,offset,nmb->header.name_trn_id);
802 ubuf[offset+2] = (nmb->header.opcode & 0xF) << 3;
803 if (nmb->header.response) ubuf[offset+2] |= (1<<7);
804 if (nmb->header.nm_flags.authoritative &&
805 nmb->header.response) ubuf[offset+2] |= 0x4;
806 if (nmb->header.nm_flags.trunc) ubuf[offset+2] |= 0x2;
807 if (nmb->header.nm_flags.recursion_desired) ubuf[offset+2] |= 0x1;
808 if (nmb->header.nm_flags.recursion_available &&
809 nmb->header.response) ubuf[offset+3] |= 0x80;
810 if (nmb->header.nm_flags.bcast) ubuf[offset+3] |= 0x10;
811 ubuf[offset+3] |= (nmb->header.rcode & 0xF);
813 RSSVAL(ubuf,offset+4,nmb->header.qdcount);
814 RSSVAL(ubuf,offset+6,nmb->header.ancount);
815 RSSVAL(ubuf,offset+8,nmb->header.nscount);
816 RSSVAL(ubuf,offset+10,nmb->header.arcount);
818 offset += 12;
819 if (nmb->header.qdcount) {
820 /* XXXX this doesn't handle a qdcount of > 1 */
821 offset += put_nmb_name((char *)ubuf,offset,&nmb->question.question_name);
822 RSSVAL(ubuf,offset,nmb->question.question_type);
823 RSSVAL(ubuf,offset+2,nmb->question.question_class);
824 offset += 4;
827 if (nmb->header.ancount)
828 offset += put_res_rec((char *)ubuf,offset,nmb->answers,
829 nmb->header.ancount);
831 if (nmb->header.nscount)
832 offset += put_res_rec((char *)ubuf,offset,nmb->nsrecs,
833 nmb->header.nscount);
836 * The spec says we must put compressed name pointers
837 * in the following outgoing packets :
838 * NAME_REGISTRATION_REQUEST, NAME_REFRESH_REQUEST,
839 * NAME_RELEASE_REQUEST.
842 if((nmb->header.response == False) &&
843 ((nmb->header.opcode == NMB_NAME_REG_OPCODE) ||
844 (nmb->header.opcode == NMB_NAME_RELEASE_OPCODE) ||
845 (nmb->header.opcode == NMB_NAME_REFRESH_OPCODE_8) ||
846 (nmb->header.opcode == NMB_NAME_REFRESH_OPCODE_9) ||
847 (nmb->header.opcode == NMB_NAME_MULTIHOMED_REG_OPCODE)) &&
848 (nmb->header.arcount == 1)) {
850 offset += put_compressed_name_ptr(ubuf,offset,nmb->additional,12);
852 } else if (nmb->header.arcount) {
853 offset += put_res_rec((char *)ubuf,offset,nmb->additional,
854 nmb->header.arcount);
856 return(offset);
860 /*******************************************************************
861 send a packet_struct
862 ******************************************************************/
863 BOOL send_packet(struct packet_struct *p)
865 char buf[1024];
866 int len=0;
868 bzero(buf,sizeof(buf));
870 switch (p->packet_type)
872 case NMB_PACKET:
873 len = build_nmb(buf,p);
874 debug_nmb_packet(p);
875 break;
877 case DGRAM_PACKET:
878 len = build_dgram(buf,p);
879 break;
882 if (!len) return(False);
884 return(send_udp(p->fd,buf,len,p->ip,p->port));
887 /****************************************************************************
888 receive a packet with timeout on a open UDP filedescriptor
889 The timeout is in milliseconds
890 ***************************************************************************/
891 struct packet_struct *receive_packet(int fd,enum packet_type type,int t)
893 fd_set fds;
894 struct timeval timeout;
896 FD_ZERO(&fds);
897 FD_SET(fd,&fds);
898 timeout.tv_sec = t/1000;
899 timeout.tv_usec = 1000*(t%1000);
901 sys_select(fd+1,&fds,&timeout);
903 if (FD_ISSET(fd,&fds))
904 return(read_packet(fd,type));
906 return(NULL);
910 /****************************************************************************
911 return the number of bits that match between two 4 character buffers
912 ***************************************************************************/
913 static int matching_bits(uchar *p1, uchar *p2)
915 int i, j, ret = 0;
916 for (i=0; i<4; i++) {
917 if (p1[i] != p2[i]) break;
918 ret += 8;
921 if (i==4) return ret;
923 for (j=0; j<8; j++) {
924 if ((p1[i] & (1<<(7-j))) != (p2[i] & (1<<(7-j)))) break;
925 ret++;
928 return ret;
932 static uchar sort_ip[4];
934 /****************************************************************************
935 compare two query reply records
936 ***************************************************************************/
937 static int name_query_comp(uchar *p1, uchar *p2)
939 return matching_bits(p2+2, sort_ip) - matching_bits(p1+2, sort_ip);
942 /****************************************************************************
943 sort a set of 6 byte name query response records so that the IPs that
944 have the most leading bits in common with the specified address come first
945 ***************************************************************************/
946 void sort_query_replies(char *data, int n, struct in_addr ip)
948 if (n <= 1) return;
950 putip(sort_ip, (char *)&ip);
952 qsort(data, n, 6, QSORT_CAST name_query_comp);