static DCPluginSyncFilterResult
empty_aaa_sync_pre(DCPlugin *dcplugin, DCPluginDNSPacket *dcp_packet)
{
    ldns_pkt                 *packet;
    ldns_rr_list             *questions;
    uint8_t                  *wire_data;
    DCPluginSyncFilterResult  result = DCP_SYNC_FILTER_RESULT_OK;

    wire_data = dcplugin_get_wire_data(dcp_packet);
    ldns_wire2pkt(&packet, wire_data, dcplugin_get_wire_data_len(dcp_packet));
    if (packet == NULL) {
        return DCP_SYNC_FILTER_RESULT_ERROR;
    }
    questions = ldns_pkt_question(packet);
    if (ldns_rr_list_rr_count(questions) == (size_t) 1U &&
        ldns_rr_get_type(ldns_rr_list_rr(questions,
                                         (size_t) 0U)) == LDNS_RR_TYPE_AAAA) {
        LDNS_QR_SET(wire_data);
        LDNS_RA_SET(wire_data);
        result = DCP_SYNC_FILTER_RESULT_DIRECT;
    }
    ldns_pkt_free(packet);

    return result;
}
Beispiel #2
0
int process_dns_answer(packetinfo *pi, ldns_pkt *dns_pkt) {
    int            rrcount_query;
    int            j;
    ldns_rr_list  *dns_query_domains;
    ldns_buffer   *dns_buff;

    dns_query_domains = ldns_pkt_question(dns_pkt);
    rrcount_query     = ldns_rr_list_rr_count(dns_query_domains);
    dns_buff = ldns_buffer_new(LDNS_MIN_BUFLEN);
    dlog("[*] rrcount_query: %d\n", rrcount_query);
    
    // Do we ever have more than one Question?
    // If we do - are we handling it correct ?
    for (j = 0; j < rrcount_query; j++) {
        ldns_rdf *rdf_data;

        rdf_data = ldns_rr_owner(ldns_rr_list_rr(dns_query_domains, j));
        dlog("[D] rdf_data: %p\n", rdf_data);

        if ( cache_dns_objects(pi, rdf_data, dns_buff, dns_pkt) != 0 ) {
            dlog("[D] cache_dns_objects() returned error\n");
        }
    }

    ldns_buffer_free(dns_buff);
    update_dns_stats(pi,SUCCESS);
    return(0);
}
static DCPluginSyncFilterResult
apply_block_domains(DCPluginDNSPacket *dcp_packet, Blocking * const blocking,
                    ldns_pkt * const packet)
{
    StrList  *scanned;
    ldns_rr  *question;
    char     *owner_str;
    size_t    owner_str_len;

    scanned = blocking->domains;
    question = ldns_rr_list_rr(ldns_pkt_question(packet), 0U);
    if ((owner_str = ldns_rdf2str(ldns_rr_owner(question))) == NULL) {
        return DCP_SYNC_FILTER_RESULT_FATAL;
    }
    owner_str_len = strlen(owner_str);
    if (owner_str_len > (size_t) 1U && owner_str[--owner_str_len] == '.') {
        owner_str[owner_str_len] = 0;
    }
    do {
        if (wildcard_match(owner_str, scanned->str)) {
            LDNS_RCODE_SET(dcplugin_get_wire_data(dcp_packet),
                           LDNS_RCODE_REFUSED);
            break;
        }
    } while ((scanned = scanned->next) != NULL);
    free(owner_str);

    return DCP_SYNC_FILTER_RESULT_OK;
}
/** 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;
}
Beispiel #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);
    
}
Beispiel #6
0
void
adjust_packet(struct entry* match, ldns_pkt* answer_pkt, ldns_pkt* query_pkt)
{
	/* copy & adjust packet */
	if(match->copy_id)
		ldns_pkt_set_id(answer_pkt, ldns_pkt_id(query_pkt));
	if(match->copy_query) {
		ldns_rr_list* list = ldns_pkt_get_section_clone(query_pkt,
			LDNS_SECTION_QUESTION);
		ldns_rr_list_deep_free(ldns_pkt_question(answer_pkt));
		ldns_pkt_set_question(answer_pkt, list);
	}
	if(match->sleeptime > 0) {
		verbose(3, "sleeping for %d seconds\n", match->sleeptime);
#ifdef HAVE_SLEEP
		sleep(match->sleeptime);
#else
		Sleep(match->sleeptime * 1000);
#endif
	}
}
Beispiel #7
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");
    }
}
Beispiel #8
0
int
main(int argc, char **argv)
{
	/* arguments */
	int port;
	const char *zone_file;

	/* network */
	int sock;
	ssize_t nb;
	struct sockaddr addr_me;
	struct sockaddr addr_him;
	socklen_t hislen = (socklen_t) sizeof(addr_him);
	uint8_t inbuf[INBUF_SIZE];
	uint8_t *outbuf;

	/* dns */
	ldns_status status;
	ldns_pkt *query_pkt;
	ldns_pkt *answer_pkt;
	size_t answer_size;
	ldns_rr *query_rr;
	ldns_rr_list *answer_qr;
	ldns_rr_list *answer_an;
	ldns_rr_list *answer_ns;
	ldns_rr_list *answer_ad;
	ldns_rdf *origin = NULL;
	
	/* zone */
	ldns_zone *zone;
	int line_nr;
	FILE *zone_fp;
	
	/* use this to listen on specified interfaces later? */
	char *my_address = NULL;
		
	if (argc < 5) {
		usage(stderr);
		exit(EXIT_FAILURE);
	} else {
	    my_address = argv[1];
		port = atoi(argv[2]);
		if (port < 1) {
			usage(stderr);
			exit(EXIT_FAILURE);
		}
		if (ldns_str2rdf_dname(&origin, argv[3]) != LDNS_STATUS_OK) {
			fprintf(stderr, "Bad origin, not a correct domain name\n");
			usage(stderr);
			exit(EXIT_FAILURE);
		}
		zone_file = argv[4];
	}
	
	printf("Reading zone file %s\n", zone_file);
	zone_fp = fopen(zone_file, "r");
	if (!zone_fp) {
		fprintf(stderr, "Unable to open %s: %s\n", zone_file, strerror(errno));
		exit(EXIT_FAILURE);
	}
	
	line_nr = 0;
	status = ldns_zone_new_frm_fp_l(&zone, zone_fp, origin, 0, LDNS_RR_CLASS_IN, &line_nr);

	if (status != LDNS_STATUS_OK) {
		printf("Zone reader failed, aborting\n");
		exit(EXIT_FAILURE);
	} else {
		printf("Read %u resource records in zone file\n", (unsigned int) ldns_zone_rr_count(zone));
	}
	fclose(zone_fp);

	printf("Listening on port %d\n", port);
	sock =  socket(AF_INET, SOCK_DGRAM, 0);
	if (sock < 0) {
		fprintf(stderr, "%s: socket(): %s\n", argv[0], strerror(errno));
		exit(1);
	}
	memset(&addr_me, 0, sizeof(addr_me));

	/* bind: try all ports in that range */
	if (udp_bind(sock, port, my_address)) {
		fprintf(stderr, "%s: cannot bind(): %s\n", argv[0], strerror(errno));
		exit(errno);
	}

	/* Done. Now receive */
	while (1) {
		nb = recvfrom(sock, (void*)inbuf, INBUF_SIZE, 0, 
			&addr_him, &hislen);
		if (nb < 1) {
			fprintf(stderr, "%s: recvfrom(): %s\n",
			argv[0], strerror(errno));
			exit(1);
		}

		/*
		show(inbuf, nb, nn, hp, sp, ip, bp);
		*/
		printf("Got query of %u bytes\n", (unsigned int) nb);
		status = ldns_wire2pkt(&query_pkt, inbuf, (size_t) nb);
		if (status != LDNS_STATUS_OK) {
			printf("Got bad packet: %s\n", ldns_get_errorstr_by_id(status));
		} else {
			ldns_pkt_print(stdout, query_pkt);
		}

		query_rr = ldns_rr_list_rr(ldns_pkt_question(query_pkt), 0);
		printf("QUERY RR: \n");
		ldns_rr_print(stdout, query_rr);
		
		answer_qr = ldns_rr_list_new();
		ldns_rr_list_push_rr(answer_qr, ldns_rr_clone(query_rr));

		answer_an = get_rrset(zone, ldns_rr_owner(query_rr), ldns_rr_get_type(query_rr), ldns_rr_get_class(query_rr));
		answer_pkt = ldns_pkt_new();
		answer_ns = ldns_rr_list_new();
		answer_ad = ldns_rr_list_new();
		
		ldns_pkt_set_qr(answer_pkt, 1);
		ldns_pkt_set_aa(answer_pkt, 1);
		ldns_pkt_set_id(answer_pkt, ldns_pkt_id(query_pkt));

		ldns_pkt_push_rr_list(answer_pkt, LDNS_SECTION_QUESTION, answer_qr);
		ldns_pkt_push_rr_list(answer_pkt, LDNS_SECTION_ANSWER, answer_an);
		ldns_pkt_push_rr_list(answer_pkt, LDNS_SECTION_AUTHORITY, answer_ns);
		ldns_pkt_push_rr_list(answer_pkt, LDNS_SECTION_ADDITIONAL, answer_ad);

		status = ldns_pkt2wire(&outbuf, answer_pkt, &answer_size);
		
		printf("Answer packet size: %u bytes.\n", (unsigned int) answer_size);
		if (status != LDNS_STATUS_OK) {
			printf("Error creating answer: %s\n", ldns_get_errorstr_by_id(status));
		} else {
			nb = sendto(sock, (void*)outbuf, answer_size, 0, 
				&addr_him, hislen);
		}
		
		ldns_pkt_free(query_pkt);
		ldns_pkt_free(answer_pkt);
		LDNS_FREE(outbuf);
		ldns_rr_list_free(answer_qr);
		ldns_rr_list_free(answer_an);
		ldns_rr_list_free(answer_ns);
		ldns_rr_list_free(answer_ad);
	}
	
	/* No cleanup because of the infinite loop
	 *
	 * ldns_rdf_deep_free(origin);
	 * ldns_zone_deep_free(zone);
	 * return 0;
	 */
}
Beispiel #9
0
ldns_status
ldns_pkt2buffer_wire(ldns_buffer *buffer, const ldns_pkt *packet)
{
	ldns_rr_list *rr_list;
	uint16_t i;
	
	/* edns tmp vars */
	ldns_rr *edns_rr;
	uint8_t edata[4];
	
	(void) ldns_hdr2buffer_wire(buffer, packet);

	rr_list = ldns_pkt_question(packet);
	if (rr_list) {
		for (i = 0; i < ldns_rr_list_rr_count(rr_list); i++) {
			(void) ldns_rr2buffer_wire(buffer, 
			             ldns_rr_list_rr(rr_list, i), LDNS_SECTION_QUESTION);
		}
	}
	rr_list = ldns_pkt_answer(packet);
	if (rr_list) {
		for (i = 0; i < ldns_rr_list_rr_count(rr_list); i++) {
			(void) ldns_rr2buffer_wire(buffer, 
			             ldns_rr_list_rr(rr_list, i), LDNS_SECTION_ANSWER);
		}
	}
	rr_list = ldns_pkt_authority(packet);
	if (rr_list) {
		for (i = 0; i < ldns_rr_list_rr_count(rr_list); i++) {
			(void) ldns_rr2buffer_wire(buffer, 
			             ldns_rr_list_rr(rr_list, i), LDNS_SECTION_AUTHORITY);
		}
	}
	rr_list = ldns_pkt_additional(packet);
	if (rr_list) {
		for (i = 0; i < ldns_rr_list_rr_count(rr_list); i++) {
			(void) ldns_rr2buffer_wire(buffer, 
			             ldns_rr_list_rr(rr_list, i), LDNS_SECTION_ADDITIONAL);
		}
	}
	
	/* add EDNS to additional if it is needed */
	if (ldns_pkt_edns(packet)) {
		edns_rr = ldns_rr_new();
		ldns_rr_set_owner(edns_rr,
				ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, "."));
		ldns_rr_set_type(edns_rr, LDNS_RR_TYPE_OPT);
		ldns_rr_set_class(edns_rr, ldns_pkt_edns_udp_size(packet));
		edata[0] = ldns_pkt_edns_extended_rcode(packet);
		edata[1] = ldns_pkt_edns_version(packet);
		ldns_write_uint16(&edata[2], ldns_pkt_edns_z(packet));
		ldns_rr_set_ttl(edns_rr, ldns_read_uint32(edata));
		(void)ldns_rr2buffer_wire(buffer, edns_rr, LDNS_SECTION_ADDITIONAL);
		ldns_rr_free(edns_rr);
	}
	
	/* add TSIG to additional if it is there */
	if (ldns_pkt_tsig(packet)) {
		(void) ldns_rr2buffer_wire(buffer,
		                           ldns_pkt_tsig(packet), LDNS_SECTION_ADDITIONAL);
	}
	
	return LDNS_STATUS_OK;
}
/**
 * Process query.
 *
 */
