]>
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
;
68 static void cache_free(struct crec
*crecp
);
69 static void cache_unlink(struct crec
*crecp
);
70 static void cache_link(struct crec
*crecp
);
71 static void rehash(int size
);
72 static void cache_hash(struct crec
*crecp
);
79 bignames_left
= daemon
->cachesize
/10;
81 if (daemon
->cachesize
> 0)
83 crecp
= safe_malloc(daemon
->cachesize
*sizeof(struct crec
));
85 for (i
=0; i
< daemon
->cachesize
; i
++, crecp
++)
93 /* create initial hash table*/
94 rehash(daemon
->cachesize
);
97 /* In most cases, we create the hash table once here by calling this with (hash_table == NULL)
98 but if the hosts file(s) are big (some people have 50000 ad-block entries), the table
99 will be much too small, so the hosts reading code calls rehash every 1000 addresses, to
101 static void rehash(int size
)
103 struct crec
**new, **old
, *p
, *tmp
;
104 int i
, new_size
, old_size
;
106 /* hash_size is a power of two. */
107 for (new_size
= 64; new_size
< size
/10; new_size
= new_size
<< 1);
109 /* must succeed in getting first instance, failure later is non-fatal */
111 new = safe_malloc(new_size
* sizeof(struct crec
*));
112 else if (new_size
<= hash_size
|| !(new = whine_malloc(new_size
* sizeof(struct crec
*))))
115 for(i
= 0; i
< new_size
; i
++)
119 old_size
= hash_size
;
121 hash_size
= new_size
;
125 for (i
= 0; i
< old_size
; i
++)
126 for (p
= old
[i
]; p
; p
= tmp
)
135 static struct crec
**hash_bucket(char *name
)
137 unsigned int c
, val
= 017465; /* Barker code - minimum self-correlation in cyclic shift */
138 const unsigned char *mix_tab
= (const unsigned char*)typestr
;
140 while((c
= (unsigned char) *name
++))
142 /* don't use tolower and friends here - they may be messed up by LOCALE */
143 if (c
>= 'A' && c
<= 'Z')
145 val
= ((val
<< 7) | (val
>> (32 - 7))) + (mix_tab
[(val
+ c
) & 0x3F] ^ c
);
148 /* hash_size is a power of two */
149 return hash_table
+ ((val
^ (val
>> 16)) & (hash_size
- 1));
152 static void cache_hash(struct crec
*crecp
)
154 /* maintain an invariant that all entries with F_REVERSE set
155 are at the start of the hash-chain and all non-reverse
156 immortal entries are at the end of the hash-chain.
157 This allows reverse searches and garbage collection to be optimised */
159 struct crec
**up
= hash_bucket(cache_get_name(crecp
));
161 if (!(crecp
->flags
& F_REVERSE
))
163 while (*up
&& ((*up
)->flags
& F_REVERSE
))
164 up
= &((*up
)->hash_next
);
166 if (crecp
->flags
& F_IMMORTAL
)
167 while (*up
&& !((*up
)->flags
& F_IMMORTAL
))
168 up
= &((*up
)->hash_next
);
170 crecp
->hash_next
= *up
;
174 static void cache_free(struct crec
*crecp
)
176 crecp
->flags
&= ~F_FORWARD
;
177 crecp
->flags
&= ~F_REVERSE
;
178 crecp
->uid
= uid
++; /* invalidate CNAMES pointing to this. */
184 cache_tail
->next
= crecp
;
187 crecp
->prev
= cache_tail
;
191 /* retrieve big name for further use. */
192 if (crecp
->flags
& F_BIGNAME
)
194 crecp
->name
.bname
->next
= big_free
;
195 big_free
= crecp
->name
.bname
;
196 crecp
->flags
&= ~F_BIGNAME
;
199 else if (crecp
->flags
& (F_DNSKEY
| F_DS
))
200 blockdata_free(crecp
->addr
.key
.keydata
);
204 /* insert a new cache entry at the head of the list (youngest entry) */
205 static void cache_link(struct crec
*crecp
)
207 if (cache_head
) /* check needed for init code */
208 cache_head
->prev
= crecp
;
209 crecp
->next
= cache_head
;
216 /* remove an arbitrary cache entry for promotion */
217 static void cache_unlink (struct crec
*crecp
)
220 crecp
->prev
->next
= crecp
->next
;
222 cache_head
= crecp
->next
;
225 crecp
->next
->prev
= crecp
->prev
;
227 cache_tail
= crecp
->prev
;
230 char *cache_get_name(struct crec
*crecp
)
232 if (crecp
->flags
& F_BIGNAME
)
233 return crecp
->name
.bname
->name
;
234 else if (crecp
->flags
& F_NAMEP
)
235 return crecp
->name
.namep
;
237 return crecp
->name
.sname
;
240 char *cache_get_cname_target(struct crec
*crecp
)
242 if (crecp
->addr
.cname
.uid
!= -1)
243 return cache_get_name(crecp
->addr
.cname
.target
.cache
);
245 return crecp
->addr
.cname
.target
.int_name
->name
;
250 struct crec
*cache_enumerate(int init
)
253 static struct crec
*cache
;
260 else if (cache
&& cache
->hash_next
)
261 cache
= cache
->hash_next
;
265 while (bucket
< hash_size
)
266 if ((cache
= hash_table
[bucket
++]))
273 static int is_outdated_cname_pointer(struct crec
*crecp
)
275 if (!(crecp
->flags
& F_CNAME
) || crecp
->addr
.cname
.uid
== -1)
278 /* NB. record may be reused as DS or DNSKEY, where uid is
279 overloaded for something completely different */
280 if (crecp
->addr
.cname
.target
.cache
&&
281 (crecp
->addr
.cname
.target
.cache
->flags
& (F_IPV4
| F_IPV6
| F_CNAME
)) &&
282 crecp
->addr
.cname
.uid
== crecp
->addr
.cname
.target
.cache
->uid
)
288 static int is_expired(time_t now
, struct crec
*crecp
)
290 if (crecp
->flags
& F_IMMORTAL
)
293 if (difftime(now
, crecp
->ttd
) < 0)
299 static int cache_scan_free(char *name
, struct all_addr
*addr
, time_t now
, unsigned short flags
)
301 /* Scan and remove old entries.
302 If (flags & F_FORWARD) then remove any forward entries for name and any expired
303 entries but only in the same hash bucket as name.
304 If (flags & F_REVERSE) then remove any reverse entries for addr and any expired
305 entries in the whole cache.
306 If (flags == 0) remove any expired entries in the whole cache.
308 In the flags & F_FORWARD case, the return code is valid, and returns zero if the
309 name exists in the cache as a HOSTS or DHCP entry (these are never deleted)
311 We take advantage of the fact that hash chains have stuff in the order <reverse>,<other>,<immortal>
312 so that when we hit an entry which isn't reverse and is immortal, we're done. */
314 struct crec
*crecp
, **up
;
316 if (flags
& F_FORWARD
)
318 for (up
= hash_bucket(name
), crecp
= *up
; crecp
; crecp
= crecp
->hash_next
)
319 if (is_expired(now
, crecp
) || is_outdated_cname_pointer(crecp
))
321 *up
= crecp
->hash_next
;
322 if (!(crecp
->flags
& (F_HOSTS
| F_DHCP
| F_CONFIG
)))
328 else if ((crecp
->flags
& F_FORWARD
) &&
329 ((flags
& crecp
->flags
& F_TYPE
) || ((crecp
->flags
| flags
) & F_CNAME
)) &&
330 hostname_isequal(cache_get_name(crecp
), name
))
332 if (crecp
->flags
& (F_HOSTS
| F_DHCP
| F_CONFIG
))
334 *up
= crecp
->hash_next
;
339 up
= &crecp
->hash_next
;
345 int addrlen
= (flags
& F_IPV6
) ? IN6ADDRSZ
: INADDRSZ
;
347 int addrlen
= INADDRSZ
;
349 for (i
= 0; i
< hash_size
; i
++)
350 for (crecp
= hash_table
[i
], up
= &hash_table
[i
];
351 crecp
&& ((crecp
->flags
& F_REVERSE
) || !(crecp
->flags
& F_IMMORTAL
));
352 crecp
= crecp
->hash_next
)
353 if (is_expired(now
, crecp
))
355 *up
= crecp
->hash_next
;
356 if (!(crecp
->flags
& (F_HOSTS
| F_DHCP
| F_CONFIG
)))
362 else if (!(crecp
->flags
& (F_HOSTS
| F_DHCP
| F_CONFIG
)) &&
363 (flags
& crecp
->flags
& F_REVERSE
) &&
364 (flags
& crecp
->flags
& (F_IPV4
| F_IPV6
)) &&
365 memcmp(&crecp
->addr
.addr
, addr
, addrlen
) == 0)
367 *up
= crecp
->hash_next
;
372 up
= &crecp
->hash_next
;
378 /* Note: The normal calling sequence is
383 but an abort can cause the cache_end_insert to be missed
384 in which can the next cache_start_insert cleans things up. */
386 void cache_start_insert(void)
388 /* Free any entries which didn't get committed during the last
393 struct crec
*tmp
= new_chain
->next
;
394 cache_free(new_chain
);
401 struct crec
*cache_insert(char *name
, struct all_addr
*addr
,
402 time_t now
, unsigned long ttl
, unsigned short flags
)
405 union bigname
*big_name
= NULL
;
406 int freed_all
= flags
& F_REVERSE
;
409 if (daemon
->max_cache_ttl
!= 0 && daemon
->max_cache_ttl
< ttl
)
410 ttl
= daemon
->max_cache_ttl
;
413 if (flags
& (F_IPV4
| F_IPV6
))
414 log_query(flags
| F_UPSTREAM
, name
, addr
, NULL
);
416 /* if previous insertion failed give up now. */
420 /* First remove any expired entries and entries for the name/address we
421 are currently inserting. Fail is we attempt to delete a name from
422 /etc/hosts or DHCP. */
423 if (!cache_scan_free(name
, addr
, now
, flags
))
429 /* Now get a cache entry from the end of the LRU list */
431 if (!(new = cache_tail
)) /* no entries left - cache is too small, bail */
437 /* End of LRU list is still in use: if we didn't scan all the hash
438 chains for expired entries do that now. If we already tried that
439 then it's time to start spilling things. */
441 if (new->flags
& (F_FORWARD
| F_REVERSE
))
443 /* If free_avail set, we believe that an entry has been freed.
444 Bugs have been known to make this not true, resulting in
445 a tight loop here. If that happens, abandon the
446 insert. Once in this state, all inserts will probably fail. */
455 free_avail
= 1; /* Must be free space now. */
456 cache_scan_free(cache_get_name(new), &new->addr
.addr
, now
, new->flags
);
461 cache_scan_free(NULL
, NULL
, now
, 0);
467 /* Check if we need to and can allocate extra memory for a long name.
468 If that fails, give up now. */
469 if (name
&& (strlen(name
) > SMALLDNAME
-1))
474 big_free
= big_free
->next
;
476 else if (!bignames_left
||
477 !(big_name
= (union bigname
*)whine_malloc(sizeof(union bigname
))))
487 /* Got the rest: finally grab entry. */
495 new->name
.bname
= big_name
;
496 new->flags
|= F_BIGNAME
;
500 strcpy(cache_get_name(new), name
);
502 *cache_get_name(new) = 0;
505 new->addr
.addr
= *addr
;
507 new->ttd
= now
+ (time_t)ttl
;
508 new->next
= new_chain
;
514 /* after end of insertion, commit the new entries */
515 void cache_end_insert(void)
522 struct crec
*tmp
= new_chain
->next
;
523 /* drop CNAMEs which didn't find a target. */
524 if (is_outdated_cname_pointer(new_chain
))
525 cache_free(new_chain
);
528 cache_hash(new_chain
);
529 cache_link(new_chain
);
537 struct crec
*cache_find_by_name(struct crec
*crecp
, char *name
, time_t now
, unsigned short prot
)
541 if (crecp
) /* iterating */
545 /* first search, look for relevant entries and push to top of list
546 also free anything which has expired */
547 struct crec
*next
, **up
, **insert
= NULL
, **chainp
= &ans
;
548 unsigned short ins_flags
= 0;
550 for (up
= hash_bucket(name
), crecp
= *up
; crecp
; crecp
= next
)
552 next
= crecp
->hash_next
;
554 if (!is_expired(now
, crecp
) && !is_outdated_cname_pointer(crecp
))
556 if ((crecp
->flags
& F_FORWARD
) &&
557 (crecp
->flags
& prot
) &&
558 hostname_isequal(cache_get_name(crecp
), name
))
560 if (crecp
->flags
& (F_HOSTS
| F_DHCP
| F_CONFIG
))
563 chainp
= &crecp
->next
;
571 /* Move all but the first entry up the hash chain
572 this implements round-robin.
573 Make sure that re-ordering doesn't break the hash-chain
576 if (insert
&& (crecp
->flags
& (F_REVERSE
| F_IMMORTAL
)) == ins_flags
)
578 *up
= crecp
->hash_next
;
579 crecp
->hash_next
= *insert
;
581 insert
= &crecp
->hash_next
;
588 ins_flags
= crecp
->flags
& (F_REVERSE
| F_IMMORTAL
);
590 up
= &crecp
->hash_next
;
594 /* case : not expired, incorrect entry. */
595 up
= &crecp
->hash_next
;
599 /* expired entry, free it */
600 *up
= crecp
->hash_next
;
601 if (!(crecp
->flags
& (F_HOSTS
| F_DHCP
| F_CONFIG
)))
609 *chainp
= cache_head
;
613 (ans
->flags
& F_FORWARD
) &&
614 (ans
->flags
& prot
) &&
615 hostname_isequal(cache_get_name(ans
), name
))
621 struct crec
*cache_find_by_addr(struct crec
*crecp
, struct all_addr
*addr
,
622 time_t now
, unsigned short prot
)
626 int addrlen
= (prot
== F_IPV6
) ? IN6ADDRSZ
: INADDRSZ
;
628 int addrlen
= INADDRSZ
;
631 if (crecp
) /* iterating */
635 /* first search, look for relevant entries and push to top of list
636 also free anything which has expired. All the reverse entries are at the
637 start of the hash chain, so we can give up when we find the first
640 struct crec
**up
, **chainp
= &ans
;
642 for (i
=0; i
<hash_size
; i
++)
643 for (crecp
= hash_table
[i
], up
= &hash_table
[i
];
644 crecp
&& (crecp
->flags
& F_REVERSE
);
645 crecp
= crecp
->hash_next
)
646 if (!is_expired(now
, crecp
))
648 if ((crecp
->flags
& prot
) &&
649 memcmp(&crecp
->addr
.addr
, addr
, addrlen
) == 0)
651 if (crecp
->flags
& (F_HOSTS
| F_DHCP
| F_CONFIG
))
654 chainp
= &crecp
->next
;
662 up
= &crecp
->hash_next
;
666 *up
= crecp
->hash_next
;
667 if (!(crecp
->flags
& (F_HOSTS
| F_DHCP
| F_CONFIG
)))
674 *chainp
= cache_head
;
678 (ans
->flags
& F_REVERSE
) &&
679 (ans
->flags
& prot
) &&
680 memcmp(&ans
->addr
.addr
, addr
, addrlen
) == 0)
686 static void add_hosts_cname(struct crec
*target
)
691 for (a
= daemon
->cnames
; a
; a
= a
->next
)
692 if (hostname_isequal(cache_get_name(target
), a
->target
) &&
693 (crec
= whine_malloc(sizeof(struct crec
))))
695 crec
->flags
= F_FORWARD
| F_IMMORTAL
| F_NAMEP
| F_CONFIG
| F_CNAME
;
696 crec
->name
.namep
= a
->alias
;
697 crec
->addr
.cname
.target
.cache
= target
;
698 crec
->addr
.cname
.uid
= target
->uid
;
700 add_hosts_cname(crec
); /* handle chains */
704 static void add_hosts_entry(struct crec
*cache
, struct all_addr
*addr
, int addrlen
,
705 int index
, struct crec
**rhash
, int hashsz
)
707 struct crec
*lookup
= cache_find_by_name(NULL
, cache_get_name(cache
), 0, cache
->flags
& (F_IPV4
| F_IPV6
));
708 int i
, nameexists
= 0;
711 /* Remove duplicates in hosts files. */
712 if (lookup
&& (lookup
->flags
& F_HOSTS
))
715 if (memcmp(&lookup
->addr
.addr
, addr
, addrlen
) == 0)
722 /* Ensure there is only one address -> name mapping (first one trumps)
723 We do this by steam here, The entries are kept in hash chains, linked
724 by ->next (which is unused at this point) held in hash buckets in
725 the array rhash, hashed on address. Note that rhash and the values
726 in ->next are only valid whilst reading hosts files: the buckets are
727 then freed, and the ->next pointer used for other things.
729 Only insert each unique address once into this hashing structure.
731 This complexity avoids O(n^2) divergent CPU use whilst reading
732 large (10000 entry) hosts files. */
735 for (j
= 0, i
= 0; i
< addrlen
; i
++)
736 j
= (j
*2 +((unsigned char *)addr
)[i
]) % hashsz
;
738 for (lookup
= rhash
[j
]; lookup
; lookup
= lookup
->next
)
739 if ((lookup
->flags
& cache
->flags
& (F_IPV4
| F_IPV6
)) &&
740 memcmp(&lookup
->addr
.addr
, addr
, addrlen
) == 0)
742 cache
->flags
&= ~F_REVERSE
;
746 /* maintain address hash chain, insert new unique address */
749 cache
->next
= rhash
[j
];
754 memcpy(&cache
->addr
.addr
, addr
, addrlen
);
757 /* don't need to do alias stuff for second and subsequent addresses. */
759 add_hosts_cname(cache
);
762 static int eatspace(FILE *f
)
768 if ((c
= getc(f
)) == '#')
769 while (c
!= '\n' && c
!= EOF
)
786 static int gettok(FILE *f
, char *token
)
792 if ((c
= getc(f
)) == EOF
)
793 return (count
== 0) ? EOF
: 1;
795 if (isspace(c
) || c
== '#')
801 if (count
< (MAXDNAME
- 1))
809 static int read_hostsfile(char *filename
, int index
, int cache_size
, struct crec
**rhash
, int hashsz
)
811 FILE *f
= fopen(filename
, "r");
812 char *token
= daemon
->namebuff
, *domain_suffix
= NULL
;
813 int addr_count
= 0, name_count
= cache_size
, lineno
= 0;
814 unsigned short flags
= 0;
815 struct all_addr addr
;
816 int atnl
, addrlen
= 0;
820 my_syslog(LOG_ERR
, _("failed to load names from %s: %s"), filename
, strerror(errno
));
826 while ((atnl
= gettok(f
, token
)) != EOF
)
830 if (inet_pton(AF_INET
, token
, &addr
) > 0)
832 flags
= F_HOSTS
| F_IMMORTAL
| F_FORWARD
| F_REVERSE
| F_IPV4
;
834 domain_suffix
= get_domain(addr
.addr
.addr4
);
837 else if (inet_pton(AF_INET6
, token
, &addr
) > 0)
839 flags
= F_HOSTS
| F_IMMORTAL
| F_FORWARD
| F_REVERSE
| F_IPV6
;
841 domain_suffix
= get_domain6(&addr
.addr
.addr6
);
846 my_syslog(LOG_ERR
, _("bad address at %s line %d"), filename
, lineno
);
848 atnl
= gettok(f
, token
);
854 /* rehash every 1000 names. */
855 if ((name_count
- cache_size
) > 1000)
858 cache_size
= name_count
;
867 if ((atnl
= gettok(f
, token
)) == EOF
)
870 fqdn
= !!strchr(token
, '.');
872 if ((canon
= canonicalise(token
, &nomem
)))
874 /* If set, add a version of the name with a default domain appended */
875 if (option_bool(OPT_EXPAND
) && domain_suffix
&& !fqdn
&&
876 (cache
= whine_malloc(sizeof(struct crec
) +
877 strlen(canon
)+2+strlen(domain_suffix
)-SMALLDNAME
)))
879 strcpy(cache
->name
.sname
, canon
);
880 strcat(cache
->name
.sname
, ".");
881 strcat(cache
->name
.sname
, domain_suffix
);
882 cache
->flags
= flags
;
883 add_hosts_entry(cache
, &addr
, addrlen
, index
, rhash
, hashsz
);
886 if ((cache
= whine_malloc(sizeof(struct crec
) + strlen(canon
)+1-SMALLDNAME
)))
888 strcpy(cache
->name
.sname
, canon
);
889 cache
->flags
= flags
;
890 add_hosts_entry(cache
, &addr
, addrlen
, index
, rhash
, hashsz
);
897 my_syslog(LOG_ERR
, _("bad name at %s line %d"), filename
, lineno
);
904 my_syslog(LOG_INFO
, _("read %s - %d addresses"), filename
, addr_count
);
909 void cache_reload(void)
911 struct crec
*cache
, **up
, *tmp
;
912 int revhashsz
, i
, total_size
= daemon
->cachesize
;
913 struct hostsfile
*ah
;
914 struct host_record
*hr
;
915 struct name_list
*nl
;
917 struct interface_name
*intr
;
922 cache_inserted
= cache_live_freed
= 0;
924 for (i
=0; i
<hash_size
; i
++)
925 for (cache
= hash_table
[i
], up
= &hash_table
[i
]; cache
; cache
= tmp
)
928 if (cache
->flags
& (F_DNSKEY
| F_DS
))
929 blockdata_free(cache
->addr
.key
.keydata
);
931 tmp
= cache
->hash_next
;
932 if (cache
->flags
& (F_HOSTS
| F_CONFIG
))
934 *up
= cache
->hash_next
;
937 else if (!(cache
->flags
& F_DHCP
))
939 *up
= cache
->hash_next
;
940 if (cache
->flags
& F_BIGNAME
)
942 cache
->name
.bname
->next
= big_free
;
943 big_free
= cache
->name
.bname
;
948 up
= &cache
->hash_next
;
951 /* Add CNAMEs to interface_names to the cache */
952 for (a
= daemon
->cnames
; a
; a
= a
->next
)
953 for (intr
= daemon
->int_names
; intr
; intr
= intr
->next
)
954 if (hostname_isequal(a
->target
, intr
->name
) &&
955 ((cache
= whine_malloc(sizeof(struct crec
)))))
957 cache
->flags
= F_FORWARD
| F_NAMEP
| F_CNAME
| F_IMMORTAL
| F_CONFIG
| F_DNSSECOK
;
958 cache
->name
.namep
= a
->alias
;
959 cache
->addr
.cname
.target
.int_name
= intr
;
960 cache
->addr
.cname
.uid
= -1;
962 add_hosts_cname(cache
); /* handle chains */
966 for (key
= daemon
->dnskeys
; key
; key
= key
->next
)
967 if ((cache
= whine_malloc(sizeof(struct crec
))) &&
968 (cache
->addr
.key
.keydata
= blockdata_alloc(key
->key
, key
->keylen
)))
970 cache
->flags
= F_FORWARD
| F_IMMORTAL
| F_DNSKEY
| F_CONFIG
| F_NAMEP
;
971 cache
->name
.namep
= key
->name
;
972 cache
->uid
= key
->keylen
;
973 cache
->addr
.key
.algo
= key
->algo
;
974 cache
->addr
.key
.keytag
= dnskey_keytag(key
->algo
, key
->flags
, (unsigned char *)key
->key
, key
->keylen
);
979 /* borrow the packet buffer for a temporary by-address hash */
980 memset(daemon
->packet
, 0, daemon
->packet_buff_sz
);
981 revhashsz
= daemon
->packet_buff_sz
/ sizeof(struct crec
*);
982 /* we overwrote the buffer... */
983 daemon
->srv_save
= NULL
;
985 /* Do host_records in config. */
986 for (hr
= daemon
->host_records
; hr
; hr
= hr
->next
)
987 for (nl
= hr
->names
; nl
; nl
= nl
->next
)
989 if (hr
->addr
.s_addr
!= 0 &&
990 (cache
= whine_malloc(sizeof(struct crec
))))
992 cache
->name
.namep
= nl
->name
;
993 cache
->flags
= F_HOSTS
| F_IMMORTAL
| F_FORWARD
| F_REVERSE
| F_IPV4
| F_NAMEP
| F_CONFIG
;
994 add_hosts_entry(cache
, (struct all_addr
*)&hr
->addr
, INADDRSZ
, 0, (struct crec
**)daemon
->packet
, revhashsz
);
997 if (!IN6_IS_ADDR_UNSPECIFIED(&hr
->addr6
) &&
998 (cache
= whine_malloc(sizeof(struct crec
))))
1000 cache
->name
.namep
= nl
->name
;
1001 cache
->flags
= F_HOSTS
| F_IMMORTAL
| F_FORWARD
| F_REVERSE
| F_IPV6
| F_NAMEP
| F_CONFIG
;
1002 add_hosts_entry(cache
, (struct all_addr
*)&hr
->addr6
, IN6ADDRSZ
, 0, (struct crec
**)daemon
->packet
, revhashsz
);
1007 if (option_bool(OPT_NO_HOSTS
) && !daemon
->addn_hosts
)
1009 if (daemon
->cachesize
> 0)
1010 my_syslog(LOG_INFO
, _("cleared cache"));
1014 if (!option_bool(OPT_NO_HOSTS
))
1015 total_size
= read_hostsfile(HOSTSFILE
, 0, total_size
, (struct crec
**)daemon
->packet
, revhashsz
);
1017 daemon
->addn_hosts
= expand_filelist(daemon
->addn_hosts
);
1018 for (ah
= daemon
->addn_hosts
; ah
; ah
= ah
->next
)
1019 if (!(ah
->flags
& AH_INACTIVE
))
1020 total_size
= read_hostsfile(ah
->fname
, ah
->index
, total_size
, (struct crec
**)daemon
->packet
, revhashsz
);
1024 struct in_addr
a_record_from_hosts(char *name
, time_t now
)
1026 struct crec
*crecp
= NULL
;
1029 while ((crecp
= cache_find_by_name(crecp
, name
, now
, F_IPV4
)))
1030 if (crecp
->flags
& F_HOSTS
)
1031 return *(struct in_addr
*)&crecp
->addr
;
1033 my_syslog(MS_DHCP
| LOG_WARNING
, _("No IPv4 address found for %s"), name
);
1039 void cache_unhash_dhcp(void)
1041 struct crec
*cache
, **up
;
1044 for (i
=0; i
<hash_size
; i
++)
1045 for (cache
= hash_table
[i
], up
= &hash_table
[i
]; cache
; cache
= cache
->hash_next
)
1046 if (cache
->flags
& F_DHCP
)
1048 *up
= cache
->hash_next
;
1049 cache
->next
= dhcp_spare
;
1053 up
= &cache
->hash_next
;
1056 static void add_dhcp_cname(struct crec
*target
, time_t ttd
)
1058 struct crec
*aliasc
;
1061 for (a
= daemon
->cnames
; a
; a
= a
->next
)
1062 if (hostname_isequal(cache_get_name(target
), a
->target
))
1064 if ((aliasc
= dhcp_spare
))
1065 dhcp_spare
= dhcp_spare
->next
;
1066 else /* need new one */
1067 aliasc
= whine_malloc(sizeof(struct crec
));
1071 aliasc
->flags
= F_FORWARD
| F_NAMEP
| F_DHCP
| F_CNAME
| F_CONFIG
;
1073 aliasc
->flags
|= F_IMMORTAL
;
1076 aliasc
->name
.namep
= a
->alias
;
1077 aliasc
->addr
.cname
.target
.cache
= target
;
1078 aliasc
->addr
.cname
.uid
= target
->uid
;
1080 add_dhcp_cname(aliasc
, ttd
);
1085 void cache_add_dhcp_entry(char *host_name
, int prot
,
1086 struct all_addr
*host_address
, time_t ttd
)
1088 struct crec
*crec
= NULL
, *fail_crec
= NULL
;
1089 unsigned short flags
= F_IPV4
;
1091 size_t addrlen
= sizeof(struct in_addr
);
1094 if (prot
== AF_INET6
)
1097 addrlen
= sizeof(struct in6_addr
);
1101 inet_ntop(prot
, host_address
, daemon
->addrbuff
, ADDRSTRLEN
);
1103 while ((crec
= cache_find_by_name(crec
, host_name
, 0, flags
| F_CNAME
)))
1105 /* check all addresses associated with name */
1106 if (crec
->flags
& (F_HOSTS
| F_CONFIG
))
1108 if (crec
->flags
& F_CNAME
)
1109 my_syslog(MS_DHCP
| LOG_WARNING
,
1110 _("%s is a CNAME, not giving it to the DHCP lease of %s"),
1111 host_name
, daemon
->addrbuff
);
1112 else if (memcmp(&crec
->addr
.addr
, host_address
, addrlen
) == 0)
1117 else if (!(crec
->flags
& F_DHCP
))
1119 cache_scan_free(host_name
, NULL
, 0, crec
->flags
& (flags
| F_CNAME
| F_FORWARD
));
1120 /* scan_free deletes all addresses associated with name */
1125 /* if in hosts, don't need DHCP record */
1129 /* Name in hosts, address doesn't match */
1132 inet_ntop(prot
, &fail_crec
->addr
.addr
, daemon
->namebuff
, MAXDNAME
);
1133 my_syslog(MS_DHCP
| LOG_WARNING
,
1134 _("not giving name %s to the DHCP lease of %s because "
1135 "the name exists in %s with address %s"),
1136 host_name
, daemon
->addrbuff
,
1137 record_source(fail_crec
->uid
), daemon
->namebuff
);
1141 if ((crec
= cache_find_by_addr(NULL
, (struct all_addr
*)host_address
, 0, flags
)))
1143 if (crec
->flags
& F_NEG
)
1146 cache_scan_free(NULL
, (struct all_addr
*)host_address
, 0, flags
);
1152 if ((crec
= dhcp_spare
))
1153 dhcp_spare
= dhcp_spare
->next
;
1154 else /* need new one */
1155 crec
= whine_malloc(sizeof(struct crec
));
1157 if (crec
) /* malloc may fail */
1159 crec
->flags
= flags
| F_NAMEP
| F_DHCP
| F_FORWARD
;
1161 crec
->flags
|= F_IMMORTAL
;
1164 crec
->addr
.addr
= *host_address
;
1165 crec
->name
.namep
= host_name
;
1169 add_dhcp_cname(crec
, ttd
);
1175 void dump_cache(time_t now
)
1177 struct server
*serv
, *serv1
;
1179 my_syslog(LOG_INFO
, _("time %lu"), (unsigned long)now
);
1180 my_syslog(LOG_INFO
, _("cache size %d, %d/%d cache insertions re-used unexpired cache entries."),
1181 daemon
->cachesize
, cache_live_freed
, cache_inserted
);
1182 my_syslog(LOG_INFO
, _("queries forwarded %u, queries answered locally %u"),
1183 daemon
->queries_forwarded
, daemon
->local_answer
);
1185 my_syslog(LOG_INFO
, _("queries for authoritative zones %u"), daemon
->auth_answer
);
1188 /* sum counts from different records for same server */
1189 for (serv
= daemon
->servers
; serv
; serv
= serv
->next
)
1190 serv
->flags
&= ~SERV_COUNTED
;
1192 for (serv
= daemon
->servers
; serv
; serv
= serv
->next
)
1194 (SERV_NO_ADDR
| SERV_LITERAL_ADDRESS
| SERV_COUNTED
| SERV_USE_RESOLV
| SERV_NO_REBIND
)))
1197 unsigned int queries
= 0, failed_queries
= 0;
1198 for (serv1
= serv
; serv1
; serv1
= serv1
->next
)
1199 if (!(serv1
->flags
&
1200 (SERV_NO_ADDR
| SERV_LITERAL_ADDRESS
| SERV_COUNTED
| SERV_USE_RESOLV
| SERV_NO_REBIND
)) &&
1201 sockaddr_isequal(&serv
->addr
, &serv1
->addr
))
1203 serv1
->flags
|= SERV_COUNTED
;
1204 queries
+= serv1
->queries
;
1205 failed_queries
+= serv1
->failed_queries
;
1207 port
= prettyprint_addr(&serv
->addr
, daemon
->addrbuff
);
1208 my_syslog(LOG_INFO
, _("server %s#%d: queries sent %u, retried or failed %u"), daemon
->addrbuff
, port
, queries
, failed_queries
);
1211 if (option_bool(OPT_DEBUG
) || option_bool(OPT_LOG
))
1213 struct crec
*cache
;
1215 my_syslog(LOG_INFO
, "Host Address Flags Expires");
1217 for (i
=0; i
<hash_size
; i
++)
1218 for (cache
= hash_table
[i
]; cache
; cache
= cache
->hash_next
)
1220 char *a
= daemon
->addrbuff
, *p
= daemon
->namebuff
, *n
= cache_get_name(cache
);
1224 p
+= sprintf(p
, "%-40.40s ", n
);
1225 if ((cache
->flags
& F_CNAME
) && !is_outdated_cname_pointer(cache
))
1226 a
= cache_get_cname_target(cache
);
1228 else if (cache
->flags
& F_DNSKEY
)
1230 a
= daemon
->addrbuff
;
1231 sprintf(a
, "%3u %u", cache
->addr
.key
.algo
, cache
->uid
);
1233 else if (cache
->flags
& F_DS
)
1235 a
= daemon
->addrbuff
;
1236 sprintf(a
, "%5u %3u %3u", cache
->addr
.key
.keytag
,
1237 cache
->addr
.key
.algo
, cache
->addr
.key
.digest
);
1240 else if (!(cache
->flags
& F_NEG
) || !(cache
->flags
& F_FORWARD
))
1242 a
= daemon
->addrbuff
;
1243 if (cache
->flags
& F_IPV4
)
1244 inet_ntop(AF_INET
, &cache
->addr
.addr
, a
, ADDRSTRLEN
);
1246 else if (cache
->flags
& F_IPV6
)
1247 inet_ntop(AF_INET6
, &cache
->addr
.addr
, a
, ADDRSTRLEN
);
1251 p
+= sprintf(p
, "%-30.30s %s%s%s%s%s%s%s%s%s%s%s%s%s ", a
,
1252 cache
->flags
& F_IPV4
? "4" : "",
1253 cache
->flags
& F_IPV6
? "6" : "",
1254 cache
->flags
& F_DNSKEY
? "K" : "",
1255 cache
->flags
& F_DS
? "S" : "",
1256 cache
->flags
& F_CNAME
? "C" : "",
1257 cache
->flags
& F_FORWARD
? "F" : " ",
1258 cache
->flags
& F_REVERSE
? "R" : " ",
1259 cache
->flags
& F_IMMORTAL
? "I" : " ",
1260 cache
->flags
& F_DHCP
? "D" : " ",
1261 cache
->flags
& F_NEG
? "N" : " ",
1262 cache
->flags
& F_NXDOMAIN
? "X" : " ",
1263 cache
->flags
& F_HOSTS
? "H" : " ",
1264 cache
->flags
& F_DNSSECOK
? "V" : " ");
1265 #ifdef HAVE_BROKEN_RTC
1266 p
+= sprintf(p
, "%lu", cache
->flags
& F_IMMORTAL
? 0: (unsigned long)(cache
->ttd
- now
));
1268 p
+= sprintf(p
, "%s", cache
->flags
& F_IMMORTAL
? "\n" : ctime(&(cache
->ttd
)));
1269 /* ctime includes trailing \n - eat it */
1272 my_syslog(LOG_INFO
, daemon
->namebuff
);
1277 char *record_source(int index
)
1279 struct hostsfile
*ah
;
1284 for (ah
= daemon
->addn_hosts
; ah
; ah
= ah
->next
)
1285 if (ah
->index
== index
)
1291 void querystr(char *desc
, char *str
, unsigned short type
)
1295 sprintf(str
, "%s[type=%d]", desc
, type
);
1296 for (i
= 0; i
< (sizeof(typestr
)/sizeof(typestr
[0])); i
++)
1297 if (typestr
[i
].type
== type
)
1298 sprintf(str
,"%s[%s]", desc
, typestr
[i
].name
);
1301 void log_query(unsigned int flags
, char *name
, struct all_addr
*addr
, char *arg
)
1303 char *source
, *dest
= daemon
->addrbuff
;
1306 if (!option_bool(OPT_LOG
))
1311 if (flags
& F_KEYTAG
)
1312 sprintf(daemon
->addrbuff
, arg
, addr
->addr
.keytag
);
1316 inet_ntop(flags
& F_IPV4
? AF_INET
: AF_INET6
,
1317 addr
, daemon
->addrbuff
, ADDRSTRLEN
);
1319 strncpy(daemon
->addrbuff
, inet_ntoa(addr
->addr
.addr4
), ADDRSTRLEN
);
1326 if (flags
& F_REVERSE
)
1329 name
= daemon
->addrbuff
;
1334 if (flags
& F_NXDOMAIN
)
1337 dest
= "NXDOMAIN-IPv4";
1338 else if (flags
& F_IPV6
)
1339 dest
= "NXDOMAIN-IPv6";
1346 dest
= "NODATA-IPv4";
1347 else if (flags
& F_IPV6
)
1348 dest
= "NODATA-IPv6";
1353 else if (flags
& F_CNAME
)
1355 else if (flags
& F_RRNAME
)
1358 if (flags
& F_CONFIG
)
1360 else if (flags
& F_DHCP
)
1362 else if (flags
& F_HOSTS
)
1364 else if (flags
& F_UPSTREAM
)
1366 else if (flags
& F_SECSTAT
)
1367 source
= "validation";
1368 else if (flags
& F_AUTH
)
1370 else if (flags
& F_SERVER
)
1372 source
= "forwarded";
1375 else if (flags
& F_QUERY
)
1380 else if (flags
& F_DNSSEC
)
1388 if (strlen(name
) == 0)
1391 my_syslog(LOG_INFO
, "%s %s %s %s", source
, name
, verb
, dest
);