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.
45 #include <sys/param.h>
46 #include <sys/ctype.h>
47 #include <sys/libkern.h>
49 #include <sys/types.h>
53 #include <arpa/inet.h>
56 #include <netinet/in_systm.h>
57 #include <netinet/in.h>
58 #include <netinet/ip.h>
59 #include <netinet/udp.h>
60 #include <netinet/tcp.h>
63 #include <netinet/libalias/alias.h>
64 #include <netinet/libalias/alias_local.h>
66 #include "alias_local.h"
70 struct in_addr oldaddr;
72 struct in_addr newaddr;
81 struct in_addr source_ip;
95 u_short dir: 1, opcode:4, nmflags:7, rcode:4;
110 #ifdef LIBALIAS_DEBUG
112 PrintRcode(u_char rcode)
117 printf("\nFormat Error.");
119 printf("\nSever failure.");
121 printf("\nUnsupported request error.\n");
123 printf("\nRefused error.\n");
125 printf("\nActive error.\n");
127 printf("\nName in conflict error.\n");
129 printf("\n?%c?=%0x\n", '?', rcode);
137 /* Handling Name field */
139 AliasHandleName(u_char * p, char *pmax)
146 /* Following length field */
148 if (p == NULL || (char *)p >= pmax)
153 if ((char *)p > pmax)
155 return ((u_char *) p);
157 while ((*p & 0x3f) != 0x00) {
164 /* Get next length field */
165 p = (u_char *) (p + (*p & 0x3f) + 1);
166 if ((char *)p > pmax) {
170 #ifdef LIBALIAS_DEBUG
175 c = (u_char) (((((*s & 0x0f) << 4) | (*(s + 1) & 0x0f)) - 0x11));
176 #ifdef LIBALIAS_DEBUG
180 printf("<0x%02x>", c);
184 #ifdef LIBALIAS_DEBUG
190 #ifdef LIBALIAS_DEBUG
196 /* Set up to out of Name field */
197 if (p == NULL || (char *)p >= pmax)
201 return ((u_char *) p);
205 * NetBios Datagram Handler (IP/UDP)
207 #define DGM_DIRECT_UNIQ 0x10
208 #define DGM_DIRECT_GROUP 0x11
209 #define DGM_BROADCAST 0x12
210 #define DGM_ERROR 0x13
211 #define DGM_QUERY 0x14
212 #define DGM_POSITIVE_RES 0x15
213 #define DGM_NEGATIVE_RES 0x16
218 struct ip *pip, /* IP packet to examine/patch */
219 struct alias_link *lnk,
220 struct in_addr *alias_address,
232 /* Calculate data length of UDP packet */
233 uh = (struct udphdr *)ip_next(pip);
234 pmax = (char *)uh + ntohs(uh->uh_ulen);
236 ndh = (NbtDataHeader *)udp_next(uh);
237 if ((char *)(ndh + 1) > pmax)
239 #ifdef LIBALIAS_DEBUG
240 printf("\nType=%02x,", ndh->type);
243 case DGM_DIRECT_UNIQ:
244 case DGM_DIRECT_GROUP:
246 p = (u_char *) ndh + 14;
247 p = AliasHandleName(p, pmax); /* Source Name */
248 p = AliasHandleName(p, pmax); /* Destination Name */
251 p = (u_char *) ndh + 11;
254 case DGM_POSITIVE_RES:
255 case DGM_NEGATIVE_RES:
256 p = (u_char *) ndh + 10;
257 p = AliasHandleName(p, pmax); /* Destination Name */
260 if (p == NULL || (char *)p > pmax)
262 #ifdef LIBALIAS_DEBUG
263 printf("%s:%d-->", inet_ntoa(ndh->source_ip), ntohs(ndh->source_port));
265 /* Doing an IP address and Port number Translation */
266 if (uh->uh_sum != 0) {
270 acc = ndh->source_port;
272 sptr = (u_short *) & (ndh->source_ip);
275 sptr = (u_short *) alias_address;
278 ADJUST_CHECKSUM(acc, uh->uh_sum);
280 ndh->source_ip = *alias_address;
281 ndh->source_port = alias_port;
282 #ifdef LIBALIAS_DEBUG
283 printf("%s:%d\n", inet_ntoa(ndh->source_ip), ntohs(ndh->source_port));
286 return ((p == NULL) ? -1 : 0);
289 /* Question Section */
290 #define QS_TYPE_NB 0x0020
291 #define QS_TYPE_NBSTAT 0x0021
292 #define QS_CLAS_IN 0x0001
294 u_short type; /* The type of Request */
295 u_short class; /* The class of Request */
303 NBTArguments * nbtarg)
310 q = (NBTNsQuestion *) AliasHandleName((u_char *) q, pmax);
312 if (q == NULL || (char *)(q + 1) > pmax) {
316 /* Type and Class filed */
317 switch (ntohs(q->type)) {
323 #ifdef LIBALIAS_DEBUG
324 printf("\nUnknown Type on Question %0x\n", ntohs(q->type));
331 /* Set up to out of Question Section */
332 return ((u_char *) q);
335 /* Resource Record */
336 #define RR_TYPE_A 0x0001
337 #define RR_TYPE_NS 0x0002
338 #define RR_TYPE_NULL 0x000a
339 #define RR_TYPE_NB 0x0020
340 #define RR_TYPE_NBSTAT 0x0021
341 #define RR_CLAS_IN 0x0001
342 #define SizeOfNsResource 8
350 #define SizeOfNsRNB 6
352 u_short g: 1 , ont:2, resv:13;
357 AliasHandleResourceNB(
360 NBTArguments * nbtarg)
365 if (q == NULL || (char *)(q + 1) > pmax)
367 /* Check out a length */
368 bcount = ntohs(q->rdlen);
370 /* Forward to Resource NB position */
371 nb = (NBTNsRNB *) ((u_char *) q + SizeOfNsResource);
373 /* Processing all in_addr array */
374 #ifdef LIBALIAS_DEBUG
375 printf("NB rec[%s", inet_ntoa(nbtarg->oldaddr));
376 printf("->%s, %dbytes] ", inet_ntoa(nbtarg->newaddr), bcount);
378 while (nb != NULL && bcount != 0) {
379 if ((char *)(nb + 1) > pmax) {
383 #ifdef LIBALIAS_DEBUG
384 printf("<%s>", inet_ntoa(nb->addr));
386 if (!bcmp(&nbtarg->oldaddr, &nb->addr, sizeof(struct in_addr))) {
387 if (*nbtarg->uh_sum != 0) {
391 sptr = (u_short *) & (nb->addr);
394 sptr = (u_short *) & (nbtarg->newaddr);
397 ADJUST_CHECKSUM(acc, *nbtarg->uh_sum);
399 nb->addr = nbtarg->newaddr;
400 #ifdef LIBALIAS_DEBUG
404 #ifdef LIBALIAS_DEBUG
409 nb = (NBTNsRNB *) ((u_char *) nb + SizeOfNsRNB);
410 bcount -= SizeOfNsRNB;
412 if (nb == NULL || (char *)(nb + 1) > pmax) {
415 return ((u_char *) nb);
418 #define SizeOfResourceA 6
424 AliasHandleResourceA(
427 NBTArguments * nbtarg)
432 if (q == NULL || (char *)(q + 1) > pmax)
435 /* Forward to Resource A position */
436 a = (NBTNsResourceA *) ((u_char *) q + sizeof(NBTNsResource));
438 /* Check out of length */
439 bcount = ntohs(q->rdlen);
441 /* Processing all in_addr array */
442 #ifdef LIBALIAS_DEBUG
443 printf("Arec [%s", inet_ntoa(nbtarg->oldaddr));
444 printf("->%s]", inet_ntoa(nbtarg->newaddr));
446 while (bcount != 0) {
447 if (a == NULL || (char *)(a + 1) > pmax)
449 #ifdef LIBALIAS_DEBUG
450 printf("..%s", inet_ntoa(a->addr));
452 if (!bcmp(&nbtarg->oldaddr, &a->addr, sizeof(struct in_addr))) {
453 if (*nbtarg->uh_sum != 0) {
457 sptr = (u_short *) & (a->addr); /* Old */
460 sptr = (u_short *) & nbtarg->newaddr; /* New */
463 ADJUST_CHECKSUM(acc, *nbtarg->uh_sum);
465 a->addr = nbtarg->newaddr;
468 bcount -= SizeOfResourceA;
470 if (a == NULL || (char *)(a + 1) > pmax)
472 return ((u_char *) a);
476 u_short opcode:4, flags:8, resv:4;
480 AliasHandleResourceNULL(
483 NBTArguments * nbtarg)
485 NBTNsResourceNULL *n;
490 if (q == NULL || (char *)(q + 1) > pmax)
493 /* Forward to Resource NULL position */
494 n = (NBTNsResourceNULL *) ((u_char *) q + sizeof(NBTNsResource));
496 /* Check out of length */
497 bcount = ntohs(q->rdlen);
499 /* Processing all in_addr array */
500 while (bcount != 0) {
501 if ((char *)(n + 1) > pmax) {
506 bcount -= sizeof(NBTNsResourceNULL);
508 if ((char *)(n + 1) > pmax)
511 return ((u_char *) n);
515 AliasHandleResourceNS(
518 NBTArguments * nbtarg)
520 NBTNsResourceNULL *n;
525 if (q == NULL || (char *)(q + 1) > pmax)
528 /* Forward to Resource NULL position */
529 n = (NBTNsResourceNULL *) ((u_char *) q + sizeof(NBTNsResource));
531 /* Check out of length */
532 bcount = ntohs(q->rdlen);
534 /* Resource Record Name Filed */
535 q = (NBTNsResource *) AliasHandleName((u_char *) n, pmax); /* XXX */
537 if (q == NULL || (char *)((u_char *) n + bcount) > pmax)
540 return ((u_char *) n + bcount);
545 } NBTNsResourceNBSTAT;
548 AliasHandleResourceNBSTAT(
551 NBTArguments * nbtarg)
553 NBTNsResourceNBSTAT *n;
558 if (q == NULL || (char *)(q + 1) > pmax)
561 /* Forward to Resource NBSTAT position */
562 n = (NBTNsResourceNBSTAT *) ((u_char *) q + sizeof(NBTNsResource));
564 /* Check out of length */
565 bcount = ntohs(q->rdlen);
567 if (q == NULL || (char *)((u_char *) n + bcount) > pmax)
570 return ((u_char *) n + bcount);
582 /* Resource Record Name Filed */
583 q = (NBTNsResource *) AliasHandleName((u_char *) q, pmax);
585 if (q == NULL || (char *)(q + 1) > pmax)
587 #ifdef LIBALIAS_DEBUG
588 printf("type=%02x, count=%d\n", ntohs(q->type), count);
591 /* Type and Class filed */
592 switch (ntohs(q->type)) {
594 q = (NBTNsResource *) AliasHandleResourceNB(
601 q = (NBTNsResource *) AliasHandleResourceA(
608 q = (NBTNsResource *) AliasHandleResourceNS(
615 q = (NBTNsResource *) AliasHandleResourceNULL(
622 q = (NBTNsResource *) AliasHandleResourceNBSTAT(
629 #ifdef LIBALIAS_DEBUG
631 "\nUnknown Type of Resource %0x\n",
640 return ((u_char *) q);
646 struct ip *pip, /* IP packet to examine/patch */
647 struct alias_link *lnk,
648 struct in_addr *alias_address,
649 u_short * alias_port,
650 struct in_addr *original_address,
651 u_short * original_port)
662 /* Set up Common Parameter */
663 nbtarg.oldaddr = *alias_address;
664 nbtarg.oldport = *alias_port;
665 nbtarg.newaddr = *original_address;
666 nbtarg.newport = *original_port;
668 /* Calculate data length of UDP packet */
669 uh = (struct udphdr *)ip_next(pip);
670 nbtarg.uh_sum = &(uh->uh_sum);
671 nsh = (NbtNSHeader *)udp_next(uh);
672 p = (u_char *) (nsh + 1);
673 pmax = (char *)uh + ntohs(uh->uh_ulen);
675 if ((char *)(nsh + 1) > pmax)
678 #ifdef LIBALIAS_DEBUG
679 printf(" [%s] ID=%02x, op=%01x, flag=%02x, rcode=%01x, qd=%04x"
680 ", an=%04x, ns=%04x, ar=%04x, [%d]-->",
681 nsh->dir ? "Response" : "Request",
690 (u_char *) p - (u_char *) nsh
694 /* Question Entries */
695 if (ntohs(nsh->qdcount) != 0) {
696 p = AliasHandleQuestion(
703 /* Answer Resource Records */
704 if (ntohs(nsh->ancount) != 0) {
705 p = AliasHandleResource(
712 /* Authority Resource Recodrs */
713 if (ntohs(nsh->nscount) != 0) {
714 p = AliasHandleResource(
721 /* Additional Resource Recodrs */
722 if (ntohs(nsh->arcount) != 0) {
723 p = AliasHandleResource(
730 #ifdef LIBALIAS_DEBUG
731 PrintRcode(nsh->rcode);
733 return ((p == NULL) ? -1 : 0);