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