2 * Written by Atsushi Murai <amurai@spec.co.jp>
3 * Copyright (c) 1998, System Planning and Engineering Co.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * oConsidering for word alignment for other platform.
31 #include <sys/cdefs.h>
32 __FBSDID("$FreeBSD$");
35 alias_nbt.c performs special processing for NetBios over TCP/IP
38 Initial version: May, 1998 (Atsushi Murai <amurai@spec.co.jp>)
40 See HISTORY file for record of revisions.
47 #include <sys/types.h>
48 #include <netinet/in_systm.h>
49 #include <netinet/in.h>
50 #include <arpa/inet.h>
51 #include <netinet/ip.h>
52 #include <netinet/udp.h>
53 #include <netinet/tcp.h>
55 #include "alias_local.h"
58 struct in_addr oldaddr;
60 struct in_addr newaddr;
69 struct in_addr source_ip;
83 u_short dir: 1, opcode:4, nmflags:7, rcode:4;
100 PrintRcode(u_char rcode)
105 printf("\nFormat Error.");
107 printf("\nSever failure.");
109 printf("\nUnsupported request error.\n");
111 printf("\nRefused error.\n");
113 printf("\nActive error.\n");
115 printf("\nName in conflict error.\n");
117 printf("\n?%c?=%0x\n", '?', rcode);
125 /* Handling Name field */
127 AliasHandleName(u_char * p, char *pmax)
134 /* Following length field */
136 if (p == NULL || (char *)p >= pmax)
141 if ((char *)p > pmax)
143 return ((u_char *) p);
145 while ((*p & 0x3f) != 0x00) {
152 /* Get next length field */
153 p = (u_char *) (p + (*p & 0x3f) + 1);
154 if ((char *)p > pmax) {
163 c = (u_char) (((((*s & 0x0f) << 4) | (*(s + 1) & 0x0f)) - 0x11));
168 printf("<0x%02x>", c);
184 /* Set up to out of Name field */
185 if (p == NULL || (char *)p >= pmax)
189 return ((u_char *) p);
193 * NetBios Datagram Handler (IP/UDP)
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
206 struct ip *pip, /* IP packet to examine/patch */
207 struct alias_link *lnk,
208 struct in_addr *alias_address,
220 /* Calculate data length of UDP packet */
221 uh = (struct udphdr *)ip_next(pip);
222 pmax = (char *)uh + ntohs(uh->uh_ulen);
224 ndh = (NbtDataHeader *)udp_next(uh);
225 if ((char *)(ndh + 1) > pmax)
228 printf("\nType=%02x,", ndh->type);
231 case DGM_DIRECT_UNIQ:
232 case DGM_DIRECT_GROUP:
234 p = (u_char *) ndh + 14;
235 p = AliasHandleName(p, pmax); /* Source Name */
236 p = AliasHandleName(p, pmax); /* Destination Name */
239 p = (u_char *) ndh + 11;
242 case DGM_POSITIVE_RES:
243 case DGM_NEGATIVE_RES:
244 p = (u_char *) ndh + 10;
245 p = AliasHandleName(p, pmax); /* Destination Name */
248 if (p == NULL || (char *)p > pmax)
251 printf("%s:%d-->", inet_ntoa(ndh->source_ip), ntohs(ndh->source_port));
253 /* Doing an IP address and Port number Translation */
254 if (uh->uh_sum != 0) {
258 acc = ndh->source_port;
260 sptr = (u_short *) & (ndh->source_ip);
263 sptr = (u_short *) alias_address;
266 ADJUST_CHECKSUM(acc, uh->uh_sum);
268 ndh->source_ip = *alias_address;
269 ndh->source_port = alias_port;
271 printf("%s:%d\n", inet_ntoa(ndh->source_ip), ntohs(ndh->source_port));
274 return ((p == NULL) ? -1 : 0);
277 /* Question Section */
278 #define QS_TYPE_NB 0x0020
279 #define QS_TYPE_NBSTAT 0x0021
280 #define QS_CLAS_IN 0x0001
282 u_short type; /* The type of Request */
283 u_short class; /* The class of Request */
291 NBTArguments * nbtarg)
298 q = (NBTNsQuestion *) AliasHandleName((u_char *) q, pmax);
300 if (q == NULL || (char *)(q + 1) > pmax) {
304 /* Type and Class filed */
305 switch (ntohs(q->type)) {
312 printf("\nUnknown Type on Question %0x\n", ntohs(q->type));
319 /* Set up to out of Question Section */
320 return ((u_char *) q);
323 /* Resource Record */
324 #define RR_TYPE_A 0x0001
325 #define RR_TYPE_NS 0x0002
326 #define RR_TYPE_NULL 0x000a
327 #define RR_TYPE_NB 0x0020
328 #define RR_TYPE_NBSTAT 0x0021
329 #define RR_CLAS_IN 0x0001
330 #define SizeOfNsResource 8
338 #define SizeOfNsRNB 6
340 u_short g: 1 , ont:2, resv:13;
345 AliasHandleResourceNB(
348 NBTArguments * nbtarg)
353 if (q == NULL || (char *)(q + 1) > pmax)
355 /* Check out a length */
356 bcount = ntohs(q->rdlen);
358 /* Forward to Resource NB position */
359 nb = (NBTNsRNB *) ((u_char *) q + SizeOfNsResource);
361 /* Processing all in_addr array */
363 printf("NB rec[%s", inet_ntoa(nbtarg->oldaddr));
364 printf("->%s, %dbytes] ", inet_ntoa(nbtarg->newaddr), bcount);
366 while (nb != NULL && bcount != 0) {
367 if ((char *)(nb + 1) > pmax) {
372 printf("<%s>", inet_ntoa(nb->addr));
374 if (!bcmp(&nbtarg->oldaddr, &nb->addr, sizeof(struct in_addr))) {
375 if (*nbtarg->uh_sum != 0) {
379 sptr = (u_short *) & (nb->addr);
382 sptr = (u_short *) & (nbtarg->newaddr);
385 ADJUST_CHECKSUM(acc, *nbtarg->uh_sum);
387 nb->addr = nbtarg->newaddr;
397 nb = (NBTNsRNB *) ((u_char *) nb + SizeOfNsRNB);
398 bcount -= SizeOfNsRNB;
400 if (nb == NULL || (char *)(nb + 1) > pmax) {
403 return ((u_char *) nb);
406 #define SizeOfResourceA 6
412 AliasHandleResourceA(
415 NBTArguments * nbtarg)
420 if (q == NULL || (char *)(q + 1) > pmax)
423 /* Forward to Resource A position */
424 a = (NBTNsResourceA *) ((u_char *) q + sizeof(NBTNsResource));
426 /* Check out of length */
427 bcount = ntohs(q->rdlen);
429 /* Processing all in_addr array */
431 printf("Arec [%s", inet_ntoa(nbtarg->oldaddr));
432 printf("->%s]", inet_ntoa(nbtarg->newaddr));
434 while (bcount != 0) {
435 if (a == NULL || (char *)(a + 1) > pmax)
438 printf("..%s", inet_ntoa(a->addr));
440 if (!bcmp(&nbtarg->oldaddr, &a->addr, sizeof(struct in_addr))) {
441 if (*nbtarg->uh_sum != 0) {
445 sptr = (u_short *) & (a->addr); /* Old */
448 sptr = (u_short *) & nbtarg->newaddr; /* New */
451 ADJUST_CHECKSUM(acc, *nbtarg->uh_sum);
453 a->addr = nbtarg->newaddr;
456 bcount -= SizeOfResourceA;
458 if (a == NULL || (char *)(a + 1) > pmax)
460 return ((u_char *) a);
464 u_short opcode:4, flags:8, resv:4;
468 AliasHandleResourceNULL(
471 NBTArguments * nbtarg)
473 NBTNsResourceNULL *n;
478 if (q == NULL || (char *)(q + 1) > pmax)
481 /* Forward to Resource NULL position */
482 n = (NBTNsResourceNULL *) ((u_char *) q + sizeof(NBTNsResource));
484 /* Check out of length */
485 bcount = ntohs(q->rdlen);
487 /* Processing all in_addr array */
488 while (bcount != 0) {
489 if ((char *)(n + 1) > pmax) {
494 bcount -= sizeof(NBTNsResourceNULL);
496 if ((char *)(n + 1) > pmax)
499 return ((u_char *) n);
503 AliasHandleResourceNS(
506 NBTArguments * nbtarg)
508 NBTNsResourceNULL *n;
513 if (q == NULL || (char *)(q + 1) > pmax)
516 /* Forward to Resource NULL position */
517 n = (NBTNsResourceNULL *) ((u_char *) q + sizeof(NBTNsResource));
519 /* Check out of length */
520 bcount = ntohs(q->rdlen);
522 /* Resource Record Name Filed */
523 q = (NBTNsResource *) AliasHandleName((u_char *) n, pmax); /* XXX */
525 if (q == NULL || (char *)((u_char *) n + bcount) > pmax)
528 return ((u_char *) n + bcount);
533 } NBTNsResourceNBSTAT;
536 AliasHandleResourceNBSTAT(
539 NBTArguments * nbtarg)
541 NBTNsResourceNBSTAT *n;
546 if (q == NULL || (char *)(q + 1) > pmax)
549 /* Forward to Resource NBSTAT position */
550 n = (NBTNsResourceNBSTAT *) ((u_char *) q + sizeof(NBTNsResource));
552 /* Check out of length */
553 bcount = ntohs(q->rdlen);
555 if (q == NULL || (char *)((u_char *) n + bcount) > pmax)
558 return ((u_char *) n + bcount);
570 /* Resource Record Name Filed */
571 q = (NBTNsResource *) AliasHandleName((u_char *) q, pmax);
573 if (q == NULL || (char *)(q + 1) > pmax)
576 printf("type=%02x, count=%d\n", ntohs(q->type), count);
579 /* Type and Class filed */
580 switch (ntohs(q->type)) {
582 q = (NBTNsResource *) AliasHandleResourceNB(
589 q = (NBTNsResource *) AliasHandleResourceA(
596 q = (NBTNsResource *) AliasHandleResourceNS(
603 q = (NBTNsResource *) AliasHandleResourceNULL(
610 q = (NBTNsResource *) AliasHandleResourceNBSTAT(
619 "\nUnknown Type of Resource %0x\n",
628 return ((u_char *) q);
634 struct ip *pip, /* IP packet to examine/patch */
635 struct alias_link *lnk,
636 struct in_addr *alias_address,
637 u_short * alias_port,
638 struct in_addr *original_address,
639 u_short * original_port)
650 /* Set up Common Parameter */
651 nbtarg.oldaddr = *alias_address;
652 nbtarg.oldport = *alias_port;
653 nbtarg.newaddr = *original_address;
654 nbtarg.newport = *original_port;
656 /* Calculate data length of UDP packet */
657 uh = (struct udphdr *)ip_next(pip);
658 nbtarg.uh_sum = &(uh->uh_sum);
659 nsh = (NbtNSHeader *)udp_next(uh);
660 p = (u_char *) (nsh + 1);
661 pmax = (char *)uh + ntohs(uh->uh_ulen);
663 if ((char *)(nsh + 1) > pmax)
667 printf(" [%s] ID=%02x, op=%01x, flag=%02x, rcode=%01x, qd=%04x"
668 ", an=%04x, ns=%04x, ar=%04x, [%d]-->",
669 nsh->dir ? "Response" : "Request",
678 (u_char *) p - (u_char *) nsh
682 /* Question Entries */
683 if (ntohs(nsh->qdcount) != 0) {
684 p = AliasHandleQuestion(
691 /* Answer Resource Records */
692 if (ntohs(nsh->ancount) != 0) {
693 p = AliasHandleResource(
700 /* Authority Resource Recodrs */
701 if (ntohs(nsh->nscount) != 0) {
702 p = AliasHandleResource(
709 /* Additional Resource Recodrs */
710 if (ntohs(nsh->arcount) != 0) {
711 p = AliasHandleResource(
719 PrintRcode(nsh->rcode);
721 return ((p == NULL) ? -1 : 0);