Esempio n. 1
0
File: lua.c Progetto: benlaurie/ldns
/* read section counters */
static int
l_pkt_qdcount(lua_State *L)
{
	ldns_pkt *p = (ldns_pkt*)lua_touserdata(L, 1);
	if (!p) {
		return 0;
	}
	lua_pushnumber(L, (lua_Number)ldns_pkt_qdcount(p));
	return 1;
}
/** 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;
}
Esempio n. 3
0
/* rejects packets that arrive with OPCODE != QUERY, or QDCOUNT != 1 */
void query_only(evldns_server_request *srq, void *user_data, ldns_rdf *qname, ldns_rr_type qtype, ldns_rr_class qclass)
{
	ldns_pkt *req = srq->request;

	if (ldns_pkt_get_opcode(req) != LDNS_PACKET_QUERY) {
		srq->response = evldns_response(req, LDNS_RCODE_NOTIMPL);
	}

	if (ldns_pkt_qdcount(req) != 1) {
		srq->response = evldns_response(req, LDNS_RCODE_FORMERR);
	}
}
Esempio n. 4
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");
    }
}
Esempio n. 5
0
void query_check(evldns_server_request *srq,
				 ATTR_UNUSED(void *user_data),
				 ATTR_UNUSED(ldns_rdf *qname),
				 ldns_rr_type qtype,
				 ldns_rr_class qclass)
{
	ldns_pkt *req = srq->request;

	/* only QUERY is supported */
	if (ldns_pkt_get_opcode(req) != LDNS_PACKET_QUERY) {
		srq->response = evldns_response(req, LDNS_RCODE_NOTIMPL);
		return;
	}

	/* QDCOUNT == 1, NB: QR == 1 now handled upstream */
	if (ldns_pkt_qdcount(req) != 1) {
		srq->response = evldns_response(req, LDNS_RCODE_FORMERR);
		return;
	}

	/* Unexpected QCLASS */
	if (qclass != LDNS_RR_CLASS_IN) {
		srq->response = evldns_response(req, LDNS_RCODE_NOTIMPL);
		return;
	}

	/* Unexpected QTYPE */
	if (qtype == LDNS_RR_TYPE_AXFR || qtype == LDNS_RR_TYPE_IXFR) {
		srq->response = evldns_response(req, LDNS_RCODE_NOTIMPL);
		return;
	}

	/* Not going to handle QTYPE == ANY either */
	if (qtype == LDNS_RR_TYPE_ANY) {
		srq->response = evldns_response(req, LDNS_RCODE_NOTIMPL);
		return;
	}
}
Esempio n. 6
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);
}
Esempio n. 7
0
void dns_parser (packetinfo *pi) {
    ldns_status   status;
    ldns_pkt     *dns_pkt;

    status = LDNS_STATUS_ERR; 

    /* In DNS tcp messages, the first 2 bytes signal the
     * amount of data to expect. So we need to skip them in the read.
     */
    if (pi->plen <= 2) return; /* The minimum bytes in a packet - else return */

    if ( pi->af == AF_INET ) {
        switch (pi->ip4->ip_p) {
            case IP_PROTO_TCP:
                status = ldns_wire2pkt(&dns_pkt,pi->payload + 2, pi->plen - 2);
                break;
            case IP_PROTO_UDP:
                status = ldns_wire2pkt(&dns_pkt,pi->payload, pi->plen);
                break;
            default:
                break;
        }
    } else if ( pi->af == AF_INET6 ) {
        switch (pi->ip6->next) {
            case IP_PROTO_TCP:
                status = ldns_wire2pkt(&dns_pkt,pi->payload + 2, pi->plen - 2);
                break;
            case IP_PROTO_UDP:
                status = ldns_wire2pkt(&dns_pkt,pi->payload, pi->plen);
                break;
            default:
                break;
        }
    }

    if (status != LDNS_STATUS_OK) {
        dlog("[D] ldns_wire2pkt status: %d\n", status);
        update_dns_stats(pi,ERROR);
        return;
    }

    /* We dont want to process Truncated packets */
    if (ldns_pkt_tc(dns_pkt)) {
       dlog("[D] DNS packet with Truncated (TC) bit set! Skipping!\n");
       ldns_pkt_free(dns_pkt);
       update_dns_stats(pi,ERROR);
       return;
    }

    /* we only care about answers when we record data */
    if (ldns_pkt_qr(dns_pkt)) {
        /* Answer must come from the server, and the client has to have sent a packet! */
        if ( pi->sc != SC_SERVER || pi->cxt->s_total_pkts == 0 ) {
            dlog("[D] DNS Answer without a Question?: Query TID = %d and Answer TID = %d\n",pi->cxt->plid,ldns_pkt_id(dns_pkt));
            ldns_pkt_free(dns_pkt);
            update_dns_stats(pi,ERROR);
            return;
        }
        dlog("[D] DNS Answer\n");
        /* Check the DNS TID */
        if ( (pi->cxt->plid == ldns_pkt_id(dns_pkt)) ) {
            dlog("[D] DNS Query TID match Answer TID: %d\n", pi->cxt->plid);
        } else {
            dlog("[D] DNS Query TID did not match Answer TID: %d != %d - Skipping!\n", pi->cxt->plid, ldns_pkt_id(dns_pkt));
            ldns_pkt_free(dns_pkt);
            update_dns_stats(pi,ERROR);
            return;
        }

        /* From isc.org wording: 
         * We do not collect any of the query-response traffic that
         * occurs when the client sets the RD or "Recursion Desired"
         * bit to 1, that is, the traffic that occurs between DNS
         * "stub" clients and the caching server itself, since only the
         * traffic generated in response to a cache miss (RD bit set to 0)
         * is strictly needed in order to build a passive DNS database.
         */
        if (ldns_pkt_rd(dns_pkt)) {
            dlog("[D] DNS packet with Recursion Desired (RD) bit set!\n");
            /* Between DNS-server to DNS-server, we should drop this kind
             * of traffic if we are thinking hardening and correctness!
             * But for people trying this out in a corporate network etc,
             * between a client and a DNS proxy, will need this most likely
             * to see any traffic at all. In the future, this might be
             * controlled by a cmdline switch.
             */ 
            //ldns_pkt_free(decoded_dns);
            //return;
        }

        if (!ldns_pkt_qdcount(dns_pkt)) {
            /* no questions or answers */
            dlog("[D] DNS packet did not contain a question. Skipping!\n");
            ldns_pkt_free(dns_pkt);
            update_dns_stats(pi,ERROR);
            return;
        }

        // send it off for processing
        if (process_dns_answer(pi, dns_pkt) < 0) {
            dlog("[D] process_dns_answer() returned -1\n");
        }
    } else {
        /* We need to get the DNS TID from the Query to later match with the
         * DNS TID in the answer - to harden the implementation.
         */

        /* Question must come from the client (and the server should not have sent a packet). */
        if ( pi->sc != SC_CLIENT ) {
            dlog("[D] DNS Query not from a client? Skipping!\n");
            ldns_pkt_free(dns_pkt);
            update_dns_stats(pi,ERROR);
            return;
        }
        
        /* Check for reuse of a session and a hack for
         * no timeout of sessions when reading pcaps atm. :/
         * 60 Secs are default UDP timeout in cxt, and should
         * be enough for a TCP session of DNS too.
         */
        if ( (pi->cxt->plid != 0 && pi->cxt->plid != ldns_pkt_id(dns_pkt)) && ((pi->cxt->last_pkt_time - pi->cxt->start_time) <= 60) ) {
            dlog("[D] DNS Query on an established DNS session - TID: Old:%d New:%d\n", pi->cxt->plid, ldns_pkt_id(dns_pkt));
            /* Some clients have bad or strange random src
             * port generator and will gladly reuse the same
             * src port several times in a short time period.
             * To implment this fully, each cxt should be include
             * the TID in its tuple, but still this will make a mess :/
             */
        } else {
            dlog("[D] New DNS Query\n");
        }

        if (!ldns_pkt_qdcount(dns_pkt)) {
            /* no questions or answers */
            dlog("[D] DNS Query packet did not contain a question? Skipping!\n");
            ldns_pkt_free(dns_pkt);
            update_dns_stats(pi,ERROR);
            return;
        }

        if ( (pi->cxt->plid = ldns_pkt_id(dns_pkt)) ) {
            dlog("[D] DNS Query with TID = %d\n", pi->cxt->plid);
        } else {
            dlog("[E] Error getting DNS TID from Query!\n");
            ldns_pkt_free(dns_pkt);
            update_dns_stats(pi,ERROR);
            return;
        }

        /* For hardening, we can extract the query and add it to the cxt
         * and then check it later in the answer, that they match.
         */
        /*
        if (update_query_cxt(pi, dns_pkt) < 0) {
            dlog("[D] update_query_cxt() returned -1\n");
        }
        */
    }

    ldns_pkt_free(dns_pkt);
}
Esempio n. 8
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++;
		}
	}
}
Esempio n. 9
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);
    }
}
Esempio n. 10
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;
}
Esempio n. 11
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;
}