From: W.C.A. Wijngaards Date: Thu, 9 Jul 2020 11:49:36 +0000 (+0200) Subject: stream reuse, check incoming messages from rbtree in outnet_tcp_cb when X-Git-Tag: release-1.13.0rc1~5^2~48 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=734a248284341603ff2885f6e17cfd639cb2c558;p=thirdparty%2Funbound.git stream reuse, check incoming messages from rbtree in outnet_tcp_cb when read a reply, and call that callback and remove that entry. --- diff --git a/services/outside_network.c b/services/outside_network.c index 95ffff935..5082f5f03 100644 --- a/services/outside_network.c +++ b/services/outside_network.c @@ -415,6 +415,28 @@ reuse_tree_by_id_insert(struct reuse_tcp* reuse, struct waiting_tcp* w) rbtree_insert(&reuse->tree_by_id, &w->id_node); } +/** find element in tree by id */ +static struct waiting_tcp* +reuse_tcp_by_id_find(struct reuse_tcp* reuse, uint16_t id) +{ + struct waiting_tcp key_w; + struct pending_tcp key_p; + memset(&key_w, 0, sizeof(key_w)); + memset(&key_p, 0, sizeof(key_p)); + key_w.next_waiting = (void*)&key_p; + key_w.id_node.key = &key_w; + key_p.id = id; + return (struct waiting_tcp*)rbtree_search(&reuse->tree_by_id, &key_w); +} + +/** return ID value of rbnode in tree_by_id */ +static uint16_t +tree_by_id_get_id(rbnode_type* node) +{ + struct waiting_tcp* w = (struct waiting_tcp*)node->key; + return ((struct pending_tcp*)w->next_waiting)->id; +} + /** find reuse tcp stream to destination for query, or NULL if none */ static struct reuse_tcp* reuse_tcp_find(struct outside_network* outnet, struct sockaddr_storage* addr, @@ -870,6 +892,7 @@ outnet_tcp_cb(struct comm_point* c, void* arg, int error, { struct pending_tcp* pend = (struct pending_tcp*)arg; struct outside_network* outnet = pend->reuse.outnet; + struct waiting_tcp* w = NULL; verbose(VERB_ALGO, "outnettcp cb"); if(error == NETEVENT_TIMEOUT) { if(pend->c->tcp_write_and_read) @@ -914,14 +937,24 @@ outnet_tcp_cb(struct comm_point* c, void* arg, int error, /* pass error below and exit */ } else { /* check ID */ - if(sldns_buffer_limit(c->buffer) < sizeof(uint16_t) || - LDNS_ID_WIRE(sldns_buffer_begin(c->buffer))!=pend->id) { + if(sldns_buffer_limit(c->buffer) < sizeof(uint16_t)) { log_addr(VERB_QUERY, - "outnettcp: bad ID in reply, from:", + "outnettcp: bad ID in reply, too short, from:", &pend->reuse.addr, pend->reuse.addrlen); error = NETEVENT_CLOSED; + } else { + uint16_t id = LDNS_ID_WIRE(sldns_buffer_begin( + c->buffer)); + /* find the query the reply is for */ + w = reuse_tcp_by_id_find(&pend->reuse, id); } } + if(!w) { + /* no struct waiting found in tree, no reply to call */ + log_addr(VERB_QUERY, "outnettcp: bad ID in reply, from:", + &pend->reuse.addr, pend->reuse.addrlen); + error = NETEVENT_CLOSED; + } if(error == NETEVENT_NOERROR) { /* add to reuse tree so it can be reused, if not a failure. * This is possible if the state machine wants to make a tcp @@ -930,11 +963,10 @@ outnet_tcp_cb(struct comm_point* c, void* arg, int error, (void)reuse_tcp_insert(outnet, pend); } } - if(pend->query) { - struct waiting_tcp* w = pend->query; - pend->query = NULL; + if(w) { reuse_tree_by_id_delete(&pend->reuse, w); - verbose(5, "outnet tcp callback query err %d buflen %d", error, (int)sldns_buffer_limit(c->buffer)); + verbose(5, "outnet tcp callback query err %d buflen %d", + error, (int)sldns_buffer_limit(c->buffer)); waiting_tcp_callback(w, c, error, reply_info); waiting_tcp_delete(w); } @@ -1851,28 +1883,6 @@ reuse_tcp_close_oldest(struct outside_network* outnet) decommission_pending_tcp(outnet, pend); } -/** find element in tree by id */ -static struct waiting_tcp* -reuse_tcp_by_id_find(struct reuse_tcp* reuse, uint16_t id) -{ - struct waiting_tcp key_w; - struct pending_tcp key_p; - memset(&key_w, 0, sizeof(key_w)); - memset(&key_p, 0, sizeof(key_p)); - key_w.next_waiting = (void*)&key_p; - key_w.id_node.key = &key_w; - key_p.id = id; - return (struct waiting_tcp*)rbtree_search(&reuse->tree_by_id, &key_w); -} - -/** return ID value of rbnode in tree_by_id */ -static uint16_t -tree_by_id_get_id(rbnode_type* node) -{ - struct waiting_tcp* w = (struct waiting_tcp*)node->key; - return ((struct pending_tcp*)w->next_waiting)->id; -} - /** find spare ID value for reuse tcp stream. That is random and also does * not collide with an existing query ID that is in use or waiting */ static uint16_t