Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

unix, win: add netmask to uv_interface_address #705

Closed
wants to merge 1 commit into from

2 participants

@wanderview

Include the netmask when returning information about the OS network
interfaces. The end goal is to get this back to node's os.networkInterfaces()
function.

This commit provides implementations for windows and those unix platforms
using getifaddrs().

AIX was not implemented because it requires the use ioctls and I do not
have an AIX development/test environment. The windows code was developed
using mingw on winxp as I do not have access to visual studio.

Tested on darwin (ipv4/ipv6) and winxp (ipv4 only). Needs testing on
newer windows using ipv6 and other unix platforms.

@wanderview wanderview unix, win: add netmask to uv_interface_address
Include the netmask when returning information about the OS network
interfaces.

This commit provides implementations for windows and those unix platforms
using getifaddrs().

AIX was not implemented because it requires the use ioctls and I do not
have an AIX development/test environment.  The windows code was developed
using mingw on winxp as I do not have access to visual studio.

Tested on darwin (ipv4/ipv6) and winxp (ipv4 only).  Needs testing on
newer windows using ipv6 and other unix platforms.
d681546
@wanderview wanderview referenced this pull request from a commit in wanderview/node
@wanderview wanderview Include netmask in os.networkInterfaces()
This commit depends on joyent/libuv#705 in order to compile.  The libuv
changes are not included here as I assume dependencies are incorporated
under a separate process.

This is a partial fix for #3765.
fd89d93
@wanderview wanderview referenced this pull request in joyent/node
Closed

Include netmask in os.networkInterfaces() #4743

@bnoordhuis

UNIX side of things LGTM.

@piscisaureus will have to sign off on the Windows changes but he probably won't be around for the next few days.

@wanderview

Thanks for the review. Note, I'd be willing to look at AIX if there was a VM or server I could use. How do you normally test AIX?

@bnoordhuis

We don't test AIX at all. Someone else wrote the port, we don't really support it.

@wanderview

@bnoordhuis If the windows code will take longer to review, would it make sense to just zero the values for now as you suggested in #730?

@wanderview

Ping @piscisaureus and @bnoordhuis now that we've gotten past the push for node v0.10.0. Willing to do more work on this if requested.

Thanks!

@bnoordhuis

Thanks Ben, landed in 14aa615.

@bnoordhuis bnoordhuis closed this
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Feb 10, 2013
  1. @wanderview

    unix, win: add netmask to uv_interface_address

    wanderview authored
    Include the netmask when returning information about the OS network
    interfaces.
    
    This commit provides implementations for windows and those unix platforms
    using getifaddrs().
    
    AIX was not implemented because it requires the use ioctls and I do not
    have an AIX development/test environment.  The windows code was developed
    using mingw on winxp as I do not have access to visual studio.
    
    Tested on darwin (ipv4/ipv6) and winxp (ipv4 only).  Needs testing on
    newer windows using ipv6 and other unix platforms.
