1 /* $OpenBSD: common.c,v 1.4 2018/12/15 15:16:12 eric Exp $ */ 2 /* 3 * Copyright (c) 2012 Eric Faurot <eric@openbsd.org> 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 #include <sys/types.h> 18 #include <sys/socket.h> 19 #include <netinet/in.h> 20 #include <arpa/inet.h> 21 #include <arpa/nameser.h> 22 23 #include <err.h> 24 #include <errno.h> 25 #include <inttypes.h> 26 #include <netdb.h> 27 #include <resolv.h> 28 #include <stdio.h> 29 #include <string.h> 30 31 #include "common.h" 32 33 int long_err; 34 int gai_errno; 35 int rrset_errno; 36 37 38 char * 39 gethostarg(char *n) 40 { 41 if (n == NULL) 42 return (n); 43 if (!strcmp(n, "NULL")) 44 return (NULL); 45 if (!strcmp(n, "EMPTY")) 46 return (""); 47 return (n); 48 } 49 50 const char *rrsetstrerror(int); 51 char * print_addr(const struct sockaddr *, char *, size_t); 52 53 struct kv { int code; const char *name; }; 54 55 struct kv kv_family[] = { 56 { AF_UNIX, "unix" }, 57 { AF_INET, "inet" }, 58 { AF_INET6, "inet6" }, 59 { 0, NULL, } 60 }; 61 struct kv kv_socktype[] = { 62 { SOCK_STREAM, "stream" }, 63 { SOCK_DGRAM, "dgram" }, 64 { SOCK_RAW, "raw" }, 65 { SOCK_SEQPACKET, "seqpacket" }, 66 { 0, NULL, } 67 }; 68 struct kv kv_protocol[] = { 69 { IPPROTO_UDP, "udp" }, 70 { IPPROTO_TCP, "tcp" }, 71 { IPPROTO_ICMP, "icmp" }, 72 { IPPROTO_ICMPV6, "icmpv6" }, 73 { 0, NULL, } 74 }; 75 76 static const char * 77 kv_lookup_name(struct kv *kv, int code, char *buf, size_t sz) 78 { 79 while (kv->name) { 80 if (kv->code == code) 81 return (kv->name); 82 kv++; 83 } 84 snprintf(buf, sz, "%i", code); 85 return (buf); 86 } 87 88 struct keyval { 89 const char *key; 90 int value; 91 }; 92 93 static struct keyval kv_class[] = { 94 { "IN", C_IN }, 95 { "CHAOS", C_CHAOS }, 96 { "HS", C_HS }, 97 { "ANY", C_ANY }, 98 { NULL, 0 }, 99 }; 100 101 static struct keyval kv_type[] = { 102 { "A", T_A }, 103 { "NS", T_NS }, 104 { "MD", T_MD }, 105 { "MF", T_MF }, 106 { "CNAME", T_CNAME }, 107 { "SOA", T_SOA }, 108 { "MB", T_MB }, 109 { "MG", T_MG }, 110 { "MR", T_MR }, 111 { "NULL", T_NULL }, 112 { "WKS", T_WKS }, 113 { "PTR", T_PTR }, 114 { "HINFO", T_HINFO }, 115 { "MINFO", T_MINFO }, 116 { "MX", T_MX }, 117 { "TXT", T_TXT }, 118 119 { "AAAA", T_AAAA }, 120 121 { "AXFR", T_AXFR }, 122 { "MAILB", T_MAILB }, 123 { "MAILA", T_MAILA }, 124 { "ANY", T_ANY }, 125 { NULL, 0 }, 126 }; 127 128 static struct keyval kv_rcode[] = { 129 { "NOERROR", NOERROR }, 130 { "FORMERR", FORMERR }, 131 { "SERVFAIL", SERVFAIL }, 132 { "NXDOMAIN", NXDOMAIN }, 133 { "NOTIMP", NOTIMP }, 134 { "REFUSED", REFUSED }, 135 { NULL, 0 }, 136 }; 137 138 static struct keyval kv_resopt[] = { 139 { "DEBUG", RES_DEBUG }, 140 { "AAONLY", RES_AAONLY }, 141 { "USEVC", RES_USEVC }, 142 { "PRIMARY", RES_PRIMARY }, 143 { "IGNTC", RES_IGNTC }, 144 { "RECURSE", RES_RECURSE }, 145 { "DEFNAMES", RES_DEFNAMES }, 146 { "STAYOPEN", RES_STAYOPEN }, 147 { "DNSRCH", RES_DNSRCH }, 148 { "INSECURE1", RES_INSECURE1 }, 149 { "INSECURE2", RES_INSECURE2 }, 150 { "NOALIASES", RES_NOALIASES }, 151 { "USE_INET6", RES_USE_INET6 }, 152 { "USE_EDNS0", RES_USE_EDNS0 }, 153 { "USE_DNSSEC", RES_USE_DNSSEC }, 154 { NULL, 0 }, 155 }; 156 157 const char * 158 rcodetostr(uint16_t v) 159 { 160 static char buf[16]; 161 size_t i; 162 163 for(i = 0; kv_rcode[i].key; i++) 164 if (kv_rcode[i].value == v) 165 return (kv_rcode[i].key); 166 167 snprintf(buf, sizeof buf, "%"PRIu16"?", v); 168 169 return (buf); 170 } 171 172 const char * 173 typetostr(uint16_t v) 174 { 175 static char buf[16]; 176 size_t i; 177 178 for(i = 0; kv_type[i].key; i++) 179 if (kv_type[i].value == v) 180 return (kv_type[i].key); 181 182 snprintf(buf, sizeof buf, "%"PRIu16"?", v); 183 184 return (buf); 185 } 186 187 const char * 188 classtostr(uint16_t v) 189 { 190 static char buf[16]; 191 size_t i; 192 193 for(i = 0; kv_class[i].key; i++) 194 if (kv_class[i].value == v) 195 return (kv_class[i].key); 196 197 snprintf(buf, sizeof buf, "%"PRIu16"?", v); 198 199 return (buf); 200 } 201 202 uint16_t 203 strtotype(const char *name) 204 { 205 size_t i; 206 207 for(i = 0; kv_type[i].key; i++) 208 if (!strcasecmp(kv_type[i].key, name)) 209 return (kv_type[i].value); 210 211 return (0); 212 } 213 214 uint16_t 215 strtoclass(const char *name) 216 { 217 size_t i; 218 219 for(i = 0; kv_class[i].key; i++) 220 if (!strcasecmp(kv_class[i].key, name)) 221 return (kv_class[i].value); 222 223 return (0); 224 } 225 226 int 227 strtoresopt(const char *name) 228 { 229 size_t i; 230 231 for(i = 0; kv_resopt[i].key; i++) 232 if (!strcasecmp(kv_resopt[i].key, name)) 233 return (kv_resopt[i].value); 234 235 return (0); 236 } 237 238 void 239 parseresopt(const char *name) 240 { 241 static int init = 0; 242 int flag, neg = 0; 243 244 if (init == 0) { 245 res_init(); 246 init = 1; 247 } 248 249 if (name[0] == '-') { 250 neg = 1; 251 name++; 252 } 253 else if (name[0] == '+') 254 name++; 255 256 flag = strtoresopt(name); 257 if (flag == 0) 258 errx(1, "unknown reslover option %s", name); 259 260 if (neg) 261 _res.options &= ~flag; 262 else 263 _res.options |= flag; 264 } 265 266 void 267 print_hostent(struct hostent *e) 268 { 269 char buf[256], **c; 270 271 printf("name = \"%s\"\n", e->h_name); 272 printf("aliases ="); 273 for(c = e->h_aliases; *c; c++) 274 printf(" \"%s\"", *c); 275 printf("\n"); 276 printf("addrtype = %i\n", e->h_addrtype); 277 printf("addrlength = %i\n", e->h_length); 278 printf("addr_list ="); 279 for(c = e->h_addr_list; *c; c++) { 280 printf(" %s", inet_ntop(e->h_addrtype, *c, buf, sizeof buf)); 281 } 282 printf("\n"); 283 } 284 285 void 286 print_netent(struct netent *e) 287 { 288 char buf[256], **c; 289 uint32_t addr; 290 291 /* network number are given in host order */ 292 addr = htonl(e->n_net); 293 294 printf("name = \"%s\"\n", e->n_name); 295 printf("aliases ="); 296 for (c = e->n_aliases; *c; c++) 297 printf(" \"%s\"", *c); 298 printf("\n"); 299 printf("addrtype = %i\n", e->n_addrtype); 300 printf("net = %s\n", inet_ntop(e->n_addrtype, &addr, buf, sizeof buf)); 301 } 302 303 void 304 print_addrinfo(struct addrinfo *ai) 305 { 306 char buf[256], bf[64], bt[64], bp[64]; 307 308 printf("family=%s socktype=%s protocol=%s addr=%s canonname=%s\n", 309 kv_lookup_name(kv_family, ai->ai_family, bf, sizeof bf), 310 kv_lookup_name(kv_socktype, ai->ai_socktype, bt, sizeof bt), 311 kv_lookup_name(kv_protocol, ai->ai_protocol, bp, sizeof bp), 312 print_addr(ai->ai_addr, buf, sizeof buf), 313 ai->ai_canonname); 314 } 315 316 const char * 317 rrsetstrerror(int e) 318 { 319 switch (e) { 320 case 0: 321 return "OK"; 322 case ERRSET_NONAME: 323 return "ERRSET_NONAME"; 324 case ERRSET_NODATA: 325 return "ERRSET_NODATA"; 326 case ERRSET_NOMEMORY: 327 return "ERRSET_NOMEMORY"; 328 case ERRSET_INVAL: 329 return "ERRSET_INVAL"; 330 case ERRSET_FAIL: 331 return "ERRSET_FAIL"; 332 default: 333 return "???"; 334 } 335 } 336 337 void 338 print_rrsetinfo(struct rrsetinfo * rrset) 339 { 340 printf("rri_flags=%u\n", rrset->rri_flags); 341 printf("rri_rdclass=%u\n", rrset->rri_rdclass); 342 printf("rri_rdtype=%u\n", rrset->rri_rdtype); 343 printf("rri_ttl=%u\n", rrset->rri_ttl); 344 printf("rri_nrdatas=%u\n", rrset->rri_nrdatas); 345 printf("rri_nsigs=%u\n", rrset->rri_nsigs); 346 printf("rri_name=\"%s\"\n", rrset->rri_name); 347 } 348 349 void 350 print_errors(void) 351 { 352 switch (long_err) { 353 case 0: 354 return; 355 case 1: 356 printf(" => errno %i, h_errno %i", errno, h_errno); 357 printf(", rrset_errno %i", rrset_errno); 358 printf(", gai_errno %i", gai_errno); 359 printf ("\n"); 360 return; 361 default: 362 printf(" => errno %i: %s\n => h_errno %i: %s\n => rrset_errno %i: %s\n", 363 errno, errno ? strerror(errno) : "ok", 364 h_errno, h_errno ? hstrerror(h_errno) : "ok", 365 rrset_errno, rrset_errno ? rrsetstrerror(rrset_errno) : "ok"); 366 printf(" => gai_errno %i: %s\n", 367 gai_errno, gai_errno ? gai_strerror(gai_errno) : "ok"); 368 } 369 } 370 371 372 static char * 373 print_host(const struct sockaddr *sa, char *buf, size_t len) 374 { 375 switch (sa->sa_family) { 376 case AF_INET: 377 inet_ntop(AF_INET, &((struct sockaddr_in*)sa)->sin_addr, 378 buf, len); 379 break; 380 case AF_INET6: 381 inet_ntop(AF_INET6, &((struct sockaddr_in6*)sa)->sin6_addr, 382 buf, len); 383 break; 384 default: 385 buf[0] = '\0'; 386 } 387 return (buf); 388 } 389 390 391 char * 392 print_addr(const struct sockaddr *sa, char *buf, size_t len) 393 { 394 char h[256]; 395 396 print_host(sa, h, sizeof h); 397 398 switch (sa->sa_family) { 399 case AF_INET: 400 snprintf(buf, len, "%s:%i", h, 401 ntohs(((struct sockaddr_in*)(sa))->sin_port)); 402 break; 403 case AF_INET6: 404 snprintf(buf, len, "[%s]:%i", h, 405 ntohs(((struct sockaddr_in6*)(sa))->sin6_port)); 406 break; 407 default: 408 snprintf(buf, len, "?"); 409 break; 410 } 411 412 return (buf); 413 } 414 415 void 416 packed_init(struct packed *pack, char *data, size_t len) 417 { 418 pack->data = data; 419 pack->len = len; 420 pack->offset = 0; 421 pack->err = NULL; 422 } 423 424 425 static ssize_t 426 dname_expand(const unsigned char *data, size_t len, size_t offset, 427 size_t *newoffset, char *dst, size_t max) 428 { 429 size_t n, count, end, ptr, start; 430 ssize_t res; 431 432 if (offset >= len) 433 return (-1); 434 435 res = 0; 436 end = start = offset; 437 438 for(; (n = data[offset]); ) { 439 if ((n & 0xc0) == 0xc0) { 440 if (offset + 2 > len) 441 return (-1); 442 ptr = 256 * (n & ~0xc0) + data[offset + 1]; 443 if (ptr >= start) 444 return (-1); 445 if (end < offset + 2) 446 end = offset + 2; 447 offset = ptr; 448 continue; 449 } 450 if (offset + n + 1 > len) 451 return (-1); 452 453 454 /* copy n + at offset+1 */ 455 if (dst != NULL && max != 0) { 456 count = (max < n + 1) ? (max) : (n + 1); 457 memmove(dst, data + offset, count); 458 dst += count; 459 max -= count; 460 } 461 res += n + 1; 462 offset += n + 1; 463 if (end < offset) 464 end = offset; 465 } 466 if (end < offset + 1) 467 end = offset + 1; 468 469 if (dst != NULL && max != 0) 470 dst[0] = 0; 471 if (newoffset) 472 *newoffset = end; 473 return (res + 1); 474 } 475 476 static int 477 unpack_data(struct packed *p, void *data, size_t len) 478 { 479 if (p->err) 480 return (-1); 481 482 if (p->len - p->offset < len) { 483 p->err = "too short"; 484 return (-1); 485 } 486 487 memmove(data, p->data + p->offset, len); 488 p->offset += len; 489 490 return (0); 491 } 492 493 static int 494 unpack_u16(struct packed *p, uint16_t *u16) 495 { 496 if (unpack_data(p, u16, 2) == -1) 497 return (-1); 498 499 *u16 = ntohs(*u16); 500 501 return (0); 502 } 503 504 static int 505 unpack_u32(struct packed *p, uint32_t *u32) 506 { 507 if (unpack_data(p, u32, 4) == -1) 508 return (-1); 509 510 *u32 = ntohl(*u32); 511 512 return (0); 513 } 514 515 static int 516 unpack_inaddr(struct packed *p, struct in_addr *a) 517 { 518 return (unpack_data(p, a, 4)); 519 } 520 521 static int 522 unpack_in6addr(struct packed *p, struct in6_addr *a6) 523 { 524 return (unpack_data(p, a6, 16)); 525 } 526 527 static int 528 unpack_dname(struct packed *p, char *dst, size_t max) 529 { 530 ssize_t e; 531 532 if (p->err) 533 return (-1); 534 535 e = dname_expand(p->data, p->len, p->offset, &p->offset, dst, max); 536 if (e == -1) { 537 p->err = "bad domain name"; 538 return (-1); 539 } 540 if (e < 0 || e > MAXDNAME) { 541 p->err = "domain name too long"; 542 return (-1); 543 } 544 545 return (0); 546 } 547 548 int 549 unpack_header(struct packed *p, struct header *h) 550 { 551 if (unpack_data(p, h, HFIXEDSZ) == -1) 552 return (-1); 553 554 h->flags = ntohs(h->flags); 555 h->qdcount = ntohs(h->qdcount); 556 h->ancount = ntohs(h->ancount); 557 h->nscount = ntohs(h->nscount); 558 h->arcount = ntohs(h->arcount); 559 560 return (0); 561 } 562 563 int 564 unpack_query(struct packed *p, struct query *q) 565 { 566 unpack_dname(p, q->q_dname, sizeof(q->q_dname)); 567 unpack_u16(p, &q->q_type); 568 unpack_u16(p, &q->q_class); 569 570 return (p->err) ? (-1) : (0); 571 } 572 573 int 574 unpack_rr(struct packed *p, struct rr *rr) 575 { 576 uint16_t rdlen; 577 size_t save_offset; 578 579 unpack_dname(p, rr->rr_dname, sizeof(rr->rr_dname)); 580 unpack_u16(p, &rr->rr_type); 581 unpack_u16(p, &rr->rr_class); 582 unpack_u32(p, &rr->rr_ttl); 583 unpack_u16(p, &rdlen); 584 585 if (p->err) 586 return (-1); 587 588 if (p->len - p->offset < rdlen) { 589 p->err = "too short"; 590 return (-1); 591 } 592 593 save_offset = p->offset; 594 595 switch(rr->rr_type) { 596 597 case T_CNAME: 598 unpack_dname(p, rr->rr.cname.cname, sizeof(rr->rr.cname.cname)); 599 break; 600 601 case T_MX: 602 unpack_u16(p, &rr->rr.mx.preference); 603 unpack_dname(p, rr->rr.mx.exchange, sizeof(rr->rr.mx.exchange)); 604 break; 605 606 case T_NS: 607 unpack_dname(p, rr->rr.ns.nsname, sizeof(rr->rr.ns.nsname)); 608 break; 609 610 case T_PTR: 611 unpack_dname(p, rr->rr.ptr.ptrname, sizeof(rr->rr.ptr.ptrname)); 612 break; 613 614 case T_SOA: 615 unpack_dname(p, rr->rr.soa.mname, sizeof(rr->rr.soa.mname)); 616 unpack_dname(p, rr->rr.soa.rname, sizeof(rr->rr.soa.rname)); 617 unpack_u32(p, &rr->rr.soa.serial); 618 unpack_u32(p, &rr->rr.soa.refresh); 619 unpack_u32(p, &rr->rr.soa.retry); 620 unpack_u32(p, &rr->rr.soa.expire); 621 unpack_u32(p, &rr->rr.soa.minimum); 622 break; 623 624 case T_A: 625 if (rr->rr_class != C_IN) 626 goto other; 627 unpack_inaddr(p, &rr->rr.in_a.addr); 628 break; 629 630 case T_AAAA: 631 if (rr->rr_class != C_IN) 632 goto other; 633 unpack_in6addr(p, &rr->rr.in_aaaa.addr6); 634 break; 635 default: 636 other: 637 rr->rr.other.rdata = p->data + p->offset; 638 rr->rr.other.rdlen = rdlen; 639 p->offset += rdlen; 640 } 641 642 if (p->err) 643 return (-1); 644 645 /* make sure that the advertised rdlen is really ok */ 646 if (p->offset - save_offset != rdlen) 647 p->err = "bad dlen"; 648 649 return (p->err) ? (-1) : (0); 650 } 651 652 int 653 sockaddr_from_str(struct sockaddr *sa, int family, const char *str) 654 { 655 struct in_addr ina; 656 struct in6_addr in6a; 657 struct sockaddr_in *sin; 658 struct sockaddr_in6 *sin6; 659 660 switch (family) { 661 case PF_UNSPEC: 662 if (sockaddr_from_str(sa, PF_INET, str) == 0) 663 return (0); 664 return sockaddr_from_str(sa, PF_INET6, str); 665 666 case PF_INET: 667 if (inet_pton(PF_INET, str, &ina) != 1) 668 return (-1); 669 670 sin = (struct sockaddr_in *)sa; 671 memset(sin, 0, sizeof *sin); 672 sin->sin_len = sizeof(struct sockaddr_in); 673 sin->sin_family = PF_INET; 674 sin->sin_addr.s_addr = ina.s_addr; 675 return (0); 676 677 case PF_INET6: 678 if (inet_pton(PF_INET6, str, &in6a) != 1) 679 return (-1); 680 681 sin6 = (struct sockaddr_in6 *)sa; 682 memset(sin6, 0, sizeof *sin6); 683 sin6->sin6_len = sizeof(struct sockaddr_in6); 684 sin6->sin6_family = PF_INET6; 685 sin6->sin6_addr = in6a; 686 return (0); 687 688 default: 689 break; 690 } 691 692 return (-1); 693 } 694