Browse Source

Rework getNetworkInterfaces() for Linux, SunOS, Mac OS X

v0.7.4-release
Robert Mustacchi 14 years ago
committed by Ryan Dahl
parent
commit
317653b4df
  1. 16
      doc/api/os.markdown
  2. 73
      src/platform_darwin.cc
  3. 94
      src/platform_linux.cc
  4. 66
      src/platform_sunos.cc

16
doc/api/os.markdown

@ -113,9 +113,15 @@ Example inspection of os.cpus:
Get a list of network interfaces:
{ lo: { ip: '127.0.0.1', internal: true, ip6: '::1' },
eth0: { ip6: 'fe80::f2de:f1ff:fe19:ae7', internal: false },
wlan0: { ip: '10.0.1.118', internal: false, ip6: 'fe80::226:c7ff:fe7d:1602' },
vboxnet0: {} }
{ lo0:
[ { address: '::1', family: 'IPv6', internal: true },
{ address: 'fe80::1', family: 'IPv6', internal: true },
{ address: '127.0.0.1', family: 'IPv4', internal: true } ],
en1:
[ { address: 'fe80::cabc:c8ff:feef:f996', family: 'IPv6',
internal: false },
{ address: '10.0.1.123', family: 'IPv4', internal: false } ],
vmnet1: [ { address: '10.99.99.254', family: 'IPv4', internal: false } ],
vmnet8: [ { address: '10.88.88.1', family: 'IPv4', internal: false } ],
ppp0: [ { address: '10.2.0.231', family: 'IPv4', internal: false } ] }

73
src/platform_darwin.cc

@ -34,6 +34,13 @@
#include <sys/param.h>
#include <sys/sysctl.h>
#include <time.h>
#include <sys/socket.h>
#include <net/if.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <ifaddrs.h>
namespace node {
@ -212,7 +219,71 @@ int Platform::GetLoadAvg(Local<Array> *loads) {
v8::Handle<v8::Value> Platform::GetInterfaceAddresses() {
HandleScope scope;
return scope.Close(Object::New());
struct ::ifaddrs *addrs, *ent;
struct ::sockaddr_in *in4;
struct ::sockaddr_in6 *in6;
char ip[INET6_ADDRSTRLEN];
Local<Object> ret, o;
Local<String> name, ipaddr, family;
Local<Array> ifarr;
if (getifaddrs(&addrs) != 0) {
return ThrowException(ErrnoException(errno, "getifaddrs"));
}
ret = Object::New();
for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
bzero(&ip, sizeof (ip));
if (!(ent->ifa_flags & IFF_UP && ent->ifa_flags & IFF_RUNNING)) {
continue;
}
if (ent->ifa_addr == NULL) {
continue;
}
/*
* On Mac OS X getifaddrs returns information related to Mac Addresses for
* various devices, such as firewire, etc. These are not relevant here.
*/
if (ent->ifa_addr->sa_family == AF_LINK)
continue;
name = String::New(ent->ifa_name);
if (ret->Has(name)) {
ifarr = Local<Array>::Cast(ret->Get(name));
} else {
ifarr = Array::New();
ret->Set(name, ifarr);
}
if (ent->ifa_addr->sa_family == AF_INET6) {
in6 = (struct sockaddr_in6 *)ent->ifa_addr;
inet_ntop(AF_INET6, &(in6->sin6_addr), ip, INET6_ADDRSTRLEN);
family = String::New("IPv6");
} else if (ent->ifa_addr->sa_family == AF_INET) {
in4 = (struct sockaddr_in *)ent->ifa_addr;
inet_ntop(AF_INET, &(in4->sin_addr), ip, INET6_ADDRSTRLEN);
family = String::New("IPv4");
} else {
(void) strlcpy(ip, "<unknown sa family>", INET6_ADDRSTRLEN);
family = String::New("<unknown>");
}
o = Object::New();
o->Set(String::New("address"), String::New(ip));
o->Set(String::New("family"), family);
o->Set(String::New("internal"), ent->ifa_flags & IFF_LOOPBACK ?
True() : False());
ifarr->Set(ifarr->Length(), o);
}
freeifaddrs(addrs);
return scope.Close(ret);
}
} // namespace node

94
src/platform_linux.cc

