Code

named plugin: Many many more fixes to get the plugin working.
authorFlorian Forster <octo@leeloo.lan.home.verplant.org>
Fri, 20 Oct 2006 09:41:35 +0000 (11:41 +0200)
committerFlorian Forster <octo@leeloo.lan.home.verplant.org>
Fri, 20 Oct 2006 09:41:35 +0000 (11:41 +0200)
So far the QTypes are collected, and nothing else. But the core pcap-capturing
and communication over the pipe work now.

src/dnstop.c
src/named.c

index ba70fd2542e448615f0671cacdc84c52332cb698..a5b651d533fc6abf5fb908860b9be66c30e4a0cb 100644 (file)
@@ -166,22 +166,10 @@ typedef int (printer)(const char *, ...);
 /*
  * Global variables
  */
-static int interactive = 1;
-static char *device = NULL;
+pcap_t *pcap = NULL;
 static struct in_addr ignore_addr;
-static pcap_t *pcap = NULL;
-static char *bpf_program_str = "udp dst port 53 and udp[10:2] & 0x8000 = 0";
-static WINDOW *w;
-static unsigned short port53;
-static void (*SubReport) (void) = NULL;
-static int (*handle_datalink) (const u_char * pkt, int len) = NULL;
-static int Quit = 0;
-static char *progname = NULL;
-static int anon_flag = 0;
 static int sld_flag = 0;
 static int nld_flag = 0;
-static int promisc_flag = 1;
-static AnonMap *Anons = NULL;
 
 static int query_count_intvl = 0;
 static int query_count_total = 0;
@@ -201,47 +189,6 @@ static struct bpf_timeval last_ts;
 static struct timeval last_ts;
 #endif
 
