mirror of
https://github.com/pi-hole/dnsmasq.git
synced 2025-12-19 18:28:25 +00:00
Cache stats availble in CHAOS .bind domain.
This commit is contained in:
@@ -1753,12 +1753,22 @@ When it receives a SIGUSR1,
|
|||||||
writes statistics to the system log. It writes the cache size,
|
writes statistics to the system log. It writes the cache size,
|
||||||
the number of names which have had to removed from the cache before
|
the number of names which have had to removed from the cache before
|
||||||
they expired in order to make room for new names and the total number
|
they expired in order to make room for new names and the total number
|
||||||
of names that have been inserted into the cache. For each upstream
|
of names that have been inserted into the cache. The number of cache hits and
|
||||||
|
misses and the number of authoritative queries answered are also given. For each upstream
|
||||||
server it gives the number of queries sent, and the number which
|
server it gives the number of queries sent, and the number which
|
||||||
resulted in an error. In
|
resulted in an error. In
|
||||||
.B --no-daemon
|
.B --no-daemon
|
||||||
mode or when full logging is enabled (-q), a complete dump of the
|
mode or when full logging is enabled (-q), a complete dump of the
|
||||||
contents of the cache is made.
|
contents of the cache is made.
|
||||||
|
|
||||||
|
The cache statistics are also available in the DNS as answers to
|
||||||
|
queries of class CHAOS and type TXT in domain bind. The domain names are cachesize.bind, insertions.bind, evictions.bind,
|
||||||
|
misses.bind, hits.bind, auth.bind and servers.bind. An example command to query this, using the
|
||||||
|
.B dig
|
||||||
|
utility would be
|
||||||
|
|
||||||
|
dig +short chaos txt cachesize.bind
|
||||||
|
|
||||||
.PP
|
.PP
|
||||||
When it receives SIGUSR2 and it is logging direct to a file (see
|
When it receives SIGUSR2 and it is logging direct to a file (see
|
||||||
.B --log-facility
|
.B --log-facility
|
||||||
|
|||||||
95
src/cache.c
95
src/cache.c
@@ -1262,6 +1262,101 @@ void cache_add_dhcp_entry(char *host_name, int prot,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
int cache_make_stat(struct txt_record *t)
|
||||||
|
{
|
||||||
|
static char *buff = NULL;
|
||||||
|
static int bufflen = 60;
|
||||||
|
int len;
|
||||||
|
struct server *serv, *serv1;
|
||||||
|
char *p;
|
||||||
|
|
||||||
|
if (!buff && !(buff = whine_malloc(60)))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
p = buff;
|
||||||
|
|
||||||
|
switch (t->stat)
|
||||||
|
{
|
||||||
|
case TXT_STAT_CACHESIZE:
|
||||||
|
sprintf(buff+1, "%d", daemon->cachesize);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TXT_STAT_INSERTS:
|
||||||
|
sprintf(buff+1, "%d", cache_inserted);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TXT_STAT_EVICTIONS:
|
||||||
|
sprintf(buff+1, "%d", cache_live_freed);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TXT_STAT_MISSES:
|
||||||
|
sprintf(buff+1, "%u", daemon->queries_forwarded);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TXT_STAT_HITS:
|
||||||
|
sprintf(buff+1, "%u", daemon->local_answer);
|
||||||
|
break;
|
||||||
|
|
||||||
|
#ifdef HAVE_AUTH
|
||||||
|
case TXT_STAT_AUTH:
|
||||||
|
sprintf(buff+1, "%u", daemon->auth_answer);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
case TXT_STAT_SERVERS:
|
||||||
|
/* sum counts from different records for same server */
|
||||||
|
for (serv = daemon->servers; serv; serv = serv->next)
|
||||||
|
serv->flags &= ~SERV_COUNTED;
|
||||||
|
|
||||||
|
for (serv = daemon->servers; serv; serv = serv->next)
|
||||||
|
if (!(serv->flags &
|
||||||
|
(SERV_NO_ADDR | SERV_LITERAL_ADDRESS | SERV_COUNTED | SERV_USE_RESOLV | SERV_NO_REBIND)))
|
||||||
|
{
|
||||||
|
char *new, *lenp;
|
||||||
|
int port, newlen, bytes_avail, bytes_needed;
|
||||||
|
unsigned int queries = 0, failed_queries = 0;
|
||||||
|
for (serv1 = serv; serv1; serv1 = serv1->next)
|
||||||
|
if (!(serv1->flags &
|
||||||
|
(SERV_NO_ADDR | SERV_LITERAL_ADDRESS | SERV_COUNTED | SERV_USE_RESOLV | SERV_NO_REBIND)) &&
|
||||||
|
sockaddr_isequal(&serv->addr, &serv1->addr))
|
||||||
|
{
|
||||||
|
serv1->flags |= SERV_COUNTED;
|
||||||
|
queries += serv1->queries;
|
||||||
|
failed_queries += serv1->failed_queries;
|
||||||
|
}
|
||||||
|
port = prettyprint_addr(&serv->addr, daemon->addrbuff);
|
||||||
|
lenp = p++; /* length */
|
||||||
|
bytes_avail = (p - buff) + bufflen;
|
||||||
|
bytes_needed = snprintf(p, bytes_avail, "%s#%d %u %u", daemon->addrbuff, port, queries, failed_queries);
|
||||||
|
if (bytes_needed >= bytes_avail)
|
||||||
|
{
|
||||||
|
/* expand buffer if necessary */
|
||||||
|
newlen = bytes_needed + 1 + bufflen - bytes_avail;
|
||||||
|
if (!(new = whine_malloc(newlen)))
|
||||||
|
return 0;
|
||||||
|
memcpy(new, buff, bufflen);
|
||||||
|
free(buff);
|
||||||
|
p = new + (p - buff);
|
||||||
|
lenp = p - 1;
|
||||||
|
buff = new;
|
||||||
|
bufflen = newlen;
|
||||||
|
bytes_avail = (p - buff) + bufflen;
|
||||||
|
bytes_needed = snprintf(p, bytes_avail, "%s#%d %u %u", daemon->addrbuff, port, queries, failed_queries);
|
||||||
|
}
|
||||||
|
*lenp = bytes_needed;
|
||||||
|
p += bytes_needed;
|
||||||
|
}
|
||||||
|
t->txt = (unsigned char *)buff;
|
||||||
|
t->len = p - buff;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
len = strlen(buff+1);
|
||||||
|
t->txt = (unsigned char *)buff;
|
||||||
|
t->len = len + 1;
|
||||||
|
*buff = len;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
void dump_cache(time_t now)
|
void dump_cache(time_t now)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -280,10 +280,19 @@ struct naptr {
|
|||||||
struct naptr *next;
|
struct naptr *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define TXT_STAT_CACHESIZE 1
|
||||||
|
#define TXT_STAT_INSERTS 2
|
||||||
|
#define TXT_STAT_EVICTIONS 3
|
||||||
|
#define TXT_STAT_MISSES 4
|
||||||
|
#define TXT_STAT_HITS 5
|
||||||
|
#define TXT_STAT_AUTH 6
|
||||||
|
#define TXT_STAT_SERVERS 7
|
||||||
|
|
||||||
struct txt_record {
|
struct txt_record {
|
||||||
char *name;
|
char *name;
|
||||||
unsigned char *txt;
|
unsigned char *txt;
|
||||||
unsigned short class, len;
|
unsigned short class, len;
|
||||||
|
int stat;
|
||||||
struct txt_record *next;
|
struct txt_record *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1027,6 +1036,7 @@ void cache_add_dhcp_entry(char *host_name, int prot, struct all_addr *host_addre
|
|||||||
struct in_addr a_record_from_hosts(char *name, time_t now);
|
struct in_addr a_record_from_hosts(char *name, time_t now);
|
||||||
void cache_unhash_dhcp(void);
|
void cache_unhash_dhcp(void);
|
||||||
void dump_cache(time_t now);
|
void dump_cache(time_t now);
|
||||||
|
int cache_make_stat(struct txt_record *t);
|
||||||
char *cache_get_name(struct crec *crecp);
|
char *cache_get_name(struct crec *crecp);
|
||||||
char *cache_get_cname_target(struct crec *crecp);
|
char *cache_get_cname_target(struct crec *crecp);
|
||||||
struct crec *cache_enumerate(int init);
|
struct crec *cache_enumerate(int init);
|
||||||
|
|||||||
33
src/option.c
33
src/option.c
@@ -615,21 +615,26 @@ static int atoi_check8(char *a, int *res)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void add_txt(char *name, char *txt)
|
static void add_txt(char *name, char *txt, int stat)
|
||||||
{
|
{
|
||||||
size_t len = strlen(txt);
|
|
||||||
struct txt_record *r = opt_malloc(sizeof(struct txt_record));
|
struct txt_record *r = opt_malloc(sizeof(struct txt_record));
|
||||||
|
|
||||||
r->name = opt_string_alloc(name);
|
if (txt)
|
||||||
r->next = daemon->txt;
|
{
|
||||||
daemon->txt = r;
|
size_t len = strlen(txt);
|
||||||
r->class = C_CHAOS;
|
|
||||||
r->txt = opt_malloc(len+1);
|
r->txt = opt_malloc(len+1);
|
||||||
r->len = len+1;
|
r->len = len+1;
|
||||||
*(r->txt) = len;
|
*(r->txt) = len;
|
||||||
memcpy((r->txt)+1, txt, len);
|
memcpy((r->txt)+1, txt, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
r->stat = stat;
|
||||||
|
r->name = opt_string_alloc(name);
|
||||||
|
r->next = daemon->txt;
|
||||||
|
daemon->txt = r;
|
||||||
|
r->class = C_CHAOS;
|
||||||
|
}
|
||||||
|
|
||||||
static void do_usage(void)
|
static void do_usage(void)
|
||||||
{
|
{
|
||||||
char buff[100];
|
char buff[100];
|
||||||
@@ -3609,6 +3614,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|||||||
new->next = daemon->txt;
|
new->next = daemon->txt;
|
||||||
daemon->txt = new;
|
daemon->txt = new;
|
||||||
new->class = C_IN;
|
new->class = C_IN;
|
||||||
|
new->stat = 0;
|
||||||
|
|
||||||
if (!(new->name = canonicalise_opt(arg)))
|
if (!(new->name = canonicalise_opt(arg)))
|
||||||
ret_err(_("bad TXT record"));
|
ret_err(_("bad TXT record"));
|
||||||
@@ -4258,9 +4264,18 @@ void read_opts(int argc, char **argv, char *compile_opts)
|
|||||||
daemon->soa_refresh = SOA_REFRESH;
|
daemon->soa_refresh = SOA_REFRESH;
|
||||||
daemon->soa_retry = SOA_RETRY;
|
daemon->soa_retry = SOA_RETRY;
|
||||||
daemon->soa_expiry = SOA_EXPIRY;
|
daemon->soa_expiry = SOA_EXPIRY;
|
||||||
add_txt("version.bind", "dnsmasq-" VERSION );
|
add_txt("version.bind", "dnsmasq-" VERSION, 0 );
|
||||||
add_txt("authors.bind", "Simon Kelley");
|
add_txt("authors.bind", "Simon Kelley", 0);
|
||||||
add_txt("copyright.bind", COPYRIGHT);
|
add_txt("copyright.bind", COPYRIGHT, 0);
|
||||||
|
add_txt("cachesize.bind", NULL, TXT_STAT_CACHESIZE);
|
||||||
|
add_txt("insertions.bind", NULL, TXT_STAT_INSERTS);
|
||||||
|
add_txt("evictions.bind", NULL, TXT_STAT_EVICTIONS);
|
||||||
|
add_txt("misses.bind", NULL, TXT_STAT_MISSES);
|
||||||
|
add_txt("hits.bind", NULL, TXT_STAT_HITS);
|
||||||
|
#ifdef HAVE_AUTH
|
||||||
|
add_txt("auth.bind", NULL, TXT_STAT_AUTH);
|
||||||
|
#endif
|
||||||
|
add_txt("servers.bind", NULL, TXT_STAT_SERVERS);
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1547,9 +1547,19 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
|||||||
ans = 1;
|
ans = 1;
|
||||||
if (!dryrun)
|
if (!dryrun)
|
||||||
{
|
{
|
||||||
|
unsigned long ttl = daemon->local_ttl;
|
||||||
|
int ok = 1;
|
||||||
log_query(F_CONFIG | F_RRNAME, name, NULL, "<TXT>");
|
log_query(F_CONFIG | F_RRNAME, name, NULL, "<TXT>");
|
||||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
/* Dynamically generate stat record */
|
||||||
daemon->local_ttl, NULL,
|
if (t->stat != 0)
|
||||||
|
{
|
||||||
|
ttl = 0;
|
||||||
|
if (!cache_make_stat(t))
|
||||||
|
ok = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ok && add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||||
|
ttl, NULL,
|
||||||
T_TXT, t->class, "t", t->len, t->txt))
|
T_TXT, t->class, "t", t->len, t->txt))
|
||||||
anscount++;
|
anscount++;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user