Merge pull request #10 from wtoorop/devel/huitema-develop

Devel/huitema develop
This commit is contained in:
huitema 2017-03-23 07:45:53 -07:00 committed by GitHub
commit 0560500e34
21 changed files with 235 additions and 99 deletions

View File

@ -1,3 +1,20 @@
* 2017-04-??: Version 1.1.0
* More fine grained control over TLS upstream retry and back off
behaviour with getdns_context_set_tls_backoff_time() and
getdns_context_set_tls_connection_retries().
* New round robin over the available upstreams feaure.
Enable with getdns_context_set_round_robin_upstreams()
* Bugfix: Queue requests when no sockets available for outgoing queries.
* Obey the outstanding query limit with STUB resolution mode too.
* Updated stubby config file
* Draft MDNS client implementation by Christian Huitema.
Enable with --enable-draft-mdns-support to configure
* bugfix: Let synchronous queries use fds > MAX_FDSETSIZE;
By moving default eventloop from select to poll
Thanks Neil Cook
* bugfix: authentication failure for self signed cert + only pinset
* bugfix: issue with session re-use making authentication appear to fail
* 2017-01-13: Version 1.0.0 * 2017-01-13: Version 1.0.0
* edns0_cookies extension enabled by default (per RFC7873) * edns0_cookies extension enabled by default (per RFC7873)
* dnssec_roadblock_avoidance enabled by default (per RFC8027) * dnssec_roadblock_avoidance enabled by default (per RFC8027)

View File

