From f860dee9cb44b67dd34690e854e2ee9e326ca706 Mon Sep 17 00:00:00 2001 From: Marko Kreen Date: Tue, 22 Nov 2011 23:18:44 +0200 Subject: [PATCH] New commands: SHOW DNS_HOSTS|DNS_ZONES To give visibility into DNS cache. --- doc/usage.txt | 27 +++++++++++++++++++ include/dnslookup.h | 6 +++++ src/admin.c | 66 ++++++++++++++++++++++++++++++++++++++++++++- src/dnslookup.c | 56 +++++++++++++++++++++++++++++++++----- 4 files changed, 147 insertions(+), 8 deletions(-) diff --git a/doc/usage.txt b/doc/usage.txt index 6810c43..3d544cb 100644 --- a/doc/usage.txt +++ b/doc/usage.txt @@ -411,6 +411,33 @@ changeable:: Either +yes+ or +no+, shows if the variable can be changed while running. If +no+, the variable can be changed only boot-time. +==== SHOW DNS_HOSTS ==== + +Show hostnames in DNS cache. + +hostname:: + Host name. + +ttl:: + How meny seconds until next lookup. + +addrs:: + Comma separated list of addresses. + +==== SHOW DNS_ZONES ==== + +Show DNS zones in cache. + +zonename:: + Zone name. + +serial:: + Current serial. + +count:: + Hostnames belonging to this zone. + + === PROCESS CONTROLLING COMMANDS === ==== PAUSE [db]; ==== diff --git a/include/dnslookup.h b/include/dnslookup.h index 78d5719..797c1d2 100644 --- a/include/dnslookup.h +++ b/include/dnslookup.h @@ -18,6 +18,7 @@ struct DNSContext; struct DNSToken; +struct addrinfo; typedef void (*adns_callback_f)(void *arg, const struct sockaddr *sa, int salen); @@ -35,3 +36,8 @@ void adns_zone_cache_maint(struct DNSContext *ctx); void adns_info(struct DNSContext *ctx, int *names, int *zones, int *queries, int *pending); +typedef void (*adns_walk_name_f)(void *arg, const char *name, const struct addrinfo *ai, usec_t ttl); +typedef void (*adns_walk_zone_f)(void *arg, const char *name, uint32_t serial, int nhosts); + +void adns_walk_names(struct DNSContext *ctx, adns_walk_name_f cb, void *arg); +void adns_walk_zones(struct DNSContext *ctx, adns_walk_zone_f cb, void *arg); diff --git a/src/admin.c b/src/admin.c index c8340ca..9f80a26 100644 --- a/src/admin.c +++ b/src/admin.c @@ -23,6 +23,7 @@ #include "bouncer.h" #include +#include /* regex elements */ #define WS0 "[ \t\n\r]*" @@ -756,6 +757,67 @@ static bool admin_show_mem(PgSocket *admin, const char *arg) return true; } +/* Command: SHOW DNS_HOSTS */ + +static void dns_name_cb(void *arg, const char *name, const struct addrinfo *ai, usec_t ttl) +{ + PktBuf *buf = arg; + char *s, *end; + char adrs[1024]; + usec_t now = get_cached_time(); + + end = adrs + sizeof(adrs) - 2; + for (s = adrs; ai && s < end; ai = ai->ai_next) { + if (s != adrs) + *s++ = ','; + sa2str(ai->ai_addr, s, end - s); + s += strlen(s); + } + *s = 0; + + pktbuf_write_DataRow(buf, "sqs", name, (ttl - now) / USEC, adrs); +} + +static bool admin_show_dns_hosts(PgSocket *admin, const char *arg) +{ + PktBuf *buf; + + buf = pktbuf_dynamic(256); + if (!buf) { + admin_error(admin, "no mem"); + return true; + } + pktbuf_write_RowDescription(buf, "sqs", "hostname", "ttl", "addrs"); + adns_walk_names(adns, dns_name_cb, buf); + admin_flush(admin, buf, "SHOW"); + return true; +} + +/* Command: SHOW DNS_ZONES */ + +static void dns_zone_cb(void *arg, const char *name, uint32_t serial, int nhosts) +{ + PktBuf *buf = arg; + pktbuf_write_DataRow(buf, "sqi", name, (uint64_t)serial, nhosts); +} + +static bool admin_show_dns_zones(PgSocket *admin, const char *arg) +{ + PktBuf *buf; + + buf = pktbuf_dynamic(256); + if (!buf) { + admin_error(admin, "no mem"); + return true; + } + pktbuf_write_RowDescription(buf, "sqi", "zonename", "serial", "count"); + adns_walk_zones(adns, dns_zone_cb, buf); + admin_flush(admin, buf, "SHOW"); + return true; +} + +/* Command: SHOW CONFIG */ + static void show_one_param(void *arg, const char *name, const char *val, bool reloadable) { PktBuf *buf = arg; @@ -763,7 +825,6 @@ static void show_one_param(void *arg, const char *name, const char *val, bool re reloadable ? "yes" : "no"); } -/* Command: SHOW CONFIG */ static bool admin_show_config(PgSocket *admin, const char *arg) { PktBuf *buf; @@ -1013,6 +1074,7 @@ static bool admin_show_help(PgSocket *admin, const char *arg) "D\n\tSHOW HELP|CONFIG|DATABASES" "|POOLS|CLIENTS|SERVERS|VERSION\n" "\tSHOW STATS|FDS|SOCKETS|ACTIVE_SOCKETS|LISTS|MEM\n" + "\tSHOW DNS_HOSTS|DNS_ZONES\n" "\tSET key = arg\n" "\tRELOAD\n" "\tPAUSE []\n" @@ -1063,6 +1125,8 @@ static struct cmd_lookup show_map [] = { {"version", admin_show_version}, {"totals", admin_show_totals}, {"mem", admin_show_mem}, + {"dns_hosts", admin_show_dns_hosts}, + {"dns_zones", admin_show_dns_zones}, {NULL, NULL} }; diff --git a/src/dnslookup.c b/src/dnslookup.c index 6c2122f..12f296c 100644 --- a/src/dnslookup.c +++ b/src/dnslookup.c @@ -92,10 +92,10 @@ struct DNSRequest { /* zone name serial */ struct DNSZone { - struct List lnode; /* DNSContext->zone_list */ - struct AANode tnode; /* DNSContext->zone_tree */ + struct List lnode; /* DNSContext->zone_list */ + struct AANode tnode; /* DNSContext->zone_tree */ - struct List host_list; /* DNSRequest->znode */ + struct StatList host_list; /* DNSRequest->znode */ const char *zonename; uint32_t serial; @@ -962,7 +962,7 @@ static void zone_register(struct DNSContext *ctx, struct DNSRequest *req) if (n) { /* already exists */ z = container_of(n, struct DNSZone, tnode); - list_append(&z->host_list, &req->znode); + statlist_append(&z->host_list, &req->znode); return; } @@ -975,13 +975,13 @@ static void zone_register(struct DNSContext *ctx, struct DNSRequest *req) free(z); return; } - list_init(&z->host_list); + statlist_init(&z->host_list, "host_list"); list_init(&z->lnode); /* link */ aatree_insert(&ctx->zone_tree, (uintptr_t)z->zonename, &z->tnode); list_append(&ctx->zone_list, &z->lnode); - list_append(&z->host_list, &req->znode); + statlist_append(&z->host_list, &req->znode); } static void zone_timer(int fd, short flg, void *arg) @@ -1035,7 +1035,7 @@ static void zone_requeue(struct DNSContext *ctx, struct DNSZone *z) { struct List *el; struct DNSRequest *req; - list_for_each(el, &z->host_list) { + statlist_for_each(el, &z->host_list) { req = container_of(el, struct DNSRequest, znode); if (!req->done) continue; @@ -1084,3 +1084,45 @@ static void got_zone_serial(struct DNSContext *ctx, uint32_t *serial) } } +/* + * Cache walkers + */ + +struct WalkInfo { + adns_walk_name_f name_cb; + adns_walk_zone_f zone_cb; + void *arg; +}; + +static void walk_name(struct AANode *n, void *arg) +{ + struct WalkInfo *w = arg; + struct DNSRequest *req = container_of(n, struct DNSRequest, node); + + w->name_cb(w->arg, req->name, req->result, req->res_ttl); +} + +static void walk_zone(struct AANode *n, void *arg) +{ + struct WalkInfo *w = arg; + struct DNSZone *z = container_of(n, struct DNSZone, tnode); + + w->zone_cb(w->arg, z->zonename, z->serial, statlist_count(&z->host_list)); +} + +void adns_walk_names(struct DNSContext *ctx, adns_walk_name_f cb, void *arg) +{ + struct WalkInfo w; + w.name_cb = cb; + w.arg = arg; + aatree_walk(&ctx->req_tree, AA_WALK_IN_ORDER, walk_name, &w); +} + +void adns_walk_zones(struct DNSContext *ctx, adns_walk_zone_f cb, void *arg) +{ + struct WalkInfo w; + w.zone_cb = cb; + w.arg = arg; + aatree_walk(&ctx->zone_tree, AA_WALK_IN_ORDER, walk_zone, &w); +} + -- 2.40.0