alias_nbt.c revision 36321
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 *
1836321Samurai * $Id:$
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 */
13536321Samuraiu_char *AliasHandleName ( u_char *p ) {
13636321Samurai
13736321Samurai	u_char *s;
13836321Samurai	u_char c;
13936321Samurai	int		compress;
14036321Samurai
14136321Samurai	/* Following length field */
14236321Samurai	if (*p & 0xc0 ) {
14336321Samurai		p = p + 2;
14436321Samurai		return ((u_char *)p);
14536321Samurai	}
14636321Samurai	while ( ( *p & 0x3f) != 0x00 ) {
14736321Samurai		s = p + 1;
14836321Samurai		if ( *p == 0x20 )
14936321Samurai			compress = 1;
15036321Samurai		else
15136321Samurai			compress = 0;
15236321Samurai
15336321Samurai	 	/* Get next length field */
15436321Samurai		p = (u_char *)(p + (*p & 0x3f) + 1);
15536321Samurai#ifdef DEBUG
15636321Samurai		printf(":");
15736321Samurai#endif
15836321Samurai		while (s < p) {
15936321Samurai			if ( compress == 1 ) {
16036321Samurai				c = (u_char )(((((*s & 0x0f) << 4) | (*(s+1) & 0x0f)) - 0x11));
16136321Samurai#ifdef DEBUG
16236321Samurai				if (isprint( c ) )
16336321Samurai					printf("%c", c );
16436321Samurai				else
16536321Samurai					printf("<0x%02x>", c );
16636321Samurai#endif
16736321Samurai				s +=2;
16836321Samurai			} else {
16936321Samurai#ifdef DEBUG
17036321Samurai				printf("%c", *s);
17136321Samurai#endif
17236321Samurai				s++;
17336321Samurai			}
17436321Samurai		}
17536321Samurai#ifdef DEBUG
17636321Samurai		printf(":");
17736321Samurai#endif
17836321Samurai		fflush(stdout);
17936321Samurai    }
18036321Samurai
18136321Samurai	/* Set up to out of Name field */
18236321Samurai	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
19736321Samuraivoid AliasHandleUdpNbt(
19836321Samurai	struct ip 		  	*pip,	 /* IP packet to examine/patch */
19936321Samurai	struct alias_link 	*link,
20036321Samurai	struct in_addr		*alias_address,
20136321Samurai	u_short 			alias_port )
20236321Samurai{
20336321Samurai    struct udphdr *	uh;
20436321Samurai    NbtDataHeader 	*ndh;
20536321Samurai	u_char			*p;
20636321Samurai
20736321Samurai    /* Calculate data length of UDP packet */
20836321Samurai    uh =  (struct udphdr *) ((char *) pip + (pip->ip_hl << 2));
20936321Samurai	ndh = (NbtDataHeader *)((char *)uh + (sizeof (struct udphdr)));
21036321Samurai#ifdef DEBUG
21136321Samurai	printf("\nType=%02x,", ndh->type );
21236321Samurai#endif
21336321Samurai	switch ( ndh->type ) {
21436321Samurai		case DGM_DIRECT_UNIQ:
21536321Samurai		case DGM_DIRECT_GROUP:
21636321Samurai		case DGM_BROADCAST:
21736321Samurai			p = (u_char *)ndh + 14;
21836321Samurai			p = AliasHandleName ( p ); /* Source Name */
21936321Samurai			p = AliasHandleName ( p ); /* Destination Name */
22036321Samurai			break;
22136321Samurai		case DGM_ERROR:
22236321Samurai			p = (u_char *)ndh + 11;
22336321Samurai			break;
22436321Samurai		case DGM_QUERY:
22536321Samurai		case DGM_POSITIVE_RES:
22636321Samurai		case DGM_NEGATIVE_RES:
22736321Samurai			p = (u_char *)ndh + 10;
22836321Samurai			p = AliasHandleName ( p ); /* Destination Name */
22936321Samurai			break;
23036321Samurai	}
23136321Samurai#ifdef DEBUG
23236321Samurai	printf("%s:%d-->", inet_ntoa(ndh->source_ip), ntohs(ndh->source_port) );
23336321Samurai#endif
23436321Samurai	/* Doing a IP address and Port number Translation */
23536321Samurai	if ( uh->uh_sum != 0 ) {
23636321Samurai		int				acc;
23736321Samurai		u_short			*sptr;
23836321Samurai		acc  = ndh->source_port;
23936321Samurai		acc -= alias_port;
24036321Samurai		sptr = (u_short *) &(ndh->source_ip);
24136321Samurai		acc += *sptr++;
24236321Samurai		acc += *sptr;
24336321Samurai		sptr = (u_short *) alias_address;
24436321Samurai		acc -= *sptr++;
24536321Samurai		acc -= *sptr;
24636321Samurai		ADJUST_CHECKSUM(acc, uh->uh_sum)
24736321Samurai	}
24836321Samurai    ndh->source_ip = *alias_address;
24936321Samurai    ndh->source_port = alias_port;
25036321Samurai#ifdef DEBUG
25136321Samurai	printf("%s:%d\n", inet_ntoa(ndh->source_ip), ntohs(ndh->source_port) );
25236321Samurai	fflush(stdout);
25336321Samurai#endif
25436321Samurai}
25536321Samurai/* Question Section */
25636321Samurai#define QS_TYPE_NB		0x0020
25736321Samurai#define QS_TYPE_NBSTAT	0x0021
25836321Samurai#define QS_CLAS_IN		0x0001
25936321Samuraitypedef struct {
26036321Samurai	u_short	type;	/* The type of Request */
26136321Samurai	u_short	class;	/* The class of Request */
26236321Samurai} NBTNsQuestion;
26336321Samurai
26436321Samuraiu_char *AliasHandleQuestion(u_short count,
26536321Samurai							NBTNsQuestion *q,
26636321Samurai							NBTArguments  *nbtarg)
26736321Samurai{
26836321Samurai
26936321Samurai	while ( count != 0 ) {
27036321Samurai		/* Name Filed */
27136321Samurai		q = (NBTNsQuestion *)AliasHandleName((u_char *)q );
27236321Samurai
27336321Samurai		/* Type and Class filed */
27436321Samurai		switch ( ntohs(q->type) ) {
27536321Samurai			case QS_TYPE_NB:
27636321Samurai			case QS_TYPE_NBSTAT:
27736321Samurai				q= q+1;
27836321Samurai			break;
27936321Samurai			default:
28036321Samurai				printf("\nUnknown Type on Question %0x\n", ntohs(q->type) );
28136321Samurai			break;
28236321Samurai		}
28336321Samurai		count--;
28436321Samurai	}
28536321Samurai
28636321Samurai	/* Set up to out of Question Section */
28736321Samurai	return ((u_char *)q);
28836321Samurai}
28936321Samurai
29036321Samurai/* Resource Record */
29136321Samurai#define RR_TYPE_A		0x0001
29236321Samurai#define RR_TYPE_NS		0x0002
29336321Samurai#define RR_TYPE_NULL	0x000a
29436321Samurai#define RR_TYPE_NB		0x0020
29536321Samurai#define RR_TYPE_NBSTAT	0x0021
29636321Samurai#define RR_CLAS_IN		0x0001
29736321Samurai#define SizeOfNsResource	8
29836321Samuraitypedef struct {
29936321Samurai 	u_short type;
30036321Samurai 	u_short class;
30136321Samurai 	unsigned int ttl;
30236321Samurai 	u_short rdlen;
30336321Samurai} NBTNsResource;
30436321Samurai
30536321Samurai#define SizeOfNsRNB			6
30636321Samuraitypedef struct {
30736321Samurai	u_short g:1, ont:2, resv:13;
30836321Samurai	struct	in_addr	addr;
30936321Samurai} NBTNsRNB;
31036321Samurai
31136321Samuraiu_char *AliasHandleResourceNB( NBTNsResource *q,
31236321Samurai							   NBTArguments  *nbtarg)
31336321Samurai{
31436321Samurai	NBTNsRNB	*nb;
31536321Samurai	u_short bcount;
31636321Samurai
31736321Samurai	/* Check out a length */
31836321Samurai	bcount = ntohs(q->rdlen);
31936321Samurai
32036321Samurai	/* Forward to Resource NB position */
32136321Samurai	nb = (NBTNsRNB *)((u_char *)q + SizeOfNsResource);
32236321Samurai
32336321Samurai	/* Processing all in_addr array */
32436321Samurai#ifdef DEBUG
32536321Samurai	printf("NB rec[%s", inet_ntoa(nbtarg->oldaddr));
32636321Samurai            printf("->%s, %dbytes] ",inet_ntoa(nbtarg->newaddr ), bcount);
32736321Samurai#endif
32836321Samurai	while ( bcount != 0 )  {
32936321Samurai#ifdef DEBUG
33036321Samurai		printf("<%s>", inet_ntoa(nb->addr) );
33136321Samurai#endif
33236321Samurai		if (!bcmp(&nbtarg->oldaddr,&nb->addr, sizeof(struct in_addr) ) ) {
33336321Samurai			if ( *nbtarg->uh_sum != 0 ) {
33436321Samurai            	int acc;
33536321Samurai            	u_short *sptr;
33636321Samurai
33736321Samurai            	sptr = (u_short *) &(nb->addr);
33836321Samurai            	acc = *sptr++;
33936321Samurai            	acc += *sptr;
34036321Samurai            	sptr = (u_short *) &(nbtarg->newaddr);
34136321Samurai            	acc -= *sptr++;
34236321Samurai            	acc -= *sptr;
34336321Samurai            	ADJUST_CHECKSUM(acc, *nbtarg->uh_sum)
34436321Samurai			}
34536321Samurai
34636321Samurai			nb->addr = nbtarg->newaddr;
34736321Samurai#ifdef DEBUG
34836321Samurai			printf("O");
34936321Samurai#endif
35036321Samurai		}
35136321Samurai#ifdef DEBUG
35236321Samurai		 else {
35336321Samurai			printf(".");
35436321Samurai		}
35536321Samurai#endif
35636321Samurai		nb=(NBTNsRNB *)((u_char *)nb + SizeOfNsRNB);
35736321Samurai	 	bcount -= SizeOfNsRNB;
35836321Samurai	}
35936321Samurai
36036321Samurai	return ((u_char *)nb);
36136321Samurai}
36236321Samurai
36336321Samurai#define SizeOfResourceA		6
36436321Samuraitypedef struct {
36536321Samurai	struct	in_addr	addr;
36636321Samurai} NBTNsResourceA;
36736321Samurai
36836321Samuraiu_char *AliasHandleResourceA( NBTNsResource *q,
36936321Samurai						 	  NBTArguments  *nbtarg)
37036321Samurai{
37136321Samurai	NBTNsResourceA	*a;
37236321Samurai	u_short bcount;
37336321Samurai
37436321Samurai	/* Forward to Resource A position */
37536321Samurai	a = (NBTNsResourceA *)( (u_char *)q + sizeof(NBTNsResource) );
37636321Samurai
37736321Samurai	/* Check out of length */
37836321Samurai	bcount = ntohs(q->rdlen);
37936321Samurai
38036321Samurai	/* Processing all in_addr array */
38136321Samurai#ifdef DEBUG
38236321Samurai	printf("Arec [%s", inet_ntoa(nbtarg->oldaddr));
38336321Samurai        printf("->%s]",inet_ntoa(nbtarg->newaddr ));
38436321Samurai#endif
38536321Samurai	while ( bcount != 0 )  {
38636321Samurai#ifdef DEBUG
38736321Samurai		printf("..%s", inet_ntoa(a->addr) );
38836321Samurai#endif
38936321Samurai		if ( !bcmp(&nbtarg->oldaddr, &a->addr, sizeof(struct in_addr) ) ) {
39036321Samurai			if ( *nbtarg->uh_sum != 0 ) {
39136321Samurai            	int acc;
39236321Samurai            	u_short *sptr;
39336321Samurai
39436321Samurai            	sptr = (u_short *) &(a->addr);		 /* Old */
39536321Samurai            	acc = *sptr++;
39636321Samurai            	acc += *sptr;
39736321Samurai            	sptr = (u_short *) &nbtarg->newaddr; /* New */
39836321Samurai            	acc -= *sptr++;
39936321Samurai            	acc -= *sptr;
40036321Samurai            	ADJUST_CHECKSUM(acc, *nbtarg->uh_sum)
40136321Samurai			}
40236321Samurai
40336321Samurai			a->addr = nbtarg->newaddr;
40436321Samurai		}
40536321Samurai		a++;	/*XXXX*/
40636321Samurai		bcount -= SizeOfResourceA;
40736321Samurai	}
40836321Samurai	return ((u_char *)a);
40936321Samurai}
41036321Samurai
41136321Samuraitypedef struct {
41236321Samurai	u_short opcode:4, flags:8, resv:4;
41336321Samurai} NBTNsResourceNULL;
41436321Samurai
41536321Samuraiu_char *AliasHandleResourceNULL( NBTNsResource *q,
41636321Samurai						 	     NBTArguments  *nbtarg)
41736321Samurai{
41836321Samurai	NBTNsResourceNULL	*n;
41936321Samurai	u_short bcount;
42036321Samurai
42136321Samurai	/* Forward to Resource NULL position */
42236321Samurai	n = (NBTNsResourceNULL *)( (u_char *)q + sizeof(NBTNsResource) );
42336321Samurai
42436321Samurai	/* Check out of length */
42536321Samurai	bcount = ntohs(q->rdlen);
42636321Samurai
42736321Samurai	/* Processing all in_addr array */
42836321Samurai	while ( bcount != 0 )  {
42936321Samurai		n++;
43036321Samurai		bcount -= sizeof(NBTNsResourceNULL);
43136321Samurai	}
43236321Samurai
43336321Samurai	return ((u_char *)n);
43436321Samurai}
43536321Samurai
43636321Samuraiu_char *AliasHandleResourceNS( NBTNsResource *q,
43736321Samurai						 	     NBTArguments  *nbtarg)
43836321Samurai{
43936321Samurai	NBTNsResourceNULL	*n;
44036321Samurai	u_short bcount;
44136321Samurai
44236321Samurai	/* Forward to Resource NULL position */
44336321Samurai	n = (NBTNsResourceNULL *)( (u_char *)q + sizeof(NBTNsResource) );
44436321Samurai
44536321Samurai	/* Check out of length */
44636321Samurai	bcount = ntohs(q->rdlen);
44736321Samurai
44836321Samurai	/* Resource Record Name Filed */
44936321Samurai	q = (NBTNsResource *)AliasHandleName( (u_char *)n ); /* XXX */
45036321Samurai
45136321Samurai	return ((u_char *)n + bcount);
45236321Samurai}
45336321Samurai
45436321Samuraitypedef struct {
45536321Samurai	u_short	numnames;
45636321Samurai} NBTNsResourceNBSTAT;
45736321Samurai
45836321Samuraiu_char *AliasHandleResourceNBSTAT( NBTNsResource *q,
45936321Samurai						 	       NBTArguments  *nbtarg)
46036321Samurai{
46136321Samurai	NBTNsResourceNBSTAT	*n;
46236321Samurai	u_short bcount;
46336321Samurai
46436321Samurai	/* Forward to Resource NBSTAT position */
46536321Samurai	n = (NBTNsResourceNBSTAT *)( (u_char *)q + sizeof(NBTNsResource) );
46636321Samurai
46736321Samurai	/* Check out of length */
46836321Samurai	bcount = ntohs(q->rdlen);
46936321Samurai
47036321Samurai	return ((u_char *)n + bcount);
47136321Samurai}
47236321Samurai
47336321Samuraiu_char *AliasHandleResource(u_short count,
47436321Samurai							NBTNsResource *q,
47536321Samurai							NBTArguments  *nbtarg)
47636321Samurai{
47736321Samurai	while ( count != 0 ) {
47836321Samurai		/* Resource Record Name Filed */
47936321Samurai		q = (NBTNsResource *)AliasHandleName( (u_char *)q );
48036321Samurai#ifdef DEBUG
48136321Samurai		printf("type=%02x, count=%d\n", ntohs(q->type), count );
48236321Samurai#endif
48336321Samurai
48436321Samurai		/* Type and Class filed */
48536321Samurai		switch ( ntohs(q->type) ) {
48636321Samurai			case RR_TYPE_NB:
48736321Samurai				q = (NBTNsResource *)AliasHandleResourceNB( q, nbtarg );
48836321Samurai				break;
48936321Samurai			case RR_TYPE_A:
49036321Samurai				q = (NBTNsResource *)AliasHandleResourceA( q, nbtarg );
49136321Samurai				break;
49236321Samurai			case RR_TYPE_NS:
49336321Samurai				q = (NBTNsResource *)AliasHandleResourceNS( q, nbtarg );
49436321Samurai				break;
49536321Samurai			case RR_TYPE_NULL:
49636321Samurai				q = (NBTNsResource *)AliasHandleResourceNULL( q, nbtarg );
49736321Samurai				break;
49836321Samurai			case RR_TYPE_NBSTAT:
49936321Samurai				q = (NBTNsResource *)AliasHandleResourceNBSTAT( q, nbtarg );
50036321Samurai				break;
50136321Samurai			default: printf("\nUnknown Type of Resource %0x\n",
50236321Samurai								 ntohs(q->type) );
50336321Samurai				break;
50436321Samurai		}
50536321Samurai		count--;
50636321Samurai	}
50736321Samurai	fflush(stdout);
50836321Samurai	return ((u_char *)q);
50936321Samurai}
51036321Samurai
51136321Samuraivoid AliasHandleUdpNbtNS(
51236321Samurai	struct ip 		  	*pip,	 /* IP packet to examine/patch */
51336321Samurai	struct alias_link 	*link,
51436321Samurai	struct in_addr		*alias_address,
51536321Samurai	u_short 			*alias_port,
51636321Samurai	struct in_addr		*original_address,
51736321Samurai	u_short 			*original_port )
51836321Samurai{
51936321Samurai    struct udphdr *	uh;
52036321Samurai	NbtNSHeader	  * nsh;
52136321Samurai	u_short		    dlen;
52236321Samurai	u_char		  * p;
52336321Samurai	NBTArguments    nbtarg;
52436321Samurai
52536321Samurai	/* Set up Common Parameter */
52636321Samurai	nbtarg.oldaddr	=	*alias_address;
52736321Samurai	nbtarg.oldport	=	*alias_port;
52836321Samurai	nbtarg.newaddr	=	*original_address;
52936321Samurai	nbtarg.newport	=	*original_port;
53036321Samurai
53136321Samurai    /* Calculate data length of UDP packet */
53236321Samurai    uh =  (struct udphdr *) ((char *) pip + (pip->ip_hl << 2));
53336321Samurai	nbtarg.uh_sum	=	&(uh->uh_sum);
53436321Samurai    dlen = ntohs( uh->uh_ulen );
53536321Samurai	nsh = (NbtNSHeader *)((char *)uh + (sizeof(struct udphdr)));
53636321Samurai	p = (u_char *)(nsh + 1);
53736321Samurai
53836321Samurai#ifdef DEBUG
53936321Samurai	printf(" [%s] ID=%02x, op=%01x, flag=%02x, rcode=%01x, qd=%04x, an=%04x, ns=%04x, ar=%04x, [%d]-->",
54036321Samurai		nsh->dir ? "Response": "Request",
54136321Samurai		nsh->nametrid,
54236321Samurai		nsh->opcode,
54336321Samurai		nsh->nmflags,
54436321Samurai		nsh->rcode,
54536321Samurai		ntohs(nsh->qdcount),
54636321Samurai		ntohs(nsh->ancount),
54736321Samurai		ntohs(nsh->nscount),
54836321Samurai		ntohs(nsh->arcount),
54936321Samurai		(u_char *)p -(u_char *)nsh);
55036321Samurai#endif
55136321Samurai
55236321Samurai	/* Question Entries */
55336321Samurai	if (ntohs(nsh->qdcount) !=0 ) {
55436321Samurai	p = AliasHandleQuestion(ntohs(nsh->qdcount), (NBTNsQuestion *)p, &nbtarg );
55536321Samurai	}
55636321Samurai
55736321Samurai	/* Answer Resource Records */
55836321Samurai	if (ntohs(nsh->ancount) !=0 ) {
55936321Samurai	p = AliasHandleResource(ntohs(nsh->ancount), (NBTNsResource *)p, &nbtarg );
56036321Samurai	}
56136321Samurai
56236321Samurai	/* Authority Resource Recodrs */
56336321Samurai	if (ntohs(nsh->nscount) !=0 ) {
56436321Samurai	p = AliasHandleResource(ntohs(nsh->nscount), (NBTNsResource *)p, &nbtarg );
56536321Samurai	}
56636321Samurai
56736321Samurai	/* Additional Resource Recodrs */
56836321Samurai	if (ntohs(nsh->arcount) !=0 ) {
56936321Samurai	p = AliasHandleResource(ntohs(nsh->arcount), (NBTNsResource *)p, &nbtarg );
57036321Samurai	}
57136321Samurai
57236321Samurai#ifdef DEBUG
57336321Samurai	 	PrintRcode(nsh->rcode);
57436321Samurai#endif
57536321Samurai	return;
57636321Samurai}
577