mirror of https://github.com/getdnsapi/getdns.git
getdns_context_set_upstream_recursive_servers
This commit is contained in:
parent
3742edaf07
commit
2dcdfaba37
254
src/context.c
254
src/context.c
|
@ -236,6 +236,35 @@ filechg_check(struct getdns_context *context, struct filechg *fchg)
|
||||||
return fchg->changes;
|
return fchg->changes;
|
||||||
} /* filechg */
|
} /* filechg */
|
||||||
|
|
||||||
|
static getdns_upstreams *
|
||||||
|
upstreams_create(getdns_context *context, size_t size)
|
||||||
|
{
|
||||||
|
getdns_upstreams *r = (void *) GETDNS_XMALLOC(context->mf, char,
|
||||||
|
sizeof(getdns_upstreams) +
|
||||||
|
sizeof(struct getdns_upstream) * size);
|
||||||
|
r->mf = context->mf;
|
||||||
|
r->referenced = 1;
|
||||||
|
r->count = 0;
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
static getdns_upstreams *
|
||||||
|
upstreams_resize(getdns_upstreams *upstreams, size_t size)
|
||||||
|
{
|
||||||
|
getdns_upstreams *r = (void *) GETDNS_XREALLOC(
|
||||||
|
upstreams->mf, upstreams, char,
|
||||||
|
sizeof(getdns_upstreams) +
|
||||||
|
sizeof(struct getdns_upstream) * size);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
upstreams_dereference(getdns_upstreams *upstreams)
|
||||||
|
{
|
||||||
|
if (--upstreams->referenced == 0)
|
||||||
|
GETDNS_FREE(upstreams->mf, upstreams);
|
||||||
|
}
|
||||||
|
|
||||||
static size_t
|
static size_t
|
||||||
upstream_addr_len(struct getdns_upstream *upstream)
|
upstream_addr_len(struct getdns_upstream *upstream)
|
||||||
{
|
{
|
||||||
|
@ -267,7 +296,7 @@ upstream_scope_id(struct getdns_upstream *upstream)
|
||||||
&((struct sockaddr_in6*)&upstream->addr)->sin6_scope_id : NULL);
|
&((struct sockaddr_in6*)&upstream->addr)->sin6_scope_id : NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
static void
|
||||||
upstream_ntop_buf(struct getdns_upstream *upstream, char *buf, size_t len)
|
upstream_ntop_buf(struct getdns_upstream *upstream, char *buf, size_t len)
|
||||||
{
|
{
|
||||||
/* Also possible but prints scope_id by name (nor parsed by unbound)
|
/* Also possible but prints scope_id by name (nor parsed by unbound)
|
||||||
|
@ -285,6 +314,31 @@ upstream_ntop_buf(struct getdns_upstream *upstream, char *buf, size_t len)
|
||||||
"@%d", (int)upstream_port(upstream));
|
"@%d", (int)upstream_port(upstream));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static getdns_dict *
|
||||||
|
upstream_dict(getdns_context *context, struct getdns_upstream *upstream)
|
||||||
|
{
|
||||||
|
getdns_dict *r = getdns_dict_create_with_context(context);
|
||||||
|
char addrstr[1024], *b;
|
||||||
|
getdns_bindata bindata;
|
||||||
|
|
||||||
|
getdns_dict_util_set_string(r, "address_type",
|
||||||
|
upstream->addr.ss_family == AF_INET ? "IPv4" : "IPv6");
|
||||||
|
|
||||||
|
bindata.size = upstream_addr_len(upstream);
|
||||||
|
bindata.data = upstream_addr(upstream);
|
||||||
|
getdns_dict_set_bindata(r, "address_data", &bindata);
|
||||||
|
|
||||||
|
if (upstream_port(upstream) != 53)
|
||||||
|
getdns_dict_set_int(r, "port", upstream_port(upstream));
|
||||||
|
|
||||||
|
(void) getnameinfo((struct sockaddr *)&upstream->addr,
|
||||||
|
upstream->addr_len, addrstr, 1024, NULL, 0, NI_NUMERICHOST);
|
||||||
|
if ((b = strchr(addrstr, '%')))
|
||||||
|
getdns_dict_util_set_string(r, "scope_id", b+1);
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
/*---------------------------------------- set_os_defaults
|
/*---------------------------------------- set_os_defaults
|
||||||
we use ldns to read the resolv.conf file - the ldns resolver is
|
we use ldns to read the resolv.conf file - the ldns resolver is
|
||||||
destroyed once the file is read
|
destroyed once the file is read
|
||||||
|
@ -300,7 +354,6 @@ set_os_defaults(struct getdns_context *context)
|
||||||
struct addrinfo hints;
|
struct addrinfo hints;
|
||||||
struct addrinfo *result;
|
struct addrinfo *result;
|
||||||
struct getdns_upstream *upstream;
|
struct getdns_upstream *upstream;
|
||||||
struct getdns_dict *addr;
|
|
||||||
int s;
|
int s;
|
||||||
|
|
||||||
if(context->fchg_resolvconf == NULL) {
|
if(context->fchg_resolvconf == NULL) {
|
||||||
|
@ -315,14 +368,8 @@ set_os_defaults(struct getdns_context *context)
|
||||||
}
|
}
|
||||||
filechg_check(context, context->fchg_resolvconf);
|
filechg_check(context, context->fchg_resolvconf);
|
||||||
|
|
||||||
context->upstream_list = getdns_list_create_with_context(context);
|
|
||||||
context->suffix = getdns_list_create_with_context(context);
|
context->suffix = getdns_list_create_with_context(context);
|
||||||
context->upstreams = (void *) GETDNS_XMALLOC(context->mf, char,
|
context->upstreams = upstreams_create(context, upstreams_limit);
|
||||||
sizeof(getdns_upstreams) +
|
|
||||||
sizeof(struct getdns_upstream) * upstreams_limit);
|
|
||||||
context->upstreams->mf = context->mf;
|
|
||||||
context->upstreams->referenced = 1;
|
|
||||||
context->upstreams->count = 0;
|
|
||||||
|
|
||||||
in = fopen(context->fchg_resolvconf->fn, "r");
|
in = fopen(context->fchg_resolvconf->fn, "r");
|
||||||
if (!in)
|
if (!in)
|
||||||
|
@ -388,13 +435,9 @@ set_os_defaults(struct getdns_context *context)
|
||||||
if (! result) continue;
|
if (! result) continue;
|
||||||
|
|
||||||
/* Grow array when needed */
|
/* Grow array when needed */
|
||||||
if (context->upstreams->count == upstreams_limit) {
|
if (context->upstreams->count == upstreams_limit)
|
||||||
upstreams_limit *= 2;
|
context->upstreams = upstreams_resize(
|
||||||
context->upstreams = (void *) GETDNS_XREALLOC(
|
context->upstreams, (upstreams_limit *= 2));
|
||||||
context->mf, context->upstreams, char,
|
|
||||||
sizeof(getdns_upstreams) +
|
|
||||||
sizeof(struct getdns_upstream) * upstreams_limit);
|
|
||||||
}
|
|
||||||
|
|
||||||
upstream = &context->upstreams->
|
upstream = &context->upstreams->
|
||||||
upstreams[context->upstreams->count++];
|
upstreams[context->upstreams->count++];
|
||||||
|
@ -404,31 +447,6 @@ set_os_defaults(struct getdns_context *context)
|
||||||
(void) memcpy(&upstream->addr,
|
(void) memcpy(&upstream->addr,
|
||||||
result->ai_addr, result->ai_addrlen);
|
result->ai_addr, result->ai_addrlen);
|
||||||
freeaddrinfo(result);
|
freeaddrinfo(result);
|
||||||
|
|
||||||
/*****************************************************
|
|
||||||
* Add to context->upstream_list too.
|
|
||||||
* TODO: remove this after async stub is finished.
|
|
||||||
*/
|
|
||||||
addr = getdns_dict_create_with_context(context);
|
|
||||||
bindata.size = upstream_addr_len(upstream);
|
|
||||||
bindata.data = upstream_addr(upstream);
|
|
||||||
(void) getdns_dict_set_int(
|
|
||||||
addr, "port", upstream_port(upstream));
|
|
||||||
(void) getdns_dict_set_bindata(addr, "address_data", &bindata);
|
|
||||||
if ((parse = strchr(parse, '%'))) {
|
|
||||||
parse += 1;
|
|
||||||
bindata.size = strlen(parse) + 1;
|
|
||||||
bindata.data = (uint8_t *)parse;
|
|
||||||
(void) getdns_dict_set_bindata(
|
|
||||||
addr, "scope_id", &bindata);
|
|
||||||
}
|
|
||||||
(void) getdns_list_get_length(context->upstream_list, &length);
|
|
||||||
(void) getdns_list_set_dict(
|
|
||||||
context->upstream_list, length, addr);
|
|
||||||
|
|
||||||
getdns_dict_destroy(addr);
|
|
||||||
/*
|
|
||||||
*****************************************************/
|
|
||||||
}
|
}
|
||||||
fclose(in);
|
fclose(in);
|
||||||
|
|
||||||
|
@ -593,7 +611,6 @@ getdns_context_create_with_extended_memory_functions(
|
||||||
result->suffix = NULL;
|
result->suffix = NULL;
|
||||||
|
|
||||||
result->dnssec_trust_anchors = NULL;
|
result->dnssec_trust_anchors = NULL;
|
||||||
result->upstream_list = NULL;
|
|
||||||
|
|
||||||
result->edns_extended_rcode = 0;
|
result->edns_extended_rcode = 0;
|
||||||
result->edns_version = 0;
|
result->edns_version = 0;
|
||||||
|
@ -717,7 +734,6 @@ getdns_context_destroy(struct getdns_context *context)
|
||||||
getdns_list_destroy(context->dns_root_servers);
|
getdns_list_destroy(context->dns_root_servers);
|
||||||
getdns_list_destroy(context->suffix);
|
getdns_list_destroy(context->suffix);
|
||||||
getdns_list_destroy(context->dnssec_trust_anchors);
|
getdns_list_destroy(context->dnssec_trust_anchors);
|
||||||
getdns_list_destroy(context->upstream_list);
|
|
||||||
|
|
||||||
/* destroy the contexts */
|
/* destroy the contexts */
|
||||||
if (context->unbound_ctx)
|
if (context->unbound_ctx)
|
||||||
|
@ -737,8 +753,7 @@ getdns_context_destroy(struct getdns_context *context)
|
||||||
GETDNS_FREE(context->my_mf, context->local_hosts);
|
GETDNS_FREE(context->my_mf, context->local_hosts);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (--context->upstreams->referenced == 0)
|
upstreams_dereference(context->upstreams);
|
||||||
GETDNS_FREE(context->upstreams->mf, context->upstreams);
|
|
||||||
|
|
||||||
GETDNS_FREE(context->my_mf, context);
|
GETDNS_FREE(context->my_mf, context);
|
||||||
} /* getdns_context_destroy */
|
} /* getdns_context_destroy */
|
||||||
|
@ -1195,47 +1210,106 @@ getdns_context_set_dnssec_allowed_skew(struct getdns_context *context,
|
||||||
*/
|
*/
|
||||||
getdns_return_t
|
getdns_return_t
|
||||||
getdns_context_set_upstream_recursive_servers(struct getdns_context *context,
|
getdns_context_set_upstream_recursive_servers(struct getdns_context *context,
|
||||||
struct getdns_list * upstream_list)
|
struct getdns_list *upstream_list)
|
||||||
{
|
{
|
||||||
size_t count = 0;
|
getdns_return_t r;
|
||||||
size_t i = 0;
|
size_t count = 0;
|
||||||
RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER);
|
size_t i;
|
||||||
RETURN_IF_NULL(upstream_list, GETDNS_RETURN_INVALID_PARAMETER);
|
getdns_upstreams *upstreams;
|
||||||
getdns_return_t r = getdns_list_get_length(upstream_list, &count);
|
char addrstr[1024], portstr[1024], *eos;
|
||||||
if (count == 0 || r != GETDNS_RETURN_GOOD) {
|
struct addrinfo hints;
|
||||||
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;
|
|
||||||
if (getdns_list_copy(upstream_list, ©) != GETDNS_RETURN_GOOD) {
|
|
||||||
return GETDNS_RETURN_CONTEXT_UPDATE_FAIL;
|
|
||||||
}
|
|
||||||
upstream_list = copy;
|
|
||||||
/* validate and add ip str */
|
|
||||||
for (i = 0; i < count; ++i) {
|
|
||||||
struct getdns_dict *dict = NULL;
|
|
||||||
getdns_list_get_dict(upstream_list, i, &dict);
|
|
||||||
if (r != GETDNS_RETURN_GOOD) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (r != GETDNS_RETURN_GOOD) {
|
RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER);
|
||||||
getdns_list_destroy(upstream_list);
|
RETURN_IF_NULL(upstream_list, GETDNS_RETURN_INVALID_PARAMETER);
|
||||||
return GETDNS_RETURN_CONTEXT_UPDATE_FAIL;
|
|
||||||
}
|
r = getdns_list_get_length(upstream_list, &count);
|
||||||
|
if (count == 0 || r != GETDNS_RETURN_GOOD) {
|
||||||
|
return GETDNS_RETURN_CONTEXT_UPDATE_FAIL;
|
||||||
|
}
|
||||||
|
if (context->resolution_type_set != 0) {
|
||||||
|
/* already setup */
|
||||||
|
return GETDNS_RETURN_CONTEXT_UPDATE_FAIL;
|
||||||
|
}
|
||||||
|
memset(&hints, 0, sizeof(struct addrinfo));
|
||||||
|
hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */
|
||||||
|
hints.ai_socktype = 0; /* Datagram socket */
|
||||||
|
hints.ai_flags = AI_NUMERICHOST; /* No reverse name lookups */
|
||||||
|
hints.ai_protocol = 0; /* Any protocol */
|
||||||
|
hints.ai_canonname = NULL;
|
||||||
|
hints.ai_addr = NULL;
|
||||||
|
hints.ai_next = NULL;
|
||||||
|
|
||||||
getdns_list_destroy(context->upstream_list);
|
upstreams = upstreams_create(context, count);
|
||||||
context->upstream_list = upstream_list;
|
for (i = 0; i < count; i++) {
|
||||||
|
getdns_dict *dict;
|
||||||
|
getdns_bindata *address_type;
|
||||||
|
getdns_bindata *address_data;
|
||||||
|
uint32_t port;
|
||||||
|
getdns_bindata *scope_id;
|
||||||
|
struct addrinfo *ai;
|
||||||
|
struct getdns_upstream *upstream;
|
||||||
|
|
||||||
dispatch_updated(context,
|
if ((r = getdns_list_get_dict(upstream_list, i, &dict)))
|
||||||
GETDNS_CONTEXT_CODE_UPSTREAM_RECURSIVE_SERVERS);
|
goto error;
|
||||||
|
|
||||||
return GETDNS_RETURN_GOOD;
|
if ((r = getdns_dict_get_bindata(
|
||||||
} /* getdns_context_set_upstream_recursive_servers */
|
dict, "address_type",&address_type)))
|
||||||
|
goto error;
|
||||||
|
if (address_type->size < 4)
|
||||||
|
goto invalid_parameter;
|
||||||
|
if (strncmp((char *)address_type->data, "IPv4", 4) == 0)
|
||||||
|
upstream->addr.ss_family = AF_INET;
|
||||||
|
else if (strncmp((char *)address_type->data, "IPv6", 4) == 0)
|
||||||
|
upstream->addr.ss_family = AF_INET6;
|
||||||
|
else goto invalid_parameter;
|
||||||
|
|
||||||
|
if ((r = getdns_dict_get_bindata(
|
||||||
|
dict, "address_data",&address_data)))
|
||||||
|
goto error;
|
||||||
|
if ((upstream->addr.ss_family == AF_INET &&
|
||||||
|
address_data->size != 4) ||
|
||||||
|
(upstream->addr.ss_family == AF_INET6 &&
|
||||||
|
address_data->size != 16))
|
||||||
|
goto invalid_parameter;
|
||||||
|
if (inet_ntop(upstream->addr.ss_family, address_data,
|
||||||
|
addrstr, 1024) == NULL)
|
||||||
|
goto invalid_parameter;
|
||||||
|
|
||||||
|
port = 53;
|
||||||
|
(void) getdns_dict_get_int(dict, "port", &port);
|
||||||
|
(void) snprintf(portstr, 1024, "%d", (int)port);
|
||||||
|
|
||||||
|
if (getdns_dict_get_bindata(dict, "scope_id", &scope_id) ==
|
||||||
|
GETDNS_RETURN_GOOD) {
|
||||||
|
if (strlen(addrstr) + scope_id->size > 1022)
|
||||||
|
goto invalid_parameter;
|
||||||
|
eos = &addrstr[strlen(addrstr)];
|
||||||
|
*eos++ = '%';
|
||||||
|
(void) memcpy(eos, scope_id->data, scope_id->size);
|
||||||
|
eos[scope_id->size] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (getaddrinfo(addrstr, portstr, &hints, &ai))
|
||||||
|
goto invalid_parameter;
|
||||||
|
|
||||||
|
upstream = &upstreams->upstreams[upstreams->count++];
|
||||||
|
upstream->rtt = 1;
|
||||||
|
upstream->tcp_fd = -1;
|
||||||
|
upstream->addr_len = ai->ai_addrlen;
|
||||||
|
(void) memcpy(&upstream->addr, ai->ai_addr, ai->ai_addrlen);
|
||||||
|
freeaddrinfo(ai);
|
||||||
|
}
|
||||||
|
dispatch_updated(context,
|
||||||
|
GETDNS_CONTEXT_CODE_UPSTREAM_RECURSIVE_SERVERS);
|
||||||
|
|
||||||
|
return GETDNS_RETURN_GOOD;
|
||||||
|
|
||||||
|
invalid_parameter:
|
||||||
|
r = GETDNS_RETURN_INVALID_PARAMETER;
|
||||||
|
error:
|
||||||
|
upstreams_dereference(upstreams);
|
||||||
|
return r;
|
||||||
|
} /* getdns_context_set_upstream_recursive_servers */
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -2045,7 +2119,23 @@ priv_get_context_settings(getdns_context* context) {
|
||||||
r |= getdns_dict_set_int(result, "append_name", context->append_name);
|
r |= getdns_dict_set_int(result, "append_name", context->append_name);
|
||||||
/* list fields */
|
/* list fields */
|
||||||
r |= priv_dict_set_list_if_not_null(result, "suffix", context->suffix);
|
r |= priv_dict_set_list_if_not_null(result, "suffix", context->suffix);
|
||||||
r |= priv_dict_set_list_if_not_null(result, "upstream_recursive_servers", context->upstream_list);
|
if (context->upstreams->count > 0) {
|
||||||
|
size_t i;
|
||||||
|
struct getdns_upstream *upstream;
|
||||||
|
getdns_list *upstreams =
|
||||||
|
getdns_list_create_with_context(context);
|
||||||
|
|
||||||
|
for (i = 0; i < context->upstreams->count; i++) {
|
||||||
|
getdns_dict *d;
|
||||||
|
upstream = &context->upstreams->upstreams[i];
|
||||||
|
d = upstream_dict(context, upstream);
|
||||||
|
r |= getdns_list_set_dict(upstreams, i, d);
|
||||||
|
getdns_dict_destroy(d);
|
||||||
|
}
|
||||||
|
r |= getdns_dict_set_list(result, "upstream_recursive_servers",
|
||||||
|
upstreams);
|
||||||
|
getdns_list_destroy(upstreams);
|
||||||
|
}
|
||||||
if (context->namespace_count > 0) {
|
if (context->namespace_count > 0) {
|
||||||
/* create a namespace list */
|
/* create a namespace list */
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
|
@ -91,7 +91,7 @@ struct getdns_context {
|
||||||
getdns_append_name_t append_name;
|
getdns_append_name_t append_name;
|
||||||
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;
|
getdns_upstreams *upstreams;
|
||||||
getdns_transport_t dns_transport;
|
getdns_transport_t dns_transport;
|
||||||
uint16_t limit_outstanding_queries;
|
uint16_t limit_outstanding_queries;
|
||||||
uint32_t dnssec_allowed_skew;
|
uint32_t dnssec_allowed_skew;
|
||||||
|
@ -153,7 +153,6 @@ struct getdns_context {
|
||||||
struct filechg *fchg_resolvconf;
|
struct filechg *fchg_resolvconf;
|
||||||
struct filechg *fchg_hosts;
|
struct filechg *fchg_hosts;
|
||||||
|
|
||||||
getdns_upstreams *upstreams;
|
|
||||||
}; /* getdns_context */
|
}; /* getdns_context */
|
||||||
|
|
||||||
/** internal functions **/
|
/** internal functions **/
|
||||||
|
|
Loading…
Reference in New Issue