Source · fairmq/tools/
Network.cxxsource
Described in Configure channels, Helpers in fair::mq::tools.
1/********************************************************************************2 * Copyright (C) 2017-2025 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *3 * *4 * This software is distributed under the terms of the *5 * GNU Lesser General Public Licence (LGPL) version 3, *6 * copied verbatim in the file "LICENSE" *7 ********************************************************************************/8 9#include <fairlogger/Logger.h>10#include <fairmq/tools/Network.h>11#include <fairmq/tools/Strings.h>12 13#ifndef _GNU_SOURCE14#define _GNU_SOURCE // To get defns of NI_MAXSERV and NI_MAXHOST15#endif16 17#include <array>18#include <boost/algorithm/string.hpp> // trim19#include <boost/asio.hpp>20#include <cstdio>21#include <exception>22#include <fstream>23#include <ifaddrs.h>24#include <iostream>25#include <map>26#include <netdb.h>27#include <stdexcept>28#include <string>29#include <sys/socket.h>30#include <sys/types.h>31 32using namespace std;33 34namespace fair::mq::tools {35 36// returns a map with network interface names as keys and their IP addresses as values37map<string, string> getHostIPs()38{39 map<string, string> addressMap;40 ifaddrs* ifaddr = nullptr;41 ifaddrs* ifa = nullptr;42 int s = 0;43 array<char, NI_MAXHOST> host{};44 45 if (getifaddrs(&ifaddr) == -1) {46 perror("getifaddrs");47 throw runtime_error("getifaddrs failed");48 }49 50 for (ifa = ifaddr; ifa != nullptr; ifa = ifa->ifa_next) {51 if (ifa->ifa_addr == nullptr) {52 continue;53 }54 55 if (ifa->ifa_addr->sa_family == AF_INET) {56 s = getnameinfo(ifa->ifa_addr,57 sizeof(sockaddr_in),58 host.data(),59 NI_MAXHOST,60 nullptr,61 0,62 NI_NUMERICHOST);63 if (s != 0) {64 cout << "getnameinfo() failed: " << gai_strerror(s) << endl;65 throw runtime_error("getnameinfo() failed");66 }67 68 addressMap.insert({ifa->ifa_name, host.data()});69 }70 }71 72 freeifaddrs(ifaddr);73 74 return addressMap;75}76 77// get IP address of a given interface name78string getInterfaceIP(const string& interface)79{80 try {81 auto IPs = getHostIPs();82 if (IPs.count(interface) > 0) {83 return IPs[interface];84 }85 LOG(error) << "Could not find provided network interface: \""86 << interface << "\"!, exiting.";87 return "";88 } catch (runtime_error& re) {89 cout << "could not get interface IP: " << re.what();90 return "";91 }92}93 94// get name of the default route interface95string getDefaultRouteNetworkInterface()96{97 const int BUFSIZE(128);98 array<char, BUFSIZE> buffer{};99 string interfaceName;100 101#ifdef __APPLE__ // MacOS102 unique_ptr<FILE, int (*)(FILE*)> file(103 popen("route -n get default | grep interface | cut -d \":\" -f 2", "r"), pclose);104#else // Linux105 ifstream is("/proc/net/route");106 string line;107 108 // discard header109 getline(is, line);110 111 // check each line, until 00000000 destination is found112 while (!is.eof()) {113 getline(is, line);114 size_t pos = line.find('\t');115 116 if (pos == string::npos) {117 break;118 }119 120 if (line.substr(pos + 1, 8) == "00000000") {121 interfaceName = line.substr(0, pos);122 LOG(debug) << "Detected network interface name for the default route: "123 << interfaceName;124 return interfaceName;125 }126 }127 128 LOG(debug) << "could not get network interface of the default route from /proc/net/route, "129 "going to try via 'ip route'";130 131 unique_ptr<FILE, int (*)(FILE*)> file(132 popen("ip route | grep default | cut -d \" \" -f 5 | head -n 1", "r"), pclose);133#endif134 135 if (!file) {136 LOG(error) << "Could not detect default route network interface name - popen() failed!";137 return "";138 }139 140 while (feof(file.get()) == 0) {141 if (fgets(buffer.data(), BUFSIZE, file.get()) != nullptr) {142 interfaceName += buffer.data();143 }144 }145 146 boost::algorithm::trim(interfaceName);147 148 if (interfaceName.empty()) {149 LOG(debug) << "Could not detect default route network interface name from /proc/net/route "150 "nor 'ip route'";151 throw DefaultRouteDetectionError("Could not detect default route network interface name "152 "from /proc/net/route nor 'ip route'");153 } else {154 LOG(debug) << "Detected network interface name for the default route: " << interfaceName;155 }156 157 return interfaceName;158}159 160string getIpFromHostname(const string& hostname)161try {162 boost::asio::io_context ioc;163 boost::asio::ip::tcp::resolver resolver(ioc);164 165 auto const result = resolver.resolve(boost::asio::ip::tcp::v4(), hostname, "");166 167 if (result.empty()) {168 LOG(warn) << "could not find ipv4 address for hostname '" << hostname << "'";169 return "";170 }171 return ToString(result.begin()->endpoint().address());172}173catch (std::exception const& ex)174{175 LOG(error) << "could not resolve hostname '" << hostname << "', reason: " << ex.what();176 return "";177}178 179} // namespace fair::mq::tools