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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
25 extern int DEBUGLEVEL
;
27 int num_good_sends
= 0;
28 int num_good_receives
= 0;
30 static struct opcode_names
{
31 const char *nmb_opcode_name
;
33 } const nmb_header_opcode_names
[] = {
39 {"Refresh(altcode)", 9 },
40 {"Multi-homed Registration", 15 },
44 /****************************************************************************
45 * Lookup a nmb opcode name.
46 ****************************************************************************/
47 static const char *lookup_opcode_name( int opcode
)
49 const struct opcode_names
*op_namep
= nmb_header_opcode_names
;
51 while(op_namep
->nmb_opcode_name
) {
52 if(opcode
== op_namep
->opcode
)
53 return op_namep
->nmb_opcode_name
;
56 return "<unknown opcode>";
59 /****************************************************************************
60 print out a res_rec structure
61 ****************************************************************************/
62 static void debug_nmb_res_rec(struct res_rec
*res
, const char *hdr
)
66 DEBUGADD( 4, ( " %s: nmb_name=%s rr_type=%d rr_class=%d ttl=%d\n",
68 nmb_namestr(&res
->rr_name
),
73 if( res
->rdlength
== 0 || res
->rdata
== NULL
)
76 for (i
= 0; i
< res
->rdlength
; i
+= 16)
78 DEBUGADD(4, (" %s %3x char ", hdr
, i
));
80 for (j
= 0; j
< 16; j
++)
82 unsigned char x
= res
->rdata
[i
+j
];
83 if (x
< 32 || x
> 127) x
= '.';
85 if (i
+j
>= res
->rdlength
) break;
86 DEBUGADD(4, ("%c", x
));
89 DEBUGADD(4, (" hex "));
91 for (j
= 0; j
< 16; j
++)
93 if (i
+j
>= res
->rdlength
) break;
94 DEBUGADD(4, ("%02X", (unsigned char)res
->rdata
[i
+j
]));
101 /****************************************************************************
103 ****************************************************************************/
104 void debug_nmb_packet(struct packet_struct
*p
)
106 struct nmb_packet
*nmb
= &p
->packet
.nmb
;
110 dbgtext( "nmb packet from %s(%d) header: id=%d opcode=%s(%d) response=%s\n",
111 inet_ntoa(p
->ip
), p
->port
,
112 nmb
->header
.name_trn_id
,
113 lookup_opcode_name(nmb
->header
.opcode
),
115 BOOLSTR(nmb
->header
.response
) );
116 dbgtext( " 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 dbgtext( " header: rcode=%d qdcount=%d ancount=%d nscount=%d arcount=%d\n",
127 nmb
->header
.arcount
);
130 if (nmb
->header
.qdcount
)
132 DEBUGADD( 4, ( " question: q_name=%s q_type=%d q_class=%d\n",
133 nmb_namestr(&nmb
->question
.question_name
),
134 nmb
->question
.question_type
,
135 nmb
->question
.question_class
) );
138 if (nmb
->answers
&& nmb
->header
.ancount
)
140 debug_nmb_res_rec(nmb
->answers
,"answers");
142 if (nmb
->nsrecs
&& nmb
->header
.nscount
)
144 debug_nmb_res_rec(nmb
->nsrecs
,"nsrecs");
146 if (nmb
->additional
&& nmb
->header
.arcount
)
148 debug_nmb_res_rec(nmb
->additional
,"additional");
152 /*******************************************************************
153 handle "compressed" name pointers
154 ******************************************************************/
155 static BOOL
handle_name_ptrs(unsigned char *ubuf
,int *offset
,int length
,
156 BOOL
*got_pointer
,int *ret
)
160 while ((ubuf
[*offset
] & 0xC0) == 0xC0) {
161 if (!*got_pointer
) (*ret
) += 2;
163 (*offset
) = ((ubuf
[*offset
] & ~0xC0)<<8) | ubuf
[(*offset
)+1];
164 if (loop_count
++ == 10 || (*offset
) < 0 || (*offset
)>(length
-2)) {
171 /*******************************************************************
172 parse a nmb name from "compressed" format to something readable
173 return the space taken by the name, or 0 if the name is invalid
174 ******************************************************************/
175 static int parse_nmb_name(char *inbuf
,int offset
,int length
, struct nmb_name
*name
)
178 unsigned char *ubuf
= (unsigned char *)inbuf
;
180 BOOL got_pointer
=False
;
182 if (length
- offset
< 2)
185 /* handle initial name pointers */
186 if (!handle_name_ptrs(ubuf
,&offset
,length
,&got_pointer
,&ret
))
193 if ((m
& 0xC0) || offset
+m
+2 > length
)
196 memset((char *)name
,'\0',sizeof(*name
));
198 /* the "compressed" part */
204 c1
= ubuf
[offset
++]-'A';
205 c2
= ubuf
[offset
++]-'A';
206 if ((c1
& 0xF0) || (c2
& 0xF0) || ((size_t) n
> sizeof(name
->name
)-1))
208 name
->name
[n
++] = (c1
<<4) | c2
;
214 /* parse out the name type,
215 its always in the 16th byte of the name */
216 name
->name_type
= ((unsigned char)name
->name
[15]) & 0xff;
218 /* remove trailing spaces */
221 while (n
&& name
->name
[n
]==' ')
225 /* now the domain parts (if any) */
227 while (ubuf
[offset
]) {
228 /* we can have pointers within the domain part as well */
229 if (!handle_name_ptrs(ubuf
,&offset
,length
,&got_pointer
,&ret
))
236 name
->scope
[n
++] = '.';
237 if (m
+2+offset
>length
|| (size_t) n
+m
+1 >sizeof(name
->scope
))
241 name
->scope
[n
++] = (char)ubuf
[offset
++];
243 name
->scope
[n
++] = 0;
249 /*******************************************************************
250 put a compressed nmb name into a buffer. return the length of the
253 compressed names are really weird. The "compression" doubles the
254 size. The idea is that it also means that compressed names conform
255 to the doman name system. See RFC1002.
256 ******************************************************************/
257 static int put_nmb_name(char *buf
,int offset
,struct nmb_name
*name
)
263 if (strcmp(name
->name
,"*") == 0) {
264 /* special case for wildcard name */
265 memset(buf1
,'\0',20);
267 buf1
[15] = name
->name_type
;
269 slprintf(buf1
, sizeof(buf1
) - 1,"%-15.15s%c",name
->name
,name
->name_type
);
277 buf
[offset
+1+2*m
] = 'A' + ((buf1
[m
]>>4)&0xF);
278 buf
[offset
+2+2*m
] = 'A' + (buf1
[m
]&0xF);
284 if (name
->scope
[0]) {
285 /* XXXX this scope handling needs testing */
286 ret
+= strlen(name
->scope
) + 1;
287 pstrcpy(&buf
[offset
+1],name
->scope
);
290 while ((p
= strchr(p
,'.'))) {
291 buf
[offset
] = PTR_DIFF(p
,&buf
[offset
+1]);
292 offset
+= (buf
[offset
] + 1);
295 buf
[offset
] = strlen(&buf
[offset
+1]);
301 /*******************************************************************
302 useful for debugging messages
303 ******************************************************************/
304 char *nmb_namestr(struct nmb_name
*n
)
307 static fstring ret
[4];
311 slprintf(p
,sizeof(fstring
)-1, "%s<%02x>",n
->name
,n
->name_type
);
313 slprintf(p
,sizeof(fstring
)-1, "%s<%02x>.%s",n
->name
,n
->name_type
,n
->scope
);
319 /*******************************************************************
320 allocate and parse some resource records
321 ******************************************************************/
322 static BOOL
parse_alloc_res_rec(char *inbuf
,int *offset
,int length
,
323 struct res_rec
**recs
, int count
)
326 *recs
= (struct res_rec
*)malloc(sizeof(**recs
)*count
);
327 if (!*recs
) return(False
);
329 memset((char *)*recs
,'\0',sizeof(**recs
)*count
);
331 for (i
=0;i
<count
;i
++) {
332 int l
= parse_nmb_name(inbuf
,*offset
,length
,&(*recs
)[i
].rr_name
);
334 if (!l
|| (*offset
)+10 > length
) {
338 (*recs
)[i
].rr_type
= RSVAL(inbuf
,(*offset
));
339 (*recs
)[i
].rr_class
= RSVAL(inbuf
,(*offset
)+2);
340 (*recs
)[i
].ttl
= RIVAL(inbuf
,(*offset
)+4);
341 (*recs
)[i
].rdlength
= RSVAL(inbuf
,(*offset
)+8);
343 if ((size_t)(*recs
)[i
].rdlength
>sizeof((*recs
)[i
].rdata
) ||
344 (*offset
)+(*recs
)[i
].rdlength
> length
) {
348 memcpy((*recs
)[i
].rdata
,inbuf
+(*offset
),(*recs
)[i
].rdlength
);
349 (*offset
) += (*recs
)[i
].rdlength
;
354 /*******************************************************************
355 put a resource record into a packet
356 ******************************************************************/
357 static int put_res_rec(char *buf
,int offset
,struct res_rec
*recs
,int count
)
362 for (i
=0;i
<count
;i
++) {
363 int l
= put_nmb_name(buf
,offset
,&recs
[i
].rr_name
);
366 RSSVAL(buf
,offset
,recs
[i
].rr_type
);
367 RSSVAL(buf
,offset
+2,recs
[i
].rr_class
);
368 RSIVAL(buf
,offset
+4,recs
[i
].ttl
);
369 RSSVAL(buf
,offset
+8,recs
[i
].rdlength
);
370 memcpy(buf
+offset
+10,recs
[i
].rdata
,recs
[i
].rdlength
);
371 offset
+= 10+recs
[i
].rdlength
;
372 ret
+= 10+recs
[i
].rdlength
;
378 /*******************************************************************
379 put a compressed name pointer record into a packet
380 ******************************************************************/
381 static int put_compressed_name_ptr(unsigned char *buf
,int offset
,struct res_rec
*rec
,int ptr_offset
)
384 buf
[offset
] = (0xC0 | ((ptr_offset
>> 8) & 0xFF));
385 buf
[offset
+1] = (ptr_offset
& 0xFF);
388 RSSVAL(buf
,offset
,rec
->rr_type
);
389 RSSVAL(buf
,offset
+2,rec
->rr_class
);
390 RSIVAL(buf
,offset
+4,rec
->ttl
);
391 RSSVAL(buf
,offset
+8,rec
->rdlength
);
392 memcpy(buf
+offset
+10,rec
->rdata
,rec
->rdlength
);
393 offset
+= 10+rec
->rdlength
;
394 ret
+= 10+rec
->rdlength
;
399 /*******************************************************************
400 parse a dgram packet. Return False if the packet can't be parsed
401 or is invalid for some reason, True otherwise
403 this is documented in section 4.4.1 of RFC1002
404 ******************************************************************/
405 static BOOL
parse_dgram(char *inbuf
,int length
,struct dgram_packet
*dgram
)
410 memset((char *)dgram
,'\0',sizeof(*dgram
));
412 if (length
< 14) return(False
);
414 dgram
->header
.msg_type
= CVAL(inbuf
,0);
415 flags
= CVAL(inbuf
,1);
416 dgram
->header
.flags
.node_type
= (enum node_type
)((flags
>>2)&3);
417 if (flags
& 1) dgram
->header
.flags
.more
= True
;
418 if (flags
& 2) dgram
->header
.flags
.first
= True
;
419 dgram
->header
.dgm_id
= RSVAL(inbuf
,2);
420 putip((char *)&dgram
->header
.source_ip
,inbuf
+4);
421 dgram
->header
.source_port
= RSVAL(inbuf
,8);
422 dgram
->header
.dgm_length
= RSVAL(inbuf
,10);
423 dgram
->header
.packet_offset
= RSVAL(inbuf
,12);
427 if (dgram
->header
.msg_type
== 0x10 ||
428 dgram
->header
.msg_type
== 0x11 ||
429 dgram
->header
.msg_type
== 0x12) {
430 offset
+= parse_nmb_name(inbuf
,offset
,length
,&dgram
->source_name
);
431 offset
+= parse_nmb_name(inbuf
,offset
,length
,&dgram
->dest_name
);
434 if (offset
>= length
|| ((size_t)length
-offset
> sizeof(dgram
->data
)))
437 dgram
->datasize
= length
-offset
;
438 memcpy(dgram
->data
,inbuf
+offset
,dgram
->datasize
);
444 /*******************************************************************
445 parse a nmb packet. Return False if the packet can't be parsed
446 or is invalid for some reason, True otherwise
447 ******************************************************************/
448 static BOOL
parse_nmb(char *inbuf
,int length
,struct nmb_packet
*nmb
)
452 memset((char *)nmb
,'\0',sizeof(*nmb
));
454 if (length
< 12) return(False
);
456 /* parse the header */
457 nmb
->header
.name_trn_id
= RSVAL(inbuf
,0);
459 DEBUG(10,("parse_nmb: packet id = %d\n", nmb
->header
.name_trn_id
));
461 nmb
->header
.opcode
= (CVAL(inbuf
,2) >> 3) & 0xF;
462 nmb
->header
.response
= ((CVAL(inbuf
,2)>>7)&1)?True
:False
;
463 nm_flags
= ((CVAL(inbuf
,2) & 0x7) << 4) + (CVAL(inbuf
,3)>>4);
464 nmb
->header
.nm_flags
.bcast
= (nm_flags
&1)?True
:False
;
465 nmb
->header
.nm_flags
.recursion_available
= (nm_flags
&8)?True
:False
;
466 nmb
->header
.nm_flags
.recursion_desired
= (nm_flags
&0x10)?True
:False
;
467 nmb
->header
.nm_flags
.trunc
= (nm_flags
&0x20)?True
:False
;
468 nmb
->header
.nm_flags
.authoritative
= (nm_flags
&0x40)?True
:False
;
469 nmb
->header
.rcode
= CVAL(inbuf
,3) & 0xF;
470 nmb
->header
.qdcount
= RSVAL(inbuf
,4);
471 nmb
->header
.ancount
= RSVAL(inbuf
,6);
472 nmb
->header
.nscount
= RSVAL(inbuf
,8);
473 nmb
->header
.arcount
= RSVAL(inbuf
,10);
475 if (nmb
->header
.qdcount
) {
476 offset
= parse_nmb_name(inbuf
,12,length
,&nmb
->question
.question_name
);
477 if (!offset
) return(False
);
479 if (length
- (12+offset
) < 4) return(False
);
480 nmb
->question
.question_type
= RSVAL(inbuf
,12+offset
);
481 nmb
->question
.question_class
= RSVAL(inbuf
,12+offset
+2);
488 /* and any resource records */
489 if (nmb
->header
.ancount
&&
490 !parse_alloc_res_rec(inbuf
,&offset
,length
,&nmb
->answers
,
491 nmb
->header
.ancount
))
494 if (nmb
->header
.nscount
&&
495 !parse_alloc_res_rec(inbuf
,&offset
,length
,&nmb
->nsrecs
,
496 nmb
->header
.nscount
))
499 if (nmb
->header
.arcount
&&
500 !parse_alloc_res_rec(inbuf
,&offset
,length
,&nmb
->additional
,
501 nmb
->header
.arcount
))
507 /*******************************************************************
508 'Copy constructor' for an nmb packet
509 ******************************************************************/
510 static struct packet_struct
*copy_nmb_packet(struct packet_struct
*packet
)
512 struct nmb_packet
*nmb
;
513 struct nmb_packet
*copy_nmb
;
514 struct packet_struct
*pkt_copy
;
516 if(( pkt_copy
= (struct packet_struct
*)malloc(sizeof(*packet
))) == NULL
)
518 DEBUG(0,("copy_nmb_packet: malloc fail.\n"));
522 /* Structure copy of entire thing. */
526 /* Ensure this copy is not locked. */
527 pkt_copy
->locked
= False
;
529 /* Ensure this copy has no resource records. */
530 nmb
= &packet
->packet
.nmb
;
531 copy_nmb
= &pkt_copy
->packet
.nmb
;
533 copy_nmb
->answers
= NULL
;
534 copy_nmb
->nsrecs
= NULL
;
535 copy_nmb
->additional
= NULL
;
537 /* Now copy any resource records. */
541 if((copy_nmb
->answers
= (struct res_rec
*)
542 malloc(nmb
->header
.ancount
* sizeof(struct res_rec
))) == NULL
)
544 memcpy((char *)copy_nmb
->answers
, (char *)nmb
->answers
,
545 nmb
->header
.ancount
* sizeof(struct res_rec
));
549 if((copy_nmb
->nsrecs
= (struct res_rec
*)
550 malloc(nmb
->header
.nscount
* sizeof(struct res_rec
))) == NULL
)
552 memcpy((char *)copy_nmb
->nsrecs
, (char *)nmb
->nsrecs
,
553 nmb
->header
.nscount
* sizeof(struct res_rec
));
557 if((copy_nmb
->additional
= (struct res_rec
*)
558 malloc(nmb
->header
.arcount
* sizeof(struct res_rec
))) == NULL
)
560 memcpy((char *)copy_nmb
->additional
, (char *)nmb
->additional
,
561 nmb
->header
.arcount
* sizeof(struct res_rec
));
568 if(copy_nmb
->answers
)
569 free((char *)copy_nmb
->answers
);
571 free((char *)copy_nmb
->nsrecs
);
572 if(copy_nmb
->additional
)
573 free((char *)copy_nmb
->additional
);
574 free((char *)pkt_copy
);
576 DEBUG(0,("copy_nmb_packet: malloc fail in resource records.\n"));
580 /*******************************************************************
581 'Copy constructor' for a dgram packet
582 ******************************************************************/
583 static struct packet_struct
*copy_dgram_packet(struct packet_struct
*packet
)
585 struct packet_struct
*pkt_copy
;
587 if(( pkt_copy
= (struct packet_struct
*)malloc(sizeof(*packet
))) == NULL
)
589 DEBUG(0,("copy_dgram_packet: malloc fail.\n"));
593 /* Structure copy of entire thing. */
597 /* Ensure this copy is not locked. */
598 pkt_copy
->locked
= False
;
600 /* There are no additional pointers in a dgram packet,
605 /*******************************************************************
606 'Copy constructor' for a generic packet
607 ******************************************************************/
608 struct packet_struct
*copy_packet(struct packet_struct
*packet
)
610 if(packet
->packet_type
== NMB_PACKET
)
611 return copy_nmb_packet(packet
);
612 else if (packet
->packet_type
== DGRAM_PACKET
)
613 return copy_dgram_packet(packet
);
617 /*******************************************************************
618 free up any resources associated with an nmb packet
619 ******************************************************************/
620 static void free_nmb_packet(struct nmb_packet
*nmb
)
622 if (nmb
->answers
) free(nmb
->answers
);
623 if (nmb
->nsrecs
) free(nmb
->nsrecs
);
624 if (nmb
->additional
) free(nmb
->additional
);
627 /*******************************************************************
628 free up any resources associated with a dgram packet
629 ******************************************************************/
630 static void free_dgram_packet(struct dgram_packet
*nmb
)
632 /* We have nothing to do for a dgram packet. */
636 /*******************************************************************
637 free up any resources associated with a packet
638 ******************************************************************/
639 void free_packet(struct packet_struct
*packet
)
643 if (packet
->packet_type
== NMB_PACKET
)
644 free_nmb_packet(&packet
->packet
.nmb
);
645 else if (packet
->packet_type
== DGRAM_PACKET
)
646 free_dgram_packet(&packet
->packet
.dgram
);
650 /*******************************************************************
651 read a packet from a socket and parse it, returning a packet ready
652 to be used or put on the queue. This assumes a UDP socket
653 ******************************************************************/
654 struct packet_struct
*read_packet(int fd
,enum packet_type packet_type
)
656 extern struct in_addr lastip
;
658 struct packet_struct
*packet
;
659 char buf
[MAX_DGRAM_SIZE
];
663 length
= read_udp_socket(fd
,buf
,sizeof(buf
));
664 if (length
< MIN_DGRAM_SIZE
) return(NULL
);
666 packet
= (struct packet_struct
*)malloc(sizeof(*packet
));
667 if (!packet
) return(NULL
);
672 packet
->port
= lastport
;
674 packet
->locked
= False
;
675 packet
->timestamp
= time(NULL
);
676 packet
->packet_type
= packet_type
;
680 ok
= parse_nmb(buf
,length
,&packet
->packet
.nmb
);
684 ok
= parse_dgram(buf
,length
,&packet
->packet
.dgram
);
688 DEBUG(10,("read_packet: discarding packet id = %d\n",
689 packet
->packet
.nmb
.header
.name_trn_id
));
696 DEBUG(5,("Received a packet of len %d from (%s) port %d\n",
697 length
, inet_ntoa(packet
->ip
), packet
->port
) );
703 /*******************************************************************
704 send a udp packet on a already open socket
705 ******************************************************************/
706 static BOOL
send_udp(int fd
,char *buf
,int len
,struct in_addr ip
,int port
)
709 struct sockaddr_in sock_out
;
711 /* set the address and port */
712 memset((char *)&sock_out
,'\0',sizeof(sock_out
));
713 putip((char *)&sock_out
.sin_addr
,(char *)&ip
);
714 sock_out
.sin_port
= htons( port
);
715 sock_out
.sin_family
= AF_INET
;
717 DEBUG( 5, ( "Sending a packet of len %d to (%s) on port %d\n",
718 len
, inet_ntoa(ip
), port
) );
720 ret
= (sendto(fd
,buf
,len
,0,(struct sockaddr
*)&sock_out
,
721 sizeof(sock_out
)) >= 0);
724 DEBUG(0,("Packet send failed to %s(%d) ERRNO=%s\n",
725 inet_ntoa(ip
),port
,strerror(errno
)));
733 /*******************************************************************
734 build a dgram packet ready for sending
736 XXXX This currently doesn't handle packets too big for one
737 datagram. It should split them and use the packet_offset, more and
738 first flags to handle the fragmentation. Yuck.
739 ******************************************************************/
740 static int build_dgram(char *buf
,struct packet_struct
*p
)
742 struct dgram_packet
*dgram
= &p
->packet
.dgram
;
743 unsigned char *ubuf
= (unsigned char *)buf
;
746 /* put in the header */
747 ubuf
[0] = dgram
->header
.msg_type
;
748 ubuf
[1] = (((int)dgram
->header
.flags
.node_type
)<<2);
749 if (dgram
->header
.flags
.more
) ubuf
[1] |= 1;
750 if (dgram
->header
.flags
.first
) ubuf
[1] |= 2;
751 RSSVAL(ubuf
,2,dgram
->header
.dgm_id
);
752 putip(ubuf
+4,(char *)&dgram
->header
.source_ip
);
753 RSSVAL(ubuf
,8,dgram
->header
.source_port
);
754 RSSVAL(ubuf
,12,dgram
->header
.packet_offset
);
758 if (dgram
->header
.msg_type
== 0x10 ||
759 dgram
->header
.msg_type
== 0x11 ||
760 dgram
->header
.msg_type
== 0x12) {
761 offset
+= put_nmb_name((char *)ubuf
,offset
,&dgram
->source_name
);
762 offset
+= put_nmb_name((char *)ubuf
,offset
,&dgram
->dest_name
);
765 memcpy(ubuf
+offset
,dgram
->data
,dgram
->datasize
);
766 offset
+= dgram
->datasize
;
768 /* automatically set the dgm_length */
769 dgram
->header
.dgm_length
= offset
;
770 RSSVAL(ubuf
,10,dgram
->header
.dgm_length
);
775 /*******************************************************************
777 *******************************************************************/
778 void make_nmb_name( struct nmb_name
*n
, const char *name
, int type
)
780 extern pstring global_scope
;
781 memset( (char *)n
, '\0', sizeof(struct nmb_name
) );
782 StrnCpy( n
->name
, name
, 15 );
784 n
->name_type
= (unsigned int)type
& 0xFF;
785 StrnCpy( n
->scope
, global_scope
, 63 );
786 strupper( n
->scope
);
789 /*******************************************************************
790 Compare two nmb names
791 ******************************************************************/
793 BOOL
nmb_name_equal(struct nmb_name
*n1
, struct nmb_name
*n2
)
795 return ((n1
->name_type
== n2
->name_type
) &&
796 strequal(n1
->name
,n2
->name
) &&
797 strequal(n1
->scope
,n2
->scope
));
800 /*******************************************************************
801 build a nmb packet ready for sending
803 XXXX this currently relies on not being passed something that expands
804 to a packet too big for the buffer. Eventually this should be
805 changed to set the trunc bit so the receiver can request the rest
806 via tcp (when that becomes supported)
807 ******************************************************************/
808 static int build_nmb(char *buf
,struct packet_struct
*p
)
810 struct nmb_packet
*nmb
= &p
->packet
.nmb
;
811 unsigned char *ubuf
= (unsigned char *)buf
;
814 /* put in the header */
815 RSSVAL(ubuf
,offset
,nmb
->header
.name_trn_id
);
816 ubuf
[offset
+2] = (nmb
->header
.opcode
& 0xF) << 3;
817 if (nmb
->header
.response
) ubuf
[offset
+2] |= (1<<7);
818 if (nmb
->header
.nm_flags
.authoritative
&&
819 nmb
->header
.response
) ubuf
[offset
+2] |= 0x4;
820 if (nmb
->header
.nm_flags
.trunc
) ubuf
[offset
+2] |= 0x2;
821 if (nmb
->header
.nm_flags
.recursion_desired
) ubuf
[offset
+2] |= 0x1;
822 if (nmb
->header
.nm_flags
.recursion_available
&&
823 nmb
->header
.response
) ubuf
[offset
+3] |= 0x80;
824 if (nmb
->header
.nm_flags
.bcast
) ubuf
[offset
+3] |= 0x10;
825 ubuf
[offset
+3] |= (nmb
->header
.rcode
& 0xF);
827 RSSVAL(ubuf
,offset
+4,nmb
->header
.qdcount
);
828 RSSVAL(ubuf
,offset
+6,nmb
->header
.ancount
);
829 RSSVAL(ubuf
,offset
+8,nmb
->header
.nscount
);
830 RSSVAL(ubuf
,offset
+10,nmb
->header
.arcount
);
833 if (nmb
->header
.qdcount
) {
834 /* XXXX this doesn't handle a qdcount of > 1 */
835 offset
+= put_nmb_name((char *)ubuf
,offset
,&nmb
->question
.question_name
);
836 RSSVAL(ubuf
,offset
,nmb
->question
.question_type
);
837 RSSVAL(ubuf
,offset
+2,nmb
->question
.question_class
);
841 if (nmb
->header
.ancount
)
842 offset
+= put_res_rec((char *)ubuf
,offset
,nmb
->answers
,
843 nmb
->header
.ancount
);
845 if (nmb
->header
.nscount
)
846 offset
+= put_res_rec((char *)ubuf
,offset
,nmb
->nsrecs
,
847 nmb
->header
.nscount
);
850 * The spec says we must put compressed name pointers
851 * in the following outgoing packets :
852 * NAME_REGISTRATION_REQUEST, NAME_REFRESH_REQUEST,
853 * NAME_RELEASE_REQUEST.
856 if((nmb
->header
.response
== False
) &&
857 ((nmb
->header
.opcode
== NMB_NAME_REG_OPCODE
) ||
858 (nmb
->header
.opcode
== NMB_NAME_RELEASE_OPCODE
) ||
859 (nmb
->header
.opcode
== NMB_NAME_REFRESH_OPCODE_8
) ||
860 (nmb
->header
.opcode
== NMB_NAME_REFRESH_OPCODE_9
) ||
861 (nmb
->header
.opcode
== NMB_NAME_MULTIHOMED_REG_OPCODE
)) &&
862 (nmb
->header
.arcount
== 1)) {
864 offset
+= put_compressed_name_ptr(ubuf
,offset
,nmb
->additional
,12);
866 } else if (nmb
->header
.arcount
) {
867 offset
+= put_res_rec((char *)ubuf
,offset
,nmb
->additional
,
868 nmb
->header
.arcount
);
874 /*******************************************************************
876 ******************************************************************/
877 BOOL
send_packet(struct packet_struct
*p
)
882 memset(buf
,'\0',sizeof(buf
));
884 switch (p
->packet_type
)
887 len
= build_nmb(buf
,p
);
892 len
= build_dgram(buf
,p
);
896 if (!len
) return(False
);
898 return(send_udp(p
->fd
,buf
,len
,p
->ip
,p
->port
));
901 /****************************************************************************
902 receive a packet with timeout on a open UDP filedescriptor
903 The timeout is in milliseconds
904 ***************************************************************************/
905 struct packet_struct
*receive_packet(int fd
,enum packet_type type
,int t
)
908 struct timeval timeout
;
912 timeout
.tv_sec
= t
/1000;
913 timeout
.tv_usec
= 1000*(t
%1000);
915 sys_select(fd
+1,&fds
,&timeout
);
917 if (FD_ISSET(fd
,&fds
))
918 return(read_packet(fd
,type
));
924 /****************************************************************************
925 return the number of bits that match between two 4 character buffers
926 ***************************************************************************/
927 static int matching_bits(uchar
*p1
, uchar
*p2
)
930 for (i
=0; i
<4; i
++) {
931 if (p1
[i
] != p2
[i
]) break;
935 if (i
==4) return ret
;
937 for (j
=0; j
<8; j
++) {
938 if ((p1
[i
] & (1<<(7-j
))) != (p2
[i
] & (1<<(7-j
)))) break;
945 static uchar sort_ip
[4];
947 /****************************************************************************
948 compare two query reply records
949 ***************************************************************************/
950 static int name_query_comp(uchar
*p1
, uchar
*p2
)
952 return matching_bits(p2
+2, sort_ip
) - matching_bits(p1
+2, sort_ip
);
955 /****************************************************************************
956 sort a set of 6 byte name query response records so that the IPs that
957 have the most leading bits in common with the specified address come first
958 ***************************************************************************/
959 void sort_query_replies(char *data
, int n
, struct in_addr ip
)
963 putip(sort_ip
, (char *)&ip
);
965 qsort(data
, n
, 6, QSORT_CAST name_query_comp
);