@ -66,7 +66,6 @@ install: all getdns.pc getdns_ext_event.pc @INSTALL_GETDNS_QUERY@ @INSTALL_STUBB
$(INSTALL) -m 644 getdns_ext_event.pc $(DESTDIR)$(libdir)/pkgconfig $(INSTALL) -m 644 getdns_ext_event.pc $(DESTDIR)$(libdir)/pkgconfig
$(INSTALL) -m 755 -d $(DESTDIR)$(docdir)/spec $(INSTALL) -m 755 -d $(DESTDIR)$(docdir)/spec
$(INSTALL) -m 644 $(srcdir)/spec/index.html $(DESTDIR)$(docdir)/spec $(INSTALL) -m 644 $(srcdir)/spec/index.html $(DESTDIR)$(docdir)/spec
$(INSTALL) -m 644 $(srcdir)/spec/getdns*tgz $(DESTDIR)$(docdir)/spec || true
cd src && $(MAKE) $@ cd src && $(MAKE) $@
cd doc && $(MAKE) $@ cd doc && $(MAKE) $@
@echo "***" @echo "***"
@ -232,12 +231,13 @@ $(distdir):
cp $(srcdir)/src/test/*.good $(distdir)/src/test cp $(srcdir)/src/test/*.good $(distdir)/src/test
cp $(srcdir)/src/compat/*.[ch] $(distdir)/src/compat cp $(srcdir)/src/compat/*.[ch] $(distdir)/src/compat
cp $(srcdir)/src/util/*.[ch] $(distdir)/src/util cp $(srcdir)/src/util/*.[ch] $(distdir)/src/util
cp -r $(srcdir)/src/util/orig-headers $(distdir)/src/util
cp -r $(srcdir)/src/util/auxiliary $(distdir)/src/util
cp $(srcdir)/src/gldns/*.[ch] $(distdir)/src/gldns cp $(srcdir)/src/gldns/*.[ch] $(distdir)/src/gldns
cp $(srcdir)/doc/Makefile.in $(distdir)/doc cp $(srcdir)/doc/Makefile.in $(distdir)/doc
cp $(srcdir)/doc/*.in $(distdir)/doc cp $(srcdir)/doc/*.in $(distdir)/doc
cp $(srcdir)/doc/manpgaltnames $(distdir)/doc cp $(srcdir)/doc/manpgaltnames $(distdir)/doc
cp $(srcdir)/spec/*.html $(distdir)/spec cp $(srcdir)/spec/*.html $(distdir)/spec
cp $(srcdir)/spec/*.tgz $(distdir)/spec || true
cp $(srcdir)/spec/example/Makefile.in $(distdir)/spec/example cp $(srcdir)/spec/example/Makefile.in $(distdir)/spec/example
cp $(srcdir)/spec/example/*.[ch] $(distdir)/spec/example cp $(srcdir)/spec/example/*.[ch] $(distdir)/spec/example
cp $(srcdir)/src/tools/Makefile.in $(distdir)/src/tools cp $(srcdir)/src/tools/Makefile.in $(distdir)/src/tools

View File

@ -19,7 +19,7 @@ Traditional access to DNS data from applications has several limitations:
* Sophisticated uses of the DNS (things like IDNA and DNSSEC validation) require considerable application work, possibly by application developers with little experience with the vagaries of DNS. * Sophisticated uses of the DNS (things like IDNA and DNSSEC validation) require considerable application work, possibly by application developers with little experience with the vagaries of DNS.
getdns also provides a experimental DNS Privacy enabled client called 'stubby' - see below for more details. getdns also provides an experimental DNS Privacy enabled client called 'stubby' - see below for more details.
## Motivation for providing the API ## Motivation for providing the API
@ -78,7 +78,7 @@ before building.
As well as building the getdns library 2 other tools are installed by default by the above process: As well as building the getdns library 2 other tools are installed by default by the above process:
* getdns_query: a command line test script wrapper for getdns * getdns_query: a command line test script wrapper for getdns
* stubby: a experimental DNS Privacy enabled client * stubby: an experimental DNS Privacy enabled client
Note: If you only want to build stubby, then use the `--enable-stub-only` and `--without-libidn` options when running 'configure'. Note: If you only want to build stubby, then use the `--enable-stub-only` and `--without-libidn` options when running 'configure'.
@ -197,18 +197,7 @@ Stub mode does not support:
# Known Issues # Known Issues
* The synchronous lookup functions will not work when new file descriptors * None
needed for the lookup will be larger than `FD_SETSIZE`. This is because
the synchronous functions use a "default" event loop under the hood
which is based on `select()` and thus inherits the limits that `select()` has.
If you need only slightly more file descriptors, it is possible to enlarge
the `FD_SETSIZE` with the `--with-fd-setsize=`*`size`* flag to `configure`.
To resolve, use the asynchronous functions with an event loop extension for
libevent, libev or libuv. Note that the asynchronous functions will have
the same problem when used in combination with `getdns_context_run()`, which
also uses the default event loop.
# Supported Platforms # Supported Platforms
@ -342,8 +331,10 @@ Contributors
* Neel Goyal, Verisign, Inc. * Neel Goyal, Verisign, Inc.
* Bryan Graham, Verisign, Inc. * Bryan Graham, Verisign, Inc.
* Robert Groenenberg * Robert Groenenberg
* Jim Hague, Sinodun
* Paul Hoffman * Paul Hoffman
* Scott Hollenbeck, Verising, Inc. * Scott Hollenbeck, Verising, Inc.
* Christian Huitema
* Shumon Huque, Verisign Labs * Shumon Huque, Verisign Labs
* Jelte Janssen * Jelte Janssen
* Guillem Jover * Guillem Jover
@ -358,6 +349,7 @@ Contributors
* Joel Purra * Joel Purra
* Tom Pusateri * Tom Pusateri
* Prithvi Ranganath, Verisign, Inc. * Prithvi Ranganath, Verisign, Inc.
* Hoda Rohani, NLnet Labs
* Rushi Shah, Verisign, Inc. * Rushi Shah, Verisign, Inc.
* Vinay Soni, Verisign, Inc. * Vinay Soni, Verisign, Inc.
* Melinda Shore, No Mountain Software LLC * Melinda Shore, No Mountain Software LLC

View File

@ -37,7 +37,7 @@ sinclude(./m4/ax_check_compile_flag.m4)
sinclude(./m4/pkg.m4) sinclude(./m4/pkg.m4)
AC_INIT([getdns], [1.1.0], [users@getdnsapi.net], [], [https://getdnsapi.net]) AC_INIT([getdns], [1.1.0], [users@getdnsapi.net], [], [https://getdnsapi.net])
AC_SUBST(RELEASE_CANDIDATE, [-alpha3]) AC_SUBST(RELEASE_CANDIDATE, [-rc1])
# Set current date from system if not set # Set current date from system if not set
AC_ARG_WITH([current-date], AC_ARG_WITH([current-date],
@ -47,7 +47,7 @@ AC_ARG_WITH([current-date],
[CURRENT_DATE="`date -u +%Y-%m-%dT%H:%M:%SZ`"]) [CURRENT_DATE="`date -u +%Y-%m-%dT%H:%M:%SZ`"])
AC_SUBST(GETDNS_VERSION, ["AC_PACKAGE_VERSION$RELEASE_CANDIDATE"]) AC_SUBST(GETDNS_VERSION, ["AC_PACKAGE_VERSION$RELEASE_CANDIDATE"])
AC_SUBST(GETDNS_NUMERIC_VERSION, [0x0100A300]) AC_SUBST(GETDNS_NUMERIC_VERSION, [0x0100C100])
AC_SUBST(API_VERSION, ["December 2015"]) AC_SUBST(API_VERSION, ["December 2015"])
AC_SUBST(API_NUMERIC_VERSION, [0x07df0c00]) AC_SUBST(API_NUMERIC_VERSION, [0x07df0c00])
GETDNS_COMPILATION_COMMENT="AC_PACKAGE_NAME $GETDNS_VERSION configured on $CURRENT_DATE for the $API_VERSION version of the API" GETDNS_COMPILATION_COMMENT="AC_PACKAGE_NAME $GETDNS_VERSION configured on $CURRENT_DATE for the $API_VERSION version of the API"

View File

@ -77,6 +77,7 @@ uninstall:
clean: clean:
for x in $(MANPAGES3); do rm -f $$($(srcdir)/manpgaltnames $$x); done for x in $(MANPAGES3); do rm -f $$($(srcdir)/manpgaltnames $$x); done
rm -f tagfile
rm -rf $(DOCDIRS) $(MANPAGES3) rm -rf $(DOCDIRS) $(MANPAGES3)
distclean : clean distclean : clean

View File

@ -1657,7 +1657,7 @@ TAGFILES =
# When a file name is specified after GENERATE_TAGFILE, doxygen will create # When a file name is specified after GENERATE_TAGFILE, doxygen will create
# a tag file that is based on the input files it reads. # a tag file that is based on the input files it reads.
GENERATE_TAGFILE = GENERATE_TAGFILE = ../doc/tagfile
# If the ALLEXTERNALS tag is set to YES all external classes will be listed # If the ALLEXTERNALS tag is set to YES all external classes will be listed
# in the class index. If set to NO only the inherited external classes # in the class index. If set to NO only the inherited external classes

View File

@ -756,7 +756,7 @@ _getdns_upstream_shutdown(getdns_upstream *upstream)
uint16_t conn_retries = upstream->upstreams->tls_connection_retries; uint16_t conn_retries = upstream->upstreams->tls_connection_retries;
/* [TLS1]TODO: This arbitrary logic at the moment - review and improve!*/ /* [TLS1]TODO: This arbitrary logic at the moment - review and improve!*/
if (upstream->conn_setup_failed >= conn_retries if (upstream->conn_setup_failed >= conn_retries
|| (upstream->conn_shutdowns >= conn_retries*((unsigned)GETDNS_TRANSPORT_FAIL_MULT) || ((int)upstream->conn_shutdowns >= conn_retries*GETDNS_TRANSPORT_FAIL_MULT
&& upstream->total_responses == 0) && upstream->total_responses == 0)
|| (upstream->conn_completed >= conn_retries && || (upstream->conn_completed >= conn_retries &&
upstream->total_responses == 0 && upstream->total_responses == 0 &&
@ -938,7 +938,7 @@ upstream_init(getdns_upstream *upstream,
upstream->keepalive_shutdown = 0; upstream->keepalive_shutdown = 0;
upstream->keepalive_timeout = 0; upstream->keepalive_timeout = 0;
/* How is this upstream doing on UDP? */ /* How is this upstream doing on UDP? */
upstream->to_retry = 2; upstream->to_retry = 1;
upstream->back_off = 1; upstream->back_off = 1;
upstream->udp_responses = 0; upstream->udp_responses = 0;
upstream->udp_timeouts = 0; upstream->udp_timeouts = 0;
@ -3572,9 +3572,9 @@ _get_context_settings(getdns_context* context)
/* the timeouts are stored as uint64, but the value maximum used in /* the timeouts are stored as uint64, but the value maximum used in
practice is 6553500ms, so we just trim the value to be on the safe side. */ practice is 6553500ms, so we just trim the value to be on the safe side. */
if ( getdns_dict_set_int(result, "timeout", if ( getdns_dict_set_int(result, "timeout",
(context->timeout > 0xFFFFFFFFull)? 0xFFFFFFFF: (uint32_t) context->timeout) (context->timeout > 0xFFFFFFFFull) ? 0xFFFFFFFF: (uint32_t) context->timeout)
|| getdns_dict_set_int(result, "idle_timeout", || getdns_dict_set_int(result, "idle_timeout",
(context->idle_timeout > 0xFFFFFFFFull) ? 0xFFFFFFFF : (uint32_t) context->idle_timeout) (context->idle_timeout > 0xFFFFFFFFull) ? 0xFFFFFFFF : (uint32_t) context->idle_timeout)
|| getdns_dict_set_int(result, "limit_outstanding_queries", || getdns_dict_set_int(result, "limit_outstanding_queries",
context->limit_outstanding_queries) context->limit_outstanding_queries)
|| getdns_dict_set_int(result, "dnssec_allowed_skew", || getdns_dict_set_int(result, "dnssec_allowed_skew",

View File

@ -131,9 +131,32 @@ typedef struct getdns_upstream {
char addr_str[INET6_ADDRSTRLEN]; char addr_str[INET6_ADDRSTRLEN];
#endif #endif
/* How is this upstream doing over UDP? */ /**
int to_retry; * How is this upstream doing over UDP?
int back_off; *
* to_retry = 1, back_off = 1, in context.c:upstream_init()
*
* When querying over UDP, first a upstream is selected which to_retry
* value > 0 in stub.c:upstream_select().
*
* Every time a udp request times out, to_retry is decreased, and if
* it reaches 0, it is set to minus back_off in
* stub.c:stub_next_upstream().
*
* to_retry will become > 0 again. because each time an upstream is
* selected for a UDP query in stub.c:upstream_select(), all to_retry
* counters <= 0 are incremented.
*
* On continuous failure, the stubs are less likely to be reselected,
* because each time to_retry is set to minus back_off, in
* stub.c:stub_next_upstream(), the back_off value is doubled.
*
* Finally, if all upstreams are failing, the upstreams with the
* smallest back_off value will be selected, and the back_off value
* decremented by one.
*/
int to_retry; /* (initialized to 1) */
int back_off; /* (initialized to 1) */
size_t udp_responses; size_t udp_responses;
size_t udp_timeouts; size_t udp_timeouts;

View File

@ -305,9 +305,14 @@ _getdns_netreq_change_state(
uint64_t now_ms; uint64_t now_ms;
getdns_network_req *prev; getdns_network_req *prev;
if (!netreq || !netreq->owner->is_dns_request) if (!netreq)
return; return;
if (!netreq->owner->is_dns_request) {
netreq->state = new_state;
return;
}
context = netreq->owner->context; context = netreq->owner->context;
if (netreq->state != NET_REQ_IN_FLIGHT) { if (netreq->state != NET_REQ_IN_FLIGHT) {
@ -585,12 +590,11 @@ getdns_general_ns(getdns_context *context, getdns_eventloop *loop,
/* Check whether the name belongs in the MDNS space */ /* Check whether the name belongs in the MDNS space */
if (!(r = _getdns_mdns_namespace_check(req))) if (!(r = _getdns_mdns_namespace_check(req)))
{ {
req->is_dns_request = 1; req->is_dns_request = 0;
// Submit the query to the MDNS transport. // Submit the query to the MDNS transport.
for (netreq_p = req->netreqs for (netreq_p = req->netreqs
; !r && (netreq = *netreq_p) ; !r && (netreq = *netreq_p)
; netreq_p++) { ; netreq_p++) {
netreq->owner = req;
if ((r = _getdns_submit_mdns_request(netreq))) { if ((r = _getdns_submit_mdns_request(netreq))) {
if (r == DNS_REQ_FINISHED) { if (r == DNS_REQ_FINISHED) {
if (return_netreq_p) if (return_netreq_p)

View File

@ -77,11 +77,11 @@ extern "C" {
#define GETDNS_CONTEXT_CODE_PUBKEY_PINSET 621 #define GETDNS_CONTEXT_CODE_PUBKEY_PINSET 621
#define GETDNS_CONTEXT_CODE_PUBKEY_PINSET_TEXT "Change related to getdns_context_set_pubkey_pinset" #define GETDNS_CONTEXT_CODE_PUBKEY_PINSET_TEXT "Change related to getdns_context_set_pubkey_pinset"
#define GETDNS_CONTEXT_CODE_ROUND_ROBIN_UPSTREAMS 622 #define GETDNS_CONTEXT_CODE_ROUND_ROBIN_UPSTREAMS 622
#define GETDNS_CONTEXT_CODE_ROUND_ROBIN_UPSTREAMS_TEXT "Change related to getdns_context_set_pubkey_pinset" #define GETDNS_CONTEXT_CODE_ROUND_ROBIN_UPSTREAMS_TEXT "Change related to getdns_context_set_round_robin_upstreams"
#define GETDNS_CONTEXT_CODE_TLS_BACKOFF_TIME 623 #define GETDNS_CONTEXT_CODE_TLS_BACKOFF_TIME 623
#define GETDNS_CONTEXT_CODE_TLS_BACKOFF_TIME_TEXT "Change related to getdns_context_set_pubkey_pinset" #define GETDNS_CONTEXT_CODE_TLS_BACKOFF_TIME_TEXT "Change related to getdns_context_set_tls_backoff_time"
#define GETDNS_CONTEXT_CODE_TLS_CONNECTION_RETRIES 624 #define GETDNS_CONTEXT_CODE_TLS_CONNECTION_RETRIES 624
#define GETDNS_CONTEXT_CODE_TLS_CONNECTION_RETRIES_TEXT "Change related to getdns_context_set_pubkey_pinset" #define GETDNS_CONTEXT_CODE_TLS_CONNECTION_RETRIES_TEXT "Change related to getdns_context_set_tls_connection_retries"
/** @} /** @}
*/ */
@ -126,7 +126,6 @@ typedef enum getdns_tls_authentication_t {
/** @} /** @}
*/ */
/** /**
* \defgroup Uvaluesandtextsdepricated Additional transport values and texts (will be deprecated) * \defgroup Uvaluesandtextsdepricated Additional transport values and texts (will be deprecated)
* @{ * @{
@ -227,15 +226,6 @@ getdns_context_run(getdns_context *context);
*/ */
/**
* \defgroup contextfunction Additional getdns_context async functions
* @{
*/
/* process async reqs */
getdns_return_t getdns_context_process_async(getdns_context* context);
/** @}
*/
/** /**
* \defgroup Ucontextset Additional getdns_context_set functions * \defgroup Ucontextset Additional getdns_context_set functions
* @{ * @{
@ -400,9 +390,6 @@ getdns_return_t
getdns_context_get_update_callback(getdns_context *context, void **userarg, getdns_context_get_update_callback(getdns_context *context, void **userarg,
void (**value) (getdns_context *, getdns_context_code_t, void *)); void (**value) (getdns_context *, getdns_context_code_t, void *));
/* Async support */
uint32_t getdns_context_get_num_pending_requests(getdns_context* context,
struct timeval* next_timeout);
/** @} /** @}
*/ */
@ -435,6 +422,8 @@ getdns_return_t getdns_dict_util_set_string(getdns_dict * dict,
getdns_return_t getdns_dict_util_get_string(getdns_dict * dict, getdns_return_t getdns_dict_util_get_string(getdns_dict * dict,
char *name, char **result); char *name, char **result);
/** /**
* Validate replies or resource records. * Validate replies or resource records.
* *
@ -521,6 +510,51 @@ getdns_return_t getdns_pubkey_pinset_sanity_check(
const getdns_list* pinset, const getdns_list* pinset,
getdns_list* errorlist); getdns_list* errorlist);
/**
* Configure a context with settings given in a getdns_dict.
*
* @param context The context to be configured.
* @param config_dict The getdns_dict containing the settings.
* The settings have the same name as returned by the
* getdns_context_get_api_information() function, or as
* used in the names of the getdns_context_get_*() and
* getdns_context_set_*() functions.
* - The dict returned by
* getdns_context_get_api_information() can be used
* as the config_dict directly, but context settings
* do *not* have to be below a `"all_context"` key.
* - It is possible to set default values for extensions
* that could otherwise only be given on a per query
* basis. For example:
* `{ dnssec_return_status: GETDNS_EXTENSION_TRUE }` is
* equivalent to using the
* getdns_context_set_return_dnssec_status() function
* with that value, but default values for the other
* extensions can be set by this method now too.
* For example
* `{ return_call_reporting: GETDNS_EXTENSION_TRUE}`
* - Trust anchor files and root hints content can also be
* given by file, for example:
*
* { dns_root_servers : "named.root"
* , dnssec_trust_anchors: "/etc/unbound/getdns-root.key"
* }
* @return GETDNS_RETURN_GOOD on success or an error code on failure.
* **Beware** that context might be partially configured on error. For retry
* strategies it is advised to recreate a new config.
*/
getdns_return_t
getdns_context_config(getdns_context *context, const getdns_dict *config_dict);
/** @}
*/
/**
* \defgroup UXTRAPrettyPrinting Pretty printing of getdns dicts and lists
* @{
*/
/** /**
* Pretty print the getdns_dict in a given buffer snprintf style. * Pretty print the getdns_dict in a given buffer snprintf style.
@ -617,6 +651,14 @@ getdns_snprint_json_list(
char *str, size_t size, const getdns_list *list, int pretty); char *str, size_t size, const getdns_list *list, int pretty);
/** @}
*/
/**
* \defgroup UDNSDataConversionFunctions Functions for converting between getdns DNS dicts, DNS wire format and DNS presentation format
* @{
*/
/** /**
* Convert rr_dict to wireformat representation of the resource record. * Convert rr_dict to wireformat representation of the resource record.
* *
@ -930,6 +972,14 @@ getdns_return_t
getdns_msg_dict2str_scan( getdns_msg_dict2str_scan(
const getdns_dict *msg_dict, char **str, int *str_len); const getdns_dict *msg_dict, char **str, int *str_len);
/** @}
*/
/**
* \defgroup Ustring2getdns_data Functions for converting strings to getdns data structures
* @{
*/
/** /**
* Convert string text to a getdns_dict. * Convert string text to a getdns_dict.
* *
@ -977,7 +1027,8 @@ getdns_str2list(const char *str, getdns_list **list);
* - bindata representation of IP or IPv6 addresses may be * - bindata representation of IP or IPv6 addresses may be
* given in their presentation format. For example: * given in their presentation format. For example:
* `{ dns_root_servers: [ 2001:7fd::1, 193.0.14.129 ] }` * `{ dns_root_servers: [ 2001:7fd::1, 193.0.14.129 ] }`
* - Arbitrary binary data may be given with a `0x` prefix. * - Arbitrary binary data may be given with a `0x` prefix,
* or in base64 encoding.
* For example: * For example:
* *
* { add_opt_parameters: * { add_opt_parameters:
@ -994,7 +1045,7 @@ getdns_str2list(const char *str, getdns_list **list);
* [ { address_data : 2a04:b900:0:100::37 * [ { address_data : 2a04:b900:0:100::37
* , tsig_name : hmac-md5.tsigs.getdnsapi.net. * , tsig_name : hmac-md5.tsigs.getdnsapi.net.
* , tsig_algorithm: hmac-md5.sig-alg.reg.int. * , tsig_algorithm: hmac-md5.sig-alg.reg.int.
* , tsig_secret : 0xD7A1BAF4E4DE5D6EB149 * , tsig_secret : 16G69OTeXW6xSQ==
* } ] * } ]
* } * }
* *
@ -1018,42 +1069,13 @@ getdns_str2bindata(const char *str, getdns_bindata **bindata);
getdns_return_t getdns_return_t
getdns_str2int(const char *str, uint32_t *value); getdns_str2int(const char *str, uint32_t *value);
/** /** @}
* Configure a context with settings given in a getdns_dict.
*
* @param context The context to be configured.
* @param config_dict The getdns_dict containing the settings.
* The settings have the same name as returned by the
* getdns_context_get_api_information() function, or as
* used in the names of the getdns_context_get_*() and
* getdns_context_set_*() functions.
* - The dict returned by
* getdns_context_get_api_information() can be used
* as the config_dict directly, but context settings
* do *not* have to be below a `"all_context"` key.
* - It is possible to set default values for extensions
* that could otherwise only be given on a per query
* basis. For example:
* `{ dnssec_return_status: GETDNS_EXTENSION_TRUE }` is
* equivalent to using the
* getdns_context_set_return_dnssec_status() function
* with that value, but default values for the other
* extensions can be set by this method now too.
* For example
* `{ return_call_reporting: GETDNS_EXTENSION_TRUE}`
* - Trust anchor files and root hints content can also be
* given by file, for example:
*
* { dns_root_servers : "named.root"
* , dnssec_trust_anchors: "/etc/unbound/getdns-root.key"
* }
* @return GETDNS_RETURN_GOOD on success or an error code on failure.
* **Beware** that context might be partially configured on error. For retry
* strategies it is advised to recreate a new config.
*/ */
getdns_return_t
getdns_context_config(getdns_context *context, const getdns_dict *config_dict);
/**
* \defgroup UServerFunctions Functions for creating simple DNS servers
* @{
*/
/** /**
* The user defined request handler that will be called on incoming requests. * The user defined request handler that will be called on incoming requests.
@ -1133,6 +1155,13 @@ getdns_reply(getdns_context *context,
* Please use getdns_get_errorstr_by_id instead of getdns_strerror. * Please use getdns_get_errorstr_by_id instead of getdns_strerror.
*/ */
getdns_return_t getdns_strerror(getdns_return_t err, char *buf, size_t buflen); getdns_return_t getdns_strerror(getdns_return_t err, char *buf, size_t buflen);
getdns_return_t getdns_context_process_async(getdns_context* context);
/* Async support */
uint32_t getdns_context_get_num_pending_requests(getdns_context* context,
struct timeval* next_timeout);
/** @} /** @}
*/ */
/** @} /** @}

View File

@ -48,6 +48,11 @@ typedef u_short sa_family_t;
#define TRUE 1 #define TRUE 1
#endif #endif
/* Define IPV6_ADD_MEMBERSHIP for FreeBSD and Mac OS X */
#ifndef IPV6_ADD_MEMBERSHIP
#define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP
#endif
uint64_t _getdns_get_time_as_uintt64(); uint64_t _getdns_get_time_as_uintt64();
#include "util/fptr_wlist.h" #include "util/fptr_wlist.h"
@ -1584,7 +1589,7 @@ static getdns_return_t mdns_initialize_continuous_request(getdns_network_req *ne
{ {
GETDNS_CLEAR_EVENT(dnsreq->loop, &netreq->event); GETDNS_CLEAR_EVENT(dnsreq->loop, &netreq->event);
GETDNS_SCHEDULE_EVENT( GETDNS_SCHEDULE_EVENT(
dnsreq->loop, -1, dnsreq->context->timeout*1000, dnsreq->loop, -1, _getdns_ms_until_expiry(dnsreq->expires),
getdns_eventloop_event_init(&netreq->event, netreq, getdns_eventloop_event_init(&netreq->event, netreq,
NULL, NULL, mdns_mcast_timeout_cb)); NULL, NULL, mdns_mcast_timeout_cb));
} }
@ -1813,7 +1818,8 @@ mdns_udp_write_cb(void *userarg)
return; return;
} }
GETDNS_SCHEDULE_EVENT( GETDNS_SCHEDULE_EVENT(
dnsreq->loop, netreq->fd, dnsreq->context->timeout*1000, dnsreq->loop, netreq->fd,
_getdns_ms_until_expiry(dnsreq->expires),
getdns_eventloop_event_init(&netreq->event, netreq, getdns_eventloop_event_init(&netreq->event, netreq,
mdns_udp_read_cb, NULL, mdns_timeout_cb)); mdns_udp_read_cb, NULL, mdns_timeout_cb));
} }
@ -1866,7 +1872,8 @@ _getdns_submit_mdns_request(getdns_network_req *netreq)
netreq->fd = fd; netreq->fd = fd;
GETDNS_CLEAR_EVENT(dnsreq->loop, &netreq->event); GETDNS_CLEAR_EVENT(dnsreq->loop, &netreq->event);
GETDNS_SCHEDULE_EVENT( GETDNS_SCHEDULE_EVENT(
dnsreq->loop, netreq->fd, dnsreq->context->timeout, dnsreq->loop, netreq->fd,
_getdns_ms_until_expiry(dnsreq->expires),
getdns_eventloop_event_init(&netreq->event, netreq, getdns_eventloop_event_init(&netreq->event, netreq,
NULL, mdns_udp_write_cb, mdns_timeout_cb)); NULL, mdns_udp_write_cb, mdns_timeout_cb));
ret = GETDNS_RETURN_GOOD; ret = GETDNS_RETURN_GOOD;

View File

@ -382,7 +382,7 @@ _getdns_verify_pinset_match(const sha256_pin_t *pinset,
X509_STORE_CTX *store) X509_STORE_CTX *store)
{ {
getdns_return_t ret = GETDNS_RETURN_GENERIC_ERROR; getdns_return_t ret = GETDNS_RETURN_GENERIC_ERROR;
X509 *x, *prev; X509 *x, *prev = NULL;
int i, len; int i, len;
unsigned char raw[4096]; unsigned char raw[4096];
unsigned char *next; unsigned char *next;

View File

@ -32,6 +32,13 @@
*/ */
#include "config.h" #include "config.h"
#ifdef USE_POLL_DEFAULT_EVENTLOOP
# ifdef HAVE_SYS_POLL_H
# include <sys/poll.h>
# else
# include <poll.h>
# endif
#endif
#include "debug.h" #include "debug.h"
#include <openssl/err.h> #include <openssl/err.h>
#include <openssl/conf.h> #include <openssl/conf.h>
@ -593,10 +600,10 @@ stub_timeout_cb(void *userarg)
#endif #endif
netreq->upstream->udp_timeouts++; netreq->upstream->udp_timeouts++;
#if defined(DAEMON_DEBUG) && DAEMON_DEBUG #if defined(DAEMON_DEBUG) && DAEMON_DEBUG
if (netreq->upstream->udp_timeouts % 100 == 0) if (netreq->upstream->udp_timeouts % 100 == 0)
DEBUG_DAEMON("%s %-40s : Upstream stats: Transport=UDP - Resp=%d,Timeouts=%d\n", DEBUG_DAEMON("%s %-40s : Upstream stats: Transport=UDP - Resp=%d,Timeouts=%d\n",
STUB_DEBUG_DAEMON, netreq->upstream->addr_str, STUB_DEBUG_DAEMON, netreq->upstream->addr_str,
(int)netreq->upstream->udp_responses, (int)netreq->upstream->udp_timeouts); (int)netreq->upstream->udp_responses, (int)netreq->upstream->udp_timeouts);
#endif #endif
stub_next_upstream(netreq); stub_next_upstream(netreq);
} else { } else {
@ -626,7 +633,15 @@ upstream_idle_timeout_cb(void *userarg)
static void static void
upstream_setup_timeout_cb(void *userarg) upstream_setup_timeout_cb(void *userarg)
{ {
int ret;
getdns_upstream *upstream = (getdns_upstream *)userarg; getdns_upstream *upstream = (getdns_upstream *)userarg;
#ifdef USE_POLL_DEFAULT_EVENTLOOP
struct pollfd fds;
#else
fd_set fds;
struct timeval tval;
#endif
DEBUG_STUB("%s %-35s: FD: %d\n", DEBUG_STUB("%s %-35s: FD: %d\n",
STUB_DEBUG_CLEANUP, __FUNC__, upstream->fd); STUB_DEBUG_CLEANUP, __FUNC__, upstream->fd);
/* Clean up and trigger a write to let the fallback code to its job */ /* Clean up and trigger a write to let the fallback code to its job */
@ -636,14 +651,17 @@ upstream_setup_timeout_cb(void *userarg)
* TCP SYN and doesn't do a reset (as is the case with e.g. 8.8.8.8@853). * TCP SYN and doesn't do a reset (as is the case with e.g. 8.8.8.8@853).
* For that case the socket never becomes writable so doesn't trigger any * For that case the socket never becomes writable so doesn't trigger any
* callbacks. If so then clear out the queue in one go.*/ * callbacks. If so then clear out the queue in one go.*/
int ret; #ifdef USE_POLL_DEFAULT_EVENTLOOP
fd_set fds; fds.fd = upstream->fd;
fds.events = POLLOUT;
ret = poll(&fds, 1, 0);
#else
FD_ZERO(&fds); FD_ZERO(&fds);
FD_SET(FD_SET_T upstream->fd, &fds); FD_SET((int)(upstream->fd), &fds);
struct timeval tval;
tval.tv_sec = 0; tval.tv_sec = 0;
tval.tv_usec = 0; tval.tv_usec = 0;
ret = select(upstream->fd+1, NULL, &fds, NULL, &tval); ret = select(upstream->fd+1, NULL, &fds, NULL, &tval);
#endif
if (ret == 0) { if (ret == 0) {
DEBUG_STUB("%s %-35s: FD: %d Cleaning up dangling queue\n", DEBUG_STUB("%s %-35s: FD: %d Cleaning up dangling queue\n",
STUB_DEBUG_CLEANUP, __FUNC__, upstream->fd); STUB_DEBUG_CLEANUP, __FUNC__, upstream->fd);
@ -1311,6 +1329,7 @@ _getdns_get_time_as_uintt64() {
/* UDP callback functions */ /* UDP callback functions */
/**************************/ /**************************/
static void static void
stub_udp_read_cb(void *userarg) stub_udp_read_cb(void *userarg)
{ {
@ -1330,8 +1349,28 @@ stub_udp_read_cb(void *userarg)
*/ */
0, NULL, NULL); 0, NULL, NULL);
if (read == -1 && _getdns_EWOULDBLOCK) if (read == -1 && _getdns_EWOULDBLOCK)
return; return; /* Try again later */
if (read == -1) {
DEBUG_STUB("%s %-35s: MSG: %p error while reading from socket:"
" %s\n", STUB_DEBUG_READ, __FUNC__, (void*)netreq
, strerror(errno));
stub_cleanup(netreq);
_getdns_netreq_change_state(netreq, NET_REQ_ERRORED);
/* Handle upstream*/
if (netreq->fd >= 0) {
#ifdef USE_WINSOCK
closesocket(netreq->fd);
#else
close(netreq->fd);
#endif
stub_next_upstream(netreq);
}
netreq->debug_end_time = _getdns_get_time_as_uintt64();
_getdns_check_dns_req_complete(netreq->owner);
return;
}
if (read < GLDNS_HEADER_SIZE) if (read < GLDNS_HEADER_SIZE)
return; /* Not DNS */ return; /* Not DNS */
@ -1853,9 +1892,10 @@ upstream_select(getdns_network_req *netreq)
upstream->back_off) upstream->back_off)
upstream = &upstreams->upstreams[i]; upstream = &upstreams->upstreams[i];
upstream->back_off++; if (upstream->back_off > 1)
upstream->back_off--;
upstream->to_retry = 1; upstream->to_retry = 1;
upstreams->current_udp = (upstream - upstreams->upstreams) / GETDNS_UPSTREAM_TRANSPORTS; upstreams->current_udp = upstream - upstreams->upstreams;
return upstream; return upstream;
} }

View File

@ -30,7 +30,10 @@
#include <string.h> #include <string.h>
#include <inttypes.h> #include <inttypes.h>
#include <unistd.h> #include <unistd.h>
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments"
#include <check.h> #include <check.h>
#pragma clang diagnostic pop
#include "getdns/getdns.h" #include "getdns/getdns.h"
#include "check_getdns_common.h" #include "check_getdns_common.h"
#include "check_getdns_address.h" #include "check_getdns_address.h"

View File

@ -29,7 +29,10 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <inttypes.h> #include <inttypes.h>
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments"
#include <check.h> #include <check.h>
#pragma clang diagnostic pop
#include "getdns/getdns.h" #include "getdns/getdns.h"
#include "config.h" #include "config.h"
#include "check_getdns_common.h" #include "check_getdns_common.h"

View File

@ -27,7 +27,10 @@
#ifndef _check_getdns_context_set_timeout_h_ #ifndef _check_getdns_context_set_timeout_h_
#define _check_getdns_context_set_timeout_h_ #define _check_getdns_context_set_timeout_h_
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments"
#include <check.h> #include <check.h>
#pragma clang diagnostic pop
Suite * Suite *
getdns_context_set_timeout_suite (void); getdns_context_set_timeout_suite (void);

View File

@ -41,7 +41,10 @@
#else #else
#include <ev.h> #include <ev.h>
#endif #endif
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments"
#include <check.h> #include <check.h>
#pragma clang diagnostic pop
#include "check_getdns_common.h" #include "check_getdns_common.h"
void run_event_loop_impl(struct getdns_context* context, void* eventloop) { void run_event_loop_impl(struct getdns_context* context, void* eventloop) {

View File

@ -37,7 +37,10 @@
#include "getdns/getdns_ext_libevent.h" #include "getdns/getdns_ext_libevent.h"
#include "check_getdns_libevent.h" #include "check_getdns_libevent.h"
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments"
#include <check.h> #include <check.h>
#pragma clang diagnostic pop
#include "check_getdns_common.h" #include "check_getdns_common.h"
void run_event_loop_impl(struct getdns_context* context, void* eventloop) { void run_event_loop_impl(struct getdns_context* context, void* eventloop) {

View File

@ -37,7 +37,10 @@
#include "getdns/getdns_ext_libuv.h" #include "getdns/getdns_ext_libuv.h"
#include <uv.h> #include <uv.h>
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments"
#include <check.h> #include <check.h>
#pragma clang diagnostic pop
#include "check_getdns_common.h" #include "check_getdns_common.h"
void run_event_loop_impl(struct getdns_context* context, void* eventloop) { void run_event_loop_impl(struct getdns_context* context, void* eventloop) {

View File

@ -27,7 +27,10 @@
#ifndef _check_getdns_transport_h_ #ifndef _check_getdns_transport_h_
#define _check_getdns_transport_h_ #define _check_getdns_transport_h_
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments"
#include <check.h> #include <check.h>
#pragma clang diagnostic pop
Suite * Suite *
getdns_transport_suite (void); getdns_transport_suite (void);

View File

@ -43,18 +43,20 @@
#include "debug.h" #include "debug.h"
#ifdef HAVE_UNBOUND_EVENT_H #ifdef HAVE_UNBOUND_EVENT_H
#include <unbound-event.h> # include <unbound-event.h>
#else #else
struct ub_event_base_vmt; struct ub_event_base_vmt;
struct ub_event_base { struct ub_event_base {
unsigned long magic; unsigned long magic;
struct ub_event_base_vmt* vmt; struct ub_event_base_vmt* vmt;
}; };
struct ub_event_base; # ifndef _UB_EVENT_PRIMITIVES
# define _UB_EVENT_PRIMITIVES
struct ub_ctx* ub_ctx_create_ub_event(struct ub_event_base* base); struct ub_ctx* ub_ctx_create_ub_event(struct ub_event_base* base);
typedef void (*ub_event_callback_t)(void*, int, void*, int, int, char*); typedef void (*ub_event_callback_t)(void*, int, void*, int, int, char*);
int ub_resolve_event(struct ub_ctx* ctx, const char* name, int rrtype, int ub_resolve_event(struct ub_ctx* ctx, const char* name, int rrtype,
int rrclass, void* mydata, ub_event_callback_t callback, int* async_id); int rrclass, void* mydata, ub_event_callback_t callback, int* async_id);
# endif
#endif #endif
typedef struct _getdns_ub_loop { typedef struct _getdns_ub_loop {