00001
00002
00003
00004
00005
00006
00007
00008 #define TRACE_NAME "TCPConnect"
00009
00010 #include <stdio.h>
00011 #include <sys/types.h>
00012 #include <sys/socket.h>
00013 #include <netinet/in.h>
00014 #include <stdlib.h>
00015 #include <unistd.h>
00016 #include <string.h>
00017 #include <sys/socket.h>
00018 #include <netinet/in.h>
00019 #include <arpa/inet.h>
00020 #include <netdb.h>
00021
00022 #include <ifaddrs.h>
00023 #include <linux/if_link.h>
00024
00025 #include <string>
00026 #include <regex>
00027 #include <map>
00028
00029 #include "artdaq/DAQdata/Globals.hh"
00030 #include "artdaq/DAQdata/TCPConnect.hh"
00031
00032
00033 int ResolveHost(char const* host_in, in_addr& addr)
00034 {
00035 std::string host;
00036 struct hostent* hostent_sp;
00037 std::cmatch mm;
00038
00039
00040 if (regex_match(host_in, mm, std::regex("([^:]+):(\\d+)")))
00041 {
00042 host = mm[1].str();
00043 }
00044 else if (regex_match(host_in, mm, std::regex(":{0,1}(\\d+)")))
00045 {
00046 host = std::string("127.0.0.1");
00047 }
00048 else if (regex_match(host_in, mm, std::regex("([^:]+):{0,1}")))
00049 {
00050 host = mm[1].str().c_str();
00051 }
00052 else
00053 {
00054 host = std::string("127.0.0.1");
00055 }
00056 TLOG(TLVL_INFO) << "Resolving host " << host;
00057
00058 bzero((char *)&addr, sizeof(addr));
00059
00060 if (regex_match(host.c_str(), mm, std::regex("\\d+(\\.\\d+){3}")))
00061 inet_aton(host.c_str(), &addr);
00062 else
00063 {
00064 hostent_sp = gethostbyname(host.c_str());
00065 if (!hostent_sp)
00066 {
00067 perror("gethostbyname");
00068 return (-1);
00069 }
00070 addr = *(struct in_addr *)(hostent_sp->h_addr_list[0]);
00071 }
00072 return 0;
00073 }
00074
00075 int GetIPOfInterface(std::string interface_name, in_addr& addr)
00076 {
00077 int sts = 0;
00078
00079 TLOG(TLVL_INFO) << "Finding address for interface " << interface_name;
00080
00081 bzero((char *)&addr, sizeof(addr));
00082
00083 struct ifaddrs *ifaddr, *ifa;
00084
00085 if (getifaddrs(&ifaddr) == -1)
00086 {
00087 perror("getifaddrs");
00088 return -1;
00089 }
00090
00091
00092
00093
00094 for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next)
00095 {
00096 if (ifa->ifa_addr == NULL)
00097 continue;
00098
00099
00100
00101 if (ifa->ifa_addr->sa_family == AF_INET)
00102 {
00103 auto if_addr = (struct sockaddr_in*) ifa->ifa_addr;
00104
00105 TLOG(15) << "IF: " << ifa->ifa_name << " Desired: " << interface_name << " IP: " << if_addr->sin_addr.s_addr;
00106
00107 if (std::string(ifa->ifa_name) == interface_name)
00108 {
00109 TLOG(TLVL_INFO) << "Interface " << ifa->ifa_name << " matches " << interface_name << " IP: " << if_addr->sin_addr.s_addr;
00110 memcpy(&addr, &if_addr->sin_addr, sizeof(addr));
00111 break;
00112 }
00113 }
00114 }
00115 if (ifa == NULL)
00116 {
00117 TLOG(TLVL_WARNING) << "No matches for if " << interface_name << ", using 0.0.0.0";
00118 inet_aton("0.0.0.0", &addr);
00119 sts = 2;
00120 }
00121
00122 freeifaddrs(ifaddr);
00123
00124 return sts;
00125 }
00126
00127 int AutodetectPrivateInterface(in_addr& addr)
00128 {
00129
00130 int sts = 0;
00131
00132 bzero((char *)&addr, sizeof(addr));
00133
00134 struct ifaddrs *ifaddr, *ifa;
00135
00136 enum ip_preference : int {
00137 IP_192 = 1,
00138 IP_172 = 2,
00139 IP_10 = 3,
00140 IP_131 =4
00141 };
00142
00143 struct in_addr addr_192, addr_172, addr_10, addr_131, nm_16, nm_12, nm_8;
00144 inet_aton("192.168.0.0", &addr_192);
00145 inet_aton("172.16.0.0", &addr_172);
00146 inet_aton("10.0.0.0", &addr_10);
00147 inet_aton("131.225.0.0", &addr_131);
00148 inet_aton("255.255.0.0", &nm_16);
00149 inet_aton("255.240.0.0", &nm_12);
00150 inet_aton("255.0.0.0", &nm_8);
00151
00152 std::map<ip_preference, in_addr> preference_map;
00153
00154 if (getifaddrs(&ifaddr) == -1)
00155 {
00156 perror("getifaddrs");
00157 return -1;
00158 }
00159
00160
00161
00162
00163 for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next)
00164 {
00165 if (ifa->ifa_addr == NULL)
00166 continue;
00167
00168
00169
00170 if (ifa->ifa_addr->sa_family == AF_INET)
00171 {
00172 auto if_addr = (struct sockaddr_in*) ifa->ifa_addr;
00173
00174 TLOG(15) << "IF: " << ifa->ifa_name << " IP: " << if_addr->sin_addr.s_addr;
00175
00176 if (preference_map.count(IP_192) == 0 && (if_addr->sin_addr.s_addr & nm_16.s_addr) == addr_192.s_addr)
00177 {
00178 preference_map[IP_192];
00179 memcpy(&preference_map[IP_192], &if_addr->sin_addr, sizeof(addr));
00180 }
00181 else if (preference_map.count(IP_172) == 0 && (if_addr->sin_addr.s_addr & nm_12.s_addr) == addr_172.s_addr)
00182 {
00183 preference_map[IP_172];
00184 memcpy(&preference_map[IP_172], &if_addr->sin_addr, sizeof(addr));
00185 }
00186 else if (preference_map.count(IP_10) == 0 && (if_addr->sin_addr.s_addr & nm_8.s_addr) == addr_10.s_addr)
00187 {
00188 preference_map[IP_10];
00189 memcpy(&preference_map[IP_10], &if_addr->sin_addr, sizeof(addr));
00190 }
00191 else if (preference_map.count(IP_131) == 0 && (if_addr->sin_addr.s_addr & nm_16.s_addr) == addr_131.s_addr)
00192 {
00193 preference_map[IP_131];
00194 memcpy(&preference_map[IP_131], &if_addr->sin_addr, sizeof(addr));
00195 }
00196 }
00197 }
00198
00199 if (preference_map.size() == 0)
00200 {
00201 TLOG(TLVL_WARNING) << "AutodetectPrivateInterface: No matches, using 0.0.0.0";
00202 inet_aton("0.0.0.0", &addr);
00203 sts = 2;
00204 }
00205 else
00206 {
00207 memcpy(&addr, &preference_map.begin()->second, sizeof(addr));
00208 }
00209
00210 freeifaddrs(ifaddr);
00211
00212 return sts;
00213 }
00214
00215
00216 int GetInterfaceForNetwork(char const* host_in, in_addr& addr)
00217 {
00218 std::string host;
00219 struct hostent* hostent_sp;
00220 std::cmatch mm;
00221 int sts = 0;
00222
00223
00224 if (regex_match(host_in, mm, std::regex("([^:]+):(\\d+)")))
00225 {
00226 host = mm[1].str();
00227 }
00228 else if (regex_match(host_in, mm, std::regex(":{0,1}(\\d+)")))
00229 {
00230 host = std::string("127.0.0.1");
00231 }
00232 else if (regex_match(host_in, mm, std::regex("([^:]+):{0,1}")))
00233 {
00234 host = mm[1].str().c_str();
00235 }
00236 else
00237 {
00238 host = std::string("127.0.0.1");
00239 }
00240 TLOG(TLVL_INFO) << "Resolving ip " << host;
00241
00242 bzero((char *)&addr, sizeof(addr));
00243
00244 if (regex_match(host.c_str(), mm, std::regex("\\d+(\\.\\d+){3}")))
00245 {
00246 in_addr desired_host;
00247 inet_aton(host.c_str(), &desired_host);
00248 struct ifaddrs *ifaddr, *ifa;
00249
00250 if (getifaddrs(&ifaddr) == -1)
00251 {
00252 perror("getifaddrs");
00253 return -1;
00254 }
00255
00256
00257
00258
00259 for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next)
00260 {
00261 if (ifa->ifa_addr == NULL)
00262 continue;
00263
00264
00265
00266 if (ifa->ifa_addr->sa_family == AF_INET)
00267 {
00268 auto if_addr = (struct sockaddr_in*) ifa->ifa_addr;
00269 auto sa = (struct sockaddr_in *) ifa->ifa_netmask;
00270
00271 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;
00272
00273 if ((if_addr->sin_addr.s_addr & sa->sin_addr.s_addr) == (desired_host.s_addr & sa->sin_addr.s_addr))
00274 {
00275 TLOG(TLVL_INFO) << "Using interface " << ifa->ifa_name;
00276 memcpy(&addr, &if_addr->sin_addr, sizeof(addr));
00277 break;
00278 }
00279 }
00280 }
00281 if (ifa == NULL)
00282 {
00283 TLOG(TLVL_WARNING) << "No matches for ip " << host << ", using 0.0.0.0";
00284 inet_aton("0.0.0.0", &addr);
00285 sts = 2;
00286 }
00287
00288 freeifaddrs(ifaddr);
00289 }
00290 else
00291 {
00292 hostent_sp = gethostbyname(host.c_str());
00293 if (!hostent_sp)
00294 {
00295 perror("gethostbyname");
00296 return (-1);
00297 }
00298 addr = *(struct in_addr *)(hostent_sp->h_addr_list[0]);
00299 }
00300 return sts;
00301 }
00302
00303
00304 int ResolveHost(char const* host_in, int dflt_port, sockaddr_in& sin)
00305 {
00306 int port;
00307 std::string host;
00308 struct hostent* hostent_sp;
00309 std::cmatch mm;
00310
00311
00312 if (regex_match(host_in, mm, std::regex("([^:]+):(\\d+)")))
00313 {
00314 host = mm[1].str();
00315 port = strtoul(mm[2].str().c_str(), NULL, 0);
00316 }
00317 else if (regex_match(host_in, mm, std::regex(":{0,1}(\\d+)")))
00318 {
00319 host = std::string("127.0.0.1");
00320 port = strtoul(mm[1].str().c_str(), NULL, 0);
00321 }
00322 else if (regex_match(host_in, mm, std::regex("([^:]+):{0,1}")))
00323 {
00324 host = mm[1].str().c_str();
00325 port = dflt_port;
00326 }
00327 else
00328 {
00329 host = std::string("127.0.0.1");
00330 port = dflt_port;
00331 }
00332 TLOG(TLVL_INFO) << "Resolving host " << host << ", on port " << port;
00333
00334 if (host == "localhost") host = "127.0.0.1";
00335
00336 bzero((char *)&sin, sizeof(sin));
00337 sin.sin_family = AF_INET;
00338 sin.sin_port = htons(port);
00339
00340 if (regex_match(host.c_str(), mm, std::regex("\\d+(\\.\\d+){3}")))
00341 inet_aton(host.c_str(), &sin.sin_addr);
00342 else
00343 {
00344 hostent_sp = gethostbyname(host.c_str());
00345 if (!hostent_sp)
00346 {
00347 perror("gethostbyname");
00348 return (-1);
00349 }
00350 sin.sin_addr = *(struct in_addr *)(hostent_sp->h_addr_list[0]);
00351 }
00352 return 0;
00353 }
00354
00355
00356 int TCPConnect(char const* host_in
00357 , int dflt_port
00358 , long flags
00359 , int sndbufsiz)
00360 {
00361 int s_fd, sts;
00362 struct sockaddr_in sin;
00363
00364
00365 s_fd = socket(PF_INET, SOCK_STREAM, 0);
00366
00367 if (s_fd == -1)
00368 {
00369 perror("socket error");
00370 return (-1);
00371 }
00372
00373 sts = ResolveHost(host_in, dflt_port, sin);
00374 if (sts == -1)
00375 {
00376 close(s_fd);
00377 return -1;
00378 }
00379
00380 sts = connect(s_fd, (struct sockaddr *)&sin, sizeof(sin));
00381 if (sts == -1)
00382 {
00383
00384 close(s_fd);
00385 return (-1);
00386 }
00387
00388 if (flags)
00389 {
00390 sts = fcntl(s_fd, F_SETFL, flags);
00391 TLOG(TLVL_TRACE) << "TCPConnect fcntl(fd=" << s_fd << ",flags=0x" << std::hex << flags << std::dec << ") =" << sts;
00392 }
00393
00394 if (sndbufsiz > 0)
00395 {
00396 int len;
00397 socklen_t lenlen = sizeof(len);
00398 len = 0;
00399 sts = getsockopt(s_fd, SOL_SOCKET, SO_SNDBUF, &len, &lenlen);
00400 TLOG(TLVL_DEBUG) << "TCPConnect SNDBUF initial: " << len << " sts/errno=" << sts << "/" << errno << " lenlen=" << lenlen;
00401 len = sndbufsiz;
00402 sts = setsockopt(s_fd, SOL_SOCKET, SO_SNDBUF, &len, lenlen);
00403 if (sts == -1)
00404 TLOG(TLVL_ERROR) << "Error with setsockopt SNDBUF " << errno;
00405 len = 0;
00406 sts = getsockopt(s_fd, SOL_SOCKET, SO_SNDBUF, &len, &lenlen);
00407 if (len < (sndbufsiz * 2))
00408 TLOG(TLVL_WARNING) << "SNDBUF " << len << " not expected (" << sndbufsiz << " sts/errno=" << sts << "/" << errno << ")";
00409 else
00410 TLOG(TLVL_DEBUG) << "SNDBUF " << len << " sts/errno=" << sts << "/" << errno;
00411 }
00412 return (s_fd);
00413 }