mirror of https://github.com/getdnsapi/getdns.git
Re-factor of internal handing of transport list.
This commit is contained in:
parent
0acdcc34b0
commit
635cf9e182
228
src/context.c
228
src/context.c
|
@ -69,11 +69,15 @@ typedef struct host_name_addrs {
|
||||||
uint8_t host_name[];
|
uint8_t host_name[];
|
||||||
} host_name_addrs;
|
} host_name_addrs;
|
||||||
|
|
||||||
|
static getdns_transport_list_t
|
||||||
|
getdns_upstream_transports[GETDNS_UPSTREAM_TRANSPORTS] = {
|
||||||
|
GETDNS_TRANSPORT_TCP,
|
||||||
|
GETDNS_TRANSPORT_TLS,
|
||||||
|
GETDNS_TRANSPORT_STARTTLS
|
||||||
|
};
|
||||||
|
|
||||||
static in_port_t
|
static in_port_t
|
||||||
getdns_port_array[GETDNS_BASE_TRANSPORT_MAX] = {
|
getdns_port_array[GETDNS_UPSTREAM_TRANSPORTS] = {
|
||||||
GETDNS_PORT_ZERO,
|
|
||||||
GETDNS_PORT_ZERO,
|
|
||||||
GETDNS_PORT_ZERO,
|
|
||||||
GETDNS_PORT_DNS,
|
GETDNS_PORT_DNS,
|
||||||
GETDNS_PORT_DNS,
|
GETDNS_PORT_DNS,
|
||||||
GETDNS_PORT_DNS_OVER_TLS
|
GETDNS_PORT_DNS_OVER_TLS
|
||||||
|
@ -81,9 +85,6 @@ getdns_port_array[GETDNS_BASE_TRANSPORT_MAX] = {
|
||||||
|
|
||||||
char*
|
char*
|
||||||
getdns_port_str_array[] = {
|
getdns_port_str_array[] = {
|
||||||
GETDNS_STR_PORT_ZERO,
|
|
||||||
GETDNS_STR_PORT_ZERO,
|
|
||||||
GETDNS_STR_PORT_ZERO,
|
|
||||||
GETDNS_STR_PORT_DNS,
|
GETDNS_STR_PORT_DNS,
|
||||||
GETDNS_STR_PORT_DNS,
|
GETDNS_STR_PORT_DNS,
|
||||||
GETDNS_STR_PORT_DNS_OVER_TLS
|
GETDNS_STR_PORT_DNS_OVER_TLS
|
||||||
|
@ -91,6 +92,7 @@ getdns_port_str_array[] = {
|
||||||
|
|
||||||
/* Private functions */
|
/* Private functions */
|
||||||
getdns_return_t create_default_namespaces(struct getdns_context *context);
|
getdns_return_t create_default_namespaces(struct getdns_context *context);
|
||||||
|
getdns_return_t create_default_dns_transports(struct getdns_context *context);
|
||||||
static struct getdns_list *create_default_root_servers(void);
|
static struct getdns_list *create_default_root_servers(void);
|
||||||
static getdns_return_t set_os_defaults(struct getdns_context *);
|
static getdns_return_t set_os_defaults(struct getdns_context *);
|
||||||
static int transaction_id_cmp(const void *, const void *);
|
static int transaction_id_cmp(const void *, const void *);
|
||||||
|
@ -139,42 +141,22 @@ create_default_namespaces(struct getdns_context *context)
|
||||||
return GETDNS_RETURN_GOOD;
|
return GETDNS_RETURN_GOOD;
|
||||||
}
|
}
|
||||||
|
|
||||||
static getdns_transport_list_t *
|
/**
|
||||||
get_dns_transport_list(getdns_context *context, int *count)
|
* Helper to get default transports.
|
||||||
|
*/
|
||||||
|
getdns_return_t
|
||||||
|
create_default_dns_transports(struct getdns_context *context)
|
||||||
{
|
{
|
||||||
if (context == NULL)
|
context->dns_transports = GETDNS_XMALLOC(context->my_mf, getdns_transport_list_t, 2);
|
||||||
return NULL;
|
if(context->dns_transports == NULL)
|
||||||
|
return GETDNS_RETURN_GENERIC_ERROR;
|
||||||
|
|
||||||
/* Count how many we have*/
|
context->dns_transports[0] = GETDNS_TRANSPORT_UDP;
|
||||||
for (*count = 0; *count < GETDNS_BASE_TRANSPORT_MAX; (*count)++) {
|
context->dns_transports[1] = GETDNS_TRANSPORT_TCP;
|
||||||
if (context->dns_base_transports[*count] == GETDNS_BASE_TRANSPORT_NONE)
|
context->dns_transport_count = 2;
|
||||||
break;
|
context->dns_transport_current = 0;
|
||||||
}
|
|
||||||
|
|
||||||
// use normal malloc here so users can do normal free
|
return GETDNS_RETURN_GOOD;
|
||||||
getdns_transport_list_t * transports = malloc(*count * sizeof(getdns_transport_list_t));
|
|
||||||
|
|
||||||
if(transports == NULL)
|
|
||||||
return NULL;
|
|
||||||
for (int i = 0; i < (int)*count; i++) {
|
|
||||||
switch(context->dns_base_transports[i]) {
|
|
||||||
case GETDNS_BASE_TRANSPORT_UDP:
|
|
||||||
transports[i] = GETDNS_TRANSPORT_UDP;
|
|
||||||
break;
|
|
||||||
case GETDNS_BASE_TRANSPORT_TCP:
|
|
||||||
transports[i] = GETDNS_TRANSPORT_TCP;
|
|
||||||
break;
|
|
||||||
case GETDNS_BASE_TRANSPORT_TLS:
|
|
||||||
transports[i] = GETDNS_TRANSPORT_TLS;
|
|
||||||
break;
|
|
||||||
case GETDNS_BASE_TRANSPORT_STARTTLS:
|
|
||||||
transports[i] = GETDNS_TRANSPORT_STARTTLS;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return transports;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void canonicalize_dname(uint8_t *dname)
|
static inline void canonicalize_dname(uint8_t *dname)
|
||||||
|
@ -621,7 +603,7 @@ upstream_init(getdns_upstream *upstream,
|
||||||
upstream->fd = -1;
|
upstream->fd = -1;
|
||||||
upstream->tls_obj = NULL;
|
upstream->tls_obj = NULL;
|
||||||
upstream->starttls_req = NULL;
|
upstream->starttls_req = NULL;
|
||||||
upstream->dns_base_transport = GETDNS_BASE_TRANSPORT_TCP;
|
upstream->transport = GETDNS_TRANSPORT_TCP;
|
||||||
upstream->tls_hs_state = GETDNS_HS_NONE;
|
upstream->tls_hs_state = GETDNS_HS_NONE;
|
||||||
upstream->loop = NULL;
|
upstream->loop = NULL;
|
||||||
(void) getdns_eventloop_event_init(
|
(void) getdns_eventloop_event_init(
|
||||||
|
@ -725,11 +707,8 @@ set_os_defaults(struct getdns_context *context)
|
||||||
token = parse + strcspn(parse, " \t\r\n");
|
token = parse + strcspn(parse, " \t\r\n");
|
||||||
*token = 0;
|
*token = 0;
|
||||||
|
|
||||||
getdns_base_transport_t base_transport = GETDNS_BASE_TRANSPORT_MIN;
|
for (size_t i = 0; i < GETDNS_UPSTREAM_TRANSPORTS; i++) {
|
||||||
for (; base_transport < GETDNS_BASE_TRANSPORT_MAX; base_transport++) {
|
char *port_str = getdns_port_str_array[i];
|
||||||
char *port_str = getdns_port_str_array[base_transport];
|
|
||||||
if (strncmp(port_str, GETDNS_STR_PORT_ZERO, 1) == 0)
|
|
||||||
continue;
|
|
||||||
if ((s = getaddrinfo(parse, port_str, &hints, &result)))
|
if ((s = getaddrinfo(parse, port_str, &hints, &result)))
|
||||||
continue;
|
continue;
|
||||||
if (!result)
|
if (!result)
|
||||||
|
@ -743,7 +722,7 @@ set_os_defaults(struct getdns_context *context)
|
||||||
upstream = &context->upstreams->
|
upstream = &context->upstreams->
|
||||||
upstreams[context->upstreams->count++];
|
upstreams[context->upstreams->count++];
|
||||||
upstream_init(upstream, context->upstreams, result);
|
upstream_init(upstream, context->upstreams, result);
|
||||||
upstream->dns_base_transport = base_transport;
|
upstream->transport = getdns_upstream_transports[i];
|
||||||
freeaddrinfo(result);
|
freeaddrinfo(result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -873,8 +852,8 @@ getdns_context_create_with_extended_memory_functions(
|
||||||
|
|
||||||
result->dnssec_allowed_skew = 0;
|
result->dnssec_allowed_skew = 0;
|
||||||
result->edns_maximum_udp_payload_size = -1;
|
result->edns_maximum_udp_payload_size = -1;
|
||||||
result->dns_base_transports[0] = GETDNS_BASE_TRANSPORT_UDP;
|
if ((r = create_default_dns_transports(result)))
|
||||||
result->dns_base_transports[1] = GETDNS_BASE_TRANSPORT_TCP;
|
goto error;
|
||||||
result->limit_outstanding_queries = 0;
|
result->limit_outstanding_queries = 0;
|
||||||
result->has_ta = priv_getdns_parse_ta_file(NULL, NULL);
|
result->has_ta = priv_getdns_parse_ta_file(NULL, NULL);
|
||||||
result->return_dnssec_status = GETDNS_EXTENSION_FALSE;
|
result->return_dnssec_status = GETDNS_EXTENSION_FALSE;
|
||||||
|
@ -1201,33 +1180,32 @@ static getdns_return_t
|
||||||
getdns_set_base_dns_transports(struct getdns_context *context,
|
getdns_set_base_dns_transports(struct getdns_context *context,
|
||||||
size_t transport_count, getdns_transport_list_t *transports)
|
size_t transport_count, getdns_transport_list_t *transports)
|
||||||
{
|
{
|
||||||
|
size_t i;
|
||||||
|
|
||||||
RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER);
|
RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER);
|
||||||
for (int i = 0; i < GETDNS_BASE_TRANSPORT_MAX; i++)
|
if (transport_count == 0 || transports == NULL) {
|
||||||
context->dns_base_transports[i] = GETDNS_BASE_TRANSPORT_NONE;
|
|
||||||
|
|
||||||
if ((int)transport_count == 0 || transports == NULL ||
|
|
||||||
(int)transport_count > GETDNS_BASE_TRANSPORT_MAX) {
|
|
||||||
return GETDNS_RETURN_CONTEXT_UPDATE_FAIL;
|
return GETDNS_RETURN_CONTEXT_UPDATE_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t j = 0; j < transport_count; j++) {
|
for(i=0; i<transport_count; i++)
|
||||||
switch(transports[j]) {
|
{
|
||||||
case GETDNS_TRANSPORT_UDP:
|
if( transports[i] != GETDNS_TRANSPORT_UDP
|
||||||
context->dns_base_transports[j] = GETDNS_BASE_TRANSPORT_UDP;
|
&& transports[i] != GETDNS_TRANSPORT_TCP
|
||||||
break;
|
&& transports[i] != GETDNS_TRANSPORT_TLS
|
||||||
case GETDNS_TRANSPORT_TCP:
|
&& transports[i] != GETDNS_TRANSPORT_STARTTLS)
|
||||||
context->dns_base_transports[j] = GETDNS_BASE_TRANSPORT_TCP;
|
return GETDNS_RETURN_INVALID_PARAMETER;
|
||||||
break;
|
|
||||||
case GETDNS_TRANSPORT_TLS:
|
|
||||||
context->dns_base_transports[j] = GETDNS_BASE_TRANSPORT_TLS;
|
|
||||||
break;
|
|
||||||
case GETDNS_TRANSPORT_STARTTLS:
|
|
||||||
context->dns_base_transports[j] = GETDNS_BASE_TRANSPORT_STARTTLS;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return GETDNS_RETURN_CONTEXT_UPDATE_FAIL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GETDNS_FREE(context->my_mf, context->dns_transports);
|
||||||
|
|
||||||
|
/** duplicate **/
|
||||||
|
context->dns_transports = GETDNS_XMALLOC(context->my_mf,
|
||||||
|
getdns_transport_list_t, transport_count);
|
||||||
|
memcpy(context->dns_transports, transports,
|
||||||
|
transport_count * sizeof(getdns_transport_list_t));
|
||||||
|
context->dns_transport_count = transport_count;
|
||||||
|
dispatch_updated(context, GETDNS_CONTEXT_CODE_NAMESPACES);
|
||||||
|
|
||||||
return GETDNS_RETURN_GOOD;
|
return GETDNS_RETURN_GOOD;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1235,28 +1213,28 @@ static getdns_return_t
|
||||||
set_ub_dns_transport(struct getdns_context* context) {
|
set_ub_dns_transport(struct getdns_context* context) {
|
||||||
/* These mappings are not exact because Unbound is configured differently,
|
/* These mappings are not exact because Unbound is configured differently,
|
||||||
so just map as close as possible from the first 1 or 2 transports. */
|
so just map as close as possible from the first 1 or 2 transports. */
|
||||||
switch (context->dns_base_transports[0]) {
|
switch (context->dns_transports[0]) {
|
||||||
case GETDNS_BASE_TRANSPORT_UDP:
|
case GETDNS_TRANSPORT_UDP:
|
||||||
set_ub_string_opt(context, "do-udp:", "yes");
|
set_ub_string_opt(context, "do-udp:", "yes");
|
||||||
if (context->dns_base_transports[1] == GETDNS_BASE_TRANSPORT_TCP)
|
if (context->dns_transports[1] == GETDNS_TRANSPORT_TCP)
|
||||||
set_ub_string_opt(context, "do-tcp:", "yes");
|
set_ub_string_opt(context, "do-tcp:", "yes");
|
||||||
else
|
else
|
||||||
set_ub_string_opt(context, "do-tcp:", "no");
|
set_ub_string_opt(context, "do-tcp:", "no");
|
||||||
break;
|
break;
|
||||||
case GETDNS_BASE_TRANSPORT_TLS:
|
case GETDNS_TRANSPORT_TLS:
|
||||||
/* Note: If TLS is used in recursive mode this will try TLS on port
|
/* Note: If TLS is used in recursive mode this will try TLS on port
|
||||||
* 53... So this is prohibited when preparing for resolution.*/
|
* 53... So this is prohibited when preparing for resolution.*/
|
||||||
if (context->dns_base_transports[1] == GETDNS_BASE_TRANSPORT_NONE) {
|
if (context->dns_transport_count == 0) {
|
||||||
set_ub_string_opt(context, "ssl-upstream:", "yes");
|
set_ub_string_opt(context, "ssl-upstream:", "yes");
|
||||||
set_ub_string_opt(context, "do-udp:", "no");
|
set_ub_string_opt(context, "do-udp:", "no");
|
||||||
set_ub_string_opt(context, "do-tcp:", "yes");
|
set_ub_string_opt(context, "do-tcp:", "yes");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (context->dns_base_transports[1] != GETDNS_BASE_TRANSPORT_TCP)
|
if (context->dns_transports[1] != GETDNS_TRANSPORT_TCP)
|
||||||
break;
|
break;
|
||||||
/* Fallthrough */
|
/* Fallthrough */
|
||||||
case GETDNS_BASE_TRANSPORT_STARTTLS:
|
case GETDNS_TRANSPORT_STARTTLS:
|
||||||
case GETDNS_BASE_TRANSPORT_TCP:
|
case GETDNS_TRANSPORT_TCP:
|
||||||
/* Note: no STARTTLS or fallback to TCP available directly in unbound, so we just
|
/* Note: no STARTTLS or fallback to TCP available directly in unbound, so we just
|
||||||
* use TCP for now to make sure the messages are sent. */
|
* use TCP for now to make sure the messages are sent. */
|
||||||
set_ub_string_opt(context, "do-udp:", "no");
|
set_ub_string_opt(context, "do-udp:", "no");
|
||||||
|
@ -1278,31 +1256,37 @@ getdns_context_set_dns_transport(struct getdns_context *context,
|
||||||
{
|
{
|
||||||
RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER);
|
RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER);
|
||||||
|
|
||||||
for (int i = 0; i < GETDNS_BASE_TRANSPORT_MAX; i++)
|
size_t count = 2;
|
||||||
context->dns_base_transports[i] = GETDNS_BASE_TRANSPORT_NONE;
|
if (value == GETDNS_TRANSPORT_UDP_ONLY ||
|
||||||
|
value == GETDNS_TRANSPORT_TCP_ONLY ||
|
||||||
|
value == GETDNS_TRANSPORT_TCP_ONLY_KEEP_CONNECTIONS_OPEN ||
|
||||||
|
value == GETDNS_TRANSPORT_TLS_ONLY_KEEP_CONNECTIONS_OPEN)
|
||||||
|
count = 1;
|
||||||
|
context->dns_transports = GETDNS_XMALLOC(context->my_mf,
|
||||||
|
getdns_transport_list_t, count);
|
||||||
|
|
||||||
switch (value) {
|
switch (value) {
|
||||||
case GETDNS_TRANSPORT_UDP_FIRST_AND_FALL_BACK_TO_TCP:
|
case GETDNS_TRANSPORT_UDP_FIRST_AND_FALL_BACK_TO_TCP:
|
||||||
context->dns_base_transports[0] = GETDNS_BASE_TRANSPORT_UDP;
|
context->dns_transports[0] = GETDNS_TRANSPORT_UDP;
|
||||||
context->dns_base_transports[1] = GETDNS_BASE_TRANSPORT_TCP;
|
context->dns_transports[1] = GETDNS_TRANSPORT_TCP;
|
||||||
break;
|
break;
|
||||||
case GETDNS_TRANSPORT_UDP_ONLY:
|
case GETDNS_TRANSPORT_UDP_ONLY:
|
||||||
context->dns_base_transports[0] = GETDNS_BASE_TRANSPORT_UDP;
|
context->dns_transports[0] = GETDNS_TRANSPORT_UDP;
|
||||||
break;
|
break;
|
||||||
case GETDNS_TRANSPORT_TCP_ONLY:
|
case GETDNS_TRANSPORT_TCP_ONLY:
|
||||||
case GETDNS_TRANSPORT_TCP_ONLY_KEEP_CONNECTIONS_OPEN:
|
case GETDNS_TRANSPORT_TCP_ONLY_KEEP_CONNECTIONS_OPEN:
|
||||||
context->dns_base_transports[0] = GETDNS_BASE_TRANSPORT_TCP;
|
context->dns_transports[0] = GETDNS_TRANSPORT_TCP;
|
||||||
break;
|
break;
|
||||||
case GETDNS_TRANSPORT_TLS_ONLY_KEEP_CONNECTIONS_OPEN:
|
case GETDNS_TRANSPORT_TLS_ONLY_KEEP_CONNECTIONS_OPEN:
|
||||||
context->dns_base_transports[0] = GETDNS_BASE_TRANSPORT_TLS;
|
context->dns_transports[0] = GETDNS_TRANSPORT_TLS;
|
||||||
break;
|
break;
|
||||||
case GETDNS_TRANSPORT_TLS_FIRST_AND_FALL_BACK_TO_TCP_KEEP_CONNECTIONS_OPEN:
|
case GETDNS_TRANSPORT_TLS_FIRST_AND_FALL_BACK_TO_TCP_KEEP_CONNECTIONS_OPEN:
|
||||||
context->dns_base_transports[0] = GETDNS_BASE_TRANSPORT_TLS;
|
context->dns_transports[0] = GETDNS_TRANSPORT_TLS;
|
||||||
context->dns_base_transports[1] = GETDNS_BASE_TRANSPORT_TCP;
|
context->dns_transports[1] = GETDNS_TRANSPORT_TCP;
|
||||||
break;
|
break;
|
||||||
case GETDNS_TRANSPORT_STARTTLS_FIRST_AND_FALL_BACK_TO_TCP_KEEP_CONNECTIONS_OPEN:
|
case GETDNS_TRANSPORT_STARTTLS_FIRST_AND_FALL_BACK_TO_TCP_KEEP_CONNECTIONS_OPEN:
|
||||||
context->dns_base_transports[0] = GETDNS_BASE_TRANSPORT_STARTTLS;
|
context->dns_transports[0] = GETDNS_TRANSPORT_STARTTLS;
|
||||||
context->dns_base_transports[1] = GETDNS_BASE_TRANSPORT_TCP;
|
context->dns_transports[1] = GETDNS_TRANSPORT_TCP;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return GETDNS_RETURN_CONTEXT_UPDATE_FAIL;
|
return GETDNS_RETURN_CONTEXT_UPDATE_FAIL;
|
||||||
|
@ -1658,15 +1642,14 @@ getdns_context_set_upstream_recursive_servers(struct getdns_context *context,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Loop to create upstreams as needed*/
|
/* Loop to create upstreams as needed*/
|
||||||
getdns_base_transport_t base_transport = GETDNS_BASE_TRANSPORT_MIN;
|
for (size_t j = 0; j < GETDNS_UPSTREAM_TRANSPORTS; j++) {
|
||||||
for (; base_transport < GETDNS_BASE_TRANSPORT_MAX; base_transport++) {
|
|
||||||
uint32_t port;
|
uint32_t port;
|
||||||
struct addrinfo *ai;
|
struct addrinfo *ai;
|
||||||
port = getdns_port_array[base_transport];
|
port = getdns_port_array[j];
|
||||||
if (port == GETDNS_PORT_ZERO)
|
if (port == GETDNS_PORT_ZERO)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (base_transport != GETDNS_BASE_TRANSPORT_TLS)
|
if (getdns_upstream_transports[j] != GETDNS_TRANSPORT_TLS)
|
||||||
(void) getdns_dict_get_int(dict, "port", &port);
|
(void) getdns_dict_get_int(dict, "port", &port);
|
||||||
else
|
else
|
||||||
(void) getdns_dict_get_int(dict, "tls_port", &port);
|
(void) getdns_dict_get_int(dict, "tls_port", &port);
|
||||||
|
@ -1689,7 +1672,7 @@ getdns_context_set_upstream_recursive_servers(struct getdns_context *context,
|
||||||
upstream = &upstreams->upstreams[upstreams->count];
|
upstream = &upstreams->upstreams[upstreams->count];
|
||||||
upstream->addr.ss_family = addr.ss_family;
|
upstream->addr.ss_family = addr.ss_family;
|
||||||
upstream_init(upstream, upstreams, ai);
|
upstream_init(upstream, upstreams, ai);
|
||||||
upstream->dns_base_transport = base_transport;
|
upstream->transport = getdns_upstream_transports[j];
|
||||||
upstreams->count++;
|
upstreams->count++;
|
||||||
freeaddrinfo(ai);
|
freeaddrinfo(ai);
|
||||||
}
|
}
|
||||||
|
@ -1913,9 +1896,9 @@ ub_setup_stub(struct ub_ctx *ctx, getdns_context *context)
|
||||||
upstream = &upstreams->upstreams[i];
|
upstream = &upstreams->upstreams[i];
|
||||||
/*[TLS]: Use only the TLS subset of upstreams when TLS is the only thing
|
/*[TLS]: Use only the TLS subset of upstreams when TLS is the only thing
|
||||||
* used. All other cases must currently fallback to TCP for libunbound.*/
|
* used. All other cases must currently fallback to TCP for libunbound.*/
|
||||||
if (context->dns_base_transports[0] == GETDNS_BASE_TRANSPORT_TLS &&
|
if (context->dns_transports[0] == GETDNS_TRANSPORT_TLS &&
|
||||||
context->dns_base_transports[1] == GETDNS_BASE_TRANSPORT_NONE &&
|
context->dns_transport_count ==1 &&
|
||||||
upstream->dns_base_transport != GETDNS_BASE_TRANSPORT_TLS)
|
upstream->transport != GETDNS_TRANSPORT_TLS)
|
||||||
continue;
|
continue;
|
||||||
upstream_ntop_buf(upstream, addr, 1024);
|
upstream_ntop_buf(upstream, addr, 1024);
|
||||||
ub_ctx_set_fwd(ctx, addr);
|
ub_ctx_set_fwd(ctx, addr);
|
||||||
|
@ -2025,8 +2008,8 @@ getdns_context_prepare_for_resolution(struct getdns_context *context,
|
||||||
}
|
}
|
||||||
/* Block use of TLS ONLY in recursive mode as it won't work */
|
/* Block use of TLS ONLY in recursive mode as it won't work */
|
||||||
if (context->resolution_type == GETDNS_RESOLUTION_RECURSING &&
|
if (context->resolution_type == GETDNS_RESOLUTION_RECURSING &&
|
||||||
context->dns_base_transports[0] == GETDNS_BASE_TRANSPORT_TLS &&
|
context->dns_transports[0] == GETDNS_TRANSPORT_TLS &&
|
||||||
context->dns_base_transports[1] == GETDNS_BASE_TRANSPORT_NONE)
|
context->dns_transport_count == 1)
|
||||||
return GETDNS_RETURN_BAD_CONTEXT;
|
return GETDNS_RETURN_BAD_CONTEXT;
|
||||||
|
|
||||||
if (context->resolution_type_set == context->resolution_type)
|
if (context->resolution_type_set == context->resolution_type)
|
||||||
|
@ -2321,17 +2304,16 @@ priv_get_context_settings(getdns_context* context) {
|
||||||
upstreams);
|
upstreams);
|
||||||
getdns_list_destroy(upstreams);
|
getdns_list_destroy(upstreams);
|
||||||
}
|
}
|
||||||
/* create a transport list */
|
if (context->dns_transport_count > 0) {
|
||||||
|
/* create a namespace list */
|
||||||
|
size_t i;
|
||||||
getdns_list* transports = getdns_list_create_with_context(context);
|
getdns_list* transports = getdns_list_create_with_context(context);
|
||||||
if (transports) {
|
if (transports) {
|
||||||
int transport_count;
|
for (i = 0; i < context->dns_transport_count; ++i) {
|
||||||
getdns_transport_list_t *transport_list =
|
r |= getdns_list_set_int(transports, i, context->dns_transports[i]);
|
||||||
get_dns_transport_list(context, &transport_count);
|
|
||||||
for (int i = 0; i < transport_count; i++) {
|
|
||||||
r |= getdns_list_set_int(transports, i, transport_list[i]);
|
|
||||||
}
|
}
|
||||||
r |= getdns_dict_set_list(result, "dns_transport_list", transports);
|
r |= getdns_dict_set_list(result, "dns_transport_list", transports);
|
||||||
free(transport_list);
|
}
|
||||||
}
|
}
|
||||||
if (context->namespace_count > 0) {
|
if (context->namespace_count > 0) {
|
||||||
/* create a namespace list */
|
/* create a namespace list */
|
||||||
|
@ -2525,35 +2507,34 @@ getdns_context_get_dns_transport(getdns_context *context,
|
||||||
getdns_transport_t* value) {
|
getdns_transport_t* value) {
|
||||||
RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER);
|
RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER);
|
||||||
RETURN_IF_NULL(value, GETDNS_RETURN_INVALID_PARAMETER);
|
RETURN_IF_NULL(value, GETDNS_RETURN_INVALID_PARAMETER);
|
||||||
int count;
|
int count = context->dns_transport_count;
|
||||||
getdns_transport_list_t *transport_list =
|
getdns_transport_list_t *transports = context->dns_transports;
|
||||||
get_dns_transport_list(context, &count);
|
|
||||||
if (!count)
|
if (!count)
|
||||||
return GETDNS_RETURN_WRONG_TYPE_REQUESTED;
|
return GETDNS_RETURN_WRONG_TYPE_REQUESTED;
|
||||||
|
|
||||||
/* Best effort mapping for backwards compatibility*/
|
/* Best effort mapping for backwards compatibility*/
|
||||||
if (transport_list[0] == GETDNS_TRANSPORT_UDP) {
|
if (transports[0] == GETDNS_TRANSPORT_UDP) {
|
||||||
if (count == 1)
|
if (count == 1)
|
||||||
*value = GETDNS_TRANSPORT_UDP_ONLY;
|
*value = GETDNS_TRANSPORT_UDP_ONLY;
|
||||||
else if (count == 2 && transport_list[1] == GETDNS_TRANSPORT_TCP)
|
else if (count == 2 && transports[1] == GETDNS_TRANSPORT_TCP)
|
||||||
*value = GETDNS_TRANSPORT_UDP_FIRST_AND_FALL_BACK_TO_TCP;
|
*value = GETDNS_TRANSPORT_UDP_FIRST_AND_FALL_BACK_TO_TCP;
|
||||||
else
|
else
|
||||||
return GETDNS_RETURN_WRONG_TYPE_REQUESTED;
|
return GETDNS_RETURN_WRONG_TYPE_REQUESTED;
|
||||||
}
|
}
|
||||||
if (transport_list[0] == GETDNS_TRANSPORT_TCP) {
|
if (transports[0] == GETDNS_TRANSPORT_TCP) {
|
||||||
if (count == 1)
|
if (count == 1)
|
||||||
*value = GETDNS_TRANSPORT_TCP_ONLY_KEEP_CONNECTIONS_OPEN;
|
*value = GETDNS_TRANSPORT_TCP_ONLY_KEEP_CONNECTIONS_OPEN;
|
||||||
}
|
}
|
||||||
if (transport_list[0] == GETDNS_TRANSPORT_TLS) {
|
if (transports[0] == GETDNS_TRANSPORT_TLS) {
|
||||||
if (count == 1)
|
if (count == 1)
|
||||||
*value = GETDNS_TRANSPORT_TLS_ONLY_KEEP_CONNECTIONS_OPEN;
|
*value = GETDNS_TRANSPORT_TLS_ONLY_KEEP_CONNECTIONS_OPEN;
|
||||||
else if (count == 2 && transport_list[1] == GETDNS_TRANSPORT_TCP)
|
else if (count == 2 && transports[1] == GETDNS_TRANSPORT_TCP)
|
||||||
*value = GETDNS_TRANSPORT_TLS_FIRST_AND_FALL_BACK_TO_TCP_KEEP_CONNECTIONS_OPEN;
|
*value = GETDNS_TRANSPORT_TLS_FIRST_AND_FALL_BACK_TO_TCP_KEEP_CONNECTIONS_OPEN;
|
||||||
else
|
else
|
||||||
return GETDNS_RETURN_WRONG_TYPE_REQUESTED;
|
return GETDNS_RETURN_WRONG_TYPE_REQUESTED;
|
||||||
}
|
}
|
||||||
if (transport_list[0] == GETDNS_TRANSPORT_STARTTLS) {
|
if (transports[0] == GETDNS_TRANSPORT_STARTTLS) {
|
||||||
if (count == 2 && transport_list[1] == GETDNS_TRANSPORT_TCP)
|
if (count == 2 && transports[1] == GETDNS_TRANSPORT_TCP)
|
||||||
*value = GETDNS_TRANSPORT_STARTTLS_FIRST_AND_FALL_BACK_TO_TCP_KEEP_CONNECTIONS_OPEN;
|
*value = GETDNS_TRANSPORT_STARTTLS_FIRST_AND_FALL_BACK_TO_TCP_KEEP_CONNECTIONS_OPEN;
|
||||||
else
|
else
|
||||||
return GETDNS_RETURN_WRONG_TYPE_REQUESTED;
|
return GETDNS_RETURN_WRONG_TYPE_REQUESTED;
|
||||||
|
@ -2567,16 +2548,15 @@ getdns_context_get_dns_transport_list(getdns_context *context,
|
||||||
RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER);
|
RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER);
|
||||||
RETURN_IF_NULL(transport_count, GETDNS_RETURN_INVALID_PARAMETER);
|
RETURN_IF_NULL(transport_count, GETDNS_RETURN_INVALID_PARAMETER);
|
||||||
RETURN_IF_NULL(transports, GETDNS_RETURN_INVALID_PARAMETER);
|
RETURN_IF_NULL(transports, GETDNS_RETURN_INVALID_PARAMETER);
|
||||||
|
*transport_count = context->dns_transport_count;
|
||||||
int count;
|
if (!context->dns_transport_count) {
|
||||||
getdns_transport_list_t *transport_list =
|
|
||||||
get_dns_transport_list(context, &count);
|
|
||||||
*transport_count = count;
|
|
||||||
if (!transport_count) {
|
|
||||||
*transports = NULL;
|
*transports = NULL;
|
||||||
return GETDNS_RETURN_GOOD;
|
return GETDNS_RETURN_GOOD;
|
||||||
}
|
}
|
||||||
*transports = transport_list;
|
// use normal malloc here so users can do normal free
|
||||||
|
*transports = malloc(context->dns_transport_count * sizeof(getdns_transport_list_t));
|
||||||
|
memcpy(*transports, context->dns_transports,
|
||||||
|
context->dns_transport_count * sizeof(getdns_transport_list_t));
|
||||||
return GETDNS_RETURN_GOOD;
|
return GETDNS_RETURN_GOOD;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -91,7 +91,7 @@ typedef struct getdns_upstream {
|
||||||
|
|
||||||
/* For sharing a TCP socket to this upstream */
|
/* For sharing a TCP socket to this upstream */
|
||||||
int fd;
|
int fd;
|
||||||
getdns_base_transport_t dns_base_transport;
|
getdns_transport_list_t transport;
|
||||||
SSL* tls_obj;
|
SSL* tls_obj;
|
||||||
getdns_tls_hs_state_t tls_hs_state;
|
getdns_tls_hs_state_t tls_hs_state;
|
||||||
getdns_dns_req * starttls_req;
|
getdns_dns_req * starttls_req;
|
||||||
|
@ -138,10 +138,13 @@ struct getdns_context {
|
||||||
struct getdns_list *suffix;
|
struct getdns_list *suffix;
|
||||||
struct getdns_list *dnssec_trust_anchors;
|
struct getdns_list *dnssec_trust_anchors;
|
||||||
getdns_upstreams *upstreams;
|
getdns_upstreams *upstreams;
|
||||||
getdns_base_transport_t dns_base_transports[GETDNS_BASE_TRANSPORT_MAX];
|
|
||||||
uint16_t limit_outstanding_queries;
|
uint16_t limit_outstanding_queries;
|
||||||
uint32_t dnssec_allowed_skew;
|
uint32_t dnssec_allowed_skew;
|
||||||
|
|
||||||
|
getdns_transport_list_t *dns_transports;
|
||||||
|
size_t dns_transport_count;
|
||||||
|
size_t dns_transport_current;
|
||||||
|
|
||||||
uint8_t edns_extended_rcode;
|
uint8_t edns_extended_rcode;
|
||||||
uint8_t edns_version;
|
uint8_t edns_version;
|
||||||
uint8_t edns_do_bit;
|
uint8_t edns_do_bit;
|
||||||
|
|
|
@ -62,6 +62,7 @@ network_req_cleanup(getdns_network_req *net_req)
|
||||||
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))
|
net_req->response > net_req->wire_data+ net_req->wire_data_sz))
|
||||||
GETDNS_FREE(net_req->owner->my_mf, net_req->response);
|
GETDNS_FREE(net_req->owner->my_mf, net_req->response);
|
||||||
|
GETDNS_FREE(net_req->owner->my_mf, net_req->transports);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -89,9 +90,13 @@ network_req_init(getdns_network_req *net_req, getdns_dns_req *owner,
|
||||||
|
|
||||||
net_req->upstream = NULL;
|
net_req->upstream = NULL;
|
||||||
net_req->fd = -1;
|
net_req->fd = -1;
|
||||||
for (i = 0; i < GETDNS_BASE_TRANSPORT_MAX; i++)
|
net_req->transports = GETDNS_XMALLOC(net_req->owner->my_mf,
|
||||||
net_req->dns_base_transports[i] = owner->context->dns_base_transports[i];
|
getdns_transport_list_t,
|
||||||
net_req->transport = 0;
|
owner->context->dns_transport_count);
|
||||||
|
memcpy(owner->context->dns_transports, net_req->transports,
|
||||||
|
owner->context->dns_transport_count * sizeof(getdns_transport_list_t));
|
||||||
|
net_req->transport_count = owner->context->dns_transport_count;
|
||||||
|
net_req->transport_current = 0;
|
||||||
memset(&net_req->event, 0, sizeof(net_req->event));
|
memset(&net_req->event, 0, sizeof(net_req->event));
|
||||||
memset(&net_req->tcp, 0, sizeof(net_req->tcp));
|
memset(&net_req->tcp, 0, sizeof(net_req->tcp));
|
||||||
net_req->query_id = 0;
|
net_req->query_id = 0;
|
||||||
|
|
142
src/stub.c
142
src/stub.c
|
@ -59,6 +59,9 @@ static void upstream_read_cb(void *userarg);
|
||||||
static void upstream_write_cb(void *userarg);
|
static void upstream_write_cb(void *userarg);
|
||||||
static void upstream_schedule_netreq(getdns_upstream *upstream,
|
static void upstream_schedule_netreq(getdns_upstream *upstream,
|
||||||
getdns_network_req *netreq);
|
getdns_network_req *netreq);
|
||||||
|
static int upstream_connect(getdns_upstream *upstream,
|
||||||
|
getdns_transport_list_t transport,
|
||||||
|
getdns_dns_req *dnsreq);
|
||||||
static void netreq_upstream_read_cb(void *userarg);
|
static void netreq_upstream_read_cb(void *userarg);
|
||||||
static void netreq_upstream_write_cb(void *userarg);
|
static void netreq_upstream_write_cb(void *userarg);
|
||||||
static int fallback_on_write(getdns_network_req *netreq);
|
static int fallback_on_write(getdns_network_req *netreq);
|
||||||
|
@ -354,7 +357,7 @@ getdns_sock_nonblock(int sockfd)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
tcp_connect(getdns_upstream *upstream, getdns_base_transport_t transport)
|
tcp_connect(getdns_upstream *upstream, getdns_transport_list_t transport)
|
||||||
{
|
{
|
||||||
int fd = -1;
|
int fd = -1;
|
||||||
if ((fd = socket(upstream->addr.ss_family, SOCK_STREAM, IPPROTO_TCP)) == -1)
|
if ((fd = socket(upstream->addr.ss_family, SOCK_STREAM, IPPROTO_TCP)) == -1)
|
||||||
|
@ -363,9 +366,8 @@ tcp_connect(getdns_upstream *upstream, getdns_base_transport_t transport)
|
||||||
getdns_sock_nonblock(fd);
|
getdns_sock_nonblock(fd);
|
||||||
#ifdef USE_TCP_FASTOPEN
|
#ifdef USE_TCP_FASTOPEN
|
||||||
/* Leave the connect to the later call to sendto() if using TCP*/
|
/* Leave the connect to the later call to sendto() if using TCP*/
|
||||||
if (transport == GETDNS_BASE_TRANSPORT_TCP ||
|
if (transport == GETDNS_TRANSPORT_TCP ||
|
||||||
transport == GETDNS_BASE_TRANSPORT_TCP_SINGLE ||
|
transport == GETDNS_TRANSPORT_STARTTLS)
|
||||||
transport == GETDNS_BASE_TRANSPORT_STARTTLS)
|
|
||||||
return fd;
|
return fd;
|
||||||
#endif
|
#endif
|
||||||
if (connect(fd, (struct sockaddr *)&upstream->addr,
|
if (connect(fd, (struct sockaddr *)&upstream->addr,
|
||||||
|
@ -667,20 +669,7 @@ stub_tcp_write(int fd, getdns_tcp_state *tcp, getdns_network_req *netreq)
|
||||||
if (! tcp->write_buf) {
|
if (! tcp->write_buf) {
|
||||||
/* No, this is an initial write. Try to send
|
/* No, this is an initial write. Try to send
|
||||||
*/
|
*/
|
||||||
|
do {
|
||||||
/* Not keeping connections open? Then the first random number
|
|
||||||
* will do as the query id.
|
|
||||||
*
|
|
||||||
* Otherwise find a unique query_id not already written (or in
|
|
||||||
* the write_queue) for that upstream. Register this netreq
|
|
||||||
* by query_id in the process.
|
|
||||||
*/
|
|
||||||
if ((netreq->dns_base_transports[netreq->transport] ==
|
|
||||||
GETDNS_BASE_TRANSPORT_TCP_SINGLE) ||
|
|
||||||
(netreq->dns_base_transports[netreq->transport] ==
|
|
||||||
GETDNS_BASE_TRANSPORT_UDP))
|
|
||||||
query_id = arc4random();
|
|
||||||
else do {
|
|
||||||
query_id = arc4random();
|
query_id = arc4random();
|
||||||
query_id_intptr = (intptr_t)query_id;
|
query_id_intptr = (intptr_t)query_id;
|
||||||
netreq->node.key = (void *)query_id_intptr;
|
netreq->node.key = (void *)query_id_intptr;
|
||||||
|
@ -774,10 +763,10 @@ stub_tcp_write(int fd, getdns_tcp_state *tcp, getdns_network_req *netreq)
|
||||||
static int
|
static int
|
||||||
tls_requested(getdns_network_req *netreq)
|
tls_requested(getdns_network_req *netreq)
|
||||||
{
|
{
|
||||||
return (netreq->dns_base_transports[netreq->transport] ==
|
return (netreq->transports[netreq->transport_current] ==
|
||||||
GETDNS_BASE_TRANSPORT_TLS ||
|
GETDNS_TRANSPORT_TLS ||
|
||||||
netreq->dns_base_transports[netreq->transport] ==
|
netreq->transports[netreq->transport_current] ==
|
||||||
GETDNS_BASE_TRANSPORT_STARTTLS) ?
|
GETDNS_TRANSPORT_STARTTLS) ?
|
||||||
1 : 0;
|
1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -786,16 +775,16 @@ tls_should_write(getdns_upstream *upstream)
|
||||||
{
|
{
|
||||||
/* Should messages be written on TLS upstream. Remember that for STARTTLS
|
/* Should messages be written on TLS upstream. Remember that for STARTTLS
|
||||||
* the first message should got over TCP as the handshake isn't started yet.*/
|
* the first message should got over TCP as the handshake isn't started yet.*/
|
||||||
return ((upstream->dns_base_transport == GETDNS_BASE_TRANSPORT_TLS ||
|
return ((upstream->transport == GETDNS_TRANSPORT_TLS ||
|
||||||
upstream->dns_base_transport == GETDNS_BASE_TRANSPORT_STARTTLS) &&
|
upstream->transport == GETDNS_TRANSPORT_STARTTLS) &&
|
||||||
upstream->tls_hs_state != GETDNS_HS_NONE) ? 1 : 0;
|
upstream->tls_hs_state != GETDNS_HS_NONE) ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
tls_should_read(getdns_upstream *upstream)
|
tls_should_read(getdns_upstream *upstream)
|
||||||
{
|
{
|
||||||
return ((upstream->dns_base_transport == GETDNS_BASE_TRANSPORT_TLS ||
|
return ((upstream->transport == GETDNS_TRANSPORT_TLS ||
|
||||||
upstream->dns_base_transport == GETDNS_BASE_TRANSPORT_STARTTLS) &&
|
upstream->transport == GETDNS_TRANSPORT_STARTTLS) &&
|
||||||
!(upstream->tls_hs_state == GETDNS_HS_FAILED ||
|
!(upstream->tls_hs_state == GETDNS_HS_FAILED ||
|
||||||
upstream->tls_hs_state == GETDNS_HS_NONE)) ? 1 : 0;
|
upstream->tls_hs_state == GETDNS_HS_NONE)) ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
@ -804,8 +793,8 @@ static int
|
||||||
tls_failed(getdns_upstream *upstream)
|
tls_failed(getdns_upstream *upstream)
|
||||||
{
|
{
|
||||||
/* No messages should be scheduled onto an upstream in this state */
|
/* No messages should be scheduled onto an upstream in this state */
|
||||||
return ((upstream->dns_base_transport == GETDNS_BASE_TRANSPORT_TLS ||
|
return ((upstream->transport == GETDNS_TRANSPORT_TLS ||
|
||||||
upstream->dns_base_transport == GETDNS_BASE_TRANSPORT_STARTTLS) &&
|
upstream->transport == GETDNS_TRANSPORT_STARTTLS) &&
|
||||||
upstream->tls_hs_state == GETDNS_HS_FAILED) ? 1: 0;
|
upstream->tls_hs_state == GETDNS_HS_FAILED) ? 1: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1070,23 +1059,16 @@ stub_udp_read_cb(void *userarg)
|
||||||
return; /* Client cookie didn't match? */
|
return; /* Client cookie didn't match? */
|
||||||
|
|
||||||
close(netreq->fd);
|
close(netreq->fd);
|
||||||
/* TODO: check not past end of transports*/
|
if (GLDNS_TC_WIRE(netreq->response)) {
|
||||||
getdns_base_transport_t next_transport =
|
if (!(netreq->transport_current < netreq->transport_count))
|
||||||
netreq->dns_base_transports[netreq->transport + 1];
|
goto done;
|
||||||
if (GLDNS_TC_WIRE(netreq->response) &&
|
netreq->transport_current++;
|
||||||
next_transport == GETDNS_BASE_TRANSPORT_TCP) {
|
if (netreq->transport_current != GETDNS_TRANSPORT_TCP)
|
||||||
|
goto done;
|
||||||
if ((netreq->fd = socket(
|
if ((netreq->fd = upstream_connect(upstream, netreq->transport_current,
|
||||||
upstream->addr.ss_family, SOCK_STREAM, IPPROTO_TCP)) == -1)
|
dnsreq)) == -1)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
getdns_sock_nonblock(netreq->fd);
|
|
||||||
if (connect(netreq->fd, (struct sockaddr *)&upstream->addr,
|
|
||||||
upstream->addr_len) == -1 && errno != EINPROGRESS) {
|
|
||||||
|
|
||||||
close(netreq->fd);
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
GETDNS_SCHEDULE_EVENT(
|
GETDNS_SCHEDULE_EVENT(
|
||||||
dnsreq->loop, netreq->fd, dnsreq->context->timeout,
|
dnsreq->loop, netreq->fd, dnsreq->context->timeout,
|
||||||
getdns_eventloop_event_init(&netreq->event, netreq,
|
getdns_eventloop_event_init(&netreq->event, netreq,
|
||||||
|
@ -1427,20 +1409,19 @@ netreq_upstream_write_cb(void *userarg)
|
||||||
|
|
||||||
static int
|
static int
|
||||||
upstream_transport_valid(getdns_upstream *upstream,
|
upstream_transport_valid(getdns_upstream *upstream,
|
||||||
getdns_base_transport_t transport)
|
getdns_transport_list_t transport)
|
||||||
{
|
{
|
||||||
/* For single shot transports, use only the TCP upstream. */
|
/* Single shot UDP, uses same upstream as plain TCP. */
|
||||||
if (transport == GETDNS_BASE_TRANSPORT_UDP ||
|
if (transport == GETDNS_TRANSPORT_UDP)
|
||||||
transport == GETDNS_BASE_TRANSPORT_TCP_SINGLE)
|
return (upstream->transport == GETDNS_TRANSPORT_TCP ? 1:0);
|
||||||
return (upstream->dns_base_transport == GETDNS_BASE_TRANSPORT_TCP ? 1:0);
|
|
||||||
/* Allow TCP messages to be sent on a STARTTLS upstream that hasn't
|
/* Allow TCP messages to be sent on a STARTTLS upstream that hasn't
|
||||||
* upgraded to avoid opening a new connection if one is aleady open. */
|
* upgraded to avoid opening a new connection if one is aleady open. */
|
||||||
if (transport == GETDNS_BASE_TRANSPORT_TCP &&
|
if (transport == GETDNS_TRANSPORT_TCP &&
|
||||||
upstream->dns_base_transport == GETDNS_BASE_TRANSPORT_STARTTLS &&
|
upstream->transport == GETDNS_TRANSPORT_STARTTLS &&
|
||||||
upstream->tls_hs_state == GETDNS_HS_FAILED)
|
upstream->tls_hs_state == GETDNS_HS_FAILED)
|
||||||
return 1;
|
return 1;
|
||||||
/* Otherwise, transport must match, and not have failed */
|
/* Otherwise, transport must match, and not have failed */
|
||||||
if (upstream->dns_base_transport != transport)
|
if (upstream->transport != transport)
|
||||||
return 0;
|
return 0;
|
||||||
if (tls_failed(upstream))
|
if (tls_failed(upstream))
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1448,7 +1429,7 @@ upstream_transport_valid(getdns_upstream *upstream,
|
||||||
}
|
}
|
||||||
|
|
||||||
static getdns_upstream *
|
static getdns_upstream *
|
||||||
upstream_select(getdns_network_req *netreq, getdns_base_transport_t transport)
|
upstream_select(getdns_network_req *netreq, getdns_transport_list_t transport)
|
||||||
{
|
{
|
||||||
getdns_upstream *upstream;
|
getdns_upstream *upstream;
|
||||||
getdns_upstreams *upstreams = netreq->owner->upstreams;
|
getdns_upstreams *upstreams = netreq->owner->upstreams;
|
||||||
|
@ -1489,31 +1470,29 @@ upstream_select(getdns_network_req *netreq, getdns_base_transport_t transport)
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
upstream_connect(getdns_upstream *upstream, getdns_base_transport_t transport,
|
upstream_connect(getdns_upstream *upstream, getdns_transport_list_t transport,
|
||||||
getdns_dns_req *dnsreq)
|
getdns_dns_req *dnsreq)
|
||||||
{
|
{
|
||||||
DEBUG_STUB("%s\n", __FUNCTION__);
|
DEBUG_STUB("%s\n", __FUNCTION__);
|
||||||
int fd = -1;
|
int fd = -1;
|
||||||
switch(transport) {
|
switch(transport) {
|
||||||
case GETDNS_BASE_TRANSPORT_UDP:
|
case GETDNS_TRANSPORT_UDP:
|
||||||
if ((fd = socket(
|
if ((fd = socket(
|
||||||
upstream->addr.ss_family, SOCK_DGRAM, IPPROTO_UDP)) == -1)
|
upstream->addr.ss_family, SOCK_DGRAM, IPPROTO_UDP)) == -1)
|
||||||
return -1;
|
return -1;
|
||||||
getdns_sock_nonblock(fd);
|
getdns_sock_nonblock(fd);
|
||||||
return fd;
|
return fd;
|
||||||
|
|
||||||
case GETDNS_BASE_TRANSPORT_TCP:
|
case GETDNS_TRANSPORT_TCP:
|
||||||
/* Use existing if available*/
|
/* Use existing if available*/
|
||||||
if (upstream->fd != -1)
|
if (upstream->fd != -1)
|
||||||
return upstream->fd;
|
return upstream->fd;
|
||||||
/* Otherwise, fall through */
|
|
||||||
case GETDNS_BASE_TRANSPORT_TCP_SINGLE:
|
|
||||||
fd = tcp_connect(upstream, transport);
|
fd = tcp_connect(upstream, transport);
|
||||||
upstream->loop = dnsreq->context->extension;
|
upstream->loop = dnsreq->context->extension;
|
||||||
upstream->fd = fd;
|
upstream->fd = fd;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GETDNS_BASE_TRANSPORT_TLS:
|
case GETDNS_TRANSPORT_TLS:
|
||||||
/* Use existing if available*/
|
/* Use existing if available*/
|
||||||
if (upstream->fd != -1 && !tls_failed(upstream))
|
if (upstream->fd != -1 && !tls_failed(upstream))
|
||||||
return upstream->fd;
|
return upstream->fd;
|
||||||
|
@ -1528,7 +1507,7 @@ upstream_connect(getdns_upstream *upstream, getdns_base_transport_t transport,
|
||||||
upstream->loop = dnsreq->context->extension;
|
upstream->loop = dnsreq->context->extension;
|
||||||
upstream->fd = fd;
|
upstream->fd = fd;
|
||||||
break;
|
break;
|
||||||
case GETDNS_BASE_TRANSPORT_STARTTLS:
|
case GETDNS_TRANSPORT_STARTTLS:
|
||||||
/* Use existing if available. Let the fallback code handle it if
|
/* Use existing if available. Let the fallback code handle it if
|
||||||
* STARTTLS isn't availble. */
|
* STARTTLS isn't availble. */
|
||||||
if (upstream->fd != -1)
|
if (upstream->fd != -1)
|
||||||
|
@ -1559,7 +1538,7 @@ upstream_connect(getdns_upstream *upstream, getdns_base_transport_t transport,
|
||||||
|
|
||||||
static getdns_upstream*
|
static getdns_upstream*
|
||||||
find_upstream_for_specific_transport(getdns_network_req *netreq,
|
find_upstream_for_specific_transport(getdns_network_req *netreq,
|
||||||
getdns_base_transport_t transport,
|
getdns_transport_list_t transport,
|
||||||
int *fd)
|
int *fd)
|
||||||
{
|
{
|
||||||
/* TODO[TLS]: Fallback through upstreams....?*/
|
/* TODO[TLS]: Fallback through upstreams....?*/
|
||||||
|
@ -1574,15 +1553,13 @@ static int
|
||||||
find_upstream_for_netreq(getdns_network_req *netreq)
|
find_upstream_for_netreq(getdns_network_req *netreq)
|
||||||
{
|
{
|
||||||
int fd = -1;
|
int fd = -1;
|
||||||
int i = netreq->transport;
|
for (size_t i = 0; i < netreq->transport_count; i++) {
|
||||||
for (; i < GETDNS_BASE_TRANSPORT_MAX &&
|
|
||||||
netreq->dns_base_transports[i] != GETDNS_BASE_TRANSPORT_NONE; i++) {
|
|
||||||
netreq->upstream = find_upstream_for_specific_transport(netreq,
|
netreq->upstream = find_upstream_for_specific_transport(netreq,
|
||||||
netreq->dns_base_transports[i],
|
netreq->transports[i],
|
||||||
&fd);
|
&fd);
|
||||||
if (fd == -1 || !netreq->upstream)
|
if (fd == -1 || !netreq->upstream)
|
||||||
continue;
|
continue;
|
||||||
netreq->transport = i;
|
netreq->transport_current = i;
|
||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -1645,7 +1622,7 @@ move_netreq(getdns_network_req *netreq, getdns_upstream *upstream,
|
||||||
stub_timeout_cb));
|
stub_timeout_cb));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
netreq->transport++;
|
netreq->transport_current++;
|
||||||
return upstream->fd;
|
return upstream->fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1654,16 +1631,18 @@ fallback_on_write(getdns_network_req *netreq)
|
||||||
{
|
{
|
||||||
DEBUG_STUB("%s\n", __FUNCTION__);
|
DEBUG_STUB("%s\n", __FUNCTION__);
|
||||||
/* TODO[TLS]: Fallback through all transports.*/
|
/* TODO[TLS]: Fallback through all transports.*/
|
||||||
getdns_base_transport_t next_transport =
|
if (netreq->transport_current = netreq->transport_count - 1)
|
||||||
netreq->dns_base_transports[netreq->transport + 1];
|
|
||||||
if (next_transport == GETDNS_BASE_TRANSPORT_NONE)
|
|
||||||
return STUB_TCP_ERROR;
|
return STUB_TCP_ERROR;
|
||||||
|
|
||||||
if (netreq->dns_base_transports[netreq->transport] ==
|
getdns_transport_list_t next_transport =
|
||||||
GETDNS_BASE_TRANSPORT_STARTTLS &&
|
netreq->transports[netreq->transport_current + 1];
|
||||||
next_transport == GETDNS_BASE_TRANSPORT_TCP) {
|
|
||||||
/* Special case where can stay on same upstream*/
|
if (netreq->transports[netreq->transport_current] ==
|
||||||
netreq->transport++;
|
GETDNS_TRANSPORT_STARTTLS &&
|
||||||
|
next_transport == GETDNS_TRANSPORT_TCP) {
|
||||||
|
/* TODO[TLS]: Check this is always OK....
|
||||||
|
* Special case where can stay on same upstream*/
|
||||||
|
netreq->transport_current++;
|
||||||
return netreq->upstream->fd;
|
return netreq->upstream->fd;
|
||||||
}
|
}
|
||||||
getdns_upstream *upstream = netreq->upstream;
|
getdns_upstream *upstream = netreq->upstream;
|
||||||
|
@ -1722,22 +1701,21 @@ priv_getdns_submit_stub_request(getdns_network_req *netreq)
|
||||||
if (fd == -1)
|
if (fd == -1)
|
||||||
return GETDNS_RETURN_GENERIC_ERROR;
|
return GETDNS_RETURN_GENERIC_ERROR;
|
||||||
|
|
||||||
getdns_base_transport_t transport =
|
getdns_transport_list_t transport =
|
||||||
netreq->dns_base_transports[netreq->transport];
|
netreq->transports[netreq->transport_current];
|
||||||
switch(transport) {
|
switch(transport) {
|
||||||
case GETDNS_BASE_TRANSPORT_UDP:
|
case GETDNS_TRANSPORT_UDP:
|
||||||
case GETDNS_BASE_TRANSPORT_TCP_SINGLE:
|
|
||||||
netreq->fd = fd;
|
netreq->fd = fd;
|
||||||
GETDNS_SCHEDULE_EVENT(
|
GETDNS_SCHEDULE_EVENT(
|
||||||
dnsreq->loop, netreq->fd, dnsreq->context->timeout,
|
dnsreq->loop, netreq->fd, dnsreq->context->timeout,
|
||||||
getdns_eventloop_event_init(&netreq->event, netreq,
|
getdns_eventloop_event_init(&netreq->event, netreq,
|
||||||
NULL, (transport == GETDNS_BASE_TRANSPORT_UDP ?
|
NULL, (transport == GETDNS_TRANSPORT_UDP ?
|
||||||
stub_udp_write_cb: stub_tcp_write_cb), stub_timeout_cb));
|
stub_udp_write_cb: stub_tcp_write_cb), stub_timeout_cb));
|
||||||
return GETDNS_RETURN_GOOD;
|
return GETDNS_RETURN_GOOD;
|
||||||
|
|
||||||
case GETDNS_BASE_TRANSPORT_STARTTLS:
|
case GETDNS_TRANSPORT_STARTTLS:
|
||||||
case GETDNS_BASE_TRANSPORT_TLS:
|
case GETDNS_TRANSPORT_TLS:
|
||||||
case GETDNS_BASE_TRANSPORT_TCP:
|
case GETDNS_TRANSPORT_TCP:
|
||||||
upstream_schedule_netreq(netreq->upstream, netreq);
|
upstream_schedule_netreq(netreq->upstream, netreq);
|
||||||
/* TODO[TLS]: Change scheduling for sync calls. */
|
/* TODO[TLS]: Change scheduling for sync calls. */
|
||||||
GETDNS_SCHEDULE_EVENT(
|
GETDNS_SCHEDULE_EVENT(
|
||||||
|
|
|
@ -443,7 +443,7 @@ getdns_return_t parse_args(int argc, char **argv)
|
||||||
return GETDNS_RETURN_GENERIC_ERROR;
|
return GETDNS_RETURN_GENERIC_ERROR;
|
||||||
}
|
}
|
||||||
size_t transport_count = 0;
|
size_t transport_count = 0;
|
||||||
getdns_transport_list_t transports[GETDNS_BASE_TRANSPORT_MAX];
|
getdns_transport_list_t transports[strlen(argv[])];
|
||||||
if ((r = fill_transport_list(context, argv[i], transports, &transport_count)) ||
|
if ((r = fill_transport_list(context, argv[i], transports, &transport_count)) ||
|
||||||
(r = getdns_context_set_dns_transport_list(context,
|
(r = getdns_context_set_dns_transport_list(context,
|
||||||
transport_count, transports))){
|
transport_count, transports))){
|
||||||
|
|
|
@ -99,6 +99,9 @@ struct getdns_upstream;
|
||||||
#define TIMEOUT_FOREVER ((int64_t)-1)
|
#define TIMEOUT_FOREVER ((int64_t)-1)
|
||||||
#define ASSERT_UNREACHABLE 0
|
#define ASSERT_UNREACHABLE 0
|
||||||
|
|
||||||
|
#define GETDNS_TRANSPORTS_MAX 4
|
||||||
|
#define GETDNS_UPSTREAM_TRANSPORTS 3
|
||||||
|
|
||||||
/** @}
|
/** @}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -164,17 +167,17 @@ typedef struct getdns_tcp_state {
|
||||||
|
|
||||||
} getdns_tcp_state;
|
} getdns_tcp_state;
|
||||||
|
|
||||||
/* TODO[TLS]: change this name to getdns_transport when API updated*/
|
// /* TODO[TLS]: change this name to getdns_transport when API updated*/
|
||||||
typedef enum getdns_base_transport {
|
// typedef enum getdns_base_transport {
|
||||||
GETDNS_BASE_TRANSPORT_MIN = 0,
|
// GETDNS_TRANSPORT_MIN = 0,
|
||||||
GETDNS_BASE_TRANSPORT_NONE = 0,
|
// GETDNS_TRANSPORT_NONE = 0,
|
||||||
GETDNS_BASE_TRANSPORT_UDP,
|
// GETDNS_TRANSPORT_UDP,
|
||||||
GETDNS_BASE_TRANSPORT_TCP_SINGLE, /* To be removed? */
|
// GETDNS_TRANSPORT_TCP_SINGLE, /* To be removed? */
|
||||||
GETDNS_BASE_TRANSPORT_STARTTLS, /* Define before TCP to allow fallback */
|
// GETDNS_TRANSPORT_STARTTLS, /* Define before TCP to allow fallback */
|
||||||
GETDNS_BASE_TRANSPORT_TCP,
|
// GETDNS_TRANSPORT_TCP,
|
||||||
GETDNS_BASE_TRANSPORT_TLS,
|
// GETDNS_TRANSPORT_TLS,
|
||||||
GETDNS_BASE_TRANSPORT_MAX
|
// GETDNS_TRANSPORT_MAX
|
||||||
} getdns_base_transport_t;
|
// } getdns_base_transport_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Request data
|
* Request data
|
||||||
|
@ -203,8 +206,9 @@ typedef struct getdns_network_req
|
||||||
/* For stub resolving */
|
/* For stub resolving */
|
||||||
struct getdns_upstream *upstream;
|
struct getdns_upstream *upstream;
|
||||||
int fd;
|
int fd;
|
||||||
getdns_base_transport_t dns_base_transports[GETDNS_BASE_TRANSPORT_MAX];
|
getdns_transport_list_t *transports;
|
||||||
int transport;
|
size_t transport_count;
|
||||||
|
size_t transport_current;
|
||||||
getdns_eventloop_event event;
|
getdns_eventloop_event event;
|
||||||
getdns_tcp_state tcp;
|
getdns_tcp_state tcp;
|
||||||
uint16_t query_id;
|
uint16_t query_id;
|
||||||
|
|
Loading…
Reference in New Issue