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