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