alias_nbt.c revision 162674
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 162674 2006-09-26 23:26:53Z 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> 53145921Sglebius#endif 54145921Sglebius 5536321Samurai#include <netinet/in_systm.h> 5636321Samurai#include <netinet/in.h> 5736321Samurai#include <netinet/ip.h> 5836321Samurai#include <netinet/udp.h> 5936321Samurai 60145921Sglebius#ifdef _KERNEL 61145921Sglebius#include <netinet/libalias/alias_local.h> 62162674Spiso#include <netinet/libalias/alias_mod.h> 63145921Sglebius#else 6436321Samurai#include "alias_local.h" 65162674Spiso#include "alias_mod.h" 66145921Sglebius#endif 6736321Samurai 68162674Spiso#define NETBIOS_NS_PORT_NUMBER 137 69162674Spiso#define NETBIOS_DGM_PORT_NUMBER 138 70162674Spiso 71162674Spisostatic int 72162674SpisoAliasHandleUdpNbt(struct libalias *, struct ip *, struct alias_link *, 73162674Spiso struct in_addr *, u_short); 74162674Spiso 75162674Spisostatic int 76162674SpisoAliasHandleUdpNbtNS(struct libalias *, struct ip *, struct alias_link *, 77162674Spiso struct in_addr *, u_short *, struct in_addr *, u_short *); 78162674Spisostatic int 79162674Spisofingerprint1(struct libalias *la, struct ip *pip, struct alias_data *ah) 80162674Spiso{ 81162674Spiso 82162674Spiso if (ah->dport == NULL || ah->sport == NULL || ah->lnk == NULL || 83162674Spiso ah->aaddr == NULL || ah->aport == NULL) 84162674Spiso return (-1); 85162674Spiso if (ntohs(*ah->dport) == NETBIOS_DGM_PORT_NUMBER 86162674Spiso || ntohs(*ah->sport) == NETBIOS_DGM_PORT_NUMBER) 87162674Spiso return (0); 88162674Spiso return (-1); 89162674Spiso} 90162674Spiso 91162674Spisostatic int 92162674Spisoprotohandler1(struct libalias *la, struct ip *pip, struct alias_data *ah) 93162674Spiso{ 94162674Spiso 95162674Spiso AliasHandleUdpNbt(la, pip, ah->lnk, ah->aaddr, *ah->aport); 96162674Spiso return (0); 97162674Spiso} 98162674Spiso 99162674Spisostatic int 100162674Spisofingerprint2(struct libalias *la, struct ip *pip, struct alias_data *ah) 101162674Spiso{ 102162674Spiso 103162674Spiso 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 112162674Spisostatic 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 121162674Spisostatic int 122162674Spisoprotohandler2out(struct libalias *la, struct ip *pip, struct alias_data *ah) 123162674Spiso{ 124162674Spiso 125162674Spiso AliasHandleUdpNbtNS(la, pip, ah->lnk, &pip->ip_src, ah->sport, 126162674Spiso ah->aaddr, ah->aport); 127162674Spiso return (0); 128162674Spiso} 129162674Spiso 130162674Spiso/* Kernel module definition. */ 131162674Spisostruct proto_handler handlers[] = { 132162674Spiso { 133162674Spiso .pri = 130, 134162674Spiso .dir = IN|OUT, 135162674Spiso .proto = UDP, 136162674Spiso .fingerprint = &fingerprint1, 137162674Spiso .protohandler = &protohandler1 138162674Spiso }, 139162674Spiso { 140162674Spiso .pri = 140, 141162674Spiso .dir = IN, 142162674Spiso .proto = UDP, 143162674Spiso .fingerprint = &fingerprint2, 144162674Spiso .protohandler = &protohandler2in 145162674Spiso }, 146162674Spiso { 147162674Spiso .pri = 140, 148162674Spiso .dir = OUT, 149162674Spiso .proto = UDP, 150162674Spiso .fingerprint = &fingerprint2, 151162674Spiso .protohandler = &protohandler2out 152162674Spiso }, 153162674Spiso { EOH } 154162674Spiso}; 155162674Spiso 156162674Spisostatic int 157162674Spisomod_handler(module_t mod, int type, void *data) 158162674Spiso{ 159162674Spiso int error; 160162674Spiso 161162674Spiso switch (type) { 162162674Spiso case MOD_LOAD: 163162674Spiso error = 0; 164162674Spiso LibAliasAttachHandlers(handlers); 165162674Spiso break; 166162674Spiso case MOD_UNLOAD: 167162674Spiso error = 0; 168162674Spiso LibAliasDetachHandlers(handlers); 169162674Spiso break; 170162674Spiso default: 171162674Spiso error = EINVAL; 172162674Spiso } 173162674Spiso return (error); 174162674Spiso} 175162674Spiso 176162674Spiso#ifdef _KERNEL 177162674Spisostatic 178162674Spiso#endif 179162674Spisomoduledata_t alias_mod = { 180162674Spiso "alias_nbt", mod_handler, NULL 181162674Spiso}; 182162674Spiso 183162674Spiso#ifdef _KERNEL 184162674SpisoDECLARE_MODULE(alias_nbt, alias_mod, SI_SUB_DRIVERS, SI_ORDER_SECOND); 185162674SpisoMODULE_VERSION(alias_nbt, 1); 186162674SpisoMODULE_DEPEND(alias_nbt, libalias, 1, 1, 1); 187162674Spiso#endif 188162674Spiso 18936321Samuraitypedef struct { 190127094Sdes struct in_addr oldaddr; 191127094Sdes u_short oldport; 192127094Sdes struct in_addr newaddr; 193127094Sdes u_short newport; 194127094Sdes u_short *uh_sum; 195127094Sdes} NBTArguments; 19636321Samurai 19736321Samuraitypedef struct { 198127094Sdes unsigned char type; 199127094Sdes unsigned char flags; 200127094Sdes u_short id; 201127094Sdes struct in_addr source_ip; 202127094Sdes u_short source_port; 203127094Sdes u_short len; 204127094Sdes u_short offset; 205127094Sdes} NbtDataHeader; 20636321Samurai 20736321Samurai#define OpQuery 0 20836321Samurai#define OpUnknown 4 20936321Samurai#define OpRegist 5 21036321Samurai#define OpRelease 6 21136321Samurai#define OpWACK 7 21236321Samurai#define OpRefresh 8 21336321Samuraitypedef struct { 214127094Sdes u_short nametrid; 215127094Sdes u_short dir: 1, opcode:4, nmflags:7, rcode:4; 216127094Sdes u_short qdcount; 217127094Sdes u_short ancount; 218127094Sdes u_short nscount; 219127094Sdes u_short arcount; 220127094Sdes} NbtNSHeader; 22136321Samurai 22236321Samurai#define FMT_ERR 0x1 22336321Samurai#define SRV_ERR 0x2 22436321Samurai#define IMP_ERR 0x4 22536321Samurai#define RFS_ERR 0x5 22636321Samurai#define ACT_ERR 0x6 22736321Samurai#define CFT_ERR 0x7 22836321Samurai 22936321Samurai 230145961Sglebius#ifdef LIBALIAS_DEBUG 231127094Sdesstatic void 232127094SdesPrintRcode(u_char rcode) 233127094Sdes{ 23436321Samurai 23536321Samurai switch (rcode) { 23636321Samurai case FMT_ERR: 237127094Sdes printf("\nFormat Error."); 238127094Sdes case SRV_ERR: 239127094Sdes printf("\nSever failure."); 240127094Sdes case IMP_ERR: 241127094Sdes printf("\nUnsupported request error.\n"); 242127094Sdes case RFS_ERR: 243127094Sdes printf("\nRefused error.\n"); 244127094Sdes case ACT_ERR: 245127094Sdes printf("\nActive error.\n"); 246127094Sdes case CFT_ERR: 247127094Sdes printf("\nName in conflict error.\n"); 248127094Sdes default: 249127094Sdes printf("\n?%c?=%0x\n", '?', rcode); 25036321Samurai 25199207Sbrian } 25236321Samurai} 253127094Sdes 25444616Sbrian#endif 25536321Samurai 25636321Samurai 25736321Samurai/* Handling Name field */ 258127094Sdesstatic u_char * 259127094SdesAliasHandleName(u_char * p, char *pmax) 260127094Sdes{ 26136321Samurai 26236321Samurai u_char *s; 26336321Samurai u_char c; 264127094Sdes int compress; 26536321Samurai 26636321Samurai /* Following length field */ 26741759Sdillon 26841759Sdillon if (p == NULL || (char *)p >= pmax) 269127094Sdes return (NULL); 27041759Sdillon 271127094Sdes if (*p & 0xc0) { 27236321Samurai p = p + 2; 27341759Sdillon if ((char *)p > pmax) 274127094Sdes return (NULL); 275127094Sdes return ((u_char *) p); 27636321Samurai } 277127094Sdes while ((*p & 0x3f) != 0x00) { 27836321Samurai s = p + 1; 279127094Sdes if (*p == 0x20) 28036321Samurai compress = 1; 28136321Samurai else 28236321Samurai compress = 0; 28399207Sbrian 284127094Sdes /* Get next length field */ 285127094Sdes p = (u_char *) (p + (*p & 0x3f) + 1); 28641759Sdillon if ((char *)p > pmax) { 28741759Sdillon p = NULL; 28841759Sdillon break; 28941759Sdillon } 290145961Sglebius#ifdef LIBALIAS_DEBUG 29136321Samurai printf(":"); 29236321Samurai#endif 29336321Samurai while (s < p) { 294127094Sdes if (compress == 1) { 295127094Sdes c = (u_char) (((((*s & 0x0f) << 4) | (*(s + 1) & 0x0f)) - 0x11)); 296145961Sglebius#ifdef LIBALIAS_DEBUG 297127094Sdes if (isprint(c)) 298127094Sdes printf("%c", c); 29936321Samurai else 300127094Sdes printf("<0x%02x>", c); 30136321Samurai#endif 302127094Sdes s += 2; 30336321Samurai } else { 304145961Sglebius#ifdef LIBALIAS_DEBUG 30536321Samurai printf("%c", *s); 30636321Samurai#endif 30736321Samurai s++; 30836321Samurai } 30936321Samurai } 310145961Sglebius#ifdef LIBALIAS_DEBUG 31136321Samurai printf(":"); 312145928Sglebius fflush(stdout); 31336321Samurai#endif 314127094Sdes } 31536321Samurai 31636321Samurai /* Set up to out of Name field */ 31741759Sdillon if (p == NULL || (char *)p >= pmax) 318127094Sdes p = NULL; 31941759Sdillon else 320127094Sdes p++; 321127094Sdes return ((u_char *) p); 32236321Samurai} 32336321Samurai 32499207Sbrian/* 32536321Samurai * NetBios Datagram Handler (IP/UDP) 32636321Samurai */ 32736321Samurai#define DGM_DIRECT_UNIQ 0x10 32836321Samurai#define DGM_DIRECT_GROUP 0x11 32936321Samurai#define DGM_BROADCAST 0x12 33036321Samurai#define DGM_ERROR 0x13 33136321Samurai#define DGM_QUERY 0x14 33236321Samurai#define DGM_POSITIVE_RES 0x15 33336321Samurai#define DGM_NEGATIVE_RES 0x16 33436321Samurai 335162674Spisostatic int 336127094SdesAliasHandleUdpNbt( 337127094Sdes struct libalias *la, 338127094Sdes struct ip *pip, /* IP packet to examine/patch */ 339131614Sdes struct alias_link *lnk, 340127094Sdes struct in_addr *alias_address, 341127094Sdes u_short alias_port 342127094Sdes) 343127094Sdes{ 344127094Sdes struct udphdr *uh; 345127094Sdes NbtDataHeader *ndh; 346127094Sdes u_char *p = NULL; 347127094Sdes char *pmax; 34899207Sbrian 349131614Sdes (void)la; 350131614Sdes (void)lnk; 351131614Sdes 352127094Sdes /* Calculate data length of UDP packet */ 353131699Sdes uh = (struct udphdr *)ip_next(pip); 354127094Sdes pmax = (char *)uh + ntohs(uh->uh_ulen); 35541759Sdillon 356131699Sdes ndh = (NbtDataHeader *)udp_next(uh); 357127094Sdes if ((char *)(ndh + 1) > pmax) 358127094Sdes return (-1); 359145961Sglebius#ifdef LIBALIAS_DEBUG 360127094Sdes printf("\nType=%02x,", ndh->type); 36136321Samurai#endif 362127094Sdes switch (ndh->type) { 363127094Sdes case DGM_DIRECT_UNIQ: 364127094Sdes case DGM_DIRECT_GROUP: 365127094Sdes case DGM_BROADCAST: 366127094Sdes p = (u_char *) ndh + 14; 367127094Sdes p = AliasHandleName(p, pmax); /* Source Name */ 368127094Sdes p = AliasHandleName(p, pmax); /* Destination Name */ 369127094Sdes break; 370127094Sdes case DGM_ERROR: 371127094Sdes p = (u_char *) ndh + 11; 372127094Sdes break; 373127094Sdes case DGM_QUERY: 374127094Sdes case DGM_POSITIVE_RES: 375127094Sdes case DGM_NEGATIVE_RES: 376127094Sdes p = (u_char *) ndh + 10; 377127094Sdes p = AliasHandleName(p, pmax); /* Destination Name */ 378127094Sdes break; 37936321Samurai } 380127094Sdes if (p == NULL || (char *)p > pmax) 381127094Sdes p = NULL; 382145961Sglebius#ifdef LIBALIAS_DEBUG 383127094Sdes printf("%s:%d-->", inet_ntoa(ndh->source_ip), ntohs(ndh->source_port)); 38436321Samurai#endif 385108533Sschweikh /* Doing an IP address and Port number Translation */ 386127094Sdes if (uh->uh_sum != 0) { 387127094Sdes int acc; 388127094Sdes u_short *sptr; 389127094Sdes 390127094Sdes acc = ndh->source_port; 39136321Samurai acc -= alias_port; 392127094Sdes sptr = (u_short *) & (ndh->source_ip); 39336321Samurai acc += *sptr++; 39436321Samurai acc += *sptr; 39536321Samurai sptr = (u_short *) alias_address; 39636321Samurai acc -= *sptr++; 39736321Samurai acc -= *sptr; 39874778Sbrian ADJUST_CHECKSUM(acc, uh->uh_sum); 39936321Samurai } 400127094Sdes ndh->source_ip = *alias_address; 401127094Sdes ndh->source_port = alias_port; 402145961Sglebius#ifdef LIBALIAS_DEBUG 403127094Sdes printf("%s:%d\n", inet_ntoa(ndh->source_ip), ntohs(ndh->source_port)); 40436321Samurai fflush(stdout); 40536321Samurai#endif 406127094Sdes return ((p == NULL) ? -1 : 0); 40736321Samurai} 408127094Sdes 40936321Samurai/* Question Section */ 41036321Samurai#define QS_TYPE_NB 0x0020 41136321Samurai#define QS_TYPE_NBSTAT 0x0021 41236321Samurai#define QS_CLAS_IN 0x0001 41336321Samuraitypedef struct { 414127094Sdes u_short type; /* The type of Request */ 415127094Sdes u_short class; /* The class of Request */ 416127094Sdes} NBTNsQuestion; 41736321Samurai 418127094Sdesstatic u_char * 41941759SdillonAliasHandleQuestion( 42041759Sdillon u_short count, 421127094Sdes NBTNsQuestion * q, 42241759Sdillon char *pmax, 423127094Sdes NBTArguments * nbtarg) 42436321Samurai{ 42536321Samurai 426131614Sdes (void)nbtarg; 427131614Sdes 428127094Sdes while (count != 0) { 42936321Samurai /* Name Filed */ 430127094Sdes q = (NBTNsQuestion *) AliasHandleName((u_char *) q, pmax); 43136321Samurai 43241759Sdillon if (q == NULL || (char *)(q + 1) > pmax) { 43341759Sdillon q = NULL; 43441759Sdillon break; 43541759Sdillon } 43636321Samurai /* Type and Class filed */ 437127094Sdes switch (ntohs(q->type)) { 438127094Sdes case QS_TYPE_NB: 439127094Sdes case QS_TYPE_NBSTAT: 440127094Sdes q = q + 1; 44136321Samurai break; 442127094Sdes default: 443145961Sglebius#ifdef LIBALIAS_DEBUG 444127094Sdes printf("\nUnknown Type on Question %0x\n", ntohs(q->type)); 44544616Sbrian#endif 44636321Samurai break; 44736321Samurai } 44836321Samurai count--; 44936321Samurai } 45036321Samurai 45136321Samurai /* Set up to out of Question Section */ 452127094Sdes return ((u_char *) q); 45336321Samurai} 45436321Samurai 45536321Samurai/* Resource Record */ 45636321Samurai#define RR_TYPE_A 0x0001 45736321Samurai#define RR_TYPE_NS 0x0002 45836321Samurai#define RR_TYPE_NULL 0x000a 45936321Samurai#define RR_TYPE_NB 0x0020 46036321Samurai#define RR_TYPE_NBSTAT 0x0021 46136321Samurai#define RR_CLAS_IN 0x0001 46236321Samurai#define SizeOfNsResource 8 46336321Samuraitypedef struct { 464127094Sdes u_short type; 465127094Sdes u_short class; 466127094Sdes unsigned int ttl; 467127094Sdes u_short rdlen; 468127094Sdes} NBTNsResource; 46936321Samurai 47036321Samurai#define SizeOfNsRNB 6 47136321Samuraitypedef struct { 472127094Sdes u_short g: 1 , ont:2, resv:13; 473127094Sdes struct in_addr addr; 474127094Sdes} NBTNsRNB; 47536321Samurai 476127094Sdesstatic u_char * 47799207SbrianAliasHandleResourceNB( 478127094Sdes NBTNsResource * q, 47999207Sbrian char *pmax, 480127094Sdes NBTArguments * nbtarg) 48136321Samurai{ 482127094Sdes NBTNsRNB *nb; 48336321Samurai u_short bcount; 48436321Samurai 48541759Sdillon if (q == NULL || (char *)(q + 1) > pmax) 486127094Sdes return (NULL); 48736321Samurai /* Check out a length */ 48836321Samurai bcount = ntohs(q->rdlen); 48936321Samurai 49036321Samurai /* Forward to Resource NB position */ 491127094Sdes nb = (NBTNsRNB *) ((u_char *) q + SizeOfNsResource); 49236321Samurai 49336321Samurai /* Processing all in_addr array */ 494145961Sglebius#ifdef LIBALIAS_DEBUG 49536321Samurai printf("NB rec[%s", inet_ntoa(nbtarg->oldaddr)); 496127094Sdes printf("->%s, %dbytes] ", inet_ntoa(nbtarg->newaddr), bcount); 49736321Samurai#endif 498127094Sdes while (nb != NULL && bcount != 0) { 49941759Sdillon if ((char *)(nb + 1) > pmax) { 50041759Sdillon nb = NULL; 50141759Sdillon break; 50241759Sdillon } 503145961Sglebius#ifdef LIBALIAS_DEBUG 504127094Sdes printf("<%s>", inet_ntoa(nb->addr)); 50536321Samurai#endif 506127094Sdes if (!bcmp(&nbtarg->oldaddr, &nb->addr, sizeof(struct in_addr))) { 507127094Sdes if (*nbtarg->uh_sum != 0) { 508127094Sdes int acc; 509127094Sdes u_short *sptr; 51036321Samurai 511127094Sdes sptr = (u_short *) & (nb->addr); 512127094Sdes acc = *sptr++; 513127094Sdes acc += *sptr; 514127094Sdes sptr = (u_short *) & (nbtarg->newaddr); 515127094Sdes acc -= *sptr++; 516127094Sdes acc -= *sptr; 517127094Sdes ADJUST_CHECKSUM(acc, *nbtarg->uh_sum); 51836321Samurai } 51936321Samurai nb->addr = nbtarg->newaddr; 520145961Sglebius#ifdef LIBALIAS_DEBUG 52136321Samurai printf("O"); 52236321Samurai#endif 52336321Samurai } 524145961Sglebius#ifdef LIBALIAS_DEBUG 525127094Sdes else { 52636321Samurai printf("."); 52736321Samurai } 52836321Samurai#endif 529127094Sdes nb = (NBTNsRNB *) ((u_char *) nb + SizeOfNsRNB); 530127094Sdes bcount -= SizeOfNsRNB; 53136321Samurai } 53241759Sdillon if (nb == NULL || (char *)(nb + 1) > pmax) { 53341759Sdillon nb = NULL; 53441759Sdillon } 535127094Sdes return ((u_char *) nb); 53636321Samurai} 53736321Samurai 53836321Samurai#define SizeOfResourceA 6 53936321Samuraitypedef struct { 540127094Sdes struct in_addr addr; 541127094Sdes} NBTNsResourceA; 54236321Samurai 543127094Sdesstatic u_char * 54499207SbrianAliasHandleResourceA( 545127094Sdes NBTNsResource * q, 54641759Sdillon char *pmax, 547127094Sdes NBTArguments * nbtarg) 54836321Samurai{ 549127094Sdes NBTNsResourceA *a; 55036321Samurai u_short bcount; 55136321Samurai 55241759Sdillon if (q == NULL || (char *)(q + 1) > pmax) 553127094Sdes return (NULL); 55441759Sdillon 55536321Samurai /* Forward to Resource A position */ 556127094Sdes a = (NBTNsResourceA *) ((u_char *) q + sizeof(NBTNsResource)); 55736321Samurai 55836321Samurai /* Check out of length */ 55936321Samurai bcount = ntohs(q->rdlen); 56036321Samurai 56136321Samurai /* Processing all in_addr array */ 562145961Sglebius#ifdef LIBALIAS_DEBUG 56336321Samurai printf("Arec [%s", inet_ntoa(nbtarg->oldaddr)); 564127094Sdes printf("->%s]", inet_ntoa(nbtarg->newaddr)); 56536321Samurai#endif 566127094Sdes while (bcount != 0) { 56741759Sdillon if (a == NULL || (char *)(a + 1) > pmax) 568127094Sdes return (NULL); 569145961Sglebius#ifdef LIBALIAS_DEBUG 570127094Sdes printf("..%s", inet_ntoa(a->addr)); 57136321Samurai#endif 572127094Sdes if (!bcmp(&nbtarg->oldaddr, &a->addr, sizeof(struct in_addr))) { 573127094Sdes if (*nbtarg->uh_sum != 0) { 574127094Sdes int acc; 575127094Sdes u_short *sptr; 57636321Samurai 577127094Sdes sptr = (u_short *) & (a->addr); /* Old */ 578127094Sdes acc = *sptr++; 579127094Sdes acc += *sptr; 580127094Sdes sptr = (u_short *) & nbtarg->newaddr; /* New */ 581127094Sdes acc -= *sptr++; 582127094Sdes acc -= *sptr; 583127094Sdes ADJUST_CHECKSUM(acc, *nbtarg->uh_sum); 58436321Samurai } 58536321Samurai a->addr = nbtarg->newaddr; 58636321Samurai } 587127094Sdes a++; /* XXXX */ 58836321Samurai bcount -= SizeOfResourceA; 58936321Samurai } 59041759Sdillon if (a == NULL || (char *)(a + 1) > pmax) 591127094Sdes a = NULL; 592127094Sdes return ((u_char *) a); 59336321Samurai} 59436321Samurai 59536321Samuraitypedef struct { 596127094Sdes u_short opcode:4, flags:8, resv:4; 597127094Sdes} NBTNsResourceNULL; 59836321Samurai 599127094Sdesstatic u_char * 60099207SbrianAliasHandleResourceNULL( 601127094Sdes NBTNsResource * q, 60241759Sdillon char *pmax, 603127094Sdes NBTArguments * nbtarg) 60436321Samurai{ 605127094Sdes NBTNsResourceNULL *n; 60636321Samurai u_short bcount; 60736321Samurai 608131614Sdes (void)nbtarg; 609131614Sdes 61041759Sdillon if (q == NULL || (char *)(q + 1) > pmax) 611127094Sdes return (NULL); 61241759Sdillon 61336321Samurai /* Forward to Resource NULL position */ 614127094Sdes n = (NBTNsResourceNULL *) ((u_char *) q + sizeof(NBTNsResource)); 61536321Samurai 61636321Samurai /* Check out of length */ 61736321Samurai bcount = ntohs(q->rdlen); 61836321Samurai 61936321Samurai /* Processing all in_addr array */ 620127094Sdes while (bcount != 0) { 62141759Sdillon if ((char *)(n + 1) > pmax) { 62241759Sdillon n = NULL; 62341759Sdillon break; 62441759Sdillon } 62536321Samurai n++; 62636321Samurai bcount -= sizeof(NBTNsResourceNULL); 62736321Samurai } 62841759Sdillon if ((char *)(n + 1) > pmax) 62941759Sdillon n = NULL; 63036321Samurai 631127094Sdes return ((u_char *) n); 63236321Samurai} 63336321Samurai 634127094Sdesstatic u_char * 63599207SbrianAliasHandleResourceNS( 636127094Sdes NBTNsResource * q, 63741759Sdillon char *pmax, 638127094Sdes NBTArguments * nbtarg) 63936321Samurai{ 640127094Sdes NBTNsResourceNULL *n; 64136321Samurai u_short bcount; 64236321Samurai 643131614Sdes (void)nbtarg; 644131614Sdes 64541759Sdillon if (q == NULL || (char *)(q + 1) > pmax) 646127094Sdes return (NULL); 64741759Sdillon 64836321Samurai /* Forward to Resource NULL position */ 649127094Sdes n = (NBTNsResourceNULL *) ((u_char *) q + sizeof(NBTNsResource)); 65036321Samurai 65136321Samurai /* Check out of length */ 65236321Samurai bcount = ntohs(q->rdlen); 65336321Samurai 65436321Samurai /* Resource Record Name Filed */ 655127094Sdes q = (NBTNsResource *) AliasHandleName((u_char *) n, pmax); /* XXX */ 65636321Samurai 657127094Sdes if (q == NULL || (char *)((u_char *) n + bcount) > pmax) 658127094Sdes return (NULL); 65941759Sdillon else 660127094Sdes return ((u_char *) n + bcount); 66136321Samurai} 66236321Samurai 66336321Samuraitypedef struct { 664127094Sdes u_short numnames; 665127094Sdes} NBTNsResourceNBSTAT; 66636321Samurai 667127094Sdesstatic u_char * 66841759SdillonAliasHandleResourceNBSTAT( 669127094Sdes NBTNsResource * q, 67041759Sdillon char *pmax, 671127094Sdes NBTArguments * nbtarg) 67236321Samurai{ 673127094Sdes NBTNsResourceNBSTAT *n; 67436321Samurai u_short bcount; 67536321Samurai 676131614Sdes (void)nbtarg; 677131614Sdes 67841759Sdillon if (q == NULL || (char *)(q + 1) > pmax) 679127094Sdes return (NULL); 68041759Sdillon 68136321Samurai /* Forward to Resource NBSTAT position */ 682127094Sdes n = (NBTNsResourceNBSTAT *) ((u_char *) q + sizeof(NBTNsResource)); 68336321Samurai 68436321Samurai /* Check out of length */ 68536321Samurai bcount = ntohs(q->rdlen); 68636321Samurai 687127094Sdes if (q == NULL || (char *)((u_char *) n + bcount) > pmax) 688127094Sdes return (NULL); 68941759Sdillon else 690127094Sdes return ((u_char *) n + bcount); 69136321Samurai} 69236321Samurai 693127094Sdesstatic u_char * 69441759SdillonAliasHandleResource( 69599207Sbrian u_short count, 696127094Sdes NBTNsResource * q, 69741759Sdillon char *pmax, 69899207Sbrian NBTArguments 699127094Sdes * nbtarg) 70036321Samurai{ 701127094Sdes while (count != 0) { 70236321Samurai /* Resource Record Name Filed */ 703127094Sdes q = (NBTNsResource *) AliasHandleName((u_char *) q, pmax); 70441759Sdillon 70541759Sdillon if (q == NULL || (char *)(q + 1) > pmax) 70641759Sdillon break; 707145961Sglebius#ifdef LIBALIAS_DEBUG 708127094Sdes printf("type=%02x, count=%d\n", ntohs(q->type), count); 70936321Samurai#endif 71036321Samurai 71136321Samurai /* Type and Class filed */ 712127094Sdes switch (ntohs(q->type)) { 713127094Sdes case RR_TYPE_NB: 714127094Sdes q = (NBTNsResource *) AliasHandleResourceNB( 715127094Sdes q, 716127094Sdes pmax, 717127094Sdes nbtarg 718127094Sdes ); 719127094Sdes break; 720127094Sdes case RR_TYPE_A: 721127094Sdes q = (NBTNsResource *) AliasHandleResourceA( 722127094Sdes q, 723127094Sdes pmax, 724127094Sdes nbtarg 725127094Sdes ); 726127094Sdes break; 727127094Sdes case RR_TYPE_NS: 728127094Sdes q = (NBTNsResource *) AliasHandleResourceNS( 729127094Sdes q, 730127094Sdes pmax, 731127094Sdes nbtarg 732127094Sdes ); 733127094Sdes break; 734127094Sdes case RR_TYPE_NULL: 735127094Sdes q = (NBTNsResource *) AliasHandleResourceNULL( 736127094Sdes q, 737127094Sdes pmax, 738127094Sdes nbtarg 739127094Sdes ); 740127094Sdes break; 741127094Sdes case RR_TYPE_NBSTAT: 742127094Sdes q = (NBTNsResource *) AliasHandleResourceNBSTAT( 743127094Sdes q, 744127094Sdes pmax, 745127094Sdes nbtarg 746127094Sdes ); 747127094Sdes break; 748127094Sdes default: 749145961Sglebius#ifdef LIBALIAS_DEBUG 750127094Sdes printf( 751127094Sdes "\nUnknown Type of Resource %0x\n", 752127094Sdes ntohs(q->type) 753127094Sdes ); 754145928Sglebius fflush(stdout); 75544616Sbrian#endif 756127094Sdes break; 75736321Samurai } 75836321Samurai count--; 75936321Samurai } 760127094Sdes return ((u_char *) q); 76136321Samurai} 76236321Samurai 763162674Spisostatic int 764127094SdesAliasHandleUdpNbtNS( 765127094Sdes struct libalias *la, 766127094Sdes struct ip *pip, /* IP packet to examine/patch */ 767131614Sdes struct alias_link *lnk, 768127094Sdes struct in_addr *alias_address, 769127094Sdes u_short * alias_port, 770127094Sdes struct in_addr *original_address, 771127094Sdes u_short * original_port) 77236321Samurai{ 773127094Sdes struct udphdr *uh; 774127094Sdes NbtNSHeader *nsh; 775127094Sdes u_char *p; 776127094Sdes char *pmax; 777127094Sdes NBTArguments nbtarg; 77836321Samurai 779131614Sdes (void)la; 780131614Sdes (void)lnk; 781131614Sdes 78299207Sbrian /* Set up Common Parameter */ 783127094Sdes nbtarg.oldaddr = *alias_address; 784127094Sdes nbtarg.oldport = *alias_port; 785127094Sdes nbtarg.newaddr = *original_address; 786127094Sdes nbtarg.newport = *original_port; 78736321Samurai 788127094Sdes /* Calculate data length of UDP packet */ 789131699Sdes uh = (struct udphdr *)ip_next(pip); 790127094Sdes nbtarg.uh_sum = &(uh->uh_sum); 791131699Sdes nsh = (NbtNSHeader *)udp_next(uh); 792127094Sdes p = (u_char *) (nsh + 1); 793127094Sdes pmax = (char *)uh + ntohs(uh->uh_ulen); 79436321Samurai 795127094Sdes if ((char *)(nsh + 1) > pmax) 796127094Sdes return (-1); 79741759Sdillon 798145961Sglebius#ifdef LIBALIAS_DEBUG 799127094Sdes printf(" [%s] ID=%02x, op=%01x, flag=%02x, rcode=%01x, qd=%04x" 800127094Sdes ", an=%04x, ns=%04x, ar=%04x, [%d]-->", 801127094Sdes nsh->dir ? "Response" : "Request", 802127094Sdes nsh->nametrid, 803127094Sdes nsh->opcode, 804127094Sdes nsh->nmflags, 805127094Sdes nsh->rcode, 806127094Sdes ntohs(nsh->qdcount), 807127094Sdes ntohs(nsh->ancount), 808127094Sdes ntohs(nsh->nscount), 809127094Sdes ntohs(nsh->arcount), 810127094Sdes (u_char *) p - (u_char *) nsh 811127094Sdes ); 81236321Samurai#endif 81336321Samurai 81436321Samurai /* Question Entries */ 815127094Sdes if (ntohs(nsh->qdcount) != 0) { 816127094Sdes p = AliasHandleQuestion( 817127094Sdes ntohs(nsh->qdcount), 818127094Sdes (NBTNsQuestion *) p, 819127094Sdes pmax, 820127094Sdes &nbtarg 821127094Sdes ); 82236321Samurai } 82336321Samurai /* Answer Resource Records */ 824127094Sdes if (ntohs(nsh->ancount) != 0) { 825127094Sdes p = AliasHandleResource( 826127094Sdes ntohs(nsh->ancount), 827127094Sdes (NBTNsResource *) p, 828127094Sdes pmax, 829127094Sdes &nbtarg 830127094Sdes ); 83136321Samurai } 83236321Samurai /* Authority Resource Recodrs */ 833127094Sdes if (ntohs(nsh->nscount) != 0) { 834127094Sdes p = AliasHandleResource( 835127094Sdes ntohs(nsh->nscount), 836127094Sdes (NBTNsResource *) p, 837127094Sdes pmax, 838127094Sdes &nbtarg 839127094Sdes ); 84036321Samurai } 84136321Samurai /* Additional Resource Recodrs */ 842127094Sdes if (ntohs(nsh->arcount) != 0) { 843127094Sdes p = AliasHandleResource( 844127094Sdes ntohs(nsh->arcount), 845127094Sdes (NBTNsResource *) p, 846127094Sdes pmax, 847127094Sdes &nbtarg 848127094Sdes ); 84936321Samurai } 850145961Sglebius#ifdef LIBALIAS_DEBUG 851127094Sdes PrintRcode(nsh->rcode); 85236321Samurai#endif 853127094Sdes return ((p == NULL) ? -1 : 0); 85436321Samurai} 855