1a9643ea8Slogwang /*-
2*22ce4affSfengbojiang  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3*22ce4affSfengbojiang  *
4a9643ea8Slogwang  * Written by Atsushi Murai <[email protected]>
5a9643ea8Slogwang  * Copyright (c) 1998, System Planning and Engineering Co.
6a9643ea8Slogwang  * All rights reserved.
7a9643ea8Slogwang  *
8a9643ea8Slogwang  * Redistribution and use in source and binary forms, with or without
9a9643ea8Slogwang  * modification, are permitted provided that the following conditions
10a9643ea8Slogwang  * are met:
11a9643ea8Slogwang  * 1. Redistributions of source code must retain the above copyright
12a9643ea8Slogwang  *    notice, this list of conditions and the following disclaimer.
13a9643ea8Slogwang  * 2. Redistributions in binary form must reproduce the above copyright
14a9643ea8Slogwang  *    notice, this list of conditions and the following disclaimer in the
15a9643ea8Slogwang  *    documentation and/or other materials provided with the distribution.
16a9643ea8Slogwang  *
17a9643ea8Slogwang  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18a9643ea8Slogwang  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19a9643ea8Slogwang  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20a9643ea8Slogwang  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21a9643ea8Slogwang  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22a9643ea8Slogwang  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23a9643ea8Slogwang  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24a9643ea8Slogwang  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25a9643ea8Slogwang  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26a9643ea8Slogwang  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27a9643ea8Slogwang  * SUCH DAMAGE.
28a9643ea8Slogwang  *  TODO:
29a9643ea8Slogwang  *       oClean up.
30a9643ea8Slogwang  *       oConsidering for word alignment for other platform.
31a9643ea8Slogwang  */
32a9643ea8Slogwang 
33a9643ea8Slogwang #include <sys/cdefs.h>
34a9643ea8Slogwang __FBSDID("$FreeBSD$");
35a9643ea8Slogwang 
36a9643ea8Slogwang /*
37a9643ea8Slogwang     alias_nbt.c performs special processing for NetBios over TCP/IP
38a9643ea8Slogwang     sessions by UDP.
39a9643ea8Slogwang 
40a9643ea8Slogwang     Initial version:  May, 1998  (Atsushi Murai <[email protected]>)
41a9643ea8Slogwang 
42a9643ea8Slogwang     See HISTORY file for record of revisions.
43a9643ea8Slogwang */
44a9643ea8Slogwang 
45a9643ea8Slogwang /* Includes */
46a9643ea8Slogwang #ifdef _KERNEL
47a9643ea8Slogwang #include <sys/param.h>
48a9643ea8Slogwang #include <sys/systm.h>
49a9643ea8Slogwang #include <sys/kernel.h>
50a9643ea8Slogwang #include <sys/module.h>
51a9643ea8Slogwang #else
52a9643ea8Slogwang #include <errno.h>
53a9643ea8Slogwang #include <sys/types.h>
54a9643ea8Slogwang #include <stdio.h>
55a9643ea8Slogwang #include <strings.h>
56a9643ea8Slogwang #endif
57a9643ea8Slogwang 
58a9643ea8Slogwang #include <netinet/in_systm.h>
59a9643ea8Slogwang #include <netinet/in.h>
60a9643ea8Slogwang #include <netinet/ip.h>
61a9643ea8Slogwang #include <netinet/udp.h>
62a9643ea8Slogwang 
63a9643ea8Slogwang #ifdef _KERNEL
64a9643ea8Slogwang #include <netinet/libalias/alias_local.h>
65a9643ea8Slogwang #include <netinet/libalias/alias_mod.h>
66a9643ea8Slogwang #else
67a9643ea8Slogwang #include "alias_local.h"
68a9643ea8Slogwang #include "alias_mod.h"
69a9643ea8Slogwang #endif
70a9643ea8Slogwang 
71a9643ea8Slogwang #define NETBIOS_NS_PORT_NUMBER 137
72a9643ea8Slogwang #define NETBIOS_DGM_PORT_NUMBER 138
73a9643ea8Slogwang 
74a9643ea8Slogwang static int
75a9643ea8Slogwang AliasHandleUdpNbt(struct libalias *, struct ip *, struct alias_link *,
76a9643ea8Slogwang 		  struct in_addr *, u_short);
77a9643ea8Slogwang 
78a9643ea8Slogwang static int
79a9643ea8Slogwang AliasHandleUdpNbtNS(struct libalias *, struct ip *, struct alias_link *,
80a9643ea8Slogwang 		    struct in_addr *, u_short *, struct in_addr *, u_short *);
81a9643ea8Slogwang static int
fingerprint1(struct libalias * la,struct alias_data * ah)82a9643ea8Slogwang fingerprint1(struct libalias *la, struct alias_data *ah)
83a9643ea8Slogwang {
84a9643ea8Slogwang 
85a9643ea8Slogwang 	if (ah->dport == NULL || ah->sport == NULL || ah->lnk == NULL ||
86a9643ea8Slogwang 	    ah->aaddr == NULL || ah->aport == NULL)
87a9643ea8Slogwang 		return (-1);
88a9643ea8Slogwang 	if (ntohs(*ah->dport) == NETBIOS_DGM_PORT_NUMBER
89a9643ea8Slogwang 	    || ntohs(*ah->sport) == NETBIOS_DGM_PORT_NUMBER)
90a9643ea8Slogwang 		return (0);
91a9643ea8Slogwang 	return (-1);
92a9643ea8Slogwang }
93a9643ea8Slogwang 
94a9643ea8Slogwang static int
protohandler1(struct libalias * la,struct ip * pip,struct alias_data * ah)95a9643ea8Slogwang protohandler1(struct libalias *la, struct ip *pip, struct alias_data *ah)
96a9643ea8Slogwang {
97a9643ea8Slogwang 
98a9643ea8Slogwang 	return (AliasHandleUdpNbt(la, pip, ah->lnk, ah->aaddr, *ah->aport));
99a9643ea8Slogwang }
100a9643ea8Slogwang 
101a9643ea8Slogwang static int
fingerprint2(struct libalias * la,struct alias_data * ah)102a9643ea8Slogwang fingerprint2(struct libalias *la, struct alias_data *ah)
103a9643ea8Slogwang {
104a9643ea8Slogwang 
105a9643ea8Slogwang 	if (ah->dport == NULL || ah->sport == NULL || ah->lnk == NULL ||
106a9643ea8Slogwang 	    ah->aaddr == NULL || ah->aport == NULL)
107a9643ea8Slogwang 		return (-1);
108a9643ea8Slogwang 	if (ntohs(*ah->dport) == NETBIOS_NS_PORT_NUMBER
109a9643ea8Slogwang 	    || ntohs(*ah->sport) == NETBIOS_NS_PORT_NUMBER)
110a9643ea8Slogwang 		return (0);
111a9643ea8Slogwang 	return (-1);
112a9643ea8Slogwang }
113a9643ea8Slogwang 
114a9643ea8Slogwang static int
protohandler2in(struct libalias * la,struct ip * pip,struct alias_data * ah)115a9643ea8Slogwang protohandler2in(struct libalias *la, struct ip *pip, struct alias_data *ah)
116a9643ea8Slogwang {
117a9643ea8Slogwang 
118a9643ea8Slogwang 	AliasHandleUdpNbtNS(la, pip, ah->lnk, ah->aaddr, ah->aport,
119a9643ea8Slogwang  			    ah->oaddr, ah->dport);
120a9643ea8Slogwang 	return (0);
121a9643ea8Slogwang }
122a9643ea8Slogwang 
123a9643ea8Slogwang static int
protohandler2out(struct libalias * la,struct ip * pip,struct alias_data * ah)124a9643ea8Slogwang protohandler2out(struct libalias *la, struct ip *pip, struct alias_data *ah)
125a9643ea8Slogwang {
126a9643ea8Slogwang 
127a9643ea8Slogwang 	return (AliasHandleUdpNbtNS(la, pip, ah->lnk, &pip->ip_src, ah->sport,
128a9643ea8Slogwang  	    ah->aaddr, ah->aport));
129a9643ea8Slogwang }
130a9643ea8Slogwang 
131a9643ea8Slogwang /* Kernel module definition. */
132a9643ea8Slogwang struct proto_handler handlers[] = {
133a9643ea8Slogwang 	{
134a9643ea8Slogwang 	  .pri = 130,
135a9643ea8Slogwang 	  .dir = IN|OUT,
136a9643ea8Slogwang 	  .proto = UDP,
137a9643ea8Slogwang 	  .fingerprint = &fingerprint1,
138a9643ea8Slogwang 	  .protohandler = &protohandler1
139a9643ea8Slogwang 	},
140a9643ea8Slogwang 	{
141a9643ea8Slogwang 	  .pri = 140,
142a9643ea8Slogwang 	  .dir = IN,
143a9643ea8Slogwang 	  .proto = UDP,
144a9643ea8Slogwang 	  .fingerprint = &fingerprint2,
145a9643ea8Slogwang 	  .protohandler = &protohandler2in
146a9643ea8Slogwang 	},
147a9643ea8Slogwang 	{
148a9643ea8Slogwang 	  .pri = 140,
149a9643ea8Slogwang 	  .dir = OUT,
150a9643ea8Slogwang 	  .proto = UDP,
151a9643ea8Slogwang 	  .fingerprint = &fingerprint2,
152a9643ea8Slogwang 	  .protohandler = &protohandler2out
153a9643ea8Slogwang 	},
154a9643ea8Slogwang 	{ EOH }
155a9643ea8Slogwang };
156a9643ea8Slogwang 
157a9643ea8Slogwang static int
mod_handler(module_t mod,int type,void * data)158a9643ea8Slogwang mod_handler(module_t mod, int type, void *data)
159a9643ea8Slogwang {
160a9643ea8Slogwang 	int error;
161a9643ea8Slogwang 
162a9643ea8Slogwang 	switch (type) {
163a9643ea8Slogwang 	case MOD_LOAD:
164a9643ea8Slogwang 		error = 0;
165a9643ea8Slogwang 		LibAliasAttachHandlers(handlers);
166a9643ea8Slogwang 		break;
167a9643ea8Slogwang 	case MOD_UNLOAD:
168a9643ea8Slogwang 		error = 0;
169a9643ea8Slogwang 		LibAliasDetachHandlers(handlers);
170a9643ea8Slogwang 		break;
171a9643ea8Slogwang 	default:
172a9643ea8Slogwang 		error = EINVAL;
173a9643ea8Slogwang 	}
174a9643ea8Slogwang 	return (error);
175a9643ea8Slogwang }
176a9643ea8Slogwang 
177a9643ea8Slogwang #ifdef	_KERNEL
178a9643ea8Slogwang static
179a9643ea8Slogwang #endif
180a9643ea8Slogwang moduledata_t alias_mod = {
181a9643ea8Slogwang        "alias_nbt", mod_handler, NULL
182a9643ea8Slogwang };
183a9643ea8Slogwang 
184a9643ea8Slogwang #ifdef	_KERNEL
185a9643ea8Slogwang DECLARE_MODULE(alias_nbt, alias_mod, SI_SUB_DRIVERS, SI_ORDER_SECOND);
186a9643ea8Slogwang MODULE_VERSION(alias_nbt, 1);
187a9643ea8Slogwang MODULE_DEPEND(alias_nbt, libalias, 1, 1, 1);
188a9643ea8Slogwang #endif
189a9643ea8Slogwang 
190a9643ea8Slogwang typedef struct {
191a9643ea8Slogwang 	struct in_addr	oldaddr;
192a9643ea8Slogwang 	u_short		oldport;
193a9643ea8Slogwang 	struct in_addr	newaddr;
194a9643ea8Slogwang 	u_short		newport;
195a9643ea8Slogwang 	u_short        *uh_sum;
196a9643ea8Slogwang }		NBTArguments;
197a9643ea8Slogwang 
198a9643ea8Slogwang typedef struct {
199a9643ea8Slogwang 	unsigned char	type;
200a9643ea8Slogwang 	unsigned char	flags;
201a9643ea8Slogwang 	u_short		id;
202a9643ea8Slogwang 	struct in_addr	source_ip;
203a9643ea8Slogwang 	u_short		source_port;
204a9643ea8Slogwang 	u_short		len;
205a9643ea8Slogwang 	u_short		offset;
206a9643ea8Slogwang }		NbtDataHeader;
207a9643ea8Slogwang 
208a9643ea8Slogwang #define OpQuery		0
209a9643ea8Slogwang #define OpUnknown	4
210a9643ea8Slogwang #define OpRegist	5
211a9643ea8Slogwang #define OpRelease	6
212a9643ea8Slogwang #define OpWACK		7
213a9643ea8Slogwang #define OpRefresh	8
214a9643ea8Slogwang typedef struct {
215a9643ea8Slogwang 	u_short		nametrid;
216a9643ea8Slogwang 	u_short		dir:	1, opcode:4, nmflags:7, rcode:4;
217a9643ea8Slogwang 	u_short		qdcount;
218a9643ea8Slogwang 	u_short		ancount;
219a9643ea8Slogwang 	u_short		nscount;
220a9643ea8Slogwang 	u_short		arcount;
221a9643ea8Slogwang }		NbtNSHeader;
222a9643ea8Slogwang 
223a9643ea8Slogwang #define FMT_ERR		0x1
224a9643ea8Slogwang #define SRV_ERR		0x2
225a9643ea8Slogwang #define IMP_ERR		0x4
226a9643ea8Slogwang #define RFS_ERR		0x5
227a9643ea8Slogwang #define ACT_ERR		0x6
228a9643ea8Slogwang #define CFT_ERR		0x7
229a9643ea8Slogwang 
230a9643ea8Slogwang #ifdef LIBALIAS_DEBUG
231a9643ea8Slogwang static void
PrintRcode(u_char rcode)232a9643ea8Slogwang PrintRcode(u_char rcode)
233a9643ea8Slogwang {
234a9643ea8Slogwang 
235a9643ea8Slogwang 	switch (rcode) {
236a9643ea8Slogwang 		case FMT_ERR:
237a9643ea8Slogwang 		printf("\nFormat Error.");
238a9643ea8Slogwang 	case SRV_ERR:
239a9643ea8Slogwang 		printf("\nSever failure.");
240a9643ea8Slogwang 	case IMP_ERR:
241a9643ea8Slogwang 		printf("\nUnsupported request error.\n");
242a9643ea8Slogwang 	case RFS_ERR:
243a9643ea8Slogwang 		printf("\nRefused error.\n");
244a9643ea8Slogwang 	case ACT_ERR:
245a9643ea8Slogwang 		printf("\nActive error.\n");
246a9643ea8Slogwang 	case CFT_ERR:
247a9643ea8Slogwang 		printf("\nName in conflict error.\n");
248a9643ea8Slogwang 	default:
249a9643ea8Slogwang 		printf("\n?%c?=%0x\n", '?', rcode);
250a9643ea8Slogwang 	}
251a9643ea8Slogwang }
252a9643ea8Slogwang 
253a9643ea8Slogwang #endif
254a9643ea8Slogwang 
255a9643ea8Slogwang /* Handling Name field */
256a9643ea8Slogwang static u_char  *
AliasHandleName(u_char * p,char * pmax)257a9643ea8Slogwang AliasHandleName(u_char * p, char *pmax)
258a9643ea8Slogwang {
259a9643ea8Slogwang 
260a9643ea8Slogwang 	u_char *s;
261a9643ea8Slogwang 	u_char c;
262a9643ea8Slogwang 	int compress;
263a9643ea8Slogwang 
264a9643ea8Slogwang 	/* Following length field */
265a9643ea8Slogwang 
266a9643ea8Slogwang 	if (p == NULL || (char *)p >= pmax)
267a9643ea8Slogwang 		return (NULL);
268a9643ea8Slogwang 
269a9643ea8Slogwang 	if (*p & 0xc0) {
270a9643ea8Slogwang 		p = p + 2;
271a9643ea8Slogwang 		if ((char *)p > pmax)
272a9643ea8Slogwang 			return (NULL);
273a9643ea8Slogwang 		return ((u_char *) p);
274a9643ea8Slogwang 	}
275a9643ea8Slogwang 	while ((*p & 0x3f) != 0x00) {
276a9643ea8Slogwang 		s = p + 1;
277a9643ea8Slogwang 		if (*p == 0x20)
278a9643ea8Slogwang 			compress = 1;
279a9643ea8Slogwang 		else
280a9643ea8Slogwang 			compress = 0;
281a9643ea8Slogwang 
282a9643ea8Slogwang 		/* Get next length field */
283a9643ea8Slogwang 		p = (u_char *) (p + (*p & 0x3f) + 1);
284a9643ea8Slogwang 		if ((char *)p > pmax) {
285a9643ea8Slogwang 			p = NULL;
286a9643ea8Slogwang 			break;
287a9643ea8Slogwang 		}
288a9643ea8Slogwang #ifdef LIBALIAS_DEBUG
289a9643ea8Slogwang 		printf(":");
290a9643ea8Slogwang #endif
291a9643ea8Slogwang 		while (s < p) {
292a9643ea8Slogwang 			if (compress == 1) {
293a9643ea8Slogwang 				c = (u_char) (((((*s & 0x0f) << 4) | (*(s + 1) & 0x0f)) - 0x11));
294a9643ea8Slogwang #ifdef LIBALIAS_DEBUG
295a9643ea8Slogwang 				if (isprint(c))
296a9643ea8Slogwang 					printf("%c", c);
297a9643ea8Slogwang 				else
298a9643ea8Slogwang 					printf("<0x%02x>", c);
299a9643ea8Slogwang #endif
300a9643ea8Slogwang 				s += 2;
301a9643ea8Slogwang 			} else {
302a9643ea8Slogwang #ifdef LIBALIAS_DEBUG
303a9643ea8Slogwang 				printf("%c", *s);
304a9643ea8Slogwang #endif
305a9643ea8Slogwang 				s++;
306a9643ea8Slogwang 			}
307a9643ea8Slogwang 		}
308a9643ea8Slogwang #ifdef LIBALIAS_DEBUG
309a9643ea8Slogwang 		printf(":");
310a9643ea8Slogwang 		fflush(stdout);
311a9643ea8Slogwang #endif
312a9643ea8Slogwang 	}
313a9643ea8Slogwang 
314a9643ea8Slogwang 	/* Set up to out of Name field */
315a9643ea8Slogwang 	if (p == NULL || (char *)p >= pmax)
316a9643ea8Slogwang 		p = NULL;
317a9643ea8Slogwang 	else
318a9643ea8Slogwang 		p++;
319a9643ea8Slogwang 	return ((u_char *) p);
320a9643ea8Slogwang }
321a9643ea8Slogwang 
322a9643ea8Slogwang /*
323a9643ea8Slogwang  * NetBios Datagram Handler (IP/UDP)
324a9643ea8Slogwang  */
325a9643ea8Slogwang #define DGM_DIRECT_UNIQ		0x10
326a9643ea8Slogwang #define DGM_DIRECT_GROUP	0x11
327a9643ea8Slogwang #define DGM_BROADCAST		0x12
328a9643ea8Slogwang #define DGM_ERROR			0x13
329a9643ea8Slogwang #define DGM_QUERY			0x14
330a9643ea8Slogwang #define DGM_POSITIVE_RES	0x15
331a9643ea8Slogwang #define DGM_NEGATIVE_RES	0x16
332a9643ea8Slogwang 
333a9643ea8Slogwang static int
AliasHandleUdpNbt(struct libalias * la,struct ip * pip,struct alias_link * lnk,struct in_addr * alias_address,u_short alias_port)334a9643ea8Slogwang AliasHandleUdpNbt(
335a9643ea8Slogwang     struct libalias *la,
336a9643ea8Slogwang     struct ip *pip,		/* IP packet to examine/patch */
337a9643ea8Slogwang     struct alias_link *lnk,
338a9643ea8Slogwang     struct in_addr *alias_address,
339a9643ea8Slogwang     u_short alias_port
340a9643ea8Slogwang )
341a9643ea8Slogwang {
342a9643ea8Slogwang 	struct udphdr *uh;
343a9643ea8Slogwang 	NbtDataHeader *ndh;
344a9643ea8Slogwang 	u_char *p = NULL;
345a9643ea8Slogwang 	char *pmax;
346*22ce4affSfengbojiang #ifdef LIBALIAS_DEBUG
347*22ce4affSfengbojiang 	char addrbuf[INET_ADDRSTRLEN];
348*22ce4affSfengbojiang #endif
349a9643ea8Slogwang 
350a9643ea8Slogwang 	(void)la;
351a9643ea8Slogwang 	(void)lnk;
352a9643ea8Slogwang 
353a9643ea8Slogwang 	/* Calculate data length of UDP packet */
354a9643ea8Slogwang 	uh = (struct udphdr *)ip_next(pip);
355a9643ea8Slogwang 	pmax = (char *)uh + ntohs(uh->uh_ulen);
356a9643ea8Slogwang 
357a9643ea8Slogwang 	ndh = (NbtDataHeader *)udp_next(uh);
358a9643ea8Slogwang 	if ((char *)(ndh + 1) > pmax)
359a9643ea8Slogwang 		return (-1);
360a9643ea8Slogwang #ifdef LIBALIAS_DEBUG
361a9643ea8Slogwang 	printf("\nType=%02x,", ndh->type);
362a9643ea8Slogwang #endif
363a9643ea8Slogwang 	switch (ndh->type) {
364a9643ea8Slogwang 	case DGM_DIRECT_UNIQ:
365a9643ea8Slogwang 	case DGM_DIRECT_GROUP:
366a9643ea8Slogwang 	case DGM_BROADCAST:
367a9643ea8Slogwang 		p = (u_char *) ndh + 14;
368a9643ea8Slogwang 		p = AliasHandleName(p, pmax);	/* Source Name */
369a9643ea8Slogwang 		p = AliasHandleName(p, pmax);	/* Destination Name */
370a9643ea8Slogwang 		break;
371a9643ea8Slogwang 	case DGM_ERROR:
372a9643ea8Slogwang 		p = (u_char *) ndh + 11;
373a9643ea8Slogwang 		break;
374a9643ea8Slogwang 	case DGM_QUERY:
375a9643ea8Slogwang 	case DGM_POSITIVE_RES:
376a9643ea8Slogwang 	case DGM_NEGATIVE_RES:
377a9643ea8Slogwang 		p = (u_char *) ndh + 10;
378a9643ea8Slogwang 		p = AliasHandleName(p, pmax);	/* Destination Name */
379a9643ea8Slogwang 		break;
380a9643ea8Slogwang 	}
381a9643ea8Slogwang 	if (p == NULL || (char *)p > pmax)
382a9643ea8Slogwang 		p = NULL;
383a9643ea8Slogwang #ifdef LIBALIAS_DEBUG
384*22ce4affSfengbojiang 	printf("%s:%d-->", inet_ntoa_r(ndh->source_ip, INET_NTOA_BUF(addrbuf)),
385*22ce4affSfengbojiang 	    ntohs(ndh->source_port));
386a9643ea8Slogwang #endif
387a9643ea8Slogwang 	/* Doing an IP address and Port number Translation */
388a9643ea8Slogwang 	if (uh->uh_sum != 0) {
389a9643ea8Slogwang 		int acc;
390a9643ea8Slogwang 		u_short *sptr;
391a9643ea8Slogwang 
392a9643ea8Slogwang 		acc = ndh->source_port;
393a9643ea8Slogwang 		acc -= alias_port;
394a9643ea8Slogwang 		sptr = (u_short *) & (ndh->source_ip);
395a9643ea8Slogwang 		acc += *sptr++;
396a9643ea8Slogwang 		acc += *sptr;
397a9643ea8Slogwang 		sptr = (u_short *) alias_address;
398a9643ea8Slogwang 		acc -= *sptr++;
399a9643ea8Slogwang 		acc -= *sptr;
400a9643ea8Slogwang 		ADJUST_CHECKSUM(acc, uh->uh_sum);
401a9643ea8Slogwang 	}
402a9643ea8Slogwang 	ndh->source_ip = *alias_address;
403a9643ea8Slogwang 	ndh->source_port = alias_port;
404a9643ea8Slogwang #ifdef LIBALIAS_DEBUG
405*22ce4affSfengbojiang 	printf("%s:%d\n", inet_ntoa_r(ndh->source_ip, INET_NTOA_BUF(addrbuf)),
406*22ce4affSfengbojiang 	    ntohs(ndh->source_port));
407a9643ea8Slogwang 	fflush(stdout);
408a9643ea8Slogwang #endif
409a9643ea8Slogwang 	return ((p == NULL) ? -1 : 0);
410a9643ea8Slogwang }
411a9643ea8Slogwang 
412a9643ea8Slogwang /* Question Section */
413a9643ea8Slogwang #define QS_TYPE_NB		0x0020
414a9643ea8Slogwang #define QS_TYPE_NBSTAT	0x0021
415a9643ea8Slogwang #define QS_CLAS_IN		0x0001
416a9643ea8Slogwang typedef struct {
417a9643ea8Slogwang 	u_short		type;	/* The type of Request */
418a9643ea8Slogwang 	u_short		class;	/* The class of Request */
419a9643ea8Slogwang }		NBTNsQuestion;
420a9643ea8Slogwang 
421a9643ea8Slogwang static u_char  *
AliasHandleQuestion(u_short count,NBTNsQuestion * q,char * pmax,NBTArguments * nbtarg)422a9643ea8Slogwang AliasHandleQuestion(
423a9643ea8Slogwang     u_short count,
424a9643ea8Slogwang     NBTNsQuestion * q,
425a9643ea8Slogwang     char *pmax,
426a9643ea8Slogwang     NBTArguments * nbtarg)
427a9643ea8Slogwang {
428a9643ea8Slogwang 
429a9643ea8Slogwang 	(void)nbtarg;
430a9643ea8Slogwang 
431a9643ea8Slogwang 	while (count != 0) {
432a9643ea8Slogwang 		/* Name Filed */
433a9643ea8Slogwang 		q = (NBTNsQuestion *) AliasHandleName((u_char *) q, pmax);
434a9643ea8Slogwang 
435a9643ea8Slogwang 		if (q == NULL || (char *)(q + 1) > pmax) {
436a9643ea8Slogwang 			q = NULL;
437a9643ea8Slogwang 			break;
438a9643ea8Slogwang 		}
439a9643ea8Slogwang 		/* Type and Class filed */
440a9643ea8Slogwang 		switch (ntohs(q->type)) {
441a9643ea8Slogwang 		case QS_TYPE_NB:
442a9643ea8Slogwang 		case QS_TYPE_NBSTAT:
443a9643ea8Slogwang 			q = q + 1;
444a9643ea8Slogwang 			break;
445a9643ea8Slogwang 		default:
446a9643ea8Slogwang #ifdef LIBALIAS_DEBUG
447a9643ea8Slogwang 			printf("\nUnknown Type on Question %0x\n", ntohs(q->type));
448a9643ea8Slogwang #endif
449a9643ea8Slogwang 			break;
450a9643ea8Slogwang 		}
451a9643ea8Slogwang 		count--;
452a9643ea8Slogwang 	}
453a9643ea8Slogwang 
454a9643ea8Slogwang 	/* Set up to out of Question Section */
455a9643ea8Slogwang 	return ((u_char *) q);
456a9643ea8Slogwang }
457a9643ea8Slogwang 
458a9643ea8Slogwang /* Resource Record */
459a9643ea8Slogwang #define RR_TYPE_A		0x0001
460a9643ea8Slogwang #define RR_TYPE_NS		0x0002
461a9643ea8Slogwang #define RR_TYPE_NULL	0x000a
462a9643ea8Slogwang #define RR_TYPE_NB		0x0020
463a9643ea8Slogwang #define RR_TYPE_NBSTAT	0x0021
464a9643ea8Slogwang #define RR_CLAS_IN		0x0001
465a9643ea8Slogwang #define SizeOfNsResource	8
466a9643ea8Slogwang typedef struct {
467a9643ea8Slogwang 	u_short		type;
468a9643ea8Slogwang 	u_short		class;
469a9643ea8Slogwang 	unsigned int	ttl;
470a9643ea8Slogwang 	u_short		rdlen;
471a9643ea8Slogwang }		NBTNsResource;
472a9643ea8Slogwang 
473a9643ea8Slogwang #define SizeOfNsRNB			6
474a9643ea8Slogwang typedef struct {
475a9643ea8Slogwang 	u_short		g:	1  , ont:2, resv:13;
476a9643ea8Slogwang 	struct in_addr	addr;
477a9643ea8Slogwang }		NBTNsRNB;
478a9643ea8Slogwang 
479a9643ea8Slogwang static u_char  *
AliasHandleResourceNB(NBTNsResource * q,char * pmax,NBTArguments * nbtarg)480a9643ea8Slogwang AliasHandleResourceNB(
481a9643ea8Slogwang     NBTNsResource * q,
482a9643ea8Slogwang     char *pmax,
483a9643ea8Slogwang     NBTArguments * nbtarg)
484a9643ea8Slogwang {
485a9643ea8Slogwang 	NBTNsRNB *nb;
486a9643ea8Slogwang 	u_short bcount;
487*22ce4affSfengbojiang #ifdef LIBALIAS_DEBUG
488*22ce4affSfengbojiang 	char oldbuf[INET_ADDRSTRLEN];
489*22ce4affSfengbojiang 	char newbuf[INET_ADDRSTRLEN];
490*22ce4affSfengbojiang #endif
491a9643ea8Slogwang 
492a9643ea8Slogwang 	if (q == NULL || (char *)(q + 1) > pmax)
493a9643ea8Slogwang 		return (NULL);
494a9643ea8Slogwang 	/* Check out a length */
495a9643ea8Slogwang 	bcount = ntohs(q->rdlen);
496a9643ea8Slogwang 
497a9643ea8Slogwang 	/* Forward to Resource NB position */
498a9643ea8Slogwang 	nb = (NBTNsRNB *) ((u_char *) q + SizeOfNsResource);
499a9643ea8Slogwang 
500a9643ea8Slogwang 	/* Processing all in_addr array */
501a9643ea8Slogwang #ifdef LIBALIAS_DEBUG
502*22ce4affSfengbojiang 	printf("NB rec[%s->%s, %dbytes] ",
503*22ce4affSfengbojiang 	    inet_ntoa_r(nbtarg->oldaddr, INET_NTOA_BUF(oldbuf)),
504*22ce4affSfengbojiang 	    inet_ntoa_r(nbtarg->newaddr, INET_NTOA_BUF(newbuf)),
505*22ce4affSfengbojiang 	    bcount);
506a9643ea8Slogwang #endif
507a9643ea8Slogwang 	while (nb != NULL && bcount != 0) {
508a9643ea8Slogwang 		if ((char *)(nb + 1) > pmax) {
509a9643ea8Slogwang 			nb = NULL;
510a9643ea8Slogwang 			break;
511a9643ea8Slogwang 		}
512a9643ea8Slogwang #ifdef LIBALIAS_DEBUG
513*22ce4affSfengbojiang 		printf("<%s>", inet_ntoa_r(nb->addr, INET_NTOA_BUF(newbuf)));
514a9643ea8Slogwang #endif
515a9643ea8Slogwang 		if (!bcmp(&nbtarg->oldaddr, &nb->addr, sizeof(struct in_addr))) {
516a9643ea8Slogwang 			if (*nbtarg->uh_sum != 0) {
517a9643ea8Slogwang 				int acc;
518a9643ea8Slogwang 				u_short *sptr;
519a9643ea8Slogwang 
520a9643ea8Slogwang 				sptr = (u_short *) & (nb->addr);
521a9643ea8Slogwang 				acc = *sptr++;
522a9643ea8Slogwang 				acc += *sptr;
523a9643ea8Slogwang 				sptr = (u_short *) & (nbtarg->newaddr);
524a9643ea8Slogwang 				acc -= *sptr++;
525a9643ea8Slogwang 				acc -= *sptr;
526a9643ea8Slogwang 				ADJUST_CHECKSUM(acc, *nbtarg->uh_sum);
527a9643ea8Slogwang 			}
528a9643ea8Slogwang 			nb->addr = nbtarg->newaddr;
529a9643ea8Slogwang #ifdef LIBALIAS_DEBUG
530a9643ea8Slogwang 			printf("O");
531a9643ea8Slogwang #endif
532a9643ea8Slogwang 		}
533a9643ea8Slogwang #ifdef LIBALIAS_DEBUG
534a9643ea8Slogwang 		else {
535a9643ea8Slogwang 			printf(".");
536a9643ea8Slogwang 		}
537a9643ea8Slogwang #endif
538a9643ea8Slogwang 		nb = (NBTNsRNB *) ((u_char *) nb + SizeOfNsRNB);
539a9643ea8Slogwang 		bcount -= SizeOfNsRNB;
540a9643ea8Slogwang 	}
541a9643ea8Slogwang 	if (nb == NULL || (char *)(nb + 1) > pmax) {
542a9643ea8Slogwang 		nb = NULL;
543a9643ea8Slogwang 	}
544a9643ea8Slogwang 	return ((u_char *) nb);
545a9643ea8Slogwang }
546a9643ea8Slogwang 
547a9643ea8Slogwang #define SizeOfResourceA		6
548a9643ea8Slogwang typedef struct {
549a9643ea8Slogwang 	struct in_addr	addr;
550a9643ea8Slogwang }		NBTNsResourceA;
551a9643ea8Slogwang 
552a9643ea8Slogwang static u_char  *
AliasHandleResourceA(NBTNsResource * q,char * pmax,NBTArguments * nbtarg)553a9643ea8Slogwang AliasHandleResourceA(
554a9643ea8Slogwang     NBTNsResource * q,
555a9643ea8Slogwang     char *pmax,
556a9643ea8Slogwang     NBTArguments * nbtarg)
557a9643ea8Slogwang {
558a9643ea8Slogwang 	NBTNsResourceA *a;
559a9643ea8Slogwang 	u_short bcount;
560*22ce4affSfengbojiang #ifdef LIBALIAS_DEBUG
561*22ce4affSfengbojiang 	char oldbuf[INET_ADDRSTRLEN];
562*22ce4affSfengbojiang 	char newbuf[INET_ADDRSTRLEN];
563*22ce4affSfengbojiang #endif
564a9643ea8Slogwang 
565a9643ea8Slogwang 	if (q == NULL || (char *)(q + 1) > pmax)
566a9643ea8Slogwang 		return (NULL);
567a9643ea8Slogwang 
568a9643ea8Slogwang 	/* Forward to Resource A position */
569a9643ea8Slogwang 	a = (NBTNsResourceA *) ((u_char *) q + sizeof(NBTNsResource));
570a9643ea8Slogwang 
571a9643ea8Slogwang 	/* Check out of length */
572a9643ea8Slogwang 	bcount = ntohs(q->rdlen);
573a9643ea8Slogwang 
574a9643ea8Slogwang 	/* Processing all in_addr array */
575a9643ea8Slogwang #ifdef LIBALIAS_DEBUG
576*22ce4affSfengbojiang 	printf("Arec [%s->%s]",
577*22ce4affSfengbojiang 	    inet_ntoa_r(nbtarg->oldaddr, INET_NTOA_BUF(oldbuf)),
578*22ce4affSfengbojiang 	    inet_ntoa_r(nbtarg->newaddr, INET_NTOA_BUF(newbuf)));
579a9643ea8Slogwang #endif
580a9643ea8Slogwang 	while (bcount != 0) {
581a9643ea8Slogwang 		if (a == NULL || (char *)(a + 1) > pmax)
582a9643ea8Slogwang 			return (NULL);
583a9643ea8Slogwang #ifdef LIBALIAS_DEBUG
584*22ce4affSfengbojiang 		printf("..%s", inet_ntoa_r(a->addr, INET_NTOA_BUF(newbuf)));
585a9643ea8Slogwang #endif
586a9643ea8Slogwang 		if (!bcmp(&nbtarg->oldaddr, &a->addr, sizeof(struct in_addr))) {
587a9643ea8Slogwang 			if (*nbtarg->uh_sum != 0) {
588a9643ea8Slogwang 				int acc;
589a9643ea8Slogwang 				u_short *sptr;
590a9643ea8Slogwang 
591a9643ea8Slogwang 				sptr = (u_short *) & (a->addr);	/* Old */
592a9643ea8Slogwang 				acc = *sptr++;
593a9643ea8Slogwang 				acc += *sptr;
594a9643ea8Slogwang 				sptr = (u_short *) & nbtarg->newaddr;	/* New */
595a9643ea8Slogwang 				acc -= *sptr++;
596a9643ea8Slogwang 				acc -= *sptr;
597a9643ea8Slogwang 				ADJUST_CHECKSUM(acc, *nbtarg->uh_sum);
598a9643ea8Slogwang 			}
599a9643ea8Slogwang 			a->addr = nbtarg->newaddr;
600a9643ea8Slogwang 		}
601a9643ea8Slogwang 		a++;		/* XXXX */
602a9643ea8Slogwang 		bcount -= SizeOfResourceA;
603a9643ea8Slogwang 	}
604a9643ea8Slogwang 	if (a == NULL || (char *)(a + 1) > pmax)
605a9643ea8Slogwang 		a = NULL;
606a9643ea8Slogwang 	return ((u_char *) a);
607a9643ea8Slogwang }
608a9643ea8Slogwang 
609a9643ea8Slogwang typedef struct {
610a9643ea8Slogwang 	u_short		opcode:4, flags:8, resv:4;
611a9643ea8Slogwang }		NBTNsResourceNULL;
612a9643ea8Slogwang 
613a9643ea8Slogwang static u_char  *
AliasHandleResourceNULL(NBTNsResource * q,char * pmax,NBTArguments * nbtarg)614a9643ea8Slogwang AliasHandleResourceNULL(
615a9643ea8Slogwang     NBTNsResource * q,
616a9643ea8Slogwang     char *pmax,
617a9643ea8Slogwang     NBTArguments * nbtarg)
618a9643ea8Slogwang {
619a9643ea8Slogwang 	NBTNsResourceNULL *n;
620a9643ea8Slogwang 	u_short bcount;
621a9643ea8Slogwang 
622a9643ea8Slogwang 	(void)nbtarg;
623a9643ea8Slogwang 
624a9643ea8Slogwang 	if (q == NULL || (char *)(q + 1) > pmax)
625a9643ea8Slogwang 		return (NULL);
626a9643ea8Slogwang 
627a9643ea8Slogwang 	/* Forward to Resource NULL position */
628a9643ea8Slogwang 	n = (NBTNsResourceNULL *) ((u_char *) q + sizeof(NBTNsResource));
629a9643ea8Slogwang 
630a9643ea8Slogwang 	/* Check out of length */
631a9643ea8Slogwang 	bcount = ntohs(q->rdlen);
632a9643ea8Slogwang 
633a9643ea8Slogwang 	/* Processing all in_addr array */
634a9643ea8Slogwang 	while (bcount != 0) {
635a9643ea8Slogwang 		if ((char *)(n + 1) > pmax) {
636a9643ea8Slogwang 			n = NULL;
637a9643ea8Slogwang 			break;
638a9643ea8Slogwang 		}
639a9643ea8Slogwang 		n++;
640a9643ea8Slogwang 		bcount -= sizeof(NBTNsResourceNULL);
641a9643ea8Slogwang 	}
642a9643ea8Slogwang 	if ((char *)(n + 1) > pmax)
643a9643ea8Slogwang 		n = NULL;
644a9643ea8Slogwang 
645a9643ea8Slogwang 	return ((u_char *) n);
646a9643ea8Slogwang }
647a9643ea8Slogwang 
648a9643ea8Slogwang static u_char  *
AliasHandleResourceNS(NBTNsResource * q,char * pmax,NBTArguments * nbtarg)649a9643ea8Slogwang AliasHandleResourceNS(
650a9643ea8Slogwang     NBTNsResource * q,
651a9643ea8Slogwang     char *pmax,
652a9643ea8Slogwang     NBTArguments * nbtarg)
653a9643ea8Slogwang {
654a9643ea8Slogwang 	NBTNsResourceNULL *n;
655a9643ea8Slogwang 	u_short bcount;
656a9643ea8Slogwang 
657a9643ea8Slogwang 	(void)nbtarg;
658a9643ea8Slogwang 
659a9643ea8Slogwang 	if (q == NULL || (char *)(q + 1) > pmax)
660a9643ea8Slogwang 		return (NULL);
661a9643ea8Slogwang 
662a9643ea8Slogwang 	/* Forward to Resource NULL position */
663a9643ea8Slogwang 	n = (NBTNsResourceNULL *) ((u_char *) q + sizeof(NBTNsResource));
664a9643ea8Slogwang 
665a9643ea8Slogwang 	/* Check out of length */
666a9643ea8Slogwang 	bcount = ntohs(q->rdlen);
667a9643ea8Slogwang 
668a9643ea8Slogwang 	/* Resource Record Name Filed */
669a9643ea8Slogwang 	q = (NBTNsResource *) AliasHandleName((u_char *) n, pmax);	/* XXX */
670a9643ea8Slogwang 
671a9643ea8Slogwang 	if (q == NULL || (char *)((u_char *) n + bcount) > pmax)
672a9643ea8Slogwang 		return (NULL);
673a9643ea8Slogwang 	else
674a9643ea8Slogwang 		return ((u_char *) n + bcount);
675a9643ea8Slogwang }
676a9643ea8Slogwang 
677a9643ea8Slogwang typedef struct {
678a9643ea8Slogwang 	u_short		numnames;
679a9643ea8Slogwang }		NBTNsResourceNBSTAT;
680a9643ea8Slogwang 
681a9643ea8Slogwang static u_char  *
AliasHandleResourceNBSTAT(NBTNsResource * q,char * pmax,NBTArguments * nbtarg)682a9643ea8Slogwang AliasHandleResourceNBSTAT(
683a9643ea8Slogwang     NBTNsResource * q,
684a9643ea8Slogwang     char *pmax,
685a9643ea8Slogwang     NBTArguments * nbtarg)
686a9643ea8Slogwang {
687a9643ea8Slogwang 	NBTNsResourceNBSTAT *n;
688a9643ea8Slogwang 	u_short bcount;
689a9643ea8Slogwang 
690a9643ea8Slogwang 	(void)nbtarg;
691a9643ea8Slogwang 
692a9643ea8Slogwang 	if (q == NULL || (char *)(q + 1) > pmax)
693a9643ea8Slogwang 		return (NULL);
694a9643ea8Slogwang 
695a9643ea8Slogwang 	/* Forward to Resource NBSTAT position */
696a9643ea8Slogwang 	n = (NBTNsResourceNBSTAT *) ((u_char *) q + sizeof(NBTNsResource));
697a9643ea8Slogwang 
698a9643ea8Slogwang 	/* Check out of length */
699a9643ea8Slogwang 	bcount = ntohs(q->rdlen);
700a9643ea8Slogwang 
701a9643ea8Slogwang 	if (q == NULL || (char *)((u_char *) n + bcount) > pmax)
702a9643ea8Slogwang 		return (NULL);
703a9643ea8Slogwang 	else
704a9643ea8Slogwang 		return ((u_char *) n + bcount);
705a9643ea8Slogwang }
706a9643ea8Slogwang 
707a9643ea8Slogwang static u_char  *
AliasHandleResource(u_short count,NBTNsResource * q,char * pmax,NBTArguments * nbtarg)708a9643ea8Slogwang AliasHandleResource(
709a9643ea8Slogwang     u_short count,
710a9643ea8Slogwang     NBTNsResource * q,
711a9643ea8Slogwang     char *pmax,
712a9643ea8Slogwang     NBTArguments
713a9643ea8Slogwang     * nbtarg)
714a9643ea8Slogwang {
715a9643ea8Slogwang 	while (count != 0) {
716a9643ea8Slogwang 		/* Resource Record Name Filed */
717a9643ea8Slogwang 		q = (NBTNsResource *) AliasHandleName((u_char *) q, pmax);
718a9643ea8Slogwang 
719a9643ea8Slogwang 		if (q == NULL || (char *)(q + 1) > pmax)
720a9643ea8Slogwang 			break;
721a9643ea8Slogwang #ifdef LIBALIAS_DEBUG
722a9643ea8Slogwang 		printf("type=%02x, count=%d\n", ntohs(q->type), count);
723a9643ea8Slogwang #endif
724a9643ea8Slogwang 
725a9643ea8Slogwang 		/* Type and Class filed */
726a9643ea8Slogwang 		switch (ntohs(q->type)) {
727a9643ea8Slogwang 		case RR_TYPE_NB:
728a9643ea8Slogwang 			q = (NBTNsResource *) AliasHandleResourceNB(
729a9643ea8Slogwang 			    q,
730a9643ea8Slogwang 			    pmax,
731a9643ea8Slogwang 			    nbtarg
732a9643ea8Slogwang 			    );
733a9643ea8Slogwang 			break;
734a9643ea8Slogwang 		case RR_TYPE_A:
735a9643ea8Slogwang 			q = (NBTNsResource *) AliasHandleResourceA(
736a9643ea8Slogwang 			    q,
737a9643ea8Slogwang 			    pmax,
738a9643ea8Slogwang 			    nbtarg
739a9643ea8Slogwang 			    );
740a9643ea8Slogwang 			break;
741a9643ea8Slogwang 		case RR_TYPE_NS:
742a9643ea8Slogwang 			q = (NBTNsResource *) AliasHandleResourceNS(
743a9643ea8Slogwang 			    q,
744a9643ea8Slogwang 			    pmax,
745a9643ea8Slogwang 			    nbtarg
746a9643ea8Slogwang 			    );
747a9643ea8Slogwang 			break;
748a9643ea8Slogwang 		case RR_TYPE_NULL:
749a9643ea8Slogwang 			q = (NBTNsResource *) AliasHandleResourceNULL(
750a9643ea8Slogwang 			    q,
751a9643ea8Slogwang 			    pmax,
752a9643ea8Slogwang 			    nbtarg
753a9643ea8Slogwang 			    );
754a9643ea8Slogwang 			break;
755a9643ea8Slogwang 		case RR_TYPE_NBSTAT:
756a9643ea8Slogwang 			q = (NBTNsResource *) AliasHandleResourceNBSTAT(
757a9643ea8Slogwang 			    q,
758a9643ea8Slogwang 			    pmax,
759a9643ea8Slogwang 			    nbtarg
760a9643ea8Slogwang 			    );
761a9643ea8Slogwang 			break;
762a9643ea8Slogwang 		default:
763a9643ea8Slogwang #ifdef LIBALIAS_DEBUG
764a9643ea8Slogwang 			printf(
765a9643ea8Slogwang 			    "\nUnknown Type of Resource %0x\n",
766a9643ea8Slogwang 			    ntohs(q->type)
767a9643ea8Slogwang 			    );
768a9643ea8Slogwang 			fflush(stdout);
769a9643ea8Slogwang #endif
770a9643ea8Slogwang 			break;
771a9643ea8Slogwang 		}
772a9643ea8Slogwang 		count--;
773a9643ea8Slogwang 	}
774a9643ea8Slogwang 	return ((u_char *) q);
775a9643ea8Slogwang }
776a9643ea8Slogwang 
777a9643ea8Slogwang 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)778a9643ea8Slogwang AliasHandleUdpNbtNS(
779a9643ea8Slogwang     struct libalias *la,
780a9643ea8Slogwang     struct ip *pip,		/* IP packet to examine/patch */
781a9643ea8Slogwang     struct alias_link *lnk,
782a9643ea8Slogwang     struct in_addr *alias_address,
783a9643ea8Slogwang     u_short * alias_port,
784a9643ea8Slogwang     struct in_addr *original_address,
785a9643ea8Slogwang     u_short * original_port)
786a9643ea8Slogwang {
787a9643ea8Slogwang 	struct udphdr *uh;
788a9643ea8Slogwang 	NbtNSHeader *nsh;
789a9643ea8Slogwang 	u_char *p;
790a9643ea8Slogwang 	char *pmax;
791a9643ea8Slogwang 	NBTArguments nbtarg;
792a9643ea8Slogwang 
793a9643ea8Slogwang 	(void)la;
794a9643ea8Slogwang 	(void)lnk;
795a9643ea8Slogwang 
796a9643ea8Slogwang 	/* Set up Common Parameter */
797a9643ea8Slogwang 	nbtarg.oldaddr = *alias_address;
798a9643ea8Slogwang 	nbtarg.oldport = *alias_port;
799a9643ea8Slogwang 	nbtarg.newaddr = *original_address;
800a9643ea8Slogwang 	nbtarg.newport = *original_port;
801a9643ea8Slogwang 
802a9643ea8Slogwang 	/* Calculate data length of UDP packet */
803a9643ea8Slogwang 	uh = (struct udphdr *)ip_next(pip);
804a9643ea8Slogwang 	nbtarg.uh_sum = &(uh->uh_sum);
805a9643ea8Slogwang 	nsh = (NbtNSHeader *)udp_next(uh);
806a9643ea8Slogwang 	p = (u_char *) (nsh + 1);
807a9643ea8Slogwang 	pmax = (char *)uh + ntohs(uh->uh_ulen);
808a9643ea8Slogwang 
809a9643ea8Slogwang 	if ((char *)(nsh + 1) > pmax)
810a9643ea8Slogwang 		return (-1);
811a9643ea8Slogwang 
812a9643ea8Slogwang #ifdef LIBALIAS_DEBUG
813a9643ea8Slogwang 	printf(" [%s] ID=%02x, op=%01x, flag=%02x, rcode=%01x, qd=%04x"
814a9643ea8Slogwang 	    ", an=%04x, ns=%04x, ar=%04x, [%d]-->",
815a9643ea8Slogwang 	    nsh->dir ? "Response" : "Request",
816a9643ea8Slogwang 	    nsh->nametrid,
817a9643ea8Slogwang 	    nsh->opcode,
818a9643ea8Slogwang 	    nsh->nmflags,
819a9643ea8Slogwang 	    nsh->rcode,
820a9643ea8Slogwang 	    ntohs(nsh->qdcount),
821a9643ea8Slogwang 	    ntohs(nsh->ancount),
822a9643ea8Slogwang 	    ntohs(nsh->nscount),
823a9643ea8Slogwang 	    ntohs(nsh->arcount),
824a9643ea8Slogwang 	    (u_char *) p - (u_char *) nsh
825a9643ea8Slogwang 	    );
826a9643ea8Slogwang #endif
827a9643ea8Slogwang 
828a9643ea8Slogwang 	/* Question Entries */
829a9643ea8Slogwang 	if (ntohs(nsh->qdcount) != 0) {
830a9643ea8Slogwang 		p = AliasHandleQuestion(
831a9643ea8Slogwang 		    ntohs(nsh->qdcount),
832a9643ea8Slogwang 		    (NBTNsQuestion *) p,
833a9643ea8Slogwang 		    pmax,
834a9643ea8Slogwang 		    &nbtarg
835a9643ea8Slogwang 		    );
836a9643ea8Slogwang 	}
837a9643ea8Slogwang 	/* Answer Resource Records */
838a9643ea8Slogwang 	if (ntohs(nsh->ancount) != 0) {
839a9643ea8Slogwang 		p = AliasHandleResource(
840a9643ea8Slogwang 		    ntohs(nsh->ancount),
841a9643ea8Slogwang 		    (NBTNsResource *) p,
842a9643ea8Slogwang 		    pmax,
843a9643ea8Slogwang 		    &nbtarg
844a9643ea8Slogwang 		    );
845a9643ea8Slogwang 	}
846a9643ea8Slogwang 	/* Authority Resource Recodrs */
847a9643ea8Slogwang 	if (ntohs(nsh->nscount) != 0) {
848a9643ea8Slogwang 		p = AliasHandleResource(
849a9643ea8Slogwang 		    ntohs(nsh->nscount),
850a9643ea8Slogwang 		    (NBTNsResource *) p,
851a9643ea8Slogwang 		    pmax,
852a9643ea8Slogwang 		    &nbtarg
853a9643ea8Slogwang 		    );
854a9643ea8Slogwang 	}
855a9643ea8Slogwang 	/* Additional Resource Recodrs */
856a9643ea8Slogwang 	if (ntohs(nsh->arcount) != 0) {
857a9643ea8Slogwang 		p = AliasHandleResource(
858a9643ea8Slogwang 		    ntohs(nsh->arcount),
859a9643ea8Slogwang 		    (NBTNsResource *) p,
860a9643ea8Slogwang 		    pmax,
861a9643ea8Slogwang 		    &nbtarg
862a9643ea8Slogwang 		    );
863a9643ea8Slogwang 	}
864a9643ea8Slogwang #ifdef LIBALIAS_DEBUG
865a9643ea8Slogwang 	PrintRcode(nsh->rcode);
866a9643ea8Slogwang #endif
867a9643ea8Slogwang 	return ((p == NULL) ? -1 : 0);
868a9643ea8Slogwang }
869