1 /* dnsmasq is Copyright (c) 2000-2009 Simon Kelley 2 3 This program is free software; you can redistribute it and/or modify 4 it under the terms of the GNU General Public License as published by 5 the Free Software Foundation; version 2 dated June, 1991, or 6 (at your option) version 3 dated 29 June, 2007. 7 8 This program is distributed in the hope that it will be useful, 9 but WITHOUT ANY WARRANTY; without even the implied warranty of 10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 GNU General Public License for more details. 12 13 You should have received a copy of the GNU General Public License 14 along with this program. If not, see <http://www.gnu.org/licenses/>. 15 */ 16 17 #include "dnsmasq.h" 18 19 static struct crec *cache_head = NULL, *cache_tail = NULL, **hash_table = NULL; 20 #ifdef HAVE_DHCP 21 static struct crec* dhcp_spare = NULL; 22 #endif 23 static struct crec* new_chain = NULL; 24 static int cache_inserted = 0, cache_live_freed = 0, insert_error; 25 static union bigname* big_free = NULL; 26 static int bignames_left, hash_size; 27 static int uid = 0; 28 static char* addrbuff = NULL; 29 30 /* type->string mapping: this is also used by the name-hash function as a mixing table. */ 31 static const struct { 32 unsigned int type; 33 const char* const name; 34 } typestr[] = {{1, "A"}, {2, "NS"}, {5, "CNAME"}, {6, "SOA"}, {10, "NULL"}, 35 {11, "WKS"}, {12, "PTR"}, {13, "HINFO"}, {15, "MX"}, {16, "TXT"}, 36 {22, "NSAP"}, {23, "NSAP_PTR"}, {24, "SIG"}, {25, "KEY"}, {28, "AAAA"}, 37 {33, "SRV"}, {35, "NAPTR"}, {36, "KX"}, {37, "CERT"}, {38, "A6"}, 38 {39, "DNAME"}, {41, "OPT"}, {48, "DNSKEY"}, {249, "TKEY"}, {250, "TSIG"}, 39 {251, "IXFR"}, {252, "AXFR"}, {253, "MAILB"}, {254, "MAILA"}, {255, "ANY"}}; 40 41 static void cache_free(struct crec* crecp); 42 static void cache_unlink(struct crec* crecp); 43 static void cache_link(struct crec* crecp); 44 static void rehash(int size); 45 static void cache_hash(struct crec* crecp); 46 47 void cache_init(void) { 48 struct crec* crecp; 49 int i; 50 51 if (daemon->options & OPT_LOG) addrbuff = safe_malloc(ADDRSTRLEN); 52 53 bignames_left = daemon->cachesize / 10; 54 55 if (daemon->cachesize > 0) { 56 crecp = safe_malloc(daemon->cachesize * sizeof(struct crec)); 57 58 for (i = 0; i < daemon->cachesize; i++, crecp++) { 59 cache_link(crecp); 60 crecp->flags = 0; 61 crecp->uid = uid++; 62 } 63 } 64 65 /* create initial hash table*/ 66 rehash(daemon->cachesize); 67 } 68 69 /* In most cases, we create the hash table once here by calling this with (hash_table == NULL) 70 but if the hosts file(s) are big (some people have 50000 ad-block entries), the table 71 will be much too small, so the hosts reading code calls rehash every 1000 addresses, to 72 expand the table. */ 73 static void rehash(int size) { 74 struct crec** new, **old, *p, *tmp; 75 int i, new_size, old_size; 76 77 /* hash_size is a power of two. */ 78 for (new_size = 64; new_size < size / 10; new_size = new_size << 1) 79 ; 80 81 /* must succeed in getting first instance, failure later is non-fatal */ 82 if (!hash_table) 83 new = safe_malloc(new_size * sizeof(struct crec*)); 84 else if (new_size <= hash_size || !(new = whine_malloc(new_size * sizeof(struct crec*)))) 85 return; 86 87 for (i = 0; i < new_size; i++) new[i] = NULL; 88 89 old = hash_table; 90 old_size = hash_size; 91 hash_table = new; 92 hash_size = new_size; 93 94 if (old) { 95 for (i = 0; i < old_size; i++) 96 for (p = old[i]; p; p = tmp) { 97 tmp = p->hash_next; 98 cache_hash(p); 99 } 100 free(old); 101 } 102 } 103 104 static struct crec** hash_bucket(char* name) { 105 unsigned int c, val = 017465; /* Barker code - minimum self-correlation in cyclic shift */ 106 const unsigned char* mix_tab = (const unsigned char*) typestr; 107 108 while ((c = (unsigned char) *name++)) { 109 /* don't use tolower and friends here - they may be messed up by LOCALE */ 110 if (c >= 'A' && c <= 'Z') c += 'a' - 'A'; 111 val = ((val << 7) | (val >> (32 - 7))) + (mix_tab[(val + c) & 0x3F] ^ c); 112 } 113 114 /* hash_size is a power of two */ 115 return hash_table + ((val ^ (val >> 16)) & (hash_size - 1)); 116 } 117 118 static void cache_hash(struct crec* crecp) { 119 /* maintain an invariant that all entries with F_REVERSE set 120 are at the start of the hash-chain and all non-reverse 121 immortal entries are at the end of the hash-chain. 122 This allows reverse searches and garbage collection to be optimised */ 123 124 struct crec** up = hash_bucket(cache_get_name(crecp)); 125 126 if (!(crecp->flags & F_REVERSE)) { 127 while (*up && ((*up)->flags & F_REVERSE)) up = &((*up)->hash_next); 128 129 if (crecp->flags & F_IMMORTAL) 130 while (*up && !((*up)->flags & F_IMMORTAL)) up = &((*up)->hash_next); 131 } 132 crecp->hash_next = *up; 133 *up = crecp; 134 } 135 136 static void cache_free(struct crec* crecp) { 137 crecp->flags &= ~F_FORWARD; 138 crecp->flags &= ~F_REVERSE; 139 crecp->uid = uid++; /* invalidate CNAMES pointing to this. */ 140 141 if (cache_tail) 142 cache_tail->next = crecp; 143 else 144 cache_head = crecp; 145 crecp->prev = cache_tail; 146 crecp->next = NULL; 147 cache_tail = crecp; 148 149 /* retrieve big name for further use. */ 150 if (crecp->flags & F_BIGNAME) { 151 crecp->name.bname->next = big_free; 152 big_free = crecp->name.bname; 153 crecp->flags &= ~F_BIGNAME; 154 } 155 } 156 157 /* insert a new cache entry at the head of the list (youngest entry) */ 158 static void cache_link(struct crec* crecp) { 159 if (cache_head) /* check needed for init code */ 160 cache_head->prev = crecp; 161 crecp->next = cache_head; 162 crecp->prev = NULL; 163 cache_head = crecp; 164 if (!cache_tail) cache_tail = crecp; 165 } 166 167 /* remove an arbitrary cache entry for promotion */ 168 static void cache_unlink(struct crec* crecp) { 169 if (crecp->prev) 170 crecp->prev->next = crecp->next; 171 else 172 cache_head = crecp->next; 173 174 if (crecp->next) 175 crecp->next->prev = crecp->prev; 176 else 177 cache_tail = crecp->prev; 178 } 179 180 char* cache_get_name(struct crec* crecp) { 181 if (crecp->flags & F_BIGNAME) 182 return crecp->name.bname->name; 183 else if (crecp->flags & (F_DHCP | F_CONFIG)) 184 return crecp->name.namep; 185 186 return crecp->name.sname; 187 } 188 189 static int is_outdated_cname_pointer(struct crec* crecp) { 190 if (!(crecp->flags & F_CNAME)) return 0; 191 192 if (crecp->addr.cname.cache && crecp->addr.cname.uid == crecp->addr.cname.cache->uid) return 0; 193 194 return 1; 195 } 196 197 static int is_expired(time_t now, struct crec* crecp) { 198 if (crecp->flags & F_IMMORTAL) return 0; 199 200 if (difftime(now, crecp->ttd) < 0) return 0; 201 202 return 1; 203 } 204 205 static int cache_scan_free(char* name, struct all_addr* addr, time_t now, unsigned short flags) { 206 /* Scan and remove old entries. 207 If (flags & F_FORWARD) then remove any forward entries for name and any expired 208 entries but only in the same hash bucket as name. 209 If (flags & F_REVERSE) then remove any reverse entries for addr and any expired 210 entries in the whole cache. 211 If (flags == 0) remove any expired entries in the whole cache. 212 213 In the flags & F_FORWARD case, the return code is valid, and returns zero if the 214 name exists in the cache as a HOSTS or DHCP entry (these are never deleted) 215 216 We take advantage of the fact that hash chains have stuff in the order 217 <reverse>,<other>,<immortal> so that when we hit an entry which isn't reverse and is 218 immortal, we're done. */ 219 220 struct crec *crecp, **up; 221 222 if (flags & F_FORWARD) { 223 for (up = hash_bucket(name), crecp = *up; crecp; crecp = crecp->hash_next) 224 if (is_expired(now, crecp) || is_outdated_cname_pointer(crecp)) { 225 *up = crecp->hash_next; 226 if (!(crecp->flags & (F_HOSTS | F_DHCP))) { 227 cache_unlink(crecp); 228 cache_free(crecp); 229 } 230 } else if ((crecp->flags & F_FORWARD) && 231 ((flags & crecp->flags & (F_IPV4 | F_IPV6)) || 232 ((crecp->flags | flags) & F_CNAME)) && 233 hostname_isequal(cache_get_name(crecp), name)) { 234 if (crecp->flags & (F_HOSTS | F_DHCP)) return 0; 235 *up = crecp->hash_next; 236 cache_unlink(crecp); 237 cache_free(crecp); 238 } else 239 up = &crecp->hash_next; 240 } else { 241 int i; 242 #ifdef HAVE_IPV6 243 int addrlen = (flags & F_IPV6) ? IN6ADDRSZ : INADDRSZ; 244 #else 245 int addrlen = INADDRSZ; 246 #endif 247 for (i = 0; i < hash_size; i++) 248 for (crecp = hash_table[i], up = &hash_table[i]; 249 crecp && ((crecp->flags & F_REVERSE) || !(crecp->flags & F_IMMORTAL)); 250 crecp = crecp->hash_next) 251 if (is_expired(now, crecp)) { 252 *up = crecp->hash_next; 253 if (!(crecp->flags & (F_HOSTS | F_DHCP))) { 254 cache_unlink(crecp); 255 cache_free(crecp); 256 } 257 } else if (!(crecp->flags & (F_HOSTS | F_DHCP)) && 258 (flags & crecp->flags & F_REVERSE) && 259 (flags & crecp->flags & (F_IPV4 | F_IPV6)) && 260 memcmp(&crecp->addr.addr, addr, addrlen) == 0) { 261 *up = crecp->hash_next; 262 cache_unlink(crecp); 263 cache_free(crecp); 264 } else 265 up = &crecp->hash_next; 266 } 267 268 return 1; 269 } 270 271 /* Note: The normal calling sequence is 272 cache_start_insert 273 cache_insert * n 274 cache_end_insert 275 276 but an abort can cause the cache_end_insert to be missed 277 in which can the next cache_start_insert cleans things up. */ 278 279 void cache_start_insert(void) { 280 /* Free any entries which didn't get committed during the last 281 insert due to error. 282 */ 283 while (new_chain) { 284 struct crec* tmp = new_chain->next; 285 cache_free(new_chain); 286 new_chain = tmp; 287 } 288 new_chain = NULL; 289 insert_error = 0; 290 } 291 292 struct crec* cache_insert(char* name, struct all_addr* addr, time_t now, unsigned long ttl, 293 unsigned short flags) { 294 struct crec* new; 295 union bigname* big_name = NULL; 296 int freed_all = flags & F_REVERSE; 297 int free_avail = 0; 298 299 log_query(flags | F_UPSTREAM, name, addr, NULL); 300 301 /* CONFIG bit means something else when stored in cache entries */ 302 flags &= ~F_CONFIG; 303 304 /* if previous insertion failed give up now. */ 305 if (insert_error) return NULL; 306 307 /* First remove any expired entries and entries for the name/address we 308 are currently inserting. Fail is we attempt to delete a name from 309 /etc/hosts or DHCP. */ 310 if (!cache_scan_free(name, addr, now, flags)) { 311 insert_error = 1; 312 return NULL; 313 } 314 315 /* Now get a cache entry from the end of the LRU list */ 316 while (1) { 317 if (!(new = cache_tail)) /* no entries left - cache is too small, bail */ 318 { 319 insert_error = 1; 320 return NULL; 321 } 322 323 /* End of LRU list is still in use: if we didn't scan all the hash 324 chains for expired entries do that now. If we already tried that 325 then it's time to start spilling things. */ 326 327 if (new->flags&(F_FORWARD | F_REVERSE)) { 328 /* If free_avail set, we believe that an entry has been freed. 329 Bugs have been known to make this not true, resulting in 330 a tight loop here. If that happens, abandon the 331 insert. Once in this state, all inserts will probably fail. */ 332 if (free_avail) { 333 insert_error = 1; 334 return NULL; 335 } 336 337 if (freed_all) { 338 free_avail = 1; /* Must be free space now. */ 339 cache_scan_free(cache_get_name(new), &new->addr.addr, now, new->flags); 340 cache_live_freed++; 341 } else { 342 cache_scan_free(NULL, NULL, now, 0); 343 freed_all = 1; 344 } 345 continue; 346 } 347 348 /* Check if we need to and can allocate extra memory for a long name. 349 If that fails, give up now. */ 350 if (name && (strlen(name) > SMALLDNAME - 1)) { 351 if (big_free) { 352 big_name = big_free; 353 big_free = big_free->next; 354 } else if (!bignames_left || 355 !(big_name = (union bigname*) whine_malloc(sizeof(union bigname)))) { 356 insert_error = 1; 357 return NULL; 358 } else 359 bignames_left--; 360 } 361 362 /* Got the rest: finally grab entry. */ 363 cache_unlink(new); 364 break; 365 } 366 367 new->flags = flags; 368 if (big_name) { 369 new->name.bname = big_name; 370 new->flags |= F_BIGNAME; 371 } 372 373 if (name) 374 strcpy(cache_get_name(new), name); 375 else 376 *cache_get_name(new) = 0; 377 378 if (addr) 379 new->addr.addr = *addr; 380 else 381 new->addr.cname.cache = NULL; 382 383 new->ttd = now + (time_t) ttl; 384 new->next = new_chain; 385 new_chain = new; 386 387 return new; 388 } 389 390 /* after end of insertion, commit the new entries */ 391 void cache_end_insert(void) { 392 if (insert_error) return; 393 394 while (new_chain) { 395 struct crec* tmp = new_chain->next; 396 /* drop CNAMEs which didn't find a target. */ 397 if (is_outdated_cname_pointer(new_chain)) 398 cache_free(new_chain); 399 else { 400 cache_hash(new_chain); 401 cache_link(new_chain); 402 cache_inserted++; 403 } 404 new_chain = tmp; 405 } 406 new_chain = NULL; 407 } 408 409 struct crec* cache_find_by_name(struct crec* crecp, char* name, time_t now, unsigned short prot) { 410 struct crec* ans; 411 412 if (crecp) /* iterating */ 413 ans = crecp->next; 414 else { 415 /* first search, look for relevant entries and push to top of list 416 also free anything which has expired */ 417 struct crec *next, **up, **insert = NULL, **chainp = &ans; 418 int ins_flags = 0; 419 420 for (up = hash_bucket(name), crecp = *up; crecp; crecp = next) { 421 next = crecp->hash_next; 422 423 if (!is_expired(now, crecp) && !is_outdated_cname_pointer(crecp)) { 424 if ((crecp->flags & F_FORWARD) && (crecp->flags & prot) && 425 hostname_isequal(cache_get_name(crecp), name)) { 426 if (crecp->flags & (F_HOSTS | F_DHCP)) { 427 *chainp = crecp; 428 chainp = &crecp->next; 429 } else { 430 cache_unlink(crecp); 431 cache_link(crecp); 432 } 433 434 /* Move all but the first entry up the hash chain 435 this implements round-robin. 436 Make sure that re-ordering doesn't break the hash-chain 437 order invariants. 438 */ 439 if (insert && (crecp->flags & (F_REVERSE | F_IMMORTAL)) == ins_flags) { 440 *up = crecp->hash_next; 441 crecp->hash_next = *insert; 442 *insert = crecp; 443 insert = &crecp->hash_next; 444 } else { 445 if (!insert) { 446 insert = up; 447 ins_flags = crecp->flags & (F_REVERSE | F_IMMORTAL); 448 } 449 up = &crecp->hash_next; 450 } 451 } else 452 /* case : not expired, incorrect entry. */ 453 up = &crecp->hash_next; 454 } else { 455 /* expired entry, free it */ 456 *up = crecp->hash_next; 457 if (!(crecp->flags & (F_HOSTS | F_DHCP))) { 458 cache_unlink(crecp); 459 cache_free(crecp); 460 } 461 } 462 } 463 464 *chainp = cache_head; 465 } 466 467 if (ans && (ans->flags & F_FORWARD) && (ans->flags & prot) && 468 hostname_isequal(cache_get_name(ans), name)) 469 return ans; 470 471 return NULL; 472 } 473 474 struct crec* cache_find_by_addr(struct crec* crecp, struct all_addr* addr, time_t now, 475 unsigned short prot) { 476 struct crec* ans; 477 #ifdef HAVE_IPV6 478 int addrlen = (prot == F_IPV6) ? IN6ADDRSZ : INADDRSZ; 479 #else 480 int addrlen = INADDRSZ; 481 #endif 482 483 if (crecp) /* iterating */ 484 ans = crecp->next; 485 else { 486 /* first search, look for relevant entries and push to top of list 487 also free anything which has expired. All the reverse entries are at the 488 start of the hash chain, so we can give up when we find the first 489 non-REVERSE one. */ 490 int i; 491 struct crec **up, **chainp = &ans; 492 493 for (i = 0; i < hash_size; i++) 494 for (crecp = hash_table[i], up = &hash_table[i]; crecp && (crecp->flags & F_REVERSE); 495 crecp = crecp->hash_next) 496 if (!is_expired(now, crecp)) { 497 if ((crecp->flags & prot) && memcmp(&crecp->addr.addr, addr, addrlen) == 0) { 498 if (crecp->flags & (F_HOSTS | F_DHCP)) { 499 *chainp = crecp; 500 chainp = &crecp->next; 501 } else { 502 cache_unlink(crecp); 503 cache_link(crecp); 504 } 505 } 506 up = &crecp->hash_next; 507 } else { 508 *up = crecp->hash_next; 509 if (!(crecp->flags & (F_HOSTS | F_DHCP))) { 510 cache_unlink(crecp); 511 cache_free(crecp); 512 } 513 } 514 515 *chainp = cache_head; 516 } 517 518 if (ans && (ans->flags & F_REVERSE) && (ans->flags & prot) && 519 memcmp(&ans->addr.addr, addr, addrlen) == 0) 520 return ans; 521 522 return NULL; 523 } 524 525 static void add_hosts_entry(struct crec* cache, struct all_addr* addr, int addrlen, 526 unsigned short flags, int index, int addr_dup) { 527 struct crec* lookup = cache_find_by_name(NULL, cache->name.sname, 0, flags & (F_IPV4 | F_IPV6)); 528 int i, nameexists = 0; 529 struct cname* a; 530 531 /* Remove duplicates in hosts files. */ 532 if (lookup && (lookup->flags & F_HOSTS)) { 533 nameexists = 1; 534 if (memcmp(&lookup->addr.addr, addr, addrlen) == 0) { 535 free(cache); 536 return; 537 } 538 } 539 540 /* Ensure there is only one address -> name mapping (first one trumps) 541 We do this by steam here, first we see if the address is the same as 542 the last one we saw, which eliminates most in the case of an ad-block 543 file with thousands of entries for the same address. 544 Then we search and bail at the first matching address that came from 545 a HOSTS file. Since the first host entry gets reverse, we know 546 then that it must exist without searching exhaustively for it. */ 547 548 if (addr_dup) 549 flags &= ~F_REVERSE; 550 else 551 for (i = 0; i < hash_size; i++) { 552 for (lookup = hash_table[i]; lookup; lookup = lookup->hash_next) 553 if ((lookup->flags & F_HOSTS) && (lookup->flags & flags & (F_IPV4 | F_IPV6)) && 554 memcmp(&lookup->addr.addr, addr, addrlen) == 0) { 555 flags &= ~F_REVERSE; 556 break; 557 } 558 if (lookup) break; 559 } 560 561 cache->flags = flags; 562 cache->uid = index; 563 memcpy(&cache->addr.addr, addr, addrlen); 564 cache_hash(cache); 565 566 /* don't need to do alias stuff for second and subsequent addresses. */ 567 if (!nameexists) 568 for (a = daemon->cnames; a; a = a->next) 569 if (hostname_isequal(cache->name.sname, a->target) && 570 (lookup = whine_malloc(sizeof(struct crec)))) { 571 lookup->flags = F_FORWARD | F_IMMORTAL | F_CONFIG | F_HOSTS | F_CNAME; 572 lookup->name.namep = a->alias; 573 lookup->addr.cname.cache = cache; 574 lookup->addr.cname.uid = index; 575 cache_hash(lookup); 576 } 577 } 578 579 static int eatspace(FILE* f) { 580 int c, nl = 0; 581 582 while (1) { 583 if ((c = getc(f)) == '#') 584 while (c != '\n' && c != EOF) c = getc(f); 585 586 if (c == EOF) return 1; 587 588 if (!isspace(c)) { 589 ungetc(c, f); 590 return nl; 591 } 592 593 if (c == '\n') nl = 1; 594 } 595 } 596 597 static int gettok(FILE* f, char* token) { 598 int c, count = 0; 599 600 while (1) { 601 if ((c = getc(f)) == EOF) return (count == 0) ? EOF : 1; 602 603 if (isspace(c) || c == '#') { 604 ungetc(c, f); 605 return eatspace(f); 606 } 607 608 if (count < (MAXDNAME - 1)) { 609 token[count++] = c; 610 token[count] = 0; 611 } 612 } 613 } 614 615 static int read_hostsfile(char* filename, int index, int cache_size) { 616 FILE* f = fopen(filename, "r"); 617 char *token = daemon->namebuff, *domain_suffix = NULL; 618 int addr_count = 0, name_count = cache_size, lineno = 0; 619 unsigned short flags = 0, saved_flags = 0; 620 struct all_addr addr, saved_addr; 621 int atnl, addrlen = 0, addr_dup; 622 623 if (!f) { 624 my_syslog(LOG_ERR, _("failed to load names from %s: %s"), filename, strerror(errno)); 625 return 0; 626 } 627 628 eatspace(f); 629 630 while ((atnl = gettok(f, token)) != EOF) { 631 addr_dup = 0; 632 lineno++; 633 634 #ifdef HAVE_IPV6 635 if (inet_pton(AF_INET, token, &addr) > 0) { 636 flags = F_HOSTS | F_IMMORTAL | F_FORWARD | F_REVERSE | F_IPV4; 637 addrlen = INADDRSZ; 638 domain_suffix = get_domain(addr.addr.addr4); 639 } else if (inet_pton(AF_INET6, token, &addr) > 0) { 640 flags = F_HOSTS | F_IMMORTAL | F_FORWARD | F_REVERSE | F_IPV6; 641 addrlen = IN6ADDRSZ; 642 domain_suffix = daemon->domain_suffix; 643 } 644 #else 645 if ((addr.addr.addr4.s_addr = inet_addr(token)) != (in_addr_t) -1) { 646 flags = F_HOSTS | F_IMMORTAL | F_FORWARD | F_REVERSE | F_IPV4; 647 addrlen = INADDRSZ; 648 domain_suffix = get_domain(addr.addr.addr4); 649 } 650 #endif 651 else { 652 my_syslog(LOG_ERR, _("bad address at %s line %d"), filename, lineno); 653 while (atnl == 0) atnl = gettok(f, token); 654 continue; 655 } 656 657 if (saved_flags == flags && memcmp(&addr, &saved_addr, addrlen) == 0) 658 addr_dup = 1; 659 else { 660 saved_flags = flags; 661 saved_addr = addr; 662 } 663 664 addr_count++; 665 666 /* rehash every 1000 names. */ 667 if ((name_count - cache_size) > 1000) { 668 rehash(name_count); 669 cache_size = name_count; 670 } 671 672 while (atnl == 0) { 673 struct crec* cache; 674 int fqdn, nomem; 675 char* canon; 676 677 if ((atnl = gettok(f, token)) == EOF) break; 678 679 fqdn = !!strchr(token, '.'); 680 681 if ((canon = canonicalise(token, &nomem))) { 682 /* If set, add a version of the name with a default domain appended */ 683 if ((daemon->options & OPT_EXPAND) && domain_suffix && !fqdn && 684 (cache = whine_malloc(sizeof(struct crec) + strlen(canon) + 2 + 685 strlen(domain_suffix) - SMALLDNAME))) { 686 strcpy(cache->name.sname, canon); 687 strcat(cache->name.sname, "."); 688 strcat(cache->name.sname, domain_suffix); 689 add_hosts_entry(cache, &addr, addrlen, flags, index, addr_dup); 690 addr_dup = 1; 691 name_count++; 692 } 693 if ((cache = whine_malloc(sizeof(struct crec) + strlen(canon) + 1 - SMALLDNAME))) { 694 strcpy(cache->name.sname, canon); 695 add_hosts_entry(cache, &addr, addrlen, flags, index, addr_dup); 696 name_count++; 697 } 698 free(canon); 699 700 } else if (!nomem) 701 my_syslog(LOG_ERR, _("bad name at %s line %d"), filename, lineno); 702 } 703 } 704 705 fclose(f); 706 rehash(name_count); 707 708 my_syslog(LOG_INFO, _("read %s - %d addresses"), filename, addr_count); 709 710 return name_count; 711 } 712 713 void cache_reload(void) { 714 struct crec *cache, **up, *tmp; 715 int i, total_size = daemon->cachesize; 716 struct hostsfile* ah; 717 718 cache_inserted = cache_live_freed = 0; 719 720 for (i = 0; i < hash_size; i++) 721 for (cache = hash_table[i], up = &hash_table[i]; cache; cache = tmp) { 722 tmp = cache->hash_next; 723 if (cache->flags & F_HOSTS) { 724 *up = cache->hash_next; 725 free(cache); 726 } else if (!(cache->flags & F_DHCP)) { 727 *up = cache->hash_next; 728 if (cache->flags & F_BIGNAME) { 729 cache->name.bname->next = big_free; 730 big_free = cache->name.bname; 731 } 732 cache->flags = 0; 733 } else 734 up = &cache->hash_next; 735 } 736 737 if ((daemon->options & OPT_NO_HOSTS) && !daemon->addn_hosts) { 738 if (daemon->cachesize > 0) my_syslog(LOG_INFO, _("cleared cache")); 739 return; 740 } 741 742 if (!(daemon->options & OPT_NO_HOSTS)) total_size = read_hostsfile(HOSTSFILE, 0, total_size); 743 744 for (i = 0, ah = daemon->addn_hosts; ah; ah = ah->next) { 745 if (i <= ah->index) i = ah->index + 1; 746 747 if (ah->flags & AH_DIR) 748 ah->flags |= AH_INACTIVE; 749 else 750 ah->flags &= ~AH_INACTIVE; 751 } 752 753 for (ah = daemon->addn_hosts; ah; ah = ah->next) 754 if (!(ah->flags & AH_INACTIVE)) { 755 struct stat buf; 756 if (stat(ah->fname, &buf) != -1 && S_ISDIR(buf.st_mode)) { 757 DIR* dir_stream; 758 struct dirent* ent; 759 760 /* don't read this as a file */ 761 ah->flags |= AH_INACTIVE; 762 763 if (!(dir_stream = opendir(ah->fname))) 764 my_syslog(LOG_ERR, _("cannot access directory %s: %s"), ah->fname, 765 strerror(errno)); 766 else { 767 while ((ent = readdir(dir_stream))) { 768 size_t lendir = strlen(ah->fname); 769 size_t lenfile = strlen(ent->d_name); 770 struct hostsfile* ah1; 771 char* path; 772 773 /* ignore emacs backups and dotfiles */ 774 if (lenfile == 0 || ent->d_name[lenfile - 1] == '~' || 775 (ent->d_name[0] == '#' && ent->d_name[lenfile - 1] == '#') || 776 ent->d_name[0] == '.') 777 continue; 778 779 /* see if we have an existing record. 780 dir is ah->fname 781 file is ent->d_name 782 path to match is ah1->fname */ 783 784 for (ah1 = daemon->addn_hosts; ah1; ah1 = ah1->next) { 785 if (lendir < strlen(ah1->fname) && 786 strstr(ah1->fname, ah->fname) == ah1->fname && 787 ah1->fname[lendir] == '/' && 788 strcmp(ah1->fname + lendir + 1, ent->d_name) == 0) { 789 ah1->flags &= ~AH_INACTIVE; 790 break; 791 } 792 } 793 794 /* make new record */ 795 if (!ah1) { 796 if (!(ah1 = whine_malloc(sizeof(struct hostsfile)))) continue; 797 798 if (!(path = whine_malloc(lendir + lenfile + 2))) { 799 free(ah1); 800 continue; 801 } 802 803 strcpy(path, ah->fname); 804 strcat(path, "/"); 805 strcat(path, ent->d_name); 806 ah1->fname = path; 807 ah1->index = i++; 808 ah1->flags = AH_DIR; 809 ah1->next = daemon->addn_hosts; 810 daemon->addn_hosts = ah1; 811 } 812 813 /* inactivate record if not regular file */ 814 if ((ah1->flags & AH_DIR) && stat(ah1->fname, &buf) != -1 && 815 !S_ISREG(buf.st_mode)) 816 ah1->flags |= AH_INACTIVE; 817 } 818 closedir(dir_stream); 819 } 820 } 821 } 822 823 for (ah = daemon->addn_hosts; ah; ah = ah->next) 824 if (!(ah->flags & AH_INACTIVE)) 825 total_size = read_hostsfile(ah->fname, ah->index, total_size); 826 } 827 828 char* get_domain(struct in_addr addr) { 829 struct cond_domain* c; 830 831 for (c = daemon->cond_domain; c; c = c->next) 832 if (ntohl(addr.s_addr) >= ntohl(c->start.s_addr) && 833 ntohl(addr.s_addr) <= ntohl(c->end.s_addr)) 834 return c->domain; 835 836 return daemon->domain_suffix; 837 } 838 839 #ifdef HAVE_DHCP 840 void cache_unhash_dhcp(void) { 841 struct crec *cache, **up; 842 int i; 843 844 for (i = 0; i < hash_size; i++) 845 for (cache = hash_table[i], up = &hash_table[i]; cache; cache = cache->hash_next) 846 if (cache->flags & F_DHCP) { 847 *up = cache->hash_next; 848 cache->next = dhcp_spare; 849 dhcp_spare = cache; 850 } else 851 up = &cache->hash_next; 852 } 853 854 void cache_add_dhcp_entry(char* host_name, struct in_addr* host_address, time_t ttd) { 855 struct crec *crec = NULL, *aliasc; 856 unsigned short flags = F_DHCP | F_FORWARD | F_IPV4 | F_REVERSE; 857 int in_hosts = 0; 858 struct cname* a; 859 860 while ((crec = cache_find_by_name(crec, host_name, 0, F_IPV4 | F_CNAME))) { 861 /* check all addresses associated with name */ 862 if (crec->flags & F_HOSTS) { 863 if (crec->addr.addr.addr.addr4.s_addr != host_address->s_addr) { 864 strcpy(daemon->namebuff, inet_ntoa(crec->addr.addr.addr.addr4)); 865 my_syslog(LOG_WARNING, 866 _("not giving name %s to the DHCP lease of %s because " 867 "the name exists in %s with address %s"), 868 host_name, inet_ntoa(*host_address), record_source(crec->uid), 869 daemon->namebuff); 870 return; 871 } else 872 /* if in hosts, don't need DHCP record */ 873 in_hosts = 1; 874 } else if (!(crec->flags & F_DHCP)) { 875 cache_scan_free(host_name, NULL, 0, crec->flags & (F_IPV4 | F_CNAME | F_FORWARD)); 876 /* scan_free deletes all addresses associated with name */ 877 break; 878 } 879 } 880 881 if (in_hosts) return; 882 883 if ((crec = cache_find_by_addr(NULL, (struct all_addr*) host_address, 0, F_IPV4))) { 884 if (crec->flags & F_NEG) 885 cache_scan_free(NULL, (struct all_addr*) host_address, 0, F_IPV4 | F_REVERSE); 886 else 887 /* avoid multiple reverse mappings */ 888 flags &= ~F_REVERSE; 889 } 890 891 if ((crec = dhcp_spare)) 892 dhcp_spare = dhcp_spare->next; 893 else /* need new one */ 894 crec = whine_malloc(sizeof(struct crec)); 895 896 if (crec) /* malloc may fail */ 897 { 898 crec->flags = flags; 899 if (ttd == 0) 900 crec->flags |= F_IMMORTAL; 901 else 902 crec->ttd = ttd; 903 crec->addr.addr.addr.addr4 = *host_address; 904 crec->name.namep = host_name; 905 crec->uid = uid++; 906 cache_hash(crec); 907 908 for (a = daemon->cnames; a; a = a->next) 909 if (hostname_isequal(host_name, a->target)) { 910 if ((aliasc = dhcp_spare)) 911 dhcp_spare = dhcp_spare->next; 912 else /* need new one */ 913 aliasc = whine_malloc(sizeof(struct crec)); 914 915 if (aliasc) { 916 aliasc->flags = F_FORWARD | F_CONFIG | F_DHCP | F_CNAME; 917 if (ttd == 0) 918 aliasc->flags |= F_IMMORTAL; 919 else 920 aliasc->ttd = ttd; 921 aliasc->name.namep = a->alias; 922 aliasc->addr.cname.cache = crec; 923 aliasc->addr.cname.uid = crec->uid; 924 cache_hash(aliasc); 925 } 926 } 927 } 928 } 929 #endif 930 931 void dump_cache(time_t now) { 932 struct server *serv, *serv1; 933 934 my_syslog(LOG_INFO, _("time %lu"), (unsigned long) now); 935 my_syslog(LOG_INFO, _("cache size %d, %d/%d cache insertions re-used unexpired cache entries."), 936 daemon->cachesize, cache_live_freed, cache_inserted); 937 my_syslog(LOG_INFO, _("queries forwarded %u, queries answered locally %u"), 938 daemon->queries_forwarded, daemon->local_answer); 939 940 if (!addrbuff && !(addrbuff = whine_malloc(ADDRSTRLEN))) return; 941 942 /* sum counts from different records for same server */ 943 for (serv = daemon->servers; serv; serv = serv->next) serv->flags &= ~SERV_COUNTED; 944 945 for (serv = daemon->servers; serv; serv = serv->next) 946 if (!(serv->flags & (SERV_NO_ADDR | SERV_LITERAL_ADDRESS | SERV_COUNTED))) { 947 int port; 948 unsigned int queries = 0, failed_queries = 0; 949 for (serv1 = serv; serv1; serv1 = serv1->next) 950 if (!(serv1->flags & (SERV_NO_ADDR | SERV_LITERAL_ADDRESS | SERV_COUNTED)) && 951 sockaddr_isequal(&serv->addr, &serv1->addr)) { 952 serv1->flags |= SERV_COUNTED; 953 queries += serv1->queries; 954 failed_queries += serv1->failed_queries; 955 } 956 port = prettyprint_addr(&serv->addr, addrbuff); 957 my_syslog(LOG_INFO, _("server %s#%d: queries sent %u, retried or failed %u"), addrbuff, 958 port, queries, failed_queries); 959 } 960 961 if ((daemon->options & (OPT_DEBUG | OPT_LOG))) { 962 struct crec* cache; 963 int i; 964 my_syslog(LOG_DEBUG, 965 "Host Address Flags " 966 " Expires"); 967 968 for (i = 0; i < hash_size; i++) 969 for (cache = hash_table[i]; cache; cache = cache->hash_next) { 970 char *a, *p = daemon->namebuff; 971 p += sprintf(p, "%-40.40s ", cache_get_name(cache)); 972 if ((cache->flags & F_NEG) && (cache->flags & F_FORWARD)) 973 a = ""; 974 else if (cache->flags & F_CNAME) { 975 a = ""; 976 if (!is_outdated_cname_pointer(cache)) 977 a = cache_get_name(cache->addr.cname.cache); 978 } 979 #ifdef HAVE_IPV6 980 else { 981 a = addrbuff; 982 if (cache->flags & F_IPV4) 983 inet_ntop(AF_INET, &cache->addr.addr, addrbuff, ADDRSTRLEN); 984 else if (cache->flags & F_IPV6) 985 inet_ntop(AF_INET6, &cache->addr.addr, addrbuff, ADDRSTRLEN); 986 } 987 #else 988 else 989 a = inet_ntoa(cache->addr.addr.addr.addr4); 990 #endif 991 p += sprintf( 992 p, "%-30.30s %s%s%s%s%s%s%s%s%s%s ", a, cache->flags & F_IPV4 ? "4" : "", 993 cache->flags & F_IPV6 ? "6" : "", cache->flags & F_CNAME ? "C" : "", 994 cache->flags & F_FORWARD ? "F" : " ", cache->flags & F_REVERSE ? "R" : " ", 995 cache->flags & F_IMMORTAL ? "I" : " ", cache->flags & F_DHCP ? "D" : " ", 996 cache->flags & F_NEG ? "N" : " ", cache->flags & F_NXDOMAIN ? "X" : " ", 997 cache->flags & F_HOSTS ? "H" : " "); 998 #ifdef HAVE_BROKEN_RTC 999 p += sprintf(p, "%lu", 1000 cache->flags & F_IMMORTAL ? 0 : (unsigned long) (cache->ttd - now)); 1001 #else 1002 p += sprintf(p, "%s", cache->flags & F_IMMORTAL ? "\n" : ctime(&(cache->ttd))); 1003 /* ctime includes trailing \n - eat it */ 1004 *(p - 1) = 0; 1005 #endif 1006 my_syslog(LOG_DEBUG, daemon->namebuff); 1007 } 1008 } 1009 } 1010 1011 char* record_source(int index) { 1012 struct hostsfile* ah; 1013 1014 if (index == 0) return HOSTSFILE; 1015 1016 for (ah = daemon->addn_hosts; ah; ah = ah->next) 1017 if (ah->index == index) return ah->fname; 1018 1019 return "<unknown>"; 1020 } 1021 1022 void querystr(char* str, unsigned short type) { 1023 unsigned int i; 1024 1025 sprintf(str, "query[type=%d]", type); 1026 for (i = 0; i < (sizeof(typestr) / sizeof(typestr[0])); i++) 1027 if (typestr[i].type == type) sprintf(str, "query[%s]", typestr[i].name); 1028 } 1029 1030 void log_query(unsigned short flags, char* name, struct all_addr* addr, char* arg) { 1031 char *source, *dest = addrbuff; 1032 char* verb = "is"; 1033 1034 if (!(daemon->options & OPT_LOG)) return; 1035 1036 if (addr) { 1037 #ifdef HAVE_IPV6 1038 /* TODO: support scoped addresses. struct all_addr doesn't store scope IDs. */ 1039 inet_ntop(flags & F_IPV4 ? AF_INET : AF_INET6, addr, addrbuff, ADDRSTRLEN); 1040 #else 1041 strncpy(addrbuff, inet_ntoa(addr->addr.addr4), ADDRSTRLEN); 1042 #endif 1043 } 1044 1045 if (flags & F_REVERSE) { 1046 dest = name; 1047 name = addrbuff; 1048 } 1049 1050 if (flags & F_NEG) { 1051 if (flags & F_NXDOMAIN) { 1052 if (flags & F_IPV4) 1053 dest = "NXDOMAIN-IPv4"; 1054 else if (flags & F_IPV6) 1055 dest = "NXDOMAIN-IPv6"; 1056 else 1057 dest = "NXDOMAIN"; 1058 } else { 1059 if (flags & F_IPV4) 1060 dest = "NODATA-IPv4"; 1061 else if (flags & F_IPV6) 1062 dest = "NODATA-IPv6"; 1063 else 1064 dest = "NODATA"; 1065 } 1066 } else if (flags & F_CNAME) { 1067 /* nasty abuse of NXDOMAIN and CNAME flags */ 1068 if (flags & F_NXDOMAIN) 1069 dest = arg; 1070 else 1071 dest = "<CNAME>"; 1072 } 1073 1074 if (flags & F_CONFIG) 1075 source = "config"; 1076 else if (flags & F_DHCP) 1077 source = "DHCP"; 1078 else if (flags & F_HOSTS) 1079 source = arg; 1080 else if (flags & F_UPSTREAM) 1081 source = "reply"; 1082 else if (flags & F_SERVER) { 1083 source = "forwarded"; 1084 verb = "to"; 1085 } else if (flags & F_QUERY) { 1086 source = arg; 1087 verb = "from"; 1088 } else 1089 source = "cached"; 1090 1091 if (strlen(name) == 0) name = "."; 1092 1093 my_syslog(LOG_DEBUG, "%s %s %s %s", source, name, verb, dest); 1094 } 1095