2 Unix SMB/Netbios implementation.
4 NBT netbios library routines
5 Copyright (C) Andrew Tridgell 1994-1995
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 pstring myname
;
31 extern struct in_addr ipzero
;
34 /****************************************************************************
35 print out a res_rec structure
36 ****************************************************************************/
37 static void debug_nmb_res_rec(struct res_rec
*res
, char *hdr
)
41 DEBUG(4,(" %s: nmb_name=%s rr_type=%d rr_class=%d ttl=%d\n",
43 namestr(&res
->rr_name
),
48 if (res
->rdlength
== 0 || res
->rdata
== NULL
) return;
50 for (i
= 0; i
< res
->rdlength
; i
+= 16)
52 DEBUG(4, (" %s %3x char ", hdr
, i
));
54 for (j
= 0; j
< 16; j
++)
56 unsigned char x
= res
->rdata
[i
+j
];
57 if (x
< 32 || x
> 127) x
= '.';
59 if (i
+j
>= res
->rdlength
) break;
63 DEBUG(4, (" hex ", i
));
65 for (j
= 0; j
< 16; j
++)
67 if (i
+j
>= res
->rdlength
) break;
68 DEBUG(4, ("%02X", (unsigned char)res
->rdata
[i
+j
]));
75 /****************************************************************************
77 ****************************************************************************/
78 void debug_nmb_packet(struct packet_struct
*p
)
80 struct nmb_packet
*nmb
= &p
->packet
.nmb
;
82 DEBUG(4,("nmb packet from %s header: id=%d opcode=%d response=%s\n",
84 nmb
->header
.name_trn_id
,nmb
->header
.opcode
,BOOLSTR(nmb
->header
.response
)));
85 DEBUG(4,(" header: flags: bcast=%s rec_avail=%s rec_des=%s trunc=%s auth=%s\n",
86 BOOLSTR(nmb
->header
.nm_flags
.bcast
),
87 BOOLSTR(nmb
->header
.nm_flags
.recursion_available
),
88 BOOLSTR(nmb
->header
.nm_flags
.recursion_desired
),
89 BOOLSTR(nmb
->header
.nm_flags
.trunc
),
90 BOOLSTR(nmb
->header
.nm_flags
.authoritative
)));
91 DEBUG(4,(" header: rcode=%d qdcount=%d ancount=%d nscount=%d arcount=%d\n",
96 nmb
->header
.arcount
));
98 if (nmb
->header
.qdcount
)
100 DEBUG(4,(" question: q_name=%s q_type=%d q_class=%d\n",
101 namestr(&nmb
->question
.question_name
),
102 nmb
->question
.question_type
,
103 nmb
->question
.question_class
));
106 if (nmb
->answers
&& nmb
->header
.ancount
)
108 debug_nmb_res_rec(nmb
->answers
,"answers");
110 if (nmb
->nsrecs
&& nmb
->header
.nscount
)
112 debug_nmb_res_rec(nmb
->nsrecs
,"nsrecs");
114 if (nmb
->additional
&& nmb
->header
.arcount
)
116 debug_nmb_res_rec(nmb
->additional
,"additional");
120 /*******************************************************************
121 handle "compressed" name pointers
122 ******************************************************************/
123 static BOOL
handle_name_ptrs(unsigned char *ubuf
,int *offset
,int length
,
124 BOOL
*got_pointer
,int *ret
)
128 while ((ubuf
[*offset
] & 0xC0) == 0xC0) {
129 if (!*got_pointer
) (*ret
) += 2;
131 (*offset
) = ((ubuf
[*offset
] & ~0xC0)<<8) | ubuf
[(*offset
)+1];
132 if (loop_count
++ == 10 || (*offset
) < 0 || (*offset
)>(length
-2)) {
139 /*******************************************************************
140 parse a nmb name from "compressed" format to something readable
141 return the space taken by the name, or 0 if the name is invalid
142 ******************************************************************/
143 static int parse_nmb_name(char *inbuf
,int offset
,int length
, struct nmb_name
*name
)
146 unsigned char *ubuf
= (unsigned char *)inbuf
;
148 BOOL got_pointer
=False
;
150 if (length
- offset
< 2) return(0);
152 /* handle initial name pointers */
153 if (!handle_name_ptrs(ubuf
,&offset
,length
,&got_pointer
,&ret
)) return(0);
158 if ((m
& 0xC0) || offset
+m
+2 > length
) return(0);
160 bzero((char *)name
,sizeof(*name
));
162 /* the "compressed" part */
163 if (!got_pointer
) ret
+= m
+ 2;
167 c1
= ubuf
[offset
++]-'A';
168 c2
= ubuf
[offset
++]-'A';
169 if ((c1
& 0xF0) || (c2
& 0xF0)) return(0);
170 name
->name
[n
++] = (c1
<<4) | c2
;
176 /* parse out the name type,
177 its always in the 16th byte of the name */
178 name
->name_type
= name
->name
[15];
180 /* remove trailing spaces */
183 while (n
&& name
->name
[n
]==' ') name
->name
[n
--] = 0;
186 /* now the domain parts (if any) */
188 while ((m
=ubuf
[offset
])) {
189 /* we can have pointers within the domain part as well */
190 if (!handle_name_ptrs(ubuf
,&offset
,length
,&got_pointer
,&ret
)) return(0);
192 if (!got_pointer
) ret
+= m
+1;
193 if (n
) name
->scope
[n
++] = '.';
194 if (m
+2+offset
>length
|| n
+m
+1>sizeof(name
->scope
)) return(0);
196 while (m
--) name
->scope
[n
++] = (char)ubuf
[offset
++];
198 name
->scope
[n
++] = 0;
204 /*******************************************************************
205 put a compressed nmb name into a buffer. return the length of the
208 compressed names are really weird. The "compression" doubles the
209 size. The idea is that it also means that compressed names conform
210 to the doman name system. See RFC1002.
211 ******************************************************************/
212 static int put_nmb_name(char *buf
,int offset
,struct nmb_name
*name
)
218 if (name
->name
[0] == '*') {
219 /* special case for wildcard name */
223 sprintf(buf1
,"%-15.15s%c",name
->name
,name
->name_type
);
231 buf
[offset
+1+2*m
] = 'A' + ((buf1
[m
]>>4)&0xF);
232 buf
[offset
+2+2*m
] = 'A' + (buf1
[m
]&0xF);
238 if (name
->scope
[0]) {
239 /* XXXX this scope handling needs testing */
240 ret
+= strlen(name
->scope
) + 1;
241 strcpy(&buf
[offset
+1],name
->scope
);
244 while ((p
= strchr(p
,'.'))) {
245 buf
[offset
] = PTR_DIFF(p
,&buf
[offset
]);
246 offset
+= buf
[offset
];
249 buf
[offset
] = strlen(&buf
[offset
+1]);
255 /*******************************************************************
256 useful for debugging messages
257 ******************************************************************/
258 char *namestr(struct nmb_name
*n
)
261 static fstring ret
[4];
265 sprintf(p
,"%s(%x)",n
->name
,n
->name_type
);
267 sprintf(p
,"%s(%x).%s",n
->name
,n
->name_type
,n
->scope
);
273 /*******************************************************************
274 allocate and parse some resource records
275 ******************************************************************/
276 static BOOL
parse_alloc_res_rec(char *inbuf
,int *offset
,int length
,
277 struct res_rec
**recs
, int count
)
280 *recs
= (struct res_rec
*)malloc(sizeof(**recs
)*count
);
281 if (!*recs
) return(False
);
283 bzero(*recs
,sizeof(**recs
)*count
);
285 for (i
=0;i
<count
;i
++) {
286 int l
= parse_nmb_name(inbuf
,*offset
,length
,&(*recs
)[i
].rr_name
);
288 if (!l
|| (*offset
)+10 > length
) {
292 (*recs
)[i
].rr_type
= RSVAL(inbuf
,(*offset
));
293 (*recs
)[i
].rr_class
= RSVAL(inbuf
,(*offset
)+2);
294 (*recs
)[i
].ttl
= RIVAL(inbuf
,(*offset
)+4);
295 (*recs
)[i
].rdlength
= RSVAL(inbuf
,(*offset
)+8);
297 if ((*recs
)[i
].rdlength
>sizeof((*recs
)[i
].rdata
) ||
298 (*offset
)+(*recs
)[i
].rdlength
> length
) {
302 memcpy((*recs
)[i
].rdata
,inbuf
+(*offset
),(*recs
)[i
].rdlength
);
303 (*offset
) += (*recs
)[i
].rdlength
;
308 /*******************************************************************
309 put a resource record into a packet
310 ******************************************************************/
311 static int put_res_rec(char *buf
,int offset
,struct res_rec
*recs
,int count
)
316 for (i
=0;i
<count
;i
++) {
317 int l
= put_nmb_name(buf
,offset
,&recs
[i
].rr_name
);
320 RSSVAL(buf
,offset
,recs
[i
].rr_type
);
321 RSSVAL(buf
,offset
+2,recs
[i
].rr_class
);
322 RSIVAL(buf
,offset
+4,recs
[i
].ttl
);
323 RSSVAL(buf
,offset
+8,recs
[i
].rdlength
);
324 memcpy(buf
+offset
+10,recs
[i
].rdata
,recs
[i
].rdlength
);
325 offset
+= 10+recs
[i
].rdlength
;
326 ret
+= 10+recs
[i
].rdlength
;
332 /*******************************************************************
333 parse a dgram packet. Return False if the packet can't be parsed
334 or is invalid for some reason, True otherwise
336 this is documented in section 4.4.1 of RFC1002
337 ******************************************************************/
338 static BOOL
parse_dgram(char *inbuf
,int length
,struct dgram_packet
*dgram
)
343 bzero((char *)dgram
,sizeof(*dgram
));
345 if (length
< 14) return(False
);
347 dgram
->header
.msg_type
= CVAL(inbuf
,0);
348 flags
= CVAL(inbuf
,1);
349 dgram
->header
.flags
.node_type
= (enum node_type
)((flags
>>2)&3);
350 if (flags
& 1) dgram
->header
.flags
.more
= True
;
351 if (flags
& 2) dgram
->header
.flags
.first
= True
;
352 dgram
->header
.dgm_id
= RSVAL(inbuf
,2);
353 putip((char *)&dgram
->header
.source_ip
,inbuf
+4);
354 dgram
->header
.source_port
= RSVAL(inbuf
,8);
355 dgram
->header
.dgm_length
= RSVAL(inbuf
,10);
356 dgram
->header
.packet_offset
= RSVAL(inbuf
,12);
360 if (dgram
->header
.msg_type
== 0x10 ||
361 dgram
->header
.msg_type
== 0x11 ||
362 dgram
->header
.msg_type
== 0x12) {
363 offset
+= parse_nmb_name(inbuf
,offset
,length
,&dgram
->source_name
);
364 offset
+= parse_nmb_name(inbuf
,offset
,length
,&dgram
->dest_name
);
367 if (offset
>= length
|| (length
-offset
> sizeof(dgram
->data
)))
370 dgram
->datasize
= length
-offset
;
371 memcpy(dgram
->data
,inbuf
+offset
,dgram
->datasize
);
377 /*******************************************************************
378 parse a nmb packet. Return False if the packet can't be parsed
379 or is invalid for some reason, True otherwise
380 ******************************************************************/
381 static BOOL
parse_nmb(char *inbuf
,int length
,struct nmb_packet
*nmb
)
385 bzero((char *)nmb
,sizeof(*nmb
));
387 if (length
< 12) return(False
);
389 /* parse the header */
390 nmb
->header
.name_trn_id
= RSVAL(inbuf
,0);
391 nmb
->header
.opcode
= (CVAL(inbuf
,2) >> 3) & 0xF;
392 nmb
->header
.response
= ((CVAL(inbuf
,2)>>7)&1)?True
:False
;
393 nm_flags
= ((CVAL(inbuf
,2) & 0x7) << 4) + (CVAL(inbuf
,3)>>4);
394 nmb
->header
.nm_flags
.bcast
= (nm_flags
&1)?True
:False
;
395 nmb
->header
.nm_flags
.recursion_available
= (nm_flags
&8)?True
:False
;
396 nmb
->header
.nm_flags
.recursion_desired
= (nm_flags
&0x10)?True
:False
;
397 nmb
->header
.nm_flags
.trunc
= (nm_flags
&0x20)?True
:False
;
398 nmb
->header
.nm_flags
.authoritative
= (nm_flags
&0x40)?True
:False
;
399 nmb
->header
.rcode
= CVAL(inbuf
,3) & 0xF;
400 nmb
->header
.qdcount
= RSVAL(inbuf
,4);
401 nmb
->header
.ancount
= RSVAL(inbuf
,6);
402 nmb
->header
.nscount
= RSVAL(inbuf
,8);
403 nmb
->header
.arcount
= RSVAL(inbuf
,10);
405 if (nmb
->header
.qdcount
) {
406 offset
= parse_nmb_name(inbuf
,12,length
,&nmb
->question
.question_name
);
407 if (!offset
) return(False
);
409 if (length
- (12+offset
) < 4) return(False
);
410 nmb
->question
.question_type
= RSVAL(inbuf
,12+offset
);
411 nmb
->question
.question_class
= RSVAL(inbuf
,12+offset
+2);
418 /* and any resource records */
419 if (nmb
->header
.ancount
&&
420 !parse_alloc_res_rec(inbuf
,&offset
,length
,&nmb
->answers
,
421 nmb
->header
.ancount
))
424 if (nmb
->header
.nscount
&&
425 !parse_alloc_res_rec(inbuf
,&offset
,length
,&nmb
->nsrecs
,
426 nmb
->header
.nscount
))
429 if (nmb
->header
.arcount
&&
430 !parse_alloc_res_rec(inbuf
,&offset
,length
,&nmb
->additional
,
431 nmb
->header
.arcount
))
437 /*******************************************************************
438 free up any resources associated with an nmb packet
439 ******************************************************************/
440 void free_nmb_packet(struct nmb_packet
*nmb
)
442 if (nmb
->answers
) free(nmb
->answers
);
443 if (nmb
->nsrecs
) free(nmb
->nsrecs
);
444 if (nmb
->additional
) free(nmb
->additional
);
447 /*******************************************************************
448 free up any resources associated with a packet
449 ******************************************************************/
450 void free_packet(struct packet_struct
*packet
)
452 if (packet
->packet_type
== NMB_PACKET
)
453 free_nmb_packet(&packet
->packet
.nmb
);
457 /*******************************************************************
458 read a packet from a socket and parse it, returning a packet ready
459 to be used or put on the queue. This assumes a UDP socket
460 ******************************************************************/
461 struct packet_struct
*read_packet(int fd
,enum packet_type packet_type
)
463 extern struct in_addr lastip
;
465 struct packet_struct
*packet
;
466 char buf
[MAX_DGRAM_SIZE
];
470 length
= read_udp_socket(fd
,buf
,sizeof(buf
));
471 if (length
< MIN_DGRAM_SIZE
) return(NULL
);
473 packet
= (struct packet_struct
*)malloc(sizeof(*packet
));
474 if (!packet
) return(NULL
);
479 packet
->port
= lastport
;
481 packet
->timestamp
= time(NULL
);
482 packet
->packet_type
= packet_type
;
486 ok
= parse_nmb(buf
,length
,&packet
->packet
.nmb
);
490 ok
= parse_dgram(buf
,length
,&packet
->packet
.dgram
);
500 DEBUG(5,("%s received a packet of len %d from (%s) port %d\n",
501 timestring(),length
,inet_ntoa(packet
->ip
),packet
->port
));
507 /*******************************************************************
508 send a udp packet on a already open socket
509 ******************************************************************/
510 static BOOL
send_udp(int fd
,char *buf
,int len
,struct in_addr ip
,int port
)
513 struct sockaddr_in sock_out
;
515 /* set the address and port */
516 bzero((char *)&sock_out
,sizeof(sock_out
));
517 putip((char *)&sock_out
.sin_addr
,(char *)&ip
);
518 sock_out
.sin_port
= htons( port
);
519 sock_out
.sin_family
= AF_INET
;
521 DEBUG(5,("%s sending a packet of len %d to (%s) on port %d\n",
522 timestring(),len
,inet_ntoa(ip
),port
));
524 ret
= (sendto(fd
,buf
,len
,0,(struct sockaddr
*)&sock_out
,
525 sizeof(sock_out
)) >= 0);
528 DEBUG(0,("Packet send failed to %s(%d) ERRNO=%s\n",
529 inet_ntoa(ip
),port
,strerror(errno
)));
537 /*******************************************************************
538 build a dgram packet ready for sending
540 XXXX This currently doesn't handle packets too big for one
541 datagram. It should split them and use the packet_offset, more and
542 first flags to handle the fragmentation. Yuck.
543 ******************************************************************/
544 static int build_dgram(char *buf
,struct packet_struct
*p
)
546 struct dgram_packet
*dgram
= &p
->packet
.dgram
;
547 unsigned char *ubuf
= (unsigned char *)buf
;
550 /* put in the header */
551 ubuf
[0] = dgram
->header
.msg_type
;
552 ubuf
[1] = (((int)dgram
->header
.flags
.node_type
)<<2);
553 if (dgram
->header
.flags
.more
) ubuf
[1] |= 1;
554 if (dgram
->header
.flags
.first
) ubuf
[1] |= 2;
555 RSSVAL(ubuf
,2,dgram
->header
.dgm_id
);
556 putip(ubuf
+4,(char *)&dgram
->header
.source_ip
);
557 RSSVAL(ubuf
,8,dgram
->header
.source_port
);
558 RSSVAL(ubuf
,12,dgram
->header
.packet_offset
);
562 if (dgram
->header
.msg_type
== 0x10 ||
563 dgram
->header
.msg_type
== 0x11 ||
564 dgram
->header
.msg_type
== 0x12) {
565 offset
+= put_nmb_name((char *)ubuf
,offset
,&dgram
->source_name
);
566 offset
+= put_nmb_name((char *)ubuf
,offset
,&dgram
->dest_name
);
569 memcpy(ubuf
+offset
,dgram
->data
,dgram
->datasize
);
570 offset
+= dgram
->datasize
;
572 /* automatically set the dgm_length */
573 dgram
->header
.dgm_length
= offset
;
574 RSSVAL(ubuf
,10,dgram
->header
.dgm_length
);
579 /*******************************************************************
581 ******************************************************************/
582 void make_nmb_name(struct nmb_name
*n
,char *name
,int type
,char *this_scope
)
584 strcpy(n
->name
,name
);
587 strcpy(n
->scope
,this_scope
);
591 /*******************************************************************
592 build a nmb packet ready for sending
594 XXXX this currently relies on not being passed something that expands
595 to a packet too big for the buffer. Eventually this should be
596 changed to set the trunc bit so the receiver can request the rest
597 via tcp (when that becomes supported)
598 ******************************************************************/
599 static int build_nmb(char *buf
,struct packet_struct
*p
)
601 struct nmb_packet
*nmb
= &p
->packet
.nmb
;
602 unsigned char *ubuf
= (unsigned char *)buf
;
605 /* put in the header */
606 RSSVAL(ubuf
,offset
,nmb
->header
.name_trn_id
);
607 ubuf
[offset
+2] = (nmb
->header
.opcode
& 0xF) << 3;
608 if (nmb
->header
.response
) ubuf
[offset
+2] |= (1<<7);
609 if (nmb
->header
.nm_flags
.authoritative
) ubuf
[offset
+2] |= 0x4;
610 if (nmb
->header
.nm_flags
.trunc
) ubuf
[offset
+2] |= 0x2;
611 if (nmb
->header
.nm_flags
.recursion_desired
) ubuf
[offset
+2] |= 0x1;
612 if (nmb
->header
.nm_flags
.recursion_available
) ubuf
[offset
+3] |= 0x80;
613 if (nmb
->header
.nm_flags
.bcast
) ubuf
[offset
+3] |= 0x10;
614 ubuf
[offset
+3] |= (nmb
->header
.rcode
& 0xF);
616 RSSVAL(ubuf
,offset
+4,nmb
->header
.qdcount
);
617 RSSVAL(ubuf
,offset
+6,nmb
->header
.ancount
);
618 RSSVAL(ubuf
,offset
+8,nmb
->header
.nscount
);
619 RSSVAL(ubuf
,offset
+10,nmb
->header
.arcount
);
622 if (nmb
->header
.qdcount
) {
623 /* XXXX this doesn't handle a qdcount of > 1 */
624 offset
+= put_nmb_name((char *)ubuf
,offset
,&nmb
->question
.question_name
);
625 RSSVAL(ubuf
,offset
,nmb
->question
.question_type
);
626 RSSVAL(ubuf
,offset
+2,nmb
->question
.question_class
);
630 if (nmb
->header
.ancount
)
631 offset
+= put_res_rec((char *)ubuf
,offset
,nmb
->answers
,
632 nmb
->header
.ancount
);
634 if (nmb
->header
.nscount
)
635 offset
+= put_res_rec((char *)ubuf
,offset
,nmb
->nsrecs
,
636 nmb
->header
.nscount
);
638 if (nmb
->header
.arcount
)
639 offset
+= put_res_rec((char *)ubuf
,offset
,nmb
->additional
,
640 nmb
->header
.arcount
);
646 /*******************************************************************
648 ******************************************************************/
649 BOOL
send_packet(struct packet_struct
*p
)
654 bzero(buf
,sizeof(buf
));
656 switch (p
->packet_type
)
659 len
= build_nmb(buf
,p
);
663 len
= build_dgram(buf
,p
);
667 if (!len
) return(False
);
669 return(send_udp(p
->fd
,buf
,len
,p
->ip
,p
->port
));
672 /****************************************************************************
673 receive a packet with timeout on a open UDP filedescriptor
674 The timeout is in milliseconds
675 ***************************************************************************/
676 struct packet_struct
*receive_packet(int fd
,enum packet_type type
,int t
)
679 struct timeval timeout
;
683 timeout
.tv_sec
= t
/1000;
684 timeout
.tv_usec
= 1000*(t
%1000);
686 sys_select(&fds
,&timeout
);
688 if (FD_ISSET(fd
,&fds
))
689 return(read_packet(fd
,type
));