Commit 2d302b6b authored by Mark Andrews's avatar Mark Andrews
Browse files

add more comments

parent 4227c8b3
...@@ -46,6 +46,9 @@ static int what = 0; ...@@ -46,6 +46,9 @@ static int what = 0;
static union res_sockaddr_union servers[10]; static union res_sockaddr_union servers[10];
static int nservers = 0; static int nservers = 0;
/*
* Doubly linked list macros.
*/
#define APPEND(list, item, link) do { \ #define APPEND(list, item, link) do { \
if ((list).tail) \ if ((list).tail) \
(list).tail->link.next = (item); \ (list).tail->link.next = (item); \
...@@ -77,29 +80,32 @@ static int nservers = 0; ...@@ -77,29 +80,32 @@ static int nservers = 0;
#define HEAD(list) (list).head #define HEAD(list) (list).head
#define TAIL(list) (list).tail #define TAIL(list) (list).tail
/*
* Test groupings
*/
#define EDNS 0x0 #define EDNS 0x0
#define COMM 0x1 #define COMM 0x1
#define FULL 0x2 #define FULL 0x2
static struct { static struct {
const char *name; const char *name; /* test nmemonic */
unsigned int what; unsigned int what; /* select what test to make / report */
unsigned short rdlen; unsigned short rdlen; /* edns rdata length */
const char *rdata; const char *rdata; /* edns rdata */
unsigned short udpsize; unsigned short udpsize; /* edns UDP size (0 == no EDNS) */
unsigned short flags; unsigned short flags; /* edns flags to be set */
unsigned short version; unsigned short version; /* edns version */
unsigned int tcp; unsigned int tcp; /* use tcp */
unsigned int ignore; unsigned int ignore; /* ignore tc in response */
unsigned int tc; unsigned int tc; /* set tc in request */
unsigned int rd; unsigned int rd; /* set rd in request */
unsigned int ra; unsigned int ra; /* set ra in request */
unsigned int cd; unsigned int cd; /* set cd in request */
unsigned int ad; unsigned int ad; /* set ad in request */
unsigned int aa; unsigned int aa; /* set aa in request */
unsigned int z; unsigned int z; /* set z in request */
unsigned int opcode; unsigned int opcode; /* use opcode for request */
unsigned short type; unsigned short type; /* query type code */
} opts[] = { } opts[] = {
{ "dns", EDNS, 0, "", 0, 0x0000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ns_t_soa }, { "dns", EDNS, 0, "", 0, 0x0000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ns_t_soa },
{ "edns", EDNS, 0, "", 4096, 0x0000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ns_t_soa }, { "edns", EDNS, 0, "", 4096, 0x0000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ns_t_soa },
...@@ -137,20 +143,23 @@ static struct { ...@@ -137,20 +143,23 @@ static struct {
{ "ednstcp", EDNS, 0, "", 512, 0x8000, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, ns_t_dnskey } { "ednstcp", EDNS, 0, "", 512, 0x8000, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, ns_t_dnskey }
}; };
/*
* Summary structure where results from multiple lookups are recorded.
*/
struct summary { struct summary {
char zone[1024]; char zone[1024];
char ns[1024]; char ns[1024];
struct sockaddr_storage storage; struct sockaddr_storage storage;
int tests; int tests; /* number of outstanding tests */
int done; int done;
int type; int type; /* recursive query lookup type */
int nodataa; int nodataa; /* recursive query got nodata */
int nodataaaa; int nodataaaaa; /* recursive query got nodata */
int nxdomain; int nxdomain; /* recursive query got nxdomain */
int nxdomaina; int nxdomaina; /* recursive query got nxdomain */
int nxdomainaaaa; int nxdomainaaaa; /* recursive query got nxdomain */
int seenrrsig; int seenrrsig; /* a rrsig was seen in "do" test */
struct summary *xlink; struct summary *xlink; /* cross link of recursive A/AAAA */
char results[sizeof(opts)/sizeof(opts[0])][100]; char results[sizeof(opts)/sizeof(opts[0])][100];
}; };
...@@ -163,12 +172,13 @@ struct workitem { ...@@ -163,12 +172,13 @@ struct workitem {
unsigned short id; unsigned short id;
struct timeval when; struct timeval when;
int type; int type;
int test; int test; /* test number / server number */
int sends; int sends; /* number of times this UDP request
* has been sent */
int buflen; int buflen;
int tcpfd; int tcpfd;
int outstanding; int outstanding; /* outstanding has been set */
int havelen; int havelen; /* readlen is tcp message length */
int readlen; int readlen;
int read; int read;
unsigned char buf[512]; unsigned char buf[512];
...@@ -178,11 +188,13 @@ struct workitem { ...@@ -178,11 +188,13 @@ struct workitem {
}; };
/* /*
* Work queues. * Work queues:
* 'work' udp qeries; * 'work' udp qeries;
* 'connecting' tcp qeries; * 'connecting' tcp qeries;
* 'reading' tcp qeries; * 'reading' tcp qeries;
* 'ids' in flight queries by qid lists; *
* Outstanding queries by qid.
* 'ids'
*/ */
static struct { static struct {
struct workitem *head; struct workitem *head;
...@@ -221,6 +233,9 @@ storage_equal(struct sockaddr_storage *s1, struct sockaddr_storage *s2) { ...@@ -221,6 +233,9 @@ storage_equal(struct sockaddr_storage *s1, struct sockaddr_storage *s2) {
return (0); return (0);
} }
/*
* Check if it is safe to use this id to this address.
*/
static int static int
checkid(struct sockaddr_storage *storage, int id) { checkid(struct sockaddr_storage *storage, int id) {
struct workitem *item; struct workitem *item;
...@@ -232,6 +247,9 @@ checkid(struct sockaddr_storage *storage, int id) { ...@@ -232,6 +247,9 @@ checkid(struct sockaddr_storage *storage, int id) {
return ((item == NULL) ? 1 : 0); return ((item == NULL) ? 1 : 0);
} }
/*
* Generate a report line.
*/
static void static void
report(struct summary *summary) { report(struct summary *summary) {
struct sockaddr_in *s = (struct sockaddr_in *)&summary->storage; struct sockaddr_in *s = (struct sockaddr_in *)&summary->storage;
...@@ -245,22 +263,40 @@ report(struct summary *summary) { ...@@ -245,22 +263,40 @@ report(struct summary *summary) {
if (summary->tests) if (summary->tests)
return; return;
/*
* If we are cross linked record the lookup details on the other
* structure.
*/
if (summary->xlink) { if (summary->xlink) {
if (summary->nodataa) if (summary->nodataa) {
summary->xlink->nodataa = 1; summary->xlink->nodataa = 1;
if (summary->nodataaaa) summary->done = 1;
summary->xlink->nodataaaa = 1; }
if (summary->nxdomaina) if (summary->nodataaaaa) {
summary->xlink->nodataaaaa = 1;
summary->done = 1;
}
if (summary->nxdomaina) {
summary->xlink->nxdomaina = 1; summary->xlink->nxdomaina = 1;
if (summary->nxdomainaaaa) summary->done = 1;
}
if (summary->nxdomainaaaa) {
summary->xlink->nxdomainaaaa = 1; summary->xlink->nxdomainaaaa = 1;
summary->done = 1;
}
/*
* Remove the cross link.
*/
summary->xlink->xlink = NULL; summary->xlink->xlink = NULL;
summary->xlink = NULL; summary->xlink = NULL;
summary->done = 1; 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->nodataaaa) { 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); free(summary);
...@@ -275,7 +311,7 @@ report(struct summary *summary) { ...@@ -275,7 +311,7 @@ report(struct summary *summary) {
return; return;
} }
if (summary->done) { if (summary->done || summary->nodataa || summary->nodataaaaa) {
free(summary); free(summary);
return; return;
} }
...@@ -344,6 +380,9 @@ report(struct summary *summary) { ...@@ -344,6 +380,9 @@ report(struct summary *summary) {
free(summary); free(summary);
} }
/*
* Free a work item and unlink.
*/
static void static void
freeitem(struct workitem * item) { freeitem(struct workitem * item) {
report(item->summary); report(item->summary);
...@@ -367,6 +406,9 @@ freeitem(struct workitem * item) { ...@@ -367,6 +406,9 @@ freeitem(struct workitem * item) {
free(item); free(item);
} }
/*
* Add a tag to the report.
*/
static void static void
addtag(struct workitem *item, char *tag) { addtag(struct workitem *item, char *tag) {
char *result = item->summary->results[item->test]; char *result = item->summary->results[item->test];
...@@ -374,6 +416,9 @@ addtag(struct workitem *item, char *tag) { ...@@ -374,6 +416,9 @@ addtag(struct workitem *item, char *tag) {
strlcat(result, tag, 100); strlcat(result, tag, 100);
} }
/*
* Resend a UDP request.
*/
static void static void
resend(struct workitem *item) { resend(struct workitem *item) {
int n, fd = -1; int n, fd = -1;
...@@ -425,6 +470,9 @@ resend(struct workitem *item) { ...@@ -425,6 +470,9 @@ resend(struct workitem *item) {
} }
} }
/*
* Start a individual test.
*/
static void static void
dotest(struct workitem *item) { dotest(struct workitem *item) {
unsigned char *cp; unsigned char *cp;
...@@ -446,6 +494,10 @@ dotest(struct workitem *item) { ...@@ -446,6 +494,10 @@ dotest(struct workitem *item) {
return; return;
} }
/*
* res_mkquery only really knows about QUERY but it is useful
* for initalising the header when the opcode isn't QUERY.
*/
opcode = opts[item->test].opcode; opcode = opts[item->test].opcode;
switch (opcode) { switch (opcode) {
case 0: break; case 0: break;
...@@ -464,6 +516,10 @@ dotest(struct workitem *item) { ...@@ -464,6 +516,10 @@ dotest(struct workitem *item) {
if (opts[item->test].opcode == 15) if (opts[item->test].opcode == 15)
item->buf[4] = item->buf[5] = 0; item->buf[4] = item->buf[5] = 0;
} }
/*
* Set DNS flags as specified by test.
*/
if (opts[item->test].tc) if (opts[item->test].tc)
item->buf[2] |= 0x2; /* set tc */ item->buf[2] |= 0x2; /* set tc */
if (opts[item->test].rd) if (opts[item->test].rd)
...@@ -490,7 +546,11 @@ dotest(struct workitem *item) { ...@@ -490,7 +546,11 @@ dotest(struct workitem *item) {
sizeof(item->summary->zone)); sizeof(item->summary->zone));
} }
if (n > 0 && opts[item->test].udpsize > 0) { /*
* Add OPT record if required by test.
*/
if (n > 0 && opts[item->test].udpsize > 0 &&
11 + opts[item->test].rdlen < 512 - n) {
cp = item->buf + n; cp = item->buf + n;
*cp++ = 0; /* name */ *cp++ = 0; /* name */
ns_put16(ns_t_opt, cp); /* type */ ns_put16(ns_t_opt, cp); /* type */
...@@ -510,6 +570,9 @@ dotest(struct workitem *item) { ...@@ -510,6 +570,9 @@ dotest(struct workitem *item) {
} }
if (n > 0) { if (n > 0) {
/*
* Adjust id if it clashes with a outstanding request.
*/
id = item->buf[0] << 8 | item->buf[1]; id = item->buf[0] << 8 | item->buf[1];
while (!checkid(&item->summary->storage, id) && while (!checkid(&item->summary->storage, id) &&
...@@ -532,6 +595,9 @@ dotest(struct workitem *item) { ...@@ -532,6 +595,9 @@ dotest(struct workitem *item) {
return; return;
} }
/*
* If there is too much outstanding work queue this item.
*/
if (outstanding > maxoutstanding) { if (outstanding > maxoutstanding) {
gettimeofday(&item->when, NULL); gettimeofday(&item->when, NULL);
item->when.tv_sec += 1; item->when.tv_sec += 1;
...@@ -566,6 +632,9 @@ dotest(struct workitem *item) { ...@@ -566,6 +632,9 @@ dotest(struct workitem *item) {
} }
} }
/*
* Start a series of tests.
*/
static void static void
check(char *zone, char *ns, char *address) { check(char *zone, char *ns, char *address) {
size_t i; size_t i;
...@@ -653,6 +722,9 @@ rcodetext(int code) { ...@@ -653,6 +722,9 @@ rcodetext(int code) {
} }
} }
/*
* Start a lookup using the recursive server(s).
*/
static void static void
dolookup(struct workitem *item, int type) { dolookup(struct workitem *item, int type) {
char name[1024]; char name[1024];
...@@ -760,6 +832,9 @@ dolookup(struct workitem *item, int type) { ...@@ -760,6 +832,9 @@ dolookup(struct workitem *item, int type) {
} }
} }
/*
* Start a A lookup.
*/
static struct summary * static struct summary *
lookupa(char *zone, char *ns) { lookupa(char *zone, char *ns) {
struct summary *summary; struct summary *summary;
...@@ -787,6 +862,9 @@ lookupa(char *zone, char *ns) { ...@@ -787,6 +862,9 @@ lookupa(char *zone, char *ns) {
return (summary); return (summary);
} }
/*
* Start a AAAA lookup.
*/
static struct summary * static struct summary *
lookupaaaa(char *zone, char *ns) { lookupaaaa(char *zone, char *ns) {
struct summary *summary; struct summary *summary;
...@@ -814,6 +892,9 @@ lookupaaaa(char *zone, char *ns) { ...@@ -814,6 +892,9 @@ lookupaaaa(char *zone, char *ns) {
return (summary); return (summary);
} }
/*
* Start a NS lookup.
*/
static void static void
lookupns(char *zone) { lookupns(char *zone) {
struct summary *summary; struct summary *summary;
...@@ -836,6 +917,9 @@ lookupns(char *zone) { ...@@ -836,6 +917,9 @@ lookupns(char *zone) {
dolookup(item, ns_t_ns); dolookup(item, ns_t_ns);
} }
/*
* Process a recieved response.
*/
static void static void
process(struct workitem *item, unsigned char *buf, int n) { process(struct workitem *item, unsigned char *buf, int n) {
char name[1024], ns[1024]; char name[1024], ns[1024];
...@@ -903,14 +987,12 @@ process(struct workitem *item, unsigned char *buf, int n) { ...@@ -903,14 +987,12 @@ process(struct workitem *item, unsigned char *buf, int n) {
if (item->type == ns_t_a && type == ns_t_a && if (item->type == ns_t_a && type == ns_t_a &&
strcasecmp(item->summary->ns, name) == 0 && strcasecmp(item->summary->ns, name) == 0 &&
rcode == 0 && ancount == 0) { rcode == 0 && ancount == 0) {
item->summary->done = 1;
item->summary->nodataa = 1; item->summary->nodataa = 1;
} }
if (item->type == ns_t_aaaa && type == ns_t_aaaa && if (item->type == ns_t_aaaa && type == ns_t_aaaa &&
strcasecmp(item->summary->ns, name) == 0 && strcasecmp(item->summary->ns, name) == 0 &&
rcode == 0 && ancount == 0) { rcode == 0 && ancount == 0) {
item->summary->done = 1; item->summary->nodataaaaa = 1;
item->summary->nodataaaa = 1;
} }
if (item->type == ns_t_ns && type == ns_t_ns && if (item->type == ns_t_ns && type == ns_t_ns &&
strcasecmp(item->summary->zone, name) == 0 && strcasecmp(item->summary->zone, name) == 0 &&
...@@ -983,6 +1065,10 @@ process(struct workitem *item, unsigned char *buf, int n) { ...@@ -983,6 +1065,10 @@ process(struct workitem *item, unsigned char *buf, int n) {
if (n != rdlen) if (n != rdlen)
goto err; goto err;
item->summary->done = 1; item->summary->done = 1;
/*
* Cross link A/AAAA lookups so that we can generate
* a single NXDOMAIN / no address report.
*/
summarya = lookupa(item->summary->zone, ns); summarya = lookupa(item->summary->zone, ns);
summaryaaaa = lookupaaaa(item->summary->zone, ns); summaryaaaa = lookupaaaa(item->summary->zone, ns);
if (summarya && summaryaaaa) { if (summarya && summaryaaaa) {
...@@ -1162,6 +1248,9 @@ process(struct workitem *item, unsigned char *buf, int n) { ...@@ -1162,6 +1248,9 @@ process(struct workitem *item, unsigned char *buf, int n) {
freeitem(item); freeitem(item);
} }
/*
* Read a TCP response.
*/
static void static void
tcpread(int fd) { tcpread(int fd) {
struct workitem *item; struct workitem *item;
...@@ -1203,6 +1292,9 @@ tcpread(int fd) { ...@@ -1203,6 +1292,9 @@ tcpread(int fd) {
} }
} }
/*
* Send the TCP request and start the read process.
*/
static void static void
startread(struct workitem *item) { startread(struct workitem *item) {
struct iovec iov[2]; struct iovec iov[2];
...@@ -1234,6 +1326,9 @@ startread(struct workitem *item) { ...@@ -1234,6 +1326,9 @@ startread(struct workitem *item) {
} }
} }
/*
* Check if the connect succeeded and start perform a TCP request if it has.
*/
static void static void
connectdone(int fd) { connectdone(int fd) {
struct workitem *item; struct workitem *item;
...@@ -1266,6 +1361,9 @@ connectdone(int fd) { ...@@ -1266,6 +1361,9 @@ connectdone(int fd) {
startread(item); startread(item);
} }
/*
* Connect to a server over TCP.
*/
static void static void
connecttoserver(struct workitem *item) { connecttoserver(struct workitem *item) {
int fd, n, on = 1; int fd, n, on = 1;
...@@ -1277,6 +1375,10 @@ connecttoserver(struct workitem *item) { ...@@ -1277,6 +1375,10 @@ connecttoserver(struct workitem *item) {
freeitem(item); freeitem(item);
return; return;
} }
/*
* Make the socket non blocking.
*/
n = ioctl(fd, FIONBIO, (void *)&on); n = ioctl(fd, FIONBIO, (void *)&on);
if (n == -1) { if (n == -1) {
close(fd); close(fd);
...@@ -1284,6 +1386,10 @@ connecttoserver(struct workitem *item) { ...@@ -1284,6 +1386,10 @@ connecttoserver(struct workitem *item) {
freeitem(item); freeitem(item);
return; return;
} }
/*
* Don't generate a SIG_PIPE if there is a I/O error on this socket.
*/
n = setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&on, sizeof(on)); n = setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&on, sizeof(on));
if (n == -1) { if (n == -1) {
close(fd); close(fd);
...@@ -1291,6 +1397,10 @@ connecttoserver(struct workitem *item) { ...@@ -1291,6 +1397,10 @@ connecttoserver(struct workitem *item) {
freeitem(item); freeitem(item);
return; return;
} }
/*
* Start the actual connect.
*/
n = connect(fd, (struct sockaddr *)&item->summary->storage, n = connect(fd, (struct sockaddr *)&item->summary->storage,
item->summary->storage.ss_len); item->summary->storage.ss_len);
if (n == -1 && errno == EINPROGRESS) { if (n == -1 && errno == EINPROGRESS) {
...@@ -1323,6 +1433,9 @@ connecttoserver(struct workitem *item) { ...@@ -1323,6 +1433,9 @@ connecttoserver(struct workitem *item) {
startread(item); startread(item);
} }
/*
* Read zone [server [address]]
*/
static void static void
readstdin(int fd) { readstdin(int fd) {
char line[4096]; char line[4096];
...@@ -1331,6 +1444,9 @@ readstdin(int fd) { ...@@ -1331,6 +1444,9 @@ readstdin(int fd) {
char address[1204]; char address[1204];
int n; int n;