xref: /freebsd/sys/netinet/libalias/alias_nbt.c (revision ae77177087c655fc883075af4f425b37e032cd05)
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 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 	return (AliasHandleUdpNbt(la, pip, ah->lnk, ah->aaddr, *ah->aport));
97 }
98 
99 static int
100 fingerprint2(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 
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 	return (AliasHandleUdpNbtNS(la, pip, ah->lnk, &pip->ip_src, ah->sport,
126  	    ah->aaddr, ah->aport));
127 }
128 
129 /* Kernel module definition. */
130 struct 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 
155 static int
156 mod_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
176 static
177 #endif
178 moduledata_t alias_mod = {
179        "alias_nbt", mod_handler, NULL
180 };
181 
182 #ifdef	_KERNEL
183 DECLARE_MODULE(alias_nbt, alias_mod, SI_SUB_DRIVERS, SI_ORDER_SECOND);
184 MODULE_VERSION(alias_nbt, 1);
185 MODULE_DEPEND(alias_nbt, libalias, 1, 1, 1);
186 #endif
187 
188 typedef 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 
196 typedef 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
212 typedef 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
230 static void
231 PrintRcode(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 */
257 static u_char  *
258 AliasHandleName(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 
334 static int
335 AliasHandleUdpNbt(
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
412 typedef struct {
413 	u_short		type;	/* The type of Request */
414 	u_short		class;	/* The class of Request */
415 }		NBTNsQuestion;
416 
417 static u_char  *
418 AliasHandleQuestion(
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
462 typedef struct {
463 	u_short		type;
464 	u_short		class;
465 	unsigned int	ttl;
466 	u_short		rdlen;
467 }		NBTNsResource;
468 
469 #define SizeOfNsRNB			6
470 typedef struct {
471 	u_short		g:	1  , ont:2, resv:13;
472 	struct in_addr	addr;
473 }		NBTNsRNB;
474 
475 static u_char  *
476 AliasHandleResourceNB(
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
538 typedef struct {
539 	struct in_addr	addr;
540 }		NBTNsResourceA;
541 
542 static u_char  *
543 AliasHandleResourceA(
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 
594 typedef struct {
595 	u_short		opcode:4, flags:8, resv:4;
596 }		NBTNsResourceNULL;
597 
598 static u_char  *
599 AliasHandleResourceNULL(
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 
633 static u_char  *
634 AliasHandleResourceNS(
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 
662 typedef struct {
663 	u_short		numnames;
664 }		NBTNsResourceNBSTAT;
665 
666 static u_char  *
667 AliasHandleResourceNBSTAT(
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 
692 static u_char  *
693 AliasHandleResource(
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 
762 static int
763 AliasHandleUdpNbtNS(
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