xref: /freebsd/sys/netinet/libalias/alias_nbt.c (revision 685dc743)
1888b1a7aSBrian Somers /*-
24d846d26SWarner Losh  * SPDX-License-Identifier: BSD-2-Clause
3fe267a55SPedro F. Giffuni  *
4fb9cd36dSAtsushi Murai  * Written by Atsushi Murai <amurai@spec.co.jp>
5888b1a7aSBrian Somers  * Copyright (c) 1998, System Planning and Engineering Co.
6888b1a7aSBrian Somers  * All rights reserved.
7fb9cd36dSAtsushi Murai  *
8888b1a7aSBrian Somers  * Redistribution and use in source and binary forms, with or without
9888b1a7aSBrian Somers  * modification, are permitted provided that the following conditions
10888b1a7aSBrian Somers  * are met:
11888b1a7aSBrian Somers  * 1. Redistributions of source code must retain the above copyright
12888b1a7aSBrian Somers  *    notice, this list of conditions and the following disclaimer.
13888b1a7aSBrian Somers  * 2. Redistributions in binary form must reproduce the above copyright
14888b1a7aSBrian Somers  *    notice, this list of conditions and the following disclaimer in the
15888b1a7aSBrian Somers  *    documentation and/or other materials provided with the distribution.
16fb9cd36dSAtsushi Murai  *
17888b1a7aSBrian Somers  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18888b1a7aSBrian Somers  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19888b1a7aSBrian Somers  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20888b1a7aSBrian Somers  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21888b1a7aSBrian Somers  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22888b1a7aSBrian Somers  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23888b1a7aSBrian Somers  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24888b1a7aSBrian Somers  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25888b1a7aSBrian Somers  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26888b1a7aSBrian Somers  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27888b1a7aSBrian Somers  * SUCH DAMAGE.
28fb9cd36dSAtsushi Murai  *  TODO:
29fb9cd36dSAtsushi Murai  *       oClean up.
30fb9cd36dSAtsushi Murai  *       oConsidering for word alignment for other platform.
31fb9cd36dSAtsushi Murai  */
32e2505aa6SMatthew Dillon 
33e2505aa6SMatthew Dillon #include <sys/cdefs.h>
34fb9cd36dSAtsushi Murai /*
35fb9cd36dSAtsushi Murai     alias_nbt.c performs special processing for NetBios over TCP/IP
36fb9cd36dSAtsushi Murai     sessions by UDP.
37fb9cd36dSAtsushi Murai 
38fb9cd36dSAtsushi Murai     Initial version:  May, 1998  (Atsushi Murai <amurai@spec.co.jp>)
39fb9cd36dSAtsushi Murai 
40fb9cd36dSAtsushi Murai     See HISTORY file for record of revisions.
41fb9cd36dSAtsushi Murai */
42fb9cd36dSAtsushi Murai 
43fb9cd36dSAtsushi Murai /* Includes */
44c649a2e0SGleb Smirnoff #ifdef _KERNEL
45c649a2e0SGleb Smirnoff #include <sys/param.h>
46be4f3cd0SPaolo Pisati #include <sys/systm.h>
47be4f3cd0SPaolo Pisati #include <sys/kernel.h>
48be4f3cd0SPaolo Pisati #include <sys/module.h>
49c649a2e0SGleb Smirnoff #else
50be4f3cd0SPaolo Pisati #include <errno.h>
51c649a2e0SGleb Smirnoff #include <sys/types.h>
52fb9cd36dSAtsushi Murai #include <stdio.h>
53dd14bc5dSPaolo Pisati #include <strings.h>
54c649a2e0SGleb Smirnoff #endif
55c649a2e0SGleb Smirnoff 
56fb9cd36dSAtsushi Murai #include <netinet/in_systm.h>
57fb9cd36dSAtsushi Murai #include <netinet/in.h>
58fb9cd36dSAtsushi Murai #include <netinet/ip.h>
59fb9cd36dSAtsushi Murai #include <netinet/udp.h>
60fb9cd36dSAtsushi Murai 
61c649a2e0SGleb Smirnoff #ifdef _KERNEL
62c649a2e0SGleb Smirnoff #include <netinet/libalias/alias_local.h>
63be4f3cd0SPaolo Pisati #include <netinet/libalias/alias_mod.h>
64c649a2e0SGleb Smirnoff #else
65fb9cd36dSAtsushi Murai #include "alias_local.h"
66be4f3cd0SPaolo Pisati #include "alias_mod.h"
67be4f3cd0SPaolo Pisati #endif
68be4f3cd0SPaolo Pisati 
69be4f3cd0SPaolo Pisati #define NETBIOS_NS_PORT_NUMBER 137
70be4f3cd0SPaolo Pisati #define NETBIOS_DGM_PORT_NUMBER 138
71be4f3cd0SPaolo Pisati 
72be4f3cd0SPaolo Pisati static int
73be4f3cd0SPaolo Pisati AliasHandleUdpNbt(struct libalias *, struct ip *, struct alias_link *,
74be4f3cd0SPaolo Pisati     struct in_addr *, u_short);
75be4f3cd0SPaolo Pisati static int
76be4f3cd0SPaolo Pisati AliasHandleUdpNbtNS(struct libalias *, struct ip *, struct alias_link *,
77be4f3cd0SPaolo Pisati     struct in_addr *, u_short *, struct in_addr *, u_short *);
78effc8e57SLutz Donnerhacke 
79be4f3cd0SPaolo Pisati static int
fingerprint1(struct libalias * la,struct alias_data * ah)8043197d29SPaolo Pisati fingerprint1(struct libalias *la, struct alias_data *ah)
81be4f3cd0SPaolo Pisati {
82be4f3cd0SPaolo Pisati 	if (ah->dport == NULL || ah->sport == NULL || ah->lnk == NULL ||
83be4f3cd0SPaolo Pisati 	    ah->aaddr == NULL || ah->aport == NULL)
84be4f3cd0SPaolo Pisati 		return (-1);
85be4f3cd0SPaolo Pisati 	if (ntohs(*ah->dport) == NETBIOS_DGM_PORT_NUMBER
86be4f3cd0SPaolo Pisati 	    || ntohs(*ah->sport) == NETBIOS_DGM_PORT_NUMBER)
87be4f3cd0SPaolo Pisati 		return (0);
88be4f3cd0SPaolo Pisati 	return (-1);
89be4f3cd0SPaolo Pisati }
90be4f3cd0SPaolo Pisati 
91be4f3cd0SPaolo Pisati static int
protohandler1(struct libalias * la,struct ip * pip,struct alias_data * ah)92be4f3cd0SPaolo Pisati protohandler1(struct libalias *la, struct ip *pip, struct alias_data *ah)
93be4f3cd0SPaolo Pisati {
94ea80b0acSPaolo Pisati 	return (AliasHandleUdpNbt(la, pip, ah->lnk, ah->aaddr, *ah->aport));
95be4f3cd0SPaolo Pisati }
96be4f3cd0SPaolo Pisati 
97be4f3cd0SPaolo Pisati static int
fingerprint2(struct libalias * la,struct alias_data * ah)9843197d29SPaolo Pisati fingerprint2(struct libalias *la, struct alias_data *ah)
99be4f3cd0SPaolo Pisati {
100be4f3cd0SPaolo Pisati 	if (ah->dport == NULL || ah->sport == NULL || ah->lnk == NULL ||
101be4f3cd0SPaolo Pisati 	    ah->aaddr == NULL || ah->aport == NULL)
102be4f3cd0SPaolo Pisati 		return (-1);
103be4f3cd0SPaolo Pisati 	if (ntohs(*ah->dport) == NETBIOS_NS_PORT_NUMBER
104be4f3cd0SPaolo Pisati 	    || ntohs(*ah->sport) == NETBIOS_NS_PORT_NUMBER)
105be4f3cd0SPaolo Pisati 		return (0);
106be4f3cd0SPaolo Pisati 	return (-1);
107be4f3cd0SPaolo Pisati }
108be4f3cd0SPaolo Pisati 
109be4f3cd0SPaolo Pisati static int
protohandler2in(struct libalias * la,struct ip * pip,struct alias_data * ah)110be4f3cd0SPaolo Pisati protohandler2in(struct libalias *la, struct ip *pip, struct alias_data *ah)
111be4f3cd0SPaolo Pisati {
112be4f3cd0SPaolo Pisati 	AliasHandleUdpNbtNS(la, pip, ah->lnk, ah->aaddr, ah->aport,
113be4f3cd0SPaolo Pisati 	    ah->oaddr, ah->dport);
114be4f3cd0SPaolo Pisati 	return (0);
115be4f3cd0SPaolo Pisati }
116be4f3cd0SPaolo Pisati 
117be4f3cd0SPaolo Pisati static int
protohandler2out(struct libalias * la,struct ip * pip,struct alias_data * ah)118be4f3cd0SPaolo Pisati protohandler2out(struct libalias *la, struct ip *pip, struct alias_data *ah)
119be4f3cd0SPaolo Pisati {
120ea80b0acSPaolo Pisati 	return (AliasHandleUdpNbtNS(la, pip, ah->lnk, &pip->ip_src, ah->sport,
121ea80b0acSPaolo Pisati 	    ah->aaddr, ah->aport));
122be4f3cd0SPaolo Pisati }
123be4f3cd0SPaolo Pisati 
124be4f3cd0SPaolo Pisati /* Kernel module definition. */
125be4f3cd0SPaolo Pisati struct proto_handler handlers[] = {
126be4f3cd0SPaolo Pisati 	{
127be4f3cd0SPaolo Pisati 	  .pri = 130,
128be4f3cd0SPaolo Pisati 	  .dir = IN|OUT,
129be4f3cd0SPaolo Pisati 	  .proto = UDP,
130be4f3cd0SPaolo Pisati 	  .fingerprint = &fingerprint1,
131be4f3cd0SPaolo Pisati 	  .protohandler = &protohandler1
132be4f3cd0SPaolo Pisati 	},
133be4f3cd0SPaolo Pisati 	{
134be4f3cd0SPaolo Pisati 	  .pri = 140,
135be4f3cd0SPaolo Pisati 	  .dir = IN,
136be4f3cd0SPaolo Pisati 	  .proto = UDP,
137be4f3cd0SPaolo Pisati 	  .fingerprint = &fingerprint2,
138be4f3cd0SPaolo Pisati 	  .protohandler = &protohandler2in
139be4f3cd0SPaolo Pisati 	},
140be4f3cd0SPaolo Pisati 	{
141be4f3cd0SPaolo Pisati 	  .pri = 140,
142be4f3cd0SPaolo Pisati 	  .dir = OUT,
143be4f3cd0SPaolo Pisati 	  .proto = UDP,
144be4f3cd0SPaolo Pisati 	  .fingerprint = &fingerprint2,
145be4f3cd0SPaolo Pisati 	  .protohandler = &protohandler2out
146be4f3cd0SPaolo Pisati 	},
147be4f3cd0SPaolo Pisati 	{ EOH }
148be4f3cd0SPaolo Pisati };
149be4f3cd0SPaolo Pisati 
150be4f3cd0SPaolo Pisati static int
mod_handler(module_t mod,int type,void * data)151be4f3cd0SPaolo Pisati mod_handler(module_t mod, int type, void *data)
152be4f3cd0SPaolo Pisati {
153be4f3cd0SPaolo Pisati 	int error;
154be4f3cd0SPaolo Pisati 
155be4f3cd0SPaolo Pisati 	switch (type) {
156be4f3cd0SPaolo Pisati 	case MOD_LOAD:
157be4f3cd0SPaolo Pisati 		error = 0;
158be4f3cd0SPaolo Pisati 		LibAliasAttachHandlers(handlers);
159be4f3cd0SPaolo Pisati 		break;
160be4f3cd0SPaolo Pisati 	case MOD_UNLOAD:
161be4f3cd0SPaolo Pisati 		error = 0;
162be4f3cd0SPaolo Pisati 		LibAliasDetachHandlers(handlers);
163be4f3cd0SPaolo Pisati 		break;
164be4f3cd0SPaolo Pisati 	default:
165be4f3cd0SPaolo Pisati 		error = EINVAL;
166be4f3cd0SPaolo Pisati 	}
167be4f3cd0SPaolo Pisati 	return (error);
168be4f3cd0SPaolo Pisati }
169be4f3cd0SPaolo Pisati 
170be4f3cd0SPaolo Pisati #ifdef _KERNEL
171be4f3cd0SPaolo Pisati static
172be4f3cd0SPaolo Pisati #endif
173be4f3cd0SPaolo Pisati moduledata_t alias_mod = {
174be4f3cd0SPaolo Pisati        "alias_nbt", mod_handler, NULL
175be4f3cd0SPaolo Pisati };
176be4f3cd0SPaolo Pisati 
177be4f3cd0SPaolo Pisati #ifdef _KERNEL
178be4f3cd0SPaolo Pisati DECLARE_MODULE(alias_nbt, alias_mod, SI_SUB_DRIVERS, SI_ORDER_SECOND);
179be4f3cd0SPaolo Pisati MODULE_VERSION(alias_nbt, 1);
180be4f3cd0SPaolo Pisati MODULE_DEPEND(alias_nbt, libalias, 1, 1, 1);
181c649a2e0SGleb Smirnoff #endif
182fb9cd36dSAtsushi Murai 
183fb9cd36dSAtsushi Murai typedef struct {
184fb9cd36dSAtsushi Murai 	struct in_addr	oldaddr;
185fb9cd36dSAtsushi Murai 	u_short		oldport;
186fb9cd36dSAtsushi Murai 	struct in_addr	newaddr;
187fb9cd36dSAtsushi Murai 	u_short		newport;
188fb9cd36dSAtsushi Murai 	u_short	       *uh_sum;
189fb9cd36dSAtsushi Murai } NBTArguments;
190fb9cd36dSAtsushi Murai 
191fb9cd36dSAtsushi Murai typedef struct {
192fb9cd36dSAtsushi Murai 	unsigned char	type;
193fb9cd36dSAtsushi Murai 	unsigned char	flags;
194fb9cd36dSAtsushi Murai 	u_short		id;
195fb9cd36dSAtsushi Murai 	struct in_addr	source_ip;
196fb9cd36dSAtsushi Murai 	u_short		source_port;
197fb9cd36dSAtsushi Murai 	u_short		len;
198fb9cd36dSAtsushi Murai 	u_short		offset;
199fb9cd36dSAtsushi Murai } NbtDataHeader;
200fb9cd36dSAtsushi Murai 
201fb9cd36dSAtsushi Murai #define OpQuery		0
202fb9cd36dSAtsushi Murai #define OpUnknown	4
203fb9cd36dSAtsushi Murai #define OpRegist	5
204fb9cd36dSAtsushi Murai #define OpRelease	6
205fb9cd36dSAtsushi Murai #define OpWACK		7
206fb9cd36dSAtsushi Murai #define OpRefresh	8
207fb9cd36dSAtsushi Murai typedef struct {
208fb9cd36dSAtsushi Murai 	u_short		nametrid;
209fb9cd36dSAtsushi Murai 	u_short		dir:1, opcode:4, nmflags:7, rcode:4;
210fb9cd36dSAtsushi Murai 	u_short		qdcount;
211fb9cd36dSAtsushi Murai 	u_short		ancount;
212fb9cd36dSAtsushi Murai 	u_short		nscount;
213fb9cd36dSAtsushi Murai 	u_short		arcount;
214fb9cd36dSAtsushi Murai } NbtNSHeader;
215fb9cd36dSAtsushi Murai 
216fb9cd36dSAtsushi Murai #define FMT_ERR		0x1
217fb9cd36dSAtsushi Murai #define SRV_ERR		0x2
218fb9cd36dSAtsushi Murai #define IMP_ERR		0x4
219fb9cd36dSAtsushi Murai #define RFS_ERR		0x5
220fb9cd36dSAtsushi Murai #define ACT_ERR		0x6
221fb9cd36dSAtsushi Murai #define CFT_ERR		0x7
222fb9cd36dSAtsushi Murai 
2236293e003SGleb Smirnoff #ifdef LIBALIAS_DEBUG
224f0f93429SDag-Erling Smørgrav static void
PrintRcode(u_char rcode)225f0f93429SDag-Erling Smørgrav PrintRcode(u_char rcode)
226f0f93429SDag-Erling Smørgrav {
227fb9cd36dSAtsushi Murai 	switch (rcode) {
228fb9cd36dSAtsushi Murai 	case FMT_ERR:
229fb9cd36dSAtsushi Murai 		printf("\nFormat Error.");
230fb9cd36dSAtsushi Murai 	case SRV_ERR:
231fb9cd36dSAtsushi Murai 		printf("\nSever failure.");
232fb9cd36dSAtsushi Murai 	case IMP_ERR:
233fb9cd36dSAtsushi Murai 		printf("\nUnsupported request error.\n");
234fb9cd36dSAtsushi Murai 	case RFS_ERR:
235fb9cd36dSAtsushi Murai 		printf("\nRefused error.\n");
236fb9cd36dSAtsushi Murai 	case ACT_ERR:
237fb9cd36dSAtsushi Murai 		printf("\nActive error.\n");
238fb9cd36dSAtsushi Murai 	case CFT_ERR:
239fb9cd36dSAtsushi Murai 		printf("\nName in conflict error.\n");
240fb9cd36dSAtsushi Murai 	default:
241c7c5d95dSGarrett Wollman 		printf("\n?%c?=%0x\n", '?', rcode);
242fb9cd36dSAtsushi Murai 	}
243fb9cd36dSAtsushi Murai }
244f0f93429SDag-Erling Smørgrav 
2454c32f5d2SBrian Somers #endif
246fb9cd36dSAtsushi Murai 
247fb9cd36dSAtsushi Murai /* Handling Name field */
248f0f93429SDag-Erling Smørgrav static u_char *
AliasHandleName(u_char * p,char * pmax)249f0f93429SDag-Erling Smørgrav AliasHandleName(u_char *p, char *pmax)
250f0f93429SDag-Erling Smørgrav {
251fb9cd36dSAtsushi Murai 	u_char *s;
2523f6d3f02SJohn Baldwin #ifdef LIBALIAS_DEBUG
253fb9cd36dSAtsushi Murai 	u_char c;
2543f6d3f02SJohn Baldwin #endif
255fb9cd36dSAtsushi Murai 	int compress;
256fb9cd36dSAtsushi Murai 
257fb9cd36dSAtsushi Murai 	/* Following length field */
258374fad8bSMatthew Dillon 
259374fad8bSMatthew Dillon 	if (p == NULL || (char *)p >= pmax)
260374fad8bSMatthew Dillon 		return (NULL);
261374fad8bSMatthew Dillon 
262fb9cd36dSAtsushi Murai 	if (*p & 0xc0) {
263fb9cd36dSAtsushi Murai 		p = p + 2;
264374fad8bSMatthew Dillon 		if ((char *)p > pmax)
265374fad8bSMatthew Dillon 			return (NULL);
266fb9cd36dSAtsushi Murai 		return ((u_char *)p);
267fb9cd36dSAtsushi Murai 	}
268fb9cd36dSAtsushi Murai 	while ((*p & 0x3f) != 0x00) {
269fb9cd36dSAtsushi Murai 		s = p + 1;
270fb9cd36dSAtsushi Murai 		if (*p == 0x20)
271fb9cd36dSAtsushi Murai 			compress = 1;
272fb9cd36dSAtsushi Murai 		else
273fb9cd36dSAtsushi Murai 			compress = 0;
274fb9cd36dSAtsushi Murai 
275fb9cd36dSAtsushi Murai 		/* Get next length field */
276fb9cd36dSAtsushi Murai 		p = (u_char *)(p + (*p & 0x3f) + 1);
277374fad8bSMatthew Dillon 		if ((char *)p > pmax) {
278374fad8bSMatthew Dillon 			p = NULL;
279374fad8bSMatthew Dillon 			break;
280374fad8bSMatthew Dillon 		}
2816293e003SGleb Smirnoff #ifdef LIBALIAS_DEBUG
282fb9cd36dSAtsushi Murai 		printf(":");
283fb9cd36dSAtsushi Murai #endif
284fb9cd36dSAtsushi Murai 		while (s < p) {
285fb9cd36dSAtsushi Murai 			if (compress == 1) {
2866293e003SGleb Smirnoff #ifdef LIBALIAS_DEBUG
2873f6d3f02SJohn Baldwin 				c = (u_char) (((((*s & 0x0f) << 4) | (*(s + 1) & 0x0f)) - 0x11));
288fb9cd36dSAtsushi Murai 				if (isprint(c))
289fb9cd36dSAtsushi Murai 					printf("%c", c);
290fb9cd36dSAtsushi Murai 				else
291fb9cd36dSAtsushi Murai 					printf("<0x%02x>", c);
292fb9cd36dSAtsushi Murai #endif
293fb9cd36dSAtsushi Murai 				s += 2;
294fb9cd36dSAtsushi Murai 			} else {
2956293e003SGleb Smirnoff #ifdef LIBALIAS_DEBUG
296fb9cd36dSAtsushi Murai 				printf("%c", *s);
297fb9cd36dSAtsushi Murai #endif
298fb9cd36dSAtsushi Murai 				s++;
299fb9cd36dSAtsushi Murai 			}
300fb9cd36dSAtsushi Murai 		}
3016293e003SGleb Smirnoff #ifdef LIBALIAS_DEBUG
302fb9cd36dSAtsushi Murai 		printf(":");
303fb9cd36dSAtsushi Murai 		fflush(stdout);
304ae044057SGleb Smirnoff #endif
305fb9cd36dSAtsushi Murai 	}
306fb9cd36dSAtsushi Murai 
307fb9cd36dSAtsushi Murai 	/* Set up to out of Name field */
308374fad8bSMatthew Dillon 	if (p == NULL || (char *)p >= pmax)
309374fad8bSMatthew Dillon 		p = NULL;
310374fad8bSMatthew Dillon 	else
311fb9cd36dSAtsushi Murai 		p++;
312fb9cd36dSAtsushi Murai 	return ((u_char *)p);
313fb9cd36dSAtsushi Murai }
314fb9cd36dSAtsushi Murai 
315fb9cd36dSAtsushi Murai /*
316fb9cd36dSAtsushi Murai  * NetBios Datagram Handler (IP/UDP)
317fb9cd36dSAtsushi Murai  */
318fb9cd36dSAtsushi Murai #define DGM_DIRECT_UNIQ		0x10
319fb9cd36dSAtsushi Murai #define DGM_DIRECT_GROUP	0x11
320fb9cd36dSAtsushi Murai #define DGM_BROADCAST		0x12
321fb9cd36dSAtsushi Murai #define DGM_ERROR		0x13
322fb9cd36dSAtsushi Murai #define DGM_QUERY		0x14
323fb9cd36dSAtsushi Murai #define DGM_POSITIVE_RES	0x15
324fb9cd36dSAtsushi Murai #define DGM_NEGATIVE_RES	0x16
325fb9cd36dSAtsushi Murai 
326be4f3cd0SPaolo Pisati static int
AliasHandleUdpNbt(struct libalias * la,struct ip * pip,struct alias_link * lnk,struct in_addr * alias_address,u_short alias_port)327f0f93429SDag-Erling Smørgrav AliasHandleUdpNbt(
3285e289f9eSPoul-Henning Kamp     struct libalias   *la,
329fb9cd36dSAtsushi Murai     struct ip         *pip,	/* IP packet to examine/patch */
330ed01a582SDag-Erling Smørgrav     struct alias_link *lnk,
331fb9cd36dSAtsushi Murai     struct in_addr    *alias_address,
332effc8e57SLutz Donnerhacke     u_short            alias_port)
333f0f93429SDag-Erling Smørgrav {
334fb9cd36dSAtsushi Murai 	struct udphdr *uh;
335fb9cd36dSAtsushi Murai 	NbtDataHeader *ndh;
336374fad8bSMatthew Dillon 	u_char *p = NULL;
337374fad8bSMatthew Dillon 	char *pmax;
3388144690aSEric van Gyzen #ifdef LIBALIAS_DEBUG
3398144690aSEric van Gyzen 	char addrbuf[INET_ADDRSTRLEN];
3408144690aSEric van Gyzen #endif
341fb9cd36dSAtsushi Murai 
342ed01a582SDag-Erling Smørgrav 	(void)la;
343ed01a582SDag-Erling Smørgrav 	(void)lnk;
344ed01a582SDag-Erling Smørgrav 
345fb9cd36dSAtsushi Murai 	/* Calculate data length of UDP packet */
3469fa0fd26SDag-Erling Smørgrav 	uh = (struct udphdr *)ip_next(pip);
347374fad8bSMatthew Dillon 	pmax = (char *)uh + ntohs(uh->uh_ulen);
348374fad8bSMatthew Dillon 
3499fa0fd26SDag-Erling Smørgrav 	ndh = (NbtDataHeader *)udp_next(uh);
350374fad8bSMatthew Dillon 	if ((char *)(ndh + 1) > pmax)
351374fad8bSMatthew Dillon 		return (-1);
3526293e003SGleb Smirnoff #ifdef LIBALIAS_DEBUG
353fb9cd36dSAtsushi Murai 	printf("\nType=%02x,", ndh->type);
354fb9cd36dSAtsushi Murai #endif
355fb9cd36dSAtsushi Murai 	switch (ndh->type) {
356fb9cd36dSAtsushi Murai 	case DGM_DIRECT_UNIQ:
357fb9cd36dSAtsushi Murai 	case DGM_DIRECT_GROUP:
358fb9cd36dSAtsushi Murai 	case DGM_BROADCAST:
359fb9cd36dSAtsushi Murai 		p = (u_char *)ndh + 14;
360374fad8bSMatthew Dillon 		p = AliasHandleName(p, pmax);	/* Source Name */
361374fad8bSMatthew Dillon 		p = AliasHandleName(p, pmax);	/* Destination Name */
362fb9cd36dSAtsushi Murai 		break;
363fb9cd36dSAtsushi Murai 	case DGM_ERROR:
364fb9cd36dSAtsushi Murai 		p = (u_char *)ndh + 11;
365fb9cd36dSAtsushi Murai 		break;
366fb9cd36dSAtsushi Murai 	case DGM_QUERY:
367fb9cd36dSAtsushi Murai 	case DGM_POSITIVE_RES:
368fb9cd36dSAtsushi Murai 	case DGM_NEGATIVE_RES:
369fb9cd36dSAtsushi Murai 		p = (u_char *)ndh + 10;
370374fad8bSMatthew Dillon 		p = AliasHandleName(p, pmax);	/* Destination Name */
371fb9cd36dSAtsushi Murai 		break;
372fb9cd36dSAtsushi Murai 	}
373374fad8bSMatthew Dillon 	if (p == NULL || (char *)p > pmax)
374374fad8bSMatthew Dillon 		p = NULL;
3756293e003SGleb Smirnoff #ifdef LIBALIAS_DEBUG
3768144690aSEric van Gyzen 	printf("%s:%d-->", inet_ntoa_r(ndh->source_ip, INET_NTOA_BUF(addrbuf)),
3778144690aSEric van Gyzen 	    ntohs(ndh->source_port));
378fb9cd36dSAtsushi Murai #endif
3799d5abbddSJens Schweikhardt 	/* Doing an IP address and Port number Translation */
380fb9cd36dSAtsushi Murai 	if (uh->uh_sum != 0) {
381fb9cd36dSAtsushi Murai 		int acc;
382fb9cd36dSAtsushi Murai 		u_short *sptr;
383f0f93429SDag-Erling Smørgrav 
384fb9cd36dSAtsushi Murai 		acc = ndh->source_port;
385fb9cd36dSAtsushi Murai 		acc -= alias_port;
386fb9cd36dSAtsushi Murai 		sptr = (u_short *)&(ndh->source_ip);
387fb9cd36dSAtsushi Murai 		acc += *sptr++;
388fb9cd36dSAtsushi Murai 		acc += *sptr;
389fb9cd36dSAtsushi Murai 		sptr = (u_short *)alias_address;
390fb9cd36dSAtsushi Murai 		acc -= *sptr++;
391fb9cd36dSAtsushi Murai 		acc -= *sptr;
39271593f95SBrian Somers 		ADJUST_CHECKSUM(acc, uh->uh_sum);
393fb9cd36dSAtsushi Murai 	}
394fb9cd36dSAtsushi Murai 	ndh->source_ip = *alias_address;
395fb9cd36dSAtsushi Murai 	ndh->source_port = alias_port;
3966293e003SGleb Smirnoff #ifdef LIBALIAS_DEBUG
3978144690aSEric van Gyzen 	printf("%s:%d\n", inet_ntoa_r(ndh->source_ip, INET_NTOA_BUF(addrbuf)),
3988144690aSEric van Gyzen 	    ntohs(ndh->source_port));
399fb9cd36dSAtsushi Murai 	fflush(stdout);
400fb9cd36dSAtsushi Murai #endif
401374fad8bSMatthew Dillon 	return ((p == NULL) ? -1 : 0);
402fb9cd36dSAtsushi Murai }
403f0f93429SDag-Erling Smørgrav 
404fb9cd36dSAtsushi Murai /* Question Section */
405fb9cd36dSAtsushi Murai #define QS_TYPE_NB	0x0020
406fb9cd36dSAtsushi Murai #define QS_TYPE_NBSTAT	0x0021
407fb9cd36dSAtsushi Murai #define QS_CLAS_IN	0x0001
408fb9cd36dSAtsushi Murai typedef struct {
409fb9cd36dSAtsushi Murai 	u_short		type;	/* The type of Request */
410fb9cd36dSAtsushi Murai 	u_short		class;	/* The class of Request */
411fb9cd36dSAtsushi Murai } NBTNsQuestion;
412fb9cd36dSAtsushi Murai 
4134c32f5d2SBrian Somers static u_char *
AliasHandleQuestion(u_short count,NBTNsQuestion * q,char * pmax,NBTArguments * nbtarg)414374fad8bSMatthew Dillon AliasHandleQuestion(
415374fad8bSMatthew Dillon     u_short count,
416fb9cd36dSAtsushi Murai     NBTNsQuestion * q,
417374fad8bSMatthew Dillon     char *pmax,
418fb9cd36dSAtsushi Murai     NBTArguments * nbtarg)
419fb9cd36dSAtsushi Murai {
420ed01a582SDag-Erling Smørgrav 	(void)nbtarg;
421ed01a582SDag-Erling Smørgrav 
422fb9cd36dSAtsushi Murai 	while (count != 0) {
423fb9cd36dSAtsushi Murai 		/* Name Filed */
424374fad8bSMatthew Dillon 		q = (NBTNsQuestion *)AliasHandleName((u_char *)q, pmax);
425374fad8bSMatthew Dillon 
426374fad8bSMatthew Dillon 		if (q == NULL || (char *)(q + 1) > pmax) {
427374fad8bSMatthew Dillon 			q = NULL;
428374fad8bSMatthew Dillon 			break;
429374fad8bSMatthew Dillon 		}
430fb9cd36dSAtsushi Murai 		/* Type and Class filed */
431fb9cd36dSAtsushi Murai 		switch (ntohs(q->type)) {
432fb9cd36dSAtsushi Murai 		case QS_TYPE_NB:
433fb9cd36dSAtsushi Murai 		case QS_TYPE_NBSTAT:
434fb9cd36dSAtsushi Murai 			q = q + 1;
435fb9cd36dSAtsushi Murai 			break;
436fb9cd36dSAtsushi Murai 		default:
4376293e003SGleb Smirnoff #ifdef LIBALIAS_DEBUG
438fb9cd36dSAtsushi Murai 			printf("\nUnknown Type on Question %0x\n", ntohs(q->type));
4394c32f5d2SBrian Somers #endif
440fb9cd36dSAtsushi Murai 			break;
441fb9cd36dSAtsushi Murai 		}
442fb9cd36dSAtsushi Murai 		count--;
443fb9cd36dSAtsushi Murai 	}
444fb9cd36dSAtsushi Murai 
445fb9cd36dSAtsushi Murai 	/* Set up to out of Question Section */
446fb9cd36dSAtsushi Murai 	return ((u_char *)q);
447fb9cd36dSAtsushi Murai }
448fb9cd36dSAtsushi Murai 
449fb9cd36dSAtsushi Murai /* Resource Record */
450fb9cd36dSAtsushi Murai #define RR_TYPE_A	0x0001
451fb9cd36dSAtsushi Murai #define RR_TYPE_NS	0x0002
452fb9cd36dSAtsushi Murai #define RR_TYPE_NULL	0x000a
453fb9cd36dSAtsushi Murai #define RR_TYPE_NB	0x0020
454fb9cd36dSAtsushi Murai #define RR_TYPE_NBSTAT	0x0021
455fb9cd36dSAtsushi Murai #define RR_CLAS_IN	0x0001
456fb9cd36dSAtsushi Murai #define SizeOfNsResource	8
457fb9cd36dSAtsushi Murai typedef struct {
458fb9cd36dSAtsushi Murai 	u_short		type;
459fb9cd36dSAtsushi Murai 	u_short		class;
460fb9cd36dSAtsushi Murai 	unsigned int	ttl;
461fb9cd36dSAtsushi Murai 	u_short		rdlen;
462fb9cd36dSAtsushi Murai } NBTNsResource;
463fb9cd36dSAtsushi Murai 
464fb9cd36dSAtsushi Murai #define SizeOfNsRNB		6
465fb9cd36dSAtsushi Murai typedef struct {
466fb9cd36dSAtsushi Murai 	u_short		g:1, ont:2, resv:13;
467fb9cd36dSAtsushi Murai 	struct in_addr	addr;
468fb9cd36dSAtsushi Murai } NBTNsRNB;
469fb9cd36dSAtsushi Murai 
4704c32f5d2SBrian Somers static u_char *
AliasHandleResourceNB(NBTNsResource * q,char * pmax,NBTArguments * nbtarg)471374fad8bSMatthew Dillon AliasHandleResourceNB(
472374fad8bSMatthew Dillon     NBTNsResource *q,
473374fad8bSMatthew Dillon     char          *pmax,
474fb9cd36dSAtsushi Murai     NBTArguments  *nbtarg)
475fb9cd36dSAtsushi Murai {
476fb9cd36dSAtsushi Murai 	NBTNsRNB *nb;
477fb9cd36dSAtsushi Murai 	u_short bcount;
4788144690aSEric van Gyzen #ifdef LIBALIAS_DEBUG
4798144690aSEric van Gyzen 	char oldbuf[INET_ADDRSTRLEN];
4808144690aSEric van Gyzen 	char newbuf[INET_ADDRSTRLEN];
4818144690aSEric van Gyzen #endif
482fb9cd36dSAtsushi Murai 
483374fad8bSMatthew Dillon 	if (q == NULL || (char *)(q + 1) > pmax)
484374fad8bSMatthew Dillon 		return (NULL);
485fb9cd36dSAtsushi Murai 	/* Check out a length */
486fb9cd36dSAtsushi Murai 	bcount = ntohs(q->rdlen);
487fb9cd36dSAtsushi Murai 
488fb9cd36dSAtsushi Murai 	/* Forward to Resource NB position */
489fb9cd36dSAtsushi Murai 	nb = (NBTNsRNB *)((u_char *)q + SizeOfNsResource);
490fb9cd36dSAtsushi Murai 
491fb9cd36dSAtsushi Murai 	/* Processing all in_addr array */
4926293e003SGleb Smirnoff #ifdef LIBALIAS_DEBUG
4938144690aSEric van Gyzen 	printf("NB rec[%s->%s, %dbytes] ",
4948144690aSEric van Gyzen 	    inet_ntoa_r(nbtarg->oldaddr, INET_NTOA_BUF(oldbuf)),
4958144690aSEric van Gyzen 	    inet_ntoa_r(nbtarg->newaddr, INET_NTOA_BUF(newbuf)),
4968144690aSEric van Gyzen 	    bcount);
497fb9cd36dSAtsushi Murai #endif
498374fad8bSMatthew Dillon 	while (nb != NULL && bcount != 0) {
499374fad8bSMatthew Dillon 		if ((char *)(nb + 1) > pmax) {
500374fad8bSMatthew Dillon 			nb = NULL;
501374fad8bSMatthew Dillon 			break;
502374fad8bSMatthew Dillon 		}
5036293e003SGleb Smirnoff #ifdef LIBALIAS_DEBUG
5048144690aSEric van Gyzen 		printf("<%s>", inet_ntoa_r(nb->addr, INET_NTOA_BUF(newbuf)));
505fb9cd36dSAtsushi Murai #endif
506fb9cd36dSAtsushi Murai 		if (!bcmp(&nbtarg->oldaddr, &nb->addr, sizeof(struct in_addr))) {
507fb9cd36dSAtsushi Murai 			if (*nbtarg->uh_sum != 0) {
508fb9cd36dSAtsushi Murai 				int acc;
509fb9cd36dSAtsushi Murai 				u_short *sptr;
510fb9cd36dSAtsushi Murai 
511fb9cd36dSAtsushi Murai 				sptr = (u_short *)&(nb->addr);
512fb9cd36dSAtsushi Murai 				acc = *sptr++;
513fb9cd36dSAtsushi Murai 				acc += *sptr;
514fb9cd36dSAtsushi Murai 				sptr = (u_short *)&(nbtarg->newaddr);
515fb9cd36dSAtsushi Murai 				acc -= *sptr++;
516fb9cd36dSAtsushi Murai 				acc -= *sptr;
51771593f95SBrian Somers 				ADJUST_CHECKSUM(acc, *nbtarg->uh_sum);
518fb9cd36dSAtsushi Murai 			}
519fb9cd36dSAtsushi Murai 			nb->addr = nbtarg->newaddr;
5206293e003SGleb Smirnoff #ifdef LIBALIAS_DEBUG
521fb9cd36dSAtsushi Murai 			printf("O");
522fb9cd36dSAtsushi Murai #endif
523fb9cd36dSAtsushi Murai 		}
5246293e003SGleb Smirnoff #ifdef LIBALIAS_DEBUG
525fb9cd36dSAtsushi Murai 		else {
526fb9cd36dSAtsushi Murai 			printf(".");
527fb9cd36dSAtsushi Murai 		}
528fb9cd36dSAtsushi Murai #endif
529fb9cd36dSAtsushi Murai 		nb = (NBTNsRNB *)((u_char *)nb + SizeOfNsRNB);
530fb9cd36dSAtsushi Murai 		bcount -= SizeOfNsRNB;
531fb9cd36dSAtsushi Murai 	}
532374fad8bSMatthew Dillon 	if (nb == NULL || (char *)(nb + 1) > pmax) {
533374fad8bSMatthew Dillon 		nb = NULL;
534374fad8bSMatthew Dillon 	}
535fb9cd36dSAtsushi Murai 	return ((u_char *)nb);
536fb9cd36dSAtsushi Murai }
537fb9cd36dSAtsushi Murai 
538fb9cd36dSAtsushi Murai #define SizeOfResourceA		6
539fb9cd36dSAtsushi Murai typedef struct {
540fb9cd36dSAtsushi Murai 	struct in_addr	addr;
541fb9cd36dSAtsushi Murai } NBTNsResourceA;
542fb9cd36dSAtsushi Murai 
5434c32f5d2SBrian Somers static u_char *
AliasHandleResourceA(NBTNsResource * q,char * pmax,NBTArguments * nbtarg)544374fad8bSMatthew Dillon AliasHandleResourceA(
545374fad8bSMatthew Dillon     NBTNsResource *q,
546374fad8bSMatthew Dillon     char          *pmax,
547fb9cd36dSAtsushi Murai     NBTArguments  *nbtarg)
548fb9cd36dSAtsushi Murai {
549fb9cd36dSAtsushi Murai 	NBTNsResourceA *a;
550fb9cd36dSAtsushi Murai 	u_short bcount;
5518144690aSEric van Gyzen #ifdef LIBALIAS_DEBUG
5528144690aSEric van Gyzen 	char oldbuf[INET_ADDRSTRLEN];
5538144690aSEric van Gyzen 	char newbuf[INET_ADDRSTRLEN];
5548144690aSEric van Gyzen #endif
555fb9cd36dSAtsushi Murai 
556374fad8bSMatthew Dillon 	if (q == NULL || (char *)(q + 1) > pmax)
557374fad8bSMatthew Dillon 		return (NULL);
558374fad8bSMatthew Dillon 
559fb9cd36dSAtsushi Murai 	/* Forward to Resource A position */
560fb9cd36dSAtsushi Murai 	a = (NBTNsResourceA *)((u_char *)q + sizeof(NBTNsResource));
561fb9cd36dSAtsushi Murai 
562fb9cd36dSAtsushi Murai 	/* Check out of length */
563fb9cd36dSAtsushi Murai 	bcount = ntohs(q->rdlen);
564fb9cd36dSAtsushi Murai 
565fb9cd36dSAtsushi Murai 	/* Processing all in_addr array */
5666293e003SGleb Smirnoff #ifdef LIBALIAS_DEBUG
5678144690aSEric van Gyzen 	printf("Arec [%s->%s]",
5688144690aSEric van Gyzen 	    inet_ntoa_r(nbtarg->oldaddr, INET_NTOA_BUF(oldbuf)),
5698144690aSEric van Gyzen 	    inet_ntoa_r(nbtarg->newaddr, INET_NTOA_BUF(newbuf)));
570fb9cd36dSAtsushi Murai #endif
571fb9cd36dSAtsushi Murai 	while (bcount != 0) {
572374fad8bSMatthew Dillon 		if (a == NULL || (char *)(a + 1) > pmax)
573374fad8bSMatthew Dillon 			return (NULL);
5746293e003SGleb Smirnoff #ifdef LIBALIAS_DEBUG
5758144690aSEric van Gyzen 		printf("..%s", inet_ntoa_r(a->addr, INET_NTOA_BUF(newbuf)));
576fb9cd36dSAtsushi Murai #endif
577fb9cd36dSAtsushi Murai 		if (!bcmp(&nbtarg->oldaddr, &a->addr, sizeof(struct in_addr))) {
578fb9cd36dSAtsushi Murai 			if (*nbtarg->uh_sum != 0) {
579fb9cd36dSAtsushi Murai 				int acc;
580fb9cd36dSAtsushi Murai 				u_short *sptr;
581fb9cd36dSAtsushi Murai 
582fb9cd36dSAtsushi Murai 				sptr = (u_short *)&(a->addr);	/* Old */
583fb9cd36dSAtsushi Murai 				acc = *sptr++;
584fb9cd36dSAtsushi Murai 				acc += *sptr;
585fb9cd36dSAtsushi Murai 				sptr = (u_short *)&nbtarg->newaddr;	/* New */
586fb9cd36dSAtsushi Murai 				acc -= *sptr++;
587fb9cd36dSAtsushi Murai 				acc -= *sptr;
58871593f95SBrian Somers 				ADJUST_CHECKSUM(acc, *nbtarg->uh_sum);
589fb9cd36dSAtsushi Murai 			}
590fb9cd36dSAtsushi Murai 			a->addr = nbtarg->newaddr;
591fb9cd36dSAtsushi Murai 		}
592fb9cd36dSAtsushi Murai 		a++;		/* XXXX */
593fb9cd36dSAtsushi Murai 		bcount -= SizeOfResourceA;
594fb9cd36dSAtsushi Murai 	}
595374fad8bSMatthew Dillon 	if (a == NULL || (char *)(a + 1) > pmax)
596374fad8bSMatthew Dillon 		a = NULL;
597fb9cd36dSAtsushi Murai 	return ((u_char *)a);
598fb9cd36dSAtsushi Murai }
599fb9cd36dSAtsushi Murai 
600fb9cd36dSAtsushi Murai typedef struct {
601fb9cd36dSAtsushi Murai 	u_short		opcode:4, flags:8, resv:4;
602fb9cd36dSAtsushi Murai } NBTNsResourceNULL;
603fb9cd36dSAtsushi Murai 
6044c32f5d2SBrian Somers static u_char *
AliasHandleResourceNULL(NBTNsResource * q,char * pmax,NBTArguments * nbtarg)605374fad8bSMatthew Dillon AliasHandleResourceNULL(
606374fad8bSMatthew Dillon     NBTNsResource *q,
607374fad8bSMatthew Dillon     char          *pmax,
608fb9cd36dSAtsushi Murai     NBTArguments  *nbtarg)
609fb9cd36dSAtsushi Murai {
610fb9cd36dSAtsushi Murai 	NBTNsResourceNULL *n;
611fb9cd36dSAtsushi Murai 	u_short bcount;
612fb9cd36dSAtsushi Murai 
613ed01a582SDag-Erling Smørgrav 	(void)nbtarg;
614ed01a582SDag-Erling Smørgrav 
615374fad8bSMatthew Dillon 	if (q == NULL || (char *)(q + 1) > pmax)
616374fad8bSMatthew Dillon 		return (NULL);
617374fad8bSMatthew Dillon 
618fb9cd36dSAtsushi Murai 	/* Forward to Resource NULL position */
619fb9cd36dSAtsushi Murai 	n = (NBTNsResourceNULL *)((u_char *)q + sizeof(NBTNsResource));
620fb9cd36dSAtsushi Murai 
621fb9cd36dSAtsushi Murai 	/* Check out of length */
622fb9cd36dSAtsushi Murai 	bcount = ntohs(q->rdlen);
623fb9cd36dSAtsushi Murai 
624fb9cd36dSAtsushi Murai 	/* Processing all in_addr array */
625fb9cd36dSAtsushi Murai 	while (bcount != 0) {
626374fad8bSMatthew Dillon 		if ((char *)(n + 1) > pmax) {
627374fad8bSMatthew Dillon 			n = NULL;
628374fad8bSMatthew Dillon 			break;
629374fad8bSMatthew Dillon 		}
630fb9cd36dSAtsushi Murai 		n++;
631fb9cd36dSAtsushi Murai 		bcount -= sizeof(NBTNsResourceNULL);
632fb9cd36dSAtsushi Murai 	}
633374fad8bSMatthew Dillon 	if ((char *)(n + 1) > pmax)
634374fad8bSMatthew Dillon 		n = NULL;
635fb9cd36dSAtsushi Murai 
636fb9cd36dSAtsushi Murai 	return ((u_char *)n);
637fb9cd36dSAtsushi Murai }
638fb9cd36dSAtsushi Murai 
6394c32f5d2SBrian Somers static u_char *
AliasHandleResourceNS(NBTNsResource * q,char * pmax,NBTArguments * nbtarg)640374fad8bSMatthew Dillon AliasHandleResourceNS(
641374fad8bSMatthew Dillon     NBTNsResource *q,
642374fad8bSMatthew Dillon     char          *pmax,
643fb9cd36dSAtsushi Murai     NBTArguments  *nbtarg)
644fb9cd36dSAtsushi Murai {
645fb9cd36dSAtsushi Murai 	NBTNsResourceNULL *n;
646fb9cd36dSAtsushi Murai 	u_short bcount;
647fb9cd36dSAtsushi Murai 
648ed01a582SDag-Erling Smørgrav 	(void)nbtarg;
649ed01a582SDag-Erling Smørgrav 
650374fad8bSMatthew Dillon 	if (q == NULL || (char *)(q + 1) > pmax)
651374fad8bSMatthew Dillon 		return (NULL);
652374fad8bSMatthew Dillon 
653fb9cd36dSAtsushi Murai 	/* Forward to Resource NULL position */
654fb9cd36dSAtsushi Murai 	n = (NBTNsResourceNULL *)((u_char *)q + sizeof(NBTNsResource));
655fb9cd36dSAtsushi Murai 
656fb9cd36dSAtsushi Murai 	/* Check out of length */
657fb9cd36dSAtsushi Murai 	bcount = ntohs(q->rdlen);
658fb9cd36dSAtsushi Murai 
659fb9cd36dSAtsushi Murai 	/* Resource Record Name Filed */
660374fad8bSMatthew Dillon 	q = (NBTNsResource *)AliasHandleName((u_char *)n, pmax);	/* XXX */
661fb9cd36dSAtsushi Murai 
662374fad8bSMatthew Dillon 	if (q == NULL || (char *)((u_char *)n + bcount) > pmax)
663374fad8bSMatthew Dillon 		return (NULL);
664374fad8bSMatthew Dillon 	else
665fb9cd36dSAtsushi Murai 		return ((u_char *)n + bcount);
666fb9cd36dSAtsushi Murai }
667fb9cd36dSAtsushi Murai 
668fb9cd36dSAtsushi Murai typedef struct {
669fb9cd36dSAtsushi Murai 	u_short		numnames;
670fb9cd36dSAtsushi Murai } NBTNsResourceNBSTAT;
671fb9cd36dSAtsushi Murai 
6724c32f5d2SBrian Somers static u_char *
AliasHandleResourceNBSTAT(NBTNsResource * q,char * pmax,NBTArguments * nbtarg)673374fad8bSMatthew Dillon AliasHandleResourceNBSTAT(
674374fad8bSMatthew Dillon     NBTNsResource *q,
675374fad8bSMatthew Dillon     char          *pmax,
676fb9cd36dSAtsushi Murai     NBTArguments  *nbtarg)
677fb9cd36dSAtsushi Murai {
678fb9cd36dSAtsushi Murai 	NBTNsResourceNBSTAT *n;
679fb9cd36dSAtsushi Murai 	u_short bcount;
680fb9cd36dSAtsushi Murai 
681ed01a582SDag-Erling Smørgrav 	(void)nbtarg;
682ed01a582SDag-Erling Smørgrav 
683374fad8bSMatthew Dillon 	if (q == NULL || (char *)(q + 1) > pmax)
684374fad8bSMatthew Dillon 		return (NULL);
685374fad8bSMatthew Dillon 
686fb9cd36dSAtsushi Murai 	/* Forward to Resource NBSTAT position */
687fb9cd36dSAtsushi Murai 	n = (NBTNsResourceNBSTAT *)((u_char *)q + sizeof(NBTNsResource));
688fb9cd36dSAtsushi Murai 
689fb9cd36dSAtsushi Murai 	/* Check out of length */
690fb9cd36dSAtsushi Murai 	bcount = ntohs(q->rdlen);
691fb9cd36dSAtsushi Murai 
692374fad8bSMatthew Dillon 	if (q == NULL || (char *)((u_char *)n + bcount) > pmax)
693374fad8bSMatthew Dillon 		return (NULL);
694374fad8bSMatthew Dillon 	else
695fb9cd36dSAtsushi Murai 		return ((u_char *)n + bcount);
696fb9cd36dSAtsushi Murai }
697fb9cd36dSAtsushi Murai 
6984c32f5d2SBrian Somers static u_char *
AliasHandleResource(u_short count,NBTNsResource * q,char * pmax,NBTArguments * nbtarg)699374fad8bSMatthew Dillon AliasHandleResource(
700374fad8bSMatthew Dillon     u_short        count,
701fb9cd36dSAtsushi Murai     NBTNsResource *q,
702374fad8bSMatthew Dillon     char          *pmax,
703effc8e57SLutz Donnerhacke     NBTArguments  *nbtarg)
704fb9cd36dSAtsushi Murai {
705fb9cd36dSAtsushi Murai 	while (count != 0) {
706fb9cd36dSAtsushi Murai 		/* Resource Record Name Filed */
707374fad8bSMatthew Dillon 		q = (NBTNsResource *)AliasHandleName((u_char *)q, pmax);
708374fad8bSMatthew Dillon 
709374fad8bSMatthew Dillon 		if (q == NULL || (char *)(q + 1) > pmax)
710374fad8bSMatthew Dillon 			break;
7116293e003SGleb Smirnoff #ifdef LIBALIAS_DEBUG
712fb9cd36dSAtsushi Murai 		printf("type=%02x, count=%d\n", ntohs(q->type), count);
713fb9cd36dSAtsushi Murai #endif
714fb9cd36dSAtsushi Murai 
715fb9cd36dSAtsushi Murai 		/* Type and Class filed */
716fb9cd36dSAtsushi Murai 		switch (ntohs(q->type)) {
717fb9cd36dSAtsushi Murai 		case RR_TYPE_NB:
718374fad8bSMatthew Dillon 			q = (NBTNsResource *)AliasHandleResourceNB(
719effc8e57SLutz Donnerhacke 			    q, pmax, nbtarg);
720fb9cd36dSAtsushi Murai 			break;
721fb9cd36dSAtsushi Murai 		case RR_TYPE_A:
722374fad8bSMatthew Dillon 			q = (NBTNsResource *)AliasHandleResourceA(
723effc8e57SLutz Donnerhacke 			    q, pmax, nbtarg);
724fb9cd36dSAtsushi Murai 			break;
725fb9cd36dSAtsushi Murai 		case RR_TYPE_NS:
726374fad8bSMatthew Dillon 			q = (NBTNsResource *)AliasHandleResourceNS(
727effc8e57SLutz Donnerhacke 			    q, pmax, nbtarg);
728fb9cd36dSAtsushi Murai 			break;
729fb9cd36dSAtsushi Murai 		case RR_TYPE_NULL:
730374fad8bSMatthew Dillon 			q = (NBTNsResource *)AliasHandleResourceNULL(
731effc8e57SLutz Donnerhacke 			    q, pmax, nbtarg);
732fb9cd36dSAtsushi Murai 			break;
733fb9cd36dSAtsushi Murai 		case RR_TYPE_NBSTAT:
734374fad8bSMatthew Dillon 			q = (NBTNsResource *)AliasHandleResourceNBSTAT(
735effc8e57SLutz Donnerhacke 			    q, pmax, nbtarg);
736fb9cd36dSAtsushi Murai 			break;
737374fad8bSMatthew Dillon 		default:
7386293e003SGleb Smirnoff #ifdef LIBALIAS_DEBUG
739374fad8bSMatthew Dillon 			printf(
740374fad8bSMatthew Dillon 			    "\nUnknown Type of Resource %0x\n",
741374fad8bSMatthew Dillon 			    ntohs(q->type)
742374fad8bSMatthew Dillon 			    );
743ae044057SGleb Smirnoff 			fflush(stdout);
7444c32f5d2SBrian Somers #endif
745fb9cd36dSAtsushi Murai 			break;
746fb9cd36dSAtsushi Murai 		}
747fb9cd36dSAtsushi Murai 		count--;
748fb9cd36dSAtsushi Murai 	}
749fb9cd36dSAtsushi Murai 	return ((u_char *)q);
750fb9cd36dSAtsushi Murai }
751fb9cd36dSAtsushi Murai 
752be4f3cd0SPaolo Pisati static int
AliasHandleUdpNbtNS(struct libalias * la,struct ip * pip,struct alias_link * lnk,struct in_addr * alias_address,u_short * alias_port,struct in_addr * original_address,u_short * original_port)753f0f93429SDag-Erling Smørgrav AliasHandleUdpNbtNS(
7545e289f9eSPoul-Henning Kamp     struct libalias   *la,
755fb9cd36dSAtsushi Murai     struct ip         *pip,	/* IP packet to examine/patch */
756ed01a582SDag-Erling Smørgrav     struct alias_link *lnk,
757fb9cd36dSAtsushi Murai     struct in_addr    *alias_address,
758fb9cd36dSAtsushi Murai     u_short           *alias_port,
759fb9cd36dSAtsushi Murai     struct in_addr    *original_address,
760fb9cd36dSAtsushi Murai     u_short           *original_port)
761fb9cd36dSAtsushi Murai {
762fb9cd36dSAtsushi Murai 	struct udphdr *uh;
763fb9cd36dSAtsushi Murai 	NbtNSHeader *nsh;
764fb9cd36dSAtsushi Murai 	u_char *p;
765374fad8bSMatthew Dillon 	char *pmax;
766fb9cd36dSAtsushi Murai 	NBTArguments nbtarg;
767fb9cd36dSAtsushi Murai 
768ed01a582SDag-Erling Smørgrav 	(void)la;
769ed01a582SDag-Erling Smørgrav 	(void)lnk;
770ed01a582SDag-Erling Smørgrav 
771fb9cd36dSAtsushi Murai 	/* Set up Common Parameter */
772fb9cd36dSAtsushi Murai 	nbtarg.oldaddr = *alias_address;
773fb9cd36dSAtsushi Murai 	nbtarg.oldport = *alias_port;
774fb9cd36dSAtsushi Murai 	nbtarg.newaddr = *original_address;
775fb9cd36dSAtsushi Murai 	nbtarg.newport = *original_port;
776fb9cd36dSAtsushi Murai 
777fb9cd36dSAtsushi Murai 	/* Calculate data length of UDP packet */
7789fa0fd26SDag-Erling Smørgrav 	uh = (struct udphdr *)ip_next(pip);
779fb9cd36dSAtsushi Murai 	nbtarg.uh_sum = &(uh->uh_sum);
7809fa0fd26SDag-Erling Smørgrav 	nsh = (NbtNSHeader *)udp_next(uh);
781fb9cd36dSAtsushi Murai 	p = (u_char *)(nsh + 1);
782374fad8bSMatthew Dillon 	pmax = (char *)uh + ntohs(uh->uh_ulen);
783374fad8bSMatthew Dillon 
784374fad8bSMatthew Dillon 	if ((char *)(nsh + 1) > pmax)
785374fad8bSMatthew Dillon 		return (-1);
786fb9cd36dSAtsushi Murai 
7876293e003SGleb Smirnoff #ifdef LIBALIAS_DEBUG
788374fad8bSMatthew Dillon 	printf(" [%s] ID=%02x, op=%01x, flag=%02x, rcode=%01x, qd=%04x"
789374fad8bSMatthew Dillon 	    ", an=%04x, ns=%04x, ar=%04x, [%d]-->",
790fb9cd36dSAtsushi Murai 	    nsh->dir ? "Response" : "Request",
791fb9cd36dSAtsushi Murai 	    nsh->nametrid,
792fb9cd36dSAtsushi Murai 	    nsh->opcode,
793fb9cd36dSAtsushi Murai 	    nsh->nmflags,
794fb9cd36dSAtsushi Murai 	    nsh->rcode,
795fb9cd36dSAtsushi Murai 	    ntohs(nsh->qdcount),
796fb9cd36dSAtsushi Murai 	    ntohs(nsh->ancount),
797fb9cd36dSAtsushi Murai 	    ntohs(nsh->nscount),
798fb9cd36dSAtsushi Murai 	    ntohs(nsh->arcount),
799374fad8bSMatthew Dillon 	    (u_char *)p - (u_char *)nsh
800374fad8bSMatthew Dillon 	    );
801fb9cd36dSAtsushi Murai #endif
802fb9cd36dSAtsushi Murai 
803fb9cd36dSAtsushi Murai 	/* Question Entries */
804fb9cd36dSAtsushi Murai 	if (ntohs(nsh->qdcount) != 0) {
805374fad8bSMatthew Dillon 		p = AliasHandleQuestion(
806374fad8bSMatthew Dillon 		    ntohs(nsh->qdcount),
807374fad8bSMatthew Dillon 		    (NBTNsQuestion *)p,
808374fad8bSMatthew Dillon 		    pmax,
809374fad8bSMatthew Dillon 		    &nbtarg
810374fad8bSMatthew Dillon 		    );
811fb9cd36dSAtsushi Murai 	}
812fb9cd36dSAtsushi Murai 	/* Answer Resource Records */
813fb9cd36dSAtsushi Murai 	if (ntohs(nsh->ancount) != 0) {
814374fad8bSMatthew Dillon 		p = AliasHandleResource(
815374fad8bSMatthew Dillon 		    ntohs(nsh->ancount),
816374fad8bSMatthew Dillon 		    (NBTNsResource *)p,
817374fad8bSMatthew Dillon 		    pmax,
818374fad8bSMatthew Dillon 		    &nbtarg
819374fad8bSMatthew Dillon 		    );
820fb9cd36dSAtsushi Murai 	}
821fb9cd36dSAtsushi Murai 	/* Authority Resource Recodrs */
822fb9cd36dSAtsushi Murai 	if (ntohs(nsh->nscount) != 0) {
823374fad8bSMatthew Dillon 		p = AliasHandleResource(
824374fad8bSMatthew Dillon 		    ntohs(nsh->nscount),
825374fad8bSMatthew Dillon 		    (NBTNsResource *)p,
826374fad8bSMatthew Dillon 		    pmax,
827374fad8bSMatthew Dillon 		    &nbtarg
828374fad8bSMatthew Dillon 		    );
829fb9cd36dSAtsushi Murai 	}
830fb9cd36dSAtsushi Murai 	/* Additional Resource Recodrs */
831fb9cd36dSAtsushi Murai 	if (ntohs(nsh->arcount) != 0) {
832374fad8bSMatthew Dillon 		p = AliasHandleResource(
833374fad8bSMatthew Dillon 		    ntohs(nsh->arcount),
834374fad8bSMatthew Dillon 		    (NBTNsResource *)p,
835374fad8bSMatthew Dillon 		    pmax,
836374fad8bSMatthew Dillon 		    &nbtarg
837374fad8bSMatthew Dillon 		    );
838fb9cd36dSAtsushi Murai 	}
8396293e003SGleb Smirnoff #ifdef LIBALIAS_DEBUG
840fb9cd36dSAtsushi Murai 	PrintRcode(nsh->rcode);
841fb9cd36dSAtsushi Murai #endif
842374fad8bSMatthew Dillon 	return ((p == NULL) ? -1 : 0);
843fb9cd36dSAtsushi Murai }
844