diff libpurple/network.c @ 29495:02f6f49da454

Add a function to enumerate all local IPs Adapted the XMPP prpl to include all local IPs as local streamhosts. I haven't had the chance to test if this actually works using a "non-default" interface, such as a VPN connection... Refs #10160
author Marcus Lundblad <ml@update.uu.se>
date Wed, 09 Sep 2009 19:01:03 +0000
parents 7fbf964c6c6c
children f1aa01ff26dd
line wrap: on
line diff
--- a/libpurple/network.c	Fri Sep 04 03:04:33 2009 +0000
+++ b/libpurple/network.c	Wed Sep 09 19:01:03 2009 +0000
@@ -200,6 +200,82 @@
 	return "0.0.0.0";
 }
 
+GList *
+purple_network_get_all_local_system_ips(int fd)
+{
+	GList *result = NULL;
+	int source = fd;
+	char buffer[1024];
+	char *tmp;
+	struct ifconf ifc;
+	struct ifreq *ifr;
+
+	if (fd < 0)
+		source = socket(PF_INET,SOCK_STREAM, 0);
+	
+	ifc.ifc_len = sizeof(buffer);
+	ifc.ifc_req = (struct ifreq *)buffer;
+	ioctl(source, SIOCGIFCONF, &ifc);
+
+	if (fd < 0)
+		close(source);
+
+	/* enumerate the interfaces on IPv4 (or from source given by fd) */
+	tmp = buffer;
+	while (tmp < buffer + ifc.ifc_len) {
+		char dst[INET6_ADDRSTRLEN];
+
+		ifr = (struct ifreq *)tmp;
+		tmp += HX_SIZE_OF_IFREQ(*ifr);
+
+		if (ifr->ifr_addr.sa_family == AF_INET) {
+			struct sockaddr_in *sinptr = (struct sockaddr_in *)&ifr->ifr_addr;
+
+			inet_ntop(AF_INET, &sinptr->sin_addr, dst,
+				sizeof(dst));
+			purple_debug_info("network", 
+				"found local i/f with address %s on IPv4\n", dst);
+			if (!purple_strequal(dst, "127.0.0.1")) {
+				result = g_list_append(result, g_strdup(dst));
+			}
+		}
+	}
+	
+	/* enumerate IPv6 interfaces (done when NOT specifying an fd,
+								  in that case use it (see above)) */
+	if (fd < 0) {
+		source = socket(PF_INET6, SOCK_STREAM, 0);
+	
+		ifc.ifc_len = sizeof(buffer);
+		ifc.ifc_req = (struct ifreq *)buffer;
+		ioctl(source, SIOCGIFCONF, &ifc);
+
+		close(source);
+
+		tmp = buffer;
+		while (tmp < buffer + ifc.ifc_len) {
+			char dst[INET6_ADDRSTRLEN];
+
+			ifr = (struct ifreq *)tmp;
+			tmp += HX_SIZE_OF_IFREQ(*ifr);
+
+			if (ifr->ifr_addr.sa_family == AF_INET6) {
+				struct sockaddr_in6 *sinptr =
+					(struct sockaddr_in6 *)&ifr->ifr_addr;
+
+				inet_ntop(AF_INET6, &sinptr->sin6_addr, dst, sizeof(dst));
+				purple_debug_info("network", 
+					"found local i/f with address %s on IPv4\n", dst);
+				if (!purple_strequal(dst, "::1")) {
+					result = g_list_append(result, g_strdup(dst));
+				}
+			}
+		}
+	}
+
+	return result;
+}
+
 const char *
 purple_network_get_my_ip(int fd)
 {