dnsmasq: upstream update to V2.68rc4
[tomato.git] / release / src / router / dnsmasq / src / cache.c
blob43a7ce9a6b63a99b87c31d90324bb57ea94bb96d
1 /* dnsmasq is Copyright (c) 2000-2013 Simon Kelley
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.
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.
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/>.
17 #include "dnsmasq.h"
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 = 1;
28 #ifdef HAVE_DNSSEC
29 static struct keydata *keyblock_free = NULL;
30 #endif
32 /* type->string mapping: this is also used by the name-hash function as a mixing table. */
33 static const struct {
34 unsigned int type;
35 const char * const name;
36 } typestr[] = {
37 { 1, "A" },
38 { 2, "NS" },
39 { 5, "CNAME" },
40 { 6, "SOA" },
41 { 10, "NULL" },
42 { 11, "WKS" },
43 { 12, "PTR" },
44 { 13, "HINFO" },
45 { 15, "MX" },
46 { 16, "TXT" },
47 { 22, "NSAP" },
48 { 23, "NSAP_PTR" },
49 { 24, "SIG" },
50 { 25, "KEY" },
51 { 28, "AAAA" },
52 { 33, "SRV" },
53 { 35, "NAPTR" },
54 { 36, "KX" },
55 { 37, "CERT" },
56 { 38, "A6" },
57 { 39, "DNAME" },
58 { 41, "OPT" },
59 { 48, "DNSKEY" },
60 { 249, "TKEY" },
61 { 250, "TSIG" },
62 { 251, "IXFR" },
63 { 252, "AXFR" },
64 { 253, "MAILB" },
65 { 254, "MAILA" },
66 { 255, "ANY" }
69 static void cache_free(struct crec *crecp);
70 static void cache_unlink(struct crec *crecp);
71 static void cache_link(struct crec *crecp);
72 static void rehash(int size);
73 static void cache_hash(struct crec *crecp);
75 void cache_init(void)
77 struct crec *crecp;
78 int i;
80 bignames_left = daemon->cachesize/10;
82 if (daemon->cachesize > 0)
84 crecp = safe_malloc(daemon->cachesize*sizeof(struct crec));
86 for (i=0; i < daemon->cachesize; i++, crecp++)
88 cache_link(crecp);
89 crecp->flags = 0;
90 crecp->uid = uid++;
94 /* create initial hash table*/
95 rehash(daemon->cachesize);
98 /* In most cases, we create the hash table once here by calling this with (hash_table == NULL)
99 but if the hosts file(s) are big (some people have 50000 ad-block entries), the table
100 will be much too small, so the hosts reading code calls rehash every 1000 addresses, to
101 expand the table. */
102 static void rehash(int size)
104 struct crec **new, **old, *p, *tmp;
105 int i, new_size, old_size;
107 /* hash_size is a power of two. */
108 for (new_size = 64; new_size < size/10; new_size = new_size << 1);
110 /* must succeed in getting first instance, failure later is non-fatal */
111 if (!hash_table)
112 new = safe_malloc(new_size * sizeof(struct crec *));
113 else if (new_size <= hash_size || !(new = whine_malloc(new_size * sizeof(struct crec *))))
114 return;
116 for(i = 0; i < new_size; i++)
117 new[i] = NULL;
119 old = hash_table;
120 old_size = hash_size;
121 hash_table = new;
122 hash_size = new_size;
124 if (old)
126 for (i = 0; i < old_size; i++)
127 for (p = old[i]; p ; p = tmp)
129 tmp = p->hash_next;
130 cache_hash(p);
132 free(old);
136 static struct crec **hash_bucket(char *name)
138 unsigned int c, val = 017465; /* Barker code - minimum self-correlation in cyclic shift */
139 const unsigned char *mix_tab = (const unsigned char*)typestr;
141 while((c = (unsigned char) *name++))
143 /* don't use tolower and friends here - they may be messed up by LOCALE */
144 if (c >= 'A' && c <= 'Z')
145 c += 'a' - 'A';
146 val = ((val << 7) | (val >> (32 - 7))) + (mix_tab[(val + c) & 0x3F] ^ c);
149 /* hash_size is a power of two */
150 return hash_table + ((val ^ (val >> 16)) & (hash_size - 1));
153 static void cache_hash(struct crec *crecp)
155 /* maintain an invariant that all entries with F_REVERSE set
156 are at the start of the hash-chain and all non-reverse
157 immortal entries are at the end of the hash-chain.
158 This allows reverse searches and garbage collection to be optimised */
160 struct crec **up = hash_bucket(cache_get_name(crecp));
162 if (!(crecp->flags & F_REVERSE))
164 while (*up && ((*up)->flags & F_REVERSE))
165 up = &((*up)->hash_next);
167 if (crecp->flags & F_IMMORTAL)
168 while (*up && !((*up)->flags & F_IMMORTAL))
169 up = &((*up)->hash_next);
171 crecp->hash_next = *up;
172 *up = crecp;
175 static void cache_free(struct crec *crecp)
177 crecp->flags &= ~F_FORWARD;
178 crecp->flags &= ~F_REVERSE;
179 crecp->uid = uid++; /* invalidate CNAMES pointing to this. */
181 if (uid == -1)
182 uid++;
184 if (cache_tail)
185 cache_tail->next = crecp;
186 else
187 cache_head = crecp;
188 crecp->prev = cache_tail;
189 crecp->next = NULL;
190 cache_tail = crecp;
192 /* retrieve big name for further use. */
193 if (crecp->flags & F_BIGNAME)
195 crecp->name.bname->next = big_free;
196 big_free = crecp->name.bname;
197 crecp->flags &= ~F_BIGNAME;
199 #ifdef HAVE_DNSSEC
200 else if (crecp->flags & (F_DNSKEY | F_DS))
201 keydata_free(crecp->addr.key.keydata);
202 #endif
205 /* insert a new cache entry at the head of the list (youngest entry) */
206 static void cache_link(struct crec *crecp)
208 if (cache_head) /* check needed for init code */
209 cache_head->prev = crecp;
210 crecp->next = cache_head;
211 crecp->prev = NULL;
212 cache_head = crecp;
213 if (!cache_tail)
214 cache_tail = crecp;
217 /* remove an arbitrary cache entry for promotion */
218 static void cache_unlink (struct crec *crecp)
220 if (crecp->prev)
221 crecp->prev->next = crecp->next;
222 else
223 cache_head = crecp->next;
225 if (crecp->next)
226 crecp->next->prev = crecp->prev;
227 else
228 cache_tail = crecp->prev;
231 char *cache_get_name(struct crec *crecp)
233 if (crecp->flags & F_BIGNAME)
234 return crecp->name.bname->name;
235 else if (crecp->flags & F_NAMEP)
236 return crecp->name.namep;
238 return crecp->name.sname;
241 char *cache_get_cname_target(struct crec *crecp)
243 if (crecp->addr.cname.uid != -1)
244 return cache_get_name(crecp->addr.cname.target.cache);
246 return crecp->addr.cname.target.int_name->name;
251 struct crec *cache_enumerate(int init)
253 static int bucket;
254 static struct crec *cache;
256 if (init)
258 bucket = 0;
259 cache = NULL;
261 else if (cache && cache->hash_next)
262 cache = cache->hash_next;
263 else
265 cache = NULL;
266 while (bucket < hash_size)
267 if ((cache = hash_table[bucket++]))
268 break;
271 return cache;
274 static int is_outdated_cname_pointer(struct crec *crecp)
276 if (!(crecp->flags & F_CNAME) || crecp->addr.cname.uid == -1)
277 return 0;
279 /* NB. record may be reused as DS or DNSKEY, where uid is
280 overloaded for something completely different */
281 if (crecp->addr.cname.target.cache &&
282 (crecp->addr.cname.target.cache->flags & (F_IPV4 | F_IPV6 | F_CNAME)) &&
283 crecp->addr.cname.uid == crecp->addr.cname.target.cache->uid)
284 return 0;
286 return 1;
289 static int is_expired(time_t now, struct crec *crecp)
291 if (crecp->flags & F_IMMORTAL)
292 return 0;
294 if (difftime(now, crecp->ttd) < 0)
295 return 0;
297 return 1;
300 static int cache_scan_free(char *name, struct all_addr *addr, time_t now, unsigned short flags)
302 /* Scan and remove old entries.
303 If (flags & F_FORWARD) then remove any forward entries for name and any expired
304 entries but only in the same hash bucket as name.
305 If (flags & F_REVERSE) then remove any reverse entries for addr and any expired
306 entries in the whole cache.
307 If (flags == 0) remove any expired entries in the whole cache.
309 In the flags & F_FORWARD case, the return code is valid, and returns zero if the
310 name exists in the cache as a HOSTS or DHCP entry (these are never deleted)
312 We take advantage of the fact that hash chains have stuff in the order <reverse>,<other>,<immortal>
313 so that when we hit an entry which isn't reverse and is immortal, we're done. */
315 struct crec *crecp, **up;
317 if (flags & F_FORWARD)
319 for (up = hash_bucket(name), crecp = *up; crecp; crecp = crecp->hash_next)
320 if (is_expired(now, crecp) || is_outdated_cname_pointer(crecp))
322 *up = crecp->hash_next;
323 if (!(crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)))
325 cache_unlink(crecp);
326 cache_free(crecp);
329 else if ((crecp->flags & F_FORWARD) &&
330 ((flags & crecp->flags & F_TYPE) || ((crecp->flags | flags) & F_CNAME)) &&
331 hostname_isequal(cache_get_name(crecp), name))
333 if (crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG))
334 return 0;
335 *up = crecp->hash_next;
336 cache_unlink(crecp);
337 cache_free(crecp);
339 else
340 up = &crecp->hash_next;
342 else
344 int i;
345 #ifdef HAVE_IPV6
346 int addrlen = (flags & F_IPV6) ? IN6ADDRSZ : INADDRSZ;
347 #else
348 int addrlen = INADDRSZ;
349 #endif
350 for (i = 0; i < hash_size; i++)
351 for (crecp = hash_table[i], up = &hash_table[i];
352 crecp && ((crecp->flags & F_REVERSE) || !(crecp->flags & F_IMMORTAL));
353 crecp = crecp->hash_next)
354 if (is_expired(now, crecp))
356 *up = crecp->hash_next;
357 if (!(crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)))
359 cache_unlink(crecp);
360 cache_free(crecp);
363 else if (!(crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)) &&
364 (flags & crecp->flags & F_REVERSE) &&
365 (flags & crecp->flags & (F_IPV4 | F_IPV6)) &&
366 memcmp(&crecp->addr.addr, addr, addrlen) == 0)
368 *up = crecp->hash_next;
369 cache_unlink(crecp);
370 cache_free(crecp);
372 else
373 up = &crecp->hash_next;
376 return 1;
379 /* Note: The normal calling sequence is
380 cache_start_insert
381 cache_insert * n
382 cache_end_insert
384 but an abort can cause the cache_end_insert to be missed
385 in which can the next cache_start_insert cleans things up. */
387 void cache_start_insert(void)
389 /* Free any entries which didn't get committed during the last
390 insert due to error.
392 while (new_chain)
394 struct crec *tmp = new_chain->next;
395 cache_free(new_chain);
396 new_chain = tmp;
398 new_chain = NULL;
399 insert_error = 0;
402 struct crec *cache_insert(char *name, struct all_addr *addr,
403 time_t now, unsigned long ttl, unsigned short flags)
405 struct crec *new;
406 union bigname *big_name = NULL;
407 int freed_all = flags & F_REVERSE;
408 int free_avail = 0;
410 if (daemon->max_cache_ttl != 0 && daemon->max_cache_ttl < ttl)
411 ttl = daemon->max_cache_ttl;
413 /* Don't log keys */
414 if (flags & (F_IPV4 | F_IPV6))
415 log_query(flags | F_UPSTREAM, name, addr, NULL);
417 /* if previous insertion failed give up now. */
418 if (insert_error)
419 return NULL;
421 /* First remove any expired entries and entries for the name/address we
422 are currently inserting. Fail is we attempt to delete a name from
423 /etc/hosts or DHCP. */
424 if (!cache_scan_free(name, addr, now, flags))
426 insert_error = 1;
427 return NULL;
430 /* Now get a cache entry from the end of the LRU list */
431 while (1) {
432 if (!(new = cache_tail)) /* no entries left - cache is too small, bail */
434 insert_error = 1;
435 return NULL;
438 /* End of LRU list is still in use: if we didn't scan all the hash
439 chains for expired entries do that now. If we already tried that
440 then it's time to start spilling things. */
442 if (new->flags & (F_FORWARD | F_REVERSE))
444 /* If free_avail set, we believe that an entry has been freed.
445 Bugs have been known to make this not true, resulting in
446 a tight loop here. If that happens, abandon the
447 insert. Once in this state, all inserts will probably fail. */
448 if (free_avail)
450 insert_error = 1;
451 return NULL;
454 if (freed_all)
456 free_avail = 1; /* Must be free space now. */
457 cache_scan_free(cache_get_name(new), &new->addr.addr, now, new->flags);
458 cache_live_freed++;
460 else
462 cache_scan_free(NULL, NULL, now, 0);
463 freed_all = 1;
465 continue;
468 /* Check if we need to and can allocate extra memory for a long name.
469 If that fails, give up now. */
470 if (name && (strlen(name) > SMALLDNAME-1))
472 if (big_free)
474 big_name = big_free;
475 big_free = big_free->next;
477 else if (!bignames_left ||
478 !(big_name = (union bigname *)whine_malloc(sizeof(union bigname))))
480 insert_error = 1;
481 return NULL;
483 else
484 bignames_left--;
488 /* Got the rest: finally grab entry. */
489 cache_unlink(new);
490 break;
493 new->flags = flags;
494 if (big_name)
496 new->name.bname = big_name;
497 new->flags |= F_BIGNAME;
500 if (name)
501 strcpy(cache_get_name(new), name);
502 else
503 *cache_get_name(new) = 0;
505 if (addr)
506 new->addr.addr = *addr;
508 new->ttd = now + (time_t)ttl;
509 new->next = new_chain;
510 new_chain = new;
512 return new;
515 /* after end of insertion, commit the new entries */
516 void cache_end_insert(void)
518 if (insert_error)
519 return;
521 while (new_chain)
523 struct crec *tmp = new_chain->next;
524 /* drop CNAMEs which didn't find a target. */
525 if (is_outdated_cname_pointer(new_chain))
526 cache_free(new_chain);
527 else
529 cache_hash(new_chain);
530 cache_link(new_chain);
531 cache_inserted++;
533 new_chain = tmp;
535 new_chain = NULL;
538 struct crec *cache_find_by_name(struct crec *crecp, char *name, time_t now, unsigned short prot)
540 struct crec *ans;
542 if (crecp) /* iterating */
543 ans = crecp->next;
544 else
546 /* first search, look for relevant entries and push to top of list
547 also free anything which has expired */
548 struct crec *next, **up, **insert = NULL, **chainp = &ans;
549 unsigned short ins_flags = 0;
551 for (up = hash_bucket(name), crecp = *up; crecp; crecp = next)
553 next = crecp->hash_next;
555 if (!is_expired(now, crecp) && !is_outdated_cname_pointer(crecp))
557 if ((crecp->flags & F_FORWARD) &&
558 (crecp->flags & prot) &&
559 hostname_isequal(cache_get_name(crecp), name))
561 if (crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG))
563 *chainp = crecp;
564 chainp = &crecp->next;
566 else
568 cache_unlink(crecp);
569 cache_link(crecp);
572 /* Move all but the first entry up the hash chain
573 this implements round-robin.
574 Make sure that re-ordering doesn't break the hash-chain
575 order invariants.
577 if (insert && (crecp->flags & (F_REVERSE | F_IMMORTAL)) == ins_flags)
579 *up = crecp->hash_next;
580 crecp->hash_next = *insert;
581 *insert = crecp;
582 insert = &crecp->hash_next;
584 else
586 if (!insert)
588 insert = up;
589 ins_flags = crecp->flags & (F_REVERSE | F_IMMORTAL);
591 up = &crecp->hash_next;
594 else
595 /* case : not expired, incorrect entry. */
596 up = &crecp->hash_next;
598 else
600 /* expired entry, free it */
601 *up = crecp->hash_next;
602 if (!(crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)))
604 cache_unlink(crecp);
605 cache_free(crecp);
610 *chainp = cache_head;
613 if (ans &&
614 (ans->flags & F_FORWARD) &&
615 (ans->flags & prot) &&
616 hostname_isequal(cache_get_name(ans), name))
617 return ans;
619 return NULL;
622 struct crec *cache_find_by_addr(struct crec *crecp, struct all_addr *addr,
623 time_t now, unsigned short prot)
625 struct crec *ans;
626 #ifdef HAVE_IPV6
627 int addrlen = (prot == F_IPV6) ? IN6ADDRSZ : INADDRSZ;
628 #else
629 int addrlen = INADDRSZ;
630 #endif
632 if (crecp) /* iterating */
633 ans = crecp->next;
634 else
636 /* first search, look for relevant entries and push to top of list
637 also free anything which has expired. All the reverse entries are at the
638 start of the hash chain, so we can give up when we find the first
639 non-REVERSE one. */
640 int i;
641 struct crec **up, **chainp = &ans;
643 for (i=0; i<hash_size; i++)
644 for (crecp = hash_table[i], up = &hash_table[i];
645 crecp && (crecp->flags & F_REVERSE);
646 crecp = crecp->hash_next)
647 if (!is_expired(now, crecp))
649 if ((crecp->flags & prot) &&
650 memcmp(&crecp->addr.addr, addr, addrlen) == 0)
652 if (crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG))
654 *chainp = crecp;
655 chainp = &crecp->next;
657 else
659 cache_unlink(crecp);
660 cache_link(crecp);
663 up = &crecp->hash_next;
665 else
667 *up = crecp->hash_next;
668 if (!(crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)))
670 cache_unlink(crecp);
671 cache_free(crecp);
675 *chainp = cache_head;
678 if (ans &&
679 (ans->flags & F_REVERSE) &&
680 (ans->flags & prot) &&
681 memcmp(&ans->addr.addr, addr, addrlen) == 0)
682 return ans;
684 return NULL;
687 static void add_hosts_cname(struct crec *target)
689 struct crec *crec;
690 struct cname *a;
692 for (a = daemon->cnames; a; a = a->next)
693 if (hostname_isequal(cache_get_name(target), a->target) &&
694 (crec = whine_malloc(sizeof(struct crec))))
696 crec->flags = F_FORWARD | F_IMMORTAL | F_NAMEP | F_CONFIG | F_CNAME;
697 crec->name.namep = a->alias;
698 crec->addr.cname.target.cache = target;
699 crec->addr.cname.uid = target->uid;
700 cache_hash(crec);
701 add_hosts_cname(crec); /* handle chains */
705 static void add_hosts_entry(struct crec *cache, struct all_addr *addr, int addrlen,
706 int index, struct crec **rhash, int hashsz)
708 struct crec *lookup = cache_find_by_name(NULL, cache_get_name(cache), 0, cache->flags & (F_IPV4 | F_IPV6));
709 int i, nameexists = 0;
710 unsigned int j;
712 /* Remove duplicates in hosts files. */
713 if (lookup && (lookup->flags & F_HOSTS))
715 nameexists = 1;
716 if (memcmp(&lookup->addr.addr, addr, addrlen) == 0)
718 free(cache);
719 return;
723 /* Ensure there is only one address -> name mapping (first one trumps)
724 We do this by steam here, The entries are kept in hash chains, linked
725 by ->next (which is unused at this point) held in hash buckets in
726 the array rhash, hashed on address. Note that rhash and the values
727 in ->next are only valid whilst reading hosts files: the buckets are
728 then freed, and the ->next pointer used for other things.
730 Only insert each unique address once into this hashing structure.
732 This complexity avoids O(n^2) divergent CPU use whilst reading
733 large (10000 entry) hosts files. */
735 /* hash address */
736 for (j = 0, i = 0; i < addrlen; i++)
737 j = (j*2 +((unsigned char *)addr)[i]) % hashsz;
739 for (lookup = rhash[j]; lookup; lookup = lookup->next)
740 if ((lookup->flags & cache->flags & (F_IPV4 | F_IPV6)) &&
741 memcmp(&lookup->addr.addr, addr, addrlen) == 0)
743 cache->flags &= ~F_REVERSE;
744 break;
747 /* maintain address hash chain, insert new unique address */
748 if (!lookup)
750 cache->next = rhash[j];
751 rhash[j] = cache;
754 cache->uid = index;
755 memcpy(&cache->addr.addr, addr, addrlen);
756 cache_hash(cache);
758 /* don't need to do alias stuff for second and subsequent addresses. */
759 if (!nameexists)
760 add_hosts_cname(cache);
763 static int eatspace(FILE *f)
765 int c, nl = 0;
767 while (1)
769 if ((c = getc(f)) == '#')
770 while (c != '\n' && c != EOF)
771 c = getc(f);
773 if (c == EOF)
774 return 1;
776 if (!isspace(c))
778 ungetc(c, f);
779 return nl;
782 if (c == '\n')
783 nl = 1;
787 static int gettok(FILE *f, char *token)
789 int c, count = 0;
791 while (1)
793 if ((c = getc(f)) == EOF)
794 return (count == 0) ? EOF : 1;
796 if (isspace(c) || c == '#')
798 ungetc(c, f);
799 return eatspace(f);
802 if (count < (MAXDNAME - 1))
804 token[count++] = c;
805 token[count] = 0;
810 static int read_hostsfile(char *filename, int index, int cache_size, struct crec **rhash, int hashsz)
812 FILE *f = fopen(filename, "r");
813 char *token = daemon->namebuff, *domain_suffix = NULL;
814 int addr_count = 0, name_count = cache_size, lineno = 0;
815 unsigned short flags = 0;
816 struct all_addr addr;
817 int atnl, addrlen = 0;
819 if (!f)
821 my_syslog(LOG_ERR, _("failed to load names from %s: %s"), filename, strerror(errno));
822 return 0;
825 eatspace(f);
827 while ((atnl = gettok(f, token)) != EOF)
829 lineno++;
831 if (inet_pton(AF_INET, token, &addr) > 0)
833 flags = F_HOSTS | F_IMMORTAL | F_FORWARD | F_REVERSE | F_IPV4;
834 addrlen = INADDRSZ;
835 domain_suffix = get_domain(addr.addr.addr4);
837 #ifdef HAVE_IPV6
838 else if (inet_pton(AF_INET6, token, &addr) > 0)
840 flags = F_HOSTS | F_IMMORTAL | F_FORWARD | F_REVERSE | F_IPV6;
841 addrlen = IN6ADDRSZ;
842 domain_suffix = get_domain6(&addr.addr.addr6);
844 #endif
845 else
847 my_syslog(LOG_ERR, _("bad address at %s line %d"), filename, lineno);
848 while (atnl == 0)
849 atnl = gettok(f, token);
850 continue;
853 addr_count++;
855 /* rehash every 1000 names. */
856 if ((name_count - cache_size) > 1000)
858 rehash(name_count);
859 cache_size = name_count;
862 while (atnl == 0)
864 struct crec *cache;
865 int fqdn, nomem;
866 char *canon;
868 if ((atnl = gettok(f, token)) == EOF)
869 break;
871 fqdn = !!strchr(token, '.');
873 if ((canon = canonicalise(token, &nomem)))
875 /* If set, add a version of the name with a default domain appended */
876 if (option_bool(OPT_EXPAND) && domain_suffix && !fqdn &&
877 (cache = whine_malloc(sizeof(struct crec) +
878 strlen(canon)+2+strlen(domain_suffix)-SMALLDNAME)))
880 strcpy(cache->name.sname, canon);
881 strcat(cache->name.sname, ".");
882 strcat(cache->name.sname, domain_suffix);
883 cache->flags = flags;
884 add_hosts_entry(cache, &addr, addrlen, index, rhash, hashsz);
885 name_count++;
887 if ((cache = whine_malloc(sizeof(struct crec) + strlen(canon)+1-SMALLDNAME)))
889 strcpy(cache->name.sname, canon);
890 cache->flags = flags;
891 add_hosts_entry(cache, &addr, addrlen, index, rhash, hashsz);
892 name_count++;
894 free(canon);
897 else if (!nomem)
898 my_syslog(LOG_ERR, _("bad name at %s line %d"), filename, lineno);
902 fclose(f);
903 rehash(name_count);
905 my_syslog(LOG_INFO, _("read %s - %d addresses"), filename, addr_count);
907 return name_count;
910 void cache_reload(void)
912 struct crec *cache, **up, *tmp;
913 int revhashsz, i, total_size = daemon->cachesize;
914 struct hostsfile *ah;
915 struct host_record *hr;
916 struct name_list *nl;
917 struct cname *a;
918 struct interface_name *intr;
920 cache_inserted = cache_live_freed = 0;
922 for (i=0; i<hash_size; i++)
923 for (cache = hash_table[i], up = &hash_table[i]; cache; cache = tmp)
925 tmp = cache->hash_next;
926 if (cache->flags & (F_HOSTS | F_CONFIG))
928 *up = cache->hash_next;
929 free(cache);
931 else if (!(cache->flags & F_DHCP))
933 *up = cache->hash_next;
934 if (cache->flags & F_BIGNAME)
936 cache->name.bname->next = big_free;
937 big_free = cache->name.bname;
939 cache->flags = 0;
941 else
942 up = &cache->hash_next;
945 /* Add CNAMEs to interface_names to the cache */
946 for (a = daemon->cnames; a; a = a->next)
947 for (intr = daemon->int_names; intr; intr = intr->next)
948 if (hostname_isequal(a->target, intr->name) &&
949 ((cache = whine_malloc(sizeof(struct crec)))))
951 cache->flags = F_FORWARD | F_NAMEP | F_CNAME | F_IMMORTAL | F_CONFIG;
952 cache->name.namep = a->alias;
953 cache->addr.cname.target.int_name = intr;
954 cache->addr.cname.uid = -1;
955 cache_hash(cache);
956 add_hosts_cname(cache); /* handle chains */
959 /* borrow the packet buffer for a temporary by-address hash */
960 memset(daemon->packet, 0, daemon->packet_buff_sz);
961 revhashsz = daemon->packet_buff_sz / sizeof(struct crec *);
962 /* we overwrote the buffer... */
963 daemon->srv_save = NULL;
965 /* Do host_records in config. */
966 for (hr = daemon->host_records; hr; hr = hr->next)
967 for (nl = hr->names; nl; nl = nl->next)
969 if (hr->addr.s_addr != 0 &&
970 (cache = whine_malloc(sizeof(struct crec))))
972 cache->name.namep = nl->name;
973 cache->flags = F_HOSTS | F_IMMORTAL | F_FORWARD | F_REVERSE | F_IPV4 | F_NAMEP | F_CONFIG;
974 add_hosts_entry(cache, (struct all_addr *)&hr->addr, INADDRSZ, 0, (struct crec **)daemon->packet, revhashsz);
976 #ifdef HAVE_IPV6
977 if (!IN6_IS_ADDR_UNSPECIFIED(&hr->addr6) &&
978 (cache = whine_malloc(sizeof(struct crec))))
980 cache->name.namep = nl->name;
981 cache->flags = F_HOSTS | F_IMMORTAL | F_FORWARD | F_REVERSE | F_IPV6 | F_NAMEP | F_CONFIG;
982 add_hosts_entry(cache, (struct all_addr *)&hr->addr6, IN6ADDRSZ, 0, (struct crec **)daemon->packet, revhashsz);
984 #endif
987 if (option_bool(OPT_NO_HOSTS) && !daemon->addn_hosts)
989 if (daemon->cachesize > 0)
990 my_syslog(LOG_INFO, _("cleared cache"));
991 return;
994 if (!option_bool(OPT_NO_HOSTS))
995 total_size = read_hostsfile(HOSTSFILE, 0, total_size, (struct crec **)daemon->packet, revhashsz);
997 daemon->addn_hosts = expand_filelist(daemon->addn_hosts);
998 for (ah = daemon->addn_hosts; ah; ah = ah->next)
999 if (!(ah->flags & AH_INACTIVE))
1000 total_size = read_hostsfile(ah->fname, ah->index, total_size, (struct crec **)daemon->packet, revhashsz);
1003 #ifdef HAVE_DHCP
1004 struct in_addr a_record_from_hosts(char *name, time_t now)
1006 struct crec *crecp = NULL;
1007 struct in_addr ret;
1009 while ((crecp = cache_find_by_name(crecp, name, now, F_IPV4)))
1010 if (crecp->flags & F_HOSTS)
1011 return *(struct in_addr *)&crecp->addr;
1013 my_syslog(MS_DHCP | LOG_WARNING, _("No IPv4 address found for %s"), name);
1015 ret.s_addr = 0;
1016 return ret;
1019 void cache_unhash_dhcp(void)
1021 struct crec *cache, **up;
1022 int i;
1024 for (i=0; i<hash_size; i++)
1025 for (cache = hash_table[i], up = &hash_table[i]; cache; cache = cache->hash_next)
1026 if (cache->flags & F_DHCP)
1028 *up = cache->hash_next;
1029 cache->next = dhcp_spare;
1030 dhcp_spare = cache;
1032 else
1033 up = &cache->hash_next;
1036 static void add_dhcp_cname(struct crec *target, time_t ttd)
1038 struct crec *aliasc;
1039 struct cname *a;
1041 for (a = daemon->cnames; a; a = a->next)
1042 if (hostname_isequal(cache_get_name(target), a->target))
1044 if ((aliasc = dhcp_spare))
1045 dhcp_spare = dhcp_spare->next;
1046 else /* need new one */
1047 aliasc = whine_malloc(sizeof(struct crec));
1049 if (aliasc)
1051 aliasc->flags = F_FORWARD | F_NAMEP | F_DHCP | F_CNAME | F_CONFIG;
1052 if (ttd == 0)
1053 aliasc->flags |= F_IMMORTAL;
1054 else
1055 aliasc->ttd = ttd;
1056 aliasc->name.namep = a->alias;
1057 aliasc->addr.cname.target.cache = target;
1058 aliasc->addr.cname.uid = target->uid;
1059 cache_hash(aliasc);
1060 add_dhcp_cname(aliasc, ttd);
1065 void cache_add_dhcp_entry(char *host_name, int prot,
1066 struct all_addr *host_address, time_t ttd)
1068 struct crec *crec = NULL, *fail_crec = NULL;
1069 unsigned short flags = F_IPV4;
1070 int in_hosts = 0;
1071 size_t addrlen = sizeof(struct in_addr);
1073 #ifdef HAVE_IPV6
1074 if (prot == AF_INET6)
1076 flags = F_IPV6;
1077 addrlen = sizeof(struct in6_addr);
1079 #endif
1081 inet_ntop(prot, host_address, daemon->addrbuff, ADDRSTRLEN);
1083 while ((crec = cache_find_by_name(crec, host_name, 0, flags | F_CNAME)))
1085 /* check all addresses associated with name */
1086 if (crec->flags & (F_HOSTS | F_CONFIG))
1088 if (crec->flags & F_CNAME)
1089 my_syslog(MS_DHCP | LOG_WARNING,
1090 _("%s is a CNAME, not giving it to the DHCP lease of %s"),
1091 host_name, daemon->addrbuff);
1092 else if (memcmp(&crec->addr.addr, host_address, addrlen) == 0)
1093 in_hosts = 1;
1094 else
1095 fail_crec = crec;
1097 else if (!(crec->flags & F_DHCP))
1099 cache_scan_free(host_name, NULL, 0, crec->flags & (flags | F_CNAME | F_FORWARD));
1100 /* scan_free deletes all addresses associated with name */
1101 break;
1105 /* if in hosts, don't need DHCP record */
1106 if (in_hosts)
1107 return;
1109 /* Name in hosts, address doesn't match */
1110 if (fail_crec)
1112 inet_ntop(prot, &fail_crec->addr.addr, daemon->namebuff, MAXDNAME);
1113 my_syslog(MS_DHCP | LOG_WARNING,
1114 _("not giving name %s to the DHCP lease of %s because "
1115 "the name exists in %s with address %s"),
1116 host_name, daemon->addrbuff,
1117 record_source(fail_crec->uid), daemon->namebuff);
1118 return;
1121 if ((crec = cache_find_by_addr(NULL, (struct all_addr *)host_address, 0, flags)))
1123 if (crec->flags & F_NEG)
1125 flags |= F_REVERSE;
1126 cache_scan_free(NULL, (struct all_addr *)host_address, 0, flags);
1129 else
1130 flags |= F_REVERSE;
1132 if ((crec = dhcp_spare))
1133 dhcp_spare = dhcp_spare->next;
1134 else /* need new one */
1135 crec = whine_malloc(sizeof(struct crec));
1137 if (crec) /* malloc may fail */
1139 crec->flags = flags | F_NAMEP | F_DHCP | F_FORWARD;
1140 if (ttd == 0)
1141 crec->flags |= F_IMMORTAL;
1142 else
1143 crec->ttd = ttd;
1144 crec->addr.addr = *host_address;
1145 crec->name.namep = host_name;
1146 crec->uid = uid++;
1147 cache_hash(crec);
1149 add_dhcp_cname(crec, ttd);
1152 #endif
1155 void dump_cache(time_t now)
1157 struct server *serv, *serv1;
1159 my_syslog(LOG_INFO, _("time %lu"), (unsigned long)now);
1160 my_syslog(LOG_INFO, _("cache size %d, %d/%d cache insertions re-used unexpired cache entries."),
1161 daemon->cachesize, cache_live_freed, cache_inserted);
1162 my_syslog(LOG_INFO, _("queries forwarded %u, queries answered locally %u"),
1163 daemon->queries_forwarded, daemon->local_answer);
1164 #ifdef HAVE_AUTH
1165 my_syslog(LOG_INFO, _("queries for authoritative zones %u"), daemon->auth_answer);
1166 #endif
1168 /* sum counts from different records for same server */
1169 for (serv = daemon->servers; serv; serv = serv->next)
1170 serv->flags &= ~SERV_COUNTED;
1172 for (serv = daemon->servers; serv; serv = serv->next)
1173 if (!(serv->flags &
1174 (SERV_NO_ADDR | SERV_LITERAL_ADDRESS | SERV_COUNTED | SERV_USE_RESOLV | SERV_NO_REBIND)))
1176 int port;
1177 unsigned int queries = 0, failed_queries = 0;
1178 for (serv1 = serv; serv1; serv1 = serv1->next)
1179 if (!(serv1->flags &
1180 (SERV_NO_ADDR | SERV_LITERAL_ADDRESS | SERV_COUNTED | SERV_USE_RESOLV | SERV_NO_REBIND)) &&
1181 sockaddr_isequal(&serv->addr, &serv1->addr))
1183 serv1->flags |= SERV_COUNTED;
1184 queries += serv1->queries;
1185 failed_queries += serv1->failed_queries;
1187 port = prettyprint_addr(&serv->addr, daemon->addrbuff);
1188 my_syslog(LOG_INFO, _("server %s#%d: queries sent %u, retried or failed %u"), daemon->addrbuff, port, queries, failed_queries);
1191 if (option_bool(OPT_DEBUG) || option_bool(OPT_LOG))
1193 struct crec *cache ;
1194 int i;
1195 my_syslog(LOG_INFO, "Host Address Flags Expires");
1197 for (i=0; i<hash_size; i++)
1198 for (cache = hash_table[i]; cache; cache = cache->hash_next)
1200 char *a, *p = daemon->namebuff;
1201 p += sprintf(p, "%-40.40s ", cache_get_name(cache));
1202 if ((cache->flags & F_NEG) && (cache->flags & F_FORWARD))
1203 a = "";
1204 else if (cache->flags & F_CNAME)
1206 a = "";
1207 if (!is_outdated_cname_pointer(cache))
1208 a = cache_get_cname_target(cache);
1210 #ifdef HAVE_DNSSEC
1211 else if (cache->flags & F_DNSKEY)
1213 a = daemon->addrbuff;
1214 sprintf(a, "%3u %u", cache->addr.key.algo, cache->uid);
1216 else if (cache->flags & F_DS)
1218 a = daemon->addrbuff;
1219 sprintf(a, "%5u %3u %3u %u", cache->addr.key.flags_or_keyid,
1220 cache->addr.key.algo, cache->addr.key.digest, cache->uid);
1222 #endif
1223 else
1225 a = daemon->addrbuff;
1226 if (cache->flags & F_IPV4)
1227 inet_ntop(AF_INET, &cache->addr.addr, a, ADDRSTRLEN);
1228 #ifdef HAVE_IPV6
1229 else if (cache->flags & F_IPV6)
1230 inet_ntop(AF_INET6, &cache->addr.addr, a, ADDRSTRLEN);
1231 #endif
1234 p += sprintf(p, "%-30.30s %s%s%s%s%s%s%s%s%s%s%s%s%s ", a,
1235 cache->flags & F_IPV4 ? "4" : "",
1236 cache->flags & F_IPV6 ? "6" : "",
1237 cache->flags & F_DNSKEY ? "K" : "",
1238 cache->flags & F_DS ? "S" : "",
1239 cache->flags & F_CNAME ? "C" : "",
1240 cache->flags & F_FORWARD ? "F" : " ",
1241 cache->flags & F_REVERSE ? "R" : " ",
1242 cache->flags & F_IMMORTAL ? "I" : " ",
1243 cache->flags & F_DHCP ? "D" : " ",
1244 cache->flags & F_NEG ? "N" : " ",
1245 cache->flags & F_NXDOMAIN ? "X" : " ",
1246 cache->flags & F_HOSTS ? "H" : " ",
1247 cache->flags & F_DNSSECOK ? "V" : " ");
1248 #ifdef HAVE_BROKEN_RTC
1249 p += sprintf(p, "%lu", cache->flags & F_IMMORTAL ? 0: (unsigned long)(cache->ttd - now));
1250 #else
1251 p += sprintf(p, "%s", cache->flags & F_IMMORTAL ? "\n" : ctime(&(cache->ttd)));
1252 /* ctime includes trailing \n - eat it */
1253 *(p-1) = 0;
1254 #endif
1255 my_syslog(LOG_INFO, daemon->namebuff);
1260 char *record_source(int index)
1262 struct hostsfile *ah;
1264 if (index == 0)
1265 return HOSTSFILE;
1267 for (ah = daemon->addn_hosts; ah; ah = ah->next)
1268 if (ah->index == index)
1269 return ah->fname;
1271 return "<unknown>";
1274 void querystr(char *desc, char *str, unsigned short type)
1276 unsigned int i;
1278 sprintf(str, "%s[type=%d]", desc, type);
1279 for (i = 0; i < (sizeof(typestr)/sizeof(typestr[0])); i++)
1280 if (typestr[i].type == type)
1281 sprintf(str,"%s[%s]", desc, typestr[i].name);
1284 void log_query(unsigned int flags, char *name, struct all_addr *addr, char *arg)
1286 char *source, *dest = daemon->addrbuff;
1287 char *verb = "is";
1289 if (!option_bool(OPT_LOG))
1290 return;
1292 if (addr)
1294 #ifdef HAVE_IPV6
1295 inet_ntop(flags & F_IPV4 ? AF_INET : AF_INET6,
1296 addr, daemon->addrbuff, ADDRSTRLEN);
1297 #else
1298 strncpy(daemon->addrbuff, inet_ntoa(addr->addr.addr4), ADDRSTRLEN);
1299 #endif
1302 if (flags & F_REVERSE)
1304 dest = name;
1305 name = daemon->addrbuff;
1308 if (flags & F_NEG)
1310 if (flags & F_NXDOMAIN)
1312 if (flags & F_IPV4)
1313 dest = "NXDOMAIN-IPv4";
1314 else if (flags & F_IPV6)
1315 dest = "NXDOMAIN-IPv6";
1316 else
1317 dest = "NXDOMAIN";
1319 else
1321 if (flags & F_IPV4)
1322 dest = "NODATA-IPv4";
1323 else if (flags & F_IPV6)
1324 dest = "NODATA-IPv6";
1325 else
1326 dest = "NODATA";
1329 else if (flags & F_CNAME)
1330 dest = "<CNAME>";
1331 else if (flags & F_RRNAME)
1332 dest = arg;
1334 if (flags & F_CONFIG)
1335 source = "config";
1336 else if (flags & F_DHCP)
1337 source = "DHCP";
1338 else if (flags & F_HOSTS)
1339 source = arg;
1340 else if (flags & F_UPSTREAM)
1341 source = "reply";
1342 else if (flags & F_AUTH)
1343 source = "auth";
1344 else if (flags & F_SERVER)
1346 source = "forwarded";
1347 verb = "to";
1349 else if (flags & F_QUERY)
1351 source = arg;
1352 verb = "from";
1354 else
1355 source = "cached";
1357 if (strlen(name) == 0)
1358 name = ".";
1360 my_syslog(LOG_INFO, "%s %s %s %s", source, name, verb, dest);
1363 #ifdef HAVE_DNSSEC
1364 struct keydata *keydata_alloc(char *data, size_t len)
1366 struct keydata *block, *ret = NULL;
1367 struct keydata **prev = &ret;
1368 while (len > 0)
1370 if (keyblock_free)
1372 block = keyblock_free;
1373 keyblock_free = block->next;
1375 else
1376 block = whine_malloc(sizeof(struct keydata));
1378 if (!block)
1380 /* failed to alloc, free partial chain */
1381 keydata_free(ret);
1382 return NULL;
1385 memcpy(block->key, data, len > KEYBLOCK_LEN ? KEYBLOCK_LEN : len);
1386 data += KEYBLOCK_LEN;
1387 len -= KEYBLOCK_LEN;
1388 *prev = block;
1389 prev = &block->next;
1390 block->next = NULL;
1393 return ret;
1396 void keydata_free(struct keydata *blocks)
1398 struct keydata *tmp;
1400 if (blocks)
1402 for (tmp = blocks; tmp->next; tmp = tmp->next);
1403 tmp->next = keyblock_free;
1404 keyblock_free = blocks;
1407 #endif