From 56d70baa79ae5907b11445364bbea9b31ee4cd20 Mon Sep 17 00:00:00 2001 From: Linus Nordberg Date: Sun, 27 Mar 2016 19:27:30 +0200 Subject: WIP --- tools/dnssec/net2wire.c | 301 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 301 insertions(+) create mode 100644 tools/dnssec/net2wire.c (limited to 'tools/dnssec/net2wire.c') 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 +#include +#include +#include +#include +#include +#include +#include + +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, §ion); + if (r) { + fprintf(stderr, + "unable to get section \"%s\" from reply\n", + section_name); + return r; + } + + r = getdns_list_get_length(section, §ion_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); +} + -- cgit v1.1