From f01ed133f5eb2f4832f97021227d722ff5f0db45 Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Wed, 11 Feb 2015 14:55:22 +0100 Subject: [PATCH] ldns_wire2pkt at create_getdns_response time only This break priv_get_validation_chain --- src/general.c | 2 +- src/request-internal.c | 14 ++++--- src/stub.c | 12 ++---- src/types-internal.h | 1 + src/util-internal.c | 95 ++++++++++++++++++++++++++++-------------- 5 files changed, 77 insertions(+), 47 deletions(-) diff --git a/src/general.c b/src/general.c index b44343b1..8531b78f 100644 --- a/src/general.c +++ b/src/general.c @@ -88,7 +88,7 @@ priv_getdns_check_dns_req_complete(getdns_dns_req *dns_req) if (netreq->state != NET_REQ_FINISHED && netreq->state != NET_REQ_CANCELED) return; - else if (netreq->result) + else if (netreq->response_len > 0) results_found = 1; if (! results_found) diff --git a/src/request-internal.c b/src/request-internal.c index d2b85434..4f34ab3e 100644 --- a/src/request-internal.c +++ b/src/request-internal.c @@ -102,6 +102,7 @@ network_req_init(getdns_network_req *net_req, getdns_dns_req *owner, ? edns_maximum_udp_payload_size : 1432; net_req->write_queue_tail = NULL; net_req->query_len = 0; + net_req->response_len = 0; net_req->wire_data_sz = wire_data_sz; if (max_query_sz) { @@ -120,8 +121,10 @@ network_req_init(getdns_network_req *net_req, getdns_dns_req *owner, buf += GLDNS_HEADER_SIZE; dname_len = max_query_sz - GLDNS_HEADER_SIZE; - if ((r = gldns_str2wire_dname_buf(name, buf, &dname_len))) + if ((r = gldns_str2wire_dname_buf(name, buf, &dname_len))) { + net_req->opt = NULL; return r; + } buf += dname_len; @@ -202,12 +205,13 @@ getdns_dns_req * dns_req_new(getdns_context *context, getdns_eventloop *loop, const char *name, uint16_t request_type, getdns_dict *extensions) { - int dnssec_return_status = context->return_dnssec_status || - is_extension_set(extensions, "dnssec_return_status"); + int dnssec_return_status + = context->return_dnssec_status == GETDNS_EXTENSION_TRUE + || is_extension_set(extensions, "dnssec_return_status"); int dnssec_return_only_secure - = is_extension_set(extensions, "dnssec_return_only_secure"); + = is_extension_set(extensions, "dnssec_return_only_secure"); int dnssec_return_validation_chain - = is_extension_set(extensions, "dnssec_return_validation_chain"); + = is_extension_set(extensions, "dnssec_return_validation_chain"); int dnssec_extension_set = dnssec_return_status || dnssec_return_only_secure || dnssec_return_validation_chain; diff --git a/src/stub.c b/src/stub.c index 445d3d86..e8f8a74b 100644 --- a/src/stub.c +++ b/src/stub.c @@ -229,9 +229,7 @@ stub_udp_read_cb(void *userarg) return; } - netreq->max_udp_payload_size = read; - ldns_wire2pkt(&(netreq->result), netreq->response, - netreq->max_udp_payload_size); + netreq->response_len = read; dnsreq->upstreams->current = 0; /* TODO: DNSSEC */ @@ -393,11 +391,9 @@ stub_tcp_read_cb(void *userarg) return; netreq->state = NET_REQ_FINISHED; netreq->response = netreq->tcp.read_buf; - netreq->max_udp_payload_size = + netreq->response_len = netreq->tcp.read_pos - netreq->tcp.read_buf; netreq->tcp.read_buf = NULL; - ldns_wire2pkt(&(netreq->result), netreq->response, - netreq->max_udp_payload_size); dnsreq->upstreams->current = 0; /* TODO: DNSSEC */ @@ -446,11 +442,9 @@ upstream_read_cb(void *userarg) netreq->state = NET_REQ_FINISHED; netreq->response = upstream->tcp.read_buf; - netreq->max_udp_payload_size = + netreq->response_len = upstream->tcp.read_pos - upstream->tcp.read_buf; upstream->tcp.read_buf = NULL; - ldns_wire2pkt(&(netreq->result), netreq->response, - netreq->max_udp_payload_size); upstream->upstreams->current = 0; /* TODO: DNSSEC */ diff --git a/src/types-internal.h b/src/types-internal.h index 9558b84c..d01a0fac 100644 --- a/src/types-internal.h +++ b/src/types-internal.h @@ -211,6 +211,7 @@ typedef struct getdns_network_req size_t query_len; uint8_t *query; uint8_t *opt; /* offset of OPT RR in query */ + size_t response_len; uint8_t *response; size_t wire_data_sz; uint8_t wire_data[]; diff --git a/src/util-internal.c b/src/util-internal.c index 1200157f..b0f2b332 100644 --- a/src/util-internal.c +++ b/src/util-internal.c @@ -48,6 +48,9 @@ #if defined(WIRE_DEBUG) && WIRE_DEBUG #include "gldns/wire2str.h" #endif +#include "gldns/str2wire.h" +#include "gldns/gbuffer.h" +#include "gldns/pkthdr.h" /** * this is a comprehensive list of extensions and their data types @@ -562,11 +565,19 @@ create_getdns_response(getdns_dns_req *completed_request) ; ! r && (netreq = *netreq_p) ; netreq_p++) { - if (! netreq->result) + assert(! netreq->result); + if (! netreq->response_len) continue; + if (ldns_wire2pkt(&(netreq->result), netreq->response, + netreq->response_len)) { + + netreq->response_len = 0; + continue; + } + if ((str_pkt = gldns_wire2str_pkt( - netreq->response, netreq->max_udp_payload_size))) { + netreq->response, netreq->response_len))) { fprintf(stderr, "%s\n", str_pkt); free(str_pkt); } @@ -868,43 +879,63 @@ validate_extensions(struct getdns_dict * extensions) getdns_return_t getdns_apply_network_result(getdns_network_req* netreq, - struct ub_result* ub_res) { + struct ub_result* ub_res) +{ + size_t dname_len; - if (ub_res == NULL) { /* Timeout */ - netreq->result = NULL; - return GETDNS_RETURN_GOOD; + netreq->secure = ub_res->secure; + netreq->bogus = ub_res->bogus; + + if (ub_res == NULL) /* Timeout */ + return GETDNS_RETURN_GOOD; + + if (ub_res->answer_packet) { + if (netreq->max_udp_payload_size < ub_res->answer_len) + netreq->response = GETDNS_XMALLOC( + netreq->owner->context->mf, + uint8_t, ub_res->answer_len + ); + (void) memcpy(netreq->response, ub_res->answer_packet, + (netreq->response_len = ub_res->answer_len)); + return GETDNS_RETURN_GOOD; + } - } else if (ub_res->answer_packet == NULL) { if (ub_res->rcode == GETDNS_RCODE_SERVFAIL) { /* Likely to be caused by timeout from a synchronous * lookup. Don't forge a packet. */ - netreq->result = NULL; - } else { - /* Likely to be because libunbound refused the request - * so ub_res->answer_packet=NULL, ub_res->answer_len=0 - * So we need to create an answer packet. - */ - netreq->result = ldns_pkt_query_new( - ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, netreq->owner->name), - netreq->request_type, - netreq->request_class,LDNS_QR|LDNS_RD|LDNS_RA); - ldns_pkt_set_rcode(netreq->result, ub_res->rcode); + return GETDNS_RETURN_GOOD; } - } else { - if (netreq->max_udp_payload_size < ub_res->answer_len) - netreq->response = GETDNS_XMALLOC( - netreq->owner->context->mf, uint8_t, ub_res->answer_len); - (void) memcpy(netreq->response, ub_res->answer_packet, - (netreq->max_udp_payload_size = ub_res->answer_len)); - ldns_status r = ldns_wire2pkt(&(netreq->result), - netreq->response, netreq->max_udp_payload_size); - if (r != LDNS_STATUS_OK) - return GETDNS_RETURN_GENERIC_ERROR; - } - netreq->secure = ub_res->secure; - netreq->bogus = ub_res->bogus; - return GETDNS_RETURN_GOOD; + /* Likely to be because libunbound refused the request + * so ub_res->answer_packet=NULL, ub_res->answer_len=0 + * So we need to create an answer packet. + */ + gldns_write_uint16(netreq->response , 0); /* query_id */ + gldns_write_uint16(netreq->response + 2, 0); /* reset all flags */ + gldns_write_uint16(netreq->response + GLDNS_QDCOUNT_OFF, 1); + gldns_write_uint16(netreq->response + GLDNS_ANCOUNT_OFF, 0); + gldns_write_uint16(netreq->response + GLDNS_NSCOUNT_OFF, 0); + gldns_write_uint16(netreq->response + GLDNS_ARCOUNT_OFF, 0); + + GLDNS_OPCODE_SET(netreq->response, 3); + GLDNS_QR_SET(netreq->response); + GLDNS_RD_SET(netreq->response); + GLDNS_RA_SET(netreq->response); + GLDNS_RCODE_SET(netreq->response, ub_res->rcode); + + dname_len = netreq->max_udp_payload_size - GLDNS_HEADER_SIZE; + if (gldns_str2wire_dname_buf(netreq->owner->name, + netreq->response + GLDNS_HEADER_SIZE, &dname_len)) + return GETDNS_RETURN_GENERIC_ERROR; + + gldns_write_uint16( netreq->response + GLDNS_HEADER_SIZE + dname_len + , netreq->request_type); + gldns_write_uint16( netreq->response + GLDNS_HEADER_SIZE + dname_len + 2 + , netreq->request_class); + + netreq->response_len = GLDNS_HEADER_SIZE + dname_len + 4; + + return GETDNS_RETURN_GOOD; }