alias_nbt.c revision 296373
1254721Semaste/*- 2254721Semaste * Written by Atsushi Murai <amurai@spec.co.jp> 3254721Semaste * Copyright (c) 1998, System Planning and Engineering Co. 4254721Semaste * All rights reserved. 5254721Semaste * 6254721Semaste * Redistribution and use in source and binary forms, with or without 7254721Semaste * modification, are permitted provided that the following conditions 8254721Semaste * are met: 9254721Semaste * 1. Redistributions of source code must retain the above copyright 10254721Semaste * notice, this list of conditions and the following disclaimer. 11254721Semaste * 2. Redistributions in binary form must reproduce the above copyright 12254721Semaste * notice, this list of conditions and the following disclaimer in the 13254721Semaste * documentation and/or other materials provided with the distribution. 14254721Semaste * 15254721Semaste * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16254721Semaste * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17254721Semaste * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18254721Semaste * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19254721Semaste * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20254721Semaste * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21254721Semaste * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22254721Semaste * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23254721Semaste * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24254721Semaste * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25254721Semaste * SUCH DAMAGE. 26254721Semaste * TODO: 27254721Semaste * oClean up. 28254721Semaste * oConsidering for word alignment for other platform. 29254721Semaste */ 30254721Semaste 31254721Semaste#include <sys/cdefs.h> 32254721Semaste__FBSDID("$FreeBSD: releng/10.3/sys/netinet/libalias/alias_nbt.c 190938 2009-04-11 15:19:09Z piso $"); 33254721Semaste 34254721Semaste/* 35254721Semaste alias_nbt.c performs special processing for NetBios over TCP/IP 36254721Semaste sessions by UDP. 37254721Semaste 38254721Semaste Initial version: May, 1998 (Atsushi Murai <amurai@spec.co.jp>) 39254721Semaste 40254721Semaste See HISTORY file for record of revisions. 41254721Semaste*/ 42254721Semaste 43254721Semaste/* Includes */ 44254721Semaste#ifdef _KERNEL 45254721Semaste#include <sys/param.h> 46254721Semaste#include <sys/systm.h> 47254721Semaste#include <sys/kernel.h> 48254721Semaste#include <sys/module.h> 49254721Semaste#else 50254721Semaste#include <errno.h> 51254721Semaste#include <sys/types.h> 52254721Semaste#include <stdio.h> 53254721Semaste#include <strings.h> 54254721Semaste#endif 55254721Semaste 56254721Semaste#include <netinet/in_systm.h> 57254721Semaste#include <netinet/in.h> 58254721Semaste#include <netinet/ip.h> 59254721Semaste#include <netinet/udp.h> 60254721Semaste 61254721Semaste#ifdef _KERNEL 62254721Semaste#include <netinet/libalias/alias_local.h> 63254721Semaste#include <netinet/libalias/alias_mod.h> 64254721Semaste#else 65254721Semaste#include "alias_local.h" 66254721Semaste#include "alias_mod.h" 67254721Semaste#endif 68254721Semaste 69254721Semaste#define NETBIOS_NS_PORT_NUMBER 137 70254721Semaste#define NETBIOS_DGM_PORT_NUMBER 138 71254721Semaste 72254721Semastestatic int 73254721SemasteAliasHandleUdpNbt(struct libalias *, struct ip *, struct alias_link *, 74254721Semaste struct in_addr *, u_short); 75254721Semaste 76254721Semastestatic int 77254721SemasteAliasHandleUdpNbtNS(struct libalias *, struct ip *, struct alias_link *, 78254721Semaste struct in_addr *, u_short *, struct in_addr *, u_short *); 79254721Semastestatic int 80254721Semastefingerprint1(struct libalias *la, struct alias_data *ah) 81254721Semaste{ 82254721Semaste 83254721Semaste if (ah->dport == NULL || ah->sport == NULL || ah->lnk == NULL || 84254721Semaste ah->aaddr == NULL || ah->aport == NULL) 85254721Semaste return (-1); 86254721Semaste if (ntohs(*ah->dport) == NETBIOS_DGM_PORT_NUMBER 87254721Semaste || ntohs(*ah->sport) == NETBIOS_DGM_PORT_NUMBER) 88254721Semaste return (0); 89254721Semaste return (-1); 90254721Semaste} 91254721Semaste 92254721Semastestatic int 93254721Semasteprotohandler1(struct libalias *la, struct ip *pip, struct alias_data *ah) 94254721Semaste{ 95254721Semaste 96254721Semaste return (AliasHandleUdpNbt(la, pip, ah->lnk, ah->aaddr, *ah->aport)); 97254721Semaste} 98254721Semaste 99254721Semastestatic int 100254721Semastefingerprint2(struct libalias *la, struct alias_data *ah) 101254721Semaste{ 102254721Semaste 103254721Semaste if (ah->dport == NULL || ah->sport == NULL || ah->lnk == NULL || 104254721Semaste ah->aaddr == NULL || ah->aport == NULL) 105254721Semaste return (-1); 106254721Semaste if (ntohs(*ah->dport) == NETBIOS_NS_PORT_NUMBER 107254721Semaste || ntohs(*ah->sport) == NETBIOS_NS_PORT_NUMBER) 108254721Semaste return (0); 109254721Semaste return (-1); 110254721Semaste} 111254721Semaste 112254721Semastestatic int 113254721Semasteprotohandler2in(struct libalias *la, struct ip *pip, struct alias_data *ah) 114254721Semaste{ 115254721Semaste 116254721Semaste AliasHandleUdpNbtNS(la, pip, ah->lnk, ah->aaddr, ah->aport, 117254721Semaste ah->oaddr, ah->dport); 118254721Semaste return (0); 119254721Semaste} 120254721Semaste 121254721Semastestatic int 122254721Semasteprotohandler2out(struct libalias *la, struct ip *pip, struct alias_data *ah) 123254721Semaste{ 124254721Semaste 125254721Semaste return (AliasHandleUdpNbtNS(la, pip, ah->lnk, &pip->ip_src, ah->sport, 126254721Semaste ah->aaddr, ah->aport)); 127254721Semaste} 128254721Semaste 129254721Semaste/* Kernel module definition. */ 130254721Semastestruct proto_handler handlers[] = { 131254721Semaste { 132254721Semaste .pri = 130, 133254721Semaste .dir = IN|OUT, 134254721Semaste .proto = UDP, 135254721Semaste .fingerprint = &fingerprint1, 136254721Semaste .protohandler = &protohandler1 137254721Semaste }, 138254721Semaste { 139254721Semaste .pri = 140, 140254721Semaste .dir = IN, 141254721Semaste .proto = UDP, 142254721Semaste .fingerprint = &fingerprint2, 143254721Semaste .protohandler = &protohandler2in 144254721Semaste }, 145254721Semaste { 146254721Semaste .pri = 140, 147254721Semaste .dir = OUT, 148254721Semaste .proto = UDP, 149254721Semaste .fingerprint = &fingerprint2, 150254721Semaste .protohandler = &protohandler2out 151254721Semaste }, 152254721Semaste { EOH } 153254721Semaste}; 154254721Semaste 155254721Semastestatic int 156254721Semastemod_handler(module_t mod, int type, void *data) 157254721Semaste{ 158254721Semaste int error; 159254721Semaste 160254721Semaste switch (type) { 161254721Semaste case MOD_LOAD: 162254721Semaste error = 0; 163254721Semaste LibAliasAttachHandlers(handlers); 164254721Semaste break; 165254721Semaste case MOD_UNLOAD: 166254721Semaste error = 0; 167254721Semaste LibAliasDetachHandlers(handlers); 168254721Semaste break; 169254721Semaste default: 170254721Semaste error = EINVAL; 171254721Semaste } 172254721Semaste return (error); 173254721Semaste} 174254721Semaste 175254721Semaste#ifdef _KERNEL 176254721Semastestatic 177254721Semaste#endif 178254721Semastemoduledata_t alias_mod = { 179254721Semaste "alias_nbt", mod_handler, NULL 180254721Semaste}; 181254721Semaste 182254721Semaste#ifdef _KERNEL 183254721SemasteDECLARE_MODULE(alias_nbt, alias_mod, SI_SUB_DRIVERS, SI_ORDER_SECOND); 184254721SemasteMODULE_VERSION(alias_nbt, 1); 185254721SemasteMODULE_DEPEND(alias_nbt, libalias, 1, 1, 1); 186254721Semaste#endif 187254721Semaste 188254721Semastetypedef struct { 189254721Semaste struct in_addr oldaddr; 190254721Semaste u_short oldport; 191254721Semaste struct in_addr newaddr; 192254721Semaste u_short newport; 193254721Semaste u_short *uh_sum; 194254721Semaste} NBTArguments; 195254721Semaste 196254721Semastetypedef struct { 197254721Semaste unsigned char type; 198254721Semaste unsigned char flags; 199254721Semaste u_short id; 200254721Semaste struct in_addr source_ip; 201254721Semaste u_short source_port; 202254721Semaste u_short len; 203254721Semaste u_short offset; 204254721Semaste} NbtDataHeader; 205254721Semaste 206254721Semaste#define OpQuery 0 207254721Semaste#define OpUnknown 4 208254721Semaste#define OpRegist 5 209254721Semaste#define OpRelease 6 210254721Semaste#define OpWACK 7 211254721Semaste#define OpRefresh 8 212254721Semastetypedef struct { 213254721Semaste u_short nametrid; 214254721Semaste u_short dir: 1, opcode:4, nmflags:7, rcode:4; 215254721Semaste u_short qdcount; 216254721Semaste u_short ancount; 217254721Semaste u_short nscount; 218254721Semaste u_short arcount; 219254721Semaste} NbtNSHeader; 220254721Semaste 221254721Semaste#define FMT_ERR 0x1 222254721Semaste#define SRV_ERR 0x2 223254721Semaste#define IMP_ERR 0x4 224254721Semaste#define RFS_ERR 0x5 225254721Semaste#define ACT_ERR 0x6 226254721Semaste#define CFT_ERR 0x7 227254721Semaste 228254721Semaste 229254721Semaste#ifdef LIBALIAS_DEBUG 230254721Semastestatic void 231254721SemastePrintRcode(u_char rcode) 232254721Semaste{ 233254721Semaste 234254721Semaste switch (rcode) { 235254721Semaste case FMT_ERR: 236254721Semaste printf("\nFormat Error."); 237254721Semaste case SRV_ERR: 238254721Semaste printf("\nSever failure."); 239254721Semaste case IMP_ERR: 240254721Semaste printf("\nUnsupported request error.\n"); 241254721Semaste case RFS_ERR: 242254721Semaste printf("\nRefused error.\n"); 243254721Semaste case ACT_ERR: 244254721Semaste printf("\nActive error.\n"); 245254721Semaste case CFT_ERR: 246254721Semaste printf("\nName in conflict error.\n"); 247254721Semaste default: 248254721Semaste printf("\n?%c?=%0x\n", '?', rcode); 249254721Semaste 250254721Semaste } 251254721Semaste} 252254721Semaste 253254721Semaste#endif 254254721Semaste 255254721Semaste 256254721Semaste/* Handling Name field */ 257254721Semastestatic u_char * 258254721SemasteAliasHandleName(u_char * p, char *pmax) 259254721Semaste{ 260254721Semaste 261254721Semaste u_char *s; 262254721Semaste u_char c; 263254721Semaste int compress; 264254721Semaste 265254721Semaste /* Following length field */ 266254721Semaste 267254721Semaste if (p == NULL || (char *)p >= pmax) 268254721Semaste return (NULL); 269254721Semaste 270254721Semaste if (*p & 0xc0) { 271254721Semaste p = p + 2; 272254721Semaste if ((char *)p > pmax) 273254721Semaste return (NULL); 274254721Semaste return ((u_char *) p); 275254721Semaste } 276254721Semaste while ((*p & 0x3f) != 0x00) { 277254721Semaste s = p + 1; 278254721Semaste if (*p == 0x20) 279254721Semaste compress = 1; 280254721Semaste else 281254721Semaste compress = 0; 282254721Semaste 283254721Semaste /* Get next length field */ 284254721Semaste p = (u_char *) (p + (*p & 0x3f) + 1); 285254721Semaste if ((char *)p > pmax) { 286254721Semaste p = NULL; 287254721Semaste break; 288254721Semaste } 289254721Semaste#ifdef LIBALIAS_DEBUG 290254721Semaste printf(":"); 291254721Semaste#endif 292254721Semaste while (s < p) { 293254721Semaste if (compress == 1) { 294254721Semaste c = (u_char) (((((*s & 0x0f) << 4) | (*(s + 1) & 0x0f)) - 0x11)); 295254721Semaste#ifdef LIBALIAS_DEBUG 296254721Semaste if (isprint(c)) 297254721Semaste printf("%c", c); 298254721Semaste else 299254721Semaste printf("<0x%02x>", c); 300254721Semaste#endif 301254721Semaste s += 2; 302254721Semaste } else { 303254721Semaste#ifdef LIBALIAS_DEBUG 304254721Semaste printf("%c", *s); 305254721Semaste#endif 306254721Semaste s++; 307254721Semaste } 308254721Semaste } 309254721Semaste#ifdef LIBALIAS_DEBUG 310254721Semaste printf(":"); 311254721Semaste fflush(stdout); 312254721Semaste#endif 313254721Semaste } 314254721Semaste 315254721Semaste /* Set up to out of Name field */ 316254721Semaste if (p == NULL || (char *)p >= pmax) 317254721Semaste p = NULL; 318254721Semaste else 319254721Semaste p++; 320254721Semaste return ((u_char *) p); 321254721Semaste} 322254721Semaste 323254721Semaste/* 324254721Semaste * NetBios Datagram Handler (IP/UDP) 325254721Semaste */ 326254721Semaste#define DGM_DIRECT_UNIQ 0x10 327254721Semaste#define DGM_DIRECT_GROUP 0x11 328254721Semaste#define DGM_BROADCAST 0x12 329254721Semaste#define DGM_ERROR 0x13 330254721Semaste#define DGM_QUERY 0x14 331254721Semaste#define DGM_POSITIVE_RES 0x15 332254721Semaste#define DGM_NEGATIVE_RES 0x16 333254721Semaste 334254721Semastestatic int 335254721SemasteAliasHandleUdpNbt( 336254721Semaste struct libalias *la, 337254721Semaste struct ip *pip, /* IP packet to examine/patch */ 338254721Semaste struct alias_link *lnk, 339254721Semaste struct in_addr *alias_address, 340254721Semaste u_short alias_port 341254721Semaste) 342254721Semaste{ 343254721Semaste struct udphdr *uh; 344254721Semaste NbtDataHeader *ndh; 345254721Semaste u_char *p = NULL; 346254721Semaste char *pmax; 347254721Semaste 348254721Semaste (void)la; 349254721Semaste (void)lnk; 350254721Semaste 351254721Semaste /* Calculate data length of UDP packet */ 352254721Semaste uh = (struct udphdr *)ip_next(pip); 353254721Semaste pmax = (char *)uh + ntohs(uh->uh_ulen); 354 355 ndh = (NbtDataHeader *)udp_next(uh); 356 if ((char *)(ndh + 1) > pmax) 357 return (-1); 358#ifdef LIBALIAS_DEBUG 359 printf("\nType=%02x,", ndh->type); 360#endif 361 switch (ndh->type) { 362 case DGM_DIRECT_UNIQ: 363 case DGM_DIRECT_GROUP: 364 case DGM_BROADCAST: 365 p = (u_char *) ndh + 14; 366 p = AliasHandleName(p, pmax); /* Source Name */ 367 p = AliasHandleName(p, pmax); /* Destination Name */ 368 break; 369 case DGM_ERROR: 370 p = (u_char *) ndh + 11; 371 break; 372 case DGM_QUERY: 373 case DGM_POSITIVE_RES: 374 case DGM_NEGATIVE_RES: 375 p = (u_char *) ndh + 10; 376 p = AliasHandleName(p, pmax); /* Destination Name */ 377 break; 378 } 379 if (p == NULL || (char *)p > pmax) 380 p = NULL; 381#ifdef LIBALIAS_DEBUG 382 printf("%s:%d-->", inet_ntoa(ndh->source_ip), ntohs(ndh->source_port)); 383#endif 384 /* Doing an IP address and Port number Translation */ 385 if (uh->uh_sum != 0) { 386 int acc; 387 u_short *sptr; 388 389 acc = ndh->source_port; 390 acc -= alias_port; 391 sptr = (u_short *) & (ndh->source_ip); 392 acc += *sptr++; 393 acc += *sptr; 394 sptr = (u_short *) alias_address; 395 acc -= *sptr++; 396 acc -= *sptr; 397 ADJUST_CHECKSUM(acc, uh->uh_sum); 398 } 399 ndh->source_ip = *alias_address; 400 ndh->source_port = alias_port; 401#ifdef LIBALIAS_DEBUG 402 printf("%s:%d\n", inet_ntoa(ndh->source_ip), ntohs(ndh->source_port)); 403 fflush(stdout); 404#endif 405 return ((p == NULL) ? -1 : 0); 406} 407 408/* Question Section */ 409#define QS_TYPE_NB 0x0020 410#define QS_TYPE_NBSTAT 0x0021 411#define QS_CLAS_IN 0x0001 412typedef struct { 413 u_short type; /* The type of Request */ 414 u_short class; /* The class of Request */ 415} NBTNsQuestion; 416 417static u_char * 418AliasHandleQuestion( 419 u_short count, 420 NBTNsQuestion * q, 421 char *pmax, 422 NBTArguments * nbtarg) 423{ 424 425 (void)nbtarg; 426 427 while (count != 0) { 428 /* Name Filed */ 429 q = (NBTNsQuestion *) AliasHandleName((u_char *) q, pmax); 430 431 if (q == NULL || (char *)(q + 1) > pmax) { 432 q = NULL; 433 break; 434 } 435 /* Type and Class filed */ 436 switch (ntohs(q->type)) { 437 case QS_TYPE_NB: 438 case QS_TYPE_NBSTAT: 439 q = q + 1; 440 break; 441 default: 442#ifdef LIBALIAS_DEBUG 443 printf("\nUnknown Type on Question %0x\n", ntohs(q->type)); 444#endif 445 break; 446 } 447 count--; 448 } 449 450 /* Set up to out of Question Section */ 451 return ((u_char *) q); 452} 453 454/* Resource Record */ 455#define RR_TYPE_A 0x0001 456#define RR_TYPE_NS 0x0002 457#define RR_TYPE_NULL 0x000a 458#define RR_TYPE_NB 0x0020 459#define RR_TYPE_NBSTAT 0x0021 460#define RR_CLAS_IN 0x0001 461#define SizeOfNsResource 8 462typedef struct { 463 u_short type; 464 u_short class; 465 unsigned int ttl; 466 u_short rdlen; 467} NBTNsResource; 468 469#define SizeOfNsRNB 6 470typedef struct { 471 u_short g: 1 , ont:2, resv:13; 472 struct in_addr addr; 473} NBTNsRNB; 474 475static u_char * 476AliasHandleResourceNB( 477 NBTNsResource * q, 478 char *pmax, 479 NBTArguments * nbtarg) 480{ 481 NBTNsRNB *nb; 482 u_short bcount; 483 484 if (q == NULL || (char *)(q + 1) > pmax) 485 return (NULL); 486 /* Check out a length */ 487 bcount = ntohs(q->rdlen); 488 489 /* Forward to Resource NB position */ 490 nb = (NBTNsRNB *) ((u_char *) q + SizeOfNsResource); 491 492 /* Processing all in_addr array */ 493#ifdef LIBALIAS_DEBUG 494 printf("NB rec[%s", inet_ntoa(nbtarg->oldaddr)); 495 printf("->%s, %dbytes] ", inet_ntoa(nbtarg->newaddr), bcount); 496#endif 497 while (nb != NULL && bcount != 0) { 498 if ((char *)(nb + 1) > pmax) { 499 nb = NULL; 500 break; 501 } 502#ifdef LIBALIAS_DEBUG 503 printf("<%s>", inet_ntoa(nb->addr)); 504#endif 505 if (!bcmp(&nbtarg->oldaddr, &nb->addr, sizeof(struct in_addr))) { 506 if (*nbtarg->uh_sum != 0) { 507 int acc; 508 u_short *sptr; 509 510 sptr = (u_short *) & (nb->addr); 511 acc = *sptr++; 512 acc += *sptr; 513 sptr = (u_short *) & (nbtarg->newaddr); 514 acc -= *sptr++; 515 acc -= *sptr; 516 ADJUST_CHECKSUM(acc, *nbtarg->uh_sum); 517 } 518 nb->addr = nbtarg->newaddr; 519#ifdef LIBALIAS_DEBUG 520 printf("O"); 521#endif 522 } 523#ifdef LIBALIAS_DEBUG 524 else { 525 printf("."); 526 } 527#endif 528 nb = (NBTNsRNB *) ((u_char *) nb + SizeOfNsRNB); 529 bcount -= SizeOfNsRNB; 530 } 531 if (nb == NULL || (char *)(nb + 1) > pmax) { 532 nb = NULL; 533 } 534 return ((u_char *) nb); 535} 536 537#define SizeOfResourceA 6 538typedef struct { 539 struct in_addr addr; 540} NBTNsResourceA; 541 542static u_char * 543AliasHandleResourceA( 544 NBTNsResource * q, 545 char *pmax, 546 NBTArguments * nbtarg) 547{ 548 NBTNsResourceA *a; 549 u_short bcount; 550 551 if (q == NULL || (char *)(q + 1) > pmax) 552 return (NULL); 553 554 /* Forward to Resource A position */ 555 a = (NBTNsResourceA *) ((u_char *) q + sizeof(NBTNsResource)); 556 557 /* Check out of length */ 558 bcount = ntohs(q->rdlen); 559 560 /* Processing all in_addr array */ 561#ifdef LIBALIAS_DEBUG 562 printf("Arec [%s", inet_ntoa(nbtarg->oldaddr)); 563 printf("->%s]", inet_ntoa(nbtarg->newaddr)); 564#endif 565 while (bcount != 0) { 566 if (a == NULL || (char *)(a + 1) > pmax) 567 return (NULL); 568#ifdef LIBALIAS_DEBUG 569 printf("..%s", inet_ntoa(a->addr)); 570#endif 571 if (!bcmp(&nbtarg->oldaddr, &a->addr, sizeof(struct in_addr))) { 572 if (*nbtarg->uh_sum != 0) { 573 int acc; 574 u_short *sptr; 575 576 sptr = (u_short *) & (a->addr); /* Old */ 577 acc = *sptr++; 578 acc += *sptr; 579 sptr = (u_short *) & nbtarg->newaddr; /* New */ 580 acc -= *sptr++; 581 acc -= *sptr; 582 ADJUST_CHECKSUM(acc, *nbtarg->uh_sum); 583 } 584 a->addr = nbtarg->newaddr; 585 } 586 a++; /* XXXX */ 587 bcount -= SizeOfResourceA; 588 } 589 if (a == NULL || (char *)(a + 1) > pmax) 590 a = NULL; 591 return ((u_char *) a); 592} 593 594typedef struct { 595 u_short opcode:4, flags:8, resv:4; 596} NBTNsResourceNULL; 597 598static u_char * 599AliasHandleResourceNULL( 600 NBTNsResource * q, 601 char *pmax, 602 NBTArguments * nbtarg) 603{ 604 NBTNsResourceNULL *n; 605 u_short bcount; 606 607 (void)nbtarg; 608 609 if (q == NULL || (char *)(q + 1) > pmax) 610 return (NULL); 611 612 /* Forward to Resource NULL position */ 613 n = (NBTNsResourceNULL *) ((u_char *) q + sizeof(NBTNsResource)); 614 615 /* Check out of length */ 616 bcount = ntohs(q->rdlen); 617 618 /* Processing all in_addr array */ 619 while (bcount != 0) { 620 if ((char *)(n + 1) > pmax) { 621 n = NULL; 622 break; 623 } 624 n++; 625 bcount -= sizeof(NBTNsResourceNULL); 626 } 627 if ((char *)(n + 1) > pmax) 628 n = NULL; 629 630 return ((u_char *) n); 631} 632 633static u_char * 634AliasHandleResourceNS( 635 NBTNsResource * q, 636 char *pmax, 637 NBTArguments * nbtarg) 638{ 639 NBTNsResourceNULL *n; 640 u_short bcount; 641 642 (void)nbtarg; 643 644 if (q == NULL || (char *)(q + 1) > pmax) 645 return (NULL); 646 647 /* Forward to Resource NULL position */ 648 n = (NBTNsResourceNULL *) ((u_char *) q + sizeof(NBTNsResource)); 649 650 /* Check out of length */ 651 bcount = ntohs(q->rdlen); 652 653 /* Resource Record Name Filed */ 654 q = (NBTNsResource *) AliasHandleName((u_char *) n, pmax); /* XXX */ 655 656 if (q == NULL || (char *)((u_char *) n + bcount) > pmax) 657 return (NULL); 658 else 659 return ((u_char *) n + bcount); 660} 661 662typedef struct { 663 u_short numnames; 664} NBTNsResourceNBSTAT; 665 666static u_char * 667AliasHandleResourceNBSTAT( 668 NBTNsResource * q, 669 char *pmax, 670 NBTArguments * nbtarg) 671{ 672 NBTNsResourceNBSTAT *n; 673 u_short bcount; 674 675 (void)nbtarg; 676 677 if (q == NULL || (char *)(q + 1) > pmax) 678 return (NULL); 679 680 /* Forward to Resource NBSTAT position */ 681 n = (NBTNsResourceNBSTAT *) ((u_char *) q + sizeof(NBTNsResource)); 682 683 /* Check out of length */ 684 bcount = ntohs(q->rdlen); 685 686 if (q == NULL || (char *)((u_char *) n + bcount) > pmax) 687 return (NULL); 688 else 689 return ((u_char *) n + bcount); 690} 691 692static u_char * 693AliasHandleResource( 694 u_short count, 695 NBTNsResource * q, 696 char *pmax, 697 NBTArguments 698 * nbtarg) 699{ 700 while (count != 0) { 701 /* Resource Record Name Filed */ 702 q = (NBTNsResource *) AliasHandleName((u_char *) q, pmax); 703 704 if (q == NULL || (char *)(q + 1) > pmax) 705 break; 706#ifdef LIBALIAS_DEBUG 707 printf("type=%02x, count=%d\n", ntohs(q->type), count); 708#endif 709 710 /* Type and Class filed */ 711 switch (ntohs(q->type)) { 712 case RR_TYPE_NB: 713 q = (NBTNsResource *) AliasHandleResourceNB( 714 q, 715 pmax, 716 nbtarg 717 ); 718 break; 719 case RR_TYPE_A: 720 q = (NBTNsResource *) AliasHandleResourceA( 721 q, 722 pmax, 723 nbtarg 724 ); 725 break; 726 case RR_TYPE_NS: 727 q = (NBTNsResource *) AliasHandleResourceNS( 728 q, 729 pmax, 730 nbtarg 731 ); 732 break; 733 case RR_TYPE_NULL: 734 q = (NBTNsResource *) AliasHandleResourceNULL( 735 q, 736 pmax, 737 nbtarg 738 ); 739 break; 740 case RR_TYPE_NBSTAT: 741 q = (NBTNsResource *) AliasHandleResourceNBSTAT( 742 q, 743 pmax, 744 nbtarg 745 ); 746 break; 747 default: 748#ifdef LIBALIAS_DEBUG 749 printf( 750 "\nUnknown Type of Resource %0x\n", 751 ntohs(q->type) 752 ); 753 fflush(stdout); 754#endif 755 break; 756 } 757 count--; 758 } 759 return ((u_char *) q); 760} 761 762static int 763AliasHandleUdpNbtNS( 764 struct libalias *la, 765 struct ip *pip, /* IP packet to examine/patch */ 766 struct alias_link *lnk, 767 struct in_addr *alias_address, 768 u_short * alias_port, 769 struct in_addr *original_address, 770 u_short * original_port) 771{ 772 struct udphdr *uh; 773 NbtNSHeader *nsh; 774 u_char *p; 775 char *pmax; 776 NBTArguments nbtarg; 777 778 (void)la; 779 (void)lnk; 780 781 /* Set up Common Parameter */ 782 nbtarg.oldaddr = *alias_address; 783 nbtarg.oldport = *alias_port; 784 nbtarg.newaddr = *original_address; 785 nbtarg.newport = *original_port; 786 787 /* Calculate data length of UDP packet */ 788 uh = (struct udphdr *)ip_next(pip); 789 nbtarg.uh_sum = &(uh->uh_sum); 790 nsh = (NbtNSHeader *)udp_next(uh); 791 p = (u_char *) (nsh + 1); 792 pmax = (char *)uh + ntohs(uh->uh_ulen); 793 794 if ((char *)(nsh + 1) > pmax) 795 return (-1); 796 797#ifdef LIBALIAS_DEBUG 798 printf(" [%s] ID=%02x, op=%01x, flag=%02x, rcode=%01x, qd=%04x" 799 ", an=%04x, ns=%04x, ar=%04x, [%d]-->", 800 nsh->dir ? "Response" : "Request", 801 nsh->nametrid, 802 nsh->opcode, 803 nsh->nmflags, 804 nsh->rcode, 805 ntohs(nsh->qdcount), 806 ntohs(nsh->ancount), 807 ntohs(nsh->nscount), 808 ntohs(nsh->arcount), 809 (u_char *) p - (u_char *) nsh 810 ); 811#endif 812 813 /* Question Entries */ 814 if (ntohs(nsh->qdcount) != 0) { 815 p = AliasHandleQuestion( 816 ntohs(nsh->qdcount), 817 (NBTNsQuestion *) p, 818 pmax, 819 &nbtarg 820 ); 821 } 822 /* Answer Resource Records */ 823 if (ntohs(nsh->ancount) != 0) { 824 p = AliasHandleResource( 825 ntohs(nsh->ancount), 826 (NBTNsResource *) p, 827 pmax, 828 &nbtarg 829 ); 830 } 831 /* Authority Resource Recodrs */ 832 if (ntohs(nsh->nscount) != 0) { 833 p = AliasHandleResource( 834 ntohs(nsh->nscount), 835 (NBTNsResource *) p, 836 pmax, 837 &nbtarg 838 ); 839 } 840 /* Additional Resource Recodrs */ 841 if (ntohs(nsh->arcount) != 0) { 842 p = AliasHandleResource( 843 ntohs(nsh->arcount), 844 (NBTNsResource *) p, 845 pmax, 846 &nbtarg 847 ); 848 } 849#ifdef LIBALIAS_DEBUG 850 PrintRcode(nsh->rcode); 851#endif 852 return ((p == NULL) ? -1 : 0); 853} 854