#include #include #include #include #define FAIL(...) do { \ fprintf(stderr, "ERROR in %s:%d, ", __FILE__, __LINE__); \ fprintf(stderr, __VA_ARGS__); \ fprintf(stderr, "\n"); \ exit(EXIT_FAILURE); \ } while (0) #define FAIL_r(function_name) FAIL( "%s returned %d: %s", function_name \ , (int)r, getdns_get_errorstr_by_id(r)); void print_dict(getdns_dict *rr_dict) { char *str = getdns_pretty_print_dict(rr_dict); printf("%s\n", str); free(str); } void print_list(getdns_list *rr_list) { char *str = getdns_pretty_print_list(rr_list); printf("%s\n", str); free(str); } void print_wire(uint8_t *wire, size_t wire_len) { size_t pos, i; for (pos = 0; pos < wire_len; pos += 16) { printf("%.4zx", pos); for (i = 0; i < 16; i++) { if (i % 8 == 0) printf(" "); if (pos + i < wire_len) printf(" %.2x", (int)wire[pos + i]); else printf(" "); } printf(" "); for (i = 0; i < 16; i++) { if (i % 8 == 0) printf(" "); if (pos + i < wire_len && isprint(wire[pos + i])) printf("%c", wire[pos + i]); else printf("."); } printf("\n"); } } int main(int argc, char const * const argv[]) { getdns_return_t r; getdns_dict *rr_dict; getdns_bindata *dns_name; getdns_bindata address = { 4, "\xb9\x31\x8d\x25" }; getdns_bindata fourth = { 11, "last string" }; size_t length; char *str; uint8_t *wire, *prev_wire; size_t wire_len; getdns_list *rr_list; FILE *in; uint8_t wire_buf[8200]; size_t i; ssize_t available; char str_buf[10000]; ssize_t str_len = sizeof(str_buf); /* Convert string to rr_dict */ if ((r = getdns_str2rr_dict( "some.domain.tld. 60 IN TXT \"first string\" second \"and third\"", &rr_dict, NULL, 3600))) FAIL_r("getdns_str2rr_dict"); /* Add a fourth text element. */ if ((r = getdns_dict_set_bindata(rr_dict, "/rdata/txt_strings/-", &fourth))) FAIL_r("getdns_list_set_bindata"); print_dict(rr_dict); /* Convert to wireformat from rdata_raw. * Added fourth list element should NOT show. */ wire = NULL; if ((r = getdns_rr_dict2wire(rr_dict, &wire, &wire_len))) FAIL_r("getdns_rr_dict2wire"); print_wire(wire, wire_len); free(wire); /* Convert to wireformat from parsing rdata fields. * Added fourth list element should show. */ if ((r = getdns_dict_remove_name(rr_dict, "/rdata/rdata_raw"))) FAIL_r("getdns_dict_remove_name"); printf("\nremoved \"/rdata/rdata_raw\":\n\n"); if ((r = getdns_rr_dict2wire(rr_dict, &wire, &wire_len))) FAIL_r("getdns_rr_dict2wire"); print_wire(wire, wire_len); free(wire); /* Remove second and third string elements and show text format. */ if ((r = getdns_dict_remove_name(rr_dict, "/rdata/txt_strings/1"))) FAIL_r("getdns_dict_remove_name"); if ((r = getdns_dict_remove_name(rr_dict, "/rdata/txt_strings/1"))) FAIL_r("getdns_dict_remove_name"); if ((r = getdns_rr_dict2str(rr_dict, &str))) FAIL_r("getdns_rr_dict2str"); printf("\n%s", str); free(str); /* Remove all string elements and show text format. */ if ((r = getdns_dict_remove_name(rr_dict, "/rdata/txt_strings/0"))) FAIL_r("getdns_dict_remove_name"); if ((r = getdns_dict_remove_name(rr_dict, "/rdata/txt_strings/0"))) FAIL_r("getdns_dict_remove_name"); if ((r = getdns_rr_dict2str(rr_dict, &str))) FAIL_r("getdns_rr_dict2str"); printf("%s", str); free(str); getdns_dict_destroy(rr_dict); /* Construct rr_dict and convert to string */ if (!(rr_dict = getdns_dict_create())) FAIL("getdns_dict_create returned NULL"); if ((r = getdns_convert_fqdn_to_dns_name("www.getdnsapi.net", &dns_name))) FAIL_r("getdns_convert_fqdn_to_dns_name"); r = getdns_dict_set_bindata(rr_dict, "name", dns_name); free(dns_name->data); free(dns_name); if (r) FAIL_r("getdns_dict_set_bindata"); if ((r = getdns_dict_set_int(rr_dict, "type", GETDNS_RRTYPE_A))) FAIL_r("getdns_dict_set_int"); if ((r = getdns_dict_set_bindata(rr_dict, "/rdata/ipv4_address", &address))) FAIL_r("getdns_dict_set_int"); if ((r = getdns_rr_dict2str(rr_dict, &str))) FAIL_r("getdns_rr_dict2str"); printf("\n%s\n", str); free(str); if ((r = getdns_rr_dict2wire(rr_dict, &wire, &wire_len))) FAIL_r("getdns_rr_dict2wire"); getdns_dict_destroy(rr_dict); print_wire(wire, wire_len); free(wire); /* Convert RR with special rdata fields and repeating last element * from string to rr_dict */ if ((r = getdns_str2rr_dict( "hip2 IN HIP 2 200100107B1A74DF365639CC39F1D578 AwEAAbdxyhNuSutc5EMzxTs9LBPCIkOFH8cIvM4p9+LrV4e19WzK00+CI6zBCQTdtWsuxKbWIy87UOoJTwkUs7lBu+Upr1gsNrut79ryra+bSRGQb1slImA8YVJyuIDsj7kwzG7jnERNqnWxZ48AWkskmdHaVDP4BcelrTI3rMXdXF5D rvs1.example.com. rvs2.example.com.", &rr_dict, "nlnetlabs.nl", 3600))) FAIL_r("getdns_str2rr_dict"); if ((r = getdns_dict_remove_name(rr_dict, "/rdata/rdata_raw"))) FAIL_r("getdns_dict_remove_name"); printf("\n"); print_dict(rr_dict); /* Convert RR with special rdata fields and repeating last element * back to string. */ if ((r = getdns_rr_dict2str(rr_dict, &str))) FAIL_r("getdns_rr_dict2str"); printf("%s", str); free(str); /* Convert RR with special rdata fields without repeating last element * to string. */ if ((r = getdns_dict_remove_name(rr_dict, "/rdata/rendezvous_servers"))) FAIL_r("getdns_dict_remove_name"); if ((r = getdns_dict_get_bindata(rr_dict, "name", &dns_name))) FAIL_r("getdns_dict_get_bindata"); dns_name->data[4] = '0'; if ((r = getdns_rr_dict2str(rr_dict, &str))) FAIL_r("getdns_rr_dict2str"); printf("%s\n", str); free(str); getdns_dict_destroy(rr_dict); /* Convert RR with repeat block from string to rr_dict */ if ((r = getdns_str2rr_dict( "apl APL 1:192.168.42.0/26 1:192.168.42.64/26 !1:192.168.42.128/25 1:224.0.0.0/4 2:FF00:0:0:0:0:0:0:0/8", &rr_dict, "net-dns.org", 3600))) FAIL_r("getdns_str2rr_dict"); if ((r = getdns_dict_remove_name(rr_dict, "/rdata/rdata_raw"))) FAIL_r("getdns_dict_remove_name"); print_dict(rr_dict); /* Convert repeat block from rr_dict back to string. */ if ((r = getdns_rr_dict2str(rr_dict, &str))) FAIL_r("getdns_rr_dict2str"); printf("%s", str); free(str); getdns_dict_destroy(rr_dict); if (!(in = fopen(argv[1], "r"))) FAIL("Could not fopen %s\n", argv[1]); if ((r = getdns_fp2rr_list(in, &rr_list, NULL, 0))) FAIL_r("getdns_fp2rr_list"); fclose(in); print_list(rr_list); /* Fill the wire_buf with wireformat RR's in rr_list * wire_buf is too small for last two rr's. */ wire = wire_buf; available = sizeof(wire_buf); for (i = 0; !(r = getdns_list_get_dict(rr_list, i, &rr_dict)); i++) { prev_wire = wire; if ((r = getdns_rr_dict2wire_scan(rr_dict,&wire,&available))) { if (r == GETDNS_RETURN_NEED_MORE_SPACE) { printf("record %.3zu, available buffer space: " "%zi\n", i, available); /* The buffer was too small to fit the wire- * format representation. available now holds * a negative number. the wire pointer is this * much beyond the end of the buffer space. * * If we would add available to wire, wire * would be positioned at the end of the buffer * but would not be positioned at a clean RR * border. Therefore we have to remember the * previous position of wire, so we can reset * it at the end of the wireformat representa- * tion of the previously converted rr_dict. */ wire = prev_wire; break; } else FAIL_r("getdns_rr_dict2wire_scan"); } printf("record %3zu, available buffer space: " "%zi\n", i, available); fflush(stdout); } if (r == GETDNS_RETURN_NO_SUCH_LIST_ITEM) r = GETDNS_RETURN_GOOD; getdns_list_destroy(rr_list); /* Now scan over the wireformat buffer and convert to rr_dicts again. * Then fill a string buffer with those rr_dicts. */ available = wire - wire_buf; wire = wire_buf; str = str_buf; str_len = sizeof(str_buf); while (available > 0 && str_len > 0) { rr_dict = NULL; if ((r = getdns_wire2rr_dict_scan( (const uint8_t **)&wire, &available, &rr_dict))) FAIL_r("getdns_wire2rr_dict_scan"); if ((r = getdns_rr_dict2str_scan(rr_dict, &str, &str_len))) FAIL_r("getdns_rr_dict2str_scan"); getdns_dict_destroy(rr_dict); } *str = 0; /* Print the entire buffer */ printf("%s", str_buf); exit(EXIT_SUCCESS); }