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