Skip to content

Instantly share code, notes, and snippets.

@krakjoe
Last active December 26, 2015 16:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save krakjoe/7181349 to your computer and use it in GitHub Desktop.
Save krakjoe/7181349 to your computer and use it in GitHub Desktop.
get_network_interfaces
diff --git a/Zend/Zend.m4 b/Zend/Zend.m4
index 945409e..ed4c0d7 100644
--- a/Zend/Zend.m4
+++ b/Zend/Zend.m4
@@ -106,6 +106,25 @@ ZEND_FP_EXCEPT
ZEND_CHECK_FLOAT_PRECISION
+AC_MSG_CHECKING([for usable ifaddrs.h])
+ AC_TRY_LINK([
+ #include <ifaddrs.h>
+ #include <netdb.h>
+ ],[
+ struct ifaddrs *interfaces;
+ if (getifaddrs(&interfaces) != -1) {
+ freeifaddrs(interfaces);
+ }
+
+ printf("%d", NI_MAXHOST);
+ ], [ac_have_ifaddrs=yes], [ac_have_ifaddrs=no])
+ if test "$ac_have_ifaddrs" = "yes" ; then
+ AC_DEFINE(HAVE_IFADDRS_H, 1, [whether ifaddrs is present and usable])
+ AC_MSG_RESULT(yes)
+ else
+ AC_MSG_RESULT(no)
+ fi
+
dnl test whether double cast to long preserves least significant bits
AC_MSG_CHECKING(whether double cast to long preserves least significant bits)
diff --git a/Zend/zend.h b/Zend/zend.h
index acbb6ac..2c171f0 100644
--- a/Zend/zend.h
+++ b/Zend/zend.h
@@ -79,6 +79,11 @@
# include <dlfcn.h>
#endif
+#ifdef HAVE_IFADDRS_H
+# include <ifaddrs.h>
+# include <netdb.h>
+#endif
+
#if defined(HAVE_LIBDL) && !defined(ZEND_WIN32)
# ifndef RTLD_LAZY
diff --git a/Zend/zend_builtin_functions.c b/Zend/zend_builtin_functions.c
index ed136f5..7de881e 100644
--- a/Zend/zend_builtin_functions.c
+++ b/Zend/zend_builtin_functions.c
@@ -82,6 +82,9 @@ static ZEND_FUNCTION(get_loaded_extensions);
static ZEND_FUNCTION(extension_loaded);
static ZEND_FUNCTION(get_extension_funcs);
static ZEND_FUNCTION(get_defined_constants);
+#ifdef HAVE_IFADDRS_H
+static ZEND_FUNCTION(get_network_interfaces);
+#endif
static ZEND_FUNCTION(debug_backtrace);
static ZEND_FUNCTION(debug_print_backtrace);
#if ZEND_DEBUG
@@ -226,6 +229,12 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_get_defined_constants, 0, 0, 0)
ZEND_ARG_INFO(0, categorize)
ZEND_END_ARG_INFO()
+#ifdef HAVE_IFADDRS_H
+ZEND_BEGIN_ARG_INFO_EX(arginfo_get_network_interfaces, 0, 0, 0)
+ ZEND_ARG_INFO(0, specific)
+ZEND_END_ARG_INFO()
+#endif
+
ZEND_BEGIN_ARG_INFO_EX(arginfo_debug_backtrace, 0, 0, 0)
ZEND_ARG_INFO(0, options)
ZEND_ARG_INFO(0, limit)
@@ -295,6 +304,9 @@ static const zend_function_entry builtin_functions[] = { /* {{{ */
ZEND_FE(extension_loaded, arginfo_extension_loaded)
ZEND_FE(get_extension_funcs, arginfo_extension_loaded)
ZEND_FE(get_defined_constants, arginfo_get_defined_constants)
+#ifdef HAVE_IFADDRS_H
+ ZEND_FE(get_network_interfaces, arginfo_get_network_interfaces)
+#endif
ZEND_FE(debug_backtrace, arginfo_debug_backtrace)
ZEND_FE(debug_print_backtrace, arginfo_debug_print_backtrace)
#if ZEND_DEBUG
@@ -2012,6 +2024,80 @@ next_constant:
}
/* }}} */
+#ifdef HAVE_IFADDRS_H
+/* {{{ proto array get_network_interfaces([string specific])
+ Return an array containing the names and addresses of specific or all interfaces */
+ZEND_FUNCTION(get_network_interfaces)
+{
+ char *specific = NULL;
+ int specific_len;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &specific, &specific_len) == FAILURE) {
+ return;
+ }
+
+ {
+ struct ifaddrs *interfaces,
+ *interface;
+
+ if (getifaddrs(&interfaces) != -1) {
+ char host[NI_MAXHOST];
+
+ array_init(return_value);
+
+ for (interface = interfaces; interface != NULL; interface = interface->ifa_next) {
+ if (interface->ifa_addr != NULL) {
+ zval *next = NULL;
+ zend_ulong ifa_name_len = strlen(interface->ifa_name);
+
+ if (!specific ||
+ memcmp(interface->ifa_name, specific, specific_len > ifa_name_len ? ifa_name_len : specific_len) == SUCCESS) {
+ switch (interface->ifa_addr->sa_family) {
+ case AF_INET:
+ case AF_INET6: {
+ MAKE_STD_ZVAL(next);
+
+ array_init(next);
+
+ add_assoc_string_ex(
+ next, "name", sizeof("name"), interface->ifa_name, 1);
+ add_assoc_long_ex(
+ next, "flags", sizeof("flags"), interface->ifa_flags);
+ add_assoc_long_ex(
+ next, "family", sizeof("family"), interface->ifa_addr->sa_family);
+
+ if (getnameinfo(interface->ifa_addr,
+ (interface->ifa_addr->sa_family == AF_INET) ?
+ sizeof(struct sockaddr_in) :
+ sizeof(struct sockaddr_in6),
+ host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST) == SUCCESS) {
+ add_assoc_string_ex(next, "address", sizeof("address"), host, 1);
+ }
+
+ if (getnameinfo(interface->ifa_netmask,
+ (interface->ifa_netmask->sa_family == AF_INET) ?
+ sizeof(struct sockaddr_in) :
+ sizeof(struct sockaddr_in6),
+ host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST) == SUCCESS) {
+ add_assoc_string_ex(next, "netmask", sizeof("netmask"), host, 1);
+ }
+ } break;
+ }
+ }
+
+ if (next) {
+ add_next_index_zval(return_value, next);
+ }
+ }
+ }
+
+ freeifaddrs(interfaces);
+ } else {
+ RETURN_FALSE;
+ }
+ }
+} /* }}} */
+#endif
static zval *debug_backtrace_get_args(void **curpos TSRMLS_DC)
{
@krakjoe
Copy link
Author

krakjoe commented Oct 27, 2013

[joe@fiji php-upstream]$ sapi/cli/php -r "var_dump(get_network_interfaces());"
array(4) {
  [0]=>
  array(5) {
    ["name"]=>
    string(2) "lo"
    ["flags"]=>
    int(65609)
    ["family"]=>
    int(2)
    ["address"]=>
    string(9) "127.0.0.1"
    ["netmask"]=>
    string(9) "255.0.0.0"
  }
  [1]=>
  array(5) {
    ["name"]=>
    string(4) "p2p1"
    ["flags"]=>
    int(69699)
    ["family"]=>
    int(2)
    ["address"]=>
    string(11) "192.168.0.3"
    ["netmask"]=>
    string(13) "255.255.255.0"
  }
  [2]=>
  array(5) {
    ["name"]=>
    string(2) "lo"
    ["flags"]=>
    int(65609)
    ["family"]=>
    int(10)
    ["address"]=>
    string(3) "::1"
    ["netmask"]=>
    string(39) "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"
  }
  [3]=>
  array(5) {
    ["name"]=>
    string(4) "p2p1"
    ["flags"]=>
    int(69699)
    ["family"]=>
    int(10)
    ["address"]=>
    string(30) "fe80::16da:e9ff:fed7:680f%p2p1"
    ["netmask"]=>
    string(21) "ffff:ffff:ffff:ffff::"
  }
}
[joe@fiji php-upstream]$ sapi/cli/php -r "var_dump(get_network_interfaces(\"p2p\"));"
array(2) {
  [0]=>
  array(5) {
    ["name"]=>
    string(4) "p2p1"
    ["flags"]=>
    int(69699)
    ["family"]=>
    int(2)
    ["address"]=>
    string(11) "192.168.0.3"
    ["netmask"]=>
    string(13) "255.255.255.0"
  }
  [1]=>
  array(5) {
    ["name"]=>
    string(4) "p2p1"
    ["flags"]=>
    int(69699)
    ["family"]=>
    int(10)
    ["address"]=>
    string(30) "fe80::16da:e9ff:fed7:680f%p2p1"
    ["netmask"]=>
    string(21) "ffff:ffff:ffff:ffff::"
  }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment