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
27 * $FreeBSD: src/lib/libalias/alias_nbt.c,v 1.4.2.3 2001/08/01 09:52:26 obrien Exp $
28 * $DragonFly: src/lib/libalias/alias_nbt.c,v 1.4 2006/03/18 19:43:18 swildner Exp $
32 * oConsidering for word alignment for other platform.
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.
44 #include <sys/param.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
) {
131 /* Following length field */
133 if (p
== NULL
|| (char *)p
>= pmax
)
138 if ((char *)p
> pmax
)
140 return ((u_char
*)p
);
142 while ( ( *p
& 0x3f) != 0x00 ) {
149 /* Get next length field */
150 p
= (u_char
*)(p
+ (*p
& 0x3f) + 1);
151 if ((char *)p
> pmax
) {
159 if ( compress
== 1 ) {
161 c
= (u_char
)(((((*s
& 0x0f) << 4) | (*(s
+1) & 0x0f)) - 0x11));
165 printf("<0x%02x>", c
);
181 /* Set up to out of Name field */
182 if (p
== NULL
|| (char *)p
>= pmax
)
186 return ((u_char
*)p
);
190 * NetBios Datagram Handler (IP/UDP)
192 #define DGM_DIRECT_UNIQ 0x10
193 #define DGM_DIRECT_GROUP 0x11
194 #define DGM_BROADCAST 0x12
195 #define DGM_ERROR 0x13
196 #define DGM_QUERY 0x14
197 #define DGM_POSITIVE_RES 0x15
198 #define DGM_NEGATIVE_RES 0x16
200 int AliasHandleUdpNbt(
201 struct ip
*pip
, /* IP packet to examine/patch */
202 struct alias_link
*link
,
203 struct in_addr
*alias_address
,
211 /* Calculate data length of UDP packet */
212 uh
= (struct udphdr
*) ((char *) pip
+ (pip
->ip_hl
<< 2));
213 pmax
= (char *)uh
+ ntohs( uh
->uh_ulen
);
215 ndh
= (NbtDataHeader
*)((char *)uh
+ (sizeof (struct udphdr
)));
216 if ((char *)(ndh
+ 1) > pmax
)
219 printf("\nType=%02x,", ndh
->type
);
221 switch ( ndh
->type
) {
222 case DGM_DIRECT_UNIQ
:
223 case DGM_DIRECT_GROUP
:
225 p
= (u_char
*)ndh
+ 14;
226 p
= AliasHandleName ( p
, pmax
); /* Source Name */
227 p
= AliasHandleName ( p
, pmax
); /* Destination Name */
230 p
= (u_char
*)ndh
+ 11;
233 case DGM_POSITIVE_RES
:
234 case DGM_NEGATIVE_RES
:
235 p
= (u_char
*)ndh
+ 10;
236 p
= AliasHandleName ( p
, pmax
); /* Destination Name */
239 if (p
== NULL
|| (char *)p
> pmax
)
242 printf("%s:%d-->", inet_ntoa(ndh
->source_ip
), ntohs(ndh
->source_port
) );
244 /* Doing a IP address and Port number Translation */
245 if ( uh
->uh_sum
!= 0 ) {
248 acc
= ndh
->source_port
;
250 sptr
= (u_short
*) &(ndh
->source_ip
);
253 sptr
= (u_short
*) alias_address
;
256 ADJUST_CHECKSUM(acc
, uh
->uh_sum
);
258 ndh
->source_ip
= *alias_address
;
259 ndh
->source_port
= alias_port
;
261 printf("%s:%d\n", inet_ntoa(ndh
->source_ip
), ntohs(ndh
->source_port
) );
264 return((p
== NULL
) ? -1 : 0);
266 /* Question Section */
267 #define QS_TYPE_NB 0x0020
268 #define QS_TYPE_NBSTAT 0x0021
269 #define QS_CLAS_IN 0x0001
271 u_short type
; /* The type of Request */
272 u_short
class; /* The class of Request */
280 NBTArguments
*nbtarg
)
283 while ( count
!= 0 ) {
285 q
= (NBTNsQuestion
*)AliasHandleName((u_char
*)q
, pmax
);
287 if (q
== NULL
|| (char *)(q
+ 1) > pmax
) {
292 /* Type and Class filed */
293 switch ( ntohs(q
->type
) ) {
300 printf("\nUnknown Type on Question %0x\n", ntohs(q
->type
) );
307 /* Set up to out of Question Section */
308 return ((u_char
*)q
);
311 /* Resource Record */
312 #define RR_TYPE_A 0x0001
313 #define RR_TYPE_NS 0x0002
314 #define RR_TYPE_NULL 0x000a
315 #define RR_TYPE_NB 0x0020
316 #define RR_TYPE_NBSTAT 0x0021
317 #define RR_CLAS_IN 0x0001
318 #define SizeOfNsResource 8
326 #define SizeOfNsRNB 6
328 u_short g
:1, ont
:2, resv
:13;
333 AliasHandleResourceNB(
336 NBTArguments
*nbtarg
)
341 if (q
== NULL
|| (char *)(q
+ 1) > pmax
)
343 /* Check out a length */
344 bcount
= ntohs(q
->rdlen
);
346 /* Forward to Resource NB position */
347 nb
= (NBTNsRNB
*)((u_char
*)q
+ SizeOfNsResource
);
349 /* Processing all in_addr array */
351 printf("NB rec[%s", inet_ntoa(nbtarg
->oldaddr
));
352 printf("->%s, %dbytes] ",inet_ntoa(nbtarg
->newaddr
), bcount
);
354 while ( nb
!= NULL
&& bcount
!= 0 ) {
355 if ((char *)(nb
+ 1) > pmax
) {
360 printf("<%s>", inet_ntoa(nb
->addr
) );
362 if (!bcmp(&nbtarg
->oldaddr
,&nb
->addr
, sizeof(struct in_addr
) ) ) {
363 if ( *nbtarg
->uh_sum
!= 0 ) {
367 sptr
= (u_short
*) &(nb
->addr
);
370 sptr
= (u_short
*) &(nbtarg
->newaddr
);
373 ADJUST_CHECKSUM(acc
, *nbtarg
->uh_sum
);
376 nb
->addr
= nbtarg
->newaddr
;
386 nb
=(NBTNsRNB
*)((u_char
*)nb
+ SizeOfNsRNB
);
387 bcount
-= SizeOfNsRNB
;
389 if (nb
== NULL
|| (char *)(nb
+ 1) > pmax
) {
393 return ((u_char
*)nb
);
396 #define SizeOfResourceA 6
402 AliasHandleResourceA(
405 NBTArguments
*nbtarg
)
410 if (q
== NULL
|| (char *)(q
+ 1) > pmax
)
413 /* Forward to Resource A position */
414 a
= (NBTNsResourceA
*)( (u_char
*)q
+ sizeof(NBTNsResource
) );
416 /* Check out of length */
417 bcount
= ntohs(q
->rdlen
);
419 /* Processing all in_addr array */
421 printf("Arec [%s", inet_ntoa(nbtarg
->oldaddr
));
422 printf("->%s]",inet_ntoa(nbtarg
->newaddr
));
424 while ( bcount
!= 0 ) {
425 if (a
== NULL
|| (char *)(a
+ 1) > pmax
)
428 printf("..%s", inet_ntoa(a
->addr
) );
430 if ( !bcmp(&nbtarg
->oldaddr
, &a
->addr
, sizeof(struct in_addr
) ) ) {
431 if ( *nbtarg
->uh_sum
!= 0 ) {
435 sptr
= (u_short
*) &(a
->addr
); /* Old */
438 sptr
= (u_short
*) &nbtarg
->newaddr
; /* New */
441 ADJUST_CHECKSUM(acc
, *nbtarg
->uh_sum
);
444 a
->addr
= nbtarg
->newaddr
;
447 bcount
-= SizeOfResourceA
;
449 if (a
== NULL
|| (char *)(a
+ 1) > pmax
)
451 return ((u_char
*)a
);
455 u_short opcode
:4, flags
:8, resv
:4;
459 AliasHandleResourceNULL(
462 NBTArguments
*nbtarg
)
464 NBTNsResourceNULL
*n
;
467 if (q
== NULL
|| (char *)(q
+ 1) > pmax
)
470 /* Forward to Resource NULL position */
471 n
= (NBTNsResourceNULL
*)( (u_char
*)q
+ sizeof(NBTNsResource
) );
473 /* Check out of length */
474 bcount
= ntohs(q
->rdlen
);
476 /* Processing all in_addr array */
477 while ( bcount
!= 0 ) {
478 if ((char *)(n
+ 1) > pmax
) {
483 bcount
-= sizeof(NBTNsResourceNULL
);
485 if ((char *)(n
+ 1) > pmax
)
488 return ((u_char
*)n
);
492 AliasHandleResourceNS(
495 NBTArguments
*nbtarg
)
497 NBTNsResourceNULL
*n
;
500 if (q
== NULL
|| (char *)(q
+ 1) > pmax
)
503 /* Forward to Resource NULL position */
504 n
= (NBTNsResourceNULL
*)( (u_char
*)q
+ sizeof(NBTNsResource
) );
506 /* Check out of length */
507 bcount
= ntohs(q
->rdlen
);
509 /* Resource Record Name Filed */
510 q
= (NBTNsResource
*)AliasHandleName( (u_char
*)n
, pmax
); /* XXX */
512 if (q
== NULL
|| (char *)((u_char
*)n
+ bcount
) > pmax
)
515 return ((u_char
*)n
+ bcount
);
520 } NBTNsResourceNBSTAT
;
523 AliasHandleResourceNBSTAT(
526 NBTArguments
*nbtarg
)
528 NBTNsResourceNBSTAT
*n
;
531 if (q
== NULL
|| (char *)(q
+ 1) > pmax
)
534 /* Forward to Resource NBSTAT position */
535 n
= (NBTNsResourceNBSTAT
*)( (u_char
*)q
+ sizeof(NBTNsResource
) );
537 /* Check out of length */
538 bcount
= ntohs(q
->rdlen
);
540 if (q
== NULL
|| (char *)((u_char
*)n
+ bcount
) > pmax
)
543 return ((u_char
*)n
+ bcount
);
554 while ( count
!= 0 ) {
555 /* Resource Record Name Filed */
556 q
= (NBTNsResource
*)AliasHandleName( (u_char
*)q
, pmax
);
558 if (q
== NULL
|| (char *)(q
+ 1) > pmax
)
561 printf("type=%02x, count=%d\n", ntohs(q
->type
), count
);
564 /* Type and Class filed */
565 switch ( ntohs(q
->type
) ) {
567 q
= (NBTNsResource
*)AliasHandleResourceNB(
574 q
= (NBTNsResource
*)AliasHandleResourceA(
581 q
= (NBTNsResource
*)AliasHandleResourceNS(
588 q
= (NBTNsResource
*)AliasHandleResourceNULL(
595 q
= (NBTNsResource
*)AliasHandleResourceNBSTAT(
604 "\nUnknown Type of Resource %0x\n",
613 return ((u_char
*)q
);
616 int AliasHandleUdpNbtNS(
617 struct ip
*pip
, /* IP packet to examine/patch */
618 struct alias_link
*link
,
619 struct in_addr
*alias_address
,
621 struct in_addr
*original_address
,
622 u_short
*original_port
)
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
;
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
);
643 if ((char *)(nsh
+ 1) > pmax
)
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",
658 (u_char
*)p
-(u_char
*)nsh
662 /* Question Entries */
663 if (ntohs(nsh
->qdcount
) !=0 ) {
664 p
= AliasHandleQuestion(
672 /* Answer Resource Records */
673 if (ntohs(nsh
->ancount
) !=0 ) {
674 p
= AliasHandleResource(
682 /* Authority Resource Recodrs */
683 if (ntohs(nsh
->nscount
) !=0 ) {
684 p
= AliasHandleResource(
692 /* Additional Resource Recodrs */
693 if (ntohs(nsh
->arcount
) !=0 ) {
694 p
= AliasHandleResource(
703 PrintRcode(nsh
->rcode
);
705 return ((p
== NULL
) ? -1 : 0);