patch to fix NetServerEnum with multiple workgroup lists kindly supplied.
[Samba.git] / source / libsmb / nmblib.c
blob3434f31a3330068fef9cddf55eb41b44d3de30ac
1 /*
2 Unix SMB/Netbios implementation.
3 Version 1.9.
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.
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;
34 /****************************************************************************
35 print out a res_rec structure
36 ****************************************************************************/
37 static void debug_nmb_res_rec(struct res_rec *res, char *hdr)
39 int i, j;
41 DEBUG(4,(" %s: nmb_name=%s rr_type=%d rr_class=%d ttl=%d\n",
42 hdr,
43 namestr(&res->rr_name),
44 res->rr_type,
45 res->rr_class,
46 res->ttl));
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;
60 DEBUG(4, ("%c", x));
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]));
71 DEBUG(4, ("\n"));
75 /****************************************************************************
76 process a nmb packet
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",
83 inet_ntoa(p->ip),
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",
92 nmb->header.rcode,
93 nmb->header.qdcount,
94 nmb->header.ancount,
95 nmb->header.nscount,
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)
126 int loop_count=0;
128 while ((ubuf[*offset] & 0xC0) == 0xC0) {
129 if (!*got_pointer) (*ret) += 2;
130 (*got_pointer)=True;
131 (*offset) = ((ubuf[*offset] & ~0xC0)<<8) | ubuf[(*offset)+1];
132 if (loop_count++ == 10 || (*offset) < 0 || (*offset)>(length-2)) {
133 return(False);
136 return(True);
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)
145 int m,n=0;
146 unsigned char *ubuf = (unsigned char *)inbuf;
147 int ret = 0;
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);
155 m = ubuf[offset];
157 if (!m) 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;
164 offset++;
165 while (m) {
166 unsigned char c1,c2;
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;
171 m -= 2;
173 name->name[n] = 0;
175 if (n==16) {
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 */
181 name->name[15] = 0;
182 n = 14;
183 while (n && name->name[n]==' ') name->name[n--] = 0;
186 /* now the domain parts (if any) */
187 n = 0;
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);
195 offset++;
196 while (m--) name->scope[n++] = (char)ubuf[offset++];
198 name->scope[n++] = 0;
200 return(ret);
204 /*******************************************************************
205 put a compressed nmb name into a buffer. return the length of the
206 compressed name
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)
214 int ret,m;
215 fstring buf1;
216 char *p;
218 if (name->name[0] == '*') {
219 /* special case for wildcard name */
220 bzero(buf1,20);
221 buf1[0] = '*';
222 } else {
223 sprintf(buf1,"%-15.15s%c",name->name,name->name_type);
226 buf[offset] = 0x20;
228 ret = 34;
230 for (m=0;m<16;m++) {
231 buf[offset+1+2*m] = 'A' + ((buf1[m]>>4)&0xF);
232 buf[offset+2+2*m] = 'A' + (buf1[m]&0xF);
234 offset += 33;
236 buf[offset] = 0;
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);
243 p = &buf[offset+1];
244 while ((p = strchr(p,'.'))) {
245 buf[offset] = PTR_DIFF(p,&buf[offset]);
246 offset += buf[offset];
247 p = &buf[offset+1];
249 buf[offset] = strlen(&buf[offset+1]);
252 return(ret);
255 /*******************************************************************
256 useful for debugging messages
257 ******************************************************************/
258 char *namestr(struct nmb_name *n)
260 static int i=0;
261 static fstring ret[4];
262 char *p = ret[i];
264 if (!n->scope[0])
265 sprintf(p,"%s(%x)",n->name,n->name_type);
266 else
267 sprintf(p,"%s(%x).%s",n->name,n->name_type,n->scope);
269 i = (i+1)%4;
270 return(p);
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)
279 int i;
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);
287 (*offset) += l;
288 if (!l || (*offset)+10 > length) {
289 free(*recs);
290 return(False);
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);
296 (*offset) += 10;
297 if ((*recs)[i].rdlength>sizeof((*recs)[i].rdata) ||
298 (*offset)+(*recs)[i].rdlength > length) {
299 free(*recs);
300 return(False);
302 memcpy((*recs)[i].rdata,inbuf+(*offset),(*recs)[i].rdlength);
303 (*offset) += (*recs)[i].rdlength;
305 return(True);
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)
313 int ret=0;
314 int i;
316 for (i=0;i<count;i++) {
317 int l = put_nmb_name(buf,offset,&recs[i].rr_name);
318 offset += l;
319 ret += l;
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;
329 return(ret);
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)
340 int offset;
341 int flags;
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);
358 offset = 14;
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)))
368 return(False);
370 dgram->datasize = length-offset;
371 memcpy(dgram->data,inbuf+offset,dgram->datasize);
373 return(True);
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)
383 int nm_flags,offset;
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);
413 offset += 12+4;
414 } else {
415 offset = 12;
418 /* and any resource records */
419 if (nmb->header.ancount &&
420 !parse_alloc_res_rec(inbuf,&offset,length,&nmb->answers,
421 nmb->header.ancount))
422 return(False);
424 if (nmb->header.nscount &&
425 !parse_alloc_res_rec(inbuf,&offset,length,&nmb->nsrecs,
426 nmb->header.nscount))
427 return(False);
429 if (nmb->header.arcount &&
430 !parse_alloc_res_rec(inbuf,&offset,length,&nmb->additional,
431 nmb->header.arcount))
432 return(False);
434 return(True);
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);
454 free(packet);
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;
464 extern int lastport;
465 struct packet_struct *packet;
466 char buf[MAX_DGRAM_SIZE];
467 int length;
468 BOOL ok=False;
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);
476 packet->next = NULL;
477 packet->prev = NULL;
478 packet->ip = lastip;
479 packet->port = lastport;
480 packet->fd = fd;
481 packet->timestamp = time(NULL);
482 packet->packet_type = packet_type;
483 switch (packet_type)
485 case NMB_PACKET:
486 ok = parse_nmb(buf,length,&packet->packet.nmb);
487 break;
489 case DGRAM_PACKET:
490 ok = parse_dgram(buf,length,&packet->packet.dgram);
491 break;
493 if (!ok) {
494 free(packet);
495 return(NULL);
498 num_good_receives++;
500 DEBUG(5,("%s received a packet of len %d from (%s) port %d\n",
501 timestring(),length,inet_ntoa(packet->ip),packet->port));
503 return(packet);
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)
512 BOOL ret;
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);
527 if (!ret)
528 DEBUG(0,("Packet send failed to %s(%d) ERRNO=%s\n",
529 inet_ntoa(ip),port,strerror(errno)));
531 if (ret)
532 num_good_sends++;
534 return(ret);
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;
548 int offset=0;
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);
560 offset = 14;
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);
576 return(offset);
579 /*******************************************************************
580 build a nmb name
581 ******************************************************************/
582 void make_nmb_name(struct nmb_name *n,char *name,int type,char *this_scope)
584 strcpy(n->name,name);
585 strupper(n->name);
586 n->name_type = type;
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;
603 int offset=0;
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);
621 offset += 12;
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);
627 offset += 4;
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);
642 return(offset);
646 /*******************************************************************
647 send a packet_struct
648 ******************************************************************/
649 BOOL send_packet(struct packet_struct *p)
651 char buf[1024];
652 int len=0;
654 bzero(buf,sizeof(buf));
656 switch (p->packet_type)
658 case NMB_PACKET:
659 len = build_nmb(buf,p);
660 break;
662 case DGRAM_PACKET:
663 len = build_dgram(buf,p);
664 break;
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)
678 fd_set fds;
679 struct timeval timeout;
681 FD_ZERO(&fds);
682 FD_SET(fd,&fds);
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));
691 return(NULL);