Deleted Added
sdiff udiff text old ( 124621 ) new ( 127094 )
full compact
1/*-
2 * Written by Atsushi Murai <amurai@spec.co.jp>
3 * Copyright (c) 1998, System Planning and Engineering Co.
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:

--- 15 unchanged lines hidden (view full) ---

24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 * TODO:
27 * oClean up.
28 * oConsidering for word alignment for other platform.
29 */
30
31#include <sys/cdefs.h>
32__FBSDID("$FreeBSD: head/sys/netinet/libalias/alias_nbt.c 124621 2004-01-17 10:52:21Z phk $");
33
34/*
35 alias_nbt.c performs special processing for NetBios over TCP/IP
36 sessions by UDP.
37
38 Initial version: May, 1998 (Atsushi Murai <amurai@spec.co.jp>)
39
40 See HISTORY file for record of revisions.

--- 9 unchanged lines hidden (view full) ---

50#include <arpa/inet.h>
51#include <netinet/ip.h>
52#include <netinet/udp.h>
53#include <netinet/tcp.h>
54
55#include "alias_local.h"
56
57typedef struct {
58 struct in_addr oldaddr;
59 u_short oldport;
60 struct in_addr newaddr;
61 u_short newport;
62 u_short *uh_sum;
63} NBTArguments;
64
65typedef struct {
66 unsigned char type;
67 unsigned char flags;
68 u_short id;
69 struct in_addr source_ip;
70 u_short source_port;
71 u_short len;
72 u_short offset;
73} NbtDataHeader;
74
75#define OpQuery 0
76#define OpUnknown 4
77#define OpRegist 5
78#define OpRelease 6
79#define OpWACK 7
80#define OpRefresh 8
81typedef struct {
82 u_short nametrid;
83 u_short dir:1, opcode:4, nmflags:7, rcode:4;
84 u_short qdcount;
85 u_short ancount;
86 u_short nscount;
87 u_short arcount;
88} NbtNSHeader;
89
90#define FMT_ERR 0x1
91#define SRV_ERR 0x2
92#define IMP_ERR 0x4
93#define RFS_ERR 0x5
94#define ACT_ERR 0x6
95#define CFT_ERR 0x7
96
97
98#ifdef DEBUG
99static void PrintRcode( u_char rcode ) {
100
101 switch (rcode) {
102 case FMT_ERR:
103 printf("\nFormat Error.");
104 case SRV_ERR:
105 printf("\nSever failure.");
106 case IMP_ERR:
107 printf("\nUnsupported request error.\n");
108 case RFS_ERR:
109 printf("\nRefused error.\n");
110 case ACT_ERR:
111 printf("\nActive error.\n");
112 case CFT_ERR:
113 printf("\nName in conflict error.\n");
114 default:
115 printf("\n?%c?=%0x\n", '?', rcode );
116
117 }
118}
119#endif
120
121
122/* Handling Name field */
123static u_char *AliasHandleName ( u_char *p, char *pmax ) {
124
125 u_char *s;
126 u_char c;
127 int compress;
128
129 /* Following length field */
130
131 if (p == NULL || (char *)p >= pmax)
132 return(NULL);
133
134 if (*p & 0xc0 ) {
135 p = p + 2;
136 if ((char *)p > pmax)
137 return(NULL);
138 return ((u_char *)p);
139 }
140 while ( ( *p & 0x3f) != 0x00 ) {
141 s = p + 1;
142 if ( *p == 0x20 )
143 compress = 1;
144 else
145 compress = 0;
146
147 /* Get next length field */
148 p = (u_char *)(p + (*p & 0x3f) + 1);
149 if ((char *)p > pmax) {
150 p = NULL;
151 break;
152 }
153#ifdef DEBUG
154 printf(":");
155#endif
156 while (s < p) {
157 if ( compress == 1 ) {
158 c = (u_char )(((((*s & 0x0f) << 4) | (*(s+1) & 0x0f)) - 0x11));
159#ifdef DEBUG
160 if (isprint( c ) )
161 printf("%c", c );
162 else
163 printf("<0x%02x>", c );
164#endif
165 s +=2;
166 } else {
167#ifdef DEBUG
168 printf("%c", *s);
169#endif
170 s++;
171 }
172 }
173#ifdef DEBUG
174 printf(":");
175#endif
176 fflush(stdout);
177 }
178
179 /* Set up to out of Name field */
180 if (p == NULL || (char *)p >= pmax)
181 p = NULL;
182 else
183 p++;
184 return ((u_char *)p);
185}
186
187/*
188 * NetBios Datagram Handler (IP/UDP)
189 */
190#define DGM_DIRECT_UNIQ 0x10
191#define DGM_DIRECT_GROUP 0x11
192#define DGM_BROADCAST 0x12
193#define DGM_ERROR 0x13
194#define DGM_QUERY 0x14
195#define DGM_POSITIVE_RES 0x15
196#define DGM_NEGATIVE_RES 0x16
197
198int AliasHandleUdpNbt(
199 struct libalias *la,
200 struct ip *pip, /* IP packet to examine/patch */
201 struct alias_link *link,
202 struct in_addr *alias_address,
203 u_short alias_port
204) {
205 struct udphdr * uh;
206 NbtDataHeader *ndh;
207 u_char *p = NULL;
208 char *pmax;
209
210 /* Calculate data length of UDP packet */
211 uh = (struct udphdr *) ((char *) pip + (pip->ip_hl << 2));
212 pmax = (char *)uh + ntohs( uh->uh_ulen );
213
214 ndh = (NbtDataHeader *)((char *)uh + (sizeof (struct udphdr)));
215 if ((char *)(ndh + 1) > pmax)
216 return(-1);
217#ifdef DEBUG
218 printf("\nType=%02x,", ndh->type );
219#endif
220 switch ( ndh->type ) {
221 case DGM_DIRECT_UNIQ:
222 case DGM_DIRECT_GROUP:
223 case DGM_BROADCAST:
224 p = (u_char *)ndh + 14;
225 p = AliasHandleName ( p, pmax ); /* Source Name */
226 p = AliasHandleName ( p, pmax ); /* Destination Name */
227 break;
228 case DGM_ERROR:
229 p = (u_char *)ndh + 11;
230 break;
231 case DGM_QUERY:
232 case DGM_POSITIVE_RES:
233 case DGM_NEGATIVE_RES:
234 p = (u_char *)ndh + 10;
235 p = AliasHandleName ( p, pmax ); /* Destination Name */
236 break;
237 }
238 if (p == NULL || (char *)p > pmax)
239 p = NULL;
240#ifdef DEBUG
241 printf("%s:%d-->", inet_ntoa(ndh->source_ip), ntohs(ndh->source_port) );
242#endif
243 /* Doing an IP address and Port number Translation */
244 if ( uh->uh_sum != 0 ) {
245 int acc;
246 u_short *sptr;
247 acc = ndh->source_port;
248 acc -= alias_port;
249 sptr = (u_short *) &(ndh->source_ip);
250 acc += *sptr++;
251 acc += *sptr;
252 sptr = (u_short *) alias_address;
253 acc -= *sptr++;
254 acc -= *sptr;
255 ADJUST_CHECKSUM(acc, uh->uh_sum);
256 }
257 ndh->source_ip = *alias_address;
258 ndh->source_port = alias_port;
259#ifdef DEBUG
260 printf("%s:%d\n", inet_ntoa(ndh->source_ip), ntohs(ndh->source_port) );
261 fflush(stdout);
262#endif
263 return((p == NULL) ? -1 : 0);
264}
265/* Question Section */
266#define QS_TYPE_NB 0x0020
267#define QS_TYPE_NBSTAT 0x0021
268#define QS_CLAS_IN 0x0001
269typedef struct {
270 u_short type; /* The type of Request */
271 u_short class; /* The class of Request */
272} NBTNsQuestion;
273
274static u_char *
275AliasHandleQuestion(
276 u_short count,
277 NBTNsQuestion *q,
278 char *pmax,
279 NBTArguments *nbtarg)
280{
281
282 while ( count != 0 ) {
283 /* Name Filed */
284 q = (NBTNsQuestion *)AliasHandleName((u_char *)q, pmax);
285
286 if (q == NULL || (char *)(q + 1) > pmax) {
287 q = NULL;
288 break;
289 }
290
291 /* Type and Class filed */
292 switch ( ntohs(q->type) ) {
293 case QS_TYPE_NB:
294 case QS_TYPE_NBSTAT:
295 q= q+1;
296 break;
297 default:
298#ifdef DEBUG
299 printf("\nUnknown Type on Question %0x\n", ntohs(q->type) );
300#endif
301 break;
302 }
303 count--;
304 }
305
306 /* Set up to out of Question Section */
307 return ((u_char *)q);
308}
309
310/* Resource Record */
311#define RR_TYPE_A 0x0001
312#define RR_TYPE_NS 0x0002
313#define RR_TYPE_NULL 0x000a
314#define RR_TYPE_NB 0x0020
315#define RR_TYPE_NBSTAT 0x0021
316#define RR_CLAS_IN 0x0001
317#define SizeOfNsResource 8
318typedef struct {
319 u_short type;
320 u_short class;
321 unsigned int ttl;
322 u_short rdlen;
323} NBTNsResource;
324
325#define SizeOfNsRNB 6
326typedef struct {
327 u_short g:1, ont:2, resv:13;
328 struct in_addr addr;
329} NBTNsRNB;
330
331static u_char *
332AliasHandleResourceNB(
333 NBTNsResource *q,
334 char *pmax,
335 NBTArguments *nbtarg)
336{
337 NBTNsRNB *nb;
338 u_short bcount;
339
340 if (q == NULL || (char *)(q + 1) > pmax)
341 return(NULL);
342 /* Check out a length */
343 bcount = ntohs(q->rdlen);
344
345 /* Forward to Resource NB position */
346 nb = (NBTNsRNB *)((u_char *)q + SizeOfNsResource);
347
348 /* Processing all in_addr array */
349#ifdef DEBUG
350 printf("NB rec[%s", inet_ntoa(nbtarg->oldaddr));
351 printf("->%s, %dbytes] ",inet_ntoa(nbtarg->newaddr ), bcount);
352#endif
353 while ( nb != NULL && bcount != 0 ) {
354 if ((char *)(nb + 1) > pmax) {
355 nb = NULL;
356 break;
357 }
358#ifdef DEBUG
359 printf("<%s>", inet_ntoa(nb->addr) );
360#endif
361 if (!bcmp(&nbtarg->oldaddr,&nb->addr, sizeof(struct in_addr) ) ) {
362 if ( *nbtarg->uh_sum != 0 ) {
363 int acc;
364 u_short *sptr;
365
366 sptr = (u_short *) &(nb->addr);
367 acc = *sptr++;
368 acc += *sptr;
369 sptr = (u_short *) &(nbtarg->newaddr);
370 acc -= *sptr++;
371 acc -= *sptr;
372 ADJUST_CHECKSUM(acc, *nbtarg->uh_sum);
373 }
374
375 nb->addr = nbtarg->newaddr;
376#ifdef DEBUG
377 printf("O");
378#endif
379 }
380#ifdef DEBUG
381 else {
382 printf(".");
383 }
384#endif
385 nb=(NBTNsRNB *)((u_char *)nb + SizeOfNsRNB);
386 bcount -= SizeOfNsRNB;
387 }
388 if (nb == NULL || (char *)(nb + 1) > pmax) {
389 nb = NULL;
390 }
391
392 return ((u_char *)nb);
393}
394
395#define SizeOfResourceA 6
396typedef struct {
397 struct in_addr addr;
398} NBTNsResourceA;
399
400static u_char *
401AliasHandleResourceA(
402 NBTNsResource *q,
403 char *pmax,
404 NBTArguments *nbtarg)
405{
406 NBTNsResourceA *a;
407 u_short bcount;
408
409 if (q == NULL || (char *)(q + 1) > pmax)
410 return(NULL);
411
412 /* Forward to Resource A position */
413 a = (NBTNsResourceA *)( (u_char *)q + sizeof(NBTNsResource) );
414
415 /* Check out of length */
416 bcount = ntohs(q->rdlen);
417
418 /* Processing all in_addr array */
419#ifdef DEBUG
420 printf("Arec [%s", inet_ntoa(nbtarg->oldaddr));
421 printf("->%s]",inet_ntoa(nbtarg->newaddr ));
422#endif
423 while ( bcount != 0 ) {
424 if (a == NULL || (char *)(a + 1) > pmax)
425 return(NULL);
426#ifdef DEBUG
427 printf("..%s", inet_ntoa(a->addr) );
428#endif
429 if ( !bcmp(&nbtarg->oldaddr, &a->addr, sizeof(struct in_addr) ) ) {
430 if ( *nbtarg->uh_sum != 0 ) {
431 int acc;
432 u_short *sptr;
433
434 sptr = (u_short *) &(a->addr); /* Old */
435 acc = *sptr++;
436 acc += *sptr;
437 sptr = (u_short *) &nbtarg->newaddr; /* New */
438 acc -= *sptr++;
439 acc -= *sptr;
440 ADJUST_CHECKSUM(acc, *nbtarg->uh_sum);
441 }
442
443 a->addr = nbtarg->newaddr;
444 }
445 a++; /*XXXX*/
446 bcount -= SizeOfResourceA;
447 }
448 if (a == NULL || (char *)(a + 1) > pmax)
449 a = NULL;
450 return ((u_char *)a);
451}
452
453typedef struct {
454 u_short opcode:4, flags:8, resv:4;
455} NBTNsResourceNULL;
456
457static u_char *
458AliasHandleResourceNULL(
459 NBTNsResource *q,
460 char *pmax,
461 NBTArguments *nbtarg)
462{
463 NBTNsResourceNULL *n;
464 u_short bcount;
465
466 if (q == NULL || (char *)(q + 1) > pmax)
467 return(NULL);
468
469 /* Forward to Resource NULL position */
470 n = (NBTNsResourceNULL *)( (u_char *)q + sizeof(NBTNsResource) );
471
472 /* Check out of length */
473 bcount = ntohs(q->rdlen);
474
475 /* Processing all in_addr array */
476 while ( bcount != 0 ) {
477 if ((char *)(n + 1) > pmax) {
478 n = NULL;
479 break;
480 }
481 n++;
482 bcount -= sizeof(NBTNsResourceNULL);
483 }
484 if ((char *)(n + 1) > pmax)
485 n = NULL;
486
487 return ((u_char *)n);
488}
489
490static u_char *
491AliasHandleResourceNS(
492 NBTNsResource *q,
493 char *pmax,
494 NBTArguments *nbtarg)
495{
496 NBTNsResourceNULL *n;
497 u_short bcount;
498
499 if (q == NULL || (char *)(q + 1) > pmax)
500 return(NULL);
501
502 /* Forward to Resource NULL position */
503 n = (NBTNsResourceNULL *)( (u_char *)q + sizeof(NBTNsResource) );
504
505 /* Check out of length */
506 bcount = ntohs(q->rdlen);
507
508 /* Resource Record Name Filed */
509 q = (NBTNsResource *)AliasHandleName( (u_char *)n, pmax ); /* XXX */
510
511 if (q == NULL || (char *)((u_char *)n + bcount) > pmax)
512 return(NULL);
513 else
514 return ((u_char *)n + bcount);
515}
516
517typedef struct {
518 u_short numnames;
519} NBTNsResourceNBSTAT;
520
521static u_char *
522AliasHandleResourceNBSTAT(
523 NBTNsResource *q,
524 char *pmax,
525 NBTArguments *nbtarg)
526{
527 NBTNsResourceNBSTAT *n;
528 u_short bcount;
529
530 if (q == NULL || (char *)(q + 1) > pmax)
531 return(NULL);
532
533 /* Forward to Resource NBSTAT position */
534 n = (NBTNsResourceNBSTAT *)( (u_char *)q + sizeof(NBTNsResource) );
535
536 /* Check out of length */
537 bcount = ntohs(q->rdlen);
538
539 if (q == NULL || (char *)((u_char *)n + bcount) > pmax)
540 return(NULL);
541 else
542 return ((u_char *)n + bcount);
543}
544
545static u_char *
546AliasHandleResource(
547 u_short count,
548 NBTNsResource *q,
549 char *pmax,
550 NBTArguments
551 *nbtarg)
552{
553 while ( count != 0 ) {
554 /* Resource Record Name Filed */
555 q = (NBTNsResource *)AliasHandleName( (u_char *)q, pmax );
556
557 if (q == NULL || (char *)(q + 1) > pmax)
558 break;
559#ifdef DEBUG
560 printf("type=%02x, count=%d\n", ntohs(q->type), count );
561#endif
562
563 /* Type and Class filed */
564 switch ( ntohs(q->type) ) {
565 case RR_TYPE_NB:
566 q = (NBTNsResource *)AliasHandleResourceNB(
567 q,
568 pmax,
569 nbtarg
570 );
571 break;
572 case RR_TYPE_A:
573 q = (NBTNsResource *)AliasHandleResourceA(
574 q,
575 pmax,
576 nbtarg
577 );
578 break;
579 case RR_TYPE_NS:
580 q = (NBTNsResource *)AliasHandleResourceNS(
581 q,
582 pmax,
583 nbtarg
584 );
585 break;
586 case RR_TYPE_NULL:
587 q = (NBTNsResource *)AliasHandleResourceNULL(
588 q,
589 pmax,
590 nbtarg
591 );
592 break;
593 case RR_TYPE_NBSTAT:
594 q = (NBTNsResource *)AliasHandleResourceNBSTAT(
595 q,
596 pmax,
597 nbtarg
598 );
599 break;
600 default:
601#ifdef DEBUG
602 printf(
603 "\nUnknown Type of Resource %0x\n",
604 ntohs(q->type)
605 );
606#endif
607 break;
608 }
609 count--;
610 }
611 fflush(stdout);
612 return ((u_char *)q);
613}
614
615int AliasHandleUdpNbtNS(
616 struct libalias *la,
617 struct ip *pip, /* IP packet to examine/patch */
618 struct alias_link *link,
619 struct in_addr *alias_address,
620 u_short *alias_port,
621 struct in_addr *original_address,
622 u_short *original_port )
623{
624 struct udphdr * uh;
625 NbtNSHeader * nsh;
626 u_char * p;
627 char *pmax;
628 NBTArguments nbtarg;
629
630 /* Set up Common Parameter */
631 nbtarg.oldaddr = *alias_address;
632 nbtarg.oldport = *alias_port;
633 nbtarg.newaddr = *original_address;
634 nbtarg.newport = *original_port;
635
636 /* Calculate data length of UDP packet */
637 uh = (struct udphdr *) ((char *) pip + (pip->ip_hl << 2));
638 nbtarg.uh_sum = &(uh->uh_sum);
639 nsh = (NbtNSHeader *)((char *)uh + (sizeof(struct udphdr)));
640 p = (u_char *)(nsh + 1);
641 pmax = (char *)uh + ntohs( uh->uh_ulen );
642
643 if ((char *)(nsh + 1) > pmax)
644 return(-1);
645
646#ifdef DEBUG
647 printf(" [%s] ID=%02x, op=%01x, flag=%02x, rcode=%01x, qd=%04x"
648 ", an=%04x, ns=%04x, ar=%04x, [%d]-->",
649 nsh->dir ? "Response": "Request",
650 nsh->nametrid,
651 nsh->opcode,
652 nsh->nmflags,
653 nsh->rcode,
654 ntohs(nsh->qdcount),
655 ntohs(nsh->ancount),
656 ntohs(nsh->nscount),
657 ntohs(nsh->arcount),
658 (u_char *)p -(u_char *)nsh
659 );
660#endif
661
662 /* Question Entries */
663 if (ntohs(nsh->qdcount) !=0 ) {
664 p = AliasHandleQuestion(
665 ntohs(nsh->qdcount),
666 (NBTNsQuestion *)p,
667 pmax,
668 &nbtarg
669 );
670 }
671
672 /* Answer Resource Records */
673 if (ntohs(nsh->ancount) !=0 ) {
674 p = AliasHandleResource(
675 ntohs(nsh->ancount),
676 (NBTNsResource *)p,
677 pmax,
678 &nbtarg
679 );
680 }
681
682 /* Authority Resource Recodrs */
683 if (ntohs(nsh->nscount) !=0 ) {
684 p = AliasHandleResource(
685 ntohs(nsh->nscount),
686 (NBTNsResource *)p,
687 pmax,
688 &nbtarg
689 );
690 }
691
692 /* Additional Resource Recodrs */
693 if (ntohs(nsh->arcount) !=0 ) {
694 p = AliasHandleResource(
695 ntohs(nsh->arcount),
696 (NBTNsResource *)p,
697 pmax,
698 &nbtarg
699 );
700 }
701
702#ifdef DEBUG
703 PrintRcode(nsh->rcode);
704#endif
705 return ((p == NULL) ? -1 : 0);
706}