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: stable/11/sys/netinet/libalias/alias_nbt.c 315456 2017-03-17 14:54:10Z vangyzen $"); 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; 347315456Svangyzen#ifdef LIBALIAS_DEBUG 348315456Svangyzen char addrbuf[INET_ADDRSTRLEN]; 349315456Svangyzen#endif 35099207Sbrian 351131614Sdes (void)la; 352131614Sdes (void)lnk; 353131614Sdes 354127094Sdes /* Calculate data length of UDP packet */ 355131699Sdes uh = (struct udphdr *)ip_next(pip); 356127094Sdes pmax = (char *)uh + ntohs(uh->uh_ulen); 35741759Sdillon 358131699Sdes ndh = (NbtDataHeader *)udp_next(uh); 359127094Sdes if ((char *)(ndh + 1) > pmax) 360127094Sdes return (-1); 361145961Sglebius#ifdef LIBALIAS_DEBUG 362127094Sdes printf("\nType=%02x,", ndh->type); 36336321Samurai#endif 364127094Sdes switch (ndh->type) { 365127094Sdes case DGM_DIRECT_UNIQ: 366127094Sdes case DGM_DIRECT_GROUP: 367127094Sdes case DGM_BROADCAST: 368127094Sdes p = (u_char *) ndh + 14; 369127094Sdes p = AliasHandleName(p, pmax); /* Source Name */ 370127094Sdes p = AliasHandleName(p, pmax); /* Destination Name */ 371127094Sdes break; 372127094Sdes case DGM_ERROR: 373127094Sdes p = (u_char *) ndh + 11; 374127094Sdes break; 375127094Sdes case DGM_QUERY: 376127094Sdes case DGM_POSITIVE_RES: 377127094Sdes case DGM_NEGATIVE_RES: 378127094Sdes p = (u_char *) ndh + 10; 379127094Sdes p = AliasHandleName(p, pmax); /* Destination Name */ 380127094Sdes break; 38136321Samurai } 382127094Sdes if (p == NULL || (char *)p > pmax) 383127094Sdes p = NULL; 384145961Sglebius#ifdef LIBALIAS_DEBUG 385315456Svangyzen printf("%s:%d-->", inet_ntoa_r(ndh->source_ip, INET_NTOA_BUF(addrbuf)), 386315456Svangyzen ntohs(ndh->source_port)); 38736321Samurai#endif 388108533Sschweikh /* Doing an IP address and Port number Translation */ 389127094Sdes if (uh->uh_sum != 0) { 390127094Sdes int acc; 391127094Sdes u_short *sptr; 392127094Sdes 393127094Sdes acc = ndh->source_port; 39436321Samurai acc -= alias_port; 395127094Sdes sptr = (u_short *) & (ndh->source_ip); 39636321Samurai acc += *sptr++; 39736321Samurai acc += *sptr; 39836321Samurai sptr = (u_short *) alias_address; 39936321Samurai acc -= *sptr++; 40036321Samurai acc -= *sptr; 40174778Sbrian ADJUST_CHECKSUM(acc, uh->uh_sum); 40236321Samurai } 403127094Sdes ndh->source_ip = *alias_address; 404127094Sdes ndh->source_port = alias_port; 405145961Sglebius#ifdef LIBALIAS_DEBUG 406315456Svangyzen printf("%s:%d\n", inet_ntoa_r(ndh->source_ip, INET_NTOA_BUF(addrbuf)), 407315456Svangyzen ntohs(ndh->source_port)); 40836321Samurai fflush(stdout); 40936321Samurai#endif 410127094Sdes return ((p == NULL) ? -1 : 0); 41136321Samurai} 412127094Sdes 41336321Samurai/* Question Section */ 41436321Samurai#define QS_TYPE_NB 0x0020 41536321Samurai#define QS_TYPE_NBSTAT 0x0021 41636321Samurai#define QS_CLAS_IN 0x0001 41736321Samuraitypedef struct { 418127094Sdes u_short type; /* The type of Request */ 419127094Sdes u_short class; /* The class of Request */ 420127094Sdes} NBTNsQuestion; 42136321Samurai 422127094Sdesstatic u_char * 42341759SdillonAliasHandleQuestion( 42441759Sdillon u_short count, 425127094Sdes NBTNsQuestion * q, 42641759Sdillon char *pmax, 427127094Sdes NBTArguments * nbtarg) 42836321Samurai{ 42936321Samurai 430131614Sdes (void)nbtarg; 431131614Sdes 432127094Sdes while (count != 0) { 43336321Samurai /* Name Filed */ 434127094Sdes q = (NBTNsQuestion *) AliasHandleName((u_char *) q, pmax); 43536321Samurai 43641759Sdillon if (q == NULL || (char *)(q + 1) > pmax) { 43741759Sdillon q = NULL; 43841759Sdillon break; 43941759Sdillon } 44036321Samurai /* Type and Class filed */ 441127094Sdes switch (ntohs(q->type)) { 442127094Sdes case QS_TYPE_NB: 443127094Sdes case QS_TYPE_NBSTAT: 444127094Sdes q = q + 1; 44536321Samurai break; 446127094Sdes default: 447145961Sglebius#ifdef LIBALIAS_DEBUG 448127094Sdes printf("\nUnknown Type on Question %0x\n", ntohs(q->type)); 44944616Sbrian#endif 45036321Samurai break; 45136321Samurai } 45236321Samurai count--; 45336321Samurai } 45436321Samurai 45536321Samurai /* Set up to out of Question Section */ 456127094Sdes return ((u_char *) q); 45736321Samurai} 45836321Samurai 45936321Samurai/* Resource Record */ 46036321Samurai#define RR_TYPE_A 0x0001 46136321Samurai#define RR_TYPE_NS 0x0002 46236321Samurai#define RR_TYPE_NULL 0x000a 46336321Samurai#define RR_TYPE_NB 0x0020 46436321Samurai#define RR_TYPE_NBSTAT 0x0021 46536321Samurai#define RR_CLAS_IN 0x0001 46636321Samurai#define SizeOfNsResource 8 46736321Samuraitypedef struct { 468127094Sdes u_short type; 469127094Sdes u_short class; 470127094Sdes unsigned int ttl; 471127094Sdes u_short rdlen; 472127094Sdes} NBTNsResource; 47336321Samurai 47436321Samurai#define SizeOfNsRNB 6 47536321Samuraitypedef struct { 476127094Sdes u_short g: 1 , ont:2, resv:13; 477127094Sdes struct in_addr addr; 478127094Sdes} NBTNsRNB; 47936321Samurai 480127094Sdesstatic u_char * 48199207SbrianAliasHandleResourceNB( 482127094Sdes NBTNsResource * q, 48399207Sbrian char *pmax, 484127094Sdes NBTArguments * nbtarg) 48536321Samurai{ 486127094Sdes NBTNsRNB *nb; 48736321Samurai u_short bcount; 488315456Svangyzen#ifdef LIBALIAS_DEBUG 489315456Svangyzen char oldbuf[INET_ADDRSTRLEN]; 490315456Svangyzen char newbuf[INET_ADDRSTRLEN]; 491315456Svangyzen#endif 49236321Samurai 49341759Sdillon if (q == NULL || (char *)(q + 1) > pmax) 494127094Sdes return (NULL); 49536321Samurai /* Check out a length */ 49636321Samurai bcount = ntohs(q->rdlen); 49736321Samurai 49836321Samurai /* Forward to Resource NB position */ 499127094Sdes nb = (NBTNsRNB *) ((u_char *) q + SizeOfNsResource); 50036321Samurai 50136321Samurai /* Processing all in_addr array */ 502145961Sglebius#ifdef LIBALIAS_DEBUG 503315456Svangyzen printf("NB rec[%s->%s, %dbytes] ", 504315456Svangyzen inet_ntoa_r(nbtarg->oldaddr, INET_NTOA_BUF(oldbuf)), 505315456Svangyzen inet_ntoa_r(nbtarg->newaddr, INET_NTOA_BUF(newbuf)), 506315456Svangyzen bcount); 50736321Samurai#endif 508127094Sdes while (nb != NULL && bcount != 0) { 50941759Sdillon if ((char *)(nb + 1) > pmax) { 51041759Sdillon nb = NULL; 51141759Sdillon break; 51241759Sdillon } 513145961Sglebius#ifdef LIBALIAS_DEBUG 514315456Svangyzen printf("<%s>", inet_ntoa_r(nb->addr, INET_NTOA_BUF(newbuf))); 51536321Samurai#endif 516127094Sdes if (!bcmp(&nbtarg->oldaddr, &nb->addr, sizeof(struct in_addr))) { 517127094Sdes if (*nbtarg->uh_sum != 0) { 518127094Sdes int acc; 519127094Sdes u_short *sptr; 52036321Samurai 521127094Sdes sptr = (u_short *) & (nb->addr); 522127094Sdes acc = *sptr++; 523127094Sdes acc += *sptr; 524127094Sdes sptr = (u_short *) & (nbtarg->newaddr); 525127094Sdes acc -= *sptr++; 526127094Sdes acc -= *sptr; 527127094Sdes ADJUST_CHECKSUM(acc, *nbtarg->uh_sum); 52836321Samurai } 52936321Samurai nb->addr = nbtarg->newaddr; 530145961Sglebius#ifdef LIBALIAS_DEBUG 53136321Samurai printf("O"); 53236321Samurai#endif 53336321Samurai } 534145961Sglebius#ifdef LIBALIAS_DEBUG 535127094Sdes else { 53636321Samurai printf("."); 53736321Samurai } 53836321Samurai#endif 539127094Sdes nb = (NBTNsRNB *) ((u_char *) nb + SizeOfNsRNB); 540127094Sdes bcount -= SizeOfNsRNB; 54136321Samurai } 54241759Sdillon if (nb == NULL || (char *)(nb + 1) > pmax) { 54341759Sdillon nb = NULL; 54441759Sdillon } 545127094Sdes return ((u_char *) nb); 54636321Samurai} 54736321Samurai 54836321Samurai#define SizeOfResourceA 6 54936321Samuraitypedef struct { 550127094Sdes struct in_addr addr; 551127094Sdes} NBTNsResourceA; 55236321Samurai 553127094Sdesstatic u_char * 55499207SbrianAliasHandleResourceA( 555127094Sdes NBTNsResource * q, 55641759Sdillon char *pmax, 557127094Sdes NBTArguments * nbtarg) 55836321Samurai{ 559127094Sdes NBTNsResourceA *a; 56036321Samurai u_short bcount; 561315456Svangyzen#ifdef LIBALIAS_DEBUG 562315456Svangyzen char oldbuf[INET_ADDRSTRLEN]; 563315456Svangyzen char newbuf[INET_ADDRSTRLEN]; 564315456Svangyzen#endif 56536321Samurai 56641759Sdillon if (q == NULL || (char *)(q + 1) > pmax) 567127094Sdes return (NULL); 56841759Sdillon 56936321Samurai /* Forward to Resource A position */ 570127094Sdes a = (NBTNsResourceA *) ((u_char *) q + sizeof(NBTNsResource)); 57136321Samurai 57236321Samurai /* Check out of length */ 57336321Samurai bcount = ntohs(q->rdlen); 57436321Samurai 57536321Samurai /* Processing all in_addr array */ 576145961Sglebius#ifdef LIBALIAS_DEBUG 577315456Svangyzen printf("Arec [%s->%s]", 578315456Svangyzen inet_ntoa_r(nbtarg->oldaddr, INET_NTOA_BUF(oldbuf)), 579315456Svangyzen inet_ntoa_r(nbtarg->newaddr, INET_NTOA_BUF(newbuf))); 58036321Samurai#endif 581127094Sdes while (bcount != 0) { 58241759Sdillon if (a == NULL || (char *)(a + 1) > pmax) 583127094Sdes return (NULL); 584145961Sglebius#ifdef LIBALIAS_DEBUG 585315456Svangyzen printf("..%s", inet_ntoa_r(a->addr, INET_NTOA_BUF(newbuf))); 58636321Samurai#endif 587127094Sdes if (!bcmp(&nbtarg->oldaddr, &a->addr, sizeof(struct in_addr))) { 588127094Sdes if (*nbtarg->uh_sum != 0) { 589127094Sdes int acc; 590127094Sdes u_short *sptr; 59136321Samurai 592127094Sdes sptr = (u_short *) & (a->addr); /* Old */ 593127094Sdes acc = *sptr++; 594127094Sdes acc += *sptr; 595127094Sdes sptr = (u_short *) & nbtarg->newaddr; /* New */ 596127094Sdes acc -= *sptr++; 597127094Sdes acc -= *sptr; 598127094Sdes ADJUST_CHECKSUM(acc, *nbtarg->uh_sum); 59936321Samurai } 60036321Samurai a->addr = nbtarg->newaddr; 60136321Samurai } 602127094Sdes a++; /* XXXX */ 60336321Samurai bcount -= SizeOfResourceA; 60436321Samurai } 60541759Sdillon if (a == NULL || (char *)(a + 1) > pmax) 606127094Sdes a = NULL; 607127094Sdes return ((u_char *) a); 60836321Samurai} 60936321Samurai 61036321Samuraitypedef struct { 611127094Sdes u_short opcode:4, flags:8, resv:4; 612127094Sdes} NBTNsResourceNULL; 61336321Samurai 614127094Sdesstatic u_char * 61599207SbrianAliasHandleResourceNULL( 616127094Sdes NBTNsResource * q, 61741759Sdillon char *pmax, 618127094Sdes NBTArguments * nbtarg) 61936321Samurai{ 620127094Sdes NBTNsResourceNULL *n; 62136321Samurai u_short bcount; 62236321Samurai 623131614Sdes (void)nbtarg; 624131614Sdes 62541759Sdillon if (q == NULL || (char *)(q + 1) > pmax) 626127094Sdes return (NULL); 62741759Sdillon 62836321Samurai /* Forward to Resource NULL position */ 629127094Sdes n = (NBTNsResourceNULL *) ((u_char *) q + sizeof(NBTNsResource)); 63036321Samurai 63136321Samurai /* Check out of length */ 63236321Samurai bcount = ntohs(q->rdlen); 63336321Samurai 63436321Samurai /* Processing all in_addr array */ 635127094Sdes while (bcount != 0) { 63641759Sdillon if ((char *)(n + 1) > pmax) { 63741759Sdillon n = NULL; 63841759Sdillon break; 63941759Sdillon } 64036321Samurai n++; 64136321Samurai bcount -= sizeof(NBTNsResourceNULL); 64236321Samurai } 64341759Sdillon if ((char *)(n + 1) > pmax) 64441759Sdillon n = NULL; 64536321Samurai 646127094Sdes return ((u_char *) n); 64736321Samurai} 64836321Samurai 649127094Sdesstatic u_char * 65099207SbrianAliasHandleResourceNS( 651127094Sdes NBTNsResource * q, 65241759Sdillon char *pmax, 653127094Sdes NBTArguments * nbtarg) 65436321Samurai{ 655127094Sdes NBTNsResourceNULL *n; 65636321Samurai u_short bcount; 65736321Samurai 658131614Sdes (void)nbtarg; 659131614Sdes 66041759Sdillon if (q == NULL || (char *)(q + 1) > pmax) 661127094Sdes return (NULL); 66241759Sdillon 66336321Samurai /* Forward to Resource NULL position */ 664127094Sdes n = (NBTNsResourceNULL *) ((u_char *) q + sizeof(NBTNsResource)); 66536321Samurai 66636321Samurai /* Check out of length */ 66736321Samurai bcount = ntohs(q->rdlen); 66836321Samurai 66936321Samurai /* Resource Record Name Filed */ 670127094Sdes q = (NBTNsResource *) AliasHandleName((u_char *) n, pmax); /* XXX */ 67136321Samurai 672127094Sdes if (q == NULL || (char *)((u_char *) n + bcount) > pmax) 673127094Sdes return (NULL); 67441759Sdillon else 675127094Sdes return ((u_char *) n + bcount); 67636321Samurai} 67736321Samurai 67836321Samuraitypedef struct { 679127094Sdes u_short numnames; 680127094Sdes} NBTNsResourceNBSTAT; 68136321Samurai 682127094Sdesstatic u_char * 68341759SdillonAliasHandleResourceNBSTAT( 684127094Sdes NBTNsResource * q, 68541759Sdillon char *pmax, 686127094Sdes NBTArguments * nbtarg) 68736321Samurai{ 688127094Sdes NBTNsResourceNBSTAT *n; 68936321Samurai u_short bcount; 69036321Samurai 691131614Sdes (void)nbtarg; 692131614Sdes 69341759Sdillon if (q == NULL || (char *)(q + 1) > pmax) 694127094Sdes return (NULL); 69541759Sdillon 69636321Samurai /* Forward to Resource NBSTAT position */ 697127094Sdes n = (NBTNsResourceNBSTAT *) ((u_char *) q + sizeof(NBTNsResource)); 69836321Samurai 69936321Samurai /* Check out of length */ 70036321Samurai bcount = ntohs(q->rdlen); 70136321Samurai 702127094Sdes if (q == NULL || (char *)((u_char *) n + bcount) > pmax) 703127094Sdes return (NULL); 70441759Sdillon else 705127094Sdes return ((u_char *) n + bcount); 70636321Samurai} 70736321Samurai 708127094Sdesstatic u_char * 70941759SdillonAliasHandleResource( 71099207Sbrian u_short count, 711127094Sdes NBTNsResource * q, 71241759Sdillon char *pmax, 71399207Sbrian NBTArguments 714127094Sdes * nbtarg) 71536321Samurai{ 716127094Sdes while (count != 0) { 71736321Samurai /* Resource Record Name Filed */ 718127094Sdes q = (NBTNsResource *) AliasHandleName((u_char *) q, pmax); 71941759Sdillon 72041759Sdillon if (q == NULL || (char *)(q + 1) > pmax) 72141759Sdillon break; 722145961Sglebius#ifdef LIBALIAS_DEBUG 723127094Sdes printf("type=%02x, count=%d\n", ntohs(q->type), count); 72436321Samurai#endif 72536321Samurai 72636321Samurai /* Type and Class filed */ 727127094Sdes switch (ntohs(q->type)) { 728127094Sdes case RR_TYPE_NB: 729127094Sdes q = (NBTNsResource *) AliasHandleResourceNB( 730127094Sdes q, 731127094Sdes pmax, 732127094Sdes nbtarg 733127094Sdes ); 734127094Sdes break; 735127094Sdes case RR_TYPE_A: 736127094Sdes q = (NBTNsResource *) AliasHandleResourceA( 737127094Sdes q, 738127094Sdes pmax, 739127094Sdes nbtarg 740127094Sdes ); 741127094Sdes break; 742127094Sdes case RR_TYPE_NS: 743127094Sdes q = (NBTNsResource *) AliasHandleResourceNS( 744127094Sdes q, 745127094Sdes pmax, 746127094Sdes nbtarg 747127094Sdes ); 748127094Sdes break; 749127094Sdes case RR_TYPE_NULL: 750127094Sdes q = (NBTNsResource *) AliasHandleResourceNULL( 751127094Sdes q, 752127094Sdes pmax, 753127094Sdes nbtarg 754127094Sdes ); 755127094Sdes break; 756127094Sdes case RR_TYPE_NBSTAT: 757127094Sdes q = (NBTNsResource *) AliasHandleResourceNBSTAT( 758127094Sdes q, 759127094Sdes pmax, 760127094Sdes nbtarg 761127094Sdes ); 762127094Sdes break; 763127094Sdes default: 764145961Sglebius#ifdef LIBALIAS_DEBUG 765127094Sdes printf( 766127094Sdes "\nUnknown Type of Resource %0x\n", 767127094Sdes ntohs(q->type) 768127094Sdes ); 769145928Sglebius fflush(stdout); 77044616Sbrian#endif 771127094Sdes break; 77236321Samurai } 77336321Samurai count--; 77436321Samurai } 775127094Sdes return ((u_char *) q); 77636321Samurai} 77736321Samurai 778162674Spisostatic int 779127094SdesAliasHandleUdpNbtNS( 780127094Sdes struct libalias *la, 781127094Sdes struct ip *pip, /* IP packet to examine/patch */ 782131614Sdes struct alias_link *lnk, 783127094Sdes struct in_addr *alias_address, 784127094Sdes u_short * alias_port, 785127094Sdes struct in_addr *original_address, 786127094Sdes u_short * original_port) 78736321Samurai{ 788127094Sdes struct udphdr *uh; 789127094Sdes NbtNSHeader *nsh; 790127094Sdes u_char *p; 791127094Sdes char *pmax; 792127094Sdes NBTArguments nbtarg; 79336321Samurai 794131614Sdes (void)la; 795131614Sdes (void)lnk; 796131614Sdes 79799207Sbrian /* Set up Common Parameter */ 798127094Sdes nbtarg.oldaddr = *alias_address; 799127094Sdes nbtarg.oldport = *alias_port; 800127094Sdes nbtarg.newaddr = *original_address; 801127094Sdes nbtarg.newport = *original_port; 80236321Samurai 803127094Sdes /* Calculate data length of UDP packet */ 804131699Sdes uh = (struct udphdr *)ip_next(pip); 805127094Sdes nbtarg.uh_sum = &(uh->uh_sum); 806131699Sdes nsh = (NbtNSHeader *)udp_next(uh); 807127094Sdes p = (u_char *) (nsh + 1); 808127094Sdes pmax = (char *)uh + ntohs(uh->uh_ulen); 80936321Samurai 810127094Sdes if ((char *)(nsh + 1) > pmax) 811127094Sdes return (-1); 81241759Sdillon 813145961Sglebius#ifdef LIBALIAS_DEBUG 814127094Sdes printf(" [%s] ID=%02x, op=%01x, flag=%02x, rcode=%01x, qd=%04x" 815127094Sdes ", an=%04x, ns=%04x, ar=%04x, [%d]-->", 816127094Sdes nsh->dir ? "Response" : "Request", 817127094Sdes nsh->nametrid, 818127094Sdes nsh->opcode, 819127094Sdes nsh->nmflags, 820127094Sdes nsh->rcode, 821127094Sdes ntohs(nsh->qdcount), 822127094Sdes ntohs(nsh->ancount), 823127094Sdes ntohs(nsh->nscount), 824127094Sdes ntohs(nsh->arcount), 825127094Sdes (u_char *) p - (u_char *) nsh 826127094Sdes ); 82736321Samurai#endif 82836321Samurai 82936321Samurai /* Question Entries */ 830127094Sdes if (ntohs(nsh->qdcount) != 0) { 831127094Sdes p = AliasHandleQuestion( 832127094Sdes ntohs(nsh->qdcount), 833127094Sdes (NBTNsQuestion *) p, 834127094Sdes pmax, 835127094Sdes &nbtarg 836127094Sdes ); 83736321Samurai } 83836321Samurai /* Answer Resource Records */ 839127094Sdes if (ntohs(nsh->ancount) != 0) { 840127094Sdes p = AliasHandleResource( 841127094Sdes ntohs(nsh->ancount), 842127094Sdes (NBTNsResource *) p, 843127094Sdes pmax, 844127094Sdes &nbtarg 845127094Sdes ); 84636321Samurai } 84736321Samurai /* Authority Resource Recodrs */ 848127094Sdes if (ntohs(nsh->nscount) != 0) { 849127094Sdes p = AliasHandleResource( 850127094Sdes ntohs(nsh->nscount), 851127094Sdes (NBTNsResource *) p, 852127094Sdes pmax, 853127094Sdes &nbtarg 854127094Sdes ); 85536321Samurai } 85636321Samurai /* Additional Resource Recodrs */ 857127094Sdes if (ntohs(nsh->arcount) != 0) { 858127094Sdes p = AliasHandleResource( 859127094Sdes ntohs(nsh->arcount), 860127094Sdes (NBTNsResource *) p, 861127094Sdes pmax, 862127094Sdes &nbtarg 863127094Sdes ); 86436321Samurai } 865145961Sglebius#ifdef LIBALIAS_DEBUG 866127094Sdes PrintRcode(nsh->rcode); 86736321Samurai#endif 868127094Sdes return ((p == NULL) ? -1 : 0); 86936321Samurai} 870