diff options
author | Adam Ierymenko <adam.ierymenko@zerotier.com> | 2017-01-19 10:47:47 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-01-19 10:47:47 -0800 |
commit | 989cbb4d8dc9a507115ed49bdcffb88b781e2b91 (patch) | |
tree | 5d7a3238c7c2a2786d0e5c6b2c3d1dfd91b601e3 | |
parent | e9007b1f569ce15780ed34b837db987eec457d2f (diff) | |
parent | 203b7e17de09c9f19b51be1435b326fb56ea3d8d (diff) | |
download | infinitytier-989cbb4d8dc9a507115ed49bdcffb88b781e2b91.tar.gz infinitytier-989cbb4d8dc9a507115ed49bdcffb88b781e2b91.zip |
Merge pull request #434 from zielmicha/fix-ip
Binder.hpp: gather all IPv4 interface addresses
-rw-r--r-- | osdep/Binder.hpp | 58 |
1 files changed, 37 insertions, 21 deletions
diff --git a/osdep/Binder.hpp b/osdep/Binder.hpp index d017f6d4..9829f170 100644 --- a/osdep/Binder.hpp +++ b/osdep/Binder.hpp @@ -236,30 +236,46 @@ public: // Get IPv4 addresses for each device if (ifnames.size() > 0) { const int controlfd = (int)socket(AF_INET,SOCK_DGRAM,0); - if (controlfd >= 0) { - for(std::set<std::string>::iterator devname(ifnames.begin());devname!=ifnames.end();++devname) { - struct ifreq ifr; - memset(&ifr,0,sizeof(ifr)); - ifr.ifr_addr.sa_family = AF_INET; - Utils::scopy(ifr.ifr_name,sizeof(ifr.ifr_name),devname->c_str()); - if (ioctl(controlfd,SIOCGIFADDR,&ifr) >= 0) { - InetAddress ip(&(((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr),4,0); - if (ifChecker.shouldBindInterface(devname->c_str(),ip)) { - switch(ip.ipScope()) { - default: break; - case InetAddress::IP_SCOPE_PSEUDOPRIVATE: - case InetAddress::IP_SCOPE_GLOBAL: - case InetAddress::IP_SCOPE_SHARED: - case InetAddress::IP_SCOPE_PRIVATE: - ip.setPort(port); - localIfAddrs.insert(std::pair<InetAddress,std::string>(ip,*devname)); - break; - } - } + struct ifconf configuration; + configuration.ifc_len = 0; + configuration.ifc_buf = nullptr; + + if (controlfd < 0) goto ip4_address_error; + + if (ioctl(controlfd, SIOCGIFCONF, &configuration) < 0) goto ip4_address_error; + + configuration.ifc_buf = (char*)malloc(configuration.ifc_len); + + if (ioctl(controlfd, SIOCGIFCONF, &configuration) < 0) goto ip4_address_error; + + for (int i=0; i < (int)(configuration.ifc_len / sizeof(ifreq)); i ++) { + struct ifreq& request = configuration.ifc_req[i]; + struct sockaddr* addr = &request.ifr_ifru.ifru_addr; + if (addr->sa_family != AF_INET) continue; + std::string ifname = request.ifr_ifrn.ifrn_name; + // name can either be just interface name or interface name followed by ':' and arbitrary label + if (ifname.find(':') != std::string::npos) { + ifname = ifname.substr(0, ifname.find(':')); + } + + InetAddress ip(&(((struct sockaddr_in *)addr)->sin_addr),4,0); + if (ifChecker.shouldBindInterface(ifname.c_str(), ip)) { + switch(ip.ipScope()) { + default: break; + case InetAddress::IP_SCOPE_PSEUDOPRIVATE: + case InetAddress::IP_SCOPE_GLOBAL: + case InetAddress::IP_SCOPE_SHARED: + case InetAddress::IP_SCOPE_PRIVATE: + ip.setPort(port); + localIfAddrs.insert(std::pair<InetAddress,std::string>(ip, ifname)); + break; } } - close(controlfd); } + + ip4_address_error: + free(configuration.ifc_buf); + if (controlfd > 0) close(controlfd); } const bool gotViaProc = (localIfAddrs.size() > 0); |