mirror of https://github.com/getdnsapi/getdns.git
Merge branch 'develop' into features/dnssec_roadblock_avoidance
This commit is contained in:
commit
8a6f7d5b90
|
@ -415,6 +415,9 @@ esac
|
||||||
AC_DEFINE_UNQUOTED([EDNS_COOKIE_OPCODE], [10], [The edns cookie option code.])
|
AC_DEFINE_UNQUOTED([EDNS_COOKIE_OPCODE], [10], [The edns cookie option code.])
|
||||||
AC_DEFINE_UNQUOTED([EDNS_COOKIE_ROLLOVER_TIME], [(24 * 60 * 60)], [How often the edns client cookie is refreshed.])
|
AC_DEFINE_UNQUOTED([EDNS_COOKIE_ROLLOVER_TIME], [(24 * 60 * 60)], [How often the edns client cookie is refreshed.])
|
||||||
|
|
||||||
|
AC_DEFINE_UNQUOTED([MAXIMUM_UPSTREAM_OPTION_SPACE], [3000], [limit for dynamically-generated DNS options])
|
||||||
|
AC_DEFINE_UNQUOTED([EDNS_PADDING_OPCODE], [65461], [The experimental edns padding option code.])
|
||||||
|
|
||||||
my_with_libunbound=1
|
my_with_libunbound=1
|
||||||
AC_ARG_ENABLE(stub-only, AC_HELP_STRING([--enable-stub-only], [Restricts resolution modes to STUB (which will be the default mode). Removes the libunbound dependency.]))
|
AC_ARG_ENABLE(stub-only, AC_HELP_STRING([--enable-stub-only], [Restricts resolution modes to STUB (which will be the default mode). Removes the libunbound dependency.]))
|
||||||
case "$enable_stub_only" in
|
case "$enable_stub_only" in
|
||||||
|
|
|
@ -117,7 +117,7 @@ install: libgetdns.la
|
||||||
$(INSTALL) -m 755 -d $(DESTDIR)$(includedir)
|
$(INSTALL) -m 755 -d $(DESTDIR)$(includedir)
|
||||||
$(INSTALL) -m 755 -d $(DESTDIR)$(includedir)/getdns
|
$(INSTALL) -m 755 -d $(DESTDIR)$(includedir)/getdns
|
||||||
$(INSTALL) -m 644 getdns/getdns.h $(DESTDIR)$(includedir)/getdns/getdns.h
|
$(INSTALL) -m 644 getdns/getdns.h $(DESTDIR)$(includedir)/getdns/getdns.h
|
||||||
$(INSTALL) -m 644 $(srcdir)/getdns/getdns_extra.h $(DESTDIR)$(includedir)/getdns/getdns_extra.h
|
$(INSTALL) -m 644 getdns/getdns_extra.h $(DESTDIR)$(includedir)/getdns/getdns_extra.h
|
||||||
$(INSTALL) -m 755 -d $(DESTDIR)$(libdir)
|
$(INSTALL) -m 755 -d $(DESTDIR)$(libdir)
|
||||||
$(LIBTOOL) --mode=install cp libgetdns.la $(DESTDIR)$(libdir)
|
$(LIBTOOL) --mode=install cp libgetdns.la $(DESTDIR)$(libdir)
|
||||||
if test $(have_libevent) = 1 ; then $(INSTALL) -m 644 $(srcdir)/getdns/getdns_ext_libevent.h $(DESTDIR)$(includedir)/getdns/ ; $(LIBTOOL) --mode=install cp $(EXTENSION_LIBEVENT_LIB) $(DESTDIR)$(libdir) ; fi
|
if test $(have_libevent) = 1 ; then $(INSTALL) -m 644 $(srcdir)/getdns/getdns_ext_libevent.h $(DESTDIR)$(includedir)/getdns/ ; $(LIBTOOL) --mode=install cp $(EXTENSION_LIBEVENT_LIB) $(DESTDIR)$(libdir) ; fi
|
||||||
|
|
|
@ -881,6 +881,8 @@ getdns_context_create_with_extended_memory_functions(
|
||||||
result->edns_extended_rcode = 0;
|
result->edns_extended_rcode = 0;
|
||||||
result->edns_version = 0;
|
result->edns_version = 0;
|
||||||
result->edns_do_bit = 0;
|
result->edns_do_bit = 0;
|
||||||
|
result->edns_client_subnet_private = 0;
|
||||||
|
result->tls_query_padding_blocksize = 1; /* default is to not try to pad */
|
||||||
result-> tls_ctx = NULL;
|
result-> tls_ctx = NULL;
|
||||||
|
|
||||||
result->extension = &result->mini_event.loop;
|
result->extension = &result->mini_event.loop;
|
||||||
|
@ -1897,6 +1899,46 @@ getdns_context_set_edns_do_bit(struct getdns_context *context, uint8_t value)
|
||||||
return GETDNS_RETURN_GOOD;
|
return GETDNS_RETURN_GOOD;
|
||||||
} /* getdns_context_set_edns_do_bit */
|
} /* getdns_context_set_edns_do_bit */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* getdns_context_set_edns_client_subnet_private
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
getdns_return_t
|
||||||
|
getdns_context_set_edns_client_subnet_private(struct getdns_context *context, uint8_t value)
|
||||||
|
{
|
||||||
|
RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER);
|
||||||
|
/* only allow 1 */
|
||||||
|
if (value != 0 && value != 1) {
|
||||||
|
return GETDNS_RETURN_CONTEXT_UPDATE_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
context->edns_client_subnet_private = value;
|
||||||
|
|
||||||
|
dispatch_updated(context, GETDNS_CONTEXT_CODE_EDNS_CLIENT_SUBNET_PRIVATE);
|
||||||
|
|
||||||
|
return GETDNS_RETURN_GOOD;
|
||||||
|
} /* getdns_context_set_edns_client_subnet_private */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* getdns_context_set_tls_query_padding_blocksize
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
getdns_return_t
|
||||||
|
getdns_context_set_tls_query_padding_blocksize(struct getdns_context *context, uint16_t value)
|
||||||
|
{
|
||||||
|
RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER);
|
||||||
|
/* only allow values between 0 and MAXIMUM_UPSTREAM_OPTION_SPACE - 4
|
||||||
|
(4 is for the overhead of the option itself) */
|
||||||
|
if (value > MAXIMUM_UPSTREAM_OPTION_SPACE - 4) {
|
||||||
|
return GETDNS_RETURN_CONTEXT_UPDATE_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
context->tls_query_padding_blocksize = value;
|
||||||
|
|
||||||
|
dispatch_updated(context, GETDNS_CONTEXT_CODE_TLS_QUERY_PADDING_BLOCKSIZE);
|
||||||
|
|
||||||
|
return GETDNS_RETURN_GOOD;
|
||||||
|
} /* getdns_context_set_tls_query_padding_blocksize */
|
||||||
/*
|
/*
|
||||||
* getdns_context_set_extended_memory_functions
|
* getdns_context_set_extended_memory_functions
|
||||||
*
|
*
|
||||||
|
@ -2211,8 +2253,8 @@ _getdns_context_prepare_for_resolution(struct getdns_context *context,
|
||||||
if(context->tls_ctx == NULL)
|
if(context->tls_ctx == NULL)
|
||||||
return GETDNS_RETURN_BAD_CONTEXT;
|
return GETDNS_RETURN_BAD_CONTEXT;
|
||||||
/* Be strict and only use the cipher suites recommended in RFC7525
|
/* Be strict and only use the cipher suites recommended in RFC7525
|
||||||
Unless we later fallback to oppotunistic. */
|
Unless we later fallback to opportunistic. */
|
||||||
const char* const PREFERRED_CIPHERS = "EECDH+aRSA+AESGCM:EDH+aRSA+AESGCM";
|
const char* const PREFERRED_CIPHERS = "EECDH+aRSA+AESGCM:EECDH+aECDSA+AESGCM:EDH+aRSA+AESGCM";
|
||||||
if (!SSL_CTX_set_cipher_list(context->tls_ctx, PREFERRED_CIPHERS))
|
if (!SSL_CTX_set_cipher_list(context->tls_ctx, PREFERRED_CIPHERS))
|
||||||
return GETDNS_RETURN_BAD_CONTEXT;
|
return GETDNS_RETURN_BAD_CONTEXT;
|
||||||
if (!SSL_CTX_set_default_verify_paths(context->tls_ctx))
|
if (!SSL_CTX_set_default_verify_paths(context->tls_ctx))
|
||||||
|
@ -2977,4 +3019,20 @@ getdns_context_get_edns_do_bit(getdns_context *context, uint8_t* value) {
|
||||||
return GETDNS_RETURN_GOOD;
|
return GETDNS_RETURN_GOOD;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getdns_return_t
|
||||||
|
getdns_context_get_edns_client_subnet_private(getdns_context *context, uint8_t* value) {
|
||||||
|
RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER);
|
||||||
|
RETURN_IF_NULL(value, GETDNS_RETURN_INVALID_PARAMETER);
|
||||||
|
*value = context->edns_client_subnet_private;
|
||||||
|
return GETDNS_RETURN_GOOD;
|
||||||
|
}
|
||||||
|
|
||||||
|
getdns_return_t
|
||||||
|
getdns_context_get_tls_query_padding_blocksize(getdns_context *context, uint16_t* value) {
|
||||||
|
RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER);
|
||||||
|
RETURN_IF_NULL(value, GETDNS_RETURN_INVALID_PARAMETER);
|
||||||
|
*value = context->tls_query_padding_blocksize;
|
||||||
|
return GETDNS_RETURN_GOOD;
|
||||||
|
}
|
||||||
|
|
||||||
/* context.c */
|
/* context.c */
|
||||||
|
|
|
@ -157,6 +157,8 @@ struct getdns_context {
|
||||||
uint8_t edns_version;
|
uint8_t edns_version;
|
||||||
uint8_t edns_do_bit;
|
uint8_t edns_do_bit;
|
||||||
int edns_maximum_udp_payload_size; /* -1 is unset */
|
int edns_maximum_udp_payload_size; /* -1 is unset */
|
||||||
|
uint8_t edns_client_subnet_private;
|
||||||
|
uint16_t tls_query_padding_blocksize;
|
||||||
SSL_CTX* tls_ctx;
|
SSL_CTX* tls_ctx;
|
||||||
|
|
||||||
getdns_update_callback update_callback;
|
getdns_update_callback update_callback;
|
||||||
|
|
|
@ -981,6 +981,7 @@ getdns_pp_dict(gldns_buffer * buf, size_t indent,
|
||||||
if (!json &&
|
if (!json &&
|
||||||
(strcmp(item->node.key, "type") == 0 ||
|
(strcmp(item->node.key, "type") == 0 ||
|
||||||
strcmp(item->node.key, "type_covered") == 0 ||
|
strcmp(item->node.key, "type_covered") == 0 ||
|
||||||
|
strcmp(item->node.key, "query_type") == 0 ||
|
||||||
strcmp(item->node.key, "qtype") == 0) &&
|
strcmp(item->node.key, "qtype") == 0) &&
|
||||||
(strval = _getdns_rr_type_name(item->i.data.n))) {
|
(strval = _getdns_rr_type_name(item->i.data.n))) {
|
||||||
if (gldns_buffer_printf(
|
if (gldns_buffer_printf(
|
||||||
|
@ -994,6 +995,7 @@ getdns_pp_dict(gldns_buffer * buf, size_t indent,
|
||||||
strcmp(item->node.key, "status") == 0 ||
|
strcmp(item->node.key, "status") == 0 ||
|
||||||
strcmp(item->node.key, "append_name") == 0 ||
|
strcmp(item->node.key, "append_name") == 0 ||
|
||||||
strcmp(item->node.key, "follow_redirects") == 0 ||
|
strcmp(item->node.key, "follow_redirects") == 0 ||
|
||||||
|
strcmp(item->node.key, "transport") == 0 ||
|
||||||
strcmp(item->node.key, "resolution_type") == 0) &&
|
strcmp(item->node.key, "resolution_type") == 0) &&
|
||||||
(strval =
|
(strval =
|
||||||
_getdns_get_const_info(item->i.data.n)->name)) {
|
_getdns_get_const_info(item->i.data.n)->name)) {
|
||||||
|
|
|
@ -194,6 +194,16 @@ getdns_context_get_edns_version(getdns_context *context, uint8_t* value);
|
||||||
getdns_return_t
|
getdns_return_t
|
||||||
getdns_context_get_edns_do_bit(getdns_context *context, uint8_t* value);
|
getdns_context_get_edns_do_bit(getdns_context *context, uint8_t* value);
|
||||||
|
|
||||||
|
getdns_return_t
|
||||||
|
getdns_context_set_edns_client_subnet_private(getdns_context *context, uint8_t value);
|
||||||
|
getdns_return_t
|
||||||
|
getdns_context_get_edns_client_subnet_private(getdns_context *context, uint8_t* value);
|
||||||
|
|
||||||
|
getdns_return_t
|
||||||
|
getdns_context_set_tls_query_padding_blocksize(getdns_context *context, uint16_t value);
|
||||||
|
getdns_return_t
|
||||||
|
getdns_context_get_tls_query_padding_blocksize(getdns_context *context, uint16_t* value);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pretty print the getdns_dict in a given buffer snprintf style.
|
* Pretty print the getdns_dict in a given buffer snprintf style.
|
||||||
|
@ -366,6 +376,10 @@ typedef enum getdns_tls_authentication_t {
|
||||||
|
|
||||||
#define GETDNS_CONTEXT_CODE_TLS_AUTHENTICATION 618
|
#define GETDNS_CONTEXT_CODE_TLS_AUTHENTICATION 618
|
||||||
#define GETDNS_CONTEXT_CODE_TLS_AUTHENTICATION_TEXT "Change related to getdns_context_set_tls_authentication"
|
#define GETDNS_CONTEXT_CODE_TLS_AUTHENTICATION_TEXT "Change related to getdns_context_set_tls_authentication"
|
||||||
|
#define GETDNS_CONTEXT_CODE_EDNS_CLIENT_SUBNET_PRIVATE 619
|
||||||
|
#define GETDNS_CONTEXT_CODE_EDNS_CLIENT_SUBNET_PRIVATE_TEXT "Change related to getdns_context_set_edns_client_subnet_private"
|
||||||
|
#define GETDNS_CONTEXT_CODE_TLS_QUERY_PADDING_BLOCKSIZE 620
|
||||||
|
#define GETDNS_CONTEXT_CODE_TLS_QUERY_PADDING_BLOCKSIZE_TEXT "Change related to getdns_context_set_tls_query_padding_blocksize"
|
||||||
|
|
||||||
getdns_return_t
|
getdns_return_t
|
||||||
getdns_context_set_tls_authentication(
|
getdns_context_set_tls_authentication(
|
||||||
|
|
|
@ -13,6 +13,7 @@ getdns_context_get_dnssec_allowed_skew
|
||||||
getdns_context_get_dnssec_trust_anchors
|
getdns_context_get_dnssec_trust_anchors
|
||||||
getdns_context_get_dns_transport
|
getdns_context_get_dns_transport
|
||||||
getdns_context_get_dns_transport_list
|
getdns_context_get_dns_transport_list
|
||||||
|
getdns_context_get_edns_client_subnet_private
|
||||||
getdns_context_get_edns_do_bit
|
getdns_context_get_edns_do_bit
|
||||||
getdns_context_get_edns_extended_rcode
|
getdns_context_get_edns_extended_rcode
|
||||||
getdns_context_get_edns_maximum_udp_payload_size
|
getdns_context_get_edns_maximum_udp_payload_size
|
||||||
|
@ -25,6 +26,7 @@ getdns_context_get_num_pending_requests
|
||||||
getdns_context_get_resolution_type
|
getdns_context_get_resolution_type
|
||||||
getdns_context_get_suffix
|
getdns_context_get_suffix
|
||||||
getdns_context_get_timeout
|
getdns_context_get_timeout
|
||||||
|
getdns_context_get_tls_query_padding_blocksize
|
||||||
getdns_context_get_update_callback
|
getdns_context_get_update_callback
|
||||||
getdns_context_get_upstream_recursive_servers
|
getdns_context_get_upstream_recursive_servers
|
||||||
getdns_context_process_async
|
getdns_context_process_async
|
||||||
|
@ -36,6 +38,7 @@ getdns_context_set_dnssec_allowed_skew
|
||||||
getdns_context_set_dnssec_trust_anchors
|
getdns_context_set_dnssec_trust_anchors
|
||||||
getdns_context_set_dns_transport
|
getdns_context_set_dns_transport
|
||||||
getdns_context_set_dns_transport_list
|
getdns_context_set_dns_transport_list
|
||||||
|
getdns_context_set_edns_client_subnet_private
|
||||||
getdns_context_set_edns_do_bit
|
getdns_context_set_edns_do_bit
|
||||||
getdns_context_set_edns_extended_rcode
|
getdns_context_set_edns_extended_rcode
|
||||||
getdns_context_set_edns_maximum_udp_payload_size
|
getdns_context_set_edns_maximum_udp_payload_size
|
||||||
|
@ -52,6 +55,7 @@ getdns_context_set_return_dnssec_status
|
||||||
getdns_context_set_suffix
|
getdns_context_set_suffix
|
||||||
getdns_context_set_timeout
|
getdns_context_set_timeout
|
||||||
getdns_context_set_tls_authentication
|
getdns_context_set_tls_authentication
|
||||||
|
getdns_context_set_tls_query_padding_blocksize
|
||||||
getdns_context_set_update_callback
|
getdns_context_set_update_callback
|
||||||
getdns_context_set_upstream_recursive_servers
|
getdns_context_set_upstream_recursive_servers
|
||||||
getdns_context_set_use_threads
|
getdns_context_set_use_threads
|
||||||
|
|
|
@ -113,6 +113,12 @@ network_req_init(getdns_network_req *net_req, getdns_dns_req *owner,
|
||||||
? edns_maximum_udp_payload_size : 1432;
|
? edns_maximum_udp_payload_size : 1432;
|
||||||
net_req->write_queue_tail = NULL;
|
net_req->write_queue_tail = NULL;
|
||||||
net_req->response_len = 0;
|
net_req->response_len = 0;
|
||||||
|
net_req->base_query_option_sz = opt_options_size;
|
||||||
|
|
||||||
|
/* Some fields to record info for return_call_debugging */
|
||||||
|
net_req->debug_start_time = 0;
|
||||||
|
net_req->debug_end_time = 0;
|
||||||
|
net_req->debug_tls_auth_status = 0;
|
||||||
|
|
||||||
net_req->wire_data_sz = wire_data_sz;
|
net_req->wire_data_sz = wire_data_sz;
|
||||||
if (max_query_sz) {
|
if (max_query_sz) {
|
||||||
|
@ -184,6 +190,75 @@ network_req_init(getdns_network_req *net_req, getdns_dns_req *owner,
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* req->opt + 9 is the length; req->opt + 11 is the start of the
|
||||||
|
options.
|
||||||
|
|
||||||
|
clear_upstream_options() goes back to the per-query options.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
_getdns_network_req_clear_upstream_options(getdns_network_req * req)
|
||||||
|
{
|
||||||
|
size_t pktlen;
|
||||||
|
if (req->opt) {
|
||||||
|
gldns_write_uint16(req->opt + 9, req->base_query_option_sz);
|
||||||
|
req->response = req->opt + 11 + req->base_query_option_sz;
|
||||||
|
pktlen = req->response - req->query;
|
||||||
|
gldns_write_uint16(req->query - 2, pktlen);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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) */
|
||||||
|
getdns_return_t
|
||||||
|
_getdns_network_req_add_upstream_option(getdns_network_req * req, uint16_t code, uint16_t sz, const void* data)
|
||||||
|
{
|
||||||
|
uint16_t oldlen;
|
||||||
|
uint32_t newlen;
|
||||||
|
uint32_t pktlen;
|
||||||
|
size_t cur_upstream_option_sz;
|
||||||
|
|
||||||
|
/* if no options are set, we can't add upstream options */
|
||||||
|
if (!req->opt)
|
||||||
|
return GETDNS_RETURN_GENERIC_ERROR;
|
||||||
|
|
||||||
|
/* if TCP, no overflow allowed for length field
|
||||||
|
https://tools.ietf.org/html/rfc1035#section-4.2.2 */
|
||||||
|
pktlen = req->response - req->query;
|
||||||
|
pktlen += 4 + sz;
|
||||||
|
if (pktlen > UINT16_MAX)
|
||||||
|
return GETDNS_RETURN_GENERIC_ERROR;
|
||||||
|
|
||||||
|
/* no overflow allowed for OPT size either (maybe this is overkill
|
||||||
|
given the above check?) */
|
||||||
|
oldlen = gldns_read_uint16(req->opt + 9);
|
||||||
|
newlen = oldlen + 4 + sz;
|
||||||
|
if (newlen > UINT16_MAX)
|
||||||
|
return GETDNS_RETURN_GENERIC_ERROR;
|
||||||
|
|
||||||
|
/* avoid overflowing MAXIMUM_UPSTREAM_OPTION_SPACE */
|
||||||
|
cur_upstream_option_sz = (size_t)oldlen - req->base_query_option_sz;
|
||||||
|
if (cur_upstream_option_sz + 4 + sz > MAXIMUM_UPSTREAM_OPTION_SPACE)
|
||||||
|
return GETDNS_RETURN_GENERIC_ERROR;
|
||||||
|
|
||||||
|
/* actually add the option: */
|
||||||
|
gldns_write_uint16(req->opt + 11 + oldlen, code);
|
||||||
|
gldns_write_uint16(req->opt + 11 + oldlen + 2, sz);
|
||||||
|
if (data != NULL)
|
||||||
|
memcpy(req->opt + 11 + oldlen + 4, data, sz);
|
||||||
|
else
|
||||||
|
memset(req->opt + 11 + oldlen + 4, 0, sz);
|
||||||
|
gldns_write_uint16(req->opt + 9, newlen);
|
||||||
|
|
||||||
|
/* the response should start right after the options end: */
|
||||||
|
req->response = req->opt + 11 + newlen;
|
||||||
|
|
||||||
|
/* for TCP, adjust the size of the wire format itself: */
|
||||||
|
gldns_write_uint16(req->query - 2, pktlen);
|
||||||
|
|
||||||
|
return GETDNS_RETURN_GOOD;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
_getdns_dns_req_free(getdns_dns_req * req)
|
_getdns_dns_req_free(getdns_dns_req * req)
|
||||||
{
|
{
|
||||||
|
@ -306,7 +381,8 @@ _getdns_dns_req_new(getdns_context *context, getdns_eventloop *loop,
|
||||||
|
|
||||||
with_opt = edns_do_bit != 0 || edns_maximum_udp_payload_size != 512 ||
|
with_opt = edns_do_bit != 0 || edns_maximum_udp_payload_size != 512 ||
|
||||||
edns_extended_rcode != 0 || edns_version != 0 || noptions ||
|
edns_extended_rcode != 0 || edns_version != 0 || noptions ||
|
||||||
edns_cookies;
|
edns_cookies || context->edns_client_subnet_private ||
|
||||||
|
context->tls_query_padding_blocksize > 1;
|
||||||
|
|
||||||
edns_maximum_udp_payload_size = with_opt &&
|
edns_maximum_udp_payload_size = with_opt &&
|
||||||
( edns_maximum_udp_payload_size == -1 ||
|
( edns_maximum_udp_payload_size == -1 ||
|
||||||
|
@ -337,12 +413,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 */
|
+ strlen(name) + 1 + 4 /* dname always smaller then strlen(name) + 1 */
|
||||||
+ 12 + opt_options_size /* space needed for OPT (if needed) */
|
+ 12 + opt_options_size /* space needed for OPT (if needed) */
|
||||||
+ ( !edns_cookies ? 0
|
+ MAXIMUM_UPSTREAM_OPTION_SPACE
|
||||||
: 2 /* EDNS0 Option Code */
|
|
||||||
+ 2 /* Option length = 8 + 16 = 24 */
|
|
||||||
+ 8 /* client cookie */
|
|
||||||
+ 16 /* server cookie */
|
|
||||||
)
|
|
||||||
/* TODO: TSIG */
|
/* TODO: TSIG */
|
||||||
+ 7) / 8 * 8;
|
+ 7) / 8 * 8;
|
||||||
}
|
}
|
||||||
|
@ -390,6 +461,10 @@ _getdns_dns_req_new(getdns_context *context, getdns_eventloop *loop,
|
||||||
result->dnssec_roadblock_avoidance = dnssec_roadblock_avoidance;
|
result->dnssec_roadblock_avoidance = dnssec_roadblock_avoidance;
|
||||||
result->avoid_dnssec_roadblocks = 0;
|
result->avoid_dnssec_roadblocks = 0;
|
||||||
#endif
|
#endif
|
||||||
|
result->edns_client_subnet_private = context->edns_client_subnet_private;
|
||||||
|
result->tls_query_padding_blocksize = context->tls_query_padding_blocksize;
|
||||||
|
result->return_call_debugging
|
||||||
|
= is_extension_set(extensions, "return_call_debugging");
|
||||||
|
|
||||||
/* will be set by caller */
|
/* will be set by caller */
|
||||||
result->user_pointer = NULL;
|
result->user_pointer = NULL;
|
||||||
|
|
147
src/stub.c
147
src/stub.c
|
@ -46,6 +46,7 @@
|
||||||
#include "util-internal.h"
|
#include "util-internal.h"
|
||||||
#include "general.h"
|
#include "general.h"
|
||||||
|
|
||||||
|
#define STUB_OUT_OF_OPTIONS -5 /* upstream options exceeded MAXIMUM_UPSTREAM_OPTION_SPACE */
|
||||||
#define STUB_TLS_SETUP_ERROR -4
|
#define STUB_TLS_SETUP_ERROR -4
|
||||||
#define STUB_TCP_AGAIN -3
|
#define STUB_TCP_AGAIN -3
|
||||||
#define STUB_TCP_ERROR -2
|
#define STUB_TCP_ERROR -2
|
||||||
|
@ -129,9 +130,27 @@ calc_new_cookie(getdns_upstream *upstream, uint8_t *cookie)
|
||||||
cookie[i % 8] ^= md_value[i];
|
cookie[i % 8] ^= md_value[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint8_t *
|
static getdns_return_t
|
||||||
attach_edns_cookie(getdns_upstream *upstream, uint8_t *opt)
|
attach_edns_client_subnet_private(getdns_network_req *req)
|
||||||
{
|
{
|
||||||
|
/* see
|
||||||
|
* https://tools.ietf.org/html/draft-ietf-dnsop-edns-client-subnet-04#section-6 */
|
||||||
|
/* all-zeros is a request to not leak the data further: */
|
||||||
|
/* "\x00\x00" FAMILY: 0 (because no address) */
|
||||||
|
/* "\x00" SOURCE PREFIX-LENGTH: 0 */
|
||||||
|
/* "\x00"; SCOPE PREFIX-LENGTH: 0 */
|
||||||
|
return _getdns_network_req_add_upstream_option(req,
|
||||||
|
GLDNS_EDNS_CLIENT_SUBNET,
|
||||||
|
4, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static getdns_return_t
|
||||||
|
attach_edns_cookie(getdns_network_req *req)
|
||||||
|
{
|
||||||
|
getdns_upstream *upstream = req->upstream;
|
||||||
|
uint16_t sz;
|
||||||
|
void* val;
|
||||||
|
uint8_t buf[8 + 32]; /* server cookies can be no larger than 32 bytes */
|
||||||
rollover_secret();
|
rollover_secret();
|
||||||
|
|
||||||
if (!upstream->has_client_cookie) {
|
if (!upstream->has_client_cookie) {
|
||||||
|
@ -139,12 +158,8 @@ attach_edns_cookie(getdns_upstream *upstream, uint8_t *opt)
|
||||||
upstream->secret = secret;
|
upstream->secret = secret;
|
||||||
upstream->has_client_cookie = 1;
|
upstream->has_client_cookie = 1;
|
||||||
|
|
||||||
gldns_write_uint16(opt + 9, 12); /* rdata len */
|
sz = 8;
|
||||||
gldns_write_uint16(opt + 11, EDNS_COOKIE_OPCODE);
|
val = upstream->client_cookie;
|
||||||
gldns_write_uint16(opt + 13, 8); /* opt len */
|
|
||||||
memcpy(opt + 15, upstream->client_cookie, 8);
|
|
||||||
return opt + 23;
|
|
||||||
|
|
||||||
} else if (upstream->secret != secret) {
|
} else if (upstream->secret != secret) {
|
||||||
memcpy( upstream->prev_client_cookie
|
memcpy( upstream->prev_client_cookie
|
||||||
, upstream->client_cookie, 8);
|
, upstream->client_cookie, 8);
|
||||||
|
@ -152,29 +167,19 @@ attach_edns_cookie(getdns_upstream *upstream, uint8_t *opt)
|
||||||
calc_new_cookie(upstream, upstream->client_cookie);
|
calc_new_cookie(upstream, upstream->client_cookie);
|
||||||
upstream->secret = secret;
|
upstream->secret = secret;
|
||||||
|
|
||||||
gldns_write_uint16(opt + 9, 12); /* rdata len */
|
sz = 8;
|
||||||
gldns_write_uint16(opt + 11, EDNS_COOKIE_OPCODE);
|
val = upstream->client_cookie;
|
||||||
gldns_write_uint16(opt + 13, 8); /* opt len */
|
|
||||||
memcpy(opt + 15, upstream->client_cookie, 8);
|
|
||||||
return opt + 23;
|
|
||||||
|
|
||||||
} else if (!upstream->has_server_cookie) {
|
} else if (!upstream->has_server_cookie) {
|
||||||
gldns_write_uint16(opt + 9, 12); /* rdata len */
|
sz = 8;
|
||||||
gldns_write_uint16(opt + 11, EDNS_COOKIE_OPCODE);
|
val = upstream->client_cookie;
|
||||||
gldns_write_uint16(opt + 13, 8); /* opt len */
|
|
||||||
memcpy(opt + 15, upstream->client_cookie, 8);
|
|
||||||
return opt + 23;
|
|
||||||
} else {
|
} else {
|
||||||
gldns_write_uint16( opt + 9, 12 /* rdata len */
|
sz = 8 + upstream->server_cookie_len;
|
||||||
+ upstream->server_cookie_len);
|
memcpy(buf, upstream->client_cookie, 8);
|
||||||
gldns_write_uint16(opt + 11, EDNS_COOKIE_OPCODE);
|
memcpy(buf+8, upstream->server_cookie, upstream->server_cookie_len);
|
||||||
gldns_write_uint16(opt + 13, 8 /* opt len */
|
val = buf;
|
||||||
+ upstream->server_cookie_len);
|
|
||||||
memcpy(opt + 15, upstream->client_cookie, 8);
|
|
||||||
memcpy(opt + 23, upstream->server_cookie
|
|
||||||
, upstream->server_cookie_len);
|
|
||||||
return opt + 23+ upstream->server_cookie_len;
|
|
||||||
}
|
}
|
||||||
|
return _getdns_network_req_add_upstream_option(req, EDNS_COOKIE_OPCODE, sz, val);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -681,7 +686,7 @@ static int
|
||||||
stub_tcp_write(int fd, getdns_tcp_state *tcp, getdns_network_req *netreq)
|
stub_tcp_write(int fd, getdns_tcp_state *tcp, getdns_network_req *netreq)
|
||||||
{
|
{
|
||||||
|
|
||||||
size_t pkt_len = netreq->response - netreq->query;
|
size_t pkt_len;
|
||||||
ssize_t written;
|
ssize_t written;
|
||||||
uint16_t query_id;
|
uint16_t query_id;
|
||||||
intptr_t query_id_intptr;
|
intptr_t query_id_intptr;
|
||||||
|
@ -704,16 +709,18 @@ stub_tcp_write(int fd, getdns_tcp_state *tcp, getdns_network_req *netreq)
|
||||||
|
|
||||||
GLDNS_ID_SET(netreq->query, query_id);
|
GLDNS_ID_SET(netreq->query, query_id);
|
||||||
if (netreq->opt) {
|
if (netreq->opt) {
|
||||||
|
_getdns_network_req_clear_upstream_options(netreq);
|
||||||
/* no limits on the max udp payload size with tcp */
|
/* no limits on the max udp payload size with tcp */
|
||||||
gldns_write_uint16(netreq->opt + 3, 65535);
|
gldns_write_uint16(netreq->opt + 3, 65535);
|
||||||
|
|
||||||
if (netreq->owner->edns_cookies) {
|
if (netreq->owner->edns_cookies)
|
||||||
netreq->response = attach_edns_cookie(
|
if (attach_edns_cookie(netreq))
|
||||||
netreq->upstream, netreq->opt);
|
return STUB_OUT_OF_OPTIONS;
|
||||||
pkt_len = netreq->response - netreq->query;
|
if (netreq->owner->edns_client_subnet_private)
|
||||||
gldns_write_uint16(netreq->query - 2, pkt_len);
|
if (attach_edns_client_subnet_private(netreq))
|
||||||
}
|
return STUB_OUT_OF_OPTIONS;
|
||||||
}
|
}
|
||||||
|
pkt_len = netreq->response - netreq->query;
|
||||||
/* We have an initialized packet buffer.
|
/* We have an initialized packet buffer.
|
||||||
* Lets see how much of it we can write
|
* Lets see how much of it we can write
|
||||||
*/
|
*/
|
||||||
|
@ -908,7 +915,7 @@ tls_create_object(getdns_dns_req *dnsreq, int fd, getdns_upstream *upstream)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
/* Allow fallback to oppotunisitc if settings permit it*/
|
/* Allow fallback to opportunistic if settings permit it*/
|
||||||
if (dnsreq->netreqs[0]->tls_auth_min == GETDNS_AUTHENTICATION_HOSTNAME)
|
if (dnsreq->netreqs[0]->tls_auth_min == GETDNS_AUTHENTICATION_HOSTNAME)
|
||||||
SSL_set_verify(ssl, SSL_VERIFY_PEER, tls_verify_callback);
|
SSL_set_verify(ssl, SSL_VERIFY_PEER, tls_verify_callback);
|
||||||
else {
|
else {
|
||||||
|
@ -923,6 +930,7 @@ tls_create_object(getdns_dns_req *dnsreq, int fd, getdns_upstream *upstream)
|
||||||
upstream->tls_auth_failed = 1;
|
upstream->tls_auth_failed = 1;
|
||||||
return NULL;
|
return NULL;
|
||||||
} else {
|
} else {
|
||||||
|
/* no hostname verification, so we will make opportunistic connections */
|
||||||
DEBUG_STUB("--- %s, PROCEEDING WITHOUT HOSTNAME VALIDATION!!\n", __FUNCTION__);
|
DEBUG_STUB("--- %s, PROCEEDING WITHOUT HOSTNAME VALIDATION!!\n", __FUNCTION__);
|
||||||
upstream->tls_auth_failed = 1;
|
upstream->tls_auth_failed = 1;
|
||||||
SSL_set_verify(ssl, SSL_VERIFY_NONE, tls_verify_callback_with_fallback);
|
SSL_set_verify(ssl, SSL_VERIFY_NONE, tls_verify_callback_with_fallback);
|
||||||
|
@ -1125,11 +1133,12 @@ static int
|
||||||
stub_tls_write(getdns_upstream *upstream, getdns_tcp_state *tcp,
|
stub_tls_write(getdns_upstream *upstream, getdns_tcp_state *tcp,
|
||||||
getdns_network_req *netreq)
|
getdns_network_req *netreq)
|
||||||
{
|
{
|
||||||
size_t pkt_len = netreq->response - netreq->query;
|
size_t pkt_len;
|
||||||
ssize_t written;
|
ssize_t written;
|
||||||
uint16_t query_id;
|
uint16_t query_id;
|
||||||
intptr_t query_id_intptr;
|
intptr_t query_id_intptr;
|
||||||
SSL* tls_obj = upstream->tls_obj;
|
SSL* tls_obj = upstream->tls_obj;
|
||||||
|
uint16_t padding_sz;
|
||||||
|
|
||||||
int q = tls_connected(upstream);
|
int q = tls_connected(upstream);
|
||||||
if (q != 0)
|
if (q != 0)
|
||||||
|
@ -1155,10 +1164,30 @@ stub_tls_write(getdns_upstream *upstream, getdns_tcp_state *tcp,
|
||||||
&netreq->upstream->netreq_by_query_id, &netreq->node));
|
&netreq->upstream->netreq_by_query_id, &netreq->node));
|
||||||
|
|
||||||
GLDNS_ID_SET(netreq->query, query_id);
|
GLDNS_ID_SET(netreq->query, query_id);
|
||||||
if (netreq->opt)
|
if (netreq->opt) {
|
||||||
|
_getdns_network_req_clear_upstream_options(netreq);
|
||||||
/* no limits on the max udp payload size with tcp */
|
/* no limits on the max udp payload size with tcp */
|
||||||
gldns_write_uint16(netreq->opt + 3, 65535);
|
gldns_write_uint16(netreq->opt + 3, 65535);
|
||||||
|
/* we do not edns_cookie over TLS, since TLS
|
||||||
|
* provides stronger guarantees than cookies
|
||||||
|
* already */
|
||||||
|
if (netreq->owner->edns_client_subnet_private)
|
||||||
|
if (attach_edns_client_subnet_private(netreq))
|
||||||
|
return STUB_OUT_OF_OPTIONS;
|
||||||
|
if (netreq->owner->tls_query_padding_blocksize > 1) {
|
||||||
|
pkt_len = netreq->response - netreq->query;
|
||||||
|
pkt_len += 4; /* this accounts for the OPTION-CODE and OPTION-LENGTH of the padding */
|
||||||
|
padding_sz = pkt_len % netreq->owner->tls_query_padding_blocksize;
|
||||||
|
if (padding_sz)
|
||||||
|
padding_sz = netreq->owner->tls_query_padding_blocksize - padding_sz;
|
||||||
|
if (_getdns_network_req_add_upstream_option(netreq,
|
||||||
|
EDNS_PADDING_OPCODE,
|
||||||
|
padding_sz, NULL))
|
||||||
|
return STUB_OUT_OF_OPTIONS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pkt_len = netreq->response - netreq->query;
|
||||||
/* We have an initialized packet buffer.
|
/* We have an initialized packet buffer.
|
||||||
* Lets see how much of it we can write */
|
* Lets see how much of it we can write */
|
||||||
|
|
||||||
|
@ -1176,6 +1205,19 @@ stub_tls_write(getdns_upstream *upstream, getdns_tcp_state *tcp,
|
||||||
return STUB_TCP_ERROR;
|
return STUB_TCP_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint64_t
|
||||||
|
_getdns_get_time_as_uintt64() {
|
||||||
|
|
||||||
|
struct timeval tv;
|
||||||
|
uint64_t now;
|
||||||
|
|
||||||
|
if (gettimeofday(&tv, NULL)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
now = tv.tv_sec * 1000000 + tv.tv_usec;
|
||||||
|
return now;
|
||||||
|
}
|
||||||
|
|
||||||
/**************************/
|
/**************************/
|
||||||
/* UDP callback functions */
|
/* UDP callback functions */
|
||||||
/**************************/
|
/**************************/
|
||||||
|
@ -1237,6 +1279,7 @@ stub_udp_read_cb(void *userarg)
|
||||||
netreq->response_len = read;
|
netreq->response_len = read;
|
||||||
dnsreq->upstreams->current = 0;
|
dnsreq->upstreams->current = 0;
|
||||||
done:
|
done:
|
||||||
|
netreq->debug_end_time = _getdns_get_time_as_uintt64();
|
||||||
netreq->state = NET_REQ_FINISHED;
|
netreq->state = NET_REQ_FINISHED;
|
||||||
_getdns_check_dns_req_complete(dnsreq);
|
_getdns_check_dns_req_complete(dnsreq);
|
||||||
}
|
}
|
||||||
|
@ -1247,25 +1290,28 @@ stub_udp_write_cb(void *userarg)
|
||||||
DEBUG_STUB("%s\n", __FUNCTION__);
|
DEBUG_STUB("%s\n", __FUNCTION__);
|
||||||
getdns_network_req *netreq = (getdns_network_req *)userarg;
|
getdns_network_req *netreq = (getdns_network_req *)userarg;
|
||||||
getdns_dns_req *dnsreq = netreq->owner;
|
getdns_dns_req *dnsreq = netreq->owner;
|
||||||
size_t pkt_len = netreq->response - netreq->query;
|
size_t pkt_len;
|
||||||
|
|
||||||
GETDNS_CLEAR_EVENT(dnsreq->loop, &netreq->event);
|
GETDNS_CLEAR_EVENT(dnsreq->loop, &netreq->event);
|
||||||
|
|
||||||
|
netreq->debug_start_time = _getdns_get_time_as_uintt64();
|
||||||
netreq->query_id = arc4random();
|
netreq->query_id = arc4random();
|
||||||
GLDNS_ID_SET(netreq->query, netreq->query_id);
|
GLDNS_ID_SET(netreq->query, netreq->query_id);
|
||||||
if (netreq->opt) {
|
if (netreq->opt) {
|
||||||
|
_getdns_network_req_clear_upstream_options(netreq);
|
||||||
if (netreq->edns_maximum_udp_payload_size == -1)
|
if (netreq->edns_maximum_udp_payload_size == -1)
|
||||||
gldns_write_uint16(netreq->opt + 3,
|
gldns_write_uint16(netreq->opt + 3,
|
||||||
( netreq->max_udp_payload_size =
|
( netreq->max_udp_payload_size =
|
||||||
netreq->upstream->addr.ss_family == AF_INET6
|
netreq->upstream->addr.ss_family == AF_INET6
|
||||||
? 1232 : 1432));
|
? 1232 : 1432));
|
||||||
if (netreq->owner->edns_cookies) {
|
if (netreq->owner->edns_cookies)
|
||||||
netreq->response = attach_edns_cookie(
|
if (attach_edns_cookie(netreq))
|
||||||
netreq->upstream, netreq->opt);
|
return; /* too many upstream options */
|
||||||
pkt_len = netreq->response - netreq->query;
|
if (netreq->owner->edns_client_subnet_private)
|
||||||
}
|
if (attach_edns_client_subnet_private(netreq))
|
||||||
|
return; /* too many upstream options */
|
||||||
}
|
}
|
||||||
|
pkt_len = netreq->response - netreq->query;
|
||||||
if ((ssize_t)pkt_len != sendto(netreq->fd, netreq->query, pkt_len, 0,
|
if ((ssize_t)pkt_len != sendto(netreq->fd, netreq->query, pkt_len, 0,
|
||||||
(struct sockaddr *)&netreq->upstream->addr,
|
(struct sockaddr *)&netreq->upstream->addr,
|
||||||
netreq->upstream->addr_len)) {
|
netreq->upstream->addr_len)) {
|
||||||
|
@ -1314,7 +1360,7 @@ stub_tcp_read_cb(void *userarg)
|
||||||
netreq->tcp.read_pos - netreq->tcp.read_buf;
|
netreq->tcp.read_pos - netreq->tcp.read_buf;
|
||||||
netreq->tcp.read_buf = NULL;
|
netreq->tcp.read_buf = NULL;
|
||||||
dnsreq->upstreams->current = 0;
|
dnsreq->upstreams->current = 0;
|
||||||
|
netreq->debug_end_time = _getdns_get_time_as_uintt64();
|
||||||
stub_cleanup(netreq);
|
stub_cleanup(netreq);
|
||||||
close(netreq->fd);
|
close(netreq->fd);
|
||||||
_getdns_check_dns_req_complete(dnsreq);
|
_getdns_check_dns_req_complete(dnsreq);
|
||||||
|
@ -1327,7 +1373,7 @@ stub_tcp_write_cb(void *userarg)
|
||||||
getdns_network_req *netreq = (getdns_network_req *)userarg;
|
getdns_network_req *netreq = (getdns_network_req *)userarg;
|
||||||
getdns_dns_req *dnsreq = netreq->owner;
|
getdns_dns_req *dnsreq = netreq->owner;
|
||||||
int q;
|
int q;
|
||||||
|
netreq->debug_start_time = _getdns_get_time_as_uintt64();
|
||||||
switch ((q = stub_tcp_write(netreq->fd, &netreq->tcp, netreq))) {
|
switch ((q = stub_tcp_write(netreq->fd, &netreq->tcp, netreq))) {
|
||||||
case STUB_TCP_AGAIN:
|
case STUB_TCP_AGAIN:
|
||||||
return;
|
return;
|
||||||
|
@ -1420,7 +1466,7 @@ upstream_read_cb(void *userarg)
|
||||||
getdns_eventloop_event_init(&upstream->event, upstream,
|
getdns_eventloop_event_init(&upstream->event, upstream,
|
||||||
NULL, upstream_write_cb, NULL));
|
NULL, upstream_write_cb, NULL));
|
||||||
}
|
}
|
||||||
|
netreq->debug_end_time = _getdns_get_time_as_uintt64();
|
||||||
/* This also reschedules events for the upstream*/
|
/* This also reschedules events for the upstream*/
|
||||||
stub_cleanup(netreq);
|
stub_cleanup(netreq);
|
||||||
|
|
||||||
|
@ -1448,6 +1494,9 @@ upstream_write_cb(void *userarg)
|
||||||
getdns_dns_req *dnsreq = netreq->owner;
|
getdns_dns_req *dnsreq = netreq->owner;
|
||||||
int q;
|
int q;
|
||||||
|
|
||||||
|
/* TODO: think about TCP AGAIN */
|
||||||
|
netreq->debug_start_time = _getdns_get_time_as_uintt64();
|
||||||
|
|
||||||
DEBUG_STUB("--- WRITE: %s: %p TYPE: %d\n", __FUNCTION__, netreq,
|
DEBUG_STUB("--- WRITE: %s: %p TYPE: %d\n", __FUNCTION__, netreq,
|
||||||
netreq->request_type);
|
netreq->request_type);
|
||||||
if (tls_requested(netreq) && tls_should_write(upstream))
|
if (tls_requested(netreq) && tls_should_write(upstream))
|
||||||
|
@ -1477,6 +1526,8 @@ upstream_write_cb(void *userarg)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
/* Need this because auth status is reset on connection clode */
|
||||||
|
netreq->debug_tls_auth_status = netreq->upstream->tls_auth_failed;
|
||||||
upstream->writes_done++;
|
upstream->writes_done++;
|
||||||
netreq->query_id = (uint16_t) q;
|
netreq->query_id = (uint16_t) q;
|
||||||
/* Unqueue the netreq from the write_queue */
|
/* Unqueue the netreq from the write_queue */
|
||||||
|
|
|
@ -365,6 +365,54 @@
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST (getdns_context_set_context_update_callback_20)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Create a context by calling getdns_context_create()
|
||||||
|
* Define a callback routine for context changes and call getdns_context_set_context_update_callback() so that it gets called when there are context changes
|
||||||
|
* Call getdns_context_set_edns_client_subnet_private() setting to 1
|
||||||
|
* expect: GETDNS_CONTEXT_CODE_EDNS_CLIENT_SUBNET_PRIVATE
|
||||||
|
*/
|
||||||
|
struct getdns_context *context = NULL;
|
||||||
|
CONTEXT_CREATE(TRUE);
|
||||||
|
|
||||||
|
ASSERT_RC(getdns_context_set_context_update_callback(context, update_callbackfn),
|
||||||
|
GETDNS_RETURN_GOOD, "Return code from getdns_context_set_context_update_callback()");
|
||||||
|
|
||||||
|
expected_changed_item = GETDNS_CONTEXT_CODE_EDNS_CLIENT_SUBNET_PRIVATE;
|
||||||
|
|
||||||
|
ASSERT_RC(getdns_context_set_edns_client_subnet_private(context, 1),
|
||||||
|
GETDNS_RETURN_GOOD, "Return code from getdns_context_set_edns_client_subnet_private()");
|
||||||
|
|
||||||
|
CONTEXT_DESTROY;
|
||||||
|
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST (getdns_context_set_context_update_callback_21)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Create a context by calling getdns_context_create()
|
||||||
|
* Define a callback routine for context changes and call getdns_context_set_context_update_callback() so that it gets called when there are context changes
|
||||||
|
* Call getdns_context_set_edns_client_subnet_private() setting to 1
|
||||||
|
* expect: GETDNS_CONTEXT_CODE_TLS_QUERY_PADDING_BLOCKSIZE
|
||||||
|
*/
|
||||||
|
struct getdns_context *context = NULL;
|
||||||
|
CONTEXT_CREATE(TRUE);
|
||||||
|
|
||||||
|
ASSERT_RC(getdns_context_set_context_update_callback(context, update_callbackfn),
|
||||||
|
GETDNS_RETURN_GOOD, "Return code from getdns_context_set_context_update_callback()");
|
||||||
|
|
||||||
|
expected_changed_item = GETDNS_CONTEXT_CODE_TLS_QUERY_PADDING_BLOCKSIZE;
|
||||||
|
|
||||||
|
ASSERT_RC(getdns_context_set_tls_query_padding_blocksize(context, 1400),
|
||||||
|
GETDNS_RETURN_GOOD, "Return code from getdns_context_set_tls_query_padding_blocksize()");
|
||||||
|
|
||||||
|
CONTEXT_DESTROY;
|
||||||
|
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Suite *
|
Suite *
|
||||||
|
@ -391,6 +439,8 @@
|
||||||
tcase_add_test(tc_pos, getdns_context_set_context_update_callback_17);
|
tcase_add_test(tc_pos, getdns_context_set_context_update_callback_17);
|
||||||
tcase_add_test(tc_pos, getdns_context_set_context_update_callback_18);
|
tcase_add_test(tc_pos, getdns_context_set_context_update_callback_18);
|
||||||
tcase_add_test(tc_pos, getdns_context_set_context_update_callback_19);
|
tcase_add_test(tc_pos, getdns_context_set_context_update_callback_19);
|
||||||
|
tcase_add_test(tc_pos, getdns_context_set_context_update_callback_20);
|
||||||
|
tcase_add_test(tc_pos, getdns_context_set_context_update_callback_21);
|
||||||
suite_add_tcase(s, tc_pos);
|
suite_add_tcase(s, tc_pos);
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
|
|
|
@ -261,7 +261,7 @@ static char *name;
|
||||||
static getdns_context *context;
|
static getdns_context *context;
|
||||||
static getdns_dict *extensions;
|
static getdns_dict *extensions;
|
||||||
static uint16_t request_type = GETDNS_RRTYPE_NS;
|
static uint16_t request_type = GETDNS_RRTYPE_NS;
|
||||||
static int timeout, edns0_size;
|
static int timeout, edns0_size, padding_blocksize;
|
||||||
static int async = 0, interactive = 0;
|
static int async = 0, interactive = 0;
|
||||||
static enum { GENERAL, ADDRESS, HOSTNAME, SERVICE } calltype = GENERAL;
|
static enum { GENERAL, ADDRESS, HOSTNAME, SERVICE } calltype = GENERAL;
|
||||||
|
|
||||||
|
@ -368,6 +368,7 @@ print_usage(FILE *out, const char *progname)
|
||||||
fprintf(out, "\t-A\taddress lookup (<type> is ignored)\n");
|
fprintf(out, "\t-A\taddress lookup (<type> is ignored)\n");
|
||||||
fprintf(out, "\t-B\tBatch mode. Schedule all messages before processing responses.\n");
|
fprintf(out, "\t-B\tBatch mode. Schedule all messages before processing responses.\n");
|
||||||
fprintf(out, "\t-b <bufsize>\tSet edns0 max_udp_payload size\n");
|
fprintf(out, "\t-b <bufsize>\tSet edns0 max_udp_payload size\n");
|
||||||
|
fprintf(out, "\t-c\tSend Client Subnet privacy request\n");
|
||||||
fprintf(out, "\t-D\tSet edns0 do bit\n");
|
fprintf(out, "\t-D\tSet edns0 do bit\n");
|
||||||
fprintf(out, "\t-d\tclear edns0 do bit\n");
|
fprintf(out, "\t-d\tclear edns0 do bit\n");
|
||||||
fprintf(out, "\t-e <idle_timeout>\tSet idle timeout in miliseconds\n");
|
fprintf(out, "\t-e <idle_timeout>\tSet idle timeout in miliseconds\n");
|
||||||
|
@ -383,6 +384,7 @@ print_usage(FILE *out, const char *progname)
|
||||||
fprintf(out, "\t-n\tSet TLS authentication mode to NONE (default)\n");
|
fprintf(out, "\t-n\tSet TLS authentication mode to NONE (default)\n");
|
||||||
fprintf(out, "\t-m\tSet TLS authentication mode to HOSTNAME\n");
|
fprintf(out, "\t-m\tSet TLS authentication mode to HOSTNAME\n");
|
||||||
fprintf(out, "\t-p\tPretty print response dict\n");
|
fprintf(out, "\t-p\tPretty print response dict\n");
|
||||||
|
fprintf(out, "\t-P <blocksize>\tPad TLS queries to a multiple of blocksize\n");
|
||||||
fprintf(out, "\t-r\tSet recursing resolution type\n");
|
fprintf(out, "\t-r\tSet recursing resolution type\n");
|
||||||
fprintf(out, "\t-q\tQuiet mode - don't print response\n");
|
fprintf(out, "\t-q\tQuiet mode - don't print response\n");
|
||||||
fprintf(out, "\t-s\tSet stub resolution type (default = recursing)\n");
|
fprintf(out, "\t-s\tSet stub resolution type (default = recursing)\n");
|
||||||
|
@ -655,6 +657,10 @@ getdns_return_t parse_args(int argc, char **argv)
|
||||||
getdns_context_set_edns_maximum_udp_payload_size(
|
getdns_context_set_edns_maximum_udp_payload_size(
|
||||||
context, (uint16_t) edns0_size);
|
context, (uint16_t) edns0_size);
|
||||||
goto next;
|
goto next;
|
||||||
|
case 'c':
|
||||||
|
if (getdns_context_set_edns_client_subnet_private(context, 1))
|
||||||
|
return GETDNS_RETURN_GENERIC_ERROR;
|
||||||
|
break;
|
||||||
case 'D':
|
case 'D':
|
||||||
(void) getdns_context_set_edns_do_bit(context, 1);
|
(void) getdns_context_set_edns_do_bit(context, 1);
|
||||||
break;
|
break;
|
||||||
|
@ -702,6 +708,23 @@ getdns_return_t parse_args(int argc, char **argv)
|
||||||
getdns_context_set_tls_authentication(context,
|
getdns_context_set_tls_authentication(context,
|
||||||
GETDNS_AUTHENTICATION_HOSTNAME);
|
GETDNS_AUTHENTICATION_HOSTNAME);
|
||||||
break;
|
break;
|
||||||
|
case 'P':
|
||||||
|
if (c[1] != 0 || ++i >= argc || !*argv[i]) {
|
||||||
|
fprintf(stderr, "tls_query_padding_blocksize "
|
||||||
|
"expected after -P\n");
|
||||||
|
return GETDNS_RETURN_GENERIC_ERROR;
|
||||||
|
}
|
||||||
|
padding_blocksize = strtol(argv[i], &endptr, 10);
|
||||||
|
if (*endptr || padding_blocksize < 0) {
|
||||||
|
fprintf(stderr, "non-negative "
|
||||||
|
"numeric padding blocksize expected "
|
||||||
|
"after -P\n");
|
||||||
|
return GETDNS_RETURN_GENERIC_ERROR;
|
||||||
|
}
|
||||||
|
if (getdns_context_set_tls_query_padding_blocksize(
|
||||||
|
context, padding_blocksize))
|
||||||
|
return GETDNS_RETURN_GENERIC_ERROR;
|
||||||
|
goto next;
|
||||||
case 'p':
|
case 'p':
|
||||||
json = 0;
|
json = 0;
|
||||||
case 'q':
|
case 'q':
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
|
DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
|
||||||
SERVER_IP="8.8.8.8"
|
SERVER_IP="8.8.8.8"
|
||||||
TLS_SERVER_IP="185.49.141.38~www.dnssec-name-and-shame.com"
|
TLS_SERVER_IP="185.49.141.38~getdnsapi.net"
|
||||||
GOOD_RESULT_SYNC="Status was: At least one response was returned"
|
GOOD_RESULT_SYNC="Status was: At least one response was returned"
|
||||||
GOOD_RESULT_ASYNC="successfull"
|
GOOD_RESULT_ASYNC="successfull"
|
||||||
BAD_RESULT_SYNC="1 'Generic error'"
|
BAD_RESULT_SYNC="1 'Generic error'"
|
||||||
|
@ -58,7 +58,7 @@ usage () {
|
||||||
echo " -p path to getdns_query binary"
|
echo " -p path to getdns_query binary"
|
||||||
echo " -s server configured for only TCP and UDP"
|
echo " -s server configured for only TCP and UDP"
|
||||||
echo " -t server configured for TLS, STARTTLS, TCP and UDP"
|
echo " -t server configured for TLS, STARTTLS, TCP and UDP"
|
||||||
echo " (This must include the hostname e.g. 185.49.141.38~www.dnssec-name-and-shame.com)"
|
echo " (This must include the hostname e.g. 185.49.141.38~getdnsapi.net)"
|
||||||
}
|
}
|
||||||
|
|
||||||
while getopts ":p:s:t:dh" opt; do
|
while getopts ":p:s:t:dh" opt; do
|
||||||
|
|
|
@ -226,17 +226,37 @@ typedef struct getdns_network_req
|
||||||
/* Network requests scheduled to write after me */
|
/* Network requests scheduled to write after me */
|
||||||
struct getdns_network_req *write_queue_tail;
|
struct getdns_network_req *write_queue_tail;
|
||||||
|
|
||||||
|
/* Some fields to record info for return_call_debugging */
|
||||||
|
uint64_t debug_start_time;
|
||||||
|
uint64_t debug_end_time;
|
||||||
|
size_t debug_tls_auth_status;
|
||||||
|
|
||||||
/* When more space is needed for the wire_data response than is
|
/* When more space is needed for the wire_data response than is
|
||||||
* available in wire_data[], it will be allocated seperately.
|
* available in wire_data[], it will be allocated seperately.
|
||||||
* response will then not point to wire_data anymore.
|
* response will then not point to wire_data anymore.
|
||||||
*/
|
*/
|
||||||
uint8_t *query;
|
uint8_t *query;
|
||||||
uint8_t *opt; /* offset of OPT RR in query */
|
uint8_t *opt; /* offset of OPT RR in query */
|
||||||
|
|
||||||
|
/* each network_req has a set of base options that are
|
||||||
|
* specific to the query, which are static and included when
|
||||||
|
* the network_req is created. When the query is sent out to
|
||||||
|
* a given upstream, some additional options are added that
|
||||||
|
* are specific to the upstream. There can be at most
|
||||||
|
* GETDNS_MAXIMUM_UPSTREAM_OPTION_SPACE bytes of
|
||||||
|
* upstream-specific options.
|
||||||
|
|
||||||
|
* use _getdns_network_req_clear_upstream_options() and
|
||||||
|
* _getdns_network_req_add_upstream_option() to fiddle with the
|
||||||
|
*/
|
||||||
|
size_t base_query_option_sz;
|
||||||
size_t response_len;
|
size_t response_len;
|
||||||
uint8_t *response;
|
uint8_t *response;
|
||||||
size_t wire_data_sz;
|
size_t wire_data_sz;
|
||||||
uint8_t wire_data[];
|
uint8_t wire_data[];
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} getdns_network_req;
|
} getdns_network_req;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -266,6 +286,9 @@ typedef struct getdns_dns_req {
|
||||||
int avoid_dnssec_roadblocks;
|
int avoid_dnssec_roadblocks;
|
||||||
#endif
|
#endif
|
||||||
int edns_cookies;
|
int edns_cookies;
|
||||||
|
int edns_client_subnet_private;
|
||||||
|
uint16_t tls_query_padding_blocksize;
|
||||||
|
int return_call_debugging;
|
||||||
|
|
||||||
/* Internally used by return_validation_chain */
|
/* Internally used by return_validation_chain */
|
||||||
int dnssec_ok_checking_disabled;
|
int dnssec_ok_checking_disabled;
|
||||||
|
@ -348,5 +371,10 @@ getdns_dns_req *_getdns_dns_req_new(getdns_context *context, getdns_eventloop *l
|
||||||
|
|
||||||
void _getdns_dns_req_free(getdns_dns_req * req);
|
void _getdns_dns_req_free(getdns_dns_req * req);
|
||||||
|
|
||||||
|
/* network request utils */
|
||||||
|
getdns_return_t _getdns_network_req_add_upstream_option(getdns_network_req * req,
|
||||||
|
uint16_t code, uint16_t sz, const void* data);
|
||||||
|
void _getdns_network_req_clear_upstream_options(getdns_network_req * req);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
/* types-internal.h */
|
/* types-internal.h */
|
||||||
|
|
|
@ -675,6 +675,69 @@ success:
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getdns_dict *
|
||||||
|
_getdns_create_call_debugging_dict(
|
||||||
|
getdns_context *context, getdns_network_req *netreq)
|
||||||
|
{
|
||||||
|
getdns_bindata qname;
|
||||||
|
getdns_dict *netreq_debug;
|
||||||
|
getdns_dict *address_debug = NULL;
|
||||||
|
|
||||||
|
assert(netreq);
|
||||||
|
|
||||||
|
/* It is the responsibility of the caller to free this */
|
||||||
|
if (!(netreq_debug = getdns_dict_create_with_context(context)))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
qname.data = netreq->owner->name;
|
||||||
|
qname.size = netreq->owner->name_len;
|
||||||
|
|
||||||
|
if (getdns_dict_set_bindata(netreq_debug, "query_name", &qname) ||
|
||||||
|
getdns_dict_set_int( netreq_debug, "query_type"
|
||||||
|
, netreq->request_type ) ||
|
||||||
|
|
||||||
|
/* Safe, because uint32_t facilitates RRT's of almost 50 days*/
|
||||||
|
getdns_dict_set_int(netreq_debug, "run_time/ms",
|
||||||
|
(uint32_t)(( netreq->debug_end_time
|
||||||
|
- netreq->debug_start_time)/1000))) {
|
||||||
|
|
||||||
|
getdns_dict_destroy(netreq_debug);
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
} else if (!netreq->upstream)
|
||||||
|
|
||||||
|
/* Nothing more for full recursion */
|
||||||
|
return netreq_debug;
|
||||||
|
|
||||||
|
|
||||||
|
/* Stub resolver debug data */
|
||||||
|
_getdns_sockaddr_to_dict(
|
||||||
|
context, &netreq->upstream->addr, &address_debug);
|
||||||
|
|
||||||
|
if (getdns_dict_set_dict(netreq_debug, "query_to", address_debug) ||
|
||||||
|
getdns_dict_set_int( netreq_debug, "transport"
|
||||||
|
, netreq->upstream->transport)) {
|
||||||
|
|
||||||
|
getdns_dict_destroy(address_debug);
|
||||||
|
getdns_dict_destroy(netreq_debug);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
getdns_dict_destroy(address_debug);
|
||||||
|
|
||||||
|
if (netreq->upstream->transport != GETDNS_TRANSPORT_TLS)
|
||||||
|
return netreq_debug;
|
||||||
|
|
||||||
|
/* Only include the auth status if TLS was used */
|
||||||
|
if (getdns_dict_util_set_string(netreq_debug, "tls_auth_status",
|
||||||
|
netreq->debug_tls_auth_status == 0 ?
|
||||||
|
"OK: Hostname matched valid cert":"FAILED: Server not validated")){
|
||||||
|
|
||||||
|
getdns_dict_destroy(netreq_debug);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return netreq_debug;
|
||||||
|
}
|
||||||
|
|
||||||
getdns_dict *
|
getdns_dict *
|
||||||
_getdns_create_getdns_response(getdns_dns_req *completed_request)
|
_getdns_create_getdns_response(getdns_dns_req *completed_request)
|
||||||
{
|
{
|
||||||
|
@ -682,12 +745,14 @@ _getdns_create_getdns_response(getdns_dns_req *completed_request)
|
||||||
getdns_list *just_addrs = NULL;
|
getdns_list *just_addrs = NULL;
|
||||||
getdns_list *replies_full;
|
getdns_list *replies_full;
|
||||||
getdns_list *replies_tree;
|
getdns_list *replies_tree;
|
||||||
|
getdns_list *call_debugging = NULL;
|
||||||
getdns_network_req *netreq, **netreq_p;
|
getdns_network_req *netreq, **netreq_p;
|
||||||
int rrsigs_in_answer = 0;
|
int rrsigs_in_answer = 0;
|
||||||
getdns_dict *reply;
|
getdns_dict *reply;
|
||||||
getdns_bindata *canonical_name = NULL;
|
getdns_bindata *canonical_name = NULL;
|
||||||
int nreplies = 0, nanswers = 0, nsecure = 0, ninsecure = 0, nbogus = 0;
|
int nreplies = 0, nanswers = 0, nsecure = 0, ninsecure = 0, nbogus = 0;
|
||||||
getdns_bindata full_data;
|
getdns_bindata full_data;
|
||||||
|
getdns_dict *netreq_debug;
|
||||||
|
|
||||||
/* info (bools) about dns_req */
|
/* info (bools) about dns_req */
|
||||||
int dnssec_return_status;
|
int dnssec_return_status;
|
||||||
|
@ -721,6 +786,10 @@ _getdns_create_getdns_response(getdns_dns_req *completed_request)
|
||||||
if (!(replies_tree = getdns_list_create_with_context(context)))
|
if (!(replies_tree = getdns_list_create_with_context(context)))
|
||||||
goto error_free_replies_full;
|
goto error_free_replies_full;
|
||||||
|
|
||||||
|
if (completed_request->return_call_debugging &&
|
||||||
|
!(call_debugging = getdns_list_create_with_context(context)))
|
||||||
|
goto error_free_replies_full;
|
||||||
|
|
||||||
for ( netreq_p = completed_request->netreqs
|
for ( netreq_p = completed_request->netreqs
|
||||||
; (netreq = *netreq_p) ; netreq_p++) {
|
; (netreq = *netreq_p) ; netreq_p++) {
|
||||||
|
|
||||||
|
@ -777,6 +846,21 @@ _getdns_create_getdns_response(getdns_dns_req *completed_request)
|
||||||
getdns_dict_destroy(reply);
|
getdns_dict_destroy(reply);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (call_debugging) {
|
||||||
|
if (!(netreq_debug =
|
||||||
|
_getdns_create_call_debugging_dict(context,netreq)))
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
if (_getdns_list_append_dict(
|
||||||
|
call_debugging, netreq_debug)) {
|
||||||
|
|
||||||
|
getdns_dict_destroy(netreq_debug);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
getdns_dict_destroy(netreq_debug);
|
||||||
|
}
|
||||||
|
|
||||||
getdns_dict_destroy(reply);
|
getdns_dict_destroy(reply);
|
||||||
|
|
||||||
/* buffer */
|
/* buffer */
|
||||||
|
@ -789,6 +873,10 @@ _getdns_create_getdns_response(getdns_dns_req *completed_request)
|
||||||
goto error;
|
goto error;
|
||||||
getdns_list_destroy(replies_tree);
|
getdns_list_destroy(replies_tree);
|
||||||
|
|
||||||
|
if (call_debugging &&
|
||||||
|
getdns_dict_set_list(result, "call_debugging", call_debugging))
|
||||||
|
goto error_free_call_debugging;
|
||||||
|
|
||||||
if (getdns_dict_set_list(result, "replies_full", replies_full))
|
if (getdns_dict_set_list(result, "replies_full", replies_full))
|
||||||
goto error_free_replies_full;
|
goto error_free_replies_full;
|
||||||
getdns_list_destroy(replies_full);
|
getdns_list_destroy(replies_full);
|
||||||
|
@ -812,6 +900,8 @@ _getdns_create_getdns_response(getdns_dns_req *completed_request)
|
||||||
error:
|
error:
|
||||||
/* cleanup */
|
/* cleanup */
|
||||||
getdns_list_destroy(replies_tree);
|
getdns_list_destroy(replies_tree);
|
||||||
|
error_free_call_debugging:
|
||||||
|
getdns_list_destroy(call_debugging);
|
||||||
error_free_replies_full:
|
error_free_replies_full:
|
||||||
getdns_list_destroy(replies_full);
|
getdns_list_destroy(replies_full);
|
||||||
error_free_result:
|
error_free_result:
|
||||||
|
|
Loading…
Reference in New Issue