2 Unix SMB/Netbios implementation.
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.
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;
33 } nmb_header_opcode_names[] = {
39 {"Refresh(altcode)", 9 },
40 {"Multi-homed Registration", 15 },
44 /****************************************************************************
45 * Lookup a nmb opcode name.
46 ****************************************************************************/
48 char *lookup_opcode_name( int opcode )
50 struct opcode_names *op_namep;
53 for(i = 0; nmb_header_opcode_names[i].nmb_opcode_name != 0; i++) {
54 op_namep = &nmb_header_opcode_names[i];
55 if(opcode == op_namep->opcode)
56 return op_namep->nmb_opcode_name;
58 return "<unknown opcode>";
61 /****************************************************************************
62 print out a res_rec structure
63 ****************************************************************************/
64 static void debug_nmb_res_rec(struct res_rec *res, char *hdr)
68 DEBUGADD( 4, ( " %s: nmb_name=%s rr_type=%d rr_class=%d ttl=%d\n",
70 namestr(&res->rr_name),
75 if( res->rdlength == 0 || res->rdata == NULL )
78 for (i = 0; i < res->rdlength; i+= 16)
80 DEBUGADD(4, (" %s %3x char ", hdr, i));
82 for (j = 0; j < 16; j++)
84 unsigned char x = res->rdata[i+j];
85 if (x < 32 || x > 127) x = '.';
87 if (i+j >= res->rdlength) break;
88 DEBUGADD(4, ("%c", x));
91 DEBUGADD(4, (" hex "));
93 for (j = 0; j < 16; j++)
95 if (i+j >= res->rdlength) break;
96 DEBUGADD(4, ("%02X", (unsigned char)res->rdata[i+j]));
103 /****************************************************************************
105 ****************************************************************************/
106 void debug_nmb_packet(struct packet_struct *p)
108 struct nmb_packet *nmb = &p->packet.nmb;
112 dbgtext( "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),
117 BOOLSTR(nmb->header.response) );
118 dbgtext( " header: flags: bcast=%s rec_avail=%s rec_des=%s trunc=%s auth=%s\n",
119 BOOLSTR(nmb->header.nm_flags.bcast),
120 BOOLSTR(nmb->header.nm_flags.recursion_available),
121 BOOLSTR(nmb->header.nm_flags.recursion_desired),
122 BOOLSTR(nmb->header.nm_flags.trunc),
123 BOOLSTR(nmb->header.nm_flags.authoritative) );
124 dbgtext( " header: rcode=%d qdcount=%d ancount=%d nscount=%d arcount=%d\n",
129 nmb->header.arcount );
132 if (nmb->header.qdcount)
134 DEBUGADD( 4, ( " question: q_name=%s q_type=%d q_class=%d\n",
135 namestr(&nmb->question.question_name),
136 nmb->question.question_type,
137 nmb->question.question_class) );
140 if (nmb->answers && nmb->header.ancount)
142 debug_nmb_res_rec(nmb->answers,"answers");
144 if (nmb->nsrecs && nmb->header.nscount)
146 debug_nmb_res_rec(nmb->nsrecs,"nsrecs");
148 if (nmb->additional && nmb->header.arcount)
150 debug_nmb_res_rec(nmb->additional,"additional");
154 /*******************************************************************
155 handle "compressed" name pointers
156 ******************************************************************/
157 static BOOL handle_name_ptrs(unsigned char *ubuf,int *offset,int length,
158 BOOL *got_pointer,int *ret)
162 while ((ubuf[*offset] & 0xC0) == 0xC0) {
163 if (!*got_pointer) (*ret) += 2;
165 (*offset) = ((ubuf[*offset] & ~0xC0)<<8) | ubuf[(*offset)+1];
166 if (loop_count++ == 10 || (*offset) < 0 || (*offset)>(length-2)) {
173 /*******************************************************************
174 parse a nmb name from "compressed" format to something readable
175 return the space taken by the name, or 0 if the name is invalid
176 ******************************************************************/
177 static int parse_nmb_name(char *inbuf,int offset,int length, struct nmb_name *name)
180 unsigned char *ubuf = (unsigned char *)inbuf;
182 BOOL got_pointer=False;
184 if (length - offset < 2) return(0);
186 /* handle initial name pointers */
187 if (!handle_name_ptrs(ubuf,&offset,length,&got_pointer,&ret)) return(0);
192 if ((m & 0xC0) || offset+m+2 > length) return(0);
194 bzero((char *)name,sizeof(*name));
196 /* the "compressed" part */
197 if (!got_pointer) ret += m + 2;
201 c1 = ubuf[offset++]-'A';
202 c2 = ubuf[offset++]-'A';
203 if ((c1 & 0xF0) || (c2 & 0xF0) || (n > sizeof(name->name)-1)) return(0);
204 name->name[n++] = (c1<<4) | c2;
210 /* parse out the name type,
211 its always in the 16th byte of the name */
212 name->name_type = ((unsigned char)name->name[15]) & 0xff;
214 /* remove trailing spaces */
217 while (n && name->name[n]==' ') name->name[n--] = 0;
220 /* now the domain parts (if any) */
222 while ((m=ubuf[offset])) {
223 /* we can have pointers within the domain part as well */
224 if (!handle_name_ptrs(ubuf,&offset,length,&got_pointer,&ret)) return(0);
226 if (!got_pointer) ret += m+1;
227 if (n) name->scope[n++] = '.';
228 if (m+2+offset>length || n+m+1>sizeof(name->scope)) return(0);
230 while (m--) name->scope[n++] = (char)ubuf[offset++];
232 name->scope[n++] = 0;
238 /*******************************************************************
239 put a compressed nmb name into a buffer. return the length of the
242 compressed names are really weird. The "compression" doubles the
243 size. The idea is that it also means that compressed names conform
244 to the doman name system. See RFC1002.
245 ******************************************************************/
246 static int put_nmb_name(char *buf,int offset,struct nmb_name *name)
252 if (name->name[0] == '*') {
253 /* special case for wildcard name */
256 buf1[15] = name->name_type;
258 slprintf(buf1, sizeof(buf1) - 1,"%-15.15s%c",name->name,name->name_type);
266 buf[offset+1+2*m] = 'A' + ((buf1[m]>>4)&0xF);
267 buf[offset+2+2*m] = 'A' + (buf1[m]&0xF);
273 if (name->scope[0]) {
274 /* XXXX this scope handling needs testing */
275 ret += strlen(name->scope) + 1;
276 pstrcpy(&buf[offset+1],name->scope);
279 while ((p = strchr(p,'.'))) {
280 buf[offset] = PTR_DIFF(p,&buf[offset]);
281 offset += buf[offset];
284 buf[offset] = strlen(&buf[offset+1]);
290 /*******************************************************************
291 useful for debugging messages
292 ******************************************************************/
293 char *namestr(struct nmb_name *n)
296 static fstring ret[4];
300 slprintf(p,sizeof(fstring)-1, "%s<%02x>",n->name,n->name_type);
302 slprintf(p,sizeof(fstring)-1, "%s<%02x>.%s",n->name,n->name_type,n->scope);
308 /*******************************************************************
309 allocate and parse some resource records
310 ******************************************************************/
311 static BOOL parse_alloc_res_rec(char *inbuf,int *offset,int length,
312 struct res_rec **recs, int count)
315 *recs = (struct res_rec *)malloc(sizeof(**recs)*count);
316 if (!*recs) return(False);
318 bzero(*recs,sizeof(**recs)*count);
320 for (i=0;i<count;i++) {
321 int l = parse_nmb_name(inbuf,*offset,length,&(*recs)[i].rr_name);
323 if (!l || (*offset)+10 > length) {
327 (*recs)[i].rr_type = RSVAL(inbuf,(*offset));
328 (*recs)[i].rr_class = RSVAL(inbuf,(*offset)+2);
329 (*recs)[i].ttl = RIVAL(inbuf,(*offset)+4);
330 (*recs)[i].rdlength = RSVAL(inbuf,(*offset)+8);
332 if ((*recs)[i].rdlength>sizeof((*recs)[i].rdata) ||
333 (*offset)+(*recs)[i].rdlength > length) {
337 memcpy((*recs)[i].rdata,inbuf+(*offset),(*recs)[i].rdlength);
338 (*offset) += (*recs)[i].rdlength;
343 /*******************************************************************
344 put a resource record into a packet
345 ******************************************************************/
346 static int put_res_rec(char *buf,int offset,struct res_rec *recs,int count)
351 for (i=0;i<count;i++) {
352 int l = put_nmb_name(buf,offset,&recs[i].rr_name);
355 RSSVAL(buf,offset,recs[i].rr_type);
356 RSSVAL(buf,offset+2,recs[i].rr_class);
357 RSIVAL(buf,offset+4,recs[i].ttl);
358 RSSVAL(buf,offset+8,recs[i].rdlength);
359 memcpy(buf+offset+10,recs[i].rdata,recs[i].rdlength);
360 offset += 10+recs[i].rdlength;
361 ret += 10+recs[i].rdlength;
367 /*******************************************************************
368 put a compressed name pointer record into a packet
369 ******************************************************************/
370 static int put_compressed_name_ptr(unsigned char *buf,int offset,struct res_rec *rec,int ptr_offset)
373 buf[offset] = (0xC0 | ((ptr_offset >> 8) & 0xFF));
374 buf[offset+1] = (ptr_offset & 0xFF);
377 RSSVAL(buf,offset,rec->rr_type);
378 RSSVAL(buf,offset+2,rec->rr_class);
379 RSIVAL(buf,offset+4,rec->ttl);
380 RSSVAL(buf,offset+8,rec->rdlength);
381 memcpy(buf+offset+10,rec->rdata,rec->rdlength);
382 offset += 10+rec->rdlength;
383 ret += 10+rec->rdlength;
388 /*******************************************************************
389 parse a dgram packet. Return False if the packet can't be parsed
390 or is invalid for some reason, True otherwise
392 this is documented in section 4.4.1 of RFC1002
393 ******************************************************************/
394 static BOOL parse_dgram(char *inbuf,int length,struct dgram_packet *dgram)
399 bzero((char *)dgram,sizeof(*dgram));
401 if (length < 14) return(False);
403 dgram->header.msg_type = CVAL(inbuf,0);
404 flags = CVAL(inbuf,1);
405 dgram->header.flags.node_type = (enum node_type)((flags>>2)&3);
406 if (flags & 1) dgram->header.flags.more = True;
407 if (flags & 2) dgram->header.flags.first = True;
408 dgram->header.dgm_id = RSVAL(inbuf,2);
409 putip((char *)&dgram->header.source_ip,inbuf+4);
410 dgram->header.source_port = RSVAL(inbuf,8);
411 dgram->header.dgm_length = RSVAL(inbuf,10);
412 dgram->header.packet_offset = RSVAL(inbuf,12);
416 if (dgram->header.msg_type == 0x10 ||
417 dgram->header.msg_type == 0x11 ||
418 dgram->header.msg_type == 0x12) {
419 offset += parse_nmb_name(inbuf,offset,length,&dgram->source_name);
420 offset += parse_nmb_name(inbuf,offset,length,&dgram->dest_name);
423 if (offset >= length || (length-offset > sizeof(dgram->data)))
426 dgram->datasize = length-offset;
427 memcpy(dgram->data,inbuf+offset,dgram->datasize);
433 /*******************************************************************
434 parse a nmb packet. Return False if the packet can't be parsed
435 or is invalid for some reason, True otherwise
436 ******************************************************************/
437 static BOOL parse_nmb(char *inbuf,int length,struct nmb_packet *nmb)
441 bzero((char *)nmb,sizeof(*nmb));
443 if (length < 12) return(False);
445 /* parse the header */
446 nmb->header.name_trn_id = RSVAL(inbuf,0);
448 DEBUG(10,("parse_nmb: packet id = %d\n", nmb->header.name_trn_id));
450 nmb->header.opcode = (CVAL(inbuf,2) >> 3) & 0xF;
451 nmb->header.response = ((CVAL(inbuf,2)>>7)&1)?True:False;
452 nm_flags = ((CVAL(inbuf,2) & 0x7) << 4) + (CVAL(inbuf,3)>>4);
453 nmb->header.nm_flags.bcast = (nm_flags&1)?True:False;
454 nmb->header.nm_flags.recursion_available = (nm_flags&8)?True:False;
455 nmb->header.nm_flags.recursion_desired = (nm_flags&0x10)?True:False;
456 nmb->header.nm_flags.trunc = (nm_flags&0x20)?True:False;
457 nmb->header.nm_flags.authoritative = (nm_flags&0x40)?True:False;
458 nmb->header.rcode = CVAL(inbuf,3) & 0xF;
459 nmb->header.qdcount = RSVAL(inbuf,4);
460 nmb->header.ancount = RSVAL(inbuf,6);
461 nmb->header.nscount = RSVAL(inbuf,8);
462 nmb->header.arcount = RSVAL(inbuf,10);
464 if (nmb->header.qdcount) {
465 offset = parse_nmb_name(inbuf,12,length,&nmb->question.question_name);
466 if (!offset) return(False);
468 if (length - (12+offset) < 4) return(False);
469 nmb->question.question_type = RSVAL(inbuf,12+offset);
470 nmb->question.question_class = RSVAL(inbuf,12+offset+2);
477 /* and any resource records */
478 if (nmb->header.ancount &&
479 !parse_alloc_res_rec(inbuf,&offset,length,&nmb->answers,
480 nmb->header.ancount))
483 if (nmb->header.nscount &&
484 !parse_alloc_res_rec(inbuf,&offset,length,&nmb->nsrecs,
485 nmb->header.nscount))
488 if (nmb->header.arcount &&
489 !parse_alloc_res_rec(inbuf,&offset,length,&nmb->additional,
490 nmb->header.arcount))
496 /*******************************************************************
497 'Copy constructor' for an nmb packet
498 ******************************************************************/
499 static struct packet_struct *copy_nmb_packet(struct packet_struct *packet)
501 struct nmb_packet *nmb;
502 struct nmb_packet *copy_nmb;
503 struct packet_struct *pkt_copy;
505 if(( pkt_copy = (struct packet_struct *)malloc(sizeof(*packet))) == NULL)
507 DEBUG(0,("copy_nmb_packet: malloc fail.\n"));
511 /* Structure copy of entire thing. */
515 /* Ensure this copy is not locked. */
516 pkt_copy->locked = False;
518 /* Ensure this copy has no resource records. */
519 nmb = &packet->packet.nmb;
520 copy_nmb = &pkt_copy->packet.nmb;
522 copy_nmb->answers = NULL;
523 copy_nmb->nsrecs = NULL;
524 copy_nmb->additional = NULL;
526 /* Now copy any resource records. */
530 if((copy_nmb->answers = (struct res_rec *)
531 malloc(nmb->header.ancount * sizeof(struct res_rec))) == NULL)
533 memcpy((char *)copy_nmb->answers, (char *)nmb->answers,
534 nmb->header.ancount * sizeof(struct res_rec));
538 if((copy_nmb->nsrecs = (struct res_rec *)
539 malloc(nmb->header.nscount * sizeof(struct res_rec))) == NULL)
541 memcpy((char *)copy_nmb->nsrecs, (char *)nmb->nsrecs,
542 nmb->header.nscount * sizeof(struct res_rec));
546 if((copy_nmb->additional = (struct res_rec *)
547 malloc(nmb->header.arcount * sizeof(struct res_rec))) == NULL)
549 memcpy((char *)copy_nmb->additional, (char *)nmb->additional,
550 nmb->header.arcount * sizeof(struct res_rec));
557 if(copy_nmb->answers)
558 free((char *)copy_nmb->answers);
560 free((char *)copy_nmb->nsrecs);
561 if(copy_nmb->additional)
562 free((char *)copy_nmb->additional);
563 free((char *)pkt_copy);
565 DEBUG(0,("copy_nmb_packet: malloc fail in resource records.\n"));
569 /*******************************************************************
570 'Copy constructor' for a dgram packet
571 ******************************************************************/
572 static struct packet_struct *copy_dgram_packet(struct packet_struct *packet)
574 struct packet_struct *pkt_copy;
576 if(( pkt_copy = (struct packet_struct *)malloc(sizeof(*packet))) == NULL)
578 DEBUG(0,("copy_dgram_packet: malloc fail.\n"));
582 /* Structure copy of entire thing. */
586 /* Ensure this copy is not locked. */
587 pkt_copy->locked = False;
589 /* There are no additional pointers in a dgram packet,
594 /*******************************************************************
595 'Copy constructor' for a generic packet
596 ******************************************************************/
597 struct packet_struct *copy_packet(struct packet_struct *packet)
599 if(packet->packet_type == NMB_PACKET)
600 return copy_nmb_packet(packet);
601 else if (packet->packet_type == DGRAM_PACKET)
602 return copy_dgram_packet(packet);
606 /*******************************************************************
607 free up any resources associated with an nmb packet
608 ******************************************************************/
609 static void free_nmb_packet(struct nmb_packet *nmb)
611 if (nmb->answers) free(nmb->answers);
612 if (nmb->nsrecs) free(nmb->nsrecs);
613 if (nmb->additional) free(nmb->additional);
616 /*******************************************************************
617 free up any resources associated with a dgram packet
618 ******************************************************************/
619 static void free_dgram_packet(struct dgram_packet *nmb)
621 /* We have nothing to do for a dgram packet. */
624 /*******************************************************************
625 free up any resources associated with a packet
626 ******************************************************************/
627 void free_packet(struct packet_struct *packet)
631 if (packet->packet_type == NMB_PACKET)
632 free_nmb_packet(&packet->packet.nmb);
633 else if (packet->packet_type == DGRAM_PACKET)
634 free_dgram_packet(&packet->packet.dgram);
638 /*******************************************************************
639 read a packet from a socket and parse it, returning a packet ready
640 to be used or put on the queue. This assumes a UDP socket
641 ******************************************************************/
642 struct packet_struct *read_packet(int fd,enum packet_type packet_type)
644 extern struct in_addr lastip;
646 struct packet_struct *packet;
647 char buf[MAX_DGRAM_SIZE];
651 length = read_udp_socket(fd,buf,sizeof(buf));
652 if (length < MIN_DGRAM_SIZE) return(NULL);
654 packet = (struct packet_struct *)malloc(sizeof(*packet));
655 if (!packet) return(NULL);
660 packet->port = lastport;
662 packet->locked = False;
663 packet->timestamp = time(NULL);
664 packet->packet_type = packet_type;
668 ok = parse_nmb(buf,length,&packet->packet.nmb);
672 ok = parse_dgram(buf,length,&packet->packet.dgram);
676 DEBUG(10,("parse_nmb: discarding packet id = %d\n",
677 packet->packet.nmb.header.name_trn_id));
684 DEBUG(5,("Received a packet of len %d from (%s) port %d\n",
685 length, inet_ntoa(packet->ip), packet->port ) );
691 /*******************************************************************
692 send a udp packet on a already open socket
693 ******************************************************************/
694 static BOOL send_udp(int fd,char *buf,int len,struct in_addr ip,int port)
697 struct sockaddr_in sock_out;
699 /* set the address and port */
700 bzero((char *)&sock_out,sizeof(sock_out));
701 putip((char *)&sock_out.sin_addr,(char *)&ip);
702 sock_out.sin_port = htons( port );
703 sock_out.sin_family = AF_INET;
705 DEBUG( 5, ( "Sending a packet of len %d to (%s) on port %d\n",
706 len, inet_ntoa(ip), port ) );
708 ret = (sendto(fd,buf,len,0,(struct sockaddr *)&sock_out,
709 sizeof(sock_out)) >= 0);
712 DEBUG(0,("Packet send failed to %s(%d) ERRNO=%s\n",
713 inet_ntoa(ip),port,strerror(errno)));
721 /*******************************************************************
722 build a dgram packet ready for sending
724 XXXX This currently doesn't handle packets too big for one
725 datagram. It should split them and use the packet_offset, more and
726 first flags to handle the fragmentation. Yuck.
727 ******************************************************************/
728 static int build_dgram(char *buf,struct packet_struct *p)
730 struct dgram_packet *dgram = &p->packet.dgram;
731 unsigned char *ubuf = (unsigned char *)buf;
734 /* put in the header */
735 ubuf[0] = dgram->header.msg_type;
736 ubuf[1] = (((int)dgram->header.flags.node_type)<<2);
737 if (dgram->header.flags.more) ubuf[1] |= 1;
738 if (dgram->header.flags.first) ubuf[1] |= 2;
739 RSSVAL(ubuf,2,dgram->header.dgm_id);
740 putip(ubuf+4,(char *)&dgram->header.source_ip);
741 RSSVAL(ubuf,8,dgram->header.source_port);
742 RSSVAL(ubuf,12,dgram->header.packet_offset);
746 if (dgram->header.msg_type == 0x10 ||
747 dgram->header.msg_type == 0x11 ||
748 dgram->header.msg_type == 0x12) {
749 offset += put_nmb_name((char *)ubuf,offset,&dgram->source_name);
750 offset += put_nmb_name((char *)ubuf,offset,&dgram->dest_name);
753 memcpy(ubuf+offset,dgram->data,dgram->datasize);
754 offset += dgram->datasize;
756 /* automatically set the dgm_length */
757 dgram->header.dgm_length = offset;
758 RSSVAL(ubuf,10,dgram->header.dgm_length);
763 /*******************************************************************
765 *******************************************************************/
766 void make_nmb_name( struct nmb_name *n, char *name, int type, char *this_scope )
768 memset( (char *)n, '\0', sizeof(struct nmb_name) );
769 StrnCpy( n->name, name, 15 );
771 n->name_type = (unsigned int)type & 0xFF;
772 StrnCpy( n->scope, this_scope, 63 );
773 strupper( n->scope );
776 /*******************************************************************
777 Compare two nmb names
778 ******************************************************************/
780 BOOL nmb_name_equal(struct nmb_name *n1, struct nmb_name *n2)
782 return ((n1->name_type == n2->name_type) &&
783 strequal(n1->name ,n2->name ) &&
784 strequal(n1->scope,n2->scope));
787 /*******************************************************************
788 build a nmb packet ready for sending
790 XXXX this currently relies on not being passed something that expands
791 to a packet too big for the buffer. Eventually this should be
792 changed to set the trunc bit so the receiver can request the rest
793 via tcp (when that becomes supported)
794 ******************************************************************/
795 static int build_nmb(char *buf,struct packet_struct *p)
797 struct nmb_packet *nmb = &p->packet.nmb;
798 unsigned char *ubuf = (unsigned char *)buf;
801 /* put in the header */
802 RSSVAL(ubuf,offset,nmb->header.name_trn_id);
803 ubuf[offset+2] = (nmb->header.opcode & 0xF) << 3;
804 if (nmb->header.response) ubuf[offset+2] |= (1<<7);
805 if (nmb->header.nm_flags.authoritative &&
806 nmb->header.response) ubuf[offset+2] |= 0x4;
807 if (nmb->header.nm_flags.trunc) ubuf[offset+2] |= 0x2;
808 if (nmb->header.nm_flags.recursion_desired) ubuf[offset+2] |= 0x1;
809 if (nmb->header.nm_flags.recursion_available &&
810 nmb->header.response) ubuf[offset+3] |= 0x80;
811 if (nmb->header.nm_flags.bcast) ubuf[offset+3] |= 0x10;
812 ubuf[offset+3] |= (nmb->header.rcode & 0xF);
814 RSSVAL(ubuf,offset+4,nmb->header.qdcount);
815 RSSVAL(ubuf,offset+6,nmb->header.ancount);
816 RSSVAL(ubuf,offset+8,nmb->header.nscount);
817 RSSVAL(ubuf,offset+10,nmb->header.arcount);
820 if (nmb->header.qdcount) {
821 /* XXXX this doesn't handle a qdcount of > 1 */
822 offset += put_nmb_name((char *)ubuf,offset,&nmb->question.question_name);
823 RSSVAL(ubuf,offset,nmb->question.question_type);
824 RSSVAL(ubuf,offset+2,nmb->question.question_class);
828 if (nmb->header.ancount)
829 offset += put_res_rec((char *)ubuf,offset,nmb->answers,
830 nmb->header.ancount);
832 if (nmb->header.nscount)
833 offset += put_res_rec((char *)ubuf,offset,nmb->nsrecs,
834 nmb->header.nscount);
837 * The spec says we must put compressed name pointers
838 * in the following outgoing packets :
839 * NAME_REGISTRATION_REQUEST, NAME_REFRESH_REQUEST,
840 * NAME_RELEASE_REQUEST.
843 if((nmb->header.response == False) &&
844 ((nmb->header.opcode == NMB_NAME_REG_OPCODE) ||
845 (nmb->header.opcode == NMB_NAME_RELEASE_OPCODE) ||
846 (nmb->header.opcode == NMB_NAME_REFRESH_OPCODE_8) ||
847 (nmb->header.opcode == NMB_NAME_REFRESH_OPCODE_9) ||
848 (nmb->header.opcode == NMB_NAME_MULTIHOMED_REG_OPCODE)) &&
849 (nmb->header.arcount == 1)) {
851 offset += put_compressed_name_ptr(ubuf,offset,nmb->additional,12);
853 } else if (nmb->header.arcount) {
854 offset += put_res_rec((char *)ubuf,offset,nmb->additional,
855 nmb->header.arcount);
861 /*******************************************************************
863 ******************************************************************/
864 BOOL send_packet(struct packet_struct *p)
869 bzero(buf,sizeof(buf));
871 switch (p->packet_type)
874 len = build_nmb(buf,p);
879 len = build_dgram(buf,p);
883 if (!len) return(False);
885 return(send_udp(p->fd,buf,len,p->ip,p->port));
888 /****************************************************************************
889 receive a packet with timeout on a open UDP filedescriptor
890 The timeout is in milliseconds
891 ***************************************************************************/
892 struct packet_struct *receive_packet(int fd,enum packet_type type,int t)
895 struct timeval timeout;
899 timeout.tv_sec = t/1000;
900 timeout.tv_usec = 1000*(t%1000);
902 sys_select(fd+1,&fds,&timeout);
904 if (FD_ISSET(fd,&fds))
905 return(read_packet(fd,type));
911 /****************************************************************************
912 return the number of bits that match between two 4 character buffers
913 ***************************************************************************/
914 static int matching_bits(uchar *p1, uchar *p2)
917 for (i=0; i<4; i++) {
918 if (p1[i] != p2[i]) break;
922 if (i==4) return ret;
924 for (j=0; j<8; j++) {
925 if ((p1[i] & (1<<(7-j))) != (p2[i] & (1<<(7-j)))) break;
933 static uchar sort_ip[4];
935 /****************************************************************************
936 compare two query reply records
937 ***************************************************************************/
938 static int name_query_comp(uchar *p1, uchar *p2)
940 return matching_bits(p2+2, sort_ip) - matching_bits(p1+2, sort_ip);
943 /****************************************************************************
944 sort a set of 6 byte name query response records so that the IPs that
945 have the most leading bits in common with the specified address come first
946 ***************************************************************************/
947 void sort_query_replies(char *data, int n, struct in_addr ip)
951 putip(sort_ip, (char *)&ip);
953 qsort(data, n, 6, name_query_comp);