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