Commit 5fa875bb authored by Mark Andrews's avatar Mark Andrews
Browse files

add inorder support

parent f5e3924c
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h> #include <unistd.h>
#include <assert.h>
#include <sys/types.h> #include <sys/types.h>
#include <netinet/in.h> #include <netinet/in.h>
...@@ -42,6 +43,7 @@ static int udp6 = -1; ...@@ -42,6 +43,7 @@ static int udp6 = -1;
static int debug = 0; static int debug = 0;
static int what = 0; static int what = 0;
static int inorder = 0;
static union res_sockaddr_union servers[10]; static union res_sockaddr_union servers[10];
static int nservers = 0; static int nservers = 0;
...@@ -56,8 +58,31 @@ static int nservers = 0; ...@@ -56,8 +58,31 @@ static int nservers = 0;
(list).head = (item); \ (list).head = (item); \
(item)->link.prev = list.tail; \ (item)->link.prev = list.tail; \
(item)->link.next = NULL; \ (item)->link.next = NULL; \
(item)->link.linked = 1; \
(list).tail = (item); \ (list).tail = (item); \
(item)->link.linked = 1; \
} while (0)
#define PREPEND(list, item, link) do { \
if ((list).head) \
(list).head->link.prev = (item); \
else \
(list).tail = (item); \
(item)->link.prev = NULL; \
(item)->link.next = list.head; \
(list).head = (item); \
(item)->link.linked = 1; \
} while (0)
#define INSERTBEFORE(list, before, item, link) do { \
assert(LINKED(before, link)); \
if ((before)->link.prev == NULL) \
PREPEND(list, item, link); \
else { \
(item)->link.prev = (before)->link.prev; \
(before)->link.prev = (item); \
(item)->link.prev->link.next = (item); \
(item)->link.next = (before); \
} \
} while (0) } while (0)
#define UNLINK(list, item, link) do { \ #define UNLINK(list, item, link) do { \
...@@ -74,7 +99,7 @@ static int nservers = 0; ...@@ -74,7 +99,7 @@ static int nservers = 0;
} while (0) } while (0)
#define NEXT(item, link) (item)->link.next #define NEXT(item, link) (item)->link.next
#define PREV(item, link) (item)->link.next #define PREV(item, link) (item)->link.prev
#define LINKED(item, link) (item)->link.linked #define LINKED(item, link) (item)->link.linked
#define HEAD(list) (list).head #define HEAD(list) (list).head
...@@ -147,10 +172,16 @@ static struct { ...@@ -147,10 +172,16 @@ static struct {
* Summary structure where results from multiple lookups are recorded. * Summary structure where results from multiple lookups are recorded.
*/ */
struct summary { struct summary {
struct {
struct summary *prev;
struct summary *next;
int linked;
} link;
char zone[1024]; char zone[1024];
char ns[1024]; char ns[1024];
struct sockaddr_storage storage; struct sockaddr_storage storage;
int tests; /* number of outstanding tests */ int tests; /* number of outstanding tests */
int deferred; /* was the printing deferred */
int done; int done;
int type; /* recursive query lookup type */ int type; /* recursive query lookup type */
int nodataa; /* recursive query got nodata */ int nodataa; /* recursive query got nodata */
...@@ -163,6 +194,11 @@ struct summary { ...@@ -163,6 +194,11 @@ struct summary {
char results[sizeof(opts)/sizeof(opts[0])][100]; char results[sizeof(opts)/sizeof(opts[0])][100];
}; };
static struct {
struct summary *head;
struct summary *tail;
} summaries;
struct workitem { struct workitem {
struct { struct {
struct workitem *next; struct workitem *next;
...@@ -204,6 +240,9 @@ static struct { ...@@ -204,6 +240,9 @@ static struct {
static void static void
connecttoserver(struct workitem *item); connecttoserver(struct workitem *item);
static void
report(struct summary *summary);
static int static int
storage_equal(struct sockaddr_storage *s1, struct sockaddr_storage *s2) { storage_equal(struct sockaddr_storage *s1, struct sockaddr_storage *s2) {
struct sockaddr_in *sin1, *sin2; struct sockaddr_in *sin1, *sin2;
...@@ -247,11 +286,18 @@ checkid(struct sockaddr_storage *storage, int id) { ...@@ -247,11 +286,18 @@ checkid(struct sockaddr_storage *storage, int id) {
return ((item == NULL) ? 1 : 0); return ((item == NULL) ? 1 : 0);
} }
static void
freesummary(struct summary *summary) {
if (LINKED(summary, link))
UNLINK(summaries, summary, link);
free(summary);
}
/* /*
* Generate a report line. * Generate a report line.
*/ */
static void static void
report(struct summary *summary) { printandfree(struct summary *summary) {
struct sockaddr_in *s = (struct sockaddr_in *)&summary->storage; struct sockaddr_in *s = (struct sockaddr_in *)&summary->storage;
struct sockaddr_in6 *s6 = (struct sockaddr_in6 *)&summary->storage;; struct sockaddr_in6 *s6 = (struct sockaddr_in6 *)&summary->storage;;
char addrbuf[64]; char addrbuf[64];
...@@ -259,47 +305,11 @@ report(struct summary *summary) { ...@@ -259,47 +305,11 @@ report(struct summary *summary) {
unsigned int i; unsigned int i;
int x; int x;
summary->tests--;
if (summary->tests)
return;
/*
* If we are cross linked record the lookup details on the other
* structure.
*/
if (summary->xlink) {
if (summary->nodataa) {
summary->xlink->nodataa = 1;
summary->done = 1;
}
if (summary->nodataaaaa) {
summary->xlink->nodataaaaa = 1;
summary->done = 1;
}
if (summary->nxdomaina) {
summary->xlink->nxdomaina = 1;
summary->done = 1;
}
if (summary->nxdomainaaaa) {
summary->xlink->nxdomainaaaa = 1;
summary->done = 1;
}
/*
* Remove the cross link.
*/
summary->xlink->xlink = NULL;
summary->xlink = NULL;
if (summary->done) {
free(summary);
return;
}
}
if ((summary->type == ns_t_a || summary->type == ns_t_aaaa) && if ((summary->type == ns_t_a || summary->type == ns_t_aaaa) &&
summary->nodataa && summary->nodataaaaa) { summary->nodataa && summary->nodataaaaa) {
printf("%s. %s: no address records found\n", printf("%s. %s: no address records found\n",
summary->zone, summary->ns); summary->zone, summary->ns);
free(summary); freesummary(summary);
return; return;
} }
...@@ -307,49 +317,49 @@ report(struct summary *summary) { ...@@ -307,49 +317,49 @@ report(struct summary *summary) {
summary->nxdomaina && summary->nxdomainaaaa) { summary->nxdomaina && summary->nxdomainaaaa) {
printf("%s. %s: no address records found (NXDOMAIN)\n", printf("%s. %s: no address records found (NXDOMAIN)\n",
summary->zone, summary->ns); summary->zone, summary->ns);
free(summary); freesummary(summary);
return; return;
} }
if (summary->done || summary->nodataa || summary->nodataaaaa) { if (summary->done || summary->nodataa || summary->nodataaaaa) {
free(summary); freesummary(summary);
return; return;
} }
if (summary->type != 0 && summary->nxdomain) { if (summary->type != 0 && summary->nxdomain) {
if (summary->type == ns_t_ns) { if (summary->type == ns_t_ns) {
printf("%s.: NS nxdomain\n", summary->zone); printf("%s.: NS nxdomain\n", summary->zone);
free(summary); freesummary(summary);
return; return;
} }
printf("%s. %s:", summary->zone, summary->ns); printf("%s. %s:", summary->zone, summary->ns);
if (summary->type == ns_t_a) printf(" A"); if (summary->type == ns_t_a) printf(" A");
if (summary->type == ns_t_aaaa) printf(" AAAA"); if (summary->type == ns_t_aaaa) printf(" AAAA");
printf(" nxdomain\n"); printf(" nxdomain\n");
free(summary); freesummary(summary);
return; return;
} }
if (summary->type == ns_t_a) { if (summary->type == ns_t_a) {
printf("%s. %s:", summary->zone, summary->ns); printf("%s. %s:", summary->zone, summary->ns);
printf(" A lookup failed\n"); printf(" A lookup failed\n");
free(summary); freesummary(summary);
return; return;
} }
if (summary->type == ns_t_aaaa) { if (summary->type == ns_t_aaaa) {
printf("%s. %s:", summary->zone, summary->ns); printf("%s. %s:", summary->zone, summary->ns);
printf(" AAAA lookup failed\n"); printf(" AAAA lookup failed\n");
free(summary); freesummary(summary);
return; return;
} }
if (summary->type == ns_t_ns) { if (summary->type == ns_t_ns) {
printf("%s. %s:", summary->zone, summary->ns); printf("%s. %s:", summary->zone, summary->ns);
printf(" NS lookup failed\n"); printf(" NS lookup failed\n");
free(summary); freesummary(summary);
return; return;
} }
if (summary->type != 0) { if (summary->type != 0) {
free(summary); freesummary(summary);
return; return;
} }
...@@ -382,7 +392,61 @@ report(struct summary *summary) { ...@@ -382,7 +392,61 @@ report(struct summary *summary) {
printf(" %s=%s", opts[i].name, summary->results[i]); printf(" %s=%s", opts[i].name, summary->results[i]);
} }
printf("\n"); printf("\n");
free(summary); freesummary(summary);
}
static void
report(struct summary *summary) {
/*
* Have all the tests completed?
*/
summary->tests--;
if (summary->tests)
return;
/*
* If we are cross linked record the lookup details on the other
* structure.
*/
if (summary->xlink) {
if (summary->nodataa) {
summary->xlink->nodataa = 1;
summary->done = 1;
}
if (summary->nodataaaaa) {
summary->xlink->nodataaaaa = 1;
summary->done = 1;
}
if (summary->nxdomaina) {
summary->xlink->nxdomaina = 1;
summary->done = 1;
}
if (summary->nxdomainaaaa) {
summary->xlink->nxdomainaaaa = 1;
summary->done = 1;
}
/*
* Remove the cross link.
*/
summary->xlink->xlink = NULL;
summary->xlink = NULL;
if (summary->done) {
freesummary(summary);
goto print_deferred;
}
}
if (inorder && PREV(summary, link)) {
summary->deferred = 1;
return;
}
printandfree(summary);
print_deferred:
while ((summary = HEAD(summaries)) && summary->deferred)
printandfree(summary);
} }
/* /*
...@@ -673,6 +737,7 @@ check(char *zone, char *ns, char *address) { ...@@ -673,6 +737,7 @@ check(char *zone, char *ns, char *address) {
summary = calloc(1, sizeof(*summary)); summary = calloc(1, sizeof(*summary));
if (summary == NULL) if (summary == NULL)
return; return;
APPEND(summaries, summary, link);
summary->storage = storage; summary->storage = storage;
...@@ -841,7 +906,7 @@ dolookup(struct workitem *item, int type) { ...@@ -841,7 +906,7 @@ dolookup(struct workitem *item, int type) {
* Start a A lookup. * Start a A lookup.
*/ */
static struct summary * static struct summary *
lookupa(char *zone, char *ns) { lookupa(char *zone, char *ns, struct summary *parent) {
struct summary *summary; struct summary *summary;
struct workitem *item; struct workitem *item;
unsigned int i; unsigned int i;
...@@ -849,6 +914,10 @@ lookupa(char *zone, char *ns) { ...@@ -849,6 +914,10 @@ lookupa(char *zone, char *ns) {
summary = calloc(1, sizeof(*summary)); summary = calloc(1, sizeof(*summary));
if (summary == NULL) if (summary == NULL)
return (NULL); return (NULL);
if (parent)
INSERTBEFORE(summaries, parent, summary, link);
else
APPEND(summaries, summary, link);
ns_makecanon(zone, summary->zone, sizeof(summary->zone)); ns_makecanon(zone, summary->zone, sizeof(summary->zone));
i = strlen(summary->zone); i = strlen(summary->zone);
...@@ -859,8 +928,11 @@ lookupa(char *zone, char *ns) { ...@@ -859,8 +928,11 @@ lookupa(char *zone, char *ns) {
if (i) summary->ns[i-1] = 0; if (i) summary->ns[i-1] = 0;
item = calloc(1, sizeof(*item)); item = calloc(1, sizeof(*item));
if (item == NULL) if (item == NULL) {
free(summary); freesummary(summary);
while ((summary = HEAD(summaries)) && summary->deferred)
printandfree(summary);
}
item->summary = summary; item->summary = summary;
dolookup(item, ns_t_a); dolookup(item, ns_t_a);
...@@ -871,7 +943,7 @@ lookupa(char *zone, char *ns) { ...@@ -871,7 +943,7 @@ lookupa(char *zone, char *ns) {
* Start a AAAA lookup. * Start a AAAA lookup.
*/ */
static struct summary * static struct summary *
lookupaaaa(char *zone, char *ns) { lookupaaaa(char *zone, char *ns, struct summary *parent) {
struct summary *summary; struct summary *summary;
struct workitem *item; struct workitem *item;
unsigned int i; unsigned int i;
...@@ -879,6 +951,10 @@ lookupaaaa(char *zone, char *ns) { ...@@ -879,6 +951,10 @@ lookupaaaa(char *zone, char *ns) {
summary = calloc(1, sizeof(*summary)); summary = calloc(1, sizeof(*summary));
if (summary == NULL) if (summary == NULL)
return (NULL); return (NULL);
if (parent)
INSERTBEFORE(summaries, parent, summary, link);
else
APPEND(summaries, summary, link);
ns_makecanon(zone, summary->zone, sizeof(summary->zone)); ns_makecanon(zone, summary->zone, sizeof(summary->zone));
i = strlen(summary->zone); i = strlen(summary->zone);
...@@ -889,8 +965,11 @@ lookupaaaa(char *zone, char *ns) { ...@@ -889,8 +965,11 @@ lookupaaaa(char *zone, char *ns) {
if (i) summary->ns[i-1] = 0; if (i) summary->ns[i-1] = 0;
item = calloc(1, sizeof(*item)); item = calloc(1, sizeof(*item));
if (item == NULL) if (item == NULL) {
free(summary); freesummary(summary);
while ((summary = HEAD(summaries)) && summary->deferred)
printandfree(summary);
}
item->summary = summary; item->summary = summary;
dolookup(item, ns_t_aaaa); dolookup(item, ns_t_aaaa);
...@@ -909,14 +988,18 @@ lookupns(char *zone) { ...@@ -909,14 +988,18 @@ lookupns(char *zone) {
summary = calloc(1, sizeof(*summary)); summary = calloc(1, sizeof(*summary));
if (summary == NULL) if (summary == NULL)
return; return;
APPEND(summaries, summary, link);
ns_makecanon(zone, summary->zone, sizeof(summary->zone)); ns_makecanon(zone, summary->zone, sizeof(summary->zone));
i = strlen(summary->zone); i = strlen(summary->zone);
if (i) summary->zone[i-1] = 0; if (i) summary->zone[i-1] = 0;
item = calloc(1, sizeof(*item)); item = calloc(1, sizeof(*item));
if (item == NULL) if (item == NULL) {
free(summary); freesummary(summary);
while ((summary = HEAD(summaries)) && summary->deferred)
printandfree(summary);
}
item->summary = summary; item->summary = summary;
dolookup(item, ns_t_ns); dolookup(item, ns_t_ns);
...@@ -1074,8 +1157,10 @@ process(struct workitem *item, unsigned char *buf, int n) { ...@@ -1074,8 +1157,10 @@ process(struct workitem *item, unsigned char *buf, int n) {
* Cross link A/AAAA lookups so that we can generate * Cross link A/AAAA lookups so that we can generate
* a single NXDOMAIN / no address report. * a single NXDOMAIN / no address report.
*/ */
summarya = lookupa(item->summary->zone, ns); summarya = lookupa(item->summary->zone, ns,
summaryaaaa = lookupaaaa(item->summary->zone, ns); item->summary);
summaryaaaa = lookupaaaa(item->summary->zone, ns,
item->summary);
if (summarya && summaryaaaa) { if (summarya && summaryaaaa) {
summarya->xlink = summaryaaaa; summarya->xlink = summaryaaaa;
summaryaaaa->xlink = summarya; summaryaaaa->xlink = summarya;
...@@ -1482,8 +1567,8 @@ readstdin(int fd) { ...@@ -1482,8 +1567,8 @@ readstdin(int fd) {
* Cross link A/AAAA lookups so that we can generate * Cross link A/AAAA lookups so that we can generate
* a single NXDOMAIN / no address report. * a single NXDOMAIN / no address report.
*/ */
summarya = lookupa(zone, ns); summarya = lookupa(zone, ns, NULL);
summaryaaaa = lookupaaaa(zone, ns); summaryaaaa = lookupaaaa(zone, ns, NULL);
if (summarya && summaryaaaa) { if (summarya && summaryaaaa) {
summarya->xlink = summaryaaaa; summarya->xlink = summaryaaaa;
summaryaaaa->xlink = summarya; summaryaaaa->xlink = summarya;
...@@ -1578,7 +1663,6 @@ nextserver(struct workitem *item) { ...@@ -1578,7 +1663,6 @@ nextserver(struct workitem *item) {
static void static void
addserver(const char *hostname) { addserver(const char *hostname) {
int n;
struct addrinfo hints, *res, *res0; struct addrinfo hints, *res, *res0;
if (nservers < 10) { if (nservers < 10) {
...@@ -1609,14 +1693,20 @@ main(int argc, char **argv) { ...@@ -1609,14 +1693,20 @@ main(int argc, char **argv) {
int nfds = 0; int nfds = 0;
int done = 0; int done = 0;
while ((n = getopt(argc, argv, "cdfs:")) != -1) { while ((n = getopt(argc, argv, "cdfos:")) != -1) {
switch (n) { switch (n) {
case 'c': what |= COMM; break; case 'c': what |= COMM; break;
case 'd': debug = 1; break; case 'd': debug = 1; break;
case 'f': what |= FULL; break; case 'f': what |= FULL; break;
case 'o': inorder = 1; break;
case 's': addserver(optarg); break; case 's': addserver(optarg); break;
default: default:
printf("usage: genreport [-c|-d|-f] [-s address]\n"); printf("usage: genreport [-c|-d|-f|-o] [-s server]\n");
printf("\t-c: add common queries\n");
printf("\t-d: enable debugging\n");
printf("\t-f: add full tests\n");
printf("\t-o: inorder output\n");
printf("\t-s: use specified recursive server\n");
exit(0); exit(0);
} }
} }
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment