/* * nsec3-covers. Parses NSEC3s from drill and shows what is covered. * * Pipe the output of the dig/drill query with NSEC3s to the tool. * It will print which domain names are covered by NSEC3s. * * (c) NLnet Labs, 2005, 2006 * See the file LICENSE for the license */ #include "config.h" #include #include void usage(FILE *output) { fprintf(output, "Usage: dig +dnssec | nsec3-covers or\n" "drill -D | nsec3-covers\n"); } void abort_ldns_error(const char* str, ldns_status err) { fprintf(stderr, "error: %s: %s\n", str, ldns_get_errorstr_by_id(err)); exit(1); } char* skip_comments_and_query(FILE* in, ldns_rdf ** qname) { static char buf[10240]; /* read comment lines */ while(1) { if(!fgets(buf, sizeof(buf), in)) return 0; /* EOF */ printf("%s", buf); /* echo */ if(strcmp(buf, "") == 0 || strcmp(buf, "\n") == 0) continue; if(buf[0] != ';') break; if(strncmp(buf, ";; QUESTION SECTION:", 20) == 0) { char *q_rr = buf; /* read question on next line, ;;s before */ if(!fgets(buf, sizeof(buf), in)) return 0; while(*q_rr == ';' || *q_rr == ' ' || *q_rr == '\t') ++q_rr; printf("Question: %s", q_rr); *strchr(q_rr, '\t') = 0; *qname = ldns_dname_new_frm_str(q_rr); } } return buf; } void read_in(ldns_rr_list* list, ldns_rdf** qname, FILE *in) { char* buf; while((buf=skip_comments_and_query(in, qname))) { /* add rr */ ldns_rr *rr=0; ldns_rdf *origin=0, *prev=0; ldns_status err; uint16_t ttl = 3600; if((err=ldns_rr_new_frm_str(&rr, buf, ttl, origin, &prev)) != LDNS_STATUS_OK) abort_ldns_error("read rr", err); ldns_rr_list_push_rr(list, rr); } printf("nsec3-covers: read %d rrs\n", (int)ldns_rr_list_rr_count(list)); if(!qname) { printf("Could not read question name\n"); exit(1); } printf("nsec3-covers: qname is "); ldns_rdf_print(stdout, *qname); printf("\n"); } struct donelist { ldns_rdf* name; struct donelist* next; }; static struct donelist *done = 0; /* this is a linear speed test (slow for large numbers). but the dig response will be small anyway. */ int check_done(ldns_rdf *qname) { struct donelist* p = done; while(p) { if(ldns_dname_compare(qname, p->name)==0) return 1; p = p->next; } /* not done yet add to list */ p = (struct donelist*)malloc(sizeof(struct donelist)); p->name = qname; p->next = done; done = p; return 0; } void check_cover(ldns_rr_list *list, ldns_rdf *qname) { ldns_status status; size_t i; if(check_done(qname)) return; for(i=0; i