'The mother of all checkins' :-). Jeremy Allison (jallison@whistle.com)
[Samba.git] / source / libsmb / nmblib.c
blob89a5cf9534bbd2f80c34b7144ef221d9d216cfb1
1 /*
2 Unix SMB/Netbios implementation.
3 Version 1.9.
4 NBT netbios library routines
5 Copyright (C) Andrew Tridgell 1994-1997
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.
23 #include "includes.h"
25 extern int DEBUGLEVEL;
27 int num_good_sends = 0;
28 int num_good_receives = 0;
29 extern pstring scope;
30 extern pstring myname;
31 extern struct in_addr ipzero;
33 static struct opcode_names {
34 const char *nmb_opcode_name;
35 int opcode;
36 } nmb_header_opcode_names[] = {
37 { "Query", 0 },
38 {"Registration", 5 },
39 {"Release", 6 },
40 {"WACK", 7 },
41 {"refresh", 8 },
42 {0, -1 }
45 /****************************************************************************
46 * Lookup a nmb opcode name.
47 ****************************************************************************/
49 const char *lookup_opcode_name( int opcode )
51 struct opcode_names *op_namep;
52 int i;
54 for(i = 0; nmb_header_opcode_names[i].nmb_opcode_name != 0; i++) {
55 op_namep = &nmb_header_opcode_names[i];
56 if(opcode == op_namep->opcode)
57 return op_namep->nmb_opcode_name;
59 return "<unknown opcode>";
62 /****************************************************************************
63 print out a res_rec structure
64 ****************************************************************************/
65 static void debug_nmb_res_rec(struct res_rec *res, char *hdr)
67 int i, j;
69 DEBUG(4,(" %s: nmb_name=%s rr_type=%d rr_class=%d ttl=%d\n",
70 hdr,
71 namestr(&res->rr_name),
72 res->rr_type,
73 res->rr_class,
74 res->ttl));
76 if (res->rdlength == 0 || res->rdata == NULL) return;
78 for (i = 0; i < res->rdlength; i+= 16)
80 DEBUG(4, (" %s %3x char ", hdr, i));
82 for (j = 0; j < 16; j++)
84 unsigned char x = res->rdata[i+j];
85 if (x < 32 || x > 127) x = '.';
87 if (i+j >= res->rdlength) break;
88 DEBUG(4, ("%c", x));
91 DEBUG(4, (" hex ", i));
93 for (j = 0; j < 16; j++)
95 if (i+j >= res->rdlength) break;
96 DEBUG(4, ("%02X", (unsigned char)res->rdata[i+j]));
99 DEBUG(4, ("\n"));
103 /****************************************************************************
104 process a nmb packet
105 ****************************************************************************/
106 void debug_nmb_packet(struct packet_struct *p)
108 struct nmb_packet *nmb = &p->packet.nmb;
110 DEBUG(4,("nmb packet from %s header: id=%d opcode=%s(%d) response=%s\n",
111 inet_ntoa(p->ip),
112 nmb->header.name_trn_id,
113 lookup_opcode_name(nmb->header.opcode),
114 nmb->header.opcode,BOOLSTR(nmb->header.response)));
115 DEBUG(4,(" header: flags: bcast=%s rec_avail=%s rec_des=%s trunc=%s auth=%s\n",
116 BOOLSTR(nmb->header.nm_flags.bcast),
117 BOOLSTR(nmb->header.nm_flags.recursion_available),
118 BOOLSTR(nmb->header.nm_flags.recursion_desired),
119 BOOLSTR(nmb->header.nm_flags.trunc),
120 BOOLSTR(nmb->header.nm_flags.authoritative)));
121 DEBUG(4,(" header: rcode=%d qdcount=%d ancount=%d nscount=%d arcount=%d\n",
122 nmb->header.rcode,
123 nmb->header.qdcount,
124 nmb->header.ancount,
125 nmb->header.nscount,
126 nmb->header.arcount));
128 if (nmb->header.qdcount)
130 DEBUG(4,(" question: q_name=%s q_type=%d q_class=%d\n",
131 namestr(&nmb->question.question_name),
132 nmb->question.question_type,
133 nmb->question.question_class));
136 if (nmb->answers && nmb->header.ancount)
138 debug_nmb_res_rec(nmb->answers,"answers");
140 if (nmb->nsrecs && nmb->header.nscount)
142 debug_nmb_res_rec(nmb->nsrecs,"nsrecs");
144 if (nmb->additional && nmb->header.arcount)
146 debug_nmb_res_rec(nmb->additional,"additional");
150 /*******************************************************************
151 handle "compressed" name pointers
152 ******************************************************************/
153 static BOOL handle_name_ptrs(unsigned char *ubuf,int *offset,int length,
154 BOOL *got_pointer,int *ret)
156 int loop_count=0;
158 while ((ubuf[*offset] & 0xC0) == 0xC0) {
159 if (!*got_pointer) (*ret) += 2;
160 (*got_pointer)=True;
161 (*offset) = ((ubuf[*offset] & ~0xC0)<<8) | ubuf[(*offset)+1];
162 if (loop_count++ == 10 || (*offset) < 0 || (*offset)>(length-2)) {
163 return(False);
166 return(True);
169 /*******************************************************************
170 parse a nmb name from "compressed" format to something readable
171 return the space taken by the name, or 0 if the name is invalid
172 ******************************************************************/
173 static int parse_nmb_name(char *inbuf,int offset,int length, struct nmb_name *name)
175 int m,n=0;
176 unsigned char *ubuf = (unsigned char *)inbuf;
177 int ret = 0;
178 BOOL got_pointer=False;
180 if (length - offset < 2) return(0);
182 /* handle initial name pointers */
183 if (!handle_name_ptrs(ubuf,&offset,length,&got_pointer,&ret)) return(0);
185 m = ubuf[offset];
187 if (!m) return(0);
188 if ((m & 0xC0) || offset+m+2 > length) return(0);
190 bzero((char *)name,sizeof(*name));
192 /* the "compressed" part */
193 if (!got_pointer) ret += m + 2;
194 offset++;
195 while (m) {
196 unsigned char c1,c2;
197 c1 = ubuf[offset++]-'A';
198 c2 = ubuf[offset++]-'A';
199 if ((c1 & 0xF0) || (c2 & 0xF0)) return(0);
200 name->name[n++] = (c1<<4) | c2;
201 m -= 2;
203 name->name[n] = 0;
205 if (n==16) {
206 /* parse out the name type,
207 its always in the 16th byte of the name */
208 name->name_type = name->name[15];
210 /* remove trailing spaces */
211 name->name[15] = 0;
212 n = 14;
213 while (n && name->name[n]==' ') name->name[n--] = 0;
216 /* now the domain parts (if any) */
217 n = 0;
218 while ((m=ubuf[offset])) {
219 /* we can have pointers within the domain part as well */
220 if (!handle_name_ptrs(ubuf,&offset,length,&got_pointer,&ret)) return(0);
222 if (!got_pointer) ret += m+1;
223 if (n) name->scope[n++] = '.';
224 if (m+2+offset>length || n+m+1>sizeof(name->scope)) return(0);
225 offset++;
226 while (m--) name->scope[n++] = (char)ubuf[offset++];
228 name->scope[n++] = 0;
230 return(ret);
234 /*******************************************************************
235 put a compressed nmb name into a buffer. return the length of the
236 compressed name
238 compressed names are really weird. The "compression" doubles the
239 size. The idea is that it also means that compressed names conform
240 to the doman name system. See RFC1002.
241 ******************************************************************/
242 static int put_nmb_name(char *buf,int offset,struct nmb_name *name)
244 int ret,m;
245 fstring buf1;
246 char *p;
248 if (name->name[0] == '*') {
249 /* special case for wildcard name */
250 bzero(buf1,20);
251 buf1[0] = '*';
252 } else {
253 sprintf(buf1,"%-15.15s%c",name->name,name->name_type);
256 buf[offset] = 0x20;
258 ret = 34;
260 for (m=0;m<16;m++) {
261 buf[offset+1+2*m] = 'A' + ((buf1[m]>>4)&0xF);
262 buf[offset+2+2*m] = 'A' + (buf1[m]&0xF);
264 offset += 33;
266 buf[offset] = 0;
268 if (name->scope[0]) {
269 /* XXXX this scope handling needs testing */
270 ret += strlen(name->scope) + 1;
271 strcpy(&buf[offset+1],name->scope);
273 p = &buf[offset+1];
274 while ((p = strchr(p,'.'))) {
275 buf[offset] = PTR_DIFF(p,&buf[offset]);
276 offset += buf[offset];
277 p = &buf[offset+1];
279 buf[offset] = strlen(&buf[offset+1]);
282 return(ret);
285 /*******************************************************************
286 useful for debugging messages
287 ******************************************************************/
288 char *namestr(struct nmb_name *n)
290 static int i=0;
291 static fstring ret[4];
292 char *p = ret[i];
294 if (!n->scope[0])
295 sprintf(p,"%s(%x)",n->name,n->name_type);
296 else
297 sprintf(p,"%s(%x).%s",n->name,n->name_type,n->scope);
299 i = (i+1)%4;
300 return(p);
303 /*******************************************************************
304 allocate and parse some resource records
305 ******************************************************************/
306 static BOOL parse_alloc_res_rec(char *inbuf,int *offset,int length,
307 struct res_rec **recs, int count)
309 int i;
310 *recs = (struct res_rec *)malloc(sizeof(**recs)*count);
311 if (!*recs) return(False);
313 bzero(*recs,sizeof(**recs)*count);
315 for (i=0;i<count;i++) {
316 int l = parse_nmb_name(inbuf,*offset,length,&(*recs)[i].rr_name);
317 (*offset) += l;
318 if (!l || (*offset)+10 > length) {
319 free(*recs);
320 return(False);
322 (*recs)[i].rr_type = RSVAL(inbuf,(*offset));
323 (*recs)[i].rr_class = RSVAL(inbuf,(*offset)+2);
324 (*recs)[i].ttl = RIVAL(inbuf,(*offset)+4);
325 (*recs)[i].rdlength = RSVAL(inbuf,(*offset)+8);
326 (*offset) += 10;
327 if ((*recs)[i].rdlength>sizeof((*recs)[i].rdata) ||
328 (*offset)+(*recs)[i].rdlength > length) {
329 free(*recs);
330 return(False);
332 memcpy((*recs)[i].rdata,inbuf+(*offset),(*recs)[i].rdlength);
333 (*offset) += (*recs)[i].rdlength;
335 return(True);
338 /*******************************************************************
339 put a resource record into a packet
340 ******************************************************************/
341 static int put_res_rec(char *buf,int offset,struct res_rec *recs,int count)
343 int ret=0;
344 int i;
346 for (i=0;i<count;i++) {
347 int l = put_nmb_name(buf,offset,&recs[i].rr_name);
348 offset += l;
349 ret += l;
350 RSSVAL(buf,offset,recs[i].rr_type);
351 RSSVAL(buf,offset+2,recs[i].rr_class);
352 RSIVAL(buf,offset+4,recs[i].ttl);
353 RSSVAL(buf,offset+8,recs[i].rdlength);
354 memcpy(buf+offset+10,recs[i].rdata,recs[i].rdlength);
355 offset += 10+recs[i].rdlength;
356 ret += 10+recs[i].rdlength;
359 return(ret);
362 /*******************************************************************
363 parse a dgram packet. Return False if the packet can't be parsed
364 or is invalid for some reason, True otherwise
366 this is documented in section 4.4.1 of RFC1002
367 ******************************************************************/
368 static BOOL parse_dgram(char *inbuf,int length,struct dgram_packet *dgram)
370 int offset;
371 int flags;
373 bzero((char *)dgram,sizeof(*dgram));
375 if (length < 14) return(False);
377 dgram->header.msg_type = CVAL(inbuf,0);
378 flags = CVAL(inbuf,1);
379 dgram->header.flags.node_type = (enum node_type)((flags>>2)&3);
380 if (flags & 1) dgram->header.flags.more = True;
381 if (flags & 2) dgram->header.flags.first = True;
382 dgram->header.dgm_id = RSVAL(inbuf,2);
383 putip((char *)&dgram->header.source_ip,inbuf+4);
384 dgram->header.source_port = RSVAL(inbuf,8);
385 dgram->header.dgm_length = RSVAL(inbuf,10);
386 dgram->header.packet_offset = RSVAL(inbuf,12);
388 offset = 14;
390 if (dgram->header.msg_type == 0x10 ||
391 dgram->header.msg_type == 0x11 ||
392 dgram->header.msg_type == 0x12) {
393 offset += parse_nmb_name(inbuf,offset,length,&dgram->source_name);
394 offset += parse_nmb_name(inbuf,offset,length,&dgram->dest_name);
397 if (offset >= length || (length-offset > sizeof(dgram->data)))
398 return(False);
400 dgram->datasize = length-offset;
401 memcpy(dgram->data,inbuf+offset,dgram->datasize);
403 return(True);
407 /*******************************************************************
408 parse a nmb packet. Return False if the packet can't be parsed
409 or is invalid for some reason, True otherwise
410 ******************************************************************/
411 static BOOL parse_nmb(char *inbuf,int length,struct nmb_packet *nmb)
413 int nm_flags,offset;
415 bzero((char *)nmb,sizeof(*nmb));
417 if (length < 12) return(False);
419 /* parse the header */
420 nmb->header.name_trn_id = RSVAL(inbuf,0);
421 nmb->header.opcode = (CVAL(inbuf,2) >> 3) & 0xF;
422 nmb->header.response = ((CVAL(inbuf,2)>>7)&1)?True:False;
423 nm_flags = ((CVAL(inbuf,2) & 0x7) << 4) + (CVAL(inbuf,3)>>4);
424 nmb->header.nm_flags.bcast = (nm_flags&1)?True:False;
425 nmb->header.nm_flags.recursion_available = (nm_flags&8)?True:False;
426 nmb->header.nm_flags.recursion_desired = (nm_flags&0x10)?True:False;
427 nmb->header.nm_flags.trunc = (nm_flags&0x20)?True:False;
428 nmb->header.nm_flags.authoritative = (nm_flags&0x40)?True:False;
429 nmb->header.rcode = CVAL(inbuf,3) & 0xF;
430 nmb->header.qdcount = RSVAL(inbuf,4);
431 nmb->header.ancount = RSVAL(inbuf,6);
432 nmb->header.nscount = RSVAL(inbuf,8);
433 nmb->header.arcount = RSVAL(inbuf,10);
435 if (nmb->header.qdcount) {
436 offset = parse_nmb_name(inbuf,12,length,&nmb->question.question_name);
437 if (!offset) return(False);
439 if (length - (12+offset) < 4) return(False);
440 nmb->question.question_type = RSVAL(inbuf,12+offset);
441 nmb->question.question_class = RSVAL(inbuf,12+offset+2);
443 offset += 12+4;
444 } else {
445 offset = 12;
448 /* and any resource records */
449 if (nmb->header.ancount &&
450 !parse_alloc_res_rec(inbuf,&offset,length,&nmb->answers,
451 nmb->header.ancount))
452 return(False);
454 if (nmb->header.nscount &&
455 !parse_alloc_res_rec(inbuf,&offset,length,&nmb->nsrecs,
456 nmb->header.nscount))
457 return(False);
459 if (nmb->header.arcount &&
460 !parse_alloc_res_rec(inbuf,&offset,length,&nmb->additional,
461 nmb->header.arcount))
462 return(False);
464 return(True);
467 /*******************************************************************
468 free up any resources associated with an nmb packet
469 ******************************************************************/
470 void free_nmb_packet(struct nmb_packet *nmb)
472 if (nmb->answers) free(nmb->answers);
473 if (nmb->nsrecs) free(nmb->nsrecs);
474 if (nmb->additional) free(nmb->additional);
477 /*******************************************************************
478 free up any resources associated with a packet
479 ******************************************************************/
480 void free_packet(struct packet_struct *packet)
482 if (packet->packet_type == NMB_PACKET)
483 free_nmb_packet(&packet->packet.nmb);
484 free(packet);
487 /*******************************************************************
488 read a packet from a socket and parse it, returning a packet ready
489 to be used or put on the queue. This assumes a UDP socket
490 ******************************************************************/
491 struct packet_struct *read_packet(int fd,enum packet_type packet_type)
493 extern struct in_addr lastip;
494 extern int lastport;
495 struct packet_struct *packet;
496 char buf[MAX_DGRAM_SIZE];
497 int length;
498 BOOL ok=False;
500 length = read_udp_socket(fd,buf,sizeof(buf));
501 if (length < MIN_DGRAM_SIZE) return(NULL);
503 packet = (struct packet_struct *)malloc(sizeof(*packet));
504 if (!packet) return(NULL);
506 packet->next = NULL;
507 packet->prev = NULL;
508 packet->ip = lastip;
509 packet->port = lastport;
510 packet->fd = fd;
511 packet->timestamp = time(NULL);
512 packet->packet_type = packet_type;
513 switch (packet_type)
515 case NMB_PACKET:
516 ok = parse_nmb(buf,length,&packet->packet.nmb);
517 break;
519 case DGRAM_PACKET:
520 ok = parse_dgram(buf,length,&packet->packet.dgram);
521 break;
523 if (!ok) {
524 free(packet);
525 return(NULL);
528 num_good_receives++;
530 DEBUG(5,("%s received a packet of len %d from (%s) port %d\n",
531 timestring(),length,inet_ntoa(packet->ip),packet->port));
533 return(packet);
537 /*******************************************************************
538 send a udp packet on a already open socket
539 ******************************************************************/
540 static BOOL send_udp(int fd,char *buf,int len,struct in_addr ip,int port)
542 BOOL ret;
543 struct sockaddr_in sock_out;
545 /* set the address and port */
546 bzero((char *)&sock_out,sizeof(sock_out));
547 putip((char *)&sock_out.sin_addr,(char *)&ip);
548 sock_out.sin_port = htons( port );
549 sock_out.sin_family = AF_INET;
551 DEBUG(5,("%s sending a packet of len %d to (%s) on port %d\n",
552 timestring(),len,inet_ntoa(ip),port));
554 ret = (sendto(fd,buf,len,0,(struct sockaddr *)&sock_out,
555 sizeof(sock_out)) >= 0);
557 if (!ret)
558 DEBUG(0,("Packet send failed to %s(%d) ERRNO=%s\n",
559 inet_ntoa(ip),port,strerror(errno)));
561 if (ret)
562 num_good_sends++;
564 return(ret);
567 /*******************************************************************
568 build a dgram packet ready for sending
570 XXXX This currently doesn't handle packets too big for one
571 datagram. It should split them and use the packet_offset, more and
572 first flags to handle the fragmentation. Yuck.
573 ******************************************************************/
574 static int build_dgram(char *buf,struct packet_struct *p)
576 struct dgram_packet *dgram = &p->packet.dgram;
577 unsigned char *ubuf = (unsigned char *)buf;
578 int offset=0;
580 /* put in the header */
581 ubuf[0] = dgram->header.msg_type;
582 ubuf[1] = (((int)dgram->header.flags.node_type)<<2);
583 if (dgram->header.flags.more) ubuf[1] |= 1;
584 if (dgram->header.flags.first) ubuf[1] |= 2;
585 RSSVAL(ubuf,2,dgram->header.dgm_id);
586 putip(ubuf+4,(char *)&dgram->header.source_ip);
587 RSSVAL(ubuf,8,dgram->header.source_port);
588 RSSVAL(ubuf,12,dgram->header.packet_offset);
590 offset = 14;
592 if (dgram->header.msg_type == 0x10 ||
593 dgram->header.msg_type == 0x11 ||
594 dgram->header.msg_type == 0x12) {
595 offset += put_nmb_name((char *)ubuf,offset,&dgram->source_name);
596 offset += put_nmb_name((char *)ubuf,offset,&dgram->dest_name);
599 memcpy(ubuf+offset,dgram->data,dgram->datasize);
600 offset += dgram->datasize;
602 /* automatically set the dgm_length */
603 dgram->header.dgm_length = offset;
604 RSSVAL(ubuf,10,dgram->header.dgm_length);
606 return(offset);
609 /*******************************************************************
610 build a nmb name
611 ******************************************************************/
612 void make_nmb_name(struct nmb_name *n,char *name,int type,char *this_scope)
614 strcpy(n->name,name);
615 strupper(n->name);
616 n->name_type = type;
617 strcpy(n->scope,this_scope);
621 /*******************************************************************
622 build a nmb packet ready for sending
624 XXXX this currently relies on not being passed something that expands
625 to a packet too big for the buffer. Eventually this should be
626 changed to set the trunc bit so the receiver can request the rest
627 via tcp (when that becomes supported)
628 ******************************************************************/
629 static int build_nmb(char *buf,struct packet_struct *p)
631 struct nmb_packet *nmb = &p->packet.nmb;
632 unsigned char *ubuf = (unsigned char *)buf;
633 int offset=0;
635 /* put in the header */
636 RSSVAL(ubuf,offset,nmb->header.name_trn_id);
637 ubuf[offset+2] = (nmb->header.opcode & 0xF) << 3;
638 if (nmb->header.response) ubuf[offset+2] |= (1<<7);
639 if (nmb->header.nm_flags.authoritative &&
640 nmb->header.response) ubuf[offset+2] |= 0x4;
641 if (nmb->header.nm_flags.trunc) ubuf[offset+2] |= 0x2;
642 if (nmb->header.nm_flags.recursion_desired) ubuf[offset+2] |= 0x1;
643 if (nmb->header.nm_flags.recursion_available &&
644 nmb->header.response) ubuf[offset+3] |= 0x80;
645 if (nmb->header.nm_flags.bcast) ubuf[offset+3] |= 0x10;
646 ubuf[offset+3] |= (nmb->header.rcode & 0xF);
648 RSSVAL(ubuf,offset+4,nmb->header.qdcount);
649 RSSVAL(ubuf,offset+6,nmb->header.ancount);
650 RSSVAL(ubuf,offset+8,nmb->header.nscount);
651 RSSVAL(ubuf,offset+10,nmb->header.arcount);
653 offset += 12;
654 if (nmb->header.qdcount) {
655 /* XXXX this doesn't handle a qdcount of > 1 */
656 offset += put_nmb_name((char *)ubuf,offset,&nmb->question.question_name);
657 RSSVAL(ubuf,offset,nmb->question.question_type);
658 RSSVAL(ubuf,offset+2,nmb->question.question_class);
659 offset += 4;
662 if (nmb->header.ancount)
663 offset += put_res_rec((char *)ubuf,offset,nmb->answers,
664 nmb->header.ancount);
666 if (nmb->header.nscount)
667 offset += put_res_rec((char *)ubuf,offset,nmb->nsrecs,
668 nmb->header.nscount);
670 if (nmb->header.arcount)
671 offset += put_res_rec((char *)ubuf,offset,nmb->additional,
672 nmb->header.arcount);
674 return(offset);
678 /*******************************************************************
679 send a packet_struct
680 ******************************************************************/
681 BOOL send_packet(struct packet_struct *p)
683 char buf[1024];
684 int len=0;
686 bzero(buf,sizeof(buf));
688 switch (p->packet_type)
690 case NMB_PACKET:
691 len = build_nmb(buf,p);
692 break;
694 case DGRAM_PACKET:
695 len = build_dgram(buf,p);
696 break;
699 if (!len) return(False);
701 return(send_udp(p->fd,buf,len,p->ip,p->port));
704 /****************************************************************************
705 receive a packet with timeout on a open UDP filedescriptor
706 The timeout is in milliseconds
707 ***************************************************************************/
708 struct packet_struct *receive_packet(int fd,enum packet_type type,int t)
710 fd_set fds;
711 struct timeval timeout;
713 FD_ZERO(&fds);
714 FD_SET(fd,&fds);
715 timeout.tv_sec = t/1000;
716 timeout.tv_usec = 1000*(t%1000);
718 sys_select(&fds,&timeout);
720 if (FD_ISSET(fd,&fds))
721 return(read_packet(fd,type));
723 return(NULL);