add and remove empty files via patch/unified diff
[Samba/vfs_proxy.git] / source3 / libsmb / nmblib.c
blobbfe5e7b97bda22a89303e15c1be05e5e75b41b80
1 /*
2 Unix SMB/CIFS implementation.
3 NBT netbios library routines
4 Copyright (C) Andrew Tridgell 1994-1998
5 Copyright (C) Jeremy Allison 2007
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 3 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, see <http://www.gnu.org/licenses/>.
22 #include "includes.h"
24 int num_good_sends = 0;
25 int num_good_receives = 0;
27 static const struct opcode_names {
28 const char *nmb_opcode_name;
29 int opcode;
30 } nmb_header_opcode_names[] = {
31 {"Query", 0 },
32 {"Registration", 5 },
33 {"Release", 6 },
34 {"WACK", 7 },
35 {"Refresh", 8 },
36 {"Refresh(altcode)", 9 },
37 {"Multi-homed Registration", 15 },
38 {0, -1 }
41 /****************************************************************************
42 Lookup a nmb opcode name.
43 ****************************************************************************/
45 static const char *lookup_opcode_name( int opcode )
47 const struct opcode_names *op_namep;
48 int i;
50 for(i = 0; nmb_header_opcode_names[i].nmb_opcode_name != 0; i++) {
51 op_namep = &nmb_header_opcode_names[i];
52 if(opcode == op_namep->opcode)
53 return op_namep->nmb_opcode_name;
55 return "<unknown opcode>";
58 /****************************************************************************
59 Print out a res_rec structure.
60 ****************************************************************************/
62 static void debug_nmb_res_rec(struct res_rec *res, const char *hdr)
64 int i, j;
66 DEBUGADD( 4, ( " %s: nmb_name=%s rr_type=%d rr_class=%d ttl=%d\n",
67 hdr,
68 nmb_namestr(&res->rr_name),
69 res->rr_type,
70 res->rr_class,
71 res->ttl ) );
73 if( res->rdlength == 0 || res->rdata == NULL )
74 return;
76 for (i = 0; i < res->rdlength; i+= MAX_NETBIOSNAME_LEN) {
77 DEBUGADD(4, (" %s %3x char ", hdr, i));
79 for (j = 0; j < MAX_NETBIOSNAME_LEN; j++) {
80 unsigned char x = res->rdata[i+j];
81 if (x < 32 || x > 127)
82 x = '.';
84 if (i+j >= res->rdlength)
85 break;
86 DEBUGADD(4, ("%c", x));
89 DEBUGADD(4, (" hex "));
91 for (j = 0; j < MAX_NETBIOSNAME_LEN; j++) {
92 if (i+j >= res->rdlength)
93 break;
94 DEBUGADD(4, ("%02X", (unsigned char)res->rdata[i+j]));
97 DEBUGADD(4, ("\n"));
101 /****************************************************************************
102 Process a nmb packet.
103 ****************************************************************************/
105 void debug_nmb_packet(struct packet_struct *p)
107 struct nmb_packet *nmb = &p->packet.nmb;
109 if( DEBUGLVL( 4 ) ) {
110 dbgtext( "nmb packet from %s(%d) header: id=%d "
111 "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,
116 BOOLSTR(nmb->header.response) );
117 dbgtext( " header: flags: bcast=%s rec_avail=%s "
118 "rec_des=%s trunc=%s auth=%s\n",
119 BOOLSTR(nmb->header.nm_flags.bcast),
120 BOOLSTR(nmb->header.nm_flags.recursion_available),
121 BOOLSTR(nmb->header.nm_flags.recursion_desired),
122 BOOLSTR(nmb->header.nm_flags.trunc),
123 BOOLSTR(nmb->header.nm_flags.authoritative) );
124 dbgtext( " header: rcode=%d qdcount=%d ancount=%d "
125 "nscount=%d arcount=%d\n",
126 nmb->header.rcode,
127 nmb->header.qdcount,
128 nmb->header.ancount,
129 nmb->header.nscount,
130 nmb->header.arcount );
133 if (nmb->header.qdcount) {
134 DEBUGADD( 4, ( " question: q_name=%s q_type=%d q_class=%d\n",
135 nmb_namestr(&nmb->question.question_name),
136 nmb->question.question_type,
137 nmb->question.question_class) );
140 if (nmb->answers && nmb->header.ancount) {
141 debug_nmb_res_rec(nmb->answers,"answers");
143 if (nmb->nsrecs && nmb->header.nscount) {
144 debug_nmb_res_rec(nmb->nsrecs,"nsrecs");
146 if (nmb->additional && nmb->header.arcount) {
147 debug_nmb_res_rec(nmb->additional,"additional");
151 /*******************************************************************
152 Handle "compressed" name pointers.
153 ******************************************************************/
155 static bool handle_name_ptrs(unsigned char *ubuf,int *offset,int length,
156 bool *got_pointer,int *ret)
158 int loop_count=0;
160 while ((ubuf[*offset] & 0xC0) == 0xC0) {
161 if (!*got_pointer)
162 (*ret) += 2;
163 (*got_pointer)=True;
164 (*offset) = ((ubuf[*offset] & ~0xC0)<<8) | ubuf[(*offset)+1];
165 if (loop_count++ == 10 ||
166 (*offset) < 0 || (*offset)>(length-2)) {
167 return False;
170 return True;
173 /*******************************************************************
174 Parse a nmb name from "compressed" format to something readable
175 return the space taken by the name, or 0 if the name is invalid
176 ******************************************************************/
178 static int parse_nmb_name(char *inbuf,int ofs,int length, struct nmb_name *name)
180 int m,n=0;
181 unsigned char *ubuf = (unsigned char *)inbuf;
182 int ret = 0;
183 bool got_pointer=False;
184 int loop_count=0;
185 int offset = ofs;
187 if (length - offset < 2)
188 return(0);
190 /* handle initial name pointers */
191 if (!handle_name_ptrs(ubuf,&offset,length,&got_pointer,&ret))
192 return(0);
194 m = ubuf[offset];
196 if (!m)
197 return(0);
198 if ((m & 0xC0) || offset+m+2 > length)
199 return(0);
201 memset((char *)name,'\0',sizeof(*name));
203 /* the "compressed" part */
204 if (!got_pointer)
205 ret += m + 2;
206 offset++;
207 while (m > 0) {
208 unsigned char c1,c2;
209 c1 = ubuf[offset++]-'A';
210 c2 = ubuf[offset++]-'A';
211 if ((c1 & 0xF0) || (c2 & 0xF0) || (n > sizeof(name->name)-1))
212 return(0);
213 name->name[n++] = (c1<<4) | c2;
214 m -= 2;
216 name->name[n] = 0;
218 if (n==MAX_NETBIOSNAME_LEN) {
219 /* parse out the name type, its always
220 * in the 16th byte of the name */
221 name->name_type = ((unsigned char)name->name[15]) & 0xff;
223 /* remove trailing spaces */
224 name->name[15] = 0;
225 n = 14;
226 while (n && name->name[n]==' ')
227 name->name[n--] = 0;
230 /* now the domain parts (if any) */
231 n = 0;
232 while (ubuf[offset]) {
233 /* we can have pointers within the domain part as well */
234 if (!handle_name_ptrs(ubuf,&offset,length,&got_pointer,&ret))
235 return(0);
237 m = ubuf[offset];
239 * Don't allow null domain parts.
241 if (!m)
242 return(0);
243 if (!got_pointer)
244 ret += m+1;
245 if (n)
246 name->scope[n++] = '.';
247 if (m+2+offset>length || n+m+1>sizeof(name->scope))
248 return(0);
249 offset++;
250 while (m--)
251 name->scope[n++] = (char)ubuf[offset++];
254 * Watch for malicious loops.
256 if (loop_count++ == 10)
257 return 0;
259 name->scope[n++] = 0;
261 return(ret);
264 /****************************************************************************
265 Put a netbios name, padding(s) and a name type into a 16 character buffer.
266 name is already in DOS charset.
267 [15 bytes name + padding][1 byte name type].
268 ****************************************************************************/
270 void put_name(char *dest, const char *name, int pad, unsigned int name_type)
272 size_t len = strlen(name);
274 memcpy(dest, name, (len < MAX_NETBIOSNAME_LEN) ?
275 len : MAX_NETBIOSNAME_LEN - 1);
276 if (len < MAX_NETBIOSNAME_LEN - 1) {
277 memset(dest + len, pad, MAX_NETBIOSNAME_LEN - 1 - len);
279 dest[MAX_NETBIOSNAME_LEN - 1] = name_type;
282 /*******************************************************************
283 Put a compressed nmb name into a buffer. Return the length of the
284 compressed name.
286 Compressed names are really weird. The "compression" doubles the
287 size. The idea is that it also means that compressed names conform
288 to the doman name system. See RFC1002.
290 If buf == NULL this is a length calculation.
291 ******************************************************************/
293 static int put_nmb_name(char *buf,int offset,struct nmb_name *name)
295 int ret,m;
296 nstring buf1;
297 char *p;
299 if (strcmp(name->name,"*") == 0) {
300 /* special case for wildcard name */
301 put_name(buf1, "*", '\0', name->name_type);
302 } else {
303 put_name(buf1, name->name, ' ', name->name_type);
306 if (buf) {
307 buf[offset] = 0x20;
310 ret = 34;
312 for (m=0;m<MAX_NETBIOSNAME_LEN;m++) {
313 if (buf) {
314 buf[offset+1+2*m] = 'A' + ((buf1[m]>>4)&0xF);
315 buf[offset+2+2*m] = 'A' + (buf1[m]&0xF);
318 offset += 33;
320 if (buf) {
321 buf[offset] = 0;
324 if (name->scope[0]) {
325 /* XXXX this scope handling needs testing */
326 ret += strlen(name->scope) + 1;
327 if (buf) {
328 safe_strcpy(&buf[offset+1],name->scope,
329 sizeof(name->scope));
331 p = &buf[offset+1];
332 while ((p = strchr_m(p,'.'))) {
333 buf[offset] = PTR_DIFF(p,&buf[offset+1]);
334 offset += (buf[offset] + 1);
335 p = &buf[offset+1];
337 buf[offset] = strlen(&buf[offset+1]);
341 return ret;
344 /*******************************************************************
345 Useful for debugging messages.
346 ******************************************************************/
348 char *nmb_namestr(const struct nmb_name *n)
350 fstring name;
351 char *result;
353 pull_ascii_fstring(name, n->name);
354 if (!n->scope[0])
355 result = talloc_asprintf(talloc_tos(), "%s<%02x>", name,
356 n->name_type);
357 else
358 result = talloc_asprintf(talloc_tos(), "%s<%02x>.%s", name,
359 n->name_type, n->scope);
361 SMB_ASSERT(result != NULL);
362 return result;
365 /*******************************************************************
366 Allocate and parse some resource records.
367 ******************************************************************/
369 static bool parse_alloc_res_rec(char *inbuf,int *offset,int length,
370 struct res_rec **recs, int count)
372 int i;
374 *recs = SMB_MALLOC_ARRAY(struct res_rec, count);
375 if (!*recs)
376 return(False);
378 memset((char *)*recs,'\0',sizeof(**recs)*count);
380 for (i=0;i<count;i++) {
381 int l = parse_nmb_name(inbuf,*offset,length,
382 &(*recs)[i].rr_name);
383 (*offset) += l;
384 if (!l || (*offset)+10 > length) {
385 SAFE_FREE(*recs);
386 return(False);
388 (*recs)[i].rr_type = RSVAL(inbuf,(*offset));
389 (*recs)[i].rr_class = RSVAL(inbuf,(*offset)+2);
390 (*recs)[i].ttl = RIVAL(inbuf,(*offset)+4);
391 (*recs)[i].rdlength = RSVAL(inbuf,(*offset)+8);
392 (*offset) += 10;
393 if ((*recs)[i].rdlength>sizeof((*recs)[i].rdata) ||
394 (*offset)+(*recs)[i].rdlength > length) {
395 SAFE_FREE(*recs);
396 return(False);
398 memcpy((*recs)[i].rdata,inbuf+(*offset),(*recs)[i].rdlength);
399 (*offset) += (*recs)[i].rdlength;
401 return(True);
404 /*******************************************************************
405 Put a resource record into a packet.
406 If buf == NULL this is a length calculation.
407 ******************************************************************/
409 static int put_res_rec(char *buf,int offset,struct res_rec *recs,int count)
411 int ret=0;
412 int i;
414 for (i=0;i<count;i++) {
415 int l = put_nmb_name(buf,offset,&recs[i].rr_name);
416 offset += l;
417 ret += l;
418 if (buf) {
419 RSSVAL(buf,offset,recs[i].rr_type);
420 RSSVAL(buf,offset+2,recs[i].rr_class);
421 RSIVAL(buf,offset+4,recs[i].ttl);
422 RSSVAL(buf,offset+8,recs[i].rdlength);
423 memcpy(buf+offset+10,recs[i].rdata,recs[i].rdlength);
425 offset += 10+recs[i].rdlength;
426 ret += 10+recs[i].rdlength;
429 return ret;
432 /*******************************************************************
433 Put a compressed name pointer record into a packet.
434 If buf == NULL this is a length calculation.
435 ******************************************************************/
437 static int put_compressed_name_ptr(unsigned char *buf,
438 int offset,
439 struct res_rec *rec,
440 int ptr_offset)
442 int ret=0;
443 if (buf) {
444 buf[offset] = (0xC0 | ((ptr_offset >> 8) & 0xFF));
445 buf[offset+1] = (ptr_offset & 0xFF);
447 offset += 2;
448 ret += 2;
449 if (buf) {
450 RSSVAL(buf,offset,rec->rr_type);
451 RSSVAL(buf,offset+2,rec->rr_class);
452 RSIVAL(buf,offset+4,rec->ttl);
453 RSSVAL(buf,offset+8,rec->rdlength);
454 memcpy(buf+offset+10,rec->rdata,rec->rdlength);
456 offset += 10+rec->rdlength;
457 ret += 10+rec->rdlength;
459 return ret;
462 /*******************************************************************
463 Parse a dgram packet. Return False if the packet can't be parsed
464 or is invalid for some reason, True otherwise.
466 This is documented in section 4.4.1 of RFC1002.
467 ******************************************************************/
469 static bool parse_dgram(char *inbuf,int length,struct dgram_packet *dgram)
471 int offset;
472 int flags;
474 memset((char *)dgram,'\0',sizeof(*dgram));
476 if (length < 14)
477 return(False);
479 dgram->header.msg_type = CVAL(inbuf,0);
480 flags = CVAL(inbuf,1);
481 dgram->header.flags.node_type = (enum node_type)((flags>>2)&3);
482 if (flags & 1)
483 dgram->header.flags.more = True;
484 if (flags & 2)
485 dgram->header.flags.first = True;
486 dgram->header.dgm_id = RSVAL(inbuf,2);
487 putip((char *)&dgram->header.source_ip,inbuf+4);
488 dgram->header.source_port = RSVAL(inbuf,8);
489 dgram->header.dgm_length = RSVAL(inbuf,10);
490 dgram->header.packet_offset = RSVAL(inbuf,12);
492 offset = 14;
494 if (dgram->header.msg_type == 0x10 ||
495 dgram->header.msg_type == 0x11 ||
496 dgram->header.msg_type == 0x12) {
497 offset += parse_nmb_name(inbuf,offset,length,
498 &dgram->source_name);
499 offset += parse_nmb_name(inbuf,offset,length,
500 &dgram->dest_name);
503 if (offset >= length || (length-offset > sizeof(dgram->data)))
504 return(False);
506 dgram->datasize = length-offset;
507 memcpy(dgram->data,inbuf+offset,dgram->datasize);
509 /* Paranioa. Ensure the last 2 bytes in the dgram buffer are
510 zero. This should be true anyway, just enforce it for
511 paranioa sake. JRA. */
512 SMB_ASSERT(dgram->datasize <= (sizeof(dgram->data)-2));
513 memset(&dgram->data[sizeof(dgram->data)-2], '\0', 2);
515 return(True);
518 /*******************************************************************
519 Parse a nmb packet. Return False if the packet can't be parsed
520 or is invalid for some reason, True otherwise.
521 ******************************************************************/
523 static bool parse_nmb(char *inbuf,int length,struct nmb_packet *nmb)
525 int nm_flags,offset;
527 memset((char *)nmb,'\0',sizeof(*nmb));
529 if (length < 12)
530 return(False);
532 /* parse the header */
533 nmb->header.name_trn_id = RSVAL(inbuf,0);
535 DEBUG(10,("parse_nmb: packet id = %d\n", nmb->header.name_trn_id));
537 nmb->header.opcode = (CVAL(inbuf,2) >> 3) & 0xF;
538 nmb->header.response = ((CVAL(inbuf,2)>>7)&1)?True:False;
539 nm_flags = ((CVAL(inbuf,2) & 0x7) << 4) + (CVAL(inbuf,3)>>4);
540 nmb->header.nm_flags.bcast = (nm_flags&1)?True:False;
541 nmb->header.nm_flags.recursion_available = (nm_flags&8)?True:False;
542 nmb->header.nm_flags.recursion_desired = (nm_flags&0x10)?True:False;
543 nmb->header.nm_flags.trunc = (nm_flags&0x20)?True:False;
544 nmb->header.nm_flags.authoritative = (nm_flags&0x40)?True:False;
545 nmb->header.rcode = CVAL(inbuf,3) & 0xF;
546 nmb->header.qdcount = RSVAL(inbuf,4);
547 nmb->header.ancount = RSVAL(inbuf,6);
548 nmb->header.nscount = RSVAL(inbuf,8);
549 nmb->header.arcount = RSVAL(inbuf,10);
551 if (nmb->header.qdcount) {
552 offset = parse_nmb_name(inbuf,12,length,
553 &nmb->question.question_name);
554 if (!offset)
555 return(False);
557 if (length - (12+offset) < 4)
558 return(False);
559 nmb->question.question_type = RSVAL(inbuf,12+offset);
560 nmb->question.question_class = RSVAL(inbuf,12+offset+2);
562 offset += 12+4;
563 } else {
564 offset = 12;
567 /* and any resource records */
568 if (nmb->header.ancount &&
569 !parse_alloc_res_rec(inbuf,&offset,length,&nmb->answers,
570 nmb->header.ancount))
571 return(False);
573 if (nmb->header.nscount &&
574 !parse_alloc_res_rec(inbuf,&offset,length,&nmb->nsrecs,
575 nmb->header.nscount))
576 return(False);
578 if (nmb->header.arcount &&
579 !parse_alloc_res_rec(inbuf,&offset,length,
580 &nmb->additional, nmb->header.arcount))
581 return(False);
583 return(True);
586 /*******************************************************************
587 'Copy constructor' for an nmb packet.
588 ******************************************************************/
590 static struct packet_struct *copy_nmb_packet(struct packet_struct *packet)
592 struct nmb_packet *nmb;
593 struct nmb_packet *copy_nmb;
594 struct packet_struct *pkt_copy;
596 if(( pkt_copy = SMB_MALLOC_P(struct packet_struct)) == NULL) {
597 DEBUG(0,("copy_nmb_packet: malloc fail.\n"));
598 return NULL;
601 /* Structure copy of entire thing. */
603 *pkt_copy = *packet;
605 /* Ensure this copy is not locked. */
606 pkt_copy->locked = False;
608 /* Ensure this copy has no resource records. */
609 nmb = &packet->packet.nmb;
610 copy_nmb = &pkt_copy->packet.nmb;
612 copy_nmb->answers = NULL;
613 copy_nmb->nsrecs = NULL;
614 copy_nmb->additional = NULL;
616 /* Now copy any resource records. */
618 if (nmb->answers) {
619 if((copy_nmb->answers = SMB_MALLOC_ARRAY(
620 struct res_rec,nmb->header.ancount)) == NULL)
621 goto free_and_exit;
622 memcpy((char *)copy_nmb->answers, (char *)nmb->answers,
623 nmb->header.ancount * sizeof(struct res_rec));
625 if (nmb->nsrecs) {
626 if((copy_nmb->nsrecs = SMB_MALLOC_ARRAY(
627 struct res_rec, nmb->header.nscount)) == NULL)
628 goto free_and_exit;
629 memcpy((char *)copy_nmb->nsrecs, (char *)nmb->nsrecs,
630 nmb->header.nscount * sizeof(struct res_rec));
632 if (nmb->additional) {
633 if((copy_nmb->additional = SMB_MALLOC_ARRAY(
634 struct res_rec, nmb->header.arcount)) == NULL)
635 goto free_and_exit;
636 memcpy((char *)copy_nmb->additional, (char *)nmb->additional,
637 nmb->header.arcount * sizeof(struct res_rec));
640 return pkt_copy;
642 free_and_exit:
644 SAFE_FREE(copy_nmb->answers);
645 SAFE_FREE(copy_nmb->nsrecs);
646 SAFE_FREE(copy_nmb->additional);
647 SAFE_FREE(pkt_copy);
649 DEBUG(0,("copy_nmb_packet: malloc fail in resource records.\n"));
650 return NULL;
653 /*******************************************************************
654 'Copy constructor' for a dgram packet.
655 ******************************************************************/
657 static struct packet_struct *copy_dgram_packet(struct packet_struct *packet)
659 struct packet_struct *pkt_copy;
661 if(( pkt_copy = SMB_MALLOC_P(struct packet_struct)) == NULL) {
662 DEBUG(0,("copy_dgram_packet: malloc fail.\n"));
663 return NULL;
666 /* Structure copy of entire thing. */
668 *pkt_copy = *packet;
670 /* Ensure this copy is not locked. */
671 pkt_copy->locked = False;
673 /* There are no additional pointers in a dgram packet,
674 we are finished. */
675 return pkt_copy;
678 /*******************************************************************
679 'Copy constructor' for a generic packet.
680 ******************************************************************/
682 struct packet_struct *copy_packet(struct packet_struct *packet)
684 if(packet->packet_type == NMB_PACKET)
685 return copy_nmb_packet(packet);
686 else if (packet->packet_type == DGRAM_PACKET)
687 return copy_dgram_packet(packet);
688 return NULL;
691 /*******************************************************************
692 Free up any resources associated with an nmb packet.
693 ******************************************************************/
695 static void free_nmb_packet(struct nmb_packet *nmb)
697 SAFE_FREE(nmb->answers);
698 SAFE_FREE(nmb->nsrecs);
699 SAFE_FREE(nmb->additional);
702 /*******************************************************************
703 Free up any resources associated with a dgram packet.
704 ******************************************************************/
706 static void free_dgram_packet(struct dgram_packet *nmb)
708 /* We have nothing to do for a dgram packet. */
711 /*******************************************************************
712 Free up any resources associated with a packet.
713 ******************************************************************/
715 void free_packet(struct packet_struct *packet)
717 if (packet->locked)
718 return;
719 if (packet->packet_type == NMB_PACKET)
720 free_nmb_packet(&packet->packet.nmb);
721 else if (packet->packet_type == DGRAM_PACKET)
722 free_dgram_packet(&packet->packet.dgram);
723 ZERO_STRUCTPN(packet);
724 SAFE_FREE(packet);
727 /*******************************************************************
728 Parse a packet buffer into a packet structure.
729 ******************************************************************/
731 struct packet_struct *parse_packet(char *buf,int length,
732 enum packet_type packet_type,
733 struct in_addr ip,
734 int port)
736 struct packet_struct *p;
737 bool ok=False;
739 p = SMB_MALLOC_P(struct packet_struct);
740 if (!p)
741 return(NULL);
743 ZERO_STRUCTP(p); /* initialize for possible padding */
745 p->next = NULL;
746 p->prev = NULL;
747 p->ip = ip;
748 p->port = port;
749 p->locked = False;
750 p->timestamp = time(NULL);
751 p->packet_type = packet_type;
753 switch (packet_type) {
754 case NMB_PACKET:
755 ok = parse_nmb(buf,length,&p->packet.nmb);
756 break;
758 case DGRAM_PACKET:
759 ok = parse_dgram(buf,length,&p->packet.dgram);
760 break;
763 if (!ok) {
764 free_packet(p);
765 return NULL;
768 return p;
771 /*******************************************************************
772 Read a packet from a socket and parse it, returning a packet ready
773 to be used or put on the queue. This assumes a UDP socket.
774 ******************************************************************/
776 struct packet_struct *read_packet(int fd,enum packet_type packet_type)
778 struct packet_struct *packet;
779 struct sockaddr_storage sa;
780 struct sockaddr_in *si = (struct sockaddr_in *)&sa;
781 char buf[MAX_DGRAM_SIZE];
782 int length;
784 length = read_udp_v4_socket(fd,buf,sizeof(buf),&sa);
785 if (length < MIN_DGRAM_SIZE || sa.ss_family != AF_INET) {
786 return NULL;
789 packet = parse_packet(buf,
790 length,
791 packet_type,
792 si->sin_addr,
793 ntohs(si->sin_port));
794 if (!packet)
795 return NULL;
797 packet->fd = fd;
799 num_good_receives++;
801 DEBUG(5,("Received a packet of len %d from (%s) port %d\n",
802 length, inet_ntoa(packet->ip), packet->port ) );
804 return(packet);
807 /*******************************************************************
808 Send a udp packet on a already open socket.
809 ******************************************************************/
811 static bool send_udp(int fd,char *buf,int len,struct in_addr ip,int port)
813 bool ret = False;
814 int i;
815 struct sockaddr_in sock_out;
817 /* set the address and port */
818 memset((char *)&sock_out,'\0',sizeof(sock_out));
819 putip((char *)&sock_out.sin_addr,(char *)&ip);
820 sock_out.sin_port = htons( port );
821 sock_out.sin_family = AF_INET;
823 DEBUG( 5, ( "Sending a packet of len %d to (%s) on port %d\n",
824 len, inet_ntoa(ip), port ) );
827 * Patch to fix asynch error notifications from Linux kernel.
830 for (i = 0; i < 5; i++) {
831 ret = (sendto(fd,buf,len,0,(struct sockaddr *)&sock_out,
832 sizeof(sock_out)) >= 0);
833 if (ret || errno != ECONNREFUSED)
834 break;
837 if (!ret)
838 DEBUG(0,("Packet send failed to %s(%d) ERRNO=%s\n",
839 inet_ntoa(ip),port,strerror(errno)));
841 if (ret)
842 num_good_sends++;
844 return(ret);
847 /*******************************************************************
848 Build a dgram packet ready for sending.
849 If buf == NULL this is a length calculation.
850 ******************************************************************/
852 static int build_dgram(char *buf, size_t len, struct dgram_packet *dgram)
854 unsigned char *ubuf = (unsigned char *)buf;
855 int offset=0;
857 /* put in the header */
858 if (buf) {
859 ubuf[0] = dgram->header.msg_type;
860 ubuf[1] = (((int)dgram->header.flags.node_type)<<2);
861 if (dgram->header.flags.more)
862 ubuf[1] |= 1;
863 if (dgram->header.flags.first)
864 ubuf[1] |= 2;
865 RSSVAL(ubuf,2,dgram->header.dgm_id);
866 putip(ubuf+4,(char *)&dgram->header.source_ip);
867 RSSVAL(ubuf,8,dgram->header.source_port);
868 RSSVAL(ubuf,12,dgram->header.packet_offset);
871 offset = 14;
873 if (dgram->header.msg_type == 0x10 ||
874 dgram->header.msg_type == 0x11 ||
875 dgram->header.msg_type == 0x12) {
876 offset += put_nmb_name((char *)ubuf,offset,&dgram->source_name);
877 offset += put_nmb_name((char *)ubuf,offset,&dgram->dest_name);
880 if (buf) {
881 memcpy(ubuf+offset,dgram->data,dgram->datasize);
883 offset += dgram->datasize;
885 /* automatically set the dgm_length
886 * NOTE: RFC1002 says the dgm_length does *not*
887 * include the fourteen-byte header. crh
889 dgram->header.dgm_length = (offset - 14);
890 if (buf) {
891 RSSVAL(ubuf,10,dgram->header.dgm_length);
894 return offset;
897 /*******************************************************************
898 Build a nmb name
899 *******************************************************************/
901 void make_nmb_name( struct nmb_name *n, const char *name, int type)
903 fstring unix_name;
904 memset( (char *)n, '\0', sizeof(struct nmb_name) );
905 fstrcpy(unix_name, name);
906 strupper_m(unix_name);
907 push_ascii(n->name, unix_name, sizeof(n->name), STR_TERMINATE);
908 n->name_type = (unsigned int)type & 0xFF;
909 push_ascii(n->scope, global_scope(), 64, STR_TERMINATE);
912 /*******************************************************************
913 Compare two nmb names
914 ******************************************************************/
916 bool nmb_name_equal(struct nmb_name *n1, struct nmb_name *n2)
918 return ((n1->name_type == n2->name_type) &&
919 strequal(n1->name ,n2->name ) &&
920 strequal(n1->scope,n2->scope));
923 /*******************************************************************
924 Build a nmb packet ready for sending.
925 If buf == NULL this is a length calculation.
926 ******************************************************************/
928 static int build_nmb(char *buf, size_t len, struct nmb_packet *nmb)
930 unsigned char *ubuf = (unsigned char *)buf;
931 int offset=0;
933 if (len && len < 12) {
934 return 0;
937 /* put in the header */
938 if (buf) {
939 RSSVAL(ubuf,offset,nmb->header.name_trn_id);
940 ubuf[offset+2] = (nmb->header.opcode & 0xF) << 3;
941 if (nmb->header.response)
942 ubuf[offset+2] |= (1<<7);
943 if (nmb->header.nm_flags.authoritative &&
944 nmb->header.response)
945 ubuf[offset+2] |= 0x4;
946 if (nmb->header.nm_flags.trunc)
947 ubuf[offset+2] |= 0x2;
948 if (nmb->header.nm_flags.recursion_desired)
949 ubuf[offset+2] |= 0x1;
950 if (nmb->header.nm_flags.recursion_available &&
951 nmb->header.response)
952 ubuf[offset+3] |= 0x80;
953 if (nmb->header.nm_flags.bcast)
954 ubuf[offset+3] |= 0x10;
955 ubuf[offset+3] |= (nmb->header.rcode & 0xF);
957 RSSVAL(ubuf,offset+4,nmb->header.qdcount);
958 RSSVAL(ubuf,offset+6,nmb->header.ancount);
959 RSSVAL(ubuf,offset+8,nmb->header.nscount);
960 RSSVAL(ubuf,offset+10,nmb->header.arcount);
963 offset += 12;
964 if (nmb->header.qdcount) {
965 /* XXXX this doesn't handle a qdcount of > 1 */
966 if (len) {
967 /* Length check. */
968 int extra = put_nmb_name(NULL,offset,
969 &nmb->question.question_name);
970 if (offset + extra > len) {
971 return 0;
974 offset += put_nmb_name((char *)ubuf,offset,
975 &nmb->question.question_name);
976 if (buf) {
977 RSSVAL(ubuf,offset,nmb->question.question_type);
978 RSSVAL(ubuf,offset+2,nmb->question.question_class);
980 offset += 4;
983 if (nmb->header.ancount) {
984 if (len) {
985 /* Length check. */
986 int extra = put_res_rec(NULL,offset,nmb->answers,
987 nmb->header.ancount);
988 if (offset + extra > len) {
989 return 0;
992 offset += put_res_rec((char *)ubuf,offset,nmb->answers,
993 nmb->header.ancount);
996 if (nmb->header.nscount) {
997 if (len) {
998 /* Length check. */
999 int extra = put_res_rec(NULL,offset,nmb->nsrecs,
1000 nmb->header.nscount);
1001 if (offset + extra > len) {
1002 return 0;
1005 offset += put_res_rec((char *)ubuf,offset,nmb->nsrecs,
1006 nmb->header.nscount);
1010 * The spec says we must put compressed name pointers
1011 * in the following outgoing packets :
1012 * NAME_REGISTRATION_REQUEST, NAME_REFRESH_REQUEST,
1013 * NAME_RELEASE_REQUEST.
1016 if((nmb->header.response == False) &&
1017 ((nmb->header.opcode == NMB_NAME_REG_OPCODE) ||
1018 (nmb->header.opcode == NMB_NAME_RELEASE_OPCODE) ||
1019 (nmb->header.opcode == NMB_NAME_REFRESH_OPCODE_8) ||
1020 (nmb->header.opcode == NMB_NAME_REFRESH_OPCODE_9) ||
1021 (nmb->header.opcode == NMB_NAME_MULTIHOMED_REG_OPCODE)) &&
1022 (nmb->header.arcount == 1)) {
1024 if (len) {
1025 /* Length check. */
1026 int extra = put_compressed_name_ptr(NULL,offset,
1027 nmb->additional,12);
1028 if (offset + extra > len) {
1029 return 0;
1032 offset += put_compressed_name_ptr(ubuf,offset,
1033 nmb->additional,12);
1034 } else if (nmb->header.arcount) {
1035 if (len) {
1036 /* Length check. */
1037 int extra = put_res_rec(NULL,offset,nmb->additional,
1038 nmb->header.arcount);
1039 if (offset + extra > len) {
1040 return 0;
1043 offset += put_res_rec((char *)ubuf,offset,nmb->additional,
1044 nmb->header.arcount);
1046 return offset;
1049 /*******************************************************************
1050 Linearise a packet.
1051 ******************************************************************/
1053 int build_packet(char *buf, size_t buflen, struct packet_struct *p)
1055 int len = 0;
1057 switch (p->packet_type) {
1058 case NMB_PACKET:
1059 len = build_nmb(buf,buflen,&p->packet.nmb);
1060 break;
1062 case DGRAM_PACKET:
1063 len = build_dgram(buf,buflen,&p->packet.dgram);
1064 break;
1067 return len;
1070 /*******************************************************************
1071 Send a packet_struct.
1072 ******************************************************************/
1074 bool send_packet(struct packet_struct *p)
1076 char buf[1024];
1077 int len=0;
1079 memset(buf,'\0',sizeof(buf));
1081 len = build_packet(buf, sizeof(buf), p);
1083 if (!len)
1084 return(False);
1086 return(send_udp(p->fd,buf,len,p->ip,p->port));
1089 /****************************************************************************
1090 Receive a packet with timeout on a open UDP filedescriptor.
1091 The timeout is in milliseconds
1092 ***************************************************************************/
1094 struct packet_struct *receive_packet(int fd,enum packet_type type,int t)
1096 fd_set fds;
1097 struct timeval timeout;
1098 int ret;
1100 FD_ZERO(&fds);
1101 FD_SET(fd,&fds);
1102 timeout.tv_sec = t/1000;
1103 timeout.tv_usec = 1000*(t%1000);
1105 if ((ret = sys_select_intr(fd+1,&fds,NULL,NULL,&timeout)) == -1) {
1106 /* errno should be EBADF or EINVAL. */
1107 DEBUG(0,("select returned -1, errno = %s (%d)\n",
1108 strerror(errno), errno));
1109 return NULL;
1112 if (ret == 0) /* timeout */
1113 return NULL;
1115 if (FD_ISSET(fd,&fds))
1116 return(read_packet(fd,type));
1118 return(NULL);
1121 /****************************************************************************
1122 Receive a UDP/137 packet either via UDP or from the unexpected packet
1123 queue. The packet must be a reply packet and have the specified trn_id.
1124 The timeout is in milliseconds.
1125 ***************************************************************************/
1127 struct packet_struct *receive_nmb_packet(int fd, int t, int trn_id)
1129 struct packet_struct *p;
1131 p = receive_packet(fd, NMB_PACKET, t);
1133 if (p && p->packet.nmb.header.response &&
1134 p->packet.nmb.header.name_trn_id == trn_id) {
1135 return p;
1137 if (p)
1138 free_packet(p);
1140 /* try the unexpected packet queue */
1141 return receive_unexpected(NMB_PACKET, trn_id, NULL);
1144 /****************************************************************************
1145 Receive a UDP/138 packet either via UDP or from the unexpected packet
1146 queue. The packet must be a reply packet and have the specified mailslot name
1147 The timeout is in milliseconds.
1148 ***************************************************************************/
1150 struct packet_struct *receive_dgram_packet(int fd, int t,
1151 const char *mailslot_name)
1153 struct packet_struct *p;
1155 p = receive_packet(fd, DGRAM_PACKET, t);
1157 if (p && match_mailslot_name(p, mailslot_name)) {
1158 return p;
1160 if (p)
1161 free_packet(p);
1163 /* try the unexpected packet queue */
1164 return receive_unexpected(DGRAM_PACKET, 0, mailslot_name);
1167 /****************************************************************************
1168 See if a datagram has the right mailslot name.
1169 ***************************************************************************/
1171 bool match_mailslot_name(struct packet_struct *p, const char *mailslot_name)
1173 struct dgram_packet *dgram = &p->packet.dgram;
1174 char *buf;
1176 buf = &dgram->data[0];
1177 buf -= 4;
1179 buf = smb_buf(buf);
1181 if (memcmp(buf, mailslot_name, strlen(mailslot_name)+1) == 0) {
1182 return True;
1185 return False;
1188 /****************************************************************************
1189 Return the number of bits that match between two len character buffers
1190 ***************************************************************************/
1192 int matching_len_bits(unsigned char *p1, unsigned char *p2, size_t len)
1194 size_t i, j;
1195 int ret = 0;
1196 for (i=0; i<len; i++) {
1197 if (p1[i] != p2[i])
1198 break;
1199 ret += 8;
1202 if (i==len)
1203 return ret;
1205 for (j=0; j<8; j++) {
1206 if ((p1[i] & (1<<(7-j))) != (p2[i] & (1<<(7-j))))
1207 break;
1208 ret++;
1211 return ret;
1214 static unsigned char sort_ip[4];
1216 /****************************************************************************
1217 Compare two query reply records.
1218 ***************************************************************************/
1220 static int name_query_comp(unsigned char *p1, unsigned char *p2)
1222 return matching_len_bits(p2+2, sort_ip, 4) -
1223 matching_len_bits(p1+2, sort_ip, 4);
1226 /****************************************************************************
1227 Sort a set of 6 byte name query response records so that the IPs that
1228 have the most leading bits in common with the specified address come first.
1229 ***************************************************************************/
1231 void sort_query_replies(char *data, int n, struct in_addr ip)
1233 if (n <= 1)
1234 return;
1236 putip(sort_ip, (char *)&ip);
1238 qsort(data, n, 6, QSORT_CAST name_query_comp);
1241 /****************************************************************************
1242 Interpret the weird netbios "name" into a unix fstring. Return the name type.
1243 ****************************************************************************/
1245 static int name_interpret(char *in, fstring name)
1247 int ret;
1248 int len = (*in++) / 2;
1249 fstring out_string;
1250 char *out = out_string;
1252 *out=0;
1254 if (len > 30 || len<1)
1255 return(0);
1257 while (len--) {
1258 if (in[0] < 'A' || in[0] > 'P' || in[1] < 'A' || in[1] > 'P') {
1259 *out = 0;
1260 return(0);
1262 *out = ((in[0]-'A')<<4) + (in[1]-'A');
1263 in += 2;
1264 out++;
1266 ret = out[-1];
1267 out[-1] = 0;
1269 #ifdef NETBIOS_SCOPE
1270 /* Handle any scope names */
1271 while(*in) {
1272 *out++ = '.'; /* Scope names are separated by periods */
1273 len = *(unsigned char *)in++;
1274 StrnCpy(out, in, len);
1275 out += len;
1276 *out=0;
1277 in += len;
1279 #endif
1280 pull_ascii_fstring(name, out_string);
1282 return(ret);
1285 /****************************************************************************
1286 Mangle a name into netbios format.
1287 Note: <Out> must be (33 + strlen(scope) + 2) bytes long, at minimum.
1288 ****************************************************************************/
1290 int name_mangle( char *In, char *Out, char name_type )
1292 int i;
1293 int len;
1294 nstring buf;
1295 char *p = Out;
1297 /* Safely copy the input string, In, into buf[]. */
1298 if (strcmp(In,"*") == 0)
1299 put_name(buf, "*", '\0', 0x00);
1300 else {
1301 /* We use an fstring here as mb dos names can expend x3 when
1302 going to utf8. */
1303 fstring buf_unix;
1304 nstring buf_dos;
1306 pull_ascii_fstring(buf_unix, In);
1307 strupper_m(buf_unix);
1309 push_ascii_nstring(buf_dos, buf_unix);
1310 put_name(buf, buf_dos, ' ', name_type);
1313 /* Place the length of the first field into the output buffer. */
1314 p[0] = 32;
1315 p++;
1317 /* Now convert the name to the rfc1001/1002 format. */
1318 for( i = 0; i < MAX_NETBIOSNAME_LEN; i++ ) {
1319 p[i*2] = ( (buf[i] >> 4) & 0x000F ) + 'A';
1320 p[(i*2)+1] = (buf[i] & 0x000F) + 'A';
1322 p += 32;
1323 p[0] = '\0';
1325 /* Add the scope string. */
1326 for( i = 0, len = 0; *(global_scope()) != '\0'; i++, len++ ) {
1327 switch( (global_scope())[i] ) {
1328 case '\0':
1329 p[0] = len;
1330 if( len > 0 )
1331 p[len+1] = 0;
1332 return( name_len(Out) );
1333 case '.':
1334 p[0] = len;
1335 p += (len + 1);
1336 len = -1;
1337 break;
1338 default:
1339 p[len+1] = (global_scope())[i];
1340 break;
1344 return( name_len(Out) );
1347 /****************************************************************************
1348 Find a pointer to a netbios name.
1349 ****************************************************************************/
1351 static char *name_ptr(char *buf,int ofs)
1353 unsigned char c = *(unsigned char *)(buf+ofs);
1355 if ((c & 0xC0) == 0xC0) {
1356 uint16 l = RSVAL(buf, ofs) & 0x3FFF;
1357 DEBUG(5,("name ptr to pos %d from %d is %s\n",l,ofs,buf+l));
1358 return(buf + l);
1359 } else {
1360 return(buf+ofs);
1364 /****************************************************************************
1365 Extract a netbios name from a buf (into a unix string) return name type.
1366 ****************************************************************************/
1368 int name_extract(char *buf,int ofs, fstring name)
1370 char *p = name_ptr(buf,ofs);
1371 int d = PTR_DIFF(p,buf+ofs);
1373 name[0] = '\0';
1374 if (d < -50 || d > 50)
1375 return(0);
1376 return(name_interpret(p,name));
1379 /****************************************************************************
1380 Return the total storage length of a mangled name.
1381 ****************************************************************************/
1383 int name_len(char *s1)
1385 /* NOTE: this argument _must_ be unsigned */
1386 unsigned char *s = (unsigned char *)s1;
1387 int len;
1389 /* If the two high bits of the byte are set, return 2. */
1390 if (0xC0 == (*s & 0xC0))
1391 return(2);
1393 /* Add up the length bytes. */
1394 for (len = 1; (*s); s += (*s) + 1) {
1395 len += *s + 1;
1396 SMB_ASSERT(len < 80);
1399 return(len);