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