1 /* 2 * Copyright (c) 2014 Andreas Schneider <asn@samba.org> 3 * Copyright (c) 2014 Jakub Hrozek <jakub.hrozek@posteo.se> 4 * 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * 3. Neither the name of the author nor the names of its contributors 19 * may be used to endorse or promote products derived from this software 20 * without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 */ 34 35 #include "config.h" 36 37 #include <errno.h> 38 #include <arpa/inet.h> 39 #ifdef HAVE_ARPA_NAMESER_H 40 #include <arpa/nameser.h> 41 #endif /* HAVE_ARPA_NAMESER_H */ 42 #include <netinet/in.h> 43 #include <sys/socket.h> 44 #include <sys/types.h> 45 #include <stdarg.h> 46 #include <stdlib.h> 47 #include <stdio.h> 48 #include <stdbool.h> 49 #include <string.h> 50 #include <unistd.h> 51 #include <ctype.h> 52 53 #include <resolv.h> 54 55 /* GCC has printf type attribute check. */ 56 #ifdef HAVE_ATTRIBUTE_PRINTF_FORMAT 57 #define PRINTF_ATTRIBUTE(a,b) __attribute__ ((__format__ (__printf__, a, b))) 58 #else 59 #define PRINTF_ATTRIBUTE(a,b) 60 #endif /* HAVE_ATTRIBUTE_PRINTF_FORMAT */ 61 62 #ifdef HAVE_DESTRUCTOR_ATTRIBUTE 63 #define DESTRUCTOR_ATTRIBUTE __attribute__ ((destructor)) 64 #else 65 #define DESTRUCTOR_ATTRIBUTE 66 #endif /* HAVE_DESTRUCTOR_ATTRIBUTE */ 67 68 #ifndef RWRAP_DEFAULT_FAKE_TTL 69 #define RWRAP_DEFAULT_FAKE_TTL 600 70 #endif /* RWRAP_DEFAULT_FAKE_TTL */ 71 72 #ifndef HAVE_NS_NAME_COMPRESS 73 #define ns_name_compress dn_comp 74 #endif 75 76 enum rwrap_dbglvl_e { 77 RWRAP_LOG_ERROR = 0, 78 RWRAP_LOG_WARN, 79 RWRAP_LOG_DEBUG, 80 RWRAP_LOG_TRACE 81 }; 82 83 #ifdef NDEBUG 84 # define RWRAP_LOG(...) 85 #else /* NDEBUG */ 86 87 static void rwrap_log(enum rwrap_dbglvl_e dbglvl, const char *func, const char *format, ...) PRINTF_ATTRIBUTE(3, 4); 88 # define RWRAP_LOG(dbglvl, ...) rwrap_log((dbglvl), __func__, __VA_ARGS__) 89 90 static void rwrap_log(enum rwrap_dbglvl_e dbglvl, 91 const char *func, 92 const char *format, ...) 93 { 94 char buffer[1024]; 95 va_list va; 96 const char *d; 97 unsigned int lvl = 0; 98 int pid = getpid(); 99 100 d = getenv("RESOLV_WRAPPER_DEBUGLEVEL"); 101 if (d != NULL) { 102 lvl = atoi(d); 103 } 104 105 va_start(va, format); 106 vsnprintf(buffer, sizeof(buffer), format, va); 107 va_end(va); 108 109 if (lvl >= dbglvl) { 110 switch (dbglvl) { 111 case RWRAP_LOG_ERROR: 112 fprintf(stderr, 113 "RWRAP_ERROR(%d) - %s: %s\n", 114 pid, func, buffer); 115 break; 116 case RWRAP_LOG_WARN: 117 fprintf(stderr, 118 "RWRAP_WARN(%d) - %s: %s\n", 119 pid, func, buffer); 120 break; 121 case RWRAP_LOG_DEBUG: 122 fprintf(stderr, 123 "RWRAP_DEBUG(%d) - %s: %s\n", 124 pid, func, buffer); 125 break; 126 case RWRAP_LOG_TRACE: 127 fprintf(stderr, 128 "RWRAP_TRACE(%d) - %s: %s\n", 129 pid, func, buffer); 130 break; 131 } 132 } 133 } 134 #endif /* NDEBUG RWRAP_LOG */ 135 136 #ifndef SAFE_FREE 137 #define SAFE_FREE(x) do { if ((x) != NULL) {free(x); (x)=NULL;} } while(0) 138 #endif 139 140 #define NEXT_KEY(buf, key) do { \ 141 (key) = (buf) ? strpbrk((buf), " \t") : NULL; \ 142 if ((key) != NULL) { \ 143 (key)[0] = '\0'; \ 144 (key)++; \ 145 } \ 146 while ((key) != NULL \ 147 && (isblank((int)(key)[0]))) { \ 148 (key)++; \ 149 } \ 150 } while(0); 151 152 #define RWRAP_MAX_RECURSION 5 153 154 /* Priority and weight can be omitted from the hosts file, but need to be part 155 * of the output 156 */ 157 #define DFL_SRV_PRIO 1 158 #define DFL_SRV_WEIGHT 100 159 160 struct rwrap_srv_rrdata { 161 uint16_t port; 162 uint16_t prio; 163 uint16_t weight; 164 char hostname[MAXDNAME]; 165 }; 166 167 struct rwrap_soa_rrdata { 168 uint32_t serial; 169 uint32_t refresh; 170 uint32_t retry; 171 uint32_t expire; 172 uint32_t minimum; 173 char nameserver[MAXDNAME]; 174 char mailbox[MAXDNAME]; 175 }; 176 177 struct rwrap_fake_rr { 178 union fake_rrdata { 179 struct in_addr a_rec; 180 struct in6_addr aaaa_rec; 181 struct rwrap_srv_rrdata srv_rec; 182 struct rwrap_soa_rrdata soa_rec; 183 char cname_rec[MAXDNAME]; 184 } rrdata; 185 186 char key[MAXDNAME]; 187 int type; /* ns_t_* */ 188 }; 189 190 static void rwrap_fake_rr_init(struct rwrap_fake_rr *rr, size_t len) 191 { 192 size_t i; 193 194 for (i = 0; i < len; i++) { 195 rr[i].type = ns_t_invalid; 196 } 197 } 198 199 static int rwrap_create_fake_a_rr(const char *key, 200 const char *value, 201 struct rwrap_fake_rr *rr) 202 { 203 int ok; 204 205 ok = inet_pton(AF_INET, value, &rr->rrdata.a_rec); 206 if (!ok) { 207 RWRAP_LOG(RWRAP_LOG_ERROR, 208 "Failed to convert [%s] to binary\n", value); 209 return -1; 210 } 211 212 memcpy(rr->key, key, strlen(key) + 1); 213 rr->type = ns_t_a; 214 return 0; 215 } 216 217 static int rwrap_create_fake_aaaa_rr(const char *key, 218 const char *value, 219 struct rwrap_fake_rr *rr) 220 { 221 int ok; 222 223 ok = inet_pton(AF_INET6, value, &rr->rrdata.aaaa_rec); 224 if (!ok) { 225 RWRAP_LOG(RWRAP_LOG_ERROR, 226 "Failed to convert [%s] to binary\n", value); 227 return -1; 228 } 229 230 memcpy(rr->key, key, strlen(key) + 1); 231 rr->type = ns_t_aaaa; 232 return 0; 233 } 234 static int rwrap_create_fake_ns_rr(const char *key, 235 const char *value, 236 struct rwrap_fake_rr *rr) 237 { 238 memcpy(rr->rrdata.srv_rec.hostname, value, strlen(value) + 1); 239 memcpy(rr->key, key, strlen(key) + 1); 240 rr->type = ns_t_ns; 241 return 0; 242 } 243 244 static int rwrap_create_fake_srv_rr(const char *key, 245 const char *value, 246 struct rwrap_fake_rr *rr) 247 { 248 char *str_prio; 249 char *str_weight; 250 char *str_port; 251 const char *hostname; 252 253 /* parse the value into priority, weight, port and hostname 254 * and check the validity */ 255 hostname = value; 256 NEXT_KEY(hostname, str_port); 257 NEXT_KEY(str_port, str_prio); 258 NEXT_KEY(str_prio, str_weight); 259 if (str_port == NULL || hostname == NULL) { 260 RWRAP_LOG(RWRAP_LOG_ERROR, 261 "Malformed SRV entry [%s]\n", value); 262 return -1; 263 } 264 265 if (str_prio) { 266 rr->rrdata.srv_rec.prio = atoi(str_prio); 267 } else { 268 rr->rrdata.srv_rec.prio = DFL_SRV_PRIO; 269 } 270 if (str_weight) { 271 rr->rrdata.srv_rec.weight = atoi(str_weight); 272 } else { 273 rr->rrdata.srv_rec.weight = DFL_SRV_WEIGHT; 274 } 275 rr->rrdata.srv_rec.port = atoi(str_port); 276 memcpy(rr->rrdata.srv_rec.hostname , hostname, strlen(hostname) + 1); 277 278 memcpy(rr->key, key, strlen(key) + 1); 279 rr->type = ns_t_srv; 280 return 0; 281 } 282 283 static int rwrap_create_fake_soa_rr(const char *key, 284 const char *value, 285 struct rwrap_fake_rr *rr) 286 { 287 const char *nameserver; 288 char *mailbox; 289 char *str_serial; 290 char *str_refresh; 291 char *str_retry; 292 char *str_expire; 293 char *str_minimum; 294 295 /* parse the value into nameserver, mailbox, serial, refresh, 296 * retry, expire, minimum and check the validity 297 */ 298 nameserver = value; 299 NEXT_KEY(nameserver, mailbox); 300 NEXT_KEY(mailbox, str_serial); 301 NEXT_KEY(str_serial, str_refresh); 302 NEXT_KEY(str_refresh, str_retry); 303 NEXT_KEY(str_retry, str_expire); 304 NEXT_KEY(str_expire, str_minimum); 305 if (nameserver == NULL || mailbox == NULL || str_serial == NULL || 306 str_refresh == NULL || str_retry == NULL || str_expire == NULL || 307 str_minimum == NULL) { 308 RWRAP_LOG(RWRAP_LOG_ERROR, 309 "Malformed SOA entry [%s]\n", value); 310 return -1; 311 } 312 313 memcpy(rr->rrdata.soa_rec.nameserver, nameserver, strlen(nameserver)+1); 314 memcpy(rr->rrdata.soa_rec.mailbox, mailbox, strlen(mailbox)+1); 315 316 rr->rrdata.soa_rec.serial = atoi(str_serial); 317 rr->rrdata.soa_rec.refresh = atoi(str_refresh); 318 rr->rrdata.soa_rec.retry = atoi(str_retry); 319 rr->rrdata.soa_rec.expire = atoi(str_expire); 320 rr->rrdata.soa_rec.minimum = atoi(str_minimum); 321 322 memcpy(rr->key, key, strlen(key) + 1); 323 rr->type = ns_t_soa; 324 return 0; 325 } 326 327 static int rwrap_create_fake_cname_rr(const char *key, 328 const char *value, 329 struct rwrap_fake_rr *rr) 330 { 331 memcpy(rr->rrdata.cname_rec , value, strlen(value) + 1); 332 memcpy(rr->key, key, strlen(key) + 1); 333 rr->type = ns_t_cname; 334 return 0; 335 } 336 337 /* Prepares a fake header with a single response. Advances header_blob */ 338 static ssize_t rwrap_fake_header(uint8_t **header_blob, size_t remaining, 339 size_t ancount, size_t arcount) 340 { 341 uint8_t *hb; 342 HEADER *h; 343 344 if (remaining < NS_HFIXEDSZ) { 345 RWRAP_LOG(RWRAP_LOG_ERROR, "Buffer too small!\n"); 346 return -1; 347 } 348 349 hb = *header_blob; 350 memset(hb, 0, NS_HFIXEDSZ); 351 352 h = (HEADER *) hb; 353 h->id = res_randomid(); /* random query ID */ 354 h->qr = 1; /* response flag */ 355 h->rd = 1; /* recursion desired */ 356 h->ra = 1; /* recursion available */ 357 358 h->qdcount = htons(1); /* no. of questions */ 359 h->ancount = htons(ancount); /* no. of answers */ 360 h->arcount = htons(arcount); /* no. of add'tl records */ 361 362 hb += NS_HFIXEDSZ; /* move past the header */ 363 *header_blob = hb; 364 365 return NS_HFIXEDSZ; 366 } 367 368 static ssize_t rwrap_fake_question(const char *question, 369 uint16_t type, 370 uint8_t **question_ptr, 371 size_t remaining) 372 { 373 uint8_t *qb = *question_ptr; 374 int n; 375 376 n = ns_name_compress(question, qb, remaining, NULL, NULL); 377 if (n < 0) { 378 RWRAP_LOG(RWRAP_LOG_ERROR, 379 "Failed to compress [%s]\n", question); 380 return -1; 381 } 382 383 qb += n; 384 remaining -= n; 385 386 if (remaining < 2 * sizeof(uint16_t)) { 387 RWRAP_LOG(RWRAP_LOG_ERROR, "Buffer too small!\n"); 388 return -1; 389 } 390 391 NS_PUT16(type, qb); 392 NS_PUT16(ns_c_in, qb); 393 394 *question_ptr = qb; 395 return n + 2 * sizeof(uint16_t); 396 } 397 398 static ssize_t rwrap_fake_rdata_common(uint16_t type, 399 size_t rdata_size, 400 const char *key, 401 size_t remaining, 402 uint8_t **rdata_ptr) 403 { 404 uint8_t *rd = *rdata_ptr; 405 ssize_t written = 0; 406 407 written = ns_name_compress(key, rd, remaining, NULL, NULL); 408 if (written < 0) { 409 RWRAP_LOG(RWRAP_LOG_ERROR, 410 "Failed to compress [%s]\n", key); 411 return -1; 412 } 413 rd += written; 414 remaining -= written; 415 416 if (remaining < 3 * sizeof(uint16_t) + sizeof(uint32_t)) { 417 RWRAP_LOG(RWRAP_LOG_ERROR, "Buffer too small\n"); 418 return -1; 419 } 420 421 NS_PUT16(type, rd); 422 NS_PUT16(ns_c_in, rd); 423 NS_PUT32(RWRAP_DEFAULT_FAKE_TTL, rd); 424 NS_PUT16(rdata_size, rd); 425 426 if (remaining < rdata_size) { 427 RWRAP_LOG(RWRAP_LOG_ERROR, "Buffer too small\n"); 428 return -1; 429 } 430 431 *rdata_ptr = rd; 432 return written + 3 * sizeof(uint16_t) + sizeof(uint32_t) + rdata_size; 433 } 434 435 static ssize_t rwrap_fake_a(struct rwrap_fake_rr *rr, 436 uint8_t *answer_ptr, 437 size_t anslen) 438 { 439 uint8_t *a = answer_ptr; 440 ssize_t resp_size; 441 442 if (rr == NULL || rr->type != ns_t_a) { 443 RWRAP_LOG(RWRAP_LOG_ERROR, 444 "Malformed record, no or wrong value!\n"); 445 return -1; 446 } 447 RWRAP_LOG(RWRAP_LOG_TRACE, "Adding A RR"); 448 449 resp_size = rwrap_fake_rdata_common(ns_t_a, sizeof(struct in_addr), rr->key, 450 anslen, &a); 451 if (resp_size < 0) { 452 return -1; 453 } 454 455 memcpy(a, &rr->rrdata.a_rec, sizeof(struct in_addr)); 456 457 return resp_size; 458 } 459 460 static ssize_t rwrap_fake_aaaa(struct rwrap_fake_rr *rr, 461 uint8_t *answer, 462 size_t anslen) 463 { 464 uint8_t *a = answer; 465 ssize_t resp_size; 466 467 if (rr == NULL || rr->type != ns_t_aaaa) { 468 RWRAP_LOG(RWRAP_LOG_ERROR, 469 "Malformed record, no or wrong value!\n"); 470 return -1; 471 } 472 RWRAP_LOG(RWRAP_LOG_TRACE, "Adding AAAA RR"); 473 474 resp_size = rwrap_fake_rdata_common(ns_t_aaaa, sizeof(struct in6_addr), 475 rr->key, anslen, &a); 476 if (resp_size < 0) { 477 return -1; 478 } 479 480 memcpy(a, &rr->rrdata.aaaa_rec, sizeof(struct in6_addr)); 481 482 return resp_size; 483 } 484 485 static ssize_t rwrap_fake_ns(struct rwrap_fake_rr *rr, 486 uint8_t *answer, 487 size_t anslen) 488 { 489 uint8_t *a = answer; 490 ssize_t resp_size = 0; 491 size_t rdata_size; 492 unsigned char hostname_compressed[MAXDNAME]; 493 ssize_t compressed_len; 494 495 if (rr == NULL || rr->type != ns_t_ns) { 496 RWRAP_LOG(RWRAP_LOG_ERROR, 497 "Malformed record, no or wrong value!\n"); 498 return -1; 499 } 500 RWRAP_LOG(RWRAP_LOG_TRACE, "Adding NS RR"); 501 502 /* Prepare the data to write */ 503 compressed_len = ns_name_compress(rr->rrdata.srv_rec.hostname, 504 hostname_compressed, 505 MAXDNAME, 506 NULL, 507 NULL); 508 if (compressed_len < 0) { 509 return -1; 510 } 511 512 /* Is this enough? */ 513 rdata_size = compressed_len; 514 515 resp_size = rwrap_fake_rdata_common(ns_t_ns, rdata_size, 516 rr->key, anslen, &a); 517 if (resp_size < 0) { 518 return -1; 519 } 520 521 memcpy(a, hostname_compressed, compressed_len); 522 523 return resp_size; 524 } 525 526 static ssize_t rwrap_fake_srv(struct rwrap_fake_rr *rr, 527 uint8_t *answer, 528 size_t anslen) 529 { 530 uint8_t *a = answer; 531 ssize_t resp_size; 532 size_t rdata_size; 533 unsigned char hostname_compressed[MAXDNAME]; 534 ssize_t compressed_len; 535 536 if (rr == NULL || rr->type != ns_t_srv) { 537 RWRAP_LOG(RWRAP_LOG_ERROR, 538 "Malformed record, no or wrong value!\n"); 539 return -1; 540 } 541 RWRAP_LOG(RWRAP_LOG_TRACE, "Adding SRV RR"); 542 rdata_size = 3 * sizeof(uint16_t); 543 544 /* Prepare the data to write */ 545 compressed_len = ns_name_compress(rr->rrdata.srv_rec.hostname, 546 hostname_compressed, MAXDNAME, 547 NULL, NULL); 548 if (compressed_len < 0) { 549 return -1; 550 } 551 rdata_size += compressed_len; 552 553 resp_size = rwrap_fake_rdata_common(ns_t_srv, rdata_size, 554 rr->key, anslen, &a); 555 if (resp_size < 0) { 556 return -1; 557 } 558 559 NS_PUT16(rr->rrdata.srv_rec.prio, a); 560 NS_PUT16(rr->rrdata.srv_rec.weight, a); 561 NS_PUT16(rr->rrdata.srv_rec.port, a); 562 memcpy(a, hostname_compressed, compressed_len); 563 564 return resp_size; 565 } 566 567 static ssize_t rwrap_fake_soa(struct rwrap_fake_rr *rr, 568 uint8_t *answer, 569 size_t anslen) 570 { 571 uint8_t *a = answer; 572 ssize_t resp_size; 573 size_t rdata_size; 574 unsigned char nameser_compressed[MAXDNAME]; 575 ssize_t compressed_ns_len; 576 unsigned char mailbox_compressed[MAXDNAME]; 577 ssize_t compressed_mb_len; 578 579 if (rr == NULL || rr->type != ns_t_soa) { 580 RWRAP_LOG(RWRAP_LOG_ERROR, 581 "Malformed record, no or wrong value!\n"); 582 return -1; 583 } 584 RWRAP_LOG(RWRAP_LOG_TRACE, "Adding SOA RR"); 585 rdata_size = 5 * sizeof(uint16_t); 586 587 compressed_ns_len = ns_name_compress(rr->rrdata.soa_rec.nameserver, 588 nameser_compressed, 589 MAXDNAME, NULL, NULL); 590 if (compressed_ns_len < 0) { 591 return -1; 592 } 593 rdata_size += compressed_ns_len; 594 595 compressed_mb_len = ns_name_compress(rr->rrdata.soa_rec.mailbox, 596 mailbox_compressed, 597 MAXDNAME, NULL, NULL); 598 if (compressed_mb_len < 0) { 599 return -1; 600 } 601 rdata_size += compressed_mb_len; 602 603 resp_size = rwrap_fake_rdata_common(ns_t_soa, rdata_size, 604 rr->key, anslen, &a); 605 if (resp_size < 0) { 606 return -1; 607 } 608 609 memcpy(a, nameser_compressed, compressed_ns_len); 610 a += compressed_ns_len; 611 memcpy(a, mailbox_compressed, compressed_mb_len); 612 a += compressed_mb_len; 613 NS_PUT32(rr->rrdata.soa_rec.serial, a); 614 NS_PUT32(rr->rrdata.soa_rec.refresh, a); 615 NS_PUT32(rr->rrdata.soa_rec.retry, a); 616 NS_PUT32(rr->rrdata.soa_rec.expire, a); 617 NS_PUT32(rr->rrdata.soa_rec.minimum, a); 618 619 return resp_size; 620 } 621 622 static ssize_t rwrap_fake_cname(struct rwrap_fake_rr *rr, 623 uint8_t *answer, 624 size_t anslen) 625 { 626 uint8_t *a = answer; 627 ssize_t resp_size; 628 unsigned char hostname_compressed[MAXDNAME]; 629 ssize_t rdata_size; 630 631 if (rr == NULL || rr->type != ns_t_cname) { 632 RWRAP_LOG(RWRAP_LOG_ERROR, 633 "Malformed record, no or wrong value!\n"); 634 return -1; 635 } 636 RWRAP_LOG(RWRAP_LOG_TRACE, "Adding CNAME RR"); 637 638 /* Prepare the data to write */ 639 rdata_size = ns_name_compress(rr->rrdata.cname_rec, 640 hostname_compressed, MAXDNAME, 641 NULL, NULL); 642 if (rdata_size < 0) { 643 return -1; 644 } 645 646 resp_size = rwrap_fake_rdata_common(ns_t_cname, rdata_size, 647 rr->key, anslen, &a); 648 if (resp_size < 0) { 649 return -1; 650 } 651 652 memcpy(a, hostname_compressed, rdata_size); 653 654 return resp_size; 655 } 656 657 #define RESOLV_MATCH(line, name) \ 658 (strncmp(line, name, sizeof(name) - 1) == 0 && \ 659 (line[sizeof(name) - 1] == ' ' || \ 660 line[sizeof(name) - 1] == '\t')) 661 662 #define TYPE_MATCH(type, ns_type, rec_type, str_type, key, query) \ 663 ((type) == (ns_type) && \ 664 (strncmp((rec_type), (str_type), sizeof(str_type)) == 0) && \ 665 (strcasecmp(key, query)) == 0) 666 667 668 static int rwrap_get_record(const char *hostfile, unsigned recursion, 669 const char *query, int type, 670 struct rwrap_fake_rr *rr); 671 672 static int rwrap_srv_recurse(const char *hostfile, unsigned recursion, 673 const char *query, struct rwrap_fake_rr *rr) 674 { 675 int rc; 676 677 rc = rwrap_get_record(hostfile, recursion, query, ns_t_a, rr); 678 if (rc == 0) return 0; 679 680 rc = rwrap_get_record(hostfile, recursion, query, ns_t_aaaa, rr); 681 if (rc == ENOENT) rc = 0; 682 683 return rc; 684 } 685 686 static int rwrap_cname_recurse(const char *hostfile, unsigned recursion, 687 const char *query, struct rwrap_fake_rr *rr) 688 { 689 int rc; 690 691 rc = rwrap_get_record(hostfile, recursion, query, ns_t_a, rr); 692 if (rc == 0) return 0; 693 694 rc = rwrap_get_record(hostfile, recursion, query, ns_t_aaaa, rr); 695 if (rc == 0) return 0; 696 697 rc = rwrap_get_record(hostfile, recursion, query, ns_t_cname, rr); 698 if (rc == ENOENT) rc = 0; 699 700 return rc; 701 } 702 703 static int rwrap_get_record(const char *hostfile, unsigned recursion, 704 const char *query, int type, 705 struct rwrap_fake_rr *rr) 706 { 707 FILE *fp = NULL; 708 char buf[BUFSIZ]; 709 char *key = NULL; 710 char *value = NULL; 711 int rc = ENOENT; 712 713 if (recursion >= RWRAP_MAX_RECURSION) { 714 RWRAP_LOG(RWRAP_LOG_ERROR, "Recursed too deep!\n"); 715 return -1; 716 } 717 718 RWRAP_LOG(RWRAP_LOG_TRACE, 719 "Searching in fake hosts file %s for %s:%d\n", hostfile, 720 query, type); 721 722 fp = fopen(hostfile, "r"); 723 if (fp == NULL) { 724 RWRAP_LOG(RWRAP_LOG_ERROR, 725 "Opening %s failed: %s", 726 hostfile, strerror(errno)); 727 return -1; 728 } 729 730 while (fgets(buf, sizeof(buf), fp) != NULL) { 731 char *rec_type; 732 char *q; 733 734 rec_type = buf; 735 key = value = NULL; 736 737 NEXT_KEY(rec_type, key); 738 NEXT_KEY(key, value); 739 740 if (key == NULL || value == NULL) { 741 RWRAP_LOG(RWRAP_LOG_WARN, 742 "Malformed line: not enough parts, use \"rec_type key data\n" 743 "For example \"A cwrap.org 10.10.10.10\""); 744 continue; 745 } 746 747 q = value; 748 while(q[0] != '\n' && q[0] != '\0') { 749 q++; 750 } 751 q[0] = '\0'; 752 753 if (TYPE_MATCH(type, ns_t_a, rec_type, "A", key, query)) { 754 rc = rwrap_create_fake_a_rr(key, value, rr); 755 break; 756 } else if (TYPE_MATCH(type, ns_t_aaaa, 757 rec_type, "AAAA", key, query)) { 758 rc = rwrap_create_fake_aaaa_rr(key, value, rr); 759 break; 760 } else if (TYPE_MATCH(type, ns_t_ns, 761 rec_type, "NS", key, query)) { 762 rc = rwrap_create_fake_ns_rr(key, value, rr); 763 break; 764 } else if (TYPE_MATCH(type, ns_t_srv, 765 rec_type, "SRV", key, query)) { 766 rc = rwrap_create_fake_srv_rr(key, value, rr); 767 if (rc == 0) { 768 rc = rwrap_srv_recurse(hostfile, recursion+1, 769 rr->rrdata.srv_rec.hostname, 770 rr + 1); 771 } 772 break; 773 } else if (TYPE_MATCH(type, ns_t_soa, 774 rec_type, "SOA", key, query)) { 775 rc = rwrap_create_fake_soa_rr(key, value, rr); 776 break; 777 } else if (TYPE_MATCH(type, ns_t_cname, 778 rec_type, "CNAME", key, query)) { 779 rc = rwrap_create_fake_cname_rr(key, value, rr); 780 if (rc == 0) { 781 rc = rwrap_cname_recurse(hostfile, recursion+1, 782 value, rr + 1); 783 } 784 break; 785 } else if (TYPE_MATCH(type, ns_t_a, rec_type, "CNAME", key, query)) { 786 rc = rwrap_create_fake_cname_rr(key, value, rr); 787 if (rc == 0) { 788 rc = rwrap_cname_recurse(hostfile, recursion+1, 789 value, rr + 1); 790 } 791 break; 792 } 793 } 794 795 if (rc == ENOENT && recursion == 0 && key != NULL) { 796 RWRAP_LOG(RWRAP_LOG_TRACE, "Record for [%s] not found\n", query); 797 memcpy(rr->key, key, strlen(key) + 1); 798 } 799 800 fclose(fp); 801 return rc; 802 } 803 804 static ssize_t rwrap_fake_empty(int type, 805 const char *question, 806 uint8_t *answer, 807 size_t anslen) 808 { 809 ssize_t resp_data; 810 size_t remaining = anslen; 811 812 resp_data = rwrap_fake_header(&answer, remaining, 0, 0); 813 if (resp_data < 0) { 814 return -1; 815 } 816 remaining -= resp_data; 817 818 resp_data += rwrap_fake_question(question, type, &answer, remaining); 819 if (resp_data < 0) { 820 return -1; 821 } 822 remaining -= resp_data; 823 824 resp_data += rwrap_fake_rdata_common(type, 0, question, 825 remaining, &answer); 826 if (resp_data < 0) { 827 return -1; 828 } 829 830 return resp_data; 831 } 832 833 static inline bool rwrap_known_type(int type) 834 { 835 switch (type) { 836 case ns_t_a: 837 case ns_t_aaaa: 838 case ns_t_ns: 839 case ns_t_srv: 840 case ns_t_soa: 841 case ns_t_cname: 842 return true; 843 } 844 845 return false; 846 } 847 848 static int rwrap_ancount(struct rwrap_fake_rr *rrs, int qtype) 849 { 850 int i; 851 int ancount = 0; 852 853 /* Include all RRs in the stack until the sought type 854 * in the answer section. This is the case i.e. when looking 855 * up an A record but the name points to a CNAME 856 */ 857 for (i = 0; i < RWRAP_MAX_RECURSION; i++) { 858 ancount++; 859 860 if (rwrap_known_type(rrs[i].type) && 861 rrs[i].type == qtype) { 862 break; 863 } 864 } 865 866 /* Return 0 records if the sought type wasn't in the stack */ 867 return i < RWRAP_MAX_RECURSION ? ancount : 0; 868 } 869 870 static int rwrap_arcount(struct rwrap_fake_rr *rrs, int ancount) 871 { 872 int i; 873 int arcount = 0; 874 875 /* start from index ancount */ 876 for (i = ancount; i < RWRAP_MAX_RECURSION; i++) { 877 if (rwrap_known_type(rrs[i].type)) { 878 arcount++; 879 } 880 } 881 882 return arcount; 883 } 884 885 static ssize_t rwrap_add_rr(struct rwrap_fake_rr *rr, 886 uint8_t *answer, 887 size_t anslen) 888 { 889 ssize_t resp_data; 890 891 switch (rr->type) { 892 case ns_t_a: 893 resp_data = rwrap_fake_a(rr, answer, anslen); 894 break; 895 case ns_t_aaaa: 896 resp_data = rwrap_fake_aaaa(rr, answer, anslen); 897 break; 898 case ns_t_ns: 899 resp_data = rwrap_fake_ns(rr, answer, anslen); 900 break; 901 case ns_t_srv: 902 resp_data = rwrap_fake_srv(rr, answer, anslen); 903 break; 904 case ns_t_soa: 905 resp_data = rwrap_fake_soa(rr, answer, anslen); 906 break; 907 case ns_t_cname: 908 resp_data = rwrap_fake_cname(rr, answer, anslen); 909 break; 910 default: 911 return -1; 912 } 913 914 return resp_data; 915 } 916 917 static ssize_t rwrap_fake_answer(struct rwrap_fake_rr *rrs, 918 int type, 919 uint8_t *answer, 920 size_t anslen) 921 922 { 923 ssize_t resp_data; 924 ssize_t rrlen; 925 size_t remaining = anslen; 926 int ancount; 927 int arcount; 928 int i; 929 930 ancount = rwrap_ancount(rrs, type); 931 arcount = rwrap_arcount(rrs, ancount); 932 RWRAP_LOG(RWRAP_LOG_TRACE, 933 "Got %d answers and %d additional records\n", ancount, arcount); 934 935 resp_data = rwrap_fake_header(&answer, remaining, ancount, arcount); 936 if (resp_data < 0) { 937 return -1; 938 } 939 remaining -= resp_data; 940 941 resp_data += rwrap_fake_question(rrs->key, rrs->type, &answer, remaining); 942 if (resp_data < 0) { 943 return -1; 944 } 945 remaining -= resp_data; 946 947 /* answer */ 948 for (i = 0; i < ancount; i++) { 949 rrlen = rwrap_add_rr(&rrs[i], answer, remaining); 950 if (rrlen < 0) { 951 return -1; 952 } 953 remaining -= rrlen; 954 answer += rrlen; 955 resp_data += rrlen; 956 } 957 958 /* add authoritative NS here? */ 959 960 /* additional records */ 961 for (i = ancount; i < ancount + arcount; i++) { 962 rrlen = rwrap_add_rr(&rrs[i], answer, remaining); 963 if (rrlen < 0) { 964 return -1; 965 } 966 remaining -= rrlen; 967 answer += rrlen; 968 resp_data += rrlen; 969 } 970 971 return resp_data; 972 } 973 974 /* Reads in a file in the following format: 975 * TYPE RDATA 976 * 977 * Malformed entries are silently skipped. 978 * Allocates answer buffer of size anslen that has to be freed after use. 979 */ 980 static int rwrap_res_fake_hosts(const char *hostfile, 981 const char *query, 982 int type, 983 unsigned char *answer, 984 size_t anslen) 985 { 986 int rc = ENOENT; 987 char *query_name = NULL; 988 size_t qlen = strlen(query); 989 struct rwrap_fake_rr rrs[RWRAP_MAX_RECURSION]; 990 ssize_t resp_size; 991 992 RWRAP_LOG(RWRAP_LOG_TRACE, 993 "Searching in fake hosts file %s\n", hostfile); 994 995 if (qlen > 0 && query[qlen-1] == '.') { 996 qlen--; 997 } 998 999 query_name = strndup(query, qlen); 1000 if (query_name == NULL) { 1001 return -1; 1002 } 1003 1004 rwrap_fake_rr_init(rrs, RWRAP_MAX_RECURSION); 1005 1006 rc = rwrap_get_record(hostfile, 0, query_name, type, rrs); 1007 switch (rc) { 1008 case 0: 1009 RWRAP_LOG(RWRAP_LOG_TRACE, 1010 "Found record for [%s]\n", query_name); 1011 resp_size = rwrap_fake_answer(rrs, type, answer, anslen); 1012 break; 1013 case ENOENT: 1014 RWRAP_LOG(RWRAP_LOG_TRACE, 1015 "No record for [%s]\n", query_name); 1016 resp_size = rwrap_fake_empty(type, rrs->key, answer, anslen); 1017 break; 1018 default: 1019 RWRAP_LOG(RWRAP_LOG_ERROR, 1020 "Error searching for [%s]\n", query_name); 1021 free(query_name); 1022 return -1; 1023 } 1024 1025 switch (resp_size) { 1026 case -1: 1027 RWRAP_LOG(RWRAP_LOG_ERROR, 1028 "Error faking answer for [%s]\n", query_name); 1029 break; 1030 default: 1031 RWRAP_LOG(RWRAP_LOG_TRACE, 1032 "Successfully faked answer for [%s]\n", 1033 query_name); 1034 break; 1035 } 1036 1037 free(query_name); 1038 return resp_size; 1039 } 1040 1041 /********************************************************* 1042 * RWRAP LOADING LIBC FUNCTIONS 1043 *********************************************************/ 1044 1045 #include <dlfcn.h> 1046 1047 typedef int (*__libc_res_ninit)(struct __res_state *state); 1048 typedef int (*__libc___res_ninit)(struct __res_state *state); 1049 typedef void (*__libc_res_nclose)(struct __res_state *state); 1050 typedef void (*__libc___res_nclose)(struct __res_state *state); 1051 typedef int (*__libc_res_nquery)(struct __res_state *state, 1052 const char *dname, 1053 int class, 1054 int type, 1055 unsigned char *answer, 1056 int anslen); 1057 typedef int (*__libc___res_nquery)(struct __res_state *state, 1058 const char *dname, 1059 int class, 1060 int type, 1061 unsigned char *answer, 1062 int anslen); 1063 typedef int (*__libc_res_nsearch)(struct __res_state *state, 1064 const char *dname, 1065 int class, 1066 int type, 1067 unsigned char *answer, 1068 int anslen); 1069 typedef int (*__libc___res_nsearch)(struct __res_state *state, 1070 const char *dname, 1071 int class, 1072 int type, 1073 unsigned char *answer, 1074 int anslen); 1075 1076 #define RWRAP_SYMBOL_ENTRY(i) \ 1077 union { \ 1078 __libc_##i f; \ 1079 void *obj; \ 1080 } _libc_##i 1081 1082 struct rwrap_libc_symbols { 1083 RWRAP_SYMBOL_ENTRY(res_ninit); 1084 RWRAP_SYMBOL_ENTRY(__res_ninit); 1085 RWRAP_SYMBOL_ENTRY(res_nclose); 1086 RWRAP_SYMBOL_ENTRY(__res_nclose); 1087 RWRAP_SYMBOL_ENTRY(res_nquery); 1088 RWRAP_SYMBOL_ENTRY(__res_nquery); 1089 RWRAP_SYMBOL_ENTRY(res_nsearch); 1090 RWRAP_SYMBOL_ENTRY(__res_nsearch); 1091 }; 1092 #undef RWRAP_SYMBOL_ENTRY 1093 1094 struct rwrap { 1095 struct { 1096 void *handle; 1097 struct rwrap_libc_symbols symbols; 1098 } libc; 1099 1100 struct { 1101 void *handle; 1102 struct rwrap_libc_symbols symbols; 1103 } libresolv; 1104 1105 bool initialised; 1106 bool enabled; 1107 1108 char *socket_dir; 1109 }; 1110 1111 static struct rwrap rwrap; 1112 1113 enum rwrap_lib { 1114 RWRAP_LIBC, 1115 RWRAP_LIBRESOLV 1116 }; 1117 1118 #ifndef NDEBUG 1119 static const char *rwrap_str_lib(enum rwrap_lib lib) 1120 { 1121 switch (lib) { 1122 case RWRAP_LIBC: 1123 return "libc"; 1124 case RWRAP_LIBRESOLV: 1125 return "libresolv"; 1126 } 1127 1128 /* Compiler would warn us about unhandled enum value if we get here */ 1129 return "unknown"; 1130 } 1131 #endif 1132 1133 static void *rwrap_load_lib_handle(enum rwrap_lib lib) 1134 { 1135 int flags = RTLD_LAZY; 1136 void *handle = NULL; 1137 int i; 1138 1139 #ifdef RTLD_DEEPBIND 1140 flags |= RTLD_DEEPBIND; 1141 #endif 1142 1143 switch (lib) { 1144 case RWRAP_LIBRESOLV: 1145 #ifdef HAVE_LIBRESOLV 1146 handle = rwrap.libresolv.handle; 1147 if (handle == NULL) { 1148 for (i = 10; i >= 0; i--) { 1149 char soname[256] = {0}; 1150 1151 snprintf(soname, sizeof(soname), "libresolv.so.%d", i); 1152 handle = dlopen(soname, flags); 1153 if (handle != NULL) { 1154 break; 1155 } 1156 } 1157 1158 rwrap.libresolv.handle = handle; 1159 } 1160 break; 1161 #endif 1162 /* FALL TROUGH */ 1163 case RWRAP_LIBC: 1164 handle = rwrap.libc.handle; 1165 #ifdef LIBC_SO 1166 if (handle == NULL) { 1167 handle = dlopen(LIBC_SO, flags); 1168 1169 rwrap.libc.handle = handle; 1170 } 1171 #endif 1172 if (handle == NULL) { 1173 for (i = 10; i >= 0; i--) { 1174 char soname[256] = {0}; 1175 1176 snprintf(soname, sizeof(soname), "libc.so.%d", i); 1177 handle = dlopen(soname, flags); 1178 if (handle != NULL) { 1179 break; 1180 } 1181 } 1182 1183 rwrap.libc.handle = handle; 1184 } 1185 break; 1186 } 1187 1188 if (handle == NULL) { 1189 #ifdef RTLD_NEXT 1190 handle = rwrap.libc.handle = rwrap.libresolv.handle = RTLD_NEXT; 1191 #else 1192 RWRAP_LOG(RWRAP_LOG_ERROR, 1193 "Failed to dlopen library: %s\n", 1194 dlerror()); 1195 exit(-1); 1196 #endif 1197 } 1198 1199 return handle; 1200 } 1201 1202 static void *_rwrap_bind_symbol(enum rwrap_lib lib, const char *fn_name) 1203 { 1204 void *handle; 1205 void *func; 1206 1207 handle = rwrap_load_lib_handle(lib); 1208 1209 func = dlsym(handle, fn_name); 1210 if (func == NULL) { 1211 RWRAP_LOG(RWRAP_LOG_ERROR, 1212 "Failed to find %s: %s\n", 1213 fn_name, dlerror()); 1214 exit(-1); 1215 } 1216 1217 RWRAP_LOG(RWRAP_LOG_TRACE, 1218 "Loaded %s from %s", 1219 fn_name, rwrap_str_lib(lib)); 1220 return func; 1221 } 1222 1223 #define rwrap_bind_symbol_libc(sym_name) \ 1224 if (rwrap.libc.symbols._libc_##sym_name.obj == NULL) { \ 1225 rwrap.libc.symbols._libc_##sym_name.obj = \ 1226 _rwrap_bind_symbol(RWRAP_LIBC, #sym_name); \ 1227 } 1228 1229 #define rwrap_bind_symbol_libresolv(sym_name) \ 1230 if (rwrap.libresolv.symbols._libc_##sym_name.obj == NULL) { \ 1231 rwrap.libresolv.symbols._libc_##sym_name.obj = \ 1232 _rwrap_bind_symbol(RWRAP_LIBRESOLV, #sym_name); \ 1233 } 1234 1235 /* 1236 * IMPORTANT 1237 * 1238 * Functions especially from libc need to be loaded individually, you can't load 1239 * all at once or gdb will segfault at startup. The same applies to valgrind and 1240 * has probably something todo with with the linker. 1241 * So we need load each function at the point it is called the first time. 1242 */ 1243 1244 static int libc_res_ninit(struct __res_state *state) 1245 { 1246 #if !defined(res_ninit) && defined(HAVE_RES_NINIT) 1247 1248 #if defined(HAVE_RES_NINIT_IN_LIBRESOLV) 1249 rwrap_bind_symbol_libresolv(res_ninit); 1250 1251 return rwrap.libresolv.symbols._libc_res_ninit.f(state); 1252 #else /* HAVE_RES_NINIT_IN_LIBRESOLV */ 1253 rwrap_bind_symbol_libc(res_ninit); 1254 1255 return rwrap.libc.symbols._libc_res_ninit.f(state); 1256 #endif /* HAVE_RES_NINIT_IN_LIBRESOLV */ 1257 1258 #elif defined(HAVE___RES_NINIT) 1259 rwrap_bind_symbol_libc(__res_ninit); 1260 1261 return rwrap.libc.symbols._libc___res_ninit.f(state); 1262 #else 1263 #error "No res_ninit function" 1264 #endif 1265 } 1266 1267 static void libc_res_nclose(struct __res_state *state) 1268 { 1269 #if !defined(res_close) && defined(HAVE_RES_NCLOSE) 1270 1271 #if defined(HAVE_RES_NCLOSE_IN_LIBRESOLV) 1272 rwrap_bind_symbol_libresolv(res_nclose); 1273 1274 rwrap.libresolv.symbols._libc_res_nclose.f(state); 1275 return; 1276 #else /* HAVE_RES_NCLOSE_IN_LIBRESOLV */ 1277 rwrap_bind_symbol_libc(res_nclose); 1278 1279 rwrap.libc.symbols._libc_res_nclose.f(state); 1280 return; 1281 #endif /* HAVE_RES_NCLOSE_IN_LIBRESOLV */ 1282 1283 #elif defined(HAVE___RES_NCLOSE) 1284 rwrap_bind_symbol_libc(__res_nclose); 1285 1286 rwrap.libc.symbols._libc___res_nclose.f(state); 1287 #else 1288 #error "No res_nclose function" 1289 #endif 1290 } 1291 1292 static int libc_res_nquery(struct __res_state *state, 1293 const char *dname, 1294 int class, 1295 int type, 1296 unsigned char *answer, 1297 int anslen) 1298 { 1299 #if !defined(res_nquery) && defined(HAVE_RES_NQUERY) 1300 rwrap_bind_symbol_libresolv(res_nquery); 1301 1302 return rwrap.libresolv.symbols._libc_res_nquery.f(state, 1303 dname, 1304 class, 1305 type, 1306 answer, 1307 anslen); 1308 #elif defined(HAVE___RES_NQUERY) 1309 rwrap_bind_symbol_libresolv(__res_nquery); 1310 1311 return rwrap.libresolv.symbols._libc___res_nquery.f(state, 1312 dname, 1313 class, 1314 type, 1315 answer, 1316 anslen); 1317 #else 1318 #error "No res_nquery function" 1319 #endif 1320 } 1321 1322 static int libc_res_nsearch(struct __res_state *state, 1323 const char *dname, 1324 int class, 1325 int type, 1326 unsigned char *answer, 1327 int anslen) 1328 { 1329 #if !defined(res_nsearch) && defined(HAVE_RES_NSEARCH) 1330 rwrap_bind_symbol_libresolv(res_nsearch); 1331 1332 return rwrap.libresolv.symbols._libc_res_nsearch.f(state, 1333 dname, 1334 class, 1335 type, 1336 answer, 1337 anslen); 1338 #elif defined(HAVE___RES_NSEARCH) 1339 rwrap_bind_symbol_libresolv(__res_nsearch); 1340 1341 return rwrap.libresolv.symbols._libc___res_nsearch.f(state, 1342 dname, 1343 class, 1344 type, 1345 answer, 1346 anslen); 1347 #else 1348 #error "No res_nsearch function" 1349 #endif 1350 } 1351 1352 /**************************************************************************** 1353 * RES_HELPER 1354 ***************************************************************************/ 1355 1356 static int rwrap_parse_resolv_conf(struct __res_state *state, 1357 const char *resolv_conf) 1358 { 1359 FILE *fp; 1360 char buf[BUFSIZ]; 1361 int nserv = 0; 1362 1363 fp = fopen(resolv_conf, "r"); 1364 if (fp == NULL) { 1365 RWRAP_LOG(RWRAP_LOG_ERROR, 1366 "Opening %s failed: %s", 1367 resolv_conf, strerror(errno)); 1368 return -1; 1369 } 1370 1371 while(fgets(buf, sizeof(buf), fp) != NULL) { 1372 char *p; 1373 1374 /* Ignore comments */ 1375 if (buf[0] == '#' || buf[0] == ';') { 1376 continue; 1377 } 1378 1379 if (RESOLV_MATCH(buf, "nameserver") && nserv < MAXNS) { 1380 struct in_addr a; 1381 char *q; 1382 int ok; 1383 1384 p = buf + strlen("nameserver"); 1385 1386 /* Skip spaces and tabs */ 1387 while(isblank((int)p[0])) { 1388 p++; 1389 } 1390 1391 q = p; 1392 while(q[0] != '\n' && q[0] != '\0') { 1393 q++; 1394 } 1395 q[0] = '\0'; 1396 1397 ok = inet_pton(AF_INET, p, &a); 1398 if (ok) { 1399 state->nsaddr_list[state->nscount] = (struct sockaddr_in) { 1400 .sin_family = AF_INET, 1401 .sin_addr = a, 1402 .sin_port = htons(53), 1403 .sin_zero = { 0 }, 1404 }; 1405 1406 state->nscount++; 1407 nserv++; 1408 } else { 1409 #ifdef HAVE_RESOLV_IPV6_NSADDRS 1410 /* IPv6 */ 1411 struct in6_addr a6; 1412 ok = inet_pton(AF_INET6, p, &a6); 1413 if (ok) { 1414 struct sockaddr_in6 *sa6; 1415 1416 sa6 = malloc(sizeof(*sa6)); 1417 if (sa6 == NULL) { 1418 fclose(fp); 1419 return -1; 1420 } 1421 1422 sa6->sin6_family = AF_INET6; 1423 sa6->sin6_port = htons(53); 1424 sa6->sin6_flowinfo = 0; 1425 sa6->sin6_addr = a6; 1426 1427 state->_u._ext.nsaddrs[state->_u._ext.nscount] = sa6; 1428 state->_u._ext.nssocks[state->_u._ext.nscount] = -1; 1429 state->_u._ext.nsmap[state->_u._ext.nscount] = MAXNS + 1; 1430 1431 state->_u._ext.nscount++; 1432 nserv++; 1433 } else { 1434 RWRAP_LOG(RWRAP_LOG_ERROR, 1435 "Malformed DNS server"); 1436 continue; 1437 } 1438 #else /* !HAVE_RESOLV_IPV6_NSADDRS */ 1439 /* 1440 * BSD uses an opaque structure to store the 1441 * IPv6 addresses. So we can not simply store 1442 * these addresses the same way as above. 1443 */ 1444 RWRAP_LOG(RWRAP_LOG_WARN, 1445 "resolve_wrapper does not support " 1446 "IPv6 on this platform"); 1447 continue; 1448 #endif 1449 } 1450 continue; 1451 } /* TODO: match other keywords */ 1452 } 1453 1454 if (ferror(fp)) { 1455 RWRAP_LOG(RWRAP_LOG_ERROR, 1456 "Reading from %s failed", 1457 resolv_conf); 1458 fclose(fp); 1459 return -1; 1460 } 1461 1462 fclose(fp); 1463 return 0; 1464 } 1465 1466 /**************************************************************************** 1467 * RES_NINIT 1468 ***************************************************************************/ 1469 1470 static int rwrap_res_ninit(struct __res_state *state) 1471 { 1472 int rc; 1473 1474 rc = libc_res_ninit(state); 1475 if (rc == 0) { 1476 const char *resolv_conf = getenv("RESOLV_WRAPPER_CONF"); 1477 1478 if (resolv_conf != NULL) { 1479 uint16_t i; 1480 1481 (void)i; /* maybe unused */ 1482 1483 /* Delete name servers */ 1484 state->nscount = 0; 1485 memset(state->nsaddr_list, 0, sizeof(state->nsaddr_list)); 1486 1487 #ifdef HAVE_RESOLV_IPV6_NSADDRS 1488 state->_u._ext.nscount = 0; 1489 for (i = 0; i < state->_u._ext.nscount; i++) { 1490 SAFE_FREE(state->_u._ext.nsaddrs[i]); 1491 } 1492 #endif 1493 1494 rc = rwrap_parse_resolv_conf(state, resolv_conf); 1495 } 1496 } 1497 1498 return rc; 1499 } 1500 1501 #if !defined(res_ninit) && defined(HAVE_RES_NINIT) 1502 int res_ninit(struct __res_state *state) 1503 #elif defined(HAVE___RES_NINIT) 1504 int __res_ninit(struct __res_state *state) 1505 #endif 1506 { 1507 return rwrap_res_ninit(state); 1508 } 1509 1510 /**************************************************************************** 1511 * RES_INIT 1512 ***************************************************************************/ 1513 1514 static struct __res_state rwrap_res_state; 1515 1516 static int rwrap_res_init(void) 1517 { 1518 int rc; 1519 1520 rc = rwrap_res_ninit(&rwrap_res_state); 1521 1522 return rc; 1523 } 1524 1525 #if !defined(res_ninit) && defined(HAVE_RES_INIT) 1526 int res_init(void) 1527 #elif defined(HAVE___RES_INIT) 1528 int __res_init(void) 1529 #endif 1530 { 1531 return rwrap_res_init(); 1532 } 1533 1534 /**************************************************************************** 1535 * RES_NCLOSE 1536 ***************************************************************************/ 1537 1538 static void rwrap_res_nclose(struct __res_state *state) 1539 { 1540 #ifdef HAVE_RESOLV_IPV6_NSADDRS 1541 int i; 1542 #endif 1543 1544 libc_res_nclose(state); 1545 1546 #ifdef HAVE_RESOLV_IPV6_NSADDRS 1547 if (state != NULL) { 1548 for (i = 0; i < state->_u._ext.nscount; i++) { 1549 SAFE_FREE(state->_u._ext.nsaddrs[i]); 1550 } 1551 } 1552 #endif 1553 } 1554 1555 #if !defined(res_nclose) && defined(HAVE_RES_NCLOSE) 1556 void res_nclose(struct __res_state *state) 1557 #elif defined(HAVE___RES_NCLOSE) 1558 void __res_nclose(struct __res_state *state) 1559 #endif 1560 { 1561 rwrap_res_nclose(state); 1562 } 1563 1564 /**************************************************************************** 1565 * RES_CLOSE 1566 ***************************************************************************/ 1567 1568 static void rwrap_res_close(void) 1569 { 1570 rwrap_res_nclose(&rwrap_res_state); 1571 } 1572 1573 #if defined(HAVE_RES_CLOSE) 1574 void res_close(void) 1575 #elif defined(HAVE___RES_CLOSE) 1576 void __res_close(void) 1577 #endif 1578 { 1579 rwrap_res_close(); 1580 } 1581 1582 /**************************************************************************** 1583 * RES_NQUERY 1584 ***************************************************************************/ 1585 1586 static int rwrap_res_nquery(struct __res_state *state, 1587 const char *dname, 1588 int class, 1589 int type, 1590 unsigned char *answer, 1591 int anslen) 1592 { 1593 int rc; 1594 const char *fake_hosts; 1595 #ifndef NDEBUG 1596 int i; 1597 #endif 1598 1599 RWRAP_LOG(RWRAP_LOG_TRACE, 1600 "Resolve the domain name [%s] - class=%d, type=%d", 1601 dname, class, type); 1602 #ifndef NDEBUG 1603 for (i = 0; i < state->nscount; i++) { 1604 char ip[INET6_ADDRSTRLEN]; 1605 1606 inet_ntop(AF_INET, &state->nsaddr_list[i].sin_addr, ip, sizeof(ip)); 1607 RWRAP_LOG(RWRAP_LOG_TRACE, 1608 " nameserver: %s", 1609 ip); 1610 } 1611 #endif 1612 1613 fake_hosts = getenv("RESOLV_WRAPPER_HOSTS"); 1614 if (fake_hosts != NULL) { 1615 rc = rwrap_res_fake_hosts(fake_hosts, dname, type, answer, anslen); 1616 } else { 1617 rc = libc_res_nquery(state, dname, class, type, answer, anslen); 1618 } 1619 1620 1621 RWRAP_LOG(RWRAP_LOG_TRACE, 1622 "The returned response length is: %d", 1623 rc); 1624 1625 return rc; 1626 } 1627 1628 #if !defined(res_nquery) && defined(HAVE_RES_NQUERY) 1629 int res_nquery(struct __res_state *state, 1630 const char *dname, 1631 int class, 1632 int type, 1633 unsigned char *answer, 1634 int anslen) 1635 #elif defined(HAVE___RES_NQUERY) 1636 int __res_nquery(struct __res_state *state, 1637 const char *dname, 1638 int class, 1639 int type, 1640 unsigned char *answer, 1641 int anslen) 1642 #endif 1643 { 1644 return rwrap_res_nquery(state, dname, class, type, answer, anslen); 1645 } 1646 1647 /**************************************************************************** 1648 * RES_QUERY 1649 ***************************************************************************/ 1650 1651 static int rwrap_res_query(const char *dname, 1652 int class, 1653 int type, 1654 unsigned char *answer, 1655 int anslen) 1656 { 1657 int rc; 1658 1659 rc = rwrap_res_ninit(&rwrap_res_state); 1660 if (rc != 0) { 1661 return rc; 1662 } 1663 1664 rc = rwrap_res_nquery(&rwrap_res_state, 1665 dname, 1666 class, 1667 type, 1668 answer, 1669 anslen); 1670 1671 return rc; 1672 } 1673 1674 #if !defined(res_query) && defined(HAVE_RES_QUERY) 1675 int res_query(const char *dname, 1676 int class, 1677 int type, 1678 unsigned char *answer, 1679 int anslen) 1680 #elif defined(HAVE___RES_QUERY) 1681 int __res_query(const char *dname, 1682 int class, 1683 int type, 1684 unsigned char *answer, 1685 int anslen) 1686 #endif 1687 { 1688 return rwrap_res_query(dname, class, type, answer, anslen); 1689 } 1690 1691 /**************************************************************************** 1692 * RES_NSEARCH 1693 ***************************************************************************/ 1694 1695 static int rwrap_res_nsearch(struct __res_state *state, 1696 const char *dname, 1697 int class, 1698 int type, 1699 unsigned char *answer, 1700 int anslen) 1701 { 1702 int rc; 1703 const char *fake_hosts; 1704 #ifndef NDEBUG 1705 int i; 1706 #endif 1707 1708 RWRAP_LOG(RWRAP_LOG_TRACE, 1709 "Resolve the domain name [%s] - class=%d, type=%d", 1710 dname, class, type); 1711 #ifndef NDEBUG 1712 for (i = 0; i < state->nscount; i++) { 1713 char ip[INET6_ADDRSTRLEN]; 1714 1715 inet_ntop(AF_INET, &state->nsaddr_list[i].sin_addr, ip, sizeof(ip)); 1716 RWRAP_LOG(RWRAP_LOG_TRACE, 1717 " nameserver: %s", 1718 ip); 1719 } 1720 #endif 1721 1722 fake_hosts = getenv("RESOLV_WRAPPER_HOSTS"); 1723 if (fake_hosts != NULL) { 1724 rc = rwrap_res_fake_hosts(fake_hosts, dname, type, answer, anslen); 1725 } else { 1726 rc = libc_res_nsearch(state, dname, class, type, answer, anslen); 1727 } 1728 1729 RWRAP_LOG(RWRAP_LOG_TRACE, 1730 "The returned response length is: %d", 1731 rc); 1732 1733 return rc; 1734 } 1735 1736 #if !defined(res_nsearch) && defined(HAVE_RES_NSEARCH) 1737 int res_nsearch(struct __res_state *state, 1738 const char *dname, 1739 int class, 1740 int type, 1741 unsigned char *answer, 1742 int anslen) 1743 #elif defined(HAVE___RES_NSEARCH) 1744 int __res_nsearch(struct __res_state *state, 1745 const char *dname, 1746 int class, 1747 int type, 1748 unsigned char *answer, 1749 int anslen) 1750 #endif 1751 { 1752 return rwrap_res_nsearch(state, dname, class, type, answer, anslen); 1753 } 1754 1755 /**************************************************************************** 1756 * RES_SEARCH 1757 ***************************************************************************/ 1758 1759 static int rwrap_res_search(const char *dname, 1760 int class, 1761 int type, 1762 unsigned char *answer, 1763 int anslen) 1764 { 1765 int rc; 1766 1767 rc = rwrap_res_ninit(&rwrap_res_state); 1768 if (rc != 0) { 1769 return rc; 1770 } 1771 1772 rc = rwrap_res_nsearch(&rwrap_res_state, 1773 dname, 1774 class, 1775 type, 1776 answer, 1777 anslen); 1778 1779 return rc; 1780 } 1781 1782 #if !defined(res_search) && defined(HAVE_RES_SEARCH) 1783 int res_search(const char *dname, 1784 int class, 1785 int type, 1786 unsigned char *answer, 1787 int anslen) 1788 #elif defined(HAVE___RES_SEARCH) 1789 int __res_search(const char *dname, 1790 int class, 1791 int type, 1792 unsigned char *answer, 1793 int anslen) 1794 #endif 1795 { 1796 return rwrap_res_search(dname, class, type, answer, anslen); 1797 } 1798