1 /* 2 * Copyright (C) 2008 The Android Open Source 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 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in 12 * the documentation and/or other materials provided with the 13 * distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 18 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 19 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 22 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 25 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29 #include "resolv_cache.h" 30 #include <resolv.h> 31 #include <stdarg.h> 32 #include <stdio.h> 33 #include <stdlib.h> 34 #include <string.h> 35 #include <time.h> 36 #include "pthread.h" 37 38 #include <errno.h> 39 #include <arpa/nameser.h> 40 #include <sys/system_properties.h> 41 #include <net/if.h> 42 #include <netdb.h> 43 #include <linux/if.h> 44 45 #include <arpa/inet.h> 46 #include "resolv_private.h" 47 #include "resolv_netid.h" 48 #include "res_private.h" 49 50 #include "private/libc_logging.h" 51 52 /* This code implements a small and *simple* DNS resolver cache. 53 * 54 * It is only used to cache DNS answers for a time defined by the smallest TTL 55 * among the answer records in order to reduce DNS traffic. It is not supposed 56 * to be a full DNS cache, since we plan to implement that in the future in a 57 * dedicated process running on the system. 58 * 59 * Note that its design is kept simple very intentionally, i.e.: 60 * 61 * - it takes raw DNS query packet data as input, and returns raw DNS 62 * answer packet data as output 63 * 64 * (this means that two similar queries that encode the DNS name 65 * differently will be treated distinctly). 66 * 67 * the smallest TTL value among the answer records are used as the time 68 * to keep an answer in the cache. 69 * 70 * this is bad, but we absolutely want to avoid parsing the answer packets 71 * (and should be solved by the later full DNS cache process). 72 * 73 * - the implementation is just a (query-data) => (answer-data) hash table 74 * with a trivial least-recently-used expiration policy. 75 * 76 * Doing this keeps the code simple and avoids to deal with a lot of things 77 * that a full DNS cache is expected to do. 78 * 79 * The API is also very simple: 80 * 81 * - the client calls _resolv_cache_get() to obtain a handle to the cache. 82 * this will initialize the cache on first usage. the result can be NULL 83 * if the cache is disabled. 84 * 85 * - the client calls _resolv_cache_lookup() before performing a query 86 * 87 * if the function returns RESOLV_CACHE_FOUND, a copy of the answer data 88 * has been copied into the client-provided answer buffer. 89 * 90 * if the function returns RESOLV_CACHE_NOTFOUND, the client should perform 91 * a request normally, *then* call _resolv_cache_add() to add the received 92 * answer to the cache. 93 * 94 * if the function returns RESOLV_CACHE_UNSUPPORTED, the client should 95 * perform a request normally, and *not* call _resolv_cache_add() 96 * 97 * note that RESOLV_CACHE_UNSUPPORTED is also returned if the answer buffer 98 * is too short to accomodate the cached result. 99 */ 100 101 /* the name of an environment variable that will be checked the first time 102 * this code is called if its value is "0", then the resolver cache is 103 * disabled. 104 */ 105 #define CONFIG_ENV "BIONIC_DNSCACHE" 106 107 /* default number of entries kept in the cache. This value has been 108 * determined by browsing through various sites and counting the number 109 * of corresponding requests. Keep in mind that our framework is currently 110 * performing two requests per name lookup (one for IPv4, the other for IPv6) 111 * 112 * www.google.com 4 113 * www.ysearch.com 6 114 * www.amazon.com 8 115 * www.nytimes.com 22 116 * www.espn.com 28 117 * www.msn.com 28 118 * www.lemonde.fr 35 119 * 120 * (determined in 2009-2-17 from Paris, France, results may vary depending 121 * on location) 122 * 123 * most high-level websites use lots of media/ad servers with different names 124 * but these are generally reused when browsing through the site. 125 * 126 * As such, a value of 64 should be relatively comfortable at the moment. 127 * 128 * ****************************************** 129 * * NOTE - this has changed. 130 * * 1) we've added IPv6 support so each dns query results in 2 responses 131 * * 2) we've made this a system-wide cache, so the cost is less (it's not 132 * * duplicated in each process) and the need is greater (more processes 133 * * making different requests). 134 * * Upping by 2x for IPv6 135 * * Upping by another 5x for the centralized nature 136 * ***************************************** 137 */ 138 #define CONFIG_MAX_ENTRIES 64 * 2 * 5 139 /* name of the system property that can be used to set the cache size */ 140 141 /****************************************************************************/ 142 /****************************************************************************/ 143 /***** *****/ 144 /***** *****/ 145 /***** *****/ 146 /****************************************************************************/ 147 /****************************************************************************/ 148 149 /* set to 1 to debug cache operations */ 150 #define DEBUG 0 151 152 /* set to 1 to debug query data */ 153 #define DEBUG_DATA 0 154 155 #if DEBUG 156 #define __DEBUG__ 157 #else 158 #define __DEBUG__ __attribute__((unused)) 159 #endif 160 161 #undef XLOG 162 163 #define XLOG(...) ({ \ 164 if (DEBUG) { \ 165 __libc_format_log(ANDROID_LOG_DEBUG,"libc",__VA_ARGS__); \ 166 } else { \ 167 ((void)0); \ 168 } \ 169 }) 170 171 /** BOUNDED BUFFER FORMATTING 172 **/ 173 174 /* technical note: 175 * 176 * the following debugging routines are used to append data to a bounded 177 * buffer they take two parameters that are: 178 * 179 * - p : a pointer to the current cursor position in the buffer 180 * this value is initially set to the buffer's address. 181 * 182 * - end : the address of the buffer's limit, i.e. of the first byte 183 * after the buffer. this address should never be touched. 184 * 185 * IMPORTANT: it is assumed that end > buffer_address, i.e. 186 * that the buffer is at least one byte. 187 * 188 * the _bprint_() functions return the new value of 'p' after the data 189 * has been appended, and also ensure the following: 190 * 191 * - the returned value will never be strictly greater than 'end' 192 * 193 * - a return value equal to 'end' means that truncation occured 194 * (in which case, end[-1] will be set to 0) 195 * 196 * - after returning from a _bprint_() function, the content of the buffer 197 * is always 0-terminated, even in the event of truncation. 198 * 199 * these conventions allow you to call _bprint_ functions multiple times and 200 * only check for truncation at the end of the sequence, as in: 201 * 202 * char buff[1000], *p = buff, *end = p + sizeof(buff); 203 * 204 * p = _bprint_c(p, end, '"'); 205 * p = _bprint_s(p, end, my_string); 206 * p = _bprint_c(p, end, '"'); 207 * 208 * if (p >= end) { 209 * // buffer was too small 210 * } 211 * 212 * printf( "%s", buff ); 213 */ 214 215 /* add a char to a bounded buffer */ 216 char* 217 _bprint_c( char* p, char* end, int c ) 218 { 219 if (p < end) { 220 if (p+1 == end) 221 *p++ = 0; 222 else { 223 *p++ = (char) c; 224 *p = 0; 225 } 226 } 227 return p; 228 } 229 230 /* add a sequence of bytes to a bounded buffer */ 231 char* 232 _bprint_b( char* p, char* end, const char* buf, int len ) 233 { 234 int avail = end - p; 235 236 if (avail <= 0 || len <= 0) 237 return p; 238 239 if (avail > len) 240 avail = len; 241 242 memcpy( p, buf, avail ); 243 p += avail; 244 245 if (p < end) 246 p[0] = 0; 247 else 248 end[-1] = 0; 249 250 return p; 251 } 252 253 /* add a string to a bounded buffer */ 254 char* 255 _bprint_s( char* p, char* end, const char* str ) 256 { 257 return _bprint_b(p, end, str, strlen(str)); 258 } 259 260 /* add a formatted string to a bounded buffer */ 261 char* _bprint( char* p, char* end, const char* format, ... ) __DEBUG__; 262 char* _bprint( char* p, char* end, const char* format, ... ) 263 { 264 int avail, n; 265 va_list args; 266 267 avail = end - p; 268 269 if (avail <= 0) 270 return p; 271 272 va_start(args, format); 273 n = vsnprintf( p, avail, format, args); 274 va_end(args); 275 276 /* certain C libraries return -1 in case of truncation */ 277 if (n < 0 || n > avail) 278 n = avail; 279 280 p += n; 281 /* certain C libraries do not zero-terminate in case of truncation */ 282 if (p == end) 283 p[-1] = 0; 284 285 return p; 286 } 287 288 /* add a hex value to a bounded buffer, up to 8 digits */ 289 char* 290 _bprint_hex( char* p, char* end, unsigned value, int numDigits ) 291 { 292 char text[sizeof(unsigned)*2]; 293 int nn = 0; 294 295 while (numDigits-- > 0) { 296 text[nn++] = "0123456789abcdef"[(value >> (numDigits*4)) & 15]; 297 } 298 return _bprint_b(p, end, text, nn); 299 } 300 301 /* add the hexadecimal dump of some memory area to a bounded buffer */ 302 char* 303 _bprint_hexdump( char* p, char* end, const uint8_t* data, int datalen ) 304 { 305 int lineSize = 16; 306 307 while (datalen > 0) { 308 int avail = datalen; 309 int nn; 310 311 if (avail > lineSize) 312 avail = lineSize; 313 314 for (nn = 0; nn < avail; nn++) { 315 if (nn > 0) 316 p = _bprint_c(p, end, ' '); 317 p = _bprint_hex(p, end, data[nn], 2); 318 } 319 for ( ; nn < lineSize; nn++ ) { 320 p = _bprint_s(p, end, " "); 321 } 322 p = _bprint_s(p, end, " "); 323 324 for (nn = 0; nn < avail; nn++) { 325 int c = data[nn]; 326 327 if (c < 32 || c > 127) 328 c = '.'; 329 330 p = _bprint_c(p, end, c); 331 } 332 p = _bprint_c(p, end, '\n'); 333 334 data += avail; 335 datalen -= avail; 336 } 337 return p; 338 } 339 340 /* dump the content of a query of packet to the log */ 341 void XLOG_BYTES( const void* base, int len ) __DEBUG__; 342 void XLOG_BYTES( const void* base, int len ) 343 { 344 if (DEBUG_DATA) { 345 char buff[1024]; 346 char* p = buff, *end = p + sizeof(buff); 347 348 p = _bprint_hexdump(p, end, base, len); 349 XLOG("%s",buff); 350 } 351 } __DEBUG__ 352 353 static time_t 354 _time_now( void ) 355 { 356 struct timeval tv; 357 358 gettimeofday( &tv, NULL ); 359 return tv.tv_sec; 360 } 361 362 /* reminder: the general format of a DNS packet is the following: 363 * 364 * HEADER (12 bytes) 365 * QUESTION (variable) 366 * ANSWER (variable) 367 * AUTHORITY (variable) 368 * ADDITIONNAL (variable) 369 * 370 * the HEADER is made of: 371 * 372 * ID : 16 : 16-bit unique query identification field 373 * 374 * QR : 1 : set to 0 for queries, and 1 for responses 375 * Opcode : 4 : set to 0 for queries 376 * AA : 1 : set to 0 for queries 377 * TC : 1 : truncation flag, will be set to 0 in queries 378 * RD : 1 : recursion desired 379 * 380 * RA : 1 : recursion available (0 in queries) 381 * Z : 3 : three reserved zero bits 382 * RCODE : 4 : response code (always 0=NOERROR in queries) 383 * 384 * QDCount: 16 : question count 385 * ANCount: 16 : Answer count (0 in queries) 386 * NSCount: 16: Authority Record count (0 in queries) 387 * ARCount: 16: Additionnal Record count (0 in queries) 388 * 389 * the QUESTION is made of QDCount Question Record (QRs) 390 * the ANSWER is made of ANCount RRs 391 * the AUTHORITY is made of NSCount RRs 392 * the ADDITIONNAL is made of ARCount RRs 393 * 394 * Each Question Record (QR) is made of: 395 * 396 * QNAME : variable : Query DNS NAME 397 * TYPE : 16 : type of query (A=1, PTR=12, MX=15, AAAA=28, ALL=255) 398 * CLASS : 16 : class of query (IN=1) 399 * 400 * Each Resource Record (RR) is made of: 401 * 402 * NAME : variable : DNS NAME 403 * TYPE : 16 : type of query (A=1, PTR=12, MX=15, AAAA=28, ALL=255) 404 * CLASS : 16 : class of query (IN=1) 405 * TTL : 32 : seconds to cache this RR (0=none) 406 * RDLENGTH: 16 : size of RDDATA in bytes 407 * RDDATA : variable : RR data (depends on TYPE) 408 * 409 * Each QNAME contains a domain name encoded as a sequence of 'labels' 410 * terminated by a zero. Each label has the following format: 411 * 412 * LEN : 8 : lenght of label (MUST be < 64) 413 * NAME : 8*LEN : label length (must exclude dots) 414 * 415 * A value of 0 in the encoding is interpreted as the 'root' domain and 416 * terminates the encoding. So 'www.android.com' will be encoded as: 417 * 418 * <3>www<7>android<3>com<0> 419 * 420 * Where <n> represents the byte with value 'n' 421 * 422 * Each NAME reflects the QNAME of the question, but has a slightly more 423 * complex encoding in order to provide message compression. This is achieved 424 * by using a 2-byte pointer, with format: 425 * 426 * TYPE : 2 : 0b11 to indicate a pointer, 0b01 and 0b10 are reserved 427 * OFFSET : 14 : offset to another part of the DNS packet 428 * 429 * The offset is relative to the start of the DNS packet and must point 430 * A pointer terminates the encoding. 431 * 432 * The NAME can be encoded in one of the following formats: 433 * 434 * - a sequence of simple labels terminated by 0 (like QNAMEs) 435 * - a single pointer 436 * - a sequence of simple labels terminated by a pointer 437 * 438 * A pointer shall always point to either a pointer of a sequence of 439 * labels (which can themselves be terminated by either a 0 or a pointer) 440 * 441 * The expanded length of a given domain name should not exceed 255 bytes. 442 * 443 * NOTE: we don't parse the answer packets, so don't need to deal with NAME 444 * records, only QNAMEs. 445 */ 446 447 #define DNS_HEADER_SIZE 12 448 449 #define DNS_TYPE_A "\00\01" /* big-endian decimal 1 */ 450 #define DNS_TYPE_PTR "\00\014" /* big-endian decimal 12 */ 451 #define DNS_TYPE_MX "\00\017" /* big-endian decimal 15 */ 452 #define DNS_TYPE_AAAA "\00\034" /* big-endian decimal 28 */ 453 #define DNS_TYPE_ALL "\00\0377" /* big-endian decimal 255 */ 454 455 #define DNS_CLASS_IN "\00\01" /* big-endian decimal 1 */ 456 457 typedef struct { 458 const uint8_t* base; 459 const uint8_t* end; 460 const uint8_t* cursor; 461 } DnsPacket; 462 463 static void 464 _dnsPacket_init( DnsPacket* packet, const uint8_t* buff, int bufflen ) 465 { 466 packet->base = buff; 467 packet->end = buff + bufflen; 468 packet->cursor = buff; 469 } 470 471 static void 472 _dnsPacket_rewind( DnsPacket* packet ) 473 { 474 packet->cursor = packet->base; 475 } 476 477 static void 478 _dnsPacket_skip( DnsPacket* packet, int count ) 479 { 480 const uint8_t* p = packet->cursor + count; 481 482 if (p > packet->end) 483 p = packet->end; 484 485 packet->cursor = p; 486 } 487 488 static int 489 _dnsPacket_readInt16( DnsPacket* packet ) 490 { 491 const uint8_t* p = packet->cursor; 492 493 if (p+2 > packet->end) 494 return -1; 495 496 packet->cursor = p+2; 497 return (p[0]<< 8) | p[1]; 498 } 499 500 /** QUERY CHECKING 501 **/ 502 503 /* check bytes in a dns packet. returns 1 on success, 0 on failure. 504 * the cursor is only advanced in the case of success 505 */ 506 static int 507 _dnsPacket_checkBytes( DnsPacket* packet, int numBytes, const void* bytes ) 508 { 509 const uint8_t* p = packet->cursor; 510 511 if (p + numBytes > packet->end) 512 return 0; 513 514 if (memcmp(p, bytes, numBytes) != 0) 515 return 0; 516 517 packet->cursor = p + numBytes; 518 return 1; 519 } 520 521 /* parse and skip a given QNAME stored in a query packet, 522 * from the current cursor position. returns 1 on success, 523 * or 0 for malformed data. 524 */ 525 static int 526 _dnsPacket_checkQName( DnsPacket* packet ) 527 { 528 const uint8_t* p = packet->cursor; 529 const uint8_t* end = packet->end; 530 531 for (;;) { 532 int c; 533 534 if (p >= end) 535 break; 536 537 c = *p++; 538 539 if (c == 0) { 540 packet->cursor = p; 541 return 1; 542 } 543 544 /* we don't expect label compression in QNAMEs */ 545 if (c >= 64) 546 break; 547 548 p += c; 549 /* we rely on the bound check at the start 550 * of the loop here */ 551 } 552 /* malformed data */ 553 XLOG("malformed QNAME"); 554 return 0; 555 } 556 557 /* parse and skip a given QR stored in a packet. 558 * returns 1 on success, and 0 on failure 559 */ 560 static int 561 _dnsPacket_checkQR( DnsPacket* packet ) 562 { 563 if (!_dnsPacket_checkQName(packet)) 564 return 0; 565 566 /* TYPE must be one of the things we support */ 567 if (!_dnsPacket_checkBytes(packet, 2, DNS_TYPE_A) && 568 !_dnsPacket_checkBytes(packet, 2, DNS_TYPE_PTR) && 569 !_dnsPacket_checkBytes(packet, 2, DNS_TYPE_MX) && 570 !_dnsPacket_checkBytes(packet, 2, DNS_TYPE_AAAA) && 571 !_dnsPacket_checkBytes(packet, 2, DNS_TYPE_ALL)) 572 { 573 XLOG("unsupported TYPE"); 574 return 0; 575 } 576 /* CLASS must be IN */ 577 if (!_dnsPacket_checkBytes(packet, 2, DNS_CLASS_IN)) { 578 XLOG("unsupported CLASS"); 579 return 0; 580 } 581 582 return 1; 583 } 584 585 /* check the header of a DNS Query packet, return 1 if it is one 586 * type of query we can cache, or 0 otherwise 587 */ 588 static int 589 _dnsPacket_checkQuery( DnsPacket* packet ) 590 { 591 const uint8_t* p = packet->base; 592 int qdCount, anCount, dnCount, arCount; 593 594 if (p + DNS_HEADER_SIZE > packet->end) { 595 XLOG("query packet too small"); 596 return 0; 597 } 598 599 /* QR must be set to 0, opcode must be 0 and AA must be 0 */ 600 /* RA, Z, and RCODE must be 0 */ 601 if ((p[2] & 0xFC) != 0 || p[3] != 0) { 602 XLOG("query packet flags unsupported"); 603 return 0; 604 } 605 606 /* Note that we ignore the TC and RD bits here for the 607 * following reasons: 608 * 609 * - there is no point for a query packet sent to a server 610 * to have the TC bit set, but the implementation might 611 * set the bit in the query buffer for its own needs 612 * between a _resolv_cache_lookup and a 613 * _resolv_cache_add. We should not freak out if this 614 * is the case. 615 * 616 * - we consider that the result from a RD=0 or a RD=1 617 * query might be different, hence that the RD bit 618 * should be used to differentiate cached result. 619 * 620 * this implies that RD is checked when hashing or 621 * comparing query packets, but not TC 622 */ 623 624 /* ANCOUNT, DNCOUNT and ARCOUNT must be 0 */ 625 qdCount = (p[4] << 8) | p[5]; 626 anCount = (p[6] << 8) | p[7]; 627 dnCount = (p[8] << 8) | p[9]; 628 arCount = (p[10]<< 8) | p[11]; 629 630 if (anCount != 0 || dnCount != 0 || arCount != 0) { 631 XLOG("query packet contains non-query records"); 632 return 0; 633 } 634 635 if (qdCount == 0) { 636 XLOG("query packet doesn't contain query record"); 637 return 0; 638 } 639 640 /* Check QDCOUNT QRs */ 641 packet->cursor = p + DNS_HEADER_SIZE; 642 643 for (;qdCount > 0; qdCount--) 644 if (!_dnsPacket_checkQR(packet)) 645 return 0; 646 647 return 1; 648 } 649 650 /** QUERY DEBUGGING 651 **/ 652 #if DEBUG 653 static char* 654 _dnsPacket_bprintQName(DnsPacket* packet, char* bp, char* bend) 655 { 656 const uint8_t* p = packet->cursor; 657 const uint8_t* end = packet->end; 658 int first = 1; 659 660 for (;;) { 661 int c; 662 663 if (p >= end) 664 break; 665 666 c = *p++; 667 668 if (c == 0) { 669 packet->cursor = p; 670 return bp; 671 } 672 673 /* we don't expect label compression in QNAMEs */ 674 if (c >= 64) 675 break; 676 677 if (first) 678 first = 0; 679 else 680 bp = _bprint_c(bp, bend, '.'); 681 682 bp = _bprint_b(bp, bend, (const char*)p, c); 683 684 p += c; 685 /* we rely on the bound check at the start 686 * of the loop here */ 687 } 688 /* malformed data */ 689 bp = _bprint_s(bp, bend, "<MALFORMED>"); 690 return bp; 691 } 692 693 static char* 694 _dnsPacket_bprintQR(DnsPacket* packet, char* p, char* end) 695 { 696 #define QQ(x) { DNS_TYPE_##x, #x } 697 static const struct { 698 const char* typeBytes; 699 const char* typeString; 700 } qTypes[] = 701 { 702 QQ(A), QQ(PTR), QQ(MX), QQ(AAAA), QQ(ALL), 703 { NULL, NULL } 704 }; 705 int nn; 706 const char* typeString = NULL; 707 708 /* dump QNAME */ 709 p = _dnsPacket_bprintQName(packet, p, end); 710 711 /* dump TYPE */ 712 p = _bprint_s(p, end, " ("); 713 714 for (nn = 0; qTypes[nn].typeBytes != NULL; nn++) { 715 if (_dnsPacket_checkBytes(packet, 2, qTypes[nn].typeBytes)) { 716 typeString = qTypes[nn].typeString; 717 break; 718 } 719 } 720 721 if (typeString != NULL) 722 p = _bprint_s(p, end, typeString); 723 else { 724 int typeCode = _dnsPacket_readInt16(packet); 725 p = _bprint(p, end, "UNKNOWN-%d", typeCode); 726 } 727 728 p = _bprint_c(p, end, ')'); 729 730 /* skip CLASS */ 731 _dnsPacket_skip(packet, 2); 732 return p; 733 } 734 735 /* this function assumes the packet has already been checked */ 736 static char* 737 _dnsPacket_bprintQuery( DnsPacket* packet, char* p, char* end ) 738 { 739 int qdCount; 740 741 if (packet->base[2] & 0x1) { 742 p = _bprint_s(p, end, "RECURSIVE "); 743 } 744 745 _dnsPacket_skip(packet, 4); 746 qdCount = _dnsPacket_readInt16(packet); 747 _dnsPacket_skip(packet, 6); 748 749 for ( ; qdCount > 0; qdCount-- ) { 750 p = _dnsPacket_bprintQR(packet, p, end); 751 } 752 return p; 753 } 754 #endif 755 756 757 /** QUERY HASHING SUPPORT 758 ** 759 ** THE FOLLOWING CODE ASSUMES THAT THE INPUT PACKET HAS ALREADY 760 ** BEEN SUCCESFULLY CHECKED. 761 **/ 762 763 /* use 32-bit FNV hash function */ 764 #define FNV_MULT 16777619U 765 #define FNV_BASIS 2166136261U 766 767 static unsigned 768 _dnsPacket_hashBytes( DnsPacket* packet, int numBytes, unsigned hash ) 769 { 770 const uint8_t* p = packet->cursor; 771 const uint8_t* end = packet->end; 772 773 while (numBytes > 0 && p < end) { 774 hash = hash*FNV_MULT ^ *p++; 775 } 776 packet->cursor = p; 777 return hash; 778 } 779 780 781 static unsigned 782 _dnsPacket_hashQName( DnsPacket* packet, unsigned hash ) 783 { 784 const uint8_t* p = packet->cursor; 785 const uint8_t* end = packet->end; 786 787 for (;;) { 788 int c; 789 790 if (p >= end) { /* should not happen */ 791 XLOG("%s: INTERNAL_ERROR: read-overflow !!\n", __FUNCTION__); 792 break; 793 } 794 795 c = *p++; 796 797 if (c == 0) 798 break; 799 800 if (c >= 64) { 801 XLOG("%s: INTERNAL_ERROR: malformed domain !!\n", __FUNCTION__); 802 break; 803 } 804 if (p + c >= end) { 805 XLOG("%s: INTERNAL_ERROR: simple label read-overflow !!\n", 806 __FUNCTION__); 807 break; 808 } 809 while (c > 0) { 810 hash = hash*FNV_MULT ^ *p++; 811 c -= 1; 812 } 813 } 814 packet->cursor = p; 815 return hash; 816 } 817 818 static unsigned 819 _dnsPacket_hashQR( DnsPacket* packet, unsigned hash ) 820 { 821 hash = _dnsPacket_hashQName(packet, hash); 822 hash = _dnsPacket_hashBytes(packet, 4, hash); /* TYPE and CLASS */ 823 return hash; 824 } 825 826 static unsigned 827 _dnsPacket_hashQuery( DnsPacket* packet ) 828 { 829 unsigned hash = FNV_BASIS; 830 int count; 831 _dnsPacket_rewind(packet); 832 833 /* we ignore the TC bit for reasons explained in 834 * _dnsPacket_checkQuery(). 835 * 836 * however we hash the RD bit to differentiate 837 * between answers for recursive and non-recursive 838 * queries. 839 */ 840 hash = hash*FNV_MULT ^ (packet->base[2] & 1); 841 842 /* assume: other flags are 0 */ 843 _dnsPacket_skip(packet, 4); 844 845 /* read QDCOUNT */ 846 count = _dnsPacket_readInt16(packet); 847 848 /* assume: ANcount, NScount, ARcount are 0 */ 849 _dnsPacket_skip(packet, 6); 850 851 /* hash QDCOUNT QRs */ 852 for ( ; count > 0; count-- ) 853 hash = _dnsPacket_hashQR(packet, hash); 854 855 return hash; 856 } 857 858 859 /** QUERY COMPARISON 860 ** 861 ** THE FOLLOWING CODE ASSUMES THAT THE INPUT PACKETS HAVE ALREADY 862 ** BEEN SUCCESFULLY CHECKED. 863 **/ 864 865 static int 866 _dnsPacket_isEqualDomainName( DnsPacket* pack1, DnsPacket* pack2 ) 867 { 868 const uint8_t* p1 = pack1->cursor; 869 const uint8_t* end1 = pack1->end; 870 const uint8_t* p2 = pack2->cursor; 871 const uint8_t* end2 = pack2->end; 872 873 for (;;) { 874 int c1, c2; 875 876 if (p1 >= end1 || p2 >= end2) { 877 XLOG("%s: INTERNAL_ERROR: read-overflow !!\n", __FUNCTION__); 878 break; 879 } 880 c1 = *p1++; 881 c2 = *p2++; 882 if (c1 != c2) 883 break; 884 885 if (c1 == 0) { 886 pack1->cursor = p1; 887 pack2->cursor = p2; 888 return 1; 889 } 890 if (c1 >= 64) { 891 XLOG("%s: INTERNAL_ERROR: malformed domain !!\n", __FUNCTION__); 892 break; 893 } 894 if ((p1+c1 > end1) || (p2+c1 > end2)) { 895 XLOG("%s: INTERNAL_ERROR: simple label read-overflow !!\n", 896 __FUNCTION__); 897 break; 898 } 899 if (memcmp(p1, p2, c1) != 0) 900 break; 901 p1 += c1; 902 p2 += c1; 903 /* we rely on the bound checks at the start of the loop */ 904 } 905 /* not the same, or one is malformed */ 906 XLOG("different DN"); 907 return 0; 908 } 909 910 static int 911 _dnsPacket_isEqualBytes( DnsPacket* pack1, DnsPacket* pack2, int numBytes ) 912 { 913 const uint8_t* p1 = pack1->cursor; 914 const uint8_t* p2 = pack2->cursor; 915 916 if ( p1 + numBytes > pack1->end || p2 + numBytes > pack2->end ) 917 return 0; 918 919 if ( memcmp(p1, p2, numBytes) != 0 ) 920 return 0; 921 922 pack1->cursor += numBytes; 923 pack2->cursor += numBytes; 924 return 1; 925 } 926 927 static int 928 _dnsPacket_isEqualQR( DnsPacket* pack1, DnsPacket* pack2 ) 929 { 930 /* compare domain name encoding + TYPE + CLASS */ 931 if ( !_dnsPacket_isEqualDomainName(pack1, pack2) || 932 !_dnsPacket_isEqualBytes(pack1, pack2, 2+2) ) 933 return 0; 934 935 return 1; 936 } 937 938 static int 939 _dnsPacket_isEqualQuery( DnsPacket* pack1, DnsPacket* pack2 ) 940 { 941 int count1, count2; 942 943 /* compare the headers, ignore most fields */ 944 _dnsPacket_rewind(pack1); 945 _dnsPacket_rewind(pack2); 946 947 /* compare RD, ignore TC, see comment in _dnsPacket_checkQuery */ 948 if ((pack1->base[2] & 1) != (pack2->base[2] & 1)) { 949 XLOG("different RD"); 950 return 0; 951 } 952 953 /* assume: other flags are all 0 */ 954 _dnsPacket_skip(pack1, 4); 955 _dnsPacket_skip(pack2, 4); 956 957 /* compare QDCOUNT */ 958 count1 = _dnsPacket_readInt16(pack1); 959 count2 = _dnsPacket_readInt16(pack2); 960 if (count1 != count2 || count1 < 0) { 961 XLOG("different QDCOUNT"); 962 return 0; 963 } 964 965 /* assume: ANcount, NScount and ARcount are all 0 */ 966 _dnsPacket_skip(pack1, 6); 967 _dnsPacket_skip(pack2, 6); 968 969 /* compare the QDCOUNT QRs */ 970 for ( ; count1 > 0; count1-- ) { 971 if (!_dnsPacket_isEqualQR(pack1, pack2)) { 972 XLOG("different QR"); 973 return 0; 974 } 975 } 976 return 1; 977 } 978 979 /****************************************************************************/ 980 /****************************************************************************/ 981 /***** *****/ 982 /***** *****/ 983 /***** *****/ 984 /****************************************************************************/ 985 /****************************************************************************/ 986 987 /* cache entry. for simplicity, 'hash' and 'hlink' are inlined in this 988 * structure though they are conceptually part of the hash table. 989 * 990 * similarly, mru_next and mru_prev are part of the global MRU list 991 */ 992 typedef struct Entry { 993 unsigned int hash; /* hash value */ 994 struct Entry* hlink; /* next in collision chain */ 995 struct Entry* mru_prev; 996 struct Entry* mru_next; 997 998 const uint8_t* query; 999 int querylen; 1000 const uint8_t* answer; 1001 int answerlen; 1002 time_t expires; /* time_t when the entry isn't valid any more */ 1003 int id; /* for debugging purpose */ 1004 } Entry; 1005 1006 /** 1007 * Find the TTL for a negative DNS result. This is defined as the minimum 1008 * of the SOA records TTL and the MINIMUM-TTL field (RFC-2308). 1009 * 1010 * Return 0 if not found. 1011 */ 1012 static u_long 1013 answer_getNegativeTTL(ns_msg handle) { 1014 int n, nscount; 1015 u_long result = 0; 1016 ns_rr rr; 1017 1018 nscount = ns_msg_count(handle, ns_s_ns); 1019 for (n = 0; n < nscount; n++) { 1020 if ((ns_parserr(&handle, ns_s_ns, n, &rr) == 0) && (ns_rr_type(rr) == ns_t_soa)) { 1021 const u_char *rdata = ns_rr_rdata(rr); // find the data 1022 const u_char *edata = rdata + ns_rr_rdlen(rr); // add the len to find the end 1023 int len; 1024 u_long ttl, rec_result = ns_rr_ttl(rr); 1025 1026 // find the MINIMUM-TTL field from the blob of binary data for this record 1027 // skip the server name 1028 len = dn_skipname(rdata, edata); 1029 if (len == -1) continue; // error skipping 1030 rdata += len; 1031 1032 // skip the admin name 1033 len = dn_skipname(rdata, edata); 1034 if (len == -1) continue; // error skipping 1035 rdata += len; 1036 1037 if (edata - rdata != 5*NS_INT32SZ) continue; 1038 // skip: serial number + refresh interval + retry interval + expiry 1039 rdata += NS_INT32SZ * 4; 1040 // finally read the MINIMUM TTL 1041 ttl = ns_get32(rdata); 1042 if (ttl < rec_result) { 1043 rec_result = ttl; 1044 } 1045 // Now that the record is read successfully, apply the new min TTL 1046 if (n == 0 || rec_result < result) { 1047 result = rec_result; 1048 } 1049 } 1050 } 1051 return result; 1052 } 1053 1054 /** 1055 * Parse the answer records and find the appropriate 1056 * smallest TTL among the records. This might be from 1057 * the answer records if found or from the SOA record 1058 * if it's a negative result. 1059 * 1060 * The returned TTL is the number of seconds to 1061 * keep the answer in the cache. 1062 * 1063 * In case of parse error zero (0) is returned which 1064 * indicates that the answer shall not be cached. 1065 */ 1066 static u_long 1067 answer_getTTL(const void* answer, int answerlen) 1068 { 1069 ns_msg handle; 1070 int ancount, n; 1071 u_long result, ttl; 1072 ns_rr rr; 1073 1074 result = 0; 1075 if (ns_initparse(answer, answerlen, &handle) >= 0) { 1076 // get number of answer records 1077 ancount = ns_msg_count(handle, ns_s_an); 1078 1079 if (ancount == 0) { 1080 // a response with no answers? Cache this negative result. 1081 result = answer_getNegativeTTL(handle); 1082 } else { 1083 for (n = 0; n < ancount; n++) { 1084 if (ns_parserr(&handle, ns_s_an, n, &rr) == 0) { 1085 ttl = ns_rr_ttl(rr); 1086 if (n == 0 || ttl < result) { 1087 result = ttl; 1088 } 1089 } else { 1090 XLOG("ns_parserr failed ancount no = %d. errno = %s\n", n, strerror(errno)); 1091 } 1092 } 1093 } 1094 } else { 1095 XLOG("ns_parserr failed. %s\n", strerror(errno)); 1096 } 1097 1098 XLOG("TTL = %lu\n", result); 1099 1100 return result; 1101 } 1102 1103 static void 1104 entry_free( Entry* e ) 1105 { 1106 /* everything is allocated in a single memory block */ 1107 if (e) { 1108 free(e); 1109 } 1110 } 1111 1112 static __inline__ void 1113 entry_mru_remove( Entry* e ) 1114 { 1115 e->mru_prev->mru_next = e->mru_next; 1116 e->mru_next->mru_prev = e->mru_prev; 1117 } 1118 1119 static __inline__ void 1120 entry_mru_add( Entry* e, Entry* list ) 1121 { 1122 Entry* first = list->mru_next; 1123 1124 e->mru_next = first; 1125 e->mru_prev = list; 1126 1127 list->mru_next = e; 1128 first->mru_prev = e; 1129 } 1130 1131 /* compute the hash of a given entry, this is a hash of most 1132 * data in the query (key) */ 1133 static unsigned 1134 entry_hash( const Entry* e ) 1135 { 1136 DnsPacket pack[1]; 1137 1138 _dnsPacket_init(pack, e->query, e->querylen); 1139 return _dnsPacket_hashQuery(pack); 1140 } 1141 1142 /* initialize an Entry as a search key, this also checks the input query packet 1143 * returns 1 on success, or 0 in case of unsupported/malformed data */ 1144 static int 1145 entry_init_key( Entry* e, const void* query, int querylen ) 1146 { 1147 DnsPacket pack[1]; 1148 1149 memset(e, 0, sizeof(*e)); 1150 1151 e->query = query; 1152 e->querylen = querylen; 1153 e->hash = entry_hash(e); 1154 1155 _dnsPacket_init(pack, query, querylen); 1156 1157 return _dnsPacket_checkQuery(pack); 1158 } 1159 1160 /* allocate a new entry as a cache node */ 1161 static Entry* 1162 entry_alloc( const Entry* init, const void* answer, int answerlen ) 1163 { 1164 Entry* e; 1165 int size; 1166 1167 size = sizeof(*e) + init->querylen + answerlen; 1168 e = calloc(size, 1); 1169 if (e == NULL) 1170 return e; 1171 1172 e->hash = init->hash; 1173 e->query = (const uint8_t*)(e+1); 1174 e->querylen = init->querylen; 1175 1176 memcpy( (char*)e->query, init->query, e->querylen ); 1177 1178 e->answer = e->query + e->querylen; 1179 e->answerlen = answerlen; 1180 1181 memcpy( (char*)e->answer, answer, e->answerlen ); 1182 1183 return e; 1184 } 1185 1186 static int 1187 entry_equals( const Entry* e1, const Entry* e2 ) 1188 { 1189 DnsPacket pack1[1], pack2[1]; 1190 1191 if (e1->querylen != e2->querylen) { 1192 return 0; 1193 } 1194 _dnsPacket_init(pack1, e1->query, e1->querylen); 1195 _dnsPacket_init(pack2, e2->query, e2->querylen); 1196 1197 return _dnsPacket_isEqualQuery(pack1, pack2); 1198 } 1199 1200 /****************************************************************************/ 1201 /****************************************************************************/ 1202 /***** *****/ 1203 /***** *****/ 1204 /***** *****/ 1205 /****************************************************************************/ 1206 /****************************************************************************/ 1207 1208 /* We use a simple hash table with external collision lists 1209 * for simplicity, the hash-table fields 'hash' and 'hlink' are 1210 * inlined in the Entry structure. 1211 */ 1212 1213 /* Maximum time for a thread to wait for an pending request */ 1214 #define PENDING_REQUEST_TIMEOUT 20; 1215 1216 typedef struct pending_req_info { 1217 unsigned int hash; 1218 pthread_cond_t cond; 1219 struct pending_req_info* next; 1220 } PendingReqInfo; 1221 1222 typedef struct resolv_cache { 1223 int max_entries; 1224 int num_entries; 1225 Entry mru_list; 1226 int last_id; 1227 Entry* entries; 1228 PendingReqInfo pending_requests; 1229 } Cache; 1230 1231 struct resolv_cache_info { 1232 unsigned netid; 1233 Cache* cache; 1234 struct resolv_cache_info* next; 1235 char* nameservers[MAXNS +1]; 1236 struct addrinfo* nsaddrinfo[MAXNS + 1]; 1237 char defdname[256]; 1238 int dnsrch_offset[MAXDNSRCH+1]; // offsets into defdname 1239 }; 1240 1241 #define HTABLE_VALID(x) ((x) != NULL && (x) != HTABLE_DELETED) 1242 1243 static pthread_once_t _res_cache_once = PTHREAD_ONCE_INIT; 1244 static void _res_cache_init(void); 1245 1246 // lock protecting everything in the _resolve_cache_info structs (next ptr, etc) 1247 static pthread_mutex_t _res_cache_list_lock; 1248 1249 /* gets cache associated with a network, or NULL if none exists */ 1250 static struct resolv_cache* _find_named_cache_locked(unsigned netid); 1251 1252 static void 1253 _cache_flush_pending_requests_locked( struct resolv_cache* cache ) 1254 { 1255 struct pending_req_info *ri, *tmp; 1256 if (cache) { 1257 ri = cache->pending_requests.next; 1258 1259 while (ri) { 1260 tmp = ri; 1261 ri = ri->next; 1262 pthread_cond_broadcast(&tmp->cond); 1263 1264 pthread_cond_destroy(&tmp->cond); 1265 free(tmp); 1266 } 1267 1268 cache->pending_requests.next = NULL; 1269 } 1270 } 1271 1272 /* Return 0 if no pending request is found matching the key. 1273 * If a matching request is found the calling thread will wait until 1274 * the matching request completes, then update *cache and return 1. */ 1275 static int 1276 _cache_check_pending_request_locked( struct resolv_cache** cache, Entry* key, unsigned netid ) 1277 { 1278 struct pending_req_info *ri, *prev; 1279 int exist = 0; 1280 1281 if (*cache && key) { 1282 ri = (*cache)->pending_requests.next; 1283 prev = &(*cache)->pending_requests; 1284 while (ri) { 1285 if (ri->hash == key->hash) { 1286 exist = 1; 1287 break; 1288 } 1289 prev = ri; 1290 ri = ri->next; 1291 } 1292 1293 if (!exist) { 1294 ri = calloc(1, sizeof(struct pending_req_info)); 1295 if (ri) { 1296 ri->hash = key->hash; 1297 pthread_cond_init(&ri->cond, NULL); 1298 prev->next = ri; 1299 } 1300 } else { 1301 struct timespec ts = {0,0}; 1302 XLOG("Waiting for previous request"); 1303 ts.tv_sec = _time_now() + PENDING_REQUEST_TIMEOUT; 1304 pthread_cond_timedwait(&ri->cond, &_res_cache_list_lock, &ts); 1305 /* Must update *cache as it could have been deleted. */ 1306 *cache = _find_named_cache_locked(netid); 1307 } 1308 } 1309 1310 return exist; 1311 } 1312 1313 /* notify any waiting thread that waiting on a request 1314 * matching the key has been added to the cache */ 1315 static void 1316 _cache_notify_waiting_tid_locked( struct resolv_cache* cache, Entry* key ) 1317 { 1318 struct pending_req_info *ri, *prev; 1319 1320 if (cache && key) { 1321 ri = cache->pending_requests.next; 1322 prev = &cache->pending_requests; 1323 while (ri) { 1324 if (ri->hash == key->hash) { 1325 pthread_cond_broadcast(&ri->cond); 1326 break; 1327 } 1328 prev = ri; 1329 ri = ri->next; 1330 } 1331 1332 // remove item from list and destroy 1333 if (ri) { 1334 prev->next = ri->next; 1335 pthread_cond_destroy(&ri->cond); 1336 free(ri); 1337 } 1338 } 1339 } 1340 1341 /* notify the cache that the query failed */ 1342 void 1343 _resolv_cache_query_failed( unsigned netid, 1344 const void* query, 1345 int querylen) 1346 { 1347 Entry key[1]; 1348 Cache* cache; 1349 1350 if (!entry_init_key(key, query, querylen)) 1351 return; 1352 1353 pthread_mutex_lock(&_res_cache_list_lock); 1354 1355 cache = _find_named_cache_locked(netid); 1356 1357 if (cache) { 1358 _cache_notify_waiting_tid_locked(cache, key); 1359 } 1360 1361 pthread_mutex_unlock(&_res_cache_list_lock); 1362 } 1363 1364 static void 1365 _cache_flush_locked( Cache* cache ) 1366 { 1367 int nn; 1368 1369 for (nn = 0; nn < cache->max_entries; nn++) 1370 { 1371 Entry** pnode = (Entry**) &cache->entries[nn]; 1372 1373 while (*pnode != NULL) { 1374 Entry* node = *pnode; 1375 *pnode = node->hlink; 1376 entry_free(node); 1377 } 1378 } 1379 1380 // flush pending request 1381 _cache_flush_pending_requests_locked(cache); 1382 1383 cache->mru_list.mru_next = cache->mru_list.mru_prev = &cache->mru_list; 1384 cache->num_entries = 0; 1385 cache->last_id = 0; 1386 1387 XLOG("*************************\n" 1388 "*** DNS CACHE FLUSHED ***\n" 1389 "*************************"); 1390 } 1391 1392 static int 1393 _res_cache_get_max_entries( void ) 1394 { 1395 int cache_size = CONFIG_MAX_ENTRIES; 1396 1397 const char* cache_mode = getenv("ANDROID_DNS_MODE"); 1398 if (cache_mode == NULL || strcmp(cache_mode, "local") != 0) { 1399 // Don't use the cache in local mode. This is used by the proxy itself. 1400 cache_size = 0; 1401 } 1402 1403 XLOG("cache size: %d", cache_size); 1404 return cache_size; 1405 } 1406 1407 static struct resolv_cache* 1408 _resolv_cache_create( void ) 1409 { 1410 struct resolv_cache* cache; 1411 1412 cache = calloc(sizeof(*cache), 1); 1413 if (cache) { 1414 cache->max_entries = _res_cache_get_max_entries(); 1415 cache->entries = calloc(sizeof(*cache->entries), cache->max_entries); 1416 if (cache->entries) { 1417 cache->mru_list.mru_prev = cache->mru_list.mru_next = &cache->mru_list; 1418 XLOG("%s: cache created\n", __FUNCTION__); 1419 } else { 1420 free(cache); 1421 cache = NULL; 1422 } 1423 } 1424 return cache; 1425 } 1426 1427 1428 #if DEBUG 1429 static void 1430 _dump_query( const uint8_t* query, int querylen ) 1431 { 1432 char temp[256], *p=temp, *end=p+sizeof(temp); 1433 DnsPacket pack[1]; 1434 1435 _dnsPacket_init(pack, query, querylen); 1436 p = _dnsPacket_bprintQuery(pack, p, end); 1437 XLOG("QUERY: %s", temp); 1438 } 1439 1440 static void 1441 _cache_dump_mru( Cache* cache ) 1442 { 1443 char temp[512], *p=temp, *end=p+sizeof(temp); 1444 Entry* e; 1445 1446 p = _bprint(temp, end, "MRU LIST (%2d): ", cache->num_entries); 1447 for (e = cache->mru_list.mru_next; e != &cache->mru_list; e = e->mru_next) 1448 p = _bprint(p, end, " %d", e->id); 1449 1450 XLOG("%s", temp); 1451 } 1452 1453 static void 1454 _dump_answer(const void* answer, int answerlen) 1455 { 1456 res_state statep; 1457 FILE* fp; 1458 char* buf; 1459 int fileLen; 1460 1461 fp = fopen("/data/reslog.txt", "w+e"); 1462 if (fp != NULL) { 1463 statep = __res_get_state(); 1464 1465 res_pquery(statep, answer, answerlen, fp); 1466 1467 //Get file length 1468 fseek(fp, 0, SEEK_END); 1469 fileLen=ftell(fp); 1470 fseek(fp, 0, SEEK_SET); 1471 buf = (char *)malloc(fileLen+1); 1472 if (buf != NULL) { 1473 //Read file contents into buffer 1474 fread(buf, fileLen, 1, fp); 1475 XLOG("%s\n", buf); 1476 free(buf); 1477 } 1478 fclose(fp); 1479 remove("/data/reslog.txt"); 1480 } 1481 else { 1482 errno = 0; // else debug is introducing error signals 1483 XLOG("%s: can't open file\n", __FUNCTION__); 1484 } 1485 } 1486 #endif 1487 1488 #if DEBUG 1489 # define XLOG_QUERY(q,len) _dump_query((q), (len)) 1490 # define XLOG_ANSWER(a, len) _dump_answer((a), (len)) 1491 #else 1492 # define XLOG_QUERY(q,len) ((void)0) 1493 # define XLOG_ANSWER(a,len) ((void)0) 1494 #endif 1495 1496 /* This function tries to find a key within the hash table 1497 * In case of success, it will return a *pointer* to the hashed key. 1498 * In case of failure, it will return a *pointer* to NULL 1499 * 1500 * So, the caller must check '*result' to check for success/failure. 1501 * 1502 * The main idea is that the result can later be used directly in 1503 * calls to _resolv_cache_add or _resolv_cache_remove as the 'lookup' 1504 * parameter. This makes the code simpler and avoids re-searching 1505 * for the key position in the htable. 1506 * 1507 * The result of a lookup_p is only valid until you alter the hash 1508 * table. 1509 */ 1510 static Entry** 1511 _cache_lookup_p( Cache* cache, 1512 Entry* key ) 1513 { 1514 int index = key->hash % cache->max_entries; 1515 Entry** pnode = (Entry**) &cache->entries[ index ]; 1516 1517 while (*pnode != NULL) { 1518 Entry* node = *pnode; 1519 1520 if (node == NULL) 1521 break; 1522 1523 if (node->hash == key->hash && entry_equals(node, key)) 1524 break; 1525 1526 pnode = &node->hlink; 1527 } 1528 return pnode; 1529 } 1530 1531 /* Add a new entry to the hash table. 'lookup' must be the 1532 * result of an immediate previous failed _lookup_p() call 1533 * (i.e. with *lookup == NULL), and 'e' is the pointer to the 1534 * newly created entry 1535 */ 1536 static void 1537 _cache_add_p( Cache* cache, 1538 Entry** lookup, 1539 Entry* e ) 1540 { 1541 *lookup = e; 1542 e->id = ++cache->last_id; 1543 entry_mru_add(e, &cache->mru_list); 1544 cache->num_entries += 1; 1545 1546 XLOG("%s: entry %d added (count=%d)", __FUNCTION__, 1547 e->id, cache->num_entries); 1548 } 1549 1550 /* Remove an existing entry from the hash table, 1551 * 'lookup' must be the result of an immediate previous 1552 * and succesful _lookup_p() call. 1553 */ 1554 static void 1555 _cache_remove_p( Cache* cache, 1556 Entry** lookup ) 1557 { 1558 Entry* e = *lookup; 1559 1560 XLOG("%s: entry %d removed (count=%d)", __FUNCTION__, 1561 e->id, cache->num_entries-1); 1562 1563 entry_mru_remove(e); 1564 *lookup = e->hlink; 1565 entry_free(e); 1566 cache->num_entries -= 1; 1567 } 1568 1569 /* Remove the oldest entry from the hash table. 1570 */ 1571 static void 1572 _cache_remove_oldest( Cache* cache ) 1573 { 1574 Entry* oldest = cache->mru_list.mru_prev; 1575 Entry** lookup = _cache_lookup_p(cache, oldest); 1576 1577 if (*lookup == NULL) { /* should not happen */ 1578 XLOG("%s: OLDEST NOT IN HTABLE ?", __FUNCTION__); 1579 return; 1580 } 1581 if (DEBUG) { 1582 XLOG("Cache full - removing oldest"); 1583 XLOG_QUERY(oldest->query, oldest->querylen); 1584 } 1585 _cache_remove_p(cache, lookup); 1586 } 1587 1588 /* Remove all expired entries from the hash table. 1589 */ 1590 static void _cache_remove_expired(Cache* cache) { 1591 Entry* e; 1592 time_t now = _time_now(); 1593 1594 for (e = cache->mru_list.mru_next; e != &cache->mru_list;) { 1595 // Entry is old, remove 1596 if (now >= e->expires) { 1597 Entry** lookup = _cache_lookup_p(cache, e); 1598 if (*lookup == NULL) { /* should not happen */ 1599 XLOG("%s: ENTRY NOT IN HTABLE ?", __FUNCTION__); 1600 return; 1601 } 1602 e = e->mru_next; 1603 _cache_remove_p(cache, lookup); 1604 } else { 1605 e = e->mru_next; 1606 } 1607 } 1608 } 1609 1610 ResolvCacheStatus 1611 _resolv_cache_lookup( unsigned netid, 1612 const void* query, 1613 int querylen, 1614 void* answer, 1615 int answersize, 1616 int *answerlen ) 1617 { 1618 Entry key[1]; 1619 Entry** lookup; 1620 Entry* e; 1621 time_t now; 1622 Cache* cache; 1623 1624 ResolvCacheStatus result = RESOLV_CACHE_NOTFOUND; 1625 1626 XLOG("%s: lookup", __FUNCTION__); 1627 XLOG_QUERY(query, querylen); 1628 1629 /* we don't cache malformed queries */ 1630 if (!entry_init_key(key, query, querylen)) { 1631 XLOG("%s: unsupported query", __FUNCTION__); 1632 return RESOLV_CACHE_UNSUPPORTED; 1633 } 1634 /* lookup cache */ 1635 pthread_once(&_res_cache_once, _res_cache_init); 1636 pthread_mutex_lock(&_res_cache_list_lock); 1637 1638 cache = _find_named_cache_locked(netid); 1639 if (cache == NULL) { 1640 result = RESOLV_CACHE_UNSUPPORTED; 1641 goto Exit; 1642 } 1643 1644 /* see the description of _lookup_p to understand this. 1645 * the function always return a non-NULL pointer. 1646 */ 1647 lookup = _cache_lookup_p(cache, key); 1648 e = *lookup; 1649 1650 if (e == NULL) { 1651 XLOG( "NOT IN CACHE"); 1652 // calling thread will wait if an outstanding request is found 1653 // that matching this query 1654 if (!_cache_check_pending_request_locked(&cache, key, netid) || cache == NULL) { 1655 goto Exit; 1656 } else { 1657 lookup = _cache_lookup_p(cache, key); 1658 e = *lookup; 1659 if (e == NULL) { 1660 goto Exit; 1661 } 1662 } 1663 } 1664 1665 now = _time_now(); 1666 1667 /* remove stale entries here */ 1668 if (now >= e->expires) { 1669 XLOG( " NOT IN CACHE (STALE ENTRY %p DISCARDED)", *lookup ); 1670 XLOG_QUERY(e->query, e->querylen); 1671 _cache_remove_p(cache, lookup); 1672 goto Exit; 1673 } 1674 1675 *answerlen = e->answerlen; 1676 if (e->answerlen > answersize) { 1677 /* NOTE: we return UNSUPPORTED if the answer buffer is too short */ 1678 result = RESOLV_CACHE_UNSUPPORTED; 1679 XLOG(" ANSWER TOO LONG"); 1680 goto Exit; 1681 } 1682 1683 memcpy( answer, e->answer, e->answerlen ); 1684 1685 /* bump up this entry to the top of the MRU list */ 1686 if (e != cache->mru_list.mru_next) { 1687 entry_mru_remove( e ); 1688 entry_mru_add( e, &cache->mru_list ); 1689 } 1690 1691 XLOG( "FOUND IN CACHE entry=%p", e ); 1692 result = RESOLV_CACHE_FOUND; 1693 1694 Exit: 1695 pthread_mutex_unlock(&_res_cache_list_lock); 1696 return result; 1697 } 1698 1699 1700 void 1701 _resolv_cache_add( unsigned netid, 1702 const void* query, 1703 int querylen, 1704 const void* answer, 1705 int answerlen ) 1706 { 1707 Entry key[1]; 1708 Entry* e; 1709 Entry** lookup; 1710 u_long ttl; 1711 Cache* cache = NULL; 1712 1713 /* don't assume that the query has already been cached 1714 */ 1715 if (!entry_init_key( key, query, querylen )) { 1716 XLOG( "%s: passed invalid query ?", __FUNCTION__); 1717 return; 1718 } 1719 1720 pthread_mutex_lock(&_res_cache_list_lock); 1721 1722 cache = _find_named_cache_locked(netid); 1723 if (cache == NULL) { 1724 goto Exit; 1725 } 1726 1727 XLOG( "%s: query:", __FUNCTION__ ); 1728 XLOG_QUERY(query,querylen); 1729 XLOG_ANSWER(answer, answerlen); 1730 #if DEBUG_DATA 1731 XLOG( "answer:"); 1732 XLOG_BYTES(answer,answerlen); 1733 #endif 1734 1735 lookup = _cache_lookup_p(cache, key); 1736 e = *lookup; 1737 1738 if (e != NULL) { /* should not happen */ 1739 XLOG("%s: ALREADY IN CACHE (%p) ? IGNORING ADD", 1740 __FUNCTION__, e); 1741 goto Exit; 1742 } 1743 1744 if (cache->num_entries >= cache->max_entries) { 1745 _cache_remove_expired(cache); 1746 if (cache->num_entries >= cache->max_entries) { 1747 _cache_remove_oldest(cache); 1748 } 1749 /* need to lookup again */ 1750 lookup = _cache_lookup_p(cache, key); 1751 e = *lookup; 1752 if (e != NULL) { 1753 XLOG("%s: ALREADY IN CACHE (%p) ? IGNORING ADD", 1754 __FUNCTION__, e); 1755 goto Exit; 1756 } 1757 } 1758 1759 ttl = answer_getTTL(answer, answerlen); 1760 if (ttl > 0) { 1761 e = entry_alloc(key, answer, answerlen); 1762 if (e != NULL) { 1763 e->expires = ttl + _time_now(); 1764 _cache_add_p(cache, lookup, e); 1765 } 1766 } 1767 #if DEBUG 1768 _cache_dump_mru(cache); 1769 #endif 1770 Exit: 1771 if (cache != NULL) { 1772 _cache_notify_waiting_tid_locked(cache, key); 1773 } 1774 pthread_mutex_unlock(&_res_cache_list_lock); 1775 } 1776 1777 /****************************************************************************/ 1778 /****************************************************************************/ 1779 /***** *****/ 1780 /***** *****/ 1781 /***** *****/ 1782 /****************************************************************************/ 1783 /****************************************************************************/ 1784 1785 // Head of the list of caches. Protected by _res_cache_list_lock. 1786 static struct resolv_cache_info _res_cache_list; 1787 1788 /* insert resolv_cache_info into the list of resolv_cache_infos */ 1789 static void _insert_cache_info_locked(struct resolv_cache_info* cache_info); 1790 /* creates a resolv_cache_info */ 1791 static struct resolv_cache_info* _create_cache_info( void ); 1792 /* gets a resolv_cache_info associated with a network, or NULL if not found */ 1793 static struct resolv_cache_info* _find_cache_info_locked(unsigned netid); 1794 /* look up the named cache, and creates one if needed */ 1795 static struct resolv_cache* _get_res_cache_for_net_locked(unsigned netid); 1796 /* empty the named cache */ 1797 static void _flush_cache_for_net_locked(unsigned netid); 1798 /* empty the nameservers set for the named cache */ 1799 static void _free_nameservers_locked(struct resolv_cache_info* cache_info); 1800 /* return 1 if the provided list of name servers differs from the list of name servers 1801 * currently attached to the provided cache_info */ 1802 static int _resolv_is_nameservers_equal_locked(struct resolv_cache_info* cache_info, 1803 const char** servers, int numservers); 1804 1805 static void 1806 _res_cache_init(void) 1807 { 1808 const char* env = getenv(CONFIG_ENV); 1809 1810 if (env && atoi(env) == 0) { 1811 /* the cache is disabled */ 1812 return; 1813 } 1814 1815 memset(&_res_cache_list, 0, sizeof(_res_cache_list)); 1816 pthread_mutex_init(&_res_cache_list_lock, NULL); 1817 } 1818 1819 static struct resolv_cache* 1820 _get_res_cache_for_net_locked(unsigned netid) 1821 { 1822 struct resolv_cache* cache = _find_named_cache_locked(netid); 1823 if (!cache) { 1824 struct resolv_cache_info* cache_info = _create_cache_info(); 1825 if (cache_info) { 1826 cache = _resolv_cache_create(); 1827 if (cache) { 1828 cache_info->cache = cache; 1829 cache_info->netid = netid; 1830 _insert_cache_info_locked(cache_info); 1831 } else { 1832 free(cache_info); 1833 } 1834 } 1835 } 1836 return cache; 1837 } 1838 1839 void 1840 _resolv_flush_cache_for_net(unsigned netid) 1841 { 1842 pthread_once(&_res_cache_once, _res_cache_init); 1843 pthread_mutex_lock(&_res_cache_list_lock); 1844 1845 _flush_cache_for_net_locked(netid); 1846 1847 pthread_mutex_unlock(&_res_cache_list_lock); 1848 } 1849 1850 static void 1851 _flush_cache_for_net_locked(unsigned netid) 1852 { 1853 struct resolv_cache* cache = _find_named_cache_locked(netid); 1854 if (cache) { 1855 _cache_flush_locked(cache); 1856 } 1857 } 1858 1859 void _resolv_delete_cache_for_net(unsigned netid) 1860 { 1861 pthread_once(&_res_cache_once, _res_cache_init); 1862 pthread_mutex_lock(&_res_cache_list_lock); 1863 1864 struct resolv_cache_info* prev_cache_info = &_res_cache_list; 1865 1866 while (prev_cache_info->next) { 1867 struct resolv_cache_info* cache_info = prev_cache_info->next; 1868 1869 if (cache_info->netid == netid) { 1870 prev_cache_info->next = cache_info->next; 1871 _cache_flush_locked(cache_info->cache); 1872 free(cache_info->cache->entries); 1873 free(cache_info->cache); 1874 _free_nameservers_locked(cache_info); 1875 free(cache_info); 1876 break; 1877 } 1878 1879 prev_cache_info = prev_cache_info->next; 1880 } 1881 1882 pthread_mutex_unlock(&_res_cache_list_lock); 1883 } 1884 1885 static struct resolv_cache_info* 1886 _create_cache_info(void) 1887 { 1888 struct resolv_cache_info* cache_info; 1889 1890 cache_info = calloc(sizeof(*cache_info), 1); 1891 return cache_info; 1892 } 1893 1894 static void 1895 _insert_cache_info_locked(struct resolv_cache_info* cache_info) 1896 { 1897 struct resolv_cache_info* last; 1898 1899 for (last = &_res_cache_list; last->next; last = last->next); 1900 1901 last->next = cache_info; 1902 1903 } 1904 1905 static struct resolv_cache* 1906 _find_named_cache_locked(unsigned netid) { 1907 1908 struct resolv_cache_info* info = _find_cache_info_locked(netid); 1909 1910 if (info != NULL) return info->cache; 1911 1912 return NULL; 1913 } 1914 1915 static struct resolv_cache_info* 1916 _find_cache_info_locked(unsigned netid) 1917 { 1918 struct resolv_cache_info* cache_info = _res_cache_list.next; 1919 1920 while (cache_info) { 1921 if (cache_info->netid == netid) { 1922 break; 1923 } 1924 1925 cache_info = cache_info->next; 1926 } 1927 return cache_info; 1928 } 1929 1930 void 1931 _resolv_set_nameservers_for_net(unsigned netid, const char** servers, int numservers, 1932 const char *domains) 1933 { 1934 int i, rt, index; 1935 struct addrinfo hints; 1936 char sbuf[NI_MAXSERV]; 1937 register char *cp; 1938 int *offset; 1939 1940 pthread_once(&_res_cache_once, _res_cache_init); 1941 pthread_mutex_lock(&_res_cache_list_lock); 1942 1943 // creates the cache if not created 1944 _get_res_cache_for_net_locked(netid); 1945 1946 struct resolv_cache_info* cache_info = _find_cache_info_locked(netid); 1947 1948 if (cache_info != NULL && 1949 !_resolv_is_nameservers_equal_locked(cache_info, servers, numservers)) { 1950 // free current before adding new 1951 _free_nameservers_locked(cache_info); 1952 1953 memset(&hints, 0, sizeof(hints)); 1954 hints.ai_family = PF_UNSPEC; 1955 hints.ai_socktype = SOCK_DGRAM; /*dummy*/ 1956 hints.ai_flags = AI_NUMERICHOST; 1957 snprintf(sbuf, sizeof(sbuf), "%u", NAMESERVER_PORT); 1958 1959 index = 0; 1960 for (i = 0; i < numservers && i < MAXNS; i++) { 1961 rt = getaddrinfo(servers[i], sbuf, &hints, &cache_info->nsaddrinfo[index]); 1962 if (rt == 0) { 1963 cache_info->nameservers[index] = strdup(servers[i]); 1964 index++; 1965 XLOG("%s: netid = %u, addr = %s\n", __FUNCTION__, netid, servers[i]); 1966 } else { 1967 cache_info->nsaddrinfo[index] = NULL; 1968 } 1969 } 1970 1971 // code moved from res_init.c, load_domain_search_list 1972 strlcpy(cache_info->defdname, domains, sizeof(cache_info->defdname)); 1973 if ((cp = strchr(cache_info->defdname, '\n')) != NULL) 1974 *cp = '\0'; 1975 cp = cache_info->defdname; 1976 offset = cache_info->dnsrch_offset; 1977 while (offset < cache_info->dnsrch_offset + MAXDNSRCH) { 1978 while (*cp == ' ' || *cp == '\t') /* skip leading white space */ 1979 cp++; 1980 if (*cp == '\0') /* stop if nothing more to do */ 1981 break; 1982 *offset++ = cp - cache_info->defdname; /* record this search domain */ 1983 while (*cp) { /* zero-terminate it */ 1984 if (*cp == ' '|| *cp == '\t') { 1985 *cp++ = '\0'; 1986 break; 1987 } 1988 cp++; 1989 } 1990 } 1991 *offset = -1; /* cache_info->dnsrch_offset has MAXDNSRCH+1 items */ 1992 1993 // flush cache since new settings 1994 _flush_cache_for_net_locked(netid); 1995 1996 } 1997 1998 pthread_mutex_unlock(&_res_cache_list_lock); 1999 } 2000 2001 static int 2002 _resolv_is_nameservers_equal_locked(struct resolv_cache_info* cache_info, 2003 const char** servers, int numservers) 2004 { 2005 int i; 2006 char** ns; 2007 int currentservers; 2008 int equal = 1; 2009 2010 if (numservers > MAXNS) numservers = MAXNS; 2011 2012 // Find out how many nameservers we had before. 2013 currentservers = 0; 2014 for (ns = cache_info->nameservers; *ns; ns++) 2015 currentservers++; 2016 2017 if (currentservers != numservers) 2018 return 0; 2019 2020 // Compare each name server against current name servers. 2021 // TODO: this is incorrect if the list of current or previous nameservers 2022 // contains duplicates. This does not really matter because the framework 2023 // filters out duplicates, but we should probably fix it. It's also 2024 // insensitive to the order of the nameservers; we should probably fix that 2025 // too. 2026 for (i = 0; i < numservers && equal; i++) { 2027 ns = cache_info->nameservers; 2028 equal = 0; 2029 while(*ns) { 2030 if (strcmp(*ns, servers[i]) == 0) { 2031 equal = 1; 2032 break; 2033 } 2034 ns++; 2035 } 2036 } 2037 2038 return equal; 2039 } 2040 2041 static void 2042 _free_nameservers_locked(struct resolv_cache_info* cache_info) 2043 { 2044 int i; 2045 for (i = 0; i <= MAXNS; i++) { 2046 free(cache_info->nameservers[i]); 2047 cache_info->nameservers[i] = NULL; 2048 if (cache_info->nsaddrinfo[i] != NULL) { 2049 freeaddrinfo(cache_info->nsaddrinfo[i]); 2050 cache_info->nsaddrinfo[i] = NULL; 2051 } 2052 } 2053 } 2054 2055 void 2056 _resolv_populate_res_for_net(res_state statp) 2057 { 2058 if (statp == NULL) { 2059 return; 2060 } 2061 2062 pthread_once(&_res_cache_once, _res_cache_init); 2063 pthread_mutex_lock(&_res_cache_list_lock); 2064 2065 struct resolv_cache_info* info = _find_cache_info_locked(statp->netid); 2066 if (info != NULL) { 2067 int nserv; 2068 struct addrinfo* ai; 2069 XLOG("%s: %u\n", __FUNCTION__, statp->netid); 2070 for (nserv = 0; nserv < MAXNS; nserv++) { 2071 ai = info->nsaddrinfo[nserv]; 2072 if (ai == NULL) { 2073 break; 2074 } 2075 2076 if ((size_t) ai->ai_addrlen <= sizeof(statp->_u._ext.ext->nsaddrs[0])) { 2077 if (statp->_u._ext.ext != NULL) { 2078 memcpy(&statp->_u._ext.ext->nsaddrs[nserv], ai->ai_addr, ai->ai_addrlen); 2079 statp->nsaddr_list[nserv].sin_family = AF_UNSPEC; 2080 } else { 2081 if ((size_t) ai->ai_addrlen 2082 <= sizeof(statp->nsaddr_list[0])) { 2083 memcpy(&statp->nsaddr_list[nserv], ai->ai_addr, 2084 ai->ai_addrlen); 2085 } else { 2086 statp->nsaddr_list[nserv].sin_family = AF_UNSPEC; 2087 } 2088 } 2089 } else { 2090 XLOG("%s: found too long addrlen", __FUNCTION__); 2091 } 2092 } 2093 statp->nscount = nserv; 2094 // now do search domains. Note that we cache the offsets as this code runs alot 2095 // but the setting/offset-computer only runs when set/changed 2096 strlcpy(statp->defdname, info->defdname, sizeof(statp->defdname)); 2097 register char **pp = statp->dnsrch; 2098 register int *p = info->dnsrch_offset; 2099 while (pp < statp->dnsrch + MAXDNSRCH && *p != -1) { 2100 *pp++ = &statp->defdname[0] + *p++; 2101 } 2102 } 2103 pthread_mutex_unlock(&_res_cache_list_lock); 2104 } 2105