ldns_rr * ldns_axfr_next(ldns_resolver *resolver) { ldns_rr *cur_rr; uint8_t *packet_wire; size_t packet_wire_size; ldns_lookup_table *rcode; ldns_status status; /* check if start() has been called */ if (!resolver || resolver->_socket == 0) { return NULL; } if (resolver->_cur_axfr_pkt) { if (resolver->_axfr_i == ldns_pkt_ancount(resolver->_cur_axfr_pkt)) { ldns_pkt_free(resolver->_cur_axfr_pkt); resolver->_cur_axfr_pkt = NULL; return ldns_axfr_next(resolver); } cur_rr = ldns_rr_clone(ldns_rr_list_rr( ldns_pkt_answer(resolver->_cur_axfr_pkt), resolver->_axfr_i)); resolver->_axfr_i++; if (ldns_rr_get_type(cur_rr) == LDNS_RR_TYPE_SOA) { resolver->_axfr_soa_count++; if (resolver->_axfr_soa_count >= 2) { close(resolver->_socket); resolver->_socket = 0; ldns_pkt_free(resolver->_cur_axfr_pkt); resolver->_cur_axfr_pkt = NULL; } } return cur_rr; } else { packet_wire = ldns_tcp_read_wire(resolver->_socket, &packet_wire_size); if(!packet_wire) return NULL; status = ldns_wire2pkt(&resolver->_cur_axfr_pkt, packet_wire, packet_wire_size); free(packet_wire); resolver->_axfr_i = 0; if (status != LDNS_STATUS_OK) { /* TODO: make status return type of this function (...api change) */ fprintf(stderr, "Error parsing rr during AXFR: %s\n", ldns_get_errorstr_by_id(status)); return NULL; } else if (ldns_pkt_get_rcode(resolver->_cur_axfr_pkt) != 0) { rcode = ldns_lookup_by_id(ldns_rcodes, (int) ldns_pkt_get_rcode(resolver->_cur_axfr_pkt)); fprintf(stderr, "Error in AXFR: %s\n", rcode->name); return NULL; } else { return ldns_axfr_next(resolver); } } }
ldns_pkt * ldns_resolver_search(const ldns_resolver *r,const ldns_rdf *name, ldns_rr_type t, ldns_rr_class c, uint16_t flags) { char *str_dname; ldns_rdf *new_name; ldns_rdf **search_list; size_t i; ldns_pkt *p; str_dname = ldns_rdf2str(name); if (ldns_dname_str_absolute(str_dname)) { /* query as-is */ return ldns_resolver_query(r, name, t, c, flags); } else if (ldns_resolver_dnsrch(r)) { search_list = ldns_resolver_searchlist(r); for (i = 0; i < ldns_resolver_searchlist_count(r); i++) { new_name = ldns_dname_cat_clone(name, search_list[i]); p = ldns_resolver_query(r, new_name, t, c, flags); ldns_rdf_free(new_name); if (p) { if (ldns_pkt_get_rcode(p) == LDNS_RCODE_NOERROR) { return p; } else { ldns_pkt_free(p); p = NULL; } } } } return NULL; }
/** check the packet and make sure that EDNS and DO and the type and RRSIG */ static int check_packet(uint8_t* wire, size_t len, int tp) { ldns_pkt *p = NULL; ldns_status s; if( (s=ldns_wire2pkt(&p, wire, len)) != LDNS_STATUS_OK) { if(verb) printf("error: %s\n", ldns_get_errorstr_by_id(s)); goto failed; } if(!p) { if(verb) printf("error: out of memory\n"); goto failed; } /* does DNS work? */ if(ldns_pkt_get_rcode(p) != LDNS_RCODE_NOERROR) { char* r = ldns_pkt_rcode2str(ldns_pkt_get_rcode(p)); if(verb) printf("no answer, %s\n", r?r:"(out of memory)"); LDNS_FREE(r); goto failed; } /* test EDNS0 presence, of OPT record */ /* LDNS forgets during pkt parse, but we test the ARCOUNT; * 0 additionals means no EDNS(on the wire), and after parsing the * same additional RRs as before means no EDNS OPT */ if(LDNS_ARCOUNT(wire) == 0 || ldns_pkt_arcount(p) == LDNS_ARCOUNT(wire)) { if(verb) printf("no EDNS\n"); goto failed; } /* test if the type, RRSIG present */ if(!check_type_in_answer(p, tp) || !check_type_in_answer(p, LDNS_RR_TYPE_RRSIG)) { goto failed; } LDNS_FREE(wire); ldns_pkt_free(p); return 1; failed: LDNS_FREE(wire); ldns_pkt_free(p); return 0; }
/** match all of the packet */ static int match_all(ldns_pkt* q, ldns_pkt* p) { if(ldns_pkt_get_opcode(q) != ldns_pkt_get_opcode(p)) { verbose(3, "allmatch: opcode different"); return 0;} if(ldns_pkt_get_rcode(q) != ldns_pkt_get_rcode(p)) { verbose(3, "allmatch: rcode different"); return 0;} if(ldns_pkt_id(q) != ldns_pkt_id(p)) { verbose(3, "allmatch: id different"); return 0;} if(cmp_bool(ldns_pkt_qr(q), ldns_pkt_qr(p)) != 0) { verbose(3, "allmatch: qr different"); return 0;} if(cmp_bool(ldns_pkt_aa(q), ldns_pkt_aa(p)) != 0) { verbose(3, "allmatch: aa different"); return 0;} if(cmp_bool(ldns_pkt_tc(q), ldns_pkt_tc(p)) != 0) { verbose(3, "allmatch: tc different"); return 0;} if(cmp_bool(ldns_pkt_rd(q), ldns_pkt_rd(p)) != 0) { verbose(3, "allmatch: rd different"); return 0;} if(cmp_bool(ldns_pkt_cd(q), ldns_pkt_cd(p)) != 0) { verbose(3, "allmatch: cd different"); return 0;} if(cmp_bool(ldns_pkt_ra(q), ldns_pkt_ra(p)) != 0) { verbose(3, "allmatch: ra different"); return 0;} if(cmp_bool(ldns_pkt_ad(q), ldns_pkt_ad(p)) != 0) { verbose(3, "allmatch: ad different"); return 0;} if(ldns_pkt_qdcount(q) != ldns_pkt_qdcount(p)) { verbose(3, "allmatch: qdcount different"); return 0;} if(ldns_pkt_ancount(q) != ldns_pkt_ancount(p)) { verbose(3, "allmatch: ancount different"); return 0;} if(ldns_pkt_nscount(q) != ldns_pkt_nscount(p)) { verbose(3, "allmatch: nscount different"); return 0;} if(ldns_pkt_arcount(q) != ldns_pkt_arcount(p)) { verbose(3, "allmatch: arcount different"); return 0;} if(!match_list(ldns_pkt_question(q), ldns_pkt_question(p))) { verbose(3, "allmatch: qd section different"); return 0;} if(!match_list(ldns_pkt_answer(q), ldns_pkt_answer(p))) { verbose(3, "allmatch: an section different"); return 0;} if(!match_list(ldns_pkt_authority(q), ldns_pkt_authority(p))) { verbose(3, "allmatch: ns section different"); return 0;} if(!match_list(ldns_pkt_additional(q), ldns_pkt_additional(p))) { verbose(3, "allmatch: ar section different"); return 0;} if(!match_edns(q, p)) { verbose(3, "edns different."); return 0;} return 1; }
void dnspkt_proc (const char *bytes, uint16_t len, struct timeval ts, host_t *src, host_t *dst) { ldns_pkt *pkt; if (ldns_wire2pkt(&pkt, bytes, len) != LDNS_STATUS_OK) { return; } if (ldns_pkt_get_opcode(pkt) != LDNS_PACKET_QUERY) goto done; uint16_t i; ldns_rr_list *rrlist; if (ldns_pkt_qr(pkt) == 0) { rrlist = ldns_pkt_question(pkt); for (i = 0; i < ldns_rr_list_rr_count(rrlist); i++) { dnspkt_printqry(ldns_rr_list_rr(rrlist, i), ts, src, dst); } } else { dnspkt_printresp(pkt, ts, src, dst); if (ldns_pkt_aa(pkt) == 0) goto done; if (ldns_pkt_tc(pkt) == 1) goto done; if (ldns_pkt_rd(pkt) == 1) goto done; if (ldns_pkt_get_rcode(pkt) != LDNS_RCODE_NOERROR) goto done; rrlist = ldns_pkt_answer(pkt); for (i = 0; i < ldns_rr_list_rr_count(rrlist); i++) { dnspkt_printrr(ldns_rr_list_rr(rrlist, i), ts, src, dst, 0); } rrlist = ldns_pkt_authority(pkt); for (i = 0; i < ldns_rr_list_rr_count(rrlist); i++) { dnspkt_printrr(ldns_rr_list_rr(rrlist, i), ts, src, dst, 1); } rrlist = ldns_pkt_additional(pkt); for (i = 0; i < ldns_rr_list_rr_count(rrlist); i++) { dnspkt_printrr(ldns_rr_list_rr(rrlist, i), ts, src, dst, 2); } } done: ldns_pkt_free(pkt); }
void dnspkt_printresp (ldns_pkt *pkt, struct timeval ts, host_t *src, host_t *dst) { FILE *output = dnsfile_resp(); __print_ts(output, ts); __print_ip(output, src); __print_ip(output, dst); fprintf(output, "%u\t", (uint16_t)ldns_pkt_size(pkt)); fprintf(output, "%u\t", ldns_pkt_aa(pkt)); fprintf(output, "%u\t", ldns_pkt_tc(pkt)); fprintf(output, "%u\t", ldns_pkt_rd(pkt)); fprintf(output, "%u\t", ldns_pkt_ra(pkt)); fprintf(output, "%u\t", ldns_pkt_get_rcode(pkt)); fprintf(output, "%u\t", ldns_pkt_qdcount(pkt)); fprintf(output, "%u\t", ldns_pkt_ancount(pkt)); fprintf(output, "%u\t", ldns_pkt_nscount(pkt)); fprintf(output, "%u\t", ldns_pkt_arcount(pkt)); ldns_rr_list *rrlist = ldns_pkt_question(pkt); if (ldns_rr_list_rr_count(rrlist) > 0) { ldns_rr_print(output, ldns_rr_list_rr(rrlist, 0)); } else { fprintf(output, "\t\t\n"); } }
/* * Copies the packet header data to the buffer in wire format */ static ldns_status ldns_hdr2buffer_wire(ldns_buffer *buffer, const ldns_pkt *packet) { uint8_t flags; uint16_t arcount; if (ldns_buffer_reserve(buffer, 12)) { ldns_buffer_write_u16(buffer, ldns_pkt_id(packet)); flags = ldns_pkt_qr(packet) << 7 | ldns_pkt_get_opcode(packet) << 3 | ldns_pkt_aa(packet) << 2 | ldns_pkt_tc(packet) << 1 | ldns_pkt_rd(packet); ldns_buffer_write_u8(buffer, flags); flags = ldns_pkt_ra(packet) << 7 /*| ldns_pkt_z(packet) << 6*/ | ldns_pkt_ad(packet) << 5 | ldns_pkt_cd(packet) << 4 | ldns_pkt_get_rcode(packet); ldns_buffer_write_u8(buffer, flags); ldns_buffer_write_u16(buffer, ldns_pkt_qdcount(packet)); ldns_buffer_write_u16(buffer, ldns_pkt_ancount(packet)); ldns_buffer_write_u16(buffer, ldns_pkt_nscount(packet)); /* add EDNS0 and TSIG to additional if they are there */ arcount = ldns_pkt_arcount(packet); if (ldns_pkt_tsig(packet)) { arcount++; } if (ldns_pkt_edns(packet)) { arcount++; } ldns_buffer_write_u16(buffer, arcount); } return ldns_buffer_status(buffer); }
int cache_dns_objects(packetinfo *pi, ldns_rdf *rdf_data, ldns_buffer *buff, ldns_pkt *dns_pkt) { int j; int dns_answer_domain_cnt; uint64_t dnshash; ldns_status status; pdns_record *pr = NULL; ldns_rr_list *dns_answer_domains; unsigned char *domain_name = 0; ldns_buffer_clear(buff); status = ldns_rdf2buffer_str(buff, rdf_data); if (status != LDNS_STATUS_OK) { dlog("[D] Error in ldns_rdf2buffer_str(): %d\n", status); return(-1); } dns_answer_domains = ldns_pkt_answer(dns_pkt); dns_answer_domain_cnt = ldns_rr_list_rr_count(dns_answer_domains); domain_name = (unsigned char *) ldns_buffer2str(buff); if (domain_name == NULL) { dlog("[D] Error in ldns_buffer2str(%p)\n", buff); return(-1); } else { dlog("[D] domain_name: %s\n", domain_name); dlog("[D] dns_answer_domain_cnt: %d\n",dns_answer_domain_cnt); } if (dns_answer_domain_cnt == 0 && ldns_pkt_get_rcode(dns_pkt) != 0) { uint16_t rcode = ldns_pkt_get_rcode(dns_pkt); dlog("[D] Error return code: %d\n", rcode); /* PROBLEM: * As there is no valid ldns_rr here and we cant fake one that will * be very unique, we cant push this to the normal * bucket[hash->linked_list]. We should probably allocate a static * bucket[MAX_NXDOMAIN] to hold NXDOMAINS, and when that is full, pop * out the oldest (LRU). A simple script quering for random non existing * domains could easly put stress on passivedns (think conficker etc.) * if the bucket is to big or non efficient. We would still store data * such as: fistseen,lastseen,client_ip,server_ip,class,query,NXDOMAIN */ if (config.dnsfe & (pdns_chk_dnsfe(rcode))) { ldns_rr_list *dns_query_domains; ldns_rr_class class; ldns_rr_type type; ldns_rr *rr; dnshash = hash(domain_name); dlog("[D] Hash: %lu\n", dnshash); /* Check if the node exists, if not, make it */ pr = get_pdns_record(dnshash, pi, domain_name); /* Set the SRC flag: */ //lname_node->srcflag |= pdns_chk_dnsfe(rcode); dns_query_domains = ldns_pkt_question(dns_pkt); rr = ldns_rr_list_rr(dns_query_domains, 0); class = ldns_rr_get_class(rr); type = ldns_rr_get_type(rr); if ((pr->last_seen.tv_sec - pr->last_print.tv_sec) >= config.dnsprinttime) { /* Print the SRC Error record */ print_passet_err(pr, rdf_data, rr, rcode); } } else {
ldns_rr * ldns_axfr_next(ldns_resolver *resolver) { ldns_rr *cur_rr; uint8_t *packet_wire; size_t packet_wire_size; ldns_lookup_table *rcode; ldns_status status; /* check if start() has been called */ if (!resolver || resolver->_socket == 0) { return NULL; } if (resolver->_cur_axfr_pkt) { if (resolver->_axfr_i == ldns_pkt_ancount(resolver->_cur_axfr_pkt)) { ldns_pkt_free(resolver->_cur_axfr_pkt); resolver->_cur_axfr_pkt = NULL; return ldns_axfr_next(resolver); } cur_rr = ldns_rr_clone(ldns_rr_list_rr( ldns_pkt_answer(resolver->_cur_axfr_pkt), resolver->_axfr_i)); resolver->_axfr_i++; if (ldns_rr_get_type(cur_rr) == LDNS_RR_TYPE_SOA) { resolver->_axfr_soa_count++; if (resolver->_axfr_soa_count >= 2) { #ifndef USE_WINSOCK close(resolver->_socket); #else closesocket(resolver->_socket); #endif resolver->_socket = 0; ldns_pkt_free(resolver->_cur_axfr_pkt); resolver->_cur_axfr_pkt = NULL; } } return cur_rr; } else { packet_wire = ldns_tcp_read_wire(resolver->_socket, &packet_wire_size); if(!packet_wire) return NULL; status = ldns_wire2pkt(&resolver->_cur_axfr_pkt, packet_wire, packet_wire_size); free(packet_wire); resolver->_axfr_i = 0; if (status != LDNS_STATUS_OK) { /* TODO: make status return type of this function (...api change) */ fprintf(stderr, "Error parsing rr during AXFR: %s\n", ldns_get_errorstr_by_id(status)); /* RoRi: we must now also close the socket, otherwise subsequent uses of the same resolver structure will fail because the link is still open or in an undefined state */ #ifndef USE_WINSOCK close(resolver->_socket); #else closesocket(resolver->_socket); #endif resolver->_socket = 0; return NULL; } else if (ldns_pkt_get_rcode(resolver->_cur_axfr_pkt) != 0) { rcode = ldns_lookup_by_id(ldns_rcodes, (int) ldns_pkt_get_rcode(resolver->_cur_axfr_pkt)); fprintf(stderr, "Error in AXFR: %s\n", rcode->name); /* RoRi: we must now also close the socket, otherwise subsequent uses of the same resolver structure will fail because the link is still open or in an undefined state */ #ifndef USE_WINSOCK close(resolver->_socket); #else closesocket(resolver->_socket); #endif resolver->_socket = 0; return NULL; } else { return ldns_axfr_next(resolver); } } }
int main(int argc, char **argv) { /* Local Vars */ int i; int soa_valid = 0; int ns_valid = 0; ldns_rdf *rd_domain; ldns_rdf *rd_trace; ldns_rdf *rd_cdomain; ldns_pkt *pkt; ldns_resolver *res; ldns_rr *rr; ldns_rr_list *rrl; ldns_rr_list *rrl_domain_soa; ldns_rr_list *rrl_domain_soa_rrsig; ldns_rr_list *rrl_domain_ns; ldns_rr_list *rrl_domain_ns_rrsig; ldns_rr_list *rrl_valid_keys; ldns_status status; /* Set signal handling and alarm */ if (signal(SIGALRM, timeout_alarm_handler) == SIG_ERR) critical("Setup SIGALRM trap failed!"); /* Process check arguments */ if (process_arguments(argc, argv) != OK) unknown("Parsing arguments failed!"); /* Start plugin timeout */ alarm(mp_timeout); rd_domain = ldns_dname_new_frm_str(domainname); if (!rd_domain) unknown("Illegal domain name"); rd_trace = ldns_dname_new_frm_str(domaintrace); if (!rd_trace) unknown("Illegal trace domain name"); /* Check domain is subdomain from trace start */ if (!ldns_dname_is_subdomain(rd_domain, rd_trace)) { ldns_rr_list_deep_free(trusted_keys); ldns_rdf_deep_free(rd_domain); ldns_rdf_deep_free(rd_trace); unknown("'%s' is not a subdomain of '%s'.", domainname, domaintrace); } /* Add trusted keys for trace domain to rrl_valid_keys. */ rrl_valid_keys = ldns_rr_list_new(); for(i = 0; i < ldns_rr_list_rr_count(trusted_keys); i++) { rr = ldns_rr_list_rr(trusted_keys, i); if (ldns_dname_compare(ldns_rr_owner(rr),rd_trace) == 0) ldns_rr_list_push_rr(rrl_valid_keys, ldns_rr_clone(rr)); } ldns_rr_list_deep_free(trusted_keys); if (ldns_rr_list_rr_count(rrl_valid_keys) == 0) { ldns_rdf_deep_free(rd_domain); ldns_rdf_deep_free(rd_trace); ldns_rr_list_deep_free(rrl_valid_keys); critical("No trusted key for trace start '%s'", domaintrace?domaintrace:"."); } if (mp_verbose >= 2) { printf("--[ Trusted keys used ]-------------------------------------\n"); ldns_rr_list_sort(rrl_valid_keys); ldns_rr_list_print(stdout, rrl_valid_keys); printf("------------------------------------------------------------\n"); } /* create a new resolver with dns_server or server from /etc/resolv.conf */ res = createResolver(hostname); if (!res) { ldns_rdf_deep_free(rd_domain); ldns_rdf_deep_free(rd_trace); ldns_rr_list_deep_free(rrl_valid_keys); unknown("Creating resolver failed."); } resolverEnableDnssec(res); ldns_resolver_set_dnssec_anchors(res, rrl_valid_keys); /* check domain exists */ pkt = mp_ldns_resolver_query(res, rd_domain, LDNS_RR_TYPE_SOA, LDNS_RR_CLASS_IN, LDNS_RD); if (pkt == NULL || ldns_pkt_get_rcode(pkt) != LDNS_RCODE_NOERROR) { ldns_rdf_deep_free(rd_domain); ldns_rdf_deep_free(rd_trace); ldns_resolver_deep_free(res); if (pkt && ldns_pkt_get_rcode(pkt) == LDNS_RCODE_NXDOMAIN) { ldns_pkt_free(pkt); critical("Domain '%s' don't exist.", domainname); } ldns_pkt_free(pkt); critical("Unable to get SOA for %s.", domainname); } rrl_domain_soa = ldns_pkt_rr_list_by_name_and_type(pkt, rd_domain, LDNS_RR_TYPE_SOA, LDNS_SECTION_ANSWER); if (rrl_domain_soa == NULL || ldns_rr_list_rr_count(rrl_domain_soa) == 0) { ldns_rdf_deep_free(rd_domain); ldns_rdf_deep_free(rd_trace); ldns_resolver_deep_free(res); ldns_pkt_free(pkt); critical("Domain '%s' not found.", domainname); } rrl_domain_soa_rrsig = ldns_dnssec_pkt_get_rrsigs_for_name_and_type(pkt, rd_domain, LDNS_RR_TYPE_SOA); if (rrl_domain_soa_rrsig == NULL || ldns_rr_list_rr_count(rrl_domain_soa_rrsig) == 0) { free(domaintrace); ldns_rdf_deep_free(rd_domain); ldns_rdf_deep_free(rd_trace); ldns_resolver_deep_free(res); ldns_pkt_free(pkt); ldns_rr_list_deep_free(rrl_domain_soa); critical("Domain '%s' not signed.", domainname); } ldns_pkt_free(pkt); pkt = ldns_resolver_query(res, rd_domain, LDNS_RR_TYPE_NS, LDNS_RR_CLASS_IN, LDNS_RD); rrl_domain_ns = ldns_pkt_rr_list_by_name_and_type(pkt, rd_domain, LDNS_RR_TYPE_NS, LDNS_SECTION_ANSWER); rrl_domain_ns_rrsig = ldns_dnssec_pkt_get_rrsigs_for_name_and_type(pkt, rd_domain, LDNS_RR_TYPE_NS); ldns_pkt_free(pkt); if (mp_verbose >= 2) { printf("--[ Checked Domain ]----------------------------------------\n"); ldns_rr_list_print(stdout, rrl_domain_soa); printf("------------------------------------------------------------\n"); ldns_rr_list_print(stdout, rrl_domain_soa_rrsig); printf("------------------------------------------------------------\n"); ldns_rr_list_print(stdout, rrl_domain_ns); printf("------------------------------------------------------------\n"); ldns_rr_list_print(stdout, rrl_domain_ns_rrsig); printf("------------------------------------------------------------\n"); } /* create a new resolver with dns_server or server from /etc/resolv.conf */ ldns_resolver_free(res); res = createResolver(resolver); if (!res) { ldns_rdf_deep_free(rd_domain); ldns_rdf_deep_free(rd_trace); ldns_rr_list_deep_free(rrl_valid_keys); unknown("Creating resolver failed."); } resolverEnableDnssec(res); ldns_resolver_set_dnssec_anchors(res, rrl_valid_keys); /* Fetch valid keys from top down */ i = ldns_dname_label_count(rd_domain) - ldns_dname_label_count(rd_trace); for (; i>=0; i--) { rd_cdomain = ldns_dname_clone_from(rd_domain, i); if (mp_verbose) { char *str = ldns_rdf2str(rd_cdomain); printf("Trace: %s\n", str); free(str); } rrl = ldns_fetch_valid_domain_keys(res, rd_cdomain, rrl_valid_keys, &status); if (mp_verbose >= 2) { printf("--[ Valid Keys ]----------------------------------------\n"); ldns_rr_list_sort(rrl); ldns_rr_list_print(stdout, rrl); printf("------------------------------------------------------------\n"); } ldns_rr_list_cat(rrl_valid_keys, rrl); ldns_rr_list_free(rrl); ldns_rdf_deep_free(rd_cdomain); } ldns_rdf_deep_free(rd_trace); ldns_rdf_deep_free(rd_domain); /* Validate SOA */ for(i = 0; i < ldns_rr_list_rr_count(rrl_domain_soa_rrsig); i++) { rr = ldns_rr_list_rr(rrl_domain_soa_rrsig, i); status = ldns_verify_rrsig_keylist(rrl_domain_soa, rr, rrl_valid_keys, NULL); if (status == LDNS_STATUS_OK) soa_valid++; else if (mp_verbose > 0) fprintf(stderr, "ldns_verify_rrsig_keylist SOA failed: %s\n", ldns_get_errorstr_by_id(status)); } ldns_rr_list_deep_free(rrl_domain_soa); ldns_rr_list_deep_free(rrl_domain_soa_rrsig); if (soa_valid == 0) { critical("No valid Signatur for SOA of '%s'", domainname); free(domainname); free(domaintrace); ldns_resolver_deep_free(res); ldns_rr_list_deep_free(rrl_domain_ns); ldns_rr_list_deep_free(rrl_domain_ns_rrsig); return checkState; } /* Validate NS */ for(i = 0; i < ldns_rr_list_rr_count(rrl_domain_ns_rrsig); i++) { rr = ldns_rr_list_rr(rrl_domain_ns_rrsig, i); status = ldns_verify_rrsig_keylist(rrl_domain_ns, rr, rrl_valid_keys, NULL); if (status == LDNS_STATUS_OK) ns_valid++; else if (mp_verbose > 0) fprintf(stderr, "ldns_verify_rrsig_keylist NS failed: %s\n", ldns_get_errorstr_by_id(status)); } ldns_rr_list_deep_free(rrl_domain_ns); ldns_rr_list_deep_free(rrl_domain_ns_rrsig); ldns_resolver_deep_free(res); if (ns_valid == 0) { critical("No valid Signatur for NS of '%s'", domainname); free(domainname); free(domaintrace); return checkState; } ok("Trust for '%s' successfull traces from '%s'", domainname, domaintrace); free(domainname); free(domaintrace); return checkState; }
static ldns_rr_list * retrieve_dnskeys(ldns_resolver *local_res, ldns_rdf *name, ldns_rr_type t, ldns_rr_class c, ldns_rr_list *dns_root) { ldns_resolver *res; ldns_pkt *p; ldns_rr_list *new_nss_a; ldns_rr_list *new_nss_aaaa; ldns_rr_list *final_answer; ldns_rr_list *new_nss; ldns_rr_list *ns_addr; ldns_rr_list *ns_addr2; uint16_t loop_count; ldns_rdf *pop; ldns_status status; size_t i; size_t nss_i; ldns_rr_list *answer_list = NULL; ldns_rr_list *authority_list = NULL; size_t last_nameserver_count; ldns_rdf **last_nameservers; loop_count = 0; new_nss_a = NULL; new_nss_aaaa = NULL; new_nss = NULL; ns_addr = NULL; ns_addr2 = NULL; final_answer = NULL; p = ldns_pkt_new(); res = ldns_resolver_new(); if (!p || !res) { fprintf(stderr, "Memory allocation failed"); return NULL; } if (verbosity >= 2) { printf("Finding dnskey data for zone: "); ldns_rdf_print(stdout, name); printf("\n\n"); } /* transfer some properties of local_res to res, * because they were given on the commandline */ ldns_resolver_set_ip6(res, ldns_resolver_ip6(local_res)); ldns_resolver_set_port(res, ldns_resolver_port(local_res)); ldns_resolver_set_debug(res, ldns_resolver_debug(local_res)); ldns_resolver_set_dnssec(res, ldns_resolver_dnssec(local_res)); ldns_resolver_set_fail(res, ldns_resolver_fail(local_res)); ldns_resolver_set_usevc(res, ldns_resolver_usevc(local_res)); ldns_resolver_set_random(res, ldns_resolver_random(local_res)); ldns_resolver_set_recursive(res, false); /* setup the root nameserver in the new resolver */ status = ldns_resolver_push_nameserver_rr_list(res, dns_root); if (status != LDNS_STATUS_OK) { fprintf(stderr, "Error setting root nameservers in resolver: %s\n", ldns_get_errorstr_by_id(status)); return NULL; } ldns_pkt_free(p); status = ldns_resolver_send(&p, res, name, t, c, 0); if (status != LDNS_STATUS_OK) { fprintf(stderr, "Error querying root servers: %s\n", ldns_get_errorstr_by_id(status)); return NULL; } if (ldns_pkt_get_rcode(p) != LDNS_RCODE_NOERROR) { printf("Error in packet:\n"); ldns_pkt_print(stdout, p); return NULL; } if (verbosity >= 4) { ldns_pkt_print(stdout, p); printf("\n\n"); } /* from now on, use TCP */ ldns_resolver_set_usevc(res, true); while(status == LDNS_STATUS_OK && ldns_pkt_reply_type(p) == LDNS_PACKET_REFERRAL) { if (verbosity >= 3) { printf("This is a delegation!\n\n"); } if (address_family == 0 || address_family == 1) { new_nss_a = ldns_pkt_rr_list_by_type(p, LDNS_RR_TYPE_A, LDNS_SECTION_ADDITIONAL); } else { new_nss_a = ldns_rr_list_new(); } if (address_family == 0 || address_family == 2) { new_nss_aaaa = ldns_pkt_rr_list_by_type(p, LDNS_RR_TYPE_AAAA, LDNS_SECTION_ADDITIONAL); } else { new_nss_aaaa = ldns_rr_list_new(); } new_nss = ldns_pkt_rr_list_by_type(p, LDNS_RR_TYPE_NS, LDNS_SECTION_AUTHORITY); /* remove the old nameserver from the resolver */ while((pop = ldns_resolver_pop_nameserver(res))) { ldns_rdf_deep_free(pop); } /* also check for new_nss emptyness */ if (!new_nss_aaaa && !new_nss_a) { /* * no nameserver found!!! * try to resolve the names we do got */ if (verbosity >= 3) { printf("Did not get address record for nameserver, doing seperate query.\n"); } ns_addr = ldns_rr_list_new(); for(i = 0; (size_t) i < ldns_rr_list_rr_count(new_nss); i++) { /* get the name of the nameserver */ pop = ldns_rr_rdf(ldns_rr_list_rr(new_nss, i), 0); if (!pop) { break; } /* retrieve it's addresses */ ns_addr2 = ldns_get_rr_list_addr_by_name(local_res, pop, c, 0); if (!ldns_rr_list_cat(ns_addr, ns_addr2)) { fprintf(stderr, "Internal error adding nameserver address.\n"); exit(EXIT_FAILURE); } ldns_rr_list_free(ns_addr2); } if (ns_addr) { if (ldns_resolver_push_nameserver_rr_list(res, ns_addr) != LDNS_STATUS_OK) { fprintf(stderr, "Error adding new nameservers"); ldns_pkt_free(p); return NULL; } ldns_rr_list_deep_free(ns_addr); } else { ldns_rr_list_print(stdout, ns_addr); fprintf(stderr, "Could not find the nameserver ip addr; abort"); ldns_pkt_free(p); return NULL; } } /* normally, the first working ns is used, but we need all now, so do it one by one * if the answer is null, take it from the next resolver * if the answer is not, compare it to that of the next resolver * error if different, continue if the same * if answer list null and no resolvers left die. */ ldns_rr_list_deep_free(answer_list); ldns_rr_list_deep_free(authority_list); answer_list = NULL; authority_list = NULL; for (nss_i = 0; nss_i < ldns_rr_list_rr_count(new_nss_aaaa); nss_i++) { while((pop = ldns_resolver_pop_nameserver(res))) { ldns_rdf_deep_free(pop); } status = ldns_resolver_push_nameserver(res, ldns_rr_rdf(ldns_rr_list_rr(new_nss_aaaa, nss_i), 0)); if (status != LDNS_STATUS_OK) { fprintf(stderr, "Error adding nameserver to resolver: %s\n", ldns_get_errorstr_by_id(status)); } if (verbosity >= 1) { fprintf(stdout, "Querying nameserver: "); ldns_rdf_print(stdout, ldns_rr_owner(ldns_rr_list_rr(new_nss_aaaa, nss_i))); fprintf(stdout, " ("); ldns_rdf_print(stdout, ldns_rr_rdf(ldns_rr_list_rr(new_nss_aaaa, nss_i), 0)); fprintf(stdout, ")\n"); } status = ldns_resolver_push_nameserver(res, ldns_rr_rdf(ldns_rr_list_rr(new_nss_aaaa, nss_i), 0)); if (status != LDNS_STATUS_OK) { fprintf(stderr, "Error adding nameserver to resolver: %s\n", ldns_get_errorstr_by_id(status)); } ldns_pkt_free(p); status = ldns_resolver_send(&p, res, name, t, c, 0); if (status == LDNS_STATUS_OK && p) { if (ldns_pkt_get_rcode(p) != LDNS_RCODE_NOERROR) { printf("Error in packet:\n"); ldns_pkt_print(stdout, p); return NULL; } if (verbosity >= 4) { ldns_pkt_print(stdout, p); printf("\n\n"); } if (answer_list) { if (verbosity >= 2) { printf("Comparing answer list of answer to previous\n\n"); } ldns_rr_list_sort(ldns_pkt_answer(p)); ldns_rr_list_sort(answer_list); if (ldns_rr_list_compare(answer_list, ldns_pkt_answer(p)) != 0) { fprintf(stderr, "ERROR: different answer answer from nameserver\n"); fprintf(stderr, "\nI had (from previous servers):\n"); ldns_rr_list_print(stderr, answer_list); fprintf(stderr, "\nI received (from nameserver at "); ldns_rdf_print(stderr, ldns_resolver_nameservers(res)[0]); fprintf(stderr, "):\n"); ldns_rr_list_print(stderr, ldns_pkt_answer(p)); exit(EXIT_FAILURE); } } else { answer_list = ldns_rr_list_clone(ldns_pkt_answer(p)); ldns_rr_list_sort(answer_list); if (verbosity >= 2) { printf("First answer list for this set, nothing to compare with\n\n"); } } if (authority_list) { if (verbosity >= 2) { printf("Comparing authority list of answer to previous\n\n"); } ldns_rr_list_sort(ldns_pkt_authority(p)); ldns_rr_list_sort(authority_list); if (ldns_rr_list_compare(authority_list, ldns_pkt_authority(p)) != 0) { fprintf(stderr, "ERROR: different authority answer from nameserver\n"); fprintf(stderr, "\nI had (from previous servers):\n"); ldns_rr_list_print(stderr, authority_list); fprintf(stderr, "\nI received (from nameserver at "); ldns_rdf_print(stderr, ldns_resolver_nameservers(res)[0]); fprintf(stderr, "):\n"); ldns_rr_list_print(stderr, ldns_pkt_authority(p)); exit(EXIT_FAILURE); } } else { authority_list = ldns_rr_list_clone(ldns_pkt_authority(p)); ldns_rr_list_sort(authority_list); if (verbosity >= 2) { printf("First authority list for this set, nothing to compare with\n\n"); } if (verbosity >= 3) { printf("NS RRset:\n"); ldns_rr_list_print(stdout, authority_list); printf("\n"); } } } } ldns_rr_list_deep_free(answer_list); ldns_rr_list_deep_free(authority_list); answer_list = NULL; authority_list = NULL; for (nss_i = 0; nss_i < ldns_rr_list_rr_count(new_nss_a); nss_i++) { while((pop = ldns_resolver_pop_nameserver(res))) {ldns_rdf_deep_free(pop); } if (verbosity >= 1) { fprintf(stdout, "Querying nameserver: "); ldns_rdf_print(stdout, ldns_rr_owner(ldns_rr_list_rr(new_nss_a, nss_i))); fprintf(stdout, " ("); ldns_rdf_print(stdout, ldns_rr_rdf(ldns_rr_list_rr(new_nss_a, nss_i), 0)); fprintf(stdout, ")\n"); } status = ldns_resolver_push_nameserver(res, ldns_rr_rdf(ldns_rr_list_rr(new_nss_a, nss_i), 0)); if (status != LDNS_STATUS_OK) { fprintf(stderr, "Error adding nameserver to resolver: %s\n", ldns_get_errorstr_by_id(status)); } ldns_pkt_free(p); status = ldns_resolver_send(&p, res, name, t, c, 0); if (status == LDNS_STATUS_OK) { if (ldns_pkt_get_rcode(p) != LDNS_RCODE_NOERROR) { printf("Error in packet:\n"); ldns_pkt_print(stdout, p); return NULL; } if (verbosity >= 4) { ldns_pkt_print(stdout, p); printf("\n\n"); } if (answer_list) { if (verbosity >= 2) { printf("Comparing answer list of answer to previous\n\n"); } ldns_rr_list_sort(ldns_pkt_answer(p)); ldns_rr_list_sort(answer_list); if (ldns_rr_list_compare(answer_list, ldns_pkt_answer(p)) != 0) { fprintf(stderr, "ERROR: different answer answer from nameserver\n"); fprintf(stderr, "\nI had (from previous servers):\n"); ldns_rr_list_print(stderr, answer_list); fprintf(stderr, "\nI received (from nameserver at "); ldns_rdf_print(stderr, ldns_resolver_nameservers(res)[0]); fprintf(stderr, "):\n"); ldns_rr_list_print(stderr, ldns_pkt_answer(p)); exit(EXIT_FAILURE); } } else { if (verbosity >= 2) { printf("First answer list for this set, nothing to compare with\n\n"); } answer_list = ldns_rr_list_clone(ldns_pkt_answer(p)); ldns_rr_list_sort(answer_list); } if (authority_list) { if (verbosity >= 2) { printf("Comparing authority list of answer to previous\n\n"); } ldns_rr_list_sort(ldns_pkt_authority(p)); ldns_rr_list_sort(authority_list); if (ldns_rr_list_compare(authority_list, ldns_pkt_authority(p)) != 0) { fprintf(stderr, "ERROR: different authority answer from nameserver\n"); fprintf(stderr, "\nI had (from previous servers):\n"); ldns_rr_list_print(stderr, authority_list); fprintf(stderr, "\nI received (from nameserver at "); ldns_rdf_print(stderr, ldns_resolver_nameservers(res)[0]); fprintf(stderr, "):\n"); ldns_rr_list_print(stderr, ldns_pkt_authority(p)); exit(EXIT_FAILURE); } } else { if (verbosity >= 2) { printf("First authority list for this set, nothing to compare with\n\n"); } authority_list = ldns_rr_list_clone(ldns_pkt_authority(p)); ldns_rr_list_sort(authority_list); if (verbosity >= 3) { printf("NS RRset:\n"); ldns_rr_list_print(stdout, authority_list); printf("\n"); } } } } ldns_rr_list_deep_free(authority_list); authority_list = NULL; if (loop_count++ > 20) { /* unlikely that we are doing something usefull */ fprintf(stderr, "Looks like we are looping"); ldns_pkt_free(p); return NULL; } ldns_pkt_free(p); if (verbosity >= 3) { fprintf(stdout, "This level ok. Continuing to next.\n\n"); } status = ldns_resolver_send(&p, res, name, t, c, 0); if (status != LDNS_STATUS_OK) { fprintf(stderr, "Error querying root servers: %s\n", ldns_get_errorstr_by_id(status)); return NULL; } if (ldns_pkt_get_rcode(p) != LDNS_RCODE_NOERROR) { printf("Error in packet:\n"); ldns_pkt_print(stdout, p); return NULL; } if (verbosity >= 4) { ldns_pkt_print(stdout, p); printf("\n\n"); } ldns_rr_list_deep_free(new_nss_aaaa); ldns_rr_list_deep_free(new_nss_a); ldns_rr_list_deep_free(new_nss); new_nss_aaaa = NULL; new_nss_a = NULL; ns_addr = NULL; } ldns_rr_list_deep_free(answer_list); answer_list = NULL; /* clone the nameserver list, we are going to handle them one by one */ last_nameserver_count = 0; last_nameservers = LDNS_XMALLOC(ldns_rdf *, ldns_resolver_nameserver_count(res)); pop = NULL; while((pop = ldns_resolver_pop_nameserver(res))) { last_nameservers[last_nameserver_count] = pop; last_nameserver_count++; } for (nss_i = 0; nss_i < last_nameserver_count; nss_i++) { /* remove previous nameserver */ while((pop = ldns_resolver_pop_nameserver(res))) { ldns_rdf_deep_free(pop); } if (verbosity >= 1) { printf("Querying nameserver: "); ldns_rdf_print(stdout, last_nameservers[nss_i]); printf("\n"); } status = ldns_resolver_push_nameserver(res, last_nameservers[nss_i]); if (status != LDNS_STATUS_OK) { fprintf(stderr, "Error adding nameserver to resolver: %s\n", ldns_get_errorstr_by_id(status)); } ldns_pkt_free(p); status = ldns_resolver_send(&p, res, name, t, c, 0); if (!p) { fprintf(stderr, "no packet received\n"); return NULL; } if (status == LDNS_STATUS_RES_NO_NS) { fprintf(stderr, "Error: nameserver at "); ldns_rdf_print(stderr, last_nameservers[nss_i]); fprintf(stderr, " not responding. Unable to check RRset here, aborting.\n"); return NULL; } if (ldns_pkt_get_rcode(p) != LDNS_RCODE_NOERROR) { printf("Error in packet:\n"); ldns_pkt_print(stdout, p); return NULL; } if (answer_list) { if (verbosity >= 2) { printf("1Comparing answer rr list of answer to previous\n"); } ldns_rr_list_sort(ldns_pkt_answer(p)); ldns_rr_list_sort(answer_list); if (ldns_rr_list_compare(answer_list, ldns_pkt_answer(p)) != 0) { printf("ERROR: different answer section in response from nameserver\n"); fprintf(stderr, "\nI had:\n"); ldns_rr_list_print(stderr, answer_list); fprintf(stderr, "\nI received (from nameserver at "); ldns_rdf_print(stderr, ldns_resolver_nameservers(res)[0]); fprintf(stderr, "):\n"); ldns_rr_list_print(stderr, ldns_pkt_answer(p)); exit(EXIT_FAILURE); } } else { if (verbosity >= 2) { printf("First answer rr list for this set, nothing to compare with\n"); } answer_list = ldns_rr_list_clone(ldns_pkt_answer(p)); if (verbosity >= 3) { printf("DNSKEY RRset:\n"); ldns_rr_list_print(stdout, answer_list); } } } for (nss_i = 0; nss_i < last_nameserver_count; nss_i++) { ldns_rdf_deep_free(last_nameservers[nss_i]); } LDNS_FREE(last_nameservers); ldns_resolver_deep_free(res); ldns_pkt_free(p); return answer_list; }
int main (int argc, char **argv) { /* Local Vars */ char *out = NULL; ldns_resolver *res; ldns_rdf *domain; ldns_rdf *host; ldns_rdf *example; ldns_pkt *pkt; ldns_rr *rr; ldns_status status; /* Set signal handling and alarm */ if (signal(SIGALRM, timeout_alarm_handler) == SIG_ERR) critical("Setup SIGALRM trap failed!"); /* Process check arguments */ if (process_arguments(argc, argv) != OK) unknown("Parsing arguments failed!"); /* Start plugin timeout */ alarm(mp_timeout); // Create DNAME from domainname domain = ldns_dname_new_frm_str(domainname); if (!domain) usage("Invalid domainname '%s'", domainname); // Create rdf from hostaddr host = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_A, hostname); #ifdef USE_IPV6 if (!host) host = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_AAAA, hostname); #endif if (!host) { ldns_rdf_deep_free(domain); usage("Invalid hostname '%s'", hostname); } // Create DNAME from example.com example = ldns_dname_new_frm_str("exmple.com"); if (!example) usage("Invalid domainname 'example.com'"); // Create resolver res = ldns_resolver_new(); if (!res) { ldns_rdf_deep_free(domain); ldns_rdf_deep_free(host); unknown("Create resolver failed."); } // Add ns to resolver status = ldns_resolver_push_nameserver(res, host); if (status != LDNS_STATUS_OK) { ldns_rdf_deep_free(domain); ldns_rdf_deep_free(host); ldns_resolver_deep_free(res); unknown("Adding %s as NS fails.", domainname); } if (udp) { // Disable TCP ldns_resolver_set_usevc(res, 0); // Fetch SOA pkt = mp_ldns_resolver_query(res, domain, LDNS_RR_TYPE_SOA, LDNS_RR_CLASS_IN, 0); if (pkt == NULL || ldns_pkt_get_rcode(pkt) != LDNS_RCODE_NOERROR) { mp_strcat_comma(&out, "No UDP Answer"); } else if (ldns_pkt_aa(pkt) == 0) { mp_strcat_comma(&out, "Non Authoritative UDP Answer"); } if (mp_verbose > 2) { printf("[ SOA Answer ]----------\n"); ldns_pkt_print(stdout,pkt); } ldns_pkt_free(pkt); if (recursion) { // Fetch example.com SOA ldns_resolver_set_recursive(res, TRUE); pkt = mp_ldns_resolver_query(res, example, LDNS_RR_TYPE_SOA, LDNS_RR_CLASS_IN, LDNS_RD); ldns_resolver_set_recursive(res, FALSE); if (pkt && (ldns_pkt_get_rcode(pkt) != LDNS_RCODE_REFUSED && ldns_pkt_get_rcode(pkt) != LDNS_RCODE_SERVFAIL)) { mp_strcat_comma(&out, "Recursive UDP Answer"); } if (mp_verbose > 2) { printf("[ SOA Answer ]----------\n"); ldns_pkt_print(stdout,pkt); } ldns_pkt_free(pkt); } } if (tcp) { // Enable TCP ldns_resolver_set_usevc(res, 1); // Fetch SOA pkt = mp_ldns_resolver_query(res, domain, LDNS_RR_TYPE_SOA, LDNS_RR_CLASS_IN, 0); if (pkt == NULL || ldns_pkt_get_rcode(pkt) != LDNS_RCODE_NOERROR) { mp_strcat_comma(&out, "No TCP Answer"); } else if (ldns_pkt_aa(pkt) == 0) { mp_strcat_comma(&out, "Non Authoritative TCP Answer"); } if (mp_verbose > 2) { printf("[ SOA Answer ]----------\n"); ldns_pkt_print(stdout,pkt); } ldns_pkt_free(pkt); if (recursion) { // Fetch example.com SOA ldns_resolver_set_recursive(res, TRUE); pkt = mp_ldns_resolver_query(res, example, LDNS_RR_TYPE_SOA, LDNS_RR_CLASS_IN, LDNS_RD); ldns_resolver_set_recursive(res, FALSE); if (pkt && (ldns_pkt_get_rcode(pkt) != LDNS_RCODE_REFUSED && ldns_pkt_get_rcode(pkt) != LDNS_RCODE_SERVFAIL)) { mp_strcat_comma(&out, "Recursive TCP Answer"); } if (mp_verbose > 2) { printf("[ SOA Answer ]----------\n"); ldns_pkt_print(stdout,pkt); } ldns_pkt_free(pkt); } } if (axfr) { status = ldns_axfr_start(res, domain, LDNS_RR_CLASS_IN); if (status == LDNS_STATUS_OK) { rr = NULL; rr = ldns_axfr_next(res); if (rr) { mp_strcat_comma(&out, "AXFR allowed."); } } } if (out) critical("Authoritative DNS for %s: %s", domainname, out); ok("Authoritative DNS for %s", domainname); }
ldns_status ldns_verify_denial(ldns_pkt *pkt, ldns_rdf *name, ldns_rr_type type, ldns_rr_list **nsec_rrs, ldns_rr_list **nsec_rr_sigs) { uint16_t nsec_i; ldns_rr_list *nsecs; ldns_status result; if (verbosity >= 5) { printf("VERIFY DENIAL FROM:\n"); ldns_pkt_print(stdout, pkt); } result = LDNS_STATUS_CRYPTO_NO_RRSIG; /* Try to see if there are NSECS in the packet */ nsecs = ldns_pkt_rr_list_by_type(pkt, LDNS_RR_TYPE_NSEC, LDNS_SECTION_ANY_NOQUESTION); if (nsecs) { for (nsec_i = 0; nsec_i < ldns_rr_list_rr_count(nsecs); nsec_i++) { /* there are four options: * - name equals ownername and is covered by the type bitmap * - name equals ownername but is not covered by the type bitmap * - name falls within nsec coverage but is not equal to the owner name * - name falls outside of nsec coverage */ if (ldns_dname_compare(ldns_rr_owner(ldns_rr_list_rr(nsecs, nsec_i)), name) == 0) { /* printf("CHECKING NSEC:\n"); ldns_rr_print(stdout, ldns_rr_list_rr(nsecs, nsec_i)); printf("DAWASEM\n"); */ if (ldns_nsec_bitmap_covers_type( ldns_nsec_get_bitmap(ldns_rr_list_rr(nsecs, nsec_i)), type)) { /* Error, according to the nsec this rrset is signed */ result = LDNS_STATUS_CRYPTO_NO_RRSIG; } else { /* ok nsec denies existence */ if (verbosity >= 3) { printf(";; Existence of data set with this type denied by NSEC\n"); } /*printf(";; Verifiably insecure.\n");*/ if (nsec_rrs && nsec_rr_sigs) { (void) get_dnssec_rr(pkt, ldns_rr_owner(ldns_rr_list_rr(nsecs, nsec_i)), LDNS_RR_TYPE_NSEC, nsec_rrs, nsec_rr_sigs); } ldns_rr_list_deep_free(nsecs); return LDNS_STATUS_OK; } } else if (ldns_nsec_covers_name(ldns_rr_list_rr(nsecs, nsec_i), name)) { if (verbosity >= 3) { printf(";; Existence of data set with this name denied by NSEC\n"); } if (nsec_rrs && nsec_rr_sigs) { (void) get_dnssec_rr(pkt, ldns_rr_owner(ldns_rr_list_rr(nsecs, nsec_i)), LDNS_RR_TYPE_NSEC, nsec_rrs, nsec_rr_sigs); } ldns_rr_list_deep_free(nsecs); return LDNS_STATUS_OK; } else { /* nsec has nothing to do with this data */ } } ldns_rr_list_deep_free(nsecs); } else if( (nsecs = ldns_pkt_rr_list_by_type(pkt, LDNS_RR_TYPE_NSEC3, LDNS_SECTION_ANY_NOQUESTION)) ) { ldns_rr_list* sigs = ldns_pkt_rr_list_by_type(pkt, LDNS_RR_TYPE_RRSIG, LDNS_SECTION_ANY_NOQUESTION); ldns_rr* q = ldns_rr_new(); if(!sigs) return LDNS_STATUS_MEM_ERR; if(!q) return LDNS_STATUS_MEM_ERR; ldns_rr_set_question(q, 1); ldns_rr_set_ttl(q, 0); ldns_rr_set_owner(q, ldns_rdf_clone(name)); if(!ldns_rr_owner(q)) return LDNS_STATUS_MEM_ERR; ldns_rr_set_type(q, type); result = ldns_dnssec_verify_denial_nsec3(q, nsecs, sigs, ldns_pkt_get_rcode(pkt), type, ldns_pkt_ancount(pkt) == 0); ldns_rr_free(q); ldns_rr_list_deep_free(nsecs); ldns_rr_list_deep_free(sigs); } return result; }
ldns_rr_list* getaddr_rdf(ldns_resolver *res, ldns_rdf *hostrdf) { ldns_rdf *rdf; ldns_resolver *r = NULL; ldns_rr_list *rrl; ldns_rr_list *ret = NULL; ldns_pkt *pkt; ldns_status status; if (ldns_rdf_get_type(hostrdf) == LDNS_RDF_TYPE_A #ifdef USE_IPV6 || ldns_rdf_get_type(hostrdf) == LDNS_RDF_TYPE_AAAA #endif ) { rdf = ldns_rdf_address_reverse(hostrdf); r = res; if (res == NULL) { status = ldns_resolver_new_frm_file(&r, NULL); if (status != LDNS_STATUS_OK) return NULL; } // Fetch PTR pkt = ldns_resolver_query(r, rdf, LDNS_RR_TYPE_PTR, LDNS_RR_CLASS_IN, LDNS_RD); if (pkt == NULL || ldns_pkt_get_rcode(pkt) != LDNS_RCODE_NOERROR) return NULL; rrl = ldns_pkt_rr_list_by_name_and_type(pkt, rdf, LDNS_RR_TYPE_PTR, LDNS_SECTION_ANSWER); if (ldns_rr_list_rr_count(rrl) != 1) return NULL; ldns_rdf_deep_free(rdf); rdf = ldns_rdf_clone(ldns_rr_rdf(ldns_rr_list_rr(rrl,0),0)); ldns_pkt_free(pkt); ldns_rr_list_deep_free(rrl); } else if (ldns_rdf_get_type(hostrdf) == LDNS_RDF_TYPE_DNAME) { rdf = hostrdf; } else { return NULL; } if (r == NULL) { r = res; if (res == NULL) { status = ldns_resolver_new_frm_file(&r, NULL); if (status != LDNS_STATUS_OK) return NULL; } } #ifdef USE_IPV6 if (ldns_rdf_get_type(hostrdf) != LDNS_RDF_TYPE_A) { // Fetch AAAA pkt = ldns_resolver_query(r, rdf, LDNS_RR_TYPE_AAAA, LDNS_RR_CLASS_IN, LDNS_RD); if (pkt != NULL && ldns_pkt_get_rcode(pkt) == LDNS_RCODE_NOERROR) { rrl = ldns_pkt_rr_list_by_name_and_type(pkt, rdf, LDNS_RR_TYPE_AAAA, LDNS_SECTION_ANSWER); ldns_pkt_free(pkt); if (ldns_rr_list_rr_count(rrl) > 0) { ret = rrl; rrl = NULL; } else { ldns_rr_list_free(rrl); } } } if (ldns_rdf_get_type(hostrdf) != LDNS_RDF_TYPE_AAAA) { #else if (1) { #endif /* USE_IPV6 */ // Fetch AA pkt = ldns_resolver_query(r, rdf, LDNS_RR_TYPE_A, LDNS_RR_CLASS_IN, LDNS_RD); if (pkt != NULL && ldns_pkt_get_rcode(pkt) == LDNS_RCODE_NOERROR) { rrl = ldns_pkt_rr_list_by_name_and_type(pkt, rdf, LDNS_RR_TYPE_A, LDNS_SECTION_ANSWER); ldns_pkt_free(pkt); if (ldns_rr_list_rr_count(rrl) > 0) { if (ret == NULL) { ret = rrl; } else { ldns_rr_list_cat(ret, rrl); ldns_rr_list_free(rrl); } } else { ldns_rr_list_free(rrl); } } // if (pkt != NULL && ldns_pkt_ge... } if (res == NULL) ldns_resolver_deep_free(r); return ret; } ldns_rr_list* getaddr(ldns_resolver *res, const char *hostname) { ldns_rdf *rdf; /* Check if hostname is a ip */ rdf = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_A, hostname); #ifdef USE_IPV6 if (!rdf) { rdf = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_AAAA, hostname); } #endif if (!rdf) { rdf = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, hostname); } if (!rdf) return NULL; return getaddr_rdf(res, rdf); }
void massdns_handle_packet(ldns_pkt *packet, struct sockaddr_storage ns, void *ctx) { if (!packet || ldns_pkt_qdcount(packet) != 1) { return; } struct timeval now; gettimeofday(&now, NULL); lookup_context_t *context = (lookup_context_t *) ctx; ldns_pkt_rcode response_code = ldns_pkt_get_rcode(packet); ldns_rr_list l = ldns_pkt_question(packet)[0]; ldns_rr *question = ldns_rr_list_rr(&l, 0); ldns_rdf* owner = ldns_rr_owner(question); char* name = ldns_rdf2str(owner); size_t name_len = strlen(name); if(name_len > 0 && name[name_len - 1] == '.') { name[name_len - 1] = 0; } lookup_t *lookup = hashmapGet(context->map, name); free(name); if (lookup == NULL) { return; } if (response_code == LDNS_RCODE_NOERROR || response_code == LDNS_RCODE_NXDOMAIN || lookup->tries == context->cmd_args.resolve_count) { switch (response_code) { case LDNS_RCODE_NOERROR: stats.noerr++; break; case LDNS_RCODE_FORMERR: stats.formerr++; break; case LDNS_RCODE_SERVFAIL: stats.servfail++; break; case LDNS_RCODE_NXDOMAIN: stats.nxdomain++; break; case LDNS_RCODE_NOTIMPL: stats.notimp++; break; case LDNS_RCODE_REFUSED: stats.refused++; break; default: stats.other++; break; } context->current_rate++; ldns_buffer *buf = ldns_buffer_new(LDNS_MAX_PACKETLEN); if(buf == NULL) { abort(); } if(LDNS_STATUS_OK != output_packet(buf, packet, ns, context)) { abort(); } char* packetstr = ldns_buffer_export2str(buf); if(packetstr == NULL) { abort(); } fprintf(stdout, "%s", packetstr); free(packetstr); if (timediff(&now, &context->next_update) <= 0) { print_stats(context); } ldns_buffer_free(buf); hashmapRemove(context->map, lookup->domain); free(lookup->domain); free(lookup); } }
int cache_dns_objects(packetinfo *pi, ldns_rdf *rdf_data, ldns_buffer *buff, ldns_pkt *dns_pkt) { int j; int dns_answer_domain_cnt; uint64_t dnshash; ldns_status status; pdns_record *pr = NULL; ldns_rr_list *dns_answer_domains; unsigned char *domain_name = 0; ldns_buffer_clear(buff); status = ldns_rdf2buffer_str(buff, rdf_data); if (status != LDNS_STATUS_OK) { dlog("[D] Error in ldns_rdf2buffer_str(): %d\n", status); return -1; } dns_answer_domains = ldns_pkt_answer(dns_pkt); dns_answer_domain_cnt = ldns_rr_list_rr_count(dns_answer_domains); domain_name = (unsigned char *) ldns_buffer2str(buff); if (domain_name == NULL) { dlog("[D] Error in ldns_buffer2str(%p)\n", buff); return -1; } else { dlog("[D] domain_name: %s\n", domain_name); dlog("[D] dns_answer_domain_cnt: %d\n",dns_answer_domain_cnt); } if (dns_answer_domain_cnt == 0 && ldns_pkt_get_rcode(dns_pkt) != 0) { uint16_t rcode = ldns_pkt_get_rcode(dns_pkt); dlog("[D] Error return code: %d\n", rcode); /* PROBLEM: * As there is no valid ldns_rr here and we can't fake one that will * be very unique, we cant push this to the normal * bucket[hash->linked_list]. We should probably allocate a static * bucket[MAX_NXDOMAIN] to hold NXDOMAINS, and when that is full, pop * out the oldest (LRU). A simple script querying for random non-existing * domains could easily put stress on passivedns (think conficker etc.) * if the bucket is to big or non-efficient. We would still store data * such as: firstseen,lastseen,client_ip,server_ip,class,query,NXDOMAIN */ if (config.dnsfe & (pdns_chk_dnsfe(rcode))) { ldns_rr_list *dns_query_domains; ldns_rr *rr; dnshash = hash(domain_name); dlog("[D] Hash: %lu\n", dnshash); /* Check if the node exists, if not, make it */ pr = get_pdns_record(dnshash, pi, domain_name); /* Set the SRC flag: */ //lname_node->srcflag |= pdns_chk_dnsfe(rcode); dns_query_domains = ldns_pkt_question(dns_pkt); rr = ldns_rr_list_rr(dns_query_domains, 0); if ((pr->last_seen.tv_sec - pr->last_print.tv_sec) >= config.dnsprinttime) { /* Print the SRC Error record */ print_passet(pr, NULL, rr, rdf_data, rcode); } } else { dlog("[D] Error return code %d was not processed:%d\n", pdns_chk_dnsfe(rcode), config.dnsfe); } free(domain_name); return 0; } for (j = 0; j < dns_answer_domain_cnt; j++) { int offset = -1; ldns_rr *rr; ldns_rdf *rname; unsigned char *rdomain_name = 0; rr = ldns_rr_list_rr(dns_answer_domains, j); switch (ldns_rr_get_type(rr)) { case LDNS_RR_TYPE_AAAA: if (config.dnsf & DNS_CHK_AAAA) offset = 0; break; case LDNS_RR_TYPE_A: if (config.dnsf & DNS_CHK_A) offset = 0; break; case LDNS_RR_TYPE_PTR: if (config.dnsf & DNS_CHK_PTR) offset = 0; break; case LDNS_RR_TYPE_CNAME: if (config.dnsf & DNS_CHK_CNAME) offset = 0; break; case LDNS_RR_TYPE_DNAME: if (config.dnsf & DNS_CHK_DNAME) offset = 0; break; case LDNS_RR_TYPE_NAPTR: if (config.dnsf & DNS_CHK_NAPTR) offset = 0; break; case LDNS_RR_TYPE_RP: if (config.dnsf & DNS_CHK_RP) offset = 0; break; case LDNS_RR_TYPE_SRV: if (config.dnsf & DNS_CHK_SRV) offset = 3; break; case LDNS_RR_TYPE_TXT: if (config.dnsf & DNS_CHK_TXT) offset = 0; break; case LDNS_RR_TYPE_SOA: if (config.dnsf & DNS_CHK_SOA) offset = 0; break; case LDNS_RR_TYPE_MX: if (config.dnsf & DNS_CHK_MX) offset = 1; break; case LDNS_RR_TYPE_NS: if (config.dnsf & DNS_CHK_NS) offset = 0; break; default: offset = -1; dlog("[D] ldns_rr_get_type: %d\n", ldns_rr_get_type(rr)); break; } if (offset == -1) { dlog("[D] LDNS_RR_TYPE not enabled/supported: %d\n", ldns_rr_get_type(rr)); //data_offset = 0; continue; } /* Get the rdf data from the rr */ rname = ldns_rr_rdf(rr, offset); if (rname == NULL) { dlog("[D] ldns_rr_rdf returned: NULL\n"); continue; } ldns_buffer_clear(buff); ldns_rdf2buffer_str(buff, rname); rdomain_name = (unsigned char *) ldns_buffer2str(buff); if (rdomain_name == NULL) { dlog("[D] ldns_buffer2str returned: NULL\n"); continue; } dlog("[D] rdomain_name: %s\n", rdomain_name); if (pr == NULL) { dnshash = hash(domain_name); dlog("[D] Hash: %lu\n", dnshash); /* Check if the node exists, if not, make it */ pr = get_pdns_record(dnshash, pi, domain_name); } /* Update the pdns record with the pdns asset */ update_pdns_record_asset(pi, pr, rr, rdomain_name); /* If CNAME, free domain_name, and cp rdomain_name to domain_name */ if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_CNAME) { if (config.dnsf & DNS_CHK_CNAME) { int len; free(domain_name); len = strlen((char *)rdomain_name); domain_name = calloc(1, (len + 1)); strncpy((char *)domain_name, (char *)rdomain_name, len); dnshash = hash(domain_name); dlog("[D] Hash: %lu\n", dnshash); pr = get_pdns_record(dnshash, pi, domain_name); } } /* Free the rdomain_name */ free(rdomain_name); } free(domain_name); return 0; }
int output_cbor(iaddr from, iaddr to, uint8_t proto, unsigned flags, unsigned sport, unsigned dport, my_bpftimeval ts, const u_char *payload, size_t payloadlen) { ldns_pkt *pkt = 0; ldns_status ldns_rc; if (!payload) { return DUMP_CBOR_EINVAL; } if (!payloadlen) { return DUMP_CBOR_EINVAL; } /* if (!cbor_stringrefs) {*/ /* cbor_stringrefs = calloc(1, cbor_stringref_size);*/ /* }*/ if (!cbor_buf) { if (!(cbor_buf = calloc(1, cbor_size + cbor_reserve))) { return DUMP_CBOR_ENOMEM; } } if (cbor_flushed) { CborError cbor_err; cbor_encoder_init(&cbor_root, cbor_buf, cbor_size, 0); /* cbor_err = cbor_encode_tag(&cbor_root, 256);*/ /* if (cbor_err == CborNoError)*/ cbor_err = cbor_encoder_create_array(&cbor_root, &cbor_pkts, CborIndefiniteLength); if (cbor_err != CborNoError) { fprintf(stderr, "cbor init error[%d]: %s\n", cbor_err, cbor_error_string(cbor_err)); return DUMP_CBOR_ECBOR; } cbor_flushed = 0; } ldns_rc = ldns_wire2pkt(&pkt, payload, payloadlen); if (ldns_rc != LDNS_STATUS_OK) { fprintf(stderr, "ldns error [%d]: %s\n", ldns_rc, ldns_get_errorstr_by_id(ldns_rc)); return DUMP_CBOR_ELDNS; } if (!pkt) { return DUMP_CBOR_ELDNS; } CborEncoder cbor, ip; CborError cbor_err = CborNoError; int should_flush = 0; cbor_err = append_cbor_map(&cbor_pkts, &cbor, CborIndefiniteLength, &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "dateSeconds", &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_double(&cbor, (double)ts.tv_sec + ( (double)ts.tv_usec / 1000000 ), &should_flush); /* if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "dateNanoFractions", &should_flush);*/ /* if (cbor_err == CborNoError) cbor_err = append_cbor_uint(&cbor, ts.tv_usec * 1000, &should_flush);*/ if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "ip", &should_flush); /* if (cbor_err == CborNoError) cbor_err = append_cbor_uint(&cbor, proto, &should_flush);*/ /* if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "sourceIpAddress", &should_flush);*/ /* if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, ia_str(from), &should_flush);*/ /* if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "sourcePort", &should_flush);*/ /* if (cbor_err == CborNoError) cbor_err = append_cbor_uint(&cbor, sport, &should_flush);*/ /* if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "destinationIpAddress", &should_flush);*/ /* if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, ia_str(to), &should_flush);*/ /* if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "destinationPort", &should_flush);*/ /* if (cbor_err == CborNoError) cbor_err = append_cbor_uint(&cbor, dport, &should_flush);*/ if (cbor_err == CborNoError) cbor_err = append_cbor_array(&cbor, &ip, CborIndefiniteLength, &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_uint(&ip, proto, &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&ip, ia_str(from), &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_uint(&ip, sport, &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&ip, ia_str(to), &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_uint(&ip, dport, &should_flush); if (cbor_err == CborNoError) cbor_err = close_cbor_container(&cbor, &ip, &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "ID", &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_uint(&cbor, ldns_pkt_id(pkt), &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "QR", &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_boolean(&cbor, ldns_pkt_qr(pkt), &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "Opcode", &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_uint(&cbor, ldns_pkt_get_opcode(pkt), &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "AA", &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_boolean(&cbor, ldns_pkt_aa(pkt), &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "TC", &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_boolean(&cbor, ldns_pkt_tc(pkt), &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "RD", &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_boolean(&cbor, ldns_pkt_rd(pkt), &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "RA", &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_boolean(&cbor, ldns_pkt_ra(pkt), &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "AD", &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_boolean(&cbor, ldns_pkt_ad(pkt), &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "CD", &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_boolean(&cbor, ldns_pkt_cd(pkt), &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "RCODE", &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_uint(&cbor, ldns_pkt_get_rcode(pkt), &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "QDCOUNT", &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_uint(&cbor, ldns_pkt_qdcount(pkt), &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "ANCOUNT", &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_uint(&cbor, ldns_pkt_ancount(pkt), &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "NSCOUNT", &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_uint(&cbor, ldns_pkt_nscount(pkt), &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "ARCOUNT", &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_uint(&cbor, ldns_pkt_arcount(pkt), &should_flush); /* questionRRs */ if (ldns_pkt_qdcount(pkt) > 0) { ldns_rr_list *list = ldns_pkt_question(pkt); ldns_rr *rr; size_t n, qdcount = ldns_pkt_qdcount(pkt); ldns_buffer *dname; char *dname_str; if (!list) { ldns_pkt_free(pkt); return DUMP_CBOR_ELDNS; } rr = ldns_rr_list_rr(list, 0); if (!rr) { ldns_pkt_free(pkt); return DUMP_CBOR_ELDNS; } if (!(dname = ldns_buffer_new(512))) { ldns_pkt_free(pkt); return DUMP_CBOR_ENOMEM; } if (ldns_rdf2buffer_str_dname(dname, ldns_rr_owner(rr)) != LDNS_STATUS_OK) { ldns_buffer_free(dname); ldns_pkt_free(pkt); return DUMP_CBOR_ELDNS; } ldns_buffer_write_u8(dname, 0); if (!(dname_str = ldns_buffer_export(dname))) { ldns_buffer_free(dname); ldns_pkt_free(pkt); return DUMP_CBOR_ENOMEM; } if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "QNAME", &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, dname_str, &should_flush); free(dname_str); ldns_buffer_free(dname); if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "QCLASS", &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_uint(&cbor, ldns_rr_get_class(rr), &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "QTYPE", &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_uint(&cbor, ldns_rr_get_type(rr), &should_flush); if (qdcount > 1) { CborEncoder queries; if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "questionRRs", &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_array(&cbor, &queries, CborIndefiniteLength, &should_flush); for (n = 1; cbor_err == CborNoError && n < qdcount; n++) { CborEncoder query; rr = ldns_rr_list_rr(list, n); if (!rr) { ldns_pkt_free(pkt); return DUMP_CBOR_ELDNS; } if (!(dname = ldns_buffer_new(512))) { ldns_pkt_free(pkt); return DUMP_CBOR_ENOMEM; } if (ldns_rdf2buffer_str_dname(dname, ldns_rr_owner(rr)) != LDNS_STATUS_OK) { ldns_buffer_free(dname); ldns_pkt_free(pkt); return DUMP_CBOR_ELDNS; } ldns_buffer_write_u8(dname, 0); if (!(dname_str = ldns_buffer_export(dname))) { ldns_buffer_free(dname); ldns_pkt_free(pkt); return DUMP_CBOR_ENOMEM; } if (cbor_err == CborNoError) cbor_err = append_cbor_map(&queries, &query, CborIndefiniteLength, &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&query, "NAME", &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&query, dname_str, &should_flush); free(dname_str); ldns_buffer_free(dname); if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&query, "CLASS", &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_uint(&query, ldns_rr_get_class(rr), &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&query, "TYPE", &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_uint(&query, ldns_rr_get_type(rr), &should_flush); if (cbor_err == CborNoError) cbor_err = close_cbor_container(&queries, &query, &should_flush); } if (cbor_err == CborNoError) cbor_err = close_cbor_container(&cbor, &queries, &should_flush); } } /* answerRRs */ if (ldns_pkt_ancount(pkt) > 0) { CborEncoder cbor_rrs; if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "answerRRs", &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_array(&cbor, &cbor_rrs, CborIndefiniteLength, &should_flush); cbor_ldns_rr_list(&cbor_rrs, ldns_pkt_answer(pkt), ldns_pkt_ancount(pkt), &should_flush); if (cbor_err == CborNoError) cbor_err = close_cbor_container(&cbor, &cbor_rrs, &should_flush); } /* authorityRRs */ if (ldns_pkt_nscount(pkt) > 0) { CborEncoder cbor_rrs; if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "authorityRRs", &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_array(&cbor, &cbor_rrs, CborIndefiniteLength, &should_flush); cbor_ldns_rr_list(&cbor_rrs, ldns_pkt_authority(pkt), ldns_pkt_nscount(pkt), &should_flush); if (cbor_err == CborNoError) cbor_err = close_cbor_container(&cbor, &cbor_rrs, &should_flush); } /* additionalRRs */ if (ldns_pkt_arcount(pkt) > 0) { CborEncoder cbor_rrs; if (cbor_err == CborNoError) cbor_err = append_cbor_text_stringz(&cbor, "additionalRRs", &should_flush); if (cbor_err == CborNoError) cbor_err = append_cbor_array(&cbor, &cbor_rrs, CborIndefiniteLength, &should_flush); cbor_ldns_rr_list(&cbor_rrs, ldns_pkt_additional(pkt), ldns_pkt_arcount(pkt), &should_flush); if (cbor_err == CborNoError) cbor_err = close_cbor_container(&cbor, &cbor_rrs, &should_flush); } ldns_pkt_free(pkt); if (cbor_err == CborNoError) cbor_err = close_cbor_container(&cbor_pkts, &cbor, &should_flush); if (cbor_err != CborNoError) { fprintf(stderr, "cbor error[%d]: %s\n", cbor_err, cbor_error_string(cbor_err)); return DUMP_CBOR_ECBOR; } if (should_flush) { if ((cbor_err = cbor_encoder_close_container_checked(&cbor_root, &cbor_pkts)) != CborNoError) { fprintf(stderr, "cbor error[%d]: %s\n", cbor_err, cbor_error_string(cbor_err)); return DUMP_CBOR_ECBOR; } fprintf(stderr, "cbor output: %lu bytes\n", cbor_encoder_get_buffer_size(&cbor_root, cbor_buf)); cbor_flushed = 1; return DUMP_CBOR_FLUSH; } return DUMP_CBOR_OK; }