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: stable/11/sys/netinet/libalias/alias_nbt.c 315456 2017-03-17 14:54:10Z vangyzen $");
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#include <strings.h>
54#endif
55
56#include <netinet/in_systm.h>
57#include <netinet/in.h>
58#include <netinet/ip.h>
59#include <netinet/udp.h>
60
61#ifdef _KERNEL
62#include <netinet/libalias/alias_local.h>
63#include <netinet/libalias/alias_mod.h>
64#else
65#include "alias_local.h"
66#include "alias_mod.h"
67#endif
68
69#define NETBIOS_NS_PORT_NUMBER 137
70#define NETBIOS_DGM_PORT_NUMBER 138
71
72static int
73AliasHandleUdpNbt(struct libalias *, struct ip *, struct alias_link *,
74		  struct in_addr *, u_short);
75
76static int
77AliasHandleUdpNbtNS(struct libalias *, struct ip *, struct alias_link *,
78		    struct in_addr *, u_short *, struct in_addr *, u_short *);
79static int
80fingerprint1(struct libalias *la, struct alias_data *ah)
81{
82
83	if (ah->dport == NULL || ah->sport == NULL || ah->lnk == NULL ||
84	    ah->aaddr == NULL || ah->aport == NULL)
85		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#ifdef LIBALIAS_DEBUG
348	char addrbuf[INET_ADDRSTRLEN];
349#endif
350
351	(void)la;
352	(void)lnk;
353
354	/* Calculate data length of UDP packet */
355	uh = (struct udphdr *)ip_next(pip);
356	pmax = (char *)uh + ntohs(uh->uh_ulen);
357
358	ndh = (NbtDataHeader *)udp_next(uh);
359	if ((char *)(ndh + 1) > pmax)
360		return (-1);
361#ifdef LIBALIAS_DEBUG
362	printf("\nType=%02x,", ndh->type);
363#endif
364	switch (ndh->type) {
365	case DGM_DIRECT_UNIQ:
366	case DGM_DIRECT_GROUP:
367	case DGM_BROADCAST:
368		p = (u_char *) ndh + 14;
369		p = AliasHandleName(p, pmax);	/* Source Name */
370		p = AliasHandleName(p, pmax);	/* Destination Name */
371		break;
372	case DGM_ERROR:
373		p = (u_char *) ndh + 11;
374		break;
375	case DGM_QUERY:
376	case DGM_POSITIVE_RES:
377	case DGM_NEGATIVE_RES:
378		p = (u_char *) ndh + 10;
379		p = AliasHandleName(p, pmax);	/* Destination Name */
380		break;
381	}
382	if (p == NULL || (char *)p > pmax)
383		p = NULL;
384#ifdef LIBALIAS_DEBUG
385	printf("%s:%d-->", inet_ntoa_r(ndh->source_ip, INET_NTOA_BUF(addrbuf)),
386	    ntohs(ndh->source_port));
387#endif
388	/* Doing an IP address and Port number Translation */
389	if (uh->uh_sum != 0) {
390		int acc;
391		u_short *sptr;
392
393		acc = ndh->source_port;
394		acc -= alias_port;
395		sptr = (u_short *) & (ndh->source_ip);
396		acc += *sptr++;
397		acc += *sptr;
398		sptr = (u_short *) alias_address;
399		acc -= *sptr++;
400		acc -= *sptr;
401		ADJUST_CHECKSUM(acc, uh->uh_sum);
402	}
403	ndh->source_ip = *alias_address;
404	ndh->source_port = alias_port;
405#ifdef LIBALIAS_DEBUG
406	printf("%s:%d\n", inet_ntoa_r(ndh->source_ip, INET_NTOA_BUF(addrbuf)),
407	    ntohs(ndh->source_port));
408	fflush(stdout);
409#endif
410	return ((p == NULL) ? -1 : 0);
411}
412
413/* Question Section */
414#define QS_TYPE_NB		0x0020
415#define QS_TYPE_NBSTAT	0x0021
416#define QS_CLAS_IN		0x0001
417typedef struct {
418	u_short		type;	/* The type of Request */
419	u_short		class;	/* The class of Request */
420}		NBTNsQuestion;
421
422static u_char  *
423AliasHandleQuestion(
424    u_short count,
425    NBTNsQuestion * q,
426    char *pmax,
427    NBTArguments * nbtarg)
428{
429
430	(void)nbtarg;
431
432	while (count != 0) {
433		/* Name Filed */
434		q = (NBTNsQuestion *) AliasHandleName((u_char *) q, pmax);
435
436		if (q == NULL || (char *)(q + 1) > pmax) {
437			q = NULL;
438			break;
439		}
440		/* Type and Class filed */
441		switch (ntohs(q->type)) {
442		case QS_TYPE_NB:
443		case QS_TYPE_NBSTAT:
444			q = q + 1;
445			break;
446		default:
447#ifdef LIBALIAS_DEBUG
448			printf("\nUnknown Type on Question %0x\n", ntohs(q->type));
449#endif
450			break;
451		}
452		count--;
453	}
454
455	/* Set up to out of Question Section */
456	return ((u_char *) q);
457}
458
459/* Resource Record */
460#define RR_TYPE_A		0x0001
461#define RR_TYPE_NS		0x0002
462#define RR_TYPE_NULL	0x000a
463#define RR_TYPE_NB		0x0020
464#define RR_TYPE_NBSTAT	0x0021
465#define RR_CLAS_IN		0x0001
466#define SizeOfNsResource	8
467typedef struct {
468	u_short		type;
469	u_short		class;
470	unsigned int	ttl;
471	u_short		rdlen;
472}		NBTNsResource;
473
474#define SizeOfNsRNB			6
475typedef struct {
476	u_short		g:	1  , ont:2, resv:13;
477	struct in_addr	addr;
478}		NBTNsRNB;
479
480static u_char  *
481AliasHandleResourceNB(
482    NBTNsResource * q,
483    char *pmax,
484    NBTArguments * nbtarg)
485{
486	NBTNsRNB *nb;
487	u_short bcount;
488#ifdef LIBALIAS_DEBUG
489	char oldbuf[INET_ADDRSTRLEN];
490	char newbuf[INET_ADDRSTRLEN];
491#endif
492
493	if (q == NULL || (char *)(q + 1) > pmax)
494		return (NULL);
495	/* Check out a length */
496	bcount = ntohs(q->rdlen);
497
498	/* Forward to Resource NB position */
499	nb = (NBTNsRNB *) ((u_char *) q + SizeOfNsResource);
500
501	/* Processing all in_addr array */
502#ifdef LIBALIAS_DEBUG
503	printf("NB rec[%s->%s, %dbytes] ",
504	    inet_ntoa_r(nbtarg->oldaddr, INET_NTOA_BUF(oldbuf)),
505	    inet_ntoa_r(nbtarg->newaddr, INET_NTOA_BUF(newbuf)),
506	    bcount);
507#endif
508	while (nb != NULL && bcount != 0) {
509		if ((char *)(nb + 1) > pmax) {
510			nb = NULL;
511			break;
512		}
513#ifdef LIBALIAS_DEBUG
514		printf("<%s>", inet_ntoa_r(nb->addr, INET_NTOA_BUF(newbuf)));
515#endif
516		if (!bcmp(&nbtarg->oldaddr, &nb->addr, sizeof(struct in_addr))) {
517			if (*nbtarg->uh_sum != 0) {
518				int acc;
519				u_short *sptr;
520
521				sptr = (u_short *) & (nb->addr);
522				acc = *sptr++;
523				acc += *sptr;
524				sptr = (u_short *) & (nbtarg->newaddr);
525				acc -= *sptr++;
526				acc -= *sptr;
527				ADJUST_CHECKSUM(acc, *nbtarg->uh_sum);
528			}
529			nb->addr = nbtarg->newaddr;
530#ifdef LIBALIAS_DEBUG
531			printf("O");
532#endif
533		}
534#ifdef LIBALIAS_DEBUG
535		else {
536			printf(".");
537		}
538#endif
539		nb = (NBTNsRNB *) ((u_char *) nb + SizeOfNsRNB);
540		bcount -= SizeOfNsRNB;
541	}
542	if (nb == NULL || (char *)(nb + 1) > pmax) {
543		nb = NULL;
544	}
545	return ((u_char *) nb);
546}
547
548#define SizeOfResourceA		6
549typedef struct {
550	struct in_addr	addr;
551}		NBTNsResourceA;
552
553static u_char  *
554AliasHandleResourceA(
555    NBTNsResource * q,
556    char *pmax,
557    NBTArguments * nbtarg)
558{
559	NBTNsResourceA *a;
560	u_short bcount;
561#ifdef LIBALIAS_DEBUG
562	char oldbuf[INET_ADDRSTRLEN];
563	char newbuf[INET_ADDRSTRLEN];
564#endif
565
566	if (q == NULL || (char *)(q + 1) > pmax)
567		return (NULL);
568
569	/* Forward to Resource A position */
570	a = (NBTNsResourceA *) ((u_char *) q + sizeof(NBTNsResource));
571
572	/* Check out of length */
573	bcount = ntohs(q->rdlen);
574
575	/* Processing all in_addr array */
576#ifdef LIBALIAS_DEBUG
577	printf("Arec [%s->%s]",
578	    inet_ntoa_r(nbtarg->oldaddr, INET_NTOA_BUF(oldbuf)),
579	    inet_ntoa_r(nbtarg->newaddr, INET_NTOA_BUF(newbuf)));
580#endif
581	while (bcount != 0) {
582		if (a == NULL || (char *)(a + 1) > pmax)
583			return (NULL);
584#ifdef LIBALIAS_DEBUG
585		printf("..%s", inet_ntoa_r(a->addr, INET_NTOA_BUF(newbuf)));
586#endif
587		if (!bcmp(&nbtarg->oldaddr, &a->addr, sizeof(struct in_addr))) {
588			if (*nbtarg->uh_sum != 0) {
589				int acc;
590				u_short *sptr;
591
592				sptr = (u_short *) & (a->addr);	/* Old */
593				acc = *sptr++;
594				acc += *sptr;
595				sptr = (u_short *) & nbtarg->newaddr;	/* New */
596				acc -= *sptr++;
597				acc -= *sptr;
598				ADJUST_CHECKSUM(acc, *nbtarg->uh_sum);
599			}
600			a->addr = nbtarg->newaddr;
601		}
602		a++;		/* XXXX */
603		bcount -= SizeOfResourceA;
604	}
605	if (a == NULL || (char *)(a + 1) > pmax)
606		a = NULL;
607	return ((u_char *) a);
608}
609
610typedef struct {
611	u_short		opcode:4, flags:8, resv:4;
612}		NBTNsResourceNULL;
613
614static u_char  *
615AliasHandleResourceNULL(
616    NBTNsResource * q,
617    char *pmax,
618    NBTArguments * nbtarg)
619{
620	NBTNsResourceNULL *n;
621	u_short bcount;
622
623	(void)nbtarg;
624
625	if (q == NULL || (char *)(q + 1) > pmax)
626		return (NULL);
627
628	/* Forward to Resource NULL position */
629	n = (NBTNsResourceNULL *) ((u_char *) q + sizeof(NBTNsResource));
630
631	/* Check out of length */
632	bcount = ntohs(q->rdlen);
633
634	/* Processing all in_addr array */
635	while (bcount != 0) {
636		if ((char *)(n + 1) > pmax) {
637			n = NULL;
638			break;
639		}
640		n++;
641		bcount -= sizeof(NBTNsResourceNULL);
642	}
643	if ((char *)(n + 1) > pmax)
644		n = NULL;
645
646	return ((u_char *) n);
647}
648
649static u_char  *
650AliasHandleResourceNS(
651    NBTNsResource * q,
652    char *pmax,
653    NBTArguments * nbtarg)
654{
655	NBTNsResourceNULL *n;
656	u_short bcount;
657
658	(void)nbtarg;
659
660	if (q == NULL || (char *)(q + 1) > pmax)
661		return (NULL);
662
663	/* Forward to Resource NULL position */
664	n = (NBTNsResourceNULL *) ((u_char *) q + sizeof(NBTNsResource));
665
666	/* Check out of length */
667	bcount = ntohs(q->rdlen);
668
669	/* Resource Record Name Filed */
670	q = (NBTNsResource *) AliasHandleName((u_char *) n, pmax);	/* XXX */
671
672	if (q == NULL || (char *)((u_char *) n + bcount) > pmax)
673		return (NULL);
674	else
675		return ((u_char *) n + bcount);
676}
677
678typedef struct {
679	u_short		numnames;
680}		NBTNsResourceNBSTAT;
681
682static u_char  *
683AliasHandleResourceNBSTAT(
684    NBTNsResource * q,
685    char *pmax,
686    NBTArguments * nbtarg)
687{
688	NBTNsResourceNBSTAT *n;
689	u_short bcount;
690
691	(void)nbtarg;
692
693	if (q == NULL || (char *)(q + 1) > pmax)
694		return (NULL);
695
696	/* Forward to Resource NBSTAT position */
697	n = (NBTNsResourceNBSTAT *) ((u_char *) q + sizeof(NBTNsResource));
698
699	/* Check out of length */
700	bcount = ntohs(q->rdlen);
701
702	if (q == NULL || (char *)((u_char *) n + bcount) > pmax)
703		return (NULL);
704	else
705		return ((u_char *) n + bcount);
706}
707
708static u_char  *
709AliasHandleResource(
710    u_short count,
711    NBTNsResource * q,
712    char *pmax,
713    NBTArguments
714    * nbtarg)
715{
716	while (count != 0) {
717		/* Resource Record Name Filed */
718		q = (NBTNsResource *) AliasHandleName((u_char *) q, pmax);
719
720		if (q == NULL || (char *)(q + 1) > pmax)
721			break;
722#ifdef LIBALIAS_DEBUG
723		printf("type=%02x, count=%d\n", ntohs(q->type), count);
724#endif
725
726		/* Type and Class filed */
727		switch (ntohs(q->type)) {
728		case RR_TYPE_NB:
729			q = (NBTNsResource *) AliasHandleResourceNB(
730			    q,
731			    pmax,
732			    nbtarg
733			    );
734			break;
735		case RR_TYPE_A:
736			q = (NBTNsResource *) AliasHandleResourceA(
737			    q,
738			    pmax,
739			    nbtarg
740			    );
741			break;
742		case RR_TYPE_NS:
743			q = (NBTNsResource *) AliasHandleResourceNS(
744			    q,
745			    pmax,
746			    nbtarg
747			    );
748			break;
749		case RR_TYPE_NULL:
750			q = (NBTNsResource *) AliasHandleResourceNULL(
751			    q,
752			    pmax,
753			    nbtarg
754			    );
755			break;
756		case RR_TYPE_NBSTAT:
757			q = (NBTNsResource *) AliasHandleResourceNBSTAT(
758			    q,
759			    pmax,
760			    nbtarg
761			    );
762			break;
763		default:
764#ifdef LIBALIAS_DEBUG
765			printf(
766			    "\nUnknown Type of Resource %0x\n",
767			    ntohs(q->type)
768			    );
769			fflush(stdout);
770#endif
771			break;
772		}
773		count--;
774	}
775	return ((u_char *) q);
776}
777
778static int
779AliasHandleUdpNbtNS(
780    struct libalias *la,
781    struct ip *pip,		/* IP packet to examine/patch */
782    struct alias_link *lnk,
783    struct in_addr *alias_address,
784    u_short * alias_port,
785    struct in_addr *original_address,
786    u_short * original_port)
787{
788	struct udphdr *uh;
789	NbtNSHeader *nsh;
790	u_char *p;
791	char *pmax;
792	NBTArguments nbtarg;
793
794	(void)la;
795	(void)lnk;
796
797	/* Set up Common Parameter */
798	nbtarg.oldaddr = *alias_address;
799	nbtarg.oldport = *alias_port;
800	nbtarg.newaddr = *original_address;
801	nbtarg.newport = *original_port;
802
803	/* Calculate data length of UDP packet */
804	uh = (struct udphdr *)ip_next(pip);
805	nbtarg.uh_sum = &(uh->uh_sum);
806	nsh = (NbtNSHeader *)udp_next(uh);
807	p = (u_char *) (nsh + 1);
808	pmax = (char *)uh + ntohs(uh->uh_ulen);
809
810	if ((char *)(nsh + 1) > pmax)
811		return (-1);
812
813#ifdef LIBALIAS_DEBUG
814	printf(" [%s] ID=%02x, op=%01x, flag=%02x, rcode=%01x, qd=%04x"
815	    ", an=%04x, ns=%04x, ar=%04x, [%d]-->",
816	    nsh->dir ? "Response" : "Request",
817	    nsh->nametrid,
818	    nsh->opcode,
819	    nsh->nmflags,
820	    nsh->rcode,
821	    ntohs(nsh->qdcount),
822	    ntohs(nsh->ancount),
823	    ntohs(nsh->nscount),
824	    ntohs(nsh->arcount),
825	    (u_char *) p - (u_char *) nsh
826	    );
827#endif
828
829	/* Question Entries */
830	if (ntohs(nsh->qdcount) != 0) {
831		p = AliasHandleQuestion(
832		    ntohs(nsh->qdcount),
833		    (NBTNsQuestion *) p,
834		    pmax,
835		    &nbtarg
836		    );
837	}
838	/* Answer Resource Records */
839	if (ntohs(nsh->ancount) != 0) {
840		p = AliasHandleResource(
841		    ntohs(nsh->ancount),
842		    (NBTNsResource *) p,
843		    pmax,
844		    &nbtarg
845		    );
846	}
847	/* Authority Resource Recodrs */
848	if (ntohs(nsh->nscount) != 0) {
849		p = AliasHandleResource(
850		    ntohs(nsh->nscount),
851		    (NBTNsResource *) p,
852		    pmax,
853		    &nbtarg
854		    );
855	}
856	/* Additional Resource Recodrs */
857	if (ntohs(nsh->arcount) != 0) {
858		p = AliasHandleResource(
859		    ntohs(nsh->arcount),
860		    (NBTNsResource *) p,
861		    pmax,
862		    &nbtarg
863		    );
864	}
865#ifdef LIBALIAS_DEBUG
866	PrintRcode(nsh->rcode);
867#endif
868	return ((p == NULL) ? -1 : 0);
869}
870