]>
git.ipfire.org Git - people/ms/dnsmasq.git/blob - src/cache.c
1 /* dnsmasq is Copyright (c) 2000-2011 Simon Kelley
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; version 2 dated June, 1991, or
6 (at your option) version 3 dated 29 June, 2007.
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
13 You should have received a copy of the GNU General Public License
14 along with this program. If not, see <http://www.gnu.org/licenses/>.
19 static struct crec
*cache_head
= NULL
, *cache_tail
= NULL
, **hash_table
= NULL
;
21 static struct crec
*dhcp_spare
= NULL
;
23 static struct crec
*new_chain
= NULL
;
24 static int cache_inserted
= 0, cache_live_freed
= 0, insert_error
;
25 static union bigname
*big_free
= NULL
;
26 static int bignames_left
, hash_size
;
28 static char *addrbuff
= NULL
;
30 /* type->string mapping: this is also used by the name-hash function as a mixing table. */
33 const char * const name
;
67 static void cache_free(struct crec
*crecp
);
68 static void cache_unlink(struct crec
*crecp
);
69 static void cache_link(struct crec
*crecp
);
70 static void rehash(int size
);
71 static void cache_hash(struct crec
*crecp
);
78 if (option_bool(OPT_LOG
))
79 addrbuff
= safe_malloc(ADDRSTRLEN
);
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
;
176 static void cache_free(struct crec
*crecp
)
178 crecp
->flags
&= ~F_FORWARD
;
179 crecp
->flags
&= ~F_REVERSE
;
180 crecp
->uid
= uid
++; /* invalidate CNAMES pointing to this. */
183 cache_tail
->next
= crecp
;
186 crecp
->prev
= cache_tail
;
190 /* retrieve big name for further use. */
191 if (crecp
->flags
& F_BIGNAME
)
193 crecp
->name
.bname
->next
= big_free
;
194 big_free
= crecp
->name
.bname
;
195 crecp
->flags
&= ~F_BIGNAME
;
199 /* insert a new cache entry at the head of the list (youngest entry) */
200 static void cache_link(struct crec
*crecp
)
202 if (cache_head
) /* check needed for init code */
203 cache_head
->prev
= crecp
;
204 crecp
->next
= cache_head
;
211 /* remove an arbitrary cache entry for promotion */
212 static void cache_unlink (struct crec
*crecp
)
215 crecp
->prev
->next
= crecp
->next
;
217 cache_head
= crecp
->next
;
220 crecp
->next
->prev
= crecp
->prev
;
222 cache_tail
= crecp
->prev
;
225 char *cache_get_name(struct crec
*crecp
)
227 if (crecp
->flags
& F_BIGNAME
)
228 return crecp
->name
.bname
->name
;
229 else if (crecp
->flags
& F_NAMEP
)
230 return crecp
->name
.namep
;
232 return crecp
->name
.sname
;
235 static int is_outdated_cname_pointer(struct crec
*crecp
)
237 if (!(crecp
->flags
& F_CNAME
))
240 if (crecp
->addr
.cname
.cache
&& crecp
->addr
.cname
.uid
== crecp
->addr
.cname
.cache
->uid
)
246 static int is_expired(time_t now
, struct crec
*crecp
)
248 if (crecp
->flags
& F_IMMORTAL
)
251 if (difftime(now
, crecp
->ttd
) < 0)
257 static int cache_scan_free(char *name
, struct all_addr
*addr
, time_t now
, unsigned short flags
)
259 /* Scan and remove old entries.
260 If (flags & F_FORWARD) then remove any forward entries for name and any expired
261 entries but only in the same hash bucket as name.
262 If (flags & F_REVERSE) then remove any reverse entries for addr and any expired
263 entries in the whole cache.
264 If (flags == 0) remove any expired entries in the whole cache.
266 In the flags & F_FORWARD case, the return code is valid, and returns zero if the
267 name exists in the cache as a HOSTS or DHCP entry (these are never deleted)
269 We take advantage of the fact that hash chains have stuff in the order <reverse>,<other>,<immortal>
270 so that when we hit an entry which isn't reverse and is immortal, we're done. */
272 struct crec
*crecp
, **up
;
274 if (flags
& F_FORWARD
)
276 for (up
= hash_bucket(name
), crecp
= *up
; crecp
; crecp
= crecp
->hash_next
)
277 if (is_expired(now
, crecp
) || is_outdated_cname_pointer(crecp
))
279 *up
= crecp
->hash_next
;
280 if (!(crecp
->flags
& (F_HOSTS
| F_DHCP
)))
286 else if ((crecp
->flags
& F_FORWARD
) &&
287 ((flags
& crecp
->flags
& (F_IPV4
| F_IPV6
)) || ((crecp
->flags
| flags
) & F_CNAME
)) &&
288 hostname_isequal(cache_get_name(crecp
), name
))
290 if (crecp
->flags
& (F_HOSTS
| F_DHCP
))
292 *up
= crecp
->hash_next
;
297 up
= &crecp
->hash_next
;
303 int addrlen
= (flags
& F_IPV6
) ? IN6ADDRSZ
: INADDRSZ
;
305 int addrlen
= INADDRSZ
;
307 for (i
= 0; i
< hash_size
; i
++)
308 for (crecp
= hash_table
[i
], up
= &hash_table
[i
];
309 crecp
&& ((crecp
->flags
& F_REVERSE
) || !(crecp
->flags
& F_IMMORTAL
));
310 crecp
= crecp
->hash_next
)
311 if (is_expired(now
, crecp
))
313 *up
= crecp
->hash_next
;
314 if (!(crecp
->flags
& (F_HOSTS
| F_DHCP
)))
320 else if (!(crecp
->flags
& (F_HOSTS
| F_DHCP
)) &&
321 (flags
& crecp
->flags
& F_REVERSE
) &&
322 (flags
& crecp
->flags
& (F_IPV4
| F_IPV6
)) &&
323 memcmp(&crecp
->addr
.addr
, addr
, addrlen
) == 0)
325 *up
= crecp
->hash_next
;
330 up
= &crecp
->hash_next
;
336 /* Note: The normal calling sequence is
341 but an abort can cause the cache_end_insert to be missed
342 in which can the next cache_start_insert cleans things up. */
344 void cache_start_insert(void)
346 /* Free any entries which didn't get committed during the last
351 struct crec
*tmp
= new_chain
->next
;
352 cache_free(new_chain
);
359 struct crec
*cache_insert(char *name
, struct all_addr
*addr
,
360 time_t now
, unsigned long ttl
, unsigned short flags
)
363 union bigname
*big_name
= NULL
;
364 int freed_all
= flags
& F_REVERSE
;
367 log_query(flags
| F_UPSTREAM
, name
, addr
, NULL
);
369 /* if previous insertion failed give up now. */
373 /* First remove any expired entries and entries for the name/address we
374 are currently inserting. Fail is we attempt to delete a name from
375 /etc/hosts or DHCP. */
376 if (!cache_scan_free(name
, addr
, now
, flags
))
382 /* Now get a cache entry from the end of the LRU list */
384 if (!(new = cache_tail
)) /* no entries left - cache is too small, bail */
390 /* End of LRU list is still in use: if we didn't scan all the hash
391 chains for expired entries do that now. If we already tried that
392 then it's time to start spilling things. */
394 if (new->flags
& (F_FORWARD
| F_REVERSE
))
396 /* If free_avail set, we believe that an entry has been freed.
397 Bugs have been known to make this not true, resulting in
398 a tight loop here. If that happens, abandon the
399 insert. Once in this state, all inserts will probably fail. */
408 free_avail
= 1; /* Must be free space now. */
409 cache_scan_free(cache_get_name(new), &new->addr
.addr
, now
, new->flags
);
414 cache_scan_free(NULL
, NULL
, now
, 0);
420 /* Check if we need to and can allocate extra memory for a long name.
421 If that fails, give up now. */
422 if (name
&& (strlen(name
) > SMALLDNAME
-1))
427 big_free
= big_free
->next
;
429 else if (!bignames_left
||
430 !(big_name
= (union bigname
*)whine_malloc(sizeof(union bigname
))))
440 /* Got the rest: finally grab entry. */
448 new->name
.bname
= big_name
;
449 new->flags
|= F_BIGNAME
;
453 strcpy(cache_get_name(new), name
);
455 *cache_get_name(new) = 0;
458 new->addr
.addr
= *addr
;
460 new->addr
.cname
.cache
= NULL
;
462 new->ttd
= now
+ (time_t)ttl
;
463 new->next
= new_chain
;
469 /* after end of insertion, commit the new entries */
470 void cache_end_insert(void)
477 struct crec
*tmp
= new_chain
->next
;
478 /* drop CNAMEs which didn't find a target. */
479 if (is_outdated_cname_pointer(new_chain
))
480 cache_free(new_chain
);
483 cache_hash(new_chain
);
484 cache_link(new_chain
);
492 struct crec
*cache_find_by_name(struct crec
*crecp
, char *name
, time_t now
, unsigned short prot
)
496 if (crecp
) /* iterating */
500 /* first search, look for relevant entries and push to top of list
501 also free anything which has expired */
502 struct crec
*next
, **up
, **insert
= NULL
, **chainp
= &ans
;
503 unsigned short ins_flags
= 0;
505 for (up
= hash_bucket(name
), crecp
= *up
; crecp
; crecp
= next
)
507 next
= crecp
->hash_next
;
509 if (!is_expired(now
, crecp
) && !is_outdated_cname_pointer(crecp
))
511 if ((crecp
->flags
& F_FORWARD
) &&
512 (crecp
->flags
& prot
) &&
513 hostname_isequal(cache_get_name(crecp
), name
))
515 if (crecp
->flags
& (F_HOSTS
| F_DHCP
))
518 chainp
= &crecp
->next
;
526 /* Move all but the first entry up the hash chain
527 this implements round-robin.
528 Make sure that re-ordering doesn't break the hash-chain
531 if (insert
&& (crecp
->flags
& (F_REVERSE
| F_IMMORTAL
)) == ins_flags
)
533 *up
= crecp
->hash_next
;
534 crecp
->hash_next
= *insert
;
536 insert
= &crecp
->hash_next
;
543 ins_flags
= crecp
->flags
& (F_REVERSE
| F_IMMORTAL
);
545 up
= &crecp
->hash_next
;
549 /* case : not expired, incorrect entry. */
550 up
= &crecp
->hash_next
;
554 /* expired entry, free it */
555 *up
= crecp
->hash_next
;
556 if (!(crecp
->flags
& (F_HOSTS
| F_DHCP
)))
564 *chainp
= cache_head
;
568 (ans
->flags
& F_FORWARD
) &&
569 (ans
->flags
& prot
) &&
570 hostname_isequal(cache_get_name(ans
), name
))
576 struct crec
*cache_find_by_addr(struct crec
*crecp
, struct all_addr
*addr
,
577 time_t now
, unsigned short prot
)
581 int addrlen
= (prot
== F_IPV6
) ? IN6ADDRSZ
: INADDRSZ
;
583 int addrlen
= INADDRSZ
;
586 if (crecp
) /* iterating */
590 /* first search, look for relevant entries and push to top of list
591 also free anything which has expired. All the reverse entries are at the
592 start of the hash chain, so we can give up when we find the first
595 struct crec
**up
, **chainp
= &ans
;
597 for (i
=0; i
<hash_size
; i
++)
598 for (crecp
= hash_table
[i
], up
= &hash_table
[i
];
599 crecp
&& (crecp
->flags
& F_REVERSE
);
600 crecp
= crecp
->hash_next
)
601 if (!is_expired(now
, crecp
))
603 if ((crecp
->flags
& prot
) &&
604 memcmp(&crecp
->addr
.addr
, addr
, addrlen
) == 0)
606 if (crecp
->flags
& (F_HOSTS
| F_DHCP
))
609 chainp
= &crecp
->next
;
617 up
= &crecp
->hash_next
;
621 *up
= crecp
->hash_next
;
622 if (!(crecp
->flags
& (F_HOSTS
| F_DHCP
)))
629 *chainp
= cache_head
;
633 (ans
->flags
& F_REVERSE
) &&
634 (ans
->flags
& prot
) &&
635 memcmp(&ans
->addr
.addr
, addr
, addrlen
) == 0)
641 static void add_hosts_entry(struct crec
*cache
, struct all_addr
*addr
, int addrlen
,
642 unsigned short flags
, int index
, int addr_dup
)
644 struct crec
*lookup
= cache_find_by_name(NULL
, cache
->name
.sname
, 0, flags
& (F_IPV4
| F_IPV6
));
645 int i
, nameexists
= 0;
648 /* Remove duplicates in hosts files. */
649 if (lookup
&& (lookup
->flags
& F_HOSTS
))
652 if (memcmp(&lookup
->addr
.addr
, addr
, addrlen
) == 0)
659 /* Ensure there is only one address -> name mapping (first one trumps)
660 We do this by steam here, first we see if the address is the same as
661 the last one we saw, which eliminates most in the case of an ad-block
662 file with thousands of entries for the same address.
663 Then we search and bail at the first matching address that came from
664 a HOSTS file. Since the first host entry gets reverse, we know
665 then that it must exist without searching exhaustively for it. */
670 for (i
=0; i
<hash_size
; i
++)
672 for (lookup
= hash_table
[i
]; lookup
; lookup
= lookup
->hash_next
)
673 if ((lookup
->flags
& F_HOSTS
) &&
674 (lookup
->flags
& flags
& (F_IPV4
| F_IPV6
)) &&
675 memcmp(&lookup
->addr
.addr
, addr
, addrlen
) == 0)
684 cache
->flags
= flags
;
686 memcpy(&cache
->addr
.addr
, addr
, addrlen
);
689 /* don't need to do alias stuff for second and subsequent addresses. */
691 for (a
= daemon
->cnames
; a
; a
= a
->next
)
692 if (hostname_isequal(cache
->name
.sname
, a
->target
) &&
693 (lookup
= whine_malloc(sizeof(struct crec
))))
695 lookup
->flags
= F_FORWARD
| F_IMMORTAL
| F_NAMEP
| F_HOSTS
| F_CNAME
;
696 lookup
->name
.namep
= a
->alias
;
697 lookup
->addr
.cname
.cache
= cache
;
698 lookup
->addr
.cname
.uid
= index
;
703 static int eatspace(FILE *f
)
709 if ((c
= getc(f
)) == '#')
710 while (c
!= '\n' && c
!= EOF
)
727 static int gettok(FILE *f
, char *token
)
733 if ((c
= getc(f
)) == EOF
)
734 return (count
== 0) ? EOF
: 1;
736 if (isspace(c
) || c
== '#')
742 if (count
< (MAXDNAME
- 1))
750 static int read_hostsfile(char *filename
, int index
, int cache_size
)
752 FILE *f
= fopen(filename
, "r");
753 char *token
= daemon
->namebuff
, *domain_suffix
= NULL
;
754 int addr_count
= 0, name_count
= cache_size
, lineno
= 0;
755 unsigned short flags
= 0, saved_flags
= 0;
756 struct all_addr addr
, saved_addr
;
757 int atnl
, addrlen
= 0, addr_dup
;
761 my_syslog(LOG_ERR
, _("failed to load names from %s: %s"), filename
, strerror(errno
));
767 while ((atnl
= gettok(f
, token
)) != EOF
)
773 if (inet_pton(AF_INET
, token
, &addr
) > 0)
775 flags
= F_HOSTS
| F_IMMORTAL
| F_FORWARD
| F_REVERSE
| F_IPV4
;
777 domain_suffix
= get_domain(addr
.addr
.addr4
);
779 else if (inet_pton(AF_INET6
, token
, &addr
) > 0)
781 flags
= F_HOSTS
| F_IMMORTAL
| F_FORWARD
| F_REVERSE
| F_IPV6
;
783 domain_suffix
= daemon
->domain_suffix
;
786 if ((addr
.addr
.addr4
.s_addr
= inet_addr(token
)) != (in_addr_t
) -1)
788 flags
= F_HOSTS
| F_IMMORTAL
| F_FORWARD
| F_REVERSE
| F_IPV4
;
790 domain_suffix
= get_domain(addr
.addr
.addr4
);
795 my_syslog(LOG_ERR
, _("bad address at %s line %d"), filename
, lineno
);
797 atnl
= gettok(f
, token
);
801 if (saved_flags
== flags
&& memcmp(&addr
, &saved_addr
, addrlen
) == 0)
811 /* rehash every 1000 names. */
812 if ((name_count
- cache_size
) > 1000)
815 cache_size
= name_count
;
824 if ((atnl
= gettok(f
, token
)) == EOF
)
827 fqdn
= !!strchr(token
, '.');
829 if ((canon
= canonicalise(token
, &nomem
)))
831 /* If set, add a version of the name with a default domain appended */
832 if (option_bool(OPT_EXPAND
) && domain_suffix
&& !fqdn
&&
833 (cache
= whine_malloc(sizeof(struct crec
) +
834 strlen(canon
)+2+strlen(domain_suffix
)-SMALLDNAME
)))
836 strcpy(cache
->name
.sname
, canon
);
837 strcat(cache
->name
.sname
, ".");
838 strcat(cache
->name
.sname
, domain_suffix
);
839 add_hosts_entry(cache
, &addr
, addrlen
, flags
, index
, addr_dup
);
843 if ((cache
= whine_malloc(sizeof(struct crec
) + strlen(canon
)+1-SMALLDNAME
)))
845 strcpy(cache
->name
.sname
, canon
);
846 add_hosts_entry(cache
, &addr
, addrlen
, flags
, index
, addr_dup
);
853 my_syslog(LOG_ERR
, _("bad name at %s line %d"), filename
, lineno
);
860 my_syslog(LOG_INFO
, _("read %s - %d addresses"), filename
, addr_count
);
865 void cache_reload(void)
867 struct crec
*cache
, **up
, *tmp
;
868 int i
, total_size
= daemon
->cachesize
;
869 struct hostsfile
*ah
;
871 cache_inserted
= cache_live_freed
= 0;
873 for (i
=0; i
<hash_size
; i
++)
874 for (cache
= hash_table
[i
], up
= &hash_table
[i
]; cache
; cache
= tmp
)
876 tmp
= cache
->hash_next
;
877 if (cache
->flags
& F_HOSTS
)
879 *up
= cache
->hash_next
;
882 else if (!(cache
->flags
& F_DHCP
))
884 *up
= cache
->hash_next
;
885 if (cache
->flags
& F_BIGNAME
)
887 cache
->name
.bname
->next
= big_free
;
888 big_free
= cache
->name
.bname
;
893 up
= &cache
->hash_next
;
896 if (option_bool(OPT_NO_HOSTS
) && !daemon
->addn_hosts
)
898 if (daemon
->cachesize
> 0)
899 my_syslog(LOG_INFO
, _("cleared cache"));
903 if (!option_bool(OPT_NO_HOSTS
))
904 total_size
= read_hostsfile(HOSTSFILE
, 0, total_size
);
906 daemon
->addn_hosts
= expand_filelist(daemon
->addn_hosts
);
907 for (ah
= daemon
->addn_hosts
; ah
; ah
= ah
->next
)
908 if (!(ah
->flags
& AH_INACTIVE
))
909 total_size
= read_hostsfile(ah
->fname
, ah
->index
, total_size
);
912 char *get_domain(struct in_addr addr
)
914 struct cond_domain
*c
;
916 for (c
= daemon
->cond_domain
; c
; c
= c
->next
)
917 if (ntohl(addr
.s_addr
) >= ntohl(c
->start
.s_addr
) &&
918 ntohl(addr
.s_addr
) <= ntohl(c
->end
.s_addr
))
921 return daemon
->domain_suffix
;
925 struct in_addr
a_record_from_hosts(char *name
, time_t now
)
927 struct crec
*crecp
= NULL
;
930 while ((crecp
= cache_find_by_name(crecp
, name
, now
, F_IPV4
)))
931 if (crecp
->flags
& F_HOSTS
)
932 return *(struct in_addr
*)&crecp
->addr
;
934 my_syslog(MS_DHCP
| LOG_WARNING
, _("No IPv4 address found for %s"), name
);
940 void cache_unhash_dhcp(void)
942 struct crec
*cache
, **up
;
945 for (i
=0; i
<hash_size
; i
++)
946 for (cache
= hash_table
[i
], up
= &hash_table
[i
]; cache
; cache
= cache
->hash_next
)
947 if (cache
->flags
& F_DHCP
)
949 *up
= cache
->hash_next
;
950 cache
->next
= dhcp_spare
;
954 up
= &cache
->hash_next
;
957 void cache_add_dhcp_entry(char *host_name
,
958 struct in_addr
*host_address
, time_t ttd
)
960 struct crec
*crec
= NULL
, *aliasc
;
961 unsigned short flags
= F_NAMEP
| F_DHCP
| F_FORWARD
| F_IPV4
| F_REVERSE
;
965 while ((crec
= cache_find_by_name(crec
, host_name
, 0, F_IPV4
| F_CNAME
)))
967 /* check all addresses associated with name */
968 if (crec
->flags
& F_HOSTS
)
970 /* if in hosts, don't need DHCP record */
973 if (crec
->flags
& F_CNAME
)
974 my_syslog(MS_DHCP
| LOG_WARNING
,
975 _("%s is a CNAME, not giving it to the DHCP lease of %s"),
976 host_name
, inet_ntoa(*host_address
));
977 else if (crec
->addr
.addr
.addr
.addr4
.s_addr
!= host_address
->s_addr
)
979 strcpy(daemon
->namebuff
, inet_ntoa(crec
->addr
.addr
.addr
.addr4
));
980 my_syslog(MS_DHCP
| LOG_WARNING
,
981 _("not giving name %s to the DHCP lease of %s because "
982 "the name exists in %s with address %s"),
983 host_name
, inet_ntoa(*host_address
),
984 record_source(crec
->uid
), daemon
->namebuff
);
987 else if (!(crec
->flags
& F_DHCP
))
989 cache_scan_free(host_name
, NULL
, 0, crec
->flags
& (F_IPV4
| F_CNAME
| F_FORWARD
));
990 /* scan_free deletes all addresses associated with name */
998 if ((crec
= cache_find_by_addr(NULL
, (struct all_addr
*)host_address
, 0, F_IPV4
)))
1000 if (crec
->flags
& F_NEG
)
1001 cache_scan_free(NULL
, (struct all_addr
*)host_address
, 0, F_IPV4
| F_REVERSE
);
1003 /* avoid multiple reverse mappings */
1004 flags
&= ~F_REVERSE
;
1007 if ((crec
= dhcp_spare
))
1008 dhcp_spare
= dhcp_spare
->next
;
1009 else /* need new one */
1010 crec
= whine_malloc(sizeof(struct crec
));
1012 if (crec
) /* malloc may fail */
1014 crec
->flags
= flags
;
1016 crec
->flags
|= F_IMMORTAL
;
1019 crec
->addr
.addr
.addr
.addr4
= *host_address
;
1020 crec
->name
.namep
= host_name
;
1024 for (a
= daemon
->cnames
; a
; a
= a
->next
)
1025 if (hostname_isequal(host_name
, a
->target
))
1027 if ((aliasc
= dhcp_spare
))
1028 dhcp_spare
= dhcp_spare
->next
;
1029 else /* need new one */
1030 aliasc
= whine_malloc(sizeof(struct crec
));
1034 aliasc
->flags
= F_FORWARD
| F_NAMEP
| F_DHCP
| F_CNAME
;
1036 aliasc
->flags
|= F_IMMORTAL
;
1039 aliasc
->name
.namep
= a
->alias
;
1040 aliasc
->addr
.cname
.cache
= crec
;
1041 aliasc
->addr
.cname
.uid
= crec
->uid
;
1050 void dump_cache(time_t now
)
1052 struct server
*serv
, *serv1
;
1054 my_syslog(LOG_INFO
, _("time %lu"), (unsigned long)now
);
1055 my_syslog(LOG_INFO
, _("cache size %d, %d/%d cache insertions re-used unexpired cache entries."),
1056 daemon
->cachesize
, cache_live_freed
, cache_inserted
);
1057 my_syslog(LOG_INFO
, _("queries forwarded %u, queries answered locally %u"),
1058 daemon
->queries_forwarded
, daemon
->local_answer
);
1060 if (!addrbuff
&& !(addrbuff
= whine_malloc(ADDRSTRLEN
)))
1063 /* sum counts from different records for same server */
1064 for (serv
= daemon
->servers
; serv
; serv
= serv
->next
)
1065 serv
->flags
&= ~SERV_COUNTED
;
1067 for (serv
= daemon
->servers
; serv
; serv
= serv
->next
)
1069 (SERV_NO_ADDR
| SERV_LITERAL_ADDRESS
| SERV_COUNTED
| SERV_USE_RESOLV
| SERV_NO_REBIND
)))
1072 unsigned int queries
= 0, failed_queries
= 0;
1073 for (serv1
= serv
; serv1
; serv1
= serv1
->next
)
1074 if (!(serv1
->flags
&
1075 (SERV_NO_ADDR
| SERV_LITERAL_ADDRESS
| SERV_COUNTED
| SERV_USE_RESOLV
| SERV_NO_REBIND
)) &&
1076 sockaddr_isequal(&serv
->addr
, &serv1
->addr
))
1078 serv1
->flags
|= SERV_COUNTED
;
1079 queries
+= serv1
->queries
;
1080 failed_queries
+= serv1
->failed_queries
;
1082 port
= prettyprint_addr(&serv
->addr
, addrbuff
);
1083 my_syslog(LOG_INFO
, _("server %s#%d: queries sent %u, retried or failed %u"), addrbuff
, port
, queries
, failed_queries
);
1086 if (option_bool(OPT_DEBUG
) || option_bool(OPT_LOG
))
1088 struct crec
*cache
;
1090 my_syslog(LOG_INFO
, "Host Address Flags Expires");
1092 for (i
=0; i
<hash_size
; i
++)
1093 for (cache
= hash_table
[i
]; cache
; cache
= cache
->hash_next
)
1095 char *a
, *p
= daemon
->namebuff
;
1096 p
+= sprintf(p
, "%-40.40s ", cache_get_name(cache
));
1097 if ((cache
->flags
& F_NEG
) && (cache
->flags
& F_FORWARD
))
1099 else if (cache
->flags
& F_CNAME
)
1102 if (!is_outdated_cname_pointer(cache
))
1103 a
= cache_get_name(cache
->addr
.cname
.cache
);
1109 if (cache
->flags
& F_IPV4
)
1110 inet_ntop(AF_INET
, &cache
->addr
.addr
, addrbuff
, ADDRSTRLEN
);
1111 else if (cache
->flags
& F_IPV6
)
1112 inet_ntop(AF_INET6
, &cache
->addr
.addr
, addrbuff
, ADDRSTRLEN
);
1116 a
= inet_ntoa(cache
->addr
.addr
.addr
.addr4
);
1118 p
+= sprintf(p
, "%-30.30s %s%s%s%s%s%s%s%s%s%s ", a
,
1119 cache
->flags
& F_IPV4
? "4" : "",
1120 cache
->flags
& F_IPV6
? "6" : "",
1121 cache
->flags
& F_CNAME
? "C" : "",
1122 cache
->flags
& F_FORWARD
? "F" : " ",
1123 cache
->flags
& F_REVERSE
? "R" : " ",
1124 cache
->flags
& F_IMMORTAL
? "I" : " ",
1125 cache
->flags
& F_DHCP
? "D" : " ",
1126 cache
->flags
& F_NEG
? "N" : " ",
1127 cache
->flags
& F_NXDOMAIN
? "X" : " ",
1128 cache
->flags
& F_HOSTS
? "H" : " ");
1129 #ifdef HAVE_BROKEN_RTC
1130 p
+= sprintf(p
, "%lu", cache
->flags
& F_IMMORTAL
? 0: (unsigned long)(cache
->ttd
- now
));
1132 p
+= sprintf(p
, "%s", cache
->flags
& F_IMMORTAL
? "\n" : ctime(&(cache
->ttd
)));
1133 /* ctime includes trailing \n - eat it */
1136 my_syslog(LOG_INFO
, daemon
->namebuff
);
1141 char *record_source(int index
)
1143 struct hostsfile
*ah
;
1148 for (ah
= daemon
->addn_hosts
; ah
; ah
= ah
->next
)
1149 if (ah
->index
== index
)
1155 void querystr(char *str
, unsigned short type
)
1159 sprintf(str
, "query[type=%d]", type
);
1160 for (i
= 0; i
< (sizeof(typestr
)/sizeof(typestr
[0])); i
++)
1161 if (typestr
[i
].type
== type
)
1162 sprintf(str
,"query[%s]", typestr
[i
].name
);
1165 void log_query(unsigned int flags
, char *name
, struct all_addr
*addr
, char *arg
)
1167 char *source
, *dest
= addrbuff
;
1170 if (!option_bool(OPT_LOG
))
1176 inet_ntop(flags
& F_IPV4
? AF_INET
: AF_INET6
,
1177 addr
, addrbuff
, ADDRSTRLEN
);
1179 strncpy(addrbuff
, inet_ntoa(addr
->addr
.addr4
), ADDRSTRLEN
);
1183 if (flags
& F_REVERSE
)
1191 if (flags
& F_NXDOMAIN
)
1194 dest
= "NXDOMAIN-IPv4";
1195 else if (flags
& F_IPV6
)
1196 dest
= "NXDOMAIN-IPv6";
1203 dest
= "NODATA-IPv4";
1204 else if (flags
& F_IPV6
)
1205 dest
= "NODATA-IPv6";
1210 else if (flags
& F_CNAME
)
1212 else if (flags
& F_RRNAME
)
1215 if (flags
& F_CONFIG
)
1217 else if (flags
& F_DHCP
)
1219 else if (flags
& F_HOSTS
)
1221 else if (flags
& F_UPSTREAM
)
1223 else if (flags
& F_SERVER
)
1225 source
= "forwarded";
1228 else if (flags
& F_QUERY
)
1236 if (strlen(name
) == 0)
1239 my_syslog(LOG_INFO
, "%s %s %s %s", source
, name
, verb
, dest
);