summaryrefslogtreecommitdiff
path: root/sbin/unwind/libunbound/util/netevent.c
diff options
context:
space:
mode:
authorStuart Henderson <sthen@cvs.openbsd.org>2019-02-08 10:35:15 +0000
committerStuart Henderson <sthen@cvs.openbsd.org>2019-02-08 10:35:15 +0000
commit386ccca312e01e4309f25858a2bef1b850e6b5a9 (patch)
tree639d15679f00af3ffe0cd77e0019b334f4f20f8e /sbin/unwind/libunbound/util/netevent.c
parent801d50e5b54dd7bd2ba3c2a14ca821f84009f4c9 (diff)
update unwind's copy of libunbound to match the new 1.9.0 update in
/usr/src/usr.sbin/unbound, diff from florian@
Diffstat (limited to 'sbin/unwind/libunbound/util/netevent.c')
-rw-r--r--sbin/unwind/libunbound/util/netevent.c101
1 files changed, 89 insertions, 12 deletions
diff --git a/sbin/unwind/libunbound/util/netevent.c b/sbin/unwind/libunbound/util/netevent.c
index 37353804142..a507faf7e41 100644
--- a/sbin/unwind/libunbound/util/netevent.c
+++ b/sbin/unwind/libunbound/util/netevent.c
@@ -50,6 +50,7 @@
#include "sldns/str2wire.h"
#include "dnstap/dnstap.h"
#include "dnscrypt/dnscrypt.h"
+#include "services/listen_dnsport.h"
#ifdef HAVE_OPENSSL_SSL_H
#include <openssl/ssl.h>
#endif
@@ -150,7 +151,8 @@ struct internal_signal {
/** create a tcp handler with a parent */
static struct comm_point* comm_point_create_tcp_handler(
struct comm_base *base, struct comm_point* parent, size_t bufsize,
- comm_point_callback_type* callback, void* callback_arg);
+ struct sldns_buffer* spoolbuf, comm_point_callback_type* callback,
+ void* callback_arg);
/* -------- End of local definitions -------- */
@@ -988,7 +990,11 @@ tcp_callback_writer(struct comm_point* c)
c->tcp_byte_count = 0;
/* switch from listening(write) to listening(read) */
comm_point_stop_listening(c);
- comm_point_start_listening(c, -1, -1);
+ if(c->tcp_req_info) {
+ tcp_req_info_handle_writedone(c->tcp_req_info);
+ } else {
+ comm_point_start_listening(c, -1, -1);
+ }
}
/** do the callback when reading is done */
@@ -1002,9 +1008,13 @@ tcp_callback_reader(struct comm_point* c)
c->tcp_byte_count = 0;
if(c->type == comm_tcp)
comm_point_stop_listening(c);
- fptr_ok(fptr_whitelist_comm_point(c->callback));
- if( (*c->callback)(c, c->cb_arg, NETEVENT_NOERROR, &c->repinfo) ) {
- comm_point_start_listening(c, -1, c->tcp_timeout_msec);
+ if(c->tcp_req_info) {
+ tcp_req_info_handle_readdone(c->tcp_req_info);
+ } else {
+ fptr_ok(fptr_whitelist_comm_point(c->callback));
+ if( (*c->callback)(c, c->cb_arg, NETEVENT_NOERROR, &c->repinfo) ) {
+ comm_point_start_listening(c, -1, c->tcp_timeout_msec);
+ }
}
}
@@ -1163,6 +1173,8 @@ ssl_handle_read(struct comm_point* c)
c->tcp_byte_count))) <= 0) {
int want = SSL_get_error(c->ssl, r);
if(want == SSL_ERROR_ZERO_RETURN) {
+ if(c->tcp_req_info)
+ return tcp_req_info_handle_read_close(c->tcp_req_info);
return 0; /* shutdown, closed */
} else if(want == SSL_ERROR_WANT_READ) {
ub_winsock_tcp_wouldblock(c->ev->ev, UB_EV_READ);
@@ -1205,6 +1217,8 @@ ssl_handle_read(struct comm_point* c)
if(r <= 0) {
int want = SSL_get_error(c->ssl, r);
if(want == SSL_ERROR_ZERO_RETURN) {
+ if(c->tcp_req_info)
+ return tcp_req_info_handle_read_close(c->tcp_req_info);
return 0; /* shutdown, closed */
} else if(want == SSL_ERROR_WANT_READ) {
ub_winsock_tcp_wouldblock(c->ev->ev, UB_EV_READ);
@@ -1365,9 +1379,11 @@ comm_point_tcp_handle_read(int fd, struct comm_point* c, int short_ok)
/* read length bytes */
r = recv(fd,(void*)sldns_buffer_at(c->buffer,c->tcp_byte_count),
sizeof(uint16_t)-c->tcp_byte_count, 0);
- if(r == 0)
+ if(r == 0) {
+ if(c->tcp_req_info)
+ return tcp_req_info_handle_read_close(c->tcp_req_info);
return 0;
- else if(r == -1) {
+ } else if(r == -1) {
#ifndef USE_WINSOCK
if(errno == EINTR || errno == EAGAIN)
return 1;
@@ -1416,6 +1432,8 @@ comm_point_tcp_handle_read(int fd, struct comm_point* c, int short_ok)
r = recv(fd, (void*)sldns_buffer_current(c->buffer),
sldns_buffer_remaining(c->buffer), 0);
if(r == 0) {
+ if(c->tcp_req_info)
+ return tcp_req_info_handle_read_close(c->tcp_req_info);
return 0;
} else if(r == -1) {
#ifndef USE_WINSOCK
@@ -1669,6 +1687,29 @@ comm_point_tcp_handle_write(int fd, struct comm_point* c)
return 1;
}
+/** read again to drain buffers when there could be more to read */
+static void
+tcp_req_info_read_again(int fd, struct comm_point* c)
+{
+ while(c->tcp_req_info->read_again) {
+ int r;
+ c->tcp_req_info->read_again = 0;
+ if(c->tcp_is_reading)
+ r = comm_point_tcp_handle_read(fd, c, 0);
+ else r = comm_point_tcp_handle_write(fd, c);
+ if(!r) {
+ reclaim_tcp_handler(c);
+ if(!c->tcp_do_close) {
+ fptr_ok(fptr_whitelist_comm_point(
+ c->callback));
+ (void)(*c->callback)(c, c->cb_arg,
+ NETEVENT_CLOSED, NULL);
+ }
+ return;
+ }
+ }
+}
+
void
comm_point_tcp_handle_callback(int fd, short event, void* arg)
{
@@ -1698,6 +1739,7 @@ comm_point_tcp_handle_callback(int fd, short event, void* arg)
#endif
if(event&UB_EV_READ) {
+ int has_tcpq = (c->tcp_req_info != NULL);
if(!comm_point_tcp_handle_read(fd, c, 0)) {
reclaim_tcp_handler(c);
if(!c->tcp_do_close) {
@@ -1707,9 +1749,12 @@ comm_point_tcp_handle_callback(int fd, short event, void* arg)
NETEVENT_CLOSED, NULL);
}
}
+ if(has_tcpq && c->tcp_req_info && c->tcp_req_info->read_again)
+ tcp_req_info_read_again(fd, c);
return;
}
if(event&UB_EV_WRITE) {
+ int has_tcpq = (c->tcp_req_info != NULL);
if(!comm_point_tcp_handle_write(fd, c)) {
reclaim_tcp_handler(c);
if(!c->tcp_do_close) {
@@ -1719,6 +1764,8 @@ comm_point_tcp_handle_callback(int fd, short event, void* arg)
NETEVENT_CLOSED, NULL);
}
}
+ if(has_tcpq && c->tcp_req_info && c->tcp_req_info->read_again)
+ tcp_req_info_read_again(fd, c);
return;
}
if(event&UB_EV_TIMEOUT) {
@@ -2523,7 +2570,8 @@ comm_point_create_udp_ancil(struct comm_base *base, int fd,
static struct comm_point*
comm_point_create_tcp_handler(struct comm_base *base,
struct comm_point* parent, size_t bufsize,
- comm_point_callback_type* callback, void* callback_arg)
+ struct sldns_buffer* spoolbuf, comm_point_callback_type* callback,
+ void* callback_arg)
{
struct comm_point* c = (struct comm_point*)calloc(1,
sizeof(struct comm_point));
@@ -2579,6 +2627,20 @@ comm_point_create_tcp_handler(struct comm_base *base,
c->repinfo.c = c;
c->callback = callback;
c->cb_arg = callback_arg;
+ if(spoolbuf) {
+ c->tcp_req_info = tcp_req_info_create(spoolbuf);
+ if(!c->tcp_req_info) {
+ log_err("could not create tcp commpoint");
+ sldns_buffer_free(c->buffer);
+ free(c->timeout);
+ free(c->ev);
+ free(c);
+ return NULL;
+ }
+ c->tcp_req_info->cp = c;
+ c->tcp_do_close = 1;
+ c->tcp_do_toggle_rw = 0;
+ }
/* add to parent free list */
c->tcp_free = parent->tcp_free;
parent->tcp_free = c;
@@ -2590,6 +2652,9 @@ comm_point_create_tcp_handler(struct comm_base *base,
{
log_err("could not basetset tcphdl event");
parent->tcp_free = c->tcp_free;
+ tcp_req_info_delete(c->tcp_req_info);
+ sldns_buffer_free(c->buffer);
+ free(c->timeout);
free(c->ev);
free(c);
return NULL;
@@ -2600,7 +2665,8 @@ comm_point_create_tcp_handler(struct comm_base *base,
struct comm_point*
comm_point_create_tcp(struct comm_base *base, int fd, int num,
int idle_timeout, struct tcl_list* tcp_conn_limit, size_t bufsize,
- comm_point_callback_type* callback, void* callback_arg)
+ struct sldns_buffer* spoolbuf, comm_point_callback_type* callback,
+ void* callback_arg)
{
struct comm_point* c = (struct comm_point*)calloc(1,
sizeof(struct comm_point));
@@ -2667,7 +2733,7 @@ comm_point_create_tcp(struct comm_base *base, int fd, int num,
/* now prealloc the tcp handlers */
for(i=0; i<num; i++) {
c->tcp_handlers[i] = comm_point_create_tcp_handler(base,
- c, bufsize, callback, callback_arg);
+ c, bufsize, spoolbuf, callback, callback_arg);
if(!c->tcp_handlers[i]) {
comm_point_delete(c);
return NULL;
@@ -2949,6 +3015,8 @@ comm_point_close(struct comm_point* c)
}
}
tcl_close_connection(c->tcl_addr);
+ if(c->tcp_req_info)
+ tcp_req_info_clear(c->tcp_req_info);
/* close fd after removing from event lists, or epoll.. is messed up */
if(c->fd != -1 && !c->do_not_close) {
if(c->type == comm_tcp || c->type == comm_http) {
@@ -2992,6 +3060,9 @@ comm_point_delete(struct comm_point* c)
sldns_buffer_free(c->dnscrypt_buffer);
}
#endif
+ if(c->tcp_req_info) {
+ tcp_req_info_delete(c->tcp_req_info);
+ }
}
ub_event_free(c->ev->ev);
free(c->ev);
@@ -3032,8 +3103,12 @@ comm_point_send_reply(struct comm_reply *repinfo)
dt_msg_send_client_response(repinfo->c->tcp_parent->dtenv,
&repinfo->addr, repinfo->c->type, repinfo->c->buffer);
#endif
- comm_point_start_listening(repinfo->c, -1,
- repinfo->c->tcp_timeout_msec);
+ if(repinfo->c->tcp_req_info) {
+ tcp_req_info_send_reply(repinfo->c->tcp_req_info);
+ } else {
+ comm_point_start_listening(repinfo->c, -1,
+ repinfo->c->tcp_timeout_msec);
+ }
}
}
@@ -3046,6 +3121,8 @@ comm_point_drop_reply(struct comm_reply* repinfo)
log_assert(repinfo->c->type != comm_tcp_accept);
if(repinfo->c->type == comm_udp)
return;
+ if(repinfo->c->tcp_req_info)
+ repinfo->c->tcp_req_info->is_drop = 1;
reclaim_tcp_handler(repinfo->c);
}