fix reuse tcp crash, use addr in reuse struct, free leaked tcp entries.

This commit is contained in:
W.C.A. Wijngaards 2020-06-24 10:09:49 +02:00
parent 6f9310173d
commit 8ca34be36a
2 changed files with 23 additions and 8 deletions

View file

@ -140,8 +140,7 @@ reuse_cmp_addrportssl(const void* key1, const void* key2)
struct reuse_tcp* r2 = (struct reuse_tcp*)key2;
int r;
/* compare address and port */
r = sockaddr_cmp(&r1->pending->query->addr, r1->pending->query->addrlen,
&r2->pending->query->addr, r2->pending->query->addrlen);
r = sockaddr_cmp(&r1->addr, r1->addrlen, &r2->addr, r2->addrlen);
if(r != 0)
return r;
@ -455,6 +454,7 @@ outnet_tcp_take_into_use(struct waiting_tcp* w)
w->outnet->tcp_free = pend->next_free;
pend->next_free = NULL;
pend->query = w;
pend->reuse.outnet = w->outnet;
pend->c->repinfo.addrlen = w->addrlen;
memcpy(&pend->c->repinfo.addr, &w->addr, w->addrlen);
pend->reuse.pending = pend;
@ -535,7 +535,7 @@ decommission_pending_tcp(struct outside_network* outnet,
comm_point_close(pend->c);
pend->next_free = outnet->tcp_free;
outnet->tcp_free = pend;
if(pend->reuse.pending) {
if(pend->reuse.node.key) {
/* needs unlink from the reuse tree to get deleted */
reuse_tcp_remove_tree_list(outnet, &pend->reuse);
}
@ -601,7 +601,7 @@ outnet_tcp_cb(struct comm_point* c, void* arg, int error,
struct comm_reply *reply_info)
{
struct pending_tcp* pend = (struct pending_tcp*)arg;
struct outside_network* outnet = pend->query->outnet;
struct outside_network* outnet = pend->reuse.outnet;
verbose(VERB_ALGO, "outnettcp cb");
if(error != NETEVENT_NOERROR) {
verbose(VERB_QUERY, "outnettcp got tcp error %d", error);
@ -612,7 +612,7 @@ outnet_tcp_cb(struct comm_point* c, void* arg, int error,
LDNS_ID_WIRE(sldns_buffer_begin(c->buffer))!=pend->id) {
log_addr(VERB_QUERY,
"outnettcp: bad ID in reply, from:",
&pend->query->addr, pend->query->addrlen);
&pend->reuse.addr, pend->reuse.addrlen);
error = NETEVENT_CLOSED;
}
}
@ -625,8 +625,12 @@ outnet_tcp_cb(struct comm_point* c, void* arg, int error,
reuse_tcp_setup_readtimeout(pend);
}
}
fptr_ok(fptr_whitelist_pending_tcp(pend->query->cb));
(void)(*pend->query->cb)(c, pend->query->cb_arg, error, reply_info);
if(pend->query) {
fptr_ok(fptr_whitelist_pending_tcp(pend->query->cb));
(void)(*pend->query->cb)(c, pend->query->cb_arg, error, reply_info);
waiting_tcp_delete(pend->query);
pend->query = NULL;
}
verbose(5, "outnet_tcp_cb reuse after cb");
if(pend->reuse.node.key) {
verbose(5, "outnet_tcp_cb reuse after cb: keep it");
@ -1467,6 +1471,9 @@ static void reuse_cb_writewait_for_failure(struct pending_tcp* pend, int err)
static void reuse_cb_readwait_for_failure(struct pending_tcp* pend, int err)
{
rbnode_type* node;
if(pend->reuse.tree_by_id.root == NULL ||
pend->reuse.tree_by_id.root == RBTREE_NULL)
return;
node = rbtree_first(&pend->reuse.tree_by_id);
while(node && node != RBTREE_NULL) {
struct waiting_tcp* w = (struct waiting_tcp*)node->key;
@ -1501,6 +1508,9 @@ static void reuse_del_readwait_elem(rbnode_type* node, void* ATTR_UNUSED(arg))
/** delete readwait waiting_tcp elements, deletes the elements in the list */
static void reuse_del_readwait(struct pending_tcp* pend)
{
if(pend->reuse.tree_by_id.root == NULL ||
pend->reuse.tree_by_id.root == RBTREE_NULL)
return;
traverse_postorder(&pend->reuse.tree_by_id, &reuse_del_readwait_elem,
NULL);
}
@ -1535,7 +1545,7 @@ outnet_tcptimer(void* arg)
/* it was in use */
struct pending_tcp* pend=(struct pending_tcp*)w->next_waiting;
/* see if it needs unlink from reuse tree */
if(pend->reuse.pending) {
if(pend->reuse.node.key) {
reuse_tcp_remove_tree_list(outnet, &pend->reuse);
}
if(pend->c->ssl) {
@ -1612,6 +1622,9 @@ reuse_tcp_find(struct outside_network* outnet, struct serviced_query* sq)
verbose(5, "reuse_tcp_find: num reuse streams %u",
(unsigned)outnet->tcp_reuse.count);
if(outnet->tcp_reuse.root == NULL ||
outnet->tcp_reuse.root == RBTREE_NULL)
return NULL;
if(rbtree_find_less_equal(&outnet->tcp_reuse, &key_p.reuse.node,
&result)) {
/* exact match */

View file

@ -271,6 +271,8 @@ struct reuse_tcp {
* They are also in the tree_by_id. Once written, the are removed
* from this list, but stay in the tree. */
struct waiting_tcp* write_wait_first, *write_wait_last;
/** the outside network it is part of */
struct outside_network* outnet;
};
/** max number of queries on a reuse connection */