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 #include <sys/cdefs.h> 31 #ifndef lint 32 #if 0 33 static const char rcsid[] _U_ = 34 "@(#) Header: /tcpdump/master/tcpdump/print-lwres.c,v 1.13 2004-03-24 01:54:29 guy Exp (LBL)"; 35 #else 36 __RCSID("$NetBSD: print-lwres.c,v 1.4 2013/12/31 17:33:31 christos Exp $"); 37 #endif 38 #endif 39 40 #ifdef HAVE_CONFIG_H 41 #include "config.h" 42 #endif 43 44 #include <tcpdump-stdinc.h> 45 46 #include "nameser.h" 47 48 #include <stdio.h> 49 #include <string.h> 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 static const 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 const struct tok ns_type2str[]; 193 extern const 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_printaddr(lwres_addr_t *); 199 200 static int 201 lwres_printname(size_t l, const char *p0) 202 { 203 const char *p; 204 size_t i; 205 206 p = p0; 207 /* + 1 for terminating \0 */ 208 if (p + l + 1 > (const char *)snapend) 209 goto trunc; 210 211 printf(" "); 212 for (i = 0; i < l; i++) 213 safeputchar(*p++); 214 p++; /* skip terminating \0 */ 215 216 return p - p0; 217 218 trunc: 219 return -1; 220 } 221 222 static int 223 lwres_printnamelen(const char *p) 224 { 225 u_int16_t l; 226 int advance; 227 228 if (p + 2 > (const char *)snapend) 229 goto trunc; 230 l = EXTRACT_16BITS(p); 231 advance = lwres_printname(l, p + 2); 232 if (advance < 0) 233 goto trunc; 234 return 2 + advance; 235 236 trunc: 237 return -1; 238 } 239 240 static int 241 lwres_printbinlen(const char *p0) 242 { 243 const char *p; 244 u_int16_t l; 245 int i; 246 247 p = p0; 248 if (p + 2 > (const char *)snapend) 249 goto trunc; 250 l = EXTRACT_16BITS(p); 251 if (p + 2 + l > (const char *)snapend) 252 goto trunc; 253 p += 2; 254 for (i = 0; i < l; i++) 255 printf("%02x", *p++); 256 return p - p0; 257 258 trunc: 259 return -1; 260 } 261 262 static int 263 lwres_printaddr(lwres_addr_t *ap) 264 { 265 u_int16_t l; 266 const char *p; 267 int i; 268 269 TCHECK(ap->length); 270 l = EXTRACT_16BITS(&ap->length); 271 /* XXX ap points to packed struct */ 272 p = (const char *)&ap->length + sizeof(ap->length); 273 TCHECK2(*p, l); 274 275 switch (EXTRACT_32BITS(&ap->family)) { 276 case 1: /* IPv4 */ 277 if (l < 4) 278 return -1; 279 printf(" %s", ipaddr_string(p)); 280 p += sizeof(struct in_addr); 281 break; 282 #ifdef INET6 283 case 2: /* IPv6 */ 284 if (l < 16) 285 return -1; 286 printf(" %s", ip6addr_string(p)); 287 p += sizeof(struct in6_addr); 288 break; 289 #endif 290 default: 291 printf(" %u/", EXTRACT_32BITS(&ap->family)); 292 for (i = 0; i < l; i++) 293 printf("%02x", *p++); 294 } 295 296 return p - (const char *)ap; 297 298 trunc: 299 return -1; 300 } 301 302 void 303 lwres_print(register const u_char *bp, u_int length) 304 { 305 const struct lwres_lwpacket *np; 306 u_int32_t v; 307 const char *s; 308 int response; 309 int advance; 310 int unsupported = 0; 311 312 np = (const struct lwres_lwpacket *)bp; 313 TCHECK(np->authlength); 314 315 printf(" lwres"); 316 v = EXTRACT_16BITS(&np->version); 317 if (vflag || v != LWRES_LWPACKETVERSION_0) 318 printf(" v%u", v); 319 if (v != LWRES_LWPACKETVERSION_0) { 320 s = (const char *)np + EXTRACT_32BITS(&np->length); 321 goto tail; 322 } 323 324 response = EXTRACT_16BITS(&np->pktflags) & LWRES_LWPACKETFLAG_RESPONSE; 325 326 /* opcode and pktflags */ 327 v = EXTRACT_32BITS(&np->opcode); 328 s = tok2str(opcode, "#0x%x", v); 329 printf(" %s%s", s, response ? "" : "?"); 330 331 /* pktflags */ 332 v = EXTRACT_16BITS(&np->pktflags); 333 if (v & ~LWRES_LWPACKETFLAG_RESPONSE) 334 printf("[0x%x]", v); 335 336 if (vflag > 1) { 337 printf(" ("); /*)*/ 338 printf("serial:0x%x", EXTRACT_32BITS(&np->serial)); 339 printf(" result:0x%x", EXTRACT_32BITS(&np->result)); 340 printf(" recvlen:%u", EXTRACT_32BITS(&np->recvlength)); 341 /* BIND910: not used */ 342 if (vflag > 2) { 343 printf(" authtype:0x%x", EXTRACT_16BITS(&np->authtype)); 344 printf(" authlen:%u", EXTRACT_16BITS(&np->authlength)); 345 } 346 /*(*/ 347 printf(")"); 348 } 349 350 /* per-opcode content */ 351 if (!response) { 352 /* 353 * queries 354 */ 355 lwres_gabnrequest_t *gabn; 356 lwres_gnbarequest_t *gnba; 357 lwres_grbnrequest_t *grbn; 358 u_int32_t l; 359 360 gabn = NULL; 361 gnba = NULL; 362 grbn = NULL; 363 364 switch (EXTRACT_32BITS(&np->opcode)) { 365 case LWRES_OPCODE_NOOP: 366 break; 367 case LWRES_OPCODE_GETADDRSBYNAME: 368 gabn = (lwres_gabnrequest_t *)(np + 1); 369 TCHECK(gabn->namelen); 370 /* XXX gabn points to packed struct */ 371 s = (const char *)&gabn->namelen + 372 sizeof(gabn->namelen); 373 l = EXTRACT_16BITS(&gabn->namelen); 374 375 /* BIND910: not used */ 376 if (vflag > 2) { 377 printf(" flags:0x%x", 378 EXTRACT_32BITS(&gabn->flags)); 379 } 380 381 v = EXTRACT_32BITS(&gabn->addrtypes); 382 switch (v & (LWRES_ADDRTYPE_V4 | LWRES_ADDRTYPE_V6)) { 383 case LWRES_ADDRTYPE_V4: 384 printf(" IPv4"); 385 break; 386 case LWRES_ADDRTYPE_V6: 387 printf(" IPv6"); 388 break; 389 case LWRES_ADDRTYPE_V4 | LWRES_ADDRTYPE_V6: 390 printf(" IPv4/6"); 391 break; 392 } 393 if (v & ~(LWRES_ADDRTYPE_V4 | LWRES_ADDRTYPE_V6)) 394 printf("[0x%x]", v); 395 396 advance = lwres_printname(l, s); 397 if (advance < 0) 398 goto trunc; 399 s += advance; 400 break; 401 case LWRES_OPCODE_GETNAMEBYADDR: 402 gnba = (lwres_gnbarequest_t *)(np + 1); 403 TCHECK(gnba->addr); 404 405 /* BIND910: not used */ 406 if (vflag > 2) { 407 printf(" flags:0x%x", 408 EXTRACT_32BITS(&gnba->flags)); 409 } 410 411 s = (const char *)&gnba->addr; 412 413 advance = lwres_printaddr(&gnba->addr); 414 if (advance < 0) 415 goto trunc; 416 s += advance; 417 break; 418 case LWRES_OPCODE_GETRDATABYNAME: 419 /* XXX no trace, not tested */ 420 grbn = (lwres_grbnrequest_t *)(np + 1); 421 TCHECK(grbn->namelen); 422 423 /* BIND910: not used */ 424 if (vflag > 2) { 425 printf(" flags:0x%x", 426 EXTRACT_32BITS(&grbn->flags)); 427 } 428 429 printf(" %s", tok2str(ns_type2str, "Type%d", 430 EXTRACT_16BITS(&grbn->rdtype))); 431 if (EXTRACT_16BITS(&grbn->rdclass) != C_IN) { 432 printf(" %s", tok2str(ns_class2str, "Class%d", 433 EXTRACT_16BITS(&grbn->rdclass))); 434 } 435 436 /* XXX grbn points to packed struct */ 437 s = (const char *)&grbn->namelen + 438 sizeof(grbn->namelen); 439 l = EXTRACT_16BITS(&grbn->namelen); 440 441 advance = lwres_printname(l, s); 442 if (advance < 0) 443 goto trunc; 444 s += advance; 445 break; 446 default: 447 unsupported++; 448 break; 449 } 450 } else { 451 /* 452 * responses 453 */ 454 lwres_gabnresponse_t *gabn; 455 lwres_gnbaresponse_t *gnba; 456 lwres_grbnresponse_t *grbn; 457 u_int32_t l, na; 458 u_int32_t i; 459 460 gabn = NULL; 461 gnba = NULL; 462 grbn = NULL; 463 464 switch (EXTRACT_32BITS(&np->opcode)) { 465 case LWRES_OPCODE_NOOP: 466 break; 467 case LWRES_OPCODE_GETADDRSBYNAME: 468 gabn = (lwres_gabnresponse_t *)(np + 1); 469 TCHECK(gabn->realnamelen); 470 /* XXX gabn points to packed struct */ 471 s = (const char *)&gabn->realnamelen + 472 sizeof(gabn->realnamelen); 473 l = EXTRACT_16BITS(&gabn->realnamelen); 474 475 /* BIND910: not used */ 476 if (vflag > 2) { 477 printf(" flags:0x%x", 478 EXTRACT_32BITS(&gabn->flags)); 479 } 480 481 printf(" %u/%u", EXTRACT_16BITS(&gabn->naliases), 482 EXTRACT_16BITS(&gabn->naddrs)); 483 484 advance = lwres_printname(l, s); 485 if (advance < 0) 486 goto trunc; 487 s += advance; 488 489 /* aliases */ 490 na = EXTRACT_16BITS(&gabn->naliases); 491 for (i = 0; i < na; i++) { 492 advance = lwres_printnamelen(s); 493 if (advance < 0) 494 goto trunc; 495 s += advance; 496 } 497 498 /* addrs */ 499 na = EXTRACT_16BITS(&gabn->naddrs); 500 for (i = 0; i < na; i++) { 501 advance = lwres_printaddr((lwres_addr_t *)s); 502 if (advance < 0) 503 goto trunc; 504 s += advance; 505 } 506 break; 507 case LWRES_OPCODE_GETNAMEBYADDR: 508 gnba = (lwres_gnbaresponse_t *)(np + 1); 509 TCHECK(gnba->realnamelen); 510 /* XXX gnba points to packed struct */ 511 s = (const char *)&gnba->realnamelen + 512 sizeof(gnba->realnamelen); 513 l = EXTRACT_16BITS(&gnba->realnamelen); 514 515 /* BIND910: not used */ 516 if (vflag > 2) { 517 printf(" flags:0x%x", 518 EXTRACT_32BITS(&gnba->flags)); 519 } 520 521 printf(" %u", EXTRACT_16BITS(&gnba->naliases)); 522 523 advance = lwres_printname(l, s); 524 if (advance < 0) 525 goto trunc; 526 s += advance; 527 528 /* aliases */ 529 na = EXTRACT_16BITS(&gnba->naliases); 530 for (i = 0; i < na; i++) { 531 advance = lwres_printnamelen(s); 532 if (advance < 0) 533 goto trunc; 534 s += advance; 535 } 536 break; 537 case LWRES_OPCODE_GETRDATABYNAME: 538 /* XXX no trace, not tested */ 539 grbn = (lwres_grbnresponse_t *)(np + 1); 540 TCHECK(grbn->nsigs); 541 542 /* BIND910: not used */ 543 if (vflag > 2) { 544 printf(" flags:0x%x", 545 EXTRACT_32BITS(&grbn->flags)); 546 } 547 548 printf(" %s", tok2str(ns_type2str, "Type%d", 549 EXTRACT_16BITS(&grbn->rdtype))); 550 if (EXTRACT_16BITS(&grbn->rdclass) != C_IN) { 551 printf(" %s", tok2str(ns_class2str, "Class%d", 552 EXTRACT_16BITS(&grbn->rdclass))); 553 } 554 printf(" TTL "); 555 relts_print(EXTRACT_32BITS(&grbn->ttl)); 556 printf(" %u/%u", EXTRACT_16BITS(&grbn->nrdatas), 557 EXTRACT_16BITS(&grbn->nsigs)); 558 559 /* XXX grbn points to packed struct */ 560 s = (const char *)&grbn->nsigs+ sizeof(grbn->nsigs); 561 562 advance = lwres_printnamelen(s); 563 if (advance < 0) 564 goto trunc; 565 s += advance; 566 567 /* rdatas */ 568 na = EXTRACT_16BITS(&grbn->nrdatas); 569 for (i = 0; i < na; i++) { 570 /* XXX should decode resource data */ 571 advance = lwres_printbinlen(s); 572 if (advance < 0) 573 goto trunc; 574 s += advance; 575 } 576 577 /* sigs */ 578 na = EXTRACT_16BITS(&grbn->nsigs); 579 for (i = 0; i < na; i++) { 580 /* XXX how should we print it? */ 581 advance = lwres_printbinlen(s); 582 if (advance < 0) 583 goto trunc; 584 s += advance; 585 } 586 break; 587 default: 588 unsupported++; 589 break; 590 } 591 } 592 593 tail: 594 /* length mismatch */ 595 if (EXTRACT_32BITS(&np->length) != length) { 596 printf(" [len: %u != %u]", EXTRACT_32BITS(&np->length), 597 length); 598 } 599 if (!unsupported && s < (const char *)np + EXTRACT_32BITS(&np->length)) 600 printf("[extra]"); 601 return; 602 603 trunc: 604 printf("[|lwres]"); 605 return; 606 } 607