Last active
December 26, 2015 16:39
-
-
Save krakjoe/7181349 to your computer and use it in GitHub Desktop.
get_network_interfaces
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | |
{ |
Author
krakjoe
commented
Oct 27, 2013
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment