00001 #ifndef TCPConnect_hh
00002 #define TCPConnect_hh
00003 #include <netinet/in.h>
00004 #include <stdio.h>
00005 #include <sys/types.h>
00006 #include <sys/socket.h>
00007 #include <netinet/in.h>
00008 #include <stdlib.h>
00009 #include <unistd.h>
00010 #include <string.h>
00011 #include <sys/socket.h>
00012 #include <netinet/in.h>
00013 #include <arpa/inet.h>
00014 #include <netdb.h>
00015
00016 #include <ifaddrs.h>
00017 #include <linux/if_link.h>
00018
00019 #include <string>
00020 #include <regex>
00021
00022 #include "trace.h"
00023
00024
00025
00026
00027
00028
00029
00030
00042 int ResolveHost(char const* host_in, in_addr& addr)
00043 {
00044 std::string host;
00045 struct hostent* hostent_sp;
00046 std::cmatch mm;
00047
00048
00049 if (regex_match(host_in, mm, std::regex("([^:]+):(\\d+)")))
00050 {
00051 host = mm[1].str();
00052 }
00053 else if (regex_match(host_in, mm, std::regex(":{0,1}(\\d+)")))
00054 {
00055 host = std::string("127.0.0.1");
00056 }
00057 else if (regex_match(host_in, mm, std::regex("([^:]+):{0,1}")))
00058 {
00059 host = mm[1].str().c_str();
00060 }
00061 else
00062 {
00063 host = std::string("127.0.0.1");
00064 }
00065 TLOG(TLVL_INFO) << "Resolving host " << host;
00066
00067 bzero((char *)&addr, sizeof(addr));
00068
00069 if (regex_match(host.c_str(), mm, std::regex("\\d+(\\.\\d+){3}")))
00070 inet_aton(host.c_str(), &addr);
00071 else
00072 {
00073 hostent_sp = gethostbyname(host.c_str());
00074 if (!hostent_sp)
00075 {
00076 perror("gethostbyname");
00077 return (-1);
00078 }
00079 addr = *(struct in_addr *)(hostent_sp->h_addr_list[0]);
00080 }
00081 return 0;
00082 }
00083
00090 int GetInterfaceForNetwork(char const* host_in, in_addr& addr)
00091 {
00092 std::string host;
00093 struct hostent* hostent_sp;
00094 std::cmatch mm;
00095 int sts = 0;
00096
00097
00098 if (regex_match(host_in, mm, std::regex("([^:]+):(\\d+)")))
00099 {
00100 host = mm[1].str();
00101 }
00102 else if (regex_match(host_in, mm, std::regex(":{0,1}(\\d+)")))
00103 {
00104 host = std::string("127.0.0.1");
00105 }
00106 else if (regex_match(host_in, mm, std::regex("([^:]+):{0,1}")))
00107 {
00108 host = mm[1].str().c_str();
00109 }
00110 else
00111 {
00112 host = std::string("127.0.0.1");
00113 }
00114 TLOG(TLVL_INFO) << "Resolving ip " << host;
00115
00116 bzero((char *)&addr, sizeof(addr));
00117
00118 if (regex_match(host.c_str(), mm, std::regex("\\d+(\\.\\d+){3}")))
00119 {
00120 in_addr desired_host;
00121 inet_aton(host.c_str(), &desired_host);
00122 struct ifaddrs *ifaddr, *ifa;
00123
00124 if (getifaddrs(&ifaddr) == -1)
00125 {
00126 perror("getifaddrs");
00127 return -1;
00128 }
00129
00130
00131
00132
00133 for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next)
00134 {
00135 if (ifa->ifa_addr == NULL)
00136 continue;
00137
00138
00139
00140 if (ifa->ifa_addr->sa_family == AF_INET)
00141 {
00142 auto if_addr = (struct sockaddr_in*) ifa->ifa_addr;
00143 auto sa = (struct sockaddr_in *) ifa->ifa_netmask;
00144
00145 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;
00146
00147 if ((if_addr->sin_addr.s_addr & sa->sin_addr.s_addr) == (desired_host.s_addr & sa->sin_addr.s_addr))
00148 {
00149 TLOG(TLVL_INFO) << "Using interface " << ifa->ifa_name;
00150 memcpy(&addr, &if_addr->sin_addr, sizeof(addr));
00151 break;
00152 }
00153 }
00154 }
00155 if (ifa == NULL)
00156 {
00157 TLOG(TLVL_WARNING) << "No matches for ip " << host << ", using 0.0.0.0";
00158 inet_aton("0.0.0.0", &addr);
00159 sts = 2;
00160 }
00161
00162 freeifaddrs(ifaddr);
00163 }
00164 else
00165 {
00166 hostent_sp = gethostbyname(host.c_str());
00167 if (!hostent_sp)
00168 {
00169 perror("gethostbyname");
00170 return (-1);
00171 }
00172 addr = *(struct in_addr *)(hostent_sp->h_addr_list[0]);
00173 }
00174 return sts;
00175 }
00176
00184 int ResolveHost(char const* host_in, int dflt_port, sockaddr_in& sin)
00185 {
00186 int port;
00187 std::string host;
00188 struct hostent* hostent_sp;
00189 std::cmatch mm;
00190
00191
00192 if (regex_match(host_in, mm, std::regex("([^:]+):(\\d+)")))
00193 {
00194 host = mm[1].str();
00195 port = strtoul(mm[2].str().c_str(), NULL, 0);
00196 }
00197 else if (regex_match(host_in, mm, std::regex(":{0,1}(\\d+)")))
00198 {
00199 host = std::string("127.0.0.1");
00200 port = strtoul(mm[1].str().c_str(), NULL, 0);
00201 }
00202 else if (regex_match(host_in, mm, std::regex("([^:]+):{0,1}")))
00203 {
00204 host = mm[1].str().c_str();
00205 port = dflt_port;
00206 }
00207 else
00208 {
00209 host = std::string("127.0.0.1");
00210 port = dflt_port;
00211 }
00212 TLOG(TLVL_INFO) << "Resolving host " << host << ", on port " << port;
00213
00214 if (host == "localhost") host = "127.0.0.1";
00215
00216 bzero((char *)&sin, sizeof(sin));
00217 sin.sin_family = AF_INET;
00218 sin.sin_port = htons(port);
00219
00220 if (regex_match(host.c_str(), mm, std::regex("\\d+(\\.\\d+){3}")))
00221 inet_aton(host.c_str(), &sin.sin_addr);
00222 else
00223 {
00224 hostent_sp = gethostbyname(host.c_str());
00225 if (!hostent_sp)
00226 {
00227 perror("gethostbyname");
00228 return (-1);
00229 }
00230 sin.sin_addr = *(struct in_addr *)(hostent_sp->h_addr_list[0]);
00231 }
00232 return 0;
00233 }
00234
00243 int TCPConnect(char const* host_in, int dflt_port, long flags = 0, int sndbufsiz = 0)
00244 {
00245 int s_fd, sts;
00246 struct sockaddr_in sin;
00247
00248
00249 s_fd = socket(PF_INET, SOCK_STREAM, 0);
00250
00251 if (s_fd == -1)
00252 {
00253 perror("socket error");
00254 return (-1);
00255 }
00256
00257 sts = ResolveHost(host_in, dflt_port, sin);
00258 if (sts == -1)
00259 {
00260 close(s_fd);
00261 return -1;
00262 }
00263
00264 sts = connect(s_fd, (struct sockaddr *)&sin, sizeof(sin));
00265 if (sts == -1)
00266 {
00267
00268 close(s_fd);
00269 return (-1);
00270 }
00271
00272 if (flags)
00273 {
00274 sts = fcntl(s_fd, F_SETFL, flags);
00275 TLOG(TLVL_TRACE) << "TCPConnect fcntl(fd=" << s_fd << ",flags=0x" << std::hex << flags << std::dec << ") =" << sts;
00276 }
00277
00278 if (sndbufsiz > 0)
00279 {
00280 int len;
00281 socklen_t lenlen = sizeof(len);
00282 len = 0;
00283 sts = getsockopt(s_fd, SOL_SOCKET, SO_SNDBUF, &len, &lenlen);
00284 TLOG(TLVL_DEBUG) << "TCPConnect SNDBUF initial: " << len << " sts/errno=" << sts << "/" << errno << " lenlen=" << lenlen;
00285 len = sndbufsiz;
00286 sts = setsockopt(s_fd, SOL_SOCKET, SO_SNDBUF, &len, lenlen);
00287 if (sts == -1)
00288 TLOG(TLVL_ERROR) << "Error with setsockopt SNDBUF " << errno;
00289 len = 0;
00290 sts = getsockopt(s_fd, SOL_SOCKET, SO_SNDBUF, &len, &lenlen);
00291 if (len < (sndbufsiz * 2))
00292 TLOG(TLVL_WARNING) << "SNDBUF " << len << " not expected (" << sndbufsiz << " sts/errno=" << sts << "/" << errno << ")";
00293 else
00294 TLOG(TLVL_DEBUG) << "SNDBUF " << len << " sts/errno=" << sts << "/" << errno;
00295 }
00296 return (s_fd);
00297 }
00298
00299
00300 #endif // TCPConnect_hh