summaryrefslogtreecommitdiff
path: root/tools/dnssec/dns-wire2text.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/dnssec/dns-wire2text.c')
-rw-r--r--tools/dnssec/dns-wire2text.c149
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;
+}