alias_nbt.c revision 187304
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 187304 2009-01-15 19:35:23Z piso $"); 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 73162674SpisoAliasHandleUdpNbt(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 *); 79162674Spisostatic int 80162674Spisofingerprint1(struct libalias *la, struct ip *pip, struct alias_data *ah) 81162674Spiso{ 82162674Spiso 83162674Spiso 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 92162674Spisostatic int 93162674Spisoprotohandler1(struct libalias *la, struct ip *pip, struct alias_data *ah) 94162674Spiso{ 95162674Spiso 96162674Spiso AliasHandleUdpNbt(la, pip, ah->lnk, ah->aaddr, *ah->aport); 97162674Spiso return (0); 98162674Spiso} 99162674Spiso 100162674Spisostatic int 101162674Spisofingerprint2(struct libalias *la, struct ip *pip, struct alias_data *ah) 102162674Spiso{ 103162674Spiso 104162674Spiso if (ah->dport == NULL || ah->sport == NULL || ah->lnk == NULL || 105162674Spiso ah->aaddr == NULL || ah->aport == NULL) 106162674Spiso return (-1); 107162674Spiso if (ntohs(*ah->dport) == NETBIOS_NS_PORT_NUMBER 108162674Spiso || ntohs(*ah->sport) == NETBIOS_NS_PORT_NUMBER) 109162674Spiso return (0); 110162674Spiso return (-1); 111162674Spiso} 112162674Spiso 113162674Spisostatic int 114162674Spisoprotohandler2in(struct libalias *la, struct ip *pip, struct alias_data *ah) 115162674Spiso{ 116162674Spiso 117162674Spiso AliasHandleUdpNbtNS(la, pip, ah->lnk, ah->aaddr, ah->aport, 118162674Spiso ah->oaddr, ah->dport); 119162674Spiso return (0); 120162674Spiso} 121162674Spiso 122162674Spisostatic int 123162674Spisoprotohandler2out(struct libalias *la, struct ip *pip, struct alias_data *ah) 124162674Spiso{ 125162674Spiso 126162674Spiso AliasHandleUdpNbtNS(la, pip, ah->lnk, &pip->ip_src, ah->sport, 127162674Spiso ah->aaddr, ah->aport); 128162674Spiso return (0); 129162674Spiso} 130162674Spiso 131162674Spiso/* Kernel module definition. */ 132162674Spisostruct proto_handler handlers[] = { 133162674Spiso { 134162674Spiso .pri = 130, 135162674Spiso .dir = IN|OUT, 136162674Spiso .proto = UDP, 137162674Spiso .fingerprint = &fingerprint1, 138162674Spiso .protohandler = &protohandler1 139162674Spiso }, 140162674Spiso { 141162674Spiso .pri = 140, 142162674Spiso .dir = IN, 143162674Spiso .proto = UDP, 144162674Spiso .fingerprint = &fingerprint2, 145162674Spiso .protohandler = &protohandler2in 146162674Spiso }, 147162674Spiso { 148162674Spiso .pri = 140, 149162674Spiso .dir = OUT, 150162674Spiso .proto = UDP, 151162674Spiso .fingerprint = &fingerprint2, 152162674Spiso .protohandler = &protohandler2out 153162674Spiso }, 154162674Spiso { EOH } 155162674Spiso}; 156162674Spiso 157162674Spisostatic int 158162674Spisomod_handler(module_t mod, int type, void *data) 159162674Spiso{ 160162674Spiso int error; 161162674Spiso 162162674Spiso switch (type) { 163162674Spiso case MOD_LOAD: 164162674Spiso error = 0; 165162674Spiso LibAliasAttachHandlers(handlers); 166162674Spiso break; 167162674Spiso case MOD_UNLOAD: 168162674Spiso error = 0; 169162674Spiso LibAliasDetachHandlers(handlers); 170162674Spiso break; 171162674Spiso default: 172162674Spiso error = EINVAL; 173162674Spiso } 174162674Spiso return (error); 175162674Spiso} 176162674Spiso 177162674Spiso#ifdef _KERNEL 178162674Spisostatic 179162674Spiso#endif 180162674Spisomoduledata_t alias_mod = { 181162674Spiso "alias_nbt", mod_handler, NULL 182162674Spiso}; 183162674Spiso 184162674Spiso#ifdef _KERNEL 185162674SpisoDECLARE_MODULE(alias_nbt, alias_mod, SI_SUB_DRIVERS, SI_ORDER_SECOND); 186162674SpisoMODULE_VERSION(alias_nbt, 1); 187162674SpisoMODULE_DEPEND(alias_nbt, libalias, 1, 1, 1); 188162674Spiso#endif 189162674Spiso 19036321Samuraitypedef struct { 191127094Sdes struct in_addr oldaddr; 192127094Sdes u_short oldport; 193127094Sdes struct in_addr newaddr; 194127094Sdes u_short newport; 195127094Sdes u_short *uh_sum; 196127094Sdes} NBTArguments; 19736321Samurai 19836321Samuraitypedef struct { 199127094Sdes unsigned char type; 200127094Sdes unsigned char flags; 201127094Sdes u_short id; 202127094Sdes struct in_addr source_ip; 203127094Sdes u_short source_port; 204127094Sdes u_short len; 205127094Sdes u_short offset; 206127094Sdes} NbtDataHeader; 20736321Samurai 20836321Samurai#define OpQuery 0 20936321Samurai#define OpUnknown 4 21036321Samurai#define OpRegist 5 21136321Samurai#define OpRelease 6 21236321Samurai#define OpWACK 7 21336321Samurai#define OpRefresh 8 21436321Samuraitypedef struct { 215127094Sdes u_short nametrid; 216127094Sdes u_short dir: 1, opcode:4, nmflags:7, rcode:4; 217127094Sdes u_short qdcount; 218127094Sdes u_short ancount; 219127094Sdes u_short nscount; 220127094Sdes u_short arcount; 221127094Sdes} NbtNSHeader; 22236321Samurai 22336321Samurai#define FMT_ERR 0x1 22436321Samurai#define SRV_ERR 0x2 22536321Samurai#define IMP_ERR 0x4 22636321Samurai#define RFS_ERR 0x5 22736321Samurai#define ACT_ERR 0x6 22836321Samurai#define CFT_ERR 0x7 22936321Samurai 23036321Samurai 231145961Sglebius#ifdef LIBALIAS_DEBUG 232127094Sdesstatic void 233127094SdesPrintRcode(u_char rcode) 234127094Sdes{ 23536321Samurai 23636321Samurai switch (rcode) { 23736321Samurai case FMT_ERR: 238127094Sdes printf("\nFormat Error."); 239127094Sdes case SRV_ERR: 240127094Sdes printf("\nSever failure."); 241127094Sdes case IMP_ERR: 242127094Sdes printf("\nUnsupported request error.\n"); 243127094Sdes case RFS_ERR: 244127094Sdes printf("\nRefused error.\n"); 245127094Sdes case ACT_ERR: 246127094Sdes printf("\nActive error.\n"); 247127094Sdes case CFT_ERR: 248127094Sdes printf("\nName in conflict error.\n"); 249127094Sdes default: 250127094Sdes printf("\n?%c?=%0x\n", '?', rcode); 25136321Samurai 25299207Sbrian } 25336321Samurai} 254127094Sdes 25544616Sbrian#endif 25636321Samurai 25736321Samurai 25836321Samurai/* Handling Name field */ 259127094Sdesstatic u_char * 260127094SdesAliasHandleName(u_char * p, char *pmax) 261127094Sdes{ 26236321Samurai 26336321Samurai u_char *s; 26436321Samurai u_char c; 265127094Sdes int compress; 26636321Samurai 26736321Samurai /* Following length field */ 26841759Sdillon 26941759Sdillon if (p == NULL || (char *)p >= pmax) 270127094Sdes return (NULL); 27141759Sdillon 272127094Sdes if (*p & 0xc0) { 27336321Samurai p = p + 2; 27441759Sdillon if ((char *)p > pmax) 275127094Sdes return (NULL); 276127094Sdes return ((u_char *) p); 27736321Samurai } 278127094Sdes while ((*p & 0x3f) != 0x00) { 27936321Samurai s = p + 1; 280127094Sdes if (*p == 0x20) 28136321Samurai compress = 1; 28236321Samurai else 28336321Samurai compress = 0; 28499207Sbrian 285127094Sdes /* Get next length field */ 286127094Sdes p = (u_char *) (p + (*p & 0x3f) + 1); 28741759Sdillon if ((char *)p > pmax) { 28841759Sdillon p = NULL; 28941759Sdillon break; 29041759Sdillon } 291145961Sglebius#ifdef LIBALIAS_DEBUG 29236321Samurai printf(":"); 29336321Samurai#endif 29436321Samurai while (s < p) { 295127094Sdes if (compress == 1) { 296127094Sdes c = (u_char) (((((*s & 0x0f) << 4) | (*(s + 1) & 0x0f)) - 0x11)); 297145961Sglebius#ifdef LIBALIAS_DEBUG 298127094Sdes if (isprint(c)) 299127094Sdes printf("%c", c); 30036321Samurai else 301127094Sdes printf("<0x%02x>", c); 30236321Samurai#endif 303127094Sdes s += 2; 30436321Samurai } else { 305145961Sglebius#ifdef LIBALIAS_DEBUG 30636321Samurai printf("%c", *s); 30736321Samurai#endif 30836321Samurai s++; 30936321Samurai } 31036321Samurai } 311145961Sglebius#ifdef LIBALIAS_DEBUG 31236321Samurai printf(":"); 313145928Sglebius fflush(stdout); 31436321Samurai#endif 315127094Sdes } 31636321Samurai 31736321Samurai /* Set up to out of Name field */ 31841759Sdillon if (p == NULL || (char *)p >= pmax) 319127094Sdes p = NULL; 32041759Sdillon else 321127094Sdes p++; 322127094Sdes return ((u_char *) p); 32336321Samurai} 32436321Samurai 32599207Sbrian/* 32636321Samurai * NetBios Datagram Handler (IP/UDP) 32736321Samurai */ 32836321Samurai#define DGM_DIRECT_UNIQ 0x10 32936321Samurai#define DGM_DIRECT_GROUP 0x11 33036321Samurai#define DGM_BROADCAST 0x12 33136321Samurai#define DGM_ERROR 0x13 33236321Samurai#define DGM_QUERY 0x14 33336321Samurai#define DGM_POSITIVE_RES 0x15 33436321Samurai#define DGM_NEGATIVE_RES 0x16 33536321Samurai 336162674Spisostatic int 337127094SdesAliasHandleUdpNbt( 338127094Sdes struct libalias *la, 339127094Sdes struct ip *pip, /* IP packet to examine/patch */ 340131614Sdes struct alias_link *lnk, 341127094Sdes struct in_addr *alias_address, 342127094Sdes u_short alias_port 343127094Sdes) 344127094Sdes{ 345127094Sdes struct udphdr *uh; 346127094Sdes NbtDataHeader *ndh; 347127094Sdes u_char *p = NULL; 348127094Sdes char *pmax; 34999207Sbrian 350131614Sdes (void)la; 351131614Sdes (void)lnk; 352131614Sdes 353127094Sdes /* Calculate data length of UDP packet */ 354131699Sdes uh = (struct udphdr *)ip_next(pip); 355127094Sdes pmax = (char *)uh + ntohs(uh->uh_ulen); 35641759Sdillon 357131699Sdes ndh = (NbtDataHeader *)udp_next(uh); 358127094Sdes if ((char *)(ndh + 1) > pmax) 359127094Sdes return (-1); 360145961Sglebius#ifdef LIBALIAS_DEBUG 361127094Sdes printf("\nType=%02x,", ndh->type); 36236321Samurai#endif 363127094Sdes switch (ndh->type) { 364127094Sdes case DGM_DIRECT_UNIQ: 365127094Sdes case DGM_DIRECT_GROUP: 366127094Sdes case DGM_BROADCAST: 367127094Sdes p = (u_char *) ndh + 14; 368127094Sdes p = AliasHandleName(p, pmax); /* Source Name */ 369127094Sdes p = AliasHandleName(p, pmax); /* Destination Name */ 370127094Sdes break; 371127094Sdes case DGM_ERROR: 372127094Sdes p = (u_char *) ndh + 11; 373127094Sdes break; 374127094Sdes case DGM_QUERY: 375127094Sdes case DGM_POSITIVE_RES: 376127094Sdes case DGM_NEGATIVE_RES: 377127094Sdes p = (u_char *) ndh + 10; 378127094Sdes p = AliasHandleName(p, pmax); /* Destination Name */ 379127094Sdes break; 38036321Samurai } 381127094Sdes if (p == NULL || (char *)p > pmax) 382127094Sdes p = NULL; 383145961Sglebius#ifdef LIBALIAS_DEBUG 384127094Sdes printf("%s:%d-->", inet_ntoa(ndh->source_ip), ntohs(ndh->source_port)); 38536321Samurai#endif 386108533Sschweikh /* Doing an IP address and Port number Translation */ 387127094Sdes if (uh->uh_sum != 0) { 388127094Sdes int acc; 389127094Sdes u_short *sptr; 390127094Sdes 391127094Sdes acc = ndh->source_port; 39236321Samurai acc -= alias_port; 393127094Sdes sptr = (u_short *) & (ndh->source_ip); 39436321Samurai acc += *sptr++; 39536321Samurai acc += *sptr; 39636321Samurai sptr = (u_short *) alias_address; 39736321Samurai acc -= *sptr++; 39836321Samurai acc -= *sptr; 39974778Sbrian ADJUST_CHECKSUM(acc, uh->uh_sum); 40036321Samurai } 401127094Sdes ndh->source_ip = *alias_address; 402127094Sdes ndh->source_port = alias_port; 403145961Sglebius#ifdef LIBALIAS_DEBUG 404127094Sdes printf("%s:%d\n", inet_ntoa(ndh->source_ip), ntohs(ndh->source_port)); 40536321Samurai fflush(stdout); 40636321Samurai#endif 407127094Sdes return ((p == NULL) ? -1 : 0); 40836321Samurai} 409127094Sdes 41036321Samurai/* Question Section */ 41136321Samurai#define QS_TYPE_NB 0x0020 41236321Samurai#define QS_TYPE_NBSTAT 0x0021 41336321Samurai#define QS_CLAS_IN 0x0001 41436321Samuraitypedef struct { 415127094Sdes u_short type; /* The type of Request */ 416127094Sdes u_short class; /* The class of Request */ 417127094Sdes} NBTNsQuestion; 41836321Samurai 419127094Sdesstatic u_char * 42041759SdillonAliasHandleQuestion( 42141759Sdillon u_short count, 422127094Sdes NBTNsQuestion * q, 42341759Sdillon char *pmax, 424127094Sdes NBTArguments * nbtarg) 42536321Samurai{ 42636321Samurai 427131614Sdes (void)nbtarg; 428131614Sdes 429127094Sdes while (count != 0) { 43036321Samurai /* Name Filed */ 431127094Sdes q = (NBTNsQuestion *) AliasHandleName((u_char *) q, pmax); 43236321Samurai 43341759Sdillon if (q == NULL || (char *)(q + 1) > pmax) { 43441759Sdillon q = NULL; 43541759Sdillon break; 43641759Sdillon } 43736321Samurai /* Type and Class filed */ 438127094Sdes switch (ntohs(q->type)) { 439127094Sdes case QS_TYPE_NB: 440127094Sdes case QS_TYPE_NBSTAT: 441127094Sdes q = q + 1; 44236321Samurai break; 443127094Sdes default: 444145961Sglebius#ifdef LIBALIAS_DEBUG 445127094Sdes printf("\nUnknown Type on Question %0x\n", ntohs(q->type)); 44644616Sbrian#endif 44736321Samurai break; 44836321Samurai } 44936321Samurai count--; 45036321Samurai } 45136321Samurai 45236321Samurai /* Set up to out of Question Section */ 453127094Sdes return ((u_char *) q); 45436321Samurai} 45536321Samurai 45636321Samurai/* Resource Record */ 45736321Samurai#define RR_TYPE_A 0x0001 45836321Samurai#define RR_TYPE_NS 0x0002 45936321Samurai#define RR_TYPE_NULL 0x000a 46036321Samurai#define RR_TYPE_NB 0x0020 46136321Samurai#define RR_TYPE_NBSTAT 0x0021 46236321Samurai#define RR_CLAS_IN 0x0001 46336321Samurai#define SizeOfNsResource 8 46436321Samuraitypedef struct { 465127094Sdes u_short type; 466127094Sdes u_short class; 467127094Sdes unsigned int ttl; 468127094Sdes u_short rdlen; 469127094Sdes} NBTNsResource; 47036321Samurai 47136321Samurai#define SizeOfNsRNB 6 47236321Samuraitypedef struct { 473127094Sdes u_short g: 1 , ont:2, resv:13; 474127094Sdes struct in_addr addr; 475127094Sdes} NBTNsRNB; 47636321Samurai 477127094Sdesstatic u_char * 47899207SbrianAliasHandleResourceNB( 479127094Sdes NBTNsResource * q, 48099207Sbrian char *pmax, 481127094Sdes NBTArguments * nbtarg) 48236321Samurai{ 483127094Sdes NBTNsRNB *nb; 48436321Samurai u_short bcount; 48536321Samurai 48641759Sdillon if (q == NULL || (char *)(q + 1) > pmax) 487127094Sdes return (NULL); 48836321Samurai /* Check out a length */ 48936321Samurai bcount = ntohs(q->rdlen); 49036321Samurai 49136321Samurai /* Forward to Resource NB position */ 492127094Sdes nb = (NBTNsRNB *) ((u_char *) q + SizeOfNsResource); 49336321Samurai 49436321Samurai /* Processing all in_addr array */ 495145961Sglebius#ifdef LIBALIAS_DEBUG 49636321Samurai printf("NB rec[%s", inet_ntoa(nbtarg->oldaddr)); 497127094Sdes printf("->%s, %dbytes] ", inet_ntoa(nbtarg->newaddr), bcount); 49836321Samurai#endif 499127094Sdes while (nb != NULL && bcount != 0) { 50041759Sdillon if ((char *)(nb + 1) > pmax) { 50141759Sdillon nb = NULL; 50241759Sdillon break; 50341759Sdillon } 504145961Sglebius#ifdef LIBALIAS_DEBUG 505127094Sdes printf("<%s>", inet_ntoa(nb->addr)); 50636321Samurai#endif 507127094Sdes if (!bcmp(&nbtarg->oldaddr, &nb->addr, sizeof(struct in_addr))) { 508127094Sdes if (*nbtarg->uh_sum != 0) { 509127094Sdes int acc; 510127094Sdes u_short *sptr; 51136321Samurai 512127094Sdes sptr = (u_short *) & (nb->addr); 513127094Sdes acc = *sptr++; 514127094Sdes acc += *sptr; 515127094Sdes sptr = (u_short *) & (nbtarg->newaddr); 516127094Sdes acc -= *sptr++; 517127094Sdes acc -= *sptr; 518127094Sdes ADJUST_CHECKSUM(acc, *nbtarg->uh_sum); 51936321Samurai } 52036321Samurai nb->addr = nbtarg->newaddr; 521145961Sglebius#ifdef LIBALIAS_DEBUG 52236321Samurai printf("O"); 52336321Samurai#endif 52436321Samurai } 525145961Sglebius#ifdef LIBALIAS_DEBUG 526127094Sdes else { 52736321Samurai printf("."); 52836321Samurai } 52936321Samurai#endif 530127094Sdes nb = (NBTNsRNB *) ((u_char *) nb + SizeOfNsRNB); 531127094Sdes bcount -= SizeOfNsRNB; 53236321Samurai } 53341759Sdillon if (nb == NULL || (char *)(nb + 1) > pmax) { 53441759Sdillon nb = NULL; 53541759Sdillon } 536127094Sdes return ((u_char *) nb); 53736321Samurai} 53836321Samurai 53936321Samurai#define SizeOfResourceA 6 54036321Samuraitypedef struct { 541127094Sdes struct in_addr addr; 542127094Sdes} NBTNsResourceA; 54336321Samurai 544127094Sdesstatic u_char * 54599207SbrianAliasHandleResourceA( 546127094Sdes NBTNsResource * q, 54741759Sdillon char *pmax, 548127094Sdes NBTArguments * nbtarg) 54936321Samurai{ 550127094Sdes NBTNsResourceA *a; 55136321Samurai u_short bcount; 55236321Samurai 55341759Sdillon if (q == NULL || (char *)(q + 1) > pmax) 554127094Sdes return (NULL); 55541759Sdillon 55636321Samurai /* Forward to Resource A position */ 557127094Sdes a = (NBTNsResourceA *) ((u_char *) q + sizeof(NBTNsResource)); 55836321Samurai 55936321Samurai /* Check out of length */ 56036321Samurai bcount = ntohs(q->rdlen); 56136321Samurai 56236321Samurai /* Processing all in_addr array */ 563145961Sglebius#ifdef LIBALIAS_DEBUG 56436321Samurai printf("Arec [%s", inet_ntoa(nbtarg->oldaddr)); 565127094Sdes printf("->%s]", inet_ntoa(nbtarg->newaddr)); 56636321Samurai#endif 567127094Sdes while (bcount != 0) { 56841759Sdillon if (a == NULL || (char *)(a + 1) > pmax) 569127094Sdes return (NULL); 570145961Sglebius#ifdef LIBALIAS_DEBUG 571127094Sdes printf("..%s", inet_ntoa(a->addr)); 57236321Samurai#endif 573127094Sdes if (!bcmp(&nbtarg->oldaddr, &a->addr, sizeof(struct in_addr))) { 574127094Sdes if (*nbtarg->uh_sum != 0) { 575127094Sdes int acc; 576127094Sdes u_short *sptr; 57736321Samurai 578127094Sdes sptr = (u_short *) & (a->addr); /* Old */ 579127094Sdes acc = *sptr++; 580127094Sdes acc += *sptr; 581127094Sdes sptr = (u_short *) & nbtarg->newaddr; /* New */ 582127094Sdes acc -= *sptr++; 583127094Sdes acc -= *sptr; 584127094Sdes ADJUST_CHECKSUM(acc, *nbtarg->uh_sum); 58536321Samurai } 58636321Samurai a->addr = nbtarg->newaddr; 58736321Samurai } 588127094Sdes a++; /* XXXX */ 58936321Samurai bcount -= SizeOfResourceA; 59036321Samurai } 59141759Sdillon if (a == NULL || (char *)(a + 1) > pmax) 592127094Sdes a = NULL; 593127094Sdes return ((u_char *) a); 59436321Samurai} 59536321Samurai 59636321Samuraitypedef struct { 597127094Sdes u_short opcode:4, flags:8, resv:4; 598127094Sdes} NBTNsResourceNULL; 59936321Samurai 600127094Sdesstatic u_char * 60199207SbrianAliasHandleResourceNULL( 602127094Sdes NBTNsResource * q, 60341759Sdillon char *pmax, 604127094Sdes NBTArguments * nbtarg) 60536321Samurai{ 606127094Sdes NBTNsResourceNULL *n; 60736321Samurai u_short bcount; 60836321Samurai 609131614Sdes (void)nbtarg; 610131614Sdes 61141759Sdillon if (q == NULL || (char *)(q + 1) > pmax) 612127094Sdes return (NULL); 61341759Sdillon 61436321Samurai /* Forward to Resource NULL position */ 615127094Sdes n = (NBTNsResourceNULL *) ((u_char *) q + sizeof(NBTNsResource)); 61636321Samurai 61736321Samurai /* Check out of length */ 61836321Samurai bcount = ntohs(q->rdlen); 61936321Samurai 62036321Samurai /* Processing all in_addr array */ 621127094Sdes while (bcount != 0) { 62241759Sdillon if ((char *)(n + 1) > pmax) { 62341759Sdillon n = NULL; 62441759Sdillon break; 62541759Sdillon } 62636321Samurai n++; 62736321Samurai bcount -= sizeof(NBTNsResourceNULL); 62836321Samurai } 62941759Sdillon if ((char *)(n + 1) > pmax) 63041759Sdillon n = NULL; 63136321Samurai 632127094Sdes return ((u_char *) n); 63336321Samurai} 63436321Samurai 635127094Sdesstatic u_char * 63699207SbrianAliasHandleResourceNS( 637127094Sdes NBTNsResource * q, 63841759Sdillon char *pmax, 639127094Sdes NBTArguments * nbtarg) 64036321Samurai{ 641127094Sdes NBTNsResourceNULL *n; 64236321Samurai u_short bcount; 64336321Samurai 644131614Sdes (void)nbtarg; 645131614Sdes 64641759Sdillon if (q == NULL || (char *)(q + 1) > pmax) 647127094Sdes return (NULL); 64841759Sdillon 64936321Samurai /* Forward to Resource NULL position */ 650127094Sdes n = (NBTNsResourceNULL *) ((u_char *) q + sizeof(NBTNsResource)); 65136321Samurai 65236321Samurai /* Check out of length */ 65336321Samurai bcount = ntohs(q->rdlen); 65436321Samurai 65536321Samurai /* Resource Record Name Filed */ 656127094Sdes q = (NBTNsResource *) AliasHandleName((u_char *) n, pmax); /* XXX */ 65736321Samurai 658127094Sdes if (q == NULL || (char *)((u_char *) n + bcount) > pmax) 659127094Sdes return (NULL); 66041759Sdillon else 661127094Sdes return ((u_char *) n + bcount); 66236321Samurai} 66336321Samurai 66436321Samuraitypedef struct { 665127094Sdes u_short numnames; 666127094Sdes} NBTNsResourceNBSTAT; 66736321Samurai 668127094Sdesstatic u_char * 66941759SdillonAliasHandleResourceNBSTAT( 670127094Sdes NBTNsResource * q, 67141759Sdillon char *pmax, 672127094Sdes NBTArguments * nbtarg) 67336321Samurai{ 674127094Sdes NBTNsResourceNBSTAT *n; 67536321Samurai u_short bcount; 67636321Samurai 677131614Sdes (void)nbtarg; 678131614Sdes 67941759Sdillon if (q == NULL || (char *)(q + 1) > pmax) 680127094Sdes return (NULL); 68141759Sdillon 68236321Samurai /* Forward to Resource NBSTAT position */ 683127094Sdes n = (NBTNsResourceNBSTAT *) ((u_char *) q + sizeof(NBTNsResource)); 68436321Samurai 68536321Samurai /* Check out of length */ 68636321Samurai bcount = ntohs(q->rdlen); 68736321Samurai 688127094Sdes if (q == NULL || (char *)((u_char *) n + bcount) > pmax) 689127094Sdes return (NULL); 69041759Sdillon else 691127094Sdes return ((u_char *) n + bcount); 69236321Samurai} 69336321Samurai 694127094Sdesstatic u_char * 69541759SdillonAliasHandleResource( 69699207Sbrian u_short count, 697127094Sdes NBTNsResource * q, 69841759Sdillon char *pmax, 69999207Sbrian NBTArguments 700127094Sdes * nbtarg) 70136321Samurai{ 702127094Sdes while (count != 0) { 70336321Samurai /* Resource Record Name Filed */ 704127094Sdes q = (NBTNsResource *) AliasHandleName((u_char *) q, pmax); 70541759Sdillon 70641759Sdillon if (q == NULL || (char *)(q + 1) > pmax) 70741759Sdillon break; 708145961Sglebius#ifdef LIBALIAS_DEBUG 709127094Sdes printf("type=%02x, count=%d\n", ntohs(q->type), count); 71036321Samurai#endif 71136321Samurai 71236321Samurai /* Type and Class filed */ 713127094Sdes switch (ntohs(q->type)) { 714127094Sdes case RR_TYPE_NB: 715127094Sdes q = (NBTNsResource *) AliasHandleResourceNB( 716127094Sdes q, 717127094Sdes pmax, 718127094Sdes nbtarg 719127094Sdes ); 720127094Sdes break; 721127094Sdes case RR_TYPE_A: 722127094Sdes q = (NBTNsResource *) AliasHandleResourceA( 723127094Sdes q, 724127094Sdes pmax, 725127094Sdes nbtarg 726127094Sdes ); 727127094Sdes break; 728127094Sdes case RR_TYPE_NS: 729127094Sdes q = (NBTNsResource *) AliasHandleResourceNS( 730127094Sdes q, 731127094Sdes pmax, 732127094Sdes nbtarg 733127094Sdes ); 734127094Sdes break; 735127094Sdes case RR_TYPE_NULL: 736127094Sdes q = (NBTNsResource *) AliasHandleResourceNULL( 737127094Sdes q, 738127094Sdes pmax, 739127094Sdes nbtarg 740127094Sdes ); 741127094Sdes break; 742127094Sdes case RR_TYPE_NBSTAT: 743127094Sdes q = (NBTNsResource *) AliasHandleResourceNBSTAT( 744127094Sdes q, 745127094Sdes pmax, 746127094Sdes nbtarg 747127094Sdes ); 748127094Sdes break; 749127094Sdes default: 750145961Sglebius#ifdef LIBALIAS_DEBUG 751127094Sdes printf( 752127094Sdes "\nUnknown Type of Resource %0x\n", 753127094Sdes ntohs(q->type) 754127094Sdes ); 755145928Sglebius fflush(stdout); 75644616Sbrian#endif 757127094Sdes break; 75836321Samurai } 75936321Samurai count--; 76036321Samurai } 761127094Sdes return ((u_char *) q); 76236321Samurai} 76336321Samurai 764162674Spisostatic int 765127094SdesAliasHandleUdpNbtNS( 766127094Sdes struct libalias *la, 767127094Sdes struct ip *pip, /* IP packet to examine/patch */ 768131614Sdes struct alias_link *lnk, 769127094Sdes struct in_addr *alias_address, 770127094Sdes u_short * alias_port, 771127094Sdes struct in_addr *original_address, 772127094Sdes u_short * original_port) 77336321Samurai{ 774127094Sdes struct udphdr *uh; 775127094Sdes NbtNSHeader *nsh; 776127094Sdes u_char *p; 777127094Sdes char *pmax; 778127094Sdes NBTArguments nbtarg; 77936321Samurai 780131614Sdes (void)la; 781131614Sdes (void)lnk; 782131614Sdes 78399207Sbrian /* Set up Common Parameter */ 784127094Sdes nbtarg.oldaddr = *alias_address; 785127094Sdes nbtarg.oldport = *alias_port; 786127094Sdes nbtarg.newaddr = *original_address; 787127094Sdes nbtarg.newport = *original_port; 78836321Samurai 789127094Sdes /* Calculate data length of UDP packet */ 790131699Sdes uh = (struct udphdr *)ip_next(pip); 791127094Sdes nbtarg.uh_sum = &(uh->uh_sum); 792131699Sdes nsh = (NbtNSHeader *)udp_next(uh); 793127094Sdes p = (u_char *) (nsh + 1); 794127094Sdes pmax = (char *)uh + ntohs(uh->uh_ulen); 79536321Samurai 796127094Sdes if ((char *)(nsh + 1) > pmax) 797127094Sdes return (-1); 79841759Sdillon 799145961Sglebius#ifdef LIBALIAS_DEBUG 800127094Sdes printf(" [%s] ID=%02x, op=%01x, flag=%02x, rcode=%01x, qd=%04x" 801127094Sdes ", an=%04x, ns=%04x, ar=%04x, [%d]-->", 802127094Sdes nsh->dir ? "Response" : "Request", 803127094Sdes nsh->nametrid, 804127094Sdes nsh->opcode, 805127094Sdes nsh->nmflags, 806127094Sdes nsh->rcode, 807127094Sdes ntohs(nsh->qdcount), 808127094Sdes ntohs(nsh->ancount), 809127094Sdes ntohs(nsh->nscount), 810127094Sdes ntohs(nsh->arcount), 811127094Sdes (u_char *) p - (u_char *) nsh 812127094Sdes ); 81336321Samurai#endif 81436321Samurai 81536321Samurai /* Question Entries */ 816127094Sdes if (ntohs(nsh->qdcount) != 0) { 817127094Sdes p = AliasHandleQuestion( 818127094Sdes ntohs(nsh->qdcount), 819127094Sdes (NBTNsQuestion *) p, 820127094Sdes pmax, 821127094Sdes &nbtarg 822127094Sdes ); 82336321Samurai } 82436321Samurai /* Answer Resource Records */ 825127094Sdes if (ntohs(nsh->ancount) != 0) { 826127094Sdes p = AliasHandleResource( 827127094Sdes ntohs(nsh->ancount), 828127094Sdes (NBTNsResource *) p, 829127094Sdes pmax, 830127094Sdes &nbtarg 831127094Sdes ); 83236321Samurai } 83336321Samurai /* Authority Resource Recodrs */ 834127094Sdes if (ntohs(nsh->nscount) != 0) { 835127094Sdes p = AliasHandleResource( 836127094Sdes ntohs(nsh->nscount), 837127094Sdes (NBTNsResource *) p, 838127094Sdes pmax, 839127094Sdes &nbtarg 840127094Sdes ); 84136321Samurai } 84236321Samurai /* Additional Resource Recodrs */ 843127094Sdes if (ntohs(nsh->arcount) != 0) { 844127094Sdes p = AliasHandleResource( 845127094Sdes ntohs(nsh->arcount), 846127094Sdes (NBTNsResource *) p, 847127094Sdes pmax, 848127094Sdes &nbtarg 849127094Sdes ); 85036321Samurai } 851145961Sglebius#ifdef LIBALIAS_DEBUG 852127094Sdes PrintRcode(nsh->rcode); 85336321Samurai#endif 854127094Sdes return ((p == NULL) ? -1 : 0); 85536321Samurai} 856