mirror of https://github.com/getdnsapi/getdns.git
Store wireformat queries in netreq's too
This commit is contained in:
parent
3f046cf573
commit
f1b916aac8
|
@ -93,8 +93,7 @@ priv_getdns_check_dns_req_complete(getdns_dns_req *dns_req)
|
|||
|
||||
if (! results_found)
|
||||
priv_getdns_call_user_callback(dns_req, NULL);
|
||||
else if (is_extension_set(dns_req->extensions,
|
||||
"dnssec_return_validation_chain"))
|
||||
else if (dns_req->dnssec_return_validation_chain)
|
||||
priv_getdns_get_validation_chain(dns_req);
|
||||
else
|
||||
priv_getdns_call_user_callback(
|
||||
|
@ -135,10 +134,9 @@ submit_network_request(getdns_network_req *netreq)
|
|||
/* TODO: Until DNSSEC with the new async stub resolver is finished,
|
||||
* use unbound when we need DNSSEC.
|
||||
*/
|
||||
(dns_req->extensions && (
|
||||
is_extension_set(dns_req->extensions, "dnssec_return_status") ||
|
||||
is_extension_set(dns_req->extensions, "dnssec_return_only_secure") ||
|
||||
is_extension_set(dns_req->extensions, "dnssec_return_validation_chain")))) {
|
||||
dns_req->dnssec_return_status ||
|
||||
dns_req->dnssec_return_only_secure ||
|
||||
dns_req->dnssec_return_validation_chain) {
|
||||
|
||||
/* schedule the timeout */
|
||||
if (! dns_req->timeout.timeout_cb) {
|
||||
|
|
|
@ -37,6 +37,22 @@
|
|||
#include "types-internal.h"
|
||||
#include "util-internal.h"
|
||||
#include "gldns/rrdef.h"
|
||||
#include "gldns/str2wire.h"
|
||||
#include "gldns/gbuffer.h"
|
||||
#include "gldns/pkthdr.h"
|
||||
|
||||
static int
|
||||
is_extension_set(getdns_dict *extensions, const char *extension)
|
||||
{
|
||||
getdns_return_t r;
|
||||
uint32_t value;
|
||||
|
||||
if (! extensions)
|
||||
return 0;
|
||||
|
||||
r = getdns_dict_get_int(extensions, extension, &value);
|
||||
return r == GETDNS_RETURN_GOOD && value == GETDNS_EXTENSION_TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
network_req_cleanup(getdns_network_req *net_req)
|
||||
|
@ -46,15 +62,28 @@ network_req_cleanup(getdns_network_req *net_req)
|
|||
if (net_req->result)
|
||||
ldns_pkt_free(net_req->result);
|
||||
|
||||
if (net_req->response && net_req->response != net_req->wire_data)
|
||||
if (net_req->response && (net_req->response < net_req->wire_data ||
|
||||
net_req->response > net_req->wire_data+ net_req->wire_data_sz))
|
||||
GETDNS_FREE(net_req->owner->my_mf, net_req->response);
|
||||
}
|
||||
|
||||
static void
|
||||
network_req_init(getdns_network_req *net_req,
|
||||
getdns_dns_req *owner, uint16_t request_type,
|
||||
uint16_t request_class, size_t wire_data_sz)
|
||||
static int
|
||||
network_req_init(getdns_network_req *net_req, getdns_dns_req *owner,
|
||||
const char *name, uint16_t request_type, uint16_t request_class,
|
||||
int dnssec_extension_set, int with_opt,
|
||||
uint16_t edns_maximum_udp_payload_size,
|
||||
uint8_t edns_extended_rcode, uint8_t edns_version, int edns_do_bit,
|
||||
uint16_t opt_options_size, size_t noptions, getdns_list *options,
|
||||
size_t wire_data_sz, size_t max_query_sz)
|
||||
{
|
||||
uint8_t *buf;
|
||||
size_t dname_len;
|
||||
getdns_dict *option;
|
||||
uint32_t option_code;
|
||||
getdns_bindata *option_data;
|
||||
size_t i;
|
||||
int r = 0;
|
||||
|
||||
net_req->result = NULL;
|
||||
|
||||
net_req->request_type = request_type;
|
||||
|
@ -68,11 +97,78 @@ network_req_init(getdns_network_req *net_req,
|
|||
memset(&net_req->event, 0, sizeof(net_req->event));
|
||||
memset(&net_req->tcp, 0, sizeof(net_req->tcp));
|
||||
net_req->query_id = 0;
|
||||
net_req->max_udp_payload_size = 0;
|
||||
net_req->edns_maximum_udp_payload_size = edns_maximum_udp_payload_size;
|
||||
net_req->max_udp_payload_size = edns_maximum_udp_payload_size != -1
|
||||
? edns_maximum_udp_payload_size : 1432;
|
||||
net_req->write_queue_tail = NULL;
|
||||
net_req->query_len = 0;
|
||||
|
||||
net_req->wire_data_sz = wire_data_sz;
|
||||
net_req->response = NULL;
|
||||
if (max_query_sz) {
|
||||
/* first two bytes will contain query length (for tcp) */
|
||||
buf = net_req->query = net_req->wire_data + 2;
|
||||
|
||||
gldns_write_uint16(buf + 2, 0); /* reset all flags */
|
||||
GLDNS_RD_SET(buf);
|
||||
if (dnssec_extension_set) /* We will do validation ourselves */
|
||||
GLDNS_CD_SET(buf);
|
||||
GLDNS_OPCODE_SET(buf, GLDNS_PACKET_QUERY);
|
||||
gldns_write_uint16(buf + GLDNS_QDCOUNT_OFF, 1); /* 1 query */
|
||||
gldns_write_uint16(buf + GLDNS_ANCOUNT_OFF, 0); /* 0 answers */
|
||||
gldns_write_uint16(buf + GLDNS_NSCOUNT_OFF, 0); /* 0 authorities */
|
||||
gldns_write_uint16(buf + GLDNS_ARCOUNT_OFF, with_opt ? 1 : 0);
|
||||
|
||||
buf += GLDNS_HEADER_SIZE;
|
||||
dname_len = max_query_sz - GLDNS_HEADER_SIZE;
|
||||
if ((r = gldns_str2wire_dname_buf(name, buf, &dname_len)))
|
||||
return r;
|
||||
|
||||
buf += dname_len;
|
||||
|
||||
gldns_write_uint16(buf, request_type);
|
||||
gldns_write_uint16(buf + 2, request_class);
|
||||
buf += 4;
|
||||
|
||||
if (with_opt) {
|
||||
net_req->opt = buf;
|
||||
buf[0] = 0; /* dname for . */
|
||||
gldns_write_uint16(buf + 1, GLDNS_RR_TYPE_OPT);
|
||||
gldns_write_uint16(net_req->opt + 3,
|
||||
net_req->max_udp_payload_size);
|
||||
buf[5] = edns_extended_rcode;
|
||||
buf[6] = edns_version;
|
||||
buf[7] = edns_do_bit ? 0x80 : 0;
|
||||
buf[8] = 0;
|
||||
gldns_write_uint16(buf + 9, opt_options_size);
|
||||
buf += 11;
|
||||
for (i = 0; i < noptions; i++) {
|
||||
if (getdns_list_get_dict(options, i, &option))
|
||||
continue;
|
||||
if (getdns_dict_get_int(
|
||||
option, "option_code", &option_code))
|
||||
continue;
|
||||
if (getdns_dict_get_bindata(
|
||||
option, "option_data", &option_data))
|
||||
continue;
|
||||
|
||||
gldns_write_uint16(buf, (uint16_t) option_code);
|
||||
gldns_write_uint16(buf + 2,
|
||||
(uint16_t) option_data->size);
|
||||
(void) memcpy(buf + 4, option_data->data,
|
||||
option_data->size);
|
||||
|
||||
buf += option_data->size + 4;
|
||||
}
|
||||
} else
|
||||
net_req->opt = NULL;
|
||||
net_req->response = buf;
|
||||
gldns_write_uint16(net_req->wire_data, net_req->response - net_req->query);
|
||||
} else {
|
||||
net_req->query = NULL;
|
||||
net_req->opt = NULL;
|
||||
net_req->response = net_req->wire_data;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -83,9 +179,6 @@ dns_req_free(getdns_dns_req * req)
|
|||
return;
|
||||
}
|
||||
|
||||
/* free extensions */
|
||||
getdns_dict_destroy(req->extensions);
|
||||
|
||||
if (req->upstreams && --req->upstreams->referenced == 0)
|
||||
GETDNS_FREE(req->upstreams->mf, req->upstreams);
|
||||
|
||||
|
@ -109,11 +202,37 @@ 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_only_secure
|
||||
= is_extension_set(extensions, "dnssec_return_only_secure");
|
||||
int 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;
|
||||
|
||||
uint32_t edns_do_bit;
|
||||
int edns_maximum_udp_payload_size;
|
||||
uint32_t get_edns_maximum_udp_payload_size;
|
||||
uint32_t edns_extended_rcode;
|
||||
uint32_t edns_version;
|
||||
|
||||
getdns_dict *add_opt_parameters;
|
||||
int have_add_opt_parameters;
|
||||
|
||||
getdns_list *options;
|
||||
size_t noptions = 0;
|
||||
size_t i;
|
||||
|
||||
getdns_dict *option;
|
||||
uint32_t option_code;
|
||||
getdns_bindata *option_data;
|
||||
size_t opt_options_size = 0;
|
||||
|
||||
int with_opt;
|
||||
|
||||
getdns_dns_req *result = NULL;
|
||||
uint32_t klass = GLDNS_RR_CLASS_IN;
|
||||
size_t edns_maximum_udp_payload_size =
|
||||
getdns_get_maximum_udp_payload_size(context, extensions, NULL);
|
||||
int a_aaaa_query =
|
||||
is_extension_set(extensions, "return_both_v4_and_v6") &&
|
||||
( request_type == GETDNS_RRTYPE_A ||
|
||||
|
@ -122,12 +241,82 @@ dns_req_new(getdns_context *context, getdns_eventloop *loop,
|
|||
* (to test for udp overflow) (hence the + 1),
|
||||
* And align on the 8 byte boundry (hence the (x + 7) / 8 * 8)
|
||||
*/
|
||||
size_t netreq_sz = ( sizeof(getdns_network_req)
|
||||
+ edns_maximum_udp_payload_size + 1 + 7) / 8 * 8;
|
||||
size_t dnsreq_base_sz = ( sizeof(getdns_dns_req)
|
||||
+ (a_aaaa_query ? 3 : 2)
|
||||
* sizeof(getdns_network_req *));
|
||||
size_t max_query_sz, max_response_sz, netreq_sz, dnsreq_base_sz;
|
||||
uint8_t *region;
|
||||
|
||||
have_add_opt_parameters = getdns_dict_get_dict(extensions,
|
||||
"add_opt_parameters", &add_opt_parameters) == GETDNS_RETURN_GOOD;
|
||||
|
||||
if (dnssec_extension_set) {
|
||||
edns_maximum_udp_payload_size = -1;
|
||||
edns_extended_rcode = 0;
|
||||
edns_version = 0;
|
||||
edns_do_bit = 1;
|
||||
} else {
|
||||
edns_maximum_udp_payload_size =
|
||||
context->edns_maximum_udp_payload_size;
|
||||
edns_extended_rcode = context->edns_extended_rcode;
|
||||
edns_version = context->edns_version;
|
||||
edns_do_bit = context->edns_do_bit;
|
||||
|
||||
if (have_add_opt_parameters) {
|
||||
if (!getdns_dict_get_int(add_opt_parameters,
|
||||
"maximum_udp_payload_size",
|
||||
&get_edns_maximum_udp_payload_size))
|
||||
edns_maximum_udp_payload_size =
|
||||
get_edns_maximum_udp_payload_size;
|
||||
(void) getdns_dict_get_int(add_opt_parameters,
|
||||
"extended_rcode", &edns_extended_rcode);
|
||||
(void) getdns_dict_get_int(add_opt_parameters,
|
||||
"version", &edns_version);
|
||||
(void) getdns_dict_get_int(add_opt_parameters,
|
||||
"do_bit", &edns_do_bit);
|
||||
}
|
||||
}
|
||||
if (have_add_opt_parameters && getdns_dict_get_list(
|
||||
add_opt_parameters, "options", &options) == GETDNS_RETURN_GOOD)
|
||||
(void) getdns_list_get_length(options, &noptions);
|
||||
|
||||
with_opt = edns_do_bit != 0 || edns_maximum_udp_payload_size != -1 ||
|
||||
edns_extended_rcode != 0 || edns_version != 0 || noptions;
|
||||
|
||||
edns_maximum_udp_payload_size = with_opt &&
|
||||
( edns_maximum_udp_payload_size == -1 ||
|
||||
edns_maximum_udp_payload_size > 512 )
|
||||
? edns_maximum_udp_payload_size : 512;
|
||||
|
||||
/* (x + 7) / 8 * 8 to align on 8 byte boundries */
|
||||
if (context->resolution_type == GETDNS_RESOLUTION_RECURSING)
|
||||
max_query_sz = 0;
|
||||
else {
|
||||
for (i = 0; i < noptions; i++) {
|
||||
if (getdns_list_get_dict(options, i, &option)) continue;
|
||||
if (getdns_dict_get_int(
|
||||
option, "option_code", &option_code)) continue;
|
||||
if (getdns_dict_get_bindata(
|
||||
option, "option_data", &option_data)) continue;
|
||||
|
||||
opt_options_size += option_data->size
|
||||
+ 2 /* option-code */
|
||||
+ 2 /* option-length */
|
||||
;
|
||||
}
|
||||
max_query_sz = ( GLDNS_HEADER_SIZE
|
||||
+ strlen(name) + 1 + 4 /* dname always smaller then strlen(name) + 1 */
|
||||
+ 12 + opt_options_size /* space needed for OPT (if needed) */
|
||||
/* TODO: TSIG */
|
||||
+ 7) / 8 * 8;
|
||||
}
|
||||
max_response_sz = (( edns_maximum_udp_payload_size != -1
|
||||
? edns_maximum_udp_payload_size : 1432
|
||||
) + 1 /* +1 for udp overflow detection */
|
||||
+ 7 ) / 8 * 8;
|
||||
|
||||
netreq_sz = ( sizeof(getdns_network_req)
|
||||
+ max_query_sz + max_response_sz + 7 ) / 8 * 8;
|
||||
dnsreq_base_sz = (( sizeof(getdns_dns_req)
|
||||
+ (a_aaaa_query ? 3 : 2) * sizeof(getdns_network_req*)
|
||||
) + 7) / 8 * 8;
|
||||
|
||||
if (! (region = GETDNS_XMALLOC(context->mf, uint8_t,
|
||||
dnsreq_base_sz + (a_aaaa_query ? 2 : 1) * netreq_sz)))
|
||||
|
@ -148,9 +337,9 @@ dns_req_new(getdns_context *context, getdns_eventloop *loop,
|
|||
result->loop = loop;
|
||||
result->canceled = 0;
|
||||
result->trans_id = (uint64_t)(((intptr_t) result) ^ ldns_get_random());
|
||||
|
||||
getdns_dict_copy(extensions, &result->extensions);
|
||||
result->return_dnssec_status = context->return_dnssec_status;
|
||||
result->dnssec_return_status = dnssec_return_status;
|
||||
result->dnssec_return_only_secure = dnssec_return_only_secure;
|
||||
result->dnssec_return_validation_chain = dnssec_return_validation_chain;
|
||||
|
||||
/* will be set by caller */
|
||||
result->user_pointer = NULL;
|
||||
|
@ -164,14 +353,23 @@ dns_req_new(getdns_context *context, getdns_eventloop *loop,
|
|||
if (result->upstreams)
|
||||
result->upstreams->referenced++;
|
||||
|
||||
network_req_init(result->netreqs[0], result, request_type,
|
||||
klass, netreq_sz - sizeof(getdns_network_req));
|
||||
network_req_init(result->netreqs[0], result,
|
||||
name, request_type, klass,
|
||||
dnssec_extension_set, with_opt,
|
||||
edns_maximum_udp_payload_size,
|
||||
edns_extended_rcode, edns_version, edns_do_bit,
|
||||
opt_options_size, noptions, options,
|
||||
netreq_sz - sizeof(getdns_network_req), max_query_sz);
|
||||
|
||||
if (a_aaaa_query)
|
||||
network_req_init(result->netreqs[1], result,
|
||||
network_req_init(result->netreqs[1], result, name,
|
||||
( request_type == GETDNS_RRTYPE_A
|
||||
? GETDNS_RRTYPE_AAAA : GETDNS_RRTYPE_A ),
|
||||
klass, netreq_sz - sizeof(getdns_network_req));
|
||||
? GETDNS_RRTYPE_AAAA : GETDNS_RRTYPE_A ), klass,
|
||||
dnssec_extension_set, with_opt,
|
||||
edns_maximum_udp_payload_size,
|
||||
edns_extended_rcode, edns_version, edns_do_bit,
|
||||
opt_options_size, noptions, options,
|
||||
netreq_sz - sizeof(getdns_network_req), max_query_sz);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
326
src/stub.c
326
src/stub.c
|
@ -43,218 +43,6 @@
|
|||
#include "util-internal.h"
|
||||
#include "general.h"
|
||||
|
||||
static int
|
||||
getdns_make_query_pkt_buf(const getdns_network_req *netreq, uint8_t *buf,
|
||||
size_t *olen, uint16_t *omax_udp_payload_size)
|
||||
{
|
||||
size_t len;
|
||||
|
||||
getdns_dns_req *dnsreq = netreq->owner;
|
||||
getdns_context *context = dnsreq->context;
|
||||
getdns_dict *extensions = dnsreq->extensions;
|
||||
|
||||
int dnssec_return_status
|
||||
= is_extension_set(extensions, "dnssec_return_status");
|
||||
int 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");
|
||||
int dnssec_extension_set = dnssec_return_status
|
||||
|| dnssec_return_only_secure || dnssec_return_validation_chain;
|
||||
|
||||
uint32_t edns_do_bit;
|
||||
int edns_maximum_udp_payload_size;
|
||||
uint32_t get_edns_maximum_udp_payload_size;
|
||||
uint32_t edns_extended_rcode;
|
||||
uint32_t edns_version;
|
||||
|
||||
getdns_dict *add_opt_parameters;
|
||||
int have_add_opt_parameters;
|
||||
|
||||
getdns_list *options;
|
||||
size_t noptions = 0;
|
||||
size_t i;
|
||||
|
||||
getdns_dict *option;
|
||||
uint32_t option_code;
|
||||
getdns_bindata *option_data;
|
||||
size_t opt_options_size = 0;
|
||||
|
||||
int with_opt;
|
||||
int r;
|
||||
size_t dname_len;
|
||||
|
||||
have_add_opt_parameters = getdns_dict_get_dict(extensions,
|
||||
"add_opt_parameters", &add_opt_parameters) == GETDNS_RETURN_GOOD;
|
||||
|
||||
if (dnssec_extension_set) {
|
||||
edns_maximum_udp_payload_size =
|
||||
netreq->upstream->addr.ss_family == AF_INET6 ? 1232 : 1432;
|
||||
edns_extended_rcode = 0;
|
||||
edns_version = 0;
|
||||
edns_do_bit = 1;
|
||||
} else {
|
||||
edns_maximum_udp_payload_size =
|
||||
context->edns_maximum_udp_payload_size;
|
||||
edns_extended_rcode = context->edns_extended_rcode;
|
||||
edns_version = context->edns_version;
|
||||
edns_do_bit = context->edns_do_bit;
|
||||
|
||||
if (have_add_opt_parameters) {
|
||||
if (!getdns_dict_get_int(add_opt_parameters,
|
||||
"maximum_udp_payload_size",
|
||||
&get_edns_maximum_udp_payload_size))
|
||||
edns_maximum_udp_payload_size =
|
||||
get_edns_maximum_udp_payload_size;
|
||||
(void) getdns_dict_get_int(add_opt_parameters,
|
||||
"extended_rcode", &edns_extended_rcode);
|
||||
(void) getdns_dict_get_int(add_opt_parameters,
|
||||
"version", &edns_version);
|
||||
(void) getdns_dict_get_int(add_opt_parameters,
|
||||
"do_bit", &edns_do_bit);
|
||||
}
|
||||
}
|
||||
if (have_add_opt_parameters && getdns_dict_get_list(
|
||||
add_opt_parameters, "options", &options) == GETDNS_RETURN_GOOD)
|
||||
(void) getdns_list_get_length(options, &noptions);
|
||||
|
||||
with_opt = edns_do_bit != 0 || edns_maximum_udp_payload_size != -1 ||
|
||||
edns_extended_rcode != 0 || edns_version != 0 || noptions;
|
||||
|
||||
*omax_udp_payload_size = edns_maximum_udp_payload_size =
|
||||
! with_opt ? 512
|
||||
: edns_maximum_udp_payload_size == -1 ?
|
||||
netreq->upstream->addr.ss_family==AF_INET6 ? 1232 : 1432
|
||||
: edns_maximum_udp_payload_size > 512 ?
|
||||
edns_maximum_udp_payload_size : 512;
|
||||
|
||||
assert(buf);
|
||||
assert(olen);
|
||||
|
||||
len = *olen;
|
||||
*olen = 0;
|
||||
|
||||
if (len < GLDNS_HEADER_SIZE)
|
||||
return GLDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL;
|
||||
|
||||
gldns_write_uint16(buf + 2, 0); /* reset all flags */
|
||||
GLDNS_RD_SET(buf);
|
||||
if (dnssec_extension_set) /* We will do validation outselves */
|
||||
GLDNS_CD_SET(buf);
|
||||
GLDNS_OPCODE_SET(buf, GLDNS_PACKET_QUERY);
|
||||
gldns_write_uint16(buf + GLDNS_QDCOUNT_OFF, 1); /* 1 query */
|
||||
gldns_write_uint16(buf + GLDNS_ANCOUNT_OFF, 0); /* 0 answers */
|
||||
gldns_write_uint16(buf + GLDNS_NSCOUNT_OFF, 0); /* 0 authorities */
|
||||
gldns_write_uint16(buf + GLDNS_ARCOUNT_OFF, with_opt ? 1 : 0);
|
||||
|
||||
len -= GLDNS_HEADER_SIZE;
|
||||
*olen += GLDNS_HEADER_SIZE;
|
||||
buf += GLDNS_HEADER_SIZE;
|
||||
|
||||
dname_len = len;
|
||||
if ((r = gldns_str2wire_dname_buf(dnsreq->name, buf, &dname_len)))
|
||||
return r;
|
||||
len -= dname_len;
|
||||
*olen += dname_len;
|
||||
buf += dname_len;
|
||||
|
||||
if (len < 4)
|
||||
return GLDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL;
|
||||
gldns_write_uint16(buf, netreq->request_type);
|
||||
gldns_write_uint16(buf + 2, netreq->request_class);
|
||||
len -= 4;
|
||||
*olen += 4;
|
||||
buf += 4;
|
||||
|
||||
if (with_opt) {
|
||||
if (len < 11)
|
||||
return GLDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL;
|
||||
|
||||
buf[0] = 0; /* dname for . */
|
||||
gldns_write_uint16(buf + 1, GLDNS_RR_TYPE_OPT);
|
||||
gldns_write_uint16(buf + 3,
|
||||
(uint16_t) edns_maximum_udp_payload_size);
|
||||
buf[5] = (uint8_t) edns_extended_rcode;
|
||||
buf[6] = (uint8_t) edns_version;
|
||||
buf[7] = edns_do_bit ? 0x80 : 0;
|
||||
buf[8] = 0;
|
||||
gldns_write_uint16(buf + 9, (uint16_t) opt_options_size);
|
||||
len -= 11;
|
||||
*olen += 11;
|
||||
buf += 11;
|
||||
for (i = 0; i < noptions; i++) {
|
||||
if (getdns_list_get_dict(options, i, &option))
|
||||
continue;
|
||||
if (getdns_dict_get_int(
|
||||
option, "option_code", &option_code)) continue;
|
||||
if (getdns_dict_get_bindata(
|
||||
option, "option_data", &option_data)) continue;
|
||||
|
||||
if (len < option_data->size + 4) {
|
||||
gldns_write_uint16(buf - opt_options_size - 2,
|
||||
(uint16_t) opt_options_size);
|
||||
return GLDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL;
|
||||
}
|
||||
gldns_write_uint16(buf, (uint16_t) option_code);
|
||||
gldns_write_uint16(buf + 2,
|
||||
(uint16_t) option_data->size);
|
||||
(void) memcpy(buf + 4, option_data->data,
|
||||
option_data->size);
|
||||
|
||||
opt_options_size += option_data->size + 4;
|
||||
len -= option_data->size + 4;
|
||||
*olen += option_data->size + 4;
|
||||
buf += option_data->size + 4;
|
||||
}
|
||||
gldns_write_uint16(buf - opt_options_size - 2,
|
||||
(uint16_t) opt_options_size);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Return a rough estimate for mallocs */
|
||||
static size_t
|
||||
getdns_get_query_pkt_size(getdns_context *context,
|
||||
const char *name, uint16_t request_type, getdns_dict *extensions)
|
||||
{
|
||||
getdns_dict *add_opt_parameters;
|
||||
|
||||
getdns_list *options;
|
||||
size_t noptions = 0;
|
||||
size_t i;
|
||||
|
||||
getdns_dict *option;
|
||||
uint32_t option_code;
|
||||
getdns_bindata *option_data;
|
||||
size_t opt_options_size = 0;
|
||||
|
||||
do {
|
||||
if (getdns_dict_get_dict(extensions,
|
||||
"add_opt_parameters", &add_opt_parameters)) break;
|
||||
if (getdns_dict_get_list(
|
||||
add_opt_parameters, "options", &options)) break;
|
||||
if (getdns_list_get_length(options, &noptions)) break;
|
||||
|
||||
for (i = 0; i < noptions; i++) {
|
||||
if (getdns_list_get_dict(options, i, &option)) continue;
|
||||
if (getdns_dict_get_int(
|
||||
option, "option_code", &option_code)) continue;
|
||||
if (getdns_dict_get_bindata(
|
||||
option, "option_data", &option_data)) continue;
|
||||
|
||||
opt_options_size += option_data->size
|
||||
+ 2 /* option-code */
|
||||
+ 2 /* option-length */
|
||||
;
|
||||
}
|
||||
} while (0);
|
||||
|
||||
return GLDNS_HEADER_SIZE
|
||||
+ strlen(name) + 1 + 4 /* dname always smaller then strlen(name) + 1 */
|
||||
+ 12 + opt_options_size /* space needed for OPT (if needed) */
|
||||
/* TODO: TSIG */
|
||||
;
|
||||
}
|
||||
|
||||
/** best effort to set nonblocking */
|
||||
static void
|
||||
|
@ -299,7 +87,6 @@ stub_cleanup(getdns_network_req *netreq)
|
|||
|
||||
GETDNS_CLEAR_EVENT(dnsreq->loop, &netreq->event);
|
||||
|
||||
GETDNS_NULL_FREE(dnsreq->context->mf, netreq->tcp.write_buf);
|
||||
GETDNS_NULL_FREE(dnsreq->context->mf, netreq->tcp.read_buf);
|
||||
|
||||
/* Nothing globally scheduled? Then nothing queued */
|
||||
|
@ -467,46 +254,29 @@ static void
|
|||
stub_udp_write_cb(void *userarg)
|
||||
{
|
||||
getdns_network_req *netreq = (getdns_network_req *)userarg;
|
||||
getdns_dns_req *dnsreq = netreq->owner;
|
||||
|
||||
static size_t pkt_buf_len = 4096;
|
||||
uint8_t pkt_buf[pkt_buf_len];
|
||||
uint8_t *pkt = pkt_buf;
|
||||
size_t pkt_len;
|
||||
size_t pkt_size_needed;
|
||||
getdns_dns_req *dnsreq = netreq->owner;
|
||||
size_t pkt_len = netreq->response - netreq->query;
|
||||
|
||||
GETDNS_CLEAR_EVENT(dnsreq->loop, &netreq->event);
|
||||
|
||||
pkt_size_needed = getdns_get_query_pkt_size(dnsreq->context,
|
||||
dnsreq->name, netreq->request_type, dnsreq->extensions);
|
||||
|
||||
if (pkt_size_needed > pkt_buf_len) {
|
||||
pkt = GETDNS_XMALLOC(
|
||||
dnsreq->context->mf, uint8_t, pkt_size_needed);
|
||||
pkt_len = pkt_size_needed;
|
||||
} else
|
||||
pkt_len = pkt_buf_len;
|
||||
|
||||
if (getdns_make_query_pkt_buf(netreq, pkt_buf, &pkt_len,
|
||||
&netreq->max_udp_payload_size))
|
||||
goto exit;
|
||||
|
||||
netreq->query_id = ldns_get_random();
|
||||
GLDNS_ID_SET(pkt, netreq->query_id);
|
||||
GLDNS_ID_SET(netreq->query, netreq->query_id);
|
||||
if (netreq->edns_maximum_udp_payload_size == -1)
|
||||
gldns_write_uint16(netreq->opt + 3,
|
||||
( netreq->max_udp_payload_size =
|
||||
netreq->upstream->addr.ss_family == AF_INET6
|
||||
? 1232 : 1432));
|
||||
|
||||
if ((ssize_t)pkt_len != sendto(netreq->fd, pkt, pkt_len, 0,
|
||||
if ((ssize_t)pkt_len != sendto(netreq->fd, netreq->query, pkt_len, 0,
|
||||
(struct sockaddr *)&netreq->upstream->addr,
|
||||
netreq->upstream->addr_len)) {
|
||||
close(netreq->fd);
|
||||
goto exit;
|
||||
return;
|
||||
}
|
||||
GETDNS_SCHEDULE_EVENT(
|
||||
dnsreq->loop, netreq->fd, dnsreq->context->timeout,
|
||||
getdns_eventloop_event_init(&netreq->event, netreq,
|
||||
stub_udp_read_cb, NULL, stub_timeout_cb));
|
||||
exit:
|
||||
if (pkt && pkt != pkt_buf)
|
||||
GETDNS_FREE(dnsreq->context->mf, pkt);
|
||||
}
|
||||
|
||||
static getdns_upstream *
|
||||
|
@ -735,47 +505,15 @@ stub_tcp_write(int fd, getdns_tcp_state *tcp, getdns_network_req *netreq)
|
|||
{
|
||||
getdns_dns_req *dnsreq = netreq->owner;
|
||||
|
||||
static size_t pkt_buf_len = 4096;
|
||||
uint8_t pkt_buf[pkt_buf_len];
|
||||
uint8_t *pkt = pkt_buf;
|
||||
size_t pkt_len;
|
||||
size_t query_pkt_size;
|
||||
|
||||
size_t pkt_len = netreq->response - netreq->query;
|
||||
ssize_t written;
|
||||
uint16_t query_id;
|
||||
intptr_t query_id_intptr;
|
||||
|
||||
/* Do we have remaining data that we could not write before? */
|
||||
if (! tcp->write_buf) {
|
||||
/* No, this is an initial write.
|
||||
* Create packet and try to send
|
||||
/* No, this is an initial write. Try to send
|
||||
*/
|
||||
query_pkt_size = getdns_get_query_pkt_size(dnsreq->context,
|
||||
dnsreq->name, netreq->request_type, dnsreq->extensions);
|
||||
|
||||
if (query_pkt_size + 2 > pkt_buf_len) {
|
||||
/* Not enough space in out stack buffer.
|
||||
* Allocate a buffer on the heap.
|
||||
*/
|
||||
if (!(pkt = GETDNS_XMALLOC(dnsreq->context->mf,
|
||||
uint8_t, query_pkt_size + 2)))
|
||||
return STUB_TCP_ERROR;
|
||||
|
||||
tcp->write_buf = pkt;
|
||||
tcp->write_buf_len = query_pkt_size + 2;
|
||||
tcp->written = 0;
|
||||
|
||||
pkt_len = query_pkt_size;
|
||||
} else
|
||||
pkt_len = pkt_buf_len - 2;
|
||||
|
||||
/* Construct query packet */
|
||||
if (getdns_make_query_pkt_buf(netreq, pkt + 2, &pkt_len,
|
||||
&netreq->max_udp_payload_size))
|
||||
return STUB_TCP_ERROR;
|
||||
|
||||
/* Prepend length short */
|
||||
gldns_write_uint16(pkt, pkt_len);
|
||||
|
||||
/* Not keeping connections open? Then the first random number
|
||||
* will do as the query id.
|
||||
|
@ -796,20 +534,23 @@ stub_tcp_write(int fd, getdns_tcp_state *tcp, getdns_network_req *netreq)
|
|||
} while (!getdns_rbtree_insert(
|
||||
&netreq->upstream->netreq_by_query_id, &netreq->node));
|
||||
|
||||
GLDNS_ID_SET(pkt + 2, query_id);
|
||||
GLDNS_ID_SET(netreq->query, query_id);
|
||||
gldns_write_uint16(netreq->opt + 3, 65535); /* no limits on the
|
||||
max udp payload
|
||||
size with tcp */
|
||||
|
||||
/* We have an initialized packet buffer.
|
||||
* Lets see how much of it we can write
|
||||
*/
|
||||
#ifdef USE_TCP_FASTOPEN
|
||||
/* We use sendto() here which will do both a connect and send */
|
||||
written = sendto(fd, pkt, pkt_len + 2, MSG_FASTOPEN,
|
||||
(struct sockaddr *)&(netreq->upstream->addr),
|
||||
netreq->upstream->addr_len);
|
||||
written = sendto(fd, netreq->query - 2, pkt_len + 2,
|
||||
MSG_FASTOPEN, (struct sockaddr *)&(netreq->upstream->addr),
|
||||
netreq->upstream->addr_len);
|
||||
/* If pipelining we will find that the connection is already up so
|
||||
just fall back to a 'normal' write. */
|
||||
if (written == -1 && errno == EISCONN)
|
||||
written = write(fd, pkt, pkt_len + 2);
|
||||
written = write(fd, netreq->query - 2, pkt_len + 2);
|
||||
|
||||
if ((written == -1 && (errno == EAGAIN ||
|
||||
errno == EWOULDBLOCK ||
|
||||
|
@ -819,26 +560,17 @@ stub_tcp_write(int fd, getdns_tcp_state *tcp, getdns_network_req *netreq)
|
|||
errno == EINPROGRESS)) ||
|
||||
written < pkt_len + 2) {
|
||||
#else
|
||||
written = write(fd, pkt, pkt_len + 2);
|
||||
written = write(fd, netreq->query - 2, pkt_len + 2);
|
||||
if ((written == -1 && (errno == EAGAIN ||
|
||||
errno == EWOULDBLOCK)) ||
|
||||
written < pkt_len + 2) {
|
||||
#endif
|
||||
/* We couldn't write the whole packet.
|
||||
* We have to return with STUB_TCP_AGAIN, but if
|
||||
* the packet was on the stack only, we have to copy
|
||||
* it to heap space fist, because the stack will be
|
||||
* gone after return.
|
||||
* We have to return with STUB_TCP_AGAIN.
|
||||
* Setup tcp to track the state.
|
||||
*/
|
||||
if (!tcp->write_buf) {
|
||||
/* Copy stack packet buffer to heap */
|
||||
if (!(tcp->write_buf = GETDNS_XMALLOC(
|
||||
dnsreq->context->mf,uint8_t,pkt_len + 2)))
|
||||
return STUB_TCP_ERROR;
|
||||
(void) memcpy(tcp->write_buf, pkt, pkt_len + 2);
|
||||
tcp->write_buf_len = pkt_len + 2;
|
||||
}
|
||||
/* Because written could be -1 (and errno EAGAIN) */
|
||||
tcp->write_buf = netreq->query - 2;
|
||||
tcp->write_buf_len = pkt_len + 2;
|
||||
tcp->written = written >= 0 ? written : 0;
|
||||
|
||||
return STUB_TCP_AGAIN;
|
||||
|
@ -847,7 +579,7 @@ stub_tcp_write(int fd, getdns_tcp_state *tcp, getdns_network_req *netreq)
|
|||
return STUB_TCP_ERROR;
|
||||
|
||||
/* We were able to write everything! Start reading. */
|
||||
GETDNS_NULL_FREE(dnsreq->context->mf, tcp->write_buf);
|
||||
return (int) query_id;
|
||||
|
||||
} else {/* if (! tcp->write_buf) */
|
||||
|
||||
|
@ -867,12 +599,10 @@ stub_tcp_write(int fd, getdns_tcp_state *tcp, getdns_network_req *netreq)
|
|||
return STUB_TCP_AGAIN;
|
||||
|
||||
/* Done. Start reading */
|
||||
query_id = GLDNS_ID_WIRE(tcp->write_buf + 2);
|
||||
tcp->write_buf = NULL;
|
||||
return (int)GLDNS_ID_WIRE(tcp->write_buf + 2);
|
||||
|
||||
} /* if (! tcp->write_buf) */
|
||||
|
||||
GETDNS_NULL_FREE(dnsreq->context->mf, tcp->write_buf);
|
||||
return (int) query_id;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#include "types-internal.h"
|
||||
|
||||
getdns_return_t priv_getdns_submit_stub_request(getdns_network_req *netreq);
|
||||
|
||||
void priv_getdns_cancel_stub_request(getdns_network_req *netreq);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -198,6 +198,7 @@ typedef struct getdns_network_req
|
|||
getdns_tcp_state tcp;
|
||||
uint16_t query_id;
|
||||
|
||||
int edns_maximum_udp_payload_size;
|
||||
uint16_t max_udp_payload_size;
|
||||
|
||||
/* Network requests scheduled to write after me */
|
||||
|
@ -207,6 +208,9 @@ typedef struct getdns_network_req
|
|||
* available in wire_data[], it will be allocated seperately.
|
||||
* response will then not point to wire_data anymore.
|
||||
*/
|
||||
size_t query_len;
|
||||
uint8_t *query;
|
||||
uint8_t *opt; /* offset of OPT RR in query */
|
||||
uint8_t *response;
|
||||
size_t wire_data_sz;
|
||||
uint8_t wire_data[];
|
||||
|
@ -231,7 +235,9 @@ typedef struct getdns_dns_req {
|
|||
struct getdns_context *context;
|
||||
|
||||
/* request extensions */
|
||||
struct getdns_dict *extensions;
|
||||
int dnssec_return_status;
|
||||
int dnssec_return_only_secure;
|
||||
int dnssec_return_validation_chain;
|
||||
|
||||
/* event loop */
|
||||
getdns_eventloop *loop;
|
||||
|
@ -246,9 +252,6 @@ typedef struct getdns_dns_req {
|
|||
/* for scheduling timeouts when using libunbound */
|
||||
getdns_eventloop_event timeout;
|
||||
|
||||
/* dnssec status */
|
||||
int return_dnssec_status;
|
||||
|
||||
/* mem funcs */
|
||||
struct mem_funcs my_mf;
|
||||
|
||||
|
|
|
@ -536,13 +536,14 @@ rrsigs_in_answer(ldns_pkt *pkt)
|
|||
}
|
||||
|
||||
struct getdns_dict *
|
||||
create_getdns_response(struct getdns_dns_req * completed_request)
|
||||
create_getdns_response(getdns_dns_req *completed_request)
|
||||
{
|
||||
struct getdns_dict *result = getdns_dict_create_with_context(completed_request->context);
|
||||
struct getdns_list *replies_full = getdns_list_create_with_context(
|
||||
getdns_dict *result = getdns_dict_create_with_context(
|
||||
completed_request->context);
|
||||
struct getdns_list *just_addrs = NULL;
|
||||
struct getdns_list *replies_tree = getdns_list_create_with_context(
|
||||
getdns_list *replies_full = getdns_list_create_with_context(
|
||||
completed_request->context);
|
||||
getdns_list *just_addrs = NULL;
|
||||
getdns_list *replies_tree = getdns_list_create_with_context(
|
||||
completed_request->context);
|
||||
getdns_network_req *netreq, **netreq_p;
|
||||
char *canonical_name = NULL;
|
||||
|
@ -550,17 +551,10 @@ create_getdns_response(struct getdns_dns_req * completed_request)
|
|||
int nreplies = 0, nanswers = 0, nsecure = 0, ninsecure = 0, nbogus = 0;
|
||||
|
||||
/* info (bools) about dns_req */
|
||||
int dnssec_return_validation_chain;
|
||||
int dnssec_return_only_secure;
|
||||
int dnssec_return_status;
|
||||
|
||||
dnssec_return_validation_chain = is_extension_set(
|
||||
completed_request->extensions, "dnssec_return_validation_chain");
|
||||
dnssec_return_only_secure = is_extension_set(
|
||||
completed_request->extensions, "dnssec_return_only_secure");
|
||||
dnssec_return_status = dnssec_return_only_secure || is_extension_set(
|
||||
completed_request->extensions, "dnssec_return_status") ||
|
||||
completed_request->return_dnssec_status == GETDNS_EXTENSION_TRUE;
|
||||
dnssec_return_status = completed_request->dnssec_return_status ||
|
||||
completed_request->dnssec_return_only_secure;
|
||||
|
||||
if (completed_request->netreqs[0]->request_type == GETDNS_RRTYPE_A ||
|
||||
completed_request->netreqs[0]->request_type == GETDNS_RRTYPE_AAAA)
|
||||
|
@ -600,10 +594,10 @@ create_getdns_response(struct getdns_dns_req * completed_request)
|
|||
ldns_pkt_get_rcode(netreq->result))
|
||||
nanswers++;
|
||||
|
||||
if (! dnssec_return_validation_chain) {
|
||||
if (! completed_request->dnssec_return_validation_chain) {
|
||||
if (dnssec_return_status && netreq->bogus)
|
||||
continue;
|
||||
else if (dnssec_return_only_secure && ! netreq->secure)
|
||||
else if (completed_request->dnssec_return_only_secure && ! netreq->secure)
|
||||
continue;
|
||||
}
|
||||
struct getdns_bindata full_data;
|
||||
|
@ -626,7 +620,7 @@ create_getdns_response(struct getdns_dns_req * completed_request)
|
|||
r = GETDNS_RETURN_MEMORY_ERROR;
|
||||
break;
|
||||
}
|
||||
if (dnssec_return_status || dnssec_return_validation_chain) {
|
||||
if (dnssec_return_status || completed_request->dnssec_return_validation_chain) {
|
||||
r = getdns_dict_set_int(reply, "dnssec_status",
|
||||
( netreq->secure ? GETDNS_DNSSEC_SECURE
|
||||
: netreq->bogus ? GETDNS_DNSSEC_BOGUS
|
||||
|
@ -692,9 +686,9 @@ create_getdns_response(struct getdns_dns_req * completed_request)
|
|||
}
|
||||
r = getdns_dict_set_int(result, GETDNS_STR_KEY_STATUS,
|
||||
nreplies == 0 ? GETDNS_RESPSTATUS_ALL_TIMEOUT :
|
||||
dnssec_return_only_secure && nsecure == 0 && ninsecure > 0
|
||||
completed_request->dnssec_return_only_secure && nsecure == 0 && ninsecure > 0
|
||||
? GETDNS_RESPSTATUS_NO_SECURE_ANSWERS :
|
||||
dnssec_return_only_secure && nsecure == 0 && nbogus > 0
|
||||
completed_request->dnssec_return_only_secure && nsecure == 0 && nbogus > 0
|
||||
? GETDNS_RESPSTATUS_ALL_BOGUS_ANSWERS :
|
||||
nanswers == 0 ? GETDNS_RESPSTATUS_NO_NAME
|
||||
: GETDNS_RESPSTATUS_GOOD);
|
||||
|
@ -956,89 +950,5 @@ validate_dname(const char* dname) {
|
|||
return GETDNS_RETURN_GOOD;
|
||||
} /* validate_dname */
|
||||
|
||||
int
|
||||
is_extension_set(getdns_dict *extensions, const char *extension)
|
||||
{
|
||||
getdns_return_t r;
|
||||
uint32_t value;
|
||||
|
||||
if (! extensions)
|
||||
return 0;
|
||||
|
||||
r = getdns_dict_get_int(extensions, extension, &value);
|
||||
return r == GETDNS_RETURN_GOOD && value == GETDNS_EXTENSION_TRUE;
|
||||
}
|
||||
|
||||
size_t
|
||||
getdns_get_maximum_udp_payload_size(getdns_context *context,
|
||||
getdns_dict *extensions, getdns_upstream *upstream)
|
||||
{
|
||||
int dnssec_return_status
|
||||
= is_extension_set(extensions, "dnssec_return_status");
|
||||
int 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");
|
||||
int dnssec_extension_set = dnssec_return_status
|
||||
|| dnssec_return_only_secure || dnssec_return_validation_chain;
|
||||
|
||||
uint32_t edns_do_bit;
|
||||
int edns_maximum_udp_payload_size;
|
||||
uint32_t get_edns_maximum_udp_payload_size;
|
||||
uint32_t edns_extended_rcode;
|
||||
uint32_t edns_version;
|
||||
|
||||
getdns_dict *add_opt_parameters;
|
||||
int have_add_opt_parameters;
|
||||
|
||||
getdns_list *options;
|
||||
size_t noptions = 0;
|
||||
|
||||
int with_opt;
|
||||
|
||||
have_add_opt_parameters = getdns_dict_get_dict(extensions,
|
||||
"add_opt_parameters", &add_opt_parameters) == GETDNS_RETURN_GOOD;
|
||||
|
||||
if (dnssec_extension_set) {
|
||||
edns_maximum_udp_payload_size =
|
||||
( upstream && upstream->addr.ss_family == AF_INET6 )
|
||||
? 1232 : 1432;
|
||||
edns_extended_rcode = 0;
|
||||
edns_version = 0;
|
||||
edns_do_bit = 1;
|
||||
} else {
|
||||
edns_maximum_udp_payload_size =
|
||||
context->edns_maximum_udp_payload_size;
|
||||
edns_extended_rcode = context->edns_extended_rcode;
|
||||
edns_version = context->edns_version;
|
||||
edns_do_bit = context->edns_do_bit;
|
||||
|
||||
if (have_add_opt_parameters) {
|
||||
if (!getdns_dict_get_int(add_opt_parameters,
|
||||
"maximum_udp_payload_size",
|
||||
&get_edns_maximum_udp_payload_size))
|
||||
edns_maximum_udp_payload_size =
|
||||
get_edns_maximum_udp_payload_size;
|
||||
(void) getdns_dict_get_int(add_opt_parameters,
|
||||
"extended_rcode", &edns_extended_rcode);
|
||||
(void) getdns_dict_get_int(add_opt_parameters,
|
||||
"version", &edns_version);
|
||||
(void) getdns_dict_get_int(add_opt_parameters,
|
||||
"do_bit", &edns_do_bit);
|
||||
}
|
||||
}
|
||||
if (have_add_opt_parameters && getdns_dict_get_list(
|
||||
add_opt_parameters, "options", &options) == GETDNS_RETURN_GOOD)
|
||||
(void) getdns_list_get_length(options, &noptions);
|
||||
|
||||
with_opt = edns_do_bit != 0 || edns_maximum_udp_payload_size != -1 ||
|
||||
edns_extended_rcode != 0 || edns_version != 0 || noptions;
|
||||
|
||||
return ! with_opt ? 512
|
||||
: edns_maximum_udp_payload_size == -1 ?
|
||||
(upstream && upstream->addr.ss_family==AF_INET6 ) ? 1232 : 1432
|
||||
: edns_maximum_udp_payload_size > 512 ?
|
||||
edns_maximum_udp_payload_size : 512;
|
||||
}
|
||||
|
||||
/* util-internal.c */
|
||||
|
|
|
@ -139,18 +139,6 @@ getdns_return_t validate_extensions(struct getdns_dict * extensions);
|
|||
struct getdns_list *
|
||||
create_list_from_rr_list(struct getdns_context *context, ldns_rr_list * rr_list);
|
||||
|
||||
/**
|
||||
* helper to check if an extension is set.
|
||||
* Should only be called for "boolean" type extensions that have a value of
|
||||
* GETDNS_EXTENSION_TRUE or GETDNS_EXTENSION_FALSE
|
||||
* @param extensions extensions dictionary
|
||||
* @param extension name of extension to check
|
||||
* @return int with value 1 if set to GETDNS_EXTENSION_TRUE and 0 otherwise
|
||||
*/
|
||||
int is_extension_set(getdns_dict *extensions, const char *extension);
|
||||
|
||||
size_t getdns_get_maximum_udp_payload_size(getdns_context *context,
|
||||
getdns_dict *extensions, getdns_upstream *upstream);
|
||||
|
||||
#define DEBUG_ON(...) do { \
|
||||
struct timeval tv; \
|
||||
|
|
Loading…
Reference in New Issue