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