summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/connman.h1
-rw-r--r--src/inet.c78
2 files changed, 79 insertions, 0 deletions
diff --git a/src/connman.h b/src/connman.h
index 5ab9eb5..6726078 100644
--- a/src/connman.h
+++ b/src/connman.h
@@ -133,6 +133,7 @@ void __connman_task_cleanup(void);
#include <connman/inet.h>
+char **__connman_inet_get_running_interfaces(void);
int __connman_inet_modify_address(int cmd, int flags, int index, int family,
const char *address,
const char *peer,
diff --git a/src/inet.c b/src/inet.c
index 7208d4e..c28c3e4 100644
--- a/src/inet.c
+++ b/src/inet.c
@@ -2238,3 +2238,81 @@ connman_bool_t connman_inet_check_hostname(const char *ptr, size_t len)
return TRUE;
}
+
+char **__connman_inet_get_running_interfaces(void)
+{
+ char **result;
+ struct ifconf ifc;
+ struct ifreq *ifr = NULL;
+ int sk, i, numif, count = 0;
+
+ memset(&ifc, 0, sizeof(ifc));
+
+ sk = socket(AF_INET, SOCK_DGRAM, 0);
+ if (sk < 0)
+ return NULL;
+
+ if (ioctl(sk, SIOCGIFCONF, &ifc) < 0)
+ goto error;
+
+ /*
+ * Allocate some extra bytes just in case there will
+ * be new interfaces added between two SIOCGIFCONF
+ * calls.
+ */
+ ifr = g_try_malloc0(ifc.ifc_len * 2);
+ if (ifr == NULL)
+ goto error;
+
+ ifc.ifc_req = ifr;
+
+ if (ioctl(sk, SIOCGIFCONF, &ifc) < 0)
+ goto error;
+
+ numif = ifc.ifc_len / sizeof(struct ifreq);
+
+ result = g_try_malloc0((numif + 1) * sizeof(char *));
+ if (result == NULL)
+ goto error;
+
+ close(sk);
+
+ for (i = 0; i < numif; i++) {
+ struct ifreq *r = &ifr[i];
+ struct in6_addr *addr6;
+ in_addr_t addr4;
+
+ /*
+ * Note that we do not return loopback interfaces here as they
+ * are not needed for our purposes.
+ */
+ switch (r->ifr_addr.sa_family) {
+ case AF_INET:
+ addr4 = ntohl(((struct sockaddr_in *)
+ &r->ifr_addr)->sin_addr.s_addr);
+ if (((addr4 & 0xff000000) >> 24) == 127)
+ continue;
+ break;
+ case AF_INET6:
+ addr6 = &((struct sockaddr_in6 *)
+ &r->ifr_addr)->sin6_addr;
+ if (IN6_IS_ADDR_LINKLOCAL(addr6))
+ continue;
+ break;
+ }
+
+ result[count++] = g_strdup(r->ifr_name);
+ }
+
+ free(ifr);
+
+ if (count < numif)
+ result = g_try_realloc(result, (count + 1) * sizeof(char *));
+
+ return result;
+
+error:
+ close(sk);
+ free(ifr);
+ return NULL;
+}