summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdam Ierymenko <adam.ierymenko@zerotier.com>2017-01-19 10:47:47 -0800
committerGitHub <noreply@github.com>2017-01-19 10:47:47 -0800
commit989cbb4d8dc9a507115ed49bdcffb88b781e2b91 (patch)
tree5d7a3238c7c2a2786d0e5c6b2c3d1dfd91b601e3
parente9007b1f569ce15780ed34b837db987eec457d2f (diff)
parent203b7e17de09c9f19b51be1435b326fb56ea3d8d (diff)
downloadinfinitytier-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.hpp58
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);