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 extern struct in_addr ipzero;
32 static struct opcode_names {
33 char *nmb_opcode_name;
35 } nmb_header_opcode_names[] = {
41 {"Refresh(altcode)", 9 },
42 {"Multi-homed Registration", 15 },
46 /****************************************************************************
47 * Lookup a nmb opcode name.
48 ****************************************************************************/
50 char *lookup_opcode_name( int opcode )
52 struct opcode_names *op_namep;
55 for(i = 0; nmb_header_opcode_names[i].nmb_opcode_name != 0; i++) {
56 op_namep = &nmb_header_opcode_names[i];
57 if(opcode == op_namep->opcode)
58 return op_namep->nmb_opcode_name;
60 return "<unknown opcode>";
63 /****************************************************************************
64 print out a res_rec structure
65 ****************************************************************************/
66 static void debug_nmb_res_rec(struct res_rec *res, char *hdr)
70 DEBUGADD( 4, ( " %s: nmb_name=%s rr_type=%d rr_class=%d ttl=%d\n",
72 namestr(&res->rr_name),
77 if( res->rdlength == 0 || res->rdata == NULL )
80 for (i = 0; i < res->rdlength; i+= 16)
82 DEBUGADD(4, (" %s %3x char ", hdr, i));
84 for (j = 0; j < 16; j++)
86 unsigned char x = res->rdata[i+j];
87 if (x < 32 || x > 127) x = '.';
89 if (i+j >= res->rdlength) break;
90 DEBUGADD(4, ("%c", x));
93 DEBUGADD(4, (" hex ", i));
95 for (j = 0; j < 16; j++)
97 if (i+j >= res->rdlength) break;
98 DEBUGADD(4, ("%02X", (unsigned char)res->rdata[i+j]));
105 /****************************************************************************
107 ****************************************************************************/
108 void debug_nmb_packet(struct packet_struct *p)
110 struct nmb_packet *nmb = &p->packet.nmb;
114 dbgtext( "nmb packet from %s(%d) header: id=%d opcode=%s(%d) response=%s\n",
115 inet_ntoa(p->ip), p->port,
116 nmb->header.name_trn_id,
117 lookup_opcode_name(nmb->header.opcode),
119 BOOLSTR(nmb->header.response) );
120 dbgtext( " header: flags: bcast=%s rec_avail=%s rec_des=%s trunc=%s auth=%s\n",
121 BOOLSTR(nmb->header.nm_flags.bcast),
122 BOOLSTR(nmb->header.nm_flags.recursion_available),
123 BOOLSTR(nmb->header.nm_flags.recursion_desired),
124 BOOLSTR(nmb->header.nm_flags.trunc),
125 BOOLSTR(nmb->header.nm_flags.authoritative) );
126 dbgtext( " header: rcode=%d qdcount=%d ancount=%d nscount=%d arcount=%d\n",
131 nmb->header.arcount );
134 if (nmb->header.qdcount)
136 DEBUGADD( 4, ( " question: q_name=%s q_type=%d q_class=%d\n",
137 namestr(&nmb->question.question_name),
138 nmb->question.question_type,
139 nmb->question.question_class) );
142 if (nmb->answers && nmb->header.ancount)
144 debug_nmb_res_rec(nmb->answers,"answers");
146 if (nmb->nsrecs && nmb->header.nscount)
148 debug_nmb_res_rec(nmb->nsrecs,"nsrecs");
150 if (nmb->additional && nmb->header.arcount)
152 debug_nmb_res_rec(nmb->additional,"additional");
156 /*******************************************************************
157 handle "compressed" name pointers
158 ******************************************************************/
159 static BOOL handle_name_ptrs(unsigned char *ubuf,int *offset,int length,
160 BOOL *got_pointer,int *ret)
164 while ((ubuf[*offset] & 0xC0) == 0xC0) {
165 if (!*got_pointer) (*ret) += 2;
167 (*offset) = ((ubuf[*offset] & ~0xC0)<<8) | ubuf[(*offset)+1];
168 if (loop_count++ == 10 || (*offset) < 0 || (*offset)>(length-2)) {
175 /*******************************************************************
176 parse a nmb name from "compressed" format to something readable
177 return the space taken by the name, or 0 if the name is invalid
178 ******************************************************************/
179 static int parse_nmb_name(char *inbuf,int offset,int length, struct nmb_name *name)
182 unsigned char *ubuf = (unsigned char *)inbuf;
184 BOOL got_pointer=False;
186 if (length - offset < 2) return(0);
188 /* handle initial name pointers */
189 if (!handle_name_ptrs(ubuf,&offset,length,&got_pointer,&ret)) return(0);
194 if ((m & 0xC0) || offset+m+2 > length) return(0);
196 bzero((char *)name,sizeof(*name));
198 /* the "compressed" part */
199 if (!got_pointer) ret += m + 2;
203 c1 = ubuf[offset++]-'A';
204 c2 = ubuf[offset++]-'A';
205 if ((c1 & 0xF0) || (c2 & 0xF0) || (n > sizeof(name->name)-1)) return(0);
206 name->name[n++] = (c1<<4) | c2;
212 /* parse out the name type,
213 its always in the 16th byte of the name */
214 name->name_type = ((unsigned char)name->name[15]) & 0xff;
216 /* remove trailing spaces */
219 while (n && name->name[n]==' ') name->name[n--] = 0;
222 /* now the domain parts (if any) */
224 while ((m=ubuf[offset])) {
225 /* we can have pointers within the domain part as well */
226 if (!handle_name_ptrs(ubuf,&offset,length,&got_pointer,&ret)) return(0);
228 if (!got_pointer) ret += m+1;
229 if (n) name->scope[n++] = '.';
230 if (m+2+offset>length || n+m+1>sizeof(name->scope)) return(0);
232 while (m--) name->scope[n++] = (char)ubuf[offset++];
234 name->scope[n++] = 0;
240 /*******************************************************************
241 put a compressed nmb name into a buffer. return the length of the
244 compressed names are really weird. The "compression" doubles the
245 size. The idea is that it also means that compressed names conform
246 to the doman name system. See RFC1002.
247 ******************************************************************/
248 static int put_nmb_name(char *buf,int offset,struct nmb_name *name)
254 if (name->name[0] == '*') {
255 /* special case for wildcard name */
258 buf1[15] = name->name_type;
260 slprintf(buf1, sizeof(buf1) - 1,"%-15.15s%c",name->name,name->name_type);
268 buf[offset+1+2*m] = 'A' + ((buf1[m]>>4)&0xF);
269 buf[offset+2+2*m] = 'A' + (buf1[m]&0xF);
275 if (name->scope[0]) {
276 /* XXXX this scope handling needs testing */
277 ret += strlen(name->scope) + 1;
278 pstrcpy(&buf[offset+1],name->scope);
281 while ((p = strchr(p,'.'))) {
282 buf[offset] = PTR_DIFF(p,&buf[offset]);
283 offset += buf[offset];
286 buf[offset] = strlen(&buf[offset+1]);
292 /*******************************************************************
293 useful for debugging messages
294 ******************************************************************/
295 char *namestr(struct nmb_name *n)
298 static fstring ret[4];
302 slprintf(p,sizeof(fstring)-1, "%s<%02x>",n->name,n->name_type);
304 slprintf(p,sizeof(fstring)-1, "%s<%02x>.%s",n->name,n->name_type,n->scope);
310 /*******************************************************************
311 allocate and parse some resource records
312 ******************************************************************/
313 static BOOL parse_alloc_res_rec(char *inbuf,int *offset,int length,
314 struct res_rec **recs, int count)
317 *recs = (struct res_rec *)malloc(sizeof(**recs)*count);
318 if (!*recs) return(False);
320 bzero(*recs,sizeof(**recs)*count);
322 for (i=0;i<count;i++) {
323 int l = parse_nmb_name(inbuf,*offset,length,&(*recs)[i].rr_name);
325 if (!l || (*offset)+10 > length) {
329 (*recs)[i].rr_type = RSVAL(inbuf,(*offset));
330 (*recs)[i].rr_class = RSVAL(inbuf,(*offset)+2);
331 (*recs)[i].ttl = RIVAL(inbuf,(*offset)+4);
332 (*recs)[i].rdlength = RSVAL(inbuf,(*offset)+8);
334 if ((*recs)[i].rdlength>sizeof((*recs)[i].rdata) ||
335 (*offset)+(*recs)[i].rdlength > length) {
339 memcpy((*recs)[i].rdata,inbuf+(*offset),(*recs)[i].rdlength);
340 (*offset) += (*recs)[i].rdlength;
345 /*******************************************************************
346 put a resource record into a packet
347 ******************************************************************/
348 static int put_res_rec(char *buf,int offset,struct res_rec *recs,int count)
353 for (i=0;i<count;i++) {
354 int l = put_nmb_name(buf,offset,&recs[i].rr_name);
357 RSSVAL(buf,offset,recs[i].rr_type);
358 RSSVAL(buf,offset+2,recs[i].rr_class);
359 RSIVAL(buf,offset+4,recs[i].ttl);
360 RSSVAL(buf,offset+8,recs[i].rdlength);
361 memcpy(buf+offset+10,recs[i].rdata,recs[i].rdlength);
362 offset += 10+recs[i].rdlength;
363 ret += 10+recs[i].rdlength;
369 /*******************************************************************
370 put a compressed name pointer record into a packet
371 ******************************************************************/
372 static int put_compressed_name_ptr(unsigned char *buf,int offset,struct res_rec *rec,int ptr_offset)
375 buf[offset] = (0xC0 | ((ptr_offset >> 8) & 0xFF));
376 buf[offset+1] = (ptr_offset & 0xFF);
379 RSSVAL(buf,offset,rec->rr_type);
380 RSSVAL(buf,offset+2,rec->rr_class);
381 RSIVAL(buf,offset+4,rec->ttl);
382 RSSVAL(buf,offset+8,rec->rdlength);
383 memcpy(buf+offset+10,rec->rdata,rec->rdlength);
384 offset += 10+rec->rdlength;
385 ret += 10+rec->rdlength;
390 /*******************************************************************
391 parse a dgram packet. Return False if the packet can't be parsed
392 or is invalid for some reason, True otherwise
394 this is documented in section 4.4.1 of RFC1002
395 ******************************************************************/
396 static BOOL parse_dgram(char *inbuf,int length,struct dgram_packet *dgram)
401 bzero((char *)dgram,sizeof(*dgram));
403 if (length < 14) return(False);
405 dgram->header.msg_type = CVAL(inbuf,0);
406 flags = CVAL(inbuf,1);
407 dgram->header.flags.node_type = (enum node_type)((flags>>2)&3);
408 if (flags & 1) dgram->header.flags.more = True;
409 if (flags & 2) dgram->header.flags.first = True;
410 dgram->header.dgm_id = RSVAL(inbuf,2);
411 putip((char *)&dgram->header.source_ip,inbuf+4);
412 dgram->header.source_port = RSVAL(inbuf,8);
413 dgram->header.dgm_length = RSVAL(inbuf,10);
414 dgram->header.packet_offset = RSVAL(inbuf,12);
418 if (dgram->header.msg_type == 0x10 ||
419 dgram->header.msg_type == 0x11 ||
420 dgram->header.msg_type == 0x12) {
421 offset += parse_nmb_name(inbuf,offset,length,&dgram->source_name);
422 offset += parse_nmb_name(inbuf,offset,length,&dgram->dest_name);
425 if (offset >= length || (length-offset > sizeof(dgram->data)))
428 dgram->datasize = length-offset;
429 memcpy(dgram->data,inbuf+offset,dgram->datasize);
435 /*******************************************************************
436 parse a nmb packet. Return False if the packet can't be parsed
437 or is invalid for some reason, True otherwise
438 ******************************************************************/
439 static BOOL parse_nmb(char *inbuf,int length,struct nmb_packet *nmb)
443 bzero((char *)nmb,sizeof(*nmb));
445 if (length < 12) return(False);
447 /* parse the header */
448 nmb->header.name_trn_id = RSVAL(inbuf,0);
450 DEBUG(10,("parse_nmb: packet id = %d\n", nmb->header.name_trn_id));
452 nmb->header.opcode = (CVAL(inbuf,2) >> 3) & 0xF;
453 nmb->header.response = ((CVAL(inbuf,2)>>7)&1)?True:False;
454 nm_flags = ((CVAL(inbuf,2) & 0x7) << 4) + (CVAL(inbuf,3)>>4);
455 nmb->header.nm_flags.bcast = (nm_flags&1)?True:False;
456 nmb->header.nm_flags.recursion_available = (nm_flags&8)?True:False;
457 nmb->header.nm_flags.recursion_desired = (nm_flags&0x10)?True:False;
458 nmb->header.nm_flags.trunc = (nm_flags&0x20)?True:False;
459 nmb->header.nm_flags.authoritative = (nm_flags&0x40)?True:False;
460 nmb->header.rcode = CVAL(inbuf,3) & 0xF;
461 nmb->header.qdcount = RSVAL(inbuf,4);
462 nmb->header.ancount = RSVAL(inbuf,6);
463 nmb->header.nscount = RSVAL(inbuf,8);
464 nmb->header.arcount = RSVAL(inbuf,10);
466 if (nmb->header.qdcount) {
467 offset = parse_nmb_name(inbuf,12,length,&nmb->question.question_name);
468 if (!offset) return(False);
470 if (length - (12+offset) < 4) return(False);
471 nmb->question.question_type = RSVAL(inbuf,12+offset);
472 nmb->question.question_class = RSVAL(inbuf,12+offset+2);
479 /* and any resource records */
480 if (nmb->header.ancount &&
481 !parse_alloc_res_rec(inbuf,&offset,length,&nmb->answers,
482 nmb->header.ancount))
485 if (nmb->header.nscount &&
486 !parse_alloc_res_rec(inbuf,&offset,length,&nmb->nsrecs,
487 nmb->header.nscount))
490 if (nmb->header.arcount &&
491 !parse_alloc_res_rec(inbuf,&offset,length,&nmb->additional,
492 nmb->header.arcount))
498 /*******************************************************************
499 'Copy constructor' for an nmb packet
500 ******************************************************************/
501 static struct packet_struct *copy_nmb_packet(struct packet_struct *packet)
503 struct nmb_packet *nmb;
504 struct nmb_packet *copy_nmb;
505 struct packet_struct *pkt_copy;
507 if(( pkt_copy = (struct packet_struct *)malloc(sizeof(*packet))) == NULL)
509 DEBUG(0,("copy_nmb_packet: malloc fail.\n"));
513 /* Structure copy of entire thing. */
517 /* Ensure this copy is not locked. */
518 pkt_copy->locked = False;
520 /* Ensure this copy has no resource records. */
521 nmb = &packet->packet.nmb;
522 copy_nmb = &pkt_copy->packet.nmb;
524 copy_nmb->answers = NULL;
525 copy_nmb->nsrecs = NULL;
526 copy_nmb->additional = NULL;
528 /* Now copy any resource records. */
532 if((copy_nmb->answers = (struct res_rec *)
533 malloc(nmb->header.ancount * sizeof(struct res_rec))) == NULL)
535 memcpy((char *)copy_nmb->answers, (char *)nmb->answers,
536 nmb->header.ancount * sizeof(struct res_rec));
540 if((copy_nmb->nsrecs = (struct res_rec *)
541 malloc(nmb->header.nscount * sizeof(struct res_rec))) == NULL)
543 memcpy((char *)copy_nmb->nsrecs, (char *)nmb->nsrecs,
544 nmb->header.nscount * sizeof(struct res_rec));
548 if((copy_nmb->additional = (struct res_rec *)
549 malloc(nmb->header.arcount * sizeof(struct res_rec))) == NULL)
551 memcpy((char *)copy_nmb->additional, (char *)nmb->additional,
552 nmb->header.arcount * sizeof(struct res_rec));
559 if(copy_nmb->answers)
560 free((char *)copy_nmb->answers);
562 free((char *)copy_nmb->nsrecs);
563 if(copy_nmb->additional)
564 free((char *)copy_nmb->additional);
565 free((char *)pkt_copy);
567 DEBUG(0,("copy_nmb_packet: malloc fail in resource records.\n"));
571 /*******************************************************************
572 'Copy constructor' for a dgram packet
573 ******************************************************************/
574 static struct packet_struct *copy_dgram_packet(struct packet_struct *packet)
576 struct packet_struct *pkt_copy;
578 if(( pkt_copy = (struct packet_struct *)malloc(sizeof(*packet))) == NULL)
580 DEBUG(0,("copy_dgram_packet: malloc fail.\n"));
584 /* Structure copy of entire thing. */
588 /* Ensure this copy is not locked. */
589 pkt_copy->locked = False;
591 /* There are no additional pointers in a dgram packet,
596 /*******************************************************************
597 'Copy constructor' for a generic packet
598 ******************************************************************/
599 struct packet_struct *copy_packet(struct packet_struct *packet)
601 if(packet->packet_type == NMB_PACKET)
602 return copy_nmb_packet(packet);
603 else if (packet->packet_type == DGRAM_PACKET)
604 return copy_dgram_packet(packet);
608 /*******************************************************************
609 free up any resources associated with an nmb packet
610 ******************************************************************/
611 static void free_nmb_packet(struct nmb_packet *nmb)
613 if (nmb->answers) free(nmb->answers);
614 if (nmb->nsrecs) free(nmb->nsrecs);
615 if (nmb->additional) free(nmb->additional);
618 /*******************************************************************
619 free up any resources associated with a dgram packet
620 ******************************************************************/
621 static void free_dgram_packet(struct dgram_packet *nmb)
623 /* We have nothing to do for a dgram packet. */
626 /*******************************************************************
627 free up any resources associated with a packet
628 ******************************************************************/
629 void free_packet(struct packet_struct *packet)
633 if (packet->packet_type == NMB_PACKET)
634 free_nmb_packet(&packet->packet.nmb);
635 else if (packet->packet_type == DGRAM_PACKET)
636 free_dgram_packet(&packet->packet.dgram);
640 /*******************************************************************
641 read a packet from a socket and parse it, returning a packet ready
642 to be used or put on the queue. This assumes a UDP socket
643 ******************************************************************/
644 struct packet_struct *read_packet(int fd,enum packet_type packet_type)
646 extern struct in_addr lastip;
648 struct packet_struct *packet;
649 char buf[MAX_DGRAM_SIZE];
653 length = read_udp_socket(fd,buf,sizeof(buf));
654 if (length < MIN_DGRAM_SIZE) return(NULL);
656 packet = (struct packet_struct *)malloc(sizeof(*packet));
657 if (!packet) return(NULL);
662 packet->port = lastport;
664 packet->locked = False;
665 packet->timestamp = time(NULL);
666 packet->packet_type = packet_type;
670 ok = parse_nmb(buf,length,&packet->packet.nmb);
674 ok = parse_dgram(buf,length,&packet->packet.dgram);
678 DEBUG(10,("parse_nmb: discarding packet id = %d\n",
679 packet->packet.nmb.header.name_trn_id));
686 DEBUG(5,("Received a packet of len %d from (%s) port %d\n",
687 length, inet_ntoa(packet->ip), packet->port ) );
693 /*******************************************************************
694 send a udp packet on a already open socket
695 ******************************************************************/
696 static BOOL send_udp(int fd,char *buf,int len,struct in_addr ip,int port)
699 struct sockaddr_in sock_out;
701 /* set the address and port */
702 bzero((char *)&sock_out,sizeof(sock_out));
703 putip((char *)&sock_out.sin_addr,(char *)&ip);
704 sock_out.sin_port = htons( port );
705 sock_out.sin_family = AF_INET;
707 DEBUG( 5, ( "Sending a packet of len %d to (%s) on port %d\n",
708 len, inet_ntoa(ip), port ) );
710 ret = (sendto(fd,buf,len,0,(struct sockaddr *)&sock_out,
711 sizeof(sock_out)) >= 0);
714 DEBUG(0,("Packet send failed to %s(%d) ERRNO=%s\n",
715 inet_ntoa(ip),port,strerror(errno)));
723 /*******************************************************************
724 build a dgram packet ready for sending
726 XXXX This currently doesn't handle packets too big for one
727 datagram. It should split them and use the packet_offset, more and
728 first flags to handle the fragmentation. Yuck.
729 ******************************************************************/
730 static int build_dgram(char *buf,struct packet_struct *p)
732 struct dgram_packet *dgram = &p->packet.dgram;
733 unsigned char *ubuf = (unsigned char *)buf;
736 /* put in the header */
737 ubuf[0] = dgram->header.msg_type;
738 ubuf[1] = (((int)dgram->header.flags.node_type)<<2);
739 if (dgram->header.flags.more) ubuf[1] |= 1;
740 if (dgram->header.flags.first) ubuf[1] |= 2;
741 RSSVAL(ubuf,2,dgram->header.dgm_id);
742 putip(ubuf+4,(char *)&dgram->header.source_ip);
743 RSSVAL(ubuf,8,dgram->header.source_port);
744 RSSVAL(ubuf,12,dgram->header.packet_offset);
748 if (dgram->header.msg_type == 0x10 ||
749 dgram->header.msg_type == 0x11 ||
750 dgram->header.msg_type == 0x12) {
751 offset += put_nmb_name((char *)ubuf,offset,&dgram->source_name);
752 offset += put_nmb_name((char *)ubuf,offset,&dgram->dest_name);
755 memcpy(ubuf+offset,dgram->data,dgram->datasize);
756 offset += dgram->datasize;
758 /* automatically set the dgm_length */
759 dgram->header.dgm_length = offset;
760 RSSVAL(ubuf,10,dgram->header.dgm_length);
765 /*******************************************************************
767 *******************************************************************/
768 void make_nmb_name( struct nmb_name *n, char *name, int type, char *this_scope )
770 memset( (char *)n, '\0', sizeof(struct nmb_name) );
771 StrnCpy( n->name, name, 15 );
773 n->name_type = (unsigned int)type & 0xFF;
774 StrnCpy( n->scope, this_scope, 63 );
775 strupper( n->scope );
778 /*******************************************************************
779 Compare two nmb names
780 ******************************************************************/
782 BOOL nmb_name_equal(struct nmb_name *n1, struct nmb_name *n2)
784 return ((n1->name_type == n2->name_type) &&
785 strequal(n1->name ,n2->name ) &&
786 strequal(n1->scope,n2->scope));
789 /*******************************************************************
790 build a nmb packet ready for sending
792 XXXX this currently relies on not being passed something that expands
793 to a packet too big for the buffer. Eventually this should be
794 changed to set the trunc bit so the receiver can request the rest
795 via tcp (when that becomes supported)
796 ******************************************************************/
797 static int build_nmb(char *buf,struct packet_struct *p)
799 struct nmb_packet *nmb = &p->packet.nmb;
800 unsigned char *ubuf = (unsigned char *)buf;
803 /* put in the header */
804 RSSVAL(ubuf,offset,nmb->header.name_trn_id);
805 ubuf[offset+2] = (nmb->header.opcode & 0xF) << 3;
806 if (nmb->header.response) ubuf[offset+2] |= (1<<7);
807 if (nmb->header.nm_flags.authoritative &&
808 nmb->header.response) ubuf[offset+2] |= 0x4;
809 if (nmb->header.nm_flags.trunc) ubuf[offset+2] |= 0x2;
810 if (nmb->header.nm_flags.recursion_desired) ubuf[offset+2] |= 0x1;
811 if (nmb->header.nm_flags.recursion_available &&
812 nmb->header.response) ubuf[offset+3] |= 0x80;
813 if (nmb->header.nm_flags.bcast) ubuf[offset+3] |= 0x10;
814 ubuf[offset+3] |= (nmb->header.rcode & 0xF);
816 RSSVAL(ubuf,offset+4,nmb->header.qdcount);
817 RSSVAL(ubuf,offset+6,nmb->header.ancount);
818 RSSVAL(ubuf,offset+8,nmb->header.nscount);
819 RSSVAL(ubuf,offset+10,nmb->header.arcount);
822 if (nmb->header.qdcount) {
823 /* XXXX this doesn't handle a qdcount of > 1 */
824 offset += put_nmb_name((char *)ubuf,offset,&nmb->question.question_name);
825 RSSVAL(ubuf,offset,nmb->question.question_type);
826 RSSVAL(ubuf,offset+2,nmb->question.question_class);
830 if (nmb->header.ancount)
831 offset += put_res_rec((char *)ubuf,offset,nmb->answers,
832 nmb->header.ancount);
834 if (nmb->header.nscount)
835 offset += put_res_rec((char *)ubuf,offset,nmb->nsrecs,
836 nmb->header.nscount);
839 * The spec says we must put compressed name pointers
840 * in the following outgoing packets :
841 * NAME_REGISTRATION_REQUEST, NAME_REFRESH_REQUEST,
842 * NAME_RELEASE_REQUEST.
845 if((nmb->header.response == False) &&
846 ((nmb->header.opcode == NMB_NAME_REG_OPCODE) ||
847 (nmb->header.opcode == NMB_NAME_RELEASE_OPCODE) ||
848 (nmb->header.opcode == NMB_NAME_REFRESH_OPCODE_8) ||
849 (nmb->header.opcode == NMB_NAME_REFRESH_OPCODE_9) ||
850 (nmb->header.opcode == NMB_NAME_MULTIHOMED_REG_OPCODE)) &&
851 (nmb->header.arcount == 1)) {
853 offset += put_compressed_name_ptr(ubuf,offset,nmb->additional,12);
855 } else if (nmb->header.arcount) {
856 offset += put_res_rec((char *)ubuf,offset,nmb->additional,
857 nmb->header.arcount);
863 /*******************************************************************
865 ******************************************************************/
866 BOOL send_packet(struct packet_struct *p)
871 bzero(buf,sizeof(buf));
873 switch (p->packet_type)
876 len = build_nmb(buf,p);
881 len = build_dgram(buf,p);
885 if (!len) return(False);
887 return(send_udp(p->fd,buf,len,p->ip,p->port));
890 /****************************************************************************
891 receive a packet with timeout on a open UDP filedescriptor
892 The timeout is in milliseconds
893 ***************************************************************************/
894 struct packet_struct *receive_packet(int fd,enum packet_type type,int t)
897 struct timeval timeout;
901 timeout.tv_sec = t/1000;
902 timeout.tv_usec = 1000*(t%1000);
904 sys_select(&fds,&timeout);
906 if (FD_ISSET(fd,&fds))
907 return(read_packet(fd,type));