Cache stats availble in CHAOS .bind domain.

This commit is contained in:
Simon Kelley
2014-03-27 20:54:34 +00:00
parent 4e1fe44428
commit fec216df32
5 changed files with 155 additions and 15 deletions

View File

@@ -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

View File

@@ -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)
{ {

View File

@@ -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);

View File

@@ -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)
{ {

View File

@@ -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++;