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