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