From: W.C.A. Wijngaards Date: Fri, 10 Jul 2020 13:37:30 +0000 (+0200) Subject: fix that ssl_handle_it() uses tcp_is_reading in tcp_write_and_read mode. X-Git-Tag: release-1.13.0rc1~5^2~38 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=7a69ff41826d7835065b0a72789c5957170c6aec;p=thirdparty%2Funbound.git fix that ssl_handle_it() uses tcp_is_reading in tcp_write_and_read mode. fix that netevent tcp_write_and_read mode does not close due to error from assert that not both write and read happen at the same time. --- diff --git a/services/outside_network.c b/services/outside_network.c index af69860b5..d7db120fe 100644 --- a/services/outside_network.c +++ b/services/outside_network.c @@ -507,6 +507,9 @@ outnet_tcp_take_query_setup(int s, struct pending_tcp* pend, struct waiting_tcp* w) { struct timeval tv; + verbose(5, "outnet_tcp_take_query_setup: setup packet to write " + "len %d timeout %d msec", + (int)w->pkt_len, w->timeout); pend->c->tcp_write_pkt = w->pkt; pend->c->tcp_write_pkt_len = w->pkt_len; pend->c->tcp_write_and_read = 1; diff --git a/util/netevent.c b/util/netevent.c index 3237907d1..63150afb7 100644 --- a/util/netevent.c +++ b/util/netevent.c @@ -1434,9 +1434,17 @@ ssl_handle_write(struct comm_point* c) /** handle ssl tcp connection with dns contents */ static int -ssl_handle_it(struct comm_point* c) +ssl_handle_it(struct comm_point* c, int is_write) { - if(c->tcp_is_reading) + /* handle case where renegotiation wants read during write call + * or write during read calls */ + if(is_write && c->ssl_shake_state == comm_ssl_shake_hs_write) + return ssl_handle_read(c); + else if(!is_write && c->ssl_shake_state == comm_ssl_shake_hs_read) + return ssl_handle_write(c); + /* handle read events for read operation and write events for a + * write operation */ + else if(!is_write) return ssl_handle_read(c); return ssl_handle_write(c); } @@ -1452,9 +1460,10 @@ comm_point_tcp_handle_read(int fd, struct comm_point* c, int short_ok) { ssize_t r; log_assert(c->type == comm_tcp || c->type == comm_local); + verbose(5, "comm point tcp handle read fd %d", fd); if(c->ssl) - return ssl_handle_it(c); - if(!c->tcp_is_reading) + return ssl_handle_it(c, 0); + if(!c->tcp_is_reading && !c->tcp_write_and_read) return 0; log_assert(fd != -1); @@ -1563,8 +1572,10 @@ comm_point_tcp_handle_write(int fd, struct comm_point* c) #else buffer = c->buffer; #endif - if(c->tcp_is_reading && !c->ssl) + verbose(5, "comm point tcp handle write fd %d", fd); + if(c->tcp_is_reading && !c->ssl && !c->tcp_write_and_read) return 0; + verbose(5, "comm point tcp handle write fd %d, part2", fd); log_assert(fd != -1); if(((!c->tcp_write_and_read && c->tcp_byte_count == 0) || (c->tcp_write_and_read && c->tcp_write_byte_count == 0)) && c->tcp_check_nb_connect) { /* check for pending error from nonblocking connect */ @@ -1606,8 +1617,10 @@ comm_point_tcp_handle_write(int fd, struct comm_point* c) return 0; } } + verbose(5, "comm point tcp handle write fd %d, part3", fd); if(c->ssl) - return ssl_handle_it(c); + return ssl_handle_it(c, 1); + verbose(5, "comm point tcp handle write fd %d, part4", fd); #ifdef USE_MSG_FASTOPEN /* Only try this on first use of a connection that uses tfo, @@ -1696,6 +1709,7 @@ comm_point_tcp_handle_write(int fd, struct comm_point* c) } #endif /* USE_MSG_FASTOPEN */ + verbose(5, "comm point tcp handle write fd %d: before write", fd); if((c->tcp_write_and_read?c->tcp_write_byte_count:c->tcp_byte_count) < sizeof(uint16_t)) { uint16_t len = htons(c->tcp_write_and_read?c->tcp_write_pkt_len:sldns_buffer_limit(buffer)); #ifdef HAVE_WRITEV @@ -1722,6 +1736,7 @@ comm_point_tcp_handle_write(int fd, struct comm_point* c) sizeof(uint16_t)-c->tcp_byte_count, 0); } #endif /* HAVE_WRITEV */ + verbose(5, "comm point tcp handle write fd %d: write res %d", fd, (int)r); if(r == -1) { #ifndef USE_WINSOCK # ifdef EPIPE @@ -1777,6 +1792,7 @@ comm_point_tcp_handle_write(int fd, struct comm_point* c) } log_assert(c->tcp_write_and_read || sldns_buffer_remaining(buffer) > 0); log_assert(!c->tcp_write_and_read || c->tcp_write_byte_count < c->tcp_write_pkt_len + 2); + verbose(5, "comm point tcp handle write fd %d: before write remain", fd); if(c->tcp_write_and_read) { r = send(fd, (void*)c->tcp_write_pkt + c->tcp_write_byte_count - 2, c->tcp_write_pkt_len + 2 - c->tcp_write_byte_count, 0); @@ -1784,6 +1800,7 @@ comm_point_tcp_handle_write(int fd, struct comm_point* c) r = send(fd, (void*)sldns_buffer_current(buffer), sldns_buffer_remaining(buffer), 0); } + verbose(5, "comm point tcp handle write fd %d: write remain res %d", fd, (int)r); if(r == -1) { #ifndef USE_WINSOCK if(errno == EINTR || errno == EAGAIN)