alias_nbt.c revision 259858
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 259858 2013-12-25 02:06:57Z glebius $"); 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 */ 44145921Sglebius#ifdef _KERNEL 45145921Sglebius#include <sys/param.h> 46162674Spiso#include <sys/systm.h> 47162674Spiso#include <sys/kernel.h> 48162674Spiso#include <sys/module.h> 49145921Sglebius#else 50162674Spiso#include <errno.h> 51145921Sglebius#include <sys/types.h> 5299207Sbrian#include <stdio.h> 53187304Spiso#include <strings.h> 54145921Sglebius#endif 55145921Sglebius 5636321Samurai#include <netinet/in_systm.h> 5736321Samurai#include <netinet/in.h> 5836321Samurai#include <netinet/ip.h> 5936321Samurai#include <netinet/udp.h> 6036321Samurai 61145921Sglebius#ifdef _KERNEL 62145921Sglebius#include <netinet/libalias/alias_local.h> 63162674Spiso#include <netinet/libalias/alias_mod.h> 64145921Sglebius#else 6536321Samurai#include "alias_local.h" 66162674Spiso#include "alias_mod.h" 67145921Sglebius#endif 6836321Samurai 69162674Spiso#define NETBIOS_NS_PORT_NUMBER 137 70162674Spiso#define NETBIOS_DGM_PORT_NUMBER 138 71162674Spiso 72162674Spisostatic int 73259858SglebiusAliasHandleUdpNbt(struct libalias *, struct ip *, struct alias_link *, 74162674Spiso struct in_addr *, u_short); 75162674Spiso 76162674Spisostatic int 77162674SpisoAliasHandleUdpNbtNS(struct libalias *, struct ip *, struct alias_link *, 78162674Spiso struct in_addr *, u_short *, struct in_addr *, u_short *); 79259858Sglebiusstatic int 80190841Spisofingerprint1(struct libalias *la, struct alias_data *ah) 81162674Spiso{ 82162674Spiso 83259858Sglebius if (ah->dport == NULL || ah->sport == NULL || ah->lnk == NULL || 84162674Spiso ah->aaddr == NULL || ah->aport == NULL) 85162674Spiso return (-1); 86162674Spiso if (ntohs(*ah->dport) == NETBIOS_DGM_PORT_NUMBER 87162674Spiso || ntohs(*ah->sport) == NETBIOS_DGM_PORT_NUMBER) 88162674Spiso return (0); 89162674Spiso return (-1); 90162674Spiso} 91162674Spiso 92259858Sglebiusstatic int 93162674Spisoprotohandler1(struct libalias *la, struct ip *pip, struct alias_data *ah) 94162674Spiso{ 95162674Spiso 96190938Spiso return (AliasHandleUdpNbt(la, pip, ah->lnk, ah->aaddr, *ah->aport)); 97162674Spiso} 98162674Spiso 99259858Sglebiusstatic int 100190841Spisofingerprint2(struct libalias *la, struct alias_data *ah) 101162674Spiso{ 102162674Spiso 103259858Sglebius if (ah->dport == NULL || ah->sport == NULL || ah->lnk == NULL || 104162674Spiso ah->aaddr == NULL || ah->aport == NULL) 105162674Spiso return (-1); 106162674Spiso if (ntohs(*ah->dport) == NETBIOS_NS_PORT_NUMBER 107162674Spiso || ntohs(*ah->sport) == NETBIOS_NS_PORT_NUMBER) 108162674Spiso return (0); 109162674Spiso return (-1); 110162674Spiso} 111162674Spiso 112259858Sglebiusstatic int 113162674Spisoprotohandler2in(struct libalias *la, struct ip *pip, struct alias_data *ah) 114162674Spiso{ 115162674Spiso 116162674Spiso AliasHandleUdpNbtNS(la, pip, ah->lnk, ah->aaddr, ah->aport, 117162674Spiso ah->oaddr, ah->dport); 118162674Spiso return (0); 119162674Spiso} 120162674Spiso 121259858Sglebiusstatic int 122162674Spisoprotohandler2out(struct libalias *la, struct ip *pip, struct alias_data *ah) 123162674Spiso{ 124162674Spiso 125190938Spiso return (AliasHandleUdpNbtNS(la, pip, ah->lnk, &pip->ip_src, ah->sport, 126190938Spiso ah->aaddr, ah->aport)); 127162674Spiso} 128162674Spiso 129162674Spiso/* Kernel module definition. */ 130162674Spisostruct proto_handler handlers[] = { 131259858Sglebius { 132259858Sglebius .pri = 130, 133259858Sglebius .dir = IN|OUT, 134259858Sglebius .proto = UDP, 135259858Sglebius .fingerprint = &fingerprint1, 136162674Spiso .protohandler = &protohandler1 137259858Sglebius }, 138259858Sglebius { 139259858Sglebius .pri = 140, 140259858Sglebius .dir = IN, 141259858Sglebius .proto = UDP, 142259858Sglebius .fingerprint = &fingerprint2, 143162674Spiso .protohandler = &protohandler2in 144259858Sglebius }, 145259858Sglebius { 146259858Sglebius .pri = 140, 147259858Sglebius .dir = OUT, 148259858Sglebius .proto = UDP, 149259858Sglebius .fingerprint = &fingerprint2, 150162674Spiso .protohandler = &protohandler2out 151259858Sglebius }, 152162674Spiso { EOH } 153162674Spiso}; 154162674Spiso 155162674Spisostatic int 156162674Spisomod_handler(module_t mod, int type, void *data) 157162674Spiso{ 158162674Spiso int error; 159162674Spiso 160162674Spiso switch (type) { 161162674Spiso case MOD_LOAD: 162162674Spiso error = 0; 163162674Spiso LibAliasAttachHandlers(handlers); 164162674Spiso break; 165162674Spiso case MOD_UNLOAD: 166162674Spiso error = 0; 167162674Spiso LibAliasDetachHandlers(handlers); 168162674Spiso break; 169162674Spiso default: 170162674Spiso error = EINVAL; 171162674Spiso } 172162674Spiso return (error); 173162674Spiso} 174162674Spiso 175162674Spiso#ifdef _KERNEL 176259858Sglebiusstatic 177162674Spiso#endif 178162674Spisomoduledata_t alias_mod = { 179162674Spiso "alias_nbt", mod_handler, NULL 180162674Spiso}; 181162674Spiso 182162674Spiso#ifdef _KERNEL 183162674SpisoDECLARE_MODULE(alias_nbt, alias_mod, SI_SUB_DRIVERS, SI_ORDER_SECOND); 184162674SpisoMODULE_VERSION(alias_nbt, 1); 185162674SpisoMODULE_DEPEND(alias_nbt, libalias, 1, 1, 1); 186162674Spiso#endif 187162674Spiso 18836321Samuraitypedef struct { 189127094Sdes struct in_addr oldaddr; 190127094Sdes u_short oldport; 191127094Sdes struct in_addr newaddr; 192127094Sdes u_short newport; 193127094Sdes u_short *uh_sum; 194127094Sdes} NBTArguments; 19536321Samurai 19636321Samuraitypedef struct { 197127094Sdes unsigned char type; 198127094Sdes unsigned char flags; 199127094Sdes u_short id; 200127094Sdes struct in_addr source_ip; 201127094Sdes u_short source_port; 202127094Sdes u_short len; 203127094Sdes u_short offset; 204127094Sdes} NbtDataHeader; 20536321Samurai 20636321Samurai#define OpQuery 0 20736321Samurai#define OpUnknown 4 20836321Samurai#define OpRegist 5 20936321Samurai#define OpRelease 6 21036321Samurai#define OpWACK 7 21136321Samurai#define OpRefresh 8 21236321Samuraitypedef struct { 213127094Sdes u_short nametrid; 214127094Sdes u_short dir: 1, opcode:4, nmflags:7, rcode:4; 215127094Sdes u_short qdcount; 216127094Sdes u_short ancount; 217127094Sdes u_short nscount; 218127094Sdes u_short arcount; 219127094Sdes} NbtNSHeader; 22036321Samurai 22136321Samurai#define FMT_ERR 0x1 22236321Samurai#define SRV_ERR 0x2 22336321Samurai#define IMP_ERR 0x4 22436321Samurai#define RFS_ERR 0x5 22536321Samurai#define ACT_ERR 0x6 22636321Samurai#define CFT_ERR 0x7 22736321Samurai 22836321Samurai 229145961Sglebius#ifdef LIBALIAS_DEBUG 230127094Sdesstatic void 231127094SdesPrintRcode(u_char rcode) 232127094Sdes{ 23336321Samurai 23436321Samurai switch (rcode) { 23536321Samurai case FMT_ERR: 236127094Sdes printf("\nFormat Error."); 237127094Sdes case SRV_ERR: 238127094Sdes printf("\nSever failure."); 239127094Sdes case IMP_ERR: 240127094Sdes printf("\nUnsupported request error.\n"); 241127094Sdes case RFS_ERR: 242127094Sdes printf("\nRefused error.\n"); 243127094Sdes case ACT_ERR: 244127094Sdes printf("\nActive error.\n"); 245127094Sdes case CFT_ERR: 246127094Sdes printf("\nName in conflict error.\n"); 247127094Sdes default: 248127094Sdes printf("\n?%c?=%0x\n", '?', rcode); 24936321Samurai 25099207Sbrian } 25136321Samurai} 252127094Sdes 25344616Sbrian#endif 25436321Samurai 25536321Samurai 25636321Samurai/* Handling Name field */ 257127094Sdesstatic u_char * 258127094SdesAliasHandleName(u_char * p, char *pmax) 259127094Sdes{ 26036321Samurai 26136321Samurai u_char *s; 26236321Samurai u_char c; 263127094Sdes int compress; 26436321Samurai 26536321Samurai /* Following length field */ 26641759Sdillon 26741759Sdillon if (p == NULL || (char *)p >= pmax) 268127094Sdes return (NULL); 26941759Sdillon 270127094Sdes if (*p & 0xc0) { 27136321Samurai p = p + 2; 27241759Sdillon if ((char *)p > pmax) 273127094Sdes return (NULL); 274127094Sdes return ((u_char *) p); 27536321Samurai } 276127094Sdes while ((*p & 0x3f) != 0x00) { 27736321Samurai s = p + 1; 278127094Sdes if (*p == 0x20) 27936321Samurai compress = 1; 28036321Samurai else 28136321Samurai compress = 0; 28299207Sbrian 283127094Sdes /* Get next length field */ 284127094Sdes p = (u_char *) (p + (*p & 0x3f) + 1); 28541759Sdillon if ((char *)p > pmax) { 28641759Sdillon p = NULL; 28741759Sdillon break; 28841759Sdillon } 289145961Sglebius#ifdef LIBALIAS_DEBUG 29036321Samurai printf(":"); 29136321Samurai#endif 29236321Samurai while (s < p) { 293127094Sdes if (compress == 1) { 294127094Sdes c = (u_char) (((((*s & 0x0f) << 4) | (*(s + 1) & 0x0f)) - 0x11)); 295145961Sglebius#ifdef LIBALIAS_DEBUG 296127094Sdes if (isprint(c)) 297127094Sdes printf("%c", c); 29836321Samurai else 299127094Sdes printf("<0x%02x>", c); 30036321Samurai#endif 301127094Sdes s += 2; 30236321Samurai } else { 303145961Sglebius#ifdef LIBALIAS_DEBUG 30436321Samurai printf("%c", *s); 30536321Samurai#endif 30636321Samurai s++; 30736321Samurai } 30836321Samurai } 309145961Sglebius#ifdef LIBALIAS_DEBUG 31036321Samurai printf(":"); 311145928Sglebius fflush(stdout); 31236321Samurai#endif 313127094Sdes } 31436321Samurai 31536321Samurai /* Set up to out of Name field */ 31641759Sdillon if (p == NULL || (char *)p >= pmax) 317127094Sdes p = NULL; 31841759Sdillon else 319127094Sdes p++; 320127094Sdes return ((u_char *) p); 32136321Samurai} 32236321Samurai 32399207Sbrian/* 32436321Samurai * NetBios Datagram Handler (IP/UDP) 32536321Samurai */ 32636321Samurai#define DGM_DIRECT_UNIQ 0x10 32736321Samurai#define DGM_DIRECT_GROUP 0x11 32836321Samurai#define DGM_BROADCAST 0x12 32936321Samurai#define DGM_ERROR 0x13 33036321Samurai#define DGM_QUERY 0x14 33136321Samurai#define DGM_POSITIVE_RES 0x15 33236321Samurai#define DGM_NEGATIVE_RES 0x16 33336321Samurai 334162674Spisostatic int 335127094SdesAliasHandleUdpNbt( 336127094Sdes struct libalias *la, 337127094Sdes struct ip *pip, /* IP packet to examine/patch */ 338131614Sdes struct alias_link *lnk, 339127094Sdes struct in_addr *alias_address, 340127094Sdes u_short alias_port 341127094Sdes) 342127094Sdes{ 343127094Sdes struct udphdr *uh; 344127094Sdes NbtDataHeader *ndh; 345127094Sdes u_char *p = NULL; 346127094Sdes char *pmax; 34799207Sbrian 348131614Sdes (void)la; 349131614Sdes (void)lnk; 350131614Sdes 351127094Sdes /* Calculate data length of UDP packet */ 352131699Sdes uh = (struct udphdr *)ip_next(pip); 353127094Sdes pmax = (char *)uh + ntohs(uh->uh_ulen); 35441759Sdillon 355131699Sdes ndh = (NbtDataHeader *)udp_next(uh); 356127094Sdes if ((char *)(ndh + 1) > pmax) 357127094Sdes return (-1); 358145961Sglebius#ifdef LIBALIAS_DEBUG 359127094Sdes printf("\nType=%02x,", ndh->type); 36036321Samurai#endif 361127094Sdes switch (ndh->type) { 362127094Sdes case DGM_DIRECT_UNIQ: 363127094Sdes case DGM_DIRECT_GROUP: 364127094Sdes case DGM_BROADCAST: 365127094Sdes p = (u_char *) ndh + 14; 366127094Sdes p = AliasHandleName(p, pmax); /* Source Name */ 367127094Sdes p = AliasHandleName(p, pmax); /* Destination Name */ 368127094Sdes break; 369127094Sdes case DGM_ERROR: 370127094Sdes p = (u_char *) ndh + 11; 371127094Sdes break; 372127094Sdes case DGM_QUERY: 373127094Sdes case DGM_POSITIVE_RES: 374127094Sdes case DGM_NEGATIVE_RES: 375127094Sdes p = (u_char *) ndh + 10; 376127094Sdes p = AliasHandleName(p, pmax); /* Destination Name */ 377127094Sdes break; 37836321Samurai } 379127094Sdes if (p == NULL || (char *)p > pmax) 380127094Sdes p = NULL; 381145961Sglebius#ifdef LIBALIAS_DEBUG 382127094Sdes printf("%s:%d-->", inet_ntoa(ndh->source_ip), ntohs(ndh->source_port)); 38336321Samurai#endif 384108533Sschweikh /* Doing an IP address and Port number Translation */ 385127094Sdes if (uh->uh_sum != 0) { 386127094Sdes int acc; 387127094Sdes u_short *sptr; 388127094Sdes 389127094Sdes acc = ndh->source_port; 39036321Samurai acc -= alias_port; 391127094Sdes sptr = (u_short *) & (ndh->source_ip); 39236321Samurai acc += *sptr++; 39336321Samurai acc += *sptr; 39436321Samurai sptr = (u_short *) alias_address; 39536321Samurai acc -= *sptr++; 39636321Samurai acc -= *sptr; 39774778Sbrian ADJUST_CHECKSUM(acc, uh->uh_sum); 39836321Samurai } 399127094Sdes ndh->source_ip = *alias_address; 400127094Sdes ndh->source_port = alias_port; 401145961Sglebius#ifdef LIBALIAS_DEBUG 402127094Sdes printf("%s:%d\n", inet_ntoa(ndh->source_ip), ntohs(ndh->source_port)); 40336321Samurai fflush(stdout); 40436321Samurai#endif 405127094Sdes return ((p == NULL) ? -1 : 0); 40636321Samurai} 407127094Sdes 40836321Samurai/* Question Section */ 40936321Samurai#define QS_TYPE_NB 0x0020 41036321Samurai#define QS_TYPE_NBSTAT 0x0021 41136321Samurai#define QS_CLAS_IN 0x0001 41236321Samuraitypedef struct { 413127094Sdes u_short type; /* The type of Request */ 414127094Sdes u_short class; /* The class of Request */ 415127094Sdes} NBTNsQuestion; 41636321Samurai 417127094Sdesstatic u_char * 41841759SdillonAliasHandleQuestion( 41941759Sdillon u_short count, 420127094Sdes NBTNsQuestion * q, 42141759Sdillon char *pmax, 422127094Sdes NBTArguments * nbtarg) 42336321Samurai{ 42436321Samurai 425131614Sdes (void)nbtarg; 426131614Sdes 427127094Sdes while (count != 0) { 42836321Samurai /* Name Filed */ 429127094Sdes q = (NBTNsQuestion *) AliasHandleName((u_char *) q, pmax); 43036321Samurai 43141759Sdillon if (q == NULL || (char *)(q + 1) > pmax) { 43241759Sdillon q = NULL; 43341759Sdillon break; 43441759Sdillon } 43536321Samurai /* Type and Class filed */ 436127094Sdes switch (ntohs(q->type)) { 437127094Sdes case QS_TYPE_NB: 438127094Sdes case QS_TYPE_NBSTAT: 439127094Sdes q = q + 1; 44036321Samurai break; 441127094Sdes default: 442145961Sglebius#ifdef LIBALIAS_DEBUG 443127094Sdes printf("\nUnknown Type on Question %0x\n", ntohs(q->type)); 44444616Sbrian#endif 44536321Samurai break; 44636321Samurai } 44736321Samurai count--; 44836321Samurai } 44936321Samurai 45036321Samurai /* Set up to out of Question Section */ 451127094Sdes return ((u_char *) q); 45236321Samurai} 45336321Samurai 45436321Samurai/* Resource Record */ 45536321Samurai#define RR_TYPE_A 0x0001 45636321Samurai#define RR_TYPE_NS 0x0002 45736321Samurai#define RR_TYPE_NULL 0x000a 45836321Samurai#define RR_TYPE_NB 0x0020 45936321Samurai#define RR_TYPE_NBSTAT 0x0021 46036321Samurai#define RR_CLAS_IN 0x0001 46136321Samurai#define SizeOfNsResource 8 46236321Samuraitypedef struct { 463127094Sdes u_short type; 464127094Sdes u_short class; 465127094Sdes unsigned int ttl; 466127094Sdes u_short rdlen; 467127094Sdes} NBTNsResource; 46836321Samurai 46936321Samurai#define SizeOfNsRNB 6 47036321Samuraitypedef struct { 471127094Sdes u_short g: 1 , ont:2, resv:13; 472127094Sdes struct in_addr addr; 473127094Sdes} NBTNsRNB; 47436321Samurai 475127094Sdesstatic u_char * 47699207SbrianAliasHandleResourceNB( 477127094Sdes NBTNsResource * q, 47899207Sbrian char *pmax, 479127094Sdes NBTArguments * nbtarg) 48036321Samurai{ 481127094Sdes NBTNsRNB *nb; 48236321Samurai u_short bcount; 48336321Samurai 48441759Sdillon if (q == NULL || (char *)(q + 1) > pmax) 485127094Sdes return (NULL); 48636321Samurai /* Check out a length */ 48736321Samurai bcount = ntohs(q->rdlen); 48836321Samurai 48936321Samurai /* Forward to Resource NB position */ 490127094Sdes nb = (NBTNsRNB *) ((u_char *) q + SizeOfNsResource); 49136321Samurai 49236321Samurai /* Processing all in_addr array */ 493145961Sglebius#ifdef LIBALIAS_DEBUG 49436321Samurai printf("NB rec[%s", inet_ntoa(nbtarg->oldaddr)); 495127094Sdes printf("->%s, %dbytes] ", inet_ntoa(nbtarg->newaddr), bcount); 49636321Samurai#endif 497127094Sdes while (nb != NULL && bcount != 0) { 49841759Sdillon if ((char *)(nb + 1) > pmax) { 49941759Sdillon nb = NULL; 50041759Sdillon break; 50141759Sdillon } 502145961Sglebius#ifdef LIBALIAS_DEBUG 503127094Sdes printf("<%s>", inet_ntoa(nb->addr)); 50436321Samurai#endif 505127094Sdes if (!bcmp(&nbtarg->oldaddr, &nb->addr, sizeof(struct in_addr))) { 506127094Sdes if (*nbtarg->uh_sum != 0) { 507127094Sdes int acc; 508127094Sdes u_short *sptr; 50936321Samurai 510127094Sdes sptr = (u_short *) & (nb->addr); 511127094Sdes acc = *sptr++; 512127094Sdes acc += *sptr; 513127094Sdes sptr = (u_short *) & (nbtarg->newaddr); 514127094Sdes acc -= *sptr++; 515127094Sdes acc -= *sptr; 516127094Sdes ADJUST_CHECKSUM(acc, *nbtarg->uh_sum); 51736321Samurai } 51836321Samurai nb->addr = nbtarg->newaddr; 519145961Sglebius#ifdef LIBALIAS_DEBUG 52036321Samurai printf("O"); 52136321Samurai#endif 52236321Samurai } 523145961Sglebius#ifdef LIBALIAS_DEBUG 524127094Sdes else { 52536321Samurai printf("."); 52636321Samurai } 52736321Samurai#endif 528127094Sdes nb = (NBTNsRNB *) ((u_char *) nb + SizeOfNsRNB); 529127094Sdes bcount -= SizeOfNsRNB; 53036321Samurai } 53141759Sdillon if (nb == NULL || (char *)(nb + 1) > pmax) { 53241759Sdillon nb = NULL; 53341759Sdillon } 534127094Sdes return ((u_char *) nb); 53536321Samurai} 53636321Samurai 53736321Samurai#define SizeOfResourceA 6 53836321Samuraitypedef struct { 539127094Sdes struct in_addr addr; 540127094Sdes} NBTNsResourceA; 54136321Samurai 542127094Sdesstatic u_char * 54399207SbrianAliasHandleResourceA( 544127094Sdes NBTNsResource * q, 54541759Sdillon char *pmax, 546127094Sdes NBTArguments * nbtarg) 54736321Samurai{ 548127094Sdes NBTNsResourceA *a; 54936321Samurai u_short bcount; 55036321Samurai 55141759Sdillon if (q == NULL || (char *)(q + 1) > pmax) 552127094Sdes return (NULL); 55341759Sdillon 55436321Samurai /* Forward to Resource A position */ 555127094Sdes a = (NBTNsResourceA *) ((u_char *) q + sizeof(NBTNsResource)); 55636321Samurai 55736321Samurai /* Check out of length */ 55836321Samurai bcount = ntohs(q->rdlen); 55936321Samurai 56036321Samurai /* Processing all in_addr array */ 561145961Sglebius#ifdef LIBALIAS_DEBUG 56236321Samurai printf("Arec [%s", inet_ntoa(nbtarg->oldaddr)); 563127094Sdes printf("->%s]", inet_ntoa(nbtarg->newaddr)); 56436321Samurai#endif 565127094Sdes while (bcount != 0) { 56641759Sdillon if (a == NULL || (char *)(a + 1) > pmax) 567127094Sdes return (NULL); 568145961Sglebius#ifdef LIBALIAS_DEBUG 569127094Sdes printf("..%s", inet_ntoa(a->addr)); 57036321Samurai#endif 571127094Sdes if (!bcmp(&nbtarg->oldaddr, &a->addr, sizeof(struct in_addr))) { 572127094Sdes if (*nbtarg->uh_sum != 0) { 573127094Sdes int acc; 574127094Sdes u_short *sptr; 57536321Samurai 576127094Sdes sptr = (u_short *) & (a->addr); /* Old */ 577127094Sdes acc = *sptr++; 578127094Sdes acc += *sptr; 579127094Sdes sptr = (u_short *) & nbtarg->newaddr; /* New */ 580127094Sdes acc -= *sptr++; 581127094Sdes acc -= *sptr; 582127094Sdes ADJUST_CHECKSUM(acc, *nbtarg->uh_sum); 58336321Samurai } 58436321Samurai a->addr = nbtarg->newaddr; 58536321Samurai } 586127094Sdes a++; /* XXXX */ 58736321Samurai bcount -= SizeOfResourceA; 58836321Samurai } 58941759Sdillon if (a == NULL || (char *)(a + 1) > pmax) 590127094Sdes a = NULL; 591127094Sdes return ((u_char *) a); 59236321Samurai} 59336321Samurai 59436321Samuraitypedef struct { 595127094Sdes u_short opcode:4, flags:8, resv:4; 596127094Sdes} NBTNsResourceNULL; 59736321Samurai 598127094Sdesstatic u_char * 59999207SbrianAliasHandleResourceNULL( 600127094Sdes NBTNsResource * q, 60141759Sdillon char *pmax, 602127094Sdes NBTArguments * nbtarg) 60336321Samurai{ 604127094Sdes NBTNsResourceNULL *n; 60536321Samurai u_short bcount; 60636321Samurai 607131614Sdes (void)nbtarg; 608131614Sdes 60941759Sdillon if (q == NULL || (char *)(q + 1) > pmax) 610127094Sdes return (NULL); 61141759Sdillon 61236321Samurai /* Forward to Resource NULL position */ 613127094Sdes n = (NBTNsResourceNULL *) ((u_char *) q + sizeof(NBTNsResource)); 61436321Samurai 61536321Samurai /* Check out of length */ 61636321Samurai bcount = ntohs(q->rdlen); 61736321Samurai 61836321Samurai /* Processing all in_addr array */ 619127094Sdes while (bcount != 0) { 62041759Sdillon if ((char *)(n + 1) > pmax) { 62141759Sdillon n = NULL; 62241759Sdillon break; 62341759Sdillon } 62436321Samurai n++; 62536321Samurai bcount -= sizeof(NBTNsResourceNULL); 62636321Samurai } 62741759Sdillon if ((char *)(n + 1) > pmax) 62841759Sdillon n = NULL; 62936321Samurai 630127094Sdes return ((u_char *) n); 63136321Samurai} 63236321Samurai 633127094Sdesstatic u_char * 63499207SbrianAliasHandleResourceNS( 635127094Sdes NBTNsResource * q, 63641759Sdillon char *pmax, 637127094Sdes NBTArguments * nbtarg) 63836321Samurai{ 639127094Sdes NBTNsResourceNULL *n; 64036321Samurai u_short bcount; 64136321Samurai 642131614Sdes (void)nbtarg; 643131614Sdes 64441759Sdillon if (q == NULL || (char *)(q + 1) > pmax) 645127094Sdes return (NULL); 64641759Sdillon 64736321Samurai /* Forward to Resource NULL position */ 648127094Sdes n = (NBTNsResourceNULL *) ((u_char *) q + sizeof(NBTNsResource)); 64936321Samurai 65036321Samurai /* Check out of length */ 65136321Samurai bcount = ntohs(q->rdlen); 65236321Samurai 65336321Samurai /* Resource Record Name Filed */ 654127094Sdes q = (NBTNsResource *) AliasHandleName((u_char *) n, pmax); /* XXX */ 65536321Samurai 656127094Sdes if (q == NULL || (char *)((u_char *) n + bcount) > pmax) 657127094Sdes return (NULL); 65841759Sdillon else 659127094Sdes return ((u_char *) n + bcount); 66036321Samurai} 66136321Samurai 66236321Samuraitypedef struct { 663127094Sdes u_short numnames; 664127094Sdes} NBTNsResourceNBSTAT; 66536321Samurai 666127094Sdesstatic u_char * 66741759SdillonAliasHandleResourceNBSTAT( 668127094Sdes NBTNsResource * q, 66941759Sdillon char *pmax, 670127094Sdes NBTArguments * nbtarg) 67136321Samurai{ 672127094Sdes NBTNsResourceNBSTAT *n; 67336321Samurai u_short bcount; 67436321Samurai 675131614Sdes (void)nbtarg; 676131614Sdes 67741759Sdillon if (q == NULL || (char *)(q + 1) > pmax) 678127094Sdes return (NULL); 67941759Sdillon 68036321Samurai /* Forward to Resource NBSTAT position */ 681127094Sdes n = (NBTNsResourceNBSTAT *) ((u_char *) q + sizeof(NBTNsResource)); 68236321Samurai 68336321Samurai /* Check out of length */ 68436321Samurai bcount = ntohs(q->rdlen); 68536321Samurai 686127094Sdes if (q == NULL || (char *)((u_char *) n + bcount) > pmax) 687127094Sdes return (NULL); 68841759Sdillon else 689127094Sdes return ((u_char *) n + bcount); 69036321Samurai} 69136321Samurai 692127094Sdesstatic u_char * 69341759SdillonAliasHandleResource( 69499207Sbrian u_short count, 695127094Sdes NBTNsResource * q, 69641759Sdillon char *pmax, 69799207Sbrian NBTArguments 698127094Sdes * nbtarg) 69936321Samurai{ 700127094Sdes while (count != 0) { 70136321Samurai /* Resource Record Name Filed */ 702127094Sdes q = (NBTNsResource *) AliasHandleName((u_char *) q, pmax); 70341759Sdillon 70441759Sdillon if (q == NULL || (char *)(q + 1) > pmax) 70541759Sdillon break; 706145961Sglebius#ifdef LIBALIAS_DEBUG 707127094Sdes printf("type=%02x, count=%d\n", ntohs(q->type), count); 70836321Samurai#endif 70936321Samurai 71036321Samurai /* Type and Class filed */ 711127094Sdes switch (ntohs(q->type)) { 712127094Sdes case RR_TYPE_NB: 713127094Sdes q = (NBTNsResource *) AliasHandleResourceNB( 714127094Sdes q, 715127094Sdes pmax, 716127094Sdes nbtarg 717127094Sdes ); 718127094Sdes break; 719127094Sdes case RR_TYPE_A: 720127094Sdes q = (NBTNsResource *) AliasHandleResourceA( 721127094Sdes q, 722127094Sdes pmax, 723127094Sdes nbtarg 724127094Sdes ); 725127094Sdes break; 726127094Sdes case RR_TYPE_NS: 727127094Sdes q = (NBTNsResource *) AliasHandleResourceNS( 728127094Sdes q, 729127094Sdes pmax, 730127094Sdes nbtarg 731127094Sdes ); 732127094Sdes break; 733127094Sdes case RR_TYPE_NULL: 734127094Sdes q = (NBTNsResource *) AliasHandleResourceNULL( 735127094Sdes q, 736127094Sdes pmax, 737127094Sdes nbtarg 738127094Sdes ); 739127094Sdes break; 740127094Sdes case RR_TYPE_NBSTAT: 741127094Sdes q = (NBTNsResource *) AliasHandleResourceNBSTAT( 742127094Sdes q, 743127094Sdes pmax, 744127094Sdes nbtarg 745127094Sdes ); 746127094Sdes break; 747127094Sdes default: 748145961Sglebius#ifdef LIBALIAS_DEBUG 749127094Sdes printf( 750127094Sdes "\nUnknown Type of Resource %0x\n", 751127094Sdes ntohs(q->type) 752127094Sdes ); 753145928Sglebius fflush(stdout); 75444616Sbrian#endif 755127094Sdes break; 75636321Samurai } 75736321Samurai count--; 75836321Samurai } 759127094Sdes return ((u_char *) q); 76036321Samurai} 76136321Samurai 762162674Spisostatic int 763127094SdesAliasHandleUdpNbtNS( 764127094Sdes struct libalias *la, 765127094Sdes struct ip *pip, /* IP packet to examine/patch */ 766131614Sdes struct alias_link *lnk, 767127094Sdes struct in_addr *alias_address, 768127094Sdes u_short * alias_port, 769127094Sdes struct in_addr *original_address, 770127094Sdes u_short * original_port) 77136321Samurai{ 772127094Sdes struct udphdr *uh; 773127094Sdes NbtNSHeader *nsh; 774127094Sdes u_char *p; 775127094Sdes char *pmax; 776127094Sdes NBTArguments nbtarg; 77736321Samurai 778131614Sdes (void)la; 779131614Sdes (void)lnk; 780131614Sdes 78199207Sbrian /* Set up Common Parameter */ 782127094Sdes nbtarg.oldaddr = *alias_address; 783127094Sdes nbtarg.oldport = *alias_port; 784127094Sdes nbtarg.newaddr = *original_address; 785127094Sdes nbtarg.newport = *original_port; 78636321Samurai 787127094Sdes /* Calculate data length of UDP packet */ 788131699Sdes uh = (struct udphdr *)ip_next(pip); 789127094Sdes nbtarg.uh_sum = &(uh->uh_sum); 790131699Sdes nsh = (NbtNSHeader *)udp_next(uh); 791127094Sdes p = (u_char *) (nsh + 1); 792127094Sdes pmax = (char *)uh + ntohs(uh->uh_ulen); 79336321Samurai 794127094Sdes if ((char *)(nsh + 1) > pmax) 795127094Sdes return (-1); 79641759Sdillon 797145961Sglebius#ifdef LIBALIAS_DEBUG 798127094Sdes printf(" [%s] ID=%02x, op=%01x, flag=%02x, rcode=%01x, qd=%04x" 799127094Sdes ", an=%04x, ns=%04x, ar=%04x, [%d]-->", 800127094Sdes nsh->dir ? "Response" : "Request", 801127094Sdes nsh->nametrid, 802127094Sdes nsh->opcode, 803127094Sdes nsh->nmflags, 804127094Sdes nsh->rcode, 805127094Sdes ntohs(nsh->qdcount), 806127094Sdes ntohs(nsh->ancount), 807127094Sdes ntohs(nsh->nscount), 808127094Sdes ntohs(nsh->arcount), 809127094Sdes (u_char *) p - (u_char *) nsh 810127094Sdes ); 81136321Samurai#endif 81236321Samurai 81336321Samurai /* Question Entries */ 814127094Sdes if (ntohs(nsh->qdcount) != 0) { 815127094Sdes p = AliasHandleQuestion( 816127094Sdes ntohs(nsh->qdcount), 817127094Sdes (NBTNsQuestion *) p, 818127094Sdes pmax, 819127094Sdes &nbtarg 820127094Sdes ); 82136321Samurai } 82236321Samurai /* Answer Resource Records */ 823127094Sdes if (ntohs(nsh->ancount) != 0) { 824127094Sdes p = AliasHandleResource( 825127094Sdes ntohs(nsh->ancount), 826127094Sdes (NBTNsResource *) p, 827127094Sdes pmax, 828127094Sdes &nbtarg 829127094Sdes ); 83036321Samurai } 83136321Samurai /* Authority Resource Recodrs */ 832127094Sdes if (ntohs(nsh->nscount) != 0) { 833127094Sdes p = AliasHandleResource( 834127094Sdes ntohs(nsh->nscount), 835127094Sdes (NBTNsResource *) p, 836127094Sdes pmax, 837127094Sdes &nbtarg 838127094Sdes ); 83936321Samurai } 84036321Samurai /* Additional Resource Recodrs */ 841127094Sdes if (ntohs(nsh->arcount) != 0) { 842127094Sdes p = AliasHandleResource( 843127094Sdes ntohs(nsh->arcount), 844127094Sdes (NBTNsResource *) p, 845127094Sdes pmax, 846127094Sdes &nbtarg 847127094Sdes ); 84836321Samurai } 849145961Sglebius#ifdef LIBALIAS_DEBUG 850127094Sdes PrintRcode(nsh->rcode); 85136321Samurai#endif 852127094Sdes return ((p == NULL) ? -1 : 0); 85336321Samurai} 854