alias_nbt.c revision 41759
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 *
1841759Sdillon * $Id: alias_nbt.c,v 1.1 1998/05/24 03:03:10 amurai 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/*******************************************************************
10536321Samurai * copy an IP address from one buffer to another                   *
10636321Samurai *******************************************************************/
10736321Samuraivoid putip(void *dest,void *src)
10836321Samurai{
10936321Samurai  memcpy(dest,src,4);
11036321Samurai}
11136321Samurai
11236321Samuraivoid PrintRcode( u_char rcode )  {
11336321Samurai
11436321Samurai	switch (rcode) {
11536321Samurai		case FMT_ERR:
11636321Samurai			printf("\nFormat Error.");
11736321Samurai		case SRV_ERR:
11836321Samurai			printf("\nSever failure.");
11936321Samurai		case IMP_ERR:
12036321Samurai			printf("\nUnsupported request error.\n");
12136321Samurai		case RFS_ERR:
12236321Samurai			printf("\nRefused error.\n");
12336321Samurai		case ACT_ERR:
12436321Samurai			printf("\nActive error.\n");
12536321Samurai		case CFT_ERR:
12636321Samurai			printf("\nName in conflict error.\n");
12736321Samurai		default:
12836321Samurai			printf("\n???=%0x\n", rcode );
12936321Samurai
13036321Samurai	}
13136321Samurai}
13236321Samurai
13336321Samurai
13436321Samurai/* Handling Name field */
13541759Sdillonu_char *AliasHandleName ( u_char *p, char *pmax ) {
13636321Samurai
13736321Samurai	u_char *s;
13836321Samurai	u_char c;
13936321Samurai	int		compress;
14036321Samurai
14136321Samurai	/* Following length field */
14241759Sdillon
14341759Sdillon	if (p == NULL || (char *)p >= pmax)
14441759Sdillon		return(NULL);
14541759Sdillon
14636321Samurai	if (*p & 0xc0 ) {
14736321Samurai		p = p + 2;
14841759Sdillon		if ((char *)p > pmax)
14941759Sdillon			return(NULL);
15036321Samurai		return ((u_char *)p);
15136321Samurai	}
15236321Samurai	while ( ( *p & 0x3f) != 0x00 ) {
15336321Samurai		s = p + 1;
15436321Samurai		if ( *p == 0x20 )
15536321Samurai			compress = 1;
15636321Samurai		else
15736321Samurai			compress = 0;
15836321Samurai
15936321Samurai	 	/* Get next length field */
16036321Samurai		p = (u_char *)(p + (*p & 0x3f) + 1);
16141759Sdillon		if ((char *)p > pmax) {
16241759Sdillon			p = NULL;
16341759Sdillon			break;
16441759Sdillon		}
16536321Samurai#ifdef DEBUG
16636321Samurai		printf(":");
16736321Samurai#endif
16836321Samurai		while (s < p) {
16936321Samurai			if ( compress == 1 ) {
17036321Samurai				c = (u_char )(((((*s & 0x0f) << 4) | (*(s+1) & 0x0f)) - 0x11));
17136321Samurai#ifdef DEBUG
17236321Samurai				if (isprint( c ) )
17336321Samurai					printf("%c", c );
17436321Samurai				else
17536321Samurai					printf("<0x%02x>", c );
17636321Samurai#endif
17736321Samurai				s +=2;
17836321Samurai			} else {
17936321Samurai#ifdef DEBUG
18036321Samurai				printf("%c", *s);
18136321Samurai#endif
18236321Samurai				s++;
18336321Samurai			}
18436321Samurai		}
18536321Samurai#ifdef DEBUG
18636321Samurai		printf(":");
18736321Samurai#endif
18836321Samurai		fflush(stdout);
18936321Samurai    }
19036321Samurai
19136321Samurai	/* Set up to out of Name field */
19241759Sdillon	if (p == NULL || (char *)p >= pmax)
19341759Sdillon	    p = NULL;
19441759Sdillon	else
19541759Sdillon	    p++;
19636321Samurai	return ((u_char *)p);
19736321Samurai}
19836321Samurai
19936321Samurai/*
20036321Samurai * NetBios Datagram Handler (IP/UDP)
20136321Samurai */
20236321Samurai#define DGM_DIRECT_UNIQ		0x10
20336321Samurai#define DGM_DIRECT_GROUP	0x11
20436321Samurai#define DGM_BROADCAST		0x12
20536321Samurai#define DGM_ERROR			0x13
20636321Samurai#define DGM_QUERY			0x14
20736321Samurai#define DGM_POSITIVE_RES	0x15
20836321Samurai#define DGM_NEGATIVE_RES	0x16
20936321Samurai
21041759Sdillonint AliasHandleUdpNbt(
21136321Samurai	struct ip 		  	*pip,	 /* IP packet to examine/patch */
21236321Samurai	struct alias_link 	*link,
21336321Samurai	struct in_addr		*alias_address,
21441759Sdillon    u_short 		alias_port
21541759Sdillon) {
21636321Samurai    struct udphdr *	uh;
21736321Samurai    NbtDataHeader 	*ndh;
21841759Sdillon    u_char		*p = NULL;
21941759Sdillon    char		*pmax;
22036321Samurai
22136321Samurai    /* Calculate data length of UDP packet */
22236321Samurai    uh =  (struct udphdr *) ((char *) pip + (pip->ip_hl << 2));
22341759Sdillon    pmax = (char *)uh + ntohs( uh->uh_ulen );
22441759Sdillon
22536321Samurai	ndh = (NbtDataHeader *)((char *)uh + (sizeof (struct udphdr)));
22641759Sdillon    if ((char *)(ndh + 1) > pmax)
22741759Sdillon	    return(-1);
22836321Samurai#ifdef DEBUG
22936321Samurai	printf("\nType=%02x,", ndh->type );
23036321Samurai#endif
23136321Samurai	switch ( ndh->type ) {
23236321Samurai		case DGM_DIRECT_UNIQ:
23336321Samurai		case DGM_DIRECT_GROUP:
23436321Samurai		case DGM_BROADCAST:
23536321Samurai			p = (u_char *)ndh + 14;
23641759Sdillon		    p = AliasHandleName ( p, pmax ); /* Source Name */
23741759Sdillon		    p = AliasHandleName ( p, pmax ); /* Destination Name */
23836321Samurai			break;
23936321Samurai		case DGM_ERROR:
24036321Samurai			p = (u_char *)ndh + 11;
24136321Samurai			break;
24236321Samurai		case DGM_QUERY:
24336321Samurai		case DGM_POSITIVE_RES:
24436321Samurai		case DGM_NEGATIVE_RES:
24536321Samurai			p = (u_char *)ndh + 10;
24641759Sdillon		    p = AliasHandleName ( p, pmax ); /* Destination Name */
24736321Samurai			break;
24836321Samurai	}
24941759Sdillon    if (p == NULL || (char *)p > pmax)
25041759Sdillon	    p = NULL;
25136321Samurai#ifdef DEBUG
25236321Samurai	printf("%s:%d-->", inet_ntoa(ndh->source_ip), ntohs(ndh->source_port) );
25336321Samurai#endif
25436321Samurai	/* Doing a IP address and Port number Translation */
25536321Samurai	if ( uh->uh_sum != 0 ) {
25636321Samurai		int				acc;
25736321Samurai		u_short			*sptr;
25836321Samurai		acc  = ndh->source_port;
25936321Samurai		acc -= alias_port;
26036321Samurai		sptr = (u_short *) &(ndh->source_ip);
26136321Samurai		acc += *sptr++;
26236321Samurai		acc += *sptr;
26336321Samurai		sptr = (u_short *) alias_address;
26436321Samurai		acc -= *sptr++;
26536321Samurai		acc -= *sptr;
26636321Samurai		ADJUST_CHECKSUM(acc, uh->uh_sum)
26736321Samurai	}
26836321Samurai    ndh->source_ip = *alias_address;
26936321Samurai    ndh->source_port = alias_port;
27036321Samurai#ifdef DEBUG
27136321Samurai	printf("%s:%d\n", inet_ntoa(ndh->source_ip), ntohs(ndh->source_port) );
27236321Samurai	fflush(stdout);
27336321Samurai#endif
27441759Sdillon    return((p == NULL) ? -1 : 0);
27536321Samurai}
27636321Samurai/* Question Section */
27736321Samurai#define QS_TYPE_NB		0x0020
27836321Samurai#define QS_TYPE_NBSTAT	0x0021
27936321Samurai#define QS_CLAS_IN		0x0001
28036321Samuraitypedef struct {
28136321Samurai	u_short	type;	/* The type of Request */
28236321Samurai	u_short	class;	/* The class of Request */
28336321Samurai} NBTNsQuestion;
28436321Samurai
28541759Sdillonu_char *
28641759SdillonAliasHandleQuestion(
28741759Sdillon    u_short count,
28836321Samurai							NBTNsQuestion *q,
28941759Sdillon    char *pmax,
29036321Samurai							NBTArguments  *nbtarg)
29136321Samurai{
29236321Samurai
29336321Samurai	while ( count != 0 ) {
29436321Samurai		/* Name Filed */
29541759Sdillon		q = (NBTNsQuestion *)AliasHandleName((u_char *)q, pmax);
29636321Samurai
29741759Sdillon		if (q == NULL || (char *)(q + 1) > pmax) {
29841759Sdillon			q = NULL;
29941759Sdillon			break;
30041759Sdillon		}
30141759Sdillon
30236321Samurai		/* Type and Class filed */
30336321Samurai		switch ( ntohs(q->type) ) {
30436321Samurai			case QS_TYPE_NB:
30536321Samurai			case QS_TYPE_NBSTAT:
30636321Samurai				q= q+1;
30736321Samurai			break;
30836321Samurai			default:
30936321Samurai				printf("\nUnknown Type on Question %0x\n", ntohs(q->type) );
31036321Samurai			break;
31136321Samurai		}
31236321Samurai		count--;
31336321Samurai	}
31436321Samurai
31536321Samurai	/* Set up to out of Question Section */
31636321Samurai	return ((u_char *)q);
31736321Samurai}
31836321Samurai
31936321Samurai/* Resource Record */
32036321Samurai#define RR_TYPE_A		0x0001
32136321Samurai#define RR_TYPE_NS		0x0002
32236321Samurai#define RR_TYPE_NULL	0x000a
32336321Samurai#define RR_TYPE_NB		0x0020
32436321Samurai#define RR_TYPE_NBSTAT	0x0021
32536321Samurai#define RR_CLAS_IN		0x0001
32636321Samurai#define SizeOfNsResource	8
32736321Samuraitypedef struct {
32836321Samurai 	u_short type;
32936321Samurai 	u_short class;
33036321Samurai 	unsigned int ttl;
33136321Samurai 	u_short rdlen;
33236321Samurai} NBTNsResource;
33336321Samurai
33436321Samurai#define SizeOfNsRNB			6
33536321Samuraitypedef struct {
33636321Samurai	u_short g:1, ont:2, resv:13;
33736321Samurai	struct	in_addr	addr;
33836321Samurai} NBTNsRNB;
33936321Samurai
34041759Sdillonu_char *
34141759SdillonAliasHandleResourceNB(
34241759Sdillon    NBTNsResource *q,
34341759Sdillon    char *pmax,
34436321Samurai							   NBTArguments  *nbtarg)
34536321Samurai{
34636321Samurai	NBTNsRNB	*nb;
34736321Samurai	u_short bcount;
34836321Samurai
34941759Sdillon	if (q == NULL || (char *)(q + 1) > pmax)
35041759Sdillon		return(NULL);
35136321Samurai	/* Check out a length */
35236321Samurai	bcount = ntohs(q->rdlen);
35336321Samurai
35436321Samurai	/* Forward to Resource NB position */
35536321Samurai	nb = (NBTNsRNB *)((u_char *)q + SizeOfNsResource);
35636321Samurai
35736321Samurai	/* Processing all in_addr array */
35836321Samurai#ifdef DEBUG
35936321Samurai	printf("NB rec[%s", inet_ntoa(nbtarg->oldaddr));
36036321Samurai            printf("->%s, %dbytes] ",inet_ntoa(nbtarg->newaddr ), bcount);
36136321Samurai#endif
36241759Sdillon	while ( nb != NULL && bcount != 0 )  {
36341759Sdillon		if ((char *)(nb + 1) > pmax) {
36441759Sdillon			nb = NULL;
36541759Sdillon			break;
36641759Sdillon		}
36736321Samurai#ifdef DEBUG
36836321Samurai		printf("<%s>", inet_ntoa(nb->addr) );
36936321Samurai#endif
37036321Samurai		if (!bcmp(&nbtarg->oldaddr,&nb->addr, sizeof(struct in_addr) ) ) {
37136321Samurai			if ( *nbtarg->uh_sum != 0 ) {
37236321Samurai            	int acc;
37336321Samurai            	u_short *sptr;
37436321Samurai
37536321Samurai            	sptr = (u_short *) &(nb->addr);
37636321Samurai            	acc = *sptr++;
37736321Samurai            	acc += *sptr;
37836321Samurai            	sptr = (u_short *) &(nbtarg->newaddr);
37936321Samurai            	acc -= *sptr++;
38036321Samurai            	acc -= *sptr;
38136321Samurai            	ADJUST_CHECKSUM(acc, *nbtarg->uh_sum)
38236321Samurai			}
38336321Samurai
38436321Samurai			nb->addr = nbtarg->newaddr;
38536321Samurai#ifdef DEBUG
38636321Samurai			printf("O");
38736321Samurai#endif
38836321Samurai		}
38936321Samurai#ifdef DEBUG
39036321Samurai		 else {
39136321Samurai			printf(".");
39236321Samurai		}
39336321Samurai#endif
39436321Samurai		nb=(NBTNsRNB *)((u_char *)nb + SizeOfNsRNB);
39536321Samurai	 	bcount -= SizeOfNsRNB;
39636321Samurai	}
39741759Sdillon	if (nb == NULL || (char *)(nb + 1) > pmax) {
39841759Sdillon		nb = NULL;
39941759Sdillon	}
40036321Samurai
40136321Samurai	return ((u_char *)nb);
40236321Samurai}
40336321Samurai
40436321Samurai#define SizeOfResourceA		6
40536321Samuraitypedef struct {
40636321Samurai	struct	in_addr	addr;
40736321Samurai} NBTNsResourceA;
40836321Samurai
40941759Sdillonu_char *
41041759SdillonAliasHandleResourceA(
41141759Sdillon    NBTNsResource *q,
41241759Sdillon    char *pmax,
41336321Samurai						 	  NBTArguments  *nbtarg)
41436321Samurai{
41536321Samurai	NBTNsResourceA	*a;
41636321Samurai	u_short bcount;
41736321Samurai
41841759Sdillon	if (q == NULL || (char *)(q + 1) > pmax)
41941759Sdillon		return(NULL);
42041759Sdillon
42136321Samurai	/* Forward to Resource A position */
42236321Samurai	a = (NBTNsResourceA *)( (u_char *)q + sizeof(NBTNsResource) );
42336321Samurai
42436321Samurai	/* Check out of length */
42536321Samurai	bcount = ntohs(q->rdlen);
42636321Samurai
42736321Samurai	/* Processing all in_addr array */
42836321Samurai#ifdef DEBUG
42936321Samurai	printf("Arec [%s", inet_ntoa(nbtarg->oldaddr));
43036321Samurai        printf("->%s]",inet_ntoa(nbtarg->newaddr ));
43136321Samurai#endif
43236321Samurai	while ( bcount != 0 )  {
43341759Sdillon		if (a == NULL || (char *)(a + 1) > pmax)
43441759Sdillon			return(NULL);
43536321Samurai#ifdef DEBUG
43636321Samurai		printf("..%s", inet_ntoa(a->addr) );
43736321Samurai#endif
43836321Samurai		if ( !bcmp(&nbtarg->oldaddr, &a->addr, sizeof(struct in_addr) ) ) {
43936321Samurai			if ( *nbtarg->uh_sum != 0 ) {
44036321Samurai            	int acc;
44136321Samurai            	u_short *sptr;
44236321Samurai
44336321Samurai            	sptr = (u_short *) &(a->addr);		 /* Old */
44436321Samurai            	acc = *sptr++;
44536321Samurai            	acc += *sptr;
44636321Samurai            	sptr = (u_short *) &nbtarg->newaddr; /* New */
44736321Samurai            	acc -= *sptr++;
44836321Samurai            	acc -= *sptr;
44936321Samurai            	ADJUST_CHECKSUM(acc, *nbtarg->uh_sum)
45036321Samurai			}
45136321Samurai
45236321Samurai			a->addr = nbtarg->newaddr;
45336321Samurai		}
45436321Samurai		a++;	/*XXXX*/
45536321Samurai		bcount -= SizeOfResourceA;
45636321Samurai	}
45741759Sdillon	if (a == NULL || (char *)(a + 1) > pmax)
45841759Sdillon		a =  NULL;
45936321Samurai	return ((u_char *)a);
46036321Samurai}
46136321Samurai
46236321Samuraitypedef struct {
46336321Samurai	u_short opcode:4, flags:8, resv:4;
46436321Samurai} NBTNsResourceNULL;
46536321Samurai
46641759Sdillonu_char *
46741759SdillonAliasHandleResourceNULL(
46841759Sdillon    NBTNsResource *q,
46941759Sdillon    char *pmax,
47036321Samurai						 	     NBTArguments  *nbtarg)
47136321Samurai{
47236321Samurai	NBTNsResourceNULL	*n;
47336321Samurai	u_short bcount;
47436321Samurai
47541759Sdillon	if (q == NULL || (char *)(q + 1) > pmax)
47641759Sdillon		return(NULL);
47741759Sdillon
47836321Samurai	/* Forward to Resource NULL position */
47936321Samurai	n = (NBTNsResourceNULL *)( (u_char *)q + sizeof(NBTNsResource) );
48036321Samurai
48136321Samurai	/* Check out of length */
48236321Samurai	bcount = ntohs(q->rdlen);
48336321Samurai
48436321Samurai	/* Processing all in_addr array */
48536321Samurai	while ( bcount != 0 )  {
48641759Sdillon		if ((char *)(n + 1) > pmax) {
48741759Sdillon			n = NULL;
48841759Sdillon			break;
48941759Sdillon		}
49036321Samurai		n++;
49136321Samurai		bcount -= sizeof(NBTNsResourceNULL);
49236321Samurai	}
49341759Sdillon	if ((char *)(n + 1) > pmax)
49441759Sdillon		n = NULL;
49536321Samurai
49636321Samurai	return ((u_char *)n);
49736321Samurai}
49836321Samurai
49941759Sdillonu_char *
50041759SdillonAliasHandleResourceNS(
50141759Sdillon    NBTNsResource *q,
50241759Sdillon    char *pmax,
50336321Samurai						 	     NBTArguments  *nbtarg)
50436321Samurai{
50536321Samurai	NBTNsResourceNULL	*n;
50636321Samurai	u_short bcount;
50736321Samurai
50841759Sdillon	if (q == NULL || (char *)(q + 1) > pmax)
50941759Sdillon		return(NULL);
51041759Sdillon
51136321Samurai	/* Forward to Resource NULL position */
51236321Samurai	n = (NBTNsResourceNULL *)( (u_char *)q + sizeof(NBTNsResource) );
51336321Samurai
51436321Samurai	/* Check out of length */
51536321Samurai	bcount = ntohs(q->rdlen);
51636321Samurai
51736321Samurai	/* Resource Record Name Filed */
51841759Sdillon	q = (NBTNsResource *)AliasHandleName( (u_char *)n, pmax ); /* XXX */
51936321Samurai
52041759Sdillon	if (q == NULL || (char *)((u_char *)n + bcount) > pmax)
52141759Sdillon		return(NULL);
52241759Sdillon	else
52336321Samurai	return ((u_char *)n + bcount);
52436321Samurai}
52536321Samurai
52636321Samuraitypedef struct {
52736321Samurai	u_short	numnames;
52836321Samurai} NBTNsResourceNBSTAT;
52936321Samurai
53041759Sdillonu_char *
53141759SdillonAliasHandleResourceNBSTAT(
53241759Sdillon    NBTNsResource *q,
53341759Sdillon    char *pmax,
53436321Samurai						 	       NBTArguments  *nbtarg)
53536321Samurai{
53636321Samurai	NBTNsResourceNBSTAT	*n;
53736321Samurai	u_short bcount;
53836321Samurai
53941759Sdillon	if (q == NULL || (char *)(q + 1) > pmax)
54041759Sdillon		return(NULL);
54141759Sdillon
54236321Samurai	/* Forward to Resource NBSTAT position */
54336321Samurai	n = (NBTNsResourceNBSTAT *)( (u_char *)q + sizeof(NBTNsResource) );
54436321Samurai
54536321Samurai	/* Check out of length */
54636321Samurai	bcount = ntohs(q->rdlen);
54736321Samurai
54841759Sdillon	if (q == NULL || (char *)((u_char *)n + bcount) > pmax)
54941759Sdillon		return(NULL);
55041759Sdillon	else
55136321Samurai	return ((u_char *)n + bcount);
55236321Samurai}
55336321Samurai
55441759Sdillonu_char *
55541759SdillonAliasHandleResource(
55641759Sdillon    u_short count,
55736321Samurai							NBTNsResource *q,
55841759Sdillon    char *pmax,
55941759Sdillon    NBTArguments
56041759Sdillon    *nbtarg)
56136321Samurai{
56236321Samurai	while ( count != 0 ) {
56336321Samurai		/* Resource Record Name Filed */
56441759Sdillon		q = (NBTNsResource *)AliasHandleName( (u_char *)q, pmax );
56541759Sdillon
56641759Sdillon		if (q == NULL || (char *)(q + 1) > pmax)
56741759Sdillon			break;
56836321Samurai#ifdef DEBUG
56936321Samurai		printf("type=%02x, count=%d\n", ntohs(q->type), count );
57036321Samurai#endif
57136321Samurai
57236321Samurai		/* Type and Class filed */
57336321Samurai		switch ( ntohs(q->type) ) {
57436321Samurai			case RR_TYPE_NB:
57541759Sdillon				q = (NBTNsResource *)AliasHandleResourceNB(
57641759Sdillon				    q,
57741759Sdillon				    pmax,
57841759Sdillon				    nbtarg
57941759Sdillon				);
58036321Samurai				break;
58136321Samurai			case RR_TYPE_A:
58241759Sdillon				q = (NBTNsResource *)AliasHandleResourceA(
58341759Sdillon				    q,
58441759Sdillon				    pmax,
58541759Sdillon				    nbtarg
58641759Sdillon				);
58736321Samurai				break;
58836321Samurai			case RR_TYPE_NS:
58941759Sdillon				q = (NBTNsResource *)AliasHandleResourceNS(
59041759Sdillon				    q,
59141759Sdillon				    pmax,
59241759Sdillon				    nbtarg
59341759Sdillon				);
59436321Samurai				break;
59536321Samurai			case RR_TYPE_NULL:
59641759Sdillon				q = (NBTNsResource *)AliasHandleResourceNULL(
59741759Sdillon				    q,
59841759Sdillon				    pmax,
59941759Sdillon				    nbtarg
60041759Sdillon				);
60136321Samurai				break;
60236321Samurai			case RR_TYPE_NBSTAT:
60341759Sdillon				q = (NBTNsResource *)AliasHandleResourceNBSTAT(
60441759Sdillon				    q,
60541759Sdillon				    pmax,
60641759Sdillon				    nbtarg
60741759Sdillon				);
60836321Samurai				break;
60941759Sdillon			default:
61041759Sdillon				printf(
61141759Sdillon				    "\nUnknown Type of Resource %0x\n",
61241759Sdillon				    ntohs(q->type)
61341759Sdillon				);
61436321Samurai				break;
61536321Samurai		}
61636321Samurai		count--;
61736321Samurai	}
61836321Samurai	fflush(stdout);
61936321Samurai	return ((u_char *)q);
62036321Samurai}
62136321Samurai
62241759Sdillonint AliasHandleUdpNbtNS(
62336321Samurai	struct ip 		  	*pip,	 /* IP packet to examine/patch */
62436321Samurai	struct alias_link 	*link,
62536321Samurai	struct in_addr		*alias_address,
62636321Samurai	u_short 			*alias_port,
62736321Samurai	struct in_addr		*original_address,
62836321Samurai	u_short 			*original_port )
62936321Samurai{
63036321Samurai    struct udphdr *	uh;
63136321Samurai	NbtNSHeader	  * nsh;
63236321Samurai	u_char		  * p;
63341759Sdillon	char		*pmax;
63436321Samurai	NBTArguments    nbtarg;
63536321Samurai
63636321Samurai	/* Set up Common Parameter */
63736321Samurai	nbtarg.oldaddr	=	*alias_address;
63836321Samurai	nbtarg.oldport	=	*alias_port;
63936321Samurai	nbtarg.newaddr	=	*original_address;
64036321Samurai	nbtarg.newport	=	*original_port;
64136321Samurai
64236321Samurai    /* Calculate data length of UDP packet */
64336321Samurai    uh =  (struct udphdr *) ((char *) pip + (pip->ip_hl << 2));
64436321Samurai	nbtarg.uh_sum	=	&(uh->uh_sum);
64536321Samurai	nsh = (NbtNSHeader *)((char *)uh + (sizeof(struct udphdr)));
64636321Samurai	p = (u_char *)(nsh + 1);
64741759Sdillon    pmax = (char *)uh + ntohs( uh->uh_ulen );
64836321Samurai
64941759Sdillon    if ((char *)(nsh + 1) > pmax)
65041759Sdillon	return(-1);
65141759Sdillon
65236321Samurai#ifdef DEBUG
65341759Sdillon    printf(" [%s] ID=%02x, op=%01x, flag=%02x, rcode=%01x, qd=%04x"
65441759Sdillon	   ", an=%04x, ns=%04x, ar=%04x, [%d]-->",
65536321Samurai		nsh->dir ? "Response": "Request",
65636321Samurai		nsh->nametrid,
65736321Samurai		nsh->opcode,
65836321Samurai		nsh->nmflags,
65936321Samurai		nsh->rcode,
66036321Samurai		ntohs(nsh->qdcount),
66136321Samurai		ntohs(nsh->ancount),
66236321Samurai		ntohs(nsh->nscount),
66336321Samurai		ntohs(nsh->arcount),
66441759Sdillon	(u_char *)p -(u_char *)nsh
66541759Sdillon    );
66636321Samurai#endif
66736321Samurai
66836321Samurai	/* Question Entries */
66936321Samurai	if (ntohs(nsh->qdcount) !=0 ) {
67041759Sdillon	p = AliasHandleQuestion(
67141759Sdillon	    ntohs(nsh->qdcount),
67241759Sdillon	    (NBTNsQuestion *)p,
67341759Sdillon	    pmax,
67441759Sdillon	    &nbtarg
67541759Sdillon	);
67636321Samurai	}
67736321Samurai
67836321Samurai	/* Answer Resource Records */
67936321Samurai	if (ntohs(nsh->ancount) !=0 ) {
68041759Sdillon	p = AliasHandleResource(
68141759Sdillon	    ntohs(nsh->ancount),
68241759Sdillon	    (NBTNsResource *)p,
68341759Sdillon	    pmax,
68441759Sdillon	    &nbtarg
68541759Sdillon	);
68636321Samurai	}
68736321Samurai
68836321Samurai	/* Authority Resource Recodrs */
68936321Samurai	if (ntohs(nsh->nscount) !=0 ) {
69041759Sdillon	p = AliasHandleResource(
69141759Sdillon	    ntohs(nsh->nscount),
69241759Sdillon	    (NBTNsResource *)p,
69341759Sdillon	    pmax,
69441759Sdillon	    &nbtarg
69541759Sdillon	);
69636321Samurai	}
69736321Samurai
69836321Samurai	/* Additional Resource Recodrs */
69936321Samurai	if (ntohs(nsh->arcount) !=0 ) {
70041759Sdillon	p = AliasHandleResource(
70141759Sdillon	    ntohs(nsh->arcount),
70241759Sdillon	    (NBTNsResource *)p,
70341759Sdillon	    pmax,
70441759Sdillon	    &nbtarg
70541759Sdillon	);
70636321Samurai	}
70736321Samurai
70836321Samurai#ifdef DEBUG
70936321Samurai	 	PrintRcode(nsh->rcode);
71036321Samurai#endif
71141759Sdillon    return ((p == NULL) ? -1 : 0);
71236321Samurai}
71341759Sdillon
714