Exemplo n.º 1
0
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);
		}
		
	}
	
}
Exemplo n.º 2
0
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;
}
Exemplo n.º 3
0
/** 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;
}
Exemplo n.º 5
0
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);
    
}
Exemplo n.º 6
0
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");
    }
}
Exemplo n.º 7
0
/*
 * 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);
}
Exemplo n.º 8
0
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 {
Exemplo n.º 9
0
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;
}
Exemplo n.º 11
0
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;
}
Exemplo n.º 12
0
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);
}
Exemplo n.º 13
0
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;
}
Exemplo n.º 14
0
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);
}
Exemplo n.º 15
0
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);
    }
}
Exemplo n.º 16
0
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;
}
Exemplo n.º 17
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;
}