alias_nbt.c revision 44616
136321Samurai/*
236321Samurai * Written by Atsushi Murai <amurai@spec.co.jp>
336321Samurai *
436321Samurai * Copyright (C) 1998, System Planning and Engineering Co. All rights reserverd.
536321Samurai *
636321Samurai * Redistribution and use in source and binary forms are permitted
736321Samurai * provided that the above copyright notice and this paragraph are
836321Samurai * duplicated in all such forms and that any documentation,
936321Samurai * advertising materials, and other materials related to such
1036321Samurai * distribution and use acknowledge that the software was developed
1136321Samurai * by the System Planning and Engineering Co.  The name of the
1236321Samurai * SPEC may not be used to endorse or promote products derived
1336321Samurai * from this software without specific prior written permission.
1436321Samurai * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
1536321Samurai * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
1636321Samurai * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1736321Samurai *
1844616Sbrian * $Id: alias_nbt.c,v 1.2 1998/12/14 02:25:32 dillon Exp $
1936321Samurai *
2036321Samurai *  TODO:
2136321Samurai *       oClean up.
2236321Samurai *       oConsidering for word alignment for other platform.
2336321Samurai */
2436321Samurai/*
2536321Samurai    alias_nbt.c performs special processing for NetBios over TCP/IP
2636321Samurai    sessions by UDP.
2736321Samurai
2836321Samurai    Initial version:  May, 1998  (Atsushi Murai <amurai@spec.co.jp>)
2936321Samurai
3036321Samurai    See HISTORY file for record of revisions.
3136321Samurai*/
3236321Samurai
3336321Samurai/* Includes */
3436321Samurai#include <ctype.h>
3536321Samurai#include <stdio.h>
3636321Samurai#include <string.h>
3736321Samurai#include <sys/types.h>
3836321Samurai#include <netinet/in_systm.h>
3936321Samurai#include <netinet/in.h>
4036321Samurai#include <arpa/inet.h>
4136321Samurai#include <netinet/ip.h>
4236321Samurai#include <netinet/udp.h>
4336321Samurai#include <netinet/tcp.h>
4436321Samurai
4536321Samurai#include "alias_local.h"
4636321Samurai
4736321Samurai#define ADJUST_CHECKSUM(acc, cksum) { \
4836321Samurai    acc += cksum; \
4936321Samurai    if (acc < 0) \
5036321Samurai    { \
5136321Samurai        acc = -acc; \
5236321Samurai        acc = (acc >> 16) + (acc & 0xffff); \
5336321Samurai        acc += acc >> 16; \
5436321Samurai        cksum = (u_short) ~acc; \
5536321Samurai    } \
5636321Samurai    else \
5736321Samurai    { \
5836321Samurai        acc = (acc >> 16) + (acc & 0xffff); \
5936321Samurai        acc += acc >> 16; \
6036321Samurai        cksum = (u_short) acc; \
6136321Samurai    } \
6236321Samurai}
6336321Samurai
6436321Samuraitypedef struct {
6536321Samurai	struct in_addr		oldaddr;
6636321Samurai	u_short 			oldport;
6736321Samurai	struct in_addr		newaddr;
6836321Samurai	u_short 			newport;
6936321Samurai	u_short 			*uh_sum;
7036321Samurai} NBTArguments;
7136321Samurai
7236321Samuraitypedef struct {
7336321Samurai	unsigned char   type;
7436321Samurai	unsigned char   flags;
7536321Samurai	u_short  		id;
7636321Samurai	struct in_addr  source_ip;
7736321Samurai	u_short			source_port;
7836321Samurai	u_short			len;
7936321Samurai	u_short			offset;
8036321Samurai} NbtDataHeader;
8136321Samurai
8236321Samurai#define OpQuery		0
8336321Samurai#define OpUnknown	4
8436321Samurai#define OpRegist	5
8536321Samurai#define OpRelease	6
8636321Samurai#define OpWACK		7
8736321Samurai#define OpRefresh	8
8836321Samuraitypedef struct {
8936321Samurai	u_short			nametrid;
9036321Samurai	u_short 		dir:1, opcode:4, nmflags:7, rcode:4;
9136321Samurai	u_short			qdcount;
9236321Samurai	u_short			ancount;
9336321Samurai	u_short			nscount;
9436321Samurai	u_short			arcount;
9536321Samurai} NbtNSHeader;
9636321Samurai
9736321Samurai#define FMT_ERR		0x1
9836321Samurai#define SRV_ERR		0x2
9936321Samurai#define IMP_ERR		0x4
10036321Samurai#define RFS_ERR		0x5
10136321Samurai#define ACT_ERR		0x6
10236321Samurai#define CFT_ERR		0x7
10336321Samurai
10436321Samurai
10544616Sbrian#ifdef DEBUG
10644616Sbrianstatic void PrintRcode( u_char rcode )  {
10736321Samurai
10836321Samurai	switch (rcode) {
10936321Samurai		case FMT_ERR:
11036321Samurai			printf("\nFormat Error.");
11136321Samurai		case SRV_ERR:
11236321Samurai			printf("\nSever failure.");
11336321Samurai		case IMP_ERR:
11436321Samurai			printf("\nUnsupported request error.\n");
11536321Samurai		case RFS_ERR:
11636321Samurai			printf("\nRefused error.\n");
11736321Samurai		case ACT_ERR:
11836321Samurai			printf("\nActive error.\n");
11936321Samurai		case CFT_ERR:
12036321Samurai			printf("\nName in conflict error.\n");
12136321Samurai		default:
12236321Samurai			printf("\n???=%0x\n", rcode );
12336321Samurai
12436321Samurai	}
12536321Samurai}
12644616Sbrian#endif
12736321Samurai
12836321Samurai
12936321Samurai/* Handling Name field */
13044616Sbrianstatic u_char *AliasHandleName ( u_char *p, char *pmax ) {
13136321Samurai
13236321Samurai	u_char *s;
13336321Samurai	u_char c;
13436321Samurai	int		compress;
13536321Samurai
13636321Samurai	/* Following length field */
13741759Sdillon
13841759Sdillon	if (p == NULL || (char *)p >= pmax)
13941759Sdillon		return(NULL);
14041759Sdillon
14136321Samurai	if (*p & 0xc0 ) {
14236321Samurai		p = p + 2;
14341759Sdillon		if ((char *)p > pmax)
14441759Sdillon			return(NULL);
14536321Samurai		return ((u_char *)p);
14636321Samurai	}
14736321Samurai	while ( ( *p & 0x3f) != 0x00 ) {
14836321Samurai		s = p + 1;
14936321Samurai		if ( *p == 0x20 )
15036321Samurai			compress = 1;
15136321Samurai		else
15236321Samurai			compress = 0;
15336321Samurai
15436321Samurai	 	/* Get next length field */
15536321Samurai		p = (u_char *)(p + (*p & 0x3f) + 1);
15641759Sdillon		if ((char *)p > pmax) {
15741759Sdillon			p = NULL;
15841759Sdillon			break;
15941759Sdillon		}
16036321Samurai#ifdef DEBUG
16136321Samurai		printf(":");
16236321Samurai#endif
16336321Samurai		while (s < p) {
16436321Samurai			if ( compress == 1 ) {
16536321Samurai				c = (u_char )(((((*s & 0x0f) << 4) | (*(s+1) & 0x0f)) - 0x11));
16636321Samurai#ifdef DEBUG
16736321Samurai				if (isprint( c ) )
16836321Samurai					printf("%c", c );
16936321Samurai				else
17036321Samurai					printf("<0x%02x>", c );
17136321Samurai#endif
17236321Samurai				s +=2;
17336321Samurai			} else {
17436321Samurai#ifdef DEBUG
17536321Samurai				printf("%c", *s);
17636321Samurai#endif
17736321Samurai				s++;
17836321Samurai			}
17936321Samurai		}
18036321Samurai#ifdef DEBUG
18136321Samurai		printf(":");
18236321Samurai#endif
18336321Samurai		fflush(stdout);
18436321Samurai    }
18536321Samurai
18636321Samurai	/* Set up to out of Name field */
18741759Sdillon	if (p == NULL || (char *)p >= pmax)
18841759Sdillon	    p = NULL;
18941759Sdillon	else
19041759Sdillon	    p++;
19136321Samurai	return ((u_char *)p);
19236321Samurai}
19336321Samurai
19436321Samurai/*
19536321Samurai * NetBios Datagram Handler (IP/UDP)
19636321Samurai */
19736321Samurai#define DGM_DIRECT_UNIQ		0x10
19836321Samurai#define DGM_DIRECT_GROUP	0x11
19936321Samurai#define DGM_BROADCAST		0x12
20036321Samurai#define DGM_ERROR			0x13
20136321Samurai#define DGM_QUERY			0x14
20236321Samurai#define DGM_POSITIVE_RES	0x15
20336321Samurai#define DGM_NEGATIVE_RES	0x16
20436321Samurai
20541759Sdillonint AliasHandleUdpNbt(
20636321Samurai	struct ip 		  	*pip,	 /* IP packet to examine/patch */
20736321Samurai	struct alias_link 	*link,
20836321Samurai	struct in_addr		*alias_address,
20941759Sdillon    u_short 		alias_port
21041759Sdillon) {
21136321Samurai    struct udphdr *	uh;
21236321Samurai    NbtDataHeader 	*ndh;
21341759Sdillon    u_char		*p = NULL;
21441759Sdillon    char		*pmax;
21536321Samurai
21636321Samurai    /* Calculate data length of UDP packet */
21736321Samurai    uh =  (struct udphdr *) ((char *) pip + (pip->ip_hl << 2));
21841759Sdillon    pmax = (char *)uh + ntohs( uh->uh_ulen );
21941759Sdillon
22036321Samurai	ndh = (NbtDataHeader *)((char *)uh + (sizeof (struct udphdr)));
22141759Sdillon    if ((char *)(ndh + 1) > pmax)
22241759Sdillon	    return(-1);
22336321Samurai#ifdef DEBUG
22436321Samurai	printf("\nType=%02x,", ndh->type );
22536321Samurai#endif
22636321Samurai	switch ( ndh->type ) {
22736321Samurai		case DGM_DIRECT_UNIQ:
22836321Samurai		case DGM_DIRECT_GROUP:
22936321Samurai		case DGM_BROADCAST:
23036321Samurai			p = (u_char *)ndh + 14;
23141759Sdillon		    p = AliasHandleName ( p, pmax ); /* Source Name */
23241759Sdillon		    p = AliasHandleName ( p, pmax ); /* Destination Name */
23336321Samurai			break;
23436321Samurai		case DGM_ERROR:
23536321Samurai			p = (u_char *)ndh + 11;
23636321Samurai			break;
23736321Samurai		case DGM_QUERY:
23836321Samurai		case DGM_POSITIVE_RES:
23936321Samurai		case DGM_NEGATIVE_RES:
24036321Samurai			p = (u_char *)ndh + 10;
24141759Sdillon		    p = AliasHandleName ( p, pmax ); /* Destination Name */
24236321Samurai			break;
24336321Samurai	}
24441759Sdillon    if (p == NULL || (char *)p > pmax)
24541759Sdillon	    p = NULL;
24636321Samurai#ifdef DEBUG
24736321Samurai	printf("%s:%d-->", inet_ntoa(ndh->source_ip), ntohs(ndh->source_port) );
24836321Samurai#endif
24936321Samurai	/* Doing a IP address and Port number Translation */
25036321Samurai	if ( uh->uh_sum != 0 ) {
25136321Samurai		int				acc;
25236321Samurai		u_short			*sptr;
25336321Samurai		acc  = ndh->source_port;
25436321Samurai		acc -= alias_port;
25536321Samurai		sptr = (u_short *) &(ndh->source_ip);
25636321Samurai		acc += *sptr++;
25736321Samurai		acc += *sptr;
25836321Samurai		sptr = (u_short *) alias_address;
25936321Samurai		acc -= *sptr++;
26036321Samurai		acc -= *sptr;
26136321Samurai		ADJUST_CHECKSUM(acc, uh->uh_sum)
26236321Samurai	}
26336321Samurai    ndh->source_ip = *alias_address;
26436321Samurai    ndh->source_port = alias_port;
26536321Samurai#ifdef DEBUG
26636321Samurai	printf("%s:%d\n", inet_ntoa(ndh->source_ip), ntohs(ndh->source_port) );
26736321Samurai	fflush(stdout);
26836321Samurai#endif
26941759Sdillon    return((p == NULL) ? -1 : 0);
27036321Samurai}
27136321Samurai/* Question Section */
27236321Samurai#define QS_TYPE_NB		0x0020
27336321Samurai#define QS_TYPE_NBSTAT	0x0021
27436321Samurai#define QS_CLAS_IN		0x0001
27536321Samuraitypedef struct {
27636321Samurai	u_short	type;	/* The type of Request */
27736321Samurai	u_short	class;	/* The class of Request */
27836321Samurai} NBTNsQuestion;
27936321Samurai
28044616Sbrianstatic u_char *
28141759SdillonAliasHandleQuestion(
28241759Sdillon    u_short count,
28336321Samurai							NBTNsQuestion *q,
28441759Sdillon    char *pmax,
28536321Samurai							NBTArguments  *nbtarg)
28636321Samurai{
28736321Samurai
28836321Samurai	while ( count != 0 ) {
28936321Samurai		/* Name Filed */
29041759Sdillon		q = (NBTNsQuestion *)AliasHandleName((u_char *)q, pmax);
29136321Samurai
29241759Sdillon		if (q == NULL || (char *)(q + 1) > pmax) {
29341759Sdillon			q = NULL;
29441759Sdillon			break;
29541759Sdillon		}
29641759Sdillon
29736321Samurai		/* Type and Class filed */
29836321Samurai		switch ( ntohs(q->type) ) {
29936321Samurai			case QS_TYPE_NB:
30036321Samurai			case QS_TYPE_NBSTAT:
30136321Samurai				q= q+1;
30236321Samurai			break;
30336321Samurai			default:
30444616Sbrian#ifdef DEBUG
30536321Samurai				printf("\nUnknown Type on Question %0x\n", ntohs(q->type) );
30644616Sbrian#endif
30736321Samurai			break;
30836321Samurai		}
30936321Samurai		count--;
31036321Samurai	}
31136321Samurai
31236321Samurai	/* Set up to out of Question Section */
31336321Samurai	return ((u_char *)q);
31436321Samurai}
31536321Samurai
31636321Samurai/* Resource Record */
31736321Samurai#define RR_TYPE_A		0x0001
31836321Samurai#define RR_TYPE_NS		0x0002
31936321Samurai#define RR_TYPE_NULL	0x000a
32036321Samurai#define RR_TYPE_NB		0x0020
32136321Samurai#define RR_TYPE_NBSTAT	0x0021
32236321Samurai#define RR_CLAS_IN		0x0001
32336321Samurai#define SizeOfNsResource	8
32436321Samuraitypedef struct {
32536321Samurai 	u_short type;
32636321Samurai 	u_short class;
32736321Samurai 	unsigned int ttl;
32836321Samurai 	u_short rdlen;
32936321Samurai} NBTNsResource;
33036321Samurai
33136321Samurai#define SizeOfNsRNB			6
33236321Samuraitypedef struct {
33336321Samurai	u_short g:1, ont:2, resv:13;
33436321Samurai	struct	in_addr	addr;
33536321Samurai} NBTNsRNB;
33636321Samurai
33744616Sbrianstatic u_char *
33841759SdillonAliasHandleResourceNB(
33941759Sdillon    NBTNsResource *q,
34041759Sdillon    char *pmax,
34136321Samurai							   NBTArguments  *nbtarg)
34236321Samurai{
34336321Samurai	NBTNsRNB	*nb;
34436321Samurai	u_short bcount;
34536321Samurai
34641759Sdillon	if (q == NULL || (char *)(q + 1) > pmax)
34741759Sdillon		return(NULL);
34836321Samurai	/* Check out a length */
34936321Samurai	bcount = ntohs(q->rdlen);
35036321Samurai
35136321Samurai	/* Forward to Resource NB position */
35236321Samurai	nb = (NBTNsRNB *)((u_char *)q + SizeOfNsResource);
35336321Samurai
35436321Samurai	/* Processing all in_addr array */
35536321Samurai#ifdef DEBUG
35636321Samurai	printf("NB rec[%s", inet_ntoa(nbtarg->oldaddr));
35736321Samurai            printf("->%s, %dbytes] ",inet_ntoa(nbtarg->newaddr ), bcount);
35836321Samurai#endif
35941759Sdillon	while ( nb != NULL && bcount != 0 )  {
36041759Sdillon		if ((char *)(nb + 1) > pmax) {
36141759Sdillon			nb = NULL;
36241759Sdillon			break;
36341759Sdillon		}
36436321Samurai#ifdef DEBUG
36536321Samurai		printf("<%s>", inet_ntoa(nb->addr) );
36636321Samurai#endif
36736321Samurai		if (!bcmp(&nbtarg->oldaddr,&nb->addr, sizeof(struct in_addr) ) ) {
36836321Samurai			if ( *nbtarg->uh_sum != 0 ) {
36936321Samurai            	int acc;
37036321Samurai            	u_short *sptr;
37136321Samurai
37236321Samurai            	sptr = (u_short *) &(nb->addr);
37336321Samurai            	acc = *sptr++;
37436321Samurai            	acc += *sptr;
37536321Samurai            	sptr = (u_short *) &(nbtarg->newaddr);
37636321Samurai            	acc -= *sptr++;
37736321Samurai            	acc -= *sptr;
37836321Samurai            	ADJUST_CHECKSUM(acc, *nbtarg->uh_sum)
37936321Samurai			}
38036321Samurai
38136321Samurai			nb->addr = nbtarg->newaddr;
38236321Samurai#ifdef DEBUG
38336321Samurai			printf("O");
38436321Samurai#endif
38536321Samurai		}
38636321Samurai#ifdef DEBUG
38736321Samurai		 else {
38836321Samurai			printf(".");
38936321Samurai		}
39036321Samurai#endif
39136321Samurai		nb=(NBTNsRNB *)((u_char *)nb + SizeOfNsRNB);
39236321Samurai	 	bcount -= SizeOfNsRNB;
39336321Samurai	}
39441759Sdillon	if (nb == NULL || (char *)(nb + 1) > pmax) {
39541759Sdillon		nb = NULL;
39641759Sdillon	}
39736321Samurai
39836321Samurai	return ((u_char *)nb);
39936321Samurai}
40036321Samurai
40136321Samurai#define SizeOfResourceA		6
40236321Samuraitypedef struct {
40336321Samurai	struct	in_addr	addr;
40436321Samurai} NBTNsResourceA;
40536321Samurai
40644616Sbrianstatic u_char *
40741759SdillonAliasHandleResourceA(
40841759Sdillon    NBTNsResource *q,
40941759Sdillon    char *pmax,
41036321Samurai						 	  NBTArguments  *nbtarg)
41136321Samurai{
41236321Samurai	NBTNsResourceA	*a;
41336321Samurai	u_short bcount;
41436321Samurai
41541759Sdillon	if (q == NULL || (char *)(q + 1) > pmax)
41641759Sdillon		return(NULL);
41741759Sdillon
41836321Samurai	/* Forward to Resource A position */
41936321Samurai	a = (NBTNsResourceA *)( (u_char *)q + sizeof(NBTNsResource) );
42036321Samurai
42136321Samurai	/* Check out of length */
42236321Samurai	bcount = ntohs(q->rdlen);
42336321Samurai
42436321Samurai	/* Processing all in_addr array */
42536321Samurai#ifdef DEBUG
42636321Samurai	printf("Arec [%s", inet_ntoa(nbtarg->oldaddr));
42736321Samurai        printf("->%s]",inet_ntoa(nbtarg->newaddr ));
42836321Samurai#endif
42936321Samurai	while ( bcount != 0 )  {
43041759Sdillon		if (a == NULL || (char *)(a + 1) > pmax)
43141759Sdillon			return(NULL);
43236321Samurai#ifdef DEBUG
43336321Samurai		printf("..%s", inet_ntoa(a->addr) );
43436321Samurai#endif
43536321Samurai		if ( !bcmp(&nbtarg->oldaddr, &a->addr, sizeof(struct in_addr) ) ) {
43636321Samurai			if ( *nbtarg->uh_sum != 0 ) {
43736321Samurai            	int acc;
43836321Samurai            	u_short *sptr;
43936321Samurai
44036321Samurai            	sptr = (u_short *) &(a->addr);		 /* Old */
44136321Samurai            	acc = *sptr++;
44236321Samurai            	acc += *sptr;
44336321Samurai            	sptr = (u_short *) &nbtarg->newaddr; /* New */
44436321Samurai            	acc -= *sptr++;
44536321Samurai            	acc -= *sptr;
44636321Samurai            	ADJUST_CHECKSUM(acc, *nbtarg->uh_sum)
44736321Samurai			}
44836321Samurai
44936321Samurai			a->addr = nbtarg->newaddr;
45036321Samurai		}
45136321Samurai		a++;	/*XXXX*/
45236321Samurai		bcount -= SizeOfResourceA;
45336321Samurai	}
45441759Sdillon	if (a == NULL || (char *)(a + 1) > pmax)
45541759Sdillon		a =  NULL;
45636321Samurai	return ((u_char *)a);
45736321Samurai}
45836321Samurai
45936321Samuraitypedef struct {
46036321Samurai	u_short opcode:4, flags:8, resv:4;
46136321Samurai} NBTNsResourceNULL;
46236321Samurai
46344616Sbrianstatic u_char *
46441759SdillonAliasHandleResourceNULL(
46541759Sdillon    NBTNsResource *q,
46641759Sdillon    char *pmax,
46736321Samurai						 	     NBTArguments  *nbtarg)
46836321Samurai{
46936321Samurai	NBTNsResourceNULL	*n;
47036321Samurai	u_short bcount;
47136321Samurai
47241759Sdillon	if (q == NULL || (char *)(q + 1) > pmax)
47341759Sdillon		return(NULL);
47441759Sdillon
47536321Samurai	/* Forward to Resource NULL position */
47636321Samurai	n = (NBTNsResourceNULL *)( (u_char *)q + sizeof(NBTNsResource) );
47736321Samurai
47836321Samurai	/* Check out of length */
47936321Samurai	bcount = ntohs(q->rdlen);
48036321Samurai
48136321Samurai	/* Processing all in_addr array */
48236321Samurai	while ( bcount != 0 )  {
48341759Sdillon		if ((char *)(n + 1) > pmax) {
48441759Sdillon			n = NULL;
48541759Sdillon			break;
48641759Sdillon		}
48736321Samurai		n++;
48836321Samurai		bcount -= sizeof(NBTNsResourceNULL);
48936321Samurai	}
49041759Sdillon	if ((char *)(n + 1) > pmax)
49141759Sdillon		n = NULL;
49236321Samurai
49336321Samurai	return ((u_char *)n);
49436321Samurai}
49536321Samurai
49644616Sbrianstatic u_char *
49741759SdillonAliasHandleResourceNS(
49841759Sdillon    NBTNsResource *q,
49941759Sdillon    char *pmax,
50036321Samurai						 	     NBTArguments  *nbtarg)
50136321Samurai{
50236321Samurai	NBTNsResourceNULL	*n;
50336321Samurai	u_short bcount;
50436321Samurai
50541759Sdillon	if (q == NULL || (char *)(q + 1) > pmax)
50641759Sdillon		return(NULL);
50741759Sdillon
50836321Samurai	/* Forward to Resource NULL position */
50936321Samurai	n = (NBTNsResourceNULL *)( (u_char *)q + sizeof(NBTNsResource) );
51036321Samurai
51136321Samurai	/* Check out of length */
51236321Samurai	bcount = ntohs(q->rdlen);
51336321Samurai
51436321Samurai	/* Resource Record Name Filed */
51541759Sdillon	q = (NBTNsResource *)AliasHandleName( (u_char *)n, pmax ); /* XXX */
51636321Samurai
51741759Sdillon	if (q == NULL || (char *)((u_char *)n + bcount) > pmax)
51841759Sdillon		return(NULL);
51941759Sdillon	else
52036321Samurai	return ((u_char *)n + bcount);
52136321Samurai}
52236321Samurai
52336321Samuraitypedef struct {
52436321Samurai	u_short	numnames;
52536321Samurai} NBTNsResourceNBSTAT;
52636321Samurai
52744616Sbrianstatic u_char *
52841759SdillonAliasHandleResourceNBSTAT(
52941759Sdillon    NBTNsResource *q,
53041759Sdillon    char *pmax,
53136321Samurai						 	       NBTArguments  *nbtarg)
53236321Samurai{
53336321Samurai	NBTNsResourceNBSTAT	*n;
53436321Samurai	u_short bcount;
53536321Samurai
53641759Sdillon	if (q == NULL || (char *)(q + 1) > pmax)
53741759Sdillon		return(NULL);
53841759Sdillon
53936321Samurai	/* Forward to Resource NBSTAT position */
54036321Samurai	n = (NBTNsResourceNBSTAT *)( (u_char *)q + sizeof(NBTNsResource) );
54136321Samurai
54236321Samurai	/* Check out of length */
54336321Samurai	bcount = ntohs(q->rdlen);
54436321Samurai
54541759Sdillon	if (q == NULL || (char *)((u_char *)n + bcount) > pmax)
54641759Sdillon		return(NULL);
54741759Sdillon	else
54836321Samurai	return ((u_char *)n + bcount);
54936321Samurai}
55036321Samurai
55144616Sbrianstatic u_char *
55241759SdillonAliasHandleResource(
55341759Sdillon    u_short count,
55436321Samurai							NBTNsResource *q,
55541759Sdillon    char *pmax,
55641759Sdillon    NBTArguments
55741759Sdillon    *nbtarg)
55836321Samurai{
55936321Samurai	while ( count != 0 ) {
56036321Samurai		/* Resource Record Name Filed */
56141759Sdillon		q = (NBTNsResource *)AliasHandleName( (u_char *)q, pmax );
56241759Sdillon
56341759Sdillon		if (q == NULL || (char *)(q + 1) > pmax)
56441759Sdillon			break;
56536321Samurai#ifdef DEBUG
56636321Samurai		printf("type=%02x, count=%d\n", ntohs(q->type), count );
56736321Samurai#endif
56836321Samurai
56936321Samurai		/* Type and Class filed */
57036321Samurai		switch ( ntohs(q->type) ) {
57136321Samurai			case RR_TYPE_NB:
57241759Sdillon				q = (NBTNsResource *)AliasHandleResourceNB(
57341759Sdillon				    q,
57441759Sdillon				    pmax,
57541759Sdillon				    nbtarg
57641759Sdillon				);
57736321Samurai				break;
57836321Samurai			case RR_TYPE_A:
57941759Sdillon				q = (NBTNsResource *)AliasHandleResourceA(
58041759Sdillon				    q,
58141759Sdillon				    pmax,
58241759Sdillon				    nbtarg
58341759Sdillon				);
58436321Samurai				break;
58536321Samurai			case RR_TYPE_NS:
58641759Sdillon				q = (NBTNsResource *)AliasHandleResourceNS(
58741759Sdillon				    q,
58841759Sdillon				    pmax,
58941759Sdillon				    nbtarg
59041759Sdillon				);
59136321Samurai				break;
59236321Samurai			case RR_TYPE_NULL:
59341759Sdillon				q = (NBTNsResource *)AliasHandleResourceNULL(
59441759Sdillon				    q,
59541759Sdillon				    pmax,
59641759Sdillon				    nbtarg
59741759Sdillon				);
59836321Samurai				break;
59936321Samurai			case RR_TYPE_NBSTAT:
60041759Sdillon				q = (NBTNsResource *)AliasHandleResourceNBSTAT(
60141759Sdillon				    q,
60241759Sdillon				    pmax,
60341759Sdillon				    nbtarg
60441759Sdillon				);
60536321Samurai				break;
60641759Sdillon			default:
60744616Sbrian#ifdef DEBUG
60841759Sdillon				printf(
60941759Sdillon				    "\nUnknown Type of Resource %0x\n",
61041759Sdillon				    ntohs(q->type)
61141759Sdillon				);
61244616Sbrian#endif
61336321Samurai				break;
61436321Samurai		}
61536321Samurai		count--;
61636321Samurai	}
61736321Samurai	fflush(stdout);
61836321Samurai	return ((u_char *)q);
61936321Samurai}
62036321Samurai
62141759Sdillonint AliasHandleUdpNbtNS(
62236321Samurai	struct ip 		  	*pip,	 /* IP packet to examine/patch */
62336321Samurai	struct alias_link 	*link,
62436321Samurai	struct in_addr		*alias_address,
62536321Samurai	u_short 			*alias_port,
62636321Samurai	struct in_addr		*original_address,
62736321Samurai	u_short 			*original_port )
62836321Samurai{
62936321Samurai    struct udphdr *	uh;
63036321Samurai	NbtNSHeader	  * nsh;
63136321Samurai	u_char		  * p;
63241759Sdillon	char		*pmax;
63336321Samurai	NBTArguments    nbtarg;
63436321Samurai
63536321Samurai	/* Set up Common Parameter */
63636321Samurai	nbtarg.oldaddr	=	*alias_address;
63736321Samurai	nbtarg.oldport	=	*alias_port;
63836321Samurai	nbtarg.newaddr	=	*original_address;
63936321Samurai	nbtarg.newport	=	*original_port;
64036321Samurai
64136321Samurai    /* Calculate data length of UDP packet */
64236321Samurai    uh =  (struct udphdr *) ((char *) pip + (pip->ip_hl << 2));
64336321Samurai	nbtarg.uh_sum	=	&(uh->uh_sum);
64436321Samurai	nsh = (NbtNSHeader *)((char *)uh + (sizeof(struct udphdr)));
64536321Samurai	p = (u_char *)(nsh + 1);
64641759Sdillon    pmax = (char *)uh + ntohs( uh->uh_ulen );
64736321Samurai
64841759Sdillon    if ((char *)(nsh + 1) > pmax)
64941759Sdillon	return(-1);
65041759Sdillon
65136321Samurai#ifdef DEBUG
65241759Sdillon    printf(" [%s] ID=%02x, op=%01x, flag=%02x, rcode=%01x, qd=%04x"
65341759Sdillon	   ", an=%04x, ns=%04x, ar=%04x, [%d]-->",
65436321Samurai		nsh->dir ? "Response": "Request",
65536321Samurai		nsh->nametrid,
65636321Samurai		nsh->opcode,
65736321Samurai		nsh->nmflags,
65836321Samurai		nsh->rcode,
65936321Samurai		ntohs(nsh->qdcount),
66036321Samurai		ntohs(nsh->ancount),
66136321Samurai		ntohs(nsh->nscount),
66236321Samurai		ntohs(nsh->arcount),
66341759Sdillon	(u_char *)p -(u_char *)nsh
66441759Sdillon    );
66536321Samurai#endif
66636321Samurai
66736321Samurai	/* Question Entries */
66836321Samurai	if (ntohs(nsh->qdcount) !=0 ) {
66941759Sdillon	p = AliasHandleQuestion(
67041759Sdillon	    ntohs(nsh->qdcount),
67141759Sdillon	    (NBTNsQuestion *)p,
67241759Sdillon	    pmax,
67341759Sdillon	    &nbtarg
67441759Sdillon	);
67536321Samurai	}
67636321Samurai
67736321Samurai	/* Answer Resource Records */
67836321Samurai	if (ntohs(nsh->ancount) !=0 ) {
67941759Sdillon	p = AliasHandleResource(
68041759Sdillon	    ntohs(nsh->ancount),
68141759Sdillon	    (NBTNsResource *)p,
68241759Sdillon	    pmax,
68341759Sdillon	    &nbtarg
68441759Sdillon	);
68536321Samurai	}
68636321Samurai
68736321Samurai	/* Authority Resource Recodrs */
68836321Samurai	if (ntohs(nsh->nscount) !=0 ) {
68941759Sdillon	p = AliasHandleResource(
69041759Sdillon	    ntohs(nsh->nscount),
69141759Sdillon	    (NBTNsResource *)p,
69241759Sdillon	    pmax,
69341759Sdillon	    &nbtarg
69441759Sdillon	);
69536321Samurai	}
69636321Samurai
69736321Samurai	/* Additional Resource Recodrs */
69836321Samurai	if (ntohs(nsh->arcount) !=0 ) {
69941759Sdillon	p = AliasHandleResource(
70041759Sdillon	    ntohs(nsh->arcount),
70141759Sdillon	    (NBTNsResource *)p,
70241759Sdillon	    pmax,
70341759Sdillon	    &nbtarg
70441759Sdillon	);
70536321Samurai	}
70636321Samurai
70736321Samurai#ifdef DEBUG
70836321Samurai	 	PrintRcode(nsh->rcode);
70936321Samurai#endif
71041759Sdillon    return ((p == NULL) ? -1 : 0);
71136321Samurai}
712