diff --git a/asyncmsg/NameService.h b/asyncmsg/NameService.h index 170abbba6973e85c4fe971105a4431a6e4be5ceb..a8a72790cee2766deb1b10f4c4a6740a5e2c09d8 100644 --- a/asyncmsg/NameService.h +++ b/asyncmsg/NameService.h @@ -2,15 +2,16 @@ #ifndef ASYNCMSG_NAMESERVICE_H_ #define ASYNCMSG_NAMESERVICE_H_ +#include "ipc/partition.h" +#include "ers/Issue.h" + +#include "boost/asio.hpp" + #include <vector> #include <string> #include <map> -#include <tuple> #include <cstdint> -#include "boost/asio.hpp" - -#include "ipc/partition.h" -#include "ers/Issue.h" +#include <variant> namespace daq { @@ -144,10 +145,10 @@ namespace daq { */ std::string lookup_multicast_address(const std::string& addr) const; - /** typedef for readability, a 2-tuple of IP addresses representing network/netmask. */ - typedef std::tuple<boost::asio::ip::address,boost::asio::ip::address> Network; + /** typedef for readability, either a ipv4 or ipv6 network */ + using Network = std::variant<boost::asio::ip::network_v4, boost::asio::ip::network_v6>; - /** \brief A helper method to parse a string of the form network/netmask. + /** \brief A helper method to parse a string of the form network/prefix. */ static Network parse_address_network(const std::string& network); @@ -157,7 +158,7 @@ namespace daq { private: - bool matches(const boost::asio::ip::address& addr, const boost::asio::ip::address& mask) const; + bool matches(const Network& addr_mask) const; IPCPartition m_partition; std::string m_is_server; diff --git a/src/NameService.cxx b/src/NameService.cxx index 9e67dd3a9435192e46928d588977dca96a5263c4..02c4ce10bb34b7a8b88b1bedd9ee1b2dabeeaccc 100644 --- a/src/NameService.cxx +++ b/src/NameService.cxx @@ -33,7 +33,6 @@ #include <algorithm> #include <map> // for map, map<>::mapped_type #include <string> // for string, allocator, operator+ -#include <tuple> // for tie, get, tuple, make_tuple #include <vector> // for vector @@ -99,33 +98,20 @@ namespace daq { for(const auto& network : m_data_networks) { - auto& addr = std::get<0>(network); - auto& mask = std::get<1>(network); + if((network.index() == 0) && (intf->family() == AF_INET)) { - if(addr.is_v4() && intf->family() == AF_INET) { - auto addr4(addr.to_v4()); - auto mask4(mask.to_v4()); + auto addr(std::get<0>(network).network()); - if(htonl(addr4.to_ulong() & mask4.to_ulong()) == (intf->address() & htonl(mask4.to_ulong()))) { - info.Addresses.push_back(intf->address_string() + '/' + mask4.to_string()); + if(htonl(addr.to_ulong()) == intf->network()) { + info.Addresses.push_back(intf->address_string() + '/' + std::to_string(std::get<0>(network).prefix_length())); } - } else if(addr.is_v6() && intf->family() == AF_INET6) { - auto addr6(addr.to_v6().to_bytes()); - auto mask6(mask.to_v6().to_bytes()); + } else if((network.index() == 1) && (intf->family() == AF_INET6)) { + auto addr(std::get<1>(network).network().to_bytes()); auto local_network = intf->network_v6(); - - bool matches = true; - for(size_t i = 0; i < addr6.size(); i++) { - if((addr6[i] & mask6[i]) != local_network.s6_addr[i]) { - matches = false; - break; - } - } - - if(matches) { - info.Addresses.push_back(intf->address_string() + '/' + intf->netmask_string()); + if(memcmp(&addr[0], &local_network.s6_addr[0], addr.size()) == 0) { + info.Addresses.push_back(intf->address_string() + '/' + std::to_string(std::get<1>(network).prefix_length())); } } } @@ -171,39 +157,32 @@ namespace daq { throw InvalidISServer(ERS_HERE, servers.name(), reason); } } - } - bool NameService::matches(const boost::asio::ip::address& addr, const boost::asio::ip::address& mask) const + bool NameService::matches(const Network& addr_mask) const { for(const auto intf : daq::asyncmsg::Interface::interfaces()) { // ignore these - if(!intf->has_flag(IFF_UP) || intf->has_flag(IFF_LOOPBACK) || intf->address() == 0) { + if(!intf->has_flag(IFF_UP) || intf->has_flag(IFF_LOOPBACK)) { continue; } - + // compare IPV4 address - if(addr.is_v4() && intf->family() == AF_INET) { - if(htonl(addr.to_v4().to_ulong() & mask.to_v4().to_ulong()) == (intf->network() & htonl(mask.to_v4().to_ulong()))) { - // found one, first match will be used + if(addr_mask.index() == 0 && intf->family() == AF_INET && intf->address() != 0) { + auto addr(std::get<0>(addr_mask).network().to_bytes()); + auto local_network = intf->network(); + + if(memcmp(&addr[0], &local_network, addr.size()) == 0) { return true; } - } else if (addr.is_v6() && intf->family() == AF_INET6) { - auto addr6(addr.to_v6().to_bytes()); - auto mask6(mask.to_v6().to_bytes()); - + } else if (addr_mask.index() == 1 && intf->family() == AF_INET6) { + auto addr(std::get<1>(addr_mask).network().to_bytes()); auto local_network = intf->network_v6(); - bool matches = true; - for(size_t i = 0; i < addr6.size(); i++) { - if((addr6[i] & mask6[i]) != local_network.s6_addr[i]) { - matches = false; - break; - } + if(memcmp(&addr[0], &local_network.s6_addr[0], addr.size()) == 0) { + return true; } - - return matches; } } @@ -229,10 +208,14 @@ namespace daq { // match my local interfaces against the list for(auto& addr_netmask : info.Addresses) { boost::asio::ip::address addr, mask; - std::tie(addr, mask) = parse_address_network(addr_netmask); - - if(matches(addr, mask)) { - results.push_back(boost::asio::ip::tcp::endpoint(addr, info.Port)); + Network addr_mask = parse_address_network(addr_netmask); + if(matches(addr_mask)) { + // retrieve address part only + if(addr_mask.index() == 0) { + results.push_back(boost::asio::ip::tcp::endpoint(std::get<0>(addr_mask).address(), info.Port)); + } else { + results.push_back(boost::asio::ip::tcp::endpoint(std::get<1>(addr_mask).address(), info.Port)); + } break; } } @@ -259,10 +242,14 @@ namespace daq { // match my local interfaces against the list for(auto& addr_netmask : info.Addresses) { boost::asio::ip::address addr, mask; - std::tie(addr, mask) = parse_address_network(addr_netmask); + Network addr_mask = parse_address_network(addr_netmask); - if(matches(addr, mask)) { - results[name.substr(m_is_server.size() + 5)] = boost::asio::ip::tcp::endpoint(addr, info.Port); + if(matches(addr_mask)) { + if(addr_mask.index() == 0) { + results[name.substr(m_is_server.size() + 5)] = boost::asio::ip::tcp::endpoint(std::get<0>(addr_mask).address(), info.Port); + } else { + results[name.substr(m_is_server.size() + 5)] = boost::asio::ip::tcp::endpoint(std::get<1>(addr_mask).address(), info.Port); + } break; } } @@ -288,11 +275,14 @@ namespace daq { // match my local interfaces against the list for(auto& addr_netmask : info.Addresses) { - boost::asio::ip::address addr, mask; - std::tie(addr, mask) = parse_address_network(addr_netmask); + Network addr_mask = parse_address_network(addr_netmask); - if(matches(addr, mask)) { - results[name.substr(m_is_server.size() + 5)].push_back(boost::asio::ip::tcp::endpoint(addr, info.Port)); + if(matches(addr_mask)) { + if(addr_mask.index() == 0) { + results[name.substr(m_is_server.size() + 5)].push_back(boost::asio::ip::tcp::endpoint(std::get<0>(addr_mask).address(), info.Port)); + } else { + results[name.substr(m_is_server.size() + 5)].push_back(boost::asio::ip::tcp::endpoint(std::get<1>(addr_mask).address(), info.Port)); + } } } } @@ -311,11 +301,14 @@ namespace daq { d.getValue(m_is_server + ".MSG_" + name, info); for(auto& addr_netmask : info.Addresses) { - boost::asio::ip::address addr, mask; - std::tie(addr, mask) = parse_address_network(addr_netmask); - - if(matches(addr, mask)) { - return boost::asio::ip::tcp::endpoint(addr, info.Port); + Network addr_mask = parse_address_network(addr_netmask); + + if(matches(addr_mask)) { + if(addr_mask.index() == 0) { + return boost::asio::ip::tcp::endpoint(std::get<0>(addr_mask).address(), info.Port); + } else { + return boost::asio::ip::tcp::endpoint(std::get<1>(addr_mask).address(), info.Port); + } } } @@ -326,15 +319,14 @@ namespace daq { NameService::Network NameService::parse_address_network(const std::string& network) { - size_t slash = network.find('/'); - std::string address = network.substr(0, slash); - std::string netmask = "255.255.255.255"; - if(slash != std::string::npos) { - netmask = network.substr(slash+1); - } + boost::system::error_code ec; - return std::make_tuple(boost::asio::ip::address::from_string(address), - boost::asio::ip::address::from_string(netmask)); + // Try v4 first + Network result{boost::asio::ip::make_network_v4(network, ec)}; + if(!ec.failed()) { + return result; + } + return Network{boost::asio::ip::make_network_v6(network)}; } boost::asio::ip::address NameService::find_interface(const std::string& netmask) diff --git a/test/test_namesvc.cxx b/test/test_namesvc.cxx index 83b4b13ca87b343bccc4dd0a5503f01269b30a70..0f5f8529c167f09a5bfab5519f85bbdf46d16460 100644 --- a/test/test_namesvc.cxx +++ b/test/test_namesvc.cxx @@ -37,12 +37,8 @@ int main(int argc, char *argv[]) // DFParameters.DefaultDataNetworks // // CERN GPN - // Testbed B.4 pub, internal // - std::vector<std::string> data_networks{"137.138.0.0/255.255.0.0", - "188.184.2.64/255.255.255.192", - "10.193.128.0/255.255.254.0", - "10.193.64.0/255.255.254.0"}; + std::vector<std::string> data_networks{"137.138.0.0/16"}; argv += 3; argc -= 3;