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 DEBUG(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) return;
79 for (i = 0; i < res->rdlength; i+= 16)
81 DEBUG(4, (" %s %3x char ", hdr, i));
83 for (j = 0; j < 16; j++)
85 unsigned char x = res->rdata[i+j];
86 if (x < 32 || x > 127) x = '.';
88 if (i+j >= res->rdlength) break;
92 DEBUG(4, (" hex ", i));
94 for (j = 0; j < 16; j++)
96 if (i+j >= res->rdlength) break;
97 DEBUG(4, ("%02X", (unsigned char)res->rdata[i+j]));
104 /****************************************************************************
106 ****************************************************************************/
107 void debug_nmb_packet(struct packet_struct *p)
109 struct nmb_packet *nmb = &p->packet.nmb;
111 DEBUG(4,("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,BOOLSTR(nmb->header.response)));
116 DEBUG(4,(" header: flags: bcast=%s rec_avail=%s rec_des=%s trunc=%s auth=%s\n",
117 BOOLSTR(nmb->header.nm_flags.bcast),
118 BOOLSTR(nmb->header.nm_flags.recursion_available),
119 BOOLSTR(nmb->header.nm_flags.recursion_desired),
120 BOOLSTR(nmb->header.nm_flags.trunc),
121 BOOLSTR(nmb->header.nm_flags.authoritative)));
122 DEBUG(4,(" header: rcode=%d qdcount=%d ancount=%d nscount=%d arcount=%d\n",
127 nmb->header.arcount));
129 if (nmb->header.qdcount)
131 DEBUG(4,(" question: q_name=%s q_type=%d q_class=%d\n",
132 namestr(&nmb->question.question_name),
133 nmb->question.question_type,
134 nmb->question.question_class));
137 if (nmb->answers && nmb->header.ancount)
139 debug_nmb_res_rec(nmb->answers,"answers");
141 if (nmb->nsrecs && nmb->header.nscount)
143 debug_nmb_res_rec(nmb->nsrecs,"nsrecs");
145 if (nmb->additional && nmb->header.arcount)
147 debug_nmb_res_rec(nmb->additional,"additional");
151 /*******************************************************************
152 handle "compressed" name pointers
153 ******************************************************************/
154 static BOOL handle_name_ptrs(unsigned char *ubuf,int *offset,int length,
155 BOOL *got_pointer,int *ret)
159 while ((ubuf[*offset] & 0xC0) == 0xC0) {
160 if (!*got_pointer) (*ret) += 2;
162 (*offset) = ((ubuf[*offset] & ~0xC0)<<8) | ubuf[(*offset)+1];
163 if (loop_count++ == 10 || (*offset) < 0 || (*offset)>(length-2)) {
170 /*******************************************************************
171 parse a nmb name from "compressed" format to something readable
172 return the space taken by the name, or 0 if the name is invalid
173 ******************************************************************/
174 static int parse_nmb_name(char *inbuf,int offset,int length, struct nmb_name *name)
177 unsigned char *ubuf = (unsigned char *)inbuf;
179 BOOL got_pointer=False;
181 if (length - offset < 2) return(0);
183 /* handle initial name pointers */
184 if (!handle_name_ptrs(ubuf,&offset,length,&got_pointer,&ret)) return(0);
189 if ((m & 0xC0) || offset+m+2 > length) return(0);
191 bzero((char *)name,sizeof(*name));
193 /* the "compressed" part */
194 if (!got_pointer) ret += m + 2;
198 c1 = ubuf[offset++]-'A';
199 c2 = ubuf[offset++]-'A';
200 if ((c1 & 0xF0) || (c2 & 0xF0)) return(0);
201 name->name[n++] = (c1<<4) | c2;
207 /* parse out the name type,
208 its always in the 16th byte of the name */
209 name->name_type = ((unsigned char)name->name[15]) & 0xff;
211 /* remove trailing spaces */
214 while (n && name->name[n]==' ') name->name[n--] = 0;
217 /* now the domain parts (if any) */
219 while ((m=ubuf[offset])) {
220 /* we can have pointers within the domain part as well */
221 if (!handle_name_ptrs(ubuf,&offset,length,&got_pointer,&ret)) return(0);
223 if (!got_pointer) ret += m+1;
224 if (n) name->scope[n++] = '.';
225 if (m+2+offset>length || n+m+1>sizeof(name->scope)) return(0);
227 while (m--) name->scope[n++] = (char)ubuf[offset++];
229 name->scope[n++] = 0;
235 /*******************************************************************
236 put a compressed nmb name into a buffer. return the length of the
239 compressed names are really weird. The "compression" doubles the
240 size. The idea is that it also means that compressed names conform
241 to the doman name system. See RFC1002.
242 ******************************************************************/
243 static int put_nmb_name(char *buf,int offset,struct nmb_name *name)
249 if (name->name[0] == '*') {
250 /* special case for wildcard name */
253 buf1[15] = name->name_type;
255 slprintf(buf1, sizeof(buf1) - 1,"%-15.15s%c",name->name,name->name_type);
263 buf[offset+1+2*m] = 'A' + ((buf1[m]>>4)&0xF);
264 buf[offset+2+2*m] = 'A' + (buf1[m]&0xF);
270 if (name->scope[0]) {
271 /* XXXX this scope handling needs testing */
272 ret += strlen(name->scope) + 1;
273 pstrcpy(&buf[offset+1],name->scope);
276 while ((p = strchr(p,'.'))) {
277 buf[offset] = PTR_DIFF(p,&buf[offset]);
278 offset += buf[offset];
281 buf[offset] = strlen(&buf[offset+1]);
287 /*******************************************************************
288 useful for debugging messages
289 ******************************************************************/
290 char *namestr(struct nmb_name *n)
293 static fstring ret[4];
297 slprintf(p,sizeof(fstring)-1, "%s<%02x>",n->name,n->name_type);
299 slprintf(p,sizeof(fstring)-1, "%s<%02x>.%s",n->name,n->name_type,n->scope);
305 /*******************************************************************
306 allocate and parse some resource records
307 ******************************************************************/
308 static BOOL parse_alloc_res_rec(char *inbuf,int *offset,int length,
309 struct res_rec **recs, int count)
312 *recs = (struct res_rec *)malloc(sizeof(**recs)*count);
313 if (!*recs) return(False);
315 bzero(*recs,sizeof(**recs)*count);
317 for (i=0;i<count;i++) {
318 int l = parse_nmb_name(inbuf,*offset,length,&(*recs)[i].rr_name);
320 if (!l || (*offset)+10 > length) {
324 (*recs)[i].rr_type = RSVAL(inbuf,(*offset));
325 (*recs)[i].rr_class = RSVAL(inbuf,(*offset)+2);
326 (*recs)[i].ttl = RIVAL(inbuf,(*offset)+4);
327 (*recs)[i].rdlength = RSVAL(inbuf,(*offset)+8);
329 if ((*recs)[i].rdlength>sizeof((*recs)[i].rdata) ||
330 (*offset)+(*recs)[i].rdlength > length) {
334 memcpy((*recs)[i].rdata,inbuf+(*offset),(*recs)[i].rdlength);
335 (*offset) += (*recs)[i].rdlength;
340 /*******************************************************************
341 put a resource record into a packet
342 ******************************************************************/
343 static int put_res_rec(char *buf,int offset,struct res_rec *recs,int count)
348 for (i=0;i<count;i++) {
349 int l = put_nmb_name(buf,offset,&recs[i].rr_name);
352 RSSVAL(buf,offset,recs[i].rr_type);
353 RSSVAL(buf,offset+2,recs[i].rr_class);
354 RSIVAL(buf,offset+4,recs[i].ttl);
355 RSSVAL(buf,offset+8,recs[i].rdlength);
356 memcpy(buf+offset+10,recs[i].rdata,recs[i].rdlength);
357 offset += 10+recs[i].rdlength;
358 ret += 10+recs[i].rdlength;
364 /*******************************************************************
365 put a compressed name pointer record into a packet
366 ******************************************************************/
367 static int put_compressed_name_ptr(unsigned char *buf,int offset,struct res_rec *rec,int ptr_offset)
370 buf[offset] = (0xC0 | ((ptr_offset >> 8) & 0xFF));
371 buf[offset+1] = (ptr_offset & 0xFF);
374 RSSVAL(buf,offset,rec->rr_type);
375 RSSVAL(buf,offset+2,rec->rr_class);
376 RSIVAL(buf,offset+4,rec->ttl);
377 RSSVAL(buf,offset+8,rec->rdlength);
378 memcpy(buf+offset+10,rec->rdata,rec->rdlength);
379 offset += 10+rec->rdlength;
380 ret += 10+rec->rdlength;
385 /*******************************************************************
386 parse a dgram packet. Return False if the packet can't be parsed
387 or is invalid for some reason, True otherwise
389 this is documented in section 4.4.1 of RFC1002
390 ******************************************************************/
391 static BOOL parse_dgram(char *inbuf,int length,struct dgram_packet *dgram)
396 bzero((char *)dgram,sizeof(*dgram));
398 if (length < 14) return(False);
400 dgram->header.msg_type = CVAL(inbuf,0);
401 flags = CVAL(inbuf,1);
402 dgram->header.flags.node_type = (enum node_type)((flags>>2)&3);
403 if (flags & 1) dgram->header.flags.more = True;
404 if (flags & 2) dgram->header.flags.first = True;
405 dgram->header.dgm_id = RSVAL(inbuf,2);
406 putip((char *)&dgram->header.source_ip,inbuf+4);
407 dgram->header.source_port = RSVAL(inbuf,8);
408 dgram->header.dgm_length = RSVAL(inbuf,10);
409 dgram->header.packet_offset = RSVAL(inbuf,12);
413 if (dgram->header.msg_type == 0x10 ||
414 dgram->header.msg_type == 0x11 ||
415 dgram->header.msg_type == 0x12) {
416 offset += parse_nmb_name(inbuf,offset,length,&dgram->source_name);
417 offset += parse_nmb_name(inbuf,offset,length,&dgram->dest_name);
420 if (offset >= length || (length-offset > sizeof(dgram->data)))
423 dgram->datasize = length-offset;
424 memcpy(dgram->data,inbuf+offset,dgram->datasize);
430 /*******************************************************************
431 parse a nmb packet. Return False if the packet can't be parsed
432 or is invalid for some reason, True otherwise
433 ******************************************************************/
434 static BOOL parse_nmb(char *inbuf,int length,struct nmb_packet *nmb)
438 bzero((char *)nmb,sizeof(*nmb));
440 if (length < 12) return(False);
442 /* parse the header */
443 nmb->header.name_trn_id = RSVAL(inbuf,0);
445 DEBUG(10,("parse_nmb: packet id = %d\n", nmb->header.name_trn_id));
447 nmb->header.opcode = (CVAL(inbuf,2) >> 3) & 0xF;
448 nmb->header.response = ((CVAL(inbuf,2)>>7)&1)?True:False;
449 nm_flags = ((CVAL(inbuf,2) & 0x7) << 4) + (CVAL(inbuf,3)>>4);
450 nmb->header.nm_flags.bcast = (nm_flags&1)?True:False;
451 nmb->header.nm_flags.recursion_available = (nm_flags&8)?True:False;
452 nmb->header.nm_flags.recursion_desired = (nm_flags&0x10)?True:False;
453 nmb->header.nm_flags.trunc = (nm_flags&0x20)?True:False;
454 nmb->header.nm_flags.authoritative = (nm_flags&0x40)?True:False;
455 nmb->header.rcode = CVAL(inbuf,3) & 0xF;
456 nmb->header.qdcount = RSVAL(inbuf,4);
457 nmb->header.ancount = RSVAL(inbuf,6);
458 nmb->header.nscount = RSVAL(inbuf,8);
459 nmb->header.arcount = RSVAL(inbuf,10);
461 if (nmb->header.qdcount) {
462 offset = parse_nmb_name(inbuf,12,length,&nmb->question.question_name);
463 if (!offset) return(False);
465 if (length - (12+offset) < 4) return(False);
466 nmb->question.question_type = RSVAL(inbuf,12+offset);
467 nmb->question.question_class = RSVAL(inbuf,12+offset+2);
474 /* and any resource records */
475 if (nmb->header.ancount &&
476 !parse_alloc_res_rec(inbuf,&offset,length,&nmb->answers,
477 nmb->header.ancount))
480 if (nmb->header.nscount &&
481 !parse_alloc_res_rec(inbuf,&offset,length,&nmb->nsrecs,
482 nmb->header.nscount))
485 if (nmb->header.arcount &&
486 !parse_alloc_res_rec(inbuf,&offset,length,&nmb->additional,
487 nmb->header.arcount))
493 /*******************************************************************
494 'Copy constructor' for an nmb packet
495 ******************************************************************/
496 static struct packet_struct *copy_nmb_packet(struct packet_struct *packet)
498 struct nmb_packet *nmb;
499 struct nmb_packet *copy_nmb;
500 struct packet_struct *pkt_copy;
502 if(( pkt_copy = (struct packet_struct *)malloc(sizeof(*packet))) == NULL)
504 DEBUG(0,("copy_nmb_packet: malloc fail.\n"));
508 /* Structure copy of entire thing. */
512 /* Ensure this copy is not locked. */
513 pkt_copy->locked = False;
515 /* Ensure this copy has no resource records. */
516 nmb = &packet->packet.nmb;
517 copy_nmb = &pkt_copy->packet.nmb;
519 copy_nmb->answers = NULL;
520 copy_nmb->nsrecs = NULL;
521 copy_nmb->additional = NULL;
523 /* Now copy any resource records. */
527 if((copy_nmb->answers = (struct res_rec *)
528 malloc(nmb->header.ancount * sizeof(struct res_rec))) == NULL)
530 memcpy((char *)copy_nmb->answers, (char *)nmb->answers,
531 nmb->header.ancount * sizeof(struct res_rec));
535 if((copy_nmb->nsrecs = (struct res_rec *)
536 malloc(nmb->header.nscount * sizeof(struct res_rec))) == NULL)
538 memcpy((char *)copy_nmb->nsrecs, (char *)nmb->nsrecs,
539 nmb->header.nscount * sizeof(struct res_rec));
543 if((copy_nmb->additional = (struct res_rec *)
544 malloc(nmb->header.arcount * sizeof(struct res_rec))) == NULL)
546 memcpy((char *)copy_nmb->additional, (char *)nmb->additional,
547 nmb->header.arcount * sizeof(struct res_rec));
554 if(copy_nmb->answers)
555 free((char *)copy_nmb->answers);
557 free((char *)copy_nmb->nsrecs);
558 if(copy_nmb->additional)
559 free((char *)copy_nmb->additional);
560 free((char *)pkt_copy);
562 DEBUG(0,("copy_nmb_packet: malloc fail in resource records.\n"));
566 /*******************************************************************
567 'Copy constructor' for a dgram packet
568 ******************************************************************/
569 static struct packet_struct *copy_dgram_packet(struct packet_struct *packet)
571 struct packet_struct *pkt_copy;
573 if(( pkt_copy = (struct packet_struct *)malloc(sizeof(*packet))) == NULL)
575 DEBUG(0,("copy_dgram_packet: malloc fail.\n"));
579 /* Structure copy of entire thing. */
583 /* Ensure this copy is not locked. */
584 pkt_copy->locked = False;
586 /* There are no additional pointers in a dgram packet,
591 /*******************************************************************
592 'Copy constructor' for a generic packet
593 ******************************************************************/
594 struct packet_struct *copy_packet(struct packet_struct *packet)
596 if(packet->packet_type == NMB_PACKET)
597 return copy_nmb_packet(packet);
598 else if (packet->packet_type == DGRAM_PACKET)
599 return copy_dgram_packet(packet);
603 /*******************************************************************
604 free up any resources associated with an nmb packet
605 ******************************************************************/
606 static void free_nmb_packet(struct nmb_packet *nmb)
608 if (nmb->answers) free(nmb->answers);
609 if (nmb->nsrecs) free(nmb->nsrecs);
610 if (nmb->additional) free(nmb->additional);
613 /*******************************************************************
614 free up any resources associated with a dgram packet
615 ******************************************************************/
616 static void free_dgram_packet(struct dgram_packet *nmb)
618 /* We have nothing to do for a dgram packet. */
621 /*******************************************************************
622 free up any resources associated with a packet
623 ******************************************************************/
624 void free_packet(struct packet_struct *packet)
628 if (packet->packet_type == NMB_PACKET)
629 free_nmb_packet(&packet->packet.nmb);
630 else if (packet->packet_type == DGRAM_PACKET)
631 free_dgram_packet(&packet->packet.dgram);
635 /*******************************************************************
636 read a packet from a socket and parse it, returning a packet ready
637 to be used or put on the queue. This assumes a UDP socket
638 ******************************************************************/
639 struct packet_struct *read_packet(int fd,enum packet_type packet_type)
641 extern struct in_addr lastip;
643 struct packet_struct *packet;
644 char buf[MAX_DGRAM_SIZE];
648 length = read_udp_socket(fd,buf,sizeof(buf));
649 if (length < MIN_DGRAM_SIZE) return(NULL);
651 packet = (struct packet_struct *)malloc(sizeof(*packet));
652 if (!packet) return(NULL);
657 packet->port = lastport;
659 packet->locked = False;
660 packet->timestamp = time(NULL);
661 packet->packet_type = packet_type;
665 ok = parse_nmb(buf,length,&packet->packet.nmb);
669 ok = parse_dgram(buf,length,&packet->packet.dgram);
673 DEBUG(10,("parse_nmb: discarding packet id = %d\n",
674 packet->packet.nmb.header.name_trn_id));
681 DEBUG(5,("%s received a packet of len %d from (%s) port %d\n",
682 timestring(),length,inet_ntoa(packet->ip),packet->port));
688 /*******************************************************************
689 send a udp packet on a already open socket
690 ******************************************************************/
691 static BOOL send_udp(int fd,char *buf,int len,struct in_addr ip,int port)
694 struct sockaddr_in sock_out;
696 /* set the address and port */
697 bzero((char *)&sock_out,sizeof(sock_out));
698 putip((char *)&sock_out.sin_addr,(char *)&ip);
699 sock_out.sin_port = htons( port );
700 sock_out.sin_family = AF_INET;
702 DEBUG(5,("%s sending a packet of len %d to (%s) on port %d\n",
703 timestring(),len,inet_ntoa(ip),port));
705 ret = (sendto(fd,buf,len,0,(struct sockaddr *)&sock_out,
706 sizeof(sock_out)) >= 0);
709 DEBUG(0,("Packet send failed to %s(%d) ERRNO=%s\n",
710 inet_ntoa(ip),port,strerror(errno)));
718 /*******************************************************************
719 build a dgram packet ready for sending
721 XXXX This currently doesn't handle packets too big for one
722 datagram. It should split them and use the packet_offset, more and
723 first flags to handle the fragmentation. Yuck.
724 ******************************************************************/
725 static int build_dgram(char *buf,struct packet_struct *p)
727 struct dgram_packet *dgram = &p->packet.dgram;
728 unsigned char *ubuf = (unsigned char *)buf;
731 /* put in the header */
732 ubuf[0] = dgram->header.msg_type;
733 ubuf[1] = (((int)dgram->header.flags.node_type)<<2);
734 if (dgram->header.flags.more) ubuf[1] |= 1;
735 if (dgram->header.flags.first) ubuf[1] |= 2;
736 RSSVAL(ubuf,2,dgram->header.dgm_id);
737 putip(ubuf+4,(char *)&dgram->header.source_ip);
738 RSSVAL(ubuf,8,dgram->header.source_port);
739 RSSVAL(ubuf,12,dgram->header.packet_offset);
743 if (dgram->header.msg_type == 0x10 ||
744 dgram->header.msg_type == 0x11 ||
745 dgram->header.msg_type == 0x12) {
746 offset += put_nmb_name((char *)ubuf,offset,&dgram->source_name);
747 offset += put_nmb_name((char *)ubuf,offset,&dgram->dest_name);
750 memcpy(ubuf+offset,dgram->data,dgram->datasize);
751 offset += dgram->datasize;
753 /* automatically set the dgm_length */
754 dgram->header.dgm_length = offset;
755 RSSVAL(ubuf,10,dgram->header.dgm_length);
760 /*******************************************************************
762 ******************************************************************/
763 void make_nmb_name(struct nmb_name *n,char *name,int type,char *this_scope)
765 StrnCpy(n->name,name,15);
767 n->name_type = (unsigned int)type & 0xFF;
768 StrnCpy(n->scope,this_scope,63);
771 /*******************************************************************
772 Compare two nmb names
773 ******************************************************************/
775 BOOL nmb_name_equal(struct nmb_name *n1, struct nmb_name *n2)
777 return ((n1->name_type == n2->name_type) &&
778 strequal(n1->name ,n2->name ) &&
779 strequal(n1->scope,n2->scope));
782 /*******************************************************************
783 build a nmb packet ready for sending
785 XXXX this currently relies on not being passed something that expands
786 to a packet too big for the buffer. Eventually this should be
787 changed to set the trunc bit so the receiver can request the rest
788 via tcp (when that becomes supported)
789 ******************************************************************/
790 static int build_nmb(char *buf,struct packet_struct *p)
792 struct nmb_packet *nmb = &p->packet.nmb;
793 unsigned char *ubuf = (unsigned char *)buf;
796 /* put in the header */
797 RSSVAL(ubuf,offset,nmb->header.name_trn_id);
798 ubuf[offset+2] = (nmb->header.opcode & 0xF) << 3;
799 if (nmb->header.response) ubuf[offset+2] |= (1<<7);
800 if (nmb->header.nm_flags.authoritative &&
801 nmb->header.response) ubuf[offset+2] |= 0x4;
802 if (nmb->header.nm_flags.trunc) ubuf[offset+2] |= 0x2;
803 if (nmb->header.nm_flags.recursion_desired) ubuf[offset+2] |= 0x1;
804 if (nmb->header.nm_flags.recursion_available &&
805 nmb->header.response) ubuf[offset+3] |= 0x80;
806 if (nmb->header.nm_flags.bcast) ubuf[offset+3] |= 0x10;
807 ubuf[offset+3] |= (nmb->header.rcode & 0xF);
809 RSSVAL(ubuf,offset+4,nmb->header.qdcount);
810 RSSVAL(ubuf,offset+6,nmb->header.ancount);
811 RSSVAL(ubuf,offset+8,nmb->header.nscount);
812 RSSVAL(ubuf,offset+10,nmb->header.arcount);
815 if (nmb->header.qdcount) {
816 /* XXXX this doesn't handle a qdcount of > 1 */
817 offset += put_nmb_name((char *)ubuf,offset,&nmb->question.question_name);
818 RSSVAL(ubuf,offset,nmb->question.question_type);
819 RSSVAL(ubuf,offset+2,nmb->question.question_class);
823 if (nmb->header.ancount)
824 offset += put_res_rec((char *)ubuf,offset,nmb->answers,
825 nmb->header.ancount);
827 if (nmb->header.nscount)
828 offset += put_res_rec((char *)ubuf,offset,nmb->nsrecs,
829 nmb->header.nscount);
832 * The spec says we must put compressed name pointers
833 * in the following outgoing packets :
834 * NAME_REGISTRATION_REQUEST, NAME_REFRESH_REQUEST,
835 * NAME_RELEASE_REQUEST.
838 if((nmb->header.response == False) &&
839 ((nmb->header.opcode == NMB_NAME_REG_OPCODE) ||
840 (nmb->header.opcode == NMB_NAME_RELEASE_OPCODE) ||
841 (nmb->header.opcode == NMB_NAME_REFRESH_OPCODE_8) ||
842 (nmb->header.opcode == NMB_NAME_REFRESH_OPCODE_9) ||
843 (nmb->header.opcode == NMB_NAME_MULTIHOMED_REG_OPCODE)) &&
844 (nmb->header.arcount == 1)) {
846 offset += put_compressed_name_ptr(ubuf,offset,nmb->additional,12);
848 } else if (nmb->header.arcount) {
849 offset += put_res_rec((char *)ubuf,offset,nmb->additional,
850 nmb->header.arcount);
856 /*******************************************************************
858 ******************************************************************/
859 BOOL send_packet(struct packet_struct *p)
864 bzero(buf,sizeof(buf));
866 switch (p->packet_type)
869 len = build_nmb(buf,p);
874 len = build_dgram(buf,p);
878 if (!len) return(False);
880 return(send_udp(p->fd,buf,len,p->ip,p->port));
883 /****************************************************************************
884 receive a packet with timeout on a open UDP filedescriptor
885 The timeout is in milliseconds
886 ***************************************************************************/
887 struct packet_struct *receive_packet(int fd,enum packet_type type,int t)
890 struct timeval timeout;
894 timeout.tv_sec = t/1000;
895 timeout.tv_usec = 1000*(t%1000);
897 sys_select(&fds,&timeout);
899 if (FD_ISSET(fd,&fds))
900 return(read_packet(fd,type));