8 #include "artdaq/DAQdata/Globals.hh"
9 #define TRACE_NAME (app_name + "_TCPConnect").c_str()
11 #include <arpa/inet.h>
13 #include <netinet/in.h>
14 #include <netinet/in.h>
15 #include <sys/socket.h>
16 #include <sys/socket.h>
17 #include <sys/types.h>
24 #include <linux/if_link.h>
36 struct hostent *hostent_sp;
40 if (regex_match(host_in, mm, std::regex(
"([^:]+):(\\d+)")))
44 else if (regex_match(host_in, mm, std::regex(
":{0,1}(\\d+)")))
46 host = std::string(
"127.0.0.1");
48 else if (regex_match(host_in, mm, std::regex(
"([^:]+):{0,1}")))
54 host = std::string(
"127.0.0.1");
56 TLOG(TLVL_INFO) <<
"Resolving host " << host;
58 memset(static_cast<void *>(&addr), 0,
sizeof(addr));
60 if (regex_match(host.c_str(), mm, std::regex(R
"(\d+(\.\d+){3})")))
62 inet_aton(host.c_str(), &addr);
66 hostent_sp = gethostbyname(host.c_str());
67 if (hostent_sp ==
nullptr)
69 perror(
"gethostbyname");
72 addr = *
reinterpret_cast<struct in_addr *
>(hostent_sp->h_addr_list[0]);
81 TLOG(TLVL_INFO) <<
"Finding address for interface " << interface_name;
83 memset(static_cast<void *>(&addr), 0,
sizeof(addr));
85 struct ifaddrs *ifaddr, *ifa;
87 if (getifaddrs(&ifaddr) == -1)
96 for (ifa = ifaddr; ifa !=
nullptr; ifa = ifa->ifa_next)
98 if (ifa->ifa_addr ==
nullptr)
105 if (ifa->ifa_addr->sa_family == AF_INET)
107 auto if_addr =
reinterpret_cast<struct sockaddr_in *
>(ifa->ifa_addr);
109 TLOG(15) <<
"IF: " << ifa->ifa_name <<
" Desired: " << interface_name <<
" IP: " << if_addr->sin_addr.s_addr;
111 if (std::string(ifa->ifa_name) == interface_name)
113 TLOG(TLVL_INFO) <<
"Interface " << ifa->ifa_name <<
" matches " << interface_name <<
" IP: " << if_addr->sin_addr.s_addr;
114 memcpy(&addr, &if_addr->sin_addr,
sizeof(addr));
121 TLOG(TLVL_WARNING) <<
"No matches for if " << interface_name <<
", using 0.0.0.0";
122 inet_aton(
"0.0.0.0", &addr);
135 memset(static_cast<void *>(&addr), 0,
sizeof(addr));
137 struct ifaddrs *ifaddr, *ifa;
139 enum ip_preference :
int
147 struct in_addr addr_192, addr_172, addr_10, addr_131, nm_16, nm_12, nm_8;
148 inet_aton(
"192.168.0.0", &addr_192);
149 inet_aton(
"172.16.0.0", &addr_172);
150 inet_aton(
"10.0.0.0", &addr_10);
151 inet_aton(
"131.225.0.0", &addr_131);
152 inet_aton(
"255.255.0.0", &nm_16);
153 inet_aton(
"255.240.0.0", &nm_12);
154 inet_aton(
"255.0.0.0", &nm_8);
156 std::map<ip_preference, in_addr> preference_map;
158 if (getifaddrs(&ifaddr) == -1)
160 perror(
"getifaddrs");
167 for (ifa = ifaddr; ifa !=
nullptr; ifa = ifa->ifa_next)
169 if (ifa->ifa_addr ==
nullptr)
176 if (ifa->ifa_addr->sa_family == AF_INET)
178 auto if_addr =
reinterpret_cast<struct sockaddr_in *
>(ifa->ifa_addr);
180 TLOG(15) <<
"IF: " << ifa->ifa_name <<
" IP: " << if_addr->sin_addr.s_addr;
182 if (preference_map.count(IP_192) == 0 && (if_addr->sin_addr.s_addr & nm_16.s_addr) == addr_192.s_addr)
184 preference_map[IP_192];
185 memcpy(&preference_map[IP_192], &if_addr->sin_addr,
sizeof(addr));
187 else if (preference_map.count(IP_172) == 0 && (if_addr->sin_addr.s_addr & nm_12.s_addr) == addr_172.s_addr)
189 preference_map[IP_172];
190 memcpy(&preference_map[IP_172], &if_addr->sin_addr,
sizeof(addr));
192 else if (preference_map.count(IP_10) == 0 && (if_addr->sin_addr.s_addr & nm_8.s_addr) == addr_10.s_addr)
194 preference_map[IP_10];
195 memcpy(&preference_map[IP_10], &if_addr->sin_addr,
sizeof(addr));
197 else if (preference_map.count(IP_131) == 0 && (if_addr->sin_addr.s_addr & nm_16.s_addr) == addr_131.s_addr)
199 preference_map[IP_131];
200 memcpy(&preference_map[IP_131], &if_addr->sin_addr,
sizeof(addr));
205 if (preference_map.empty())
207 TLOG(TLVL_WARNING) <<
"AutodetectPrivateInterface: No matches, using 0.0.0.0";
208 inet_aton(
"0.0.0.0", &addr);
213 TLOG(TLVL_INFO) <<
"AutodetectPrivateInterface: Using " << inet_ntoa(addr);
214 memcpy(&addr, &preference_map.begin()->second,
sizeof(addr));
226 struct hostent *hostent_sp;
231 if (regex_match(host_in, mm, std::regex(
"([^:]+):(\\d+)")))
235 else if (regex_match(host_in, mm, std::regex(
":{0,1}(\\d+)")))
237 host = std::string(
"127.0.0.1");
239 else if (regex_match(host_in, mm, std::regex(
"([^:]+):{0,1}")))
245 host = std::string(
"127.0.0.1");
247 TLOG(TLVL_INFO) <<
"Resolving ip " << host;
249 memset(static_cast<void *>(&addr), 0,
sizeof(addr));
251 if (regex_match(host.c_str(), mm, std::regex(R
"(\d+(\.\d+){3})")))
253 in_addr desired_host;
254 inet_aton(host.c_str(), &desired_host);
255 struct ifaddrs *ifaddr, *ifa;
257 if (getifaddrs(&ifaddr) == -1)
259 perror(
"getifaddrs");
266 for (ifa = ifaddr; ifa !=
nullptr; ifa = ifa->ifa_next)
268 if (ifa->ifa_addr ==
nullptr)
275 if (ifa->ifa_addr->sa_family == AF_INET)
277 auto if_addr =
reinterpret_cast<struct sockaddr_in *
>(ifa->ifa_addr);
278 auto sa =
reinterpret_cast<struct sockaddr_in *
>(ifa->ifa_netmask);
280 TLOG(15) <<
"IF: " << ifa->ifa_name <<
" Desired: " << desired_host.s_addr <<
" netmask: " << sa->sin_addr.s_addr <<
" this interface: " << if_addr->sin_addr.s_addr;
282 if ((if_addr->sin_addr.s_addr & sa->sin_addr.s_addr) == (desired_host.s_addr & sa->sin_addr.s_addr))
284 TLOG(TLVL_INFO) <<
"Using interface " << ifa->ifa_name;
285 memcpy(&addr, &if_addr->sin_addr,
sizeof(addr));
292 if (host != std::string(
"0.0.0.0"))
294 TLOG(TLVL_WARNING) <<
"No matches for ip " << host <<
", using 0.0.0.0";
296 inet_aton(
"0.0.0.0", &addr);
304 hostent_sp = gethostbyname(host.c_str());
305 if (hostent_sp ==
nullptr)
307 perror(
"gethostbyname");
310 addr = *
reinterpret_cast<struct in_addr *
>(hostent_sp->h_addr_list[0]);
316 int ResolveHost(
char const *host_in,
int dflt_port, sockaddr_in &sin)
320 struct hostent *hostent_sp;
324 if (regex_match(host_in, mm, std::regex(
"([^:]+):(\\d+)")))
327 port = strtoul(mm[2].str().c_str(),
nullptr, 0);
329 else if (regex_match(host_in, mm, std::regex(
":{0,1}(\\d+)")))
331 host = std::string(
"127.0.0.1");
332 port = strtoul(mm[1].str().c_str(),
nullptr, 0);
334 else if (regex_match(host_in, mm, std::regex(
"([^:]+):{0,1}")))
341 host = std::string(
"127.0.0.1");
344 TLOG(TLVL_INFO) <<
"Resolving host " << host <<
", on port " << port;
346 if (host ==
"localhost")
351 memset(static_cast<void *>(&sin), 0,
sizeof(sin));
352 sin.sin_family = AF_INET;
353 sin.sin_port = htons(port);
355 if (regex_match(host.c_str(), mm, std::regex(R
"(\d+(\.\d+){3})")))
357 inet_aton(host.c_str(), &sin.sin_addr);
361 hostent_sp = gethostbyname(host.c_str());
362 if (hostent_sp ==
nullptr)
364 TLOG(TLVL_ERROR) <<
"Error calling gethostbyname: " << errno <<
" (" << strerror(errno) <<
")";
365 perror(
"gethostbyname");
368 sin.sin_addr = *
reinterpret_cast<struct in_addr *
>(hostent_sp->h_addr_list[0]);
371 TLOG(TLVL_INFO) <<
"Host resolved as " << inet_ntoa(sin.sin_addr);
376 int TCPConnect(
char const *host_in,
int dflt_port, int64_t flags,
int sndbufsiz)
379 struct sockaddr_in sin;
381 s_fd = socket(PF_INET, SOCK_STREAM , 0);
385 perror(
"socket error");
396 sts = connect(s_fd, reinterpret_cast<struct sockaddr *>(&sin),
sizeof(sin));
406 sts = fcntl(s_fd, F_SETFL, flags);
407 TLOG(TLVL_TRACE) <<
"TCPConnect fcntl(fd=" << s_fd <<
",flags=0x" << std::hex << flags << std::dec <<
") =" << sts;
413 socklen_t lenlen =
sizeof(len);
415 sts = getsockopt(s_fd, SOL_SOCKET, SO_SNDBUF, &len, &lenlen);
416 TLOG(TLVL_DEBUG) <<
"TCPConnect SNDBUF initial: " << len <<
" sts/errno=" << sts <<
"/" << errno <<
" lenlen=" << lenlen;
418 sts = setsockopt(s_fd, SOL_SOCKET, SO_SNDBUF, &len, lenlen);
421 TLOG(TLVL_ERROR) <<
"Error with setsockopt SNDBUF " << errno;
424 sts = getsockopt(s_fd, SOL_SOCKET, SO_SNDBUF, &len, &lenlen);
425 if (len < (sndbufsiz * 2))
427 TLOG(TLVL_WARNING) <<
"SNDBUF " << len <<
" not expected (" << sndbufsiz <<
" sts/errno=" << sts <<
"/" << errno <<
")";
431 TLOG(TLVL_DEBUG) <<
"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.