alias_nbt.c revision 99207
11556Srgrimes/*-
21556Srgrimes * Written by Atsushi Murai <amurai@spec.co.jp>
31556Srgrimes * Copyright (c) 1998, System Planning and Engineering Co.
41556Srgrimes * All rights reserved.
51556Srgrimes *
61556Srgrimes * Redistribution and use in source and binary forms, with or without
71556Srgrimes * modification, are permitted provided that the following conditions
81556Srgrimes * are met:
91556Srgrimes * 1. Redistributions of source code must retain the above copyright
101556Srgrimes *    notice, this list of conditions and the following disclaimer.
111556Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
121556Srgrimes *    notice, this list of conditions and the following disclaimer in the
131556Srgrimes *    documentation and/or other materials provided with the distribution.
141556Srgrimes *
151556Srgrimes * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
161556Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
171556Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
181556Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
191556Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
201556Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
211556Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
221556Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
231556Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
241556Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
251556Srgrimes * SUCH DAMAGE.
261556Srgrimes *  TODO:
271556Srgrimes *       oClean up.
281556Srgrimes *       oConsidering for word alignment for other platform.
291556Srgrimes */
301556Srgrimes
311556Srgrimes#include <sys/cdefs.h>
321556Srgrimes__FBSDID("$FreeBSD: head/sys/netinet/libalias/alias_nbt.c 99207 2002-07-01 11:19:40Z brian $");
331556Srgrimes
341556Srgrimes/*
351556Srgrimes    alias_nbt.c performs special processing for NetBios over TCP/IP
361556Srgrimes    sessions by UDP.
371556Srgrimes
3820412Ssteve    Initial version:  May, 1998  (Atsushi Murai <amurai@spec.co.jp>)
391556Srgrimes
401556Srgrimes    See HISTORY file for record of revisions.
411556Srgrimes*/
421556Srgrimes
431556Srgrimes/* Includes */
4435772Scharnier#include <ctype.h>
4536000Scharnier#include <stdio.h>
4635772Scharnier#include <string.h>
4735772Scharnier#include <sys/types.h>
4850471Speter#include <netinet/in_systm.h>
491556Srgrimes#include <netinet/in.h>
501556Srgrimes#include <arpa/inet.h>
511556Srgrimes#include <netinet/ip.h>
521556Srgrimes#include <netinet/udp.h>
5383482Sdillon#include <netinet/tcp.h>
5483482Sdillon
5583482Sdillon#include "alias_local.h"
5683482Sdillon
5783482Sdillontypedef struct {
581556Srgrimes	struct in_addr		oldaddr;
591556Srgrimes	u_short 			oldport;
601556Srgrimes	struct in_addr		newaddr;
611556Srgrimes	u_short 			newport;
6218578Sache	u_short 			*uh_sum;
631556Srgrimes} NBTArguments;
641556Srgrimes
6578732Sddtypedef struct {
661556Srgrimes	unsigned char   type;
6783482Sdillon	unsigned char   flags;
681556Srgrimes	u_short  		id;
691556Srgrimes	struct in_addr  source_ip;
701556Srgrimes	u_short			source_port;
7139065Simp	u_short			len;
721556Srgrimes	u_short			offset;
7339138Simp} NbtDataHeader;
741556Srgrimes
7583482Sdillon#define OpQuery		0
7683482Sdillon#define OpUnknown	4
7783482Sdillon#define OpRegist	5
7883482Sdillon#define OpRelease	6
7983482Sdillon#define OpWACK		7
8083482Sdillon#define OpRefresh	8
8183482Sdillontypedef struct {
8283482Sdillon	u_short			nametrid;
831556Srgrimes	u_short 		dir:1, opcode:4, nmflags:7, rcode:4;
8439138Simp	u_short			qdcount;
8539138Simp	u_short			ancount;
8639138Simp	u_short			nscount;
871556Srgrimes	u_short			arcount;
881556Srgrimes} NbtNSHeader;
891556Srgrimes
9018578Sache#define FMT_ERR		0x1
9118578Sache#define SRV_ERR		0x2
9224348Simp#define IMP_ERR		0x4
931556Srgrimes#define RFS_ERR		0x5
941556Srgrimes#define ACT_ERR		0x6
951556Srgrimes#define CFT_ERR		0x7
961556Srgrimes
971556Srgrimes
981556Srgrimes#ifdef DEBUG
991556Srgrimesstatic void PrintRcode( u_char rcode )  {
1001556Srgrimes
1011556Srgrimes	switch (rcode) {
1021556Srgrimes		case FMT_ERR:
1031556Srgrimes			printf("\nFormat Error.");
1041556Srgrimes		case SRV_ERR:
1051556Srgrimes			printf("\nSever failure.");
1061556Srgrimes		case IMP_ERR:
1071556Srgrimes			printf("\nUnsupported request error.\n");
1081556Srgrimes		case RFS_ERR:
1091556Srgrimes			printf("\nRefused error.\n");
11059239Sasmodai		case ACT_ERR:
1111556Srgrimes			printf("\nActive error.\n");
1121556Srgrimes		case CFT_ERR:
1131556Srgrimes			printf("\nName in conflict error.\n");
1141556Srgrimes		default:
11518546Simp			printf("\n?%c?=%0x\n", '?', rcode );
1161556Srgrimes
1171556Srgrimes	}
1181556Srgrimes}
1191556Srgrimes#endif
1201556Srgrimes
1211556Srgrimes
1221556Srgrimes/* Handling Name field */
12383482Sdillonstatic u_char *AliasHandleName ( u_char *p, char *pmax ) {
1241556Srgrimes
12583482Sdillon	u_char *s;
1261556Srgrimes	u_char c;
1271556Srgrimes	int		compress;
1281556Srgrimes
1291556Srgrimes	/* Following length field */
1301556Srgrimes
1311556Srgrimes	if (p == NULL || (char *)p >= pmax)
13283482Sdillon		return(NULL);
13383482Sdillon
13483482Sdillon	if (*p & 0xc0 ) {
1351556Srgrimes		p = p + 2;
13683482Sdillon		if ((char *)p > pmax)
13783482Sdillon			return(NULL);
13883961Sru		return ((u_char *)p);
1391556Srgrimes	}
14083482Sdillon	while ( ( *p & 0x3f) != 0x00 ) {
14183482Sdillon		s = p + 1;
14283482Sdillon		if ( *p == 0x20 )
14383482Sdillon			compress = 1;
14483482Sdillon		else
14583961Sru			compress = 0;
14683482Sdillon
14783482Sdillon	 	/* Get next length field */
14883482Sdillon		p = (u_char *)(p + (*p & 0x3f) + 1);
14983482Sdillon		if ((char *)p > pmax) {
15083482Sdillon			p = NULL;
15183482Sdillon			break;
15283482Sdillon		}
1531556Srgrimes#ifdef DEBUG
15483482Sdillon		printf(":");
15583482Sdillon#endif
15683482Sdillon		while (s < p) {
15783482Sdillon			if ( compress == 1 ) {
15883961Sru				c = (u_char )(((((*s & 0x0f) << 4) | (*(s+1) & 0x0f)) - 0x11));
15983961Sru#ifdef DEBUG
16083961Sru				if (isprint( c ) )
16183961Sru					printf("%c", c );
16283961Sru				else
16383961Sru					printf("<0x%02x>", c );
16483961Sru#endif
16583482Sdillon				s +=2;
16683482Sdillon			} else {
16783961Sru#ifdef DEBUG
16883961Sru				printf("%c", *s);
16983482Sdillon#endif
17083482Sdillon				s++;
17183482Sdillon			}
17283482Sdillon		}
17383482Sdillon#ifdef DEBUG
1741556Srgrimes		printf(":");
1751556Srgrimes#endif
17683482Sdillon		fflush(stdout);
17783482Sdillon    }
1781556Srgrimes
1791556Srgrimes	/* Set up to out of Name field */
1801556Srgrimes	if (p == NULL || (char *)p >= pmax)
1811556Srgrimes	    p = NULL;
18283961Sru	else
18383961Sru	    p++;
18483961Sru	return ((u_char *)p);
18583961Sru}
1861556Srgrimes
1871556Srgrimes/*
1881556Srgrimes * NetBios Datagram Handler (IP/UDP)
1891556Srgrimes */
1901556Srgrimes#define DGM_DIRECT_UNIQ		0x10
1911556Srgrimes#define DGM_DIRECT_GROUP	0x11
1921556Srgrimes#define DGM_BROADCAST		0x12
1931556Srgrimes#define DGM_ERROR			0x13
1941556Srgrimes#define DGM_QUERY			0x14
1951556Srgrimes#define DGM_POSITIVE_RES	0x15
1961556Srgrimes#define DGM_NEGATIVE_RES	0x16
1971556Srgrimes
1981556Srgrimesint AliasHandleUdpNbt(
1991556Srgrimes	struct ip 		  	*pip,	 /* IP packet to examine/patch */
2001556Srgrimes	struct alias_link 	*link,
2011556Srgrimes	struct in_addr		*alias_address,
2021556Srgrimes    u_short 		alias_port
2031556Srgrimes) {
2041556Srgrimes    struct udphdr *	uh;
2051556Srgrimes    NbtDataHeader 	*ndh;
2061556Srgrimes    u_char		*p = NULL;
2071556Srgrimes    char		*pmax;
2081556Srgrimes
2091556Srgrimes    /* Calculate data length of UDP packet */
2101556Srgrimes    uh =  (struct udphdr *) ((char *) pip + (pip->ip_hl << 2));
2111556Srgrimes    pmax = (char *)uh + ntohs( uh->uh_ulen );
2121556Srgrimes
2131556Srgrimes	ndh = (NbtDataHeader *)((char *)uh + (sizeof (struct udphdr)));
2141556Srgrimes    if ((char *)(ndh + 1) > pmax)
2151556Srgrimes	    return(-1);
2161556Srgrimes#ifdef DEBUG
2171556Srgrimes	printf("\nType=%02x,", ndh->type );
2181556Srgrimes#endif
21918578Sache	switch ( ndh->type ) {
2201556Srgrimes		case DGM_DIRECT_UNIQ:
2211556Srgrimes		case DGM_DIRECT_GROUP:
2221556Srgrimes		case DGM_BROADCAST:
2231556Srgrimes			p = (u_char *)ndh + 14;
2241556Srgrimes		    p = AliasHandleName ( p, pmax ); /* Source Name */
2251556Srgrimes		    p = AliasHandleName ( p, pmax ); /* Destination Name */
2261556Srgrimes			break;
2271556Srgrimes		case DGM_ERROR:
2281556Srgrimes			p = (u_char *)ndh + 11;
2291556Srgrimes			break;
2301556Srgrimes		case DGM_QUERY:
2311556Srgrimes		case DGM_POSITIVE_RES:
2321556Srgrimes		case DGM_NEGATIVE_RES:
2331556Srgrimes			p = (u_char *)ndh + 10;
2341556Srgrimes		    p = AliasHandleName ( p, pmax ); /* Destination Name */
2351556Srgrimes			break;
2361556Srgrimes	}
23711145Sbde    if (p == NULL || (char *)p > pmax)
2381556Srgrimes	    p = NULL;
2391556Srgrimes#ifdef DEBUG
2401556Srgrimes	printf("%s:%d-->", inet_ntoa(ndh->source_ip), ntohs(ndh->source_port) );
2411556Srgrimes#endif
2421556Srgrimes	/* Doing a IP address and Port number Translation */
2431556Srgrimes	if ( uh->uh_sum != 0 ) {
24483482Sdillon		int				acc;
2451556Srgrimes		u_short			*sptr;
2461556Srgrimes		acc  = ndh->source_port;
2471556Srgrimes		acc -= alias_port;
24839065Simp		sptr = (u_short *) &(ndh->source_ip);
24939065Simp		acc += *sptr++;
25039065Simp		acc += *sptr;
2511556Srgrimes		sptr = (u_short *) alias_address;
2521556Srgrimes		acc -= *sptr++;
2531556Srgrimes		acc -= *sptr;
2541556Srgrimes		ADJUST_CHECKSUM(acc, uh->uh_sum);
2551556Srgrimes	}
2561556Srgrimes    ndh->source_ip = *alias_address;
2571556Srgrimes    ndh->source_port = alias_port;
2581556Srgrimes#ifdef DEBUG
25939138Simp	printf("%s:%d\n", inet_ntoa(ndh->source_ip), ntohs(ndh->source_port) );
26059239Sasmodai	fflush(stdout);
2611556Srgrimes#endif
2621556Srgrimes    return((p == NULL) ? -1 : 0);
2631556Srgrimes}
26439138Simp/* Question Section */
2651556Srgrimes#define QS_TYPE_NB		0x0020
26611145Sbde#define QS_TYPE_NBSTAT	0x0021
2671556Srgrimes#define QS_CLAS_IN		0x0001
26811145Sbdetypedef struct {
26911145Sbde	u_short	type;	/* The type of Request */
2701556Srgrimes	u_short	class;	/* The class of Request */
27183482Sdillon} NBTNsQuestion;
27283482Sdillon
27383482Sdillonstatic u_char *
27483482SdillonAliasHandleQuestion(
27583482Sdillon    u_short count,
27683482Sdillon							NBTNsQuestion *q,
27783482Sdillon    char *pmax,
27883482Sdillon							NBTArguments  *nbtarg)
27983482Sdillon{
28083482Sdillon
28183482Sdillon	while ( count != 0 ) {
28283482Sdillon		/* Name Filed */
28383482Sdillon		q = (NBTNsQuestion *)AliasHandleName((u_char *)q, pmax);
28483482Sdillon
28583482Sdillon		if (q == NULL || (char *)(q + 1) > pmax) {
28683482Sdillon			q = NULL;
28783482Sdillon			break;
28883482Sdillon		}
28983482Sdillon
29083482Sdillon		/* Type and Class filed */
29183482Sdillon		switch ( ntohs(q->type) ) {
29283482Sdillon			case QS_TYPE_NB:
29383482Sdillon			case QS_TYPE_NBSTAT:
29483482Sdillon				q= q+1;
29583482Sdillon			break;
29683482Sdillon			default:
29783482Sdillon#ifdef DEBUG
29883482Sdillon				printf("\nUnknown Type on Question %0x\n", ntohs(q->type) );
29983482Sdillon#endif
30083482Sdillon			break;
30183482Sdillon		}
30283482Sdillon		count--;
30383482Sdillon	}
30483482Sdillon
30583482Sdillon	/* Set up to out of Question Section */
30683482Sdillon	return ((u_char *)q);
30783482Sdillon}
30883482Sdillon
30983482Sdillon/* Resource Record */
31083482Sdillon#define RR_TYPE_A		0x0001
31183482Sdillon#define RR_TYPE_NS		0x0002
31283482Sdillon#define RR_TYPE_NULL	0x000a
31383482Sdillon#define RR_TYPE_NB		0x0020
31483482Sdillon#define RR_TYPE_NBSTAT	0x0021
31583482Sdillon#define RR_CLAS_IN		0x0001
31683482Sdillon#define SizeOfNsResource	8
31783482Sdillontypedef struct {
31883482Sdillon 	u_short type;
31983482Sdillon 	u_short class;
32083482Sdillon 	unsigned int ttl;
321 	u_short rdlen;
322} NBTNsResource;
323
324#define SizeOfNsRNB			6
325typedef struct {
326	u_short g:1, ont:2, resv:13;
327	struct	in_addr	addr;
328} NBTNsRNB;
329
330static u_char *
331AliasHandleResourceNB(
332    NBTNsResource *q,
333    char *pmax,
334							   NBTArguments  *nbtarg)
335{
336	NBTNsRNB	*nb;
337	u_short bcount;
338
339	if (q == NULL || (char *)(q + 1) > pmax)
340		return(NULL);
341	/* Check out a length */
342	bcount = ntohs(q->rdlen);
343
344	/* Forward to Resource NB position */
345	nb = (NBTNsRNB *)((u_char *)q + SizeOfNsResource);
346
347	/* Processing all in_addr array */
348#ifdef DEBUG
349	printf("NB rec[%s", inet_ntoa(nbtarg->oldaddr));
350            printf("->%s, %dbytes] ",inet_ntoa(nbtarg->newaddr ), bcount);
351#endif
352	while ( nb != NULL && bcount != 0 )  {
353		if ((char *)(nb + 1) > pmax) {
354			nb = NULL;
355			break;
356		}
357#ifdef DEBUG
358		printf("<%s>", inet_ntoa(nb->addr) );
359#endif
360		if (!bcmp(&nbtarg->oldaddr,&nb->addr, sizeof(struct in_addr) ) ) {
361			if ( *nbtarg->uh_sum != 0 ) {
362            	int acc;
363            	u_short *sptr;
364
365            	sptr = (u_short *) &(nb->addr);
366            	acc = *sptr++;
367            	acc += *sptr;
368            	sptr = (u_short *) &(nbtarg->newaddr);
369            	acc -= *sptr++;
370            	acc -= *sptr;
371            	ADJUST_CHECKSUM(acc, *nbtarg->uh_sum);
372			}
373
374			nb->addr = nbtarg->newaddr;
375#ifdef DEBUG
376			printf("O");
377#endif
378		}
379#ifdef DEBUG
380		 else {
381			printf(".");
382		}
383#endif
384		nb=(NBTNsRNB *)((u_char *)nb + SizeOfNsRNB);
385	 	bcount -= SizeOfNsRNB;
386	}
387	if (nb == NULL || (char *)(nb + 1) > pmax) {
388		nb = NULL;
389	}
390
391	return ((u_char *)nb);
392}
393
394#define SizeOfResourceA		6
395typedef struct {
396	struct	in_addr	addr;
397} NBTNsResourceA;
398
399static u_char *
400AliasHandleResourceA(
401    NBTNsResource *q,
402    char *pmax,
403						 	  NBTArguments  *nbtarg)
404{
405	NBTNsResourceA	*a;
406	u_short bcount;
407
408	if (q == NULL || (char *)(q + 1) > pmax)
409		return(NULL);
410
411	/* Forward to Resource A position */
412	a = (NBTNsResourceA *)( (u_char *)q + sizeof(NBTNsResource) );
413
414	/* Check out of length */
415	bcount = ntohs(q->rdlen);
416
417	/* Processing all in_addr array */
418#ifdef DEBUG
419	printf("Arec [%s", inet_ntoa(nbtarg->oldaddr));
420        printf("->%s]",inet_ntoa(nbtarg->newaddr ));
421#endif
422	while ( bcount != 0 )  {
423		if (a == NULL || (char *)(a + 1) > pmax)
424			return(NULL);
425#ifdef DEBUG
426		printf("..%s", inet_ntoa(a->addr) );
427#endif
428		if ( !bcmp(&nbtarg->oldaddr, &a->addr, sizeof(struct in_addr) ) ) {
429			if ( *nbtarg->uh_sum != 0 ) {
430            	int acc;
431            	u_short *sptr;
432
433            	sptr = (u_short *) &(a->addr);		 /* Old */
434            	acc = *sptr++;
435            	acc += *sptr;
436            	sptr = (u_short *) &nbtarg->newaddr; /* New */
437            	acc -= *sptr++;
438            	acc -= *sptr;
439            	ADJUST_CHECKSUM(acc, *nbtarg->uh_sum);
440			}
441
442			a->addr = nbtarg->newaddr;
443		}
444		a++;	/*XXXX*/
445		bcount -= SizeOfResourceA;
446	}
447	if (a == NULL || (char *)(a + 1) > pmax)
448		a =  NULL;
449	return ((u_char *)a);
450}
451
452typedef struct {
453	u_short opcode:4, flags:8, resv:4;
454} NBTNsResourceNULL;
455
456static u_char *
457AliasHandleResourceNULL(
458    NBTNsResource *q,
459    char *pmax,
460						 	     NBTArguments  *nbtarg)
461{
462	NBTNsResourceNULL	*n;
463	u_short bcount;
464
465	if (q == NULL || (char *)(q + 1) > pmax)
466		return(NULL);
467
468	/* Forward to Resource NULL position */
469	n = (NBTNsResourceNULL *)( (u_char *)q + sizeof(NBTNsResource) );
470
471	/* Check out of length */
472	bcount = ntohs(q->rdlen);
473
474	/* Processing all in_addr array */
475	while ( bcount != 0 )  {
476		if ((char *)(n + 1) > pmax) {
477			n = NULL;
478			break;
479		}
480		n++;
481		bcount -= sizeof(NBTNsResourceNULL);
482	}
483	if ((char *)(n + 1) > pmax)
484		n = NULL;
485
486	return ((u_char *)n);
487}
488
489static u_char *
490AliasHandleResourceNS(
491    NBTNsResource *q,
492    char *pmax,
493						 	     NBTArguments  *nbtarg)
494{
495	NBTNsResourceNULL	*n;
496	u_short bcount;
497
498	if (q == NULL || (char *)(q + 1) > pmax)
499		return(NULL);
500
501	/* Forward to Resource NULL position */
502	n = (NBTNsResourceNULL *)( (u_char *)q + sizeof(NBTNsResource) );
503
504	/* Check out of length */
505	bcount = ntohs(q->rdlen);
506
507	/* Resource Record Name Filed */
508	q = (NBTNsResource *)AliasHandleName( (u_char *)n, pmax ); /* XXX */
509
510	if (q == NULL || (char *)((u_char *)n + bcount) > pmax)
511		return(NULL);
512	else
513	return ((u_char *)n + bcount);
514}
515
516typedef struct {
517	u_short	numnames;
518} NBTNsResourceNBSTAT;
519
520static u_char *
521AliasHandleResourceNBSTAT(
522    NBTNsResource *q,
523    char *pmax,
524						 	       NBTArguments  *nbtarg)
525{
526	NBTNsResourceNBSTAT	*n;
527	u_short bcount;
528
529	if (q == NULL || (char *)(q + 1) > pmax)
530		return(NULL);
531
532	/* Forward to Resource NBSTAT position */
533	n = (NBTNsResourceNBSTAT *)( (u_char *)q + sizeof(NBTNsResource) );
534
535	/* Check out of length */
536	bcount = ntohs(q->rdlen);
537
538	if (q == NULL || (char *)((u_char *)n + bcount) > pmax)
539		return(NULL);
540	else
541	return ((u_char *)n + bcount);
542}
543
544static u_char *
545AliasHandleResource(
546    u_short count,
547							NBTNsResource *q,
548    char *pmax,
549    NBTArguments
550    *nbtarg)
551{
552	while ( count != 0 ) {
553		/* Resource Record Name Filed */
554		q = (NBTNsResource *)AliasHandleName( (u_char *)q, pmax );
555
556		if (q == NULL || (char *)(q + 1) > pmax)
557			break;
558#ifdef DEBUG
559		printf("type=%02x, count=%d\n", ntohs(q->type), count );
560#endif
561
562		/* Type and Class filed */
563		switch ( ntohs(q->type) ) {
564			case RR_TYPE_NB:
565				q = (NBTNsResource *)AliasHandleResourceNB(
566				    q,
567				    pmax,
568				    nbtarg
569				);
570				break;
571			case RR_TYPE_A:
572				q = (NBTNsResource *)AliasHandleResourceA(
573				    q,
574				    pmax,
575				    nbtarg
576				);
577				break;
578			case RR_TYPE_NS:
579				q = (NBTNsResource *)AliasHandleResourceNS(
580				    q,
581				    pmax,
582				    nbtarg
583				);
584				break;
585			case RR_TYPE_NULL:
586				q = (NBTNsResource *)AliasHandleResourceNULL(
587				    q,
588				    pmax,
589				    nbtarg
590				);
591				break;
592			case RR_TYPE_NBSTAT:
593				q = (NBTNsResource *)AliasHandleResourceNBSTAT(
594				    q,
595				    pmax,
596				    nbtarg
597				);
598				break;
599			default:
600#ifdef DEBUG
601				printf(
602				    "\nUnknown Type of Resource %0x\n",
603				    ntohs(q->type)
604				);
605#endif
606				break;
607		}
608		count--;
609	}
610	fflush(stdout);
611	return ((u_char *)q);
612}
613
614int AliasHandleUdpNbtNS(
615	struct ip 		  	*pip,	 /* IP packet to examine/patch */
616	struct alias_link 	*link,
617	struct in_addr		*alias_address,
618	u_short 			*alias_port,
619	struct in_addr		*original_address,
620	u_short 			*original_port )
621{
622    struct udphdr *	uh;
623	NbtNSHeader	  * nsh;
624	u_char		  * p;
625	char		*pmax;
626	NBTArguments    nbtarg;
627
628	/* Set up Common Parameter */
629	nbtarg.oldaddr	=	*alias_address;
630	nbtarg.oldport	=	*alias_port;
631	nbtarg.newaddr	=	*original_address;
632	nbtarg.newport	=	*original_port;
633
634    /* Calculate data length of UDP packet */
635    uh =  (struct udphdr *) ((char *) pip + (pip->ip_hl << 2));
636	nbtarg.uh_sum	=	&(uh->uh_sum);
637	nsh = (NbtNSHeader *)((char *)uh + (sizeof(struct udphdr)));
638	p = (u_char *)(nsh + 1);
639    pmax = (char *)uh + ntohs( uh->uh_ulen );
640
641    if ((char *)(nsh + 1) > pmax)
642	return(-1);
643
644#ifdef DEBUG
645    printf(" [%s] ID=%02x, op=%01x, flag=%02x, rcode=%01x, qd=%04x"
646	   ", an=%04x, ns=%04x, ar=%04x, [%d]-->",
647		nsh->dir ? "Response": "Request",
648		nsh->nametrid,
649		nsh->opcode,
650		nsh->nmflags,
651		nsh->rcode,
652		ntohs(nsh->qdcount),
653		ntohs(nsh->ancount),
654		ntohs(nsh->nscount),
655		ntohs(nsh->arcount),
656	(u_char *)p -(u_char *)nsh
657    );
658#endif
659
660	/* Question Entries */
661	if (ntohs(nsh->qdcount) !=0 ) {
662	p = AliasHandleQuestion(
663	    ntohs(nsh->qdcount),
664	    (NBTNsQuestion *)p,
665	    pmax,
666	    &nbtarg
667	);
668	}
669
670	/* Answer Resource Records */
671	if (ntohs(nsh->ancount) !=0 ) {
672	p = AliasHandleResource(
673	    ntohs(nsh->ancount),
674	    (NBTNsResource *)p,
675	    pmax,
676	    &nbtarg
677	);
678	}
679
680	/* Authority Resource Recodrs */
681	if (ntohs(nsh->nscount) !=0 ) {
682	p = AliasHandleResource(
683	    ntohs(nsh->nscount),
684	    (NBTNsResource *)p,
685	    pmax,
686	    &nbtarg
687	);
688	}
689
690	/* Additional Resource Recodrs */
691	if (ntohs(nsh->arcount) !=0 ) {
692	p = AliasHandleResource(
693	    ntohs(nsh->arcount),
694	    (NBTNsResource *)p,
695	    pmax,
696	    &nbtarg
697	);
698	}
699
700#ifdef DEBUG
701	 	PrintRcode(nsh->rcode);
702#endif
703    return ((p == NULL) ? -1 : 0);
704}
705