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