1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Written by Atsushi Murai <amurai@spec.co.jp> 5 * Copyright (c) 1998, System Planning and Engineering Co. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 * TODO: 29 * oClean up. 30 * oConsidering for word alignment for other platform. 31 */ 32 33 #include <sys/cdefs.h> 34 __FBSDID("$FreeBSD$"); 35 36 /* 37 alias_nbt.c performs special processing for NetBios over TCP/IP 38 sessions by UDP. 39 40 Initial version: May, 1998 (Atsushi Murai <amurai@spec.co.jp>) 41 42 See HISTORY file for record of revisions. 43 */ 44 45 /* Includes */ 46 #ifdef _KERNEL 47 #include <sys/param.h> 48 #include <sys/systm.h> 49 #include <sys/kernel.h> 50 #include <sys/module.h> 51 #else 52 #include <errno.h> 53 #include <sys/types.h> 54 #include <stdio.h> 55 #include <strings.h> 56 #endif 57 58 #include <netinet/in_systm.h> 59 #include <netinet/in.h> 60 #include <netinet/ip.h> 61 #include <netinet/udp.h> 62 63 #ifdef _KERNEL 64 #include <netinet/libalias/alias_local.h> 65 #include <netinet/libalias/alias_mod.h> 66 #else 67 #include "alias_local.h" 68 #include "alias_mod.h" 69 #endif 70 71 #define NETBIOS_NS_PORT_NUMBER 137 72 #define NETBIOS_DGM_PORT_NUMBER 138 73 74 static int 75 AliasHandleUdpNbt(struct libalias *, struct ip *, struct alias_link *, 76 struct in_addr *, u_short); 77 static int 78 AliasHandleUdpNbtNS(struct libalias *, struct ip *, struct alias_link *, 79 struct in_addr *, u_short *, struct in_addr *, u_short *); 80 81 static int 82 fingerprint1(struct libalias *la, struct alias_data *ah) 83 { 84 if (ah->dport == NULL || ah->sport == NULL || ah->lnk == NULL || 85 ah->aaddr == NULL || ah->aport == NULL) 86 return (-1); 87 if (ntohs(*ah->dport) == NETBIOS_DGM_PORT_NUMBER 88 || ntohs(*ah->sport) == NETBIOS_DGM_PORT_NUMBER) 89 return (0); 90 return (-1); 91 } 92 93 static int 94 protohandler1(struct libalias *la, struct ip *pip, struct alias_data *ah) 95 { 96 return (AliasHandleUdpNbt(la, pip, ah->lnk, ah->aaddr, *ah->aport)); 97 } 98 99 static int 100 fingerprint2(struct libalias *la, struct alias_data *ah) 101 { 102 if (ah->dport == NULL || ah->sport == NULL || ah->lnk == NULL || 103 ah->aaddr == NULL || ah->aport == NULL) 104 return (-1); 105 if (ntohs(*ah->dport) == NETBIOS_NS_PORT_NUMBER 106 || ntohs(*ah->sport) == NETBIOS_NS_PORT_NUMBER) 107 return (0); 108 return (-1); 109 } 110 111 static int 112 protohandler2in(struct libalias *la, struct ip *pip, struct alias_data *ah) 113 { 114 AliasHandleUdpNbtNS(la, pip, ah->lnk, ah->aaddr, ah->aport, 115 ah->oaddr, ah->dport); 116 return (0); 117 } 118 119 static int 120 protohandler2out(struct libalias *la, struct ip *pip, struct alias_data *ah) 121 { 122 return (AliasHandleUdpNbtNS(la, pip, ah->lnk, &pip->ip_src, ah->sport, 123 ah->aaddr, ah->aport)); 124 } 125 126 /* Kernel module definition. */ 127 struct proto_handler handlers[] = { 128 { 129 .pri = 130, 130 .dir = IN|OUT, 131 .proto = UDP, 132 .fingerprint = &fingerprint1, 133 .protohandler = &protohandler1 134 }, 135 { 136 .pri = 140, 137 .dir = IN, 138 .proto = UDP, 139 .fingerprint = &fingerprint2, 140 .protohandler = &protohandler2in 141 }, 142 { 143 .pri = 140, 144 .dir = OUT, 145 .proto = UDP, 146 .fingerprint = &fingerprint2, 147 .protohandler = &protohandler2out 148 }, 149 { EOH } 150 }; 151 152 static int 153 mod_handler(module_t mod, int type, void *data) 154 { 155 int error; 156 157 switch (type) { 158 case MOD_LOAD: 159 error = 0; 160 LibAliasAttachHandlers(handlers); 161 break; 162 case MOD_UNLOAD: 163 error = 0; 164 LibAliasDetachHandlers(handlers); 165 break; 166 default: 167 error = EINVAL; 168 } 169 return (error); 170 } 171 172 #ifdef _KERNEL 173 static 174 #endif 175 moduledata_t alias_mod = { 176 "alias_nbt", mod_handler, NULL 177 }; 178 179 #ifdef _KERNEL 180 DECLARE_MODULE(alias_nbt, alias_mod, SI_SUB_DRIVERS, SI_ORDER_SECOND); 181 MODULE_VERSION(alias_nbt, 1); 182 MODULE_DEPEND(alias_nbt, libalias, 1, 1, 1); 183 #endif 184 185 typedef struct { 186 struct in_addr oldaddr; 187 u_short oldport; 188 struct in_addr newaddr; 189 u_short newport; 190 u_short *uh_sum; 191 } NBTArguments; 192 193 typedef struct { 194 unsigned char type; 195 unsigned char flags; 196 u_short id; 197 struct in_addr source_ip; 198 u_short source_port; 199 u_short len; 200 u_short offset; 201 } NbtDataHeader; 202 203 #define OpQuery 0 204 #define OpUnknown 4 205 #define OpRegist 5 206 #define OpRelease 6 207 #define OpWACK 7 208 #define OpRefresh 8 209 typedef struct { 210 u_short nametrid; 211 u_short dir:1, opcode:4, nmflags:7, rcode:4; 212 u_short qdcount; 213 u_short ancount; 214 u_short nscount; 215 u_short arcount; 216 } NbtNSHeader; 217 218 #define FMT_ERR 0x1 219 #define SRV_ERR 0x2 220 #define IMP_ERR 0x4 221 #define RFS_ERR 0x5 222 #define ACT_ERR 0x6 223 #define CFT_ERR 0x7 224 225 #ifdef LIBALIAS_DEBUG 226 static void 227 PrintRcode(u_char rcode) 228 { 229 switch (rcode) { 230 case FMT_ERR: 231 printf("\nFormat Error."); 232 case SRV_ERR: 233 printf("\nSever failure."); 234 case IMP_ERR: 235 printf("\nUnsupported request error.\n"); 236 case RFS_ERR: 237 printf("\nRefused error.\n"); 238 case ACT_ERR: 239 printf("\nActive error.\n"); 240 case CFT_ERR: 241 printf("\nName in conflict error.\n"); 242 default: 243 printf("\n?%c?=%0x\n", '?', rcode); 244 } 245 } 246 247 #endif 248 249 /* Handling Name field */ 250 static u_char * 251 AliasHandleName(u_char *p, char *pmax) 252 { 253 u_char *s; 254 #ifdef LIBALIAS_DEBUG 255 u_char c; 256 #endif 257 int compress; 258 259 /* Following length field */ 260 261 if (p == NULL || (char *)p >= pmax) 262 return (NULL); 263 264 if (*p & 0xc0) { 265 p = p + 2; 266 if ((char *)p > pmax) 267 return (NULL); 268 return ((u_char *)p); 269 } 270 while ((*p & 0x3f) != 0x00) { 271 s = p + 1; 272 if (*p == 0x20) 273 compress = 1; 274 else 275 compress = 0; 276 277 /* Get next length field */ 278 p = (u_char *)(p + (*p & 0x3f) + 1); 279 if ((char *)p > pmax) { 280 p = NULL; 281 break; 282 } 283 #ifdef LIBALIAS_DEBUG 284 printf(":"); 285 #endif 286 while (s < p) { 287 if (compress == 1) { 288 #ifdef LIBALIAS_DEBUG 289 c = (u_char) (((((*s & 0x0f) << 4) | (*(s + 1) & 0x0f)) - 0x11)); 290 if (isprint(c)) 291 printf("%c", c); 292 else 293 printf("<0x%02x>", c); 294 #endif 295 s += 2; 296 } else { 297 #ifdef LIBALIAS_DEBUG 298 printf("%c", *s); 299 #endif 300 s++; 301 } 302 } 303 #ifdef LIBALIAS_DEBUG 304 printf(":"); 305 fflush(stdout); 306 #endif 307 } 308 309 /* Set up to out of Name field */ 310 if (p == NULL || (char *)p >= pmax) 311 p = NULL; 312 else 313 p++; 314 return ((u_char *)p); 315 } 316 317 /* 318 * NetBios Datagram Handler (IP/UDP) 319 */ 320 #define DGM_DIRECT_UNIQ 0x10 321 #define DGM_DIRECT_GROUP 0x11 322 #define DGM_BROADCAST 0x12 323 #define DGM_ERROR 0x13 324 #define DGM_QUERY 0x14 325 #define DGM_POSITIVE_RES 0x15 326 #define DGM_NEGATIVE_RES 0x16 327 328 static int 329 AliasHandleUdpNbt( 330 struct libalias *la, 331 struct ip *pip, /* IP packet to examine/patch */ 332 struct alias_link *lnk, 333 struct in_addr *alias_address, 334 u_short alias_port) 335 { 336 struct udphdr *uh; 337 NbtDataHeader *ndh; 338 u_char *p = NULL; 339 char *pmax; 340 #ifdef LIBALIAS_DEBUG 341 char addrbuf[INET_ADDRSTRLEN]; 342 #endif 343 344 (void)la; 345 (void)lnk; 346 347 /* Calculate data length of UDP packet */ 348 uh = (struct udphdr *)ip_next(pip); 349 pmax = (char *)uh + ntohs(uh->uh_ulen); 350 351 ndh = (NbtDataHeader *)udp_next(uh); 352 if ((char *)(ndh + 1) > pmax) 353 return (-1); 354 #ifdef LIBALIAS_DEBUG 355 printf("\nType=%02x,", ndh->type); 356 #endif 357 switch (ndh->type) { 358 case DGM_DIRECT_UNIQ: 359 case DGM_DIRECT_GROUP: 360 case DGM_BROADCAST: 361 p = (u_char *)ndh + 14; 362 p = AliasHandleName(p, pmax); /* Source Name */ 363 p = AliasHandleName(p, pmax); /* Destination Name */ 364 break; 365 case DGM_ERROR: 366 p = (u_char *)ndh + 11; 367 break; 368 case DGM_QUERY: 369 case DGM_POSITIVE_RES: 370 case DGM_NEGATIVE_RES: 371 p = (u_char *)ndh + 10; 372 p = AliasHandleName(p, pmax); /* Destination Name */ 373 break; 374 } 375 if (p == NULL || (char *)p > pmax) 376 p = NULL; 377 #ifdef LIBALIAS_DEBUG 378 printf("%s:%d-->", inet_ntoa_r(ndh->source_ip, INET_NTOA_BUF(addrbuf)), 379 ntohs(ndh->source_port)); 380 #endif 381 /* Doing an IP address and Port number Translation */ 382 if (uh->uh_sum != 0) { 383 int acc; 384 u_short *sptr; 385 386 acc = ndh->source_port; 387 acc -= alias_port; 388 sptr = (u_short *)&(ndh->source_ip); 389 acc += *sptr++; 390 acc += *sptr; 391 sptr = (u_short *)alias_address; 392 acc -= *sptr++; 393 acc -= *sptr; 394 ADJUST_CHECKSUM(acc, uh->uh_sum); 395 } 396 ndh->source_ip = *alias_address; 397 ndh->source_port = alias_port; 398 #ifdef LIBALIAS_DEBUG 399 printf("%s:%d\n", inet_ntoa_r(ndh->source_ip, INET_NTOA_BUF(addrbuf)), 400 ntohs(ndh->source_port)); 401 fflush(stdout); 402 #endif 403 return ((p == NULL) ? -1 : 0); 404 } 405 406 /* Question Section */ 407 #define QS_TYPE_NB 0x0020 408 #define QS_TYPE_NBSTAT 0x0021 409 #define QS_CLAS_IN 0x0001 410 typedef struct { 411 u_short type; /* The type of Request */ 412 u_short class; /* The class of Request */ 413 } NBTNsQuestion; 414 415 static u_char * 416 AliasHandleQuestion( 417 u_short count, 418 NBTNsQuestion * q, 419 char *pmax, 420 NBTArguments * nbtarg) 421 { 422 (void)nbtarg; 423 424 while (count != 0) { 425 /* Name Filed */ 426 q = (NBTNsQuestion *)AliasHandleName((u_char *)q, pmax); 427 428 if (q == NULL || (char *)(q + 1) > pmax) { 429 q = NULL; 430 break; 431 } 432 /* Type and Class filed */ 433 switch (ntohs(q->type)) { 434 case QS_TYPE_NB: 435 case QS_TYPE_NBSTAT: 436 q = q + 1; 437 break; 438 default: 439 #ifdef LIBALIAS_DEBUG 440 printf("\nUnknown Type on Question %0x\n", ntohs(q->type)); 441 #endif 442 break; 443 } 444 count--; 445 } 446 447 /* Set up to out of Question Section */ 448 return ((u_char *)q); 449 } 450 451 /* Resource Record */ 452 #define RR_TYPE_A 0x0001 453 #define RR_TYPE_NS 0x0002 454 #define RR_TYPE_NULL 0x000a 455 #define RR_TYPE_NB 0x0020 456 #define RR_TYPE_NBSTAT 0x0021 457 #define RR_CLAS_IN 0x0001 458 #define SizeOfNsResource 8 459 typedef struct { 460 u_short type; 461 u_short class; 462 unsigned int ttl; 463 u_short rdlen; 464 } NBTNsResource; 465 466 #define SizeOfNsRNB 6 467 typedef struct { 468 u_short g:1, ont:2, resv:13; 469 struct in_addr addr; 470 } NBTNsRNB; 471 472 static u_char * 473 AliasHandleResourceNB( 474 NBTNsResource *q, 475 char *pmax, 476 NBTArguments *nbtarg) 477 { 478 NBTNsRNB *nb; 479 u_short bcount; 480 #ifdef LIBALIAS_DEBUG 481 char oldbuf[INET_ADDRSTRLEN]; 482 char newbuf[INET_ADDRSTRLEN]; 483 #endif 484 485 if (q == NULL || (char *)(q + 1) > pmax) 486 return (NULL); 487 /* Check out a length */ 488 bcount = ntohs(q->rdlen); 489 490 /* Forward to Resource NB position */ 491 nb = (NBTNsRNB *)((u_char *)q + SizeOfNsResource); 492 493 /* Processing all in_addr array */ 494 #ifdef LIBALIAS_DEBUG 495 printf("NB rec[%s->%s, %dbytes] ", 496 inet_ntoa_r(nbtarg->oldaddr, INET_NTOA_BUF(oldbuf)), 497 inet_ntoa_r(nbtarg->newaddr, INET_NTOA_BUF(newbuf)), 498 bcount); 499 #endif 500 while (nb != NULL && bcount != 0) { 501 if ((char *)(nb + 1) > pmax) { 502 nb = NULL; 503 break; 504 } 505 #ifdef LIBALIAS_DEBUG 506 printf("<%s>", inet_ntoa_r(nb->addr, INET_NTOA_BUF(newbuf))); 507 #endif 508 if (!bcmp(&nbtarg->oldaddr, &nb->addr, sizeof(struct in_addr))) { 509 if (*nbtarg->uh_sum != 0) { 510 int acc; 511 u_short *sptr; 512 513 sptr = (u_short *)&(nb->addr); 514 acc = *sptr++; 515 acc += *sptr; 516 sptr = (u_short *)&(nbtarg->newaddr); 517 acc -= *sptr++; 518 acc -= *sptr; 519 ADJUST_CHECKSUM(acc, *nbtarg->uh_sum); 520 } 521 nb->addr = nbtarg->newaddr; 522 #ifdef LIBALIAS_DEBUG 523 printf("O"); 524 #endif 525 } 526 #ifdef LIBALIAS_DEBUG 527 else { 528 printf("."); 529 } 530 #endif 531 nb = (NBTNsRNB *)((u_char *)nb + SizeOfNsRNB); 532 bcount -= SizeOfNsRNB; 533 } 534 if (nb == NULL || (char *)(nb + 1) > pmax) { 535 nb = NULL; 536 } 537 return ((u_char *)nb); 538 } 539 540 #define SizeOfResourceA 6 541 typedef struct { 542 struct in_addr addr; 543 } NBTNsResourceA; 544 545 static u_char * 546 AliasHandleResourceA( 547 NBTNsResource *q, 548 char *pmax, 549 NBTArguments *nbtarg) 550 { 551 NBTNsResourceA *a; 552 u_short bcount; 553 #ifdef LIBALIAS_DEBUG 554 char oldbuf[INET_ADDRSTRLEN]; 555 char newbuf[INET_ADDRSTRLEN]; 556 #endif 557 558 if (q == NULL || (char *)(q + 1) > pmax) 559 return (NULL); 560 561 /* Forward to Resource A position */ 562 a = (NBTNsResourceA *)((u_char *)q + sizeof(NBTNsResource)); 563 564 /* Check out of length */ 565 bcount = ntohs(q->rdlen); 566 567 /* Processing all in_addr array */ 568 #ifdef LIBALIAS_DEBUG 569 printf("Arec [%s->%s]", 570 inet_ntoa_r(nbtarg->oldaddr, INET_NTOA_BUF(oldbuf)), 571 inet_ntoa_r(nbtarg->newaddr, INET_NTOA_BUF(newbuf))); 572 #endif 573 while (bcount != 0) { 574 if (a == NULL || (char *)(a + 1) > pmax) 575 return (NULL); 576 #ifdef LIBALIAS_DEBUG 577 printf("..%s", inet_ntoa_r(a->addr, INET_NTOA_BUF(newbuf))); 578 #endif 579 if (!bcmp(&nbtarg->oldaddr, &a->addr, sizeof(struct in_addr))) { 580 if (*nbtarg->uh_sum != 0) { 581 int acc; 582 u_short *sptr; 583 584 sptr = (u_short *)&(a->addr); /* Old */ 585 acc = *sptr++; 586 acc += *sptr; 587 sptr = (u_short *)&nbtarg->newaddr; /* New */ 588 acc -= *sptr++; 589 acc -= *sptr; 590 ADJUST_CHECKSUM(acc, *nbtarg->uh_sum); 591 } 592 a->addr = nbtarg->newaddr; 593 } 594 a++; /* XXXX */ 595 bcount -= SizeOfResourceA; 596 } 597 if (a == NULL || (char *)(a + 1) > pmax) 598 a = NULL; 599 return ((u_char *)a); 600 } 601 602 typedef struct { 603 u_short opcode:4, flags:8, resv:4; 604 } NBTNsResourceNULL; 605 606 static u_char * 607 AliasHandleResourceNULL( 608 NBTNsResource *q, 609 char *pmax, 610 NBTArguments *nbtarg) 611 { 612 NBTNsResourceNULL *n; 613 u_short bcount; 614 615 (void)nbtarg; 616 617 if (q == NULL || (char *)(q + 1) > pmax) 618 return (NULL); 619 620 /* Forward to Resource NULL position */ 621 n = (NBTNsResourceNULL *)((u_char *)q + sizeof(NBTNsResource)); 622 623 /* Check out of length */ 624 bcount = ntohs(q->rdlen); 625 626 /* Processing all in_addr array */ 627 while (bcount != 0) { 628 if ((char *)(n + 1) > pmax) { 629 n = NULL; 630 break; 631 } 632 n++; 633 bcount -= sizeof(NBTNsResourceNULL); 634 } 635 if ((char *)(n + 1) > pmax) 636 n = NULL; 637 638 return ((u_char *)n); 639 } 640 641 static u_char * 642 AliasHandleResourceNS( 643 NBTNsResource *q, 644 char *pmax, 645 NBTArguments *nbtarg) 646 { 647 NBTNsResourceNULL *n; 648 u_short bcount; 649 650 (void)nbtarg; 651 652 if (q == NULL || (char *)(q + 1) > pmax) 653 return (NULL); 654 655 /* Forward to Resource NULL position */ 656 n = (NBTNsResourceNULL *)((u_char *)q + sizeof(NBTNsResource)); 657 658 /* Check out of length */ 659 bcount = ntohs(q->rdlen); 660 661 /* Resource Record Name Filed */ 662 q = (NBTNsResource *)AliasHandleName((u_char *)n, pmax); /* XXX */ 663 664 if (q == NULL || (char *)((u_char *)n + bcount) > pmax) 665 return (NULL); 666 else 667 return ((u_char *)n + bcount); 668 } 669 670 typedef struct { 671 u_short numnames; 672 } NBTNsResourceNBSTAT; 673 674 static u_char * 675 AliasHandleResourceNBSTAT( 676 NBTNsResource *q, 677 char *pmax, 678 NBTArguments *nbtarg) 679 { 680 NBTNsResourceNBSTAT *n; 681 u_short bcount; 682 683 (void)nbtarg; 684 685 if (q == NULL || (char *)(q + 1) > pmax) 686 return (NULL); 687 688 /* Forward to Resource NBSTAT position */ 689 n = (NBTNsResourceNBSTAT *)((u_char *)q + sizeof(NBTNsResource)); 690 691 /* Check out of length */ 692 bcount = ntohs(q->rdlen); 693 694 if (q == NULL || (char *)((u_char *)n + bcount) > pmax) 695 return (NULL); 696 else 697 return ((u_char *)n + bcount); 698 } 699 700 static u_char * 701 AliasHandleResource( 702 u_short count, 703 NBTNsResource *q, 704 char *pmax, 705 NBTArguments *nbtarg) 706 { 707 while (count != 0) { 708 /* Resource Record Name Filed */ 709 q = (NBTNsResource *)AliasHandleName((u_char *)q, pmax); 710 711 if (q == NULL || (char *)(q + 1) > pmax) 712 break; 713 #ifdef LIBALIAS_DEBUG 714 printf("type=%02x, count=%d\n", ntohs(q->type), count); 715 #endif 716 717 /* Type and Class filed */ 718 switch (ntohs(q->type)) { 719 case RR_TYPE_NB: 720 q = (NBTNsResource *)AliasHandleResourceNB( 721 q, pmax, nbtarg); 722 break; 723 case RR_TYPE_A: 724 q = (NBTNsResource *)AliasHandleResourceA( 725 q, pmax, nbtarg); 726 break; 727 case RR_TYPE_NS: 728 q = (NBTNsResource *)AliasHandleResourceNS( 729 q, pmax, nbtarg); 730 break; 731 case RR_TYPE_NULL: 732 q = (NBTNsResource *)AliasHandleResourceNULL( 733 q, pmax, nbtarg); 734 break; 735 case RR_TYPE_NBSTAT: 736 q = (NBTNsResource *)AliasHandleResourceNBSTAT( 737 q, pmax, nbtarg); 738 break; 739 default: 740 #ifdef LIBALIAS_DEBUG 741 printf( 742 "\nUnknown Type of Resource %0x\n", 743 ntohs(q->type) 744 ); 745 fflush(stdout); 746 #endif 747 break; 748 } 749 count--; 750 } 751 return ((u_char *)q); 752 } 753 754 static int 755 AliasHandleUdpNbtNS( 756 struct libalias *la, 757 struct ip *pip, /* IP packet to examine/patch */ 758 struct alias_link *lnk, 759 struct in_addr *alias_address, 760 u_short *alias_port, 761 struct in_addr *original_address, 762 u_short *original_port) 763 { 764 struct udphdr *uh; 765 NbtNSHeader *nsh; 766 u_char *p; 767 char *pmax; 768 NBTArguments nbtarg; 769 770 (void)la; 771 (void)lnk; 772 773 /* Set up Common Parameter */ 774 nbtarg.oldaddr = *alias_address; 775 nbtarg.oldport = *alias_port; 776 nbtarg.newaddr = *original_address; 777 nbtarg.newport = *original_port; 778 779 /* Calculate data length of UDP packet */ 780 uh = (struct udphdr *)ip_next(pip); 781 nbtarg.uh_sum = &(uh->uh_sum); 782 nsh = (NbtNSHeader *)udp_next(uh); 783 p = (u_char *)(nsh + 1); 784 pmax = (char *)uh + ntohs(uh->uh_ulen); 785 786 if ((char *)(nsh + 1) > pmax) 787 return (-1); 788 789 #ifdef LIBALIAS_DEBUG 790 printf(" [%s] ID=%02x, op=%01x, flag=%02x, rcode=%01x, qd=%04x" 791 ", an=%04x, ns=%04x, ar=%04x, [%d]-->", 792 nsh->dir ? "Response" : "Request", 793 nsh->nametrid, 794 nsh->opcode, 795 nsh->nmflags, 796 nsh->rcode, 797 ntohs(nsh->qdcount), 798 ntohs(nsh->ancount), 799 ntohs(nsh->nscount), 800 ntohs(nsh->arcount), 801 (u_char *)p - (u_char *)nsh 802 ); 803 #endif 804 805 /* Question Entries */ 806 if (ntohs(nsh->qdcount) != 0) { 807 p = AliasHandleQuestion( 808 ntohs(nsh->qdcount), 809 (NBTNsQuestion *)p, 810 pmax, 811 &nbtarg 812 ); 813 } 814 /* Answer Resource Records */ 815 if (ntohs(nsh->ancount) != 0) { 816 p = AliasHandleResource( 817 ntohs(nsh->ancount), 818 (NBTNsResource *)p, 819 pmax, 820 &nbtarg 821 ); 822 } 823 /* Authority Resource Recodrs */ 824 if (ntohs(nsh->nscount) != 0) { 825 p = AliasHandleResource( 826 ntohs(nsh->nscount), 827 (NBTNsResource *)p, 828 pmax, 829 &nbtarg 830 ); 831 } 832 /* Additional Resource Recodrs */ 833 if (ntohs(nsh->arcount) != 0) { 834 p = AliasHandleResource( 835 ntohs(nsh->arcount), 836 (NBTNsResource *)p, 837 pmax, 838 &nbtarg 839 ); 840 } 841 #ifdef LIBALIAS_DEBUG 842 PrintRcode(nsh->rcode); 843 #endif 844 return ((p == NULL) ? -1 : 0); 845 } 846