aboutsummaryrefslogtreecommitdiff
path: root/util/netevent.c
diff options
context:
space:
mode:
Diffstat (limited to 'util/netevent.c')
-rw-r--r--util/netevent.c122
1 files changed, 97 insertions, 25 deletions
diff --git a/util/netevent.c b/util/netevent.c
index 3525af39aa30..a2c0e6073e36 100644
--- a/util/netevent.c
+++ b/util/netevent.c
@@ -388,8 +388,9 @@ comm_point_send_udp_msg(struct comm_point *c, sldns_buffer* packet,
} else {
verbose(VERB_OPS, "send failed: %s", sock_strerror(errno));
}
- log_addr(VERB_OPS, "remote address is",
- (struct sockaddr_storage*)addr, addrlen);
+ if(addr)
+ log_addr(VERB_OPS, "remote address is",
+ (struct sockaddr_storage*)addr, addrlen);
return 0;
} else if((size_t)sent != sldns_buffer_remaining(packet)) {
log_err("sent %d in place of %d bytes",
@@ -592,6 +593,8 @@ comm_point_send_udp_msg_if(struct comm_point *c, sldns_buffer* packet,
static int udp_recv_needs_log(int err)
{
switch(err) {
+ case EACCES: /* some hosts send ICMP 'Permission Denied' */
+#ifndef USE_WINSOCK
case ECONNREFUSED:
# ifdef ENETUNREACH
case ENETUNREACH:
@@ -605,6 +608,13 @@ static int udp_recv_needs_log(int err)
# ifdef ENETDOWN
case ENETDOWN:
# endif
+#else /* USE_WINSOCK */
+ case WSAECONNREFUSED:
+ case WSAENETUNREACH:
+ case WSAEHOSTDOWN:
+ case WSAEHOSTUNREACH:
+ case WSAENETDOWN:
+#endif
if(verbosity >= VERB_ALGO)
return 1;
return 0;
@@ -745,7 +755,8 @@ comm_point_udp_callback(int fd, short event, void* arg)
#else
if(WSAGetLastError() != WSAEINPROGRESS &&
WSAGetLastError() != WSAECONNRESET &&
- WSAGetLastError()!= WSAEWOULDBLOCK)
+ WSAGetLastError()!= WSAEWOULDBLOCK &&
+ udp_recv_needs_log(WSAGetLastError()))
log_err("recvfrom failed: %s",
wsa_strerror(WSAGetLastError()));
#endif
@@ -771,6 +782,13 @@ comm_point_udp_callback(int fd, short event, void* arg)
}
}
+int adjusted_tcp_timeout(struct comm_point* c)
+{
+ if(c->tcp_timeout_msec < TCP_QUERY_TIMEOUT_MINIMUM)
+ return TCP_QUERY_TIMEOUT_MINIMUM;
+ return c->tcp_timeout_msec;
+}
+
/** Use a new tcp handler for new query fd, set to read query */
static void
setup_tcp_handler(struct comm_point* c, int fd, int cur, int max)
@@ -804,10 +822,7 @@ setup_tcp_handler(struct comm_point* c, int fd, int cur, int max)
c->tcp_timeout_msec /= 500;
else if (handler_usage > 80)
c->tcp_timeout_msec = 0;
- comm_point_start_listening(c, fd,
- c->tcp_timeout_msec < TCP_QUERY_TIMEOUT_MINIMUM
- ? TCP_QUERY_TIMEOUT_MINIMUM
- : c->tcp_timeout_msec);
+ comm_point_start_listening(c, fd, adjusted_tcp_timeout(c));
}
void comm_base_handle_slow_accept(int ATTR_UNUSED(fd),
@@ -1117,10 +1132,11 @@ tcp_callback_writer(struct comm_point* c)
if( (*c->callback)(c, c->cb_arg, NETEVENT_PKT_WRITTEN,
&c->repinfo) ) {
comm_point_start_listening(c, -1,
- c->tcp_timeout_msec);
+ adjusted_tcp_timeout(c));
}
} else {
- comm_point_start_listening(c, -1, c->tcp_timeout_msec);
+ comm_point_start_listening(c, -1,
+ adjusted_tcp_timeout(c));
}
}
}
@@ -1141,7 +1157,8 @@ tcp_callback_reader(struct comm_point* c)
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);
+ comm_point_start_listening(c, -1,
+ adjusted_tcp_timeout(c));
}
}
}
@@ -1603,6 +1620,33 @@ comm_point_tcp_handle_read(int fd, struct comm_point* c, int short_ok)
if(errno == ECONNRESET && verbosity < 2)
return 0; /* silence reset by peer */
#endif
+#ifdef ENETUNREACH
+ if(errno == ENETUNREACH && verbosity < 2)
+ return 0; /* silence it */
+#endif
+#ifdef EHOSTDOWN
+ if(errno == EHOSTDOWN && verbosity < 2)
+ return 0; /* silence it */
+#endif
+#ifdef EHOSTUNREACH
+ if(errno == EHOSTUNREACH && verbosity < 2)
+ return 0; /* silence it */
+#endif
+#ifdef ENETDOWN
+ if(errno == ENETDOWN && verbosity < 2)
+ return 0; /* silence it */
+#endif
+#ifdef EACCES
+ if(errno == EACCES && verbosity < 2)
+ return 0; /* silence it */
+#endif
+#ifdef ENOTCONN
+ if(errno == ENOTCONN) {
+ log_err_addr("read (in tcp s) failed and this could be because TCP Fast Open is enabled [--disable-tfo-client --disable-tfo-server] but does not work", sock_strerror(errno),
+ &c->repinfo.addr, c->repinfo.addrlen);
+ return 0;
+ }
+#endif
#else /* USE_WINSOCK */
if(WSAGetLastError() == WSAECONNRESET)
return 0;
@@ -1901,7 +1945,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);
if(c->tcp_write_and_read) {
- r = send(fd, (void*)c->tcp_write_pkt + c->tcp_write_byte_count - 2,
+ 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);
} else {
r = send(fd, (void*)sldns_buffer_current(buffer),
@@ -2369,7 +2413,7 @@ http_nonchunk_segment(struct comm_point* c)
return 1;
}
-/** handle nonchunked data segment, return 0=fail, 1=wait, 2=process more */
+/** handle chunked data segment, return 0=fail, 1=wait, 2=process more */
static int
http_chunked_segment(struct comm_point* c)
{
@@ -2379,6 +2423,7 @@ http_chunked_segment(struct comm_point* c)
*/
size_t remainbufferlen;
size_t got_now = sldns_buffer_limit(c->buffer) - c->http_stored;
+ verbose(VERB_ALGO, "http_chunked_segment: got now %d, tcpbytcount %d, http_stored %d, buffer pos %d, buffer limit %d", (int)got_now, (int)c->tcp_byte_count, (int)c->http_stored, (int)sldns_buffer_position(c->buffer), (int)sldns_buffer_limit(c->buffer));
if(c->tcp_byte_count <= got_now) {
/* the chunk has completed (with perhaps some extra data
* from next chunk header and next chunk) */
@@ -2446,7 +2491,7 @@ http_chunked_segment(struct comm_point* c)
#ifdef HAVE_NGHTTP2
/** Create new http2 session. Called when creating handling comm point. */
-struct http2_session* http2_session_create(struct comm_point* c)
+static struct http2_session* http2_session_create(struct comm_point* c)
{
struct http2_session* session = calloc(1, sizeof(*session));
if(!session) {
@@ -2460,7 +2505,7 @@ struct http2_session* http2_session_create(struct comm_point* c)
#endif
/** Delete http2 session. After closing connection or on error */
-void http2_session_delete(struct http2_session* h2_session)
+static void http2_session_delete(struct http2_session* h2_session)
{
#ifdef HAVE_NGHTTP2
if(h2_session->callbacks)
@@ -2536,7 +2581,7 @@ void http2_session_add_stream(struct http2_session* h2_session,
/** remove stream from session linked list. After stream close callback or
* closing connection */
-void http2_session_remove_stream(struct http2_session* h2_session,
+static void http2_session_remove_stream(struct http2_session* h2_session,
struct http2_stream* h2_stream)
{
if(h2_stream->prev)
@@ -2662,7 +2707,7 @@ comm_point_http2_handle_read(int ATTR_UNUSED(fd), struct comm_point* c)
if(nghttp2_session_want_write(c->h2_session->session)) {
c->tcp_is_reading = 0;
comm_point_stop_listening(c);
- comm_point_start_listening(c, -1, c->tcp_timeout_msec);
+ comm_point_start_listening(c, -1, adjusted_tcp_timeout(c));
} else if(!nghttp2_session_want_read(c->h2_session->session))
return 0; /* connection can be closed */
return 1;
@@ -2718,6 +2763,11 @@ comm_point_http_handle_read(int fd, struct comm_point* c)
}
sldns_buffer_flip(c->buffer);
+ /* if we are partway in a segment of data, position us at the point
+ * where we left off previously */
+ if(c->http_stored < sldns_buffer_limit(c->buffer))
+ sldns_buffer_set_position(c->buffer, c->http_stored);
+ else sldns_buffer_set_position(c->buffer, sldns_buffer_limit(c->buffer));
while(sldns_buffer_remaining(c->buffer) > 0) {
/* Handle HTTP/1.x data */
@@ -2980,7 +3030,7 @@ comm_point_http2_handle_write(int ATTR_UNUSED(fd), struct comm_point* c)
if(nghttp2_session_want_read(c->h2_session->session)) {
c->tcp_is_reading = 1;
comm_point_stop_listening(c);
- comm_point_start_listening(c, -1, c->tcp_timeout_msec);
+ comm_point_start_listening(c, -1, adjusted_tcp_timeout(c));
} else if(!nghttp2_session_want_write(c->h2_session->session))
return 0; /* connection can be closed */
return 1;
@@ -3187,6 +3237,7 @@ comm_point_create_udp(struct comm_base *base, int fd, sldns_buffer* buffer,
comm_point_delete(c);
return NULL;
}
+ c->event_added = 1;
return c;
}
@@ -3246,6 +3297,7 @@ comm_point_create_udp_ancil(struct comm_base *base, int fd,
comm_point_delete(c);
return NULL;
}
+ c->event_added = 1;
return c;
}
@@ -3530,6 +3582,7 @@ comm_point_create_tcp(struct comm_base *base, int fd, int num,
comm_point_delete(c);
return NULL;
}
+ c->event_added = 1;
/* now prealloc the handlers */
for(i=0; i<num; i++) {
if(port_type == listen_type_tcp ||
@@ -3753,6 +3806,7 @@ comm_point_create_local(struct comm_base *base, int fd, size_t bufsize,
free(c);
return NULL;
}
+ c->event_added = 1;
return c;
}
@@ -3815,6 +3869,7 @@ comm_point_create_raw(struct comm_base* base, int fd, int writing,
free(c);
return NULL;
}
+ c->event_added = 1;
return c;
}
@@ -3825,8 +3880,11 @@ comm_point_close(struct comm_point* c)
return;
if(c->fd != -1) {
verbose(5, "comm_point_close of %d: event_del", c->fd);
- if(ub_event_del(c->ev->ev) != 0) {
- log_err("could not event_del on close");
+ if(c->event_added) {
+ if(ub_event_del(c->ev->ev) != 0) {
+ log_err("could not event_del on close");
+ }
+ c->event_added = 0;
}
}
tcl_close_connection(c->tcl_addr);
@@ -3938,11 +3996,11 @@ comm_point_send_reply(struct comm_reply *repinfo)
repinfo->c->tcp_is_reading = 0;
comm_point_stop_listening(repinfo->c);
comm_point_start_listening(repinfo->c, -1,
- repinfo->c->tcp_timeout_msec);
+ adjusted_tcp_timeout(repinfo->c));
return;
} else {
comm_point_start_listening(repinfo->c, -1,
- repinfo->c->tcp_timeout_msec);
+ adjusted_tcp_timeout(repinfo->c));
}
}
}
@@ -3975,8 +4033,11 @@ void
comm_point_stop_listening(struct comm_point* c)
{
verbose(VERB_ALGO, "comm point stop listening %d", c->fd);
- if(ub_event_del(c->ev->ev) != 0) {
- log_err("event_del error to stoplisten");
+ if(c->event_added) {
+ if(ub_event_del(c->ev->ev) != 0) {
+ log_err("event_del error to stoplisten");
+ }
+ c->event_added = 0;
}
}
@@ -3989,6 +4050,12 @@ comm_point_start_listening(struct comm_point* c, int newfd, int msec)
/* no use to start listening no free slots. */
return;
}
+ if(c->event_added) {
+ if(ub_event_del(c->ev->ev) != 0) {
+ log_err("event_del error to startlisten");
+ }
+ c->event_added = 0;
+ }
if(msec != -1 && msec != 0) {
if(!c->timeout) {
c->timeout = (struct timeval*)malloc(sizeof(
@@ -4028,13 +4095,17 @@ comm_point_start_listening(struct comm_point* c, int newfd, int msec)
if(ub_event_add(c->ev->ev, msec==0?NULL:c->timeout) != 0) {
log_err("event_add failed. in cpsl.");
}
+ c->event_added = 1;
}
void comm_point_listen_for_rw(struct comm_point* c, int rd, int wr)
{
verbose(VERB_ALGO, "comm point listen_for_rw %d %d", c->fd, wr);
- if(ub_event_del(c->ev->ev) != 0) {
- log_err("event_del error to cplf");
+ if(c->event_added) {
+ if(ub_event_del(c->ev->ev) != 0) {
+ log_err("event_del error to cplf");
+ }
+ c->event_added = 0;
}
ub_event_del_bits(c->ev->ev, UB_EV_READ|UB_EV_WRITE);
if(rd) ub_event_add_bits(c->ev->ev, UB_EV_READ);
@@ -4042,6 +4113,7 @@ void comm_point_listen_for_rw(struct comm_point* c, int rd, int wr)
if(ub_event_add(c->ev->ev, c->timeout) != 0) {
log_err("event_add failed. in cplf.");
}
+ c->event_added = 1;
}
size_t comm_point_get_mem(struct comm_point* c)