Rework getNetworkInterfaces() for Linux, SunOS, Mac OS X
This commit is contained in:
parent
73ea01cd64
commit
317653b4df
@ -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 } ] }
|
||||
|
||||
|
@ -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
|
||||
|
@ -313,63 +313,71 @@ bool IsInternal(struct ifaddrs* addr) {
|
||||
|
||||
Handle<Value> Platform::GetInterfaceAddresses() {
|
||||
HandleScope scope;
|
||||
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;
|
||||
|
||||
struct ::ifaddrs *addrs;
|
||||
|
||||
int r = getifaddrs(&addrs);
|
||||
|
||||
if (r != 0) {
|
||||
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;
|
||||
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>");
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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…
x
Reference in New Issue
Block a user