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