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