query_state
query_process(query_type* q, void* engine)
{
    ldns_status status = LDNS_STATUS_OK;
    ldns_pkt* pkt = NULL;
    ldns_rr* rr = NULL;
    ldns_pkt_rcode rcode = LDNS_RCODE_NOERROR;
    ldns_pkt_opcode opcode = LDNS_PACKET_QUERY;
    ldns_rr_type qtype = LDNS_RR_TYPE_SOA;
    engine_type* e = (engine_type*) engine;
    ods_log_assert(e);
    ods_log_assert(q);
    ods_log_assert(q->buffer);
    if (!e || !q || !q->buffer) {
        ods_log_error("[%s] drop query: assertion error", query_str);
        return QUERY_DISCARDED; /* should not happen */
    }
    if (buffer_limit(q->buffer) < BUFFER_PKT_HEADER_SIZE) {
        ods_log_debug("[%s] drop query: packet too small", query_str);
        return QUERY_DISCARDED; /* too small */
    }
    if (buffer_pkt_qr(q->buffer)) {
        ods_log_debug("[%s] drop query: qr bit set", query_str);
        return QUERY_DISCARDED; /* not a query */
    }
    /* parse packet */
    status = ldns_wire2pkt(&pkt, buffer_current(q->buffer),
        buffer_remaining(q->buffer));
    if (status != LDNS_STATUS_OK) {
        ods_log_debug("[%s] got bad packet: %s", query_str,
            ldns_get_errorstr_by_id(status));
        return query_formerr(q);
    }
    rr = ldns_rr_list_rr(ldns_pkt_question(pkt), 0);
    lock_basic_lock(&e->zonelist->zl_lock);
    /* we can just lookup the zone, because we will only handle SOA queries,
       zone transfers, updates and notifies */
    q->zone = zonelist_lookup_zone_by_dname(e->zonelist, ldns_rr_owner(rr),
        ldns_rr_get_class(rr));
    /* don't answer for zones that are just added */
    if (q->zone && q->zone->zl_status == ZONE_ZL_ADDED) {
        ods_log_warning("[%s] zone %s just added, don't answer for now",
            query_str, q->zone->name);
        q->zone = NULL;
    }
    lock_basic_unlock(&e->zonelist->zl_lock);
    if (!q->zone) {
        ods_log_debug("[%s] zone not found", query_str);
        return query_servfail(q);
    }
    /* see if it is tsig signed */
    if (!query_find_tsig(q)) {
        return query_formerr(q);
    }
    /* else: valid tsig, or no tsig present */
    ods_log_debug("[%s] tsig %s", query_str, tsig_status2str(q->tsig_rr->status));
    rcode = query_process_tsig(q);
    if (rcode != LDNS_RCODE_NOERROR) {
        return query_error(q, rcode);
    }
    /* process edns */
    rcode = query_process_edns(q);
    if (rcode != LDNS_RCODE_NOERROR) {
        /* We should not return FORMERR, but BADVERS (=16).
         * BADVERS is created with Ext. RCODE, followed by RCODE.
         * Ext. RCODE is set to 1, RCODE must be 0 (getting 0x10 = 16).
         * Thus RCODE = NOERROR = NSD_RC_OK. */
        return query_error(q, LDNS_RCODE_NOERROR);
    }

    /* handle incoming request */
    opcode = ldns_pkt_get_opcode(pkt);
    qtype = ldns_rr_get_type(rr);
    ldns_pkt_free(pkt);

    switch (opcode) {
        case LDNS_PACKET_NOTIFY:
            return query_process_notify(q, qtype, engine);
        case LDNS_PACKET_QUERY:
            return query_process_query(q, qtype, engine);
        case LDNS_PACKET_UPDATE:
            return query_process_update(q);
        default:
            break;
    }
    return query_notimpl(q);
}
Beispiel #11
0
ldns_status output_packet(ldns_buffer *output, const ldns_pkt *pkt, struct sockaddr_storage sa, lookup_context_t* context)
{
    const ldns_output_format *fmt = ldns_output_format_nocomments;
    uint16_t i;
    ldns_status status = LDNS_STATUS_OK;

    time_t now = time(NULL);
    char nsbuffer[INET6_ADDRSTRLEN];
    char* ip_prefix = "";
    char* ip_suffix = "";
    switch (((struct sockaddr *) &sa)->sa_family)
    {
        case AF_INET:
            inet_ntop(AF_INET, &(((struct sockaddr_in *) &sa)->sin_addr), nsbuffer, INET_ADDRSTRLEN);
            break;
        case AF_INET6:
            inet_ntop(AF_INET6, &(((struct sockaddr_in6 *) &sa)->sin6_addr), nsbuffer, INET6_ADDRSTRLEN);
            ip_prefix = "[";
            ip_suffix = "]";
            break;
        default:
            exit(1);
    }

    if (!pkt)
    {
        if(0 > ldns_buffer_printf(output, ""))
        {
            abort();
        }
        return LDNS_STATUS_OK;
    }

    if(!context->cmd_args.only_responses)
    {
        if(0 > ldns_buffer_printf(output, "%s%s%s:%u %ld ", ip_prefix, ip_suffix, nsbuffer, ntohs(((struct sockaddr_in *) &sa)->sin_port), now))
        {
            abort();
        }
        for (i = 0; i < ldns_pkt_qdcount(pkt); i++)
        {
            status = ldns_rr2buffer_str_fmt(output, fmt, ldns_rr_list_rr(ldns_pkt_question(pkt), i));
            if (status != LDNS_STATUS_OK)
            {
                return status;
            }
        }
    }

    if (ldns_buffer_status_ok(output))
    {
        for (i = 0; i < ldns_pkt_ancount(pkt); i++)
        {
            if(!context->cmd_args.only_responses)
            {
                if(0 > ldns_buffer_printf(output, "\t"))
                {
                    abort();
                }
            }
            status = ldns_rr2buffer_str_fmt(output, fmt, ldns_rr_list_rr(ldns_pkt_answer(pkt), i));
            if (status != LDNS_STATUS_OK)
            {
                return status;
            }

        }
        if(!context->cmd_args.no_authority)
        {
            if(0 > ldns_buffer_printf(output, "\n"))
            {
                abort();
            }
            for (i = 0; i < ldns_pkt_nscount(pkt); i++)
            {
                if(!context->cmd_args.only_responses)
                {
                    ldns_buffer_printf(output, "\t");
                }
                status = ldns_rr2buffer_str_fmt(output, fmt, ldns_rr_list_rr(ldns_pkt_authority(pkt), i));
                if (status != LDNS_STATUS_OK)
                {
                    return status;
                }
            }
        }
        if(context->cmd_args.additional)
        {
            for (i = 0; i < ldns_pkt_arcount(pkt); i++)
            {
                if(!context->cmd_args.only_responses)
                {
                    ldns_buffer_printf(output, "\t");
                }
                status = ldns_rr2buffer_str_fmt(output, fmt, ldns_rr_list_rr(ldns_pkt_additional(pkt), i));
                if (status != LDNS_STATUS_OK)
                {
                    return status;
                }

            }
        }
    }
    else
    {
        return ldns_buffer_status(output);
    }
    return status;
}
Beispiel #12
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 {
Beispiel #13
0
/*
 * Parses data buffer to a query, finds the correct answer 
 * and calls the given function for every packet to send.
 */
void
handle_query(uint8_t* inbuf, ssize_t inlen, struct entry* entries, int* count,
	enum transport_type transport, void (*sendfunc)(uint8_t*, size_t, void*),
	void* userdata, FILE* verbose_out)
{
	ldns_status status;
	ldns_pkt *query_pkt = NULL;
	ldns_pkt *answer_pkt = NULL;
	struct reply_packet *p;
	ldns_rr *query_rr = NULL;
	uint8_t *outbuf = NULL;
	size_t answer_size = 0;
	struct entry* entry = NULL;
	ldns_rdf *stop_command = ldns_dname_new_frm_str("server.stop.");

	status = ldns_wire2pkt(&query_pkt, inbuf, (size_t)inlen);
	if (status != LDNS_STATUS_OK) {
		verbose(1, "Got bad packet: %s\n", ldns_get_errorstr_by_id(status));
		ldns_rdf_free(stop_command);
		return;
	}
	
	query_rr = ldns_rr_list_rr(ldns_pkt_question(query_pkt), 0);
	verbose(1, "query %d: id %d: %s %d bytes: ", ++(*count), (int)ldns_pkt_id(query_pkt), 
		(transport==transport_tcp)?"TCP":"UDP", (int)inlen);
	if(verbose_out) ldns_rr_print(verbose_out, query_rr);
	if(verbose_out) ldns_pkt_print(verbose_out, query_pkt);

	if (ldns_rr_get_type(query_rr) == LDNS_RR_TYPE_TXT &&
	    ldns_rr_get_class(query_rr) == LDNS_RR_CLASS_CH &&
	    ldns_dname_compare(ldns_rr_owner(query_rr), stop_command) == 0) {
		exit(0);
        }
	
	/* fill up answer packet */
	entry = find_match(entries, query_pkt, transport);
	if(!entry || !entry->reply_list) {
		verbose(1, "no answer packet for this query, no reply.\n");
		ldns_pkt_free(query_pkt);
		ldns_rdf_free(stop_command);
		return;
	}
	for(p = entry->reply_list; p; p = p->next)
	{
		verbose(3, "Answer pkt:\n");
		if (p->reply_from_hex) {
			/* try to parse the hex packet, if it can be
			 * parsed, we can use adjust rules. if not,
			 * send packet literally */
			status = ldns_buffer2pkt_wire(&answer_pkt, p->reply_from_hex);
			if (status == LDNS_STATUS_OK) {
				adjust_packet(entry, answer_pkt, query_pkt);
				if(verbose_out) ldns_pkt_print(verbose_out, answer_pkt);
				status = ldns_pkt2wire(&outbuf, answer_pkt, &answer_size);
				verbose(2, "Answer packet size: %u bytes.\n", (unsigned int)answer_size);
				if (status != LDNS_STATUS_OK) {
					verbose(1, "Error creating answer: %s\n", ldns_get_errorstr_by_id(status));
					ldns_pkt_free(query_pkt);
					ldns_rdf_free(stop_command);
					return;
				}
				ldns_pkt_free(answer_pkt);
				answer_pkt = NULL;
			} else {
				verbose(3, "Could not parse hex data (%s), sending hex data directly.\n", ldns_get_errorstr_by_id(status));
				/* still try to adjust ID */
				answer_size = ldns_buffer_capacity(p->reply_from_hex);
				outbuf = LDNS_XMALLOC(uint8_t, answer_size);
				memcpy(outbuf, ldns_buffer_export(p->reply_from_hex), answer_size);
				if(entry->copy_id) {
					ldns_write_uint16(outbuf, 
						ldns_pkt_id(query_pkt));
				}
			}
		} else {
			answer_pkt = ldns_pkt_clone(p->reply);
			adjust_packet(entry, answer_pkt, query_pkt);
			if(verbose_out) ldns_pkt_print(verbose_out, answer_pkt);
			status = ldns_pkt2wire(&outbuf, answer_pkt, &answer_size);
			verbose(1, "Answer packet size: %u bytes.\n", (unsigned int)answer_size);
			if (status != LDNS_STATUS_OK) {
				verbose(1, "Error creating answer: %s\n", ldns_get_errorstr_by_id(status));
				ldns_pkt_free(query_pkt);
				ldns_rdf_free(stop_command);
				return;
			}
			ldns_pkt_free(answer_pkt);
			answer_pkt = NULL;
		}
		if(p->packet_sleep) {
			verbose(3, "sleeping for next packet %d secs\n", 
				p->packet_sleep);
#ifdef HAVE_SLEEP
			sleep(p->packet_sleep);
#else
			Sleep(p->packet_sleep * 1000);
#endif
			verbose(3, "wakeup for next packet "
				"(slept %d secs)\n", p->packet_sleep);
		}
		sendfunc(outbuf, answer_size, userdata);
		LDNS_FREE(outbuf);
		outbuf = NULL;
		answer_size = 0;
	}
	ldns_pkt_free(query_pkt);
	ldns_rdf_free(stop_command);
}
Beispiel #14
0
/** returns owner from rr */
static ldns_rdf* get_owner(ldns_pkt* p)
{
	if(!ldns_rr_list_rr(ldns_pkt_question(p), 0))
		return NULL;
	return ldns_rr_owner(ldns_rr_list_rr(ldns_pkt_question(p), 0));
}
Beispiel #15
0
/** get qtype from rr */
static ldns_rr_type get_qtype(ldns_pkt* p)
{
	if(!ldns_rr_list_rr(ldns_pkt_question(p), 0))
		return 0;
	return ldns_rr_get_type(ldns_rr_list_rr(ldns_pkt_question(p), 0));
}
Beispiel #16
0
int
main(int argc, char **argv)
{
	/* arguments */
	int port;
	int soa;
	ldns_rdf *zone_name;
	size_t count;
	size_t maxcount;

	/* network */
	int sock;
	ssize_t nb;
	struct sockaddr addr_me;
	struct sockaddr addr_him;
	socklen_t hislen = sizeof(addr_him);
	const char *my_address;
	uint8_t inbuf[INBUF_SIZE];
	uint8_t *outbuf;

	/* dns */
	ldns_status status;
	ldns_pkt *query_pkt;
	ldns_pkt *answer_pkt;
	size_t answer_size;
	ldns_rr *query_rr;
	ldns_rr *rr;
	char rr_string[MAX_LEN + 1];
	ldns_rr *soa_rr;
	char soa_string[MAX_LEN + 1];
	
	/* use this to listen on specified interfaces later? */
	my_address = NULL;

	if(argc == 5) {
		/* -# num given */
		if (argv[1][0] == '-') {
			maxcount = atoi(argv[1] + 1);
			if (maxcount == 0) {
				usage(stdout);
				exit(EXIT_FAILURE);
			} else {
				fprintf(stderr, "quiting after %d qs\n", (int)maxcount);
			}
		} else {
			fprintf(stderr, "Use -Number for max count\n");
			exit(EXIT_FAILURE);
		}
		argc--;
		argv++;
	} else {
		maxcount = 0;
	}
	
	if (argc != 4) {
		usage(stdout);
		exit(EXIT_FAILURE);
	} else {
		port = atoi(argv[1]);
		if (port < 1) {
			fprintf(stderr, "Use a number for the port\n");
			usage(stdout);
			exit(EXIT_FAILURE);
		}
		
		zone_name = ldns_dname_new_frm_str(argv[2]);
		if (!zone_name) {
			fprintf(stderr, "Illegal domain name: %s\n", argv[2]);
			usage(stdout);
			exit(EXIT_FAILURE);
		}
		soa =  atoi(argv[3]);
		if (soa < 1) {
			fprintf(stderr, "Illegal soa number\n");
			usage(stdout);
			exit(EXIT_FAILURE);
		}
			
	}
	
	printf("Listening on port %d\n", port);
	sock =  socket(AF_INET, SOCK_DGRAM, 0);
	if (sock < 0) {
		fprintf(stderr, "%s: socket(): %s\n", argv[0], strerror(errno));
		exit(EXIT_FAILURE);
	}

	memset(&addr_me, 0, sizeof(addr_me));

	/* bind: try all ports in that range */
	if (udp_bind(sock, port, my_address)) {
		fprintf(stderr, "%s: cannot bind(): %s\n", argv[0], strerror(errno));
	}

	/* create our ixfr answer */
	answer_pkt = ldns_pkt_new();

	snprintf(rr_string, MAX_LEN, "%s IN IXFR", argv[2]);
	(void)ldns_rr_new_frm_str(&rr, rr_string , 0, NULL, NULL);
	(void)ldns_pkt_push_rr(answer_pkt, LDNS_SECTION_QUESTION, rr);

	 /* next add some rrs, with SOA stuff so that we mimic or ixfr reply */
	snprintf(soa_string, MAX_LEN, "%s IN SOA miek.miek.nl elektron.atoom.net %d 1 2 3000 4",
			argv[2], soa);

        (void)ldns_rr_new_frm_str(&soa_rr, soa_string, 0, NULL, NULL);
	snprintf(rr_string, MAX_LEN, "%s IN A 127.0.0.1", argv[2]);
        (void)ldns_rr_new_frm_str(&rr, rr_string , 0, NULL, NULL);

        /* compose the ixfr pkt */
        (void)ldns_pkt_push_rr(answer_pkt, LDNS_SECTION_ANSWER, soa_rr);
        (void)ldns_pkt_push_rr(answer_pkt, LDNS_SECTION_ANSWER, rr);
        (void)ldns_pkt_push_rr(answer_pkt, LDNS_SECTION_ANSWER, soa_rr);

	/* Done. Now receive */
	count = 0;
	while (1) {
		nb = recvfrom(sock, inbuf, INBUF_SIZE, 0, &addr_him, &hislen);
		if (nb < 1) {
			fprintf(stderr, "%s: recvfrom(): %s\n",
				argv[0], strerror(errno));
			exit(EXIT_FAILURE);
		}
		
		printf("Got query of %d bytes\n", (int)nb);
		status = ldns_wire2pkt(&query_pkt, inbuf, nb);
		if (status != LDNS_STATUS_OK) {
			printf("Got bad packet: %s\n", ldns_get_errorstr_by_id(status));
			continue;
		}
		
		query_rr = ldns_rr_list_rr(ldns_pkt_question(query_pkt), 0);
		printf("%d QUERY RR +%d: \n", (int)++count, ldns_pkt_id(query_pkt));
		ldns_rr_print(stdout, query_rr);
		
		ldns_pkt_set_id(answer_pkt, ldns_pkt_id(query_pkt));

		status = ldns_pkt2wire(&outbuf, answer_pkt, &answer_size);
		
		printf("Answer packet size: %u bytes.\n", (unsigned int) answer_size);
		if (status != LDNS_STATUS_OK) {
			printf("Error creating answer: %s\n", ldns_get_errorstr_by_id(status));
		} else {
			nb = (size_t) sendto(sock, outbuf, answer_size, 0, &addr_him, hislen);
		}

		if (maxcount > 0  && count >= maxcount) {
			fprintf(stderr, "%d queries seen... goodbye\n", (int)count);
			exit(EXIT_SUCCESS);
		}
	}
        return 0;
}
Beispiel #17
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);
    }
}
Beispiel #18
0
void
compare(struct dns_info *d1, struct dns_info *d2)
{
	ldns_pkt *p1, *p2, *pq;
	bool diff = false;
	char *pstr1, *pstr2;
	struct timeval now;
	char *compare_result;
	size_t file_nr;

	gettimeofday(&now, NULL);
	if (verbosity > 0) {
		printf("Id: %u\n", (unsigned int) d1->seq);
	}
	
	if (strcmp(d1->qdata, d2->qdata) != 0) {
		fprintf(stderr, "Query differs!\n");
		fprintf(stdout, "q: %d:%d\n%s\n%s\n%s\n", (int)d1->seq, (int)d2->seq, 
			d1->qdata, d1->qdata, d2->qdata);
	} else {
		if (strcmp(d1->adata, d2->adata) != 0) {
			if (advanced_match) {
				/* try to read the packet and sort the sections */
				p1 = read_hex_pkt(d1->adata);
				p2 = read_hex_pkt(d2->adata);
				if (p1) {
					ldns_pkt_set_timestamp(p1, now);
				}
				if (p2) {
					ldns_pkt_set_timestamp(p2, now);
				}
				if (p1 && ldns_pkt_qdcount(p1) > 0) {
					ldns_rr_list2canonical(ldns_pkt_question(p1));
					ldns_rr_list_sort(ldns_pkt_question(p1));
				}
				if (p1 && ldns_pkt_ancount(p1) > 0) {
					ldns_rr_list2canonical(ldns_pkt_answer(p1));
					ldns_rr_list_sort(ldns_pkt_answer(p1));
				}
				if (p1 && ldns_pkt_nscount(p1) > 0) {
					ldns_rr_list2canonical(ldns_pkt_authority(p1));
					ldns_rr_list_sort(ldns_pkt_authority(p1));
				}
				if (p1 && ldns_pkt_arcount(p1) > 0) {
					ldns_rr_list2canonical(ldns_pkt_additional(p1));
					ldns_rr_list_sort(ldns_pkt_additional(p1));
				}
				if (p2 && ldns_pkt_qdcount(p2) > 0) {
					ldns_rr_list2canonical(ldns_pkt_question(p2));
					ldns_rr_list_sort(ldns_pkt_question(p2));
				}
				if (p2 && ldns_pkt_ancount(p2) > 0) {
					ldns_rr_list2canonical(ldns_pkt_answer(p2));
					ldns_rr_list_sort(ldns_pkt_answer(p2));
				}
				if (p2 && ldns_pkt_nscount(p2) > 0) {
					ldns_rr_list2canonical(ldns_pkt_authority(p2));
					ldns_rr_list_sort(ldns_pkt_authority(p2));
				}
				if (p2 && ldns_pkt_arcount(p2) > 0) {
					ldns_rr_list2canonical(ldns_pkt_additional(p2));
					ldns_rr_list_sort(ldns_pkt_additional(p2));
				}

				/* simply do string comparison first */
				pstr1 = ldns_pkt2str(p1);
				pstr2 = ldns_pkt2str(p2);
				if ((!p1 && !p2) || strcmp(pstr1, pstr2) != 0) {
					/* okay strings still differ, get the query and do a match for the match files */
					pq = read_hex_pkt(d1->qdata);
					compare_result = compare_to_file(pq, p1, p2);
					if (compare_result != NULL) {
						/*fprintf(stderr, compare_result);*/
						if (compare_result[strlen(compare_result)-1] == '\n') {
							compare_result[strlen(compare_result)-1] = 0;
						}
						file_nr = add_known_difference(compare_result);
						if (store_known_differences) {
							fprintf(known_differences[file_nr].file, "q: %d:%d\n%s\n%s\n%s\n", (int)d1->seq, (int)d2->seq, 
								d1->qdata, d1->adata, d2->adata);
						}
						
						free(compare_result);
						diff = false;
					} else {
						diff=false;
						printf("Error: Unknown difference in packet number %u:\n", (unsigned int) total_nr_of_packets);
						ldns_pkt_print(stdout, pq);
						printf("\n");
						ldns_pkt_print(stdout, p1);
						printf("\n");
						ldns_pkt_print(stdout, p2);
						
						printf("Quitting at packet %u\n", (unsigned int) d1->seq);
						exit(1);
					}
					ldns_pkt_free(pq);
				} else {
					sames++;
				}					
				if (diff) {
					if (show_originals) {
						fprintf(stdout, "%d:%d\n%s\n%s\n%s\n", (int)d1->seq, (int)d2->seq, 
							d1->qdata, d1->adata, d2->adata);
					} else {
						fprintf(stdout, "%d:%d\n", (int)d1->seq, (int)d2->seq);
						if (!dump_hex(stdout, p1)) {
							fprintf(stdout, "%s", d1->adata);
						}
						fprintf(stdout, "\n");
						if (!dump_hex(stdout, p2)) {
							fprintf(stdout, "%s", d2->adata);
						}
						fprintf(stdout, "\n");
					}
				}
				LDNS_FREE(pstr1);
				LDNS_FREE(pstr2);
				ldns_pkt_free(p1);
				ldns_pkt_free(p2);
			} else {
				fprintf(stdout, "%d:%d\n%s\n%s\n%s\n", (int)d1->seq, (int)d2->seq, 
					d1->qdata, d1->adata, d2->adata);
			}
		} else {
			sames++;
			bytesames++;
		}
	}
}
Beispiel #19
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;
}
Beispiel #20
0
Datei: clib.c Projekt: crnt/zkdns
void zkdns_start(const char* my_address, int port, const char* my_zone)
{
	rp_handle = rp_initialize(my_zone);
	/* network */
	int sock;
	ssize_t nb;
	struct sockaddr addr_me;
	struct sockaddr addr_him;
	socklen_t hislen = (socklen_t) sizeof(addr_him);
	uint8_t inbuf[INBUF_SIZE];
	uint8_t *outbuf;

	/* dns */
	ldns_status status;
	ldns_pkt *query_pkt;
	ldns_pkt *answer_pkt;
	size_t answer_size;
	ldns_rr *query_rr;
	ldns_rr_list *answer_qr;
	ldns_rr_list *answer_an;
	ldns_rr_list *answer_ns;
	ldns_rr_list *answer_ad;
	ldns_rdf *origin = NULL;
	
	/* zone */
	ldns_zone *zone;
	int line_nr;
	FILE *zone_fp;
	
	if (ldns_str2rdf_dname(&origin, my_zone) != LDNS_STATUS_OK) {
		fprintf(stderr, "Bad origin, not a correct domain name\n");
		exit(EXIT_FAILURE);
	}

	printf("Listening on port %d\n", port);
	sock =  socket(AF_INET, SOCK_DGRAM, 0);
	if (sock < 0) {
		fprintf(stderr, "socket(): %s\n", strerror(errno));
		exit(1);
	}
	memset(&addr_me, 0, sizeof(addr_me));

	/* bind: try all ports in that range */
	if (udp_bind(sock, port, my_address)) {
		fprintf(stderr, "cannot bind(): %s\n", strerror(errno));
		exit(errno);
	}

	/* Done. Now receive */
	while (1) {
		nb = recvfrom(sock, (void*)inbuf, INBUF_SIZE, 0, 
			&addr_him, &hislen);
		if (nb < 1) {
			fprintf(stderr, "recvfrom(): %s\n",
			strerror(errno));
			exit(1);
		}

		/*
		show(inbuf, nb, nn, hp, sp, ip, bp);
		*/
		status = ldns_wire2pkt(&query_pkt, inbuf, (size_t) nb);
		if (status != LDNS_STATUS_OK) {
			printf("Got bad packet: %s\n", ldns_get_errorstr_by_id(status));
		}

		query_rr = ldns_rr_list_rr(ldns_pkt_question(query_pkt), 0);
		
		answer_qr = ldns_rr_list_new();
		ldns_rr_list_push_rr(answer_qr, ldns_rr_clone(query_rr));

		answer_an = get_rrset(zone, ldns_rr_owner(query_rr), ldns_rr_get_type(query_rr), ldns_rr_get_class(query_rr));
		answer_pkt = ldns_pkt_new();
		answer_ns = ldns_rr_list_new();
		answer_ad = ldns_rr_list_new();
		
		ldns_pkt_set_qr(answer_pkt, 1);
		ldns_pkt_set_aa(answer_pkt, 1);
		ldns_pkt_set_id(answer_pkt, ldns_pkt_id(query_pkt));

		ldns_pkt_push_rr_list(answer_pkt, LDNS_SECTION_QUESTION, answer_qr);
		ldns_pkt_push_rr_list(answer_pkt, LDNS_SECTION_ANSWER, answer_an);
		ldns_pkt_push_rr_list(answer_pkt, LDNS_SECTION_AUTHORITY, answer_ns);
		ldns_pkt_push_rr_list(answer_pkt, LDNS_SECTION_ADDITIONAL, answer_ad);

		status = ldns_pkt2wire(&outbuf, answer_pkt, &answer_size);
		
		if (status != LDNS_STATUS_OK) {
			printf("Error creating answer: %s\n", ldns_get_errorstr_by_id(status));
		} else {
			nb = sendto(sock, (void*)outbuf, answer_size, 0, 
				&addr_him, hislen);
		}
		
		ldns_pkt_free(query_pkt);
		ldns_pkt_free(answer_pkt);
		LDNS_FREE(outbuf);
		ldns_rr_list_free(answer_qr);
		ldns_rr_list_free(answer_an);
		ldns_rr_list_free(answer_ns);
		ldns_rr_list_free(answer_ad);
	}
	
	ldns_rdf_deep_free(origin);
	ldns_zone_deep_free(zone);
	rp_shutdown(rp_handle);
}
Beispiel #21
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;
}