Skip to content

Commit

Permalink
unix: add if_indextoname
Browse files Browse the repository at this point in the history
if_indextoname(...) is a function defined in <net/if.h>

It is used to convert an IPv6 scope_id into an interface
identifier string such as %eth0 or %lo

The Windows implementation has not been tested.

Adds documentation and an ASSERT to the relevant test case.

PR-URL: libuv#1445
  • Loading branch information
pekkanikander committed Jul 28, 2017
1 parent 19e51ae commit dc401bf
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 0 deletions.
15 changes: 15 additions & 0 deletions docs/src/misc.rst
Expand Up @@ -271,6 +271,21 @@ API
and :man:`inet_pton(3)`. On success they return 0. In case of error
the target `dst` pointer is unmodified.
.. c:macro:: UV_IF_NAMESIZE
Maximum IPv6 interface identifier name lenght. Defined as
`IFNAMSIZ` in Unix and `IF_NAMESIZE` in Linux and Windows.
.. versionadded:: 1.14.0
.. c:function:: char* uv_if_indextoname(unsigned int ifindex, char* ifname)
Cross-platform IPv6-capable implementation of :man:`if_indextoname(3)`.
Writes the result to `ifname`, which must be at least `UV_IF_NAMESIZE` long.
On success returns the generated string. In case of error returns `NULL`.
.. versionadded:: 1.14.0
.. c:function:: int uv_exepath(char* buffer, size_t* size)
Gets the executable path.
Expand Down
1 change: 1 addition & 0 deletions include/uv-unix.h
Expand Up @@ -32,6 +32,7 @@
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <net/if.h>

#include <termios.h>
#include <pwd.h>
Expand Down
8 changes: 8 additions & 0 deletions include/uv.h
Expand Up @@ -1392,6 +1392,14 @@ UV_EXTERN int uv_ip6_name(const struct sockaddr_in6* src, char* dst, size_t size
UV_EXTERN int uv_inet_ntop(int af, const void* src, char* dst, size_t size);
UV_EXTERN int uv_inet_pton(int af, const char* src, void* dst);

#if defined(IF_NAMESIZE)
# define UV_IF_NAMESIZE IF_NAMESIZE
#elif defined(IFNAMSIZ)
# define UV_IF_NAMESIZE IFNAMSIZ
#endif

UV_EXTERN int uv_if_indextoname(unsigned int ifindex, char* ifname);

UV_EXTERN int uv_exepath(char* buffer, size_t* size);

UV_EXTERN int uv_cwd(char* buffer, size_t* size);
Expand Down
29 changes: 29 additions & 0 deletions src/uv-common.c
Expand Up @@ -225,6 +225,35 @@ int uv_ip6_name(const struct sockaddr_in6* src, char* dst, size_t size) {
return uv_inet_ntop(AF_INET6, &src->sin6_addr, dst, size);
}

int uv_if_indextoname(unsigned int ifindex, char* ifname) {
#ifdef _WIN32
NET_LUID InterfaceLuid;
int error = ConvertInterfaceIndexToLuid(ifindex, &InterfaceLuid);
if (NO_ERROR != error) {
return -error;
}
char InterfaceName[NDIS_IF_MAX_STRING_SIZE + 1];
int status = ConvertInterfaceLuidToAName(InterfaceLuid, InterfaceName, sizeof(InterfaceName));
if (NETIO_ERROR_SUCCESS != status) {
return -status;
}
if (strlen(InterfaceName) >= UV_IF_NAMESIZE) {
return UV__ENAMETOOLONG;
}
strncpy(ifname, InterfaceName, UV_IF_NAMESIZE);
return 0;
#else
const int saved_errno = errno;
errno = 0;
if (NULL == if_indextoname(ifindex, ifname)) {
assert(errno);
return -errno;
}
errno = saved_errno;
return 0;
#endif
}


int uv_tcp_bind(uv_tcp_t* handle,
const struct sockaddr* addr,
Expand Down
5 changes: 5 additions & 0 deletions test/test-ip6-addr.c
Expand Up @@ -67,6 +67,9 @@ TEST_IMPL(ip6_addr_link_local) {
iface_index = address->address.address6.sin6_scope_id;
device_name = address->name;

ASSERT(0 == uv_if_indextoname(iface_index, scoped_addr));
ASSERT(0 == strcmp(device_name, scoped_addr));

#ifdef _WIN32
snprintf(scoped_addr,
sizeof(scoped_addr),
Expand Down Expand Up @@ -96,6 +99,8 @@ TEST_IMPL(ip6_addr_link_local) {

uv_free_interface_addresses(addresses, count);

ASSERT(0 != uv_if_indextoname((unsigned int)-1, scoped_addr));

MAKE_VALGRIND_HAPPY();
return 0;
}
Expand Down

0 comments on commit dc401bf

Please sign in to comment.