]>
git.ipfire.org Git - people/ms/dnsmasq.git/blob - src/cache.c
1 /* dnsmasq is Copyright (c) 2000-2007 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
;
20 static struct crec
*dhcp_spare
= NULL
, *new_chain
= NULL
;
21 static int cache_inserted
= 0, cache_live_freed
= 0, insert_error
;
22 static union bigname
*big_free
= NULL
;
23 static int bignames_left
, hash_size
;
25 static char *addrbuff
= NULL
;
27 /* type->string mapping: this is also used by the name-hash function as a mixing table. */
30 const char * const name
;
64 static void cache_free(struct crec
*crecp
);
65 static void cache_unlink(struct crec
*crecp
);
66 static void cache_link(struct crec
*crecp
);
67 static void rehash(int size
);
68 static void cache_hash(struct crec
*crecp
);
75 if (daemon
->options
& OPT_LOG
)
76 addrbuff
= safe_malloc(ADDRSTRLEN
);
78 bignames_left
= daemon
->cachesize
/10;
80 if (daemon
->cachesize
> 0)
82 crecp
= safe_malloc(daemon
->cachesize
*sizeof(struct crec
));
84 for (i
=0; i
< daemon
->cachesize
; i
++, crecp
++)
92 /* create initial hash table*/
93 rehash(daemon
->cachesize
);
96 /* In most cases, we create the hash table once here by calling this with (hash_table == NULL)
97 but if the hosts file(s) are big (some people have 50000 ad-block entries), the table
98 will be much too small, so the hosts reading code calls rehash every 1000 addresses, to
100 static void rehash(int size
)
102 struct crec
**new, **old
, *p
, *tmp
;
103 int i
, new_size
, old_size
;
105 /* hash_size is a power of two. */
106 for (new_size
= 64; new_size
< size
/10; new_size
= new_size
<< 1);
108 /* must succeed in getting first instance, failure later is non-fatal */
110 new = safe_malloc(new_size
* sizeof(struct crec
*));
111 else if (new_size
<= hash_size
|| !(new = whine_malloc(new_size
* sizeof(struct crec
*))))
114 for(i
= 0; i
< new_size
; i
++)
118 old_size
= hash_size
;
120 hash_size
= new_size
;
124 for (i
= 0; i
< old_size
; i
++)
125 for (p
= old
[i
]; p
; p
= tmp
)
134 static struct crec
**hash_bucket(char *name
)
136 unsigned int c
, val
= 017465; /* Barker code - minimum self-correlation in cyclic shift */
137 const unsigned char *mix_tab
= (const unsigned char*)typestr
;
139 while((c
= (unsigned char) *name
++))
141 /* don't use tolower and friends here - they may be messed up by LOCALE */
142 if (c
>= 'A' && c
<= 'Z')
144 val
= ((val
<< 7) | (val
>> (32 - 7))) + (mix_tab
[(val
+ c
) & 0x3F] ^ c
);
147 /* hash_size is a power of two */
148 return hash_table
+ ((val
^ (val
>> 16)) & (hash_size
- 1));
151 static void cache_hash(struct crec
*crecp
)
153 /* maintain an invariant that all entries with F_REVERSE set
154 are at the start of the hash-chain and all non-reverse
155 immortal entries are at the end of the hash-chain.
156 This allows reverse searches and garbage collection to be optimised */
158 struct crec
**up
= hash_bucket(cache_get_name(crecp
));
160 if (!(crecp
->flags
& F_REVERSE
))
162 while (*up
&& ((*up
)->flags
& F_REVERSE
))
163 up
= &((*up
)->hash_next
);
165 if (crecp
->flags
& F_IMMORTAL
)
166 while (*up
&& !((*up
)->flags
& F_IMMORTAL
))
167 up
= &((*up
)->hash_next
);
169 crecp
->hash_next
= *up
;
173 static void cache_free(struct crec
*crecp
)
175 crecp
->flags
&= ~F_FORWARD
;
176 crecp
->flags
&= ~F_REVERSE
;
177 crecp
->uid
= uid
++; /* invalidate CNAMES pointing to this. */
180 cache_tail
->next
= crecp
;
183 crecp
->prev
= cache_tail
;
187 /* retrieve big name for further use. */
188 if (crecp
->flags
& F_BIGNAME
)
190 crecp
->name
.bname
->next
= big_free
;
191 big_free
= crecp
->name
.bname
;
192 crecp
->flags
&= ~F_BIGNAME
;
196 /* insert a new cache entry at the head of the list (youngest entry) */
197 static void cache_link(struct crec
*crecp
)
199 if (cache_head
) /* check needed for init code */
200 cache_head
->prev
= crecp
;
201 crecp
->next
= cache_head
;
208 /* remove an arbitrary cache entry for promotion */
209 static void cache_unlink (struct crec
*crecp
)
212 crecp
->prev
->next
= crecp
->next
;
214 cache_head
= crecp
->next
;
217 crecp
->next
->prev
= crecp
->prev
;
219 cache_tail
= crecp
->prev
;
222 char *cache_get_name(struct crec
*crecp
)
224 if (crecp
->flags
& F_BIGNAME
)
225 return crecp
->name
.bname
->name
;
226 else if (crecp
->flags
& F_DHCP
)
227 return crecp
->name
.namep
;
229 return crecp
->name
.sname
;
232 static int is_outdated_cname_pointer(struct crec
*crecp
)
234 if (!(crecp
->flags
& F_CNAME
))
237 if (crecp
->addr
.cname
.cache
&& crecp
->addr
.cname
.uid
== crecp
->addr
.cname
.cache
->uid
)
243 static int is_expired(time_t now
, struct crec
*crecp
)
245 if (crecp
->flags
& F_IMMORTAL
)
248 if (difftime(now
, crecp
->ttd
) < 0)
254 static int cache_scan_free(char *name
, struct all_addr
*addr
, time_t now
, unsigned short flags
)
256 /* Scan and remove old entries.
257 If (flags & F_FORWARD) then remove any forward entries for name and any expired
258 entries but only in the same hash bucket as name.
259 If (flags & F_REVERSE) then remove any reverse entries for addr and any expired
260 entries in the whole cache.
261 If (flags == 0) remove any expired entries in the whole cache.
263 In the flags & F_FORWARD case, the return code is valid, and returns zero if the
264 name exists in the cache as a HOSTS or DHCP entry (these are never deleted)
266 We take advantage of the fact that hash chains have stuff in the order <reverse>,<other>,<immortal>
267 so that when we hit an entry which isn't reverse and is immortal, we're done. */
269 struct crec
*crecp
, **up
;
271 if (flags
& F_FORWARD
)
273 for (up
= hash_bucket(name
), crecp
= *up
; crecp
; crecp
= crecp
->hash_next
)
274 if (is_expired(now
, crecp
) || is_outdated_cname_pointer(crecp
))
276 *up
= crecp
->hash_next
;
277 if (!(crecp
->flags
& (F_HOSTS
| F_DHCP
)))
283 else if ((crecp
->flags
& F_FORWARD
) &&
284 ((flags
& crecp
->flags
& (F_IPV4
| F_IPV6
)) || ((crecp
->flags
| flags
) & F_CNAME
)) &&
285 hostname_isequal(cache_get_name(crecp
), name
))
287 if (crecp
->flags
& (F_HOSTS
| F_DHCP
))
289 *up
= crecp
->hash_next
;
294 up
= &crecp
->hash_next
;
300 int addrlen
= (flags
& F_IPV6
) ? IN6ADDRSZ
: INADDRSZ
;
302 int addrlen
= INADDRSZ
;
304 for (i
= 0; i
< hash_size
; i
++)
305 for (crecp
= hash_table
[i
], up
= &hash_table
[i
];
306 crecp
&& ((crecp
->flags
& F_REVERSE
) || !(crecp
->flags
& F_IMMORTAL
));
307 crecp
= crecp
->hash_next
)
308 if (is_expired(now
, crecp
))
310 *up
= crecp
->hash_next
;
311 if (!(crecp
->flags
& (F_HOSTS
| F_DHCP
)))
317 else if (!(crecp
->flags
& (F_HOSTS
| F_DHCP
)) &&
318 (flags
& crecp
->flags
& F_REVERSE
) &&
319 (flags
& crecp
->flags
& (F_IPV4
| F_IPV6
)) &&
320 memcmp(&crecp
->addr
.addr
, addr
, addrlen
) == 0)
322 *up
= crecp
->hash_next
;
327 up
= &crecp
->hash_next
;
333 /* Note: The normal calling sequence is
338 but an abort can cause the cache_end_insert to be missed
339 in which can the next cache_start_insert cleans things up. */
341 void cache_start_insert(void)
343 /* Free any entries which didn't get committed during the last
348 struct crec
*tmp
= new_chain
->next
;
349 cache_free(new_chain
);
356 struct crec
*cache_insert(char *name
, struct all_addr
*addr
,
357 time_t now
, unsigned long ttl
, unsigned short flags
)
360 union bigname
*big_name
= NULL
;
361 int freed_all
= flags
& F_REVERSE
;
364 log_query(flags
| F_UPSTREAM
, name
, addr
, NULL
);
366 /* CONFIG bit no needed except for logging */
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
;
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
));
647 /* Remove duplicates in hosts files. */
648 if (lookup
&& (lookup
->flags
& F_HOSTS
) &&
649 memcmp(&lookup
->addr
.addr
, addr
, addrlen
) == 0)
653 /* Ensure there is only one address -> name mapping (first one trumps)
654 We do this by steam here, first we see if the address is the same as
655 the last one we saw, which eliminates most in the case of an ad-block
656 file with thousands of entries for the same address.
657 Then we search and bail at the first matching address that came from
658 a HOSTS file. Since the first host entry gets reverse, we know
659 then that it must exist without searching exhaustively for it. */
664 for (i
=0; i
<hash_size
; i
++)
666 for (lookup
= hash_table
[i
]; lookup
; lookup
= lookup
->hash_next
)
667 if ((lookup
->flags
& F_HOSTS
) &&
668 (lookup
->flags
& flags
& (F_IPV4
| F_IPV6
)) &&
669 memcmp(&lookup
->addr
.addr
, addr
, addrlen
) == 0)
678 cache
->flags
= flags
;
680 memcpy(&cache
->addr
.addr
, addr
, addrlen
);
685 static int read_hostsfile(char *filename
, int opts
, char *buff
, char *domain_suffix
, int index
, int cache_size
)
687 FILE *f
= fopen(filename
, "r");
689 int addr_count
= 0, name_count
= cache_size
, lineno
= 0;
690 unsigned short flags
, saved_flags
= 0;
691 struct all_addr addr
, saved_addr
;
695 my_syslog(LOG_ERR
, _("failed to load names from %s: %s"), filename
, strerror(errno
));
699 while ((line
= fgets(buff
, MAXDNAME
, f
)))
701 char *token
= strtok(line
, " \t\n\r");
702 int addrlen
, addr_dup
= 0;
706 if (!token
|| (*token
== '#'))
710 if (inet_pton(AF_INET
, token
, &addr
) > 0)
712 flags
= F_HOSTS
| F_IMMORTAL
| F_FORWARD
| F_REVERSE
| F_IPV4
;
715 else if (inet_pton(AF_INET6
, token
, &addr
) > 0)
717 flags
= F_HOSTS
| F_IMMORTAL
| F_FORWARD
| F_REVERSE
| F_IPV6
;
721 if ((addr
.addr
.addr4
.s_addr
= inet_addr(token
)) != (in_addr_t
) -1)
723 flags
= F_HOSTS
| F_IMMORTAL
| F_FORWARD
| F_REVERSE
| F_IPV4
;
729 my_syslog(LOG_ERR
, _("bad address at %s line %d"), filename
, lineno
);
733 if (saved_flags
== flags
&& memcmp(&addr
, &saved_addr
, addrlen
) == 0)
743 /* rehash every 1000 names. */
744 if ((name_count
- cache_size
) > 1000)
747 cache_size
= name_count
;
750 while ((token
= strtok(NULL
, " \t\n\r")) && (*token
!= '#'))
753 int fqdn
= !!strchr(token
, '.');
754 if (canonicalise(token
))
756 /* If set, add a version of the name with a default domain appended */
757 if ((opts
& OPT_EXPAND
) && domain_suffix
&& !fqdn
&&
758 (cache
= whine_malloc(sizeof(struct crec
) +
759 strlen(token
)+2+strlen(domain_suffix
)-SMALLDNAME
)))
761 strcpy(cache
->name
.sname
, token
);
762 strcat(cache
->name
.sname
, ".");
763 strcat(cache
->name
.sname
, domain_suffix
);
764 add_hosts_entry(cache
, &addr
, addrlen
, flags
, index
, addr_dup
);
768 if ((cache
= whine_malloc(sizeof(struct crec
) + strlen(token
)+1-SMALLDNAME
)))
770 strcpy(cache
->name
.sname
, token
);
771 add_hosts_entry(cache
, &addr
, addrlen
, flags
, index
, addr_dup
);
776 my_syslog(LOG_ERR
, _("bad name at %s line %d"), filename
, lineno
);
783 my_syslog(LOG_INFO
, _("read %s - %d addresses"), filename
, addr_count
);
788 void cache_reload(int opts
, char *buff
, char *domain_suffix
, struct hostsfile
*addn_hosts
)
790 struct crec
*cache
, **up
, *tmp
;
791 int i
, total_size
= daemon
->cachesize
;
793 cache_inserted
= cache_live_freed
= 0;
795 for (i
=0; i
<hash_size
; i
++)
796 for (cache
= hash_table
[i
], up
= &hash_table
[i
]; cache
; cache
= tmp
)
798 tmp
= cache
->hash_next
;
799 if (cache
->flags
& F_HOSTS
)
801 *up
= cache
->hash_next
;
804 else if (!(cache
->flags
& F_DHCP
))
806 *up
= cache
->hash_next
;
807 if (cache
->flags
& F_BIGNAME
)
809 cache
->name
.bname
->next
= big_free
;
810 big_free
= cache
->name
.bname
;
815 up
= &cache
->hash_next
;
818 if ((opts
& OPT_NO_HOSTS
) && !addn_hosts
)
820 if (daemon
->cachesize
> 0)
821 my_syslog(LOG_INFO
, _("cleared cache"));
825 if (!(opts
& OPT_NO_HOSTS
))
826 total_size
= read_hostsfile(HOSTSFILE
, opts
, buff
, domain_suffix
, 0, total_size
);
829 total_size
= read_hostsfile(addn_hosts
->fname
, opts
, buff
, domain_suffix
, addn_hosts
->index
, total_size
);
830 addn_hosts
= addn_hosts
->next
;
834 void cache_unhash_dhcp(void)
836 struct crec
*cache
, **up
;
839 for (i
=0; i
<hash_size
; i
++)
840 for (cache
= hash_table
[i
], up
= &hash_table
[i
]; cache
; cache
= cache
->hash_next
)
841 if (cache
->flags
& F_DHCP
)
843 *up
= cache
->hash_next
;
844 cache
->next
= dhcp_spare
;
848 up
= &cache
->hash_next
;
851 void cache_add_dhcp_entry(char *host_name
,
852 struct in_addr
*host_address
, time_t ttd
)
854 struct crec
*crec
= NULL
;
855 unsigned short flags
= F_DHCP
| F_FORWARD
| F_IPV4
| F_REVERSE
;
861 while ((crec
= cache_find_by_name(crec
, host_name
, 0, F_IPV4
| F_CNAME
)))
863 /* check all addresses associated with name */
864 if (crec
->flags
& F_HOSTS
)
866 if (crec
->addr
.addr
.addr
.addr4
.s_addr
!= host_address
->s_addr
)
868 strcpy(daemon
->namebuff
, inet_ntoa(crec
->addr
.addr
.addr
.addr4
));
869 my_syslog(LOG_WARNING
,
870 _("not giving name %s to the DHCP lease of %s because "
871 "the name exists in %s with address %s"),
872 host_name
, inet_ntoa(*host_address
),
873 record_source(daemon
->addn_hosts
, crec
->uid
), daemon
->namebuff
);
877 /* if in hosts, don't need DHCP record */
880 else if (!(crec
->flags
& F_DHCP
))
882 cache_scan_free(host_name
, NULL
, 0, crec
->flags
& (F_IPV4
| F_CNAME
| F_FORWARD
));
883 /* scan_free deletes all addresses associated with name */
891 if ((crec
= cache_find_by_addr(NULL
, (struct all_addr
*)host_address
, 0, F_IPV4
)))
893 if (crec
->flags
& F_NEG
)
894 cache_scan_free(NULL
, (struct all_addr
*)host_address
, 0, F_IPV4
| F_REVERSE
);
896 /* avoid multiple reverse mappings */
900 if ((crec
= dhcp_spare
))
901 dhcp_spare
= dhcp_spare
->next
;
902 else /* need new one */
903 crec
= whine_malloc(sizeof(struct crec
));
905 if (crec
) /* malloc may fail */
909 crec
->flags
|= F_IMMORTAL
;
912 crec
->addr
.addr
.addr
.addr4
= *host_address
;
913 crec
->name
.namep
= host_name
;
918 void dump_cache(time_t now
)
920 struct server
*serv
, *serv1
;
922 my_syslog(LOG_INFO
, _("time %lu"), (unsigned long)now
);
923 my_syslog(LOG_INFO
, _("cache size %d, %d/%d cache insertions re-used unexpired cache entries."),
924 daemon
->cachesize
, cache_live_freed
, cache_inserted
);
925 my_syslog(LOG_INFO
, _("queries forwarded %u, queries answered locally %u"),
926 daemon
->queries_forwarded
, daemon
->local_answer
);
928 if (!addrbuff
&& !(addrbuff
= whine_malloc(ADDRSTRLEN
)))
931 /* sum counts from different records for same server */
932 for (serv
= daemon
->servers
; serv
; serv
= serv
->next
)
933 serv
->flags
&= ~SERV_COUNTED
;
935 for (serv
= daemon
->servers
; serv
; serv
= serv
->next
)
936 if (!(serv
->flags
& (SERV_NO_ADDR
| SERV_LITERAL_ADDRESS
| SERV_COUNTED
)))
939 unsigned int queries
= 0, failed_queries
= 0;
940 for (serv1
= serv
; serv1
; serv1
= serv1
->next
)
941 if (!(serv1
->flags
& (SERV_NO_ADDR
| SERV_LITERAL_ADDRESS
| SERV_COUNTED
)) && sockaddr_isequal(&serv
->addr
, &serv1
->addr
))
943 serv1
->flags
|= SERV_COUNTED
;
944 queries
+= serv1
->queries
;
945 failed_queries
+= serv1
->failed_queries
;
947 port
= prettyprint_addr(&serv
->addr
, addrbuff
);
948 my_syslog(LOG_INFO
, _("server %s#%d: queries sent %u, retried or failed %u"), addrbuff
, port
, queries
, failed_queries
);
951 if ((daemon
->options
& (OPT_DEBUG
| OPT_LOG
)))
955 my_syslog(LOG_DEBUG
, "Host Address Flags Expires");
957 for (i
=0; i
<hash_size
; i
++)
958 for (cache
= hash_table
[i
]; cache
; cache
= cache
->hash_next
)
960 char *a
, *p
= daemon
->namebuff
;
961 p
+= sprintf(p
, "%-40.40s ", cache_get_name(cache
));
962 if ((cache
->flags
& F_NEG
) && (cache
->flags
& F_FORWARD
))
964 else if (cache
->flags
& F_CNAME
)
967 if (!is_outdated_cname_pointer(cache
))
968 a
= cache_get_name(cache
->addr
.cname
.cache
);
974 if (cache
->flags
& F_IPV4
)
975 inet_ntop(AF_INET
, &cache
->addr
.addr
, addrbuff
, ADDRSTRLEN
);
976 else if (cache
->flags
& F_IPV6
)
977 inet_ntop(AF_INET6
, &cache
->addr
.addr
, addrbuff
, ADDRSTRLEN
);
981 a
= inet_ntoa(cache
->addr
.addr
.addr
.addr4
);
983 p
+= sprintf(p
, "%-30.30s %s%s%s%s%s%s%s%s%s%s ", a
,
984 cache
->flags
& F_IPV4
? "4" : "",
985 cache
->flags
& F_IPV6
? "6" : "",
986 cache
->flags
& F_CNAME
? "C" : "",
987 cache
->flags
& F_FORWARD
? "F" : " ",
988 cache
->flags
& F_REVERSE
? "R" : " ",
989 cache
->flags
& F_IMMORTAL
? "I" : " ",
990 cache
->flags
& F_DHCP
? "D" : " ",
991 cache
->flags
& F_NEG
? "N" : " ",
992 cache
->flags
& F_NXDOMAIN
? "X" : " ",
993 cache
->flags
& F_HOSTS
? "H" : " ");
994 #ifdef HAVE_BROKEN_RTC
995 p
+= sprintf(p
, "%lu", cache
->flags
& F_IMMORTAL
? 0: (unsigned long)(cache
->ttd
- now
));
997 p
+= sprintf(p
, "%s", cache
->flags
& F_IMMORTAL
? "\n" : ctime(&(cache
->ttd
)));
998 /* ctime includes trailing \n - eat it */
1001 my_syslog(LOG_DEBUG
, daemon
->namebuff
);
1006 char *record_source(struct hostsfile
*addn_hosts
, int index
)
1008 char *source
= HOSTSFILE
;
1011 if (addn_hosts
->index
== index
)
1013 source
= addn_hosts
->fname
;
1016 addn_hosts
= addn_hosts
->next
;
1022 void querystr(char *str
, unsigned short type
)
1026 sprintf(str
, "query[type=%d]", type
);
1027 for (i
= 0; i
< (sizeof(typestr
)/sizeof(typestr
[0])); i
++)
1028 if (typestr
[i
].type
== type
)
1029 sprintf(str
,"query[%s]", typestr
[i
].name
);
1032 void log_query(unsigned short flags
, char *name
, struct all_addr
*addr
, char *arg
)
1034 char *source
, *dest
= addrbuff
;
1037 if (!(daemon
->options
& OPT_LOG
))
1043 inet_ntop(flags
& F_IPV4
? AF_INET
: AF_INET6
,
1044 addr
, addrbuff
, ADDRSTRLEN
);
1046 strncpy(addrbuff
, inet_ntoa(addr
->addr
.addr4
), ADDRSTRLEN
);
1050 if (flags
& F_REVERSE
)
1058 if (flags
& F_NXDOMAIN
)
1061 dest
= "NXDOMAIN-IPv4";
1062 else if (flags
& F_IPV6
)
1063 dest
= "NXDOMAIN-IPv6";
1070 dest
= "NODATA-IPv4";
1071 else if (flags
& F_IPV6
)
1072 dest
= "NODATA-IPv6";
1077 else if (flags
& F_CNAME
)
1079 /* nasty abuse of NXDOMAIN and CNAME flags */
1080 if (flags
& F_NXDOMAIN
)
1088 else if (flags
& F_HOSTS
)
1090 else if (flags
& F_CONFIG
)
1092 else if (flags
& F_UPSTREAM
)
1094 else if (flags
& F_SERVER
)
1096 source
= "forwarded";
1099 else if (flags
& F_QUERY
)
1107 if (strlen(name
) == 0)
1110 my_syslog(LOG_DEBUG
, "%s %s %s %s", source
, name
, verb
, dest
);