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