]> granicus.if.org Git - pgbouncer/commitdiff
New commands: SHOW DNS_HOSTS|DNS_ZONES
authorMarko Kreen <markokr@gmail.com>
Tue, 22 Nov 2011 21:18:44 +0000 (23:18 +0200)
committerMarko Kreen <markokr@gmail.com>
Tue, 22 Nov 2011 21:18:44 +0000 (23:18 +0200)
To give visibility into DNS cache.

doc/usage.txt
include/dnslookup.h
src/admin.c
src/dnslookup.c

index 6810c4329f7682fd9f440e4e7475366e08c91579..3d544cb00865d84b0f91fb1856c2dbcdc014d3c9 100644 (file)
@@ -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]; ====
index 78d5719af49ec7952f60c89ef891b5e35c15c234..797c1d24cf571eba849b2150d957f8dfb8dda7eb 100644 (file)
@@ -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);
index c8340ca0f2945b1ad47e2ea383c3493ec7e4e83a..9f80a265601f28be3cf191ff927f3351b45b2be5 100644 (file)
@@ -23,6 +23,7 @@
 #include "bouncer.h"
 
 #include <usual/regex.h>
+#include <usual/netdb.h>
 
 /* 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 [<db>]\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}
 };
 
index 6c2122fa2081101e56dd6b6d8f39fc3c86d64168..12f296c6451d7811c23203c454c22ac9832fa440 100644 (file)
@@ -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);
+}
+