1 /* 2 * Copyright (C) 2001 WIDE Project. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. Neither the name of the project nor the names of its contributors 14 * may be used to endorse or promote products derived from this software 15 * without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE PROJECT 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 PROJECT 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 */ 29 30 #ifdef HAVE_CONFIG_H 31 #include "config.h" 32 #endif 33 34 #include <sys/param.h> 35 #include <sys/time.h> 36 37 #include <netinet/in.h> 38 39 #ifdef NOERROR 40 #undef NOERROR /* Solaris sucks */ 41 #endif 42 #ifdef NOERROR 43 #undef T_UNSPEC /* SINIX does too */ 44 #endif 45 #include "nameser.h" 46 47 #include <stdio.h> 48 #include <string.h> 49 #include <stdlib.h> 50 #include <resolv.h> /* for b64_ntop() proto */ 51 52 #include "interface.h" 53 #include "addrtoname.h" 54 #include "extract.h" /* must come after interface.h */ 55 56 /* BIND9 lib/lwres/include/lwres */ 57 typedef u_int32_t lwres_uint32_t; 58 typedef u_int16_t lwres_uint16_t; 59 typedef u_int8_t lwres_uint8_t; 60 61 struct lwres_lwpacket { 62 lwres_uint32_t length; 63 lwres_uint16_t version; 64 lwres_uint16_t pktflags; 65 lwres_uint32_t serial; 66 lwres_uint32_t opcode; 67 lwres_uint32_t result; 68 lwres_uint32_t recvlength; 69 lwres_uint16_t authtype; 70 lwres_uint16_t authlength; 71 }; 72 73 #define LWRES_LWPACKETFLAG_RESPONSE 0x0001U /* if set, pkt is a response */ 74 75 #define LWRES_LWPACKETVERSION_0 0 76 77 #define LWRES_FLAG_TRUSTNOTREQUIRED 0x00000001U 78 #define LWRES_FLAG_SECUREDATA 0x00000002U 79 80 /* 81 * no-op 82 */ 83 #define LWRES_OPCODE_NOOP 0x00000000U 84 85 typedef struct { 86 /* public */ 87 lwres_uint16_t datalength; 88 /* data follows */ 89 } lwres_nooprequest_t; 90 91 typedef struct { 92 /* public */ 93 lwres_uint16_t datalength; 94 /* data follows */ 95 } lwres_noopresponse_t; 96 97 /* 98 * get addresses by name 99 */ 100 #define LWRES_OPCODE_GETADDRSBYNAME 0x00010001U 101 102 typedef struct lwres_addr lwres_addr_t; 103 104 struct lwres_addr { 105 lwres_uint32_t family; 106 lwres_uint16_t length; 107 /* address folows */ 108 }; 109 110 typedef struct { 111 /* public */ 112 lwres_uint32_t flags; 113 lwres_uint32_t addrtypes; 114 lwres_uint16_t namelen; 115 /* name follows */ 116 } lwres_gabnrequest_t; 117 118 typedef struct { 119 /* public */ 120 lwres_uint32_t flags; 121 lwres_uint16_t naliases; 122 lwres_uint16_t naddrs; 123 lwres_uint16_t realnamelen; 124 /* aliases follows */ 125 /* addrs follows */ 126 /* realname follows */ 127 } lwres_gabnresponse_t; 128 129 /* 130 * get name by address 131 */ 132 #define LWRES_OPCODE_GETNAMEBYADDR 0x00010002U 133 typedef struct { 134 /* public */ 135 lwres_uint32_t flags; 136 lwres_addr_t addr; 137 /* addr body follows */ 138 } lwres_gnbarequest_t; 139 140 typedef struct { 141 /* public */ 142 lwres_uint32_t flags; 143 lwres_uint16_t naliases; 144 lwres_uint16_t realnamelen; 145 /* aliases follows */ 146 /* realname follows */ 147 } lwres_gnbaresponse_t; 148 149 /* 150 * get rdata by name 151 */ 152 #define LWRES_OPCODE_GETRDATABYNAME 0x00010003U 153 154 typedef struct { 155 /* public */ 156 lwres_uint32_t flags; 157 lwres_uint16_t rdclass; 158 lwres_uint16_t rdtype; 159 lwres_uint16_t namelen; 160 /* name follows */ 161 } lwres_grbnrequest_t; 162 163 typedef struct { 164 /* public */ 165 lwres_uint32_t flags; 166 lwres_uint16_t rdclass; 167 lwres_uint16_t rdtype; 168 lwres_uint32_t ttl; 169 lwres_uint16_t nrdatas; 170 lwres_uint16_t nsigs; 171 /* realname here (len + name) */ 172 /* rdata here (len + name) */ 173 /* signatures here (len + name) */ 174 } lwres_grbnresponse_t; 175 176 #define LWRDATA_VALIDATED 0x00000001 177 178 #define LWRES_ADDRTYPE_V4 0x00000001U /* ipv4 */ 179 #define LWRES_ADDRTYPE_V6 0x00000002U /* ipv6 */ 180 181 #define LWRES_MAX_ALIASES 16 /* max # of aliases */ 182 #define LWRES_MAX_ADDRS 64 /* max # of addrs */ 183 184 struct tok opcode[] = { 185 { LWRES_OPCODE_NOOP, "noop", }, 186 { LWRES_OPCODE_GETADDRSBYNAME, "getaddrsbyname", }, 187 { LWRES_OPCODE_GETNAMEBYADDR, "getnamebyaddr", }, 188 { LWRES_OPCODE_GETRDATABYNAME, "getrdatabyname", }, 189 { 0, NULL, }, 190 }; 191 192 /* print-domain.c */ 193 extern struct tok ns_type2str[]; 194 extern struct tok ns_class2str[]; 195 196 static int lwres_printname(size_t, const char *); 197 static int lwres_printnamelen(const char *); 198 /* static int lwres_printbinlen(const char *); */ 199 static int lwres_printb64len(const char *); 200 static int lwres_printaddr(lwres_addr_t *); 201 202 static int 203 lwres_printname(size_t l, const char *p0) 204 { 205 const char *p; 206 int i; 207 208 p = p0; 209 /* + 1 for terminating \0 */ 210 if (p + l + 1 > (const char *)snapend) 211 goto trunc; 212 213 printf(" "); 214 for (i = 0; i < l; i++) 215 safeputchar(*p++); 216 p++; /* skip terminating \0 */ 217 218 return p - p0; 219 220 trunc: 221 return -1; 222 } 223 224 static int 225 lwres_printnamelen(const char *p) 226 { 227 u_int16_t l; 228 int advance; 229 230 if (p + 2 > (const char *)snapend) 231 goto trunc; 232 l = EXTRACT_16BITS(p); 233 advance = lwres_printname(l, p + 2); 234 if (advance < 0) 235 goto trunc; 236 return 2 + advance; 237 238 trunc: 239 return -1; 240 } 241 242 #if 0 243 static int 244 lwres_printbinlen(const char *p0) 245 { 246 u_int8_t *p; 247 u_int16_t l; 248 int i; 249 250 p = (u_int8_t *)p0; 251 if (p + 2 > (u_int8_t *)snapend) 252 goto trunc; 253 l = EXTRACT_16BITS(p); 254 if (p + 2 + l > (u_int8_t *)snapend) 255 goto trunc; 256 p += 2; 257 for (i = 0; i < l; i++) 258 printf("%02x", *p++); 259 return p - (u_int8_t *)p0; 260 261 trunc: 262 return -1; 263 } 264 #endif 265 266 static int 267 lwres_printb64len(const char *p0) 268 { 269 u_int8_t *p; 270 u_int16_t l; 271 char *dbuf, *b64buf; 272 int i; 273 274 p = (u_int8_t *)p0; 275 if (p + 2 > (u_int8_t *)snapend) 276 goto trunc; 277 l = EXTRACT_16BITS(p); 278 if (p + 2 + l > (u_int8_t *)snapend) 279 goto trunc; 280 281 dbuf = (char *)malloc(l + 1); 282 if (!dbuf) 283 return -1; 284 285 b64buf = (char *)malloc((l + 2) * 4 / 3); 286 if (!b64buf) 287 { 288 free(dbuf); 289 return -1; 290 } 291 292 memcpy(dbuf, p, l); 293 *(dbuf + l) = (char)0; 294 295 i = b64_ntop (dbuf, l, b64buf, (l + 2) * 4 / 3); 296 b64buf[i] = (char)0; 297 printf ("%s", b64buf); 298 299 free (dbuf); 300 free (b64buf); 301 302 return l + 2; 303 304 trunc: 305 return -1; 306 } 307 308 static int 309 lwres_printaddr(lwres_addr_t *ap) 310 { 311 u_int16_t l; 312 const char *p; 313 int i; 314 315 TCHECK(ap->length); 316 l = ntohs(ap->length); 317 /* XXX ap points to packed struct */ 318 p = (const char *)&ap->length + sizeof(ap->length); 319 if (p + l > (const char *)snapend) 320 goto trunc; 321 322 switch (ntohl(ap->family)) { 323 case 1: /* IPv4 */ 324 printf(" %s", ipaddr_string(p)); 325 p += sizeof(struct in_addr); 326 break; 327 #ifdef INET6 328 case 2: /* IPv6 */ 329 printf(" %s", ip6addr_string(p)); 330 p += sizeof(struct in6_addr); 331 break; 332 #endif 333 default: 334 printf(" %lu/", (unsigned long)ntohl(ap->family)); 335 for (i = 0; i < l; i++) 336 printf("%02x", *p++); 337 } 338 339 return p - (const char *)ap; 340 341 trunc: 342 return -1; 343 } 344 345 void 346 lwres_print(register const u_char *bp, u_int length) 347 { 348 const struct lwres_lwpacket *np; 349 u_int32_t v; 350 const char *s; 351 int response; 352 int advance; 353 int unsupported = 0; 354 355 np = (const struct lwres_lwpacket *)bp; 356 TCHECK(np->authlength); 357 358 printf(" lwres"); 359 v = ntohs(np->version); 360 if (vflag || v != LWRES_LWPACKETVERSION_0) 361 printf(" v%u", v); 362 if (v != LWRES_LWPACKETVERSION_0) { 363 s = (const char *)np + ntohl(np->length); 364 goto tail; 365 } 366 367 response = ntohs(np->pktflags) & LWRES_LWPACKETFLAG_RESPONSE; 368 369 /* opcode and pktflags */ 370 v = (u_int32_t)ntohl(np->opcode); 371 s = tok2str(opcode, "#0x%x", v); 372 printf(" %s%s", s, response ? "" : "?"); 373 374 /* pktflags */ 375 v = ntohs(np->pktflags); 376 if (v & ~LWRES_LWPACKETFLAG_RESPONSE) 377 printf("[0x%x]", v); 378 379 if (vflag > 1) { 380 printf(" ("); /*)*/ 381 printf("serial:0x%lx", (unsigned long)ntohl(np->serial)); 382 printf(" result:0x%lx", (unsigned long)ntohl(np->result)); 383 printf(" recvlen:%lu", (unsigned long)ntohl(np->recvlength)); 384 /* BIND910: not used */ 385 if (vflag > 2) { 386 printf(" authtype:0x%x", ntohs(np->authtype)); 387 printf(" authlen:%u", ntohs(np->authlength)); 388 } 389 /*(*/ 390 printf(")"); 391 } 392 393 /* per-opcode content */ 394 if (!response) { 395 /* 396 * queries 397 */ 398 lwres_gabnrequest_t *gabn; 399 lwres_gnbarequest_t *gnba; 400 lwres_grbnrequest_t *grbn; 401 u_int32_t l; 402 403 gabn = NULL; 404 gnba = NULL; 405 grbn = NULL; 406 407 switch (ntohl(np->opcode)) { 408 case LWRES_OPCODE_NOOP: 409 break; 410 case LWRES_OPCODE_GETADDRSBYNAME: 411 gabn = (lwres_gabnrequest_t *)(np + 1); 412 TCHECK(gabn->namelen); 413 /* XXX gabn points to packed struct */ 414 s = (const char *)&gabn->namelen + 415 sizeof(gabn->namelen); 416 l = ntohs(gabn->namelen); 417 418 /* BIND910: not used */ 419 if (vflag > 2) { 420 printf(" flags:0x%lx", 421 (unsigned long)ntohl(gabn->flags)); 422 } 423 424 v = (u_int32_t)ntohl(gabn->addrtypes); 425 switch (v & (LWRES_ADDRTYPE_V4 | LWRES_ADDRTYPE_V6)) { 426 case LWRES_ADDRTYPE_V4: 427 printf(" IPv4"); 428 break; 429 case LWRES_ADDRTYPE_V6: 430 printf(" IPv6"); 431 break; 432 case LWRES_ADDRTYPE_V4 | LWRES_ADDRTYPE_V6: 433 printf(" IPv4/6"); 434 break; 435 } 436 if (v & ~(LWRES_ADDRTYPE_V4 | LWRES_ADDRTYPE_V6)) 437 printf("[0x%x]", v); 438 439 advance = lwres_printname(l, s); 440 if (advance < 0) 441 goto trunc; 442 s += advance; 443 break; 444 case LWRES_OPCODE_GETNAMEBYADDR: 445 gnba = (lwres_gnbarequest_t *)(np + 1); 446 TCHECK(gnba->addr); 447 448 /* BIND910: not used */ 449 if (vflag > 2) { 450 printf(" flags:0x%lx", 451 (unsigned long)ntohl(gnba->flags)); 452 } 453 454 s = (const char *)&gnba->addr; 455 456 advance = lwres_printaddr(&gnba->addr); 457 if (advance < 0) 458 goto trunc; 459 s += advance; 460 break; 461 default: 462 unsupported++; 463 break; 464 } 465 } else { 466 /* 467 * responses 468 */ 469 lwres_gabnresponse_t *gabn; 470 lwres_gnbaresponse_t *gnba; 471 lwres_grbnresponse_t *grbn; 472 u_int32_t l, na; 473 int i; 474 475 gabn = NULL; 476 gnba = NULL; 477 grbn = NULL; 478 479 switch (ntohl(np->opcode)) { 480 case LWRES_OPCODE_NOOP: 481 break; 482 case LWRES_OPCODE_GETADDRSBYNAME: 483 gabn = (lwres_gabnresponse_t *)(np + 1); 484 TCHECK(gabn->realnamelen); 485 /* XXX gabn points to packed struct */ 486 s = (const char *)&gabn->realnamelen + 487 sizeof(gabn->realnamelen); 488 l = ntohs(gabn->realnamelen); 489 490 /* BIND910: not used */ 491 if (vflag > 2) { 492 printf(" flags:0x%lx", 493 (unsigned long)ntohl(gabn->flags)); 494 } 495 496 printf(" %u/%u", ntohs(gabn->naliases), 497 ntohs(gabn->naddrs)); 498 499 advance = lwres_printname(l, s); 500 if (advance < 0) 501 goto trunc; 502 s += advance; 503 504 /* aliases */ 505 na = ntohs(gabn->naliases); 506 for (i = 0; i < na; i++) { 507 advance = lwres_printnamelen(s); 508 if (advance < 0) 509 goto trunc; 510 s += advance; 511 } 512 513 /* addrs */ 514 na = ntohs(gabn->naddrs); 515 for (i = 0; i < na; i++) { 516 advance = lwres_printaddr((lwres_addr_t *)s); 517 if (advance < 0) 518 goto trunc; 519 s += advance; 520 } 521 break; 522 case LWRES_OPCODE_GETNAMEBYADDR: 523 gnba = (lwres_gnbaresponse_t *)(np + 1); 524 TCHECK(gnba->realnamelen); 525 /* XXX gnba points to packed struct */ 526 s = (const char *)&gnba->realnamelen + 527 sizeof(gnba->realnamelen); 528 l = ntohs(gnba->realnamelen); 529 530 /* BIND910: not used */ 531 if (vflag > 2) { 532 printf(" flags:0x%lx", 533 (unsigned long)ntohl(gnba->flags)); 534 } 535 536 printf(" %u", ntohs(gnba->naliases)); 537 538 advance = lwres_printname(l, s); 539 if (advance < 0) 540 goto trunc; 541 s += advance; 542 543 /* aliases */ 544 na = ntohs(gnba->naliases); 545 for (i = 0; i < na; i++) { 546 advance = lwres_printnamelen(s); 547 if (advance < 0) 548 goto trunc; 549 s += advance; 550 } 551 break; 552 case LWRES_OPCODE_GETRDATABYNAME: 553 /* XXX no trace, not tested */ 554 grbn = (lwres_grbnresponse_t *)(np + 1); 555 TCHECK(grbn->nsigs); 556 557 /* BIND910: not used */ 558 if (vflag > 2) { 559 printf(" flags:0x%lx", 560 (unsigned long)ntohl(grbn->flags)); 561 } 562 563 printf(" %s", tok2str(ns_type2str, "Type%d", 564 ntohs(grbn->rdtype))); 565 if (ntohs(grbn->rdclass) != C_IN) 566 printf(" %s", tok2str(ns_class2str, "Class%d", 567 ntohs(grbn->rdclass))); 568 printf(" TTL "); 569 relts_print(ntohl(grbn->ttl)); 570 printf(" %u/%u", ntohs(grbn->nrdatas), 571 ntohs(grbn->nsigs)); 572 573 /* XXX grbn points to packed struct */ 574 s = (const char *)&grbn->nsigs+ sizeof(grbn->nsigs); 575 576 advance = lwres_printnamelen(s); 577 if (advance < 0) 578 goto trunc; 579 s += advance; 580 581 /* rdatas */ 582 na = ntohs(grbn->nrdatas); 583 if (na > 0) 584 printf(" "); 585 586 for (i = 0; i < na; i++) { 587 /* XXX should decode resource data */ 588 advance = lwres_printb64len(s); 589 if (advance < 0) 590 goto trunc; 591 s += advance; 592 } 593 594 /* sigs */ 595 na = ntohs(grbn->nsigs); 596 if (na > 0) 597 printf(" "); 598 599 for (i = 0; i < na; i++) { 600 /* XXX how should we print it? */ 601 advance = lwres_printb64len(s); 602 if (advance < 0) 603 goto trunc; 604 s += advance; 605 } 606 break; 607 default: 608 unsupported++; 609 break; 610 } 611 } 612 613 tail: 614 /* length mismatch */ 615 if (ntohl(np->length) != length) { 616 printf(" [len: %lu != %u]", (unsigned long)ntohl(np->length), 617 length); 618 } 619 if (!unsupported && s < (const char *)np + ntohl(np->length)) 620 printf("[extra]"); 621 return; 622 623 trunc: 624 printf("[|lwres]"); 625 return; 626 } 627