This page is out of date. Refresh to see the latest.
View
4 include/uv.h
@@ -1437,6 +1437,10 @@ struct uv_interface_address_s {
struct sockaddr_in address4;
struct sockaddr_in6 address6;
} address;
+ union {
+ struct sockaddr_in netmask4;
+ struct sockaddr_in6 netmask6;
+ } netmask;
};
UV_EXTERN char** uv_setup_args(int argc, char** argv);
View
2  src/unix/aix.c
@@ -369,6 +369,8 @@ uv_err_t uv_interface_addresses(uv_interface_address_t** addresses,
address->address.address4 = *((struct sockaddr_in *)&p->ifr_addr);
}
+ /* TODO: Retrieve netmask using SIOCGIFNETMASK ioctl */
+
address->is_internal = flg.ifr_flags & IFF_LOOPBACK ? 1 : 0;
address++;
View
6 src/unix/darwin.c
@@ -435,6 +435,12 @@ uv_err_t uv_interface_addresses(uv_interface_address_t** addresses,
address->address.address4 = *((struct sockaddr_in *)ent->ifa_addr);
}
+ if (ent->ifa_netmask->sa_family == AF_INET6) {
+ address->netmask.netmask6 = *((struct sockaddr_in6 *)ent->ifa_netmask);
+ } else {
+ address->netmask.netmask4 = *((struct sockaddr_in *)ent->ifa_netmask);
+ }
+
address->is_internal = ent->ifa_flags & IFF_LOOPBACK ? 1 : 0;
address++;
View
6 src/unix/linux-core.c
@@ -770,6 +770,12 @@ uv_err_t uv_interface_addresses(uv_interface_address_t** addresses,
address->address.address4 = *((struct sockaddr_in *)ent->ifa_addr);
}
+ if (ent->ifa_netmask->sa_family == AF_INET6) {
+ address->netmask.netmask6 = *((struct sockaddr_in6 *)ent->ifa_netmask);
+ } else {
+ address->netmask.netmask4 = *((struct sockaddr_in *)ent->ifa_netmask);
+ }
+
address->is_internal = ent->ifa_flags & IFF_LOOPBACK ? 1 : 0;
address++;
View
6 src/unix/netbsd.c
@@ -331,6 +331,12 @@ uv_err_t uv_interface_addresses(uv_interface_address_t** addresses, int* count)
address->address.address4 = *((struct sockaddr_in *)ent->ifa_addr);
}
+ if (ent->ifa_netmask->sa_family == AF_INET6) {
+ address->netmask.netmask6 = *((struct sockaddr_in6 *)ent->ifa_netmask);
+ } else {
+ address->netmask.netmask4 = *((struct sockaddr_in *)ent->ifa_netmask);
+ }
+
address->is_internal = !!(ent->ifa_flags & IFF_LOOPBACK) ? 1 : 0;
address++;
View
6 src/unix/sunos.c
@@ -622,6 +622,12 @@ uv_err_t uv_interface_addresses(uv_interface_address_t** addresses,
address->address.address4 = *((struct sockaddr_in *)ent->ifa_addr);
}
+ if (ent->ifa_netmask->sa_family == AF_INET6) {
+ address->netmask.netmask6 = *((struct sockaddr_in6 *)ent->ifa_netmask);
+ } else {
+ address->netmask.netmask4 = *((struct sockaddr_in *)ent->ifa_netmask);
+ }
+
address->is_internal = ent->ifa_flags & IFF_PRIVATE || ent->ifa_flags &
IFF_LOOPBACK ? 1 : 0;
View
42 src/win/util.c
@@ -31,6 +31,7 @@
#include "uv.h"
#include "internal.h"
+#include <Winsock2.h>
#include <iphlpapi.h>
#include <psapi.h>
#include <tlhelp32.h>
@@ -765,7 +766,7 @@ uv_err_t uv_interface_addresses(uv_interface_address_t** addresses_ptr,
/* ERROR_BUFFER_OVERFLOW, and the required buffer size will be stored in */
/* win_address_buf_size. */
r = GetAdaptersAddresses(AF_UNSPEC,
- 0,
+ GAA_FLAG_INCLUDE_PREFIX,
NULL,
win_address_buf,
&win_address_buf_size);
@@ -882,6 +883,7 @@ uv_err_t uv_interface_addresses(uv_interface_address_t** addresses_ptr,
win_address != NULL;
win_address = win_address->Next) {
IP_ADAPTER_UNICAST_ADDRESS_XP* unicast_address;
+ IP_ADAPTER_PREFIX* prefix;
int name_size;
size_t max_name_size;
@@ -907,21 +909,55 @@ uv_err_t uv_interface_addresses(uv_interface_address_t** addresses_ptr,
return uv__new_sys_error(GetLastError());
}
+ prefix = win_address->FirstPrefix;
+
/* Add an uv_interface_address_t element for every unicast address. */
for (unicast_address = (IP_ADAPTER_UNICAST_ADDRESS_XP*)
win_address->FirstUnicastAddress;
unicast_address != NULL;
unicast_address = unicast_address->Next) {
struct sockaddr* sa;
+ int prefixlen;
uv_address->name = name_buf;
+ /* Walk the prefix list in sync with the address list and extract
+ the prefixlen for each address. On Vista and newer, we could
+ instead just use: unicast_address->OnLinkPrefixLength */
+ if (prefix != NULL) {
+ prefixlen = prefix->PrefixLength;
+ prefix = prefix->Next;
+ } else {
+ prefixlen = 0;
+ }
+
sa = unicast_address->Address.lpSockaddr;
- if (sa->sa_family == AF_INET6)
+ if (sa->sa_family == AF_INET6) {
+ int i;
+
uv_address->address.address6 = *((struct sockaddr_in6 *) sa);
- else
+
+ uv_address->netmask.netmask6.sin6_family = AF_INET6;
+ prefixlen = prefixlen > 0 ? prefixlen : 128;
+ for (i = 0; i < 16; ++i) {
+ int bits;
+ uint8_t byte_val;
+
+ bits = prefixlen < 8 ? prefixlen : 8;
+ byte_val = ~(0xff >> bits);
+ prefixlen -= bits;
+
+ uv_address->netmask.netmask6.sin6_addr.s6_addr[i] = byte_val;
+ }
+ } else {
uv_address->address.address4 = *((struct sockaddr_in *) sa);
+ uv_address->netmask.netmask4.sin_family = AF_INET;
+ prefixlen = prefixlen > 0 ? prefixlen : 32;
+ uv_address->netmask.netmask4.sin_addr.s_addr =
+ htonl(0xffffffff << (32 - prefixlen));
+ }
+
uv_address->is_internal =
(win_address->IfType == IF_TYPE_SOFTWARE_LOOPBACK);
View
8 test/test-platform-output.c
@@ -80,6 +80,14 @@ TEST_IMPL(platform_output) {
}
printf(" address: %s\n", buffer);
+
+ if (interfaces[i].netmask.netmask4.sin_family == AF_INET) {
+ uv_ip4_name(&interfaces[i].netmask.netmask4, buffer, sizeof(buffer));
+ } else if (interfaces[i].netmask.netmask4.sin_family == AF_INET6) {
+ uv_ip6_name(&interfaces[i].netmask.netmask6, buffer, sizeof(buffer));
+ }
+
+ printf(" netmask: %s\n", buffer);
}
uv_free_interface_addresses(interfaces, count);
Something went wrong with that request. Please try again.