From 91b7a72ac55bf33996d551e86dd1a09ce8516952 Mon Sep 17 00:00:00 2001 From: Alexey Rybalchenko Date: Wed, 1 Mar 2017 11:25:42 +0100 Subject: [PATCH] get default network interface from the default route --- fairmq/FairMQDevice.cxx | 7 +++- fairmq/options/FairMQProgOptions.cxx | 6 ++-- fairmq/tools/FairMQTools.h | 50 +++++++++++++++++++++++++++- 3 files changed, 58 insertions(+), 5 deletions(-) diff --git a/fairmq/FairMQDevice.cxx b/fairmq/FairMQDevice.cxx index b9e44bc3..bdb81cab 100644 --- a/fairmq/FairMQDevice.cxx +++ b/fairmq/FairMQDevice.cxx @@ -185,9 +185,14 @@ void FairMQDevice::InitWrapper() if (vi->fMethod == "bind") { - // if binding address is not specified, set it up to try getting it from the configured network interface + // if binding address is not specified, try getting it from the configured network interface if (vi->fAddress == "unspecified" || vi->fAddress == "") { + // if the configured network interface is default, get its name from the default route + if (fNetworkInterface == "default") + { + fNetworkInterface = FairMQ::tools::getDefaultRouteNetworkInterface(); + } vi->fAddress = "tcp://" + FairMQ::tools::getInterfaceIP(fNetworkInterface) + ":1"; } // fill the uninitialized list diff --git a/fairmq/options/FairMQProgOptions.cxx b/fairmq/options/FairMQProgOptions.cxx index 91303348..fc5ff61b 100644 --- a/fairmq/options/FairMQProgOptions.cxx +++ b/fairmq/options/FairMQProgOptions.cxx @@ -316,7 +316,7 @@ void FairMQProgOptions::InitOptionDescription() ("transport", po::value()->default_value("zeromq"), "Transport ('zeromq'/'nanomsg').") ("config", po::value()->default_value("static"), "Config source ('static'/).") ("control", po::value()->default_value("interactive"), "States control ('interactive'/'static'/).") - ("network-interface", po::value()->default_value("eth0"), "Network interface to bind on (e.g. eth0, ib0, wlan0, en0, lo...).") + ("network-interface", po::value()->default_value("default"), "Network interface to bind on (e.g. eth0, ib0..., default will try to detect the interface of the default route).") ("config-key", po::value(), "Use provided value instead of device id for fetching the configuration from the config file") ("catch-signals", po::value()->default_value(1), "Enable signal handling (1/0)") ("log-to-file", po::value()->default_value(""), "Log output to a file") @@ -328,7 +328,7 @@ void FairMQProgOptions::InitOptionDescription() ("transport", po::value()->default_value("zeromq"), "Transport ('zeromq'/'nanomsg').") ("config", po::value()->default_value("static"), "Config source ('static'/).") ("control", po::value()->default_value("interactive"), "States control ('interactive'/'static'/).") - ("network-interface", po::value()->default_value("eth0"), "Network interface to bind on (e.g. eth0, ib0, wlan0, en0, lo...).") + ("network-interface", po::value()->default_value("default"), "Network interface to bind on (e.g. eth0, ib0..., default will try to detect the interface of the default route).") ("config-key", po::value(), "Use provided value instead of device id for fetching the configuration from the config file") ("catch-signals", po::value()->default_value(1), "Enable signal handling (1/0)") ("log-to-file", po::value()->default_value(""), "Log output to a file") @@ -342,7 +342,7 @@ void FairMQProgOptions::InitOptionDescription() ("transport", po::value()->default_value("zeromq"), "Transport ('zeromq'/'nanomsg').") ("config", po::value()->default_value("static"), "Config source ('static'/).") ("control", po::value()->default_value("interactive"), "States control ('interactive'/'static'/).") - ("network-interface", po::value()->default_value("eth0"), "Network interface to bind on (e.g. eth0, ib0, wlan0, en0, lo...).") + ("network-interface", po::value()->default_value("default"), "Network interface to bind on (e.g. eth0, ib0..., default will try to detect the interface of the default route).") ("config-key", po::value(), "Use provided value instead of device id for fetching the configuration from the config file") ("catch-signals", po::value()->default_value(1), "Enable signal handling (1/0)") ("log-to-file", po::value()->default_value(""), "Log output to a file") diff --git a/fairmq/tools/FairMQTools.h b/fairmq/tools/FairMQTools.h index 446060dd..8d6ad468 100644 --- a/fairmq/tools/FairMQTools.h +++ b/fairmq/tools/FairMQTools.h @@ -5,16 +5,21 @@ #define _GNU_SOURCE // To get defns of NI_MAXSERV and NI_MAXHOST #endif +#include "FairMQLogger.h" + #include #include #include #include #include +#include // trim + #include #include #include #include +#include using namespace std; @@ -23,12 +28,14 @@ namespace FairMQ namespace tools { +// make_unique implementation, until C++14 is default template unique_ptr make_unique(Args&& ...args) { return unique_ptr(new T(forward(args)...)); } +// returns a map with network interface names as keys and their IP addresses as values int getHostIPs(map& addressMap) { struct ifaddrs *ifaddr, *ifa; @@ -65,6 +72,7 @@ int getHostIPs(map& addressMap) return 0; } +// get IP address of a given interface name string getInterfaceIP(string interface) { map IPs; @@ -76,10 +84,50 @@ string getInterfaceIP(string interface) else { LOG(ERROR) << "Could not find provided network interface: \"" << interface << "\"!, exiting."; - exit(EXIT_FAILURE); + return ""; } } +// get name of the default route interface +string getDefaultRouteNetworkInterface() +{ + array buffer; + string interfaceName; + +#ifdef __APPLE__ // MacOS + unique_ptr file(popen("route -n get default | grep interface | cut -d \":\" -f 2", "r"), pclose); +#else // Linux + unique_ptr file(popen("ip route | grep default | cut -d \" \" -f 5", "r"), pclose); +#endif + + if (!file) + { + LOG(ERROR) << "Could not detect default route network interface name - popen() failed!"; + return ""; + } + + while (!feof(file.get())) + { + if (fgets(buffer.data(), 128, file.get()) != NULL) + { + interfaceName += buffer.data(); + } + } + + boost::algorithm::trim(interfaceName); + + if (interfaceName == "") + { + LOG(ERROR) << "Could not detect default route network interface name"; + } + else + { + LOG(DEBUG) << "Detected network interface name for the default route: " << interfaceName; + } + + return interfaceName; +} + #if defined(__GNUC__) || defined(__GNUG__) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Weffc++"