]>
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
;
29 /* type->string mapping: this is also used by the name-hash function as a mixing table. */
32 const char * const name
;
70 static void cache_free(struct crec
*crecp
);
71 static void cache_unlink(struct crec
*crecp
);
72 static void cache_link(struct crec
*crecp
);
73 static void rehash(int size
);
74 static void cache_hash(struct crec
*crecp
);
81 bignames_left
= daemon
->cachesize
/10;
83 if (daemon
->cachesize
> 0)
85 crecp
= safe_malloc(daemon
->cachesize
*sizeof(struct crec
));
87 for (i
=0; i
< daemon
->cachesize
; i
++, crecp
++)
95 /* create initial hash table*/
96 rehash(daemon
->cachesize
);
99 /* In most cases, we create the hash table once here by calling this with (hash_table == NULL)
100 but if the hosts file(s) are big (some people have 50000 ad-block entries), the table
101 will be much too small, so the hosts reading code calls rehash every 1000 addresses, to
103 static void rehash(int size
)
105 struct crec
**new, **old
, *p
, *tmp
;
106 int i
, new_size
, old_size
;
108 /* hash_size is a power of two. */
109 for (new_size
= 64; new_size
< size
/10; new_size
= new_size
<< 1);
111 /* must succeed in getting first instance, failure later is non-fatal */
113 new = safe_malloc(new_size
* sizeof(struct crec
*));
114 else if (new_size
<= hash_size
|| !(new = whine_malloc(new_size
* sizeof(struct crec
*))))
117 for(i
= 0; i
< new_size
; i
++)
121 old_size
= hash_size
;
123 hash_size
= new_size
;
127 for (i
= 0; i
< old_size
; i
++)
128 for (p
= old
[i
]; p
; p
= tmp
)
137 static struct crec
**hash_bucket(char *name
)
139 unsigned int c
, val
= 017465; /* Barker code - minimum self-correlation in cyclic shift */
140 const unsigned char *mix_tab
= (const unsigned char*)typestr
;
142 while((c
= (unsigned char) *name
++))
144 /* don't use tolower and friends here - they may be messed up by LOCALE */
145 if (c
>= 'A' && c
<= 'Z')
147 val
= ((val
<< 7) | (val
>> (32 - 7))) + (mix_tab
[(val
+ c
) & 0x3F] ^ c
);
150 /* hash_size is a power of two */
151 return hash_table
+ ((val
^ (val
>> 16)) & (hash_size
- 1));
154 static void cache_hash(struct crec
*crecp
)
156 /* maintain an invariant that all entries with F_REVERSE set
157 are at the start of the hash-chain and all non-reverse
158 immortal entries are at the end of the hash-chain.
159 This allows reverse searches and garbage collection to be optimised */
161 struct crec
**up
= hash_bucket(cache_get_name(crecp
));
163 if (!(crecp
->flags
& F_REVERSE
))
165 while (*up
&& ((*up
)->flags
& F_REVERSE
))
166 up
= &((*up
)->hash_next
);
168 if (crecp
->flags
& F_IMMORTAL
)
169 while (*up
&& !((*up
)->flags
& F_IMMORTAL
))
170 up
= &((*up
)->hash_next
);
172 crecp
->hash_next
= *up
;
177 static void cache_blockdata_free(struct crec
*crecp
)
179 if (crecp
->flags
& F_DNSKEY
)
181 if (crecp
->flags
& F_DS
)
182 blockdata_free(crecp
->addr
.sig
.keydata
);
184 blockdata_free(crecp
->addr
.key
.keydata
);
186 else if (crecp
->flags
& F_DS
)
187 blockdata_free(crecp
->addr
.ds
.keydata
);
191 static void cache_free(struct crec
*crecp
)
193 crecp
->flags
&= ~F_FORWARD
;
194 crecp
->flags
&= ~F_REVERSE
;
195 crecp
->uid
= uid
++; /* invalidate CNAMES pointing to this. */
201 cache_tail
->next
= crecp
;
204 crecp
->prev
= cache_tail
;
208 /* retrieve big name for further use. */
209 if (crecp
->flags
& F_BIGNAME
)
211 crecp
->name
.bname
->next
= big_free
;
212 big_free
= crecp
->name
.bname
;
213 crecp
->flags
&= ~F_BIGNAME
;
217 cache_blockdata_free(crecp
);
221 /* insert a new cache entry at the head of the list (youngest entry) */
222 static void cache_link(struct crec
*crecp
)
224 if (cache_head
) /* check needed for init code */
225 cache_head
->prev
= crecp
;
226 crecp
->next
= cache_head
;
233 /* remove an arbitrary cache entry for promotion */
234 static void cache_unlink (struct crec
*crecp
)
237 crecp
->prev
->next
= crecp
->next
;
239 cache_head
= crecp
->next
;
242 crecp
->next
->prev
= crecp
->prev
;
244 cache_tail
= crecp
->prev
;
247 char *cache_get_name(struct crec
*crecp
)
249 if (crecp
->flags
& F_BIGNAME
)
250 return crecp
->name
.bname
->name
;
251 else if (crecp
->flags
& F_NAMEP
)
252 return crecp
->name
.namep
;
254 return crecp
->name
.sname
;
257 char *cache_get_cname_target(struct crec
*crecp
)
259 if (crecp
->addr
.cname
.uid
!= -1)
260 return cache_get_name(crecp
->addr
.cname
.target
.cache
);
262 return crecp
->addr
.cname
.target
.int_name
->name
;
267 struct crec
*cache_enumerate(int init
)
270 static struct crec
*cache
;
277 else if (cache
&& cache
->hash_next
)
278 cache
= cache
->hash_next
;
282 while (bucket
< hash_size
)
283 if ((cache
= hash_table
[bucket
++]))
290 static int is_outdated_cname_pointer(struct crec
*crecp
)
292 if (!(crecp
->flags
& F_CNAME
) || crecp
->addr
.cname
.uid
== -1)
295 /* NB. record may be reused as DS or DNSKEY, where uid is
296 overloaded for something completely different */
297 if (crecp
->addr
.cname
.target
.cache
&&
298 (crecp
->addr
.cname
.target
.cache
->flags
& (F_IPV4
| F_IPV6
| F_CNAME
)) &&
299 crecp
->addr
.cname
.uid
== crecp
->addr
.cname
.target
.cache
->uid
)
305 static int is_expired(time_t now
, struct crec
*crecp
)
307 if (crecp
->flags
& F_IMMORTAL
)
310 if (difftime(now
, crecp
->ttd
) < 0)
316 static int cache_scan_free(char *name
, struct all_addr
*addr
, time_t now
, unsigned short flags
)
318 /* Scan and remove old entries.
319 If (flags & F_FORWARD) then remove any forward entries for name and any expired
320 entries but only in the same hash bucket as name.
321 If (flags & F_REVERSE) then remove any reverse entries for addr and any expired
322 entries in the whole cache.
323 If (flags == 0) remove any expired entries in the whole cache.
325 In the flags & F_FORWARD case, the return code is valid, and returns zero if the
326 name exists in the cache as a HOSTS or DHCP entry (these are never deleted)
328 We take advantage of the fact that hash chains have stuff in the order <reverse>,<other>,<immortal>
329 so that when we hit an entry which isn't reverse and is immortal, we're done. */
331 struct crec
*crecp
, **up
;
333 if (flags
& F_FORWARD
)
335 for (up
= hash_bucket(name
), crecp
= *up
; crecp
; crecp
= crecp
->hash_next
)
337 if (is_expired(now
, crecp
) || is_outdated_cname_pointer(crecp
))
339 *up
= crecp
->hash_next
;
340 if (!(crecp
->flags
& (F_HOSTS
| F_DHCP
| F_CONFIG
)))
348 if ((crecp
->flags
& F_FORWARD
) && hostname_isequal(cache_get_name(crecp
), name
))
350 /* Don't delete DNSSEC in favour of a CNAME, they can co-exist */
351 if ((flags
& crecp
->flags
& (F_IPV4
| F_IPV6
)) ||
352 (((crecp
->flags
| flags
) & F_CNAME
) && !(crecp
->flags
& (F_DNSKEY
| F_DS
))))
354 if (crecp
->flags
& (F_HOSTS
| F_DHCP
| F_CONFIG
))
356 *up
= crecp
->hash_next
;
363 /* Deletion has to be class-sensitive for DS, DNSKEY, RRSIG, also
364 type-covered sensitive for RRSIG */
365 if ((flags
& (F_DNSKEY
| F_DS
)) &&
366 (flags
& (F_DNSKEY
| F_DS
)) == (crecp
->flags
& (F_DNSKEY
| F_DS
)) &&
367 crecp
->uid
== addr
->addr
.dnssec
.class &&
368 (!((flags
& (F_DS
| F_DNSKEY
)) == (F_DS
| F_DNSKEY
)) ||
369 crecp
->addr
.sig
.type_covered
== addr
->addr
.dnssec
.type
))
371 if (crecp
->flags
& F_CONFIG
)
373 *up
= crecp
->hash_next
;
380 up
= &crecp
->hash_next
;
387 int addrlen
= (flags
& F_IPV6
) ? IN6ADDRSZ
: INADDRSZ
;
389 int addrlen
= INADDRSZ
;
391 for (i
= 0; i
< hash_size
; i
++)
392 for (crecp
= hash_table
[i
], up
= &hash_table
[i
];
393 crecp
&& ((crecp
->flags
& F_REVERSE
) || !(crecp
->flags
& F_IMMORTAL
));
394 crecp
= crecp
->hash_next
)
395 if (is_expired(now
, crecp
))
397 *up
= crecp
->hash_next
;
398 if (!(crecp
->flags
& (F_HOSTS
| F_DHCP
| F_CONFIG
)))
404 else if (!(crecp
->flags
& (F_HOSTS
| F_DHCP
| F_CONFIG
)) &&
405 (flags
& crecp
->flags
& F_REVERSE
) &&
406 (flags
& crecp
->flags
& (F_IPV4
| F_IPV6
)) &&
407 memcmp(&crecp
->addr
.addr
, addr
, addrlen
) == 0)
409 *up
= crecp
->hash_next
;
414 up
= &crecp
->hash_next
;
420 /* Note: The normal calling sequence is
425 but an abort can cause the cache_end_insert to be missed
426 in which can the next cache_start_insert cleans things up. */
428 void cache_start_insert(void)
430 /* Free any entries which didn't get committed during the last
435 struct crec
*tmp
= new_chain
->next
;
436 cache_free(new_chain
);
443 struct crec
*cache_insert(char *name
, struct all_addr
*addr
,
444 time_t now
, unsigned long ttl
, unsigned short flags
)
447 union bigname
*big_name
= NULL
;
448 int freed_all
= flags
& F_REVERSE
;
451 /* Don't log DNSSEC records here, done elsewhere */
452 if (flags
& (F_IPV4
| F_IPV6
| F_CNAME
))
454 log_query(flags
| F_UPSTREAM
, name
, addr
, NULL
);
455 /* Don;t mess with TTL for DNSSEC records. */
456 if (daemon
->max_cache_ttl
!= 0 && daemon
->max_cache_ttl
< ttl
)
457 ttl
= daemon
->max_cache_ttl
;
460 /* if previous insertion failed give up now. */
464 /* First remove any expired entries and entries for the name/address we
465 are currently inserting. Fail if we attempt to delete a name from
466 /etc/hosts or DHCP. */
467 if (!cache_scan_free(name
, addr
, now
, flags
))
473 /* Now get a cache entry from the end of the LRU list */
475 if (!(new = cache_tail
)) /* no entries left - cache is too small, bail */
481 /* End of LRU list is still in use: if we didn't scan all the hash
482 chains for expired entries do that now. If we already tried that
483 then it's time to start spilling things. */
485 if (new->flags
& (F_FORWARD
| F_REVERSE
))
487 /* If free_avail set, we believe that an entry has been freed.
488 Bugs have been known to make this not true, resulting in
489 a tight loop here. If that happens, abandon the
490 insert. Once in this state, all inserts will probably fail. */
493 static int warned
= 0;
496 my_syslog(LOG_ERR
, _("Internal error in cache."));
505 struct all_addr free_addr
= new->addr
.addr
;;
508 /* For DNSSEC records, addr holds class and type_covered for RRSIG */
509 if (new->flags
& (F_DS
| F_DNSKEY
))
511 free_addr
.addr
.dnssec
.class = new->uid
;
512 if ((new->flags
& (F_DS
| F_DNSKEY
)) == (F_DS
| F_DNSKEY
))
513 free_addr
.addr
.dnssec
.type
= new->addr
.sig
.type_covered
;
517 free_avail
= 1; /* Must be free space now. */
518 cache_scan_free(cache_get_name(new), &free_addr
, now
, new->flags
);
523 cache_scan_free(NULL
, NULL
, now
, 0);
529 /* Check if we need to and can allocate extra memory for a long name.
530 If that fails, give up now, always succeed for DNSSEC records. */
531 if (name
&& (strlen(name
) > SMALLDNAME
-1))
536 big_free
= big_free
->next
;
538 else if ((bignames_left
== 0 && !(flags
& (F_DS
| F_DNSKEY
))) ||
539 !(big_name
= (union bigname
*)whine_malloc(sizeof(union bigname
))))
544 else if (bignames_left
!= 0)
549 /* Got the rest: finally grab entry. */
557 new->name
.bname
= big_name
;
558 new->flags
|= F_BIGNAME
;
562 strcpy(cache_get_name(new), name
);
564 *cache_get_name(new) = 0;
567 new->addr
.addr
= *addr
;
569 new->ttd
= now
+ (time_t)ttl
;
570 new->next
= new_chain
;
576 /* after end of insertion, commit the new entries */
577 void cache_end_insert(void)
584 struct crec
*tmp
= new_chain
->next
;
585 /* drop CNAMEs which didn't find a target. */
586 if (is_outdated_cname_pointer(new_chain
))
587 cache_free(new_chain
);
590 cache_hash(new_chain
);
591 cache_link(new_chain
);
599 struct crec
*cache_find_by_name(struct crec
*crecp
, char *name
, time_t now
, unsigned int prot
)
602 int no_rr
= prot
& F_NO_RR
;
606 if (crecp
) /* iterating */
610 /* first search, look for relevant entries and push to top of list
611 also free anything which has expired */
612 struct crec
*next
, **up
, **insert
= NULL
, **chainp
= &ans
;
613 unsigned short ins_flags
= 0;
615 for (up
= hash_bucket(name
), crecp
= *up
; crecp
; crecp
= next
)
617 next
= crecp
->hash_next
;
619 if (!is_expired(now
, crecp
) && !is_outdated_cname_pointer(crecp
))
621 if ((crecp
->flags
& F_FORWARD
) &&
623 ((crecp
->flags
& (F_DNSKEY
| F_DS
)) == (prot
& (F_DNSKEY
| F_DS
))) &&
625 (crecp
->flags
& prot
) &&
626 hostname_isequal(cache_get_name(crecp
), name
))
628 if (crecp
->flags
& (F_HOSTS
| F_DHCP
| F_CONFIG
))
631 chainp
= &crecp
->next
;
639 /* Move all but the first entry up the hash chain
640 this implements round-robin.
641 Make sure that re-ordering doesn't break the hash-chain
644 if (insert
&& (crecp
->flags
& (F_REVERSE
| F_IMMORTAL
)) == ins_flags
)
646 *up
= crecp
->hash_next
;
647 crecp
->hash_next
= *insert
;
649 insert
= &crecp
->hash_next
;
653 if (!insert
&& !no_rr
)
656 ins_flags
= crecp
->flags
& (F_REVERSE
| F_IMMORTAL
);
658 up
= &crecp
->hash_next
;
662 /* case : not expired, incorrect entry. */
663 up
= &crecp
->hash_next
;
667 /* expired entry, free it */
668 *up
= crecp
->hash_next
;
669 if (!(crecp
->flags
& (F_HOSTS
| F_DHCP
| F_CONFIG
)))
677 *chainp
= cache_head
;
681 (ans
->flags
& F_FORWARD
) &&
683 ((ans
->flags
& (F_DNSKEY
| F_DS
)) == (prot
& (F_DNSKEY
| F_DS
))) &&
685 (ans
->flags
& prot
) &&
686 hostname_isequal(cache_get_name(ans
), name
))
692 struct crec
*cache_find_by_addr(struct crec
*crecp
, struct all_addr
*addr
,
693 time_t now
, unsigned int prot
)
697 int addrlen
= (prot
== F_IPV6
) ? IN6ADDRSZ
: INADDRSZ
;
699 int addrlen
= INADDRSZ
;
702 if (crecp
) /* iterating */
706 /* first search, look for relevant entries and push to top of list
707 also free anything which has expired. All the reverse entries are at the
708 start of the hash chain, so we can give up when we find the first
711 struct crec
**up
, **chainp
= &ans
;
713 for (i
=0; i
<hash_size
; i
++)
714 for (crecp
= hash_table
[i
], up
= &hash_table
[i
];
715 crecp
&& (crecp
->flags
& F_REVERSE
);
716 crecp
= crecp
->hash_next
)
717 if (!is_expired(now
, crecp
))
719 if ((crecp
->flags
& prot
) &&
720 memcmp(&crecp
->addr
.addr
, addr
, addrlen
) == 0)
722 if (crecp
->flags
& (F_HOSTS
| F_DHCP
| F_CONFIG
))
725 chainp
= &crecp
->next
;
733 up
= &crecp
->hash_next
;
737 *up
= crecp
->hash_next
;
738 if (!(crecp
->flags
& (F_HOSTS
| F_DHCP
| F_CONFIG
)))
745 *chainp
= cache_head
;
749 (ans
->flags
& F_REVERSE
) &&
750 (ans
->flags
& prot
) &&
751 memcmp(&ans
->addr
.addr
, addr
, addrlen
) == 0)
757 static void add_hosts_cname(struct crec
*target
)
762 for (a
= daemon
->cnames
; a
; a
= a
->next
)
763 if (hostname_isequal(cache_get_name(target
), a
->target
) &&
764 (crec
= whine_malloc(sizeof(struct crec
))))
766 crec
->flags
= F_FORWARD
| F_IMMORTAL
| F_NAMEP
| F_CONFIG
| F_CNAME
;
767 crec
->name
.namep
= a
->alias
;
768 crec
->addr
.cname
.target
.cache
= target
;
769 crec
->addr
.cname
.uid
= target
->uid
;
771 add_hosts_cname(crec
); /* handle chains */
775 static void add_hosts_entry(struct crec
*cache
, struct all_addr
*addr
, int addrlen
,
776 int index
, struct crec
**rhash
, int hashsz
)
778 struct crec
*lookup
= cache_find_by_name(NULL
, cache_get_name(cache
), 0, cache
->flags
& (F_IPV4
| F_IPV6
));
779 int i
, nameexists
= 0;
782 /* Remove duplicates in hosts files. */
783 if (lookup
&& (lookup
->flags
& F_HOSTS
))
786 if (memcmp(&lookup
->addr
.addr
, addr
, addrlen
) == 0)
793 /* Ensure there is only one address -> name mapping (first one trumps)
794 We do this by steam here, The entries are kept in hash chains, linked
795 by ->next (which is unused at this point) held in hash buckets in
796 the array rhash, hashed on address. Note that rhash and the values
797 in ->next are only valid whilst reading hosts files: the buckets are
798 then freed, and the ->next pointer used for other things.
800 Only insert each unique address once into this hashing structure.
802 This complexity avoids O(n^2) divergent CPU use whilst reading
803 large (10000 entry) hosts files. */
806 for (j
= 0, i
= 0; i
< addrlen
; i
++)
807 j
= (j
*2 +((unsigned char *)addr
)[i
]) % hashsz
;
809 for (lookup
= rhash
[j
]; lookup
; lookup
= lookup
->next
)
810 if ((lookup
->flags
& cache
->flags
& (F_IPV4
| F_IPV6
)) &&
811 memcmp(&lookup
->addr
.addr
, addr
, addrlen
) == 0)
813 cache
->flags
&= ~F_REVERSE
;
817 /* maintain address hash chain, insert new unique address */
820 cache
->next
= rhash
[j
];
825 memcpy(&cache
->addr
.addr
, addr
, addrlen
);
828 /* don't need to do alias stuff for second and subsequent addresses. */
830 add_hosts_cname(cache
);
833 static int eatspace(FILE *f
)
839 if ((c
= getc(f
)) == '#')
840 while (c
!= '\n' && c
!= EOF
)
857 static int gettok(FILE *f
, char *token
)
863 if ((c
= getc(f
)) == EOF
)
864 return (count
== 0) ? EOF
: 1;
866 if (isspace(c
) || c
== '#')
872 if (count
< (MAXDNAME
- 1))
880 static int read_hostsfile(char *filename
, int index
, int cache_size
, struct crec
**rhash
, int hashsz
)
882 FILE *f
= fopen(filename
, "r");
883 char *token
= daemon
->namebuff
, *domain_suffix
= NULL
;
884 int addr_count
= 0, name_count
= cache_size
, lineno
= 0;
885 unsigned short flags
= 0;
886 struct all_addr addr
;
887 int atnl
, addrlen
= 0;
891 my_syslog(LOG_ERR
, _("failed to load names from %s: %s"), filename
, strerror(errno
));
897 while ((atnl
= gettok(f
, token
)) != EOF
)
901 if (inet_pton(AF_INET
, token
, &addr
) > 0)
903 flags
= F_HOSTS
| F_IMMORTAL
| F_FORWARD
| F_REVERSE
| F_IPV4
;
905 domain_suffix
= get_domain(addr
.addr
.addr4
);
908 else if (inet_pton(AF_INET6
, token
, &addr
) > 0)
910 flags
= F_HOSTS
| F_IMMORTAL
| F_FORWARD
| F_REVERSE
| F_IPV6
;
912 domain_suffix
= get_domain6(&addr
.addr
.addr6
);
917 my_syslog(LOG_ERR
, _("bad address at %s line %d"), filename
, lineno
);
919 atnl
= gettok(f
, token
);
925 /* rehash every 1000 names. */
926 if ((name_count
- cache_size
) > 1000)
929 cache_size
= name_count
;
938 if ((atnl
= gettok(f
, token
)) == EOF
)
941 fqdn
= !!strchr(token
, '.');
943 if ((canon
= canonicalise(token
, &nomem
)))
945 /* If set, add a version of the name with a default domain appended */
946 if (option_bool(OPT_EXPAND
) && domain_suffix
&& !fqdn
&&
947 (cache
= whine_malloc(sizeof(struct crec
) +
948 strlen(canon
)+2+strlen(domain_suffix
)-SMALLDNAME
)))
950 strcpy(cache
->name
.sname
, canon
);
951 strcat(cache
->name
.sname
, ".");
952 strcat(cache
->name
.sname
, domain_suffix
);
953 cache
->flags
= flags
;
954 add_hosts_entry(cache
, &addr
, addrlen
, index
, rhash
, hashsz
);
957 if ((cache
= whine_malloc(sizeof(struct crec
) + strlen(canon
)+1-SMALLDNAME
)))
959 strcpy(cache
->name
.sname
, canon
);
960 cache
->flags
= flags
;
961 add_hosts_entry(cache
, &addr
, addrlen
, index
, rhash
, hashsz
);
968 my_syslog(LOG_ERR
, _("bad name at %s line %d"), filename
, lineno
);
975 my_syslog(LOG_INFO
, _("read %s - %d addresses"), filename
, addr_count
);
980 void cache_reload(void)
982 struct crec
*cache
, **up
, *tmp
;
983 int revhashsz
, i
, total_size
= daemon
->cachesize
;
984 struct hostsfile
*ah
;
985 struct host_record
*hr
;
986 struct name_list
*nl
;
988 struct interface_name
*intr
;
990 struct ds_config
*ds
;
993 cache_inserted
= cache_live_freed
= 0;
995 for (i
=0; i
<hash_size
; i
++)
996 for (cache
= hash_table
[i
], up
= &hash_table
[i
]; cache
; cache
= tmp
)
999 cache_blockdata_free(cache
);
1001 tmp
= cache
->hash_next
;
1002 if (cache
->flags
& (F_HOSTS
| F_CONFIG
))
1004 *up
= cache
->hash_next
;
1007 else if (!(cache
->flags
& F_DHCP
))
1009 *up
= cache
->hash_next
;
1010 if (cache
->flags
& F_BIGNAME
)
1012 cache
->name
.bname
->next
= big_free
;
1013 big_free
= cache
->name
.bname
;
1018 up
= &cache
->hash_next
;
1021 /* Add CNAMEs to interface_names to the cache */
1022 for (a
= daemon
->cnames
; a
; a
= a
->next
)
1023 for (intr
= daemon
->int_names
; intr
; intr
= intr
->next
)
1024 if (hostname_isequal(a
->target
, intr
->name
) &&
1025 ((cache
= whine_malloc(sizeof(struct crec
)))))
1027 cache
->flags
= F_FORWARD
| F_NAMEP
| F_CNAME
| F_IMMORTAL
| F_CONFIG
;
1028 cache
->name
.namep
= a
->alias
;
1029 cache
->addr
.cname
.target
.int_name
= intr
;
1030 cache
->addr
.cname
.uid
= -1;
1032 add_hosts_cname(cache
); /* handle chains */
1036 for (ds
= daemon
->ds
; ds
; ds
= ds
->next
)
1037 if ((cache
= whine_malloc(sizeof(struct crec
))) &&
1038 (cache
->addr
.ds
.keydata
= blockdata_alloc(ds
->digest
, ds
->digestlen
)))
1040 cache
->flags
= F_FORWARD
| F_IMMORTAL
| F_DS
| F_CONFIG
| F_NAMEP
;
1041 cache
->name
.namep
= ds
->name
;
1042 cache
->addr
.ds
.keylen
= ds
->digestlen
;
1043 cache
->addr
.ds
.algo
= ds
->algo
;
1044 cache
->addr
.ds
.keytag
= ds
->keytag
;
1045 cache
->addr
.ds
.digest
= ds
->digest_type
;
1046 cache
->uid
= ds
->class;
1051 /* borrow the packet buffer for a temporary by-address hash */
1052 memset(daemon
->packet
, 0, daemon
->packet_buff_sz
);
1053 revhashsz
= daemon
->packet_buff_sz
/ sizeof(struct crec
*);
1054 /* we overwrote the buffer... */
1055 daemon
->srv_save
= NULL
;
1057 /* Do host_records in config. */
1058 for (hr
= daemon
->host_records
; hr
; hr
= hr
->next
)
1059 for (nl
= hr
->names
; nl
; nl
= nl
->next
)
1061 if (hr
->addr
.s_addr
!= 0 &&
1062 (cache
= whine_malloc(sizeof(struct crec
))))
1064 cache
->name
.namep
= nl
->name
;
1065 cache
->flags
= F_HOSTS
| F_IMMORTAL
| F_FORWARD
| F_REVERSE
| F_IPV4
| F_NAMEP
| F_CONFIG
;
1066 add_hosts_entry(cache
, (struct all_addr
*)&hr
->addr
, INADDRSZ
, 0, (struct crec
**)daemon
->packet
, revhashsz
);
1069 if (!IN6_IS_ADDR_UNSPECIFIED(&hr
->addr6
) &&
1070 (cache
= whine_malloc(sizeof(struct crec
))))
1072 cache
->name
.namep
= nl
->name
;
1073 cache
->flags
= F_HOSTS
| F_IMMORTAL
| F_FORWARD
| F_REVERSE
| F_IPV6
| F_NAMEP
| F_CONFIG
;
1074 add_hosts_entry(cache
, (struct all_addr
*)&hr
->addr6
, IN6ADDRSZ
, 0, (struct crec
**)daemon
->packet
, revhashsz
);
1079 if (option_bool(OPT_NO_HOSTS
) && !daemon
->addn_hosts
)
1081 if (daemon
->cachesize
> 0)
1082 my_syslog(LOG_INFO
, _("cleared cache"));
1086 if (!option_bool(OPT_NO_HOSTS
))
1087 total_size
= read_hostsfile(HOSTSFILE
, 0, total_size
, (struct crec
**)daemon
->packet
, revhashsz
);
1089 daemon
->addn_hosts
= expand_filelist(daemon
->addn_hosts
);
1090 for (ah
= daemon
->addn_hosts
; ah
; ah
= ah
->next
)
1091 if (!(ah
->flags
& AH_INACTIVE
))
1092 total_size
= read_hostsfile(ah
->fname
, ah
->index
, total_size
, (struct crec
**)daemon
->packet
, revhashsz
);
1096 struct in_addr
a_record_from_hosts(char *name
, time_t now
)
1098 struct crec
*crecp
= NULL
;
1101 while ((crecp
= cache_find_by_name(crecp
, name
, now
, F_IPV4
)))
1102 if (crecp
->flags
& F_HOSTS
)
1103 return *(struct in_addr
*)&crecp
->addr
;
1105 my_syslog(MS_DHCP
| LOG_WARNING
, _("No IPv4 address found for %s"), name
);
1111 void cache_unhash_dhcp(void)
1113 struct crec
*cache
, **up
;
1116 for (i
=0; i
<hash_size
; i
++)
1117 for (cache
= hash_table
[i
], up
= &hash_table
[i
]; cache
; cache
= cache
->hash_next
)
1118 if (cache
->flags
& F_DHCP
)
1120 *up
= cache
->hash_next
;
1121 cache
->next
= dhcp_spare
;
1125 up
= &cache
->hash_next
;
1128 static void add_dhcp_cname(struct crec
*target
, time_t ttd
)
1130 struct crec
*aliasc
;
1133 for (a
= daemon
->cnames
; a
; a
= a
->next
)
1134 if (hostname_isequal(cache_get_name(target
), a
->target
))
1136 if ((aliasc
= dhcp_spare
))
1137 dhcp_spare
= dhcp_spare
->next
;
1138 else /* need new one */
1139 aliasc
= whine_malloc(sizeof(struct crec
));
1143 aliasc
->flags
= F_FORWARD
| F_NAMEP
| F_DHCP
| F_CNAME
| F_CONFIG
;
1145 aliasc
->flags
|= F_IMMORTAL
;
1148 aliasc
->name
.namep
= a
->alias
;
1149 aliasc
->addr
.cname
.target
.cache
= target
;
1150 aliasc
->addr
.cname
.uid
= target
->uid
;
1152 add_dhcp_cname(aliasc
, ttd
);
1157 void cache_add_dhcp_entry(char *host_name
, int prot
,
1158 struct all_addr
*host_address
, time_t ttd
)
1160 struct crec
*crec
= NULL
, *fail_crec
= NULL
;
1161 unsigned short flags
= F_IPV4
;
1163 size_t addrlen
= sizeof(struct in_addr
);
1166 if (prot
== AF_INET6
)
1169 addrlen
= sizeof(struct in6_addr
);
1173 inet_ntop(prot
, host_address
, daemon
->addrbuff
, ADDRSTRLEN
);
1175 while ((crec
= cache_find_by_name(crec
, host_name
, 0, flags
| F_CNAME
)))
1177 /* check all addresses associated with name */
1178 if (crec
->flags
& (F_HOSTS
| F_CONFIG
))
1180 if (crec
->flags
& F_CNAME
)
1181 my_syslog(MS_DHCP
| LOG_WARNING
,
1182 _("%s is a CNAME, not giving it to the DHCP lease of %s"),
1183 host_name
, daemon
->addrbuff
);
1184 else if (memcmp(&crec
->addr
.addr
, host_address
, addrlen
) == 0)
1189 else if (!(crec
->flags
& F_DHCP
))
1191 cache_scan_free(host_name
, NULL
, 0, crec
->flags
& (flags
| F_CNAME
| F_FORWARD
));
1192 /* scan_free deletes all addresses associated with name */
1197 /* if in hosts, don't need DHCP record */
1201 /* Name in hosts, address doesn't match */
1204 inet_ntop(prot
, &fail_crec
->addr
.addr
, daemon
->namebuff
, MAXDNAME
);
1205 my_syslog(MS_DHCP
| LOG_WARNING
,
1206 _("not giving name %s to the DHCP lease of %s because "
1207 "the name exists in %s with address %s"),
1208 host_name
, daemon
->addrbuff
,
1209 record_source(fail_crec
->uid
), daemon
->namebuff
);
1213 if ((crec
= cache_find_by_addr(NULL
, (struct all_addr
*)host_address
, 0, flags
)))
1215 if (crec
->flags
& F_NEG
)
1218 cache_scan_free(NULL
, (struct all_addr
*)host_address
, 0, flags
);
1224 if ((crec
= dhcp_spare
))
1225 dhcp_spare
= dhcp_spare
->next
;
1226 else /* need new one */
1227 crec
= whine_malloc(sizeof(struct crec
));
1229 if (crec
) /* malloc may fail */
1231 crec
->flags
= flags
| F_NAMEP
| F_DHCP
| F_FORWARD
;
1233 crec
->flags
|= F_IMMORTAL
;
1236 crec
->addr
.addr
= *host_address
;
1237 crec
->name
.namep
= host_name
;
1241 add_dhcp_cname(crec
, ttd
);
1247 void dump_cache(time_t now
)
1249 struct server
*serv
, *serv1
;
1252 my_syslog(LOG_INFO
, _("time %lu"), (unsigned long)now
);
1253 my_syslog(LOG_INFO
, _("cache size %d, %d/%d cache insertions re-used unexpired cache entries."),
1254 daemon
->cachesize
, cache_live_freed
, cache_inserted
);
1255 my_syslog(LOG_INFO
, _("queries forwarded %u, queries answered locally %u"),
1256 daemon
->queries_forwarded
, daemon
->local_answer
);
1258 my_syslog(LOG_INFO
, _("queries for authoritative zones %u"), daemon
->auth_answer
);
1264 /* sum counts from different records for same server */
1265 for (serv
= daemon
->servers
; serv
; serv
= serv
->next
)
1266 serv
->flags
&= ~SERV_COUNTED
;
1268 for (serv
= daemon
->servers
; serv
; serv
= serv
->next
)
1270 (SERV_NO_ADDR
| SERV_LITERAL_ADDRESS
| SERV_COUNTED
| SERV_USE_RESOLV
| SERV_NO_REBIND
)))
1273 unsigned int queries
= 0, failed_queries
= 0;
1274 for (serv1
= serv
; serv1
; serv1
= serv1
->next
)
1275 if (!(serv1
->flags
&
1276 (SERV_NO_ADDR
| SERV_LITERAL_ADDRESS
| SERV_COUNTED
| SERV_USE_RESOLV
| SERV_NO_REBIND
)) &&
1277 sockaddr_isequal(&serv
->addr
, &serv1
->addr
))
1279 serv1
->flags
|= SERV_COUNTED
;
1280 queries
+= serv1
->queries
;
1281 failed_queries
+= serv1
->failed_queries
;
1283 port
= prettyprint_addr(&serv
->addr
, daemon
->addrbuff
);
1284 my_syslog(LOG_INFO
, _("server %s#%d: queries sent %u, retried or failed %u"), daemon
->addrbuff
, port
, queries
, failed_queries
);
1287 if (option_bool(OPT_DEBUG
) || option_bool(OPT_LOG
))
1289 struct crec
*cache
;
1291 my_syslog(LOG_INFO
, "Host Address Flags Expires");
1293 for (i
=0; i
<hash_size
; i
++)
1294 for (cache
= hash_table
[i
]; cache
; cache
= cache
->hash_next
)
1296 char *a
= daemon
->addrbuff
, *p
= daemon
->namebuff
, *n
= cache_get_name(cache
);
1298 if (strlen(n
) == 0 && !(cache
->flags
& F_REVERSE
))
1300 p
+= sprintf(p
, "%-40.40s ", n
);
1301 if ((cache
->flags
& F_CNAME
) && !is_outdated_cname_pointer(cache
))
1302 a
= cache_get_cname_target(cache
);
1304 else if (cache
->flags
& F_DS
)
1306 if (cache
->flags
& F_DNSKEY
)
1309 a
= daemon
->addrbuff
;
1310 sprintf(a
, "%5u %3u %s", cache
->addr
.sig
.keytag
,
1311 cache
->addr
.sig
.algo
, querystr("", cache
->addr
.sig
.type_covered
));
1315 a
= daemon
->addrbuff
;
1316 sprintf(a
, "%5u %3u %3u", cache
->addr
.ds
.keytag
,
1317 cache
->addr
.ds
.algo
, cache
->addr
.ds
.digest
);
1320 else if (cache
->flags
& F_DNSKEY
)
1322 a
= daemon
->addrbuff
;
1323 sprintf(a
, "%5u %3u %3u", cache
->addr
.key
.keytag
,
1324 cache
->addr
.key
.algo
, cache
->addr
.key
.flags
);
1327 else if (!(cache
->flags
& F_NEG
) || !(cache
->flags
& F_FORWARD
))
1329 a
= daemon
->addrbuff
;
1330 if (cache
->flags
& F_IPV4
)
1331 inet_ntop(AF_INET
, &cache
->addr
.addr
, a
, ADDRSTRLEN
);
1333 else if (cache
->flags
& F_IPV6
)
1334 inet_ntop(AF_INET6
, &cache
->addr
.addr
, a
, ADDRSTRLEN
);
1338 if (cache
->flags
& F_IPV4
)
1340 else if (cache
->flags
& F_IPV6
)
1342 else if (cache
->flags
& F_CNAME
)
1345 else if ((cache
->flags
& (F_DS
| F_DNSKEY
)) == (F_DS
| F_DNSKEY
))
1346 t
= "G"; /* DNSKEY and DS set -> RRISG */
1347 else if (cache
->flags
& F_DS
)
1349 else if (cache
->flags
& F_DNSKEY
)
1352 p
+= sprintf(p
, "%-30.30s %s%s%s%s%s%s%s%s%s ", a
, t
,
1353 cache
->flags
& F_FORWARD
? "F" : " ",
1354 cache
->flags
& F_REVERSE
? "R" : " ",
1355 cache
->flags
& F_IMMORTAL
? "I" : " ",
1356 cache
->flags
& F_DHCP
? "D" : " ",
1357 cache
->flags
& F_NEG
? "N" : " ",
1358 cache
->flags
& F_NXDOMAIN
? "X" : " ",
1359 cache
->flags
& F_HOSTS
? "H" : " ",
1360 cache
->flags
& F_DNSSECOK
? "V" : " ");
1361 #ifdef HAVE_BROKEN_RTC
1362 p
+= sprintf(p
, "%lu", cache
->flags
& F_IMMORTAL
? 0: (unsigned long)(cache
->ttd
- now
));
1364 p
+= sprintf(p
, "%s", cache
->flags
& F_IMMORTAL
? "\n" : ctime(&(cache
->ttd
)));
1365 /* ctime includes trailing \n - eat it */
1368 my_syslog(LOG_INFO
, daemon
->namebuff
);
1373 char *record_source(int index
)
1375 struct hostsfile
*ah
;
1380 for (ah
= daemon
->addn_hosts
; ah
; ah
= ah
->next
)
1381 if (ah
->index
== index
)
1387 char *querystr(char *desc
, unsigned short type
)
1390 int len
= 10; /* strlen("type=xxxxx") */
1391 const char *types
= NULL
;
1392 static char *buff
= NULL
;
1393 static int bufflen
= 0;
1395 for (i
= 0; i
< (sizeof(typestr
)/sizeof(typestr
[0])); i
++)
1396 if (typestr
[i
].type
== type
)
1398 types
= typestr
[i
].name
;
1399 len
= strlen(types
);
1403 len
+= 3; /* braces, terminator */
1404 len
+= strlen(desc
);
1406 if (!buff
|| bufflen
< len
)
1413 buff
= whine_malloc(len
);
1420 sprintf(buff
, "%s[%s]", desc
, types
);
1422 sprintf(buff
, "%s[type=%d]", desc
, type
);
1425 return buff
? buff
: "";
1428 void log_query(unsigned int flags
, char *name
, struct all_addr
*addr
, char *arg
)
1430 char *source
, *dest
= daemon
->addrbuff
;
1433 if (!option_bool(OPT_LOG
))
1438 if (flags
& F_KEYTAG
)
1439 sprintf(daemon
->addrbuff
, arg
, addr
->addr
.keytag
);
1443 inet_ntop(flags
& F_IPV4
? AF_INET
: AF_INET6
,
1444 addr
, daemon
->addrbuff
, ADDRSTRLEN
);
1446 strncpy(daemon
->addrbuff
, inet_ntoa(addr
->addr
.addr4
), ADDRSTRLEN
);
1453 if (flags
& F_REVERSE
)
1456 name
= daemon
->addrbuff
;
1461 if (flags
& F_NXDOMAIN
)
1466 dest
= "NODATA-IPv4";
1467 else if (flags
& F_IPV6
)
1468 dest
= "NODATA-IPv6";
1473 else if (flags
& F_CNAME
)
1475 else if (flags
& F_RRNAME
)
1478 if (flags
& F_CONFIG
)
1480 else if (flags
& F_DHCP
)
1482 else if (flags
& F_HOSTS
)
1484 else if (flags
& F_UPSTREAM
)
1486 else if (flags
& F_SECSTAT
)
1487 source
= "validation";
1488 else if (flags
& F_AUTH
)
1490 else if (flags
& F_SERVER
)
1492 source
= "forwarded";
1495 else if (flags
& F_QUERY
)
1500 else if (flags
& F_DNSSEC
)
1508 if (strlen(name
) == 0)
1511 my_syslog(LOG_INFO
, "%s %s %s %s", source
, name
, verb
, dest
);