-/* Prototypes */
-static void SldBySource_report(void);
-static void NldBySource_report(void);
-static void Sources_report(void);
-static void Destinatioreport(void);
-static void Qtypes_report(void);
-static void Opcodes_report(void);
-static void Tld_report(void);
-static void Sld_report(void);
-static void Nld_report(void);
-static void Help_report(void);
-static void ResetCounters(void);
-
-static Filter_t UnknownTldFilter;
-static Filter_t AforAFilter;
-static Filter_t RFC1918PtrFilter;
-static Filter_t *Filter = NULL;
-
-static printer *print_func = (printer *) printw;
-
-static struct in_addr
-AnonMap_lookup_or_add(AnonMap ** headP, struct in_addr real)
-{
-    AnonMap **T;
-    for (T = headP; (*T); T = &(*T)->next)
-       if ((*T)->real.s_addr == real.s_addr)
-           return (*T)->anon;
-    (*T) = calloc(1, sizeof(**T));
-    (*T)->real = real;
-    (*T)->anon.s_addr = random();
-    return (*T)->anon;
-}
-
-static char *
-anon_inet_ntoa(struct in_addr a)
-{
-    if (anon_flag)
-       a = AnonMap_lookup_or_add(&Anons, a);
-    return inet_ntoa(a);
-}
-
 static AgentAddr *
 AgentAddr_lookup_or_add(AgentAddr ** headP, struct in_addr a)
 {
@@ -280,97 +227,6 @@ StringAddrCounter_lookup_or_add(StringAddrCounter ** headP, struct in_addr a, co
     return (*T);
 }
 
-static int
-foo_cmp(const void *A, const void *B)
-{
-    const foo *a = A;
-    const foo *b = B;
-    if (a->cnt < b->cnt)
-       return 1;
-    if (a->cnt > b->cnt)
-       return -1;
-    if (a->ptr < b->ptr)
-       return 1;
-    if (a->ptr > b->ptr)
-       return -1;
-    return 0;
-}
-
-static void
-AgentAddr_sort(AgentAddr ** headP)
-{
-    foo *sortme;
-    int n_agents = 0;
-    int i;
-    AgentAddr *a;
-    for (a = *headP; a; a = a->next)
-       n_agents++;
-    sortme = calloc(n_agents, sizeof(foo));
-    n_agents = 0;
-    for (a = *headP; a; a = a->next) {
-       sortme[n_agents].cnt = a->count;
-       sortme[n_agents].ptr = a;
-       n_agents++;
-    }
-    qsort(sortme, n_agents, sizeof(foo), foo_cmp);
-    for (i = 0; i < n_agents; i++) {
-       *headP = sortme[i].ptr;
-       headP = &(*headP)->next;
-    }
-    free(sortme);
-    *headP = NULL;
-}
-
-static void
-StringCounter_sort(StringCounter ** headP)
-{
-    foo *sortme;
-    int n_things = 0;
-    int i;
-    StringCounter *sc;
-    for (sc = *headP; sc; sc = sc->next)
-       n_things++;
-    sortme = calloc(n_things, sizeof(foo));
-    n_things = 0;
-    for (sc = *headP; sc; sc = sc->next) {
-       sortme[n_things].cnt = sc->count;
-       sortme[n_things].ptr = sc;
-       n_things++;
-    }
-    qsort(sortme, n_things, sizeof(foo), foo_cmp);
-    for (i = 0; i < n_things; i++) {
-       *headP = sortme[i].ptr;
-       headP = &(*headP)->next;
-    }
-    free(sortme);
-    *headP = NULL;
-}
-
-static void
-StringAddrCounter_sort(StringAddrCounter ** headP)
-{
-    foo *sortme;
-    int n_things = 0;
-    int i;
-    StringAddrCounter *ssc;
-    for (ssc = *headP; ssc; ssc = ssc->next)
-       n_things++;
-    sortme = calloc(n_things, sizeof(foo));
-    n_things = 0;
-    for (ssc = *headP; ssc; ssc = ssc->next) {
-       sortme[n_things].cnt = ssc->count;
-       sortme[n_things].ptr = ssc;
-       n_things++;
-    }
-    qsort(sortme, n_things, sizeof(foo), foo_cmp);
-    for (i = 0; i < n_things; i++) {
-       *headP = sortme[i].ptr;
-       headP = &(*headP)->next;
-    }
-    free(sortme);
-    *headP = NULL;
-}
-
 #define RFC1035_MAXLABELSZ 63
 static int
 rfc1035NameUnpack(const char *buf, size_t sz, off_t * off, char *name, size_t ns
@@ -460,6 +316,9 @@ handle_dns(const char *buf, int len, const struct in_addr sip, const struct in_a
     StringCounter *sc;
     StringAddrCounter *ssc;
 
+    fprintf (stderr, "handle_dns (buf = %p, len = %i)\n",
+                   (void *) buf, len);
+
     if (len < sizeof(qh))
        return 0;
 
@@ -507,8 +366,7 @@ handle_dns(const char *buf, int len, const struct in_addr sip, const struct in_a
     memcpy(&us, buf + offset + 2, 2);
     qclass = ntohs(us);
 
-    if (Filter && 0 == Filter(qtype, qclass, qname, sip, dip))
-       return 0;
+    fprintf (stderr, "qtype = %hu\n", qtype);
 
     /* gather stats */
     qtype_counts[qtype]++;
@@ -546,7 +404,9 @@ static int
 handle_udp(const struct udphdr *udp, int len, struct in_addr sip, struct in_addr dip)
 {
     char buf[PCAP_SNAPLEN];
-    if (port53 != udp->uh_dport)
+    fprintf (stderr, "handle_udp (udp = %p, len = %i)\n",
+                   (void *) udp, len);
+    if (ntohs (udp->uh_dport) != 53)
        return 0;
     memcpy(buf, udp + 1, len - sizeof(*udp));
     if (0 == handle_dns(buf, len - sizeof(*udp), sip, dip))
@@ -561,6 +421,8 @@ handle_ip(const struct ip *ip, int len)
     int offset = ip->ip_hl << 2;
     AgentAddr *clt;
     AgentAddr *srv;
+    fprintf (stderr, "handle_ip (ip = %p, len = %i)\n",
+                   (void *) ip, len);
     if (ignore_addr.s_addr)
        if (ip->ip_src.s_addr == ignore_addr.s_addr)
            return 0;
@@ -647,6 +509,8 @@ handle_ether(const u_char * pkt, int len)
     char buf[PCAP_SNAPLEN];
     struct ether_header *e = (void *) pkt;
     unsigned short etype = ntohs(e->ether_type);
+    fprintf (stderr, "handle_ether (pkt = %p, len = %i)\n",
+                   (void *) pkt, len);
     if (len < ETHER_HDR_LEN)
        return 0;
     pkt += ETHER_HDR_LEN;
@@ -667,6 +531,10 @@ void handle_pcap(u_char *udata, const struct pcap_pkthdr *hdr, const u_char *pkt
 {
     int status;
 
+    fprintf (stderr, "handle_pcap (udata = %p, hdr = %p, pkt = %p): hdr->caplen = %i\n",
+                   (void *) udata, (void *) hdr, (void *) pkt,
+                   hdr->caplen);
+
     if (hdr->caplen < ETHER_HDR_LEN)
        return;
 
@@ -709,147 +577,61 @@ void handle_pcap(u_char *udata, const struct pcap_pkthdr *hdr, const u_char *pkt
     last_ts = hdr->ts;
 }
 
-static void
-cron_pre(void)
-{
-    AgentAddr_sort(&Sources);
-    AgentAddr_sort(&Destinations);
-    StringCounter_sort(&Tlds);
-    StringCounter_sort(&Slds);
-    StringCounter_sort(&Nlds);
-    StringAddrCounter_sort(&SSC2);
-    StringAddrCounter_sort(&SSC3);
-}
-
-static void
-cron_post(void)
-{
-    query_count_intvl = 0;
-}
-
-static void
-keyboard(void)
-{
-    int ch;
-    ch = getch() & 0xff;
-    if (ch >= 'A' && ch <= 'Z')
-       ch += 'a' - 'A';
-    switch (ch) {
-    case 's':
-       SubReport = Sources_report;
-       break;
-    case 'd':
-       SubReport = Destinatioreport;
-       break;
-    case '1':
-       SubReport = Tld_report;
-       break;
-    case '2':
-       SubReport = Sld_report;
-       break;
-    case '3':
-       SubReport = Nld_report;
-       break;
-    case 'c':
-    case '@':
-       SubReport = SldBySource_report;
-       break;
-    case '#':
-       SubReport = NldBySource_report;
-       break;
-    case 't':
-       SubReport = Qtypes_report;
-       break;
-    case 'o':
-       SubReport = Opcodes_report;
-       break;
-    case 030:
-       Quit = 1;
-       break;
-    case 022:
-       ResetCounters();
-       break;
-    case '?':
-       SubReport = Help_report;
-       break;
-    default:
-       break;
-    }
-}
-
-static void
-Help_report(void)
-{
-    print_func(" s - Sources list\n");
-    print_func(" d - Destinations list\n");
-    print_func(" t - Query types\n");
-    print_func(" o - Opcodes\n");
-    print_func(" 1 - TLD list\n");
-    print_func(" 2 - SLD list\n");
-    print_func(" 3 - 3LD list\n");
-    print_func(" @ - SLD+Sources list\n");
-    print_func(" # - 3LD+Sources list\n");
-    print_func("^R - Reset counters\n");
-    print_func("^X - Exit\n");
-    print_func("\n");
-    print_func("? - this\n");
-}
-
-static char *
+char *
 qtype_str(int t)
 {
     static char buf[30];
     switch (t) {
     case T_A:
-       return "A?";
+       return "A";
        break;
     case T_NS:
-       return "NS?";
+       return "NS";
        break;
     case T_CNAME:
-       return "CNAME?";
+       return "CNAME";
        break;
     case T_SOA:
-       return "SOA?";
+       return "SOA";
        break;
     case T_PTR:
-       return "PTR?";
+       return "PTR";
        break;
     case T_MX:
-       return "MX?";
+       return "MX";
        break;
     case T_TXT:
-       return "TXT?";
+       return "TXT";
        break;
     case T_SIG:
-       return "SIG?";
+       return "SIG";
        break;
     case T_KEY:
-       return "KEY?";
+       return "KEY";
        break;
     case T_AAAA:
-       return "AAAA?";
+       return "AAAA";
        break;
     case T_LOC:
-       return "LOC?";
+       return "LOC";
        break;
     case T_SRV:
-       return "SRV?";
+       return "SRV";
        break;
     case T_A6:
-       return "A6?";
+       return "A6";
        break;
     case T_ANY:
-       return "ANY?";
+       return "ANY";
        break;
     default:
-       snprintf(buf, 30, "#%d?", t);
+       snprintf(buf, 30, "#%d", t);
        return buf;
     }
     /* NOTREACHED */
 }
 
-static char *
+char *
 opcode_str(int o)
 {
     static char buf[30];
@@ -876,358 +658,6 @@ opcode_str(int o)
     /* NOTREACHED */
 }
 
-static int
-get_nlines(void)
-{
-       if (interactive)
-               return getmaxy(w) - 6;
-       else
-               return 50;
-}
-
-static void
-StringCounter_report(StringCounter * list, char *what)
-{
-    StringCounter *sc;
-    int nlines = get_nlines();
-    print_func("%-30s %9s %6s\n", what, "count", "%");
-    print_func("%-30s %9s %6s\n",
-       "------------------------------", "---------", "------");
-    for (sc = list; sc; sc = sc->next) {
-       print_func("%-30.30s %9d %6.1f\n",
-           sc->s,
-           sc->count,
-           100.0 * sc->count / query_count_total);
-       if (0 == --nlines)
-           break;
-    }
-}
-
-static void
-StringCounter_free(StringCounter ** headP)
-{
-    StringCounter *sc;
-    void *next;
-    for (sc = *headP; sc; sc = next) {
-       next = sc->next;
-       free(sc->s);
-       free(sc);
-    }
-    *headP = NULL;
-}
-
-static void
-StringAddrCounter_free(StringAddrCounter ** headP)
-{
-    StringAddrCounter *ssc;
-    void *next;
-    for (ssc = *headP; ssc; ssc = next) {
-       next = ssc->next;
-       free(ssc->str);
-       free(ssc);
-    }
-    *headP = NULL;
-}
-
-static void
-Tld_report(void)
-{
-    StringCounter_report(Tlds, "TLD");
-}
-
-static void
-Sld_report(void)
-{
-    if (0 == sld_flag) {
-       print_func("\tYou must start %s with the -s option\n", progname);
-       print_func("\tto collect 2nd level domain stats.\n", progname);
-    } else {
-       StringCounter_report(Slds, "SLD");
-    }
-}
-
-static void
-Nld_report(void)
-{
-    if (0 == nld_flag) {
-       print_func("\tYou must start %s with the -t option\n", progname);
-       print_func("\tto collect 3nd level domain stats.\n", progname);
-    } else {
-       StringCounter_report(Nlds, "3LD");
-    }
-}
-
-static void
-Qtypes_report(void)
-{
-    int type;
-    int nlines = get_nlines();
-    print_func("%-10s %9s %6s\n", "Query Type", "count", "%");
-    print_func("%-10s %9s %6s\n", "----------", "---------", "------");
-    for (type = 0; type < T_MAX; type++) {
-       if (0 == qtype_counts[type])
-           continue;
-       print_func("%-10s %9d %6.1f\n",
-           qtype_str(type),
-           qtype_counts[type],
-           100.0 * qtype_counts[type] / query_count_total);
-       if (0 == --nlines)
-           break;
-    }
-}
-
-static void
-Opcodes_report(void)
-{
-    int op;
-    int nlines = get_nlines();
-    print_func("%-10s %9s %6s\n", "Opcode    ", "count", "%");
-    print_func("%-10s %9s %6s\n", "----------", "---------", "------");
-    for (op = 0; op < OP_MAX; op++) {
-       if (0 == opcode_counts[op])
-           continue;
-       print_func("%-10s %9d %6.1f\n",
-           opcode_str(op),
-           opcode_counts[op],
-           100.0 * opcode_counts[op] / query_count_total);
-       if (0 == --nlines)
-           break;
-    }
-}
-
-static void
-AgentAddr_report(AgentAddr * list, const char *what)
-{
-    AgentAddr *agent;
-    int nlines = get_nlines();
-    print_func("%-16s %9s %6s\n", what, "count", "%");
-    print_func("%-16s %9s %6s\n", "----------------", "---------", "------");
-    for (agent = list; agent; agent = agent->next) {
-       print_func("%-16s %9d %6.1f\n",
-           anon_inet_ntoa(agent->src),
-           agent->count,
-           100.0 * agent->count / query_count_total);
-       if (0 == --nlines)
-           break;
-    }
-}
-
-static void
-Combo_report(StringAddrCounter * list, char *what1, char *what2)
-{
-    StringAddrCounter *ssc;
-    int nlines = get_nlines();
-    print_func("%-16s %-32s %9s %6s\n", what1, what2, "count", "%");
-    print_func("%-16s %-32s %9s %6s\n",
-       "----------------", "--------------------", "---------", "------");
-    for (ssc = list; ssc; ssc = ssc->next) {
-       print_func("%-16s %-32s %9d %6.1f\n",
-           anon_inet_ntoa(ssc->src),
-           ssc->str,
-           ssc->count,
-           100.0 * ssc->count / query_count_total);
-       if (0 == --nlines)
-           break;
-    }
-}
-
-static void
-SldBySource_report(void)
-{
-    if (0 == sld_flag) {
-       print_func("\tYou must start %s with the -s option\n", progname);
-       print_func("\tto collect 2nd level domain stats.\n", progname);
-    } else {
-       Combo_report(SSC2, "Source", "SLD");
-    }
-}
-
-static void
-NldBySource_report(void)
-{
-    if (0 == nld_flag) {
-       print_func("\tYou must start %s with the -t option\n", progname);
-       print_func("\tto collect 3nd level domain stats.\n", progname);
-    } else {
-       Combo_report(SSC3, "Source", "3LD");
-    }
-}
-
-
-static void
-AgentAddr_free(AgentAddr ** headP)
-{
-    AgentAddr *aa;
-    void *next;
-    for (aa = *headP; aa; aa = next) {
-       next = aa->next;
-       free(aa);
-    }
-    *headP = NULL;
-}
-
-static void
-Sources_report(void)
-{
-    AgentAddr_report(Sources, "Sources");
-}
-
-static void
-Destinatioreport(void)
-{
-    AgentAddr_report(Destinations, "Destinations");
-}
-
-static void
-report(void)
-{
-    move(0, 0);
-    print_func("%d new queries, %d total queries",
-       query_count_intvl, query_count_total);
-    clrtoeol();
-    if (last_ts.tv_sec) {
-       time_t t = (time_t) last_ts.tv_sec;
-       move(0, 50);
-       print_func("%s", ctime(&t));
-    }
-    move(2, 0);
-    clrtobot();
-    if (SubReport)
-       SubReport();
-    refresh();
-}
-
-/*
- * === BEGIN FILTERS ==========================================================
- */
-
-#include "known_tlds.h"
-
-static int
-UnknownTldFilter(unsigned short qt, unsigned short qc, const char *qn, const struct in_addr sip, const struct in_addr dip)
-{
-    const char *tld = QnameToNld(qn, 1);
-    unsigned int i;
-    if (NULL == tld)
-       return 1;               /* tld is unknown */
-    for (i = 0; KnownTLDS[i]; i++)
-       if (0 == strcmp(KnownTLDS[i], tld))
-           return 0;           /* tld is known */
-    return 1;                  /* tld is unknown */
-}
-
-static int
-AforAFilter(unsigned short qt, unsigned short qc, const char *qn, const struct in_addr sip, const struct in_addr dip)
-{
-    struct in_addr a;
-    if (qt != T_A)
-       return 0;  
-    return inet_aton(qn, &a);
-}
-
-static int
-RFC1918PtrFilter(unsigned short qt, unsigned short qc, const char *qn, const struct in_addr sip, const struct in_addr dip)
-{
-    char *t;
-    char q[128];   
-    unsigned int i = 0;
-    if (qt != T_PTR)
-       return 0;  
-    strncpy(q, qn, sizeof(q)-1);
-    q[sizeof(q)-1] = '\0';
-    t = strstr(q, ".in-addr.arpa");
-    if (NULL == t)
-       return 0;
-    *t = '\0';
-    for (t = strtok(q, "."); t; t = strtok(NULL, ".")) {
-       i >>= 8;
-       i |= ((atoi(t) & 0xff) << 24);
-    }
-    if ((i & 0xff000000) == 0x0a000000)
-       return 1;
-    if ((i & 0xfff00000) == 0xac100000)
-       return 1;
-    if ((i & 0xffff0000) == 0xc0a80000)
-       return 1;
-    return 0;
-}
-
-static void
-set_filter(const char *fn)
-{
-       if (0 == strcmp(fn, "unknown-tlds"))
-               Filter = UnknownTldFilter;
-       else if (0 == strcmp(fn, "A-for-A"))
-               Filter = AforAFilter;
-       else if (0 == strcmp(fn, "rfc1918-ptr"))
-               Filter = RFC1918PtrFilter;
-       else
-               Filter = NULL;
-}
-
-/*
- * === END FILTERS ==========================================================
- */
-
-static void
-init_curses(void)
-{
-    w = initscr();
-    cbreak();
-    noecho();
-    nodelay(w, 1);
-}
-
-static void
-ResetCounters(void)
-{
-    query_count_intvl = 0;
-    query_count_total = 0;
-    memset(qtype_counts, '\0', sizeof(qtype_counts));
-    memset(qclass_counts, '\0', sizeof(qclass_counts));
-    memset(opcode_counts, '\0', sizeof(opcode_counts));
-    AgentAddr_free(&Sources);
-    AgentAddr_free(&Destinations);
-    StringCounter_free(&Tlds);
-    StringCounter_free(&Slds);
-    StringCounter_free(&Nlds);
-    StringAddrCounter_free(&SSC2);
-    StringAddrCounter_free(&SSC3);
-    memset(&last_ts, '\0', sizeof(last_ts));
-}
-
-static void
-usage(void)
-{
-    fprintf(stderr, "usage: %s [opts] netdevice|savefile\n",
-       progname);
-    fprintf(stderr, "\t-a\tAnonymize IP Addrs\n");
-    fprintf(stderr, "\t-b expr\tBPF program code\n");
-    fprintf(stderr, "\t-i addr\tIgnore this source IP address\n");
-    fprintf(stderr, "\t-p\tDon't put interface in promiscuous mode\n");
-    fprintf(stderr, "\t-s\tEnable 2nd level domain stats collection\n");
-    fprintf(stderr, "\t-t\tEnable 3nd level domain stats collection\n");
-    fprintf(stderr, "\t-f\tfilter-name\n");
-    fprintf(stderr, "\n");
-    fprintf(stderr, "Available filters:\n");
-    fprintf(stderr, "\tunknown-tlds\n");
-    fprintf(stderr, "\tA-for-A\n");
-    fprintf(stderr, "\trfc1918-ptr\n");
-    exit(1);
-}
-
-static int
-pcap_select(pcap_t * p, int sec, int usec)
-{
-    fd_set R;
-    struct timeval to;
-    FD_ZERO(&R);
-    FD_SET(pcap_fileno(p), &R);
-    to.tv_sec = sec;
-    to.tv_usec = usec;
-    return select(pcap_fileno(p) + 1, &R, NULL, NULL, &to);
-}
-
 #if 0
 static int
 main(int argc, char *argv[])
index 2ff92b9b13f9e450071f1b5c66b9801f6b6adced..ca50902b7a9a8a02cd516340d5a9c02726233d8b 100644 (file)
@@ -68,7 +68,7 @@ static int config_keys_num = 1;
 #if HAVE_LIBPCAP
 #define PCAP_SNAPLEN 1460
 static char   *pcap_device = NULL;
-static int     pipe_fd;
+static int     pipe_fd = -1;
 #endif
 
 #if NAMED_HAVE_CONFIG
@@ -98,6 +98,9 @@ static int named_child_send_data (void)
        int values_num;
        int i;
 
+       if (pipe_fd < 0)
+               return (-1);
+
        values_num = 0;
        for (i = 0; i < T_MAX; i++)
        {
@@ -109,15 +112,22 @@ static int named_child_send_data (void)
                }
        }
 
+       DBG ("swrite (pipe_fd = %i, values_num = %i)", pipe_fd, values_num);
        if (swrite (pipe_fd, (const void *) &values_num, sizeof (values_num)) != 0)
        {
+               DBG ("Writing to pipe failed: %s", strerror (errno));
                syslog (LOG_ERR, "named plugin: Writing to pipe failed: %s",
                                strerror (errno));
                return (-1);
        }
 
+       if (values_num == 0)
+               return (0);
+
+       DBG ("swrite (pipe_fd = %i, values = %p, size = %i)", pipe_fd, (void *) values, (int) (sizeof (int) * values_num));
        if (swrite (pipe_fd, (const void *) values, 2 * sizeof (int) * values_num) != 0)
        {
+               DBG ("Writing to pipe failed: %s", strerror (errno));
                syslog (LOG_ERR, "named plugin: Writing to pipe failed: %s",
                                strerror (errno));
                return (-1);
@@ -130,11 +140,13 @@ static void named_child_loop (void)
 {
        pcap_t *pcap_obj;
        char    pcap_error[PCAP_ERRBUF_SIZE];
+       struct  bpf_program fp;
 
        struct pollfd poll_fds[2];
        int status;
 
        /* Passing `pcap_device == NULL' is okay and the same as passign "any" */
+       DBG ("Creating PCAP object..");
        pcap_obj = pcap_open_live (pcap_device,
                        PCAP_SNAPLEN,
                        0 /* Not promiscuous */,
@@ -146,9 +158,31 @@ static void named_child_loop (void)
                                (pcap_device != NULL) ? pcap_device : "any",
                                pcap_error);
                close (pipe_fd);
+               pipe_fd = -1;
+               return;
+       }
+       pcap = pcap_obj; /* FIXME: This is used by `handle_pcap' */
+
+       memset (&fp, 0, sizeof (fp));
+       if (pcap_compile (pcap_obj, &fp, "udp dst port 53", 1, 0) < 0)
+       {
+               DBG ("pcap_compile failed");
+               syslog (LOG_ERR, "named plugin: pcap_compile failed");
+               close (pipe_fd);
+               pipe_fd = -1;
+               return;
+       }
+       if (pcap_setfilter (pcap_obj, &fp) < 0)
+       {
+               DBG ("pcap_setfilter failed");
+               syslog (LOG_ERR, "named plugin: pcap_setfilter failed");
+               close (pipe_fd);
+               pipe_fd = -1;
                return;
        }
 
+       DBG ("PCAP object created.");
+
        /* Set up pipe end */
        poll_fds[0].fd = pipe_fd;
        poll_fds[0].events = POLLOUT;
@@ -159,6 +193,7 @@ static void named_child_loop (void)
 
        while (42)
        {
+               DBG ("poll (...)");
                status = poll (poll_fds, 2, -1 /* wait forever for a change */);
 
                if (status < 0)
@@ -170,11 +205,13 @@ static void named_child_loop (void)
 
                if (poll_fds[0].revents & (POLLERR | POLLHUP | POLLNVAL))
                {
+                       DBG ("Pipe closed. Exiting.");
                        syslog (LOG_NOTICE, "named plugin: Pipe closed. Exiting.");
                        break;
                }
                else if (poll_fds[0].revents & POLLOUT)
                {
+                       DBG ("Calling `named_child_send_data'");
                        if (named_child_send_data () < 0)
                        {
                                break;
@@ -183,6 +220,7 @@ static void named_child_loop (void)
 
                if (poll_fds[1].revents & (POLLERR | POLLHUP | POLLNVAL))
                {
+                       DBG ("pcap-device closed. Exiting.");
                        syslog (LOG_ERR, "named plugin: pcap-device closed. Exiting.");
                        break;
                }
@@ -190,11 +228,12 @@ static void named_child_loop (void)
                {
                        /* TODO: Read and analyse packet */
                        status = pcap_dispatch (pcap_obj,
-                                       10 /* Only handle 10 packets at a time */,
+                                       1 /* Only handle 10 packets at a time */,
                                        handle_pcap /* callback */,
                                        NULL /* Whatever this means.. */);
                        if (status < 0)
                        {
+                               DBG ("pcap_dispatch failed: %s", pcap_geterr (pcap_obj));
                                syslog (LOG_ERR, "named plugin: pcap_dispatch failed: %s",
                                                pcap_geterr (pcap_obj));
                                break;
@@ -202,7 +241,10 @@ static void named_child_loop (void)
                }
        } /* while (42) */
 
+       DBG ("child is exiting");
+
        close (pipe_fd);
+       pipe_fd = -1;
        pcap_close (pcap_obj);
 } /* static void named_child_loop (void) */
 
@@ -245,10 +287,39 @@ static void named_init (void)
                exit (0);
        }
 
-       fcntl (pipe_fd, F_SETFL, O_NONBLOCK);
+       /* fcntl (pipe_fd, F_SETFL, O_NONBLOCK); */
 #endif
 }
 
+static void qtype_write (char *host, char *inst, char *val)
+{
+       char file[512];
+       int status;
+
+       status = snprintf (file, 512, qtype_file, inst);
+       if (status < 1)
+               return;
+       else if (status >= 512)
+               return;
+
+       rrd_update_file (host, file, val, qtype_ds_def, qtype_ds_num);
+}
+
+static void qtype_submit (int qtype_int, unsigned int counter)
+{
+       char *qtype_char;
+       char  buffer[32];
+       int   status;
+
+       qtype_char = qtype_str (qtype_int);
+
+       status = snprintf (buffer, 32, "N:%i", counter);
+       if ((status < 1) || (status >= 32))
+               return;
+
+       plugin_submit ("named_qtype", qtype_char, buffer);
+}
+
 #if NAMED_HAVE_READ
 static void named_read (void)
 {
@@ -258,19 +329,32 @@ static void named_read (void)
        int counter;
        int i;
 
+       if (pipe_fd < 0)
+               return;
+
+       DBG ("Reading from pipe_fd = %i..", pipe_fd);
        if (sread (pipe_fd, (void *) &values_num, sizeof (values_num)) != 0)
        {
                syslog (LOG_ERR, "named plugin: Reading from the pipe failed: %s",
                                strerror (errno));
+               pipe_fd = -1;
                return;
        }
 
        assert ((values_num >= 0) && (values_num <= T_MAX));
 
+       if (values_num == 0)
+       {
+               DBG ("No values available; returning");
+               return;
+       }
+
+       DBG ("Reading %i qtype/values from pipe_fd = %i..", values_num, pipe_fd);
        if (sread (pipe_fd, (void *) values, 2 * sizeof (int) * values_num) != 0)
        {
                syslog (LOG_ERR, "named plugin: Reading from the pipe failed: %s",
                                strerror (errno));
+               pipe_fd = -1;
                return;
        }
 
@@ -280,6 +364,7 @@ static void named_read (void)
                counter = values[(2 * i) + 1];
 
                DBG ("qtype = %i; counter = %i;", qtype, counter);
+               qtype_submit (qtype, counter);
        }
 }
 #else /* if !NAMED_HAVE_READ */
@@ -289,6 +374,7 @@ static void named_read (void)
 void module_register (void)
 {
        plugin_register (MODULE_NAME, named_init, named_read, NULL);
+       plugin_register ("named_qtype", NULL, NULL, qtype_write);
        /* TODO */
        cf_register (MODULE_NAME, named_config, config_keys, config_keys_num);
 }