source: branches/samba-3.2.x/source/libsmb/nmblib.c@ 411

Last change on this file since 411 was 133, checked in by Paul Smedley, 17 years ago

Update trunk to 3.2.0pre3

File size: 36.2 KB
Line 
1/*
2 Unix SMB/CIFS implementation.
3 NBT netbios library routines
4 Copyright (C) Andrew Tridgell 1994-1998
5 Copyright (C) Jeremy Allison 2007
6
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.
11
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.
16
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/>.
19
20*/
21
22#include "includes.h"
23
24int num_good_sends = 0;
25int num_good_receives = 0;
26
27static 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 }
39};
40
41/****************************************************************************
42 Lookup a nmb opcode name.
43****************************************************************************/
44
45static const char *lookup_opcode_name( int opcode )
46{
47 const struct opcode_names *op_namep;
48 int i;
49
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;
54 }
55 return "<unknown opcode>";
56}
57
58/****************************************************************************
59 Print out a res_rec structure.
60****************************************************************************/
61
62static void debug_nmb_res_rec(struct res_rec *res, const char *hdr)
63{
64 int i, j;
65
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 ) );
72
73 if( res->rdlength == 0 || res->rdata == NULL )
74 return;
75
76 for (i = 0; i < res->rdlength; i+= MAX_NETBIOSNAME_LEN) {
77 DEBUGADD(4, (" %s %3x char ", hdr, i));
78
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 = '.';
83
84 if (i+j >= res->rdlength)
85 break;
86 DEBUGADD(4, ("%c", x));
87 }
88
89 DEBUGADD(4, (" hex "));
90
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]));
95 }
96
97 DEBUGADD(4, ("\n"));
98 }
99}
100
101/****************************************************************************
102 Process a nmb packet.
103****************************************************************************/
104
105void debug_nmb_packet(struct packet_struct *p)
106{
107 struct nmb_packet *nmb = &p->packet.nmb;
108
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 );
131 }
132
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) );
138 }
139
140 if (nmb->answers && nmb->header.ancount) {
141 debug_nmb_res_rec(nmb->answers,"answers");
142 }
143 if (nmb->nsrecs && nmb->header.nscount) {
144 debug_nmb_res_rec(nmb->nsrecs,"nsrecs");
145 }
146 if (nmb->additional && nmb->header.arcount) {
147 debug_nmb_res_rec(nmb->additional,"additional");
148 }
149}
150
151/*******************************************************************
152 Handle "compressed" name pointers.
153******************************************************************/
154
155static bool handle_name_ptrs(unsigned char *ubuf,int *offset,int length,
156 bool *got_pointer,int *ret)
157{
158 int loop_count=0;
159
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;
168 }
169 }
170 return True;
171}
172
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******************************************************************/
177
178static int parse_nmb_name(char *inbuf,int ofs,int length, struct nmb_name *name)
179{
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;
186
187 if (length - offset < 2)
188 return(0);
189
190 /* handle initial name pointers */
191 if (!handle_name_ptrs(ubuf,&offset,length,&got_pointer,&ret))
192 return(0);
193
194 m = ubuf[offset];
195
196 if (!m)
197 return(0);
198 if ((m & 0xC0) || offset+m+2 > length)
199 return(0);
200
201 memset((char *)name,'\0',sizeof(*name));
202
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;
215 }
216 name->name[n] = 0;
217
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;
222
223 /* remove trailing spaces */
224 name->name[15] = 0;
225 n = 14;
226 while (n && name->name[n]==' ')
227 name->name[n--] = 0;
228 }
229
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);
236
237 m = ubuf[offset];
238 /*
239 * Don't allow null domain parts.
240 */
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++];
252
253 /*
254 * Watch for malicious loops.
255 */
256 if (loop_count++ == 10)
257 return 0;
258 }
259 name->scope[n++] = 0;
260
261 return(ret);
262}
263
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****************************************************************************/
269
270void put_name(char *dest, const char *name, int pad, unsigned int name_type)
271{
272 size_t len = strlen(name);
273
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);
278 }
279 dest[MAX_NETBIOSNAME_LEN - 1] = name_type;
280}
281
282/*******************************************************************
283 Put a compressed nmb name into a buffer. Return the length of the
284 compressed name.
285
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.
289
290 If buf == NULL this is a length calculation.
291******************************************************************/
292
293static int put_nmb_name(char *buf,int offset,struct nmb_name *name)
294{
295 int ret,m;
296 nstring buf1;
297 char *p;
298
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);
304 }
305
306 if (buf) {
307 buf[offset] = 0x20;
308 }
309
310 ret = 34;
311
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);
316 }
317 }
318 offset += 33;
319
320 if (buf) {
321 buf[offset] = 0;
322 }
323
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));
330
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];
336 }
337 buf[offset] = strlen(&buf[offset+1]);
338 }
339 }
340
341 return ret;
342}
343
344/*******************************************************************
345 Useful for debugging messages.
346******************************************************************/
347
348char *nmb_namestr(const struct nmb_name *n)
349{
350 fstring name;
351 char *result;
352
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);
360
361 SMB_ASSERT(result != NULL);
362 return result;
363}
364
365/*******************************************************************
366 Allocate and parse some resource records.
367******************************************************************/
368
369static bool parse_alloc_res_rec(char *inbuf,int *offset,int length,
370 struct res_rec **recs, int count)
371{
372 int i;
373
374 *recs = SMB_MALLOC_ARRAY(struct res_rec, count);
375 if (!*recs)
376 return(False);
377
378 memset((char *)*recs,'\0',sizeof(**recs)*count);
379
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);
387 }
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);
397 }
398 memcpy((*recs)[i].rdata,inbuf+(*offset),(*recs)[i].rdlength);
399 (*offset) += (*recs)[i].rdlength;
400 }
401 return(True);
402}
403
404/*******************************************************************
405 Put a resource record into a packet.
406 If buf == NULL this is a length calculation.
407******************************************************************/
408
409static int put_res_rec(char *buf,int offset,struct res_rec *recs,int count)
410{
411 int ret=0;
412 int i;
413
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);
424 }
425 offset += 10+recs[i].rdlength;
426 ret += 10+recs[i].rdlength;
427 }
428
429 return ret;
430}
431
432/*******************************************************************
433 Put a compressed name pointer record into a packet.
434 If buf == NULL this is a length calculation.
435******************************************************************/
436
437static int put_compressed_name_ptr(unsigned char *buf,
438 int offset,
439 struct res_rec *rec,
440 int ptr_offset)
441{
442 int ret=0;
443 if (buf) {
444 buf[offset] = (0xC0 | ((ptr_offset >> 8) & 0xFF));
445 buf[offset+1] = (ptr_offset & 0xFF);
446 }
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);
455 }
456 offset += 10+rec->rdlength;
457 ret += 10+rec->rdlength;
458
459 return ret;
460}
461
462/*******************************************************************
463 Parse a dgram packet. Return False if the packet can't be parsed
464 or is invalid for some reason, True otherwise.
465
466 This is documented in section 4.4.1 of RFC1002.
467******************************************************************/
468
469static bool parse_dgram(char *inbuf,int length,struct dgram_packet *dgram)
470{
471 int offset;
472 int flags;
473
474 memset((char *)dgram,'\0',sizeof(*dgram));
475
476 if (length < 14)
477 return(False);
478
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);
491
492 offset = 14;
493
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);
501 }
502
503 if (offset >= length || (length-offset > sizeof(dgram->data)))
504 return(False);
505
506 dgram->datasize = length-offset;
507 memcpy(dgram->data,inbuf+offset,dgram->datasize);
508
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);
514
515 return(True);
516}
517
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******************************************************************/
522
523static bool parse_nmb(char *inbuf,int length,struct nmb_packet *nmb)
524{
525 int nm_flags,offset;
526
527 memset((char *)nmb,'\0',sizeof(*nmb));
528
529 if (length < 12)
530 return(False);
531
532 /* parse the header */
533 nmb->header.name_trn_id = RSVAL(inbuf,0);
534
535 DEBUG(10,("parse_nmb: packet id = %d\n", nmb->header.name_trn_id));
536
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);
550
551 if (nmb->header.qdcount) {
552 offset = parse_nmb_name(inbuf,12,length,
553 &nmb->question.question_name);
554 if (!offset)
555 return(False);
556
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);
561
562 offset += 12+4;
563 } else {
564 offset = 12;
565 }
566
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);
572
573 if (nmb->header.nscount &&
574 !parse_alloc_res_rec(inbuf,&offset,length,&nmb->nsrecs,
575 nmb->header.nscount))
576 return(False);
577
578 if (nmb->header.arcount &&
579 !parse_alloc_res_rec(inbuf,&offset,length,
580 &nmb->additional, nmb->header.arcount))
581 return(False);
582
583 return(True);
584}
585
586/*******************************************************************
587 'Copy constructor' for an nmb packet.
588******************************************************************/
589
590static struct packet_struct *copy_nmb_packet(struct packet_struct *packet)
591{
592 struct nmb_packet *nmb;
593 struct nmb_packet *copy_nmb;
594 struct packet_struct *pkt_copy;
595
596 if(( pkt_copy = SMB_MALLOC_P(struct packet_struct)) == NULL) {
597 DEBUG(0,("copy_nmb_packet: malloc fail.\n"));
598 return NULL;
599 }
600
601 /* Structure copy of entire thing. */
602
603 *pkt_copy = *packet;
604
605 /* Ensure this copy is not locked. */
606 pkt_copy->locked = False;
607
608 /* Ensure this copy has no resource records. */
609 nmb = &packet->packet.nmb;
610 copy_nmb = &pkt_copy->packet.nmb;
611
612 copy_nmb->answers = NULL;
613 copy_nmb->nsrecs = NULL;
614 copy_nmb->additional = NULL;
615
616 /* Now copy any resource records. */
617
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));
624 }
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));
631 }
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));
638 }
639
640 return pkt_copy;
641
642 free_and_exit:
643
644 SAFE_FREE(copy_nmb->answers);
645 SAFE_FREE(copy_nmb->nsrecs);
646 SAFE_FREE(copy_nmb->additional);
647 SAFE_FREE(pkt_copy);
648
649 DEBUG(0,("copy_nmb_packet: malloc fail in resource records.\n"));
650 return NULL;
651}
652
653/*******************************************************************
654 'Copy constructor' for a dgram packet.
655******************************************************************/
656
657static struct packet_struct *copy_dgram_packet(struct packet_struct *packet)
658{
659 struct packet_struct *pkt_copy;
660
661 if(( pkt_copy = SMB_MALLOC_P(struct packet_struct)) == NULL) {
662 DEBUG(0,("copy_dgram_packet: malloc fail.\n"));
663 return NULL;
664 }
665
666 /* Structure copy of entire thing. */
667
668 *pkt_copy = *packet;
669
670 /* Ensure this copy is not locked. */
671 pkt_copy->locked = False;
672
673 /* There are no additional pointers in a dgram packet,
674 we are finished. */
675 return pkt_copy;
676}
677
678/*******************************************************************
679 'Copy constructor' for a generic packet.
680******************************************************************/
681
682struct packet_struct *copy_packet(struct packet_struct *packet)
683{
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;
689}
690
691/*******************************************************************
692 Free up any resources associated with an nmb packet.
693******************************************************************/
694
695static void free_nmb_packet(struct nmb_packet *nmb)
696{
697 SAFE_FREE(nmb->answers);
698 SAFE_FREE(nmb->nsrecs);
699 SAFE_FREE(nmb->additional);
700}
701
702/*******************************************************************
703 Free up any resources associated with a dgram packet.
704******************************************************************/
705
706static void free_dgram_packet(struct dgram_packet *nmb)
707{
708 /* We have nothing to do for a dgram packet. */
709}
710
711/*******************************************************************
712 Free up any resources associated with a packet.
713******************************************************************/
714
715void free_packet(struct packet_struct *packet)
716{
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);
725}
726
727/*******************************************************************
728 Parse a packet buffer into a packet structure.
729******************************************************************/
730
731struct packet_struct *parse_packet(char *buf,int length,
732 enum packet_type packet_type,
733 struct in_addr ip,
734 int port)
735{
736 struct packet_struct *p;
737 bool ok=False;
738
739 p = SMB_MALLOC_P(struct packet_struct);
740 if (!p)
741 return(NULL);
742
743 ZERO_STRUCTP(p); /* initialize for possible padding */
744
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;
752
753 switch (packet_type) {
754 case NMB_PACKET:
755 ok = parse_nmb(buf,length,&p->packet.nmb);
756 break;
757
758 case DGRAM_PACKET:
759 ok = parse_dgram(buf,length,&p->packet.dgram);
760 break;
761 }
762
763 if (!ok) {
764 free_packet(p);
765 return NULL;
766 }
767
768 return p;
769}
770
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******************************************************************/
775
776struct packet_struct *read_packet(int fd,enum packet_type packet_type)
777{
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;
783
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;
787 }
788
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;
796
797 packet->fd = fd;
798
799 num_good_receives++;
800
801 DEBUG(5,("Received a packet of len %d from (%s) port %d\n",
802 length, inet_ntoa(packet->ip), packet->port ) );
803
804 return(packet);
805}
806
807/*******************************************************************
808 Send a udp packet on a already open socket.
809******************************************************************/
810
811static bool send_udp(int fd,char *buf,int len,struct in_addr ip,int port)
812{
813 bool ret = False;
814 int i;
815 struct sockaddr_in sock_out;
816
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;
822
823 DEBUG( 5, ( "Sending a packet of len %d to (%s) on port %d\n",
824 len, inet_ntoa(ip), port ) );
825
826 /*
827 * Patch to fix asynch error notifications from Linux kernel.
828 */
829
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;
835 }
836
837 if (!ret)
838 DEBUG(0,("Packet send failed to %s(%d) ERRNO=%s\n",
839 inet_ntoa(ip),port,strerror(errno)));
840
841 if (ret)
842 num_good_sends++;
843
844 return(ret);
845}
846
847/*******************************************************************
848 Build a dgram packet ready for sending.
849 If buf == NULL this is a length calculation.
850******************************************************************/
851
852static int build_dgram(char *buf, size_t len, struct dgram_packet *dgram)
853{
854 unsigned char *ubuf = (unsigned char *)buf;
855 int offset=0;
856
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);
869 }
870
871 offset = 14;
872
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);
878 }
879
880 if (buf) {
881 memcpy(ubuf+offset,dgram->data,dgram->datasize);
882 }
883 offset += dgram->datasize;
884
885 /* automatically set the dgm_length
886 * NOTE: RFC1002 says the dgm_length does *not*
887 * include the fourteen-byte header. crh
888 */
889 dgram->header.dgm_length = (offset - 14);
890 if (buf) {
891 RSSVAL(ubuf,10,dgram->header.dgm_length);
892 }
893
894 return offset;
895}
896
897/*******************************************************************
898 Build a nmb name
899*******************************************************************/
900
901void make_nmb_name( struct nmb_name *n, const char *name, int type)
902{
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);
910}
911
912/*******************************************************************
913 Compare two nmb names
914******************************************************************/
915
916bool nmb_name_equal(struct nmb_name *n1, struct nmb_name *n2)
917{
918 return ((n1->name_type == n2->name_type) &&
919 strequal(n1->name ,n2->name ) &&
920 strequal(n1->scope,n2->scope));
921}
922
923/*******************************************************************
924 Build a nmb packet ready for sending.
925 If buf == NULL this is a length calculation.
926******************************************************************/
927
928static int build_nmb(char *buf, size_t len, struct nmb_packet *nmb)
929{
930 unsigned char *ubuf = (unsigned char *)buf;
931 int offset=0;
932
933 if (len && len < 12) {
934 return 0;
935 }
936
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);
956
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);
961 }
962
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;
972 }
973 }
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);
979 }
980 offset += 4;
981 }
982
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;
990 }
991 }
992 offset += put_res_rec((char *)ubuf,offset,nmb->answers,
993 nmb->header.ancount);
994 }
995
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;
1003 }
1004 }
1005 offset += put_res_rec((char *)ubuf,offset,nmb->nsrecs,
1006 nmb->header.nscount);
1007 }
1008
1009 /*
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.
1014 */
1015
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)) {
1023
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;
1030 }
1031 }
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;
1041 }
1042 }
1043 offset += put_res_rec((char *)ubuf,offset,nmb->additional,
1044 nmb->header.arcount);
1045 }
1046 return offset;
1047}
1048
1049/*******************************************************************
1050 Linearise a packet.
1051******************************************************************/
1052
1053int build_packet(char *buf, size_t buflen, struct packet_struct *p)
1054{
1055 int len = 0;
1056
1057 switch (p->packet_type) {
1058 case NMB_PACKET:
1059 len = build_nmb(buf,buflen,&p->packet.nmb);
1060 break;
1061
1062 case DGRAM_PACKET:
1063 len = build_dgram(buf,buflen,&p->packet.dgram);
1064 break;
1065 }
1066
1067 return len;
1068}
1069
1070/*******************************************************************
1071 Send a packet_struct.
1072******************************************************************/
1073
1074bool send_packet(struct packet_struct *p)
1075{
1076 char buf[1024];
1077 int len=0;
1078
1079 memset(buf,'\0',sizeof(buf));
1080
1081 len = build_packet(buf, sizeof(buf), p);
1082
1083 if (!len)
1084 return(False);
1085
1086 return(send_udp(p->fd,buf,len,p->ip,p->port));
1087}
1088
1089/****************************************************************************
1090 Receive a packet with timeout on a open UDP filedescriptor.
1091 The timeout is in milliseconds
1092***************************************************************************/
1093
1094struct packet_struct *receive_packet(int fd,enum packet_type type,int t)
1095{
1096 fd_set fds;
1097 struct timeval timeout;
1098 int ret;
1099
1100 FD_ZERO(&fds);
1101 FD_SET(fd,&fds);
1102 timeout.tv_sec = t/1000;
1103 timeout.tv_usec = 1000*(t%1000);
1104
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;
1110 }
1111
1112 if (ret == 0) /* timeout */
1113 return NULL;
1114
1115 if (FD_ISSET(fd,&fds))
1116 return(read_packet(fd,type));
1117
1118 return(NULL);
1119}
1120
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***************************************************************************/
1126
1127struct packet_struct *receive_nmb_packet(int fd, int t, int trn_id)
1128{
1129 struct packet_struct *p;
1130
1131 p = receive_packet(fd, NMB_PACKET, t);
1132
1133 if (p && p->packet.nmb.header.response &&
1134 p->packet.nmb.header.name_trn_id == trn_id) {
1135 return p;
1136 }
1137 if (p)
1138 free_packet(p);
1139
1140 /* try the unexpected packet queue */
1141 return receive_unexpected(NMB_PACKET, trn_id, NULL);
1142}
1143
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***************************************************************************/
1149
1150struct packet_struct *receive_dgram_packet(int fd, int t,
1151 const char *mailslot_name)
1152{
1153 struct packet_struct *p;
1154
1155 p = receive_packet(fd, DGRAM_PACKET, t);
1156
1157 if (p && match_mailslot_name(p, mailslot_name)) {
1158 return p;
1159 }
1160 if (p)
1161 free_packet(p);
1162
1163 /* try the unexpected packet queue */
1164 return receive_unexpected(DGRAM_PACKET, 0, mailslot_name);
1165}
1166
1167/****************************************************************************
1168 See if a datagram has the right mailslot name.
1169***************************************************************************/
1170
1171bool match_mailslot_name(struct packet_struct *p, const char *mailslot_name)
1172{
1173 struct dgram_packet *dgram = &p->packet.dgram;
1174 char *buf;
1175
1176 buf = &dgram->data[0];
1177 buf -= 4;
1178
1179 buf = smb_buf(buf);
1180
1181 if (memcmp(buf, mailslot_name, strlen(mailslot_name)+1) == 0) {
1182 return True;
1183 }
1184
1185 return False;
1186}
1187
1188/****************************************************************************
1189 Return the number of bits that match between two len character buffers
1190***************************************************************************/
1191
1192int matching_len_bits(unsigned char *p1, unsigned char *p2, size_t len)
1193{
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;
1200 }
1201
1202 if (i==len)
1203 return ret;
1204
1205 for (j=0; j<8; j++) {
1206 if ((p1[i] & (1<<(7-j))) != (p2[i] & (1<<(7-j))))
1207 break;
1208 ret++;
1209 }
1210
1211 return ret;
1212}
1213
1214static unsigned char sort_ip[4];
1215
1216/****************************************************************************
1217 Compare two query reply records.
1218***************************************************************************/
1219
1220static int name_query_comp(unsigned char *p1, unsigned char *p2)
1221{
1222 return matching_len_bits(p2+2, sort_ip, 4) -
1223 matching_len_bits(p1+2, sort_ip, 4);
1224}
1225
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***************************************************************************/
1230
1231void sort_query_replies(char *data, int n, struct in_addr ip)
1232{
1233 if (n <= 1)
1234 return;
1235
1236 putip(sort_ip, (char *)&ip);
1237
1238 qsort(data, n, 6, QSORT_CAST name_query_comp);
1239}
1240
1241/****************************************************************************
1242 Interpret the weird netbios "name" into a unix fstring. Return the name type.
1243****************************************************************************/
1244
1245static int name_interpret(char *in, fstring name)
1246{
1247 int ret;
1248 int len = (*in++) / 2;
1249 fstring out_string;
1250 char *out = out_string;
1251
1252 *out=0;
1253
1254 if (len > 30 || len<1)
1255 return(0);
1256
1257 while (len--) {
1258 if (in[0] < 'A' || in[0] > 'P' || in[1] < 'A' || in[1] > 'P') {
1259 *out = 0;
1260 return(0);
1261 }
1262 *out = ((in[0]-'A')<<4) + (in[1]-'A');
1263 in += 2;
1264 out++;
1265 }
1266 ret = out[-1];
1267 out[-1] = 0;
1268
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;
1278 }
1279#endif
1280 pull_ascii_fstring(name, out_string);
1281
1282 return(ret);
1283}
1284
1285/****************************************************************************
1286 Mangle a name into netbios format.
1287 Note: <Out> must be (33 + strlen(scope) + 2) bytes long, at minimum.
1288****************************************************************************/
1289
1290int name_mangle( char *In, char *Out, char name_type )
1291{
1292 int i;
1293 int len;
1294 nstring buf;
1295 char *p = Out;
1296
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;
1305
1306 pull_ascii_fstring(buf_unix, In);
1307 strupper_m(buf_unix);
1308
1309 push_ascii_nstring(buf_dos, buf_unix);
1310 put_name(buf, buf_dos, ' ', name_type);
1311 }
1312
1313 /* Place the length of the first field into the output buffer. */
1314 p[0] = 32;
1315 p++;
1316
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';
1321 }
1322 p += 32;
1323 p[0] = '\0';
1324
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;
1341 }
1342 }
1343
1344 return( name_len(Out) );
1345}
1346
1347/****************************************************************************
1348 Find a pointer to a netbios name.
1349****************************************************************************/
1350
1351static char *name_ptr(char *buf,int ofs)
1352{
1353 unsigned char c = *(unsigned char *)(buf+ofs);
1354
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);
1361 }
1362}
1363
1364/****************************************************************************
1365 Extract a netbios name from a buf (into a unix string) return name type.
1366****************************************************************************/
1367
1368int name_extract(char *buf,int ofs, fstring name)
1369{
1370 char *p = name_ptr(buf,ofs);
1371 int d = PTR_DIFF(p,buf+ofs);
1372
1373 name[0] = '\0';
1374 if (d < -50 || d > 50)
1375 return(0);
1376 return(name_interpret(p,name));
1377}
1378
1379/****************************************************************************
1380 Return the total storage length of a mangled name.
1381****************************************************************************/
1382
1383int name_len(char *s1)
1384{
1385 /* NOTE: this argument _must_ be unsigned */
1386 unsigned char *s = (unsigned char *)s1;
1387 int len;
1388
1389 /* If the two high bits of the byte are set, return 2. */
1390 if (0xC0 == (*s & 0xC0))
1391 return(2);
1392
1393 /* Add up the length bytes. */
1394 for (len = 1; (*s); s += (*s) + 1) {
1395 len += *s + 1;
1396 SMB_ASSERT(len < 80);
1397 }
1398
1399 return(len);
1400}
Note: See TracBrowser for help on using the repository browser.