unix: fix udp_options test on OS X and Solaris

setsockopt(IP_TTL) will happily let you set a TTL > 255 on OS X, cap it.

-1 or 0 is a valid TTL on Linux but not portable, deny it.
This commit is contained in:
Ben Noordhuis 2012-04-11 16:24:20 +02:00
parent 3c415975d9
commit 42d3533487
2 changed files with 31 additions and 32 deletions

View File

@ -530,21 +530,6 @@ int uv_udp_set_membership(uv_udp_t* handle, const char* multicast_addr,
} }
#define X(name, level, option) \
int uv_udp_set_##name(uv_udp_t* handle, int flag) { \
if (setsockopt(handle->fd, level, option, &flag, sizeof(flag))) { \
uv__set_sys_error(handle->loop, errno); \
return -1; \
} \
return 0; \
}
X(broadcast, SOL_SOCKET, SO_BROADCAST)
X(ttl, IPPROTO_IP, IP_TTL)
#undef X
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 option, int val) {
#if __sun #if __sun
char arg = val; char arg = val;
@ -552,17 +537,30 @@ static int uv__setsockopt_maybe_char(uv_udp_t* handle, int option, int val) {
int arg = val; int arg = val;
#endif #endif
#if __sun if (val < 0 || val > 255)
if (val < 0 || val > 255) { return uv__set_sys_error(handle->loop, EINVAL);
uv__set_sys_error(handle->loop, EINVAL);
return -1;
}
#endif
if (setsockopt(handle->fd, IPPROTO_IP, option, &arg, sizeof(arg))) { if (setsockopt(handle->fd, IPPROTO_IP, option, &arg, sizeof(arg)))
uv__set_sys_error(handle->loop, errno); return uv__set_sys_error(handle->loop, errno);
return -1;
} return 0;
}
int uv_udp_set_broadcast(uv_udp_t* handle, int on) {
if (setsockopt(handle->fd, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on)))
return uv__set_sys_error(handle->loop, errno);
return 0;
}
int uv_udp_set_ttl(uv_udp_t* handle, int ttl) {
if (ttl < 1 || ttl > 255)
return uv__set_sys_error(handle->loop, EINVAL);
if (setsockopt(handle->fd, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl)))
return uv__set_sys_error(handle->loop, errno);
return 0; return 0;
} }

View File

@ -28,6 +28,7 @@
TEST_IMPL(udp_options) { TEST_IMPL(udp_options) {
static int invalid_ttls[] = { -1, 0, 256 };
uv_loop_t* loop; uv_loop_t* loop;
uv_udp_t h; uv_udp_t h;
int i, r; int i, r;
@ -48,17 +49,17 @@ TEST_IMPL(udp_options) {
r |= uv_udp_set_broadcast(&h, 0); r |= uv_udp_set_broadcast(&h, 0);
ASSERT(r == 0); ASSERT(r == 0);
/* values 0-255 should work */ /* values 1-255 should work */
for (i = 0; i <= 255; i++) { for (i = 1; i <= 255; i++) {
r = uv_udp_set_ttl(&h, i); r = uv_udp_set_ttl(&h, i);
ASSERT(r == 0); ASSERT(r == 0);
} }
/* anything >255 should fail */ for (i = 0; i < (int) ARRAY_SIZE(invalid_ttls); i++) {
r = uv_udp_set_ttl(&h, 256); r = uv_udp_set_ttl(&h, invalid_ttls[i]);
ASSERT(r == -1); ASSERT(r == -1);
ASSERT(uv_last_error(loop).code == UV_EINVAL); ASSERT(uv_last_error(loop).code == UV_EINVAL);
/* don't test ttl=-1, it's a valid value on some platforms */ }
r = uv_udp_set_multicast_loop(&h, 1); r = uv_udp_set_multicast_loop(&h, 1);
r |= uv_udp_set_multicast_loop(&h, 1); r |= uv_udp_set_multicast_loop(&h, 1);