s3/libsmb: clang: Fix value stored to 'offset' is never read
[Samba.git] / source3 / libsmb / nmblib.c
blobb6dca800e9466167515414b561a59aaa03f5eee8
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"
23 #include "libsmb/nmblib.h"
25 static const struct opcode_names {
26 const char *nmb_opcode_name;
27 int opcode;
28 } nmb_header_opcode_names[] = {
29 {"Query", 0 },
30 {"Registration", 5 },
31 {"Release", 6 },
32 {"WACK", 7 },
33 {"Refresh", 8 },
34 {"Refresh(altcode)", 9 },
35 {"Multi-homed Registration", 15 },
36 {0, -1 }
39 /****************************************************************************
40 Lookup a nmb opcode name.
41 ****************************************************************************/
43 static const char *lookup_opcode_name( int opcode )
45 const struct opcode_names *op_namep;
46 int i;
48 for(i = 0; nmb_header_opcode_names[i].nmb_opcode_name != 0; i++) {
49 op_namep = &nmb_header_opcode_names[i];
50 if(opcode == op_namep->opcode)
51 return op_namep->nmb_opcode_name;
53 return "<unknown opcode>";
56 /****************************************************************************
57 Print out a res_rec structure.
58 ****************************************************************************/
60 static void debug_nmb_res_rec(struct res_rec *res, const char *hdr)
62 int i, j;
64 DEBUGADD( 4, ( " %s: nmb_name=%s rr_type=%d rr_class=%d ttl=%d\n",
65 hdr,
66 nmb_namestr(&res->rr_name),
67 res->rr_type,
68 res->rr_class,
69 res->ttl ) );
71 if (res->rdlength == 0) {
72 return;
75 for (i = 0; i < res->rdlength; i+= MAX_NETBIOSNAME_LEN) {
76 DEBUGADD(4, (" %s %3x char ", hdr, i));
78 for (j = 0; j < MAX_NETBIOSNAME_LEN; j++) {
79 unsigned char x = res->rdata[i+j];
80 if (x < 32 || x > 127)
81 x = '.';
83 if (i+j >= res->rdlength)
84 break;
85 DEBUGADD(4, ("%c", x));
88 DEBUGADD(4, (" hex "));
90 for (j = 0; j < MAX_NETBIOSNAME_LEN; j++) {
91 if (i+j >= res->rdlength)
92 break;
93 DEBUGADD(4, ("%02X", (unsigned char)res->rdata[i+j]));
96 DEBUGADD(4, ("\n"));
100 /****************************************************************************
101 Process a nmb packet.
102 ****************************************************************************/
104 void debug_nmb_packet(struct packet_struct *p)
106 struct nmb_packet *nmb = &p->packet.nmb;
108 if( DEBUGLVL( 4 ) ) {
109 dbgtext( "nmb packet from %s(%d) header: id=%d "
110 "opcode=%s(%d) response=%s\n",
111 inet_ntoa(p->ip), p->port,
112 nmb->header.name_trn_id,
113 lookup_opcode_name(nmb->header.opcode),
114 nmb->header.opcode,
115 BOOLSTR(nmb->header.response) );
116 dbgtext( " header: flags: bcast=%s rec_avail=%s "
117 "rec_des=%s trunc=%s auth=%s\n",
118 BOOLSTR(nmb->header.nm_flags.bcast),
119 BOOLSTR(nmb->header.nm_flags.recursion_available),
120 BOOLSTR(nmb->header.nm_flags.recursion_desired),
121 BOOLSTR(nmb->header.nm_flags.trunc),
122 BOOLSTR(nmb->header.nm_flags.authoritative) );
123 dbgtext( " header: rcode=%d qdcount=%d ancount=%d "
124 "nscount=%d arcount=%d\n",
125 nmb->header.rcode,
126 nmb->header.qdcount,
127 nmb->header.ancount,
128 nmb->header.nscount,
129 nmb->header.arcount );
132 if (nmb->header.qdcount) {
133 DEBUGADD( 4, ( " question: q_name=%s q_type=%d q_class=%d\n",
134 nmb_namestr(&nmb->question.question_name),
135 nmb->question.question_type,
136 nmb->question.question_class) );
139 if (nmb->answers && nmb->header.ancount) {
140 debug_nmb_res_rec(nmb->answers,"answers");
142 if (nmb->nsrecs && nmb->header.nscount) {
143 debug_nmb_res_rec(nmb->nsrecs,"nsrecs");
145 if (nmb->additional && nmb->header.arcount) {
146 debug_nmb_res_rec(nmb->additional,"additional");
150 /*******************************************************************
151 Handle "compressed" name pointers.
152 ******************************************************************/
154 static bool handle_name_ptrs(unsigned char *ubuf,int *offset,int length,
155 bool *got_pointer,int *ret)
157 int loop_count=0;
159 while ((ubuf[*offset] & 0xC0) == 0xC0) {
160 if (!*got_pointer)
161 (*ret) += 2;
162 (*got_pointer)=True;
163 (*offset) = ((ubuf[*offset] & ~0xC0)<<8) | ubuf[(*offset)+1];
164 if (loop_count++ == 10 ||
165 (*offset) < 0 || (*offset)>(length-2)) {
166 return False;
169 return True;
172 /*******************************************************************
173 Parse a nmb name from "compressed" format to something readable
174 return the space taken by the name, or 0 if the name is invalid
175 ******************************************************************/
177 static int parse_nmb_name(char *inbuf,int ofs,int length, struct nmb_name *name)
179 size_t m,n=0;
180 unsigned char *ubuf = (unsigned char *)inbuf;
181 int ret = 0;
182 bool got_pointer=False;
183 size_t loop_count=0;
184 int offset = ofs;
186 if (length - offset < 2)
187 return(0);
189 /* handle initial name pointers */
190 if (!handle_name_ptrs(ubuf,&offset,length,&got_pointer,&ret))
191 return(0);
193 m = ubuf[offset];
195 if (!m)
196 return(0);
197 if ((m & 0xC0) || offset+m+2 > length)
198 return(0);
200 memset((char *)name,'\0',sizeof(*name));
202 /* the "compressed" part */
203 if (!got_pointer)
204 ret += m + 2;
205 offset++;
206 while (m > 0) {
207 unsigned char c1,c2;
208 c1 = ubuf[offset++]-'A';
209 c2 = ubuf[offset++]-'A';
210 if ((c1 & 0xF0) || (c2 & 0xF0)) {
211 return(0);
213 if (n >= sizeof(name->name)) {
214 return 0;
216 name->name[n++] = (c1<<4) | c2;
217 m -= 2;
220 * RFC1002: For a valid NetBIOS name, exiting from the above,
221 * n *must* be MAX_NETBIOSNAME_LEN (16).
223 if (n != MAX_NETBIOSNAME_LEN) {
224 return 0;
227 /* parse out the name type, its always
228 * in the 16th byte of the name */
229 name->name_type = ((unsigned char)name->name[15]) & 0xff;
231 /* remove trailing spaces */
232 name->name[15] = 0;
233 n = 14;
234 while (n && name->name[n]==' ')
235 name->name[n--] = 0;
237 /* now the domain parts (if any) */
238 n = 0;
239 while (ubuf[offset]) {
240 /* we can have pointers within the domain part as well */
241 if (!handle_name_ptrs(ubuf,&offset,length,&got_pointer,&ret))
242 return(0);
244 m = ubuf[offset];
246 * Don't allow null domain parts.
248 if (!m)
249 return(0);
250 if (!got_pointer)
251 ret += m+1;
252 if (n)
253 name->scope[n++] = '.';
254 if (m+2+offset>length || n+m+1>sizeof(name->scope))
255 return(0);
256 offset++;
257 while (m--)
258 name->scope[n++] = (char)ubuf[offset++];
261 * Watch for malicious loops.
263 if (loop_count++ == 10)
264 return 0;
266 name->scope[n++] = 0;
268 return(ret);
271 /****************************************************************************
272 Put a netbios name, padding(s) and a name type into a 16 character buffer.
273 name is already in DOS charset.
274 [15 bytes name + padding][1 byte name type].
275 ****************************************************************************/
277 void put_name(char *dest, const char *name, int pad, unsigned int name_type)
279 size_t len = strlen(name);
281 memcpy(dest, name, (len < MAX_NETBIOSNAME_LEN) ?
282 len : MAX_NETBIOSNAME_LEN - 1);
283 if (len < MAX_NETBIOSNAME_LEN - 1) {
284 memset(dest + len, pad, MAX_NETBIOSNAME_LEN - 1 - len);
286 dest[MAX_NETBIOSNAME_LEN - 1] = name_type;
289 /*******************************************************************
290 Put a compressed nmb name into a buffer. Return the length of the
291 compressed name.
293 Compressed names are really weird. The "compression" doubles the
294 size. The idea is that it also means that compressed names conform
295 to the doman name system. See RFC1002.
297 If buf == NULL this is a length calculation.
298 ******************************************************************/
300 static int put_nmb_name(char *buf, size_t buflen, int offset,struct nmb_name *name)
302 int ret,m;
303 nstring buf1;
304 char *p;
306 if (strcmp(name->name,"*") == 0) {
307 /* special case for wildcard name */
308 put_name(buf1, "*", '\0', name->name_type);
309 } else {
310 put_name(buf1, name->name, ' ', name->name_type);
313 if (buf) {
314 if (offset >= buflen) {
315 return 0;
317 buf[offset] = 0x20;
320 ret = 34;
322 for (m=0;m<MAX_NETBIOSNAME_LEN;m++) {
323 if (buf) {
324 if (offset+2+2*m >= buflen) {
325 return 0;
327 buf[offset+1+2*m] = 'A' + ((buf1[m]>>4)&0xF);
328 buf[offset+2+2*m] = 'A' + (buf1[m]&0xF);
331 offset += 33;
333 if (buf) {
334 if (offset >= buflen) {
335 return 0;
337 buf[offset] = 0;
340 if (name->scope[0]) {
341 /* XXXX this scope handling needs testing */
342 size_t scopenamelen = strlen(name->scope) + 1;
343 ret += scopenamelen;
344 if (buf) {
345 if (offset+1+scopenamelen >= buflen) {
346 return 0;
348 strlcpy(&buf[offset+1],name->scope,
349 buflen - (offset+1));
351 p = &buf[offset+1];
352 while ((p = strchr_m(p,'.'))) {
353 buf[offset] = PTR_DIFF(p,&buf[offset+1]);
354 offset += (buf[offset] + 1);
355 if (offset+1 >= buflen) {
356 return 0;
358 p = &buf[offset+1];
360 buf[offset] = strlen(&buf[offset+1]);
364 return ret;
367 /*******************************************************************
368 Useful for debugging messages.
369 ******************************************************************/
371 char *nmb_namestr(const struct nmb_name *n)
373 fstring name;
374 char *result;
376 pull_ascii_fstring(name, n->name);
377 if (!n->scope[0])
378 result = talloc_asprintf(talloc_tos(), "%s<%02x>", name,
379 n->name_type);
380 else
381 result = talloc_asprintf(talloc_tos(), "%s<%02x>.%s", name,
382 n->name_type, n->scope);
384 SMB_ASSERT(result != NULL);
385 return result;
388 /*******************************************************************
389 Allocate and parse some resource records.
390 ******************************************************************/
392 static bool parse_alloc_res_rec(char *inbuf,int *offset,int length,
393 struct res_rec **recs, int count)
395 int i;
397 *recs = SMB_MALLOC_ARRAY(struct res_rec, count);
398 if (!*recs)
399 return(False);
401 memset((char *)*recs,'\0',sizeof(**recs)*count);
403 for (i=0;i<count;i++) {
404 int l = parse_nmb_name(inbuf,*offset,length,
405 &(*recs)[i].rr_name);
406 (*offset) += l;
407 if (!l || (*offset)+10 > length) {
408 SAFE_FREE(*recs);
409 return(False);
411 (*recs)[i].rr_type = RSVAL(inbuf,(*offset));
412 (*recs)[i].rr_class = RSVAL(inbuf,(*offset)+2);
413 (*recs)[i].ttl = RIVAL(inbuf,(*offset)+4);
414 (*recs)[i].rdlength = RSVAL(inbuf,(*offset)+8);
415 (*offset) += 10;
416 if ((*recs)[i].rdlength>sizeof((*recs)[i].rdata) ||
417 (*offset)+(*recs)[i].rdlength > length) {
418 SAFE_FREE(*recs);
419 return(False);
421 memcpy((*recs)[i].rdata,inbuf+(*offset),(*recs)[i].rdlength);
422 (*offset) += (*recs)[i].rdlength;
424 return(True);
427 /*******************************************************************
428 Put a resource record into a packet.
429 If buf == NULL this is a length calculation.
430 ******************************************************************/
432 static int put_res_rec(char *buf, size_t buflen, int offset,struct res_rec *recs,int count)
434 int ret=0;
435 int i;
437 for (i=0;i<count;i++) {
438 int l = put_nmb_name(buf,buflen,offset,&recs[i].rr_name);
439 offset += l;
440 ret += l;
441 if (buf) {
442 RSSVAL(buf,offset,recs[i].rr_type);
443 RSSVAL(buf,offset+2,recs[i].rr_class);
444 RSIVAL(buf,offset+4,recs[i].ttl);
445 RSSVAL(buf,offset+8,recs[i].rdlength);
446 memcpy(buf+offset+10,recs[i].rdata,recs[i].rdlength);
448 offset += 10+recs[i].rdlength;
449 ret += 10+recs[i].rdlength;
452 return ret;
455 /*******************************************************************
456 Put a compressed name pointer record into a packet.
457 If buf == NULL this is a length calculation.
458 ******************************************************************/
460 static int put_compressed_name_ptr(unsigned char *buf,
461 int offset,
462 struct res_rec *rec,
463 int ptr_offset)
465 int ret=offset;
466 if (buf) {
467 buf[offset] = (0xC0 | ((ptr_offset >> 8) & 0xFF));
468 buf[offset+1] = (ptr_offset & 0xFF);
470 offset += 2;
471 if (buf) {
472 RSSVAL(buf,offset,rec->rr_type);
473 RSSVAL(buf,offset+2,rec->rr_class);
474 RSIVAL(buf,offset+4,rec->ttl);
475 RSSVAL(buf,offset+8,rec->rdlength);
476 memcpy(buf+offset+10,rec->rdata,rec->rdlength);
478 offset += 10+rec->rdlength;
479 ret = (offset - ret);
481 return ret;
484 /*******************************************************************
485 Parse a dgram packet. Return False if the packet can't be parsed
486 or is invalid for some reason, True otherwise.
488 This is documented in section 4.4.1 of RFC1002.
489 ******************************************************************/
491 static bool parse_dgram(char *inbuf,int length,struct dgram_packet *dgram)
493 size_t offset;
494 int flags;
496 memset((char *)dgram,'\0',sizeof(*dgram));
498 if (length < 14)
499 return(False);
501 dgram->header.msg_type = CVAL(inbuf,0);
502 flags = CVAL(inbuf,1);
503 dgram->header.flags.node_type = (enum node_type)((flags>>2)&3);
504 if (flags & 1)
505 dgram->header.flags.more = True;
506 if (flags & 2)
507 dgram->header.flags.first = True;
508 dgram->header.dgm_id = RSVAL(inbuf,2);
509 putip((char *)&dgram->header.source_ip,inbuf+4);
510 dgram->header.source_port = RSVAL(inbuf,8);
511 dgram->header.dgm_length = RSVAL(inbuf,10);
512 dgram->header.packet_offset = RSVAL(inbuf,12);
514 offset = 14;
516 if (dgram->header.msg_type == 0x10 ||
517 dgram->header.msg_type == 0x11 ||
518 dgram->header.msg_type == 0x12) {
519 offset += parse_nmb_name(inbuf,offset,length,
520 &dgram->source_name);
521 offset += parse_nmb_name(inbuf,offset,length,
522 &dgram->dest_name);
525 if (offset >= length || (length-offset > sizeof(dgram->data)))
526 return(False);
528 dgram->datasize = length-offset;
529 memcpy(dgram->data,inbuf+offset,dgram->datasize);
531 /* Paranioa. Ensure the last 2 bytes in the dgram buffer are
532 zero. This should be true anyway, just enforce it for
533 paranioa sake. JRA. */
534 SMB_ASSERT(dgram->datasize <= (sizeof(dgram->data)-2));
535 memset(&dgram->data[sizeof(dgram->data)-2], '\0', 2);
537 return(True);
540 /*******************************************************************
541 Parse a nmb packet. Return False if the packet can't be parsed
542 or is invalid for some reason, True otherwise.
543 ******************************************************************/
545 static bool parse_nmb(char *inbuf,int length,struct nmb_packet *nmb)
547 int nm_flags,offset;
549 memset((char *)nmb,'\0',sizeof(*nmb));
551 if (length < 12)
552 return(False);
554 /* parse the header */
555 nmb->header.name_trn_id = RSVAL(inbuf,0);
557 DEBUG(10,("parse_nmb: packet id = %d\n", nmb->header.name_trn_id));
559 nmb->header.opcode = (CVAL(inbuf,2) >> 3) & 0xF;
560 nmb->header.response = ((CVAL(inbuf,2)>>7)&1)?True:False;
561 nm_flags = ((CVAL(inbuf,2) & 0x7) << 4) + (CVAL(inbuf,3)>>4);
562 nmb->header.nm_flags.bcast = (nm_flags&1)?True:False;
563 nmb->header.nm_flags.recursion_available = (nm_flags&8)?True:False;
564 nmb->header.nm_flags.recursion_desired = (nm_flags&0x10)?True:False;
565 nmb->header.nm_flags.trunc = (nm_flags&0x20)?True:False;
566 nmb->header.nm_flags.authoritative = (nm_flags&0x40)?True:False;
567 nmb->header.rcode = CVAL(inbuf,3) & 0xF;
568 nmb->header.qdcount = RSVAL(inbuf,4);
569 nmb->header.ancount = RSVAL(inbuf,6);
570 nmb->header.nscount = RSVAL(inbuf,8);
571 nmb->header.arcount = RSVAL(inbuf,10);
573 if (nmb->header.qdcount) {
574 offset = parse_nmb_name(inbuf,12,length,
575 &nmb->question.question_name);
576 if (!offset)
577 return(False);
579 if (length - (12+offset) < 4)
580 return(False);
581 nmb->question.question_type = RSVAL(inbuf,12+offset);
582 nmb->question.question_class = RSVAL(inbuf,12+offset+2);
584 offset += 12+4;
585 } else {
586 offset = 12;
589 /* and any resource records */
590 if (nmb->header.ancount &&
591 !parse_alloc_res_rec(inbuf,&offset,length,&nmb->answers,
592 nmb->header.ancount))
593 return(False);
595 if (nmb->header.nscount &&
596 !parse_alloc_res_rec(inbuf,&offset,length,&nmb->nsrecs,
597 nmb->header.nscount))
598 return(False);
600 if (nmb->header.arcount &&
601 !parse_alloc_res_rec(inbuf,&offset,length,
602 &nmb->additional, nmb->header.arcount))
603 return(False);
605 return(True);
608 /*******************************************************************
609 'Copy constructor' for an nmb packet.
610 ******************************************************************/
612 static struct packet_struct *copy_nmb_packet(struct packet_struct *packet)
614 struct nmb_packet *nmb;
615 struct nmb_packet *copy_nmb;
616 struct packet_struct *pkt_copy;
618 if(( pkt_copy = SMB_MALLOC_P(struct packet_struct)) == NULL) {
619 DEBUG(0,("copy_nmb_packet: malloc fail.\n"));
620 return NULL;
623 /* Structure copy of entire thing. */
625 *pkt_copy = *packet;
627 /* Ensure this copy is not locked. */
628 pkt_copy->locked = False;
629 pkt_copy->recv_fd = -1;
630 pkt_copy->send_fd = -1;
632 /* Ensure this copy has no resource records. */
633 nmb = &packet->packet.nmb;
634 copy_nmb = &pkt_copy->packet.nmb;
636 copy_nmb->answers = NULL;
637 copy_nmb->nsrecs = NULL;
638 copy_nmb->additional = NULL;
640 /* Now copy any resource records. */
642 if (nmb->answers) {
643 if((copy_nmb->answers = SMB_MALLOC_ARRAY(
644 struct res_rec,nmb->header.ancount)) == NULL)
645 goto free_and_exit;
646 memcpy((char *)copy_nmb->answers, (char *)nmb->answers,
647 nmb->header.ancount * sizeof(struct res_rec));
649 if (nmb->nsrecs) {
650 if((copy_nmb->nsrecs = SMB_MALLOC_ARRAY(
651 struct res_rec, nmb->header.nscount)) == NULL)
652 goto free_and_exit;
653 memcpy((char *)copy_nmb->nsrecs, (char *)nmb->nsrecs,
654 nmb->header.nscount * sizeof(struct res_rec));
656 if (nmb->additional) {
657 if((copy_nmb->additional = SMB_MALLOC_ARRAY(
658 struct res_rec, nmb->header.arcount)) == NULL)
659 goto free_and_exit;
660 memcpy((char *)copy_nmb->additional, (char *)nmb->additional,
661 nmb->header.arcount * sizeof(struct res_rec));
664 return pkt_copy;
666 free_and_exit:
668 SAFE_FREE(copy_nmb->answers);
669 SAFE_FREE(copy_nmb->nsrecs);
670 SAFE_FREE(copy_nmb->additional);
671 SAFE_FREE(pkt_copy);
673 DEBUG(0,("copy_nmb_packet: malloc fail in resource records.\n"));
674 return NULL;
677 /*******************************************************************
678 'Copy constructor' for a dgram packet.
679 ******************************************************************/
681 static struct packet_struct *copy_dgram_packet(struct packet_struct *packet)
683 struct packet_struct *pkt_copy;
685 if(( pkt_copy = SMB_MALLOC_P(struct packet_struct)) == NULL) {
686 DEBUG(0,("copy_dgram_packet: malloc fail.\n"));
687 return NULL;
690 /* Structure copy of entire thing. */
692 *pkt_copy = *packet;
694 /* Ensure this copy is not locked. */
695 pkt_copy->locked = False;
696 pkt_copy->recv_fd = -1;
697 pkt_copy->send_fd = -1;
699 /* There are no additional pointers in a dgram packet,
700 we are finished. */
701 return pkt_copy;
704 /*******************************************************************
705 'Copy constructor' for a generic packet.
706 ******************************************************************/
708 struct packet_struct *copy_packet(struct packet_struct *packet)
710 if(packet->packet_type == NMB_PACKET)
711 return copy_nmb_packet(packet);
712 else if (packet->packet_type == DGRAM_PACKET)
713 return copy_dgram_packet(packet);
714 return NULL;
717 /*******************************************************************
718 Free up any resources associated with an nmb packet.
719 ******************************************************************/
721 static void free_nmb_packet(struct nmb_packet *nmb)
723 SAFE_FREE(nmb->answers);
724 SAFE_FREE(nmb->nsrecs);
725 SAFE_FREE(nmb->additional);
728 /*******************************************************************
729 Free up any resources associated with a dgram packet.
730 ******************************************************************/
732 static void free_dgram_packet(struct dgram_packet *nmb)
734 /* We have nothing to do for a dgram packet. */
737 /*******************************************************************
738 Free up any resources associated with a packet.
739 ******************************************************************/
741 void free_packet(struct packet_struct *packet)
743 if (packet->locked)
744 return;
745 if (packet->packet_type == NMB_PACKET)
746 free_nmb_packet(&packet->packet.nmb);
747 else if (packet->packet_type == DGRAM_PACKET)
748 free_dgram_packet(&packet->packet.dgram);
749 ZERO_STRUCTPN(packet);
750 SAFE_FREE(packet);
753 int packet_trn_id(struct packet_struct *p)
755 int result;
756 switch (p->packet_type) {
757 case NMB_PACKET:
758 result = p->packet.nmb.header.name_trn_id;
759 break;
760 case DGRAM_PACKET:
761 result = p->packet.dgram.header.dgm_id;
762 break;
763 default:
764 result = -1;
766 return result;
769 /*******************************************************************
770 Parse a packet buffer into a packet structure.
771 ******************************************************************/
773 struct packet_struct *parse_packet(char *buf,int length,
774 enum packet_type packet_type,
775 struct in_addr ip,
776 int port)
778 struct packet_struct *p;
779 bool ok=False;
781 p = SMB_MALLOC_P(struct packet_struct);
782 if (!p)
783 return(NULL);
785 ZERO_STRUCTP(p); /* initialize for possible padding */
787 p->next = NULL;
788 p->prev = NULL;
789 p->ip = ip;
790 p->port = port;
791 p->locked = False;
792 p->timestamp = time(NULL);
793 p->packet_type = packet_type;
795 switch (packet_type) {
796 case NMB_PACKET:
797 ok = parse_nmb(buf,length,&p->packet.nmb);
798 break;
800 case DGRAM_PACKET:
801 ok = parse_dgram(buf,length,&p->packet.dgram);
802 break;
805 if (!ok) {
806 free_packet(p);
807 return NULL;
810 return p;
813 static struct packet_struct *copy_packet_talloc(
814 TALLOC_CTX *mem_ctx, const struct packet_struct *src)
816 struct packet_struct *pkt;
818 pkt = talloc_memdup(mem_ctx, src, sizeof(struct packet_struct));
819 if (pkt == NULL) {
820 return NULL;
822 pkt->locked = false;
823 pkt->recv_fd = -1;
824 pkt->send_fd = -1;
826 if (src->packet_type == NMB_PACKET) {
827 const struct nmb_packet *nsrc = &src->packet.nmb;
828 struct nmb_packet *ndst = &pkt->packet.nmb;
830 if (nsrc->answers != NULL) {
831 ndst->answers = talloc_memdup(
832 pkt, nsrc->answers,
833 sizeof(struct res_rec) * nsrc->header.ancount);
834 if (ndst->answers == NULL) {
835 goto fail;
838 if (nsrc->nsrecs != NULL) {
839 ndst->nsrecs = talloc_memdup(
840 pkt, nsrc->nsrecs,
841 sizeof(struct res_rec) * nsrc->header.nscount);
842 if (ndst->nsrecs == NULL) {
843 goto fail;
846 if (nsrc->additional != NULL) {
847 ndst->additional = talloc_memdup(
848 pkt, nsrc->additional,
849 sizeof(struct res_rec) * nsrc->header.arcount);
850 if (ndst->additional == NULL) {
851 goto fail;
856 return pkt;
859 * DGRAM packets have no substructures
862 fail:
863 TALLOC_FREE(pkt);
864 return NULL;
867 struct packet_struct *parse_packet_talloc(TALLOC_CTX *mem_ctx,
868 char *buf,int length,
869 enum packet_type packet_type,
870 struct in_addr ip,
871 int port)
873 struct packet_struct *pkt, *result;
875 pkt = parse_packet(buf, length, packet_type, ip, port);
876 if (pkt == NULL) {
877 return NULL;
879 result = copy_packet_talloc(mem_ctx, pkt);
880 free_packet(pkt);
881 return result;
884 /*******************************************************************
885 Send a udp packet on a already open socket.
886 ******************************************************************/
888 static bool send_udp(int fd,char *buf,int len,struct in_addr ip,int port)
890 bool ret = False;
891 int i;
892 struct sockaddr_in sock_out;
894 /* set the address and port */
895 memset((char *)&sock_out,'\0',sizeof(sock_out));
896 putip((char *)&sock_out.sin_addr,(char *)&ip);
897 sock_out.sin_port = htons( port );
898 sock_out.sin_family = AF_INET;
900 DEBUG( 5, ( "Sending a packet of len %d to (%s) on port %d\n",
901 len, inet_ntoa(ip), port ) );
904 * Patch to fix asynch error notifications from Linux kernel.
907 for (i = 0; i < 5; i++) {
908 ret = (sendto(fd,buf,len,0,(struct sockaddr *)&sock_out,
909 sizeof(sock_out)) >= 0);
910 if (ret || errno != ECONNREFUSED)
911 break;
914 if (!ret)
915 DEBUG(0,("Packet send failed to %s(%d) ERRNO=%s\n",
916 inet_ntoa(ip),port,strerror(errno)));
918 return(ret);
921 /*******************************************************************
922 Build a dgram packet ready for sending.
923 If buf == NULL this is a length calculation.
924 ******************************************************************/
926 static int build_dgram(char *buf, size_t len, struct dgram_packet *dgram)
928 unsigned char *ubuf = (unsigned char *)buf;
929 int offset=0;
931 /* put in the header */
932 if (buf) {
933 ubuf[0] = dgram->header.msg_type;
934 ubuf[1] = (((int)dgram->header.flags.node_type)<<2);
935 if (dgram->header.flags.more)
936 ubuf[1] |= 1;
937 if (dgram->header.flags.first)
938 ubuf[1] |= 2;
939 RSSVAL(ubuf,2,dgram->header.dgm_id);
940 putip(ubuf+4,(char *)&dgram->header.source_ip);
941 RSSVAL(ubuf,8,dgram->header.source_port);
942 RSSVAL(ubuf,12,dgram->header.packet_offset);
945 offset = 14;
947 if (dgram->header.msg_type == 0x10 ||
948 dgram->header.msg_type == 0x11 ||
949 dgram->header.msg_type == 0x12) {
950 offset += put_nmb_name((char *)ubuf,len,offset,&dgram->source_name);
951 offset += put_nmb_name((char *)ubuf,len,offset,&dgram->dest_name);
954 if (buf) {
955 memcpy(ubuf+offset,dgram->data,dgram->datasize);
957 offset += dgram->datasize;
959 /* automatically set the dgm_length
960 * NOTE: RFC1002 says the dgm_length does *not*
961 * include the fourteen-byte header. crh
963 dgram->header.dgm_length = (offset - 14);
964 if (buf) {
965 RSSVAL(ubuf,10,dgram->header.dgm_length);
968 return offset;
971 /*******************************************************************
972 Build a nmb name
973 *******************************************************************/
975 void make_nmb_name( struct nmb_name *n, const char *name, int type)
977 fstring unix_name;
978 memset( (char *)n, '\0', sizeof(struct nmb_name) );
979 fstrcpy(unix_name, name);
980 (void)strupper_m(unix_name);
981 push_ascii(n->name, unix_name, sizeof(n->name), STR_TERMINATE);
982 n->name_type = (unsigned int)type & 0xFF;
983 push_ascii(n->scope, lp_netbios_scope(), 64, STR_TERMINATE);
986 /*******************************************************************
987 Compare two nmb names
988 ******************************************************************/
990 bool nmb_name_equal(struct nmb_name *n1, struct nmb_name *n2)
992 return ((n1->name_type == n2->name_type) &&
993 strequal(n1->name ,n2->name ) &&
994 strequal(n1->scope,n2->scope));
997 /*******************************************************************
998 Build a nmb packet ready for sending.
999 If buf == NULL this is a length calculation.
1000 ******************************************************************/
1002 static int build_nmb(char *buf, size_t len, struct nmb_packet *nmb)
1004 unsigned char *ubuf = (unsigned char *)buf;
1005 int offset=0;
1007 if (len && len < 12) {
1008 return 0;
1011 /* put in the header */
1012 if (buf) {
1013 RSSVAL(ubuf,offset,nmb->header.name_trn_id);
1014 ubuf[offset+2] = (nmb->header.opcode & 0xF) << 3;
1015 if (nmb->header.response)
1016 ubuf[offset+2] |= (1<<7);
1017 if (nmb->header.nm_flags.authoritative &&
1018 nmb->header.response)
1019 ubuf[offset+2] |= 0x4;
1020 if (nmb->header.nm_flags.trunc)
1021 ubuf[offset+2] |= 0x2;
1022 if (nmb->header.nm_flags.recursion_desired)
1023 ubuf[offset+2] |= 0x1;
1024 if (nmb->header.nm_flags.recursion_available &&
1025 nmb->header.response)
1026 ubuf[offset+3] |= 0x80;
1027 if (nmb->header.nm_flags.bcast)
1028 ubuf[offset+3] |= 0x10;
1029 ubuf[offset+3] |= (nmb->header.rcode & 0xF);
1031 RSSVAL(ubuf,offset+4,nmb->header.qdcount);
1032 RSSVAL(ubuf,offset+6,nmb->header.ancount);
1033 RSSVAL(ubuf,offset+8,nmb->header.nscount);
1034 RSSVAL(ubuf,offset+10,nmb->header.arcount);
1037 offset += 12;
1038 if (nmb->header.qdcount) {
1039 /* XXXX this doesn't handle a qdcount of > 1 */
1040 if (len) {
1041 /* Length check. */
1042 int extra = put_nmb_name(NULL,0,offset,
1043 &nmb->question.question_name);
1044 if (offset + extra > len) {
1045 return 0;
1048 offset += put_nmb_name((char *)ubuf,len,offset,
1049 &nmb->question.question_name);
1050 if (buf) {
1051 RSSVAL(ubuf,offset,nmb->question.question_type);
1052 RSSVAL(ubuf,offset+2,nmb->question.question_class);
1054 offset += 4;
1057 if (nmb->header.ancount) {
1058 if (len) {
1059 /* Length check. */
1060 int extra = put_res_rec(NULL,0,offset,nmb->answers,
1061 nmb->header.ancount);
1062 if (offset + extra > len) {
1063 return 0;
1066 offset += put_res_rec((char *)ubuf,len,offset,nmb->answers,
1067 nmb->header.ancount);
1070 if (nmb->header.nscount) {
1071 if (len) {
1072 /* Length check. */
1073 int extra = put_res_rec(NULL,0,offset,nmb->nsrecs,
1074 nmb->header.nscount);
1075 if (offset + extra > len) {
1076 return 0;
1079 offset += put_res_rec((char *)ubuf,len,offset,nmb->nsrecs,
1080 nmb->header.nscount);
1084 * The spec says we must put compressed name pointers
1085 * in the following outgoing packets :
1086 * NAME_REGISTRATION_REQUEST, NAME_REFRESH_REQUEST,
1087 * NAME_RELEASE_REQUEST.
1090 if((nmb->header.response == False) &&
1091 ((nmb->header.opcode == NMB_NAME_REG_OPCODE) ||
1092 (nmb->header.opcode == NMB_NAME_RELEASE_OPCODE) ||
1093 (nmb->header.opcode == NMB_NAME_REFRESH_OPCODE_8) ||
1094 (nmb->header.opcode == NMB_NAME_REFRESH_OPCODE_9) ||
1095 (nmb->header.opcode == NMB_NAME_MULTIHOMED_REG_OPCODE)) &&
1096 (nmb->header.arcount == 1)) {
1098 if (len) {
1099 /* Length check. */
1100 int extra = put_compressed_name_ptr(NULL,offset,
1101 nmb->additional,12);
1102 if (offset + extra > len) {
1103 return 0;
1106 offset += put_compressed_name_ptr(ubuf,offset,
1107 nmb->additional,12);
1108 } else if (nmb->header.arcount) {
1109 if (len) {
1110 /* Length check. */
1111 int extra = put_res_rec(NULL,0,offset,nmb->additional,
1112 nmb->header.arcount);
1113 if (offset + extra > len) {
1114 return 0;
1117 offset += put_res_rec((char *)ubuf,len,offset,nmb->additional,
1118 nmb->header.arcount);
1120 return offset;
1123 /*******************************************************************
1124 Linearise a packet.
1125 ******************************************************************/
1127 int build_packet(char *buf, size_t buflen, struct packet_struct *p)
1129 int len = 0;
1131 switch (p->packet_type) {
1132 case NMB_PACKET:
1133 len = build_nmb(buf,buflen,&p->packet.nmb);
1134 break;
1136 case DGRAM_PACKET:
1137 len = build_dgram(buf,buflen,&p->packet.dgram);
1138 break;
1141 return len;
1144 /*******************************************************************
1145 Send a packet_struct.
1146 ******************************************************************/
1148 bool send_packet(struct packet_struct *p)
1150 char buf[1024];
1151 int len=0;
1153 memset(buf,'\0',sizeof(buf));
1155 len = build_packet(buf, sizeof(buf), p);
1157 if (!len)
1158 return(False);
1160 return(send_udp(p->send_fd,buf,len,p->ip,p->port));
1163 /****************************************************************************
1164 Receive a UDP/138 packet either via UDP or from the unexpected packet
1165 queue. The packet must be a reply packet and have the specified mailslot name
1166 The timeout is in milliseconds.
1167 ***************************************************************************/
1169 /****************************************************************************
1170 See if a datagram has the right mailslot name.
1171 ***************************************************************************/
1173 bool match_mailslot_name(struct packet_struct *p, const char *mailslot_name)
1175 struct dgram_packet *dgram = &p->packet.dgram;
1176 char *buf;
1178 buf = &dgram->data[0];
1179 buf -= 4;
1181 buf = smb_buf(buf);
1183 if (memcmp(buf, mailslot_name, strlen(mailslot_name)+1) == 0) {
1184 return True;
1187 return False;
1190 /****************************************************************************
1191 Return the number of bits that match between two len character buffers
1192 ***************************************************************************/
1194 int matching_len_bits(const unsigned char *p1, const unsigned char *p2, size_t len)
1196 size_t i, j;
1197 int ret = 0;
1198 for (i=0; i<len; i++) {
1199 if (p1[i] != p2[i])
1200 break;
1201 ret += 8;
1204 if (i==len)
1205 return ret;
1207 for (j=0; j<8; j++) {
1208 if ((p1[i] & (1<<(7-j))) != (p2[i] & (1<<(7-j))))
1209 break;
1210 ret++;
1213 return ret;
1216 static unsigned char sort_ip[4];
1218 /****************************************************************************
1219 Compare two query reply records.
1220 ***************************************************************************/
1222 static int name_query_comp(unsigned char *p1, unsigned char *p2)
1224 return matching_len_bits(p2+2, sort_ip, 4) -
1225 matching_len_bits(p1+2, sort_ip, 4);
1228 /****************************************************************************
1229 Sort a set of 6 byte name query response records so that the IPs that
1230 have the most leading bits in common with the specified address come first.
1231 ***************************************************************************/
1233 void sort_query_replies(char *data, int n, struct in_addr ip)
1235 if (n <= 1)
1236 return;
1238 putip(sort_ip, (char *)&ip);
1240 /* TODO:
1241 this can't use TYPESAFE_QSORT() as the types are wrong.
1242 It should be fixed to use a real type instead of char*
1244 qsort(data, n, 6, QSORT_CAST name_query_comp);
1247 /****************************************************************************
1248 Interpret the weird netbios "name" into a unix fstring. Return the name type.
1249 Returns -1 on error.
1250 ****************************************************************************/
1252 static int name_interpret(unsigned char *buf, size_t buf_len,
1253 unsigned char *in, fstring name)
1255 unsigned char *end_ptr = buf + buf_len;
1256 int ret;
1257 unsigned int len;
1258 fstring out_string;
1259 unsigned char *out = (unsigned char *)out_string;
1261 *out=0;
1263 if (in >= end_ptr) {
1264 return -1;
1266 len = (*in++) / 2;
1268 if (len<1) {
1269 return -1;
1272 while (len--) {
1273 if (&in[1] >= end_ptr) {
1274 return -1;
1276 if (in[0] < 'A' || in[0] > 'P' || in[1] < 'A' || in[1] > 'P') {
1277 *out = 0;
1278 return(0);
1280 *out = ((in[0]-'A')<<4) + (in[1]-'A');
1281 in += 2;
1282 out++;
1283 if (PTR_DIFF(out,out_string) >= sizeof(fstring)) {
1284 return -1;
1287 ret = out[-1];
1288 out[-1] = 0;
1290 pull_ascii_fstring(name, out_string);
1292 return(ret);
1295 /****************************************************************************
1296 Mangle a name into netbios format.
1297 Note: <Out> must be (33 + strlen(scope) + 2) bytes long, at minimum.
1298 ****************************************************************************/
1300 char *name_mangle(TALLOC_CTX *mem_ctx, const char *In, char name_type)
1302 int i;
1303 int len;
1304 nstring buf;
1305 char *result;
1306 char *p;
1308 result = talloc_array(mem_ctx, char, 33 + strlen(lp_netbios_scope()) + 2);
1309 if (result == NULL) {
1310 return NULL;
1312 p = result;
1314 /* Safely copy the input string, In, into buf[]. */
1315 if (strcmp(In,"*") == 0)
1316 put_name(buf, "*", '\0', 0x00);
1317 else {
1318 /* We use an fstring here as mb dos names can expend x3 when
1319 going to utf8. */
1320 fstring buf_unix;
1321 nstring buf_dos;
1323 pull_ascii_fstring(buf_unix, In);
1324 if (!strupper_m(buf_unix)) {
1325 return NULL;
1328 push_ascii_nstring(buf_dos, buf_unix);
1329 put_name(buf, buf_dos, ' ', name_type);
1332 /* Place the length of the first field into the output buffer. */
1333 p[0] = 32;
1334 p++;
1336 /* Now convert the name to the rfc1001/1002 format. */
1337 for( i = 0; i < MAX_NETBIOSNAME_LEN; i++ ) {
1338 p[i*2] = ( (buf[i] >> 4) & 0x000F ) + 'A';
1339 p[(i*2)+1] = (buf[i] & 0x000F) + 'A';
1341 p += 32;
1342 p[0] = '\0';
1344 /* Add the scope string. */
1345 for( i = 0, len = 0; *(lp_netbios_scope()) != '\0'; i++, len++ ) {
1346 switch( (lp_netbios_scope())[i] ) {
1347 case '\0':
1348 p[0] = len;
1349 if( len > 0 )
1350 p[len+1] = 0;
1351 return result;
1352 case '.':
1353 p[0] = len;
1354 p += (len + 1);
1355 len = -1;
1356 break;
1357 default:
1358 p[len+1] = (lp_netbios_scope())[i];
1359 break;
1363 return result;
1366 /****************************************************************************
1367 Find a pointer to a netbios name.
1368 ****************************************************************************/
1370 static unsigned char *name_ptr(unsigned char *buf, size_t buf_len, unsigned int ofs)
1372 unsigned char c = 0;
1374 if (ofs > buf_len || buf_len < 1) {
1375 return NULL;
1378 c = *(unsigned char *)(buf+ofs);
1379 if ((c & 0xC0) == 0xC0) {
1380 uint16_t l = 0;
1382 if (ofs > buf_len - 1) {
1383 return NULL;
1385 l = RSVAL(buf, ofs) & 0x3FFF;
1386 if (l > buf_len) {
1387 return NULL;
1389 DEBUG(5,("name ptr to pos %d from %d is %s\n",l,ofs,buf+l));
1390 return(buf + l);
1391 } else {
1392 return(buf+ofs);
1396 /****************************************************************************
1397 Extract a netbios name from a buf (into a unix string) return name type.
1398 Returns -1 on error.
1399 ****************************************************************************/
1401 int name_extract(unsigned char *buf, size_t buf_len, unsigned int ofs, fstring name)
1403 unsigned char *p = name_ptr(buf,buf_len,ofs);
1405 name[0] = '\0';
1406 if (p == NULL) {
1407 return -1;
1409 return(name_interpret(buf,buf_len,p,name));
1412 /****************************************************************************
1413 Return the total storage length of a mangled name.
1414 Returns -1 on error.
1415 ****************************************************************************/
1417 int name_len(unsigned char *s1, size_t buf_len)
1419 /* NOTE: this argument _must_ be unsigned */
1420 unsigned char *s = (unsigned char *)s1;
1421 int len = 0;
1423 if (buf_len < 1) {
1424 return -1;
1426 /* If the two high bits of the byte are set, return 2. */
1427 if (0xC0 == (*s & 0xC0)) {
1428 if (buf_len < 2) {
1429 return -1;
1431 return(2);
1434 /* Add up the length bytes. */
1435 for (len = 1; (*s); s += (*s) + 1) {
1436 len += *s + 1;
1437 if (len > buf_len) {
1438 return -1;
1442 return(len);