ldns_resolver_set_recursive(res, false);
/* setup the root nameserver in the new resolver */
- if (ldns_resolver_push_nameserver_rr_list(res, global_dns_root) != LDNS_STATUS_OK) {
+ status = ldns_resolver_push_nameserver_rr_list(res, global_dns_root);
+ if (status != LDNS_STATUS_OK) {
+ fprintf(stderr, "Error adding root servers to resolver: %s\n", ldns_get_errorstr_by_id(status));
+ ldns_rr_list_print(stdout, global_dns_root);
return NULL;
}
/* this must be a real query to local_res */
- status = ldns_resolver_send(&p, local_res, ldns_dname_new_frm_str("."), LDNS_RR_TYPE_NS, c, 0);
+ status = ldns_resolver_send(&p, res, ldns_dname_new_frm_str("."), LDNS_RR_TYPE_NS, c, 0);
/* p can still be NULL */
fprintf(stream, "\t-u\t\tsend the query with udp (the default)\n");
fprintf(stream, "\t-x\t\tdo a reverse lookup\n");
fprintf(stream, "\twhen doing a secure trace:\n");
- fprintf(stream, "\t-r <file>\t\tuse file as root servers hint file (NOT IMPLEMENTED YET)\n");
+ fprintf(stream, "\t-r <file>\t\tuse file as root servers hint file\n");
fprintf(stream, "\t-d <domain>\t\tuse domain as the start point for the trace\n");
fprintf(stream, "\t-y <name:key[:algo]>\tspecify named base64 tsig key, and optional an\n\t\t\talgorithm (defaults to hmac-md5.sig-alg.reg.int)\n");
fprintf(stream, "\t-z\t\tdon't randomize the nameservers before use\n");
case 'q':
query_file = optarg;
PURPOSE = DRILL_QTOFILE;
+ break;
+ case 'r':
+ if (global_dns_root) {
+ fprintf(stderr, "There was already a series of root servers set\n");
+ exit(EXIT_FAILURE);
+ }
+ global_dns_root = read_root_hints(optarg);
+ if (!global_dns_root) {
+ fprintf(stderr, "Unable to read root hints file %s, aborting\n", optarg);
+ exit(EXIT_FAILURE);
+ }
+ break;
/* query options */
case 'a':
qfail = true;
}
break;
case 'h':
+ version(stdout, progname);
usage(stdout, progname);
result = EXIT_SUCCESS;
goto exit;
switch(PURPOSE) {
case DRILL_TRACE:
/* do a trace from the root down */
- init_root();
+ if (!global_dns_root) {
+
+ init_root();
+ }
qname = ldns_dname_new_frm_str(name);
if (!qname) {
error("%s", "making qname");
break;
case DRILL_SECTRACE:
/* do a secure trace from the root down */
- init_root();
+ if (!global_dns_root) {
+ init_root();
+ }
qname = ldns_dname_new_frm_str(name);
if (!qname) {
error("%s", "making qname");
ldns_pkt *read_hex_pkt(char *filename);
ldns_buffer *read_hex_buffer(char *filename);
void init_root(void);
+ldns_rr_list *read_root_hints(const char *filename);
void clear_root(void);
void dump_hex(const ldns_pkt *pkt, const char *file);
void warning(const char *fmt, ...);
#include "drill.h"
#include <ldns/ldns.h>
+#include <errno.h>
/* a global list of the root-servers */
-ldns_rr_list *global_dns_root;
+ldns_rr_list *global_dns_root = NULL;
/* put a hardcoded list in the root and
* init the root rrlist structure */
ldns_rr_list_push_rr(global_dns_root, r);
}
+/*
+ * Read a hints file as root
+ *
+ * The file with the given path should contain a list of NS RRs
+ * for the root zone and A records for those NS RRs.
+ * Read them, check them, and append the a records to the rr list given.
+ */
+ldns_rr_list *
+read_root_hints(const char *filename)
+{
+ FILE *fp = NULL;
+ int line_nr = 0;
+ ldns_zone *z;
+ ldns_status status;
+ ldns_rr_list *addresses = NULL;
+ ldns_rr *rr;
+ size_t i;
+
+ fp = fopen(filename, "r");
+ if (!fp) {
+ fprintf(stderr, "Unable to open %s for reading: %s\n", filename, strerror(errno));
+ return NULL;
+ }
+
+ status = ldns_zone_new_frm_fp_l(&z, fp, NULL, 0, 0, &line_nr);
+ fclose(fp);
+ if (status != LDNS_STATUS_OK) {
+ fprintf(stderr, "Error reading root hints file: %s\n", ldns_get_errorstr_by_id(status));
+ return NULL;
+ } else {
+ addresses = ldns_rr_list_new();
+ for (i = 0; i < ldns_rr_list_rr_count(ldns_zone_rrs(z)); i++) {
+ rr = ldns_rr_list_rr(ldns_zone_rrs(z), i);
+ /*if ((address_family == 0 || address_family == 1) &&
+ */
+ if ( ldns_rr_get_type(rr) == LDNS_RR_TYPE_A ) {
+ ldns_rr_list_push_rr(addresses, ldns_rr_clone(rr));
+ }
+ /*if ((address_family == 0 || address_family == 2) &&*/
+ if ( ldns_rr_get_type(rr) == LDNS_RR_TYPE_AAAA) {
+ ldns_rr_list_push_rr(addresses, ldns_rr_clone(rr));
+ }
+ }
+ ldns_zone_deep_free(z);
+ return addresses;
+ }
+}
+
+
void
clear_root(void)
{
ldns_resolver_set_dnssec_cd(res, false);
ldns_resolver_set_dnssec(res, true);
+ /* setup the root nameserver in the new resolver */
+ status = ldns_resolver_push_nameserver_rr_list(res, global_dns_root);
+ if (status != LDNS_STATUS_OK) {
+ printf("ERRRRR: %s\n", ldns_get_errorstr_by_id(status));
+ ldns_rr_list_print(stdout, global_dns_root);
+ return NULL;
+ }
labels_count = ldns_dname_label_count(name);
if (start_name) {
if (ldns_dname_is_subdomain(name, start_name)) {
int ldns_rr_compare_wire(ldns_buffer *rr1_buf, ldns_buffer *rr2_buf)
{
- size_t rr1_len, rr2_len, min_len, i;
+ size_t rr1_len, rr2_len, min_len, i, offset;
-
rr1_len = ldns_buffer_capacity(rr1_buf);
rr2_len = ldns_buffer_capacity(rr2_buf);
+ /* jump past dname (checked in earlier part)
+ * and especially past TTL */
+ offset = 0;
+ while (offset < rr1_len && *ldns_buffer_at(rr1_buf, offset) != 0) {
+ offset += *ldns_buffer_at(rr1_buf, offset);
+ }
+ offset += 9;
min_len = (rr1_len < rr2_len) ? rr1_len : rr2_len;
/* Compare RRs RDATA byte for byte. */
- for(i = 0; i < min_len; i++) {
+ for(i = offset; i < min_len; i++) {
if (*ldns_buffer_at(rr1_buf,i) < *ldns_buffer_at(rr2_buf,i)) {
return -1;
} else if (*ldns_buffer_at(rr1_buf,i) > *ldns_buffer_at(rr2_buf,i)) {
ldns_buffer_free(rr2_buf);
}
-
return result;
}