#endif /* G_OS_UNIX */
+#ifdef IGNORED_IFACE_PREFIX
+static const gchar *ignored_iface_prefix_list[] = {
+ IGNORED_IFACE_PREFIX,
+ NULL
+};
+#endif
+
#if (defined(G_OS_UNIX) && defined(HAVE_GETIFADDRS)) || defined(G_OS_WIN32)
/* Works on both UNIX and Windows. Magic! */
static gchar *
#ifdef G_OS_UNIX
+static GList *
+get_local_interfaces_ioctl (void)
+{
+ GList *interfaces = NULL;
+ gint sockfd;
+ gint size = 0;
+ struct ifreq *ifr;
+ struct ifconf ifc;
+
+ if ((sockfd = socket (AF_INET, SOCK_DGRAM, IPPROTO_IP)) < 0) {
+ nice_debug ("error : Cannot open socket to retrieve interface list");
+ return NULL;
+ }
+
+ ifc.ifc_len = 0;
+ ifc.ifc_req = NULL;
+
+ /* Loop and get each interface the system has, one by one... */
+ do {
+ size += sizeof (struct ifreq);
+ /* realloc buffer size until no overflow occurs */
+ if (NULL == (ifc.ifc_req = realloc (ifc.ifc_req, size))) {
+ nice_debug ("Error : Out of memory while allocation interface"
+ "configuration structure");
+ close (sockfd);
+ return NULL;
+ }
+ ifc.ifc_len = size;
+
+ if (ioctl (sockfd, SIOCGIFCONF, &ifc)) {
+ perror ("ioctl SIOCFIFCONF");
+ close (sockfd);
+ free (ifc.ifc_req);
+ return NULL;
+ }
+ } while (size <= ifc.ifc_len);
+
+
+ /* Loop throught the interface list and get the IP address of each IF */
+ for (ifr = ifc.ifc_req;
+ (gchar *) ifr < (gchar *) ifc.ifc_req + ifc.ifc_len;
+ ++ifr) {
+ nice_debug ("Found interface : %s", ifr->ifr_name);
+ interfaces = g_list_prepend (interfaces, g_strdup (ifr->ifr_name));
+ }
+
+ free (ifc.ifc_req);
+ close (sockfd);
+
+ return interfaces;
+}
+
#ifdef HAVE_GETIFADDRS
GList *
struct ifaddrs *ifa, *results;
if (getifaddrs (&results) < 0) {
- return NULL;
+ nice_debug ("Failed to retrieve list of network interfaces with \"getifaddrs\": %s."
+ "Trying to use fallback ...", strerror (errno));
+ return get_local_interfaces_ioctl ();
}
/* Loop and get each interface the system has, one by one... */
GList *
nice_interfaces_get_local_interfaces (void)
{
- GList *interfaces = NULL;
+ return get_local_interfaces_ioctl ();
+}
+
+#endif /* HAVE_GETIFADDRS */
+
+
+static gboolean
+nice_interfaces_is_private_ip (const struct sockaddr *sa)
+{
+ NiceAddress niceaddr;
+
+ nice_address_init (&niceaddr);
+ nice_address_set_from_sockaddr (&niceaddr, sa);
+ return nice_address_is_private (&niceaddr);
+}
+
+static GList *
+add_ip_to_list (GList *list, gchar *ip, gboolean append)
+{
+ GList *i;
+
+ for (i = list; i; i = i->next) {
+ gchar *addr = (gchar *) i->data;
+
+ if (g_strcmp0 (addr, ip) == 0)
+ return list;
+ }
+ if (append)
+ return g_list_append (list, ip);
+ else
+ return g_list_prepend (list, ip);
+}
+
+static GList *
+get_local_ips_ioctl (gboolean include_loopback)
+{
+ GList *ips = NULL;
gint sockfd;
gint size = 0;
struct ifreq *ifr;
struct ifconf ifc;
+ union {
+ struct sockaddr_in *sin;
+ struct sockaddr *sa;
+ } sa;
+
+ GList *loopbacks = NULL;
+#ifdef IGNORED_IFACE_PREFIX
+ const gchar **prefix;
+ gboolean ignored;
+#endif
if ((sockfd = socket (AF_INET, SOCK_DGRAM, IPPROTO_IP)) < 0) {
- nice_debug ("error : Cannot open socket to retrieve interface list");
+ nice_debug ("Error : Cannot open socket to retrieve interface list");
return NULL;
}
/* realloc buffer size until no overflow occurs */
if (NULL == (ifc.ifc_req = realloc (ifc.ifc_req, size))) {
nice_debug ("Error : Out of memory while allocation interface"
- "configuration structure");
+ " configuration structure");
close (sockfd);
return NULL;
}
free (ifc.ifc_req);
return NULL;
}
- } while (size <= ifc.ifc_len);
+ } while (size <= ifc.ifc_len);
/* Loop throught the interface list and get the IP address of each IF */
for (ifr = ifc.ifc_req;
(gchar *) ifr < (gchar *) ifc.ifc_req + ifc.ifc_len;
++ifr) {
- nice_debug ("Found interface : %s", ifr->ifr_name);
- interfaces = g_list_prepend (interfaces, g_strdup (ifr->ifr_name));
- }
-
- free (ifc.ifc_req);
- close (sockfd);
-
- return interfaces;
-}
-#endif /* HAVE_GETIFADDRS */
+ if (ioctl (sockfd, SIOCGIFFLAGS, ifr)) {
+ nice_debug ("Error : Unable to get IP information for interface %s."
+ " Skipping...", ifr->ifr_name);
+ continue; /* failed to get flags, skip it */
+ }
-static gboolean
-nice_interfaces_is_private_ip (const struct sockaddr *_sa)
-{
- union {
- const struct sockaddr *addr;
- const struct sockaddr_in *in;
- } sa;
+ /* no ip address from interface that is down */
+ if ((ifr->ifr_flags & IFF_UP) == 0)
+ continue;
- sa.addr = _sa;
+ /* no ip address from interface that isn't running */
+ if ((ifr->ifr_flags & IFF_RUNNING) == 0)
+ continue;
- if (sa.addr->sa_family == AF_INET) {
- /* 10.x.x.x/8 */
- if (sa.in->sin_addr.s_addr >> 24 == 0x0A)
- return TRUE;
+ sa.sa = &ifr->ifr_addr;
+ nice_debug ("Interface: %s", ifr->ifr_name);
+ nice_debug ("IP Address: %s", inet_ntoa (sa.sin->sin_addr));
+ if ((ifr->ifr_flags & IFF_LOOPBACK) == IFF_LOOPBACK){
+ if (include_loopback)
+ loopbacks = add_ip_to_list (loopbacks, g_strdup (inet_ntoa (sa.sin->sin_addr)), TRUE);
+ else
+ nice_debug ("Ignoring loopback interface");
+ continue;
+ }
- /* 172.16.0.0 - 172.31.255.255 = 172.16.0.0/10 */
- if (sa.in->sin_addr.s_addr >> 20 == 0xAC1)
- return TRUE;
+#ifdef IGNORED_IFACE_PREFIX
+ ignored = FALSE;
+ for (prefix = ignored_iface_prefix_list; *prefix; prefix++) {
+ if (g_str_has_prefix (ifr->ifr_name, *prefix)) {
+ nice_debug ("Ignoring interface %s as it matches prefix %s",
+ ifr->ifr_name, *prefix);
+ ignored = TRUE;
+ break;
+ }
+ }
- /* 192.168.x.x/16 */
- if (sa.in->sin_addr.s_addr >> 16 == 0xC0A8)
- return TRUE;
+ if (ignored)
+ continue;
+#endif
- /* 169.254.x.x/16 (for APIPA) */
- if (sa.in->sin_addr.s_addr >> 16 == 0xA9FE)
- return TRUE;
+ if (nice_interfaces_is_private_ip (sa.sa)) {
+ ips = add_ip_to_list (ips, g_strdup (inet_ntoa (sa.sin->sin_addr)), TRUE);
+ } else {
+ ips = add_ip_to_list (ips, g_strdup (inet_ntoa (sa.sin->sin_addr)), FALSE);
+ }
}
-
- return FALSE;
-}
-static GList *
-add_ip_to_list (GList *list, gchar *ip, gboolean append)
-{
- GList *i;
+ close (sockfd);
+ free (ifc.ifc_req);
- for (i = list; i; i = i->next) {
- gchar *addr = (gchar *) i->data;
+ if (loopbacks)
+ ips = g_list_concat (ips, loopbacks);
- if (g_strcmp0 (addr, ip) == 0)
- return list;
- }
- if (append)
- return g_list_append (list, ip);
- else
- return g_list_prepend (list, ip);
+ return ips;
}
#ifdef HAVE_GETIFADDRS
GList *ips = NULL;
struct ifaddrs *ifa, *results;
GList *loopbacks = NULL;
+#ifdef IGNORED_IFACE_PREFIX
+ const gchar **prefix;
+ gboolean ignored;
+#endif
-
- if (getifaddrs (&results) < 0)
- return NULL;
+ if (getifaddrs (&results) < 0) {
+ nice_debug ("Failed to retrieve list of network interfaces with \"getifaddrs\": %s."
+ "Trying to use fallback ...", strerror (errno));
+ return get_local_ips_ioctl (include_loopback);
+ }
/* Loop through the interface list and get the IP address of each IF */
for (ifa = results; ifa; ifa = ifa->ifa_next) {
if ((ifa->ifa_flags & IFF_UP) == 0)
continue;
+ /* no ip address from interface that isn't running */
+ if ((ifa->ifa_flags & IFF_RUNNING) == 0)
+ continue;
+
if (ifa->ifa_addr == NULL)
continue;
nice_debug ("Ignoring loopback interface");
g_free (addr_string);
}
+ continue;
+ }
+
#ifdef IGNORED_IFACE_PREFIX
- } else if (g_str_has_prefix (ifa->ifa_name, IGNORED_IFACE_PREFIX)) {
- nice_debug ("Ignoring interface %s as it matches prefix %s",
- ifa->ifa_name, IGNORED_IFACE_PREFIX);
- g_free (addr_string);
-#endif
- } else {
- if (nice_interfaces_is_private_ip (ifa->ifa_addr))
- ips = add_ip_to_list (ips, addr_string, TRUE);
- else
- ips = add_ip_to_list (ips, addr_string, FALSE);
+ ignored = FALSE;
+ for (prefix = ignored_iface_prefix_list; *prefix; prefix++) {
+ if (g_str_has_prefix (ifa->ifa_name, *prefix)) {
+ nice_debug ("Ignoring interface %s as it matches prefix %s",
+ ifa->ifa_name, *prefix);
+ g_free (addr_string);
+ ignored = TRUE;
+ break;
+ }
}
+
+ if (ignored)
+ continue;
+#endif
+
+ if (nice_interfaces_is_private_ip (ifa->ifa_addr))
+ ips = add_ip_to_list (ips, addr_string, TRUE);
+ else
+ ips = add_ip_to_list (ips, addr_string, FALSE);
}
freeifaddrs (results);
GList *
nice_interfaces_get_local_ips (gboolean include_loopback)
{
- GList *ips = NULL;
- gint sockfd;
- gint size = 0;
- struct ifreq *ifr;
- struct ifconf ifc;
- struct sockaddr_in *sa;
- gchar *loopback = NULL;
-
- if ((sockfd = socket (AF_INET, SOCK_DGRAM, IPPROTO_IP)) < 0) {
- nice_debug ("Error : Cannot open socket to retrieve interface list");
- return NULL;
- }
-
- ifc.ifc_len = 0;
- ifc.ifc_req = NULL;
-
- /* Loop and get each interface the system has, one by one... */
- do {
- size += sizeof (struct ifreq);
- /* realloc buffer size until no overflow occurs */
- if (NULL == (ifc.ifc_req = realloc (ifc.ifc_req, size))) {
- nice_debug ("Error : Out of memory while allocation interface"
- " configuration structure");
- close (sockfd);
- return NULL;
- }
- ifc.ifc_len = size;
-
- if (ioctl (sockfd, SIOCGIFCONF, &ifc)) {
- perror ("ioctl SIOCFIFCONF");
- close (sockfd);
- free (ifc.ifc_req);
- return NULL;
- }
- } while (size <= ifc.ifc_len);
-
-
- /* Loop throught the interface list and get the IP address of each IF */
- for (ifr = ifc.ifc_req;
- (gchar *) ifr < (gchar *) ifc.ifc_req + ifc.ifc_len;
- ++ifr) {
-
- if (ioctl (sockfd, SIOCGIFFLAGS, ifr)) {
- nice_debug ("Error : Unable to get IP information for interface %s."
- " Skipping...", ifr->ifr_name);
- continue; /* failed to get flags, skip it */
- }
- sa = (struct sockaddr_in *) &ifr->ifr_addr;
- nice_debug ("Interface: %s", ifr->ifr_name);
- nice_debug ("IP Address: %s", inet_ntoa (sa->sin_addr));
- if ((ifr->ifr_flags & IFF_LOOPBACK) == IFF_LOOPBACK){
- if (include_loopback)
- loopback = g_strdup (inet_ntoa (sa->sin_addr));
- else
- nice_debug ("Ignoring loopback interface");
- } else {
- if (nice_interfaces_is_private_ip ((struct sockaddr *) sa)) {
- ips = add_ip_to_list (ips, g_strdup (inet_ntoa (sa->sin_addr)), TRUE);
- } else {
- ips = add_ip_to_list (ips, g_strdup (inet_ntoa (sa->sin_addr)), FALSE);
- }
- }
- }
-
- close (sockfd);
- free (ifc.ifc_req);
-
- if (loopback)
- ips = add_ip_to_list (ips, loopback, TRUE);
-
- return ips;
+ return get_local_ips_ioctl (include_loopback);
}
#endif /* HAVE_GETIFADDRS */