alias_nbt.c revision 127094
177696Sbrian/*- 236321Samurai * Written by Atsushi Murai <amurai@spec.co.jp> 377696Sbrian * Copyright (c) 1998, System Planning and Engineering Co. 477696Sbrian * All rights reserved. 536321Samurai * 677696Sbrian * Redistribution and use in source and binary forms, with or without 777696Sbrian * modification, are permitted provided that the following conditions 877696Sbrian * are met: 977696Sbrian * 1. Redistributions of source code must retain the above copyright 1077696Sbrian * notice, this list of conditions and the following disclaimer. 1177696Sbrian * 2. Redistributions in binary form must reproduce the above copyright 1277696Sbrian * notice, this list of conditions and the following disclaimer in the 1377696Sbrian * documentation and/or other materials provided with the distribution. 1436321Samurai * 1577696Sbrian * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1677696Sbrian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1777696Sbrian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1877696Sbrian * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1977696Sbrian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2077696Sbrian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2177696Sbrian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2277696Sbrian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2377696Sbrian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2477696Sbrian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2577696Sbrian * SUCH DAMAGE. 2636321Samurai * TODO: 2799207Sbrian * oClean up. 2836321Samurai * oConsidering for word alignment for other platform. 2936321Samurai */ 3084195Sdillon 3184195Sdillon#include <sys/cdefs.h> 3284195Sdillon__FBSDID("$FreeBSD: head/sys/netinet/libalias/alias_nbt.c 127094 2004-03-16 21:30:41Z des $"); 3384195Sdillon 3436321Samurai/* 3536321Samurai alias_nbt.c performs special processing for NetBios over TCP/IP 3636321Samurai sessions by UDP. 3736321Samurai 3836321Samurai Initial version: May, 1998 (Atsushi Murai <amurai@spec.co.jp>) 3936321Samurai 4036321Samurai See HISTORY file for record of revisions. 4136321Samurai*/ 4236321Samurai 4336321Samurai/* Includes */ 4436321Samurai#include <ctype.h> 4599207Sbrian#include <stdio.h> 4636321Samurai#include <string.h> 4736321Samurai#include <sys/types.h> 4836321Samurai#include <netinet/in_systm.h> 4936321Samurai#include <netinet/in.h> 5036321Samurai#include <arpa/inet.h> 5136321Samurai#include <netinet/ip.h> 5236321Samurai#include <netinet/udp.h> 5336321Samurai#include <netinet/tcp.h> 5436321Samurai 5536321Samurai#include "alias_local.h" 5636321Samurai 5736321Samuraitypedef struct { 58127094Sdes struct in_addr oldaddr; 59127094Sdes u_short oldport; 60127094Sdes struct in_addr newaddr; 61127094Sdes u_short newport; 62127094Sdes u_short *uh_sum; 63127094Sdes} NBTArguments; 6436321Samurai 6536321Samuraitypedef struct { 66127094Sdes unsigned char type; 67127094Sdes unsigned char flags; 68127094Sdes u_short id; 69127094Sdes struct in_addr source_ip; 70127094Sdes u_short source_port; 71127094Sdes u_short len; 72127094Sdes u_short offset; 73127094Sdes} NbtDataHeader; 7436321Samurai 7536321Samurai#define OpQuery 0 7636321Samurai#define OpUnknown 4 7736321Samurai#define OpRegist 5 7836321Samurai#define OpRelease 6 7936321Samurai#define OpWACK 7 8036321Samurai#define OpRefresh 8 8136321Samuraitypedef struct { 82127094Sdes u_short nametrid; 83127094Sdes u_short dir: 1, opcode:4, nmflags:7, rcode:4; 84127094Sdes u_short qdcount; 85127094Sdes u_short ancount; 86127094Sdes u_short nscount; 87127094Sdes u_short arcount; 88127094Sdes} NbtNSHeader; 8936321Samurai 9036321Samurai#define FMT_ERR 0x1 9136321Samurai#define SRV_ERR 0x2 9236321Samurai#define IMP_ERR 0x4 9336321Samurai#define RFS_ERR 0x5 9436321Samurai#define ACT_ERR 0x6 9536321Samurai#define CFT_ERR 0x7 9636321Samurai 9736321Samurai 9844616Sbrian#ifdef DEBUG 99127094Sdesstatic void 100127094SdesPrintRcode(u_char rcode) 101127094Sdes{ 10236321Samurai 10336321Samurai switch (rcode) { 10436321Samurai case FMT_ERR: 105127094Sdes printf("\nFormat Error."); 106127094Sdes case SRV_ERR: 107127094Sdes printf("\nSever failure."); 108127094Sdes case IMP_ERR: 109127094Sdes printf("\nUnsupported request error.\n"); 110127094Sdes case RFS_ERR: 111127094Sdes printf("\nRefused error.\n"); 112127094Sdes case ACT_ERR: 113127094Sdes printf("\nActive error.\n"); 114127094Sdes case CFT_ERR: 115127094Sdes printf("\nName in conflict error.\n"); 116127094Sdes default: 117127094Sdes printf("\n?%c?=%0x\n", '?', rcode); 11836321Samurai 11999207Sbrian } 12036321Samurai} 121127094Sdes 12244616Sbrian#endif 12336321Samurai 12436321Samurai 12536321Samurai/* Handling Name field */ 126127094Sdesstatic u_char * 127127094SdesAliasHandleName(u_char * p, char *pmax) 128127094Sdes{ 12936321Samurai 13036321Samurai u_char *s; 13136321Samurai u_char c; 132127094Sdes int compress; 13336321Samurai 13436321Samurai /* Following length field */ 13541759Sdillon 13641759Sdillon if (p == NULL || (char *)p >= pmax) 137127094Sdes return (NULL); 13841759Sdillon 139127094Sdes if (*p & 0xc0) { 14036321Samurai p = p + 2; 14141759Sdillon if ((char *)p > pmax) 142127094Sdes return (NULL); 143127094Sdes return ((u_char *) p); 14436321Samurai } 145127094Sdes while ((*p & 0x3f) != 0x00) { 14636321Samurai s = p + 1; 147127094Sdes if (*p == 0x20) 14836321Samurai compress = 1; 14936321Samurai else 15036321Samurai compress = 0; 15199207Sbrian 152127094Sdes /* Get next length field */ 153127094Sdes p = (u_char *) (p + (*p & 0x3f) + 1); 15441759Sdillon if ((char *)p > pmax) { 15541759Sdillon p = NULL; 15641759Sdillon break; 15741759Sdillon } 15836321Samurai#ifdef DEBUG 15936321Samurai printf(":"); 16036321Samurai#endif 16136321Samurai while (s < p) { 162127094Sdes if (compress == 1) { 163127094Sdes c = (u_char) (((((*s & 0x0f) << 4) | (*(s + 1) & 0x0f)) - 0x11)); 16436321Samurai#ifdef DEBUG 165127094Sdes if (isprint(c)) 166127094Sdes printf("%c", c); 16736321Samurai else 168127094Sdes printf("<0x%02x>", c); 16936321Samurai#endif 170127094Sdes s += 2; 17136321Samurai } else { 17236321Samurai#ifdef DEBUG 17336321Samurai printf("%c", *s); 17436321Samurai#endif 17536321Samurai s++; 17636321Samurai } 17736321Samurai } 17836321Samurai#ifdef DEBUG 17936321Samurai printf(":"); 18036321Samurai#endif 18136321Samurai fflush(stdout); 182127094Sdes } 18336321Samurai 18436321Samurai /* Set up to out of Name field */ 18541759Sdillon if (p == NULL || (char *)p >= pmax) 186127094Sdes p = NULL; 18741759Sdillon else 188127094Sdes p++; 189127094Sdes return ((u_char *) p); 19036321Samurai} 19136321Samurai 19299207Sbrian/* 19336321Samurai * NetBios Datagram Handler (IP/UDP) 19436321Samurai */ 19536321Samurai#define DGM_DIRECT_UNIQ 0x10 19636321Samurai#define DGM_DIRECT_GROUP 0x11 19736321Samurai#define DGM_BROADCAST 0x12 19836321Samurai#define DGM_ERROR 0x13 19936321Samurai#define DGM_QUERY 0x14 20036321Samurai#define DGM_POSITIVE_RES 0x15 20136321Samurai#define DGM_NEGATIVE_RES 0x16 20236321Samurai 203127094Sdesint 204127094SdesAliasHandleUdpNbt( 205127094Sdes struct libalias *la, 206127094Sdes struct ip *pip, /* IP packet to examine/patch */ 207127094Sdes struct alias_link *link, 208127094Sdes struct in_addr *alias_address, 209127094Sdes u_short alias_port 210127094Sdes) 211127094Sdes{ 212127094Sdes struct udphdr *uh; 213127094Sdes NbtDataHeader *ndh; 214127094Sdes u_char *p = NULL; 215127094Sdes char *pmax; 21699207Sbrian 217127094Sdes /* Calculate data length of UDP packet */ 218127094Sdes uh = (struct udphdr *)((char *)pip + (pip->ip_hl << 2)); 219127094Sdes pmax = (char *)uh + ntohs(uh->uh_ulen); 22041759Sdillon 221127094Sdes ndh = (NbtDataHeader *) ((char *)uh + (sizeof(struct udphdr))); 222127094Sdes if ((char *)(ndh + 1) > pmax) 223127094Sdes return (-1); 22436321Samurai#ifdef DEBUG 225127094Sdes printf("\nType=%02x,", ndh->type); 22636321Samurai#endif 227127094Sdes switch (ndh->type) { 228127094Sdes case DGM_DIRECT_UNIQ: 229127094Sdes case DGM_DIRECT_GROUP: 230127094Sdes case DGM_BROADCAST: 231127094Sdes p = (u_char *) ndh + 14; 232127094Sdes p = AliasHandleName(p, pmax); /* Source Name */ 233127094Sdes p = AliasHandleName(p, pmax); /* Destination Name */ 234127094Sdes break; 235127094Sdes case DGM_ERROR: 236127094Sdes p = (u_char *) ndh + 11; 237127094Sdes break; 238127094Sdes case DGM_QUERY: 239127094Sdes case DGM_POSITIVE_RES: 240127094Sdes case DGM_NEGATIVE_RES: 241127094Sdes p = (u_char *) ndh + 10; 242127094Sdes p = AliasHandleName(p, pmax); /* Destination Name */ 243127094Sdes break; 24436321Samurai } 245127094Sdes if (p == NULL || (char *)p > pmax) 246127094Sdes p = NULL; 24736321Samurai#ifdef DEBUG 248127094Sdes printf("%s:%d-->", inet_ntoa(ndh->source_ip), ntohs(ndh->source_port)); 24936321Samurai#endif 250108533Sschweikh /* Doing an IP address and Port number Translation */ 251127094Sdes if (uh->uh_sum != 0) { 252127094Sdes int acc; 253127094Sdes u_short *sptr; 254127094Sdes 255127094Sdes acc = ndh->source_port; 25636321Samurai acc -= alias_port; 257127094Sdes sptr = (u_short *) & (ndh->source_ip); 25836321Samurai acc += *sptr++; 25936321Samurai acc += *sptr; 26036321Samurai sptr = (u_short *) alias_address; 26136321Samurai acc -= *sptr++; 26236321Samurai acc -= *sptr; 26374778Sbrian ADJUST_CHECKSUM(acc, uh->uh_sum); 26436321Samurai } 265127094Sdes ndh->source_ip = *alias_address; 266127094Sdes ndh->source_port = alias_port; 26736321Samurai#ifdef DEBUG 268127094Sdes printf("%s:%d\n", inet_ntoa(ndh->source_ip), ntohs(ndh->source_port)); 26936321Samurai fflush(stdout); 27036321Samurai#endif 271127094Sdes return ((p == NULL) ? -1 : 0); 27236321Samurai} 273127094Sdes 27436321Samurai/* Question Section */ 27536321Samurai#define QS_TYPE_NB 0x0020 27636321Samurai#define QS_TYPE_NBSTAT 0x0021 27736321Samurai#define QS_CLAS_IN 0x0001 27836321Samuraitypedef struct { 279127094Sdes u_short type; /* The type of Request */ 280127094Sdes u_short class; /* The class of Request */ 281127094Sdes} NBTNsQuestion; 28236321Samurai 283127094Sdesstatic u_char * 28441759SdillonAliasHandleQuestion( 28541759Sdillon u_short count, 286127094Sdes NBTNsQuestion * q, 28741759Sdillon char *pmax, 288127094Sdes NBTArguments * nbtarg) 28936321Samurai{ 29036321Samurai 291127094Sdes while (count != 0) { 29236321Samurai /* Name Filed */ 293127094Sdes q = (NBTNsQuestion *) AliasHandleName((u_char *) q, pmax); 29436321Samurai 29541759Sdillon if (q == NULL || (char *)(q + 1) > pmax) { 29641759Sdillon q = NULL; 29741759Sdillon break; 29841759Sdillon } 29936321Samurai /* Type and Class filed */ 300127094Sdes switch (ntohs(q->type)) { 301127094Sdes case QS_TYPE_NB: 302127094Sdes case QS_TYPE_NBSTAT: 303127094Sdes q = q + 1; 30436321Samurai break; 305127094Sdes default: 30644616Sbrian#ifdef DEBUG 307127094Sdes printf("\nUnknown Type on Question %0x\n", ntohs(q->type)); 30844616Sbrian#endif 30936321Samurai break; 31036321Samurai } 31136321Samurai count--; 31236321Samurai } 31336321Samurai 31436321Samurai /* Set up to out of Question Section */ 315127094Sdes return ((u_char *) q); 31636321Samurai} 31736321Samurai 31836321Samurai/* Resource Record */ 31936321Samurai#define RR_TYPE_A 0x0001 32036321Samurai#define RR_TYPE_NS 0x0002 32136321Samurai#define RR_TYPE_NULL 0x000a 32236321Samurai#define RR_TYPE_NB 0x0020 32336321Samurai#define RR_TYPE_NBSTAT 0x0021 32436321Samurai#define RR_CLAS_IN 0x0001 32536321Samurai#define SizeOfNsResource 8 32636321Samuraitypedef struct { 327127094Sdes u_short type; 328127094Sdes u_short class; 329127094Sdes unsigned int ttl; 330127094Sdes u_short rdlen; 331127094Sdes} NBTNsResource; 33236321Samurai 33336321Samurai#define SizeOfNsRNB 6 33436321Samuraitypedef struct { 335127094Sdes u_short g: 1 , ont:2, resv:13; 336127094Sdes struct in_addr addr; 337127094Sdes} NBTNsRNB; 33836321Samurai 339127094Sdesstatic u_char * 34099207SbrianAliasHandleResourceNB( 341127094Sdes NBTNsResource * q, 34299207Sbrian char *pmax, 343127094Sdes NBTArguments * nbtarg) 34436321Samurai{ 345127094Sdes NBTNsRNB *nb; 34636321Samurai u_short bcount; 34736321Samurai 34841759Sdillon if (q == NULL || (char *)(q + 1) > pmax) 349127094Sdes return (NULL); 35036321Samurai /* Check out a length */ 35136321Samurai bcount = ntohs(q->rdlen); 35236321Samurai 35336321Samurai /* Forward to Resource NB position */ 354127094Sdes nb = (NBTNsRNB *) ((u_char *) q + SizeOfNsResource); 35536321Samurai 35636321Samurai /* Processing all in_addr array */ 35736321Samurai#ifdef DEBUG 35836321Samurai printf("NB rec[%s", inet_ntoa(nbtarg->oldaddr)); 359127094Sdes printf("->%s, %dbytes] ", inet_ntoa(nbtarg->newaddr), bcount); 36036321Samurai#endif 361127094Sdes while (nb != NULL && bcount != 0) { 36241759Sdillon if ((char *)(nb + 1) > pmax) { 36341759Sdillon nb = NULL; 36441759Sdillon break; 36541759Sdillon } 36636321Samurai#ifdef DEBUG 367127094Sdes printf("<%s>", inet_ntoa(nb->addr)); 36836321Samurai#endif 369127094Sdes if (!bcmp(&nbtarg->oldaddr, &nb->addr, sizeof(struct in_addr))) { 370127094Sdes if (*nbtarg->uh_sum != 0) { 371127094Sdes int acc; 372127094Sdes u_short *sptr; 37336321Samurai 374127094Sdes sptr = (u_short *) & (nb->addr); 375127094Sdes acc = *sptr++; 376127094Sdes acc += *sptr; 377127094Sdes sptr = (u_short *) & (nbtarg->newaddr); 378127094Sdes acc -= *sptr++; 379127094Sdes acc -= *sptr; 380127094Sdes ADJUST_CHECKSUM(acc, *nbtarg->uh_sum); 38136321Samurai } 38236321Samurai nb->addr = nbtarg->newaddr; 38336321Samurai#ifdef DEBUG 38436321Samurai printf("O"); 38536321Samurai#endif 38636321Samurai } 38736321Samurai#ifdef DEBUG 388127094Sdes else { 38936321Samurai printf("."); 39036321Samurai } 39136321Samurai#endif 392127094Sdes nb = (NBTNsRNB *) ((u_char *) nb + SizeOfNsRNB); 393127094Sdes bcount -= SizeOfNsRNB; 39436321Samurai } 39541759Sdillon if (nb == NULL || (char *)(nb + 1) > pmax) { 39641759Sdillon nb = NULL; 39741759Sdillon } 398127094Sdes return ((u_char *) nb); 39936321Samurai} 40036321Samurai 40136321Samurai#define SizeOfResourceA 6 40236321Samuraitypedef struct { 403127094Sdes struct in_addr addr; 404127094Sdes} NBTNsResourceA; 40536321Samurai 406127094Sdesstatic u_char * 40799207SbrianAliasHandleResourceA( 408127094Sdes NBTNsResource * q, 40941759Sdillon char *pmax, 410127094Sdes NBTArguments * nbtarg) 41136321Samurai{ 412127094Sdes NBTNsResourceA *a; 41336321Samurai u_short bcount; 41436321Samurai 41541759Sdillon if (q == NULL || (char *)(q + 1) > pmax) 416127094Sdes return (NULL); 41741759Sdillon 41836321Samurai /* Forward to Resource A position */ 419127094Sdes a = (NBTNsResourceA *) ((u_char *) q + sizeof(NBTNsResource)); 42036321Samurai 42136321Samurai /* Check out of length */ 42236321Samurai bcount = ntohs(q->rdlen); 42336321Samurai 42436321Samurai /* Processing all in_addr array */ 42536321Samurai#ifdef DEBUG 42636321Samurai printf("Arec [%s", inet_ntoa(nbtarg->oldaddr)); 427127094Sdes printf("->%s]", inet_ntoa(nbtarg->newaddr)); 42836321Samurai#endif 429127094Sdes while (bcount != 0) { 43041759Sdillon if (a == NULL || (char *)(a + 1) > pmax) 431127094Sdes return (NULL); 43236321Samurai#ifdef DEBUG 433127094Sdes printf("..%s", inet_ntoa(a->addr)); 43436321Samurai#endif 435127094Sdes if (!bcmp(&nbtarg->oldaddr, &a->addr, sizeof(struct in_addr))) { 436127094Sdes if (*nbtarg->uh_sum != 0) { 437127094Sdes int acc; 438127094Sdes u_short *sptr; 43936321Samurai 440127094Sdes sptr = (u_short *) & (a->addr); /* Old */ 441127094Sdes acc = *sptr++; 442127094Sdes acc += *sptr; 443127094Sdes sptr = (u_short *) & nbtarg->newaddr; /* New */ 444127094Sdes acc -= *sptr++; 445127094Sdes acc -= *sptr; 446127094Sdes ADJUST_CHECKSUM(acc, *nbtarg->uh_sum); 44736321Samurai } 44836321Samurai a->addr = nbtarg->newaddr; 44936321Samurai } 450127094Sdes a++; /* XXXX */ 45136321Samurai bcount -= SizeOfResourceA; 45236321Samurai } 45341759Sdillon if (a == NULL || (char *)(a + 1) > pmax) 454127094Sdes a = NULL; 455127094Sdes return ((u_char *) a); 45636321Samurai} 45736321Samurai 45836321Samuraitypedef struct { 459127094Sdes u_short opcode:4, flags:8, resv:4; 460127094Sdes} NBTNsResourceNULL; 46136321Samurai 462127094Sdesstatic u_char * 46399207SbrianAliasHandleResourceNULL( 464127094Sdes NBTNsResource * q, 46541759Sdillon char *pmax, 466127094Sdes NBTArguments * nbtarg) 46736321Samurai{ 468127094Sdes NBTNsResourceNULL *n; 46936321Samurai u_short bcount; 47036321Samurai 47141759Sdillon if (q == NULL || (char *)(q + 1) > pmax) 472127094Sdes return (NULL); 47341759Sdillon 47436321Samurai /* Forward to Resource NULL position */ 475127094Sdes n = (NBTNsResourceNULL *) ((u_char *) q + sizeof(NBTNsResource)); 47636321Samurai 47736321Samurai /* Check out of length */ 47836321Samurai bcount = ntohs(q->rdlen); 47936321Samurai 48036321Samurai /* Processing all in_addr array */ 481127094Sdes while (bcount != 0) { 48241759Sdillon if ((char *)(n + 1) > pmax) { 48341759Sdillon n = NULL; 48441759Sdillon break; 48541759Sdillon } 48636321Samurai n++; 48736321Samurai bcount -= sizeof(NBTNsResourceNULL); 48836321Samurai } 48941759Sdillon if ((char *)(n + 1) > pmax) 49041759Sdillon n = NULL; 49136321Samurai 492127094Sdes return ((u_char *) n); 49336321Samurai} 49436321Samurai 495127094Sdesstatic u_char * 49699207SbrianAliasHandleResourceNS( 497127094Sdes NBTNsResource * q, 49841759Sdillon char *pmax, 499127094Sdes NBTArguments * nbtarg) 50036321Samurai{ 501127094Sdes NBTNsResourceNULL *n; 50236321Samurai u_short bcount; 50336321Samurai 50441759Sdillon if (q == NULL || (char *)(q + 1) > pmax) 505127094Sdes return (NULL); 50641759Sdillon 50736321Samurai /* Forward to Resource NULL position */ 508127094Sdes n = (NBTNsResourceNULL *) ((u_char *) q + sizeof(NBTNsResource)); 50936321Samurai 51036321Samurai /* Check out of length */ 51136321Samurai bcount = ntohs(q->rdlen); 51236321Samurai 51336321Samurai /* Resource Record Name Filed */ 514127094Sdes q = (NBTNsResource *) AliasHandleName((u_char *) n, pmax); /* XXX */ 51536321Samurai 516127094Sdes if (q == NULL || (char *)((u_char *) n + bcount) > pmax) 517127094Sdes return (NULL); 51841759Sdillon else 519127094Sdes return ((u_char *) n + bcount); 52036321Samurai} 52136321Samurai 52236321Samuraitypedef struct { 523127094Sdes u_short numnames; 524127094Sdes} NBTNsResourceNBSTAT; 52536321Samurai 526127094Sdesstatic u_char * 52741759SdillonAliasHandleResourceNBSTAT( 528127094Sdes NBTNsResource * q, 52941759Sdillon char *pmax, 530127094Sdes NBTArguments * nbtarg) 53136321Samurai{ 532127094Sdes NBTNsResourceNBSTAT *n; 53336321Samurai u_short bcount; 53436321Samurai 53541759Sdillon if (q == NULL || (char *)(q + 1) > pmax) 536127094Sdes return (NULL); 53741759Sdillon 53836321Samurai /* Forward to Resource NBSTAT position */ 539127094Sdes n = (NBTNsResourceNBSTAT *) ((u_char *) q + sizeof(NBTNsResource)); 54036321Samurai 54136321Samurai /* Check out of length */ 54236321Samurai bcount = ntohs(q->rdlen); 54336321Samurai 544127094Sdes if (q == NULL || (char *)((u_char *) n + bcount) > pmax) 545127094Sdes return (NULL); 54641759Sdillon else 547127094Sdes return ((u_char *) n + bcount); 54836321Samurai} 54936321Samurai 550127094Sdesstatic u_char * 55141759SdillonAliasHandleResource( 55299207Sbrian u_short count, 553127094Sdes NBTNsResource * q, 55441759Sdillon char *pmax, 55599207Sbrian NBTArguments 556127094Sdes * nbtarg) 55736321Samurai{ 558127094Sdes while (count != 0) { 55936321Samurai /* Resource Record Name Filed */ 560127094Sdes q = (NBTNsResource *) AliasHandleName((u_char *) q, pmax); 56141759Sdillon 56241759Sdillon if (q == NULL || (char *)(q + 1) > pmax) 56341759Sdillon break; 56436321Samurai#ifdef DEBUG 565127094Sdes printf("type=%02x, count=%d\n", ntohs(q->type), count); 56636321Samurai#endif 56736321Samurai 56836321Samurai /* Type and Class filed */ 569127094Sdes switch (ntohs(q->type)) { 570127094Sdes case RR_TYPE_NB: 571127094Sdes q = (NBTNsResource *) AliasHandleResourceNB( 572127094Sdes q, 573127094Sdes pmax, 574127094Sdes nbtarg 575127094Sdes ); 576127094Sdes break; 577127094Sdes case RR_TYPE_A: 578127094Sdes q = (NBTNsResource *) AliasHandleResourceA( 579127094Sdes q, 580127094Sdes pmax, 581127094Sdes nbtarg 582127094Sdes ); 583127094Sdes break; 584127094Sdes case RR_TYPE_NS: 585127094Sdes q = (NBTNsResource *) AliasHandleResourceNS( 586127094Sdes q, 587127094Sdes pmax, 588127094Sdes nbtarg 589127094Sdes ); 590127094Sdes break; 591127094Sdes case RR_TYPE_NULL: 592127094Sdes q = (NBTNsResource *) AliasHandleResourceNULL( 593127094Sdes q, 594127094Sdes pmax, 595127094Sdes nbtarg 596127094Sdes ); 597127094Sdes break; 598127094Sdes case RR_TYPE_NBSTAT: 599127094Sdes q = (NBTNsResource *) AliasHandleResourceNBSTAT( 600127094Sdes q, 601127094Sdes pmax, 602127094Sdes nbtarg 603127094Sdes ); 604127094Sdes break; 605127094Sdes default: 60644616Sbrian#ifdef DEBUG 607127094Sdes printf( 608127094Sdes "\nUnknown Type of Resource %0x\n", 609127094Sdes ntohs(q->type) 610127094Sdes ); 61144616Sbrian#endif 612127094Sdes break; 61336321Samurai } 61436321Samurai count--; 61536321Samurai } 61636321Samurai fflush(stdout); 617127094Sdes return ((u_char *) q); 61836321Samurai} 61936321Samurai 620127094Sdesint 621127094SdesAliasHandleUdpNbtNS( 622127094Sdes struct libalias *la, 623127094Sdes struct ip *pip, /* IP packet to examine/patch */ 624127094Sdes struct alias_link *link, 625127094Sdes struct in_addr *alias_address, 626127094Sdes u_short * alias_port, 627127094Sdes struct in_addr *original_address, 628127094Sdes u_short * original_port) 62936321Samurai{ 630127094Sdes struct udphdr *uh; 631127094Sdes NbtNSHeader *nsh; 632127094Sdes u_char *p; 633127094Sdes char *pmax; 634127094Sdes NBTArguments nbtarg; 63536321Samurai 63699207Sbrian /* Set up Common Parameter */ 637127094Sdes nbtarg.oldaddr = *alias_address; 638127094Sdes nbtarg.oldport = *alias_port; 639127094Sdes nbtarg.newaddr = *original_address; 640127094Sdes nbtarg.newport = *original_port; 64136321Samurai 642127094Sdes /* Calculate data length of UDP packet */ 643127094Sdes uh = (struct udphdr *)((char *)pip + (pip->ip_hl << 2)); 644127094Sdes nbtarg.uh_sum = &(uh->uh_sum); 645127094Sdes nsh = (NbtNSHeader *) ((char *)uh + (sizeof(struct udphdr))); 646127094Sdes p = (u_char *) (nsh + 1); 647127094Sdes pmax = (char *)uh + ntohs(uh->uh_ulen); 64836321Samurai 649127094Sdes if ((char *)(nsh + 1) > pmax) 650127094Sdes return (-1); 65141759Sdillon 65236321Samurai#ifdef DEBUG 653127094Sdes printf(" [%s] ID=%02x, op=%01x, flag=%02x, rcode=%01x, qd=%04x" 654127094Sdes ", an=%04x, ns=%04x, ar=%04x, [%d]-->", 655127094Sdes nsh->dir ? "Response" : "Request", 656127094Sdes nsh->nametrid, 657127094Sdes nsh->opcode, 658127094Sdes nsh->nmflags, 659127094Sdes nsh->rcode, 660127094Sdes ntohs(nsh->qdcount), 661127094Sdes ntohs(nsh->ancount), 662127094Sdes ntohs(nsh->nscount), 663127094Sdes ntohs(nsh->arcount), 664127094Sdes (u_char *) p - (u_char *) nsh 665127094Sdes ); 66636321Samurai#endif 66736321Samurai 66836321Samurai /* Question Entries */ 669127094Sdes if (ntohs(nsh->qdcount) != 0) { 670127094Sdes p = AliasHandleQuestion( 671127094Sdes ntohs(nsh->qdcount), 672127094Sdes (NBTNsQuestion *) p, 673127094Sdes pmax, 674127094Sdes &nbtarg 675127094Sdes ); 67636321Samurai } 67736321Samurai /* Answer Resource Records */ 678127094Sdes if (ntohs(nsh->ancount) != 0) { 679127094Sdes p = AliasHandleResource( 680127094Sdes ntohs(nsh->ancount), 681127094Sdes (NBTNsResource *) p, 682127094Sdes pmax, 683127094Sdes &nbtarg 684127094Sdes ); 68536321Samurai } 68636321Samurai /* Authority Resource Recodrs */ 687127094Sdes if (ntohs(nsh->nscount) != 0) { 688127094Sdes p = AliasHandleResource( 689127094Sdes ntohs(nsh->nscount), 690127094Sdes (NBTNsResource *) p, 691127094Sdes pmax, 692127094Sdes &nbtarg 693127094Sdes ); 69436321Samurai } 69536321Samurai /* Additional Resource Recodrs */ 696127094Sdes if (ntohs(nsh->arcount) != 0) { 697127094Sdes p = AliasHandleResource( 698127094Sdes ntohs(nsh->arcount), 699127094Sdes (NBTNsResource *) p, 700127094Sdes pmax, 701127094Sdes &nbtarg 702127094Sdes ); 70336321Samurai } 70436321Samurai#ifdef DEBUG 705127094Sdes PrintRcode(nsh->rcode); 70636321Samurai#endif 707127094Sdes return ((p == NULL) ? -1 : 0); 70836321Samurai} 709