diff options
Diffstat (limited to 'tools/dnssec/dns-wire2text.c')
-rw-r--r-- | tools/dnssec/dns-wire2text.c | 149 |
1 files changed, 149 insertions, 0 deletions
diff --git a/tools/dnssec/dns-wire2text.c b/tools/dnssec/dns-wire2text.c new file mode 100644 index 0000000..8e4b55d --- /dev/null +++ b/tools/dnssec/dns-wire2text.c @@ -0,0 +1,149 @@ +/* + Read RR's in getdns wire format and print them in presentation + format on stdout. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <assert.h> +#include <errno.h> +#include <getdns/getdns.h> +#include <getdns/getdns_extra.h> + +#undef DEBUG + +#if defined(DEBUG) +static void +hd(const char *buf, size_t buf_len) +{ + for (size_t n = 0; n < buf_len; n++) + { + if (n % 16 == 0) + { + if (n != 0) + fprintf(stderr, "\n"); + fprintf(stderr, "%08x ", n); + } + else if (n % 8 == 0) + fprintf(stderr, " "); + fprintf(stderr, "%02hhx ", buf[n]); + } + fprintf(stderr, "\n"); +} +#else /* !DEBUG */ +#define hd(a,b) +#endif + +/* Return value: + <0 -- error, the return value being -errorcode + 0 -- done + >0 -- not done yet, call me again +*/ +static int +read_rr(const uint8_t **buf, size_t *buf_len, getdns_dict **rr_dict) +{ + getdns_return_t r = getdns_wire2rr_dict_scan(buf, buf_len, rr_dict); + + if (r) + return -r; + return *buf_len; +} + +#define INBUFLEN 4096 + +static size_t +read_inbuf(FILE *infp, uint8_t **bufp_out) +{ + size_t nread = 0; + uint8_t *wirebuf = malloc(INBUFLEN); + int chunks = 1; + + if (wirebuf == NULL) + goto out; + + while (1) + { + size_t n = fread(wirebuf + nread, 1, INBUFLEN, infp); + nread += n; + if (n < INBUFLEN) + break; /* Done. */ + + wirebuf = realloc(wirebuf, ++chunks * INBUFLEN); + if (wirebuf == NULL) + break; + } + + out: + if (bufp_out != NULL) + *bufp_out = wirebuf; + return nread; +} + +int +main(int argc, char *argv[]) +{ + int rrv = 0; + uint8_t *inbuf = NULL; + const uint8_t *bufp = NULL; + size_t inbuf_len = 0; + getdns_dict *rr_dict = NULL; + getdns_return_t r = 0; + FILE *infp = stdin; + + if (argc > 1) + { + infp = fopen(argv[1], "r"); + if (infp == NULL) + { + perror("fopen(argv[1])"); + return -errno; + } + } + inbuf_len = read_inbuf(infp, &inbuf); + if (inbuf == NULL) + { + perror("read_inbuf"); + return -errno; + } + if (infp != stdin) + if (fclose(infp)) + perror("fclose"); + hd((const char *) wirebuf, n); + + bufp = inbuf; + while (1) + { + char *stringbuf = NULL; + + rrv = read_rr(&bufp, &inbuf_len, &rr_dict); + if (rrv < 0) + break; + + r = getdns_rr_dict2str(rr_dict, &stringbuf); + if (r) + break; + + getdns_dict_destroy(rr_dict); + printf("%s", stringbuf); + free(stringbuf); + + if (rrv == 0) + break; /* Done. */ + } + free(inbuf); + + if (rrv < 0) + { + fprintf(stderr, "parsing input failed: %s\n", + getdns_get_errorstr_by_id(-rrv)); + return rrv; + } + if (r) + { + fprintf(stderr, "converting dict to string failed: %s\n", + getdns_get_errorstr_by_id(r)); + return -r; + } + + return 0; +} |