summaryrefslogtreecommitdiff
path: root/tools/dnssec/net2wire.c
diff options
context:
space:
mode:
authorLinus Nordberg <linus@nordu.net>2016-03-27 19:27:30 +0200
committerLinus Nordberg <linus@nordu.net>2016-03-27 19:44:25 +0200
commit56d70baa79ae5907b11445364bbea9b31ee4cd20 (patch)
treeef0403255a04de75736da82385d282a0198c52c2 /tools/dnssec/net2wire.c
parent9f723f6f1d79c1be460ece10555945346045b175 (diff)
WIP
Diffstat (limited to 'tools/dnssec/net2wire.c')
-rw-r--r--tools/dnssec/net2wire.c301
1 files changed, 301 insertions, 0 deletions
diff --git a/tools/dnssec/net2wire.c b/tools/dnssec/net2wire.c
new file mode 100644
index 0000000..fb4620b
--- /dev/null
+++ b/tools/dnssec/net2wire.c
@@ -0,0 +1,301 @@
+/* This program is based on (IIRC)
+ * getdns/spec/example/example-simple-answers.c.
+ *
+ * Resolve DNS name argv[1] of type argv[2] using libgetdns and write
+ * the resulting RRs to two files, in DNS binary wire format:
+ *
+ * - binout: /just_address_answers/0/address_data and
+ * /just_address_answers/1/address_data
+ *
+ * - treeout: output from getdns_rr_dict2wire for all RR's in the
+ * answer section
+ *
+ * Based on getdns/spec/example/example-simple-answers.c.
+ */
+
+#include <assert.h>
+#include <inttypes.h>
+#include <string.h>
+#include <errno.h>
+#include <stdio.h>
+#include <getdns/getdns.h>
+#include <getdns/getdns_ext_libevent.h>
+#include <event2/event.h>
+
+static int debug = 1;
+
+static getdns_return_t
+dump_reply(FILE *fp, getdns_dict *reply, const char *section_name)
+{
+ getdns_list *section = NULL;
+ size_t section_len = -1;
+ getdns_return_t r;
+ uint8_t res_buf[4096], *res = NULL;
+ size_t res_len = sizeof(res_buf);
+
+ r = getdns_dict_get_list(reply, section_name, &section);
+ if (r) {
+ fprintf(stderr,
+ "unable to get section \"%s\" from reply\n",
+ section_name);
+ return r;
+ }
+
+ r = getdns_list_get_length(section, &section_len);
+ if (r) {
+ fprintf(stderr, "unable to get length of section\n");
+ return r;
+ }
+
+ for (size_t j = 0; j < section_len; j++) {
+ getdns_dict *rr = NULL;
+
+ r = getdns_list_get_dict(section, j , &rr);
+ if (r) {
+ fprintf(stderr, "unable to get rr from entry "
+ "%d: %d\n", j, r);
+ return r;
+ }
+
+ r = getdns_rr_dict2wire(rr, &res, &res_len);
+ if (r) {
+ fprintf(stderr,
+ "unable to convert entry %d "
+ "to wire format: %d\n", j, r);
+ return r;
+ }
+
+ if (0 && debug) {
+ char *s = getdns_pretty_print_dict(rr);
+ puts(s);
+ free(s);
+ }
+
+ if (fwrite(res, 1, res_len, fp) != res_len) {
+ fprintf(stderr,
+ "unable to write buffer to file: %s\n",
+ strerror(errno));
+ return -errno;
+ }
+
+ free(res);
+ }
+
+ return 0;
+}
+
+int
+dump_tree(FILE *fp, const getdns_dict *response, const char *tree_name)
+{
+ getdns_return_t r;
+ getdns_list *tree = NULL;
+ size_t n_replies = -1;
+
+ r = getdns_dict_get_list(response, tree_name, &tree);
+ if (r) {
+ fprintf(stderr, "unable to get tree %s\n", tree_name);
+ return r;
+ }
+
+ r = getdns_list_get_length(tree, &n_replies);
+ if (r) {
+ fprintf(stderr, "unable to get number of replies\n");
+ return r;
+ }
+
+ for (size_t i = 0; i < n_replies; i++) {
+ getdns_dict *reply = NULL;
+
+ r = getdns_list_get_dict(tree, i, &reply);
+ if (r) {
+ fprintf(stderr, "unable to get reply %d from tree\n", i);
+ return r;
+ }
+
+ if (debug) {
+ char *s = getdns_pretty_print_dict(reply);
+ printf("Pretty-printing reply #%d:%s\n", i, s);
+ free(s);
+ }
+
+ dump_reply(fp, reply, "answer");
+ }
+
+ return 0;
+}
+
+
+/* Set up the callback function, which will also do the processing of the results */
+void callback(getdns_context *context,
+ getdns_callback_type_t callback_type,
+ getdns_dict *response,
+ void *userarg,
+ getdns_transaction_t transaction_id)
+{
+ getdns_return_t r; /* Holder for all function returns */
+ uint32_t status;
+ getdns_bindata *address_data;
+ char *first = NULL, *second = NULL;
+ FILE *binoutfp = NULL, *treeoutfp = NULL;
+
+ (void) context; /* unused parameter */
+
+ binoutfp = fopen("binout", "w");
+ assert(binoutfp != NULL);
+ treeoutfp = fopen("treeout", "w");
+ assert(treeoutfp != NULL);
+
+ printf( "Callback for query \"%s\" with request ID %"PRIu64".\n"
+ , (char *)userarg, transaction_id );
+
+ switch(callback_type) {
+ case GETDNS_CALLBACK_CANCEL:
+ printf("Transaction with ID %"PRIu64" was cancelled.\n", transaction_id);
+ return;
+ case GETDNS_CALLBACK_TIMEOUT:
+ printf("Transaction with ID %"PRIu64" timed out.\n", transaction_id);
+ return;
+ case GETDNS_CALLBACK_ERROR:
+ printf("An error occurred for transaction ID %"PRIu64".\n", transaction_id);
+ return;
+ default: break;
+ }
+ assert( callback_type == GETDNS_CALLBACK_COMPLETE );
+
+ if ((r = getdns_dict_get_int(response, "status", &status)))
+ fprintf(stderr, "Could not get \"status\" from reponse");
+
+ else if (status != GETDNS_RESPSTATUS_GOOD)
+ fprintf(stderr, "The search had no results, and a return value of %"PRIu32".\n", status);
+
+ static char *TREES[] = {"replies_tree", "validation_chain"};
+ static const int TREES_LEN = 2;
+ for (int i = 0; i < TREES_LEN; i++) {
+ if (dump_tree(treeoutfp, response, TREES[i]))
+ fprintf(stderr, "Could not dump %s to file\n", TREES[i]);
+
+ else if ((r = getdns_dict_get_bindata(response, "/just_address_answers/0/address_data", &address_data)))
+ fprintf(stderr, "Could not get first address");
+
+ else if (fwrite(address_data->data, 1, address_data->size, binoutfp) !=
+ address_data->size)
+ fprintf(stderr, "first fwrite: %s\n", strerror(errno));
+
+ else if (!(first = getdns_display_ip_address(address_data)))
+ fprintf(stderr, "Could not convert first address to string\n");
+
+ else if ((r = getdns_dict_get_bindata(response, "/just_address_answers/1/address_data", &address_data)))
+ fprintf(stderr, "Could not get second address");
+
+ else if (fwrite(address_data->data, 1, address_data->size, binoutfp) !=
+ address_data->size)
+ fprintf(stderr, "second fwrite: %s\n", strerror(errno));
+
+ else if (!(second = getdns_display_ip_address(address_data)))
+ fprintf(stderr, "Could not convert second address to string\n");
+ if (first) {
+ printf("The address is %s\n", first);
+ free(first);
+ }
+ if (second) {
+ printf("The address is %s\n", second);
+ free(second);
+ }
+ if (r) {
+ assert( r != GETDNS_RETURN_GOOD );
+ fprintf(stderr, ": %d\n", r);
+ }
+ }
+ getdns_dict_destroy(response);
+ if (binoutfp) fclose(binoutfp);
+ if (treeoutfp) fclose(treeoutfp);
+}
+
+static getdns_return_t
+send_query(getdns_context *context,
+ char *query_name,
+ const uint16_t query_type,
+ getdns_transaction_t *transaction_id)
+{
+ getdns_return_t r = GETDNS_RETURN_GENERIC_ERROR;
+ getdns_dict *extensions = getdns_dict_create();
+ char *userarg = query_name;
+
+ assert(extensions != NULL);
+
+ r = getdns_dict_set_int(extensions,
+ "dnssec_return_validation_chain",
+ GETDNS_EXTENSION_TRUE);
+ if (r) return r;
+
+#if 0
+ r = getdns_dict_set_int(extensions,
+ "dnssec_return_status",
+ GETDNS_EXTENSION_TRUE);
+ if (r) return r;
+#endif
+
+ if (query_type == 0)
+ r = getdns_address(context, query_name, extensions, userarg,
+ transaction_id, callback);
+ else
+ r = getdns_general(context, query_name, query_type,
+ extensions, userarg,
+ transaction_id, callback);
+ if (r) return r;
+
+ return r;
+}
+
+int main(int argc, char *argv[])
+{
+ getdns_return_t r; /* Holder for all function returns */
+ getdns_context *context = NULL;
+ struct event_base *event_base = NULL;
+ char *query_name = "www.example.com";
+ uint16_t query_type = 0;
+ getdns_transaction_t transaction_id;
+ getdns_list *trust_anchors;
+
+
+ if (argc > 1)
+ query_name = argv[1];
+ if (argc > 2)
+ query_type = (uint16_t) atoi(argv[2]);
+
+ if ((r = getdns_context_create(&context, 1)))
+ fprintf(stderr, "Trying to create the context failed");
+
+ else if ((r = getdns_context_get_dnssec_trust_anchors(
+ context, &trust_anchors)) ||
+ trust_anchors == NULL)
+ fprintf(stderr, "No trust anchor.\n");
+
+ else if (!(event_base = event_base_new()))
+ fprintf(stderr, "Trying to create the event base failed.\n");
+
+ else if ((r = getdns_extension_set_libevent_base(context, event_base)))
+ fprintf(stderr, "Setting the event base failed");
+
+ else if ((r = send_query(context, query_name, query_type,
+ &transaction_id)))
+ fprintf(stderr, "Queueing query failed: %d\n", r);
+
+ else {
+ printf("Request with transaction ID %"PRIu64" scheduled.\n",
+ transaction_id);
+ if (event_base_dispatch(event_base) < 0)
+ fprintf(stderr, "Error dispatching events\n");
+ }
+
+ /* Clean up */
+ if (event_base)
+ event_base_free(event_base);
+
+ if (context)
+ getdns_context_destroy(context);
+
+ /* Assuming we get here, leave gracefully */
+ exit(EXIT_SUCCESS);
+}
+