pidgin.next.minor: b1a88e67: network: Use getifaddrs() to enumerate l...

darkrain42 at pidgin.im darkrain42 at pidgin.im
Mon Feb 15 21:25:42 EST 2010


-----------------------------------------------------------------
Revision: b1a88e6744bf54989e88f6d91369c834026683ac
Ancestor: c126b299b6ed60ee434d905a37b1901ce9572af3
Author: darkrain42 at pidgin.im
Date: 2010-02-16T02:21:33
Branch: im.pidgin.pidgin.next.minor
URL: http://d.pidgin.im/viewmtn/revision/info/b1a88e6744bf54989e88f6d91369c834026683ac

Modified files:
        ChangeLog.API configure.ac libpurple/network.c

ChangeLog: 

network: Use getifaddrs() to enumerate local interfaces/IPs if available.

On Linux, it seems SIOCGIFCONF just doesn't support IPv6, and various
systems have getifaddrs(), so here we are.  Fixes #10160.

-------------- next part --------------
============================================================
--- ChangeLog.API	bfe165f5ce67328f7ea9ef6cfdb716d6f14423b5
+++ ChangeLog.API	55a182de3156def6fee9f3984e73ebaffb7c39df
@@ -11,7 +11,10 @@ version 2.7.0 (??/??/????):
 		* purple_media_codec_copy
 		* purple_media_manager_get_backend_type
 		* purple_media_manager_set_backend_type
-		* purple_network_get_all_local_system_ips
+		* purple_network_get_all_local_system_ips, which returns all local
+		  IPs on the system.  On systems with the getifaddrs() function,
+		  this will return both IPv4 and IPv6 addresses (excluding link-local
+		  and loopback addresses).  On others, it returns just IPv4 addresses.
 		* purple_prpl_got_media_caps
 		* purple_unescape_text
 		* purple_uuid_random
============================================================
--- configure.ac	31fbc023f80de04af3a4d5580ff9efb1aace461c
+++ configure.ac	67d33d06f4a70538608e9a0fbc88d0c17f629f48
@@ -211,6 +211,7 @@ AC_CHECK_FUNCS(inet_ntop)
 	[AC_CHECK_LIB(socket, getaddrinfo,
 		[AC_DEFINE([HAVE_GETADDRINFO]) LIBS="-lsocket -lsnl $LIBS"], , , -lnsl)])
 AC_CHECK_FUNCS(inet_ntop)
+AC_CHECK_FUNCS(getifaddrs)
 dnl Check for socklen_t (in Unix98)
 AC_MSG_CHECKING(for socklen_t)
 AC_TRY_COMPILE([
============================================================
--- libpurple/network.c	df0dd1f1e7e8019d5ad36ba5c69e41668eab4166
+++ libpurple/network.c	0b90658d94de6b28162d3d21107629ffa1ba7600
@@ -32,6 +32,9 @@
 #include <netinet/in.h>
 #include <net/if.h>
 #include <sys/ioctl.h>
+#ifdef HAVE_GETIFADDRS
+#include <ifaddrs.h>
+#endif
 #else
 #include <nspapi.h>
 #endif
@@ -203,7 +206,47 @@ purple_network_get_all_local_system_ips(
 GList *
 purple_network_get_all_local_system_ips(void)
 {
+#ifdef HAVE_GETIFADDRS
 	GList *result = NULL;
+	struct ifaddrs *start, *ifa;
+	int ret;
+
+	ret = getifaddrs(&start);
+	if (ret < 0) {
+		purple_debug_warning("network",
+				"getifaddrs() failed: %s\n", g_strerror(errno));
+		return NULL;
+	}
+
+	for (ifa = start; ifa; ifa = ifa->ifa_next) {
+		int family = ifa->ifa_addr ? ifa->ifa_addr->sa_family : AF_UNSPEC;
+		char host[INET6_ADDRSTRLEN];
+		const char *tmp = NULL;
+
+		if ((family != AF_INET && family != AF_INET6) || ifa->ifa_flags & IFF_LOOPBACK)
+			continue;
+
+		if (family == AF_INET)
+			tmp = inet_ntop(family, &((struct sockaddr_in *)ifa->ifa_addr)->sin_addr, host, sizeof(host));
+		else {
+			struct sockaddr_in6 *sockaddr = (struct sockaddr_in6 *)ifa->ifa_addr;
+			/* Peer-peer link-local communication is a big TODO.  I am not sure
+			 * how communicating link-local addresses is supposed to work, and
+			 * it seems like it would require attempting the cartesian product
+			 * of the local and remote interfaces to see if any match (eww).
+			 */
+			if (!IN6_IS_ADDR_LINKLOCAL(&sockaddr->sin6_addr))
+				tmp = inet_ntop(family, &sockaddr->sin6_addr, host, sizeof(host));
+		}
+		if (tmp != NULL)
+			result = g_list_prepend(result, g_strdup(tmp));
+	}
+
+	freeifaddrs(start);
+
+	return g_list_reverse(result);
+#else /* HAVE_GETIFADDRS */
+	GList *result = NULL;
 	int source = socket(PF_INET,SOCK_STREAM, 0);
 	char buffer[1024];
 	char *tmp;
@@ -222,7 +265,6 @@ purple_network_get_all_local_system_ips(
 		ifr = (struct ifreq *)tmp;
 		tmp += HX_SIZE_OF_IFREQ(*ifr);
 
-		/* TODO: handle IPv6 */
 		if (ifr->ifr_addr.sa_family == AF_INET) {
 			struct sockaddr_in *sinptr = (struct sockaddr_in *)&ifr->ifr_addr;
 
@@ -237,6 +279,7 @@ purple_network_get_all_local_system_ips(
 	}
 
 	return result;
+#endif /* HAVE_GETIFADDRS */
 }
 
 const char *


More information about the Commits mailing list