]>
git.ipfire.org Git - people/ms/dnsmasq.git/blob - src/cache.c
1 /* dnsmasq is Copyright (c) 2000-2013 Simon Kelley
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; version 2 dated June, 1991, or
6 (at your option) version 3 dated 29 June, 2007.
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
13 You should have received a copy of the GNU General Public License
14 along with this program. If not, see <http://www.gnu.org/licenses/>.
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 static struct keydata
*keyblock_free
= NULL
;
32 /* type->string mapping: this is also used by the name-hash function as a mixing table. */
35 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
);
80 bignames_left
= daemon
->cachesize
/10;
82 if (daemon
->cachesize
> 0)
84 crecp
= safe_malloc(daemon
->cachesize
*sizeof(struct crec
));
86 for (i
=0; i
< daemon
->cachesize
; i
++, crecp
++)
94 /* create initial hash table*/
95 rehash(daemon
->cachesize
);
98 /* In most cases, we create the hash table once here by calling this with (hash_table == NULL)
99 but if the hosts file(s) are big (some people have 50000 ad-block entries), the table
100 will be much too small, so the hosts reading code calls rehash every 1000 addresses, to
102 static void rehash(int size
)
104 struct crec
**new, **old
, *p
, *tmp
;
105 int i
, new_size
, old_size
;
107 /* hash_size is a power of two. */
108 for (new_size
= 64; new_size
< size
/10; new_size
= new_size
<< 1);
110 /* must succeed in getting first instance, failure later is non-fatal */
112 new = safe_malloc(new_size
* sizeof(struct crec
*));
113 else if (new_size
<= hash_size
|| !(new = whine_malloc(new_size
* sizeof(struct crec
*))))
116 for(i
= 0; i
< new_size
; i
++)
120 old_size
= hash_size
;
122 hash_size
= new_size
;
126 for (i
= 0; i
< old_size
; i
++)
127 for (p
= old
[i
]; p
; p
= tmp
)
136 static struct crec
**hash_bucket(char *name
)
138 unsigned int c
, val
= 017465; /* Barker code - minimum self-correlation in cyclic shift */
139 const unsigned char *mix_tab
= (const unsigned char*)typestr
;
141 while((c
= (unsigned char) *name
++))
143 /* don't use tolower and friends here - they may be messed up by LOCALE */
144 if (c
>= 'A' && c
<= 'Z')
146 val
= ((val
<< 7) | (val
>> (32 - 7))) + (mix_tab
[(val
+ c
) & 0x3F] ^ c
);
149 /* hash_size is a power of two */
150 return hash_table
+ ((val
^ (val
>> 16)) & (hash_size
- 1));
153 static void cache_hash(struct crec
*crecp
)
155 /* maintain an invariant that all entries with F_REVERSE set
156 are at the start of the hash-chain and all non-reverse
157 immortal entries are at the end of the hash-chain.
158 This allows reverse searches and garbage collection to be optimised */
160 struct crec
**up
= hash_bucket(cache_get_name(crecp
));
162 if (!(crecp
->flags
& F_REVERSE
))
164 while (*up
&& ((*up
)->flags
& F_REVERSE
))
165 up
= &((*up
)->hash_next
);
167 if (crecp
->flags
& F_IMMORTAL
)
168 while (*up
&& !((*up
)->flags
& F_IMMORTAL
))
169 up
= &((*up
)->hash_next
);
171 crecp
->hash_next
= *up
;
175 static void cache_free(struct crec
*crecp
)
177 crecp
->flags
&= ~F_FORWARD
;
178 crecp
->flags
&= ~F_REVERSE
;
179 crecp
->uid
= uid
++; /* invalidate CNAMES pointing to this. */
185 cache_tail
->next
= crecp
;
188 crecp
->prev
= cache_tail
;
192 /* retrieve big name for further use. */
193 if (crecp
->flags
& F_BIGNAME
)
195 crecp
->name
.bname
->next
= big_free
;
196 big_free
= crecp
->name
.bname
;
197 crecp
->flags
&= ~F_BIGNAME
;
200 else if (crecp
->flags
& (F_DNSKEY
| F_DS
))
201 keydata_free(crecp
->addr
.key
.keydata
);
205 /* insert a new cache entry at the head of the list (youngest entry) */
206 static void cache_link(struct crec
*crecp
)
208 if (cache_head
) /* check needed for init code */
209 cache_head
->prev
= crecp
;
210 crecp
->next
= cache_head
;
217 /* remove an arbitrary cache entry for promotion */
218 static void cache_unlink (struct crec
*crecp
)
221 crecp
->prev
->next
= crecp
->next
;
223 cache_head
= crecp
->next
;
226 crecp
->next
->prev
= crecp
->prev
;
228 cache_tail
= crecp
->prev
;
231 char *cache_get_name(struct crec
*crecp
)
233 if (crecp
->flags
& F_BIGNAME
)
234 return crecp
->name
.bname
->name
;
235 else if (crecp
->flags
& F_NAMEP
)
236 return crecp
->name
.namep
;
238 return crecp
->name
.sname
;
241 char *cache_get_cname_target(struct crec
*crecp
)
243 if (crecp
->addr
.cname
.uid
!= -1)
244 return cache_get_name(crecp
->addr
.cname
.target
.cache
);
246 return crecp
->addr
.cname
.target
.int_name
->name
;
251 struct crec
*cache_enumerate(int init
)
254 static struct crec
*cache
;
261 else if (cache
&& cache
->hash_next
)
262 cache
= cache
->hash_next
;
266 while (bucket
< hash_size
)
267 if ((cache
= hash_table
[bucket
++]))
274 static int is_outdated_cname_pointer(struct crec
*crecp
)
276 if (!(crecp
->flags
& F_CNAME
) || crecp
->addr
.cname
.uid
== -1)
279 /* NB. record may be reused as DS or DNSKEY, where uid is
280 overloaded for something completely different */
281 if (crecp
->addr
.cname
.target
.cache
&&
282 (crecp
->addr
.cname
.target
.cache
->flags
& (F_IPV4
| F_IPV6
| F_CNAME
)) &&
283 crecp
->addr
.cname
.uid
== crecp
->addr
.cname
.target
.cache
->uid
)
289 static int is_expired(time_t now
, struct crec
*crecp
)
291 if (crecp
->flags
& F_IMMORTAL
)
294 if (difftime(now
, crecp
->ttd
) < 0)
300 static int cache_scan_free(char *name
, struct all_addr
*addr
, time_t now
, unsigned short flags
)
302 /* Scan and remove old entries.
303 If (flags & F_FORWARD) then remove any forward entries for name and any expired
304 entries but only in the same hash bucket as name.
305 If (flags & F_REVERSE) then remove any reverse entries for addr and any expired
306 entries in the whole cache.
307 If (flags == 0) remove any expired entries in the whole cache.
309 In the flags & F_FORWARD case, the return code is valid, and returns zero if the
310 name exists in the cache as a HOSTS or DHCP entry (these are never deleted)
312 We take advantage of the fact that hash chains have stuff in the order <reverse>,<other>,<immortal>
313 so that when we hit an entry which isn't reverse and is immortal, we're done. */
315 struct crec
*crecp
, **up
;
317 if (flags
& F_FORWARD
)
319 for (up
= hash_bucket(name
), crecp
= *up
; crecp
; crecp
= crecp
->hash_next
)
320 if (is_expired(now
, crecp
) || is_outdated_cname_pointer(crecp
))
322 *up
= crecp
->hash_next
;
323 if (!(crecp
->flags
& (F_HOSTS
| F_DHCP
)))
329 else if ((crecp
->flags
& F_FORWARD
) &&
330 ((flags
& crecp
->flags
& F_TYPE
) || ((crecp
->flags
| flags
) & F_CNAME
)) &&
331 hostname_isequal(cache_get_name(crecp
), name
))
333 if (crecp
->flags
& (F_HOSTS
| F_DHCP
| F_CONFIG
))
335 *up
= crecp
->hash_next
;
340 up
= &crecp
->hash_next
;
346 int addrlen
= (flags
& F_IPV6
) ? IN6ADDRSZ
: INADDRSZ
;
348 int addrlen
= INADDRSZ
;
350 for (i
= 0; i
< hash_size
; i
++)
351 for (crecp
= hash_table
[i
], up
= &hash_table
[i
];
352 crecp
&& ((crecp
->flags
& F_REVERSE
) || !(crecp
->flags
& F_IMMORTAL
));
353 crecp
= crecp
->hash_next
)
354 if (is_expired(now
, crecp
))
356 *up
= crecp
->hash_next
;
357 if (!(crecp
->flags
& (F_HOSTS
| F_DHCP
)))
363 else if (!(crecp
->flags
& (F_HOSTS
| F_DHCP
)) &&
364 (flags
& crecp
->flags
& F_REVERSE
) &&
365 (flags
& crecp
->flags
& (F_IPV4
| F_IPV6
)) &&
366 memcmp(&crecp
->addr
.addr
, addr
, addrlen
) == 0)
368 *up
= crecp
->hash_next
;
373 up
= &crecp
->hash_next
;
379 /* Note: The normal calling sequence is
384 but an abort can cause the cache_end_insert to be missed
385 in which can the next cache_start_insert cleans things up. */
387 void cache_start_insert(void)
389 /* Free any entries which didn't get committed during the last
394 struct crec
*tmp
= new_chain
->next
;
395 cache_free(new_chain
);
402 struct crec
*cache_insert(char *name
, struct all_addr
*addr
,
403 time_t now
, unsigned long ttl
, unsigned short flags
)
406 union bigname
*big_name
= NULL
;
407 int freed_all
= flags
& F_REVERSE
;
410 if (daemon
->max_cache_ttl
!= 0 && daemon
->max_cache_ttl
< ttl
)
411 ttl
= daemon
->max_cache_ttl
;
414 if (flags
& (F_IPV4
| F_IPV6
))
415 log_query(flags
| F_UPSTREAM
, name
, addr
, NULL
);
417 /* if previous insertion failed give up now. */
421 /* First remove any expired entries and entries for the name/address we
422 are currently inserting. Fail is we attempt to delete a name from
423 /etc/hosts or DHCP. */
424 if (!cache_scan_free(name
, addr
, now
, flags
))
430 /* Now get a cache entry from the end of the LRU list */
432 if (!(new = cache_tail
)) /* no entries left - cache is too small, bail */
438 /* End of LRU list is still in use: if we didn't scan all the hash
439 chains for expired entries do that now. If we already tried that
440 then it's time to start spilling things. */
442 if (new->flags
& (F_FORWARD
| F_REVERSE
))
444 /* If free_avail set, we believe that an entry has been freed.
445 Bugs have been known to make this not true, resulting in
446 a tight loop here. If that happens, abandon the
447 insert. Once in this state, all inserts will probably fail. */
456 free_avail
= 1; /* Must be free space now. */
457 cache_scan_free(cache_get_name(new), &new->addr
.addr
, now
, new->flags
);
462 cache_scan_free(NULL
, NULL
, now
, 0);
468 /* Check if we need to and can allocate extra memory for a long name.
469 If that fails, give up now. */
470 if (name
&& (strlen(name
) > SMALLDNAME
-1))
475 big_free
= big_free
->next
;
477 else if (!bignames_left
||
478 !(big_name
= (union bigname
*)whine_malloc(sizeof(union bigname
))))
488 /* Got the rest: finally grab entry. */
496 new->name
.bname
= big_name
;
497 new->flags
|= F_BIGNAME
;
501 strcpy(cache_get_name(new), name
);
503 *cache_get_name(new) = 0;
506 new->addr
.addr
= *addr
;
508 new->ttd
= now
+ (time_t)ttl
;
509 new->next
= new_chain
;
515 /* after end of insertion, commit the new entries */
516 void cache_end_insert(void)
523 struct crec
*tmp
= new_chain
->next
;
524 /* drop CNAMEs which didn't find a target. */
525 if (is_outdated_cname_pointer(new_chain
))
526 cache_free(new_chain
);
529 cache_hash(new_chain
);
530 cache_link(new_chain
);
538 struct crec
*cache_find_by_name(struct crec
*crecp
, char *name
, time_t now
, unsigned short prot
)
542 if (crecp
) /* iterating */
546 /* first search, look for relevant entries and push to top of list
547 also free anything which has expired */
548 struct crec
*next
, **up
, **insert
= NULL
, **chainp
= &ans
;
549 unsigned short ins_flags
= 0;
551 for (up
= hash_bucket(name
), crecp
= *up
; crecp
; crecp
= next
)
553 next
= crecp
->hash_next
;
555 if (!is_expired(now
, crecp
) && !is_outdated_cname_pointer(crecp
))
557 if ((crecp
->flags
& F_FORWARD
) &&
558 (crecp
->flags
& prot
) &&
559 hostname_isequal(cache_get_name(crecp
), name
))
561 if (crecp
->flags
& (F_HOSTS
| F_DHCP
))
564 chainp
= &crecp
->next
;
572 /* Move all but the first entry up the hash chain
573 this implements round-robin.
574 Make sure that re-ordering doesn't break the hash-chain
577 if (insert
&& (crecp
->flags
& (F_REVERSE
| F_IMMORTAL
)) == ins_flags
)
579 *up
= crecp
->hash_next
;
580 crecp
->hash_next
= *insert
;
582 insert
= &crecp
->hash_next
;
589 ins_flags
= crecp
->flags
& (F_REVERSE
| F_IMMORTAL
);
591 up
= &crecp
->hash_next
;
595 /* case : not expired, incorrect entry. */
596 up
= &crecp
->hash_next
;
600 /* expired entry, free it */
601 *up
= crecp
->hash_next
;
602 if (!(crecp
->flags
& (F_HOSTS
| F_DHCP
)))
610 *chainp
= cache_head
;
614 (ans
->flags
& F_FORWARD
) &&
615 (ans
->flags
& prot
) &&
616 hostname_isequal(cache_get_name(ans
), name
))
622 struct crec
*cache_find_by_addr(struct crec
*crecp
, struct all_addr
*addr
,
623 time_t now
, unsigned short prot
)
627 int addrlen
= (prot
== F_IPV6
) ? IN6ADDRSZ
: INADDRSZ
;
629 int addrlen
= INADDRSZ
;
632 if (crecp
) /* iterating */
636 /* first search, look for relevant entries and push to top of list
637 also free anything which has expired. All the reverse entries are at the
638 start of the hash chain, so we can give up when we find the first
641 struct crec
**up
, **chainp
= &ans
;
643 for (i
=0; i
<hash_size
; i
++)
644 for (crecp
= hash_table
[i
], up
= &hash_table
[i
];
645 crecp
&& (crecp
->flags
& F_REVERSE
);
646 crecp
= crecp
->hash_next
)
647 if (!is_expired(now
, crecp
))
649 if ((crecp
->flags
& prot
) &&
650 memcmp(&crecp
->addr
.addr
, addr
, addrlen
) == 0)
652 if (crecp
->flags
& (F_HOSTS
| F_DHCP
))
655 chainp
= &crecp
->next
;
663 up
= &crecp
->hash_next
;
667 *up
= crecp
->hash_next
;
668 if (!(crecp
->flags
& (F_HOSTS
| F_DHCP
)))
675 *chainp
= cache_head
;
679 (ans
->flags
& F_REVERSE
) &&
680 (ans
->flags
& prot
) &&
681 memcmp(&ans
->addr
.addr
, addr
, addrlen
) == 0)
687 static void add_hosts_cname(struct crec
*target
)
692 for (a
= daemon
->cnames
; a
; a
= a
->next
)
693 if (hostname_isequal(cache_get_name(target
), a
->target
) &&
694 (crec
= whine_malloc(sizeof(struct crec
))))
696 crec
->flags
= F_FORWARD
| F_IMMORTAL
| F_NAMEP
| F_CONFIG
| F_CNAME
;
697 crec
->name
.namep
= a
->alias
;
698 crec
->addr
.cname
.target
.cache
= target
;
699 crec
->addr
.cname
.uid
= target
->uid
;
701 add_hosts_cname(crec
); /* handle chains */
705 static void add_hosts_entry(struct crec
*cache
, struct all_addr
*addr
, int addrlen
,
706 int index
, struct crec
**rhash
, int hashsz
)
708 struct crec
*lookup
= cache_find_by_name(NULL
, cache_get_name(cache
), 0, cache
->flags
& (F_IPV4
| F_IPV6
));
709 int i
, nameexists
= 0;
712 /* Remove duplicates in hosts files. */
713 if (lookup
&& (lookup
->flags
& F_HOSTS
))
716 if (memcmp(&lookup
->addr
.addr
, addr
, addrlen
) == 0)
723 /* Ensure there is only one address -> name mapping (first one trumps)
724 We do this by steam here, The entries are kept in hash chains, linked
725 by ->next (which is unused at this point) held in hash buckets in
726 the array rhash, hashed on address. Note that rhash and the values
727 in ->next are only valid whilst reading hosts files: the buckets are
728 then freed, and the ->next pointer used for other things.
730 Only insert each unique address once into this hashing structure.
732 This complexity avoids O(n^2) divergent CPU use whilst reading
733 large (10000 entry) hosts files. */
736 for (j
= 0, i
= 0; i
< addrlen
; i
++)
737 j
= (j
*2 +((unsigned char *)addr
)[i
]) % hashsz
;
739 for (lookup
= rhash
[j
]; lookup
; lookup
= lookup
->next
)
740 if ((lookup
->flags
& cache
->flags
& (F_IPV4
| F_IPV6
)) &&
741 memcmp(&lookup
->addr
.addr
, addr
, addrlen
) == 0)
743 cache
->flags
&= ~F_REVERSE
;
747 /* maintain address hash chain, insert new unique address */
750 cache
->next
= rhash
[j
];
755 memcpy(&cache
->addr
.addr
, addr
, addrlen
);
758 /* don't need to do alias stuff for second and subsequent addresses. */
760 add_hosts_cname(cache
);
763 static int eatspace(FILE *f
)
769 if ((c
= getc(f
)) == '#')
770 while (c
!= '\n' && c
!= EOF
)
787 static int gettok(FILE *f
, char *token
)
793 if ((c
= getc(f
)) == EOF
)
794 return (count
== 0) ? EOF
: 1;
796 if (isspace(c
) || c
== '#')
802 if (count
< (MAXDNAME
- 1))
810 static int read_hostsfile(char *filename
, int index
, int cache_size
, struct crec
**rhash
, int hashsz
)
812 FILE *f
= fopen(filename
, "r");
813 char *token
= daemon
->namebuff
, *domain_suffix
= NULL
;
814 int addr_count
= 0, name_count
= cache_size
, lineno
= 0;
815 unsigned short flags
= 0;
816 struct all_addr addr
;
817 int atnl
, addrlen
= 0;
821 my_syslog(LOG_ERR
, _("failed to load names from %s: %s"), filename
, strerror(errno
));
827 while ((atnl
= gettok(f
, token
)) != EOF
)
831 if (inet_pton(AF_INET
, token
, &addr
) > 0)
833 flags
= F_HOSTS
| F_IMMORTAL
| F_FORWARD
| F_REVERSE
| F_IPV4
;
835 domain_suffix
= get_domain(addr
.addr
.addr4
);
838 else if (inet_pton(AF_INET6
, token
, &addr
) > 0)
840 flags
= F_HOSTS
| F_IMMORTAL
| F_FORWARD
| F_REVERSE
| F_IPV6
;
842 domain_suffix
= get_domain6(&addr
.addr
.addr6
);
847 my_syslog(LOG_ERR
, _("bad address at %s line %d"), filename
, lineno
);
849 atnl
= gettok(f
, token
);
855 /* rehash every 1000 names. */
856 if ((name_count
- cache_size
) > 1000)
859 cache_size
= name_count
;
868 if ((atnl
= gettok(f
, token
)) == EOF
)
871 fqdn
= !!strchr(token
, '.');
873 if ((canon
= canonicalise(token
, &nomem
)))
875 /* If set, add a version of the name with a default domain appended */
876 if (option_bool(OPT_EXPAND
) && domain_suffix
&& !fqdn
&&
877 (cache
= whine_malloc(sizeof(struct crec
) +
878 strlen(canon
)+2+strlen(domain_suffix
)-SMALLDNAME
)))
880 strcpy(cache
->name
.sname
, canon
);
881 strcat(cache
->name
.sname
, ".");
882 strcat(cache
->name
.sname
, domain_suffix
);
883 cache
->flags
= flags
;
884 add_hosts_entry(cache
, &addr
, addrlen
, index
, rhash
, hashsz
);
887 if ((cache
= whine_malloc(sizeof(struct crec
) + strlen(canon
)+1-SMALLDNAME
)))
889 strcpy(cache
->name
.sname
, canon
);
890 cache
->flags
= flags
;
891 add_hosts_entry(cache
, &addr
, addrlen
, index
, rhash
, hashsz
);
898 my_syslog(LOG_ERR
, _("bad name at %s line %d"), filename
, lineno
);
905 my_syslog(LOG_INFO
, _("read %s - %d addresses"), filename
, addr_count
);
910 void cache_reload(void)
912 struct crec
*cache
, **up
, *tmp
;
913 int revhashsz
, i
, total_size
= daemon
->cachesize
;
914 struct hostsfile
*ah
;
915 struct host_record
*hr
;
916 struct name_list
*nl
;
918 struct interface_name
*intr
;
920 cache_inserted
= cache_live_freed
= 0;
922 for (i
=0; i
<hash_size
; i
++)
923 for (cache
= hash_table
[i
], up
= &hash_table
[i
]; cache
; cache
= tmp
)
925 tmp
= cache
->hash_next
;
926 if (cache
->flags
& F_HOSTS
)
928 *up
= cache
->hash_next
;
931 else if (!(cache
->flags
& F_DHCP
))
933 *up
= cache
->hash_next
;
934 if (cache
->flags
& F_BIGNAME
)
936 cache
->name
.bname
->next
= big_free
;
937 big_free
= cache
->name
.bname
;
942 up
= &cache
->hash_next
;
945 /* Add CNAMEs to interface_names to the cache */
946 for (a
= daemon
->cnames
; a
; a
= a
->next
)
947 for (intr
= daemon
->int_names
; intr
; intr
= intr
->next
)
948 if (hostname_isequal(a
->target
, intr
->name
))
950 struct crec
*aliasc
= safe_malloc(sizeof(struct crec
));
951 aliasc
->flags
= F_FORWARD
| F_NAMEP
| F_CNAME
| F_IMMORTAL
| F_CONFIG
;
952 aliasc
->name
.namep
= a
->alias
;
953 aliasc
->addr
.cname
.target
.int_name
= intr
;
954 aliasc
->addr
.cname
.uid
= -1;
956 add_hosts_cname(aliasc
); /* handle chains */
959 /* borrow the packet buffer for a temporary by-address hash */
960 memset(daemon
->packet
, 0, daemon
->packet_buff_sz
);
961 revhashsz
= daemon
->packet_buff_sz
/ sizeof(struct crec
*);
962 /* we overwrote the buffer... */
963 daemon
->srv_save
= NULL
;
965 /* Do host_records in config. */
966 for (hr
= daemon
->host_records
; hr
; hr
= hr
->next
)
967 for (nl
= hr
->names
; nl
; nl
= nl
->next
)
969 if (hr
->addr
.s_addr
!= 0 &&
970 (cache
= whine_malloc(sizeof(struct crec
))))
972 cache
->name
.namep
= nl
->name
;
973 cache
->flags
= F_HOSTS
| F_IMMORTAL
| F_FORWARD
| F_REVERSE
| F_IPV4
| F_NAMEP
| F_CONFIG
;
974 add_hosts_entry(cache
, (struct all_addr
*)&hr
->addr
, INADDRSZ
, 0, (struct crec
**)daemon
->packet
, revhashsz
);
977 if (!IN6_IS_ADDR_UNSPECIFIED(&hr
->addr6
) &&
978 (cache
= whine_malloc(sizeof(struct crec
))))
980 cache
->name
.namep
= nl
->name
;
981 cache
->flags
= F_HOSTS
| F_IMMORTAL
| F_FORWARD
| F_REVERSE
| F_IPV6
| F_NAMEP
| F_CONFIG
;
982 add_hosts_entry(cache
, (struct all_addr
*)&hr
->addr6
, IN6ADDRSZ
, 0, (struct crec
**)daemon
->packet
, revhashsz
);
987 if (option_bool(OPT_NO_HOSTS
) && !daemon
->addn_hosts
)
989 if (daemon
->cachesize
> 0)
990 my_syslog(LOG_INFO
, _("cleared cache"));
994 if (!option_bool(OPT_NO_HOSTS
))
995 total_size
= read_hostsfile(HOSTSFILE
, 0, total_size
, (struct crec
**)daemon
->packet
, revhashsz
);
997 daemon
->addn_hosts
= expand_filelist(daemon
->addn_hosts
);
998 for (ah
= daemon
->addn_hosts
; ah
; ah
= ah
->next
)
999 if (!(ah
->flags
& AH_INACTIVE
))
1000 total_size
= read_hostsfile(ah
->fname
, ah
->index
, total_size
, (struct crec
**)daemon
->packet
, revhashsz
);
1004 struct in_addr
a_record_from_hosts(char *name
, time_t now
)
1006 struct crec
*crecp
= NULL
;
1009 while ((crecp
= cache_find_by_name(crecp
, name
, now
, F_IPV4
)))
1010 if (crecp
->flags
& F_HOSTS
)
1011 return *(struct in_addr
*)&crecp
->addr
;
1013 my_syslog(MS_DHCP
| LOG_WARNING
, _("No IPv4 address found for %s"), name
);
1019 void cache_unhash_dhcp(void)
1021 struct crec
*cache
, **up
;
1024 for (i
=0; i
<hash_size
; i
++)
1025 for (cache
= hash_table
[i
], up
= &hash_table
[i
]; cache
; cache
= cache
->hash_next
)
1026 if (cache
->flags
& F_DHCP
)
1028 *up
= cache
->hash_next
;
1029 cache
->next
= dhcp_spare
;
1033 up
= &cache
->hash_next
;
1036 static void add_dhcp_cname(struct crec
*target
, time_t ttd
)
1038 struct crec
*aliasc
;
1041 for (a
= daemon
->cnames
; a
; a
= a
->next
)
1042 if (hostname_isequal(cache_get_name(target
), a
->target
))
1044 if ((aliasc
= dhcp_spare
))
1045 dhcp_spare
= dhcp_spare
->next
;
1046 else /* need new one */
1047 aliasc
= whine_malloc(sizeof(struct crec
));
1051 aliasc
->flags
= F_FORWARD
| F_NAMEP
| F_DHCP
| F_CNAME
| F_CONFIG
;
1053 aliasc
->flags
|= F_IMMORTAL
;
1056 aliasc
->name
.namep
= a
->alias
;
1057 aliasc
->addr
.cname
.target
.cache
= target
;
1058 aliasc
->addr
.cname
.uid
= target
->uid
;
1060 add_dhcp_cname(aliasc
, ttd
);
1065 void cache_add_dhcp_entry(char *host_name
, int prot
,
1066 struct all_addr
*host_address
, time_t ttd
)
1068 struct crec
*crec
= NULL
, *fail_crec
= NULL
;
1069 unsigned short flags
= F_IPV4
;
1071 size_t addrlen
= sizeof(struct in_addr
);
1074 if (prot
== AF_INET6
)
1077 addrlen
= sizeof(struct in6_addr
);
1081 inet_ntop(prot
, host_address
, daemon
->addrbuff
, ADDRSTRLEN
);
1083 while ((crec
= cache_find_by_name(crec
, host_name
, 0, flags
| F_CNAME
)))
1085 /* check all addresses associated with name */
1086 if (crec
->flags
& F_HOSTS
)
1088 if (crec
->flags
& F_CNAME
)
1089 my_syslog(MS_DHCP
| LOG_WARNING
,
1090 _("%s is a CNAME, not giving it to the DHCP lease of %s"),
1091 host_name
, daemon
->addrbuff
);
1092 else if (memcmp(&crec
->addr
.addr
, host_address
, addrlen
) == 0)
1097 else if (!(crec
->flags
& F_DHCP
))
1099 cache_scan_free(host_name
, NULL
, 0, crec
->flags
& (flags
| F_CNAME
| F_FORWARD
));
1100 /* scan_free deletes all addresses associated with name */
1105 /* if in hosts, don't need DHCP record */
1109 /* Name in hosts, address doesn't match */
1112 inet_ntop(prot
, &fail_crec
->addr
.addr
, daemon
->namebuff
, MAXDNAME
);
1113 my_syslog(MS_DHCP
| LOG_WARNING
,
1114 _("not giving name %s to the DHCP lease of %s because "
1115 "the name exists in %s with address %s"),
1116 host_name
, daemon
->addrbuff
,
1117 record_source(fail_crec
->uid
), daemon
->namebuff
);
1121 if ((crec
= cache_find_by_addr(NULL
, (struct all_addr
*)host_address
, 0, flags
)))
1123 if (crec
->flags
& F_NEG
)
1126 cache_scan_free(NULL
, (struct all_addr
*)host_address
, 0, flags
);
1132 if ((crec
= dhcp_spare
))
1133 dhcp_spare
= dhcp_spare
->next
;
1134 else /* need new one */
1135 crec
= whine_malloc(sizeof(struct crec
));
1137 if (crec
) /* malloc may fail */
1139 crec
->flags
= flags
| F_NAMEP
| F_DHCP
| F_FORWARD
;
1141 crec
->flags
|= F_IMMORTAL
;
1144 crec
->addr
.addr
= *host_address
;
1145 crec
->name
.namep
= host_name
;
1149 add_dhcp_cname(crec
, ttd
);
1155 void dump_cache(time_t now
)
1157 struct server
*serv
, *serv1
;
1159 my_syslog(LOG_INFO
, _("time %lu"), (unsigned long)now
);
1160 my_syslog(LOG_INFO
, _("cache size %d, %d/%d cache insertions re-used unexpired cache entries."),
1161 daemon
->cachesize
, cache_live_freed
, cache_inserted
);
1162 my_syslog(LOG_INFO
, _("queries forwarded %u, queries answered locally %u"),
1163 daemon
->queries_forwarded
, daemon
->local_answer
);
1165 my_syslog(LOG_INFO
, _("queries for authoritative zones %u"), daemon
->auth_answer
);
1168 /* sum counts from different records for same server */
1169 for (serv
= daemon
->servers
; serv
; serv
= serv
->next
)
1170 serv
->flags
&= ~SERV_COUNTED
;
1172 for (serv
= daemon
->servers
; serv
; serv
= serv
->next
)
1174 (SERV_NO_ADDR
| SERV_LITERAL_ADDRESS
| SERV_COUNTED
| SERV_USE_RESOLV
| SERV_NO_REBIND
)))
1177 unsigned int queries
= 0, failed_queries
= 0;
1178 for (serv1
= serv
; serv1
; serv1
= serv1
->next
)
1179 if (!(serv1
->flags
&
1180 (SERV_NO_ADDR
| SERV_LITERAL_ADDRESS
| SERV_COUNTED
| SERV_USE_RESOLV
| SERV_NO_REBIND
)) &&
1181 sockaddr_isequal(&serv
->addr
, &serv1
->addr
))
1183 serv1
->flags
|= SERV_COUNTED
;
1184 queries
+= serv1
->queries
;
1185 failed_queries
+= serv1
->failed_queries
;
1187 port
= prettyprint_addr(&serv
->addr
, daemon
->addrbuff
);
1188 my_syslog(LOG_INFO
, _("server %s#%d: queries sent %u, retried or failed %u"), daemon
->addrbuff
, port
, queries
, failed_queries
);
1191 if (option_bool(OPT_DEBUG
) || option_bool(OPT_LOG
))
1193 struct crec
*cache
;
1195 my_syslog(LOG_INFO
, "Host Address Flags Expires");
1197 for (i
=0; i
<hash_size
; i
++)
1198 for (cache
= hash_table
[i
]; cache
; cache
= cache
->hash_next
)
1200 char *a
, *p
= daemon
->namebuff
;
1201 p
+= sprintf(p
, "%-40.40s ", cache_get_name(cache
));
1202 if ((cache
->flags
& F_NEG
) && (cache
->flags
& F_FORWARD
))
1204 else if (cache
->flags
& F_CNAME
)
1207 if (!is_outdated_cname_pointer(cache
))
1208 a
= cache_get_cname_target(cache
);
1211 else if (cache
->flags
& F_DNSKEY
)
1213 a
= daemon
->addrbuff
;
1214 sprintf(a
, "%3u %u", cache
->addr
.key
.algo
, cache
->uid
);
1216 else if (cache
->flags
& F_DS
)
1218 a
= daemon
->addrbuff
;
1219 sprintf(a
, "%5u %3u %3u %u", cache
->addr
.key
.flags_or_keyid
,
1220 cache
->addr
.key
.algo
, cache
->addr
.key
.digest
, cache
->uid
);
1225 a
= daemon
->addrbuff
;
1226 if (cache
->flags
& F_IPV4
)
1227 inet_ntop(AF_INET
, &cache
->addr
.addr
, a
, ADDRSTRLEN
);
1229 else if (cache
->flags
& F_IPV6
)
1230 inet_ntop(AF_INET6
, &cache
->addr
.addr
, a
, ADDRSTRLEN
);
1234 p
+= sprintf(p
, "%-30.30s %s%s%s%s%s%s%s%s%s%s%s%s%s ", a
,
1235 cache
->flags
& F_IPV4
? "4" : "",
1236 cache
->flags
& F_IPV6
? "6" : "",
1237 cache
->flags
& F_DNSKEY
? "K" : "",
1238 cache
->flags
& F_DS
? "S" : "",
1239 cache
->flags
& F_CNAME
? "C" : "",
1240 cache
->flags
& F_FORWARD
? "F" : " ",
1241 cache
->flags
& F_REVERSE
? "R" : " ",
1242 cache
->flags
& F_IMMORTAL
? "I" : " ",
1243 cache
->flags
& F_DHCP
? "D" : " ",
1244 cache
->flags
& F_NEG
? "N" : " ",
1245 cache
->flags
& F_NXDOMAIN
? "X" : " ",
1246 cache
->flags
& F_HOSTS
? "H" : " ",
1247 cache
->flags
& F_DNSSECOK
? "V" : " ");
1248 #ifdef HAVE_BROKEN_RTC
1249 p
+= sprintf(p
, "%lu", cache
->flags
& F_IMMORTAL
? 0: (unsigned long)(cache
->ttd
- now
));
1251 p
+= sprintf(p
, "%s", cache
->flags
& F_IMMORTAL
? "\n" : ctime(&(cache
->ttd
)));
1252 /* ctime includes trailing \n - eat it */
1255 my_syslog(LOG_INFO
, daemon
->namebuff
);
1260 char *record_source(int index
)
1262 struct hostsfile
*ah
;
1267 for (ah
= daemon
->addn_hosts
; ah
; ah
= ah
->next
)
1268 if (ah
->index
== index
)
1274 void querystr(char *desc
, char *str
, unsigned short type
)
1278 sprintf(str
, "%s[type=%d]", desc
, type
);
1279 for (i
= 0; i
< (sizeof(typestr
)/sizeof(typestr
[0])); i
++)
1280 if (typestr
[i
].type
== type
)
1281 sprintf(str
,"%s[%s]", desc
, typestr
[i
].name
);
1284 void log_query(unsigned int flags
, char *name
, struct all_addr
*addr
, char *arg
)
1286 char *source
, *dest
= daemon
->addrbuff
;
1289 if (!option_bool(OPT_LOG
))
1295 inet_ntop(flags
& F_IPV4
? AF_INET
: AF_INET6
,
1296 addr
, daemon
->addrbuff
, ADDRSTRLEN
);
1298 strncpy(daemon
->addrbuff
, inet_ntoa(addr
->addr
.addr4
), ADDRSTRLEN
);
1302 if (flags
& F_REVERSE
)
1305 name
= daemon
->addrbuff
;
1310 if (flags
& F_NXDOMAIN
)
1313 dest
= "NXDOMAIN-IPv4";
1314 else if (flags
& F_IPV6
)
1315 dest
= "NXDOMAIN-IPv6";
1322 dest
= "NODATA-IPv4";
1323 else if (flags
& F_IPV6
)
1324 dest
= "NODATA-IPv6";
1329 else if (flags
& F_CNAME
)
1331 else if (flags
& F_RRNAME
)
1334 if (flags
& F_CONFIG
)
1336 else if (flags
& F_DHCP
)
1338 else if (flags
& F_HOSTS
)
1340 else if (flags
& F_UPSTREAM
)
1342 else if (flags
& F_AUTH
)
1344 else if (flags
& F_SERVER
)
1346 source
= "forwarded";
1349 else if (flags
& F_QUERY
)
1357 if (strlen(name
) == 0)
1360 my_syslog(LOG_INFO
, "%s %s %s %s", source
, name
, verb
, dest
);
1364 struct keydata
*keydata_alloc(char *data
, size_t len
)
1366 struct keydata
*block
, *ret
= NULL
;
1367 struct keydata
**prev
= &ret
;
1372 block
= keyblock_free
;
1373 keyblock_free
= block
->next
;
1376 block
= whine_malloc(sizeof(struct keydata
));
1380 /* failed to alloc, free partial chain */
1385 memcpy(block
->key
, data
, len
> KEYBLOCK_LEN
? KEYBLOCK_LEN
: len
);
1386 data
+= KEYBLOCK_LEN
;
1387 len
-= KEYBLOCK_LEN
;
1389 prev
= &block
->next
;
1396 void keydata_free(struct keydata
*blocks
)
1398 struct keydata
*tmp
;
1402 for (tmp
= blocks
; tmp
->next
; tmp
= tmp
->next
);
1403 tmp
->next
= keyblock_free
;
1404 keyblock_free
= blocks
;