mirror of https://github.com/getdnsapi/getdns.git
Merge branch 'features/suffix_handling' into develop
This commit is contained in:
commit
853bc6c150
187
src/context.c
187
src/context.c
|
@ -98,12 +98,14 @@ getdns_port_array[GETDNS_UPSTREAM_TRANSPORTS] = {
|
||||||
GETDNS_PORT_DNS_OVER_TLS
|
GETDNS_PORT_DNS_OVER_TLS
|
||||||
};
|
};
|
||||||
|
|
||||||
char*
|
static char*
|
||||||
getdns_port_str_array[] = {
|
getdns_port_str_array[] = {
|
||||||
GETDNS_STR_PORT_DNS,
|
GETDNS_STR_PORT_DNS,
|
||||||
GETDNS_STR_PORT_DNS_OVER_TLS
|
GETDNS_STR_PORT_DNS_OVER_TLS
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const uint8_t no_suffixes[] = { 1, 0 };
|
||||||
|
|
||||||
/* Private functions */
|
/* Private functions */
|
||||||
static getdns_return_t create_default_namespaces(struct getdns_context *context);
|
static getdns_return_t create_default_namespaces(struct getdns_context *context);
|
||||||
static getdns_return_t create_default_dns_transports(struct getdns_context *context);
|
static getdns_return_t create_default_dns_transports(struct getdns_context *context);
|
||||||
|
@ -717,7 +719,7 @@ upstream_init(getdns_upstream *upstream,
|
||||||
static getdns_return_t
|
static getdns_return_t
|
||||||
set_os_defaults_windows(struct getdns_context *context)
|
set_os_defaults_windows(struct getdns_context *context)
|
||||||
{
|
{
|
||||||
char domain[1024];
|
char domain[1024] = "";
|
||||||
size_t upstreams_limit = 10, length;
|
size_t upstreams_limit = 10, length;
|
||||||
struct getdns_bindata bindata;
|
struct getdns_bindata bindata;
|
||||||
struct addrinfo hints;
|
struct addrinfo hints;
|
||||||
|
@ -737,7 +739,6 @@ set_os_defaults_windows(struct getdns_context *context)
|
||||||
}
|
}
|
||||||
_getdns_filechg_check(context, context->fchg_resolvconf);
|
_getdns_filechg_check(context, context->fchg_resolvconf);
|
||||||
|
|
||||||
context->suffix = getdns_list_create_with_context(context);
|
|
||||||
context->upstreams = upstreams_create(context, upstreams_limit);
|
context->upstreams = upstreams_create(context, upstreams_limit);
|
||||||
|
|
||||||
memset(&hints, 0, sizeof(struct addrinfo));
|
memset(&hints, 0, sizeof(struct addrinfo));
|
||||||
|
@ -786,13 +787,6 @@ set_os_defaults_windows(struct getdns_context *context)
|
||||||
}
|
}
|
||||||
free(info);
|
free(info);
|
||||||
}
|
}
|
||||||
|
|
||||||
(void)getdns_list_get_length(context->suffix, &length);
|
|
||||||
if (length == 0 && *domain != 0) {
|
|
||||||
bindata.data = (uint8_t *)domain;
|
|
||||||
bindata.size = strlen(domain) + 1;
|
|
||||||
(void)getdns_list_set_bindata(context->suffix, 0, &bindata);
|
|
||||||
}
|
|
||||||
return GETDNS_RETURN_GOOD;
|
return GETDNS_RETURN_GOOD;
|
||||||
} /* set_os_defaults_windows */
|
} /* set_os_defaults_windows */
|
||||||
#else
|
#else
|
||||||
|
@ -806,6 +800,7 @@ set_os_defaults(struct getdns_context *context)
|
||||||
struct addrinfo hints;
|
struct addrinfo hints;
|
||||||
struct addrinfo *result;
|
struct addrinfo *result;
|
||||||
getdns_upstream *upstream;
|
getdns_upstream *upstream;
|
||||||
|
getdns_list *suffix;
|
||||||
int s;
|
int s;
|
||||||
|
|
||||||
if(context->fchg_resolvconf == NULL) {
|
if(context->fchg_resolvconf == NULL) {
|
||||||
|
@ -830,7 +825,7 @@ set_os_defaults(struct getdns_context *context)
|
||||||
upstream_count++;
|
upstream_count++;
|
||||||
fclose(in);
|
fclose(in);
|
||||||
|
|
||||||
context->suffix = getdns_list_create_with_context(context);
|
suffix = getdns_list_create_with_context(context);
|
||||||
context->upstreams = upstreams_create(
|
context->upstreams = upstreams_create(
|
||||||
context, upstream_count * GETDNS_UPSTREAM_TRANSPORTS);
|
context, upstream_count * GETDNS_UPSTREAM_TRANSPORTS);
|
||||||
|
|
||||||
|
@ -871,7 +866,7 @@ set_os_defaults(struct getdns_context *context)
|
||||||
prev_ch = *token;
|
prev_ch = *token;
|
||||||
*token = 0;
|
*token = 0;
|
||||||
|
|
||||||
_getdns_list_append_string(context->suffix, parse);
|
_getdns_list_append_string(suffix, parse);
|
||||||
|
|
||||||
*token = prev_ch;
|
*token = prev_ch;
|
||||||
parse = token;
|
parse = token;
|
||||||
|
@ -902,9 +897,12 @@ set_os_defaults(struct getdns_context *context)
|
||||||
}
|
}
|
||||||
fclose(in);
|
fclose(in);
|
||||||
|
|
||||||
(void) getdns_list_get_length(context->suffix, &length);
|
(void) getdns_list_get_length(suffix, &length);
|
||||||
if (length == 0 && *domain != 0)
|
if (length == 0 && *domain != 0)
|
||||||
_getdns_list_append_string(context->suffix, domain);
|
_getdns_list_append_string(suffix, domain);
|
||||||
|
(void )getdns_context_set_suffix(context, suffix);
|
||||||
|
getdns_list_destroy(suffix);
|
||||||
|
|
||||||
return GETDNS_RETURN_GOOD;
|
return GETDNS_RETURN_GOOD;
|
||||||
} /* set_os_defaults */
|
} /* set_os_defaults */
|
||||||
#endif
|
#endif
|
||||||
|
@ -1008,7 +1006,8 @@ getdns_context_create_with_extended_memory_functions(
|
||||||
result->dns_root_servers = NULL;
|
result->dns_root_servers = NULL;
|
||||||
result->root_servers_fn[0] = 0;
|
result->root_servers_fn[0] = 0;
|
||||||
result->append_name = GETDNS_APPEND_NAME_ALWAYS;
|
result->append_name = GETDNS_APPEND_NAME_ALWAYS;
|
||||||
result->suffix = NULL;
|
result->suffixes = no_suffixes;
|
||||||
|
result->suffixes_len = sizeof(no_suffixes);
|
||||||
|
|
||||||
gldns_buffer_init_frm_data(&gbuf, result->trust_anchors_spc
|
gldns_buffer_init_frm_data(&gbuf, result->trust_anchors_spc
|
||||||
, sizeof(result->trust_anchors_spc));
|
, sizeof(result->trust_anchors_spc));
|
||||||
|
@ -1181,7 +1180,8 @@ getdns_context_destroy(struct getdns_context *context)
|
||||||
if (context->root_servers_fn[0])
|
if (context->root_servers_fn[0])
|
||||||
unlink(context->root_servers_fn);
|
unlink(context->root_servers_fn);
|
||||||
|
|
||||||
getdns_list_destroy(context->suffix);
|
if (context->suffixes && context->suffixes != no_suffixes)
|
||||||
|
GETDNS_FREE(context->mf, (void *)context->suffixes);
|
||||||
|
|
||||||
if (context->trust_anchors &&
|
if (context->trust_anchors &&
|
||||||
context->trust_anchors != context->trust_anchors_spc)
|
context->trust_anchors != context->trust_anchors_spc)
|
||||||
|
@ -1813,26 +1813,90 @@ getdns_context_set_append_name(struct getdns_context *context,
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
getdns_return_t
|
getdns_return_t
|
||||||
getdns_context_set_suffix(struct getdns_context *context, struct getdns_list * value)
|
getdns_context_set_suffix(getdns_context *context, getdns_list *value)
|
||||||
{
|
{
|
||||||
struct getdns_list *copy = NULL;
|
getdns_return_t r;
|
||||||
RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER);
|
size_t i;
|
||||||
if (context->resolution_type_set != 0) {
|
gldns_buffer gbuf;
|
||||||
/* already setup */
|
uint8_t buf_spc[1024], *suffixes = NULL;
|
||||||
return GETDNS_RETURN_CONTEXT_UPDATE_FAIL;
|
size_t suffixes_len = 0;
|
||||||
}
|
uint8_t dname[256];
|
||||||
if (value != NULL) {
|
size_t dname_len;
|
||||||
if (_getdns_list_copy(value, ©) != GETDNS_RETURN_GOOD) {
|
char name_spc[1025], *name;
|
||||||
return GETDNS_RETURN_CONTEXT_UPDATE_FAIL;
|
getdns_bindata *bindata;
|
||||||
}
|
|
||||||
value = copy;
|
|
||||||
}
|
|
||||||
getdns_list_destroy(context->suffix);
|
|
||||||
context->suffix = value;
|
|
||||||
|
|
||||||
dispatch_updated(context, GETDNS_CONTEXT_CODE_SUFFIX);
|
if (!context)
|
||||||
|
return GETDNS_RETURN_INVALID_PARAMETER;
|
||||||
|
|
||||||
return GETDNS_RETURN_GOOD;
|
if (value == NULL) {
|
||||||
|
if (context->suffixes && context->suffixes != no_suffixes)
|
||||||
|
GETDNS_FREE(context->mf, (void *)context->suffixes);
|
||||||
|
|
||||||
|
context->suffixes = no_suffixes;
|
||||||
|
context->suffixes_len = sizeof(no_suffixes);
|
||||||
|
return GETDNS_RETURN_GOOD;
|
||||||
|
}
|
||||||
|
gldns_buffer_init_frm_data(&gbuf, buf_spc, sizeof(buf_spc));
|
||||||
|
for (;;) {
|
||||||
|
for ( i = 0
|
||||||
|
; !(r = getdns_list_get_bindata(value, i, &bindata))
|
||||||
|
; i++) {
|
||||||
|
|
||||||
|
if (bindata->size == 0 || bindata->size >= sizeof(name_spc))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (bindata->data[bindata->size-1] != 0) {
|
||||||
|
/* Unterminated string */
|
||||||
|
(void) memcpy(name_spc, bindata->data, bindata->size);
|
||||||
|
name_spc[bindata->size] = 0;
|
||||||
|
name = name_spc;
|
||||||
|
} else
|
||||||
|
/* Terminated string */
|
||||||
|
name = (char *)bindata->data;
|
||||||
|
|
||||||
|
dname_len = sizeof(dname);
|
||||||
|
if (gldns_str2wire_dname_buf(name, dname, &dname_len))
|
||||||
|
return GETDNS_RETURN_GENERIC_ERROR;
|
||||||
|
|
||||||
|
gldns_buffer_write_u8(&gbuf, dname_len);
|
||||||
|
gldns_buffer_write(&gbuf, dname, dname_len);
|
||||||
|
}
|
||||||
|
if (r == GETDNS_RETURN_NO_SUCH_LIST_ITEM)
|
||||||
|
r = GETDNS_RETURN_GOOD;
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
|
||||||
|
gldns_buffer_write_u8(&gbuf, 1);
|
||||||
|
gldns_buffer_write_u8(&gbuf, 0);
|
||||||
|
|
||||||
|
if (gldns_buffer_begin(&gbuf) != buf_spc)
|
||||||
|
break;
|
||||||
|
|
||||||
|
suffixes_len = gldns_buffer_position(&gbuf);
|
||||||
|
if (!(suffixes = GETDNS_XMALLOC(
|
||||||
|
context->mf, uint8_t, suffixes_len))) {
|
||||||
|
r = GETDNS_RETURN_MEMORY_ERROR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (suffixes_len <= gldns_buffer_limit(&gbuf)) {
|
||||||
|
(void) memcpy (suffixes, buf_spc, suffixes_len);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
gldns_buffer_init_frm_data(&gbuf, suffixes, suffixes_len);
|
||||||
|
}
|
||||||
|
if (r) {
|
||||||
|
if (gldns_buffer_begin(&gbuf) != buf_spc)
|
||||||
|
GETDNS_FREE(context->mf, suffixes);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
if (context->suffixes && context->suffixes != no_suffixes)
|
||||||
|
GETDNS_FREE(context->mf, (void *)context->suffixes);
|
||||||
|
|
||||||
|
context->suffixes = suffixes;
|
||||||
|
context->suffixes_len = suffixes_len;
|
||||||
|
|
||||||
|
dispatch_updated(context, GETDNS_CONTEXT_CODE_SUFFIX);
|
||||||
|
return GETDNS_RETURN_GOOD;
|
||||||
} /* getdns_context_set_suffix */
|
} /* getdns_context_set_suffix */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -2840,7 +2904,7 @@ _get_context_settings(getdns_context* context)
|
||||||
{
|
{
|
||||||
getdns_return_t r = GETDNS_RETURN_GOOD;
|
getdns_return_t r = GETDNS_RETURN_GOOD;
|
||||||
getdns_dict* result = getdns_dict_create_with_context(context);
|
getdns_dict* result = getdns_dict_create_with_context(context);
|
||||||
getdns_list *upstreams;
|
getdns_list *list;
|
||||||
|
|
||||||
if (!result) {
|
if (!result) {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -2858,12 +2922,14 @@ _get_context_settings(getdns_context* context)
|
||||||
r |= getdns_dict_set_int(result, "edns_do_bit", context->edns_do_bit);
|
r |= getdns_dict_set_int(result, "edns_do_bit", context->edns_do_bit);
|
||||||
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 */
|
||||||
if (context->suffix) r |= getdns_dict_set_list(result, "suffix", context->suffix);
|
if (!getdns_context_get_suffix(context, &list)) {
|
||||||
|
r |= getdns_dict_set_list(result, "suffix", list);
|
||||||
if (!getdns_context_get_upstream_recursive_servers(context, &upstreams)) {
|
getdns_list_destroy(list);
|
||||||
|
}
|
||||||
|
if (!getdns_context_get_upstream_recursive_servers(context, &list)) {
|
||||||
r |= getdns_dict_set_list(result, "upstream_recursive_servers",
|
r |= getdns_dict_set_list(result, "upstream_recursive_servers",
|
||||||
upstreams);
|
list);
|
||||||
getdns_list_destroy(upstreams);
|
getdns_list_destroy(list);
|
||||||
}
|
}
|
||||||
if (context->dns_transport_count > 0) {
|
if (context->dns_transport_count > 0) {
|
||||||
/* create a namespace list */
|
/* create a namespace list */
|
||||||
|
@ -3179,14 +3245,41 @@ getdns_context_get_append_name(getdns_context *context,
|
||||||
}
|
}
|
||||||
|
|
||||||
getdns_return_t
|
getdns_return_t
|
||||||
getdns_context_get_suffix(getdns_context *context, getdns_list **value) {
|
getdns_context_get_suffix(getdns_context *context, getdns_list **value)
|
||||||
RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER);
|
{
|
||||||
RETURN_IF_NULL(value, GETDNS_RETURN_INVALID_PARAMETER);
|
size_t dname_len;
|
||||||
*value = NULL;
|
const uint8_t *dname;
|
||||||
if (context->suffix) {
|
char name[1024];
|
||||||
return _getdns_list_copy(context->suffix, value);
|
getdns_return_t r = GETDNS_RETURN_GOOD;
|
||||||
}
|
getdns_list *list;
|
||||||
return GETDNS_RETURN_GOOD;
|
|
||||||
|
if (!context || !value)
|
||||||
|
return GETDNS_RETURN_INVALID_PARAMETER;
|
||||||
|
|
||||||
|
if (!(list = getdns_list_create_with_context(context)))
|
||||||
|
return GETDNS_RETURN_MEMORY_ERROR;
|
||||||
|
|
||||||
|
assert(context->suffixes);
|
||||||
|
dname_len = context->suffixes[0];
|
||||||
|
dname = context->suffixes + 1;
|
||||||
|
while (dname_len && *dname) {
|
||||||
|
if (! gldns_wire2str_dname_buf((UNCONST_UINT8_p)
|
||||||
|
dname, dname_len, name, sizeof(name))) {
|
||||||
|
r = GETDNS_RETURN_GENERIC_ERROR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if ((r = _getdns_list_append_const_bindata(
|
||||||
|
list, strlen(name) + 1, name)))
|
||||||
|
break;
|
||||||
|
dname += dname_len;
|
||||||
|
dname_len = *dname++;
|
||||||
|
}
|
||||||
|
if (r)
|
||||||
|
getdns_list_destroy(list);
|
||||||
|
else
|
||||||
|
*value = list;
|
||||||
|
|
||||||
|
return GETDNS_RETURN_GOOD;
|
||||||
}
|
}
|
||||||
|
|
||||||
getdns_return_t
|
getdns_return_t
|
||||||
|
|
|
@ -179,7 +179,13 @@ struct getdns_context {
|
||||||
getdns_list *dns_root_servers;
|
getdns_list *dns_root_servers;
|
||||||
char root_servers_fn[FILENAME_MAX];
|
char root_servers_fn[FILENAME_MAX];
|
||||||
getdns_append_name_t append_name;
|
getdns_append_name_t append_name;
|
||||||
struct getdns_list *suffix;
|
/* Suffix buffer containing a list of (length byte | dname) where
|
||||||
|
* length bytes contains the length of the following dname.
|
||||||
|
* The last dname should be the zero byte.
|
||||||
|
*/
|
||||||
|
const uint8_t *suffixes;
|
||||||
|
/* Length of all suffixes in the suffix buffer */
|
||||||
|
size_t suffixes_len;
|
||||||
uint8_t *trust_anchors;
|
uint8_t *trust_anchors;
|
||||||
size_t trust_anchors_len;
|
size_t trust_anchors_len;
|
||||||
getdns_upstreams *upstreams;
|
getdns_upstreams *upstreams;
|
||||||
|
|
30
src/dict.c
30
src/dict.c
|
@ -280,7 +280,8 @@ getdns_dict_get_names(const getdns_dict *dict, getdns_list **answer)
|
||||||
|
|
||||||
RBTREE_FOR(item, struct getdns_dict_item *,
|
RBTREE_FOR(item, struct getdns_dict_item *,
|
||||||
(_getdns_rbtree_t *)&(dict->root)) {
|
(_getdns_rbtree_t *)&(dict->root)) {
|
||||||
_getdns_list_append_string(*answer, item->node.key);
|
_getdns_list_append_const_bindata(*answer,
|
||||||
|
strlen(item->node.key) + 1, item->node.key);
|
||||||
}
|
}
|
||||||
return GETDNS_RETURN_GOOD;
|
return GETDNS_RETURN_GOOD;
|
||||||
} /* getdns_dict_get_names */
|
} /* getdns_dict_get_names */
|
||||||
|
@ -578,7 +579,7 @@ getdns_dict_set_list(
|
||||||
/*---------------------------------------- getdns_dict_set_bindata */
|
/*---------------------------------------- getdns_dict_set_bindata */
|
||||||
getdns_return_t
|
getdns_return_t
|
||||||
_getdns_dict_set_const_bindata(
|
_getdns_dict_set_const_bindata(
|
||||||
getdns_dict *dict, const char *name, size_t size, const uint8_t *data)
|
getdns_dict *dict, const char *name, size_t size, const void *data)
|
||||||
{
|
{
|
||||||
getdns_item *item;
|
getdns_item *item;
|
||||||
getdns_bindata *newbindata;
|
getdns_bindata *newbindata;
|
||||||
|
@ -612,28 +613,9 @@ getdns_dict_set_bindata(
|
||||||
getdns_return_t
|
getdns_return_t
|
||||||
getdns_dict_util_set_string(getdns_dict *dict, char *name, const char *value)
|
getdns_dict_util_set_string(getdns_dict *dict, char *name, const char *value)
|
||||||
{
|
{
|
||||||
getdns_item *item;
|
return value
|
||||||
getdns_bindata *newbindata;
|
? _getdns_dict_set_const_bindata(dict, name, strlen(value), value)
|
||||||
getdns_return_t r;
|
: GETDNS_RETURN_INVALID_PARAMETER;
|
||||||
|
|
||||||
if (!dict || !name || !value)
|
|
||||||
return GETDNS_RETURN_INVALID_PARAMETER;
|
|
||||||
|
|
||||||
if (!(newbindata = GETDNS_MALLOC(dict->mf, getdns_bindata)))
|
|
||||||
return GETDNS_RETURN_MEMORY_ERROR;
|
|
||||||
|
|
||||||
newbindata->size = strlen(value);
|
|
||||||
if (!(newbindata->data = (void *)_getdns_strdup(&dict->mf, value))) {
|
|
||||||
GETDNS_FREE(dict->mf, newbindata);
|
|
||||||
return GETDNS_RETURN_MEMORY_ERROR;
|
|
||||||
}
|
|
||||||
if ((r = _getdns_dict_find_and_add(dict, name, &item))) {
|
|
||||||
_getdns_bindata_destroy(&dict->mf, newbindata);
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
item->dtype = t_bindata;
|
|
||||||
item->data.bindata = newbindata;
|
|
||||||
return GETDNS_RETURN_GOOD;
|
|
||||||
} /* getdns_dict_util_set_dict */
|
} /* getdns_dict_util_set_dict */
|
||||||
|
|
||||||
/*---------------------------------------- getdns_dict_set_int */
|
/*---------------------------------------- getdns_dict_set_int */
|
||||||
|
|
|
@ -3269,7 +3269,7 @@ void _getdns_get_validation_chain(getdns_dns_req *dnsreq)
|
||||||
, netreq->response, netreq->response_len
|
, netreq->response, netreq->response_len
|
||||||
, netreq->owner->name
|
, netreq->owner->name
|
||||||
, netreq->request_type
|
, netreq->request_type
|
||||||
, netreq->request_class
|
, netreq->owner->request_class
|
||||||
, netreq
|
, netreq
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
148
src/general.c
148
src/general.c
|
@ -44,6 +44,7 @@
|
||||||
#include "util-internal.h"
|
#include "util-internal.h"
|
||||||
#include "dnssec.h"
|
#include "dnssec.h"
|
||||||
#include "stub.h"
|
#include "stub.h"
|
||||||
|
#include "general.h"
|
||||||
|
|
||||||
/* cancel, cleanup and send timeout to callback */
|
/* cancel, cleanup and send timeout to callback */
|
||||||
static void
|
static void
|
||||||
|
@ -72,6 +73,83 @@ void _getdns_call_user_callback(getdns_dns_req *dns_req,
|
||||||
context->processing = 0;
|
context->processing = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
no_answer(getdns_dns_req *dns_req)
|
||||||
|
{
|
||||||
|
getdns_network_req **netreq_p, *netreq;
|
||||||
|
int new_canonical = 0;
|
||||||
|
uint8_t canon_spc[256];
|
||||||
|
const uint8_t *canon;
|
||||||
|
size_t canon_len;
|
||||||
|
uint8_t owner_spc[256];
|
||||||
|
const uint8_t *owner;
|
||||||
|
size_t owner_len;
|
||||||
|
|
||||||
|
_getdns_rr_iter rr_spc, *rr;
|
||||||
|
_getdns_rdf_iter rdf_spc, *rdf;
|
||||||
|
|
||||||
|
for (netreq_p = dns_req->netreqs; (netreq = *netreq_p); netreq_p++) {
|
||||||
|
if (netreq->response_len == 0 ||
|
||||||
|
GLDNS_ANCOUNT(netreq->response) == 0)
|
||||||
|
continue;
|
||||||
|
canon = netreq->owner->name;
|
||||||
|
canon_len = netreq->owner->name_len;
|
||||||
|
if (netreq->request_type != GETDNS_RRTYPE_CNAME
|
||||||
|
&& GLDNS_ANCOUNT(netreq->response) > 1) do {
|
||||||
|
new_canonical = 0;
|
||||||
|
for ( rr = _getdns_rr_iter_init(&rr_spc
|
||||||
|
, netreq->response
|
||||||
|
, netreq->response_len)
|
||||||
|
; rr && _getdns_rr_iter_section(rr)
|
||||||
|
<= GLDNS_SECTION_ANSWER
|
||||||
|
; rr = _getdns_rr_iter_next(rr)) {
|
||||||
|
|
||||||
|
if (_getdns_rr_iter_section(rr) !=
|
||||||
|
GLDNS_SECTION_ANSWER)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (gldns_read_uint16(rr->rr_type) !=
|
||||||
|
GETDNS_RRTYPE_CNAME)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
owner = _getdns_owner_if_or_as_decompressed(
|
||||||
|
rr, owner_spc, &owner_len);
|
||||||
|
if (!_getdns_dname_equal(canon, owner))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!(rdf = _getdns_rdf_iter_init(
|
||||||
|
&rdf_spc, rr)))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
canon = _getdns_rdf_if_or_as_decompressed(
|
||||||
|
rdf, canon_spc, &canon_len);
|
||||||
|
new_canonical = 1;
|
||||||
|
}
|
||||||
|
} while (new_canonical);
|
||||||
|
for ( rr = _getdns_rr_iter_init(&rr_spc
|
||||||
|
, netreq->response
|
||||||
|
, netreq->response_len)
|
||||||
|
; rr && _getdns_rr_iter_section(rr)
|
||||||
|
<= GLDNS_SECTION_ANSWER
|
||||||
|
; rr = _getdns_rr_iter_next(rr)) {
|
||||||
|
|
||||||
|
if (_getdns_rr_iter_section(rr) !=
|
||||||
|
GLDNS_SECTION_ANSWER)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (gldns_read_uint16(rr->rr_type) !=
|
||||||
|
netreq->request_type)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
owner = _getdns_owner_if_or_as_decompressed(
|
||||||
|
rr, owner_spc, &owner_len);
|
||||||
|
if (_getdns_dname_equal(canon, owner))
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
_getdns_check_dns_req_complete(getdns_dns_req *dns_req)
|
_getdns_check_dns_req_complete(getdns_dns_req *dns_req)
|
||||||
{
|
{
|
||||||
|
@ -85,6 +163,74 @@ _getdns_check_dns_req_complete(getdns_dns_req *dns_req)
|
||||||
else if (netreq->response_len > 0)
|
else if (netreq->response_len > 0)
|
||||||
results_found = 1;
|
results_found = 1;
|
||||||
|
|
||||||
|
/* Do we have to check more suffixes on nxdomain/nodata?
|
||||||
|
*/
|
||||||
|
if (dns_req->suffix_appended && /* Something was appended */
|
||||||
|
dns_req->suffix_len > 1 && /* Next suffix available */
|
||||||
|
no_answer(dns_req)) {
|
||||||
|
/* Remove suffix from name */
|
||||||
|
dns_req->name_len -= dns_req->suffix_len - 1;
|
||||||
|
dns_req->name[dns_req->name_len - 1] = 0;
|
||||||
|
do {
|
||||||
|
dns_req->suffix += dns_req->suffix_len;
|
||||||
|
dns_req->suffix_len = *dns_req->suffix++;
|
||||||
|
if (dns_req->suffix_len + dns_req->name_len - 1 <
|
||||||
|
sizeof(dns_req->name)) {
|
||||||
|
memcpy(dns_req->name + dns_req->name_len - 1,
|
||||||
|
dns_req->suffix, dns_req->suffix_len);
|
||||||
|
dns_req->name_len += dns_req->suffix_len - 1;
|
||||||
|
dns_req->suffix_appended = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} while (dns_req->suffix_len > 1 && *dns_req->suffix);
|
||||||
|
if (dns_req->append_name == GETDNS_APPEND_NAME_ALWAYS ||
|
||||||
|
(dns_req->suffix_len > 1 && *dns_req->suffix)) {
|
||||||
|
for ( netreq_p = dns_req->netreqs
|
||||||
|
; (netreq = *netreq_p)
|
||||||
|
; netreq_p++ ) {
|
||||||
|
_getdns_netreq_reinit(netreq);
|
||||||
|
if (_getdns_submit_netreq(netreq))
|
||||||
|
netreq->state = NET_REQ_FINISHED;
|
||||||
|
}
|
||||||
|
_getdns_check_dns_req_complete(dns_req);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else if (
|
||||||
|
( dns_req->append_name ==
|
||||||
|
GETDNS_APPEND_NAME_ONLY_TO_SINGLE_LABEL_AFTER_FAILURE ||
|
||||||
|
dns_req->append_name ==
|
||||||
|
GETDNS_APPEND_NAME_ONLY_TO_MULTIPLE_LABEL_NAME_AFTER_FAILURE
|
||||||
|
) &&
|
||||||
|
!dns_req->suffix_appended &&
|
||||||
|
dns_req->suffix_len > 1 &&
|
||||||
|
no_answer(dns_req)) {
|
||||||
|
/* Initial suffix append */
|
||||||
|
for (
|
||||||
|
; dns_req->suffix_len > 1 && *dns_req->suffix
|
||||||
|
; dns_req->suffix += dns_req->suffix_len
|
||||||
|
, dns_req->suffix_len = *dns_req->suffix++) {
|
||||||
|
|
||||||
|
if (dns_req->suffix_len + dns_req->name_len - 1 <
|
||||||
|
sizeof(dns_req->name)) {
|
||||||
|
memcpy(dns_req->name + dns_req->name_len - 1,
|
||||||
|
dns_req->suffix, dns_req->suffix_len);
|
||||||
|
dns_req->name_len += dns_req->suffix_len - 1;
|
||||||
|
dns_req->suffix_appended = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (dns_req->suffix_appended) {
|
||||||
|
for ( netreq_p = dns_req->netreqs
|
||||||
|
; (netreq = *netreq_p)
|
||||||
|
; netreq_p++ ) {
|
||||||
|
_getdns_netreq_reinit(netreq);
|
||||||
|
if (_getdns_submit_netreq(netreq))
|
||||||
|
netreq->state = NET_REQ_FINISHED;
|
||||||
|
}
|
||||||
|
_getdns_check_dns_req_complete(dns_req);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (dns_req->internal_cb)
|
if (dns_req->internal_cb)
|
||||||
dns_req->internal_cb(dns_req);
|
dns_req->internal_cb(dns_req);
|
||||||
else if (! results_found)
|
else if (! results_found)
|
||||||
|
@ -173,7 +319,7 @@ _getdns_submit_netreq(getdns_network_req *netreq)
|
||||||
|
|
||||||
#ifdef HAVE_LIBUNBOUND
|
#ifdef HAVE_LIBUNBOUND
|
||||||
return ub_resolve_async(dns_req->context->unbound_ctx,
|
return ub_resolve_async(dns_req->context->unbound_ctx,
|
||||||
name, netreq->request_type, netreq->request_class,
|
name, netreq->request_type, netreq->owner->request_class,
|
||||||
netreq, ub_resolve_callback, &(netreq->unbound_id)) ?
|
netreq, ub_resolve_callback, &(netreq->unbound_id)) ?
|
||||||
GETDNS_RETURN_GENERIC_ERROR : GETDNS_RETURN_GOOD;
|
GETDNS_RETURN_GENERIC_ERROR : GETDNS_RETURN_GOOD;
|
||||||
#else
|
#else
|
||||||
|
|
29
src/list.c
29
src/list.c
|
@ -554,7 +554,7 @@ getdns_list_set_list(
|
||||||
/*---------------------------------------- getdns_list_set_bindata */
|
/*---------------------------------------- getdns_list_set_bindata */
|
||||||
static getdns_return_t
|
static getdns_return_t
|
||||||
_getdns_list_set_const_bindata(
|
_getdns_list_set_const_bindata(
|
||||||
getdns_list *list, size_t index, size_t size, const uint8_t *data)
|
getdns_list *list, size_t index, size_t size, const void *data)
|
||||||
{
|
{
|
||||||
getdns_bindata *newbindata;
|
getdns_bindata *newbindata;
|
||||||
getdns_return_t r;
|
getdns_return_t r;
|
||||||
|
@ -587,28 +587,9 @@ getdns_list_set_bindata(
|
||||||
static getdns_return_t
|
static getdns_return_t
|
||||||
getdns_list_set_string(getdns_list *list, size_t index, const char *value)
|
getdns_list_set_string(getdns_list *list, size_t index, const char *value)
|
||||||
{
|
{
|
||||||
getdns_bindata *newbindata;
|
return value
|
||||||
getdns_return_t r;
|
? _getdns_list_set_const_bindata(list, index, strlen(value), value)
|
||||||
|
: GETDNS_RETURN_INVALID_PARAMETER;
|
||||||
if (!list || !value)
|
|
||||||
return GETDNS_RETURN_INVALID_PARAMETER;
|
|
||||||
|
|
||||||
if (!(newbindata = GETDNS_MALLOC(list->mf, getdns_bindata)))
|
|
||||||
return GETDNS_RETURN_MEMORY_ERROR;
|
|
||||||
|
|
||||||
newbindata->size = strlen(value);
|
|
||||||
if (!(newbindata->data = (void *)_getdns_strdup(&list->mf, value))) {
|
|
||||||
GETDNS_FREE(list->mf, newbindata);
|
|
||||||
return GETDNS_RETURN_MEMORY_ERROR;
|
|
||||||
}
|
|
||||||
if ((r = _getdns_list_request_index(list, index))) {
|
|
||||||
GETDNS_FREE(list->mf, newbindata->data);
|
|
||||||
GETDNS_FREE(list->mf, newbindata);
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
list->items[index].dtype = t_bindata;
|
|
||||||
list->items[index].data.bindata = newbindata;
|
|
||||||
return GETDNS_RETURN_GOOD;
|
|
||||||
} /* getdns_list_set_string */
|
} /* getdns_list_set_string */
|
||||||
|
|
||||||
/*---------------------------------------- getdns_list_set_int */
|
/*---------------------------------------- getdns_list_set_int */
|
||||||
|
@ -648,7 +629,7 @@ _getdns_list_append_bindata(getdns_list *list, const getdns_bindata *child_binda
|
||||||
}
|
}
|
||||||
getdns_return_t
|
getdns_return_t
|
||||||
_getdns_list_append_const_bindata(
|
_getdns_list_append_const_bindata(
|
||||||
getdns_list *list, size_t size, const uint8_t *data)
|
getdns_list *list, size_t size, const void *data)
|
||||||
{
|
{
|
||||||
if (!list) return GETDNS_RETURN_INVALID_PARAMETER;
|
if (!list) return GETDNS_RETURN_INVALID_PARAMETER;
|
||||||
return _getdns_list_set_const_bindata(list, list->numinuse, size, data);
|
return _getdns_list_set_const_bindata(list, list->numinuse, size, data);
|
||||||
|
|
|
@ -110,123 +110,134 @@ network_req_cleanup(getdns_network_req *net_req)
|
||||||
GETDNS_FREE(net_req->owner->my_mf, net_req->response);
|
GETDNS_FREE(net_req->owner->my_mf, net_req->response);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint8_t *
|
||||||
|
netreq_reset(getdns_network_req *net_req)
|
||||||
|
{
|
||||||
|
uint8_t *buf;
|
||||||
|
/* variables that need to be reset on reinit
|
||||||
|
*/
|
||||||
|
net_req->unbound_id = -1;
|
||||||
|
net_req->state = NET_REQ_NOT_SENT;
|
||||||
|
net_req->dnssec_status = GETDNS_DNSSEC_INDETERMINATE;
|
||||||
|
net_req->tsig_status = GETDNS_DNSSEC_INDETERMINATE;
|
||||||
|
net_req->query_id = 0;
|
||||||
|
net_req->response_len = 0;
|
||||||
|
/* Some fields to record info for return_call_reporting */
|
||||||
|
net_req->debug_start_time = 0;
|
||||||
|
net_req->debug_end_time = 0;
|
||||||
|
if (!net_req->query)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
buf = net_req->query + GLDNS_HEADER_SIZE;
|
||||||
|
(void) memcpy(buf, net_req->owner->name, net_req->owner->name_len);
|
||||||
|
buf += net_req->owner->name_len;
|
||||||
|
|
||||||
|
gldns_write_uint16(buf, net_req->request_type);
|
||||||
|
gldns_write_uint16(buf + 2, net_req->owner->request_class);
|
||||||
|
return buf + 4;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
network_req_init(getdns_network_req *net_req, getdns_dns_req *owner,
|
network_req_init(getdns_network_req *net_req, getdns_dns_req *owner,
|
||||||
const char *name, uint16_t request_type, uint16_t request_class,
|
uint16_t request_type, int dnssec_extension_set, int with_opt,
|
||||||
int dnssec_extension_set, int with_opt,
|
|
||||||
int edns_maximum_udp_payload_size,
|
int edns_maximum_udp_payload_size,
|
||||||
uint8_t edns_extended_rcode, uint8_t edns_version, int edns_do_bit,
|
uint8_t edns_extended_rcode, uint8_t edns_version, int edns_do_bit,
|
||||||
uint16_t opt_options_size, size_t noptions, getdns_list *options,
|
uint16_t opt_options_size, size_t noptions, getdns_list *options,
|
||||||
size_t wire_data_sz, size_t max_query_sz)
|
size_t wire_data_sz, size_t max_query_sz)
|
||||||
{
|
{
|
||||||
uint8_t *buf;
|
uint8_t *buf;
|
||||||
size_t dname_len;
|
|
||||||
getdns_dict *option;
|
getdns_dict *option;
|
||||||
uint32_t option_code;
|
uint32_t option_code;
|
||||||
getdns_bindata *option_data;
|
getdns_bindata *option_data;
|
||||||
size_t i;
|
size_t i;
|
||||||
int r = 0;
|
int r = 0;
|
||||||
|
|
||||||
|
/* variables that stay the same on reinit, don't touch
|
||||||
|
*/
|
||||||
net_req->request_type = request_type;
|
net_req->request_type = request_type;
|
||||||
net_req->request_class = request_class;
|
|
||||||
net_req->unbound_id = -1;
|
|
||||||
net_req->state = NET_REQ_NOT_SENT;
|
|
||||||
net_req->owner = owner;
|
net_req->owner = owner;
|
||||||
|
|
||||||
net_req->dnssec_status = GETDNS_DNSSEC_INDETERMINATE;
|
|
||||||
net_req->tsig_status = GETDNS_DNSSEC_INDETERMINATE;
|
|
||||||
|
|
||||||
net_req->upstream = NULL;
|
|
||||||
net_req->fd = -1;
|
|
||||||
net_req->transport_count = owner->context->dns_transport_count;
|
|
||||||
net_req->transport_current = 0;
|
|
||||||
memcpy(net_req->transports, owner->context->dns_transports,
|
|
||||||
net_req->transport_count * sizeof(getdns_transport_list_t));
|
|
||||||
net_req->tls_auth_min = owner->context->tls_auth_min;
|
|
||||||
memset(&net_req->event, 0, sizeof(net_req->event));
|
|
||||||
memset(&net_req->tcp, 0, sizeof(net_req->tcp));
|
|
||||||
net_req->query_id = 0;
|
|
||||||
net_req->edns_maximum_udp_payload_size = edns_maximum_udp_payload_size;
|
net_req->edns_maximum_udp_payload_size = edns_maximum_udp_payload_size;
|
||||||
net_req->max_udp_payload_size = edns_maximum_udp_payload_size != -1
|
net_req->max_udp_payload_size = edns_maximum_udp_payload_size != -1
|
||||||
? edns_maximum_udp_payload_size : 1432;
|
? edns_maximum_udp_payload_size : 1432;
|
||||||
|
net_req->base_query_option_sz = opt_options_size;
|
||||||
|
net_req->wire_data_sz = wire_data_sz;
|
||||||
|
|
||||||
|
net_req->transport_count = owner->context->dns_transport_count;
|
||||||
|
memcpy(net_req->transports, owner->context->dns_transports,
|
||||||
|
net_req->transport_count * sizeof(getdns_transport_list_t));
|
||||||
|
net_req->tls_auth_min = owner->context->tls_auth_min;
|
||||||
|
|
||||||
|
/* state variables from the resolver, don't touch
|
||||||
|
*/
|
||||||
|
net_req->upstream = NULL;
|
||||||
|
net_req->fd = -1;
|
||||||
|
net_req->transport_current = 0;
|
||||||
|
memset(&net_req->event, 0, sizeof(net_req->event));
|
||||||
|
memset(&net_req->tcp, 0, sizeof(net_req->tcp));
|
||||||
net_req->keepalive_sent = 0;
|
net_req->keepalive_sent = 0;
|
||||||
net_req->write_queue_tail = NULL;
|
net_req->write_queue_tail = NULL;
|
||||||
net_req->response_len = 0;
|
|
||||||
net_req->base_query_option_sz = opt_options_size;
|
|
||||||
|
|
||||||
/* Some fields to record info for return_call_reporting */
|
/* Some fields to record info for return_call_reporting */
|
||||||
net_req->debug_start_time = 0;
|
|
||||||
net_req->debug_end_time = 0;
|
|
||||||
net_req->debug_tls_auth_status = 0;
|
net_req->debug_tls_auth_status = 0;
|
||||||
net_req->debug_udp = 0;
|
net_req->debug_udp = 0;
|
||||||
|
|
||||||
net_req->wire_data_sz = wire_data_sz;
|
if (max_query_sz == 0) {
|
||||||
if (max_query_sz) {
|
|
||||||
/* first two bytes will contain query length (for tcp) */
|
|
||||||
buf = net_req->query = net_req->wire_data + 2;
|
|
||||||
|
|
||||||
gldns_write_uint16(buf + 2, 0); /* reset all flags */
|
|
||||||
GLDNS_RD_SET(buf);
|
|
||||||
if (dnssec_extension_set) /* We will do validation ourselves */
|
|
||||||
GLDNS_CD_SET(buf);
|
|
||||||
GLDNS_OPCODE_SET(buf, GLDNS_PACKET_QUERY);
|
|
||||||
gldns_write_uint16(buf + GLDNS_QDCOUNT_OFF, 1); /* 1 query */
|
|
||||||
gldns_write_uint16(buf + GLDNS_ANCOUNT_OFF, 0); /* 0 answers */
|
|
||||||
gldns_write_uint16(buf + GLDNS_NSCOUNT_OFF, 0); /* 0 authorities */
|
|
||||||
gldns_write_uint16(buf + GLDNS_ARCOUNT_OFF, with_opt ? 1 : 0);
|
|
||||||
|
|
||||||
buf += GLDNS_HEADER_SIZE;
|
|
||||||
dname_len = max_query_sz - GLDNS_HEADER_SIZE;
|
|
||||||
if ((r = gldns_str2wire_dname_buf(name, buf, &dname_len))) {
|
|
||||||
net_req->opt = NULL;
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
buf += dname_len;
|
|
||||||
|
|
||||||
gldns_write_uint16(buf, request_type);
|
|
||||||
gldns_write_uint16(buf + 2, request_class);
|
|
||||||
buf += 4;
|
|
||||||
|
|
||||||
if (with_opt) {
|
|
||||||
net_req->opt = buf;
|
|
||||||
buf[0] = 0; /* dname for . */
|
|
||||||
gldns_write_uint16(buf + 1, GLDNS_RR_TYPE_OPT);
|
|
||||||
gldns_write_uint16(net_req->opt + 3,
|
|
||||||
net_req->max_udp_payload_size);
|
|
||||||
buf[5] = edns_extended_rcode;
|
|
||||||
buf[6] = edns_version;
|
|
||||||
buf[7] = edns_do_bit ? 0x80 : 0;
|
|
||||||
buf[8] = 0;
|
|
||||||
gldns_write_uint16(buf + 9, opt_options_size);
|
|
||||||
buf += 11;
|
|
||||||
for (i = 0; i < noptions; i++) {
|
|
||||||
if (getdns_list_get_dict(options, i, &option))
|
|
||||||
continue;
|
|
||||||
if (getdns_dict_get_int(
|
|
||||||
option, "option_code", &option_code))
|
|
||||||
continue;
|
|
||||||
if (getdns_dict_get_bindata(
|
|
||||||
option, "option_data", &option_data))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
gldns_write_uint16(buf, (uint16_t) option_code);
|
|
||||||
gldns_write_uint16(buf + 2,
|
|
||||||
(uint16_t) option_data->size);
|
|
||||||
(void) memcpy(buf + 4, option_data->data,
|
|
||||||
option_data->size);
|
|
||||||
|
|
||||||
buf += option_data->size + 4;
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
net_req->opt = NULL;
|
|
||||||
net_req->response = buf;
|
|
||||||
gldns_write_uint16(net_req->wire_data, net_req->response - net_req->query);
|
|
||||||
} else {
|
|
||||||
net_req->query = NULL;
|
net_req->query = NULL;
|
||||||
net_req->opt = NULL;
|
net_req->opt = NULL;
|
||||||
net_req->response = net_req->wire_data;
|
net_req->response = net_req->wire_data;
|
||||||
|
netreq_reset(net_req);
|
||||||
|
return r;
|
||||||
}
|
}
|
||||||
|
/* first two bytes will contain query length (for tcp) */
|
||||||
|
net_req->query = net_req->wire_data + 2;
|
||||||
|
|
||||||
|
buf = net_req->query;
|
||||||
|
gldns_write_uint16(buf + 2, 0); /* reset all flags */
|
||||||
|
GLDNS_RD_SET(buf);
|
||||||
|
if (dnssec_extension_set) /* We will do validation ourselves */
|
||||||
|
GLDNS_CD_SET(buf);
|
||||||
|
GLDNS_OPCODE_SET(buf, GLDNS_PACKET_QUERY);
|
||||||
|
gldns_write_uint16(buf + GLDNS_QDCOUNT_OFF, 1); /* 1 query */
|
||||||
|
gldns_write_uint16(buf + GLDNS_ANCOUNT_OFF, 0); /* 0 answers */
|
||||||
|
gldns_write_uint16(buf + GLDNS_NSCOUNT_OFF, 0); /* 0 authorities */
|
||||||
|
gldns_write_uint16(buf + GLDNS_ARCOUNT_OFF, with_opt ? 1 : 0);
|
||||||
|
|
||||||
|
buf = netreq_reset(net_req);
|
||||||
|
if (with_opt) {
|
||||||
|
net_req->opt = buf;
|
||||||
|
buf[0] = 0; /* dname for . */
|
||||||
|
gldns_write_uint16(buf + 1, GLDNS_RR_TYPE_OPT);
|
||||||
|
gldns_write_uint16(net_req->opt + 3,
|
||||||
|
net_req->max_udp_payload_size);
|
||||||
|
buf[5] = edns_extended_rcode;
|
||||||
|
buf[6] = edns_version;
|
||||||
|
buf[7] = edns_do_bit ? 0x80 : 0;
|
||||||
|
buf[8] = 0;
|
||||||
|
gldns_write_uint16(buf + 9, opt_options_size);
|
||||||
|
buf += 11;
|
||||||
|
for (i = 0; i < noptions; i++) {
|
||||||
|
if (getdns_list_get_dict(options, i, &option))
|
||||||
|
continue;
|
||||||
|
if (getdns_dict_get_int(
|
||||||
|
option, "option_code", &option_code))
|
||||||
|
continue;
|
||||||
|
if (getdns_dict_get_bindata(
|
||||||
|
option, "option_data", &option_data))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
gldns_write_uint16(buf, (uint16_t) option_code);
|
||||||
|
gldns_write_uint16(buf + 2,
|
||||||
|
(uint16_t) option_data->size);
|
||||||
|
(void) memcpy(buf + 4, option_data->data,
|
||||||
|
option_data->size);
|
||||||
|
|
||||||
|
buf += option_data->size + 4;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
net_req->opt = NULL;
|
||||||
|
|
||||||
|
net_req->response = buf;
|
||||||
|
gldns_write_uint16(net_req->wire_data, net_req->response - net_req->query);
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -248,6 +259,39 @@ _getdns_network_req_clear_upstream_options(getdns_network_req * req)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_getdns_netreq_reinit(getdns_network_req *netreq)
|
||||||
|
{
|
||||||
|
uint8_t *base_opt_backup;
|
||||||
|
size_t base_opt_rr_sz;
|
||||||
|
|
||||||
|
if (!netreq->query) {
|
||||||
|
(void) netreq_reset(netreq);
|
||||||
|
return;
|
||||||
|
|
||||||
|
} else if (!netreq->opt) {
|
||||||
|
/* Remove TSIG (if any) */
|
||||||
|
gldns_write_uint16(netreq->query + GLDNS_ARCOUNT_OFF, 0);
|
||||||
|
netreq->response = netreq_reset(netreq);
|
||||||
|
gldns_write_uint16(netreq->wire_data,
|
||||||
|
netreq->response - netreq->query);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_getdns_network_req_clear_upstream_options(netreq);
|
||||||
|
base_opt_rr_sz = netreq->base_query_option_sz + 11;
|
||||||
|
base_opt_backup = netreq->wire_data + netreq->wire_data_sz
|
||||||
|
- base_opt_rr_sz;
|
||||||
|
(void) memcpy(base_opt_backup, netreq->opt, base_opt_rr_sz);
|
||||||
|
netreq->opt = netreq_reset(netreq);
|
||||||
|
(void) memcpy(netreq->opt, base_opt_backup, base_opt_rr_sz);
|
||||||
|
netreq->response = netreq->opt + base_opt_rr_sz;
|
||||||
|
/* Remove TSIG (if any), but leave the opt RR */
|
||||||
|
gldns_write_uint16(netreq->query + GLDNS_ARCOUNT_OFF, 1);
|
||||||
|
gldns_write_uint16(netreq->wire_data,
|
||||||
|
netreq->response - netreq->query);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* add_upstream_option appends an option that is derived at send time.
|
/* add_upstream_option appends an option that is derived at send time.
|
||||||
(you can send data as NULL and it will fill with all zeros) */
|
(you can send data as NULL and it will fill with all zeros) */
|
||||||
getdns_return_t
|
getdns_return_t
|
||||||
|
@ -583,6 +627,8 @@ _getdns_dns_req_free(getdns_dns_req * req)
|
||||||
GETDNS_FREE(req->my_mf, req);
|
GETDNS_FREE(req->my_mf, req);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const uint8_t no_suffixes[] = { 1, 0 };
|
||||||
|
|
||||||
/* create a new dns req to be submitted */
|
/* create a new dns req to be submitted */
|
||||||
getdns_dns_req *
|
getdns_dns_req *
|
||||||
_getdns_dns_req_new(getdns_context *context, getdns_eventloop *loop,
|
_getdns_dns_req_new(getdns_context *context, getdns_eventloop *loop,
|
||||||
|
@ -647,7 +693,7 @@ _getdns_dns_req_new(getdns_context *context, getdns_eventloop *loop,
|
||||||
* And align on the 8 byte boundry (hence the (x + 7) / 8 * 8)
|
* And align on the 8 byte boundry (hence the (x + 7) / 8 * 8)
|
||||||
*/
|
*/
|
||||||
size_t max_query_sz, max_response_sz, netreq_sz, dnsreq_base_sz;
|
size_t max_query_sz, max_response_sz, netreq_sz, dnsreq_base_sz;
|
||||||
uint8_t *region;
|
uint8_t *region, *suffixes;
|
||||||
|
|
||||||
if (extensions == dnssec_ok_checking_disabled ||
|
if (extensions == dnssec_ok_checking_disabled ||
|
||||||
extensions == dnssec_ok_checking_disabled_roadblock_avoidance ||
|
extensions == dnssec_ok_checking_disabled_roadblock_avoidance ||
|
||||||
|
@ -719,7 +765,7 @@ _getdns_dns_req_new(getdns_context *context, getdns_eventloop *loop,
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
max_query_sz = ( GLDNS_HEADER_SIZE
|
max_query_sz = ( GLDNS_HEADER_SIZE
|
||||||
+ strlen(name) + 1 + 4 /* dname always smaller then strlen(name) + 1 */
|
+ 256 + 4 /* dname maximum 255 bytes (256 with mdns)*/
|
||||||
+ 12 + opt_options_size /* space needed for OPT (if needed) */
|
+ 12 + opt_options_size /* space needed for OPT (if needed) */
|
||||||
+ MAXIMUM_UPSTREAM_OPTION_SPACE
|
+ MAXIMUM_UPSTREAM_OPTION_SPACE
|
||||||
+ MAXIMUM_TSIG_SPACE
|
+ MAXIMUM_TSIG_SPACE
|
||||||
|
@ -734,6 +780,7 @@ _getdns_dns_req_new(getdns_context *context, getdns_eventloop *loop,
|
||||||
+ max_query_sz + max_response_sz + 7 ) / 8 * 8;
|
+ max_query_sz + max_response_sz + 7 ) / 8 * 8;
|
||||||
dnsreq_base_sz = (( sizeof(getdns_dns_req)
|
dnsreq_base_sz = (( sizeof(getdns_dns_req)
|
||||||
+ (a_aaaa_query ? 3 : 2) * sizeof(getdns_network_req*)
|
+ (a_aaaa_query ? 3 : 2) * sizeof(getdns_network_req*)
|
||||||
|
+ context->suffixes_len
|
||||||
) + 7) / 8 * 8;
|
) + 7) / 8 * 8;
|
||||||
|
|
||||||
if (! (region = GETDNS_XMALLOC(context->mf, uint8_t,
|
if (! (region = GETDNS_XMALLOC(context->mf, uint8_t,
|
||||||
|
@ -750,12 +797,52 @@ _getdns_dns_req_new(getdns_context *context, getdns_eventloop *loop,
|
||||||
result->netreqs[1] = NULL;
|
result->netreqs[1] = NULL;
|
||||||
|
|
||||||
result->my_mf = context->mf;
|
result->my_mf = context->mf;
|
||||||
|
|
||||||
|
suffixes = region + dnsreq_base_sz - context->suffixes_len;
|
||||||
|
assert(context->suffixes);
|
||||||
|
assert(context->suffixes_len);
|
||||||
|
memcpy(suffixes, context->suffixes, context->suffixes_len);
|
||||||
|
|
||||||
|
result->append_name = context->append_name;
|
||||||
|
if (!strlen(name) || name[strlen(name)-1] == '.' ||
|
||||||
|
result->append_name == GETDNS_APPEND_NAME_NEVER) {
|
||||||
|
/* Absolute query string, no appending */
|
||||||
|
result->suffix_len = no_suffixes[0];
|
||||||
|
result->suffix = no_suffixes + 1;
|
||||||
|
result->suffix_appended = 1;
|
||||||
|
} else {
|
||||||
|
result->suffix_len = suffixes[0];
|
||||||
|
result->suffix = suffixes + 1;
|
||||||
|
result->suffix_appended = 0;
|
||||||
|
}
|
||||||
result->name_len = sizeof(result->name);
|
result->name_len = sizeof(result->name);
|
||||||
if (gldns_str2wire_dname_buf(name, result->name, &result->name_len)) {
|
if (gldns_str2wire_dname_buf(name, result->name, &result->name_len)) {
|
||||||
GETDNS_FREE(result->my_mf, result);
|
GETDNS_FREE(result->my_mf, result);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
if (result->append_name == GETDNS_APPEND_NAME_ALWAYS) {
|
||||||
|
for (
|
||||||
|
; result->suffix_len > 1 && *result->suffix
|
||||||
|
; result->suffix += result->suffix_len
|
||||||
|
, result->suffix_len = *result->suffix++) {
|
||||||
|
|
||||||
|
if (result->suffix_len + result->name_len - 1 <
|
||||||
|
sizeof(result->name)) {
|
||||||
|
memcpy(result->name + result->name_len - 1,
|
||||||
|
result->suffix, result->suffix_len);
|
||||||
|
result->name_len += result->suffix_len - 1;
|
||||||
|
result->suffix_appended = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (result->append_name ==
|
||||||
|
GETDNS_APPEND_NAME_ONLY_TO_SINGLE_LABEL_AFTER_FAILURE &&
|
||||||
|
result->name[result->name[0]+1] != 0) {
|
||||||
|
/* We have multiple labels, no appending */
|
||||||
|
result->suffix_len = no_suffixes[0];
|
||||||
|
result->suffix = no_suffixes + 1;
|
||||||
|
result->suffix_appended = 1;
|
||||||
|
}
|
||||||
result->context = context;
|
result->context = context;
|
||||||
result->loop = loop;
|
result->loop = loop;
|
||||||
result->canceled = 0;
|
result->canceled = 0;
|
||||||
|
@ -783,23 +870,23 @@ _getdns_dns_req_new(getdns_context *context, getdns_eventloop *loop,
|
||||||
|
|
||||||
/* check the specify_class extension */
|
/* check the specify_class extension */
|
||||||
(void) getdns_dict_get_int(extensions, "specify_class", &klass);
|
(void) getdns_dict_get_int(extensions, "specify_class", &klass);
|
||||||
|
result->request_class = klass;
|
||||||
|
|
||||||
result->upstreams = context->upstreams;
|
result->upstreams = context->upstreams;
|
||||||
if (result->upstreams)
|
if (result->upstreams)
|
||||||
result->upstreams->referenced++;
|
result->upstreams->referenced++;
|
||||||
|
|
||||||
network_req_init(result->netreqs[0], result,
|
network_req_init(result->netreqs[0], result,
|
||||||
name, request_type, klass,
|
request_type, dnssec_extension_set, with_opt,
|
||||||
dnssec_extension_set, with_opt,
|
|
||||||
edns_maximum_udp_payload_size,
|
edns_maximum_udp_payload_size,
|
||||||
edns_extended_rcode, edns_version, edns_do_bit,
|
edns_extended_rcode, edns_version, edns_do_bit,
|
||||||
opt_options_size, noptions, options,
|
opt_options_size, noptions, options,
|
||||||
netreq_sz - sizeof(getdns_network_req), max_query_sz);
|
netreq_sz - sizeof(getdns_network_req), max_query_sz);
|
||||||
|
|
||||||
if (a_aaaa_query)
|
if (a_aaaa_query)
|
||||||
network_req_init(result->netreqs[1], result, name,
|
network_req_init(result->netreqs[1], result,
|
||||||
( request_type == GETDNS_RRTYPE_A
|
( request_type == GETDNS_RRTYPE_A
|
||||||
? GETDNS_RRTYPE_AAAA : GETDNS_RRTYPE_A ), klass,
|
? GETDNS_RRTYPE_AAAA : GETDNS_RRTYPE_A ),
|
||||||
dnssec_extension_set, with_opt,
|
dnssec_extension_set, with_opt,
|
||||||
edns_maximum_udp_payload_size,
|
edns_maximum_udp_payload_size,
|
||||||
edns_extended_rcode, edns_version, edns_do_bit,
|
edns_extended_rcode, edns_version, edns_do_bit,
|
||||||
|
|
|
@ -490,6 +490,13 @@ print_usage(FILE *out, const char *progname)
|
||||||
fprintf(out, "\t-s\tSet stub resolution type (default = recursing)\n");
|
fprintf(out, "\t-s\tSet stub resolution type (default = recursing)\n");
|
||||||
fprintf(out, "\t-S\tservice lookup (<type> is ignored)\n");
|
fprintf(out, "\t-S\tservice lookup (<type> is ignored)\n");
|
||||||
fprintf(out, "\t-t <timeout>\tSet timeout in miliseconds\n");
|
fprintf(out, "\t-t <timeout>\tSet timeout in miliseconds\n");
|
||||||
|
|
||||||
|
fprintf(out, "\t-W\tAppend suffix always (default)\n");
|
||||||
|
fprintf(out, "\t-1\tAppend suffix only to single label after failure\n");
|
||||||
|
fprintf(out, "\t-M\tAppend suffix only to multi label name after failure\n");
|
||||||
|
fprintf(out, "\t-N\tNever append a suffix\n");
|
||||||
|
fprintf(out, "\t-Z <suffixes>\tSet suffixes with the given comma separed list\n");
|
||||||
|
|
||||||
fprintf(out, "\t-T\tSet transport to TCP only\n");
|
fprintf(out, "\t-T\tSet transport to TCP only\n");
|
||||||
fprintf(out, "\t-O\tSet transport to TCP only keep connections open\n");
|
fprintf(out, "\t-O\tSet transport to TCP only keep connections open\n");
|
||||||
fprintf(out, "\t-L\tSet transport to TLS only keep connections open\n");
|
fprintf(out, "\t-L\tSet transport to TLS only keep connections open\n");
|
||||||
|
@ -680,12 +687,15 @@ done:
|
||||||
getdns_return_t parse_args(int argc, char **argv)
|
getdns_return_t parse_args(int argc, char **argv)
|
||||||
{
|
{
|
||||||
getdns_return_t r = GETDNS_RETURN_GOOD;
|
getdns_return_t r = GETDNS_RETURN_GOOD;
|
||||||
size_t i;
|
size_t i, j;
|
||||||
char *arg, *c, *endptr;
|
char *arg, *c, *endptr;
|
||||||
int t, print_api_info = 0, print_trust_anchors = 0;
|
int t, print_api_info = 0, print_trust_anchors = 0;
|
||||||
getdns_list *upstream_list = NULL;
|
getdns_list *upstream_list = NULL;
|
||||||
getdns_list *tas = NULL, *hints = NULL;
|
getdns_list *tas = NULL, *hints = NULL;
|
||||||
getdns_dict *pubkey_pin = NULL;
|
getdns_dict *pubkey_pin = NULL;
|
||||||
|
getdns_list *suffixes;
|
||||||
|
char *suffix;
|
||||||
|
getdns_bindata bindata;
|
||||||
size_t upstream_count = 0;
|
size_t upstream_count = 0;
|
||||||
FILE *fh;
|
FILE *fh;
|
||||||
|
|
||||||
|
@ -958,6 +968,43 @@ getdns_return_t parse_args(int argc, char **argv)
|
||||||
getdns_context_set_idle_timeout(
|
getdns_context_set_idle_timeout(
|
||||||
context, timeout);
|
context, timeout);
|
||||||
goto next;
|
goto next;
|
||||||
|
case 'W':
|
||||||
|
(void) getdns_context_set_append_name(context,
|
||||||
|
GETDNS_APPEND_NAME_ALWAYS);
|
||||||
|
break;
|
||||||
|
case '1':
|
||||||
|
(void) getdns_context_set_append_name(context,
|
||||||
|
GETDNS_APPEND_NAME_ONLY_TO_SINGLE_LABEL_AFTER_FAILURE);
|
||||||
|
break;
|
||||||
|
case 'M':
|
||||||
|
(void) getdns_context_set_append_name(context,
|
||||||
|
GETDNS_APPEND_NAME_ONLY_TO_MULTIPLE_LABEL_NAME_AFTER_FAILURE);
|
||||||
|
break;
|
||||||
|
case 'N':
|
||||||
|
(void) getdns_context_set_append_name(context,
|
||||||
|
GETDNS_APPEND_NAME_NEVER);
|
||||||
|
break;
|
||||||
|
case 'Z':
|
||||||
|
if (c[1] != 0 || ++i >= argc || !*argv[i]) {
|
||||||
|
fprintf(stderr, "suffixes expected"
|
||||||
|
"after -Z\n");
|
||||||
|
return GETDNS_RETURN_GENERIC_ERROR;
|
||||||
|
}
|
||||||
|
if (!(suffixes = getdns_list_create()))
|
||||||
|
return GETDNS_RETURN_MEMORY_ERROR;
|
||||||
|
suffix = strtok(argv[i], ",");
|
||||||
|
j = 0;
|
||||||
|
while (suffix) {
|
||||||
|
bindata.size = strlen(suffix);
|
||||||
|
bindata.data = (void *)suffix;
|
||||||
|
(void) getdns_list_set_bindata(
|
||||||
|
suffixes, j++, &bindata);
|
||||||
|
suffix = strtok(NULL, ",");
|
||||||
|
}
|
||||||
|
(void) getdns_context_set_suffix(context,
|
||||||
|
suffixes);
|
||||||
|
getdns_list_destroy(suffixes);
|
||||||
|
goto next;
|
||||||
case 'T':
|
case 'T':
|
||||||
getdns_context_set_dns_transport(context,
|
getdns_context_set_dns_transport(context,
|
||||||
GETDNS_TRANSPORT_TCP_ONLY);
|
GETDNS_TRANSPORT_TCP_ONLY);
|
||||||
|
@ -999,7 +1046,7 @@ getdns_return_t parse_args(int argc, char **argv)
|
||||||
break;
|
break;
|
||||||
case 'B':
|
case 'B':
|
||||||
batch_mode = 1;
|
batch_mode = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -203,9 +203,6 @@ typedef struct getdns_network_req
|
||||||
/* request type */
|
/* request type */
|
||||||
uint16_t request_type;
|
uint16_t request_type;
|
||||||
|
|
||||||
/* request class */
|
|
||||||
uint16_t request_class;
|
|
||||||
|
|
||||||
/* dnssec status */
|
/* dnssec status */
|
||||||
int dnssec_status;
|
int dnssec_status;
|
||||||
|
|
||||||
|
@ -282,6 +279,13 @@ typedef struct getdns_dns_req {
|
||||||
uint8_t name[256];
|
uint8_t name[256];
|
||||||
size_t name_len;
|
size_t name_len;
|
||||||
|
|
||||||
|
getdns_append_name_t append_name;
|
||||||
|
const uint8_t *suffix;
|
||||||
|
size_t suffix_len;
|
||||||
|
int suffix_appended;
|
||||||
|
|
||||||
|
uint16_t request_class;
|
||||||
|
|
||||||
/* canceled flag */
|
/* canceled flag */
|
||||||
int canceled;
|
int canceled;
|
||||||
|
|
||||||
|
@ -395,5 +399,7 @@ size_t _getdns_network_req_add_tsig(getdns_network_req *req);
|
||||||
|
|
||||||
void _getdns_network_validate_tsig(getdns_network_req *req);
|
void _getdns_network_validate_tsig(getdns_network_req *req);
|
||||||
|
|
||||||
|
void _getdns_netreq_reinit(getdns_network_req *netreq);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
/* types-internal.h */
|
/* types-internal.h */
|
||||||
|
|
|
@ -1130,7 +1130,7 @@ getdns_apply_network_result(getdns_network_req* netreq,
|
||||||
, netreq->request_type);
|
, netreq->request_type);
|
||||||
gldns_write_uint16( netreq->response + GLDNS_HEADER_SIZE
|
gldns_write_uint16( netreq->response + GLDNS_HEADER_SIZE
|
||||||
+ netreq->owner->name_len + 2
|
+ netreq->owner->name_len + 2
|
||||||
, netreq->request_class);
|
, netreq->owner->request_class);
|
||||||
|
|
||||||
netreq->response_len = GLDNS_HEADER_SIZE + netreq->owner->name_len + 4;
|
netreq->response_len = GLDNS_HEADER_SIZE + netreq->owner->name_len + 4;
|
||||||
|
|
||||||
|
|
|
@ -83,10 +83,10 @@ getdns_return_t _getdns_list_append_int(getdns_list *list,
|
||||||
uint32_t child_uint32);
|
uint32_t child_uint32);
|
||||||
|
|
||||||
getdns_return_t _getdns_list_append_const_bindata(getdns_list *list,
|
getdns_return_t _getdns_list_append_const_bindata(getdns_list *list,
|
||||||
size_t size, const uint8_t *data);
|
size_t size, const void *data);
|
||||||
|
|
||||||
getdns_return_t _getdns_dict_set_const_bindata(getdns_dict *dict,
|
getdns_return_t _getdns_dict_set_const_bindata(getdns_dict *dict,
|
||||||
const char *name, size_t size, const uint8_t *data);
|
const char *name, size_t size, const void *data);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* private function (API users should not be calling this), this uses library
|
* private function (API users should not be calling this), this uses library
|
||||||
|
|
Loading…
Reference in New Issue