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