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 follows */ 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 = malloc(l + 1); 281 if (!dbuf) 282 return -1; 283 284 b64buf = 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 case 2: /* IPv6 */ 327 printf(" %s", ip6addr_string(p)); 328 p += sizeof(struct in6_addr); 329 break; 330 default: 331 printf(" %lu/", (unsigned long)ntohl(ap->family)); 332 for (i = 0; i < l; i++) 333 printf("%02x", *p++); 334 } 335 336 return p - (const char *)ap; 337 338 trunc: 339 return -1; 340 } 341 342 void 343 lwres_print(const u_char *bp, u_int length) 344 { 345 const struct lwres_lwpacket *np; 346 u_int32_t v; 347 const char *s; 348 int response; 349 int advance; 350 int unsupported = 0; 351 352 np = (const struct lwres_lwpacket *)bp; 353 TCHECK(np->authlength); 354 355 printf("lwres"); 356 v = ntohs(np->version); 357 if (vflag || v != LWRES_LWPACKETVERSION_0) 358 printf(" v%u", v); 359 if (v != LWRES_LWPACKETVERSION_0) { 360 s = (const char *)np + ntohl(np->length); 361 goto tail; 362 } 363 364 response = ntohs(np->pktflags) & LWRES_LWPACKETFLAG_RESPONSE; 365 366 /* opcode and pktflags */ 367 v = (u_int32_t)ntohl(np->opcode); 368 s = tok2str(opcode, "#0x%x", v); 369 printf(" %s%s", s, response ? "" : "?"); 370 371 /* pktflags */ 372 v = ntohs(np->pktflags); 373 if (v & ~LWRES_LWPACKETFLAG_RESPONSE) 374 printf("[0x%x]", v); 375 376 if (vflag > 1) { 377 printf(" ("); /*)*/ 378 printf("serial:0x%lx", (unsigned long)ntohl(np->serial)); 379 printf(" result:0x%lx", (unsigned long)ntohl(np->result)); 380 printf(" recvlen:%lu", (unsigned long)ntohl(np->recvlength)); 381 /* BIND910: not used */ 382 if (vflag > 2) { 383 printf(" authtype:0x%x", ntohs(np->authtype)); 384 printf(" authlen:%u", ntohs(np->authlength)); 385 } 386 /*(*/ 387 printf(")"); 388 } 389 390 /* per-opcode content */ 391 if (!response) { 392 /* 393 * queries 394 */ 395 lwres_gabnrequest_t *gabn; 396 lwres_gnbarequest_t *gnba; 397 u_int32_t l; 398 399 gabn = NULL; 400 gnba = NULL; 401 402 switch (ntohl(np->opcode)) { 403 case LWRES_OPCODE_NOOP: 404 break; 405 case LWRES_OPCODE_GETADDRSBYNAME: 406 gabn = (lwres_gabnrequest_t *)(np + 1); 407 TCHECK(gabn->namelen); 408 /* XXX gabn points to packed struct */ 409 s = (const char *)&gabn->namelen + 410 sizeof(gabn->namelen); 411 l = ntohs(gabn->namelen); 412 413 /* BIND910: not used */ 414 if (vflag > 2) { 415 printf(" flags:0x%lx", 416 (unsigned long)ntohl(gabn->flags)); 417 } 418 419 v = (u_int32_t)ntohl(gabn->addrtypes); 420 switch (v & (LWRES_ADDRTYPE_V4 | LWRES_ADDRTYPE_V6)) { 421 case LWRES_ADDRTYPE_V4: 422 printf(" IPv4"); 423 break; 424 case LWRES_ADDRTYPE_V6: 425 printf(" IPv6"); 426 break; 427 case LWRES_ADDRTYPE_V4 | LWRES_ADDRTYPE_V6: 428 printf(" IPv4/6"); 429 break; 430 } 431 if (v & ~(LWRES_ADDRTYPE_V4 | LWRES_ADDRTYPE_V6)) 432 printf("[0x%x]", v); 433 434 advance = lwres_printname(l, s); 435 if (advance < 0) 436 goto trunc; 437 s += advance; 438 break; 439 case LWRES_OPCODE_GETNAMEBYADDR: 440 gnba = (lwres_gnbarequest_t *)(np + 1); 441 TCHECK(gnba->addr); 442 443 /* BIND910: not used */ 444 if (vflag > 2) { 445 printf(" flags:0x%lx", 446 (unsigned long)ntohl(gnba->flags)); 447 } 448 449 s = (const char *)&gnba->addr; 450 451 advance = lwres_printaddr(&gnba->addr); 452 if (advance < 0) 453 goto trunc; 454 s += advance; 455 break; 456 default: 457 unsupported++; 458 break; 459 } 460 } else { 461 /* 462 * responses 463 */ 464 lwres_gabnresponse_t *gabn; 465 lwres_gnbaresponse_t *gnba; 466 lwres_grbnresponse_t *grbn; 467 u_int32_t l, na; 468 int i; 469 470 gabn = NULL; 471 gnba = NULL; 472 grbn = NULL; 473 474 switch (ntohl(np->opcode)) { 475 case LWRES_OPCODE_NOOP: 476 break; 477 case LWRES_OPCODE_GETADDRSBYNAME: 478 gabn = (lwres_gabnresponse_t *)(np + 1); 479 TCHECK(gabn->realnamelen); 480 /* XXX gabn points to packed struct */ 481 s = (const char *)&gabn->realnamelen + 482 sizeof(gabn->realnamelen); 483 l = ntohs(gabn->realnamelen); 484 485 /* BIND910: not used */ 486 if (vflag > 2) { 487 printf(" flags:0x%lx", 488 (unsigned long)ntohl(gabn->flags)); 489 } 490 491 printf(" %u/%u", ntohs(gabn->naliases), 492 ntohs(gabn->naddrs)); 493 494 advance = lwres_printname(l, s); 495 if (advance < 0) 496 goto trunc; 497 s += advance; 498 499 /* aliases */ 500 na = ntohs(gabn->naliases); 501 for (i = 0; i < na; i++) { 502 advance = lwres_printnamelen(s); 503 if (advance < 0) 504 goto trunc; 505 s += advance; 506 } 507 508 /* addrs */ 509 na = ntohs(gabn->naddrs); 510 for (i = 0; i < na; i++) { 511 advance = lwres_printaddr((lwres_addr_t *)s); 512 if (advance < 0) 513 goto trunc; 514 s += advance; 515 } 516 break; 517 case LWRES_OPCODE_GETNAMEBYADDR: 518 gnba = (lwres_gnbaresponse_t *)(np + 1); 519 TCHECK(gnba->realnamelen); 520 /* XXX gnba points to packed struct */ 521 s = (const char *)&gnba->realnamelen + 522 sizeof(gnba->realnamelen); 523 l = ntohs(gnba->realnamelen); 524 525 /* BIND910: not used */ 526 if (vflag > 2) { 527 printf(" flags:0x%lx", 528 (unsigned long)ntohl(gnba->flags)); 529 } 530 531 printf(" %u", ntohs(gnba->naliases)); 532 533 advance = lwres_printname(l, s); 534 if (advance < 0) 535 goto trunc; 536 s += advance; 537 538 /* aliases */ 539 na = ntohs(gnba->naliases); 540 for (i = 0; i < na; i++) { 541 advance = lwres_printnamelen(s); 542 if (advance < 0) 543 goto trunc; 544 s += advance; 545 } 546 break; 547 case LWRES_OPCODE_GETRDATABYNAME: 548 /* XXX no trace, not tested */ 549 grbn = (lwres_grbnresponse_t *)(np + 1); 550 TCHECK(grbn->nsigs); 551 552 /* BIND910: not used */ 553 if (vflag > 2) { 554 printf(" flags:0x%lx", 555 (unsigned long)ntohl(grbn->flags)); 556 } 557 558 printf(" %s", tok2str(ns_type2str, "Type%d", 559 ntohs(grbn->rdtype))); 560 if (ntohs(grbn->rdclass) != C_IN) 561 printf(" %s", tok2str(ns_class2str, "Class%d", 562 ntohs(grbn->rdclass))); 563 printf(" TTL "); 564 relts_print(ntohl(grbn->ttl)); 565 printf(" %u/%u", ntohs(grbn->nrdatas), 566 ntohs(grbn->nsigs)); 567 568 /* XXX grbn points to packed struct */ 569 s = (const char *)&grbn->nsigs+ sizeof(grbn->nsigs); 570 571 advance = lwres_printnamelen(s); 572 if (advance < 0) 573 goto trunc; 574 s += advance; 575 576 /* rdatas */ 577 na = ntohs(grbn->nrdatas); 578 if (na > 0) 579 printf(" "); 580 581 for (i = 0; i < na; i++) { 582 /* XXX should decode resource data */ 583 advance = lwres_printb64len(s); 584 if (advance < 0) 585 goto trunc; 586 s += advance; 587 } 588 589 /* sigs */ 590 na = ntohs(grbn->nsigs); 591 if (na > 0) 592 printf(" "); 593 594 for (i = 0; i < na; i++) { 595 /* XXX how should we print it? */ 596 advance = lwres_printb64len(s); 597 if (advance < 0) 598 goto trunc; 599 s += advance; 600 } 601 break; 602 default: 603 unsupported++; 604 break; 605 } 606 } 607 608 tail: 609 /* length mismatch */ 610 if (ntohl(np->length) != length) { 611 printf(" [len: %lu != %u]", (unsigned long)ntohl(np->length), 612 length); 613 } 614 if (!unsupported && s < (const char *)np + ntohl(np->length)) 615 printf("[extra]"); 616 return; 617 618 trunc: 619 printf("[|lwres]"); 620 return; 621 } 622