Merge branch 'develop' into devel/without-stubby

This commit is contained in:
Willem Toorop 2017-08-22 11:27:11 +02:00
commit 6024f9d72e
8 changed files with 115 additions and 25 deletions

View File

@ -99,7 +99,7 @@ Note: If you only want to build stubby, then use the `--enable-stub-only` and `-
## Extensions and Event loop dependencies ## Extensions and Event loop dependencies
The implementation works with a variety of event loops, each built as a separate shared library. See [the wiki](https://github.com/getdnsapi/getdns/wiki/Asynchronous-Support#wiki-included-event-loop-integrations) for more details. The implementation works with a variety of event loops, each built as a separate shared library. See [this Doxygen page](https://getdnsapi.net/doxygen/group__eventloops.html) and [this man page](https://getdnsapi.net/documentation/manpages/#ASYNCHRONOUS USE) for more details.
* [libevent](http://libevent.org). Note: the examples *require* this and should work with either libevent 1.x or 2.x. 2.x is preferred. * [libevent](http://libevent.org). Note: the examples *require* this and should work with either libevent 1.x or 2.x. 2.x is preferred.
* [libuv](https://github.com/joyent/libuv) * [libuv](https://github.com/joyent/libuv)
@ -170,8 +170,8 @@ Non-goals (things we will not be doing at least initially) include:
## Language Bindings ## Language Bindings
In parallel, the team is actively developing bindings for various languages. In parallel, the team is actively developing bindings for various languages.
For more information, visit the For more information, visit this
[wiki](https://github.com/getdnsapi/getdns/wiki/Language-Bindings). [webpage](https://getdnsapi.net/bindings/).
## Unsupported getDNS Features ## Unsupported getDNS Features
@ -187,10 +187,10 @@ The following minor implementation omissions are noted:
Recursive mode does not support: Recursive mode does not support:
* TLS as a transport * TLS as a transport
* Non-zero connection idle timeouts or query pipelining * Non-zero connection idle timeouts or query pipelining
* Anything other than query_type and resolution_type in the return_call_reporting extension
Stub mode does not support: Stub mode does not support:
* Non zero idle timeouts for synchronous calls * Non zero idle timeouts for synchronous calls
* Limit on number of outstanding queries
# Known Issues # Known Issues
@ -264,7 +264,7 @@ build the packages; this is simply the one we chose to use.
If you're using [Homebrew](http://brew.sh/), you may run `brew install getdns`. By default, this will only build the core library without any 3rd party event loop support. If you're using [Homebrew](http://brew.sh/), you may run `brew install getdns`. By default, this will only build the core library without any 3rd party event loop support.
To install the [event loop integration libraries](https://github.com/getdnsapi/getdns/wiki/Asynchronous-Support) that enable support for libevent, libuv, and libev, run: `brew install getdns --with-libevent --with-libuv --with-libev`. All switches are optional. To install the [event loop integration libraries](https://getdnsapi.net/doxygen/group__eventloops.html) that enable support for libevent, libuv, and libev, run: `brew install getdns --with-libevent --with-libuv --with-libev`. All switches are optional.
Note that in order to compile the examples, the `--with-libevent` switch is required. Note that in order to compile the examples, the `--with-libevent` switch is required.

View File

@ -875,7 +875,7 @@ names:</p>
<li><code>query_name</code> (a bindata) is the name that was sent</li> <li><code>query_name</code> (a bindata) is the name that was sent</li>
<li><code>query_type</code> (an int) is the type that was queried for</li> <li><code>query_type</code> (an int) is the type that was queried for</li>
<li><code>query_to</code> (a bindata) is the address to which the query was sent</li> <li><code>query_to</code> (a bindata) is the address to which the query was sent</li>
<li><code>run_time</code> (a bindata) is the difference between the time the successful <li><code>run_time/ms</code> (a bindata) is the difference between the time the successful
query started and ended in milliseconds, represented query started and ended in milliseconds, represented
as a uint32_t (this does not include time taken for connection set up as a uint32_t (this does not include time taken for connection set up
or transport fallback)</li> or transport fallback)</li>

View File

@ -550,11 +550,26 @@ static chain_head *add_rrset2val_chain(struct mem_funcs *mf,
/* Also, try to prevent adding double rrsets */ /* Also, try to prevent adding double rrsets */
if ( rrset->rr_class == head->rrset.rr_class if ( rrset->rr_class == head->rrset.rr_class
&& rrset->rr_type == head->rrset.rr_type && rrset->rr_type == head->rrset.rr_type
&& rrset->pkt == head->rrset.pkt && _dname_equal(rrset->name, head->rrset.name)) {
&& rrset->pkt_len == head->rrset.pkt_len
&& _dname_equal(rrset->name, head->rrset.name))
return NULL;
if (rrset->pkt == head->rrset.pkt &&
rrset->pkt_len == head->rrset.pkt_len)
return NULL;
else {
/* Anticipate resubmissions due to
* roadblock avoidance */
head->rrset.pkt = rrset->pkt;
head->rrset.pkt_len = rrset->pkt_len;
return head;
}
}
if ( rrset->rr_class == head->rrset.rr_class
&& rrset->rr_type == head->rrset.rr_type
&& rrset->pkt != head->rrset.pkt
&& _dname_equal(rrset->name, head->rrset.name)) {
return NULL;
}
for (label = labels; label < last_label; label++) { for (label = labels; label < last_label; label++) {
if (! _dname_is_parent(*label, head->rrset.name)) if (! _dname_is_parent(*label, head->rrset.name))
break; break;
@ -2416,6 +2431,7 @@ static int key_proves_nonexistance(
* ========================+ * ========================+
* First find the closest encloser. * First find the closest encloser.
*/ */
if (*rrset->name)
for ( nc_name = rrset->name, ce_name = rrset->name + *rrset->name + 1 for ( nc_name = rrset->name, ce_name = rrset->name + *rrset->name + 1
; *ce_name ; nc_name = ce_name, ce_name += *ce_name + 1) { ; *ce_name ; nc_name = ce_name, ce_name += *ce_name + 1) {
@ -3029,19 +3045,50 @@ static void check_chain_complete(chain_head *chain)
&& !dnsreq->avoid_dnssec_roadblocks && !dnsreq->avoid_dnssec_roadblocks
&& dnsreq->netreqs[0]->dnssec_status == GETDNS_DNSSEC_BOGUS) { && dnsreq->netreqs[0]->dnssec_status == GETDNS_DNSSEC_BOGUS) {
int r = GETDNS_RETURN_GOOD;
getdns_network_req **netreq_p, *netreq; getdns_network_req **netreq_p, *netreq;
uint64_t now_ms = 0; uint64_t now_ms = 0;
dnsreq->avoid_dnssec_roadblocks = 1; dnsreq->avoid_dnssec_roadblocks = 1;
dnsreq->chain->lock += 1;
for ( netreq_p = dnsreq->netreqs for ( netreq_p = dnsreq->netreqs
; !r && (netreq = *netreq_p) ; (netreq = *netreq_p)
; netreq_p++) { ; netreq_p++) {
_getdns_netreq_change_state(netreq, NET_REQ_NOT_SENT); _getdns_netreq_change_state(netreq, NET_REQ_NOT_SENT);
netreq->dnssec_status =
GETDNS_DNSSEC_INDETERMINATE;
netreq->owner = dnsreq; netreq->owner = dnsreq;
r = _getdns_submit_netreq(netreq, &now_ms); (void) _getdns_submit_netreq(netreq, &now_ms);
}
if (!dnsreq->dnssec_return_validation_chain)
return;
for ( head = chain; head ; head = next ) {
next = head->next;
for ( node_count = head->node_count
, node = head->parent
; node_count
; node_count--, node = node->parent ) {
if (node->dnskey_req) {
_getdns_netreq_change_state(
node->dnskey_req,
NET_REQ_NOT_SENT);
node->dnskey_req->owner->
avoid_dnssec_roadblocks = 1;
(void) _getdns_submit_netreq(
node->dnskey_req, &now_ms);
}
if (node->ds_req) {
_getdns_netreq_change_state(
node->ds_req, NET_REQ_NOT_SENT);
node->ds_req->owner->
avoid_dnssec_roadblocks = 1;
(void) _getdns_submit_netreq(
node->ds_req, &now_ms);
}
}
} }
return; return;
} }
@ -3185,11 +3232,16 @@ void _getdns_get_validation_chain(getdns_dns_req *dnsreq)
getdns_network_req *netreq, **netreq_p; getdns_network_req *netreq, **netreq_p;
chain_head *chain = NULL, *chain_p; chain_head *chain = NULL, *chain_p;
if (dnsreq->validating) if (dnsreq->avoid_dnssec_roadblocks) {
chain = dnsreq->chain;
} else if (dnsreq->validating)
return; return;
dnsreq->validating = 1; dnsreq->validating = 1;
for (netreq_p = dnsreq->netreqs; (netreq = *netreq_p) ; netreq_p++) { if (dnsreq->avoid_dnssec_roadblocks && chain->lock == 0)
; /* pass */
else for (netreq_p = dnsreq->netreqs; (netreq = *netreq_p) ; netreq_p++) {
if (! netreq->response if (! netreq->response
|| netreq->response_len < GLDNS_HEADER_SIZE || netreq->response_len < GLDNS_HEADER_SIZE
|| ( GLDNS_RCODE_WIRE(netreq->response) || ( GLDNS_RCODE_WIRE(netreq->response)
@ -3217,6 +3269,9 @@ void _getdns_get_validation_chain(getdns_dns_req *dnsreq)
if (chain_p->lock) chain_p->lock--; if (chain_p->lock) chain_p->lock--;
} }
dnsreq->chain = chain; dnsreq->chain = chain;
if (dnsreq->avoid_dnssec_roadblocks && chain->lock)
chain->lock -= 1;
check_chain_complete(chain); check_chain_complete(chain);
} else { } else {
dnsreq->validating = 0; dnsreq->validating = 0;

View File

@ -59,6 +59,9 @@ void _getdns_call_user_callback(getdns_dns_req *dnsreq, getdns_dict *response)
{ {
_getdns_context_clear_outbound_request(dnsreq); _getdns_context_clear_outbound_request(dnsreq);
#if defined(REQ_DEBUG) && REQ_DEBUG
debug_req(__FUNC__, *dnsreq->netreqs);
#endif
if (dnsreq->user_callback) { if (dnsreq->user_callback) {
dnsreq->context->processing = 1; dnsreq->context->processing = 1;
dnsreq->user_callback(dnsreq->context, dnsreq->user_callback(dnsreq->context,
@ -211,6 +214,7 @@ _getdns_check_dns_req_complete(getdns_dns_req *dns_req)
#ifdef STUB_NATIVE_DNSSEC #ifdef STUB_NATIVE_DNSSEC
|| (dns_req->context->resolution_type == GETDNS_RESOLUTION_STUB || (dns_req->context->resolution_type == GETDNS_RESOLUTION_STUB
&& !dns_req->avoid_dnssec_roadblocks
&& (dns_req->dnssec_return_status || && (dns_req->dnssec_return_status ||
dns_req->dnssec_return_only_secure || dns_req->dnssec_return_only_secure ||
dns_req->dnssec_return_all_statuses dns_req->dnssec_return_all_statuses
@ -228,6 +232,9 @@ _getdns_check_dns_req_complete(getdns_dns_req *dns_req)
NULL, NULL, (getdns_eventloop_callback) NULL, NULL, (getdns_eventloop_callback)
_getdns_validation_chain_timeout)); _getdns_validation_chain_timeout));
#if defined(REQ_DEBUG) && REQ_DEBUG
debug_req("getting validation chain for ", *dns_req->netreqs);
#endif
_getdns_get_validation_chain(dns_req); _getdns_get_validation_chain(dns_req);
} else } else
_getdns_call_user_callback( _getdns_call_user_callback(

View File

@ -1101,7 +1101,6 @@ getdns_service(getdns_context *context,
* (e.g. CRYPTO_THREADID_set_call) depending on the library version used. * (e.g. CRYPTO_THREADID_set_call) depending on the library version used.
* @param context context that can be used immediately with other API calls * @param context context that can be used immediately with other API calls
* @param set_from_os set to 1 to initialize the context with os defaults * @param set_from_os set to 1 to initialize the context with os defaults
* the second bit set (2) prevents OpenSSL library initialization.
* @return GETDNS_RETURN_GOOD on success * @return GETDNS_RETURN_GOOD on success
*/ */
getdns_return_t getdns_return_t
@ -1114,7 +1113,6 @@ getdns_context_create(getdns_context ** context, int set_from_os);
* (e.g. CRYPTO_THREADID_set_call) depending on the library version used. * (e.g. CRYPTO_THREADID_set_call) depending on the library version used.
* @param context context that can be used immediately with other API calls * @param context context that can be used immediately with other API calls
* @param set_from_os set to 1 to initialize the context with os defaults * @param set_from_os set to 1 to initialize the context with os defaults
* the second bit set (2) prevents OpenSSL library initialization.
* @param malloc custom malloc function * @param malloc custom malloc function
* @param realloc custom realloc function * @param realloc custom realloc function
* @param free custom free function * @param free custom free function
@ -1136,7 +1134,6 @@ getdns_context_create_with_memory_functions(
* (e.g. CRYPTO_THREADID_set_call) depending on the library version used. * (e.g. CRYPTO_THREADID_set_call) depending on the library version used.
* @param context context that can be used immediately with other API calls * @param context context that can be used immediately with other API calls
* @param set_from_os set to 1 to initialize the context with os defaults * @param set_from_os set to 1 to initialize the context with os defaults
* the second bit set (2) prevents OpenSSL library initialization.
* @param userarg parameter passed to the custom malloc, realloc and free functions * @param userarg parameter passed to the custom malloc, realloc and free functions
* @param malloc custom malloc function * @param malloc custom malloc function
* @param realloc custom realloc function * @param realloc custom realloc function

View File

@ -588,6 +588,7 @@ _getdns_cancel_stub_request(getdns_network_req *netreq)
#else #else
close(netreq->fd); close(netreq->fd);
#endif #endif
netreq->fd = -1;
} }
} }
@ -606,6 +607,7 @@ stub_timeout_cb(void *userarg)
#else #else
close(netreq->fd); close(netreq->fd);
#endif #endif
netreq->fd = -1;
netreq->upstream->udp_timeouts++; netreq->upstream->udp_timeouts++;
if (netreq->upstream->udp_timeouts % 100 == 0) if (netreq->upstream->udp_timeouts % 100 == 0)
_getdns_upstream_log(netreq->upstream, GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_DEBUG, _getdns_upstream_log(netreq->upstream, GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_DEBUG,
@ -1413,6 +1415,7 @@ stub_udp_read_cb(void *userarg)
#else #else
close(netreq->fd); close(netreq->fd);
#endif #endif
netreq->fd = -1;
stub_next_upstream(netreq); stub_next_upstream(netreq);
} }
netreq->debug_end_time = _getdns_get_time_as_uintt64(); netreq->debug_end_time = _getdns_get_time_as_uintt64();
@ -1435,8 +1438,8 @@ stub_udp_read_cb(void *userarg)
closesocket(netreq->fd); closesocket(netreq->fd);
#else #else
close(netreq->fd); close(netreq->fd);
netreq->fd = -1;
#endif #endif
netreq->fd = -1;
while (GLDNS_TC_WIRE(netreq->response)) { while (GLDNS_TC_WIRE(netreq->response)) {
DEBUG_STUB("%s %-35s: MSG: %p TC bit set in response \n", STUB_DEBUG_READ, DEBUG_STUB("%s %-35s: MSG: %p TC bit set in response \n", STUB_DEBUG_READ,
__FUNC__, (void*)netreq); __FUNC__, (void*)netreq);
@ -1533,6 +1536,7 @@ stub_udp_write_cb(void *userarg)
#else #else
close(netreq->fd); close(netreq->fd);
#endif #endif
netreq->fd = -1;
stub_next_upstream(netreq); stub_next_upstream(netreq);
} }
netreq->debug_end_time = _getdns_get_time_as_uintt64(); netreq->debug_end_time = _getdns_get_time_as_uintt64();
@ -1958,7 +1962,7 @@ upstream_select(getdns_network_req *netreq)
return &upstreams->upstreams[i]; return &upstreams->upstreams[i];
} }
i+=GETDNS_UPSTREAM_TRANSPORTS; i+=GETDNS_UPSTREAM_TRANSPORTS;
if (i > upstreams->count) if (i >= upstreams->count)
i = 0; i = 0;
} while (i != upstreams->current_udp); } while (i != upstreams->current_udp);

View File

@ -24,7 +24,7 @@ RUN set -ex \
&& cd /usr/src \ && cd /usr/src \
&& git clone https://github.com/getdnsapi/getdns.git \ && git clone https://github.com/getdnsapi/getdns.git \
&& cd /usr/src/getdns \ && cd /usr/src/getdns \
&& git checkout release/1.1.1 \ && git checkout master \
&& git submodule update --init \ && git submodule update --init \
&& libtoolize -ci \ && libtoolize -ci \
&& autoreconf -fi \ && autoreconf -fi \
@ -35,7 +35,7 @@ RUN set -ex \
&& cp src/tools/stubby.conf /etc \ && cp src/tools/stubby.conf /etc \
&& mkdir -p /etc/unbound \ && mkdir -p /etc/unbound \
&& cd /etc/unbound \ && cd /etc/unbound \
&& wget http://www.nomountain.net/getdns-root.key && unbound-anchor -a /etc/unbound/getdns-root.key || :
EXPOSE 53 EXPOSE 53

View File

@ -81,6 +81,8 @@ static uint16_t request_type = GETDNS_RRTYPE_NS;
static int timeout, edns0_size, padding_blocksize; 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;
static int bogus_answers = 0;
static int check_dnssec = 0;
static int get_rrtype(const char *t) static int get_rrtype(const char *t)
{ {
@ -317,6 +319,7 @@ static getdns_return_t validate_chain(getdns_dict *response)
break; break;
case GETDNS_DNSSEC_BOGUS: case GETDNS_DNSSEC_BOGUS:
if (verbosity) fprintf(stdout, "GETDNS_DNSSEC_BOGUS\n"); if (verbosity) fprintf(stdout, "GETDNS_DNSSEC_BOGUS\n");
bogus_answers += 1;
break; break;
case GETDNS_DNSSEC_INDETERMINATE: case GETDNS_DNSSEC_INDETERMINATE:
if (verbosity) fprintf(stdout, "GETDNS_DNSSEC_INDETERMINATE\n"); if (verbosity) fprintf(stdout, "GETDNS_DNSSEC_INDETERMINATE\n");
@ -346,6 +349,7 @@ static getdns_return_t validate_chain(getdns_dict *response)
break; break;
case GETDNS_DNSSEC_BOGUS: case GETDNS_DNSSEC_BOGUS:
if (verbosity) fprintf(stdout, "GETDNS_DNSSEC_BOGUS\n"); if (verbosity) fprintf(stdout, "GETDNS_DNSSEC_BOGUS\n");
bogus_answers += 1;
break; break;
case GETDNS_DNSSEC_INDETERMINATE: case GETDNS_DNSSEC_INDETERMINATE:
if (verbosity) fprintf(stdout, "GETDNS_DNSSEC_INDETERMINATE\n"); if (verbosity) fprintf(stdout, "GETDNS_DNSSEC_INDETERMINATE\n");
@ -389,6 +393,14 @@ void callback(getdns_context *context, getdns_callback_type_t callback_type,
if (callback_type == GETDNS_CALLBACK_COMPLETE) { if (callback_type == GETDNS_CALLBACK_COMPLETE) {
if (verbosity) printf("Response code was: GOOD. Status was: Callback with ID %"PRIu64" was successful.\n", if (verbosity) printf("Response code was: GOOD. Status was: Callback with ID %"PRIu64" was successful.\n",
trans_id); trans_id);
if (check_dnssec) {
uint32_t dnssec_status = GETDNS_DNSSEC_SECURE;
(void )getdns_dict_get_int(response,
"/replies_tree/0/dnssec_status", &dnssec_status);
if (dnssec_status == GETDNS_DNSSEC_BOGUS)
bogus_answers += 1;
}
} else if (callback_type == GETDNS_CALLBACK_CANCEL) } else if (callback_type == GETDNS_CALLBACK_CANCEL)
fprintf(stderr, fprintf(stderr,
@ -403,7 +415,6 @@ void callback(getdns_context *context, getdns_callback_type_t callback_type,
getdns_get_errorstr_by_id(callback_type)); getdns_get_errorstr_by_id(callback_type));
} }
getdns_dict_destroy(response); getdns_dict_destroy(response);
response = NULL;
} }
#define CONTINUE ((getdns_return_t)-2) #define CONTINUE ((getdns_return_t)-2)
@ -578,6 +589,9 @@ getdns_return_t parse_args(int argc, char **argv)
continue; continue;
} else if (arg[0] == '+') { } else if (arg[0] == '+') {
if (strncmp(arg+1, "dnssec_", 7) == 0)
check_dnssec = 1;
if (arg[1] == 's' && arg[2] == 'i' && arg[3] == 't' && if (arg[1] == 's' && arg[2] == 'i' && arg[3] == 't' &&
(arg[4] == '=' || arg[4] == '\0')) { (arg[4] == '=' || arg[4] == '\0')) {
if ((r = set_cookie(extensions, arg+4))) { if ((r = set_cookie(extensions, arg+4))) {
@ -1196,6 +1210,7 @@ getdns_return_t do_the_call(void)
fprintf( stdout, "%s\n", response_str); fprintf( stdout, "%s\n", response_str);
if (verbosity) fprintf( stdout, "SYNC call completed.\n"); if (verbosity) fprintf( stdout, "SYNC call completed.\n");
validate_chain(response); validate_chain(response);
free(response_str); free(response_str);
} else { } else {
@ -1208,8 +1223,18 @@ getdns_return_t do_the_call(void)
if (verbosity) if (verbosity)
fprintf(stdout, "Response code was: GOOD. Status was: %s\n", fprintf(stdout, "Response code was: GOOD. Status was: %s\n",
getdns_get_errorstr_by_id(status)); getdns_get_errorstr_by_id(status));
if (response) if (response) {
if (check_dnssec) {
uint32_t dnssec_status = GETDNS_DNSSEC_SECURE;
(void )getdns_dict_get_int(response,
"/replies_tree/0/dnssec_status",
&dnssec_status);
if (dnssec_status == GETDNS_DNSSEC_BOGUS)
bogus_answers += 1;
}
getdns_dict_destroy(response); getdns_dict_destroy(response);
}
} }
getdns_dict_destroy(address); getdns_dict_destroy(address);
return r; return r;
@ -1790,5 +1815,7 @@ done_destroy_context:
if (!i_am_stubby && verbosity) if (!i_am_stubby && verbosity)
fprintf(stdout, "\nAll done.\n"); fprintf(stdout, "\nAll done.\n");
return r; return r ? r
: bogus_answers ? GETDNS_DNSSEC_BOGUS
: GETDNS_RETURN_GOOD;
} }