diff --git a/doc/api/os.markdown b/doc/api/os.markdown index 3c4e1b44fd..d5e4a7c4e8 100644 --- a/doc/api/os.markdown +++ b/doc/api/os.markdown @@ -99,4 +99,15 @@ Example inspection of os.cpus: nice: 1480, sys: 34920, idle: 1072572010, - irq: 30 } } ] \ No newline at end of file + irq: 30 } } ] + +### os.getNetworkInterfaces() + +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: {} } + + diff --git a/lib/os.js b/lib/os.js index d2ff550814..e1535bcb8b 100644 --- a/lib/os.js +++ b/lib/os.js @@ -29,3 +29,4 @@ exports.totalmem = binding.getTotalMem; exports.cpus = binding.getCPUs; exports.type = binding.getOSType; exports.release = binding.getOSRelease; +exports.getNetworkInterfaces = binding.getInterfaceAddresses; diff --git a/src/node_os.cc b/src/node_os.cc index 1b985276c4..077e207a72 100644 --- a/src/node_os.cc +++ b/src/node_os.cc @@ -161,6 +161,12 @@ static Handle GetLoadAvg(const Arguments& args) { return scope.Close(loads); } + +static Handle GetInterfaceAddresses(const Arguments& args) { + return Platform::GetInterfaceAddresses(); +} + + #ifdef __MINGW32__ static Handle OpenOSHandle(const Arguments& args) { HandleScope scope; @@ -186,6 +192,7 @@ void OS::Initialize(v8::Handle target) { NODE_SET_METHOD(target, "getCPUs", GetCPUInfo); NODE_SET_METHOD(target, "getOSType", GetOSType); NODE_SET_METHOD(target, "getOSRelease", GetOSRelease); + NODE_SET_METHOD(target, "getInterfaceAddresses", GetInterfaceAddresses); #ifdef __MINGW32__ NODE_SET_METHOD(target, "openOSHandle", OpenOSHandle); diff --git a/src/platform.h b/src/platform.h index d31c9a415a..a0b45b92aa 100644 --- a/src/platform.h +++ b/src/platform.h @@ -42,6 +42,7 @@ class Platform { return adjusted ? GetUptimeImpl() - prog_start_time : GetUptimeImpl(); } static int GetLoadAvg(v8::Local *loads); + static v8::Handle GetInterfaceAddresses(); private: static double GetUptimeImpl(); static double prog_start_time; diff --git a/src/platform_cygwin.cc b/src/platform_cygwin.cc index 7dc610a41d..77e48ca41a 100644 --- a/src/platform_cygwin.cc +++ b/src/platform_cygwin.cc @@ -380,4 +380,10 @@ int Platform::GetLoadAvg(Local *loads) { } +Handle Platform::GetInterfaceAddresses() { + HandleScope scope; + return scope.Close(Object::New()); +} + + } // namespace node diff --git a/src/platform_darwin.cc b/src/platform_darwin.cc index a2149b4c77..13a5133644 100644 --- a/src/platform_darwin.cc +++ b/src/platform_darwin.cc @@ -209,4 +209,10 @@ int Platform::GetLoadAvg(Local *loads) { return 0; } + +Handle Platform::GetInterfaceAddresses() { + HandleScope scope; + return scope.Close(Object::New()); +} + } // namespace node diff --git a/src/platform_freebsd.cc b/src/platform_freebsd.cc index 2bb373f061..1377250f34 100644 --- a/src/platform_freebsd.cc +++ b/src/platform_freebsd.cc @@ -229,4 +229,10 @@ int Platform::GetLoadAvg(Local *loads) { return 0; } + +Handle Platform::GetInterfaceAddresses() { + HandleScope scope; + return scope.Close(Object::New()); +} + } // namespace node diff --git a/src/platform_linux.cc b/src/platform_linux.cc index 7602c92826..d87c8d04e5 100644 --- a/src/platform_linux.cc +++ b/src/platform_linux.cc @@ -36,6 +36,14 @@ #include // free #include // strdup +/* GetInterfaceAddresses */ +#include +#include +#include +#include +#include +#include + #if HAVE_MONOTONIC_CLOCK #include #endif @@ -295,4 +303,77 @@ int Platform::GetLoadAvg(Local *loads) { return 0; } + +bool IsInternal(struct ifaddrs* addr) { + return addr->ifa_flags & IFF_UP && + addr->ifa_flags & IFF_RUNNING && + addr->ifa_flags & IFF_LOOPBACK; +} + + +Handle Platform::GetInterfaceAddresses() { + HandleScope scope; + + struct ::ifaddrs *addrs; + + int r = getifaddrs(&addrs); + + if (r != 0) { + return ThrowException(ErrnoException(errno, "getifaddrs")); + } + + struct ::ifaddrs *addr; + + Local a = Object::New(); + + for (addr = addrs; + addr; + addr = addr->ifa_next) { + Local name = String::New(addr->ifa_name); + Local info; + + if (a->Has(name)) { + info = a->Get(name)->ToObject(); + } else { + info = Object::New(); + a->Set(name, info); + } + + 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; + } + + default: + assert(0); + } + } + + freeifaddrs(addrs); + + return scope.Close(a); +} + + } // namespace node diff --git a/src/platform_openbsd.cc b/src/platform_openbsd.cc index 1583647ef0..9a9ba01499 100644 --- a/src/platform_openbsd.cc +++ b/src/platform_openbsd.cc @@ -220,4 +220,11 @@ int Platform::GetLoadAvg(Local *loads) { return 0; } + +Handle Platform::GetInterfaceAddresses() { + HandleScope scope; + return scope.Close(Object::New()); +} + + } // namespace node diff --git a/src/platform_sunos.cc b/src/platform_sunos.cc index 38d4ea4e68..59bf2e7698 100644 --- a/src/platform_sunos.cc +++ b/src/platform_sunos.cc @@ -140,5 +140,11 @@ int Platform::GetLoadAvg(Local *loads) { } +Handle Platform::GetInterfaceAddresses() { + HandleScope scope; + return scope.Close(Object::New()); +} + + } // namespace node diff --git a/src/platform_win32.cc b/src/platform_win32.cc index a39b06cac4..d5a15d607b 100644 --- a/src/platform_win32.cc +++ b/src/platform_win32.cc @@ -250,4 +250,11 @@ int Platform::GetLoadAvg(Local *loads) { return -1; } + +Handle Platform::GetInterfaceAddresses() { + HandleScope scope; + return scope.Close(Object::New()); +} + + } // namespace node diff --git a/test/simple/test-os.js b/test/simple/test-os.js index 5903f8f6b1..b09073c641 100644 --- a/test/simple/test-os.js +++ b/test/simple/test-os.js @@ -30,4 +30,13 @@ assert.ok(os.freemem() > 0); assert.ok(os.totalmem() > 0); assert.ok(os.cpus().length > 0); assert.ok(os.type().length > 0); -assert.ok(os.release().length > 0); \ No newline at end of file +assert.ok(os.release().length > 0); + + +var interfaces = os.getNetworkInterfaces(); +console.error(interfaces); +switch (process.platform) { + case 'linux': + assert.equal('127.0.0.1', interfaces.lo.ip); + break; +}