]>
git.ipfire.org Git - people/ms/dnsmasq.git/blob - src/cache.c
1 /* dnsmasq is Copyright (c) 2000-2012 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. */
182 cache_tail
->next
= crecp
;
185 crecp
->prev
= cache_tail
;
189 /* retrieve big name for further use. */
190 if (crecp
->flags
& F_BIGNAME
)
192 crecp
->name
.bname
->next
= big_free
;
193 big_free
= crecp
->name
.bname
;
194 crecp
->flags
&= ~F_BIGNAME
;
197 else if (crecp
->flags
& (F_DNSKEY
| F_DS
))
198 keydata_free(crecp
->addr
.key
.keydata
);
202 /* insert a new cache entry at the head of the list (youngest entry) */
203 static void cache_link(struct crec
*crecp
)
205 if (cache_head
) /* check needed for init code */
206 cache_head
->prev
= crecp
;
207 crecp
->next
= cache_head
;
214 /* remove an arbitrary cache entry for promotion */
215 static void cache_unlink (struct crec
*crecp
)
218 crecp
->prev
->next
= crecp
->next
;
220 cache_head
= crecp
->next
;
223 crecp
->next
->prev
= crecp
->prev
;
225 cache_tail
= crecp
->prev
;
228 char *cache_get_name(struct crec
*crecp
)
230 if (crecp
->flags
& F_BIGNAME
)
231 return crecp
->name
.bname
->name
;
232 else if (crecp
->flags
& F_NAMEP
)
233 return crecp
->name
.namep
;
235 return crecp
->name
.sname
;
238 static int is_outdated_cname_pointer(struct crec
*crecp
)
240 if (!(crecp
->flags
& F_CNAME
))
243 /* NB. record may be reused as DS or DNSKEY, where uid is
244 overloaded for something completely different */
245 if (crecp
->addr
.cname
.cache
&&
246 (crecp
->addr
.cname
.cache
->flags
& (F_IPV4
| F_IPV6
| F_CNAME
)) &&
247 crecp
->addr
.cname
.uid
== crecp
->addr
.cname
.cache
->uid
)
253 static int is_expired(time_t now
, struct crec
*crecp
)
255 if (crecp
->flags
& F_IMMORTAL
)
258 if (difftime(now
, crecp
->ttd
) < 0)
264 static int cache_scan_free(char *name
, struct all_addr
*addr
, time_t now
, unsigned short flags
)
266 /* Scan and remove old entries.
267 If (flags & F_FORWARD) then remove any forward entries for name and any expired
268 entries but only in the same hash bucket as name.
269 If (flags & F_REVERSE) then remove any reverse entries for addr and any expired
270 entries in the whole cache.
271 If (flags == 0) remove any expired entries in the whole cache.
273 In the flags & F_FORWARD case, the return code is valid, and returns zero if the
274 name exists in the cache as a HOSTS or DHCP entry (these are never deleted)
276 We take advantage of the fact that hash chains have stuff in the order <reverse>,<other>,<immortal>
277 so that when we hit an entry which isn't reverse and is immortal, we're done. */
279 struct crec
*crecp
, **up
;
281 if (flags
& F_FORWARD
)
283 for (up
= hash_bucket(name
), crecp
= *up
; crecp
; crecp
= crecp
->hash_next
)
284 if (is_expired(now
, crecp
) || is_outdated_cname_pointer(crecp
))
286 *up
= crecp
->hash_next
;
287 if (!(crecp
->flags
& (F_HOSTS
| F_DHCP
)))
293 else if ((crecp
->flags
& F_FORWARD
) &&
294 ((flags
& crecp
->flags
& F_TYPE
) || ((crecp
->flags
| flags
) & F_CNAME
)) &&
295 hostname_isequal(cache_get_name(crecp
), name
))
297 if (crecp
->flags
& (F_HOSTS
| F_DHCP
))
299 *up
= crecp
->hash_next
;
304 up
= &crecp
->hash_next
;
310 int addrlen
= (flags
& F_IPV6
) ? IN6ADDRSZ
: INADDRSZ
;
312 int addrlen
= INADDRSZ
;
314 for (i
= 0; i
< hash_size
; i
++)
315 for (crecp
= hash_table
[i
], up
= &hash_table
[i
];
316 crecp
&& ((crecp
->flags
& F_REVERSE
) || !(crecp
->flags
& F_IMMORTAL
));
317 crecp
= crecp
->hash_next
)
318 if (is_expired(now
, crecp
))
320 *up
= crecp
->hash_next
;
321 if (!(crecp
->flags
& (F_HOSTS
| F_DHCP
)))
327 else if (!(crecp
->flags
& (F_HOSTS
| F_DHCP
)) &&
328 (flags
& crecp
->flags
& F_REVERSE
) &&
329 (flags
& crecp
->flags
& (F_IPV4
| F_IPV6
)) &&
330 memcmp(&crecp
->addr
.addr
, addr
, addrlen
) == 0)
332 *up
= crecp
->hash_next
;
337 up
= &crecp
->hash_next
;
343 /* Note: The normal calling sequence is
348 but an abort can cause the cache_end_insert to be missed
349 in which can the next cache_start_insert cleans things up. */
351 void cache_start_insert(void)
353 /* Free any entries which didn't get committed during the last
358 struct crec
*tmp
= new_chain
->next
;
359 cache_free(new_chain
);
366 struct crec
*cache_insert(char *name
, struct all_addr
*addr
,
367 time_t now
, unsigned long ttl
, unsigned short flags
)
370 union bigname
*big_name
= NULL
;
371 int freed_all
= flags
& F_REVERSE
;
375 if (flags
& (F_IPV4
| F_IPV6
))
376 log_query(flags
| F_UPSTREAM
, name
, addr
, NULL
);
378 /* if previous insertion failed give up now. */
382 /* First remove any expired entries and entries for the name/address we
383 are currently inserting. Fail is we attempt to delete a name from
384 /etc/hosts or DHCP. */
385 if (!cache_scan_free(name
, addr
, now
, flags
))
391 /* Now get a cache entry from the end of the LRU list */
393 if (!(new = cache_tail
)) /* no entries left - cache is too small, bail */
399 /* End of LRU list is still in use: if we didn't scan all the hash
400 chains for expired entries do that now. If we already tried that
401 then it's time to start spilling things. */
403 if (new->flags
& (F_FORWARD
| F_REVERSE
))
405 /* If free_avail set, we believe that an entry has been freed.
406 Bugs have been known to make this not true, resulting in
407 a tight loop here. If that happens, abandon the
408 insert. Once in this state, all inserts will probably fail. */
417 free_avail
= 1; /* Must be free space now. */
418 cache_scan_free(cache_get_name(new), &new->addr
.addr
, now
, new->flags
);
423 cache_scan_free(NULL
, NULL
, now
, 0);
429 /* Check if we need to and can allocate extra memory for a long name.
430 If that fails, give up now. */
431 if (name
&& (strlen(name
) > SMALLDNAME
-1))
436 big_free
= big_free
->next
;
438 else if (!bignames_left
||
439 !(big_name
= (union bigname
*)whine_malloc(sizeof(union bigname
))))
449 /* Got the rest: finally grab entry. */
457 new->name
.bname
= big_name
;
458 new->flags
|= F_BIGNAME
;
462 strcpy(cache_get_name(new), name
);
464 *cache_get_name(new) = 0;
467 new->addr
.addr
= *addr
;
469 new->ttd
= now
+ (time_t)ttl
;
470 new->next
= new_chain
;
476 /* after end of insertion, commit the new entries */
477 void cache_end_insert(void)
484 struct crec
*tmp
= new_chain
->next
;
485 /* drop CNAMEs which didn't find a target. */
486 if (is_outdated_cname_pointer(new_chain
))
487 cache_free(new_chain
);
490 cache_hash(new_chain
);
491 cache_link(new_chain
);
499 struct crec
*cache_find_by_name(struct crec
*crecp
, char *name
, time_t now
, unsigned short prot
)
503 if (crecp
) /* iterating */
507 /* first search, look for relevant entries and push to top of list
508 also free anything which has expired */
509 struct crec
*next
, **up
, **insert
= NULL
, **chainp
= &ans
;
510 unsigned short ins_flags
= 0;
512 for (up
= hash_bucket(name
), crecp
= *up
; crecp
; crecp
= next
)
514 next
= crecp
->hash_next
;
516 if (!is_expired(now
, crecp
) && !is_outdated_cname_pointer(crecp
))
518 if ((crecp
->flags
& F_FORWARD
) &&
519 (crecp
->flags
& prot
) &&
520 hostname_isequal(cache_get_name(crecp
), name
))
522 if (crecp
->flags
& (F_HOSTS
| F_DHCP
))
525 chainp
= &crecp
->next
;
533 /* Move all but the first entry up the hash chain
534 this implements round-robin.
535 Make sure that re-ordering doesn't break the hash-chain
538 if (insert
&& (crecp
->flags
& (F_REVERSE
| F_IMMORTAL
)) == ins_flags
)
540 *up
= crecp
->hash_next
;
541 crecp
->hash_next
= *insert
;
543 insert
= &crecp
->hash_next
;
550 ins_flags
= crecp
->flags
& (F_REVERSE
| F_IMMORTAL
);
552 up
= &crecp
->hash_next
;
556 /* case : not expired, incorrect entry. */
557 up
= &crecp
->hash_next
;
561 /* expired entry, free it */
562 *up
= crecp
->hash_next
;
563 if (!(crecp
->flags
& (F_HOSTS
| F_DHCP
)))
571 *chainp
= cache_head
;
575 (ans
->flags
& F_FORWARD
) &&
576 (ans
->flags
& prot
) &&
577 hostname_isequal(cache_get_name(ans
), name
))
583 struct crec
*cache_find_by_addr(struct crec
*crecp
, struct all_addr
*addr
,
584 time_t now
, unsigned short prot
)
588 int addrlen
= (prot
== F_IPV6
) ? IN6ADDRSZ
: INADDRSZ
;
590 int addrlen
= INADDRSZ
;
593 if (crecp
) /* iterating */
597 /* first search, look for relevant entries and push to top of list
598 also free anything which has expired. All the reverse entries are at the
599 start of the hash chain, so we can give up when we find the first
602 struct crec
**up
, **chainp
= &ans
;
604 for (i
=0; i
<hash_size
; i
++)
605 for (crecp
= hash_table
[i
], up
= &hash_table
[i
];
606 crecp
&& (crecp
->flags
& F_REVERSE
);
607 crecp
= crecp
->hash_next
)
608 if (!is_expired(now
, crecp
))
610 if ((crecp
->flags
& prot
) &&
611 memcmp(&crecp
->addr
.addr
, addr
, addrlen
) == 0)
613 if (crecp
->flags
& (F_HOSTS
| F_DHCP
))
616 chainp
= &crecp
->next
;
624 up
= &crecp
->hash_next
;
628 *up
= crecp
->hash_next
;
629 if (!(crecp
->flags
& (F_HOSTS
| F_DHCP
)))
636 *chainp
= cache_head
;
640 (ans
->flags
& F_REVERSE
) &&
641 (ans
->flags
& prot
) &&
642 memcmp(&ans
->addr
.addr
, addr
, addrlen
) == 0)
648 static void add_hosts_cname(struct crec
*target
)
653 for (a
= daemon
->cnames
; a
; a
= a
->next
)
654 if (hostname_isequal(cache_get_name(target
), a
->target
) &&
655 (crec
= whine_malloc(sizeof(struct crec
))))
657 crec
->flags
= F_FORWARD
| F_IMMORTAL
| F_NAMEP
| F_HOSTS
| F_CNAME
;
658 crec
->name
.namep
= a
->alias
;
659 crec
->addr
.cname
.cache
= target
;
660 crec
->addr
.cname
.uid
= target
->uid
;
662 add_hosts_cname(crec
); /* handle chains */
666 static void add_hosts_entry(struct crec
*cache
, struct all_addr
*addr
, int addrlen
,
667 int index
, struct crec
**rhash
, int hashsz
)
669 struct crec
*lookup
= cache_find_by_name(NULL
, cache_get_name(cache
), 0, cache
->flags
& (F_IPV4
| F_IPV6
));
670 int i
, nameexists
= 0;
673 /* Remove duplicates in hosts files. */
674 if (lookup
&& (lookup
->flags
& F_HOSTS
))
677 if (memcmp(&lookup
->addr
.addr
, addr
, addrlen
) == 0)
684 /* Ensure there is only one address -> name mapping (first one trumps)
685 We do this by steam here, The entries are kept in hash chains, linked
686 by ->next (which is unused at this point) held in hash buckets in
687 the array rhash, hashed on address. Note that rhash and the values
688 in ->next are only valid whilst reading hosts files: the buckets are
689 then freed, and the ->next pointer used for other things.
691 Only insert each unique address once into this hashing structure.
693 This complexity avoids O(n^2) divergent CPU use whilst reading
694 large (10000 entry) hosts files. */
697 for (j
= 0, i
= 0; i
< addrlen
; i
++)
698 j
= (j
*2 +((unsigned char *)addr
)[i
]) % hashsz
;
700 for (lookup
= rhash
[j
]; lookup
; lookup
= lookup
->next
)
701 if ((lookup
->flags
& cache
->flags
& (F_IPV4
| F_IPV6
)) &&
702 memcmp(&lookup
->addr
.addr
, addr
, addrlen
) == 0)
704 cache
->flags
&= ~F_REVERSE
;
708 /* maintain address hash chain, insert new unique address */
711 cache
->next
= rhash
[j
];
716 memcpy(&cache
->addr
.addr
, addr
, addrlen
);
719 /* don't need to do alias stuff for second and subsequent addresses. */
721 add_hosts_cname(cache
);
724 static int eatspace(FILE *f
)
730 if ((c
= getc(f
)) == '#')
731 while (c
!= '\n' && c
!= EOF
)
748 static int gettok(FILE *f
, char *token
)
754 if ((c
= getc(f
)) == EOF
)
755 return (count
== 0) ? EOF
: 1;
757 if (isspace(c
) || c
== '#')
763 if (count
< (MAXDNAME
- 1))
771 static int read_hostsfile(char *filename
, int index
, int cache_size
, struct crec
**rhash
, int hashsz
)
773 FILE *f
= fopen(filename
, "r");
774 char *token
= daemon
->namebuff
, *domain_suffix
= NULL
;
775 int addr_count
= 0, name_count
= cache_size
, lineno
= 0;
776 unsigned short flags
= 0;
777 struct all_addr addr
;
778 int atnl
, addrlen
= 0;
782 my_syslog(LOG_ERR
, _("failed to load names from %s: %s"), filename
, strerror(errno
));
788 while ((atnl
= gettok(f
, token
)) != EOF
)
792 if (inet_pton(AF_INET
, token
, &addr
) > 0)
794 flags
= F_HOSTS
| F_IMMORTAL
| F_FORWARD
| F_REVERSE
| F_IPV4
;
796 domain_suffix
= get_domain(addr
.addr
.addr4
);
799 else if (inet_pton(AF_INET6
, token
, &addr
) > 0)
801 flags
= F_HOSTS
| F_IMMORTAL
| F_FORWARD
| F_REVERSE
| F_IPV6
;
803 domain_suffix
= get_domain6(&addr
.addr
.addr6
);
808 my_syslog(LOG_ERR
, _("bad address at %s line %d"), filename
, lineno
);
810 atnl
= gettok(f
, token
);
816 /* rehash every 1000 names. */
817 if ((name_count
- cache_size
) > 1000)
820 cache_size
= name_count
;
829 if ((atnl
= gettok(f
, token
)) == EOF
)
832 fqdn
= !!strchr(token
, '.');
834 if ((canon
= canonicalise(token
, &nomem
)))
836 /* If set, add a version of the name with a default domain appended */
837 if (option_bool(OPT_EXPAND
) && domain_suffix
&& !fqdn
&&
838 (cache
= whine_malloc(sizeof(struct crec
) +
839 strlen(canon
)+2+strlen(domain_suffix
)-SMALLDNAME
)))
841 strcpy(cache
->name
.sname
, canon
);
842 strcat(cache
->name
.sname
, ".");
843 strcat(cache
->name
.sname
, domain_suffix
);
844 cache
->flags
= flags
;
845 add_hosts_entry(cache
, &addr
, addrlen
, index
, rhash
, hashsz
);
848 if ((cache
= whine_malloc(sizeof(struct crec
) + strlen(canon
)+1-SMALLDNAME
)))
850 strcpy(cache
->name
.sname
, canon
);
851 cache
->flags
= flags
;
852 add_hosts_entry(cache
, &addr
, addrlen
, index
, rhash
, hashsz
);
859 my_syslog(LOG_ERR
, _("bad name at %s line %d"), filename
, lineno
);
866 my_syslog(LOG_INFO
, _("read %s - %d addresses"), filename
, addr_count
);
871 void cache_reload(void)
873 struct crec
*cache
, **up
, *tmp
;
874 int revhashsz
, i
, total_size
= daemon
->cachesize
;
875 struct hostsfile
*ah
;
876 struct host_record
*hr
;
877 struct name_list
*nl
;
879 cache_inserted
= cache_live_freed
= 0;
881 for (i
=0; i
<hash_size
; i
++)
882 for (cache
= hash_table
[i
], up
= &hash_table
[i
]; cache
; cache
= tmp
)
884 tmp
= cache
->hash_next
;
885 if (cache
->flags
& F_HOSTS
)
887 *up
= cache
->hash_next
;
890 else if (!(cache
->flags
& F_DHCP
))
892 *up
= cache
->hash_next
;
893 if (cache
->flags
& F_BIGNAME
)
895 cache
->name
.bname
->next
= big_free
;
896 big_free
= cache
->name
.bname
;
901 up
= &cache
->hash_next
;
904 /* borrow the packet buffer for a temporary by-address hash */
905 memset(daemon
->packet
, 0, daemon
->packet_buff_sz
);
906 revhashsz
= daemon
->packet_buff_sz
/ sizeof(struct crec
*);
907 /* we overwrote the buffer... */
908 daemon
->srv_save
= NULL
;
910 /* Do host_records in config. */
911 for (hr
= daemon
->host_records
; hr
; hr
= hr
->next
)
912 for (nl
= hr
->names
; nl
; nl
= nl
->next
)
914 if (hr
->addr
.s_addr
!= 0 &&
915 (cache
= whine_malloc(sizeof(struct crec
))))
917 cache
->name
.namep
= nl
->name
;
918 cache
->flags
= F_HOSTS
| F_IMMORTAL
| F_FORWARD
| F_REVERSE
| F_IPV4
| F_NAMEP
| F_CONFIG
;
919 add_hosts_entry(cache
, (struct all_addr
*)&hr
->addr
, INADDRSZ
, 0, (struct crec
**)daemon
->packet
, revhashsz
);
922 if (!IN6_IS_ADDR_UNSPECIFIED(&hr
->addr6
) &&
923 (cache
= whine_malloc(sizeof(struct crec
))))
925 cache
->name
.namep
= nl
->name
;
926 cache
->flags
= F_HOSTS
| F_IMMORTAL
| F_FORWARD
| F_REVERSE
| F_IPV6
| F_NAMEP
| F_CONFIG
;
927 add_hosts_entry(cache
, (struct all_addr
*)&hr
->addr6
, IN6ADDRSZ
, 0, (struct crec
**)daemon
->packet
, revhashsz
);
932 if (option_bool(OPT_NO_HOSTS
) && !daemon
->addn_hosts
)
934 if (daemon
->cachesize
> 0)
935 my_syslog(LOG_INFO
, _("cleared cache"));
939 if (!option_bool(OPT_NO_HOSTS
))
940 total_size
= read_hostsfile(HOSTSFILE
, 0, total_size
, (struct crec
**)daemon
->packet
, revhashsz
);
942 daemon
->addn_hosts
= expand_filelist(daemon
->addn_hosts
);
943 for (ah
= daemon
->addn_hosts
; ah
; ah
= ah
->next
)
944 if (!(ah
->flags
& AH_INACTIVE
))
945 total_size
= read_hostsfile(ah
->fname
, ah
->index
, total_size
, (struct crec
**)daemon
->packet
, revhashsz
);
948 char *get_domain(struct in_addr addr
)
950 struct cond_domain
*c
;
952 for (c
= daemon
->cond_domain
; c
; c
= c
->next
)
954 ntohl(addr
.s_addr
) >= ntohl(c
->start
.s_addr
) &&
955 ntohl(addr
.s_addr
) <= ntohl(c
->end
.s_addr
))
958 return daemon
->domain_suffix
;
963 char *get_domain6(struct in6_addr
*addr
)
965 struct cond_domain
*c
;
967 u64 addrpart
= addr6part(addr
);
969 for (c
= daemon
->cond_domain
; c
; c
= c
->next
)
971 is_same_net6(addr
, &c
->start6
, 64) &&
972 addrpart
>= addr6part(&c
->start6
) &&
973 addrpart
<= addr6part(&c
->end6
))
976 return daemon
->domain_suffix
;
981 struct in_addr
a_record_from_hosts(char *name
, time_t now
)
983 struct crec
*crecp
= NULL
;
986 while ((crecp
= cache_find_by_name(crecp
, name
, now
, F_IPV4
)))
987 if (crecp
->flags
& F_HOSTS
)
988 return *(struct in_addr
*)&crecp
->addr
;
990 my_syslog(MS_DHCP
| LOG_WARNING
, _("No IPv4 address found for %s"), name
);
996 void cache_unhash_dhcp(void)
998 struct crec
*cache
, **up
;
1001 for (i
=0; i
<hash_size
; i
++)
1002 for (cache
= hash_table
[i
], up
= &hash_table
[i
]; cache
; cache
= cache
->hash_next
)
1003 if (cache
->flags
& F_DHCP
)
1005 *up
= cache
->hash_next
;
1006 cache
->next
= dhcp_spare
;
1010 up
= &cache
->hash_next
;
1013 static void add_dhcp_cname(struct crec
*target
, time_t ttd
)
1015 struct crec
*aliasc
;
1018 for (a
= daemon
->cnames
; a
; a
= a
->next
)
1019 if (hostname_isequal(cache_get_name(target
), a
->target
))
1021 if ((aliasc
= dhcp_spare
))
1022 dhcp_spare
= dhcp_spare
->next
;
1023 else /* need new one */
1024 aliasc
= whine_malloc(sizeof(struct crec
));
1028 aliasc
->flags
= F_FORWARD
| F_NAMEP
| F_DHCP
| F_CNAME
;
1030 aliasc
->flags
|= F_IMMORTAL
;
1033 aliasc
->name
.namep
= a
->alias
;
1034 aliasc
->addr
.cname
.cache
= target
;
1035 aliasc
->addr
.cname
.uid
= target
->uid
;
1037 add_dhcp_cname(aliasc
, ttd
);
1042 void cache_add_dhcp_entry(char *host_name
, int prot
,
1043 struct all_addr
*host_address
, time_t ttd
)
1045 struct crec
*crec
= NULL
, *fail_crec
= NULL
;
1046 unsigned short flags
= F_IPV4
;
1048 size_t addrlen
= sizeof(struct in_addr
);
1051 if (prot
== AF_INET6
)
1054 addrlen
= sizeof(struct in6_addr
);
1058 inet_ntop(prot
, host_address
, daemon
->addrbuff
, ADDRSTRLEN
);
1060 while ((crec
= cache_find_by_name(crec
, host_name
, 0, flags
| F_CNAME
)))
1062 /* check all addresses associated with name */
1063 if (crec
->flags
& F_HOSTS
)
1065 if (crec
->flags
& F_CNAME
)
1066 my_syslog(MS_DHCP
| LOG_WARNING
,
1067 _("%s is a CNAME, not giving it to the DHCP lease of %s"),
1068 host_name
, daemon
->addrbuff
);
1069 else if (memcmp(&crec
->addr
.addr
, host_address
, addrlen
) == 0)
1074 else if (!(crec
->flags
& F_DHCP
))
1076 cache_scan_free(host_name
, NULL
, 0, crec
->flags
& (flags
| F_CNAME
| F_FORWARD
));
1077 /* scan_free deletes all addresses associated with name */
1082 /* if in hosts, don't need DHCP record */
1086 /* Name in hosts, address doesn't match */
1089 inet_ntop(prot
, &fail_crec
->addr
.addr
, daemon
->namebuff
, MAXDNAME
);
1090 my_syslog(MS_DHCP
| LOG_WARNING
,
1091 _("not giving name %s to the DHCP lease of %s because "
1092 "the name exists in %s with address %s"),
1093 host_name
, daemon
->addrbuff
,
1094 record_source(fail_crec
->uid
), daemon
->namebuff
);
1098 if ((crec
= cache_find_by_addr(NULL
, (struct all_addr
*)host_address
, 0, flags
)))
1100 if (crec
->flags
& F_NEG
)
1103 cache_scan_free(NULL
, (struct all_addr
*)host_address
, 0, flags
);
1109 if ((crec
= dhcp_spare
))
1110 dhcp_spare
= dhcp_spare
->next
;
1111 else /* need new one */
1112 crec
= whine_malloc(sizeof(struct crec
));
1114 if (crec
) /* malloc may fail */
1116 crec
->flags
= flags
| F_NAMEP
| F_DHCP
| F_FORWARD
;
1118 crec
->flags
|= F_IMMORTAL
;
1121 crec
->addr
.addr
= *host_address
;
1122 crec
->name
.namep
= host_name
;
1126 add_dhcp_cname(crec
, ttd
);
1132 void dump_cache(time_t now
)
1134 struct server
*serv
, *serv1
;
1136 my_syslog(LOG_INFO
, _("time %lu"), (unsigned long)now
);
1137 my_syslog(LOG_INFO
, _("cache size %d, %d/%d cache insertions re-used unexpired cache entries."),
1138 daemon
->cachesize
, cache_live_freed
, cache_inserted
);
1139 my_syslog(LOG_INFO
, _("queries forwarded %u, queries answered locally %u"),
1140 daemon
->queries_forwarded
, daemon
->local_answer
);
1142 /* sum counts from different records for same server */
1143 for (serv
= daemon
->servers
; serv
; serv
= serv
->next
)
1144 serv
->flags
&= ~SERV_COUNTED
;
1146 for (serv
= daemon
->servers
; serv
; serv
= serv
->next
)
1148 (SERV_NO_ADDR
| SERV_LITERAL_ADDRESS
| SERV_COUNTED
| SERV_USE_RESOLV
| SERV_NO_REBIND
)))
1151 unsigned int queries
= 0, failed_queries
= 0;
1152 for (serv1
= serv
; serv1
; serv1
= serv1
->next
)
1153 if (!(serv1
->flags
&
1154 (SERV_NO_ADDR
| SERV_LITERAL_ADDRESS
| SERV_COUNTED
| SERV_USE_RESOLV
| SERV_NO_REBIND
)) &&
1155 sockaddr_isequal(&serv
->addr
, &serv1
->addr
))
1157 serv1
->flags
|= SERV_COUNTED
;
1158 queries
+= serv1
->queries
;
1159 failed_queries
+= serv1
->failed_queries
;
1161 port
= prettyprint_addr(&serv
->addr
, daemon
->addrbuff
);
1162 my_syslog(LOG_INFO
, _("server %s#%d: queries sent %u, retried or failed %u"), daemon
->addrbuff
, port
, queries
, failed_queries
);
1165 if (option_bool(OPT_DEBUG
) || option_bool(OPT_LOG
))
1167 struct crec
*cache
;
1169 my_syslog(LOG_INFO
, "Host Address Flags Expires");
1171 for (i
=0; i
<hash_size
; i
++)
1172 for (cache
= hash_table
[i
]; cache
; cache
= cache
->hash_next
)
1174 char *a
, *p
= daemon
->namebuff
;
1175 p
+= sprintf(p
, "%-40.40s ", cache_get_name(cache
));
1176 if ((cache
->flags
& F_NEG
) && (cache
->flags
& F_FORWARD
))
1178 else if (cache
->flags
& F_CNAME
)
1181 if (!is_outdated_cname_pointer(cache
))
1182 a
= cache_get_name(cache
->addr
.cname
.cache
);
1185 else if (cache
->flags
& F_DNSKEY
)
1187 a
= daemon
->addrbuff
;
1188 sprintf(a
, "%3u %u", cache
->addr
.key
.algo
, cache
->uid
);
1190 else if (cache
->flags
& F_DS
)
1192 a
= daemon
->addrbuff
;
1193 sprintf(a
, "%5u %3u %3u %u", cache
->addr
.key
.flags_or_keyid
,
1194 cache
->addr
.key
.algo
, cache
->addr
.key
.digest
, cache
->uid
);
1199 a
= daemon
->addrbuff
;
1200 if (cache
->flags
& F_IPV4
)
1201 inet_ntop(AF_INET
, &cache
->addr
.addr
, a
, ADDRSTRLEN
);
1203 else if (cache
->flags
& F_IPV6
)
1204 inet_ntop(AF_INET6
, &cache
->addr
.addr
, a
, ADDRSTRLEN
);
1208 p
+= sprintf(p
, "%-30.30s %s%s%s%s%s%s%s%s%s%s%s%s%s ", a
,
1209 cache
->flags
& F_IPV4
? "4" : "",
1210 cache
->flags
& F_IPV6
? "6" : "",
1211 cache
->flags
& F_DNSKEY
? "K" : "",
1212 cache
->flags
& F_DS
? "S" : "",
1213 cache
->flags
& F_CNAME
? "C" : "",
1214 cache
->flags
& F_FORWARD
? "F" : " ",
1215 cache
->flags
& F_REVERSE
? "R" : " ",
1216 cache
->flags
& F_IMMORTAL
? "I" : " ",
1217 cache
->flags
& F_DHCP
? "D" : " ",
1218 cache
->flags
& F_NEG
? "N" : " ",
1219 cache
->flags
& F_NXDOMAIN
? "X" : " ",
1220 cache
->flags
& F_HOSTS
? "H" : " ",
1221 cache
->flags
& F_DNSSECOK
? "V" : " ");
1222 #ifdef HAVE_BROKEN_RTC
1223 p
+= sprintf(p
, "%lu", cache
->flags
& F_IMMORTAL
? 0: (unsigned long)(cache
->ttd
- now
));
1225 p
+= sprintf(p
, "%s", cache
->flags
& F_IMMORTAL
? "\n" : ctime(&(cache
->ttd
)));
1226 /* ctime includes trailing \n - eat it */
1229 my_syslog(LOG_INFO
, daemon
->namebuff
);
1234 char *record_source(int index
)
1236 struct hostsfile
*ah
;
1241 for (ah
= daemon
->addn_hosts
; ah
; ah
= ah
->next
)
1242 if (ah
->index
== index
)
1248 void querystr(char *str
, unsigned short type
)
1252 sprintf(str
, "query[type=%d]", type
);
1253 for (i
= 0; i
< (sizeof(typestr
)/sizeof(typestr
[0])); i
++)
1254 if (typestr
[i
].type
== type
)
1255 sprintf(str
,"query[%s]", typestr
[i
].name
);
1258 void log_query(unsigned int flags
, char *name
, struct all_addr
*addr
, char *arg
)
1260 char *source
, *dest
= daemon
->addrbuff
;
1263 if (!option_bool(OPT_LOG
))
1269 inet_ntop(flags
& F_IPV4
? AF_INET
: AF_INET6
,
1270 addr
, daemon
->addrbuff
, ADDRSTRLEN
);
1272 strncpy(daemon
->addrbuff
, inet_ntoa(addr
->addr
.addr4
), ADDRSTRLEN
);
1276 if (flags
& F_REVERSE
)
1279 name
= daemon
->addrbuff
;
1284 if (flags
& F_NXDOMAIN
)
1287 dest
= "NXDOMAIN-IPv4";
1288 else if (flags
& F_IPV6
)
1289 dest
= "NXDOMAIN-IPv6";
1296 dest
= "NODATA-IPv4";
1297 else if (flags
& F_IPV6
)
1298 dest
= "NODATA-IPv6";
1303 else if (flags
& F_CNAME
)
1305 else if (flags
& F_RRNAME
)
1308 if (flags
& F_CONFIG
)
1310 else if (flags
& F_DHCP
)
1312 else if (flags
& F_HOSTS
)
1314 else if (flags
& F_UPSTREAM
)
1316 else if (flags
& F_SERVER
)
1318 source
= "forwarded";
1321 else if (flags
& F_QUERY
)
1329 if (strlen(name
) == 0)
1332 my_syslog(LOG_INFO
, "%s %s %s %s", source
, name
, verb
, dest
);
1336 struct keydata
*keydata_alloc(char *data
, size_t len
)
1338 struct keydata
*block
, *ret
= NULL
;
1339 struct keydata
**prev
= &ret
;
1344 block
= keyblock_free
;
1345 keyblock_free
= block
->next
;
1348 block
= whine_malloc(sizeof(struct keydata
));
1352 /* failed to alloc, free partial chain */
1357 memcpy(block
->key
, data
, len
> KEYBLOCK_LEN
? KEYBLOCK_LEN
: len
);
1358 data
+= KEYBLOCK_LEN
;
1359 len
-= KEYBLOCK_LEN
;
1361 prev
= &block
->next
;
1368 void keydata_free(struct keydata
*blocks
)
1370 struct keydata
*tmp
;
1374 for (tmp
= blocks
; tmp
->next
; tmp
= tmp
->next
);
1375 tmp
->next
= keyblock_free
;
1376 keyblock_free
= blocks
;