1 /* $OpenBSD: common.c,v 1.3 2014/08/10 07:31:58 guenther 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 uint16_t 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 139 const char * 140 rcodetostr(uint16_t v) 141 { 142 static char buf[16]; 143 size_t i; 144 145 for(i = 0; kv_rcode[i].key; i++) 146 if (kv_rcode[i].value == v) 147 return (kv_rcode[i].key); 148 149 snprintf(buf, sizeof buf, "%"PRIu16"?", v); 150 151 return (buf); 152 } 153 154 const char * 155 typetostr(uint16_t v) 156 { 157 static char buf[16]; 158 size_t i; 159 160 for(i = 0; kv_type[i].key; i++) 161 if (kv_type[i].value == v) 162 return (kv_type[i].key); 163 164 snprintf(buf, sizeof buf, "%"PRIu16"?", v); 165 166 return (buf); 167 } 168 169 const char * 170 classtostr(uint16_t v) 171 { 172 static char buf[16]; 173 size_t i; 174 175 for(i = 0; kv_class[i].key; i++) 176 if (kv_class[i].value == v) 177 return (kv_class[i].key); 178 179 snprintf(buf, sizeof buf, "%"PRIu16"?", v); 180 181 return (buf); 182 } 183 184 uint16_t 185 strtotype(const char *name) 186 { 187 size_t i; 188 189 for(i = 0; kv_type[i].key; i++) 190 if (!strcmp(kv_type[i].key, name)) 191 return (kv_type[i].value); 192 193 return (0); 194 } 195 196 uint16_t 197 strtoclass(const char *name) 198 { 199 size_t i; 200 201 for(i = 0; kv_class[i].key; i++) 202 if (!strcmp(kv_class[i].key, name)) 203 return (kv_class[i].value); 204 205 return (0); 206 } 207 208 void 209 print_hostent(struct hostent *e) 210 { 211 char buf[256], **c; 212 213 printf("name = \"%s\"\n", e->h_name); 214 printf("aliases ="); 215 for(c = e->h_aliases; *c; c++) 216 printf(" \"%s\"", *c); 217 printf("\n"); 218 printf("addrtype = %i\n", e->h_addrtype); 219 printf("addrlength = %i\n", e->h_length); 220 printf("addr_list ="); 221 for(c = e->h_addr_list; *c; c++) { 222 printf(" %s", inet_ntop(e->h_addrtype, *c, buf, sizeof buf)); 223 } 224 printf("\n"); 225 } 226 227 void 228 print_netent(struct netent *e) 229 { 230 char buf[256], **c; 231 uint32_t addr; 232 233 /* network number are given in host order */ 234 addr = htonl(e->n_net); 235 236 printf("name = \"%s\"\n", e->n_name); 237 printf("aliases ="); 238 for (c = e->n_aliases; *c; c++) 239 printf(" \"%s\"", *c); 240 printf("\n"); 241 printf("addrtype = %i\n", e->n_addrtype); 242 printf("net = %s\n", inet_ntop(e->n_addrtype, &addr, buf, sizeof buf)); 243 } 244 245 void 246 print_addrinfo(struct addrinfo *ai) 247 { 248 char buf[256], bf[64], bt[64], bp[64]; 249 250 printf("family=%s socktype=%s protocol=%s addr=%s canonname=%s\n", 251 kv_lookup_name(kv_family, ai->ai_family, bf, sizeof bf), 252 kv_lookup_name(kv_socktype, ai->ai_socktype, bt, sizeof bt), 253 kv_lookup_name(kv_protocol, ai->ai_protocol, bp, sizeof bp), 254 print_addr(ai->ai_addr, buf, sizeof buf), 255 ai->ai_canonname); 256 } 257 258 const char * 259 rrsetstrerror(int e) 260 { 261 switch (e) { 262 case 0: 263 return "OK"; 264 case ERRSET_NONAME: 265 return "ERRSET_NONAME"; 266 case ERRSET_NODATA: 267 return "ERRSET_NODATA"; 268 case ERRSET_NOMEMORY: 269 return "ERRSET_NOMEMORY"; 270 case ERRSET_INVAL: 271 return "ERRSET_INVAL"; 272 case ERRSET_FAIL: 273 return "ERRSET_FAIL"; 274 default: 275 return "???"; 276 } 277 } 278 279 void 280 print_rrsetinfo(struct rrsetinfo * rrset) 281 { 282 printf("rri_flags=%u\n", rrset->rri_flags); 283 printf("rri_rdclass=%u\n", rrset->rri_rdclass); 284 printf("rri_rdtype=%u\n", rrset->rri_rdtype); 285 printf("rri_ttl=%u\n", rrset->rri_ttl); 286 printf("rri_nrdatas=%u\n", rrset->rri_nrdatas); 287 printf("rri_nsigs=%u\n", rrset->rri_nsigs); 288 printf("rri_name=\"%s\"\n", rrset->rri_name); 289 } 290 291 void 292 print_errors(void) 293 { 294 switch (long_err) { 295 case 0: 296 return; 297 case 1: 298 printf(" => errno %i, h_errno %i", errno, h_errno); 299 printf(", rrset_errno %i", rrset_errno); 300 printf(", gai_errno %i", gai_errno); 301 printf ("\n"); 302 return; 303 default: 304 printf(" => errno %i: %s\n => h_errno %i: %s\n => rrset_errno %i: %s\n", 305 errno, errno ? strerror(errno) : "ok", 306 h_errno, h_errno ? hstrerror(h_errno) : "ok", 307 rrset_errno, rrset_errno ? rrsetstrerror(rrset_errno) : "ok"); 308 printf(" => gai_errno %i: %s\n", 309 gai_errno, gai_errno ? gai_strerror(gai_errno) : "ok"); 310 } 311 } 312 313 314 static char * 315 print_host(const struct sockaddr *sa, char *buf, size_t len) 316 { 317 switch (sa->sa_family) { 318 case AF_INET: 319 inet_ntop(AF_INET, &((struct sockaddr_in*)sa)->sin_addr, 320 buf, len); 321 break; 322 case AF_INET6: 323 inet_ntop(AF_INET6, &((struct sockaddr_in6*)sa)->sin6_addr, 324 buf, len); 325 break; 326 default: 327 buf[0] = '\0'; 328 } 329 return (buf); 330 } 331 332 333 char * 334 print_addr(const struct sockaddr *sa, char *buf, size_t len) 335 { 336 char h[256]; 337 338 print_host(sa, h, sizeof h); 339 340 switch (sa->sa_family) { 341 case AF_INET: 342 snprintf(buf, len, "%s:%i", h, 343 ntohs(((struct sockaddr_in*)(sa))->sin_port)); 344 break; 345 case AF_INET6: 346 snprintf(buf, len, "[%s]:%i", h, 347 ntohs(((struct sockaddr_in6*)(sa))->sin6_port)); 348 break; 349 default: 350 snprintf(buf, len, "?"); 351 break; 352 } 353 354 return (buf); 355 } 356 357 void 358 packed_init(struct packed *pack, char *data, size_t len) 359 { 360 pack->data = data; 361 pack->len = len; 362 pack->offset = 0; 363 pack->err = NULL; 364 } 365 366 367 static ssize_t 368 dname_expand(const unsigned char *data, size_t len, size_t offset, 369 size_t *newoffset, char *dst, size_t max) 370 { 371 size_t n, count, end, ptr, start; 372 ssize_t res; 373 374 if (offset >= len) 375 return (-1); 376 377 res = 0; 378 end = start = offset; 379 380 for(; (n = data[offset]); ) { 381 if ((n & 0xc0) == 0xc0) { 382 if (offset + 2 > len) 383 return (-1); 384 ptr = 256 * (n & ~0xc0) + data[offset + 1]; 385 if (ptr >= start) 386 return (-1); 387 if (end < offset + 2) 388 end = offset + 2; 389 offset = ptr; 390 continue; 391 } 392 if (offset + n + 1 > len) 393 return (-1); 394 395 396 /* copy n + at offset+1 */ 397 if (dst != NULL && max != 0) { 398 count = (max < n + 1) ? (max) : (n + 1); 399 memmove(dst, data + offset, count); 400 dst += count; 401 max -= count; 402 } 403 res += n + 1; 404 offset += n + 1; 405 if (end < offset) 406 end = offset; 407 } 408 if (end < offset + 1) 409 end = offset + 1; 410 411 if (dst != NULL && max != 0) 412 dst[0] = 0; 413 if (newoffset) 414 *newoffset = end; 415 return (res + 1); 416 } 417 418 static int 419 unpack_data(struct packed *p, void *data, size_t len) 420 { 421 if (p->err) 422 return (-1); 423 424 if (p->len - p->offset < len) { 425 p->err = "too short"; 426 return (-1); 427 } 428 429 memmove(data, p->data + p->offset, len); 430 p->offset += len; 431 432 return (0); 433 } 434 435 static int 436 unpack_u16(struct packed *p, uint16_t *u16) 437 { 438 if (unpack_data(p, u16, 2) == -1) 439 return (-1); 440 441 *u16 = ntohs(*u16); 442 443 return (0); 444 } 445 446 static int 447 unpack_u32(struct packed *p, uint32_t *u32) 448 { 449 if (unpack_data(p, u32, 4) == -1) 450 return (-1); 451 452 *u32 = ntohl(*u32); 453 454 return (0); 455 } 456 457 static int 458 unpack_inaddr(struct packed *p, struct in_addr *a) 459 { 460 return (unpack_data(p, a, 4)); 461 } 462 463 static int 464 unpack_in6addr(struct packed *p, struct in6_addr *a6) 465 { 466 return (unpack_data(p, a6, 16)); 467 } 468 469 static int 470 unpack_dname(struct packed *p, char *dst, size_t max) 471 { 472 ssize_t e; 473 474 if (p->err) 475 return (-1); 476 477 e = dname_expand(p->data, p->len, p->offset, &p->offset, dst, max); 478 if (e == -1) { 479 p->err = "bad domain name"; 480 return (-1); 481 } 482 if (e < 0 || e > MAXDNAME) { 483 p->err = "domain name too long"; 484 return (-1); 485 } 486 487 return (0); 488 } 489 490 int 491 unpack_header(struct packed *p, struct header *h) 492 { 493 if (unpack_data(p, h, HFIXEDSZ) == -1) 494 return (-1); 495 496 h->flags = ntohs(h->flags); 497 h->qdcount = ntohs(h->qdcount); 498 h->ancount = ntohs(h->ancount); 499 h->nscount = ntohs(h->nscount); 500 h->arcount = ntohs(h->arcount); 501 502 return (0); 503 } 504 505 int 506 unpack_query(struct packed *p, struct query *q) 507 { 508 unpack_dname(p, q->q_dname, sizeof(q->q_dname)); 509 unpack_u16(p, &q->q_type); 510 unpack_u16(p, &q->q_class); 511 512 return (p->err) ? (-1) : (0); 513 } 514 515 int 516 unpack_rr(struct packed *p, struct rr *rr) 517 { 518 uint16_t rdlen; 519 size_t save_offset; 520 521 unpack_dname(p, rr->rr_dname, sizeof(rr->rr_dname)); 522 unpack_u16(p, &rr->rr_type); 523 unpack_u16(p, &rr->rr_class); 524 unpack_u32(p, &rr->rr_ttl); 525 unpack_u16(p, &rdlen); 526 527 if (p->err) 528 return (-1); 529 530 if (p->len - p->offset < rdlen) { 531 p->err = "too short"; 532 return (-1); 533 } 534 535 save_offset = p->offset; 536 537 switch(rr->rr_type) { 538 539 case T_CNAME: 540 unpack_dname(p, rr->rr.cname.cname, sizeof(rr->rr.cname.cname)); 541 break; 542 543 case T_MX: 544 unpack_u16(p, &rr->rr.mx.preference); 545 unpack_dname(p, rr->rr.mx.exchange, sizeof(rr->rr.mx.exchange)); 546 break; 547 548 case T_NS: 549 unpack_dname(p, rr->rr.ns.nsname, sizeof(rr->rr.ns.nsname)); 550 break; 551 552 case T_PTR: 553 unpack_dname(p, rr->rr.ptr.ptrname, sizeof(rr->rr.ptr.ptrname)); 554 break; 555 556 case T_SOA: 557 unpack_dname(p, rr->rr.soa.mname, sizeof(rr->rr.soa.mname)); 558 unpack_dname(p, rr->rr.soa.rname, sizeof(rr->rr.soa.rname)); 559 unpack_u32(p, &rr->rr.soa.serial); 560 unpack_u32(p, &rr->rr.soa.refresh); 561 unpack_u32(p, &rr->rr.soa.retry); 562 unpack_u32(p, &rr->rr.soa.expire); 563 unpack_u32(p, &rr->rr.soa.minimum); 564 break; 565 566 case T_A: 567 if (rr->rr_class != C_IN) 568 goto other; 569 unpack_inaddr(p, &rr->rr.in_a.addr); 570 break; 571 572 case T_AAAA: 573 if (rr->rr_class != C_IN) 574 goto other; 575 unpack_in6addr(p, &rr->rr.in_aaaa.addr6); 576 break; 577 default: 578 other: 579 rr->rr.other.rdata = p->data + p->offset; 580 rr->rr.other.rdlen = rdlen; 581 p->offset += rdlen; 582 } 583 584 if (p->err) 585 return (-1); 586 587 /* make sure that the advertised rdlen is really ok */ 588 if (p->offset - save_offset != rdlen) 589 p->err = "bad dlen"; 590 591 return (p->err) ? (-1) : (0); 592 } 593 594 int 595 sockaddr_from_str(struct sockaddr *sa, int family, const char *str) 596 { 597 struct in_addr ina; 598 struct in6_addr in6a; 599 struct sockaddr_in *sin; 600 struct sockaddr_in6 *sin6; 601 602 switch (family) { 603 case PF_UNSPEC: 604 if (sockaddr_from_str(sa, PF_INET, str) == 0) 605 return (0); 606 return sockaddr_from_str(sa, PF_INET6, str); 607 608 case PF_INET: 609 if (inet_pton(PF_INET, str, &ina) != 1) 610 return (-1); 611 612 sin = (struct sockaddr_in *)sa; 613 memset(sin, 0, sizeof *sin); 614 sin->sin_len = sizeof(struct sockaddr_in); 615 sin->sin_family = PF_INET; 616 sin->sin_addr.s_addr = ina.s_addr; 617 return (0); 618 619 case PF_INET6: 620 if (inet_pton(PF_INET6, str, &in6a) != 1) 621 return (-1); 622 623 sin6 = (struct sockaddr_in6 *)sa; 624 memset(sin6, 0, sizeof *sin6); 625 sin6->sin6_len = sizeof(struct sockaddr_in6); 626 sin6->sin6_family = PF_INET6; 627 sin6->sin6_addr = in6a; 628 return (0); 629 630 default: 631 break; 632 } 633 634 return (-1); 635 } 636