diff options
author | Adam Ierymenko <adam.ierymenko@gmail.com> | 2018-01-25 14:59:11 -0500 |
---|---|---|
committer | Adam Ierymenko <adam.ierymenko@gmail.com> | 2018-01-25 14:59:11 -0500 |
commit | 125ec622ca446021ad3d2a707752b11fcb5dd195 (patch) | |
tree | 2da8ecc9cfb6a34165cc556def152497e85a9002 /osdep | |
parent | 384e5b66decbbe3eda00b95690c6a56cb140c4f7 (diff) | |
download | infinitytier-125ec622ca446021ad3d2a707752b11fcb5dd195.tar.gz infinitytier-125ec622ca446021ad3d2a707752b11fcb5dd195.zip |
Add bindToWildcard local.conf option.
Diffstat (limited to 'osdep')
-rw-r--r-- | osdep/Binder.hpp | 316 |
1 files changed, 159 insertions, 157 deletions
diff --git a/osdep/Binder.hpp b/osdep/Binder.hpp index e10c0080..f5fc32e3 100644 --- a/osdep/Binder.hpp +++ b/osdep/Binder.hpp @@ -125,184 +125,110 @@ public: * * @param phy Physical interface * @param ports Ports to bind on all interfaces - * @param ignoreInterfacesByName Ignore these interfaces by name - * @param ignoreInterfacesByNamePrefix Ignore these interfaces by name-prefix (starts-with, e.g. zt ignores zt*) - * @param ignoreInterfacesByAddress Ignore these interfaces by address + * @param portCount Number of ports + * @param bindtoWildcard If true, bind wildcard instead of per-interface IPs + * @param ifChecker Interface checker function to see if an interface should be used * @tparam PHY_HANDLER_TYPE Type for Phy<> template * @tparam INTERFACE_CHECKER Type for class containing shouldBindInterface() method */ template<typename PHY_HANDLER_TYPE,typename INTERFACE_CHECKER> - void refresh(Phy<PHY_HANDLER_TYPE> &phy,unsigned int *ports,unsigned int portCount,INTERFACE_CHECKER &ifChecker) + void refresh(Phy<PHY_HANDLER_TYPE> &phy,unsigned int *ports,unsigned int portCount,bool bindToWildcard,INTERFACE_CHECKER &ifChecker) { std::map<InetAddress,std::string> localIfAddrs; PhySocket *udps,*tcps; Mutex::Lock _l(_lock); bool interfacesEnumerated = true; + if (!bindToWildcard) { #ifdef __WINDOWS__ - char aabuf[32768]; - ULONG aalen = sizeof(aabuf); - if (GetAdaptersAddresses(AF_UNSPEC,GAA_FLAG_SKIP_ANYCAST|GAA_FLAG_SKIP_MULTICAST|GAA_FLAG_SKIP_DNS_SERVER,(void *)0,reinterpret_cast<PIP_ADAPTER_ADDRESSES>(aabuf),&aalen) == NO_ERROR) { - PIP_ADAPTER_ADDRESSES a = reinterpret_cast<PIP_ADAPTER_ADDRESSES>(aabuf); - while (a) { - PIP_ADAPTER_UNICAST_ADDRESS ua = a->FirstUnicastAddress; - while (ua) { - InetAddress ip(ua->Address.lpSockaddr); - if (ifChecker.shouldBindInterface("",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: - for(int x=0;x<(int)portCount;++x) { - ip.setPort(ports[x]); - localIfAddrs.insert(std::pair<InetAddress,std::string>(ip,std::string())); - } - break; + char aabuf[32768]; + ULONG aalen = sizeof(aabuf); + if (GetAdaptersAddresses(AF_UNSPEC,GAA_FLAG_SKIP_ANYCAST|GAA_FLAG_SKIP_MULTICAST|GAA_FLAG_SKIP_DNS_SERVER,(void *)0,reinterpret_cast<PIP_ADAPTER_ADDRESSES>(aabuf),&aalen) == NO_ERROR) { + PIP_ADAPTER_ADDRESSES a = reinterpret_cast<PIP_ADAPTER_ADDRESSES>(aabuf); + while (a) { + PIP_ADAPTER_UNICAST_ADDRESS ua = a->FirstUnicastAddress; + while (ua) { + InetAddress ip(ua->Address.lpSockaddr); + if (ifChecker.shouldBindInterface("",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: + for(int x=0;x<(int)portCount;++x) { + ip.setPort(ports[x]); + localIfAddrs.insert(std::pair<InetAddress,std::string>(ip,std::string())); + } + break; + } } + ua = ua->Next; } - ua = ua->Next; + a = a->Next; } - a = a->Next; } - } - else { - interfacesEnumerated = false; - } + else { + interfacesEnumerated = false; + } #else // not __WINDOWS__ - /* On Linux we use an alternative method if available since getifaddrs() - * gets very slow when there are lots of network namespaces. This won't - * work unless /proc/PID/net/if_inet6 exists and it may not on some - * embedded systems, so revert to getifaddrs() there. */ + /* On Linux we use an alternative method if available since getifaddrs() + * gets very slow when there are lots of network namespaces. This won't + * work unless /proc/PID/net/if_inet6 exists and it may not on some + * embedded systems, so revert to getifaddrs() there. */ #ifdef __LINUX__ - char fn[256],tmp[256]; - std::set<std::string> ifnames; - const unsigned long pid = (unsigned long)getpid(); - - // Get all device names - OSUtils::ztsnprintf(fn,sizeof(fn),"/proc/%lu/net/dev",pid); - FILE *procf = fopen(fn,"r"); - if (procf) { - while (fgets(tmp,sizeof(tmp),procf)) { - tmp[255] = 0; - char *saveptr = (char *)0; - for(char *f=Utils::stok(tmp," \t\r\n:|",&saveptr);(f);f=Utils::stok((char *)0," \t\r\n:|",&saveptr)) { - if ((strcmp(f,"Inter-") != 0)&&(strcmp(f,"face") != 0)&&(f[0] != 0)) - ifnames.insert(f); - break; // we only want the first field - } - } - fclose(procf); - } - else { - interfacesEnumerated = false; - } - - // Get IPv6 addresses (and any device names we don't already know) - OSUtils::ztsnprintf(fn,sizeof(fn),"/proc/%lu/net/if_inet6",pid); - procf = fopen(fn,"r"); - if (procf) { - while (fgets(tmp,sizeof(tmp),procf)) { - tmp[255] = 0; - char *saveptr = (char *)0; - unsigned char ipbits[16]; - memset(ipbits,0,sizeof(ipbits)); - char *devname = (char *)0; - int n = 0; - for(char *f=Utils::stok(tmp," \t\r\n",&saveptr);(f);f=Utils::stok((char *)0," \t\r\n",&saveptr)) { - switch(n++) { - case 0: // IP in hex - Utils::unhex(f,32,ipbits,16); - break; - case 5: // device name - devname = f; - break; - } - } - if (devname) { - ifnames.insert(devname); - InetAddress ip(ipbits,16,0); - if (ifChecker.shouldBindInterface(devname,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: - for(int x=0;x<(int)portCount;++x) { - ip.setPort(ports[x]); - localIfAddrs.insert(std::pair<InetAddress,std::string>(ip,std::string(devname))); - } - break; - } + char fn[256],tmp[256]; + std::set<std::string> ifnames; + const unsigned long pid = (unsigned long)getpid(); + + // Get all device names + OSUtils::ztsnprintf(fn,sizeof(fn),"/proc/%lu/net/dev",pid); + FILE *procf = fopen(fn,"r"); + if (procf) { + while (fgets(tmp,sizeof(tmp),procf)) { + tmp[255] = 0; + char *saveptr = (char *)0; + for(char *f=Utils::stok(tmp," \t\r\n:|",&saveptr);(f);f=Utils::stok((char *)0," \t\r\n:|",&saveptr)) { + if ((strcmp(f,"Inter-") != 0)&&(strcmp(f,"face") != 0)&&(f[0] != 0)) + ifnames.insert(f); + break; // we only want the first field } } + fclose(procf); + } + else { + interfacesEnumerated = false; } - fclose(procf); - } - // Get IPv4 addresses for each device - if (ifnames.size() > 0) { - const int controlfd = (int)socket(AF_INET,SOCK_DGRAM,0); - 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: - for(int x=0;x<(int)portCount;++x) { - ip.setPort(ports[x]); - localIfAddrs.insert(std::pair<InetAddress,std::string>(ip,ifname)); + // Get IPv6 addresses (and any device names we don't already know) + OSUtils::ztsnprintf(fn,sizeof(fn),"/proc/%lu/net/if_inet6",pid); + procf = fopen(fn,"r"); + if (procf) { + while (fgets(tmp,sizeof(tmp),procf)) { + tmp[255] = 0; + char *saveptr = (char *)0; + unsigned char ipbits[16]; + memset(ipbits,0,sizeof(ipbits)); + char *devname = (char *)0; + int n = 0; + for(char *f=Utils::stok(tmp," \t\r\n",&saveptr);(f);f=Utils::stok((char *)0," \t\r\n",&saveptr)) { + switch(n++) { + case 0: // IP in hex + Utils::unhex(f,32,ipbits,16); + break; + case 5: // device name + devname = f; + break; } - break; } - } - } - - ip4_address_error: - free(configuration.ifc_buf); - if (controlfd > 0) close(controlfd); - } - - const bool gotViaProc = (localIfAddrs.size() > 0); -#else - const bool gotViaProc = false; -#endif - - if (!gotViaProc) { - struct ifaddrs *ifatbl = (struct ifaddrs *)0; - struct ifaddrs *ifa; - if ((getifaddrs(&ifatbl) == 0)&&(ifatbl)) { - ifa = ifatbl; - while (ifa) { - if ((ifa->ifa_name)&&(ifa->ifa_addr)) { - InetAddress ip = *(ifa->ifa_addr); - if (ifChecker.shouldBindInterface(ifa->ifa_name,ip)) { + if (devname) { + ifnames.insert(devname); + InetAddress ip(ipbits,16,0); + if (ifChecker.shouldBindInterface(devname,ip)) { switch(ip.ipScope()) { default: break; case InetAddress::IP_SCOPE_PSEUDOPRIVATE: @@ -311,23 +237,99 @@ public: case InetAddress::IP_SCOPE_PRIVATE: for(int x=0;x<(int)portCount;++x) { ip.setPort(ports[x]); - localIfAddrs.insert(std::pair<InetAddress,std::string>(ip,std::string(ifa->ifa_name))); + localIfAddrs.insert(std::pair<InetAddress,std::string>(ip,std::string(devname))); } break; } } } - ifa = ifa->ifa_next; } - freeifaddrs(ifatbl); + fclose(procf); } - else { - interfacesEnumerated = false; + + // Get IPv4 addresses for each device + if (ifnames.size() > 0) { + const int controlfd = (int)socket(AF_INET,SOCK_DGRAM,0); + 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: + for(int x=0;x<(int)portCount;++x) { + ip.setPort(ports[x]); + localIfAddrs.insert(std::pair<InetAddress,std::string>(ip,ifname)); + } + break; + } + } + } + + ip4_address_error: + free(configuration.ifc_buf); + if (controlfd > 0) close(controlfd); } - } + const bool gotViaProc = (localIfAddrs.size() > 0); +#else + const bool gotViaProc = false; #endif + if (!gotViaProc) { + struct ifaddrs *ifatbl = (struct ifaddrs *)0; + struct ifaddrs *ifa; + if ((getifaddrs(&ifatbl) == 0)&&(ifatbl)) { + ifa = ifatbl; + while (ifa) { + if ((ifa->ifa_name)&&(ifa->ifa_addr)) { + InetAddress ip = *(ifa->ifa_addr); + if (ifChecker.shouldBindInterface(ifa->ifa_name,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: + for(int x=0;x<(int)portCount;++x) { + ip.setPort(ports[x]); + localIfAddrs.insert(std::pair<InetAddress,std::string>(ip,std::string(ifa->ifa_name))); + } + break; + } + } + } + ifa = ifa->ifa_next; + } + freeifaddrs(ifatbl); + } + else { + interfacesEnumerated = false; + } + } + +#endif + } + // Default to binding to wildcard if we can't enumerate addresses if (!interfacesEnumerated && localIfAddrs.empty()) { for(int x=0;x<(int)portCount;++x) { |