]>
git.ipfire.org Git - people/ms/dnsmasq.git/blob - src/cache.c
1 /* dnsmasq is Copyright (c) 2000-2014 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/>.
19 static struct crec
*cache_head
= NULL
, *cache_tail
= NULL
, **hash_table
= NULL
;
21 static struct crec
*dhcp_spare
= NULL
;
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
;
28 /* type->string mapping: this is also used by the name-hash function as a mixing table. */
31 const char * const name
;
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 static unsigned int next_uid(void)
77 static unsigned int uid
= 0;
81 /* uid == 0 used to indicate CNAME to interface name. */
82 if (uid
== SRC_INTERFACE
)
93 bignames_left
= daemon
->cachesize
/10;
95 if (daemon
->cachesize
> 0)
97 crecp
= safe_malloc(daemon
->cachesize
*sizeof(struct crec
));
99 for (i
=0; i
< daemon
->cachesize
; i
++, crecp
++)
103 crecp
->uid
= next_uid();
107 /* create initial hash table*/
108 rehash(daemon
->cachesize
);
111 /* In most cases, we create the hash table once here by calling this with (hash_table == NULL)
112 but if the hosts file(s) are big (some people have 50000 ad-block entries), the table
113 will be much too small, so the hosts reading code calls rehash every 1000 addresses, to
115 static void rehash(int size
)
117 struct crec
**new, **old
, *p
, *tmp
;
118 int i
, new_size
, old_size
;
120 /* hash_size is a power of two. */
121 for (new_size
= 64; new_size
< size
/10; new_size
= new_size
<< 1);
123 /* must succeed in getting first instance, failure later is non-fatal */
125 new = safe_malloc(new_size
* sizeof(struct crec
*));
126 else if (new_size
<= hash_size
|| !(new = whine_malloc(new_size
* sizeof(struct crec
*))))
129 for(i
= 0; i
< new_size
; i
++)
133 old_size
= hash_size
;
135 hash_size
= new_size
;
139 for (i
= 0; i
< old_size
; i
++)
140 for (p
= old
[i
]; p
; p
= tmp
)
149 static struct crec
**hash_bucket(char *name
)
151 unsigned int c
, val
= 017465; /* Barker code - minimum self-correlation in cyclic shift */
152 const unsigned char *mix_tab
= (const unsigned char*)typestr
;
154 while((c
= (unsigned char) *name
++))
156 /* don't use tolower and friends here - they may be messed up by LOCALE */
157 if (c
>= 'A' && c
<= 'Z')
159 val
= ((val
<< 7) | (val
>> (32 - 7))) + (mix_tab
[(val
+ c
) & 0x3F] ^ c
);
162 /* hash_size is a power of two */
163 return hash_table
+ ((val
^ (val
>> 16)) & (hash_size
- 1));
166 static void cache_hash(struct crec
*crecp
)
168 /* maintain an invariant that all entries with F_REVERSE set
169 are at the start of the hash-chain and all non-reverse
170 immortal entries are at the end of the hash-chain.
171 This allows reverse searches and garbage collection to be optimised */
173 struct crec
**up
= hash_bucket(cache_get_name(crecp
));
175 if (!(crecp
->flags
& F_REVERSE
))
177 while (*up
&& ((*up
)->flags
& F_REVERSE
))
178 up
= &((*up
)->hash_next
);
180 if (crecp
->flags
& F_IMMORTAL
)
181 while (*up
&& !((*up
)->flags
& F_IMMORTAL
))
182 up
= &((*up
)->hash_next
);
184 crecp
->hash_next
= *up
;
189 static void cache_blockdata_free(struct crec
*crecp
)
191 if (crecp
->flags
& F_DNSKEY
)
193 if (crecp
->flags
& F_DS
)
194 blockdata_free(crecp
->addr
.sig
.keydata
);
196 blockdata_free(crecp
->addr
.key
.keydata
);
198 else if ((crecp
->flags
& F_DS
) && !(crecp
->flags
& F_NEG
))
199 blockdata_free(crecp
->addr
.ds
.keydata
);
203 static void cache_free(struct crec
*crecp
)
205 crecp
->flags
&= ~F_FORWARD
;
206 crecp
->flags
&= ~F_REVERSE
;
207 crecp
->uid
= next_uid(); /* invalidate CNAMES pointing to this. */
210 cache_tail
->next
= crecp
;
213 crecp
->prev
= cache_tail
;
217 /* retrieve big name for further use. */
218 if (crecp
->flags
& F_BIGNAME
)
220 crecp
->name
.bname
->next
= big_free
;
221 big_free
= crecp
->name
.bname
;
222 crecp
->flags
&= ~F_BIGNAME
;
226 cache_blockdata_free(crecp
);
230 /* insert a new cache entry at the head of the list (youngest entry) */
231 static void cache_link(struct crec
*crecp
)
233 if (cache_head
) /* check needed for init code */
234 cache_head
->prev
= crecp
;
235 crecp
->next
= cache_head
;
242 /* remove an arbitrary cache entry for promotion */
243 static void cache_unlink (struct crec
*crecp
)
246 crecp
->prev
->next
= crecp
->next
;
248 cache_head
= crecp
->next
;
251 crecp
->next
->prev
= crecp
->prev
;
253 cache_tail
= crecp
->prev
;
256 char *cache_get_name(struct crec
*crecp
)
258 if (crecp
->flags
& F_BIGNAME
)
259 return crecp
->name
.bname
->name
;
260 else if (crecp
->flags
& F_NAMEP
)
261 return crecp
->name
.namep
;
263 return crecp
->name
.sname
;
266 char *cache_get_cname_target(struct crec
*crecp
)
268 if (crecp
->addr
.cname
.uid
!= SRC_INTERFACE
)
269 return cache_get_name(crecp
->addr
.cname
.target
.cache
);
271 return crecp
->addr
.cname
.target
.int_name
->name
;
276 struct crec
*cache_enumerate(int init
)
279 static struct crec
*cache
;
286 else if (cache
&& cache
->hash_next
)
287 cache
= cache
->hash_next
;
291 while (bucket
< hash_size
)
292 if ((cache
= hash_table
[bucket
++]))
299 static int is_outdated_cname_pointer(struct crec
*crecp
)
301 if (!(crecp
->flags
& F_CNAME
) || crecp
->addr
.cname
.uid
== SRC_INTERFACE
)
304 /* NB. record may be reused as DS or DNSKEY, where uid is
305 overloaded for something completely different */
306 if (crecp
->addr
.cname
.target
.cache
&&
307 (crecp
->addr
.cname
.target
.cache
->flags
& (F_IPV4
| F_IPV6
| F_CNAME
)) &&
308 crecp
->addr
.cname
.uid
== crecp
->addr
.cname
.target
.cache
->uid
)
314 static int is_expired(time_t now
, struct crec
*crecp
)
316 if (crecp
->flags
& F_IMMORTAL
)
319 if (difftime(now
, crecp
->ttd
) < 0)
325 static int cache_scan_free(char *name
, struct all_addr
*addr
, time_t now
, unsigned short flags
)
327 /* Scan and remove old entries.
328 If (flags & F_FORWARD) then remove any forward entries for name and any expired
329 entries but only in the same hash bucket as name.
330 If (flags & F_REVERSE) then remove any reverse entries for addr and any expired
331 entries in the whole cache.
332 If (flags == 0) remove any expired entries in the whole cache.
334 In the flags & F_FORWARD case, the return code is valid, and returns zero if the
335 name exists in the cache as a HOSTS or DHCP entry (these are never deleted)
337 We take advantage of the fact that hash chains have stuff in the order <reverse>,<other>,<immortal>
338 so that when we hit an entry which isn't reverse and is immortal, we're done. */
340 struct crec
*crecp
, **up
;
342 if (flags
& F_FORWARD
)
344 for (up
= hash_bucket(name
), crecp
= *up
; crecp
; crecp
= crecp
->hash_next
)
346 if (is_expired(now
, crecp
) || is_outdated_cname_pointer(crecp
))
348 *up
= crecp
->hash_next
;
349 if (!(crecp
->flags
& (F_HOSTS
| F_DHCP
| F_CONFIG
)))
357 if ((crecp
->flags
& F_FORWARD
) && hostname_isequal(cache_get_name(crecp
), name
))
359 /* Don't delete DNSSEC in favour of a CNAME, they can co-exist */
360 if ((flags
& crecp
->flags
& (F_IPV4
| F_IPV6
)) ||
361 (((crecp
->flags
| flags
) & F_CNAME
) && !(crecp
->flags
& (F_DNSKEY
| F_DS
))))
363 if (crecp
->flags
& (F_HOSTS
| F_DHCP
| F_CONFIG
))
365 *up
= crecp
->hash_next
;
372 /* Deletion has to be class-sensitive for DS, DNSKEY, RRSIG, also
373 type-covered sensitive for RRSIG */
374 if ((flags
& (F_DNSKEY
| F_DS
)) &&
375 (flags
& (F_DNSKEY
| F_DS
)) == (crecp
->flags
& (F_DNSKEY
| F_DS
)) &&
376 crecp
->uid
== addr
->addr
.dnssec
.class &&
377 (!((flags
& (F_DS
| F_DNSKEY
)) == (F_DS
| F_DNSKEY
)) ||
378 crecp
->addr
.sig
.type_covered
== addr
->addr
.dnssec
.type
))
380 if (crecp
->flags
& F_CONFIG
)
382 *up
= crecp
->hash_next
;
389 up
= &crecp
->hash_next
;
396 int addrlen
= (flags
& F_IPV6
) ? IN6ADDRSZ
: INADDRSZ
;
398 int addrlen
= INADDRSZ
;
400 for (i
= 0; i
< hash_size
; i
++)
401 for (crecp
= hash_table
[i
], up
= &hash_table
[i
];
402 crecp
&& ((crecp
->flags
& F_REVERSE
) || !(crecp
->flags
& F_IMMORTAL
));
403 crecp
= crecp
->hash_next
)
404 if (is_expired(now
, crecp
))
406 *up
= crecp
->hash_next
;
407 if (!(crecp
->flags
& (F_HOSTS
| F_DHCP
| F_CONFIG
)))
413 else if (!(crecp
->flags
& (F_HOSTS
| F_DHCP
| F_CONFIG
)) &&
414 (flags
& crecp
->flags
& F_REVERSE
) &&
415 (flags
& crecp
->flags
& (F_IPV4
| F_IPV6
)) &&
416 memcmp(&crecp
->addr
.addr
, addr
, addrlen
) == 0)
418 *up
= crecp
->hash_next
;
423 up
= &crecp
->hash_next
;
429 /* Note: The normal calling sequence is
434 but an abort can cause the cache_end_insert to be missed
435 in which can the next cache_start_insert cleans things up. */
437 void cache_start_insert(void)
439 /* Free any entries which didn't get committed during the last
444 struct crec
*tmp
= new_chain
->next
;
445 cache_free(new_chain
);
452 struct crec
*cache_insert(char *name
, struct all_addr
*addr
,
453 time_t now
, unsigned long ttl
, unsigned short flags
)
456 union bigname
*big_name
= NULL
;
457 int freed_all
= flags
& F_REVERSE
;
460 /* Don't log DNSSEC records here, done elsewhere */
461 if (flags
& (F_IPV4
| F_IPV6
| F_CNAME
))
463 log_query(flags
| F_UPSTREAM
, name
, addr
, NULL
);
464 /* Don;t mess with TTL for DNSSEC records. */
465 if (daemon
->max_cache_ttl
!= 0 && daemon
->max_cache_ttl
< ttl
)
466 ttl
= daemon
->max_cache_ttl
;
469 /* if previous insertion failed give up now. */
473 /* First remove any expired entries and entries for the name/address we
474 are currently inserting. Fail if we attempt to delete a name from
475 /etc/hosts or DHCP. */
476 if (!cache_scan_free(name
, addr
, now
, flags
))
482 /* Now get a cache entry from the end of the LRU list */
484 if (!(new = cache_tail
)) /* no entries left - cache is too small, bail */
490 /* End of LRU list is still in use: if we didn't scan all the hash
491 chains for expired entries do that now. If we already tried that
492 then it's time to start spilling things. */
494 if (new->flags
& (F_FORWARD
| F_REVERSE
))
496 /* If free_avail set, we believe that an entry has been freed.
497 Bugs have been known to make this not true, resulting in
498 a tight loop here. If that happens, abandon the
499 insert. Once in this state, all inserts will probably fail. */
502 static int warned
= 0;
505 my_syslog(LOG_ERR
, _("Internal error in cache."));
514 struct all_addr free_addr
= new->addr
.addr
;;
517 /* For DNSSEC records, addr holds class and type_covered for RRSIG */
518 if (new->flags
& (F_DS
| F_DNSKEY
))
520 free_addr
.addr
.dnssec
.class = new->uid
;
521 if ((new->flags
& (F_DS
| F_DNSKEY
)) == (F_DS
| F_DNSKEY
))
522 free_addr
.addr
.dnssec
.type
= new->addr
.sig
.type_covered
;
526 free_avail
= 1; /* Must be free space now. */
527 cache_scan_free(cache_get_name(new), &free_addr
, now
, new->flags
);
532 cache_scan_free(NULL
, NULL
, now
, 0);
538 /* Check if we need to and can allocate extra memory for a long name.
539 If that fails, give up now, always succeed for DNSSEC records. */
540 if (name
&& (strlen(name
) > SMALLDNAME
-1))
545 big_free
= big_free
->next
;
547 else if ((bignames_left
== 0 && !(flags
& (F_DS
| F_DNSKEY
))) ||
548 !(big_name
= (union bigname
*)whine_malloc(sizeof(union bigname
))))
553 else if (bignames_left
!= 0)
558 /* Got the rest: finally grab entry. */
566 new->name
.bname
= big_name
;
567 new->flags
|= F_BIGNAME
;
571 strcpy(cache_get_name(new), name
);
573 *cache_get_name(new) = 0;
578 if (flags
& (F_DS
| F_DNSKEY
))
579 new->uid
= addr
->addr
.dnssec
.class;
582 new->addr
.addr
= *addr
;
585 new->ttd
= now
+ (time_t)ttl
;
586 new->next
= new_chain
;
592 /* after end of insertion, commit the new entries */
593 void cache_end_insert(void)
600 struct crec
*tmp
= new_chain
->next
;
601 /* drop CNAMEs which didn't find a target. */
602 if (is_outdated_cname_pointer(new_chain
))
603 cache_free(new_chain
);
606 cache_hash(new_chain
);
607 cache_link(new_chain
);
615 struct crec
*cache_find_by_name(struct crec
*crecp
, char *name
, time_t now
, unsigned int prot
)
618 int no_rr
= prot
& F_NO_RR
;
622 if (crecp
) /* iterating */
626 /* first search, look for relevant entries and push to top of list
627 also free anything which has expired */
628 struct crec
*next
, **up
, **insert
= NULL
, **chainp
= &ans
;
629 unsigned short ins_flags
= 0;
631 for (up
= hash_bucket(name
), crecp
= *up
; crecp
; crecp
= next
)
633 next
= crecp
->hash_next
;
635 if (!is_expired(now
, crecp
) && !is_outdated_cname_pointer(crecp
))
637 if ((crecp
->flags
& F_FORWARD
) &&
639 ((crecp
->flags
& (F_DNSKEY
| F_DS
)) == (prot
& (F_DNSKEY
| F_DS
))) &&
641 (crecp
->flags
& prot
) &&
642 hostname_isequal(cache_get_name(crecp
), name
))
644 if (crecp
->flags
& (F_HOSTS
| F_DHCP
| F_CONFIG
))
647 chainp
= &crecp
->next
;
655 /* Move all but the first entry up the hash chain
656 this implements round-robin.
657 Make sure that re-ordering doesn't break the hash-chain
660 if (insert
&& (crecp
->flags
& (F_REVERSE
| F_IMMORTAL
)) == ins_flags
)
662 *up
= crecp
->hash_next
;
663 crecp
->hash_next
= *insert
;
665 insert
= &crecp
->hash_next
;
669 if (!insert
&& !no_rr
)
672 ins_flags
= crecp
->flags
& (F_REVERSE
| F_IMMORTAL
);
674 up
= &crecp
->hash_next
;
678 /* case : not expired, incorrect entry. */
679 up
= &crecp
->hash_next
;
683 /* expired entry, free it */
684 *up
= crecp
->hash_next
;
685 if (!(crecp
->flags
& (F_HOSTS
| F_DHCP
| F_CONFIG
)))
693 *chainp
= cache_head
;
697 (ans
->flags
& F_FORWARD
) &&
699 ((ans
->flags
& (F_DNSKEY
| F_DS
)) == (prot
& (F_DNSKEY
| F_DS
))) &&
701 (ans
->flags
& prot
) &&
702 hostname_isequal(cache_get_name(ans
), name
))
708 struct crec
*cache_find_by_addr(struct crec
*crecp
, struct all_addr
*addr
,
709 time_t now
, unsigned int prot
)
713 int addrlen
= (prot
== F_IPV6
) ? IN6ADDRSZ
: INADDRSZ
;
715 int addrlen
= INADDRSZ
;
718 if (crecp
) /* iterating */
722 /* first search, look for relevant entries and push to top of list
723 also free anything which has expired. All the reverse entries are at the
724 start of the hash chain, so we can give up when we find the first
727 struct crec
**up
, **chainp
= &ans
;
729 for (i
=0; i
<hash_size
; i
++)
730 for (crecp
= hash_table
[i
], up
= &hash_table
[i
];
731 crecp
&& (crecp
->flags
& F_REVERSE
);
732 crecp
= crecp
->hash_next
)
733 if (!is_expired(now
, crecp
))
735 if ((crecp
->flags
& prot
) &&
736 memcmp(&crecp
->addr
.addr
, addr
, addrlen
) == 0)
738 if (crecp
->flags
& (F_HOSTS
| F_DHCP
| F_CONFIG
))
741 chainp
= &crecp
->next
;
749 up
= &crecp
->hash_next
;
753 *up
= crecp
->hash_next
;
754 if (!(crecp
->flags
& (F_HOSTS
| F_DHCP
| F_CONFIG
)))
761 *chainp
= cache_head
;
765 (ans
->flags
& F_REVERSE
) &&
766 (ans
->flags
& prot
) &&
767 memcmp(&ans
->addr
.addr
, addr
, addrlen
) == 0)
773 static void add_hosts_cname(struct crec
*target
)
778 for (a
= daemon
->cnames
; a
; a
= a
->next
)
779 if (hostname_isequal(cache_get_name(target
), a
->target
) &&
780 (crec
= whine_malloc(sizeof(struct crec
))))
782 crec
->flags
= F_FORWARD
| F_IMMORTAL
| F_NAMEP
| F_CONFIG
| F_CNAME
;
783 crec
->name
.namep
= a
->alias
;
784 crec
->addr
.cname
.target
.cache
= target
;
785 crec
->addr
.cname
.uid
= target
->uid
;
786 crec
->uid
= next_uid();
788 add_hosts_cname(crec
); /* handle chains */
792 static void add_hosts_entry(struct crec
*cache
, struct all_addr
*addr
, int addrlen
,
793 unsigned int index
, struct crec
**rhash
, int hashsz
)
795 struct crec
*lookup
= cache_find_by_name(NULL
, cache_get_name(cache
), 0, cache
->flags
& (F_IPV4
| F_IPV6
));
796 int i
, nameexists
= 0;
799 /* Remove duplicates in hosts files. */
800 if (lookup
&& (lookup
->flags
& F_HOSTS
))
803 if (memcmp(&lookup
->addr
.addr
, addr
, addrlen
) == 0)
810 /* Ensure there is only one address -> name mapping (first one trumps)
811 We do this by steam here, The entries are kept in hash chains, linked
812 by ->next (which is unused at this point) held in hash buckets in
813 the array rhash, hashed on address. Note that rhash and the values
814 in ->next are only valid whilst reading hosts files: the buckets are
815 then freed, and the ->next pointer used for other things.
817 Only insert each unique address once into this hashing structure.
819 This complexity avoids O(n^2) divergent CPU use whilst reading
820 large (10000 entry) hosts files. */
823 for (j
= 0, i
= 0; i
< addrlen
; i
++)
824 j
= (j
*2 +((unsigned char *)addr
)[i
]) % hashsz
;
826 for (lookup
= rhash
[j
]; lookup
; lookup
= lookup
->next
)
827 if ((lookup
->flags
& cache
->flags
& (F_IPV4
| F_IPV6
)) &&
828 memcmp(&lookup
->addr
.addr
, addr
, addrlen
) == 0)
830 cache
->flags
&= ~F_REVERSE
;
834 /* maintain address hash chain, insert new unique address */
837 cache
->next
= rhash
[j
];
842 memcpy(&cache
->addr
.addr
, addr
, addrlen
);
845 /* don't need to do alias stuff for second and subsequent addresses. */
847 add_hosts_cname(cache
);
850 static int eatspace(FILE *f
)
856 if ((c
= getc(f
)) == '#')
857 while (c
!= '\n' && c
!= EOF
)
874 static int gettok(FILE *f
, char *token
)
880 if ((c
= getc(f
)) == EOF
)
881 return (count
== 0) ? EOF
: 1;
883 if (isspace(c
) || c
== '#')
889 if (count
< (MAXDNAME
- 1))
897 static int read_hostsfile(char *filename
, unsigned int index
, int cache_size
, struct crec
**rhash
, int hashsz
)
899 FILE *f
= fopen(filename
, "r");
900 char *token
= daemon
->namebuff
, *domain_suffix
= NULL
;
901 int addr_count
= 0, name_count
= cache_size
, lineno
= 0;
902 unsigned short flags
= 0;
903 struct all_addr addr
;
904 int atnl
, addrlen
= 0;
908 my_syslog(LOG_ERR
, _("failed to load names from %s: %s"), filename
, strerror(errno
));
914 while ((atnl
= gettok(f
, token
)) != EOF
)
918 if (inet_pton(AF_INET
, token
, &addr
) > 0)
920 flags
= F_HOSTS
| F_IMMORTAL
| F_FORWARD
| F_REVERSE
| F_IPV4
;
922 domain_suffix
= get_domain(addr
.addr
.addr4
);
925 else if (inet_pton(AF_INET6
, token
, &addr
) > 0)
927 flags
= F_HOSTS
| F_IMMORTAL
| F_FORWARD
| F_REVERSE
| F_IPV6
;
929 domain_suffix
= get_domain6(&addr
.addr
.addr6
);
934 my_syslog(LOG_ERR
, _("bad address at %s line %d"), filename
, lineno
);
936 atnl
= gettok(f
, token
);
942 /* rehash every 1000 names. */
943 if ((name_count
- cache_size
) > 1000)
946 cache_size
= name_count
;
955 if ((atnl
= gettok(f
, token
)) == EOF
)
958 fqdn
= !!strchr(token
, '.');
960 if ((canon
= canonicalise(token
, &nomem
)))
962 /* If set, add a version of the name with a default domain appended */
963 if (option_bool(OPT_EXPAND
) && domain_suffix
&& !fqdn
&&
964 (cache
= whine_malloc(sizeof(struct crec
) +
965 strlen(canon
)+2+strlen(domain_suffix
)-SMALLDNAME
)))
967 strcpy(cache
->name
.sname
, canon
);
968 strcat(cache
->name
.sname
, ".");
969 strcat(cache
->name
.sname
, domain_suffix
);
970 cache
->flags
= flags
;
971 add_hosts_entry(cache
, &addr
, addrlen
, index
, rhash
, hashsz
);
974 if ((cache
= whine_malloc(sizeof(struct crec
) + strlen(canon
)+1-SMALLDNAME
)))
976 strcpy(cache
->name
.sname
, canon
);
977 cache
->flags
= flags
;
978 add_hosts_entry(cache
, &addr
, addrlen
, index
, rhash
, hashsz
);
985 my_syslog(LOG_ERR
, _("bad name at %s line %d"), filename
, lineno
);
992 my_syslog(LOG_INFO
, _("read %s - %d addresses"), filename
, addr_count
);
997 void cache_reload(void)
999 struct crec
*cache
, **up
, *tmp
;
1000 int revhashsz
, i
, total_size
= daemon
->cachesize
;
1001 struct hostsfile
*ah
;
1002 struct host_record
*hr
;
1003 struct name_list
*nl
;
1005 struct interface_name
*intr
;
1007 struct ds_config
*ds
;
1010 cache_inserted
= cache_live_freed
= 0;
1012 for (i
=0; i
<hash_size
; i
++)
1013 for (cache
= hash_table
[i
], up
= &hash_table
[i
]; cache
; cache
= tmp
)
1016 cache_blockdata_free(cache
);
1018 tmp
= cache
->hash_next
;
1019 if (cache
->flags
& (F_HOSTS
| F_CONFIG
))
1021 *up
= cache
->hash_next
;
1024 else if (!(cache
->flags
& F_DHCP
))
1026 *up
= cache
->hash_next
;
1027 if (cache
->flags
& F_BIGNAME
)
1029 cache
->name
.bname
->next
= big_free
;
1030 big_free
= cache
->name
.bname
;
1035 up
= &cache
->hash_next
;
1038 /* Add CNAMEs to interface_names to the cache */
1039 for (a
= daemon
->cnames
; a
; a
= a
->next
)
1040 for (intr
= daemon
->int_names
; intr
; intr
= intr
->next
)
1041 if (hostname_isequal(a
->target
, intr
->name
) &&
1042 ((cache
= whine_malloc(sizeof(struct crec
)))))
1044 cache
->flags
= F_FORWARD
| F_NAMEP
| F_CNAME
| F_IMMORTAL
| F_CONFIG
;
1045 cache
->name
.namep
= a
->alias
;
1046 cache
->addr
.cname
.target
.int_name
= intr
;
1047 cache
->addr
.cname
.uid
= SRC_INTERFACE
;
1048 cache
->uid
= next_uid();
1050 add_hosts_cname(cache
); /* handle chains */
1054 for (ds
= daemon
->ds
; ds
; ds
= ds
->next
)
1055 if ((cache
= whine_malloc(sizeof(struct crec
))) &&
1056 (cache
->addr
.ds
.keydata
= blockdata_alloc(ds
->digest
, ds
->digestlen
)))
1058 cache
->flags
= F_FORWARD
| F_IMMORTAL
| F_DS
| F_CONFIG
| F_NAMEP
;
1059 cache
->name
.namep
= ds
->name
;
1060 cache
->addr
.ds
.keylen
= ds
->digestlen
;
1061 cache
->addr
.ds
.algo
= ds
->algo
;
1062 cache
->addr
.ds
.keytag
= ds
->keytag
;
1063 cache
->addr
.ds
.digest
= ds
->digest_type
;
1064 cache
->uid
= ds
->class;
1069 /* borrow the packet buffer for a temporary by-address hash */
1070 memset(daemon
->packet
, 0, daemon
->packet_buff_sz
);
1071 revhashsz
= daemon
->packet_buff_sz
/ sizeof(struct crec
*);
1072 /* we overwrote the buffer... */
1073 daemon
->srv_save
= NULL
;
1075 /* Do host_records in config. */
1076 for (hr
= daemon
->host_records
; hr
; hr
= hr
->next
)
1077 for (nl
= hr
->names
; nl
; nl
= nl
->next
)
1079 if (hr
->addr
.s_addr
!= 0 &&
1080 (cache
= whine_malloc(sizeof(struct crec
))))
1082 cache
->name
.namep
= nl
->name
;
1083 cache
->flags
= F_HOSTS
| F_IMMORTAL
| F_FORWARD
| F_REVERSE
| F_IPV4
| F_NAMEP
| F_CONFIG
;
1084 add_hosts_entry(cache
, (struct all_addr
*)&hr
->addr
, INADDRSZ
, SRC_CONFIG
, (struct crec
**)daemon
->packet
, revhashsz
);
1087 if (!IN6_IS_ADDR_UNSPECIFIED(&hr
->addr6
) &&
1088 (cache
= whine_malloc(sizeof(struct crec
))))
1090 cache
->name
.namep
= nl
->name
;
1091 cache
->flags
= F_HOSTS
| F_IMMORTAL
| F_FORWARD
| F_REVERSE
| F_IPV6
| F_NAMEP
| F_CONFIG
;
1092 add_hosts_entry(cache
, (struct all_addr
*)&hr
->addr6
, IN6ADDRSZ
, SRC_CONFIG
, (struct crec
**)daemon
->packet
, revhashsz
);
1097 if (option_bool(OPT_NO_HOSTS
) && !daemon
->addn_hosts
)
1099 if (daemon
->cachesize
> 0)
1100 my_syslog(LOG_INFO
, _("cleared cache"));
1104 if (!option_bool(OPT_NO_HOSTS
))
1105 total_size
= read_hostsfile(HOSTSFILE
, SRC_HOSTS
, total_size
, (struct crec
**)daemon
->packet
, revhashsz
);
1107 daemon
->addn_hosts
= expand_filelist(daemon
->addn_hosts
);
1108 for (ah
= daemon
->addn_hosts
; ah
; ah
= ah
->next
)
1109 if (!(ah
->flags
& AH_INACTIVE
))
1110 total_size
= read_hostsfile(ah
->fname
, ah
->index
, total_size
, (struct crec
**)daemon
->packet
, revhashsz
);
1114 struct in_addr
a_record_from_hosts(char *name
, time_t now
)
1116 struct crec
*crecp
= NULL
;
1119 while ((crecp
= cache_find_by_name(crecp
, name
, now
, F_IPV4
)))
1120 if (crecp
->flags
& F_HOSTS
)
1121 return *(struct in_addr
*)&crecp
->addr
;
1123 my_syslog(MS_DHCP
| LOG_WARNING
, _("No IPv4 address found for %s"), name
);
1129 void cache_unhash_dhcp(void)
1131 struct crec
*cache
, **up
;
1134 for (i
=0; i
<hash_size
; i
++)
1135 for (cache
= hash_table
[i
], up
= &hash_table
[i
]; cache
; cache
= cache
->hash_next
)
1136 if (cache
->flags
& F_DHCP
)
1138 *up
= cache
->hash_next
;
1139 cache
->next
= dhcp_spare
;
1143 up
= &cache
->hash_next
;
1146 static void add_dhcp_cname(struct crec
*target
, time_t ttd
)
1148 struct crec
*aliasc
;
1151 for (a
= daemon
->cnames
; a
; a
= a
->next
)
1152 if (hostname_isequal(cache_get_name(target
), a
->target
))
1154 if ((aliasc
= dhcp_spare
))
1155 dhcp_spare
= dhcp_spare
->next
;
1156 else /* need new one */
1157 aliasc
= whine_malloc(sizeof(struct crec
));
1161 aliasc
->flags
= F_FORWARD
| F_NAMEP
| F_DHCP
| F_CNAME
| F_CONFIG
;
1163 aliasc
->flags
|= F_IMMORTAL
;
1166 aliasc
->name
.namep
= a
->alias
;
1167 aliasc
->addr
.cname
.target
.cache
= target
;
1168 aliasc
->addr
.cname
.uid
= target
->uid
;
1169 aliasc
->uid
= next_uid();
1171 add_dhcp_cname(aliasc
, ttd
);
1176 void cache_add_dhcp_entry(char *host_name
, int prot
,
1177 struct all_addr
*host_address
, time_t ttd
)
1179 struct crec
*crec
= NULL
, *fail_crec
= NULL
;
1180 unsigned short flags
= F_IPV4
;
1182 size_t addrlen
= sizeof(struct in_addr
);
1185 if (prot
== AF_INET6
)
1188 addrlen
= sizeof(struct in6_addr
);
1192 inet_ntop(prot
, host_address
, daemon
->addrbuff
, ADDRSTRLEN
);
1194 while ((crec
= cache_find_by_name(crec
, host_name
, 0, flags
| F_CNAME
)))
1196 /* check all addresses associated with name */
1197 if (crec
->flags
& (F_HOSTS
| F_CONFIG
))
1199 if (crec
->flags
& F_CNAME
)
1200 my_syslog(MS_DHCP
| LOG_WARNING
,
1201 _("%s is a CNAME, not giving it to the DHCP lease of %s"),
1202 host_name
, daemon
->addrbuff
);
1203 else if (memcmp(&crec
->addr
.addr
, host_address
, addrlen
) == 0)
1208 else if (!(crec
->flags
& F_DHCP
))
1210 cache_scan_free(host_name
, NULL
, 0, crec
->flags
& (flags
| F_CNAME
| F_FORWARD
));
1211 /* scan_free deletes all addresses associated with name */
1216 /* if in hosts, don't need DHCP record */
1220 /* Name in hosts, address doesn't match */
1223 inet_ntop(prot
, &fail_crec
->addr
.addr
, daemon
->namebuff
, MAXDNAME
);
1224 my_syslog(MS_DHCP
| LOG_WARNING
,
1225 _("not giving name %s to the DHCP lease of %s because "
1226 "the name exists in %s with address %s"),
1227 host_name
, daemon
->addrbuff
,
1228 record_source(fail_crec
->uid
), daemon
->namebuff
);
1232 if ((crec
= cache_find_by_addr(NULL
, (struct all_addr
*)host_address
, 0, flags
)))
1234 if (crec
->flags
& F_NEG
)
1237 cache_scan_free(NULL
, (struct all_addr
*)host_address
, 0, flags
);
1243 if ((crec
= dhcp_spare
))
1244 dhcp_spare
= dhcp_spare
->next
;
1245 else /* need new one */
1246 crec
= whine_malloc(sizeof(struct crec
));
1248 if (crec
) /* malloc may fail */
1250 crec
->flags
= flags
| F_NAMEP
| F_DHCP
| F_FORWARD
;
1252 crec
->flags
|= F_IMMORTAL
;
1255 crec
->addr
.addr
= *host_address
;
1256 crec
->name
.namep
= host_name
;
1257 crec
->uid
= next_uid();
1260 add_dhcp_cname(crec
, ttd
);
1265 int cache_make_stat(struct txt_record
*t
)
1267 static char *buff
= NULL
;
1268 static int bufflen
= 60;
1270 struct server
*serv
, *serv1
;
1273 if (!buff
&& !(buff
= whine_malloc(60)))
1280 case TXT_STAT_CACHESIZE
:
1281 sprintf(buff
+1, "%d", daemon
->cachesize
);
1284 case TXT_STAT_INSERTS
:
1285 sprintf(buff
+1, "%d", cache_inserted
);
1288 case TXT_STAT_EVICTIONS
:
1289 sprintf(buff
+1, "%d", cache_live_freed
);
1292 case TXT_STAT_MISSES
:
1293 sprintf(buff
+1, "%u", daemon
->queries_forwarded
);
1297 sprintf(buff
+1, "%u", daemon
->local_answer
);
1302 sprintf(buff
+1, "%u", daemon
->auth_answer
);
1306 case TXT_STAT_SERVERS
:
1307 /* sum counts from different records for same server */
1308 for (serv
= daemon
->servers
; serv
; serv
= serv
->next
)
1309 serv
->flags
&= ~SERV_COUNTED
;
1311 for (serv
= daemon
->servers
; serv
; serv
= serv
->next
)
1313 (SERV_NO_ADDR
| SERV_LITERAL_ADDRESS
| SERV_COUNTED
| SERV_USE_RESOLV
| SERV_NO_REBIND
)))
1316 int port
, newlen
, bytes_avail
, bytes_needed
;
1317 unsigned int queries
= 0, failed_queries
= 0;
1318 for (serv1
= serv
; serv1
; serv1
= serv1
->next
)
1319 if (!(serv1
->flags
&
1320 (SERV_NO_ADDR
| SERV_LITERAL_ADDRESS
| SERV_COUNTED
| SERV_USE_RESOLV
| SERV_NO_REBIND
)) &&
1321 sockaddr_isequal(&serv
->addr
, &serv1
->addr
))
1323 serv1
->flags
|= SERV_COUNTED
;
1324 queries
+= serv1
->queries
;
1325 failed_queries
+= serv1
->failed_queries
;
1327 port
= prettyprint_addr(&serv
->addr
, daemon
->addrbuff
);
1328 lenp
= p
++; /* length */
1329 bytes_avail
= (p
- buff
) + bufflen
;
1330 bytes_needed
= snprintf(p
, bytes_avail
, "%s#%d %u %u", daemon
->addrbuff
, port
, queries
, failed_queries
);
1331 if (bytes_needed
>= bytes_avail
)
1333 /* expand buffer if necessary */
1334 newlen
= bytes_needed
+ 1 + bufflen
- bytes_avail
;
1335 if (!(new = whine_malloc(newlen
)))
1337 memcpy(new, buff
, bufflen
);
1339 p
= new + (p
- buff
);
1343 bytes_avail
= (p
- buff
) + bufflen
;
1344 bytes_needed
= snprintf(p
, bytes_avail
, "%s#%d %u %u", daemon
->addrbuff
, port
, queries
, failed_queries
);
1346 *lenp
= bytes_needed
;
1349 t
->txt
= (unsigned char *)buff
;
1354 len
= strlen(buff
+1);
1355 t
->txt
= (unsigned char *)buff
;
1361 void dump_cache(time_t now
)
1363 struct server
*serv
, *serv1
;
1366 my_syslog(LOG_INFO
, _("time %lu"), (unsigned long)now
);
1367 my_syslog(LOG_INFO
, _("cache size %d, %d/%d cache insertions re-used unexpired cache entries."),
1368 daemon
->cachesize
, cache_live_freed
, cache_inserted
);
1369 my_syslog(LOG_INFO
, _("queries forwarded %u, queries answered locally %u"),
1370 daemon
->queries_forwarded
, daemon
->local_answer
);
1372 my_syslog(LOG_INFO
, _("queries for authoritative zones %u"), daemon
->auth_answer
);
1378 /* sum counts from different records for same server */
1379 for (serv
= daemon
->servers
; serv
; serv
= serv
->next
)
1380 serv
->flags
&= ~SERV_COUNTED
;
1382 for (serv
= daemon
->servers
; serv
; serv
= serv
->next
)
1384 (SERV_NO_ADDR
| SERV_LITERAL_ADDRESS
| SERV_COUNTED
| SERV_USE_RESOLV
| SERV_NO_REBIND
)))
1387 unsigned int queries
= 0, failed_queries
= 0;
1388 for (serv1
= serv
; serv1
; serv1
= serv1
->next
)
1389 if (!(serv1
->flags
&
1390 (SERV_NO_ADDR
| SERV_LITERAL_ADDRESS
| SERV_COUNTED
| SERV_USE_RESOLV
| SERV_NO_REBIND
)) &&
1391 sockaddr_isequal(&serv
->addr
, &serv1
->addr
))
1393 serv1
->flags
|= SERV_COUNTED
;
1394 queries
+= serv1
->queries
;
1395 failed_queries
+= serv1
->failed_queries
;
1397 port
= prettyprint_addr(&serv
->addr
, daemon
->addrbuff
);
1398 my_syslog(LOG_INFO
, _("server %s#%d: queries sent %u, retried or failed %u"), daemon
->addrbuff
, port
, queries
, failed_queries
);
1401 if (option_bool(OPT_DEBUG
) || option_bool(OPT_LOG
))
1403 struct crec
*cache
;
1405 my_syslog(LOG_INFO
, "Host Address Flags Expires");
1407 for (i
=0; i
<hash_size
; i
++)
1408 for (cache
= hash_table
[i
]; cache
; cache
= cache
->hash_next
)
1410 char *a
= daemon
->addrbuff
, *p
= daemon
->namebuff
, *n
= cache_get_name(cache
);
1412 if (strlen(n
) == 0 && !(cache
->flags
& F_REVERSE
))
1414 p
+= sprintf(p
, "%-40.40s ", n
);
1415 if ((cache
->flags
& F_CNAME
) && !is_outdated_cname_pointer(cache
))
1416 a
= cache_get_cname_target(cache
);
1418 else if (cache
->flags
& F_DS
)
1420 if (cache
->flags
& F_DNSKEY
)
1422 sprintf(a
, "%5u %3u %s", cache
->addr
.sig
.keytag
,
1423 cache
->addr
.sig
.algo
, querystr("", cache
->addr
.sig
.type_covered
));
1424 else if (!(cache
->flags
& F_NEG
))
1425 sprintf(a
, "%5u %3u %3u", cache
->addr
.ds
.keytag
,
1426 cache
->addr
.ds
.algo
, cache
->addr
.ds
.digest
);
1428 else if (cache
->flags
& F_DNSKEY
)
1429 sprintf(a
, "%5u %3u %3u", cache
->addr
.key
.keytag
,
1430 cache
->addr
.key
.algo
, cache
->addr
.key
.flags
);
1432 else if (!(cache
->flags
& F_NEG
) || !(cache
->flags
& F_FORWARD
))
1434 a
= daemon
->addrbuff
;
1435 if (cache
->flags
& F_IPV4
)
1436 inet_ntop(AF_INET
, &cache
->addr
.addr
, a
, ADDRSTRLEN
);
1438 else if (cache
->flags
& F_IPV6
)
1439 inet_ntop(AF_INET6
, &cache
->addr
.addr
, a
, ADDRSTRLEN
);
1443 if (cache
->flags
& F_IPV4
)
1445 else if (cache
->flags
& F_IPV6
)
1447 else if (cache
->flags
& F_CNAME
)
1450 else if ((cache
->flags
& (F_DS
| F_DNSKEY
)) == (F_DS
| F_DNSKEY
))
1451 t
= "G"; /* DNSKEY and DS set -> RRISG */
1452 else if (cache
->flags
& F_DS
)
1454 else if (cache
->flags
& F_DNSKEY
)
1457 p
+= sprintf(p
, "%-30.30s %s%s%s%s%s%s%s%s%s ", a
, t
,
1458 cache
->flags
& F_FORWARD
? "F" : " ",
1459 cache
->flags
& F_REVERSE
? "R" : " ",
1460 cache
->flags
& F_IMMORTAL
? "I" : " ",
1461 cache
->flags
& F_DHCP
? "D" : " ",
1462 cache
->flags
& F_NEG
? "N" : " ",
1463 cache
->flags
& F_NXDOMAIN
? "X" : " ",
1464 cache
->flags
& F_HOSTS
? "H" : " ",
1465 cache
->flags
& F_DNSSECOK
? "V" : " ");
1466 #ifdef HAVE_BROKEN_RTC
1467 p
+= sprintf(p
, "%lu", cache
->flags
& F_IMMORTAL
? 0: (unsigned long)(cache
->ttd
- now
));
1469 p
+= sprintf(p
, "%s", cache
->flags
& F_IMMORTAL
? "\n" : ctime(&(cache
->ttd
)));
1470 /* ctime includes trailing \n - eat it */
1473 my_syslog(LOG_INFO
, daemon
->namebuff
);
1478 char *record_source(unsigned int index
)
1480 struct hostsfile
*ah
;
1482 if (index
== SRC_CONFIG
)
1484 else if (index
== SRC_HOSTS
)
1487 for (ah
= daemon
->addn_hosts
; ah
; ah
= ah
->next
)
1488 if (ah
->index
== index
)
1494 char *querystr(char *desc
, unsigned short type
)
1497 int len
= 10; /* strlen("type=xxxxx") */
1498 const char *types
= NULL
;
1499 static char *buff
= NULL
;
1500 static int bufflen
= 0;
1502 for (i
= 0; i
< (sizeof(typestr
)/sizeof(typestr
[0])); i
++)
1503 if (typestr
[i
].type
== type
)
1505 types
= typestr
[i
].name
;
1506 len
= strlen(types
);
1510 len
+= 3; /* braces, terminator */
1511 len
+= strlen(desc
);
1513 if (!buff
|| bufflen
< len
)
1520 buff
= whine_malloc(len
);
1527 sprintf(buff
, "%s[%s]", desc
, types
);
1529 sprintf(buff
, "%s[type=%d]", desc
, type
);
1532 return buff
? buff
: "";
1535 void log_query(unsigned int flags
, char *name
, struct all_addr
*addr
, char *arg
)
1537 char *source
, *dest
= daemon
->addrbuff
;
1540 if (!option_bool(OPT_LOG
))
1545 if (flags
& F_KEYTAG
)
1546 sprintf(daemon
->addrbuff
, arg
, addr
->addr
.keytag
);
1550 inet_ntop(flags
& F_IPV4
? AF_INET
: AF_INET6
,
1551 addr
, daemon
->addrbuff
, ADDRSTRLEN
);
1553 strncpy(daemon
->addrbuff
, inet_ntoa(addr
->addr
.addr4
), ADDRSTRLEN
);
1560 if (flags
& F_REVERSE
)
1563 name
= daemon
->addrbuff
;
1568 if (flags
& F_NXDOMAIN
)
1573 dest
= "NODATA-IPv4";
1574 else if (flags
& F_IPV6
)
1575 dest
= "NODATA-IPv6";
1580 else if (flags
& F_CNAME
)
1582 else if (flags
& F_RRNAME
)
1585 if (flags
& F_CONFIG
)
1587 else if (flags
& F_DHCP
)
1589 else if (flags
& F_HOSTS
)
1591 else if (flags
& F_UPSTREAM
)
1593 else if (flags
& F_SECSTAT
)
1594 source
= "validation";
1595 else if (flags
& F_AUTH
)
1597 else if (flags
& F_SERVER
)
1599 source
= "forwarded";
1602 else if (flags
& F_QUERY
)
1607 else if (flags
& F_DNSSEC
)
1615 if (strlen(name
) == 0)
1618 my_syslog(LOG_INFO
, "%s %s %s %s", source
, name
, verb
, dest
);