summaryrefslogtreecommitdiff
path: root/src/inet.c
diff options
context:
space:
mode:
authorJukka Rissanen <jukka.rissanen@linux.intel.com>2012-07-09 12:24:47 +0300
committerMarcel Holtmann <marcel@holtmann.org>2012-07-09 09:30:50 -0300
commitdebd3f4f9865fdd5a998a3845c42fb1d415ceef6 (patch)
treee5dc5bd0d750ab45d8f5164a95057c28d1b45786 /src/inet.c
parent2c1534b97872f83538684a72f8876012f78da7e6 (diff)
downloadconnman-debd3f4f9865fdd5a998a3845c42fb1d415ceef6.tar.gz
connman-debd3f4f9865fdd5a998a3845c42fb1d415ceef6.tar.bz2
connman-debd3f4f9865fdd5a998a3845c42fb1d415ceef6.zip
inet: Return all running interfaces
Add a function that returns all (except loopback) interfaces that are up and running (have IP address). This information is used in following patch to clean up the routes that are left hanging around.
Diffstat (limited to 'src/inet.c')
-rw-r--r--src/inet.c78
1 files changed, 78 insertions, 0 deletions
diff --git a/src/inet.c b/src/inet.c
index 7208d4eb..c28c3e41 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;
+}