diff --git a/include/apr_network_io.h b/include/apr_network_io.h index e26959cddf2..733bf5a1791 100644 --- a/include/apr_network_io.h +++ b/include/apr_network_io.h @@ -444,6 +444,8 @@ APR_DECLARE(apr_status_t) apr_sockaddr_info_copy(apr_sockaddr_t **dst, /* Set the zone of an IPv6 link-local address object. * @param sa Socket address object * @param zone_id Zone ID (textual "eth0" or numeric "3"). + * @return Returns APR_EBADIP for non-IPv6 socket or an IPv6 address + * which isn't link-local. */ APR_DECLARE(apr_status_t) apr_sockaddr_zone_set(apr_sockaddr_t *sa, const char *zone_id); diff --git a/network_io/unix/sockaddr.c b/network_io/unix/sockaddr.c index 3b711fd5ba6..8e4bde3e3b4 100644 --- a/network_io/unix/sockaddr.c +++ b/network_io/unix/sockaddr.c @@ -1225,7 +1225,8 @@ APR_DECLARE(apr_status_t) apr_sockaddr_zone_set(apr_sockaddr_t *sa, #else unsigned int idx; - if (sa->family != APR_INET6) { + if (sa->family != APR_INET6 + || !IN6_IS_ADDR_LINKLOCAL((struct in6_addr *)sa->ipaddr_ptr)) { return APR_EBADIP; } diff --git a/test/testsock.c b/test/testsock.c index 933aa1da8d4..64df725ea06 100644 --- a/test/testsock.c +++ b/test/testsock.c @@ -660,7 +660,6 @@ static void test_zone(abts_case *tc, void *data) const char *name = NULL; apr_uint32_t id = 0; - /* RFC 5737 address */ rv = apr_sockaddr_info_get(&sa, "127.0.0.1", APR_INET, 8080, 0, p); APR_ASSERT_SUCCESS(tc, "Problem generating sockaddr", rv); @@ -669,6 +668,12 @@ static void test_zone(abts_case *tc, void *data) apr_sockaddr_zone_set(sa, "1")); ABTS_INT_EQUAL(tc, APR_EBADIP, apr_sockaddr_zone_get(sa, &name, &id, p)); + + rv = apr_sockaddr_info_get(&sa, "::1", APR_INET6, 8080, 0, p); + APR_ASSERT_SUCCESS(tc, "Problem generating sockaddr", rv); + + /* Fail for an address which isn't link-local */ + ABTS_INT_EQUAL(tc, APR_EBADIP, apr_sockaddr_zone_set(sa, "1")); rv = apr_sockaddr_info_get(&sa, TEST_ZONE_ADDR, APR_INET6, 8080, 0, p); APR_ASSERT_SUCCESS(tc, "Problem generating sockaddr", rv);