WIP: Don't pick unique Query ID for connected UDP sockets

This commit is contained in:
Ondřej Surý
2022-11-29 13:32:04 +01:00
parent 6aac2ae6cd
commit 2bc695dd53

View File

@@ -64,8 +64,6 @@ struct dns_dispatchmgr {
isc_mutex_t lock;
ISC_LIST(dns_dispatch_t) list;
dns_qid_t qid;
in_port_t *v4ports; /*%< available ports for IPv4 */
unsigned int nv4ports; /*%< # of available ports for IPv4 */
in_port_t *v6ports; /*%< available ports for IPv4 */
@@ -144,6 +142,8 @@ struct dns_dispatch {
unsigned int tcpbuffers; /*%< allocated buffers */
unsigned int timedout;
dns_qid_t qid;
};
#define RESPONSE_MAGIC ISC_MAGIC('D', 'r', 's', 'p')
@@ -673,7 +673,7 @@ tcp_recv(isc_nmhandle_t *handle, isc_result_t result, isc_region_t *region,
atomic_store(&disp->tcpreading, false);
qid = &disp->mgr->qid;
qid = &disp->qid;
ISC_LIST_INIT(resps);
@@ -855,8 +855,6 @@ dns_dispatchmgr_create(isc_mem_t *mctx, isc_nm_t *nm,
isc_portset_destroy(mctx, &v4portset);
isc_portset_destroy(mctx, &v6portset);
qid_init(mgr->mctx, &mgr->qid);
*mgrp = mgr;
return (ISC_R_SUCCESS);
}
@@ -894,8 +892,6 @@ dispatchmgr_destroy(dns_dispatchmgr_t *mgr) {
mgr->magic = 0;
isc_mutex_destroy(&mgr->lock);
qid_free(&mgr->qid);
if (mgr->blackhole != NULL) {
dns_acl_detach(&mgr->blackhole);
}
@@ -1017,6 +1013,10 @@ dispatch_free(dns_dispatch_t **dispp) {
INSIST(disp->requests == 0);
INSIST(ISC_LIST_EMPTY(disp->active));
if (disp->socktype == isc_socktype_tcp) {
qid_free(&disp->qid);
}
isc_mutex_destroy(&disp->lock);
isc_mem_put(mgr->mctx, disp, sizeof(*disp));
@@ -1048,6 +1048,8 @@ dns_dispatch_createtcp(dns_dispatchmgr_t *mgr, const isc_sockaddr_t *localaddr,
isc_sockaddr_setport(&disp->local, 0);
}
qid_init(mgr->mctx, &disp->qid);
/*
* Append it to the dispatcher list.
*/
@@ -1275,8 +1277,6 @@ dns_dispatch_add(dns_dispatch_t *disp, unsigned int options,
LOCK(&disp->lock);
qid = &disp->mgr->qid;
resp = isc_mem_get(disp->mgr->mctx, sizeof(*resp));
*resp = (dns_dispentry_t){
@@ -1291,57 +1291,73 @@ dns_dispatch_add(dns_dispatch_t *disp, unsigned int options,
.alink = ISC_LINK_INITIALIZER,
.plink = ISC_LINK_INITIALIZER,
.rlink = ISC_LINK_INITIALIZER,
.magic = RESPONSE_MAGIC,
};
isc_refcount_init(&resp->references, 1);
if (disp->socktype == isc_socktype_udp) {
switch (disp->socktype) {
case isc_socktype_udp:
result = setup_socket(disp, resp, dest, &localport);
if (result != ISC_R_SUCCESS) {
goto fail;
}
}
/*
* Try somewhat hard to find a unique ID. Start with
* a random number unless DNS_DISPATCHOPT_FIXEDID is set,
* in which case we start with the ID passed in via *idp.
*/
if ((options & DNS_DISPATCHOPT_FIXEDID) != 0) {
tries = 1;
}
LOCK(&qid->lock);
for (int i = 0; i < tries; i++) {
/* Pick new messsage ID */
if ((options & DNS_DISPATCHOPT_FIXEDID) != 0) {
id = *idp;
} else {
id = (dns_messageid_t)isc_random16();
}
/* Compute the hashtable key */
INSIST(disp->socktype == isc_socktype_udp || localport == 0);
resp->keylen = qid_makekey(resp->key, dest, id, localport);
uint32_t hashval = isc_hashmap_hash(qid->table, resp->key,
resp->keylen);
/* Try to add this to the hashtable */
result = isc_hashmap_add(qid->table, &hashval, resp->key,
resp->keylen, resp);
if (result == ISC_R_EXISTS) {
/* Aw, try again */
continue;
}
/* Success */
ok = true;
break;
}
UNLOCK(&qid->lock);
case isc_socktype_tcp:
/*
* Try somewhat hard to find a unique ID. Start with a random
* number unless DNS_DISPATCHOPT_FIXEDID is set, in which case
* we start with the ID passed in via *idp.
*/
if (!ok) {
result = ISC_R_NOMORE;
goto fail;
qid = &disp->qid;
if ((options & DNS_DISPATCHOPT_FIXEDID) != 0) {
tries = 1;
}
LOCK(&qid->lock);
for (int i = 0; i < tries; i++) {
/* Pick new messsage ID */
if ((options & DNS_DISPATCHOPT_FIXEDID) != 0) {
id = *idp;
} else {
id = (dns_messageid_t)isc_random16();
}
/* Compute the hashtable key */
INSIST(disp->socktype == isc_socktype_udp ||
localport == 0);
resp->keylen = qid_makekey(resp->key, dest, id,
localport);
uint32_t hashval = isc_hashmap_hash(
qid->table, resp->key, resp->keylen);
/* Try to add this to the hashtable */
result = isc_hashmap_add(qid->table, &hashval,
resp->key, resp->keylen, resp);
if (result == ISC_R_EXISTS) {
/* Aw, try again */
continue;
}
/* Success */
ok = true;
break;
}
UNLOCK(&qid->lock);
if (!ok) {
result = ISC_R_NOMORE;
goto fail;
}
break;
default:
UNREACHABLE();
}
if (transport != NULL) {
@@ -1355,7 +1371,6 @@ dns_dispatch_add(dns_dispatch_t *disp, unsigned int options,
dns_dispatch_attach(disp, &resp->disp);
resp->id = id;
resp->magic = RESPONSE_MAGIC;
disp->requests++;
@@ -1517,8 +1532,6 @@ dns_dispatch_done(dns_dispentry_t **respp) {
REQUIRE(VALID_DISPATCHMGR(mgr));
qid = &mgr->qid;
LOCK(&disp->lock);
INSIST(disp->requests > 0);
disp->requests--;
@@ -1529,13 +1542,17 @@ dns_dispatch_done(dns_dispentry_t **respp) {
deactivate_dispentry(disp, resp);
LOCK(&qid->lock);
uint32_t hashval = isc_hashmap_hash(qid->table, resp->key,
resp->keylen);
isc_result_t result = isc_hashmap_delete(qid->table, &hashval,
resp->key, resp->keylen);
INSIST(result == ISC_R_SUCCESS);
UNLOCK(&qid->lock);
if (disp->socktype == isc_socktype_tcp) {
qid = &disp->qid;
LOCK(&qid->lock);
uint32_t hashval = isc_hashmap_hash(qid->table, resp->key,
resp->keylen);
isc_result_t result = isc_hashmap_delete(
qid->table, &hashval, resp->key, resp->keylen);
INSIST(result == ISC_R_SUCCESS);
UNLOCK(&qid->lock);
}
UNLOCK(&disp->lock);
dns_dispentry_detach(respp);