diff options
Diffstat (limited to 'util/netevent.c')
| -rw-r--r-- | util/netevent.c | 122 |
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) |
