Skip to content
Snippets Groups Projects
Commit 008cf1bb authored by Reiner Hauser's avatar Reiner Hauser
Browse files

Update to latest boost::asio, better IPv6 support.

Make use of newer boost::asio methods, avoid deprecated ones.
Switch to <address>/<prefix> notation instead of <address>/<netmask>.
parent 9d36eb93
Branches ipv6
No related tags found
No related merge requests found
......@@ -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;
......
......@@ -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)
......
......@@ -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;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment