From a0c313412dbc5c152fe78eb93cf092f99d109ef9 Mon Sep 17 00:00:00 2001 From: Jim Hague Date: Wed, 4 Oct 2017 17:31:33 +0100 Subject: [PATCH 01/10] Adjust Unix socket/Winsock handling. Centralise it into util-internal.h, remove duplicate definitions from mdns, and add new pseudo-functions _getdns_closesocket(), _getdns_poll() and _getdns_socketerror(). Convert error values to simple values and convert error checking to use _getdns_socketerror() and the simple values. The simple values can also be used with the result from getsockopt() with SO_ERROR in stub.c. --- src/anchor.c | 8 ++-- src/context.c | 12 +---- src/extension/poll_eventloop.c | 12 +---- src/mdns.c | 72 +++++------------------------ src/mdns.h | 5 +- src/server.c | 31 +++---------- src/stub.c | 84 ++++++++-------------------------- src/util-internal.h | 42 ++++++++++++++--- 8 files changed, 81 insertions(+), 185 deletions(-) diff --git a/src/anchor.c b/src/anchor.c index d37cdec4..6872ab18 100644 --- a/src/anchor.c +++ b/src/anchor.c @@ -1198,7 +1198,7 @@ static void tas_read_cb(void *userarg) return; } } - } else if (_getdns_EWOULDBLOCK) + } else if (_getdns_socketerror() == _getdns_EWOULDBLOCK) return; DEBUG_ANCHOR("Read error: %d %s\n", (int)n, strerror(errno)); @@ -1248,7 +1248,7 @@ static void tas_write_cb(void *userarg) tas_read_cb, NULL, tas_timeout_cb)); return; - } else if (_getdns_EWOULDBLOCK || _getdns_EINPROGRESS) + } else if (_getdns_socketerror() == _getdns_EWOULDBLOCK || _getdns_socketerror() == _getdns_EINPROGRESS) return; DEBUG_ANCHOR("Write error: %s\n", strerror(errno)); @@ -1348,8 +1348,8 @@ static void tas_connect(getdns_context *context, tas_connection *a) addr.sin6_scope_id = 0; r = connect(a->fd, (struct sockaddr *)&addr, sizeof(addr)); } - if (r == 0 || (r == -1 && (_getdns_EINPROGRESS || - _getdns_EWOULDBLOCK))) { + if (r == 0 || (r == -1 && (_getdns_socketerror() == _getdns_EINPROGRESS || + _getdns_socketerror() == _getdns_EWOULDBLOCK))) { char tas_hostname[256]; const char *path = "", *fmt; getdns_return_t R; diff --git a/src/context.c b/src/context.c index ada3e7bd..9b43ff76 100644 --- a/src/context.c +++ b/src/context.c @@ -704,11 +704,7 @@ _getdns_upstreams_dereference(getdns_upstreams *upstreams) } if (upstream->fd != -1) { -#ifdef USE_WINSOCK - closesocket(upstream->fd); -#else - close(upstream->fd); -#endif + _getdns_closesocket(upstream->fd); } while (pin) { sha256_pin_t *nextpin = pin->next; @@ -809,11 +805,7 @@ _getdns_upstream_reset(getdns_upstream *upstream) upstream->tls_obj = NULL; } if (upstream->fd != -1) { -#ifdef USE_WINSOCK - closesocket(upstream->fd); -#else - close(upstream->fd); -#endif + _getdns_closesocket(upstream->fd); upstream->fd = -1; } /* Set connection ready for use again*/ diff --git a/src/extension/poll_eventloop.c b/src/extension/poll_eventloop.c index b4f204b1..b0793e7c 100644 --- a/src/extension/poll_eventloop.c +++ b/src/extension/poll_eventloop.c @@ -27,13 +27,7 @@ #include "config.h" -#ifdef HAVE_SYS_POLL_H -#include -#else -#ifndef USE_WINSOCK -#include -#endif -#endif +#include "util-internal.h" #ifdef HAVE_SYS_RESOURCE_H #include #endif @@ -411,10 +405,8 @@ poll_eventloop_run_once(getdns_eventloop *loop, int blocking) { Sleep(poll_timeout); } else - if (WSAPoll(poll_loop->pfds, poll_loop->fd_events_free, poll_timeout) < 0) { -#else - if (poll(poll_loop->pfds, poll_loop->fd_events_free, poll_timeout) < 0) { #endif + if (poll(poll_loop->pfds, poll_loop->fd_events_free, poll_timeout) < 0) { perror("poll() failed"); exit(EXIT_FAILURE); } diff --git a/src/mdns.c b/src/mdns.c index 073c48cb..3d5efe6e 100644 --- a/src/mdns.c +++ b/src/mdns.c @@ -30,24 +30,6 @@ #ifdef HAVE_MDNS_SUPPORT -#ifdef USE_WINSOCK -typedef u_short sa_family_t; -#define _getdns_EWOULDBLOCK (WSAGetLastError() == WSATRY_AGAIN ||\ - WSAGetLastError() == WSAEWOULDBLOCK) -#define _getdns_EINPROGRESS (WSAGetLastError() == WSAEINPROGRESS) -#else -#define _getdns_EWOULDBLOCK (errno == EAGAIN || errno == EWOULDBLOCK) -#define _getdns_EINPROGRESS (errno == EINPROGRESS) -#define SOCKADDR struct sockaddr -#define SOCKADDR_IN struct sockaddr_in -#define SOCKADDR_IN6 struct sockaddr_in6 -#define SOCKET int -#define IP_MREQ struct ip_mreq -#define IPV6_MREQ struct ipv6_mreq -#define BOOL int -#define TRUE 1 -#endif - /* Define IPV6_ADD_MEMBERSHIP for FreeBSD and Mac OS X */ #ifndef IPV6_ADD_MEMBERSHIP #define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP @@ -1148,7 +1130,8 @@ mdns_udp_multicast_read_cb(void *userarg) sizeof(cnx->response), 0, NULL, NULL); - if (read == -1 && _getdns_EWOULDBLOCK) + if (read == -1 && (_getdns_socketerror() == _getdns_EWOULDBLOCK || + _getdns_socketerror() == _getdns_ECONNRESET) return; /* TODO: this will stop the receive loop! */ if (read >= GLDNS_HEADER_SIZE) @@ -1353,11 +1336,7 @@ static int mdns_open_ipv4_multicast(SOCKADDR_STORAGE* mcast_dest, int* mcast_des if (ret != 0 && fd4 != -1) { -#ifdef USE_WINSOCK - closesocket(fd4); -#else - close(fd4); -#endif + _getdns_closesocket(fd4); fd4 = -1; } @@ -1428,11 +1407,7 @@ static int mdns_open_ipv6_multicast(SOCKADDR_STORAGE* mcast_dest, int* mcast_des if (ret != 0 && fd6 != -1) { -#ifdef USE_WINSOCK - closesocket(fd6); -#else - close(fd6); -#endif + _getdns_closesocket(fd6); fd6 = -1; } @@ -1514,11 +1489,7 @@ static getdns_return_t mdns_delayed_network_init(struct getdns_context *context) GETDNS_CLEAR_EVENT(context->extension , &context->mdns_connection[i].event); -#ifdef USE_WINSOCK - closesocket(context->mdns_connection[i].fd); -#else - close(context->mdns_connection[i].fd); -#endif + _getdns_closesocket(context->mdns_connection[i].fd); } } @@ -1657,11 +1628,7 @@ void _getdns_mdns_context_destroy(struct getdns_context *context) /* suppress the receive event */ GETDNS_CLEAR_EVENT(context->extension, &context->mdns_connection[i].event); /* close the socket */ -#ifdef USE_WINSOCK - closesocket(context->mdns_connection[i].fd); -#else - close(context->mdns_connection[i].fd); -#endif + _getdns_closesocket(context->mdns_connection[i].fd); } GETDNS_FREE(context->mf, context->mdns_connection); @@ -1686,11 +1653,7 @@ _getdns_cancel_mdns_request(getdns_network_req *netreq) { mdns_cleanup(netreq); if (netreq->fd >= 0) { -#ifdef USE_WINSOCK - closesocket(netreq->fd); -#else - close(netreq->fd); -#endif + _getdns_closesocket(netreq->fd); } } @@ -1706,11 +1669,7 @@ mdns_timeout_cb(void *userarg) /* Check the required cleanup */ mdns_cleanup(netreq); if (netreq->fd >= 0) -#ifdef USE_WINSOCK - closesocket(netreq->fd); -#else - close(netreq->fd); -#endif + _getdns_closesocket(netreq->fd); _getdns_netreq_change_state(netreq, NET_REQ_TIMED_OUT); if (netreq->owner->user_callback) { netreq->debug_end_time = _getdns_get_time_as_uintt64(); @@ -1745,7 +1704,8 @@ mdns_udp_read_cb(void *userarg) * i.e. overflow */ 0, NULL, NULL); - if (read == -1 && _getdns_EWOULDBLOCK) + if (read == -1 && (_getdns_socketerror() == _getdns_EWOULDBLOCK || + _getdns_socketerror() == _getdns_ECONNRESET) return; if (read < GLDNS_HEADER_SIZE) @@ -1759,11 +1719,7 @@ mdns_udp_read_cb(void *userarg) // TODO: check that the source address originates from the local network. // TODO: check TTL = 255 -#ifdef USE_WINSOCK - closesocket(netreq->fd); -#else - close(netreq->fd); -#endif + _getdns_closesocket(netreq->fd); /* * TODO: how to handle an MDNS response with TC bit set? * Ignore it for now, as we do not support any kind of TCP fallback @@ -1814,11 +1770,7 @@ mdns_udp_write_cb(void *userarg) netreq->fd, (const void *)netreq->query, pkt_len, 0, (struct sockaddr *)&mdns_mcast_v4, sizeof(mdns_mcast_v4))) { -#ifdef USE_WINSOCK - closesocket(netreq->fd); -#else - close(netreq->fd); -#endif + _getdns_closesocket(netreq->fd); return; } GETDNS_SCHEDULE_EVENT( diff --git a/src/mdns.h b/src/mdns.h index b7c7d20c..e53f79a1 100644 --- a/src/mdns.h +++ b/src/mdns.h @@ -24,13 +24,10 @@ #ifdef HAVE_MDNS_SUPPORT #include "getdns/getdns.h" #include "types-internal.h" +#include "util-internal.h" #include "util/lruhash.h" #include "config.h" -#ifndef USE_WINSOCK -#define SOCKADDR_STORAGE struct sockaddr_storage -#endif - getdns_return_t _getdns_submit_mdns_request(getdns_network_req *netreq); diff --git a/src/server.c b/src/server.c index ab986a41..68b6d09d 100644 --- a/src/server.c +++ b/src/server.c @@ -39,6 +39,7 @@ #include "types-internal.h" #include "debug.h" #include "util/rbtree.h" +#include "util-internal.h" #include "server.h" #define DNS_REQUEST_SZ 4096 @@ -135,11 +136,7 @@ static void tcp_connection_destroy(tcp_connection *conn) loop->vmt->clear(loop, &conn->event); if (conn->fd >= 0) -#ifdef USE_WINSOCK - (void) closesocket(conn->fd); -#else - (void) close(conn->fd); -#endif + (void) _getdns_closesocket(conn->fd); GETDNS_FREE(*mf, conn->read_buf); for (cur = conn->to_write; cur; cur = next) { @@ -285,11 +282,7 @@ getdns_reply( (struct sockaddr *)&conn->remote_in, conn->addrlen) == -1) { /* IO error, cleanup this listener */ loop->vmt->clear(loop, &conn->l->event); -#ifdef USE_WINSOCK - closesocket(conn->l->fd); -#else - close(conn->l->fd); -#endif + _getdns_closesocket(conn->l->fd); conn->l->fd = -1; } /* Unlink this connection */ @@ -483,11 +476,7 @@ static void tcp_accept_cb(void *userarg) &conn->super.remote_in, &conn->super.addrlen)) == -1) { /* IO error, cleanup this listener */ loop->vmt->clear(loop, &l->event); -#ifdef USE_WINSOCK - closesocket(l->fd); -#else - close(l->fd); -#endif + _getdns_closesocket(l->fd); l->fd = -1; GETDNS_FREE(*mf, conn); return; @@ -557,11 +546,7 @@ static void udp_read_cb(void *userarg) (struct sockaddr *)&conn->remote_in, &conn->addrlen)) == -1) { /* IO error, cleanup this listener. */ loop->vmt->clear(loop, &l->event); -#ifdef USE_WINSOCK - closesocket(l->fd); -#else - close(l->fd); -#endif + _getdns_closesocket(l->fd); l->fd = -1; #if 0 && defined(SERVER_DEBUG) && SERVER_DEBUG @@ -710,11 +695,7 @@ static void remove_listeners(listen_set *set) continue; loop->vmt->clear(loop, &l->event); -#ifdef USE_WINSOCK - closesocket(l->fd); -#else - close(l->fd); -#endif + _getdns_closesocket(l->fd); l->fd = -1; if (l->transport != GETDNS_TRANSPORT_TCP) diff --git a/src/stub.c b/src/stub.c index 1d16c4bb..4674356c 100644 --- a/src/stub.c +++ b/src/stub.c @@ -38,17 +38,6 @@ */ #define INTERCEPT_COM_DS 0 -#ifdef USE_POLL_DEFAULT_EVENTLOOP -# ifdef HAVE_SYS_POLL_H -# include -# else -#ifdef USE_WINSOCK -#define poll(fdarray, nbsockets, timer) WSAPoll(fdarray, nbsockets, timer) -#else -# include -#endif -# endif -#endif #include "debug.h" #include #include @@ -426,13 +415,10 @@ tcp_connect(getdns_upstream *upstream, getdns_transport_list_t transport) #endif if (connect(fd, (struct sockaddr *)&upstream->addr, upstream->addr_len) == -1) { - if (_getdns_EINPROGRESS || _getdns_EWOULDBLOCK) + if (_getdns_socketerror() == _getdns_EINPROGRESS || + _getdns_socketerror() == _getdns_EWOULDBLOCK) return fd; -#ifdef USE_WINSOCK - closesocket(fd); -#else - close(fd); -#endif + _getdns_closesocket(fd); return -1; } return fd; @@ -443,22 +429,13 @@ tcp_connected(getdns_upstream *upstream) { int error = 0; socklen_t len = (socklen_t)sizeof(error); getsockopt(upstream->fd, SOL_SOCKET, SO_ERROR, (void*)&error, &len); -#ifdef USE_WINSOCK - if (error == WSAEINPROGRESS) + if (error == _getdns_EINPROGRESS) return STUB_TCP_AGAIN; - else if (error == WSAEWOULDBLOCK) - return STUB_TCP_WOULDBLOCK; - else if (error != 0) - return STUB_SETUP_ERROR; -#else - if (error == EINPROGRESS) - return STUB_TCP_AGAIN; - else if (error == EWOULDBLOCK || error == EAGAIN) + else if (error == _getdns_EWOULDBLOCK || error == _getdns_EAGAIN) return STUB_TCP_WOULDBLOCK; else if (error != 0) { return STUB_SETUP_ERROR; } -#endif if (upstream->transport == GETDNS_TRANSPORT_TCP && upstream->queries_sent == 0) { upstream->conn_state = GETDNS_CONN_OPEN; @@ -570,11 +547,7 @@ _getdns_cancel_stub_request(getdns_network_req *netreq) STUB_DEBUG_CLEANUP, __FUNC__, (void*)netreq); stub_cleanup(netreq); if (netreq->fd >= 0) { -#ifdef USE_WINSOCK - closesocket(netreq->fd); -#else - close(netreq->fd); -#endif + _getdns_closesocket(netreq->fd); netreq->fd = -1; } } @@ -589,11 +562,7 @@ stub_timeout_cb(void *userarg) _getdns_netreq_change_state(netreq, NET_REQ_TIMED_OUT); /* Handle upstream*/ if (netreq->fd >= 0) { -#ifdef USE_WINSOCK - closesocket(netreq->fd); -#else - close(netreq->fd); -#endif + _getdns_closesocket(netreq->fd); netreq->fd = -1; netreq->upstream->udp_timeouts++; if (netreq->upstream->udp_timeouts % 100 == 0) @@ -650,7 +619,7 @@ upstream_setup_timeout_cb(void *userarg) #ifdef USE_POLL_DEFAULT_EVENTLOOP fds.fd = upstream->fd; fds.events = POLLOUT; - ret = poll(&fds, 1, 0); + ret = _getdns_poll(&fds, 1, 0); #else FD_ZERO(&fds); FD_SET((int)(upstream->fd), &fds); @@ -690,7 +659,7 @@ stub_tcp_read(int fd, getdns_tcp_state *tcp, struct mem_funcs *mf) } read = recv(fd, (void *)tcp->read_pos, tcp->to_read, 0); if (read < 0) { - if (_getdns_EWOULDBLOCK) + if (_getdns_socketerror() == _getdns_EWOULDBLOCK) return STUB_TCP_WOULDBLOCK; else return STUB_TCP_ERROR; @@ -807,11 +776,11 @@ stub_tcp_write(int fd, getdns_tcp_state *tcp, getdns_network_req *netreq) (struct sockaddr *)&(netreq->upstream->addr), netreq->upstream->addr_len); #endif - if ((written < 0 && (_getdns_EWOULDBLOCK || + if ((written < 0 && (_getdns_socketerror() == _getdns_EWOULDBLOCK || /* Add the error case where the connection is in progress which is when a cookie is not available (e.g. when doing the first request to an upstream). We must let the handshake complete since non-blocking. */ - _getdns_EINPROGRESS)) || + _getdns_socketerror() == _getdns_EINPROGRESS)) || (size_t)written < pkt_len + 2) { /* We couldn't write the whole packet. @@ -847,7 +816,7 @@ stub_tcp_write(int fd, getdns_tcp_state *tcp, getdns_network_req *netreq) tcp->write_buf_len - tcp->written); #endif if (written == -1) { - if (_getdns_EWOULDBLOCK) + if (_getdns_socketerror() == _getdns_EWOULDBLOCK) return STUB_TCP_WOULDBLOCK; else { DEBUG_STUB("%s %-35s: MSG: %p error while writing to TCP socket:" @@ -1386,7 +1355,8 @@ stub_udp_read_cb(void *userarg) * i.e. overflow */ 0, NULL, NULL); - if (read == -1 && _getdns_EWOULDBLOCK) + if (read == -1 && (_getdns_socketerror() == _getdns_EWOULDBLOCK || + _getdns_socketerror() == _getdns_ECONNRESET)) return; /* Try again later */ if (read == -1) { @@ -1398,11 +1368,7 @@ stub_udp_read_cb(void *userarg) _getdns_netreq_change_state(netreq, NET_REQ_ERRORED); /* Handle upstream*/ if (netreq->fd >= 0) { -#ifdef USE_WINSOCK - closesocket(netreq->fd); -#else - close(netreq->fd); -#endif + _getdns_closesocket(netreq->fd); netreq->fd = -1; stub_next_upstream(netreq); } @@ -1422,11 +1388,7 @@ stub_udp_read_cb(void *userarg) GETDNS_CLEAR_EVENT(dnsreq->loop, &netreq->event); -#ifdef USE_WINSOCK - closesocket(netreq->fd); -#else - close(netreq->fd); -#endif + _getdns_closesocket(netreq->fd); netreq->fd = -1; while (GLDNS_TC_WIRE(netreq->response)) { DEBUG_STUB("%s %-35s: MSG: %p TC bit set in response \n", STUB_DEBUG_READ, @@ -1519,11 +1481,7 @@ stub_udp_write_cb(void *userarg) _getdns_netreq_change_state(netreq, NET_REQ_ERRORED); /* Handle upstream*/ if (netreq->fd >= 0) { -#ifdef USE_WINSOCK - closesocket(netreq->fd); -#else - close(netreq->fd); -#endif + _getdns_closesocket(netreq->fd); netreq->fd = -1; stub_next_upstream(netreq); } @@ -2055,11 +2013,7 @@ upstream_connect(getdns_upstream *upstream, getdns_transport_list_t transport, if (upstream->tls_obj == NULL) { upstream_failed(upstream, 1); _getdns_upstream_reset(upstream); -#ifdef USE_WINSOCK - closesocket(fd); -#else - close(fd); -#endif + _getdns_closesocket(fd); return -1; } upstream->tls_hs_state = GETDNS_HS_WRITE; @@ -2128,7 +2082,7 @@ upstream_find_for_netreq(getdns_network_req *netreq) continue; if (fd == -1) { - if (_getdns_EMFILE) + if (_getdns_socketerror() == _getdns_EMFILE) return STUB_TRY_AGAIN_LATER; return -1; } diff --git a/src/util-internal.h b/src/util-internal.h index 1ef007bc..faab07b0 100644 --- a/src/util-internal.h +++ b/src/util-internal.h @@ -221,14 +221,42 @@ INLINE uint64_t _getdns_ms_until_expiry2(uint64_t expires, uint64_t *now_ms) #ifdef USE_WINSOCK typedef u_short sa_family_t; -#define _getdns_EWOULDBLOCK (WSAGetLastError() == WSATRY_AGAIN ||\ - WSAGetLastError() == WSAEWOULDBLOCK) -#define _getdns_EINPROGRESS (WSAGetLastError() == WSAEINPROGRESS) -#define _getdns_EMFILE (WSAGetLastError() == WSAEMFILE) +#define _getdns_EAGAIN (WSATRY_AGAIN) +#define _getdns_EWOULDBLOCK (WSAEWOULDBLOCK) +#define _getdns_EINPROGRESS (WSAEINPROGRESS) +#define _getdns_EMFILE (WSAEMFILE) +#define _getdns_ECONNRESET (WSAECONNRESET) + +#define _getdns_closesocket(fd) closesocket(fd) +#define _getdns_poll(fdarray, nsockets, timer) WSAPoll(fdarray, nsockets, timer) +#define _getdns_socketerror() (WSAGetLastError()) #else -#define _getdns_EWOULDBLOCK (errno == EAGAIN || errno == EWOULDBLOCK) -#define _getdns_EINPROGRESS (errno == EINPROGRESS) -#define _getdns_EMFILE (errno == EMFILE) +#ifdef HAVE_SYS_POLL_H +# include +#else +# include +#endif + +#define _getdns_EAGAIN (EAGAIN) +#define _getdns_EWOULDBLOCK (EWOULDBLOCK) +#define _getdns_EINPROGRESS (EINPROGRESS) +#define _getdns_EMFILE (EMFILE) +#define _getdns_ECONNRESET (ECONNRESET) + +#define SOCKADDR struct sockaddr +#define SOCKADDR_IN struct sockaddr_in +#define SOCKADDR_IN6 struct sockaddr_in6 +#define SOCKADDR_STORAGE struct sockaddr_storage +#define SOCKET int + +#define IP_MREQ struct ip_mreq +#define IPV6_MREQ struct ipv6_mreq +#define BOOL int +#define TRUE 1 + +#define _getdns_closesocket(fd) close(fd) +#define _getdns_poll(fdarray, nsockets, timer) poll(fdarray, nsockets, timer) +#define _getdns_socketerror() (errno) #endif #endif From 757becc81201875f7e6c2872cbe25231033c9bbc Mon Sep 17 00:00:00 2001 From: Jim Hague Date: Wed, 4 Oct 2017 17:32:52 +0100 Subject: [PATCH 02/10] write() on a socket is equivalent to send() with flag value of 0. --- src/stub.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/stub.c b/src/stub.c index 4674356c..5d472f72 100644 --- a/src/stub.c +++ b/src/stub.c @@ -808,13 +808,8 @@ stub_tcp_write(int fd, getdns_tcp_state *tcp, getdns_network_req *netreq) /* Coming back from an earlier unfinished write or handshake. * Try to send remaining data */ -#ifdef USE_WINSOCK written = send(fd, (void *)(tcp->write_buf + tcp->written), tcp->write_buf_len - tcp->written, 0); -#else - written = write(fd, tcp->write_buf + tcp->written, - tcp->write_buf_len - tcp->written); -#endif if (written == -1) { if (_getdns_socketerror() == _getdns_EWOULDBLOCK) return STUB_TCP_WOULDBLOCK; From 1eae1ad96bc78437e9baf540949231d7958bbedd Mon Sep 17 00:00:00 2001 From: Jim Hague Date: Wed, 4 Oct 2017 17:42:06 +0100 Subject: [PATCH 03/10] Fix problem where Stubby stops listening to UDP on Win10. Winsock can return ECONNRESET when receiving UDP via recvfrom() if an ICMP Port Unreachable has been received. Rather than treat the socket as being in error and closing it, just ignore the error. --- src/server.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/server.c b/src/server.c index 68b6d09d..319991da 100644 --- a/src/server.c +++ b/src/server.c @@ -544,6 +544,14 @@ static void udp_read_cb(void *userarg) conn->addrlen = sizeof(conn->remote_in); if ((len = recvfrom(l->fd, (void *)buf, sizeof(buf), 0, (struct sockaddr *)&conn->remote_in, &conn->addrlen)) == -1) { + if (_getdns_socketerror() == _getdns_ECONNRESET) { + /* + * WINSOCK gives ECONNRESET on ICMP Port Unreachable + * being received. Ignore it. + * */ + GETDNS_FREE(*mf, conn); + return; + } /* IO error, cleanup this listener. */ loop->vmt->clear(loop, &l->event); _getdns_closesocket(l->fd); From a70efd118d5fd372d7ed891eb75cadd9fd39eb90 Mon Sep 17 00:00:00 2001 From: Jim Hague Date: Thu, 5 Oct 2017 12:36:03 +0100 Subject: [PATCH 04/10] Fix build warnings about inet_ntop() not being declared on Win10/MinGW. --- configure.ac | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/configure.ac b/configure.ac index ca8c6d81..d08beefb 100644 --- a/configure.ac +++ b/configure.ac @@ -1274,7 +1274,7 @@ CFLAGS="$CFLAGS $LIBBSD_CFLAGS" ],[ AC_MSG_WARN([libbsd not found or usable; using embedded code instead]) ]) -AC_CHECK_DECLS([strlcpy,arc4random,arc4random_uniform]) +AC_CHECK_DECLS([inet_pton,inet_ntop,strlcpy,arc4random,arc4random_uniform]) AC_REPLACE_FUNCS(inet_pton) AC_REPLACE_FUNCS(inet_ntop) AC_REPLACE_FUNCS(strlcpy) @@ -1449,11 +1449,11 @@ void SHA512_Final(uint8_t[SHA512_DIGEST_LENGTH], SHA512_CTX*); unsigned char *SHA512(void* data, unsigned int data_len, unsigned char *digest); #endif /* COMPAT_SHA512 */ -#ifndef HAVE_INET_PTON +#ifndef HAVE_DECL_INET_PTON int inet_pton(int af, const char* src, void* dst); #endif /* HAVE_INET_PTON */ -#ifndef HAVE_INET_NTOP +#ifndef HAVE_DECL_INET_NTOP const char *inet_ntop(int af, const void *src, char *dst, size_t size); #endif From ff7c85ab20a7c386ef1ab0e141f17628524013de Mon Sep 17 00:00:00 2001 From: Jim Hague Date: Thu, 5 Oct 2017 12:43:35 +0100 Subject: [PATCH 05/10] Fix build errors introduced by a0c3134. --- src/mdns.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mdns.c b/src/mdns.c index 3d5efe6e..7578a262 100644 --- a/src/mdns.c +++ b/src/mdns.c @@ -1131,7 +1131,7 @@ mdns_udp_multicast_read_cb(void *userarg) if (read == -1 && (_getdns_socketerror() == _getdns_EWOULDBLOCK || - _getdns_socketerror() == _getdns_ECONNRESET) + _getdns_socketerror() == _getdns_ECONNRESET)) return; /* TODO: this will stop the receive loop! */ if (read >= GLDNS_HEADER_SIZE) @@ -1705,7 +1705,7 @@ mdns_udp_read_cb(void *userarg) */ 0, NULL, NULL); if (read == -1 && (_getdns_socketerror() == _getdns_EWOULDBLOCK || - _getdns_socketerror() == _getdns_ECONNRESET) + _getdns_socketerror() == _getdns_ECONNRESET)) return; if (read < GLDNS_HEADER_SIZE) From 59e6ec80fe4041e89f674c74af0bc0b8dc79a0f1 Mon Sep 17 00:00:00 2001 From: Jim Hague Date: Thu, 5 Oct 2017 15:04:40 +0100 Subject: [PATCH 06/10] Fix configure runtime error. Error was: checking for DSA_SIG_new... yes ../configure: line 13315: test: too many arguments --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index d08beefb..49fa72d5 100644 --- a/configure.ac +++ b/configure.ac @@ -589,7 +589,7 @@ case "$enable_ed25519" in no) ;; *) - if test $USE_NSS = "no" -a $USE_NETTLE = "no"; then + if test "$USE_NSS" = "no" -a "$USE_NETTLE" = "no"; then AC_CHECK_DECLS([NID_ED25519], [ AC_DEFINE_UNQUOTED([USE_ED25519], [1], [Define this to enable ED25519 support.]) use_ed25519="yes" From dc7daede40138d3359cd217998463b2a0efc5e2f Mon Sep 17 00:00:00 2001 From: Jim Hague Date: Fri, 6 Oct 2017 12:07:15 +0100 Subject: [PATCH 07/10] Move Windows/Unix functions into new platform.h. --- src/anchor.c | 1 + src/context.c | 1 + src/extension/poll_eventloop.c | 1 + src/mdns.c | 1 + src/server.c | 1 + src/stub.c | 1 + src/util-internal.h | 41 ---------------------------------- 7 files changed, 6 insertions(+), 41 deletions(-) diff --git a/src/anchor.c b/src/anchor.c index 6872ab18..a5a31b2e 100644 --- a/src/anchor.c +++ b/src/anchor.c @@ -50,6 +50,7 @@ #include "gldns/keyraw.h" #include "general.h" #include "util-internal.h" +#include "platform.h" /* get key usage out of its extension, returns 0 if no key_usage extension */ static unsigned long diff --git a/src/context.c b/src/context.c index 9b43ff76..3456bfa0 100644 --- a/src/context.c +++ b/src/context.c @@ -80,6 +80,7 @@ typedef unsigned short in_port_t; #include "context.h" #include "types-internal.h" #include "util-internal.h" +#include "platform.h" #include "dnssec.h" #include "stub.h" #include "list.h" diff --git a/src/extension/poll_eventloop.c b/src/extension/poll_eventloop.c index b0793e7c..f6fdddda 100644 --- a/src/extension/poll_eventloop.c +++ b/src/extension/poll_eventloop.c @@ -28,6 +28,7 @@ #include "config.h" #include "util-internal.h" +#include "platform.h" #ifdef HAVE_SYS_RESOURCE_H #include #endif diff --git a/src/mdns.c b/src/mdns.c index 7578a262..30bdab6e 100644 --- a/src/mdns.c +++ b/src/mdns.c @@ -26,6 +26,7 @@ #include "gldns/pkthdr.h" #include "gldns/rrdef.h" #include "util-internal.h" +#include "platform.h" #include "mdns.h" #ifdef HAVE_MDNS_SUPPORT diff --git a/src/server.c b/src/server.c index 319991da..f29cb603 100644 --- a/src/server.c +++ b/src/server.c @@ -40,6 +40,7 @@ #include "debug.h" #include "util/rbtree.h" #include "util-internal.h" +#include "platform.h" #include "server.h" #define DNS_REQUEST_SZ 4096 diff --git a/src/stub.c b/src/stub.c index 5d472f72..ebcb2527 100644 --- a/src/stub.c +++ b/src/stub.c @@ -52,6 +52,7 @@ #include "rr-iter.h" #include "context.h" #include "util-internal.h" +#include "platform.h" #include "general.h" #include "pubkey-pinning.h" diff --git a/src/util-internal.h b/src/util-internal.h index faab07b0..3d768de1 100644 --- a/src/util-internal.h +++ b/src/util-internal.h @@ -218,46 +218,5 @@ INLINE uint64_t _getdns_ms_until_expiry2(uint64_t expires, uint64_t *now_ms) return *now_ms >= expires ? 0 : expires - *now_ms; } - -#ifdef USE_WINSOCK -typedef u_short sa_family_t; -#define _getdns_EAGAIN (WSATRY_AGAIN) -#define _getdns_EWOULDBLOCK (WSAEWOULDBLOCK) -#define _getdns_EINPROGRESS (WSAEINPROGRESS) -#define _getdns_EMFILE (WSAEMFILE) -#define _getdns_ECONNRESET (WSAECONNRESET) - -#define _getdns_closesocket(fd) closesocket(fd) -#define _getdns_poll(fdarray, nsockets, timer) WSAPoll(fdarray, nsockets, timer) -#define _getdns_socketerror() (WSAGetLastError()) -#else -#ifdef HAVE_SYS_POLL_H -# include -#else -# include -#endif - -#define _getdns_EAGAIN (EAGAIN) -#define _getdns_EWOULDBLOCK (EWOULDBLOCK) -#define _getdns_EINPROGRESS (EINPROGRESS) -#define _getdns_EMFILE (EMFILE) -#define _getdns_ECONNRESET (ECONNRESET) - -#define SOCKADDR struct sockaddr -#define SOCKADDR_IN struct sockaddr_in -#define SOCKADDR_IN6 struct sockaddr_in6 -#define SOCKADDR_STORAGE struct sockaddr_storage -#define SOCKET int - -#define IP_MREQ struct ip_mreq -#define IPV6_MREQ struct ipv6_mreq -#define BOOL int -#define TRUE 1 - -#define _getdns_closesocket(fd) close(fd) -#define _getdns_poll(fdarray, nsockets, timer) poll(fdarray, nsockets, timer) -#define _getdns_socketerror() (errno) -#endif - #endif /* util-internal.h */ From eb6da94e257f87827e71b79eabec9b36fd5d938b Mon Sep 17 00:00:00 2001 From: Jim Hague Date: Fri, 6 Oct 2017 12:07:47 +0100 Subject: [PATCH 08/10] Convert one more poll() to _getdns_poll(). --- src/extension/poll_eventloop.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/extension/poll_eventloop.c b/src/extension/poll_eventloop.c index f6fdddda..7d6bb99c 100644 --- a/src/extension/poll_eventloop.c +++ b/src/extension/poll_eventloop.c @@ -407,7 +407,7 @@ poll_eventloop_run_once(getdns_eventloop *loop, int blocking) Sleep(poll_timeout); } else #endif - if (poll(poll_loop->pfds, poll_loop->fd_events_free, poll_timeout) < 0) { + if (_getdns_poll(poll_loop->pfds, poll_loop->fd_events_free, poll_timeout) < 0) { perror("poll() failed"); exit(EXIT_FAILURE); } From 74eaf4b03e0283fd8d55d762986f234a8a7eb7e1 Mon Sep 17 00:00:00 2001 From: Jim Hague Date: Fri, 6 Oct 2017 14:38:59 +0100 Subject: [PATCH 09/10] Previous commit omitted platform.h. --- src/platform.h | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 src/platform.h diff --git a/src/platform.h b/src/platform.h new file mode 100644 index 00000000..0cd4c9f6 --- /dev/null +++ b/src/platform.h @@ -0,0 +1,81 @@ +/** + * + * /brief general functions with platform-dependent implementations + * + */ + +/* + * Copyright (c) 2017, NLnet Labs, Sinodun + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the names of the copyright holders nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL Verisign, Inc. BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef PLATFORM_H +#define PLATFORM_H + +#include "config.h" + +#ifdef USE_WINSOCK +typedef u_short sa_family_t; +#define _getdns_EAGAIN (WSATRY_AGAIN) +#define _getdns_EWOULDBLOCK (WSAEWOULDBLOCK) +#define _getdns_EINPROGRESS (WSAEINPROGRESS) +#define _getdns_EMFILE (WSAEMFILE) +#define _getdns_ECONNRESET (WSAECONNRESET) + +#define _getdns_closesocket(fd) closesocket(fd) +#define _getdns_poll(fdarray, nsockets, timer) WSAPoll(fdarray, nsockets, timer) +#define _getdns_socketerror() (WSAGetLastError()) + +#else /* USE_WINSOCK */ + +#ifdef HAVE_SYS_POLL_H +# include +#else +# include +#endif + +#define _getdns_EAGAIN (EAGAIN) +#define _getdns_EWOULDBLOCK (EWOULDBLOCK) +#define _getdns_EINPROGRESS (EINPROGRESS) +#define _getdns_EMFILE (EMFILE) +#define _getdns_ECONNRESET (ECONNRESET) + +#define SOCKADDR struct sockaddr +#define SOCKADDR_IN struct sockaddr_in +#define SOCKADDR_IN6 struct sockaddr_in6 +#define SOCKADDR_STORAGE struct sockaddr_storage +#define SOCKET int + +#define IP_MREQ struct ip_mreq +#define IPV6_MREQ struct ipv6_mreq +#define BOOL int +#define TRUE 1 + +#define _getdns_closesocket(fd) close(fd) +#define _getdns_poll(fdarray, nsockets, timer) poll(fdarray, nsockets, timer) +#define _getdns_socketerror() (errno) +#endif + +#endif From 5e415b60b6a9cfb9762c504da9b328435ec2ea69 Mon Sep 17 00:00:00 2001 From: Jim Hague Date: Fri, 6 Oct 2017 15:04:49 +0100 Subject: [PATCH 10/10] Add missing platform.h include. --- src/mdns.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/mdns.h b/src/mdns.h index e53f79a1..79ec05fe 100644 --- a/src/mdns.h +++ b/src/mdns.h @@ -25,6 +25,7 @@ #include "getdns/getdns.h" #include "types-internal.h" #include "util-internal.h" +#include "platform.h" #include "util/lruhash.h" #include "config.h"