10 #include "TRACE/tracemf.h"
11 #include "artdaq/DAQdata/Globals.hh"
12 #define TRACE_NAME (app_name + "_TCPConnect").c_str()
14 #include <arpa/inet.h>
16 #include <netinet/in.h>
17 #include <netinet/in.h>
18 #include <sys/socket.h>
19 #include <sys/socket.h>
20 #include <sys/types.h>
27 #include <linux/if_link.h>
37 struct hostent *hostent_sp;
41 if (regex_match(host_in, mm, std::regex(
"([^:]+):(\\d+)")))
45 else if (regex_match(host_in, mm, std::regex(
":{0,1}(\\d+)")))
47 host = std::string(
"127.0.0.1");
49 else if (regex_match(host_in, mm, std::regex(
"([^:]+):{0,1}")))
55 host = std::string(
"127.0.0.1");
57 TLOG(TLVL_INFO) <<
"Resolving host " << host;
59 memset(static_cast<void *>(&addr), 0,
sizeof(addr));
61 if (regex_match(host.c_str(), mm, std::regex(R
"(\d+(\.\d+){3})")))
63 inet_aton(host.c_str(), &addr);
67 hostent_sp = gethostbyname(host.c_str());
68 if (hostent_sp ==
nullptr)
70 perror(
"gethostbyname");
73 addr = *
reinterpret_cast<struct in_addr *
>(hostent_sp->h_addr_list[0]);
82 TLOG(TLVL_INFO) <<
"Finding address for interface " << interface_name;
84 memset(static_cast<void *>(&addr), 0,
sizeof(addr));
86 struct ifaddrs *ifaddr, *ifa;
88 if (getifaddrs(&ifaddr) == -1)
97 for (ifa = ifaddr; ifa !=
nullptr; ifa = ifa->ifa_next)
99 if (ifa->ifa_addr ==
nullptr)
106 if (ifa->ifa_addr->sa_family == AF_INET)
108 auto if_addr =
reinterpret_cast<struct sockaddr_in *
>(ifa->ifa_addr);
110 TLOG(TLVL_DEBUG + 35) <<
"IF: " << ifa->ifa_name <<
" Desired: " << interface_name <<
" IP: " << if_addr->sin_addr.s_addr;
112 if (std::string(ifa->ifa_name) == interface_name)
114 TLOG(TLVL_INFO) <<
"Interface " << ifa->ifa_name <<
" matches " << interface_name <<
" IP: " << if_addr->sin_addr.s_addr;
115 memcpy(&addr, &if_addr->sin_addr,
sizeof(addr));
122 TLOG(TLVL_WARNING) <<
"No matches for if " << interface_name <<
", using 0.0.0.0";
123 inet_aton(
"0.0.0.0", &addr);
136 memset(static_cast<void *>(&addr), 0,
sizeof(addr));
138 struct ifaddrs *ifaddr, *ifa;
140 enum ip_preference :
int
148 struct in_addr addr_192, addr_172, addr_10, addr_131, nm_16, nm_12, nm_8;
149 inet_aton(
"192.168.0.0", &addr_192);
150 inet_aton(
"172.16.0.0", &addr_172);
151 inet_aton(
"10.0.0.0", &addr_10);
152 inet_aton(
"131.225.0.0", &addr_131);
153 inet_aton(
"255.255.0.0", &nm_16);
154 inet_aton(
"255.240.0.0", &nm_12);
155 inet_aton(
"255.0.0.0", &nm_8);
157 std::map<ip_preference, in_addr> preference_map;
159 if (getifaddrs(&ifaddr) == -1)
161 perror(
"getifaddrs");
168 for (ifa = ifaddr; ifa !=
nullptr; ifa = ifa->ifa_next)
170 if (ifa->ifa_addr ==
nullptr)
177 if (ifa->ifa_addr->sa_family == AF_INET)
179 auto if_addr =
reinterpret_cast<struct sockaddr_in *
>(ifa->ifa_addr);
181 TLOG(TLVL_DEBUG + 35) <<
"IF: " << ifa->ifa_name <<
" IP: " << if_addr->sin_addr.s_addr;
183 if (preference_map.count(IP_192) == 0 && (if_addr->sin_addr.s_addr & nm_16.s_addr) == addr_192.s_addr)
185 preference_map[IP_192];
186 memcpy(&preference_map[IP_192], &if_addr->sin_addr,
sizeof(addr));
188 else if (preference_map.count(IP_172) == 0 && (if_addr->sin_addr.s_addr & nm_12.s_addr) == addr_172.s_addr)
190 preference_map[IP_172];
191 memcpy(&preference_map[IP_172], &if_addr->sin_addr,
sizeof(addr));
193 else if (preference_map.count(IP_10) == 0 && (if_addr->sin_addr.s_addr & nm_8.s_addr) == addr_10.s_addr)
195 preference_map[IP_10];
196 memcpy(&preference_map[IP_10], &if_addr->sin_addr,
sizeof(addr));
198 else if (preference_map.count(IP_131) == 0 && (if_addr->sin_addr.s_addr & nm_16.s_addr) == addr_131.s_addr)
200 preference_map[IP_131];
201 memcpy(&preference_map[IP_131], &if_addr->sin_addr,
sizeof(addr));
206 if (preference_map.empty())
208 TLOG(TLVL_WARNING) <<
"AutodetectPrivateInterface: No matches, using 0.0.0.0";
209 inet_aton(
"0.0.0.0", &addr);
214 TLOG(TLVL_INFO) <<
"AutodetectPrivateInterface: Using " << inet_ntoa(addr);
215 memcpy(&addr, &preference_map.begin()->second,
sizeof(addr));
227 struct hostent *hostent_sp;
232 if (regex_match(host_in, mm, std::regex(
"([^:]+):(\\d+)")))
236 else if (regex_match(host_in, mm, std::regex(
":{0,1}(\\d+)")))
238 host = std::string(
"127.0.0.1");
240 else if (regex_match(host_in, mm, std::regex(
"([^:]+):{0,1}")))
246 host = std::string(
"127.0.0.1");
248 TLOG(TLVL_INFO) <<
"Resolving ip " << host;
250 memset(static_cast<void *>(&addr), 0,
sizeof(addr));
252 if (regex_match(host.c_str(), mm, std::regex(R
"(\d+(\.\d+){3})")))
254 in_addr desired_host;
255 inet_aton(host.c_str(), &desired_host);
256 struct ifaddrs *ifaddr, *ifa;
258 if (getifaddrs(&ifaddr) == -1)
260 perror(
"getifaddrs");
267 for (ifa = ifaddr; ifa !=
nullptr; ifa = ifa->ifa_next)
269 if (ifa->ifa_addr ==
nullptr)
276 if (ifa->ifa_addr->sa_family == AF_INET)
278 auto if_addr =
reinterpret_cast<struct sockaddr_in *
>(ifa->ifa_addr);
279 auto sa =
reinterpret_cast<struct sockaddr_in *
>(ifa->ifa_netmask);
281 TLOG(TLVL_DEBUG + 35) <<
"IF: " << ifa->ifa_name <<
" Desired: " << desired_host.s_addr <<
" netmask: " << sa->sin_addr.s_addr <<
" this interface: " << if_addr->sin_addr.s_addr;
283 if ((if_addr->sin_addr.s_addr & sa->sin_addr.s_addr) == (desired_host.s_addr & sa->sin_addr.s_addr))
285 TLOG(TLVL_INFO) <<
"Using interface " << ifa->ifa_name;
286 memcpy(&addr, &if_addr->sin_addr,
sizeof(addr));
293 if (host != std::string(
"0.0.0.0"))
295 TLOG(TLVL_WARNING) <<
"No matches for ip " << host <<
", using 0.0.0.0";
297 inet_aton(
"0.0.0.0", &addr);
305 hostent_sp = gethostbyname(host.c_str());
306 if (hostent_sp ==
nullptr)
308 perror(
"gethostbyname");
311 addr = *
reinterpret_cast<struct in_addr *
>(hostent_sp->h_addr_list[0]);
317 int ResolveHost(
char const *host_in,
int dflt_port, sockaddr_in &sin)
321 struct hostent *hostent_sp;
325 if (regex_match(host_in, mm, std::regex(
"([^:]+):(\\d+)")))
328 port = strtoul(mm[2].str().c_str(),
nullptr, 0);
330 else if (regex_match(host_in, mm, std::regex(
":{0,1}(\\d+)")))
332 host = std::string(
"127.0.0.1");
333 port = strtoul(mm[1].str().c_str(),
nullptr, 0);
335 else if (regex_match(host_in, mm, std::regex(
"([^:]+):{0,1}")))
342 host = std::string(
"127.0.0.1");
345 TLOG(TLVL_INFO) <<
"Resolving host " << host <<
", on port " << port;
347 if (host ==
"localhost")
352 memset(static_cast<void *>(&sin), 0,
sizeof(sin));
353 sin.sin_family = AF_INET;
354 sin.sin_port = htons(port);
356 if (regex_match(host.c_str(), mm, std::regex(R
"(\d+(\.\d+){3})")))
358 inet_aton(host.c_str(), &sin.sin_addr);
362 hostent_sp = gethostbyname(host.c_str());
363 if (hostent_sp ==
nullptr)
365 TLOG(TLVL_ERROR) <<
"Error calling gethostbyname: " << errno <<
" (" << strerror(errno) <<
")";
366 perror(
"gethostbyname");
369 sin.sin_addr = *
reinterpret_cast<struct in_addr *
>(hostent_sp->h_addr_list[0]);
372 TLOG(TLVL_INFO) <<
"Host resolved as " << inet_ntoa(sin.sin_addr);
377 int TCPConnect(
char const *host_in,
int dflt_port, int64_t flags,
int sndbufsiz)
380 struct sockaddr_in sin;
382 s_fd = socket(PF_INET, SOCK_STREAM , 0);
386 perror(
"socket error");
397 sts = connect(s_fd, reinterpret_cast<struct sockaddr *>(&sin),
sizeof(sin));
407 sts = fcntl(s_fd, F_SETFL, flags);
408 TLOG(TLVL_DEBUG + 33) <<
"TCPConnect fcntl(fd=" << s_fd <<
",flags=0x" << std::hex << flags << std::dec <<
") =" << sts;
414 socklen_t lenlen =
sizeof(len);
416 sts = getsockopt(s_fd, SOL_SOCKET, SO_SNDBUF, &len, &lenlen);
417 TLOG(TLVL_DEBUG + 32) <<
"TCPConnect SNDBUF initial: " << len <<
" sts/errno=" << sts <<
"/" << errno <<
" lenlen=" << lenlen;
419 sts = setsockopt(s_fd, SOL_SOCKET, SO_SNDBUF, &len, lenlen);
422 TLOG(TLVL_ERROR) <<
"Error with setsockopt SNDBUF " << errno;
425 sts = getsockopt(s_fd, SOL_SOCKET, SO_SNDBUF, &len, &lenlen);
426 if (len < (sndbufsiz * 2))
428 TLOG(TLVL_WARNING) <<
"SNDBUF " << len <<
" not expected (" << sndbufsiz <<
" sts/errno=" << sts <<
"/" << errno <<
")";
432 TLOG(TLVL_DEBUG + 32) <<
"SNDBUF " << len <<
" sts/errno=" << sts <<
"/" << errno;
int ResolveHost(char const *host_in, in_addr &addr)
Convert a string hostname to a in_addr suitable for socket communication.
int GetIPOfInterface(const std::string &interface_name, in_addr &addr)
Get the IP address associated with a given interface name.
int TCPConnect(char const *host_in, int dflt_port, int64_t flags=0, int sndbufsiz=0)
Connect to a host on a given port.
int GetInterfaceForNetwork(char const *host_in, in_addr &addr)
Convert an IP address to the network address of the interface sharing the subnet mask.
int AutodetectPrivateInterface(in_addr &addr)
Pick a private IP address on this host.