alias_nbt.c revision 127094
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 *  TODO:
2799207Sbrian *       oClean up.
2836321Samurai *       oConsidering for word alignment for other platform.
2936321Samurai */
3084195Sdillon
3184195Sdillon#include <sys/cdefs.h>
3284195Sdillon__FBSDID("$FreeBSD: head/sys/netinet/libalias/alias_nbt.c 127094 2004-03-16 21:30:41Z des $");
3384195Sdillon
3436321Samurai/*
3536321Samurai    alias_nbt.c performs special processing for NetBios over TCP/IP
3636321Samurai    sessions by UDP.
3736321Samurai
3836321Samurai    Initial version:  May, 1998  (Atsushi Murai <amurai@spec.co.jp>)
3936321Samurai
4036321Samurai    See HISTORY file for record of revisions.
4136321Samurai*/
4236321Samurai
4336321Samurai/* Includes */
4436321Samurai#include <ctype.h>
4599207Sbrian#include <stdio.h>
4636321Samurai#include <string.h>
4736321Samurai#include <sys/types.h>
4836321Samurai#include <netinet/in_systm.h>
4936321Samurai#include <netinet/in.h>
5036321Samurai#include <arpa/inet.h>
5136321Samurai#include <netinet/ip.h>
5236321Samurai#include <netinet/udp.h>
5336321Samurai#include <netinet/tcp.h>
5436321Samurai
5536321Samurai#include "alias_local.h"
5636321Samurai
5736321Samuraitypedef struct {
58127094Sdes	struct in_addr	oldaddr;
59127094Sdes	u_short		oldport;
60127094Sdes	struct in_addr	newaddr;
61127094Sdes	u_short		newport;
62127094Sdes	u_short        *uh_sum;
63127094Sdes}		NBTArguments;
6436321Samurai
6536321Samuraitypedef struct {
66127094Sdes	unsigned char	type;
67127094Sdes	unsigned char	flags;
68127094Sdes	u_short		id;
69127094Sdes	struct in_addr	source_ip;
70127094Sdes	u_short		source_port;
71127094Sdes	u_short		len;
72127094Sdes	u_short		offset;
73127094Sdes}		NbtDataHeader;
7436321Samurai
7536321Samurai#define OpQuery		0
7636321Samurai#define OpUnknown	4
7736321Samurai#define OpRegist	5
7836321Samurai#define OpRelease	6
7936321Samurai#define OpWACK		7
8036321Samurai#define OpRefresh	8
8136321Samuraitypedef struct {
82127094Sdes	u_short		nametrid;
83127094Sdes	u_short		dir:	1, opcode:4, nmflags:7, rcode:4;
84127094Sdes	u_short		qdcount;
85127094Sdes	u_short		ancount;
86127094Sdes	u_short		nscount;
87127094Sdes	u_short		arcount;
88127094Sdes}		NbtNSHeader;
8936321Samurai
9036321Samurai#define FMT_ERR		0x1
9136321Samurai#define SRV_ERR		0x2
9236321Samurai#define IMP_ERR		0x4
9336321Samurai#define RFS_ERR		0x5
9436321Samurai#define ACT_ERR		0x6
9536321Samurai#define CFT_ERR		0x7
9636321Samurai
9736321Samurai
9844616Sbrian#ifdef DEBUG
99127094Sdesstatic void
100127094SdesPrintRcode(u_char rcode)
101127094Sdes{
10236321Samurai
10336321Samurai	switch (rcode) {
10436321Samurai		case FMT_ERR:
105127094Sdes		printf("\nFormat Error.");
106127094Sdes	case SRV_ERR:
107127094Sdes		printf("\nSever failure.");
108127094Sdes	case IMP_ERR:
109127094Sdes		printf("\nUnsupported request error.\n");
110127094Sdes	case RFS_ERR:
111127094Sdes		printf("\nRefused error.\n");
112127094Sdes	case ACT_ERR:
113127094Sdes		printf("\nActive error.\n");
114127094Sdes	case CFT_ERR:
115127094Sdes		printf("\nName in conflict error.\n");
116127094Sdes	default:
117127094Sdes		printf("\n?%c?=%0x\n", '?', rcode);
11836321Samurai
11999207Sbrian	}
12036321Samurai}
121127094Sdes
12244616Sbrian#endif
12336321Samurai
12436321Samurai
12536321Samurai/* Handling Name field */
126127094Sdesstatic u_char  *
127127094SdesAliasHandleName(u_char * p, char *pmax)
128127094Sdes{
12936321Samurai
13036321Samurai	u_char *s;
13136321Samurai	u_char c;
132127094Sdes	int compress;
13336321Samurai
13436321Samurai	/* Following length field */
13541759Sdillon
13641759Sdillon	if (p == NULL || (char *)p >= pmax)
137127094Sdes		return (NULL);
13841759Sdillon
139127094Sdes	if (*p & 0xc0) {
14036321Samurai		p = p + 2;
14141759Sdillon		if ((char *)p > pmax)
142127094Sdes			return (NULL);
143127094Sdes		return ((u_char *) p);
14436321Samurai	}
145127094Sdes	while ((*p & 0x3f) != 0x00) {
14636321Samurai		s = p + 1;
147127094Sdes		if (*p == 0x20)
14836321Samurai			compress = 1;
14936321Samurai		else
15036321Samurai			compress = 0;
15199207Sbrian
152127094Sdes		/* Get next length field */
153127094Sdes		p = (u_char *) (p + (*p & 0x3f) + 1);
15441759Sdillon		if ((char *)p > pmax) {
15541759Sdillon			p = NULL;
15641759Sdillon			break;
15741759Sdillon		}
15836321Samurai#ifdef DEBUG
15936321Samurai		printf(":");
16036321Samurai#endif
16136321Samurai		while (s < p) {
162127094Sdes			if (compress == 1) {
163127094Sdes				c = (u_char) (((((*s & 0x0f) << 4) | (*(s + 1) & 0x0f)) - 0x11));
16436321Samurai#ifdef DEBUG
165127094Sdes				if (isprint(c))
166127094Sdes					printf("%c", c);
16736321Samurai				else
168127094Sdes					printf("<0x%02x>", c);
16936321Samurai#endif
170127094Sdes				s += 2;
17136321Samurai			} else {
17236321Samurai#ifdef DEBUG
17336321Samurai				printf("%c", *s);
17436321Samurai#endif
17536321Samurai				s++;
17636321Samurai			}
17736321Samurai		}
17836321Samurai#ifdef DEBUG
17936321Samurai		printf(":");
18036321Samurai#endif
18136321Samurai		fflush(stdout);
182127094Sdes	}
18336321Samurai
18436321Samurai	/* Set up to out of Name field */
18541759Sdillon	if (p == NULL || (char *)p >= pmax)
186127094Sdes		p = NULL;
18741759Sdillon	else
188127094Sdes		p++;
189127094Sdes	return ((u_char *) p);
19036321Samurai}
19136321Samurai
19299207Sbrian/*
19336321Samurai * NetBios Datagram Handler (IP/UDP)
19436321Samurai */
19536321Samurai#define DGM_DIRECT_UNIQ		0x10
19636321Samurai#define DGM_DIRECT_GROUP	0x11
19736321Samurai#define DGM_BROADCAST		0x12
19836321Samurai#define DGM_ERROR			0x13
19936321Samurai#define DGM_QUERY			0x14
20036321Samurai#define DGM_POSITIVE_RES	0x15
20136321Samurai#define DGM_NEGATIVE_RES	0x16
20236321Samurai
203127094Sdesint
204127094SdesAliasHandleUdpNbt(
205127094Sdes    struct libalias *la,
206127094Sdes    struct ip *pip,		/* IP packet to examine/patch */
207127094Sdes    struct alias_link *link,
208127094Sdes    struct in_addr *alias_address,
209127094Sdes    u_short alias_port
210127094Sdes)
211127094Sdes{
212127094Sdes	struct udphdr *uh;
213127094Sdes	NbtDataHeader *ndh;
214127094Sdes	u_char *p = NULL;
215127094Sdes	char *pmax;
21699207Sbrian
217127094Sdes	/* Calculate data length of UDP packet */
218127094Sdes	uh = (struct udphdr *)((char *)pip + (pip->ip_hl << 2));
219127094Sdes	pmax = (char *)uh + ntohs(uh->uh_ulen);
22041759Sdillon
221127094Sdes	ndh = (NbtDataHeader *) ((char *)uh + (sizeof(struct udphdr)));
222127094Sdes	if ((char *)(ndh + 1) > pmax)
223127094Sdes		return (-1);
22436321Samurai#ifdef DEBUG
225127094Sdes	printf("\nType=%02x,", ndh->type);
22636321Samurai#endif
227127094Sdes	switch (ndh->type) {
228127094Sdes	case DGM_DIRECT_UNIQ:
229127094Sdes	case DGM_DIRECT_GROUP:
230127094Sdes	case DGM_BROADCAST:
231127094Sdes		p = (u_char *) ndh + 14;
232127094Sdes		p = AliasHandleName(p, pmax);	/* Source Name */
233127094Sdes		p = AliasHandleName(p, pmax);	/* Destination Name */
234127094Sdes		break;
235127094Sdes	case DGM_ERROR:
236127094Sdes		p = (u_char *) ndh + 11;
237127094Sdes		break;
238127094Sdes	case DGM_QUERY:
239127094Sdes	case DGM_POSITIVE_RES:
240127094Sdes	case DGM_NEGATIVE_RES:
241127094Sdes		p = (u_char *) ndh + 10;
242127094Sdes		p = AliasHandleName(p, pmax);	/* Destination Name */
243127094Sdes		break;
24436321Samurai	}
245127094Sdes	if (p == NULL || (char *)p > pmax)
246127094Sdes		p = NULL;
24736321Samurai#ifdef DEBUG
248127094Sdes	printf("%s:%d-->", inet_ntoa(ndh->source_ip), ntohs(ndh->source_port));
24936321Samurai#endif
250108533Sschweikh	/* Doing an IP address and Port number Translation */
251127094Sdes	if (uh->uh_sum != 0) {
252127094Sdes		int acc;
253127094Sdes		u_short *sptr;
254127094Sdes
255127094Sdes		acc = ndh->source_port;
25636321Samurai		acc -= alias_port;
257127094Sdes		sptr = (u_short *) & (ndh->source_ip);
25836321Samurai		acc += *sptr++;
25936321Samurai		acc += *sptr;
26036321Samurai		sptr = (u_short *) alias_address;
26136321Samurai		acc -= *sptr++;
26236321Samurai		acc -= *sptr;
26374778Sbrian		ADJUST_CHECKSUM(acc, uh->uh_sum);
26436321Samurai	}
265127094Sdes	ndh->source_ip = *alias_address;
266127094Sdes	ndh->source_port = alias_port;
26736321Samurai#ifdef DEBUG
268127094Sdes	printf("%s:%d\n", inet_ntoa(ndh->source_ip), ntohs(ndh->source_port));
26936321Samurai	fflush(stdout);
27036321Samurai#endif
271127094Sdes	return ((p == NULL) ? -1 : 0);
27236321Samurai}
273127094Sdes
27436321Samurai/* Question Section */
27536321Samurai#define QS_TYPE_NB		0x0020
27636321Samurai#define QS_TYPE_NBSTAT	0x0021
27736321Samurai#define QS_CLAS_IN		0x0001
27836321Samuraitypedef struct {
279127094Sdes	u_short		type;	/* The type of Request */
280127094Sdes	u_short		class;	/* The class of Request */
281127094Sdes}		NBTNsQuestion;
28236321Samurai
283127094Sdesstatic u_char  *
28441759SdillonAliasHandleQuestion(
28541759Sdillon    u_short count,
286127094Sdes    NBTNsQuestion * q,
28741759Sdillon    char *pmax,
288127094Sdes    NBTArguments * nbtarg)
28936321Samurai{
29036321Samurai
291127094Sdes	while (count != 0) {
29236321Samurai		/* Name Filed */
293127094Sdes		q = (NBTNsQuestion *) AliasHandleName((u_char *) q, pmax);
29436321Samurai
29541759Sdillon		if (q == NULL || (char *)(q + 1) > pmax) {
29641759Sdillon			q = NULL;
29741759Sdillon			break;
29841759Sdillon		}
29936321Samurai		/* Type and Class filed */
300127094Sdes		switch (ntohs(q->type)) {
301127094Sdes		case QS_TYPE_NB:
302127094Sdes		case QS_TYPE_NBSTAT:
303127094Sdes			q = q + 1;
30436321Samurai			break;
305127094Sdes		default:
30644616Sbrian#ifdef DEBUG
307127094Sdes			printf("\nUnknown Type on Question %0x\n", ntohs(q->type));
30844616Sbrian#endif
30936321Samurai			break;
31036321Samurai		}
31136321Samurai		count--;
31236321Samurai	}
31336321Samurai
31436321Samurai	/* Set up to out of Question Section */
315127094Sdes	return ((u_char *) q);
31636321Samurai}
31736321Samurai
31836321Samurai/* Resource Record */
31936321Samurai#define RR_TYPE_A		0x0001
32036321Samurai#define RR_TYPE_NS		0x0002
32136321Samurai#define RR_TYPE_NULL	0x000a
32236321Samurai#define RR_TYPE_NB		0x0020
32336321Samurai#define RR_TYPE_NBSTAT	0x0021
32436321Samurai#define RR_CLAS_IN		0x0001
32536321Samurai#define SizeOfNsResource	8
32636321Samuraitypedef struct {
327127094Sdes	u_short		type;
328127094Sdes	u_short		class;
329127094Sdes	unsigned int	ttl;
330127094Sdes	u_short		rdlen;
331127094Sdes}		NBTNsResource;
33236321Samurai
33336321Samurai#define SizeOfNsRNB			6
33436321Samuraitypedef struct {
335127094Sdes	u_short		g:	1  , ont:2, resv:13;
336127094Sdes	struct in_addr	addr;
337127094Sdes}		NBTNsRNB;
33836321Samurai
339127094Sdesstatic u_char  *
34099207SbrianAliasHandleResourceNB(
341127094Sdes    NBTNsResource * q,
34299207Sbrian    char *pmax,
343127094Sdes    NBTArguments * nbtarg)
34436321Samurai{
345127094Sdes	NBTNsRNB *nb;
34636321Samurai	u_short bcount;
34736321Samurai
34841759Sdillon	if (q == NULL || (char *)(q + 1) > pmax)
349127094Sdes		return (NULL);
35036321Samurai	/* Check out a length */
35136321Samurai	bcount = ntohs(q->rdlen);
35236321Samurai
35336321Samurai	/* Forward to Resource NB position */
354127094Sdes	nb = (NBTNsRNB *) ((u_char *) q + SizeOfNsResource);
35536321Samurai
35636321Samurai	/* Processing all in_addr array */
35736321Samurai#ifdef DEBUG
35836321Samurai	printf("NB rec[%s", inet_ntoa(nbtarg->oldaddr));
359127094Sdes	printf("->%s, %dbytes] ", inet_ntoa(nbtarg->newaddr), bcount);
36036321Samurai#endif
361127094Sdes	while (nb != NULL && bcount != 0) {
36241759Sdillon		if ((char *)(nb + 1) > pmax) {
36341759Sdillon			nb = NULL;
36441759Sdillon			break;
36541759Sdillon		}
36636321Samurai#ifdef DEBUG
367127094Sdes		printf("<%s>", inet_ntoa(nb->addr));
36836321Samurai#endif
369127094Sdes		if (!bcmp(&nbtarg->oldaddr, &nb->addr, sizeof(struct in_addr))) {
370127094Sdes			if (*nbtarg->uh_sum != 0) {
371127094Sdes				int acc;
372127094Sdes				u_short *sptr;
37336321Samurai
374127094Sdes				sptr = (u_short *) & (nb->addr);
375127094Sdes				acc = *sptr++;
376127094Sdes				acc += *sptr;
377127094Sdes				sptr = (u_short *) & (nbtarg->newaddr);
378127094Sdes				acc -= *sptr++;
379127094Sdes				acc -= *sptr;
380127094Sdes				ADJUST_CHECKSUM(acc, *nbtarg->uh_sum);
38136321Samurai			}
38236321Samurai			nb->addr = nbtarg->newaddr;
38336321Samurai#ifdef DEBUG
38436321Samurai			printf("O");
38536321Samurai#endif
38636321Samurai		}
38736321Samurai#ifdef DEBUG
388127094Sdes		else {
38936321Samurai			printf(".");
39036321Samurai		}
39136321Samurai#endif
392127094Sdes		nb = (NBTNsRNB *) ((u_char *) nb + SizeOfNsRNB);
393127094Sdes		bcount -= SizeOfNsRNB;
39436321Samurai	}
39541759Sdillon	if (nb == NULL || (char *)(nb + 1) > pmax) {
39641759Sdillon		nb = NULL;
39741759Sdillon	}
398127094Sdes	return ((u_char *) nb);
39936321Samurai}
40036321Samurai
40136321Samurai#define SizeOfResourceA		6
40236321Samuraitypedef struct {
403127094Sdes	struct in_addr	addr;
404127094Sdes}		NBTNsResourceA;
40536321Samurai
406127094Sdesstatic u_char  *
40799207SbrianAliasHandleResourceA(
408127094Sdes    NBTNsResource * q,
40941759Sdillon    char *pmax,
410127094Sdes    NBTArguments * nbtarg)
41136321Samurai{
412127094Sdes	NBTNsResourceA *a;
41336321Samurai	u_short bcount;
41436321Samurai
41541759Sdillon	if (q == NULL || (char *)(q + 1) > pmax)
416127094Sdes		return (NULL);
41741759Sdillon
41836321Samurai	/* Forward to Resource A position */
419127094Sdes	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));
427127094Sdes	printf("->%s]", inet_ntoa(nbtarg->newaddr));
42836321Samurai#endif
429127094Sdes	while (bcount != 0) {
43041759Sdillon		if (a == NULL || (char *)(a + 1) > pmax)
431127094Sdes			return (NULL);
43236321Samurai#ifdef DEBUG
433127094Sdes		printf("..%s", inet_ntoa(a->addr));
43436321Samurai#endif
435127094Sdes		if (!bcmp(&nbtarg->oldaddr, &a->addr, sizeof(struct in_addr))) {
436127094Sdes			if (*nbtarg->uh_sum != 0) {
437127094Sdes				int acc;
438127094Sdes				u_short *sptr;
43936321Samurai
440127094Sdes				sptr = (u_short *) & (a->addr);	/* Old */
441127094Sdes				acc = *sptr++;
442127094Sdes				acc += *sptr;
443127094Sdes				sptr = (u_short *) & nbtarg->newaddr;	/* New */
444127094Sdes				acc -= *sptr++;
445127094Sdes				acc -= *sptr;
446127094Sdes				ADJUST_CHECKSUM(acc, *nbtarg->uh_sum);
44736321Samurai			}
44836321Samurai			a->addr = nbtarg->newaddr;
44936321Samurai		}
450127094Sdes		a++;		/* XXXX */
45136321Samurai		bcount -= SizeOfResourceA;
45236321Samurai	}
45341759Sdillon	if (a == NULL || (char *)(a + 1) > pmax)
454127094Sdes		a = NULL;
455127094Sdes	return ((u_char *) a);
45636321Samurai}
45736321Samurai
45836321Samuraitypedef struct {
459127094Sdes	u_short		opcode:4, flags:8, resv:4;
460127094Sdes}		NBTNsResourceNULL;
46136321Samurai
462127094Sdesstatic u_char  *
46399207SbrianAliasHandleResourceNULL(
464127094Sdes    NBTNsResource * q,
46541759Sdillon    char *pmax,
466127094Sdes    NBTArguments * nbtarg)
46736321Samurai{
468127094Sdes	NBTNsResourceNULL *n;
46936321Samurai	u_short bcount;
47036321Samurai
47141759Sdillon	if (q == NULL || (char *)(q + 1) > pmax)
472127094Sdes		return (NULL);
47341759Sdillon
47436321Samurai	/* Forward to Resource NULL position */
475127094Sdes	n = (NBTNsResourceNULL *) ((u_char *) q + sizeof(NBTNsResource));
47636321Samurai
47736321Samurai	/* Check out of length */
47836321Samurai	bcount = ntohs(q->rdlen);
47936321Samurai
48036321Samurai	/* Processing all in_addr array */
481127094Sdes	while (bcount != 0) {
48241759Sdillon		if ((char *)(n + 1) > pmax) {
48341759Sdillon			n = NULL;
48441759Sdillon			break;
48541759Sdillon		}
48636321Samurai		n++;
48736321Samurai		bcount -= sizeof(NBTNsResourceNULL);
48836321Samurai	}
48941759Sdillon	if ((char *)(n + 1) > pmax)
49041759Sdillon		n = NULL;
49136321Samurai
492127094Sdes	return ((u_char *) n);
49336321Samurai}
49436321Samurai
495127094Sdesstatic u_char  *
49699207SbrianAliasHandleResourceNS(
497127094Sdes    NBTNsResource * q,
49841759Sdillon    char *pmax,
499127094Sdes    NBTArguments * nbtarg)
50036321Samurai{
501127094Sdes	NBTNsResourceNULL *n;
50236321Samurai	u_short bcount;
50336321Samurai
50441759Sdillon	if (q == NULL || (char *)(q + 1) > pmax)
505127094Sdes		return (NULL);
50641759Sdillon
50736321Samurai	/* Forward to Resource NULL position */
508127094Sdes	n = (NBTNsResourceNULL *) ((u_char *) q + sizeof(NBTNsResource));
50936321Samurai
51036321Samurai	/* Check out of length */
51136321Samurai	bcount = ntohs(q->rdlen);
51236321Samurai
51336321Samurai	/* Resource Record Name Filed */
514127094Sdes	q = (NBTNsResource *) AliasHandleName((u_char *) n, pmax);	/* XXX */
51536321Samurai
516127094Sdes	if (q == NULL || (char *)((u_char *) n + bcount) > pmax)
517127094Sdes		return (NULL);
51841759Sdillon	else
519127094Sdes		return ((u_char *) n + bcount);
52036321Samurai}
52136321Samurai
52236321Samuraitypedef struct {
523127094Sdes	u_short		numnames;
524127094Sdes}		NBTNsResourceNBSTAT;
52536321Samurai
526127094Sdesstatic u_char  *
52741759SdillonAliasHandleResourceNBSTAT(
528127094Sdes    NBTNsResource * q,
52941759Sdillon    char *pmax,
530127094Sdes    NBTArguments * nbtarg)
53136321Samurai{
532127094Sdes	NBTNsResourceNBSTAT *n;
53336321Samurai	u_short bcount;
53436321Samurai
53541759Sdillon	if (q == NULL || (char *)(q + 1) > pmax)
536127094Sdes		return (NULL);
53741759Sdillon
53836321Samurai	/* Forward to Resource NBSTAT position */
539127094Sdes	n = (NBTNsResourceNBSTAT *) ((u_char *) q + sizeof(NBTNsResource));
54036321Samurai
54136321Samurai	/* Check out of length */
54236321Samurai	bcount = ntohs(q->rdlen);
54336321Samurai
544127094Sdes	if (q == NULL || (char *)((u_char *) n + bcount) > pmax)
545127094Sdes		return (NULL);
54641759Sdillon	else
547127094Sdes		return ((u_char *) n + bcount);
54836321Samurai}
54936321Samurai
550127094Sdesstatic u_char  *
55141759SdillonAliasHandleResource(
55299207Sbrian    u_short count,
553127094Sdes    NBTNsResource * q,
55441759Sdillon    char *pmax,
55599207Sbrian    NBTArguments
556127094Sdes    * nbtarg)
55736321Samurai{
558127094Sdes	while (count != 0) {
55936321Samurai		/* Resource Record Name Filed */
560127094Sdes		q = (NBTNsResource *) AliasHandleName((u_char *) q, pmax);
56141759Sdillon
56241759Sdillon		if (q == NULL || (char *)(q + 1) > pmax)
56341759Sdillon			break;
56436321Samurai#ifdef DEBUG
565127094Sdes		printf("type=%02x, count=%d\n", ntohs(q->type), count);
56636321Samurai#endif
56736321Samurai
56836321Samurai		/* Type and Class filed */
569127094Sdes		switch (ntohs(q->type)) {
570127094Sdes		case RR_TYPE_NB:
571127094Sdes			q = (NBTNsResource *) AliasHandleResourceNB(
572127094Sdes			    q,
573127094Sdes			    pmax,
574127094Sdes			    nbtarg
575127094Sdes			    );
576127094Sdes			break;
577127094Sdes		case RR_TYPE_A:
578127094Sdes			q = (NBTNsResource *) AliasHandleResourceA(
579127094Sdes			    q,
580127094Sdes			    pmax,
581127094Sdes			    nbtarg
582127094Sdes			    );
583127094Sdes			break;
584127094Sdes		case RR_TYPE_NS:
585127094Sdes			q = (NBTNsResource *) AliasHandleResourceNS(
586127094Sdes			    q,
587127094Sdes			    pmax,
588127094Sdes			    nbtarg
589127094Sdes			    );
590127094Sdes			break;
591127094Sdes		case RR_TYPE_NULL:
592127094Sdes			q = (NBTNsResource *) AliasHandleResourceNULL(
593127094Sdes			    q,
594127094Sdes			    pmax,
595127094Sdes			    nbtarg
596127094Sdes			    );
597127094Sdes			break;
598127094Sdes		case RR_TYPE_NBSTAT:
599127094Sdes			q = (NBTNsResource *) AliasHandleResourceNBSTAT(
600127094Sdes			    q,
601127094Sdes			    pmax,
602127094Sdes			    nbtarg
603127094Sdes			    );
604127094Sdes			break;
605127094Sdes		default:
60644616Sbrian#ifdef DEBUG
607127094Sdes			printf(
608127094Sdes			    "\nUnknown Type of Resource %0x\n",
609127094Sdes			    ntohs(q->type)
610127094Sdes			    );
61144616Sbrian#endif
612127094Sdes			break;
61336321Samurai		}
61436321Samurai		count--;
61536321Samurai	}
61636321Samurai	fflush(stdout);
617127094Sdes	return ((u_char *) q);
61836321Samurai}
61936321Samurai
620127094Sdesint
621127094SdesAliasHandleUdpNbtNS(
622127094Sdes    struct libalias *la,
623127094Sdes    struct ip *pip,		/* IP packet to examine/patch */
624127094Sdes    struct alias_link *link,
625127094Sdes    struct in_addr *alias_address,
626127094Sdes    u_short * alias_port,
627127094Sdes    struct in_addr *original_address,
628127094Sdes    u_short * original_port)
62936321Samurai{
630127094Sdes	struct udphdr *uh;
631127094Sdes	NbtNSHeader *nsh;
632127094Sdes	u_char *p;
633127094Sdes	char *pmax;
634127094Sdes	NBTArguments nbtarg;
63536321Samurai
63699207Sbrian	/* Set up Common Parameter */
637127094Sdes	nbtarg.oldaddr = *alias_address;
638127094Sdes	nbtarg.oldport = *alias_port;
639127094Sdes	nbtarg.newaddr = *original_address;
640127094Sdes	nbtarg.newport = *original_port;
64136321Samurai
642127094Sdes	/* Calculate data length of UDP packet */
643127094Sdes	uh = (struct udphdr *)((char *)pip + (pip->ip_hl << 2));
644127094Sdes	nbtarg.uh_sum = &(uh->uh_sum);
645127094Sdes	nsh = (NbtNSHeader *) ((char *)uh + (sizeof(struct udphdr)));
646127094Sdes	p = (u_char *) (nsh + 1);
647127094Sdes	pmax = (char *)uh + ntohs(uh->uh_ulen);
64836321Samurai
649127094Sdes	if ((char *)(nsh + 1) > pmax)
650127094Sdes		return (-1);
65141759Sdillon
65236321Samurai#ifdef DEBUG
653127094Sdes	printf(" [%s] ID=%02x, op=%01x, flag=%02x, rcode=%01x, qd=%04x"
654127094Sdes	    ", an=%04x, ns=%04x, ar=%04x, [%d]-->",
655127094Sdes	    nsh->dir ? "Response" : "Request",
656127094Sdes	    nsh->nametrid,
657127094Sdes	    nsh->opcode,
658127094Sdes	    nsh->nmflags,
659127094Sdes	    nsh->rcode,
660127094Sdes	    ntohs(nsh->qdcount),
661127094Sdes	    ntohs(nsh->ancount),
662127094Sdes	    ntohs(nsh->nscount),
663127094Sdes	    ntohs(nsh->arcount),
664127094Sdes	    (u_char *) p - (u_char *) nsh
665127094Sdes	    );
66636321Samurai#endif
66736321Samurai
66836321Samurai	/* Question Entries */
669127094Sdes	if (ntohs(nsh->qdcount) != 0) {
670127094Sdes		p = AliasHandleQuestion(
671127094Sdes		    ntohs(nsh->qdcount),
672127094Sdes		    (NBTNsQuestion *) p,
673127094Sdes		    pmax,
674127094Sdes		    &nbtarg
675127094Sdes		    );
67636321Samurai	}
67736321Samurai	/* Answer Resource Records */
678127094Sdes	if (ntohs(nsh->ancount) != 0) {
679127094Sdes		p = AliasHandleResource(
680127094Sdes		    ntohs(nsh->ancount),
681127094Sdes		    (NBTNsResource *) p,
682127094Sdes		    pmax,
683127094Sdes		    &nbtarg
684127094Sdes		    );
68536321Samurai	}
68636321Samurai	/* Authority Resource Recodrs */
687127094Sdes	if (ntohs(nsh->nscount) != 0) {
688127094Sdes		p = AliasHandleResource(
689127094Sdes		    ntohs(nsh->nscount),
690127094Sdes		    (NBTNsResource *) p,
691127094Sdes		    pmax,
692127094Sdes		    &nbtarg
693127094Sdes		    );
69436321Samurai	}
69536321Samurai	/* Additional Resource Recodrs */
696127094Sdes	if (ntohs(nsh->arcount) != 0) {
697127094Sdes		p = AliasHandleResource(
698127094Sdes		    ntohs(nsh->arcount),
699127094Sdes		    (NBTNsResource *) p,
700127094Sdes		    pmax,
701127094Sdes		    &nbtarg
702127094Sdes		    );
70336321Samurai	}
70436321Samurai#ifdef DEBUG
705127094Sdes	PrintRcode(nsh->rcode);
70636321Samurai#endif
707127094Sdes	return ((p == NULL) ? -1 : 0);
70836321Samurai}
709