Add stub for rebuilding unbound ctx. Only allow updates to certain context fields if unbound query hasn't been sent.

This commit is contained in:
Neel Goyal 2014-02-19 14:56:37 -05:00
parent 38904780f2
commit a80d22f07f
2 changed files with 142 additions and 69 deletions

View File

@ -62,13 +62,22 @@ static struct getdns_list *create_from_ldns_list(struct getdns_context *,
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 *);
static int timeout_cmp(const void *, const void *); static int timeout_cmp(const void *, const void *);
static void set_ub_string_opt(struct getdns_context *, char *, char *);
static void set_ub_number_opt(struct getdns_context *, char *, uint16_t);
static inline void clear_resolution_type_set_flag(struct getdns_context *, uint16_t);
static void dispatch_updated(struct getdns_context *, uint16_t); static void dispatch_updated(struct getdns_context *, uint16_t);
static void cancel_dns_req(getdns_dns_req *); static void cancel_dns_req(getdns_dns_req *);
static void cancel_outstanding_requests(struct getdns_context*, int); static void cancel_outstanding_requests(struct getdns_context*, int);
/* unbound helpers */
static getdns_return_t rebuild_ub_ctx(struct getdns_context* context);
static void set_ub_string_opt(struct getdns_context *, char *, char *);
static void set_ub_number_opt(struct getdns_context *, char *, uint16_t);
static getdns_return_t set_ub_dns_transport(struct getdns_context*, getdns_transport_t);
static void set_ub_limit_outstanding_queries(struct getdns_context*,
uint16_t);
static void set_ub_dnssec_allowed_skew(struct getdns_context*, uint32_t);
static void set_ub_edns_maximum_udp_payload_size(struct getdns_context*,
uint16_t);
/* Stuff to make it compile pedantically */ /* Stuff to make it compile pedantically */
#define RETURN_IF_NULL(ptr, code) if(ptr == NULL) return code; #define RETURN_IF_NULL(ptr, code) if(ptr == NULL) return code;
@ -408,8 +417,6 @@ getdns_context_create_with_extended_memory_functions(
result->mf.mf.ext.realloc = realloc; result->mf.mf.ext.realloc = realloc;
result->mf.mf.ext.free = free; result->mf.mf.ext.free = free;
result->unbound_ctx = ub_ctx_create();
result->resolution_type_set = 0; result->resolution_type_set = 0;
result->outbound_requests = ldns_rbtree_create(transaction_id_cmp); result->outbound_requests = ldns_rbtree_create(transaction_id_cmp);
@ -444,21 +451,19 @@ getdns_context_create_with_extended_memory_functions(
return GETDNS_RETURN_GENERIC_ERROR; return GETDNS_RETURN_GENERIC_ERROR;
} }
} }
result->dnssec_allowed_skew = 0;
*context = result; result->edns_maximum_udp_payload_size = 512;
result->dns_transport = GETDNS_TRANSPORT_UDP_FIRST_AND_FALL_BACK_TO_TCP;
/* other opts */ result->limit_outstanding_queries = 0;
getdns_context_set_dnssec_allowed_skew(result, 0);
getdns_context_set_edns_maximum_udp_payload_size(result, 512);
getdns_context_set_dns_transport(result,
GETDNS_TRANSPORT_UDP_FIRST_AND_FALL_BACK_TO_TCP);
/* Set default trust anchor */
result->has_ta = priv_getdns_parse_ta_file(NULL, NULL); result->has_ta = priv_getdns_parse_ta_file(NULL, NULL);
if (result->has_ta) {
(void) ub_ctx_add_ta_file( /* unbound context is initialized here */
result->unbound_ctx, TRUST_ANCHOR_FILE); result->unbound_ctx = NULL;
if (GETDNS_RETURN_GOOD != rebuild_ub_ctx(result)) {
getdns_context_destroy(result);
return GETDNS_RETURN_GENERIC_ERROR;
} }
*context = result;
return GETDNS_RETURN_GOOD; return GETDNS_RETURN_GOOD;
} /* getdns_context_create_with_extended_memory_functions */ } /* getdns_context_create_with_extended_memory_functions */
@ -525,7 +530,7 @@ getdns_context_destroy(struct getdns_context *context)
GETDNS_FREE(context->my_mf, context->fchg_hosts); GETDNS_FREE(context->my_mf, context->fchg_hosts);
} }
cancel_outstanding_requests(context, 0); cancel_outstanding_requests(context, 1);
getdns_extension_detach_eventloop(context); getdns_extension_detach_eventloop(context);
getdns_list_destroy(context->dns_root_servers); getdns_list_destroy(context->dns_root_servers);
@ -534,6 +539,7 @@ getdns_context_destroy(struct getdns_context *context)
getdns_list_destroy(context->upstream_list); getdns_list_destroy(context->upstream_list);
/* destroy the ub context */ /* destroy the ub context */
if (context->unbound_ctx)
ub_ctx_delete(context->unbound_ctx); ub_ctx_delete(context->unbound_ctx);
ldns_rbtree_free(context->outbound_requests); ldns_rbtree_free(context->outbound_requests);
@ -565,6 +571,7 @@ getdns_context_set_context_update_callback(struct getdns_context *context,
static void static void
set_ub_string_opt(struct getdns_context *ctx, char *opt, char *value) set_ub_string_opt(struct getdns_context *ctx, char *opt, char *value)
{ {
if (ctx->unbound_ctx)
ub_ctx_set_option(ctx->unbound_ctx, opt, value); ub_ctx_set_option(ctx->unbound_ctx, opt, value);
} }
@ -576,15 +583,32 @@ set_ub_number_opt(struct getdns_context *ctx, char *opt, uint16_t value)
set_ub_string_opt(ctx, opt, buffer); set_ub_string_opt(ctx, opt, buffer);
} }
/* static getdns_return_t
* Clear the resolution type set flag if needed rebuild_ub_ctx(struct getdns_context* context) {
*/ if (context->unbound_ctx != NULL) {
static inline void /* cancel all requests and delete */
clear_resolution_type_set_flag(struct getdns_context *context, uint16_t type) cancel_outstanding_requests(context, 1);
{ ub_ctx_delete(context->unbound_ctx);
if (context->resolution_type_set == type) { context->unbound_ctx = NULL;
context->resolution_type_set = 0;
} }
/* setup */
context->unbound_ctx = ub_ctx_create();
if (!context->unbound_ctx) {
return GETDNS_RETURN_MEMORY_ERROR;
}
set_ub_dnssec_allowed_skew(context,
context->dnssec_allowed_skew);
set_ub_edns_maximum_udp_payload_size(context,
context->edns_maximum_udp_payload_size);
set_ub_dns_transport(context,
context->dns_transport);
/* Set default trust anchor */
if (context->has_ta) {
(void) ub_ctx_add_ta_file(
context->unbound_ctx, TRUST_ANCHOR_FILE);
}
return GETDNS_RETURN_GOOD;
} }
/** /**
@ -610,8 +634,11 @@ getdns_context_set_resolution_type(struct getdns_context *context,
if (value != GETDNS_RESOLUTION_STUB && value != GETDNS_RESOLUTION_RECURSING) { if (value != GETDNS_RESOLUTION_STUB && value != GETDNS_RESOLUTION_RECURSING) {
return GETDNS_RETURN_CONTEXT_UPDATE_FAIL; return GETDNS_RETURN_CONTEXT_UPDATE_FAIL;
} }
if (context->resolution_type_set != 0) {
/* already setup */
return GETDNS_RETURN_CONTEXT_UPDATE_FAIL;
}
context->resolution_type = value; context->resolution_type = value;
clear_resolution_type_set_flag(context, value);
dispatch_updated(context, GETDNS_CONTEXT_CODE_RESOLUTION_TYPE); dispatch_updated(context, GETDNS_CONTEXT_CODE_RESOLUTION_TYPE);
@ -632,6 +659,9 @@ getdns_context_set_namespaces(struct getdns_context *context,
if (namespace_count == 0 || namespaces == NULL) { if (namespace_count == 0 || namespaces == NULL) {
return GETDNS_RETURN_CONTEXT_UPDATE_FAIL; return GETDNS_RETURN_CONTEXT_UPDATE_FAIL;
} }
if (context->resolution_type_set != 0) {
return GETDNS_RETURN_CONTEXT_UPDATE_FAIL;
}
for(i=0; i<namespace_count; i++) for(i=0; i<namespace_count; i++)
{ {
@ -656,15 +686,9 @@ getdns_context_set_namespaces(struct getdns_context *context,
return GETDNS_RETURN_GOOD; return GETDNS_RETURN_GOOD;
} /* getdns_context_set_namespaces */ } /* getdns_context_set_namespaces */
/* static getdns_return_t
* getdns_context_set_dns_transport set_ub_dns_transport(struct getdns_context* context,
* getdns_transport_t value) {
*/
getdns_return_t
getdns_context_set_dns_transport(struct getdns_context *context,
getdns_transport_t value)
{
RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER);
switch (value) { switch (value) {
case GETDNS_TRANSPORT_UDP_FIRST_AND_FALL_BACK_TO_TCP: case GETDNS_TRANSPORT_UDP_FIRST_AND_FALL_BACK_TO_TCP:
set_ub_string_opt(context, "do-udp", "yes"); set_ub_string_opt(context, "do-udp", "yes");
@ -682,12 +706,33 @@ getdns_context_set_dns_transport(struct getdns_context *context,
/* TODO GETDNS_CONTEXT_TCP_ONLY_KEEP_CONNECTIONS_OPEN */ /* TODO GETDNS_CONTEXT_TCP_ONLY_KEEP_CONNECTIONS_OPEN */
return GETDNS_RETURN_CONTEXT_UPDATE_FAIL; return GETDNS_RETURN_CONTEXT_UPDATE_FAIL;
} }
return GETDNS_RETURN_GOOD;
}
/*
* getdns_context_set_dns_transport
*
*/
getdns_return_t
getdns_context_set_dns_transport(struct getdns_context *context,
getdns_transport_t value)
{
RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER);
if (set_ub_dns_transport(context, value) != GETDNS_RETURN_GOOD) {
return GETDNS_RETURN_CONTEXT_UPDATE_FAIL;
}
if (value != context->dns_transport) {
context->dns_transport = value;
dispatch_updated(context, GETDNS_CONTEXT_CODE_DNS_TRANSPORT); dispatch_updated(context, GETDNS_CONTEXT_CODE_DNS_TRANSPORT);
}
return GETDNS_RETURN_GOOD; return GETDNS_RETURN_GOOD;
} /* getdns_context_set_dns_transport */ } /* getdns_context_set_dns_transport */
static void
set_ub_limit_outstanding_queries(struct getdns_context* context, uint16_t value) {
/* num-queries-per-thread */
set_ub_number_opt(context, "num-queries-per-thread", value);
}
/* /*
* getdns_context_set_limit_outstanding_queries * getdns_context_set_limit_outstanding_queries
* *
@ -697,11 +742,12 @@ getdns_context_set_limit_outstanding_queries(struct getdns_context *context,
uint16_t limit) uint16_t limit)
{ {
RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER); RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER);
/* num-queries-per-thread */ set_ub_limit_outstanding_queries(context, limit);
set_ub_number_opt(context, "num-queries-per-thread", limit); if (limit != context->limit_outstanding_queries) {
context->limit_outstanding_queries = limit;
dispatch_updated(context, dispatch_updated(context,
GETDNS_CONTEXT_CODE_LIMIT_OUTSTANDING_QUERIES); GETDNS_CONTEXT_CODE_LIMIT_OUTSTANDING_QUERIES);
}
return GETDNS_RETURN_GOOD; return GETDNS_RETURN_GOOD;
} /* getdns_context_set_limit_outstanding_queries */ } /* getdns_context_set_limit_outstanding_queries */
@ -736,10 +782,12 @@ getdns_context_set_follow_redirects(struct getdns_context *context,
{ {
RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER); RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER);
context->follow_redirects = value; context->follow_redirects = value;
if (context->resolution_type_set != 0) {
/* already setup */
return GETDNS_RETURN_CONTEXT_UPDATE_FAIL;
}
clear_resolution_type_set_flag(context, GETDNS_RESOLUTION_RECURSING);
dispatch_updated(context, GETDNS_CONTEXT_CODE_FOLLOW_REDIRECTS); dispatch_updated(context, GETDNS_CONTEXT_CODE_FOLLOW_REDIRECTS);
return GETDNS_RETURN_GOOD; return GETDNS_RETURN_GOOD;
} /* getdns_context_set_follow_redirects */ } /* getdns_context_set_follow_redirects */
@ -754,6 +802,10 @@ getdns_context_set_dns_root_servers(struct getdns_context *context,
struct getdns_list *copy = NULL; struct getdns_list *copy = NULL;
size_t count = 0; size_t count = 0;
RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER); RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER);
if (context->resolution_type_set != 0) {
/* already setup */
return GETDNS_RETURN_CONTEXT_UPDATE_FAIL;
}
if (addresses != NULL) { if (addresses != NULL) {
if (getdns_list_copy(addresses, &copy) != GETDNS_RETURN_GOOD) { if (getdns_list_copy(addresses, &copy) != GETDNS_RETURN_GOOD) {
return GETDNS_RETURN_CONTEXT_UPDATE_FAIL; return GETDNS_RETURN_CONTEXT_UPDATE_FAIL;
@ -785,8 +837,6 @@ getdns_context_set_dns_root_servers(struct getdns_context *context,
getdns_list_destroy(context->dns_root_servers); getdns_list_destroy(context->dns_root_servers);
context->dns_root_servers = addresses; context->dns_root_servers = addresses;
clear_resolution_type_set_flag(context, GETDNS_RESOLUTION_RECURSING);
dispatch_updated(context, GETDNS_CONTEXT_CODE_DNS_ROOT_SERVERS); dispatch_updated(context, GETDNS_CONTEXT_CODE_DNS_ROOT_SERVERS);
return GETDNS_RETURN_GOOD; return GETDNS_RETURN_GOOD;
@ -824,6 +874,10 @@ getdns_context_set_suffix(struct getdns_context *context, struct getdns_list * v
{ {
struct getdns_list *copy = NULL; struct getdns_list *copy = NULL;
RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER); RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER);
if (context->resolution_type_set != 0) {
/* already setup */
return GETDNS_RETURN_CONTEXT_UPDATE_FAIL;
}
if (value != NULL) { if (value != NULL) {
if (getdns_list_copy(value, &copy) != GETDNS_RETURN_GOOD) { if (getdns_list_copy(value, &copy) != GETDNS_RETURN_GOOD) {
return GETDNS_RETURN_CONTEXT_UPDATE_FAIL; return GETDNS_RETURN_CONTEXT_UPDATE_FAIL;
@ -833,8 +887,6 @@ getdns_context_set_suffix(struct getdns_context *context, struct getdns_list * v
getdns_list_destroy(context->suffix); getdns_list_destroy(context->suffix);
context->suffix = value; context->suffix = value;
clear_resolution_type_set_flag(context, GETDNS_RESOLUTION_STUB);
dispatch_updated(context, GETDNS_CONTEXT_CODE_SUFFIX); dispatch_updated(context, GETDNS_CONTEXT_CODE_SUFFIX);
return GETDNS_RETURN_GOOD; return GETDNS_RETURN_GOOD;
@ -864,6 +916,11 @@ getdns_context_set_dnssec_trust_anchors(struct getdns_context *context,
return GETDNS_RETURN_GOOD; return GETDNS_RETURN_GOOD;
} /* getdns_context_set_dnssec_trust_anchors */ } /* getdns_context_set_dnssec_trust_anchors */
static void
set_ub_dnssec_allowed_skew(struct getdns_context* context, uint32_t value) {
set_ub_number_opt(context, "val-sig-skew-min", value);
set_ub_number_opt(context, "val-sig-skew-max", value);
}
/* /*
* getdns_context_set_dnssec_allowed_skew * getdns_context_set_dnssec_allowed_skew
* *
@ -873,9 +930,11 @@ getdns_context_set_dnssec_allowed_skew(struct getdns_context *context,
uint32_t value) uint32_t value)
{ {
RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER); RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER);
set_ub_number_opt(context, "val-sig-skew-min", value); set_ub_dnssec_allowed_skew(context, value);
set_ub_number_opt(context, "val-sig-skew-max", value); if (value != context->dnssec_allowed_skew) {
context->dnssec_allowed_skew = value;
dispatch_updated(context, GETDNS_CONTEXT_CODE_DNSSEC_ALLOWED_SKEW); dispatch_updated(context, GETDNS_CONTEXT_CODE_DNSSEC_ALLOWED_SKEW);
}
return GETDNS_RETURN_GOOD; return GETDNS_RETURN_GOOD;
} /* getdns_context_set_dnssec_allowed_skew */ } /* getdns_context_set_dnssec_allowed_skew */
@ -896,6 +955,10 @@ getdns_context_set_upstream_recursive_servers(struct getdns_context *context,
if (count == 0 || r != GETDNS_RETURN_GOOD) { if (count == 0 || r != GETDNS_RETURN_GOOD) {
return GETDNS_RETURN_CONTEXT_UPDATE_FAIL; return GETDNS_RETURN_CONTEXT_UPDATE_FAIL;
} }
if (context->resolution_type_set != 0) {
/* already setup */
return GETDNS_RETURN_CONTEXT_UPDATE_FAIL;
}
struct getdns_list *copy = NULL; struct getdns_list *copy = NULL;
if (getdns_list_copy(upstream_list, &copy) != GETDNS_RETURN_GOOD) { if (getdns_list_copy(upstream_list, &copy) != GETDNS_RETURN_GOOD) {
return GETDNS_RETURN_CONTEXT_UPDATE_FAIL; return GETDNS_RETURN_CONTEXT_UPDATE_FAIL;
@ -919,14 +982,19 @@ getdns_context_set_upstream_recursive_servers(struct getdns_context *context,
getdns_list_destroy(context->upstream_list); getdns_list_destroy(context->upstream_list);
context->upstream_list = upstream_list; context->upstream_list = upstream_list;
clear_resolution_type_set_flag(context, GETDNS_RESOLUTION_STUB);
dispatch_updated(context, dispatch_updated(context,
GETDNS_CONTEXT_CODE_UPSTREAM_RECURSIVE_SERVERS); GETDNS_CONTEXT_CODE_UPSTREAM_RECURSIVE_SERVERS);
return GETDNS_RETURN_GOOD; return GETDNS_RETURN_GOOD;
} /* getdns_context_set_upstream_recursive_servers */ } /* getdns_context_set_upstream_recursive_servers */
static void
set_ub_edns_maximum_udp_payload_size(struct getdns_context* context,
uint16_t value) {
/* max-udp-size */
set_ub_number_opt(context, "max-udp-size", value);
}
/* /*
* getdns_context_set_edns_maximum_udp_payload_size * getdns_context_set_edns_maximum_udp_payload_size
* *
@ -940,12 +1008,12 @@ getdns_context_set_edns_maximum_udp_payload_size(struct getdns_context *context,
if (value < 512) { if (value < 512) {
return GETDNS_RETURN_CONTEXT_UPDATE_FAIL; return GETDNS_RETURN_CONTEXT_UPDATE_FAIL;
} }
set_ub_edns_maximum_udp_payload_size(context, value);
/* max-udp-size */ if (value != context->edns_maximum_udp_payload_size) {
set_ub_number_opt(context, "max-udp-size", value); context->edns_maximum_udp_payload_size = value;
dispatch_updated(context, dispatch_updated(context,
GETDNS_CONTEXT_CODE_EDNS_MAXIMUM_UDP_PAYLOAD_SIZE); GETDNS_CONTEXT_CODE_EDNS_MAXIMUM_UDP_PAYLOAD_SIZE);
}
return GETDNS_RETURN_GOOD; return GETDNS_RETURN_GOOD;
} /* getdns_context_set_edns_maximum_udp_payload_size */ } /* getdns_context_set_edns_maximum_udp_payload_size */
@ -1243,6 +1311,7 @@ getdns_context_prepare_for_resolution(struct getdns_context *context,
* so we need to respect that order * so we need to respect that order
*/ */
if (! usenamespaces) { if (! usenamespaces) {
r = priv_getdns_ns_dns_setup(context); r = priv_getdns_ns_dns_setup(context);
if (r == GETDNS_RETURN_GOOD) if (r == GETDNS_RETURN_GOOD)

View File

@ -78,10 +78,14 @@ struct getdns_context {
struct getdns_list *suffix; struct getdns_list *suffix;
struct getdns_list *dnssec_trust_anchors; struct getdns_list *dnssec_trust_anchors;
struct getdns_list *upstream_list; struct getdns_list *upstream_list;
getdns_transport_t dns_transport;
uint16_t limit_outstanding_queries;
uint32_t dnssec_allowed_skew;
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;
uint16_t edns_maximum_udp_payload_size;
getdns_update_callback update_callback; getdns_update_callback update_callback;