xref: /freebsd/sys/netinet/libalias/alias_nbt.c (revision b3aaa0cc21c63d388230c7ef2a80abd631ff20d5)
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$");
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 
72 static int
73 AliasHandleUdpNbt(struct libalias *, struct ip *, struct alias_link *,
74 		  struct in_addr *, u_short);
75 
76 static int
77 AliasHandleUdpNbtNS(struct libalias *, struct ip *, struct alias_link *,
78 		    struct in_addr *, u_short *, struct in_addr *, u_short *);
79 static int
80 fingerprint1(struct libalias *la, struct ip *pip, 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 
92 static int
93 protohandler1(struct libalias *la, struct ip *pip, struct alias_data *ah)
94 {
95 
96 	AliasHandleUdpNbt(la, pip, ah->lnk, ah->aaddr, *ah->aport);
97 	return (0);
98 }
99 
100 static int
101 fingerprint2(struct libalias *la, struct ip *pip, struct alias_data *ah)
102 {
103 
104 	if (ah->dport == NULL || ah->sport == NULL || ah->lnk == NULL ||
105 	    ah->aaddr == NULL || ah->aport == NULL)
106 		return (-1);
107 	if (ntohs(*ah->dport) == NETBIOS_NS_PORT_NUMBER
108 	    || ntohs(*ah->sport) == NETBIOS_NS_PORT_NUMBER)
109 		return (0);
110 	return (-1);
111 }
112 
113 static int
114 protohandler2in(struct libalias *la, struct ip *pip, struct alias_data *ah)
115 {
116 
117 	AliasHandleUdpNbtNS(la, pip, ah->lnk, ah->aaddr, ah->aport,
118  			    ah->oaddr, ah->dport);
119 	return (0);
120 }
121 
122 static int
123 protohandler2out(struct libalias *la, struct ip *pip, struct alias_data *ah)
124 {
125 
126 	AliasHandleUdpNbtNS(la, pip, ah->lnk, &pip->ip_src, ah->sport,
127  			    ah->aaddr, ah->aport);
128 	return (0);
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 
231 #ifdef LIBALIAS_DEBUG
232 static void
233 PrintRcode(u_char rcode)
234 {
235 
236 	switch (rcode) {
237 		case FMT_ERR:
238 		printf("\nFormat Error.");
239 	case SRV_ERR:
240 		printf("\nSever failure.");
241 	case IMP_ERR:
242 		printf("\nUnsupported request error.\n");
243 	case RFS_ERR:
244 		printf("\nRefused error.\n");
245 	case ACT_ERR:
246 		printf("\nActive error.\n");
247 	case CFT_ERR:
248 		printf("\nName in conflict error.\n");
249 	default:
250 		printf("\n?%c?=%0x\n", '?', rcode);
251 
252 	}
253 }
254 
255 #endif
256 
257 
258 /* Handling Name field */
259 static u_char  *
260 AliasHandleName(u_char * p, char *pmax)
261 {
262 
263 	u_char *s;
264 	u_char c;
265 	int compress;
266 
267 	/* Following length field */
268 
269 	if (p == NULL || (char *)p >= pmax)
270 		return (NULL);
271 
272 	if (*p & 0xc0) {
273 		p = p + 2;
274 		if ((char *)p > pmax)
275 			return (NULL);
276 		return ((u_char *) p);
277 	}
278 	while ((*p & 0x3f) != 0x00) {
279 		s = p + 1;
280 		if (*p == 0x20)
281 			compress = 1;
282 		else
283 			compress = 0;
284 
285 		/* Get next length field */
286 		p = (u_char *) (p + (*p & 0x3f) + 1);
287 		if ((char *)p > pmax) {
288 			p = NULL;
289 			break;
290 		}
291 #ifdef LIBALIAS_DEBUG
292 		printf(":");
293 #endif
294 		while (s < p) {
295 			if (compress == 1) {
296 				c = (u_char) (((((*s & 0x0f) << 4) | (*(s + 1) & 0x0f)) - 0x11));
297 #ifdef LIBALIAS_DEBUG
298 				if (isprint(c))
299 					printf("%c", c);
300 				else
301 					printf("<0x%02x>", c);
302 #endif
303 				s += 2;
304 			} else {
305 #ifdef LIBALIAS_DEBUG
306 				printf("%c", *s);
307 #endif
308 				s++;
309 			}
310 		}
311 #ifdef LIBALIAS_DEBUG
312 		printf(":");
313 		fflush(stdout);
314 #endif
315 	}
316 
317 	/* Set up to out of Name field */
318 	if (p == NULL || (char *)p >= pmax)
319 		p = NULL;
320 	else
321 		p++;
322 	return ((u_char *) p);
323 }
324 
325 /*
326  * NetBios Datagram Handler (IP/UDP)
327  */
328 #define DGM_DIRECT_UNIQ		0x10
329 #define DGM_DIRECT_GROUP	0x11
330 #define DGM_BROADCAST		0x12
331 #define DGM_ERROR			0x13
332 #define DGM_QUERY			0x14
333 #define DGM_POSITIVE_RES	0x15
334 #define DGM_NEGATIVE_RES	0x16
335 
336 static int
337 AliasHandleUdpNbt(
338     struct libalias *la,
339     struct ip *pip,		/* IP packet to examine/patch */
340     struct alias_link *lnk,
341     struct in_addr *alias_address,
342     u_short alias_port
343 )
344 {
345 	struct udphdr *uh;
346 	NbtDataHeader *ndh;
347 	u_char *p = NULL;
348 	char *pmax;
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(ndh->source_ip), ntohs(ndh->source_port));
385 #endif
386 	/* Doing an IP address and Port number Translation */
387 	if (uh->uh_sum != 0) {
388 		int acc;
389 		u_short *sptr;
390 
391 		acc = ndh->source_port;
392 		acc -= alias_port;
393 		sptr = (u_short *) & (ndh->source_ip);
394 		acc += *sptr++;
395 		acc += *sptr;
396 		sptr = (u_short *) alias_address;
397 		acc -= *sptr++;
398 		acc -= *sptr;
399 		ADJUST_CHECKSUM(acc, uh->uh_sum);
400 	}
401 	ndh->source_ip = *alias_address;
402 	ndh->source_port = alias_port;
403 #ifdef LIBALIAS_DEBUG
404 	printf("%s:%d\n", inet_ntoa(ndh->source_ip), ntohs(ndh->source_port));
405 	fflush(stdout);
406 #endif
407 	return ((p == NULL) ? -1 : 0);
408 }
409 
410 /* Question Section */
411 #define QS_TYPE_NB		0x0020
412 #define QS_TYPE_NBSTAT	0x0021
413 #define QS_CLAS_IN		0x0001
414 typedef struct {
415 	u_short		type;	/* The type of Request */
416 	u_short		class;	/* The class of Request */
417 }		NBTNsQuestion;
418 
419 static u_char  *
420 AliasHandleQuestion(
421     u_short count,
422     NBTNsQuestion * q,
423     char *pmax,
424     NBTArguments * nbtarg)
425 {
426 
427 	(void)nbtarg;
428 
429 	while (count != 0) {
430 		/* Name Filed */
431 		q = (NBTNsQuestion *) AliasHandleName((u_char *) q, pmax);
432 
433 		if (q == NULL || (char *)(q + 1) > pmax) {
434 			q = NULL;
435 			break;
436 		}
437 		/* Type and Class filed */
438 		switch (ntohs(q->type)) {
439 		case QS_TYPE_NB:
440 		case QS_TYPE_NBSTAT:
441 			q = q + 1;
442 			break;
443 		default:
444 #ifdef LIBALIAS_DEBUG
445 			printf("\nUnknown Type on Question %0x\n", ntohs(q->type));
446 #endif
447 			break;
448 		}
449 		count--;
450 	}
451 
452 	/* Set up to out of Question Section */
453 	return ((u_char *) q);
454 }
455 
456 /* Resource Record */
457 #define RR_TYPE_A		0x0001
458 #define RR_TYPE_NS		0x0002
459 #define RR_TYPE_NULL	0x000a
460 #define RR_TYPE_NB		0x0020
461 #define RR_TYPE_NBSTAT	0x0021
462 #define RR_CLAS_IN		0x0001
463 #define SizeOfNsResource	8
464 typedef struct {
465 	u_short		type;
466 	u_short		class;
467 	unsigned int	ttl;
468 	u_short		rdlen;
469 }		NBTNsResource;
470 
471 #define SizeOfNsRNB			6
472 typedef struct {
473 	u_short		g:	1  , ont:2, resv:13;
474 	struct in_addr	addr;
475 }		NBTNsRNB;
476 
477 static u_char  *
478 AliasHandleResourceNB(
479     NBTNsResource * q,
480     char *pmax,
481     NBTArguments * nbtarg)
482 {
483 	NBTNsRNB *nb;
484 	u_short bcount;
485 
486 	if (q == NULL || (char *)(q + 1) > pmax)
487 		return (NULL);
488 	/* Check out a length */
489 	bcount = ntohs(q->rdlen);
490 
491 	/* Forward to Resource NB position */
492 	nb = (NBTNsRNB *) ((u_char *) q + SizeOfNsResource);
493 
494 	/* Processing all in_addr array */
495 #ifdef LIBALIAS_DEBUG
496 	printf("NB rec[%s", inet_ntoa(nbtarg->oldaddr));
497 	printf("->%s, %dbytes] ", inet_ntoa(nbtarg->newaddr), bcount);
498 #endif
499 	while (nb != NULL && bcount != 0) {
500 		if ((char *)(nb + 1) > pmax) {
501 			nb = NULL;
502 			break;
503 		}
504 #ifdef LIBALIAS_DEBUG
505 		printf("<%s>", inet_ntoa(nb->addr));
506 #endif
507 		if (!bcmp(&nbtarg->oldaddr, &nb->addr, sizeof(struct in_addr))) {
508 			if (*nbtarg->uh_sum != 0) {
509 				int acc;
510 				u_short *sptr;
511 
512 				sptr = (u_short *) & (nb->addr);
513 				acc = *sptr++;
514 				acc += *sptr;
515 				sptr = (u_short *) & (nbtarg->newaddr);
516 				acc -= *sptr++;
517 				acc -= *sptr;
518 				ADJUST_CHECKSUM(acc, *nbtarg->uh_sum);
519 			}
520 			nb->addr = nbtarg->newaddr;
521 #ifdef LIBALIAS_DEBUG
522 			printf("O");
523 #endif
524 		}
525 #ifdef LIBALIAS_DEBUG
526 		else {
527 			printf(".");
528 		}
529 #endif
530 		nb = (NBTNsRNB *) ((u_char *) nb + SizeOfNsRNB);
531 		bcount -= SizeOfNsRNB;
532 	}
533 	if (nb == NULL || (char *)(nb + 1) > pmax) {
534 		nb = NULL;
535 	}
536 	return ((u_char *) nb);
537 }
538 
539 #define SizeOfResourceA		6
540 typedef struct {
541 	struct in_addr	addr;
542 }		NBTNsResourceA;
543 
544 static u_char  *
545 AliasHandleResourceA(
546     NBTNsResource * q,
547     char *pmax,
548     NBTArguments * nbtarg)
549 {
550 	NBTNsResourceA *a;
551 	u_short bcount;
552 
553 	if (q == NULL || (char *)(q + 1) > pmax)
554 		return (NULL);
555 
556 	/* Forward to Resource A position */
557 	a = (NBTNsResourceA *) ((u_char *) q + sizeof(NBTNsResource));
558 
559 	/* Check out of length */
560 	bcount = ntohs(q->rdlen);
561 
562 	/* Processing all in_addr array */
563 #ifdef LIBALIAS_DEBUG
564 	printf("Arec [%s", inet_ntoa(nbtarg->oldaddr));
565 	printf("->%s]", inet_ntoa(nbtarg->newaddr));
566 #endif
567 	while (bcount != 0) {
568 		if (a == NULL || (char *)(a + 1) > pmax)
569 			return (NULL);
570 #ifdef LIBALIAS_DEBUG
571 		printf("..%s", inet_ntoa(a->addr));
572 #endif
573 		if (!bcmp(&nbtarg->oldaddr, &a->addr, sizeof(struct in_addr))) {
574 			if (*nbtarg->uh_sum != 0) {
575 				int acc;
576 				u_short *sptr;
577 
578 				sptr = (u_short *) & (a->addr);	/* Old */
579 				acc = *sptr++;
580 				acc += *sptr;
581 				sptr = (u_short *) & nbtarg->newaddr;	/* New */
582 				acc -= *sptr++;
583 				acc -= *sptr;
584 				ADJUST_CHECKSUM(acc, *nbtarg->uh_sum);
585 			}
586 			a->addr = nbtarg->newaddr;
587 		}
588 		a++;		/* XXXX */
589 		bcount -= SizeOfResourceA;
590 	}
591 	if (a == NULL || (char *)(a + 1) > pmax)
592 		a = NULL;
593 	return ((u_char *) a);
594 }
595 
596 typedef struct {
597 	u_short		opcode:4, flags:8, resv:4;
598 }		NBTNsResourceNULL;
599 
600 static u_char  *
601 AliasHandleResourceNULL(
602     NBTNsResource * q,
603     char *pmax,
604     NBTArguments * nbtarg)
605 {
606 	NBTNsResourceNULL *n;
607 	u_short bcount;
608 
609 	(void)nbtarg;
610 
611 	if (q == NULL || (char *)(q + 1) > pmax)
612 		return (NULL);
613 
614 	/* Forward to Resource NULL position */
615 	n = (NBTNsResourceNULL *) ((u_char *) q + sizeof(NBTNsResource));
616 
617 	/* Check out of length */
618 	bcount = ntohs(q->rdlen);
619 
620 	/* Processing all in_addr array */
621 	while (bcount != 0) {
622 		if ((char *)(n + 1) > pmax) {
623 			n = NULL;
624 			break;
625 		}
626 		n++;
627 		bcount -= sizeof(NBTNsResourceNULL);
628 	}
629 	if ((char *)(n + 1) > pmax)
630 		n = NULL;
631 
632 	return ((u_char *) n);
633 }
634 
635 static u_char  *
636 AliasHandleResourceNS(
637     NBTNsResource * q,
638     char *pmax,
639     NBTArguments * nbtarg)
640 {
641 	NBTNsResourceNULL *n;
642 	u_short bcount;
643 
644 	(void)nbtarg;
645 
646 	if (q == NULL || (char *)(q + 1) > pmax)
647 		return (NULL);
648 
649 	/* Forward to Resource NULL position */
650 	n = (NBTNsResourceNULL *) ((u_char *) q + sizeof(NBTNsResource));
651 
652 	/* Check out of length */
653 	bcount = ntohs(q->rdlen);
654 
655 	/* Resource Record Name Filed */
656 	q = (NBTNsResource *) AliasHandleName((u_char *) n, pmax);	/* XXX */
657 
658 	if (q == NULL || (char *)((u_char *) n + bcount) > pmax)
659 		return (NULL);
660 	else
661 		return ((u_char *) n + bcount);
662 }
663 
664 typedef struct {
665 	u_short		numnames;
666 }		NBTNsResourceNBSTAT;
667 
668 static u_char  *
669 AliasHandleResourceNBSTAT(
670     NBTNsResource * q,
671     char *pmax,
672     NBTArguments * nbtarg)
673 {
674 	NBTNsResourceNBSTAT *n;
675 	u_short bcount;
676 
677 	(void)nbtarg;
678 
679 	if (q == NULL || (char *)(q + 1) > pmax)
680 		return (NULL);
681 
682 	/* Forward to Resource NBSTAT position */
683 	n = (NBTNsResourceNBSTAT *) ((u_char *) q + sizeof(NBTNsResource));
684 
685 	/* Check out of length */
686 	bcount = ntohs(q->rdlen);
687 
688 	if (q == NULL || (char *)((u_char *) n + bcount) > pmax)
689 		return (NULL);
690 	else
691 		return ((u_char *) n + bcount);
692 }
693 
694 static u_char  *
695 AliasHandleResource(
696     u_short count,
697     NBTNsResource * q,
698     char *pmax,
699     NBTArguments
700     * nbtarg)
701 {
702 	while (count != 0) {
703 		/* Resource Record Name Filed */
704 		q = (NBTNsResource *) AliasHandleName((u_char *) q, pmax);
705 
706 		if (q == NULL || (char *)(q + 1) > pmax)
707 			break;
708 #ifdef LIBALIAS_DEBUG
709 		printf("type=%02x, count=%d\n", ntohs(q->type), count);
710 #endif
711 
712 		/* Type and Class filed */
713 		switch (ntohs(q->type)) {
714 		case RR_TYPE_NB:
715 			q = (NBTNsResource *) AliasHandleResourceNB(
716 			    q,
717 			    pmax,
718 			    nbtarg
719 			    );
720 			break;
721 		case RR_TYPE_A:
722 			q = (NBTNsResource *) AliasHandleResourceA(
723 			    q,
724 			    pmax,
725 			    nbtarg
726 			    );
727 			break;
728 		case RR_TYPE_NS:
729 			q = (NBTNsResource *) AliasHandleResourceNS(
730 			    q,
731 			    pmax,
732 			    nbtarg
733 			    );
734 			break;
735 		case RR_TYPE_NULL:
736 			q = (NBTNsResource *) AliasHandleResourceNULL(
737 			    q,
738 			    pmax,
739 			    nbtarg
740 			    );
741 			break;
742 		case RR_TYPE_NBSTAT:
743 			q = (NBTNsResource *) AliasHandleResourceNBSTAT(
744 			    q,
745 			    pmax,
746 			    nbtarg
747 			    );
748 			break;
749 		default:
750 #ifdef LIBALIAS_DEBUG
751 			printf(
752 			    "\nUnknown Type of Resource %0x\n",
753 			    ntohs(q->type)
754 			    );
755 			fflush(stdout);
756 #endif
757 			break;
758 		}
759 		count--;
760 	}
761 	return ((u_char *) q);
762 }
763 
764 static int
765 AliasHandleUdpNbtNS(
766     struct libalias *la,
767     struct ip *pip,		/* IP packet to examine/patch */
768     struct alias_link *lnk,
769     struct in_addr *alias_address,
770     u_short * alias_port,
771     struct in_addr *original_address,
772     u_short * original_port)
773 {
774 	struct udphdr *uh;
775 	NbtNSHeader *nsh;
776 	u_char *p;
777 	char *pmax;
778 	NBTArguments nbtarg;
779 
780 	(void)la;
781 	(void)lnk;
782 
783 	/* Set up Common Parameter */
784 	nbtarg.oldaddr = *alias_address;
785 	nbtarg.oldport = *alias_port;
786 	nbtarg.newaddr = *original_address;
787 	nbtarg.newport = *original_port;
788 
789 	/* Calculate data length of UDP packet */
790 	uh = (struct udphdr *)ip_next(pip);
791 	nbtarg.uh_sum = &(uh->uh_sum);
792 	nsh = (NbtNSHeader *)udp_next(uh);
793 	p = (u_char *) (nsh + 1);
794 	pmax = (char *)uh + ntohs(uh->uh_ulen);
795 
796 	if ((char *)(nsh + 1) > pmax)
797 		return (-1);
798 
799 #ifdef LIBALIAS_DEBUG
800 	printf(" [%s] ID=%02x, op=%01x, flag=%02x, rcode=%01x, qd=%04x"
801 	    ", an=%04x, ns=%04x, ar=%04x, [%d]-->",
802 	    nsh->dir ? "Response" : "Request",
803 	    nsh->nametrid,
804 	    nsh->opcode,
805 	    nsh->nmflags,
806 	    nsh->rcode,
807 	    ntohs(nsh->qdcount),
808 	    ntohs(nsh->ancount),
809 	    ntohs(nsh->nscount),
810 	    ntohs(nsh->arcount),
811 	    (u_char *) p - (u_char *) nsh
812 	    );
813 #endif
814 
815 	/* Question Entries */
816 	if (ntohs(nsh->qdcount) != 0) {
817 		p = AliasHandleQuestion(
818 		    ntohs(nsh->qdcount),
819 		    (NBTNsQuestion *) p,
820 		    pmax,
821 		    &nbtarg
822 		    );
823 	}
824 	/* Answer Resource Records */
825 	if (ntohs(nsh->ancount) != 0) {
826 		p = AliasHandleResource(
827 		    ntohs(nsh->ancount),
828 		    (NBTNsResource *) p,
829 		    pmax,
830 		    &nbtarg
831 		    );
832 	}
833 	/* Authority Resource Recodrs */
834 	if (ntohs(nsh->nscount) != 0) {
835 		p = AliasHandleResource(
836 		    ntohs(nsh->nscount),
837 		    (NBTNsResource *) p,
838 		    pmax,
839 		    &nbtarg
840 		    );
841 	}
842 	/* Additional Resource Recodrs */
843 	if (ntohs(nsh->arcount) != 0) {
844 		p = AliasHandleResource(
845 		    ntohs(nsh->arcount),
846 		    (NBTNsResource *) p,
847 		    pmax,
848 		    &nbtarg
849 		    );
850 	}
851 #ifdef LIBALIAS_DEBUG
852 	PrintRcode(nsh->rcode);
853 #endif
854 	return ((p == NULL) ? -1 : 0);
855 }
856