inet: Return all running interfaces
authorJukka Rissanen <jukka.rissanen@linux.intel.com>
Mon, 9 Jul 2012 09:24:47 +0000 (12:24 +0300)
committerMarcel Holtmann <marcel@holtmann.org>
Mon, 9 Jul 2012 12:30:50 +0000 (09:30 -0300)
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.

src/connman.h
src/inet.c

index 5ab9eb5edd4fb538230816373d7341935bf0b117..6726078b8db077df0d216fc4f3776e2c5a6b01ed 100644 (file)
@@ -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,
index 7208d4ebe6427dc54a4be80b12c4fb2c72fee709..c28c3e4101278359c1e564a017432755560b6359 100644 (file)
@@ -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;
+}