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;
99 static void PrintRcode( u_char rcode ) {
103 printf("\nFormat Error.");
105 printf("\nSever failure.");
107 printf("\nUnsupported request error.\n");
109 printf("\nRefused error.\n");
111 printf("\nActive error.\n");
113 printf("\nName in conflict error.\n");
115 printf("\n???=%0x\n", rcode );
122 /* Handling Name field */
123 static u_char *AliasHandleName ( u_char *p, char *pmax ) {
129 /* Following length field */
131 if (p == NULL || (char *)p >= pmax)
136 if ((char *)p > pmax)
138 return ((u_char *)p);
140 while ( ( *p & 0x3f) != 0x00 ) {
147 /* Get next length field */
148 p = (u_char *)(p + (*p & 0x3f) + 1);
149 if ((char *)p > pmax) {
157 if ( compress == 1 ) {
158 c = (u_char )(((((*s & 0x0f) << 4) | (*(s+1) & 0x0f)) - 0x11));
163 printf("<0x%02x>", c );
179 /* Set up to out of Name field */
180 if (p == NULL || (char *)p >= pmax)
184 return ((u_char *)p);
188 * NetBios Datagram Handler (IP/UDP)
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
198 int AliasHandleUdpNbt(
199 struct ip *pip, /* IP packet to examine/patch */
200 struct alias_link *link,
201 struct in_addr *alias_address,
209 /* Calculate data length of UDP packet */
210 uh = (struct udphdr *) ((char *) pip + (pip->ip_hl << 2));
211 pmax = (char *)uh + ntohs( uh->uh_ulen );
213 ndh = (NbtDataHeader *)((char *)uh + (sizeof (struct udphdr)));
214 if ((char *)(ndh + 1) > pmax)
217 printf("\nType=%02x,", ndh->type );
219 switch ( ndh->type ) {
220 case DGM_DIRECT_UNIQ:
221 case DGM_DIRECT_GROUP:
223 p = (u_char *)ndh + 14;
224 p = AliasHandleName ( p, pmax ); /* Source Name */
225 p = AliasHandleName ( p, pmax ); /* Destination Name */
228 p = (u_char *)ndh + 11;
231 case DGM_POSITIVE_RES:
232 case DGM_NEGATIVE_RES:
233 p = (u_char *)ndh + 10;
234 p = AliasHandleName ( p, pmax ); /* Destination Name */
237 if (p == NULL || (char *)p > pmax)
240 printf("%s:%d-->", inet_ntoa(ndh->source_ip), ntohs(ndh->source_port) );
242 /* Doing a IP address and Port number Translation */
243 if ( uh->uh_sum != 0 ) {
246 acc = ndh->source_port;
248 sptr = (u_short *) &(ndh->source_ip);
251 sptr = (u_short *) alias_address;
254 ADJUST_CHECKSUM(acc, uh->uh_sum);
256 ndh->source_ip = *alias_address;
257 ndh->source_port = alias_port;
259 printf("%s:%d\n", inet_ntoa(ndh->source_ip), ntohs(ndh->source_port) );
262 return((p == NULL) ? -1 : 0);
264 /* Question Section */
265 #define QS_TYPE_NB 0x0020
266 #define QS_TYPE_NBSTAT 0x0021
267 #define QS_CLAS_IN 0x0001
269 u_short type; /* The type of Request */
270 u_short class; /* The class of Request */
278 NBTArguments *nbtarg)
281 while ( count != 0 ) {
283 q = (NBTNsQuestion *)AliasHandleName((u_char *)q, pmax);
285 if (q == NULL || (char *)(q + 1) > pmax) {
290 /* Type and Class filed */
291 switch ( ntohs(q->type) ) {
298 printf("\nUnknown Type on Question %0x\n", ntohs(q->type) );
305 /* Set up to out of Question Section */
306 return ((u_char *)q);
309 /* Resource Record */
310 #define RR_TYPE_A 0x0001
311 #define RR_TYPE_NS 0x0002
312 #define RR_TYPE_NULL 0x000a
313 #define RR_TYPE_NB 0x0020
314 #define RR_TYPE_NBSTAT 0x0021
315 #define RR_CLAS_IN 0x0001
316 #define SizeOfNsResource 8
324 #define SizeOfNsRNB 6
326 u_short g:1, ont:2, resv:13;
331 AliasHandleResourceNB(
334 NBTArguments *nbtarg)
339 if (q == NULL || (char *)(q + 1) > pmax)
341 /* Check out a length */
342 bcount = ntohs(q->rdlen);
344 /* Forward to Resource NB position */
345 nb = (NBTNsRNB *)((u_char *)q + SizeOfNsResource);
347 /* Processing all in_addr array */
349 printf("NB rec[%s", inet_ntoa(nbtarg->oldaddr));
350 printf("->%s, %dbytes] ",inet_ntoa(nbtarg->newaddr ), bcount);
352 while ( nb != NULL && bcount != 0 ) {
353 if ((char *)(nb + 1) > pmax) {
358 printf("<%s>", inet_ntoa(nb->addr) );
360 if (!bcmp(&nbtarg->oldaddr,&nb->addr, sizeof(struct in_addr) ) ) {
361 if ( *nbtarg->uh_sum != 0 ) {
365 sptr = (u_short *) &(nb->addr);
368 sptr = (u_short *) &(nbtarg->newaddr);
371 ADJUST_CHECKSUM(acc, *nbtarg->uh_sum);
374 nb->addr = nbtarg->newaddr;
384 nb=(NBTNsRNB *)((u_char *)nb + SizeOfNsRNB);
385 bcount -= SizeOfNsRNB;
387 if (nb == NULL || (char *)(nb + 1) > pmax) {
391 return ((u_char *)nb);
394 #define SizeOfResourceA 6
400 AliasHandleResourceA(
403 NBTArguments *nbtarg)
408 if (q == NULL || (char *)(q + 1) > pmax)
411 /* Forward to Resource A position */
412 a = (NBTNsResourceA *)( (u_char *)q + sizeof(NBTNsResource) );
414 /* Check out of length */
415 bcount = ntohs(q->rdlen);
417 /* Processing all in_addr array */
419 printf("Arec [%s", inet_ntoa(nbtarg->oldaddr));
420 printf("->%s]",inet_ntoa(nbtarg->newaddr ));
422 while ( bcount != 0 ) {
423 if (a == NULL || (char *)(a + 1) > pmax)
426 printf("..%s", inet_ntoa(a->addr) );
428 if ( !bcmp(&nbtarg->oldaddr, &a->addr, sizeof(struct in_addr) ) ) {
429 if ( *nbtarg->uh_sum != 0 ) {
433 sptr = (u_short *) &(a->addr); /* Old */
436 sptr = (u_short *) &nbtarg->newaddr; /* New */
439 ADJUST_CHECKSUM(acc, *nbtarg->uh_sum);
442 a->addr = nbtarg->newaddr;
445 bcount -= SizeOfResourceA;
447 if (a == NULL || (char *)(a + 1) > pmax)
449 return ((u_char *)a);
453 u_short opcode:4, flags:8, resv:4;
457 AliasHandleResourceNULL(
460 NBTArguments *nbtarg)
462 NBTNsResourceNULL *n;
465 if (q == NULL || (char *)(q + 1) > pmax)
468 /* Forward to Resource NULL position */
469 n = (NBTNsResourceNULL *)( (u_char *)q + sizeof(NBTNsResource) );
471 /* Check out of length */
472 bcount = ntohs(q->rdlen);
474 /* Processing all in_addr array */
475 while ( bcount != 0 ) {
476 if ((char *)(n + 1) > pmax) {
481 bcount -= sizeof(NBTNsResourceNULL);
483 if ((char *)(n + 1) > pmax)
486 return ((u_char *)n);
490 AliasHandleResourceNS(
493 NBTArguments *nbtarg)
495 NBTNsResourceNULL *n;
498 if (q == NULL || (char *)(q + 1) > pmax)
501 /* Forward to Resource NULL position */
502 n = (NBTNsResourceNULL *)( (u_char *)q + sizeof(NBTNsResource) );
504 /* Check out of length */
505 bcount = ntohs(q->rdlen);
507 /* Resource Record Name Filed */
508 q = (NBTNsResource *)AliasHandleName( (u_char *)n, pmax ); /* XXX */
510 if (q == NULL || (char *)((u_char *)n + bcount) > pmax)
513 return ((u_char *)n + bcount);
518 } NBTNsResourceNBSTAT;
521 AliasHandleResourceNBSTAT(
524 NBTArguments *nbtarg)
526 NBTNsResourceNBSTAT *n;
529 if (q == NULL || (char *)(q + 1) > pmax)
532 /* Forward to Resource NBSTAT position */
533 n = (NBTNsResourceNBSTAT *)( (u_char *)q + sizeof(NBTNsResource) );
535 /* Check out of length */
536 bcount = ntohs(q->rdlen);
538 if (q == NULL || (char *)((u_char *)n + bcount) > pmax)
541 return ((u_char *)n + bcount);
552 while ( count != 0 ) {
553 /* Resource Record Name Filed */
554 q = (NBTNsResource *)AliasHandleName( (u_char *)q, pmax );
556 if (q == NULL || (char *)(q + 1) > pmax)
559 printf("type=%02x, count=%d\n", ntohs(q->type), count );
562 /* Type and Class filed */
563 switch ( ntohs(q->type) ) {
565 q = (NBTNsResource *)AliasHandleResourceNB(
572 q = (NBTNsResource *)AliasHandleResourceA(
579 q = (NBTNsResource *)AliasHandleResourceNS(
586 q = (NBTNsResource *)AliasHandleResourceNULL(
593 q = (NBTNsResource *)AliasHandleResourceNBSTAT(
602 "\nUnknown Type of Resource %0x\n",
611 return ((u_char *)q);
614 int AliasHandleUdpNbtNS(
615 struct ip *pip, /* IP packet to examine/patch */
616 struct alias_link *link,
617 struct in_addr *alias_address,
619 struct in_addr *original_address,
620 u_short *original_port )
628 /* Set up Common Parameter */
629 nbtarg.oldaddr = *alias_address;
630 nbtarg.oldport = *alias_port;
631 nbtarg.newaddr = *original_address;
632 nbtarg.newport = *original_port;
634 /* Calculate data length of UDP packet */
635 uh = (struct udphdr *) ((char *) pip + (pip->ip_hl << 2));
636 nbtarg.uh_sum = &(uh->uh_sum);
637 nsh = (NbtNSHeader *)((char *)uh + (sizeof(struct udphdr)));
638 p = (u_char *)(nsh + 1);
639 pmax = (char *)uh + ntohs( uh->uh_ulen );
641 if ((char *)(nsh + 1) > pmax)
645 printf(" [%s] ID=%02x, op=%01x, flag=%02x, rcode=%01x, qd=%04x"
646 ", an=%04x, ns=%04x, ar=%04x, [%d]-->",
647 nsh->dir ? "Response": "Request",
656 (u_char *)p -(u_char *)nsh
660 /* Question Entries */
661 if (ntohs(nsh->qdcount) !=0 ) {
662 p = AliasHandleQuestion(
670 /* Answer Resource Records */
671 if (ntohs(nsh->ancount) !=0 ) {
672 p = AliasHandleResource(
680 /* Authority Resource Recodrs */
681 if (ntohs(nsh->nscount) !=0 ) {
682 p = AliasHandleResource(
690 /* Additional Resource Recodrs */
691 if (ntohs(nsh->arcount) !=0 ) {
692 p = AliasHandleResource(
701 PrintRcode(nsh->rcode);
703 return ((p == NULL) ? -1 : 0);