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