mirror of https://github.com/getdnsapi/getdns.git
Change internal transport handling to use a list, not a fixed type
This commit is contained in:
parent
f2ae55858f
commit
3de15ad782
119
src/context.c
119
src/context.c
|
@ -526,8 +526,7 @@ upstream_scope_id(getdns_upstream *upstream)
|
|||
}
|
||||
|
||||
static void
|
||||
upstream_ntop_buf(getdns_upstream *upstream, getdns_transport_t transport,
|
||||
char *buf, size_t len)
|
||||
upstream_ntop_buf(getdns_upstream *upstream, char *buf, size_t len)
|
||||
{
|
||||
/* Also possible but prints scope_id by name (nor parsed by unbound)
|
||||
*
|
||||
|
@ -566,9 +565,8 @@ upstream_init(getdns_upstream *upstream,
|
|||
/* For sharing a socket to this upstream with TCP */
|
||||
upstream->fd = -1;
|
||||
upstream->tls_obj = NULL;
|
||||
upstream->base_transport = (upstream_port(upstream) == GETDNS_PORT_NUM_TLS ?
|
||||
GETDNS_TRANSPORT_TLS :
|
||||
GETDNS_TRANSPORT_TCP);
|
||||
upstream->dns_base_transport = (upstream_port(upstream) == GETDNS_PORT_NUM_TLS ?
|
||||
GETDNS_BASE_TRANSPORT_TLS : GETDNS_BASE_TRANSPORT_TCP);
|
||||
upstream->tls_hs_state = GETDNS_HS_NONE;
|
||||
upstream->loop = NULL;
|
||||
(void) getdns_eventloop_event_init(
|
||||
|
@ -672,10 +670,10 @@ set_os_defaults(struct getdns_context *context)
|
|||
token = parse + strcspn(parse, " \t\r\n");
|
||||
*token = 0;
|
||||
|
||||
//getdns_port_type_t port_type = GETDNS_PORT_FIRST;
|
||||
//for (; port_type < GETDNS_PORT_LAST; port_type++) {
|
||||
// TODO[TLS]: Seeing strange crash in ub_create_ctx when using the loop here....
|
||||
//fprintf(stderr,"creating upstream %s\n", parse);
|
||||
getdns_port_type_t port_type = GETDNS_PORT_FIRST;
|
||||
for (; port_type < GETDNS_PORT_LAST; port_type++) {
|
||||
// TODO[TLS]: Seeing strange crash in ub_create_ctx when using the loop here....
|
||||
fprintf(stderr,"creating upstream %s\n", parse);
|
||||
if ((s = getaddrinfo(parse, "53", /*getdns_port_str_array[port_type],*/ &hints, &result)))
|
||||
continue;
|
||||
|
||||
|
@ -690,7 +688,7 @@ set_os_defaults(struct getdns_context *context)
|
|||
upstream = &context->upstreams->
|
||||
upstreams[context->upstreams->count++];
|
||||
upstream_init(upstream, context->upstreams, result);
|
||||
//}
|
||||
}
|
||||
freeaddrinfo(result);
|
||||
}
|
||||
fclose(in);
|
||||
|
@ -819,6 +817,7 @@ getdns_context_create_with_extended_memory_functions(
|
|||
result->dnssec_allowed_skew = 0;
|
||||
result->edns_maximum_udp_payload_size = -1;
|
||||
result->dns_transport = GETDNS_TRANSPORT_UDP_FIRST_AND_FALL_BACK_TO_TCP;
|
||||
priv_set_base_dns_transports(result->dns_base_transports, result->dns_transport);
|
||||
result->limit_outstanding_queries = 0;
|
||||
result->has_ta = priv_getdns_parse_ta_file(NULL, NULL);
|
||||
result->return_dnssec_status = GETDNS_EXTENSION_FALSE;
|
||||
|
@ -1142,31 +1141,38 @@ getdns_context_set_namespaces(struct getdns_context *context,
|
|||
return GETDNS_RETURN_GOOD;
|
||||
} /* getdns_context_set_namespaces */
|
||||
|
||||
getdns_base_transport_t
|
||||
priv_get_base_transport(getdns_transport_t transport, int level) {
|
||||
if (!(level == 0 || level == 1)) return GETDNS_TRANSPORT_NONE;
|
||||
switch (transport) {
|
||||
case GETDNS_TRANSPORT_UDP_FIRST_AND_FALL_BACK_TO_TCP:
|
||||
if (level == 0) return GETDNS_TRANSPORT_UDP;
|
||||
if (level == 1) return GETDNS_TRANSPORT_TCP;
|
||||
case GETDNS_TRANSPORT_UDP_ONLY:
|
||||
if (level == 0) return GETDNS_TRANSPORT_UDP;
|
||||
if (level == 1) return GETDNS_TRANSPORT_NONE;
|
||||
case GETDNS_TRANSPORT_TCP_ONLY:
|
||||
if (level == 0) return GETDNS_TRANSPORT_TCP_SINGLE;
|
||||
if (level == 1) return GETDNS_TRANSPORT_NONE;
|
||||
case GETDNS_TRANSPORT_TCP_ONLY_KEEP_CONNECTIONS_OPEN:
|
||||
if (level == 0) return GETDNS_TRANSPORT_TCP;
|
||||
if (level == 1) return GETDNS_TRANSPORT_NONE;
|
||||
case GETDNS_TRANSPORT_TLS_ONLY_KEEP_CONNECTIONS_OPEN:
|
||||
if (level == 0) return GETDNS_TRANSPORT_TLS;
|
||||
if (level == 1) return GETDNS_TRANSPORT_NONE;
|
||||
case GETDNS_TRANSPORT_TLS_FIRST_AND_FALL_BACK_TO_TCP_KEEP_CONNECTIONS_OPEN:
|
||||
if (level == 0) return GETDNS_TRANSPORT_TLS;
|
||||
if (level == 1) return GETDNS_TRANSPORT_TCP;
|
||||
default:
|
||||
return GETDNS_TRANSPORT_NONE;
|
||||
}
|
||||
/* TODO[TLS]: Modify further when API changed.*/
|
||||
getdns_return_t
|
||||
priv_set_base_dns_transports(getdns_base_transport_t *dns_base_transports,
|
||||
getdns_transport_t value)
|
||||
{
|
||||
for (int i = 0; i < GETDNS_BASE_TRANSPORT_MAX; i++)
|
||||
dns_base_transports[i] = GETDNS_BASE_TRANSPORT_NONE;
|
||||
switch (value) {
|
||||
case GETDNS_TRANSPORT_UDP_FIRST_AND_FALL_BACK_TO_TCP:
|
||||
dns_base_transports[0] = GETDNS_BASE_TRANSPORT_UDP;
|
||||
dns_base_transports[1] = GETDNS_BASE_TRANSPORT_TCP_SINGLE;
|
||||
break;
|
||||
case GETDNS_TRANSPORT_UDP_ONLY:
|
||||
dns_base_transports[0] = GETDNS_BASE_TRANSPORT_UDP;
|
||||
break;
|
||||
case GETDNS_TRANSPORT_TCP_ONLY:
|
||||
dns_base_transports[0] = GETDNS_BASE_TRANSPORT_TCP_SINGLE;
|
||||
break;
|
||||
case GETDNS_TRANSPORT_TCP_ONLY_KEEP_CONNECTIONS_OPEN:
|
||||
dns_base_transports[0] = GETDNS_BASE_TRANSPORT_TCP;
|
||||
break;
|
||||
case GETDNS_TRANSPORT_TLS_ONLY_KEEP_CONNECTIONS_OPEN:
|
||||
dns_base_transports[0] = GETDNS_BASE_TRANSPORT_TLS;
|
||||
break;
|
||||
case GETDNS_TRANSPORT_TLS_FIRST_AND_FALL_BACK_TO_TCP_KEEP_CONNECTIONS_OPEN:
|
||||
dns_base_transports[0] = GETDNS_BASE_TRANSPORT_TLS;
|
||||
dns_base_transports[1] = GETDNS_BASE_TRANSPORT_TCP;
|
||||
break;
|
||||
default:
|
||||
return GETDNS_RETURN_CONTEXT_UPDATE_FAIL;
|
||||
}
|
||||
return GETDNS_RETURN_GOOD;
|
||||
}
|
||||
|
||||
static getdns_return_t
|
||||
|
@ -1188,9 +1194,8 @@ set_ub_dns_transport(struct getdns_context* context,
|
|||
set_ub_string_opt(context, "do-tcp:", "yes");
|
||||
break;
|
||||
case GETDNS_TRANSPORT_TLS_ONLY_KEEP_CONNECTIONS_OPEN:
|
||||
/* Hum. If used in recursive mode this will try TLS on port 53...
|
||||
* So we need to fix or document that or delay setting it until
|
||||
* resolution.*/
|
||||
/* Note: If TLS is used in recursive mode this will try TLS on port
|
||||
* 53... So this is prohibited when preparing for resolution.*/
|
||||
set_ub_string_opt(context, "ssl-upstream:", "yes");
|
||||
/* Fall through*/
|
||||
case GETDNS_TRANSPORT_TLS_FIRST_AND_FALL_BACK_TO_TCP_KEEP_CONNECTIONS_OPEN:
|
||||
|
@ -1213,17 +1218,22 @@ getdns_return_t
|
|||
getdns_context_set_dns_transport(struct getdns_context *context,
|
||||
getdns_transport_t value)
|
||||
{
|
||||
/* TODO[TLS]: Modify further when API changed.*/
|
||||
RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER);
|
||||
/* Note that the call below does not have any effect in unbound after the
|
||||
* ctx is finalised. So will not apply for recursive mode or stub + dnssec.
|
||||
* ctx is finalised so for recursive mode or stub + dnssec only the first
|
||||
* transport specified on the first query is used.
|
||||
* However the method returns success as otherwise the transport could not
|
||||
* be reset for stub mode.....
|
||||
* be reset for stub mode.
|
||||
* Also, not all transport options supported in libunbound yet */
|
||||
if (set_ub_dns_transport(context, value) != GETDNS_RETURN_GOOD) {
|
||||
return GETDNS_RETURN_CONTEXT_UPDATE_FAIL;
|
||||
}
|
||||
if (value != context->dns_transport) {
|
||||
/*TODO[TLS]: remove this line*/
|
||||
context->dns_transport = value;
|
||||
if (priv_set_base_dns_transports(context->dns_base_transports, value) != GETDNS_RETURN_GOOD)
|
||||
return GETDNS_RETURN_CONTEXT_UPDATE_FAIL;
|
||||
dispatch_updated(context, GETDNS_CONTEXT_CODE_DNS_TRANSPORT);
|
||||
}
|
||||
|
||||
|
@ -1752,10 +1762,10 @@ ub_setup_stub(struct ub_ctx *ctx, getdns_context *context)
|
|||
getdns_upstreams *upstreams = context->upstreams;
|
||||
|
||||
(void) ub_ctx_set_fwd(ctx, NULL);
|
||||
/*TODO[TLS]: Order the upstreams so the TLS ones are first if doing TLS*/
|
||||
/*TODO[TLS]: Use only the subset of upstreams that match the first transport */
|
||||
for (i = 0; i < upstreams->count; i++) {
|
||||
upstream = &upstreams->upstreams[i];
|
||||
upstream_ntop_buf(upstream, context->dns_transport, addr, 1024);
|
||||
upstream_ntop_buf(upstream, addr, 1024);
|
||||
ub_ctx_set_fwd(ctx, addr);
|
||||
}
|
||||
|
||||
|
@ -1850,27 +1860,22 @@ getdns_context_prepare_for_resolution(struct getdns_context *context,
|
|||
}
|
||||
|
||||
/* Transport can in theory be set per query in stub mode */
|
||||
/* TODO: move this transport logic to a separate functions*/
|
||||
if (context->resolution_type == GETDNS_RESOLUTION_STUB) {
|
||||
switch (context->dns_transport) {
|
||||
case GETDNS_TRANSPORT_TLS_ONLY_KEEP_CONNECTIONS_OPEN:
|
||||
case GETDNS_TRANSPORT_TLS_FIRST_AND_FALL_BACK_TO_TCP_KEEP_CONNECTIONS_OPEN:
|
||||
if (context->tls_ctx == NULL) {
|
||||
/*TODO[TLS]: Check if TLS is in the list of transports.*/
|
||||
if (context->tls_ctx == NULL) {
|
||||
#ifdef HAVE_LIBTLS1_2
|
||||
/* Create client context, use TLS v1.2 only for now */
|
||||
context->tls_ctx = SSL_CTX_new(TLSv1_2_client_method());
|
||||
/* Create client context, use TLS v1.2 only for now */
|
||||
context->tls_ctx = SSL_CTX_new(TLSv1_2_client_method());
|
||||
#endif
|
||||
if(!context->tls_ctx && context->dns_transport ==
|
||||
GETDNS_TRANSPORT_TLS_ONLY_KEEP_CONNECTIONS_OPEN) {
|
||||
return GETDNS_RETURN_BAD_CONTEXT;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
/* TODO[TLS]: Check if TLS is the only option in the list*/
|
||||
// if(!context->tls_ctx && context->dns_transport ==
|
||||
// GETDNS_TRANSPORT_TLS_ONLY_KEEP_CONNECTIONS_OPEN) {
|
||||
// return GETDNS_RETURN_BAD_CONTEXT;
|
||||
// }
|
||||
}
|
||||
}
|
||||
/* Block use of TLS ONLY in recursive mode as it won't work */
|
||||
/* TODO[TLS]: Check if TLS is the only option in the list*/
|
||||
if (context->resolution_type == GETDNS_RESOLUTION_RECURSING
|
||||
&& context->dns_transport == GETDNS_TRANSPORT_TLS_ONLY_KEEP_CONNECTIONS_OPEN)
|
||||
return GETDNS_RETURN_BAD_CONTEXT;
|
||||
|
|
|
@ -75,14 +75,6 @@ struct filechg {
|
|||
struct stat *prevstat;
|
||||
};
|
||||
|
||||
typedef enum getdns_base_transport {
|
||||
GETDNS_TRANSPORT_NONE,
|
||||
GETDNS_TRANSPORT_UDP,
|
||||
GETDNS_TRANSPORT_TCP_SINGLE,
|
||||
GETDNS_TRANSPORT_TCP,
|
||||
GETDNS_TRANSPORT_TLS
|
||||
} getdns_base_transport_t;
|
||||
|
||||
typedef enum getdns_port_type {
|
||||
GETDNS_PORT_FIRST = 0,
|
||||
GETDNS_PORT_TCP = 0,
|
||||
|
@ -111,7 +103,7 @@ typedef struct getdns_upstream {
|
|||
/* For sharing a TCP socket to this upstream */
|
||||
int fd;
|
||||
SSL* tls_obj;
|
||||
getdns_base_transport_t base_transport;
|
||||
getdns_base_transport_t dns_base_transport;
|
||||
getdns_tls_hs_state_t tls_hs_state;
|
||||
getdns_eventloop_event event;
|
||||
getdns_eventloop *loop;
|
||||
|
@ -156,6 +148,7 @@ struct getdns_context {
|
|||
struct getdns_list *dnssec_trust_anchors;
|
||||
getdns_upstreams *upstreams;
|
||||
getdns_transport_t dns_transport;
|
||||
getdns_base_transport_t dns_base_transports[GETDNS_BASE_TRANSPORT_MAX];
|
||||
uint16_t limit_outstanding_queries;
|
||||
uint32_t dnssec_allowed_skew;
|
||||
|
||||
|
@ -251,6 +244,9 @@ int filechg_check(struct getdns_context *context, struct filechg *fchg);
|
|||
|
||||
void priv_getdns_context_ub_read_cb(void *userarg);
|
||||
|
||||
getdns_return_t priv_set_base_dns_transports(getdns_base_transport_t *,
|
||||
getdns_transport_t);
|
||||
|
||||
getdns_base_transport_t priv_get_base_transport(getdns_transport_t transport, int level);
|
||||
|
||||
void priv_getdns_upstreams_dereference(getdns_upstreams *upstreams);
|
||||
|
|
|
@ -89,7 +89,9 @@ network_req_init(getdns_network_req *net_req, getdns_dns_req *owner,
|
|||
|
||||
net_req->upstream = NULL;
|
||||
net_req->fd = -1;
|
||||
net_req->transport = GETDNS_TRANSPORT_UDP_FIRST_AND_FALL_BACK_TO_TCP;
|
||||
priv_set_base_dns_transports(net_req->dns_base_transports,
|
||||
GETDNS_TRANSPORT_UDP_FIRST_AND_FALL_BACK_TO_TCP);
|
||||
net_req->dns_base_transport = net_req->dns_base_transports;
|
||||
memset(&net_req->event, 0, sizeof(net_req->event));
|
||||
memset(&net_req->tcp, 0, sizeof(net_req->tcp));
|
||||
net_req->query_id = 0;
|
||||
|
|
223
src/stub.c
223
src/stub.c
|
@ -407,6 +407,7 @@ stub_udp_read_cb(void *userarg)
|
|||
return; /* Client cookie didn't match? */
|
||||
|
||||
close(netreq->fd);
|
||||
/*TODO[TLS]: Switch this to use the transport fallback list*/
|
||||
if (GLDNS_TC_WIRE(netreq->response) &&
|
||||
dnsreq->context->dns_transport ==
|
||||
GETDNS_TRANSPORT_UDP_FIRST_AND_FALL_BACK_TO_TCP) {
|
||||
|
@ -478,51 +479,49 @@ stub_udp_write_cb(void *userarg)
|
|||
|
||||
|
||||
static int
|
||||
transport_matches(struct getdns_upstream *upstream, getdns_base_transport_t transport) {
|
||||
if (upstream->base_transport != transport)
|
||||
transport_valid(struct getdns_upstream *upstream, getdns_base_transport_t transport) {
|
||||
if (upstream->dns_base_transport != transport)
|
||||
return 0;
|
||||
if (transport == GETDNS_TRANSPORT_TLS &&
|
||||
if (transport == GETDNS_BASE_TRANSPORT_TLS &&
|
||||
upstream->tls_hs_state == GETDNS_HS_FAILED)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static getdns_upstream *
|
||||
pick_upstream(getdns_dns_req *dnsreq, int level)
|
||||
pick_upstream(getdns_network_req *netreq, getdns_base_transport_t transport)
|
||||
{
|
||||
getdns_upstream *upstream;
|
||||
getdns_upstreams *upstreams = netreq->owner->context->upstreams;
|
||||
size_t i;
|
||||
|
||||
if (!dnsreq->upstreams->count)
|
||||
if (!upstreams->count)
|
||||
return NULL;
|
||||
|
||||
getdns_base_transport_t transport = priv_get_base_transport(
|
||||
dnsreq->context->dns_transport, level);
|
||||
for (i = 0; i < upstreams->count; i++)
|
||||
if (upstreams->upstreams[i].to_retry <= 0)
|
||||
upstreams->upstreams[i].to_retry++;
|
||||
|
||||
for (i = 0; i < dnsreq->upstreams->count; i++)
|
||||
if (dnsreq->upstreams->upstreams[i].to_retry <= 0)
|
||||
dnsreq->upstreams->upstreams[i].to_retry++;
|
||||
|
||||
i = dnsreq->upstreams->current;
|
||||
i = upstreams->current;
|
||||
do {
|
||||
if (dnsreq->upstreams->upstreams[i].to_retry > 0 &&
|
||||
transport_matches(&dnsreq->upstreams->upstreams[i], transport)) {
|
||||
dnsreq->upstreams->current = i;
|
||||
return &dnsreq->upstreams->upstreams[i];
|
||||
if (upstreams->upstreams[i].to_retry > 0 &&
|
||||
transport_valid(&upstreams->upstreams[i], transport)) {
|
||||
upstreams->current = i;
|
||||
return &upstreams->upstreams[i];
|
||||
}
|
||||
if (++i > dnsreq->upstreams->count)
|
||||
if (++i > upstreams->count)
|
||||
i = 0;
|
||||
} while (i != dnsreq->upstreams->current);
|
||||
} while (i != upstreams->current);
|
||||
|
||||
upstream = dnsreq->upstreams->upstreams;
|
||||
for (i = 1; i < dnsreq->upstreams->count; i++)
|
||||
if (dnsreq->upstreams->upstreams[i].back_off < upstream->back_off &&
|
||||
transport_matches(&dnsreq->upstreams->upstreams[i], transport))
|
||||
upstream = &dnsreq->upstreams->upstreams[i];
|
||||
upstream = upstreams->upstreams;
|
||||
for (i = 1; i < upstreams->count; i++)
|
||||
if (upstreams->upstreams[i].back_off < upstream->back_off &&
|
||||
transport_valid(&upstreams->upstreams[i], transport))
|
||||
upstream = &upstreams->upstreams[i];
|
||||
|
||||
upstream->back_off++;
|
||||
upstream->to_retry = 1;
|
||||
dnsreq->upstreams->current = upstream - dnsreq->upstreams->upstreams;
|
||||
upstreams->current = upstream - upstreams->upstreams;
|
||||
return upstream;
|
||||
}
|
||||
|
||||
|
@ -698,58 +697,61 @@ do_tls_handshake(getdns_upstream *upstream)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* TODO[TLS]: Could think about fallback on read error aswell.*/
|
||||
/* TODO[TLS]: Make generic function for switching transport */
|
||||
/* TODO[TLS]: Should think about fallback on read error aswell.*/
|
||||
static int
|
||||
fallback_on_write(getdns_network_req *netreq) {
|
||||
fallback_on_tls_write_error(getdns_network_req *netreq) {
|
||||
|
||||
/* This should really check if any request in the queue can fallback...*/
|
||||
if (netreq->transport != GETDNS_TRANSPORT_TLS_FIRST_AND_FALL_BACK_TO_TCP_KEEP_CONNECTIONS_OPEN)
|
||||
return STUB_TCP_ERROR;
|
||||
fprintf(stderr,"[TLS]: method: fallback_on_tls_write_error\n");
|
||||
getdns_base_transport_t *next_transport = netreq->dns_base_transport;
|
||||
if (*(++next_transport) != GETDNS_BASE_TRANSPORT_TCP)
|
||||
/* TODO[TLS]: Fallback through upstreams....?*/
|
||||
return STUB_TCP_ERROR;
|
||||
|
||||
/* Deal with old upstream */
|
||||
getdns_upstream *upstream = netreq->upstream;
|
||||
upstream->write_queue = NULL;
|
||||
upstream->write_queue_last = NULL;
|
||||
upstream->event.write_cb = NULL;
|
||||
GETDNS_CLEAR_EVENT(upstream->loop, &upstream->event);
|
||||
/* Remove from queue, clearing event if we are the last*/
|
||||
if (!(upstream->write_queue = netreq->write_queue_tail)) {
|
||||
upstream->write_queue_last = NULL;
|
||||
upstream->event.write_cb = NULL;
|
||||
GETDNS_CLEAR_EVENT(upstream->loop, &upstream->event);
|
||||
}
|
||||
|
||||
/* Now set up new upstream */
|
||||
getdns_upstream *new_upstream = pick_upstream(netreq->owner, 1);
|
||||
getdns_upstream *new_upstream = pick_upstream(netreq, *next_transport);
|
||||
/* TODO[TLS]: Fallback through upstreams....?*/
|
||||
if (!new_upstream)
|
||||
return STUB_TCP_ERROR;
|
||||
|
||||
/* get transport generically*/
|
||||
int fd = connect_to_upstream(new_upstream, GETDNS_TRANSPORT_TCP, netreq->owner->context);
|
||||
return STUB_TCP_ERROR;
|
||||
int fd = connect_to_upstream(new_upstream, *next_transport, netreq->owner->context);
|
||||
if (fd == -1)
|
||||
return STUB_TCP_ERROR;
|
||||
|
||||
fprintf(stderr,"[TLS]: tcp_fallback to %d \n", new_upstream->fd);
|
||||
getdns_network_req *next_req;
|
||||
while (netreq != NULL) {
|
||||
next_req = netreq->write_queue_tail;
|
||||
if (netreq->transport == GETDNS_TRANSPORT_TLS_FIRST_AND_FALL_BACK_TO_TCP_KEEP_CONNECTIONS_OPEN) {
|
||||
netreq->upstream = new_upstream;
|
||||
upstream_schedule_netreq(new_upstream, netreq);
|
||||
/* TODO: Timout need to be adjusted and rescheduled on the new fd ....*/
|
||||
/* Note, setup timeout should be shorter than message timeout for
|
||||
* messages with fallback or don't have time to re-try. */
|
||||
}
|
||||
/*else.... leave request to timeout?*/
|
||||
netreq = next_req;
|
||||
}
|
||||
netreq->upstream = new_upstream;
|
||||
upstream_schedule_netreq(new_upstream, netreq);
|
||||
|
||||
/* TODO[TLS]: Timout need to be adjusted and rescheduled on the new fd ....*/
|
||||
/* Note, setup timeout should be shorter than message timeout for
|
||||
* messages with fallback or don't have time to re-try. */
|
||||
// GETDNS_SCHEDULE_EVENT(
|
||||
// dnsreq->loop, upstream->fd, dnsreq->context->timeout,
|
||||
// getdns_eventloop_event_init(&netreq->event, netreq, NULL,
|
||||
// ( dnsreq->loop != upstream->loop /* Synchronous lookup? */
|
||||
// ? netreq_upstream_write_cb : NULL), stub_timeout_cb));
|
||||
|
||||
return STUB_TCP_AGAIN;
|
||||
}
|
||||
|
||||
static int
|
||||
setup_tls(getdns_upstream* upstream)
|
||||
check_tls(getdns_upstream* upstream)
|
||||
{
|
||||
int ret;
|
||||
/* Already have a connection*/
|
||||
if (upstream->tls_hs_state == GETDNS_HS_DONE &&
|
||||
(upstream->tls_obj != NULL) && (upstream->fd != -1))
|
||||
return 0;
|
||||
|
||||
/* This upstream can't be used, so let the fallback code take care of things */
|
||||
if (upstream->tls_hs_state == GETDNS_HS_FAILED)
|
||||
return STUB_TLS_SETUP_ERROR;
|
||||
|
||||
/* Lets make sure the connection is up before we try a handshake*/
|
||||
int error = 0;
|
||||
socklen_t len = (socklen_t)sizeof(error);
|
||||
|
@ -774,17 +776,7 @@ setup_tls(getdns_upstream* upstream)
|
|||
return STUB_TLS_SETUP_ERROR;
|
||||
}
|
||||
|
||||
ret = do_tls_handshake(upstream);
|
||||
switch (ret) {
|
||||
case STUB_TCP_AGAIN:
|
||||
return ret;
|
||||
case STUB_TCP_ERROR:
|
||||
fprintf(stderr,"[TLS]: W: Handshake has failed %d\n", upstream->tls_hs_state);
|
||||
return STUB_TLS_SETUP_ERROR;
|
||||
default:
|
||||
fprintf(stderr,"[TLS]: W:after handshake %d, %s\n", upstream->tls_hs_state, upstream->tls_obj== NULL? "NULL":"Not NULL" );
|
||||
return 0;
|
||||
}
|
||||
return do_tls_handshake(upstream);
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -795,7 +787,7 @@ stub_tls_read(getdns_upstream *upstream, getdns_tcp_state *tcp, struct mem_funcs
|
|||
size_t buf_size;
|
||||
SSL* tls_obj = upstream->tls_obj;
|
||||
|
||||
int q = setup_tls(upstream);
|
||||
int q = check_tls(upstream);
|
||||
if (q != 0)
|
||||
return q;
|
||||
|
||||
|
@ -883,7 +875,7 @@ upstream_read_cb(void *userarg)
|
|||
|
||||
fprintf(stderr,"[TLS]: upstream_read_cb on %d\n", upstream->fd);
|
||||
|
||||
if (upstream->tls_obj)
|
||||
if (upstream->dns_base_transport == GETDNS_BASE_TRANSPORT_TLS)
|
||||
q = stub_tls_read(upstream, &upstream->tcp,
|
||||
&upstream->upstreams->mf);
|
||||
else
|
||||
|
@ -1114,7 +1106,7 @@ stub_tls_write(getdns_upstream *upstream, getdns_tcp_state *tcp, getdns_network_
|
|||
intptr_t query_id_intptr;
|
||||
SSL* tls_obj = upstream->tls_obj;
|
||||
|
||||
int q = setup_tls(upstream);
|
||||
int q = check_tls(upstream);
|
||||
if (q != 0)
|
||||
return q;
|
||||
|
||||
|
@ -1169,7 +1161,7 @@ upstream_write_cb(void *userarg)
|
|||
|
||||
fprintf(stderr,"[TLS]: method: upstream_write_cb %d\n", upstream->fd);
|
||||
|
||||
if (upstream->tls_obj)
|
||||
if (upstream->dns_base_transport == GETDNS_BASE_TRANSPORT_TLS)
|
||||
q = stub_tls_write(upstream, &upstream->tcp, netreq);
|
||||
else
|
||||
q = stub_tcp_write(upstream->fd, &upstream->tcp, netreq);
|
||||
|
@ -1185,13 +1177,14 @@ upstream_write_cb(void *userarg)
|
|||
case STUB_TLS_SETUP_ERROR:
|
||||
/* Could not complete the TLS set up. Need to fallback on this upstream
|
||||
* if possible.*/
|
||||
if (fallback_on_write(netreq) == STUB_TCP_ERROR)
|
||||
if (fallback_on_tls_write_error(netreq) == STUB_TCP_ERROR)
|
||||
//TODO[TLS]: Need a different error case here for msg_erred?
|
||||
stub_erred(netreq);
|
||||
return;
|
||||
|
||||
default:
|
||||
netreq->query_id = (uint16_t) q;
|
||||
fprintf(stderr,"[TLS]: method: upstream_write_cb, successfull write %d\n", upstream->fd);
|
||||
fprintf(stderr,"[TLS]: method: upstream_write_cb, successfull write %d\n", upstream->fd);
|
||||
|
||||
/* Unqueue the netreq from the write_queue */
|
||||
if (!(upstream->write_queue = netreq->write_queue_tail)) {
|
||||
|
@ -1231,6 +1224,7 @@ upstream_write_cb(void *userarg)
|
|||
static void
|
||||
netreq_upstream_write_cb(void *userarg)
|
||||
{
|
||||
fprintf(stderr,"[TLS]: method: SYNC netreq_upstream_write_cb \n");
|
||||
upstream_write_cb(((getdns_network_req *)userarg)->upstream);
|
||||
}
|
||||
|
||||
|
@ -1267,8 +1261,8 @@ tcp_connect(getdns_upstream *upstream, getdns_base_transport_t transport)
|
|||
getdns_sock_nonblock(fd);
|
||||
#ifdef USE_TCP_FASTOPEN
|
||||
/* Leave the connect to the later call to sendto() if using TCP*/
|
||||
if (transport == GETDNS_TRANSPORT_TCP ||
|
||||
transport == GETDNS_TRANSPORT_TCP_SINGLE)
|
||||
if (transport == GETDNS_BASE_TRANSPORT_TCP ||
|
||||
transport == GETDNS_BASE_TRANSPORT_TCP_SINGLE)
|
||||
return fd;
|
||||
#endif
|
||||
if (connect(fd, (struct sockaddr *)&upstream->addr,
|
||||
|
@ -1286,31 +1280,33 @@ connect_to_upstream(getdns_upstream *upstream, getdns_base_transport_t transport
|
|||
getdns_context *context)
|
||||
{
|
||||
|
||||
if ((transport == GETDNS_TRANSPORT_TCP ||
|
||||
transport == GETDNS_TRANSPORT_TLS)
|
||||
if ((transport == GETDNS_BASE_TRANSPORT_TCP ||
|
||||
transport == GETDNS_BASE_TRANSPORT_TLS)
|
||||
&& upstream->fd != -1) {
|
||||
fprintf(stderr,"[TLS]: method: tcp_connect using existing fd %d\n", upstream->fd);
|
||||
return upstream->fd;
|
||||
}
|
||||
|
||||
int fd;
|
||||
int fd = -1;
|
||||
switch(transport) {
|
||||
case GETDNS_TRANSPORT_UDP:
|
||||
case GETDNS_BASE_TRANSPORT_UDP:
|
||||
if ((fd = socket(
|
||||
upstream->addr.ss_family, SOCK_DGRAM, IPPROTO_UDP)) == -1)
|
||||
return -1;
|
||||
getdns_sock_nonblock(fd);
|
||||
return fd;
|
||||
|
||||
case GETDNS_TRANSPORT_TCP_SINGLE:
|
||||
case GETDNS_TRANSPORT_TCP:
|
||||
case GETDNS_BASE_TRANSPORT_TCP_SINGLE:
|
||||
case GETDNS_BASE_TRANSPORT_TCP:
|
||||
fd = tcp_connect(upstream, transport);
|
||||
break;
|
||||
|
||||
case GETDNS_TRANSPORT_TLS:
|
||||
case GETDNS_BASE_TRANSPORT_TLS:
|
||||
fd = tcp_connect(upstream, transport);
|
||||
if (fd == -1 ||
|
||||
(upstream->tls_obj = create_tls_object(context, fd)) == NULL ) {
|
||||
if (fd == -1) return -1;
|
||||
upstream->tls_obj = create_tls_object(context, fd);
|
||||
if (upstream->tls_obj == NULL) {
|
||||
fprintf(stderr,"[TLS]: could not create tls object\n");
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
@ -1331,50 +1327,47 @@ connect_to_upstream(getdns_upstream *upstream, getdns_base_transport_t transport
|
|||
getdns_return_t
|
||||
priv_getdns_submit_stub_request(getdns_network_req *netreq)
|
||||
{
|
||||
getdns_dns_req *dnsreq = netreq->owner;
|
||||
int fd = -1;
|
||||
int i;
|
||||
getdns_dns_req *dnsreq = netreq->owner;
|
||||
getdns_upstream *upstream = NULL;
|
||||
|
||||
/* TODO[TLS - 1]: This will become a double while loop trying all the upstreams on all the
|
||||
* transports for a connection since we need a fd to schedule on, using previous known capabilities
|
||||
* All other set up is done async*/
|
||||
/* Work out the primary and fallback transport options */
|
||||
getdns_base_transport_t transport = priv_get_base_transport(
|
||||
dnsreq->context->dns_transport,0);
|
||||
getdns_base_transport_t fb_transport = priv_get_base_transport(
|
||||
dnsreq->context->dns_transport,1);
|
||||
getdns_upstream *upstream = pick_upstream(dnsreq, 0);
|
||||
if (!upstream)
|
||||
return GETDNS_RETURN_GENERIC_ERROR;
|
||||
int fd = connect_to_upstream(upstream, transport, dnsreq->context);
|
||||
if (fd == -1) {
|
||||
if (fb_transport == GETDNS_TRANSPORT_NONE)
|
||||
return GETDNS_RETURN_GENERIC_ERROR;
|
||||
upstream = pick_upstream(dnsreq, 1);
|
||||
if ((fd = connect_to_upstream(upstream, fb_transport, dnsreq->context)) == -1)
|
||||
return GETDNS_RETURN_GENERIC_ERROR;
|
||||
/* This loop does a best effort to get a initial fd falling back through
|
||||
* transport (then upstream?). All other set up is done async*/
|
||||
for (i = 0; i < GETDNS_BASE_TRANSPORT_MAX; i++)
|
||||
netreq->dns_base_transports[i] = dnsreq->context->dns_base_transports[i];
|
||||
for (i = 0; i < GETDNS_BASE_TRANSPORT_MAX &&
|
||||
netreq->dns_base_transports[i] != GETDNS_BASE_TRANSPORT_NONE; i++) {
|
||||
/*TODO[TLS]: Loop over upstreams, but don't loop more than once*/
|
||||
upstream = pick_upstream(netreq, netreq->dns_base_transports[i]);
|
||||
if (!upstream) {
|
||||
continue;
|
||||
}
|
||||
fd = connect_to_upstream(upstream, netreq->dns_base_transports[i],
|
||||
dnsreq->context);
|
||||
if (fd != -1)
|
||||
break;
|
||||
}
|
||||
if (fd == -1)
|
||||
return GETDNS_RETURN_GENERIC_ERROR;
|
||||
|
||||
netreq->upstream = upstream;
|
||||
netreq->transport = dnsreq->context->dns_transport;
|
||||
netreq->dns_base_transport = &(netreq->dns_base_transports[i]);
|
||||
|
||||
switch(transport) {
|
||||
case GETDNS_TRANSPORT_UDP:
|
||||
case GETDNS_TRANSPORT_TCP_SINGLE:
|
||||
switch(*netreq->dns_base_transport) {
|
||||
case GETDNS_BASE_TRANSPORT_UDP:
|
||||
case GETDNS_BASE_TRANSPORT_TCP_SINGLE:
|
||||
netreq->fd = fd;
|
||||
GETDNS_SCHEDULE_EVENT(
|
||||
dnsreq->loop, netreq->fd, dnsreq->context->timeout,
|
||||
getdns_eventloop_event_init(&netreq->event, netreq,
|
||||
NULL, (transport == GETDNS_TRANSPORT_UDP ? stub_udp_write_cb:
|
||||
stub_tcp_write_cb), stub_timeout_cb));
|
||||
NULL, (*netreq->dns_base_transport == GETDNS_BASE_TRANSPORT_UDP ?
|
||||
stub_udp_write_cb: stub_tcp_write_cb), stub_timeout_cb));
|
||||
return GETDNS_RETURN_GOOD;
|
||||
|
||||
case GETDNS_TRANSPORT_TCP:
|
||||
case GETDNS_TRANSPORT_TLS:
|
||||
case GETDNS_BASE_TRANSPORT_TCP:
|
||||
case GETDNS_BASE_TRANSPORT_TLS:
|
||||
|
||||
/* In coming comments, "global" means "context wide" */
|
||||
if (upstream->fd == -1) {
|
||||
upstream->loop = dnsreq->context->extension;
|
||||
upstream->fd = fd;
|
||||
}
|
||||
upstream_schedule_netreq(upstream, netreq);
|
||||
/* TODO[TLS]: Timeout handling for async calls must change....
|
||||
* Maybe even change scheduling for sync calls here too*/
|
||||
|
|
|
@ -164,6 +164,16 @@ typedef struct getdns_tcp_state {
|
|||
|
||||
} getdns_tcp_state;
|
||||
|
||||
typedef enum getdns_base_transport {
|
||||
GETDNS_BASE_TRANSPORT_NONE,
|
||||
GETDNS_BASE_TRANSPORT_UDP,
|
||||
GETDNS_BASE_TRANSPORT_TCP_SINGLE, /* To be removed? */
|
||||
GETDNS_BASE_TRANSPORT_TCP,
|
||||
GETDNS_BASE_TRANSPORT_TLS,
|
||||
GETDNS_BASE_TRANSPORT_STARTTLS, /* Not yet implemented*/
|
||||
GETDNS_BASE_TRANSPORT_MAX
|
||||
} getdns_base_transport_t;
|
||||
|
||||
/**
|
||||
* Request data
|
||||
**/
|
||||
|
@ -191,7 +201,8 @@ typedef struct getdns_network_req
|
|||
/* For stub resolving */
|
||||
struct getdns_upstream *upstream;
|
||||
int fd;
|
||||
getdns_transport_t transport;
|
||||
getdns_base_transport_t dns_base_transports[GETDNS_BASE_TRANSPORT_MAX];
|
||||
getdns_base_transport_t *dns_base_transport;
|
||||
getdns_eventloop_event event;
|
||||
getdns_tcp_state tcp;
|
||||
uint16_t query_id;
|
||||
|
|
Loading…
Reference in New Issue