From 2daee9fbebecab32b931feda29c7de9092d6558b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sa=C3=BAl=20Ibarra=20Corretg=C3=A9?= Date: Thu, 1 Jan 2015 13:15:57 +0100 Subject: [PATCH] unix: fix ttl, multicast ttl and loop options on IPv6 Fixes #93 PR-URL: https://github.com/libuv/libuv/pull/99 Reviewed-By: Ben Noordhuis --- src/unix/udp.c | 39 +++++++++++++++++++++++++++++++-------- test/test-list.h | 2 ++ test/test-udp-options.c | 23 ++++++++++++++++++----- 3 files changed, 51 insertions(+), 13 deletions(-) diff --git a/src/unix/udp.c b/src/unix/udp.c index 71a0e41f..2e1824c3 100644 --- a/src/unix/udp.c +++ b/src/unix/udp.c @@ -598,7 +598,11 @@ int uv_udp_set_membership(uv_udp_t* handle, } -static int uv__setsockopt_maybe_char(uv_udp_t* handle, int option, int val) { +static int uv__setsockopt_maybe_char(uv_udp_t* handle, + int option4, + int option6, + int val) { + int r; #if defined(__sun) || defined(_AIX) char arg = val; #else @@ -608,7 +612,20 @@ static int uv__setsockopt_maybe_char(uv_udp_t* handle, int option, int val) { if (val < 0 || val > 255) return -EINVAL; - if (setsockopt(handle->io_watcher.fd, IPPROTO_IP, option, &arg, sizeof(arg))) + if (handle->flags & UV_HANDLE_IPV6) + r = setsockopt(handle->io_watcher.fd, + IPPROTO_IPV6, + option6, + &arg, + sizeof(arg)); + else + r = setsockopt(handle->io_watcher.fd, + IPPROTO_IP, + option4, + &arg, + sizeof(arg)); + + if (r) return -errno; return 0; @@ -632,20 +649,26 @@ int uv_udp_set_ttl(uv_udp_t* handle, int ttl) { if (ttl < 1 || ttl > 255) return -EINVAL; - if (setsockopt(handle->io_watcher.fd, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl))) - return -errno; - - return 0; + return uv__setsockopt_maybe_char(handle, + IP_TTL, + IPV6_UNICAST_HOPS, + ttl); } int uv_udp_set_multicast_ttl(uv_udp_t* handle, int ttl) { - return uv__setsockopt_maybe_char(handle, IP_MULTICAST_TTL, ttl); + return uv__setsockopt_maybe_char(handle, + IP_MULTICAST_TTL, + IPV6_MULTICAST_HOPS, + ttl); } int uv_udp_set_multicast_loop(uv_udp_t* handle, int on) { - return uv__setsockopt_maybe_char(handle, IP_MULTICAST_LOOP, on); + return uv__setsockopt_maybe_char(handle, + IP_MULTICAST_LOOP, + IPV6_MULTICAST_LOOP, + on); } int uv_udp_set_multicast_interface(uv_udp_t* handle, const char* interface_addr) { diff --git a/test/test-list.h b/test/test-list.h index 9c888554..eb78a43c 100644 --- a/test/test-list.h +++ b/test/test-list.h @@ -104,6 +104,7 @@ TEST_DECLARE (udp_dgram_too_big) TEST_DECLARE (udp_dual_stack) TEST_DECLARE (udp_ipv6_only) TEST_DECLARE (udp_options) +TEST_DECLARE (udp_options6) TEST_DECLARE (udp_no_autobind) TEST_DECLARE (udp_open) TEST_DECLARE (udp_try_send) @@ -413,6 +414,7 @@ TASK_LIST_START TEST_ENTRY (udp_dual_stack) TEST_ENTRY (udp_ipv6_only) TEST_ENTRY (udp_options) + TEST_ENTRY (udp_options6) TEST_ENTRY (udp_no_autobind) TEST_ENTRY (udp_multicast_interface) TEST_ENTRY (udp_multicast_interface6) diff --git a/test/test-udp-options.c b/test/test-udp-options.c index 19c45c2e..3020ef5f 100644 --- a/test/test-udp-options.c +++ b/test/test-udp-options.c @@ -27,15 +27,12 @@ #include -TEST_IMPL(udp_options) { +static int udp_options_test(const struct sockaddr* addr) { static int invalid_ttls[] = { -1, 0, 256 }; - struct sockaddr_in addr; uv_loop_t* loop; uv_udp_t h; int i, r; - ASSERT(0 == uv_ip4_addr("0.0.0.0", TEST_PORT, &addr)); - loop = uv_default_loop(); r = uv_udp_init(loop, &h); @@ -43,7 +40,7 @@ TEST_IMPL(udp_options) { uv_unref((uv_handle_t*)&h); /* don't keep the loop alive */ - r = uv_udp_bind(&h, (const struct sockaddr*) &addr, 0); + r = uv_udp_bind(&h, addr, 0); ASSERT(r == 0); r = uv_udp_set_broadcast(&h, 1); @@ -88,6 +85,22 @@ TEST_IMPL(udp_options) { } +TEST_IMPL(udp_options) { + struct sockaddr_in addr; + + ASSERT(0 == uv_ip4_addr("0.0.0.0", TEST_PORT, &addr)); + return udp_options_test((const struct sockaddr*) &addr); +} + + +TEST_IMPL(udp_options6) { + struct sockaddr_in6 addr; + + ASSERT(0 == uv_ip6_addr("::", TEST_PORT, &addr)); + return udp_options_test((const struct sockaddr*) &addr); +} + + TEST_IMPL(udp_no_autobind) { uv_loop_t* loop; uv_udp_t h;