This adds support for mapping scope/zone names to interface IDs for IPv6 link-local addresses. Not sure if scope or zone is the better term to use here, any opinions? Could s/_zone_/_scope_/g easily enough.
Google suggests Windows supports if_nametoindex too, so the API should be portable, though I don't know about other platforms. Regards, Joe
Index: include/apr_network_io.h =================================================================== --- include/apr_network_io.h (revision 1815933) +++ include/apr_network_io.h (working copy) @@ -441,6 +441,13 @@ const apr_sockaddr_t *src, apr_pool_t *p); +/* 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"). + */ +APR_DECLARE(apr_status_t) apr_sockaddr_zone_set(apr_sockaddr_t *sa, + const char *zone_id); + /** * Look up the host name from an apr_sockaddr_t. * @param hostname The hostname. Index: configure.in =================================================================== --- configure.in (revision 1815933) +++ configure.in (working copy) @@ -1069,7 +1069,9 @@ #endif";; esac -AC_CHECK_HEADERS([sys/types.h sys/mman.h sys/ipc.h sys/mutex.h sys/shm.h sys/file.h kernel/OS.h os2.h windows.h]) +AC_CHECK_HEADERS([sys/types.h sys/mman.h sys/ipc.h sys/mutex.h \ + sys/shm.h sys/file.h kernel/OS.h os2.h windows.h \ + net/if.h]) AC_CHECK_FUNCS([mmap munmap shm_open shm_unlink shmget shmat shmdt shmctl \ create_area mprotect]) @@ -2755,7 +2757,7 @@ AC_SEARCH_LIBS(getaddrinfo, socket inet6) AC_SEARCH_LIBS(gai_strerror, socket inet6) AC_SEARCH_LIBS(getnameinfo, socket inet6) -AC_CHECK_FUNCS(gai_strerror) +AC_CHECK_FUNCS(gai_strerror if_nametoindex) APR_CHECK_WORKING_GETADDRINFO APR_CHECK_NEGATIVE_EAI APR_CHECK_WORKING_GETNAMEINFO Index: network_io/unix/sockaddr.c =================================================================== --- network_io/unix/sockaddr.c (revision 1815933) +++ network_io/unix/sockaddr.c (working copy) @@ -25,6 +25,10 @@ #include <stdlib.h> #endif +#ifdef HAVE_NET_IF_H +#include <net/if.h> +#endif + #define APR_WANT_STRFUNC #include "apr_want.h" @@ -1182,3 +1186,38 @@ #endif /* APR_HAVE_IPV6 */ return 0; /* no match */ } + +APR_DECLARE(apr_status_t) apr_sockaddr_zone_set(apr_sockaddr_t *sa, + const char *zone_id) +{ +#if !APR_HAVE_IPV6 || !defined(HAVE_IF_NAMETOINDEX) + return APR_ENOTIMPL; +#else + unsigned int idx; + + if (sa->family != APR_INET6) { + return APR_EBADIP; + } + + idx = if_nametoindex(zone_id); + if (idx) { + sa->sa.sin6.sin6_scope_id = idx; + return APR_SUCCESS; + } + + if (errno != ENODEV) { + return errno; + } + else { + char *endptr; + apr_int64_t i = apr_strtoi64(zone_id, &endptr, 10); + + if (*endptr != '\0' || errno || i < 1 || i > APR_INT16_MAX) { + return APR_EGENERAL; + } + + sa->sa.sin6.sin6_scope_id = i; + return APR_SUCCESS; + } +#endif +}