xref: /freebsd/sys/netinet/libalias/alias_nbt.c (revision 1e413cf93298b5b97441a21d9a50fdcd0ee9945e)
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 #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 
71 static int
72 AliasHandleUdpNbt(struct libalias *, struct ip *, struct alias_link *,
73 		  struct in_addr *, u_short);
74 
75 static int
76 AliasHandleUdpNbtNS(struct libalias *, struct ip *, struct alias_link *,
77 		    struct in_addr *, u_short *, struct in_addr *, u_short *);
78 static int
79 fingerprint1(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 
91 static int
92 protohandler1(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 
99 static int
100 fingerprint2(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 
112 static int
113 protohandler2in(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 
121 static int
122 protohandler2out(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. */
131 struct 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 
156 static int
157 mod_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
177 static
178 #endif
179 moduledata_t alias_mod = {
180        "alias_nbt", mod_handler, NULL
181 };
182 
183 #ifdef	_KERNEL
184 DECLARE_MODULE(alias_nbt, alias_mod, SI_SUB_DRIVERS, SI_ORDER_SECOND);
185 MODULE_VERSION(alias_nbt, 1);
186 MODULE_DEPEND(alias_nbt, libalias, 1, 1, 1);
187 #endif
188 
189 typedef 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 
197 typedef 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
213 typedef 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
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 
254 #endif
255 
256 
257 /* Handling Name field */
258 static u_char  *
259 AliasHandleName(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 
335 static int
336 AliasHandleUdpNbt(
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
413 typedef struct {
414 	u_short		type;	/* The type of Request */
415 	u_short		class;	/* The class of Request */
416 }		NBTNsQuestion;
417 
418 static u_char  *
419 AliasHandleQuestion(
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
463 typedef struct {
464 	u_short		type;
465 	u_short		class;
466 	unsigned int	ttl;
467 	u_short		rdlen;
468 }		NBTNsResource;
469 
470 #define SizeOfNsRNB			6
471 typedef struct {
472 	u_short		g:	1  , ont:2, resv:13;
473 	struct in_addr	addr;
474 }		NBTNsRNB;
475 
476 static u_char  *
477 AliasHandleResourceNB(
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
539 typedef struct {
540 	struct in_addr	addr;
541 }		NBTNsResourceA;
542 
543 static u_char  *
544 AliasHandleResourceA(
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 
595 typedef struct {
596 	u_short		opcode:4, flags:8, resv:4;
597 }		NBTNsResourceNULL;
598 
599 static u_char  *
600 AliasHandleResourceNULL(
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 
634 static u_char  *
635 AliasHandleResourceNS(
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 
663 typedef struct {
664 	u_short		numnames;
665 }		NBTNsResourceNBSTAT;
666 
667 static u_char  *
668 AliasHandleResourceNBSTAT(
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 
693 static u_char  *
694 AliasHandleResource(
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 
763 static int
764 AliasHandleUdpNbtNS(
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