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