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 72static int 73AliasHandleUdpNbt(struct libalias *, struct ip *, struct alias_link *, 74 struct in_addr *, u_short); 75 76static int 77AliasHandleUdpNbtNS(struct libalias *, struct ip *, struct alias_link *, 78 struct in_addr *, u_short *, struct in_addr *, u_short *); 79static int 80fingerprint1(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 92static int 93protohandler1(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 99static int 100fingerprint2(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 112static int 113protohandler2in(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 121static int 122protohandler2out(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. */ 130struct 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 155static int 156mod_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 176static 177#endif 178moduledata_t alias_mod = { 179 "alias_nbt", mod_handler, NULL 180}; 181 182#ifdef _KERNEL 183DECLARE_MODULE(alias_nbt, alias_mod, SI_SUB_DRIVERS, SI_ORDER_SECOND); 184MODULE_VERSION(alias_nbt, 1); 185MODULE_DEPEND(alias_nbt, libalias, 1, 1, 1); 186#endif 187 188typedef 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 196typedef 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 212typedef 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 230static void 231PrintRcode(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 */ 257static u_char * 258AliasHandleName(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 334static int 335AliasHandleUdpNbt( 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 412typedef struct { 413 u_short type; /* The type of Request */ 414 u_short class; /* The class of Request */ 415} NBTNsQuestion; 416 417static u_char * 418AliasHandleQuestion( 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 462typedef struct { 463 u_short type; 464 u_short class; 465 unsigned int ttl; 466 u_short rdlen; 467} NBTNsResource; 468 469#define SizeOfNsRNB 6 470typedef struct { 471 u_short g: 1 , ont:2, resv:13; 472 struct in_addr addr; 473} NBTNsRNB; 474 475static u_char * 476AliasHandleResourceNB( 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 538typedef struct { 539 struct in_addr addr; 540} NBTNsResourceA; 541 542static u_char * 543AliasHandleResourceA( 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 594typedef struct { 595 u_short opcode:4, flags:8, resv:4; 596} NBTNsResourceNULL; 597 598static u_char * 599AliasHandleResourceNULL( 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 633static u_char * 634AliasHandleResourceNS( 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 662typedef struct { 663 u_short numnames; 664} NBTNsResourceNBSTAT; 665 666static u_char * 667AliasHandleResourceNBSTAT( 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 692static u_char * 693AliasHandleResource( 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 762static int 763AliasHandleUdpNbtNS( 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