@ -313,63 +313,71 @@ bool IsInternal(struct ifaddrs* addr) {
Handle<Value> Platform::GetInterfaceAddresses() {
HandleScope scope;
struct ::ifaddrs *addrs;
int r = getifaddrs(&addrs);
if (r != 0) {
struct ::ifaddrs *addrs, *ent;
struct ::sockaddr_in *in4;
struct ::sockaddr_in6 *in6;
char ip[INET6_ADDRSTRLEN];
Local<Object> ret, o;
Local<String> name, ipaddr, family;
Local<Array> ifarr;
if (getifaddrs(&addrs) != 0) {
return ThrowException(ErrnoException(errno, "getifaddrs"));
}
struct ::ifaddrs *addr;
ret = Object::New();
Local<Object> a = Object::New();
for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
bzero(&ip, sizeof (ip));
if (!(ent->ifa_flags & IFF_UP && ent->ifa_flags & IFF_RUNNING)) {
continue;
}
for (addr = addrs;
addr;
addr = addr->ifa_next) {
Local<String> name = String::New(addr->ifa_name);
Local<Object> info;
if (ent->ifa_addr == NULL) {
continue;
}
if (a->Has(name)) {
info = a->Get(name)->ToObject();
/*
* On Linux getifaddrs returns information related to the raw underlying
* devices. We're not interested in this information.
*/
if (ent->ifa_addr->sa_family == PF_PACKET)
continue;
name = String::New(ent->ifa_name);
if (ret->Has(name)) {
ifarr = Local<Array>::Cast(ret->Get(name));
} else {
info = Object::New();
a->Set(name, info);
ifarr = Array::New();
ret->Set(name, ifarr);
}
struct sockaddr *address = addr->ifa_addr;
char ip[INET6_ADDRSTRLEN];
switch (address->sa_family) {
case AF_INET6: {
struct sockaddr_in6 *a6 = (struct sockaddr_in6*)address;
inet_ntop(AF_INET6, &(a6->sin6_addr), ip, INET6_ADDRSTRLEN);
info->Set(String::New("ip6"), String::New(ip));
if (addr->ifa_flags) {
info->Set(String::New("internal"),
IsInternal(addr) ? True() : False());
}
break;
}
case AF_INET: {
struct sockaddr_in *a4 = (struct sockaddr_in*)address;
inet_ntop(AF_INET, &(a4->sin_addr), ip, INET6_ADDRSTRLEN);
info->Set(String::New("ip"), String::New(ip));
if (addr->ifa_flags) {
info->Set(String::New("internal"),
IsInternal(addr) ? True() : False());
}
break;
}
if (ent->ifa_addr->sa_family == AF_INET6) {
in6 = (struct sockaddr_in6 *)ent->ifa_addr;
inet_ntop(AF_INET6, &(in6->sin6_addr), ip, INET6_ADDRSTRLEN);
family = String::New("IPv6");
} else if (ent->ifa_addr->sa_family == AF_INET) {
in4 = (struct sockaddr_in *)ent->ifa_addr;
inet_ntop(AF_INET, &(in4->sin_addr), ip, INET6_ADDRSTRLEN);
family = String::New("IPv4");
} else {
(void) strncpy(ip, "<unknown sa family>", INET6_ADDRSTRLEN);
family = String::New("<unknown>");
}
o = Object::New();
o->Set(String::New("address"), String::New(ip));
o->Set(String::New("family"), family);
o->Set(String::New("internal"), ent->ifa_flags & IFF_LOOPBACK ?
True() : False());
ifarr->Set(ifarr->Length(), o);
}
freeifaddrs(addrs);
return scope.Close(a);
return scope.Close(ret);
}

66
src/platform_sunos.cc

@ -32,6 +32,13 @@
#include <inttypes.h>
#include <sys/types.h>
#include <sys/loadavg.h>
#include <sys/socket.h>
#include <net/if.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <ifaddrs.h>
#if (!defined(_LP64)) && (_FILE_OFFSET_BITS - 0 == 64)
#define PROCFS_FILE_OFFSET_BITS_HACK 1
@ -265,7 +272,64 @@ int Platform::GetLoadAvg(Local<Array> *loads) {
Handle<Value> Platform::GetInterfaceAddresses() {
HandleScope scope;
return scope.Close(Object::New());
struct ::ifaddrs *addrs, *ent;
struct ::sockaddr_in *in4;
struct ::sockaddr_in6 *in6;
char ip[INET6_ADDRSTRLEN];
Local<Object> ret, o;
Local<String> name, ipaddr, family;
Local<Array> ifarr;
if (getifaddrs(&addrs) != 0) {
return ThrowException(ErrnoException(errno, "getifaddrs"));
}
ret = Object::New();
for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
bzero(&ip, sizeof (ip));
if (!(ent->ifa_flags & IFF_UP && ent->ifa_flags & IFF_RUNNING)) {
continue;
}
if (ent->ifa_addr == NULL) {
continue;
}
name = String::New(ent->ifa_name);
if (ret->Has(name)) {
ifarr = Local<Array>::Cast(ret->Get(name));
} else {
ifarr = Array::New();
ret->Set(name, ifarr);
}
if (ent->ifa_addr->sa_family == AF_INET6) {
in6 = (struct sockaddr_in6 *)ent->ifa_addr;
inet_ntop(AF_INET6, &(in6->sin6_addr), ip, INET6_ADDRSTRLEN);
family = String::New("IPv6");
} else if (ent->ifa_addr->sa_family == AF_INET) {
in4 = (struct sockaddr_in *)ent->ifa_addr;
inet_ntop(AF_INET, &(in4->sin_addr), ip, INET6_ADDRSTRLEN);
family = String::New("IPv4");
} else {
(void) strlcpy(ip, "<unknown sa family>", INET6_ADDRSTRLEN);
family = String::New("<unknown>");
}
o = Object::New();
o->Set(String::New("address"), String::New(ip));
o->Set(String::New("family"), family);
o->Set(String::New("internal"), ent->ifa_flags & IFF_PRIVATE || ent->ifa_flags &
IFF_LOOPBACK ? True() : False());
ifarr->Set(ifarr->Length(), o);
}
freeifaddrs(addrs);
return scope.Close(ret);
}

Loading…
Cancel
Save