doh: use dedicated probe slots

... to easier allow additional DNS transactions.

Closes #4629
This commit is contained in:
Niall 2019-11-21 12:15:44 +00:00 committed by Daniel Stenberg
parent c393b66df9
commit 8acfad38ca
No known key found for this signature in database
GPG Key ID: 5CC908FDB71E12C2
2 changed files with 63 additions and 41 deletions

View File

@ -385,6 +385,7 @@ Curl_addrinfo *Curl_doh(struct connectdata *conn,
{ {
struct Curl_easy *data = conn->data; struct Curl_easy *data = conn->data;
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
int slot;
*waitp = TRUE; /* this never returns synchronously */ *waitp = TRUE; /* this never returns synchronously */
(void)conn; (void)conn;
(void)hostname; (void)hostname;
@ -403,8 +404,8 @@ Curl_addrinfo *Curl_doh(struct connectdata *conn,
if(conn->ip_version != CURL_IPRESOLVE_V6) { if(conn->ip_version != CURL_IPRESOLVE_V6) {
/* create IPv4 DOH request */ /* create IPv4 DOH request */
result = dohprobe(data, &data->req.doh.probe[0], DNS_TYPE_A, result = dohprobe(data, &data->req.doh.probe[DOH_PROBE_SLOT_IPADDR_V4],
hostname, data->set.str[STRING_DOH], DNS_TYPE_A, hostname, data->set.str[STRING_DOH],
data->multi, data->req.doh.headers); data->multi, data->req.doh.headers);
if(result) if(result)
goto error; goto error;
@ -413,8 +414,8 @@ Curl_addrinfo *Curl_doh(struct connectdata *conn,
if(conn->ip_version != CURL_IPRESOLVE_V4) { if(conn->ip_version != CURL_IPRESOLVE_V4) {
/* create IPv6 DOH request */ /* create IPv6 DOH request */
result = dohprobe(data, &data->req.doh.probe[1], DNS_TYPE_AAAA, result = dohprobe(data, &data->req.doh.probe[DOH_PROBE_SLOT_IPADDR_V6],
hostname, data->set.str[STRING_DOH], DNS_TYPE_AAAA, hostname, data->set.str[STRING_DOH],
data->multi, data->req.doh.headers); data->multi, data->req.doh.headers);
if(result) if(result)
goto error; goto error;
@ -425,8 +426,9 @@ Curl_addrinfo *Curl_doh(struct connectdata *conn,
error: error:
curl_slist_free_all(data->req.doh.headers); curl_slist_free_all(data->req.doh.headers);
data->req.doh.headers = NULL; data->req.doh.headers = NULL;
Curl_close(&data->req.doh.probe[0].easy); for(slot = 0; slot < DOH_PROBE_SLOTS; slot++) {
Curl_close(&data->req.doh.probe[1].easy); Curl_close(&data->req.doh.probe[slot].easy);
}
return NULL; return NULL;
} }
@ -937,46 +939,43 @@ UNITTEST void de_cleanup(struct dohentry *d)
CURLcode Curl_doh_is_resolved(struct connectdata *conn, CURLcode Curl_doh_is_resolved(struct connectdata *conn,
struct Curl_dns_entry **dnsp) struct Curl_dns_entry **dnsp)
{ {
CURLcode result;
struct Curl_easy *data = conn->data; struct Curl_easy *data = conn->data;
*dnsp = NULL; /* defaults to no response */ *dnsp = NULL; /* defaults to no response */
if(!data->req.doh.probe[0].easy && !data->req.doh.probe[1].easy) { if(!data->req.doh.probe[DOH_PROBE_SLOT_IPADDR_V4].easy &&
!data->req.doh.probe[DOH_PROBE_SLOT_IPADDR_V6].easy) {
failf(data, "Could not DOH-resolve: %s", conn->async.hostname); failf(data, "Could not DOH-resolve: %s", conn->async.hostname);
return conn->bits.proxy?CURLE_COULDNT_RESOLVE_PROXY: return conn->bits.proxy?CURLE_COULDNT_RESOLVE_PROXY:
CURLE_COULDNT_RESOLVE_HOST; CURLE_COULDNT_RESOLVE_HOST;
} }
else if(!data->req.doh.pending) { else if(!data->req.doh.pending) {
DOHcode rc; DOHcode rc[DOH_PROBE_SLOTS];
DOHcode rc2;
struct dohentry de; struct dohentry de;
int slot;
/* remove DOH handles from multi handle and close them */ /* remove DOH handles from multi handle and close them */
curl_multi_remove_handle(data->multi, data->req.doh.probe[0].easy); for(slot = 0; slot < DOH_PROBE_SLOTS; slot++) {
Curl_close(&data->req.doh.probe[0].easy); curl_multi_remove_handle(data->multi, data->req.doh.probe[slot].easy);
curl_multi_remove_handle(data->multi, data->req.doh.probe[1].easy); Curl_close(&data->req.doh.probe[slot].easy);
Curl_close(&data->req.doh.probe[1].easy); }
/* parse the responses, create the struct and return it! */ /* parse the responses, create the struct and return it! */
init_dohentry(&de); init_dohentry(&de);
rc = doh_decode(data->req.doh.probe[0].serverdoh.memory, for(slot = 0; slot < DOH_PROBE_SLOTS; slot++) {
data->req.doh.probe[0].serverdoh.size, rc[slot] = doh_decode(data->req.doh.probe[slot].serverdoh.memory,
data->req.doh.probe[0].dnstype, data->req.doh.probe[slot].serverdoh.size,
&de); data->req.doh.probe[slot].dnstype,
Curl_safefree(data->req.doh.probe[0].serverdoh.memory); &de);
if(rc) { Curl_safefree(data->req.doh.probe[slot].serverdoh.memory);
infof(data, "DOH: %s type %s for %s\n", doh_strerror(rc), if(rc[slot]) {
type2name(data->req.doh.probe[0].dnstype), infof(data, "DOH: %s type %s for %s\n", doh_strerror(rc[slot]),
data->req.doh.host); type2name(data->req.doh.probe[slot].dnstype),
} data->req.doh.host);
rc2 = doh_decode(data->req.doh.probe[1].serverdoh.memory, }
data->req.doh.probe[1].serverdoh.size, } /* next slot */
data->req.doh.probe[1].dnstype,
&de); result = CURLE_COULDNT_RESOLVE_HOST; /* until we know better */
Curl_safefree(data->req.doh.probe[1].serverdoh.memory); if(!rc[DOH_PROBE_SLOT_IPADDR_V4] || !rc[DOH_PROBE_SLOT_IPADDR_V6]) {
if(rc2) { /* we have an address, of one kind or other */
infof(data, "DOH: %s type %s for %s\n", doh_strerror(rc2),
type2name(data->req.doh.probe[1].dnstype),
data->req.doh.host);
}
if(!rc || !rc2) {
struct Curl_dns_entry *dns; struct Curl_dns_entry *dns;
struct Curl_addrinfo *ai; struct Curl_addrinfo *ai;
@ -998,21 +997,26 @@ CURLcode Curl_doh_is_resolved(struct connectdata *conn,
if(data->share) if(data->share)
Curl_share_unlock(data, CURL_LOCK_DATA_DNS); Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
de_cleanup(&de); if(!dns) {
if(!dns)
/* returned failure, bail out nicely */ /* returned failure, bail out nicely */
Curl_freeaddrinfo(ai); Curl_freeaddrinfo(ai);
}
else { else {
conn->async.dns = dns; conn->async.dns = dns;
*dnsp = dns; *dnsp = dns;
return CURLE_OK; result = CURLE_OK; /* address resolution OK */
} }
} } /* address processing done */
/* Now process any build-specific attributes retrieved from DNS */
/* All done */
de_cleanup(&de); de_cleanup(&de);
return result;
return CURLE_COULDNT_RESOLVE_HOST; } /* !data->req.doh.pending */
}
/* else wait for pending DOH transactions to complete */
return CURLE_OK; return CURLE_OK;
} }

View File

@ -528,6 +528,24 @@ enum upgrade101 {
UPGR101_WORKING /* talking upgraded protocol */ UPGR101_WORKING /* talking upgraded protocol */
}; };
enum doh_slots {
/* Explicit values for first two symbols so as to match hard-coded
* constants in existing code
*/
DOH_PROBE_SLOT_IPADDR_V4 = 0, /* make 'V4' stand out for readability */
DOH_PROBE_SLOT_IPADDR_V6 = 1, /* 'V6' likewise */
/* Space here for (possibly build-specific) additional slot definitions */
/* for example */
/* #ifdef WANT_DOH_FOOBAR_TXT */
/* DOH_PROBE_SLOT_FOOBAR_TXT, */
/* #endif */
/* AFTER all slot definitions, establish how many we have */
DOH_PROBE_SLOTS
};
struct dohresponse { struct dohresponse {
unsigned char *memory; unsigned char *memory;
size_t size; size_t size;
@ -544,7 +562,7 @@ struct dnsprobe {
struct dohdata { struct dohdata {
struct curl_slist *headers; struct curl_slist *headers;
struct dnsprobe probe[2]; struct dnsprobe probe[DOH_PROBE_SLOTS];
unsigned int pending; /* still outstanding requests */ unsigned int pending; /* still outstanding requests */
const char *host; const char *host;
int port; int port;