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