summaryrefslogtreecommitdiffstats
path: root/Utilities/cmlibuv/src/unix/udp.c
diff options
context:
space:
mode:
Diffstat (limited to 'Utilities/cmlibuv/src/unix/udp.c')
-rw-r--r--Utilities/cmlibuv/src/unix/udp.c39
1 files changed, 34 insertions, 5 deletions
diff --git a/Utilities/cmlibuv/src/unix/udp.c b/Utilities/cmlibuv/src/unix/udp.c
index 7d699a1..71bfbf7 100644
--- a/Utilities/cmlibuv/src/unix/udp.c
+++ b/Utilities/cmlibuv/src/unix/udp.c
@@ -32,8 +32,6 @@
#endif
#include <sys/un.h>
-#define UV__UDP_DGRAM_MAXSIZE (64 * 1024)
-
#if defined(IPV6_JOIN_GROUP) && !defined(IPV6_ADD_MEMBERSHIP)
# define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP
#endif
@@ -377,8 +375,11 @@ write_queue_drain:
return;
}
+ /* Safety: npkts known to be >0 below. Hence cast from ssize_t
+ * to size_t safe.
+ */
for (i = 0, q = QUEUE_HEAD(&handle->write_queue);
- i < pkts && q != &handle->write_queue;
+ i < (size_t)npkts && q != &handle->write_queue;
++i, q = QUEUE_HEAD(&handle->write_queue)) {
assert(q != NULL);
req = QUEUE_DATA(q, uv_udp_send_t, queue);
@@ -504,6 +505,28 @@ static int uv__set_reuse(int fd) {
return 0;
}
+/*
+ * The Linux kernel suppresses some ICMP error messages by default for UDP
+ * sockets. Setting IP_RECVERR/IPV6_RECVERR on the socket enables full ICMP
+ * error reporting, hopefully resulting in faster failover to working name
+ * servers.
+ */
+static int uv__set_recverr(int fd, sa_family_t ss_family) {
+#if defined(__linux__)
+ int yes;
+
+ yes = 1;
+ if (ss_family == AF_INET) {
+ if (setsockopt(fd, IPPROTO_IP, IP_RECVERR, &yes, sizeof(yes)))
+ return UV__ERR(errno);
+ } else if (ss_family == AF_INET6) {
+ if (setsockopt(fd, IPPROTO_IPV6, IPV6_RECVERR, &yes, sizeof(yes)))
+ return UV__ERR(errno);
+ }
+#endif
+ return 0;
+}
+
int uv__udp_bind(uv_udp_t* handle,
const struct sockaddr* addr,
@@ -514,7 +537,7 @@ int uv__udp_bind(uv_udp_t* handle,
int fd;
/* Check for bad flags. */
- if (flags & ~(UV_UDP_IPV6ONLY | UV_UDP_REUSEADDR))
+ if (flags & ~(UV_UDP_IPV6ONLY | UV_UDP_REUSEADDR | UV_UDP_LINUX_RECVERR))
return UV_EINVAL;
/* Cannot set IPv6-only mode on non-IPv6 socket. */
@@ -530,6 +553,12 @@ int uv__udp_bind(uv_udp_t* handle,
handle->io_watcher.fd = fd;
}
+ if (flags & UV_UDP_LINUX_RECVERR) {
+ err = uv__set_recverr(fd, addr->sa_family);
+ if (err)
+ return err;
+ }
+
if (flags & UV_UDP_REUSEADDR) {
err = uv__set_reuse(fd);
if (err)
@@ -854,7 +883,7 @@ static int uv__udp_set_membership6(uv_udp_t* handle,
#if !defined(__OpenBSD__) && \
!defined(__NetBSD__) && \
!defined(__ANDROID__) && \
- !defined(__DragonFly__) & \
+ !defined(__DragonFly__) && \
!defined(__QNX__)
static int uv__udp_set_source_membership4(uv_udp_t* handle,
const struct sockaddr_in* multicast_addr,