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