--- embedaddon/miniupnpd/getifaddr.c 2012/02/21 23:16:02 1.1.1.1 +++ embedaddon/miniupnpd/getifaddr.c 2012/05/29 12:55:57 1.1.1.2 @@ -1,10 +1,11 @@ -/* $Id: getifaddr.c,v 1.1.1.1 2012/02/21 23:16:02 misho Exp $ */ +/* $Id: getifaddr.c,v 1.1.1.2 2012/05/29 12:55:57 misho Exp $ */ /* MiniUPnP project * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006-2008 Thomas Bernard + * (c) 2006-2011 Thomas Bernard * This software is subject to the conditions detailed * in the LICENCE file provided within the distribution */ +#include #include #include #include @@ -18,17 +19,24 @@ #include #endif +#include "config.h" #include "getifaddr.h" +#if defined(USE_GETIFADDRS) || defined(ENABLE_IPV6) +#include +#endif int getifaddr(const char * ifname, char * buf, int len) { +#ifndef USE_GETIFADDRS + /* use ioctl SIOCGIFADDR. Works only for ip v4 */ /* SIOCGIFADDR struct ifreq * */ int s; struct ifreq ifr; int ifrlen; struct sockaddr_in * addr; ifrlen = sizeof(ifr); + if(!ifname || ifname[0]=='\0') return -1; s = socket(PF_INET, SOCK_DGRAM, 0); @@ -52,6 +60,83 @@ getifaddr(const char * ifname, char * buf, int len) return -1; } close(s); +#else /* ifndef USE_GETIFADDRS */ + /* Works for all address families (both ip v4 and ip v6) */ + struct ifaddrs * ifap; + struct ifaddrs * ife; + + if(!ifname || ifname[0]=='\0') + return -1; + if(getifaddrs(&ifap)<0) + { + syslog(LOG_ERR, "getifaddrs: %m"); + return -1; + } + for(ife = ifap; ife; ife = ife->ifa_next) + { + /* skip other interfaces */ + if(0 != strcmp(ifname, ife->ifa_name)) + continue; + switch(ife->ifa_addr->sa_family) + { + case AF_INET: + inet_ntop(ife->ifa_addr->sa_family, + &((struct sockaddr_in *)ife->ifa_addr)->sin_addr, + buf, len); + break; +/* + case AF_INET6: + inet_ntop(ife->ifa_addr->sa_family, + &((struct sockaddr_in6 *)ife->ifa_addr)->sin6_addr, + buf, len); +*/ + } + } + freeifaddrs(ifap); +#endif return 0; } + +#ifdef ENABLE_IPV6 +int +find_ipv6_addr(const char * ifname, + char * dst, int n) +{ + struct ifaddrs * ifap; + struct ifaddrs * ife; + const struct sockaddr_in6 * addr; + char buf[64]; + int r = 0; + + if(!dst) + return -1; + + if(getifaddrs(&ifap)<0) + { + syslog(LOG_ERR, "getifaddrs: %m"); + return -1; + } + for(ife = ifap; ife; ife = ife->ifa_next) + { + /* skip other interfaces if one was specified */ + if(ifname && (0 != strcmp(ifname, ife->ifa_name))) + continue; + if(ife->ifa_addr->sa_family == AF_INET6) + { + addr = (const struct sockaddr_in6 *)ife->ifa_addr; + if(!IN6_IS_ADDR_LOOPBACK(&addr->sin6_addr) + && !IN6_IS_ADDR_LINKLOCAL(&addr->sin6_addr)) + { + inet_ntop(ife->ifa_addr->sa_family, + &addr->sin6_addr, + buf, sizeof(buf)); + /* add brackets */ + snprintf(dst, n, "[%s]", buf); + r = 1; + } + } + } + return r; +} +#endif