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