From 85226726981be4dba10b460f086939c4c4719ecc Mon Sep 17 00:00:00 2001 From: paul vixie Date: Mon, 21 Jun 2021 10:24:04 -0700 Subject: [PATCH] Issue183 (#184) * style * add -0 option to test countoff() * shelter callers of countoff() from its recursive innards; change counted->nlabel from size_t to int * change counted->nlabel from size_t to int * if there are no alnums, cons up a "." string, in sortable_dnsname(); style * gcc-11 caught an if statement that needed curly brackets * promote -0 to permanence Co-authored-by: Paul Vixie Co-authored-by: David Waitzman --- dnsdbq.c | 20 ++++++++++++++++++-- dnsdbq.man | 3 +++ netio.c | 4 ++-- pdns.c | 33 ++++++++++++++++++++++++++------- pdns.h | 8 +++++--- pdns_dnsdb.c | 2 +- sort.c | 13 +++++++++---- 7 files changed, 64 insertions(+), 19 deletions(-) diff --git a/dnsdbq.c b/dnsdbq.c index 8a202a4..79e1ea3 100644 --- a/dnsdbq.c +++ b/dnsdbq.c @@ -140,7 +140,7 @@ main(int argc, char *argv[]) { /* process the command line options. */ while ((ch = getopt(argc, argv, - "D:R:r:N:n:i:M:u:p:t:b:k:J:V:T:" + "D:R:r:N:n:i:M:u:p:t:b:k:J:V:T:0:" "adfhIjmqSsUv468" QPARAM_GETOPT)) != -1) { @@ -153,6 +153,21 @@ main(int argc, char *argv[]) { if ((msg = qparam_option(ch, optarg, &qp)) != NULL) usage(msg); break; + case '0': { + const char *equal = strchr(optarg, '='); + if (equal == NULL) + usage("-0 requires 'function='"); + size_t length = (size_t) (equal - optarg); + const char *thing = optarg + length + 1; + if (strncmp(optarg, "countoff", length) == 0) { + struct counted *c = countoff(thing); + countoff_debug("main", thing, c); + DESTROY(c); + } else { + usage("-0 function unrecognized"); + } + my_exit(0); + } case 'a': asinfo_lookup = true; break; @@ -660,7 +675,7 @@ help(void) { printf("usage: %s [-acdfGghIjmqSsUv468] [-p dns|json|csv]\n", program_name); - puts("\t[-u SYSTEM] [-V VERB]\n" + puts("\t[-u SYSTEM] [-V VERB] [-0 FUNCTION=INPUT]\n" "\t[-k (first|last|duration|count|name|data)[,...]]\n" "\t[-l QUERY-LIMIT] [-L OUTPUT-LIMIT]\n" "\t[-O OFFSET] [-M MAX_COUNT]\n" @@ -682,6 +697,7 @@ help(void) { "use -c to get complete (strict) time matching for -A and -B.\n" "for -D, the default is \"%s\"\n" "use -d one or more times to ramp up the diagnostic output.\n" + "for -0, the function must be \"countoff\"\n" "for -f, stdin must contain lines of the following forms:\n" "\trrset/name/NAME[/TYPE[/BAILIWICK]]\n" "\trrset/raw/HEX-PAIRS[/RRTYPE[/BAILIWICK]]\n" diff --git a/dnsdbq.man b/dnsdbq.man index 12ae932..ff906c9 100644 --- a/dnsdbq.man +++ b/dnsdbq.man @@ -41,6 +41,7 @@ .Op Fl t Ar rrtype .Op Fl u Ar server_sys .Op Fl V Ar verb +.Op Fl 0 Ar function=thing .Sh DESCRIPTION .Nm dnsdbq constructs and issues queries to Passive DNS systems which return data @@ -405,6 +406,8 @@ result size. At-a-glance, it provides information on when a given domain name, IP address or other DNS asset was first-seen and last-seen by the global sensor network, as well as the total observation count. +.It Fl 0 Ar function=thing +This is a developer tool meant to feed automated testing systems. .It Fl U turns off TLS certificate verification (unsafe). .It Fl v diff --git a/netio.c b/netio.c index 95b36fe..65b45d2 100644 --- a/netio.c +++ b/netio.c @@ -697,7 +697,7 @@ io_drain(void) { DEBUG(2, true, "io_drain(%s) DONE rcode=%d\n", query->command, fetch->rcode); - if (psys->encap == encap_saf) + if (psys->encap == encap_saf) { if (query->saf_cond == sc_begin || query->saf_cond == sc_ongoing) { @@ -717,7 +717,7 @@ io_drain(void) { DEBUG(2, true, "... saf_cond %d saf_msg %s\n", query->saf_cond, or_else(query->saf_msg, "")); - + } if (cm->data.result == CURLE_COULDNT_RESOLVE_HOST) { fprintf(stderr, "%s: warning: libcurl failed since " diff --git a/pdns.c b/pdns.c index b42c52e..a04b56b 100644 --- a/pdns.c +++ b/pdns.c @@ -38,6 +38,7 @@ static json_t *annotate_one(json_t *, const char *, const char *, json_t *); #ifndef CRIPPLED_LIBC static json_t *annotate_asinfo(const char *, const char *); #endif +static struct counted *countoff_r(const char *, int); /* present_text_lookup -- render one pdns tuple in "dig" style ascii text. */ @@ -729,16 +730,16 @@ tuple_unmake(pdns_tuple_t tup) { json_decref(tup->obj.main); } -/* countoff -- count each label in a DNS string. +/* countoff{_r,_debug} -- count and map the labels in a DNS name. */ -struct counted * -countoff(const char *src, size_t nlabel) { +static struct counted * +countoff_r(const char *src, int nlabel) { const char *sp = src; bool slash = false; struct counted *c; int ch; - /* count and map the unescaped dots (dns label separators). */ + /* count and map the alnums in the facing dns label. */ size_t nalnum = 0; while ((ch = *sp++) != '\0') { if (isalnum(ch)) @@ -752,10 +753,11 @@ countoff(const char *src, size_t nlabel) { slash = false; } } - size_t len = (size_t)(sp - src); + size_t len = (size_t) (sp - src); if (ch == '.') { /* end of label, recurse to reach rest of name. */ - c = countoff(sp, nlabel+1); + c = countoff_r(sp, nlabel+1); + /* fill in output structure on the way back up. */ c->nchar += len; c->nalnum += nalnum; c->lens[nlabel] = len; @@ -778,13 +780,30 @@ countoff(const char *src, size_t nlabel) { return c; } +struct counted * +countoff(const char *src) { + return countoff_r(src, 0); +} + +void +countoff_debug(const char *place, const char *thing, const struct counted *c) { + printf("\"%s\" -> {nlabel %d, nchar %zd, nalnum %zd, lens [", + thing, c->nlabel, c->nchar, c->nalnum); + const char *sep = ""; + for (int i = 0; i < c->nlabel; i++) { + printf("%s%zd", sep, c->lens[i]); + sep = ", "; + } + printf("]} (%s)\n", place); +} + /* reverse -- put a domain name into TLD-first order. * * returns NULL if errno is set, else, a heap string. */ char * reverse(const char *src) { - struct counted *c = countoff(src, 0); + struct counted *c = countoff(src); char *ret = malloc(c->nchar + 1/*'.'*/ + 1/*'\0'*/); char *p = ret; size_t nchar = 0; diff --git a/pdns.h b/pdns.h index dbc759a..d74a81b 100644 --- a/pdns.h +++ b/pdns.h @@ -153,12 +153,13 @@ typedef struct qdesc *qdesc_t; typedef const struct qdesc *qdesc_ct; struct counted { - size_t nlabel; + int nlabel; size_t nchar; size_t nalnum; size_t lens[]; }; -#define COUNTED_SIZE(nlabel) (sizeof(struct counted) + nlabel * sizeof(size_t)) +#define COUNTED_SIZE(nlabel) \ + (sizeof(struct counted) + (unsigned int) nlabel * sizeof(size_t)) bool pprint_json(const char *, size_t, FILE *); void present_json_lookup(pdns_tuple_ct, const char *, size_t, writer_t); @@ -170,7 +171,8 @@ void present_text_summarize(pdns_tuple_ct, const char *, size_t, writer_t); void present_csv_summarize(pdns_tuple_ct, const char *, size_t, writer_t); const char *tuple_make(pdns_tuple_t, const char *, size_t); void tuple_unmake(pdns_tuple_t); -struct counted *countoff(const char *, size_t); +struct counted *countoff(const char *); +void countoff_debug(const char *, const char *, const struct counted *); char *reverse(const char *); int data_blob(query_t, const char *, size_t); void pick_system(const char *, const char *); diff --git a/pdns_dnsdb.c b/pdns_dnsdb.c index 963aada..ed29ecd 100644 --- a/pdns_dnsdb.c +++ b/pdns_dnsdb.c @@ -484,7 +484,7 @@ print_burstrate(const char *key, */ static const char * rateval_make(rateval_t tp, const json_t *obj, const char *key) { - struct rateval rvalue = {rk_naught, 0UL}; + struct rateval rvalue = {.rk = rk_naught}; const json_t *jvalue = json_object_get(obj, key); if (jvalue != NULL) { diff --git a/sort.c b/sort.c index fe7b5d8..3779b55 100644 --- a/sort.c +++ b/sort.c @@ -146,7 +146,7 @@ exec_sort(int p1[], int p2[]) { */ char * sortable_rrname(pdns_tuple_ct tup) { - struct sortbuf buf = {NULL, 0}; + struct sortbuf buf = {}; sortable_dnsname(&buf, json_string_value(tup->obj.rrname)); buf.base = realloc(buf.base, buf.size+1); @@ -158,7 +158,7 @@ sortable_rrname(pdns_tuple_ct tup) { */ char * sortable_rdata(pdns_tuple_ct tup) { - struct sortbuf buf = {NULL, 0}; + struct sortbuf buf = {}; if (json_is_array(tup->obj.rdata)) { size_t index; @@ -247,11 +247,16 @@ sortable_hexify(sortbuf_t buf, const u_char *src, size_t len) { */ void sortable_dnsname(sortbuf_t buf, const char *name) { - struct counted *c = countoff(name, 0); + struct counted *c = countoff(name); // ensure our result buffer is large enough. size_t new_size = buf->size + c->nalnum; - assert(new_size != 0); + if (new_size == 0) { + buf->base = realloc(buf->base, 1); + buf->base[0] = '.'; + buf->size = 1; + return; + } if (new_size != buf->size) buf->base = realloc(buf->base, new_size); char *p = buf->base + buf->size;