alias_nbt.c revision 77696
177696Sbrian/*-
236321Samurai * Written by Atsushi Murai <amurai@spec.co.jp>
377696Sbrian * Copyright (c) 1998, System Planning and Engineering Co.
477696Sbrian * All rights reserved.
536321Samurai *
677696Sbrian * Redistribution and use in source and binary forms, with or without
777696Sbrian * modification, are permitted provided that the following conditions
877696Sbrian * are met:
977696Sbrian * 1. Redistributions of source code must retain the above copyright
1077696Sbrian *    notice, this list of conditions and the following disclaimer.
1177696Sbrian * 2. Redistributions in binary form must reproduce the above copyright
1277696Sbrian *    notice, this list of conditions and the following disclaimer in the
1377696Sbrian *    documentation and/or other materials provided with the distribution.
1436321Samurai *
1577696Sbrian * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1677696Sbrian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1777696Sbrian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1877696Sbrian * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1977696Sbrian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2077696Sbrian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2177696Sbrian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2277696Sbrian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2377696Sbrian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2477696Sbrian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2577696Sbrian * SUCH DAMAGE.
2636321Samurai *
2750476Speter * $FreeBSD: head/sys/netinet/libalias/alias_nbt.c 77696 2001-06-04 14:52:17Z brian $
2836321Samurai *
2936321Samurai *  TODO:
3036321Samurai *       oClean up.
3136321Samurai *       oConsidering for word alignment for other platform.
3236321Samurai */
3336321Samurai/*
3436321Samurai    alias_nbt.c performs special processing for NetBios over TCP/IP
3536321Samurai    sessions by UDP.
3636321Samurai
3736321Samurai    Initial version:  May, 1998  (Atsushi Murai <amurai@spec.co.jp>)
3836321Samurai
3936321Samurai    See HISTORY file for record of revisions.
4036321Samurai*/
4136321Samurai
4236321Samurai/* Includes */
4336321Samurai#include <ctype.h>
4436321Samurai#include <stdio.h>
4536321Samurai#include <string.h>
4636321Samurai#include <sys/types.h>
4736321Samurai#include <netinet/in_systm.h>
4836321Samurai#include <netinet/in.h>
4936321Samurai#include <arpa/inet.h>
5036321Samurai#include <netinet/ip.h>
5136321Samurai#include <netinet/udp.h>
5236321Samurai#include <netinet/tcp.h>
5336321Samurai
5436321Samurai#include "alias_local.h"
5536321Samurai
5636321Samuraitypedef struct {
5736321Samurai	struct in_addr		oldaddr;
5836321Samurai	u_short 			oldport;
5936321Samurai	struct in_addr		newaddr;
6036321Samurai	u_short 			newport;
6136321Samurai	u_short 			*uh_sum;
6236321Samurai} NBTArguments;
6336321Samurai
6436321Samuraitypedef struct {
6536321Samurai	unsigned char   type;
6636321Samurai	unsigned char   flags;
6736321Samurai	u_short  		id;
6836321Samurai	struct in_addr  source_ip;
6936321Samurai	u_short			source_port;
7036321Samurai	u_short			len;
7136321Samurai	u_short			offset;
7236321Samurai} NbtDataHeader;
7336321Samurai
7436321Samurai#define OpQuery		0
7536321Samurai#define OpUnknown	4
7636321Samurai#define OpRegist	5
7736321Samurai#define OpRelease	6
7836321Samurai#define OpWACK		7
7936321Samurai#define OpRefresh	8
8036321Samuraitypedef struct {
8136321Samurai	u_short			nametrid;
8236321Samurai	u_short 		dir:1, opcode:4, nmflags:7, rcode:4;
8336321Samurai	u_short			qdcount;
8436321Samurai	u_short			ancount;
8536321Samurai	u_short			nscount;
8636321Samurai	u_short			arcount;
8736321Samurai} NbtNSHeader;
8836321Samurai
8936321Samurai#define FMT_ERR		0x1
9036321Samurai#define SRV_ERR		0x2
9136321Samurai#define IMP_ERR		0x4
9236321Samurai#define RFS_ERR		0x5
9336321Samurai#define ACT_ERR		0x6
9436321Samurai#define CFT_ERR		0x7
9536321Samurai
9636321Samurai
9744616Sbrian#ifdef DEBUG
9844616Sbrianstatic void PrintRcode( u_char rcode )  {
9936321Samurai
10036321Samurai	switch (rcode) {
10136321Samurai		case FMT_ERR:
10236321Samurai			printf("\nFormat Error.");
10336321Samurai		case SRV_ERR:
10436321Samurai			printf("\nSever failure.");
10536321Samurai		case IMP_ERR:
10636321Samurai			printf("\nUnsupported request error.\n");
10736321Samurai		case RFS_ERR:
10836321Samurai			printf("\nRefused error.\n");
10936321Samurai		case ACT_ERR:
11036321Samurai			printf("\nActive error.\n");
11136321Samurai		case CFT_ERR:
11236321Samurai			printf("\nName in conflict error.\n");
11336321Samurai		default:
11436321Samurai			printf("\n???=%0x\n", rcode );
11536321Samurai
11636321Samurai	}
11736321Samurai}
11844616Sbrian#endif
11936321Samurai
12036321Samurai
12136321Samurai/* Handling Name field */
12244616Sbrianstatic u_char *AliasHandleName ( u_char *p, char *pmax ) {
12336321Samurai
12436321Samurai	u_char *s;
12536321Samurai	u_char c;
12636321Samurai	int		compress;
12736321Samurai
12836321Samurai	/* Following length field */
12941759Sdillon
13041759Sdillon	if (p == NULL || (char *)p >= pmax)
13141759Sdillon		return(NULL);
13241759Sdillon
13336321Samurai	if (*p & 0xc0 ) {
13436321Samurai		p = p + 2;
13541759Sdillon		if ((char *)p > pmax)
13641759Sdillon			return(NULL);
13736321Samurai		return ((u_char *)p);
13836321Samurai	}
13936321Samurai	while ( ( *p & 0x3f) != 0x00 ) {
14036321Samurai		s = p + 1;
14136321Samurai		if ( *p == 0x20 )
14236321Samurai			compress = 1;
14336321Samurai		else
14436321Samurai			compress = 0;
14536321Samurai
14636321Samurai	 	/* Get next length field */
14736321Samurai		p = (u_char *)(p + (*p & 0x3f) + 1);
14841759Sdillon		if ((char *)p > pmax) {
14941759Sdillon			p = NULL;
15041759Sdillon			break;
15141759Sdillon		}
15236321Samurai#ifdef DEBUG
15336321Samurai		printf(":");
15436321Samurai#endif
15536321Samurai		while (s < p) {
15636321Samurai			if ( compress == 1 ) {
15736321Samurai				c = (u_char )(((((*s & 0x0f) << 4) | (*(s+1) & 0x0f)) - 0x11));
15836321Samurai#ifdef DEBUG
15936321Samurai				if (isprint( c ) )
16036321Samurai					printf("%c", c );
16136321Samurai				else
16236321Samurai					printf("<0x%02x>", c );
16336321Samurai#endif
16436321Samurai				s +=2;
16536321Samurai			} else {
16636321Samurai#ifdef DEBUG
16736321Samurai				printf("%c", *s);
16836321Samurai#endif
16936321Samurai				s++;
17036321Samurai			}
17136321Samurai		}
17236321Samurai#ifdef DEBUG
17336321Samurai		printf(":");
17436321Samurai#endif
17536321Samurai		fflush(stdout);
17636321Samurai    }
17736321Samurai
17836321Samurai	/* Set up to out of Name field */
17941759Sdillon	if (p == NULL || (char *)p >= pmax)
18041759Sdillon	    p = NULL;
18141759Sdillon	else
18241759Sdillon	    p++;
18336321Samurai	return ((u_char *)p);
18436321Samurai}
18536321Samurai
18636321Samurai/*
18736321Samurai * NetBios Datagram Handler (IP/UDP)
18836321Samurai */
18936321Samurai#define DGM_DIRECT_UNIQ		0x10
19036321Samurai#define DGM_DIRECT_GROUP	0x11
19136321Samurai#define DGM_BROADCAST		0x12
19236321Samurai#define DGM_ERROR			0x13
19336321Samurai#define DGM_QUERY			0x14
19436321Samurai#define DGM_POSITIVE_RES	0x15
19536321Samurai#define DGM_NEGATIVE_RES	0x16
19636321Samurai
19741759Sdillonint AliasHandleUdpNbt(
19836321Samurai	struct ip 		  	*pip,	 /* IP packet to examine/patch */
19936321Samurai	struct alias_link 	*link,
20036321Samurai	struct in_addr		*alias_address,
20141759Sdillon    u_short 		alias_port
20241759Sdillon) {
20336321Samurai    struct udphdr *	uh;
20436321Samurai    NbtDataHeader 	*ndh;
20541759Sdillon    u_char		*p = NULL;
20641759Sdillon    char		*pmax;
20736321Samurai
20836321Samurai    /* Calculate data length of UDP packet */
20936321Samurai    uh =  (struct udphdr *) ((char *) pip + (pip->ip_hl << 2));
21041759Sdillon    pmax = (char *)uh + ntohs( uh->uh_ulen );
21141759Sdillon
21236321Samurai	ndh = (NbtDataHeader *)((char *)uh + (sizeof (struct udphdr)));
21341759Sdillon    if ((char *)(ndh + 1) > pmax)
21441759Sdillon	    return(-1);
21536321Samurai#ifdef DEBUG
21636321Samurai	printf("\nType=%02x,", ndh->type );
21736321Samurai#endif
21836321Samurai	switch ( ndh->type ) {
21936321Samurai		case DGM_DIRECT_UNIQ:
22036321Samurai		case DGM_DIRECT_GROUP:
22136321Samurai		case DGM_BROADCAST:
22236321Samurai			p = (u_char *)ndh + 14;
22341759Sdillon		    p = AliasHandleName ( p, pmax ); /* Source Name */
22441759Sdillon		    p = AliasHandleName ( p, pmax ); /* Destination Name */
22536321Samurai			break;
22636321Samurai		case DGM_ERROR:
22736321Samurai			p = (u_char *)ndh + 11;
22836321Samurai			break;
22936321Samurai		case DGM_QUERY:
23036321Samurai		case DGM_POSITIVE_RES:
23136321Samurai		case DGM_NEGATIVE_RES:
23236321Samurai			p = (u_char *)ndh + 10;
23341759Sdillon		    p = AliasHandleName ( p, pmax ); /* Destination Name */
23436321Samurai			break;
23536321Samurai	}
23641759Sdillon    if (p == NULL || (char *)p > pmax)
23741759Sdillon	    p = NULL;
23836321Samurai#ifdef DEBUG
23936321Samurai	printf("%s:%d-->", inet_ntoa(ndh->source_ip), ntohs(ndh->source_port) );
24036321Samurai#endif
24136321Samurai	/* Doing a IP address and Port number Translation */
24236321Samurai	if ( uh->uh_sum != 0 ) {
24336321Samurai		int				acc;
24436321Samurai		u_short			*sptr;
24536321Samurai		acc  = ndh->source_port;
24636321Samurai		acc -= alias_port;
24736321Samurai		sptr = (u_short *) &(ndh->source_ip);
24836321Samurai		acc += *sptr++;
24936321Samurai		acc += *sptr;
25036321Samurai		sptr = (u_short *) alias_address;
25136321Samurai		acc -= *sptr++;
25236321Samurai		acc -= *sptr;
25374778Sbrian		ADJUST_CHECKSUM(acc, uh->uh_sum);
25436321Samurai	}
25536321Samurai    ndh->source_ip = *alias_address;
25636321Samurai    ndh->source_port = alias_port;
25736321Samurai#ifdef DEBUG
25836321Samurai	printf("%s:%d\n", inet_ntoa(ndh->source_ip), ntohs(ndh->source_port) );
25936321Samurai	fflush(stdout);
26036321Samurai#endif
26141759Sdillon    return((p == NULL) ? -1 : 0);
26236321Samurai}
26336321Samurai/* Question Section */
26436321Samurai#define QS_TYPE_NB		0x0020
26536321Samurai#define QS_TYPE_NBSTAT	0x0021
26636321Samurai#define QS_CLAS_IN		0x0001
26736321Samuraitypedef struct {
26836321Samurai	u_short	type;	/* The type of Request */
26936321Samurai	u_short	class;	/* The class of Request */
27036321Samurai} NBTNsQuestion;
27136321Samurai
27244616Sbrianstatic u_char *
27341759SdillonAliasHandleQuestion(
27441759Sdillon    u_short count,
27536321Samurai							NBTNsQuestion *q,
27641759Sdillon    char *pmax,
27736321Samurai							NBTArguments  *nbtarg)
27836321Samurai{
27936321Samurai
28036321Samurai	while ( count != 0 ) {
28136321Samurai		/* Name Filed */
28241759Sdillon		q = (NBTNsQuestion *)AliasHandleName((u_char *)q, pmax);
28336321Samurai
28441759Sdillon		if (q == NULL || (char *)(q + 1) > pmax) {
28541759Sdillon			q = NULL;
28641759Sdillon			break;
28741759Sdillon		}
28841759Sdillon
28936321Samurai		/* Type and Class filed */
29036321Samurai		switch ( ntohs(q->type) ) {
29136321Samurai			case QS_TYPE_NB:
29236321Samurai			case QS_TYPE_NBSTAT:
29336321Samurai				q= q+1;
29436321Samurai			break;
29536321Samurai			default:
29644616Sbrian#ifdef DEBUG
29736321Samurai				printf("\nUnknown Type on Question %0x\n", ntohs(q->type) );
29844616Sbrian#endif
29936321Samurai			break;
30036321Samurai		}
30136321Samurai		count--;
30236321Samurai	}
30336321Samurai
30436321Samurai	/* Set up to out of Question Section */
30536321Samurai	return ((u_char *)q);
30636321Samurai}
30736321Samurai
30836321Samurai/* Resource Record */
30936321Samurai#define RR_TYPE_A		0x0001
31036321Samurai#define RR_TYPE_NS		0x0002
31136321Samurai#define RR_TYPE_NULL	0x000a
31236321Samurai#define RR_TYPE_NB		0x0020
31336321Samurai#define RR_TYPE_NBSTAT	0x0021
31436321Samurai#define RR_CLAS_IN		0x0001
31536321Samurai#define SizeOfNsResource	8
31636321Samuraitypedef struct {
31736321Samurai 	u_short type;
31836321Samurai 	u_short class;
31936321Samurai 	unsigned int ttl;
32036321Samurai 	u_short rdlen;
32136321Samurai} NBTNsResource;
32236321Samurai
32336321Samurai#define SizeOfNsRNB			6
32436321Samuraitypedef struct {
32536321Samurai	u_short g:1, ont:2, resv:13;
32636321Samurai	struct	in_addr	addr;
32736321Samurai} NBTNsRNB;
32836321Samurai
32944616Sbrianstatic u_char *
33041759SdillonAliasHandleResourceNB(
33141759Sdillon    NBTNsResource *q,
33241759Sdillon    char *pmax,
33336321Samurai							   NBTArguments  *nbtarg)
33436321Samurai{
33536321Samurai	NBTNsRNB	*nb;
33636321Samurai	u_short bcount;
33736321Samurai
33841759Sdillon	if (q == NULL || (char *)(q + 1) > pmax)
33941759Sdillon		return(NULL);
34036321Samurai	/* Check out a length */
34136321Samurai	bcount = ntohs(q->rdlen);
34236321Samurai
34336321Samurai	/* Forward to Resource NB position */
34436321Samurai	nb = (NBTNsRNB *)((u_char *)q + SizeOfNsResource);
34536321Samurai
34636321Samurai	/* Processing all in_addr array */
34736321Samurai#ifdef DEBUG
34836321Samurai	printf("NB rec[%s", inet_ntoa(nbtarg->oldaddr));
34936321Samurai            printf("->%s, %dbytes] ",inet_ntoa(nbtarg->newaddr ), bcount);
35036321Samurai#endif
35141759Sdillon	while ( nb != NULL && bcount != 0 )  {
35241759Sdillon		if ((char *)(nb + 1) > pmax) {
35341759Sdillon			nb = NULL;
35441759Sdillon			break;
35541759Sdillon		}
35636321Samurai#ifdef DEBUG
35736321Samurai		printf("<%s>", inet_ntoa(nb->addr) );
35836321Samurai#endif
35936321Samurai		if (!bcmp(&nbtarg->oldaddr,&nb->addr, sizeof(struct in_addr) ) ) {
36036321Samurai			if ( *nbtarg->uh_sum != 0 ) {
36136321Samurai            	int acc;
36236321Samurai            	u_short *sptr;
36336321Samurai
36436321Samurai            	sptr = (u_short *) &(nb->addr);
36536321Samurai            	acc = *sptr++;
36636321Samurai            	acc += *sptr;
36736321Samurai            	sptr = (u_short *) &(nbtarg->newaddr);
36836321Samurai            	acc -= *sptr++;
36936321Samurai            	acc -= *sptr;
37074778Sbrian            	ADJUST_CHECKSUM(acc, *nbtarg->uh_sum);
37136321Samurai			}
37236321Samurai
37336321Samurai			nb->addr = nbtarg->newaddr;
37436321Samurai#ifdef DEBUG
37536321Samurai			printf("O");
37636321Samurai#endif
37736321Samurai		}
37836321Samurai#ifdef DEBUG
37936321Samurai		 else {
38036321Samurai			printf(".");
38136321Samurai		}
38236321Samurai#endif
38336321Samurai		nb=(NBTNsRNB *)((u_char *)nb + SizeOfNsRNB);
38436321Samurai	 	bcount -= SizeOfNsRNB;
38536321Samurai	}
38641759Sdillon	if (nb == NULL || (char *)(nb + 1) > pmax) {
38741759Sdillon		nb = NULL;
38841759Sdillon	}
38936321Samurai
39036321Samurai	return ((u_char *)nb);
39136321Samurai}
39236321Samurai
39336321Samurai#define SizeOfResourceA		6
39436321Samuraitypedef struct {
39536321Samurai	struct	in_addr	addr;
39636321Samurai} NBTNsResourceA;
39736321Samurai
39844616Sbrianstatic u_char *
39941759SdillonAliasHandleResourceA(
40041759Sdillon    NBTNsResource *q,
40141759Sdillon    char *pmax,
40236321Samurai						 	  NBTArguments  *nbtarg)
40336321Samurai{
40436321Samurai	NBTNsResourceA	*a;
40536321Samurai	u_short bcount;
40636321Samurai
40741759Sdillon	if (q == NULL || (char *)(q + 1) > pmax)
40841759Sdillon		return(NULL);
40941759Sdillon
41036321Samurai	/* Forward to Resource A position */
41136321Samurai	a = (NBTNsResourceA *)( (u_char *)q + sizeof(NBTNsResource) );
41236321Samurai
41336321Samurai	/* Check out of length */
41436321Samurai	bcount = ntohs(q->rdlen);
41536321Samurai
41636321Samurai	/* Processing all in_addr array */
41736321Samurai#ifdef DEBUG
41836321Samurai	printf("Arec [%s", inet_ntoa(nbtarg->oldaddr));
41936321Samurai        printf("->%s]",inet_ntoa(nbtarg->newaddr ));
42036321Samurai#endif
42136321Samurai	while ( bcount != 0 )  {
42241759Sdillon		if (a == NULL || (char *)(a + 1) > pmax)
42341759Sdillon			return(NULL);
42436321Samurai#ifdef DEBUG
42536321Samurai		printf("..%s", inet_ntoa(a->addr) );
42636321Samurai#endif
42736321Samurai		if ( !bcmp(&nbtarg->oldaddr, &a->addr, sizeof(struct in_addr) ) ) {
42836321Samurai			if ( *nbtarg->uh_sum != 0 ) {
42936321Samurai            	int acc;
43036321Samurai            	u_short *sptr;
43136321Samurai
43236321Samurai            	sptr = (u_short *) &(a->addr);		 /* Old */
43336321Samurai            	acc = *sptr++;
43436321Samurai            	acc += *sptr;
43536321Samurai            	sptr = (u_short *) &nbtarg->newaddr; /* New */
43636321Samurai            	acc -= *sptr++;
43736321Samurai            	acc -= *sptr;
43874778Sbrian            	ADJUST_CHECKSUM(acc, *nbtarg->uh_sum);
43936321Samurai			}
44036321Samurai
44136321Samurai			a->addr = nbtarg->newaddr;
44236321Samurai		}
44336321Samurai		a++;	/*XXXX*/
44436321Samurai		bcount -= SizeOfResourceA;
44536321Samurai	}
44641759Sdillon	if (a == NULL || (char *)(a + 1) > pmax)
44741759Sdillon		a =  NULL;
44836321Samurai	return ((u_char *)a);
44936321Samurai}
45036321Samurai
45136321Samuraitypedef struct {
45236321Samurai	u_short opcode:4, flags:8, resv:4;
45336321Samurai} NBTNsResourceNULL;
45436321Samurai
45544616Sbrianstatic u_char *
45641759SdillonAliasHandleResourceNULL(
45741759Sdillon    NBTNsResource *q,
45841759Sdillon    char *pmax,
45936321Samurai						 	     NBTArguments  *nbtarg)
46036321Samurai{
46136321Samurai	NBTNsResourceNULL	*n;
46236321Samurai	u_short bcount;
46336321Samurai
46441759Sdillon	if (q == NULL || (char *)(q + 1) > pmax)
46541759Sdillon		return(NULL);
46641759Sdillon
46736321Samurai	/* Forward to Resource NULL position */
46836321Samurai	n = (NBTNsResourceNULL *)( (u_char *)q + sizeof(NBTNsResource) );
46936321Samurai
47036321Samurai	/* Check out of length */
47136321Samurai	bcount = ntohs(q->rdlen);
47236321Samurai
47336321Samurai	/* Processing all in_addr array */
47436321Samurai	while ( bcount != 0 )  {
47541759Sdillon		if ((char *)(n + 1) > pmax) {
47641759Sdillon			n = NULL;
47741759Sdillon			break;
47841759Sdillon		}
47936321Samurai		n++;
48036321Samurai		bcount -= sizeof(NBTNsResourceNULL);
48136321Samurai	}
48241759Sdillon	if ((char *)(n + 1) > pmax)
48341759Sdillon		n = NULL;
48436321Samurai
48536321Samurai	return ((u_char *)n);
48636321Samurai}
48736321Samurai
48844616Sbrianstatic u_char *
48941759SdillonAliasHandleResourceNS(
49041759Sdillon    NBTNsResource *q,
49141759Sdillon    char *pmax,
49236321Samurai						 	     NBTArguments  *nbtarg)
49336321Samurai{
49436321Samurai	NBTNsResourceNULL	*n;
49536321Samurai	u_short bcount;
49636321Samurai
49741759Sdillon	if (q == NULL || (char *)(q + 1) > pmax)
49841759Sdillon		return(NULL);
49941759Sdillon
50036321Samurai	/* Forward to Resource NULL position */
50136321Samurai	n = (NBTNsResourceNULL *)( (u_char *)q + sizeof(NBTNsResource) );
50236321Samurai
50336321Samurai	/* Check out of length */
50436321Samurai	bcount = ntohs(q->rdlen);
50536321Samurai
50636321Samurai	/* Resource Record Name Filed */
50741759Sdillon	q = (NBTNsResource *)AliasHandleName( (u_char *)n, pmax ); /* XXX */
50836321Samurai
50941759Sdillon	if (q == NULL || (char *)((u_char *)n + bcount) > pmax)
51041759Sdillon		return(NULL);
51141759Sdillon	else
51236321Samurai	return ((u_char *)n + bcount);
51336321Samurai}
51436321Samurai
51536321Samuraitypedef struct {
51636321Samurai	u_short	numnames;
51736321Samurai} NBTNsResourceNBSTAT;
51836321Samurai
51944616Sbrianstatic u_char *
52041759SdillonAliasHandleResourceNBSTAT(
52141759Sdillon    NBTNsResource *q,
52241759Sdillon    char *pmax,
52336321Samurai						 	       NBTArguments  *nbtarg)
52436321Samurai{
52536321Samurai	NBTNsResourceNBSTAT	*n;
52636321Samurai	u_short bcount;
52736321Samurai
52841759Sdillon	if (q == NULL || (char *)(q + 1) > pmax)
52941759Sdillon		return(NULL);
53041759Sdillon
53136321Samurai	/* Forward to Resource NBSTAT position */
53236321Samurai	n = (NBTNsResourceNBSTAT *)( (u_char *)q + sizeof(NBTNsResource) );
53336321Samurai
53436321Samurai	/* Check out of length */
53536321Samurai	bcount = ntohs(q->rdlen);
53636321Samurai
53741759Sdillon	if (q == NULL || (char *)((u_char *)n + bcount) > pmax)
53841759Sdillon		return(NULL);
53941759Sdillon	else
54036321Samurai	return ((u_char *)n + bcount);
54136321Samurai}
54236321Samurai
54344616Sbrianstatic u_char *
54441759SdillonAliasHandleResource(
54541759Sdillon    u_short count,
54636321Samurai							NBTNsResource *q,
54741759Sdillon    char *pmax,
54841759Sdillon    NBTArguments
54941759Sdillon    *nbtarg)
55036321Samurai{
55136321Samurai	while ( count != 0 ) {
55236321Samurai		/* Resource Record Name Filed */
55341759Sdillon		q = (NBTNsResource *)AliasHandleName( (u_char *)q, pmax );
55441759Sdillon
55541759Sdillon		if (q == NULL || (char *)(q + 1) > pmax)
55641759Sdillon			break;
55736321Samurai#ifdef DEBUG
55836321Samurai		printf("type=%02x, count=%d\n", ntohs(q->type), count );
55936321Samurai#endif
56036321Samurai
56136321Samurai		/* Type and Class filed */
56236321Samurai		switch ( ntohs(q->type) ) {
56336321Samurai			case RR_TYPE_NB:
56441759Sdillon				q = (NBTNsResource *)AliasHandleResourceNB(
56541759Sdillon				    q,
56641759Sdillon				    pmax,
56741759Sdillon				    nbtarg
56841759Sdillon				);
56936321Samurai				break;
57036321Samurai			case RR_TYPE_A:
57141759Sdillon				q = (NBTNsResource *)AliasHandleResourceA(
57241759Sdillon				    q,
57341759Sdillon				    pmax,
57441759Sdillon				    nbtarg
57541759Sdillon				);
57636321Samurai				break;
57736321Samurai			case RR_TYPE_NS:
57841759Sdillon				q = (NBTNsResource *)AliasHandleResourceNS(
57941759Sdillon				    q,
58041759Sdillon				    pmax,
58141759Sdillon				    nbtarg
58241759Sdillon				);
58336321Samurai				break;
58436321Samurai			case RR_TYPE_NULL:
58541759Sdillon				q = (NBTNsResource *)AliasHandleResourceNULL(
58641759Sdillon				    q,
58741759Sdillon				    pmax,
58841759Sdillon				    nbtarg
58941759Sdillon				);
59036321Samurai				break;
59136321Samurai			case RR_TYPE_NBSTAT:
59241759Sdillon				q = (NBTNsResource *)AliasHandleResourceNBSTAT(
59341759Sdillon				    q,
59441759Sdillon				    pmax,
59541759Sdillon				    nbtarg
59641759Sdillon				);
59736321Samurai				break;
59841759Sdillon			default:
59944616Sbrian#ifdef DEBUG
60041759Sdillon				printf(
60141759Sdillon				    "\nUnknown Type of Resource %0x\n",
60241759Sdillon				    ntohs(q->type)
60341759Sdillon				);
60444616Sbrian#endif
60536321Samurai				break;
60636321Samurai		}
60736321Samurai		count--;
60836321Samurai	}
60936321Samurai	fflush(stdout);
61036321Samurai	return ((u_char *)q);
61136321Samurai}
61236321Samurai
61341759Sdillonint AliasHandleUdpNbtNS(
61436321Samurai	struct ip 		  	*pip,	 /* IP packet to examine/patch */
61536321Samurai	struct alias_link 	*link,
61636321Samurai	struct in_addr		*alias_address,
61736321Samurai	u_short 			*alias_port,
61836321Samurai	struct in_addr		*original_address,
61936321Samurai	u_short 			*original_port )
62036321Samurai{
62136321Samurai    struct udphdr *	uh;
62236321Samurai	NbtNSHeader	  * nsh;
62336321Samurai	u_char		  * p;
62441759Sdillon	char		*pmax;
62536321Samurai	NBTArguments    nbtarg;
62636321Samurai
62736321Samurai	/* Set up Common Parameter */
62836321Samurai	nbtarg.oldaddr	=	*alias_address;
62936321Samurai	nbtarg.oldport	=	*alias_port;
63036321Samurai	nbtarg.newaddr	=	*original_address;
63136321Samurai	nbtarg.newport	=	*original_port;
63236321Samurai
63336321Samurai    /* Calculate data length of UDP packet */
63436321Samurai    uh =  (struct udphdr *) ((char *) pip + (pip->ip_hl << 2));
63536321Samurai	nbtarg.uh_sum	=	&(uh->uh_sum);
63636321Samurai	nsh = (NbtNSHeader *)((char *)uh + (sizeof(struct udphdr)));
63736321Samurai	p = (u_char *)(nsh + 1);
63841759Sdillon    pmax = (char *)uh + ntohs( uh->uh_ulen );
63936321Samurai
64041759Sdillon    if ((char *)(nsh + 1) > pmax)
64141759Sdillon	return(-1);
64241759Sdillon
64336321Samurai#ifdef DEBUG
64441759Sdillon    printf(" [%s] ID=%02x, op=%01x, flag=%02x, rcode=%01x, qd=%04x"
64541759Sdillon	   ", an=%04x, ns=%04x, ar=%04x, [%d]-->",
64636321Samurai		nsh->dir ? "Response": "Request",
64736321Samurai		nsh->nametrid,
64836321Samurai		nsh->opcode,
64936321Samurai		nsh->nmflags,
65036321Samurai		nsh->rcode,
65136321Samurai		ntohs(nsh->qdcount),
65236321Samurai		ntohs(nsh->ancount),
65336321Samurai		ntohs(nsh->nscount),
65436321Samurai		ntohs(nsh->arcount),
65541759Sdillon	(u_char *)p -(u_char *)nsh
65641759Sdillon    );
65736321Samurai#endif
65836321Samurai
65936321Samurai	/* Question Entries */
66036321Samurai	if (ntohs(nsh->qdcount) !=0 ) {
66141759Sdillon	p = AliasHandleQuestion(
66241759Sdillon	    ntohs(nsh->qdcount),
66341759Sdillon	    (NBTNsQuestion *)p,
66441759Sdillon	    pmax,
66541759Sdillon	    &nbtarg
66641759Sdillon	);
66736321Samurai	}
66836321Samurai
66936321Samurai	/* Answer Resource Records */
67036321Samurai	if (ntohs(nsh->ancount) !=0 ) {
67141759Sdillon	p = AliasHandleResource(
67241759Sdillon	    ntohs(nsh->ancount),
67341759Sdillon	    (NBTNsResource *)p,
67441759Sdillon	    pmax,
67541759Sdillon	    &nbtarg
67641759Sdillon	);
67736321Samurai	}
67836321Samurai
67936321Samurai	/* Authority Resource Recodrs */
68036321Samurai	if (ntohs(nsh->nscount) !=0 ) {
68141759Sdillon	p = AliasHandleResource(
68241759Sdillon	    ntohs(nsh->nscount),
68341759Sdillon	    (NBTNsResource *)p,
68441759Sdillon	    pmax,
68541759Sdillon	    &nbtarg
68641759Sdillon	);
68736321Samurai	}
68836321Samurai
68936321Samurai	/* Additional Resource Recodrs */
69036321Samurai	if (ntohs(nsh->arcount) !=0 ) {
69141759Sdillon	p = AliasHandleResource(
69241759Sdillon	    ntohs(nsh->arcount),
69341759Sdillon	    (NBTNsResource *)p,
69441759Sdillon	    pmax,
69541759Sdillon	    &nbtarg
69641759Sdillon	);
69736321Samurai	}
69836321Samurai
69936321Samurai#ifdef DEBUG
70036321Samurai	 	PrintRcode(nsh->rcode);
70136321Samurai#endif
70241759Sdillon    return ((p == NULL) ? -1 : 0);
70336321Samurai}
704