Mercurial > pidgin.yaz
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) {