You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

TcpSocket.cxx 12KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500
  1. /* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
  2. *
  3. * This is free software; you can redistribute it and/or modify
  4. * it under the terms of the GNU General Public License as published by
  5. * the Free Software Foundation; either version 2 of the License, or
  6. * (at your option) any later version.
  7. *
  8. * This software is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. *
  13. * You should have received a copy of the GNU General Public License
  14. * along with this software; if not, write to the Free Software
  15. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
  16. * USA.
  17. */
  18. #ifdef WIN32
  19. //#include <io.h>
  20. #include <winsock2.h>
  21. #define errorNumber WSAGetLastError()
  22. #define snprintf _snprintf
  23. #else
  24. #define errorNumber errno
  25. #define closesocket close
  26. #include <sys/types.h>
  27. #include <sys/socket.h>
  28. #include <arpa/inet.h>
  29. #include <netinet/in.h>
  30. #include <netinet/tcp.h>
  31. #include <netdb.h>
  32. #include <unistd.h>
  33. #include <errno.h>
  34. #include <string.h>
  35. #include <signal.h>
  36. #include <fcntl.h>
  37. #endif
  38. #include <stdlib.h>
  39. #include <network/TcpSocket.h>
  40. #include <rfb/util.h>
  41. #include <rfb/LogWriter.h>
  42. #ifndef VNC_SOCKLEN_T
  43. #define VNC_SOCKLEN_T int
  44. #endif
  45. #ifndef INADDR_NONE
  46. #define INADDR_NONE ((unsigned long)-1)
  47. #endif
  48. #ifndef INADDR_LOOPBACK
  49. #define INADDR_LOOPBACK ((unsigned long)0x7F000001)
  50. #endif
  51. using namespace network;
  52. using namespace rdr;
  53. static rfb::LogWriter vlog("TcpSocket");
  54. /* Tunnelling support. */
  55. int network::findFreeTcpPort (void)
  56. {
  57. int sock, port;
  58. struct sockaddr_in addr;
  59. memset(&addr, 0, sizeof(addr));
  60. addr.sin_family = AF_INET;
  61. addr.sin_addr.s_addr = INADDR_ANY;
  62. if ((sock = socket (AF_INET, SOCK_STREAM, 0)) < 0)
  63. throw SocketException ("unable to create socket", errorNumber);
  64. for (port = TUNNEL_PORT_OFFSET + 99; port > TUNNEL_PORT_OFFSET; port--) {
  65. addr.sin_port = htons ((unsigned short) port);
  66. if (bind (sock, (struct sockaddr *)&addr, sizeof (addr)) == 0) {
  67. closesocket (sock);
  68. return port;
  69. }
  70. }
  71. throw SocketException ("no free port in range", 0);
  72. return 0;
  73. }
  74. // -=- Socket initialisation
  75. static bool socketsInitialised = false;
  76. static void initSockets() {
  77. if (socketsInitialised)
  78. return;
  79. #ifdef WIN32
  80. WORD requiredVersion = MAKEWORD(2,0);
  81. WSADATA initResult;
  82. if (WSAStartup(requiredVersion, &initResult) != 0)
  83. throw SocketException("unable to initialise Winsock2", errorNumber);
  84. #else
  85. signal(SIGPIPE, SIG_IGN);
  86. #endif
  87. socketsInitialised = true;
  88. }
  89. // -=- TcpSocket
  90. TcpSocket::TcpSocket(int sock, bool close)
  91. : Socket(new FdInStream(sock), new FdOutStream(sock), true), closeFd(close)
  92. {
  93. }
  94. TcpSocket::TcpSocket(const char *host, int port)
  95. : closeFd(true)
  96. {
  97. int sock;
  98. // - Create a socket
  99. initSockets();
  100. if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
  101. throw SocketException("unable to create socket", errorNumber);
  102. #ifndef WIN32
  103. // - By default, close the socket on exec()
  104. fcntl(sock, F_SETFD, FD_CLOEXEC);
  105. #endif
  106. // - Connect it to something
  107. // Try processing the host as an IP address
  108. struct sockaddr_in addr;
  109. memset(&addr, 0, sizeof(addr));
  110. addr.sin_family = AF_INET;
  111. addr.sin_addr.s_addr = inet_addr((char *)host);
  112. addr.sin_port = htons(port);
  113. if ((int)addr.sin_addr.s_addr == -1) {
  114. // Host was not an IP address - try resolving as DNS name
  115. struct hostent *hostinfo;
  116. hostinfo = gethostbyname((char *)host);
  117. if (hostinfo && hostinfo->h_addr) {
  118. addr.sin_addr.s_addr = ((struct in_addr *)hostinfo->h_addr)->s_addr;
  119. } else {
  120. int e = errorNumber;
  121. closesocket(sock);
  122. throw SocketException("unable to resolve host by name", e);
  123. }
  124. }
  125. // Attempt to connect to the remote host
  126. for (;;) {
  127. if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) != 0) {
  128. int e = errorNumber;
  129. #ifndef WIN32
  130. if (e == EINTR)
  131. continue;
  132. #endif
  133. closesocket(sock);
  134. throw SocketException("unable to connect to host", e);
  135. } else break;
  136. }
  137. // Disable Nagle's algorithm, to reduce latency
  138. enableNagles(sock, false);
  139. // Create the input and output streams
  140. instream = new FdInStream(sock);
  141. outstream = new FdOutStream(sock);
  142. ownStreams = true;
  143. }
  144. TcpSocket::~TcpSocket() {
  145. if (closeFd)
  146. closesocket(getFd());
  147. }
  148. char* TcpSocket::getMyAddress() {
  149. struct sockaddr_in info;
  150. struct in_addr addr;
  151. VNC_SOCKLEN_T info_size = sizeof(info);
  152. getsockname(getFd(), (struct sockaddr *)&info, &info_size);
  153. memcpy(&addr, &info.sin_addr, sizeof(addr));
  154. char* name = inet_ntoa(addr);
  155. if (name) {
  156. return rfb::strDup(name);
  157. } else {
  158. return rfb::strDup("");
  159. }
  160. }
  161. int TcpSocket::getMyPort() {
  162. return getSockPort(getFd());
  163. }
  164. char* TcpSocket::getMyEndpoint() {
  165. rfb::CharArray address; address.buf = getMyAddress();
  166. int port = getMyPort();
  167. int buflen = strlen(address.buf) + 32;
  168. char* buffer = new char[buflen];
  169. sprintf(buffer, "%s::%d", address.buf, port);
  170. return buffer;
  171. }
  172. char* TcpSocket::getPeerAddress() {
  173. struct sockaddr_in info;
  174. struct in_addr addr;
  175. VNC_SOCKLEN_T info_size = sizeof(info);
  176. getpeername(getFd(), (struct sockaddr *)&info, &info_size);
  177. memcpy(&addr, &info.sin_addr, sizeof(addr));
  178. char* name = inet_ntoa(addr);
  179. if (name) {
  180. return rfb::strDup(name);
  181. } else {
  182. return rfb::strDup("");
  183. }
  184. }
  185. int TcpSocket::getPeerPort() {
  186. struct sockaddr_in info;
  187. VNC_SOCKLEN_T info_size = sizeof(info);
  188. getpeername(getFd(), (struct sockaddr *)&info, &info_size);
  189. return ntohs(info.sin_port);
  190. }
  191. char* TcpSocket::getPeerEndpoint() {
  192. rfb::CharArray address; address.buf = getPeerAddress();
  193. int port = getPeerPort();
  194. int buflen = strlen(address.buf) + 32;
  195. char* buffer = new char[buflen];
  196. sprintf(buffer, "%s::%d", address.buf, port);
  197. return buffer;
  198. }
  199. bool TcpSocket::sameMachine() {
  200. struct sockaddr_in peeraddr, myaddr;
  201. VNC_SOCKLEN_T addrlen = sizeof(struct sockaddr_in);
  202. getpeername(getFd(), (struct sockaddr *)&peeraddr, &addrlen);
  203. getsockname(getFd(), (struct sockaddr *)&myaddr, &addrlen);
  204. return (peeraddr.sin_addr.s_addr == myaddr.sin_addr.s_addr);
  205. }
  206. void TcpSocket::shutdown()
  207. {
  208. Socket::shutdown();
  209. ::shutdown(getFd(), 2);
  210. }
  211. bool TcpSocket::enableNagles(int sock, bool enable) {
  212. int one = enable ? 0 : 1;
  213. if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,
  214. (char *)&one, sizeof(one)) < 0) {
  215. int e = errorNumber;
  216. vlog.error("unable to setsockopt TCP_NODELAY: %d", e);
  217. return false;
  218. }
  219. return true;
  220. }
  221. bool TcpSocket::isSocket(int sock)
  222. {
  223. struct sockaddr_in info;
  224. VNC_SOCKLEN_T info_size = sizeof(info);
  225. return getsockname(sock, (struct sockaddr *)&info, &info_size) >= 0;
  226. }
  227. bool TcpSocket::isConnected(int sock)
  228. {
  229. struct sockaddr_in info;
  230. VNC_SOCKLEN_T info_size = sizeof(info);
  231. return getpeername(sock, (struct sockaddr *)&info, &info_size) >= 0;
  232. }
  233. int TcpSocket::getSockPort(int sock)
  234. {
  235. struct sockaddr_in info;
  236. VNC_SOCKLEN_T info_size = sizeof(info);
  237. if (getsockname(sock, (struct sockaddr *)&info, &info_size) < 0)
  238. return 0;
  239. return ntohs(info.sin_port);
  240. }
  241. TcpListener::TcpListener(int port, bool localhostOnly, int sock, bool close_)
  242. : closeFd(close_)
  243. {
  244. if (sock != -1) {
  245. fd = sock;
  246. return;
  247. }
  248. initSockets();
  249. if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
  250. throw SocketException("unable to create listening socket", errorNumber);
  251. #ifndef WIN32
  252. // - By default, close the socket on exec()
  253. fcntl(fd, F_SETFD, FD_CLOEXEC);
  254. int one = 1;
  255. if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
  256. (char *)&one, sizeof(one)) < 0) {
  257. int e = errorNumber;
  258. closesocket(fd);
  259. throw SocketException("unable to create listening socket", e);
  260. }
  261. #endif
  262. // - Bind it to the desired port
  263. struct sockaddr_in addr;
  264. memset(&addr, 0, sizeof(addr));
  265. addr.sin_family = AF_INET;
  266. addr.sin_port = htons(port);
  267. if (localhostOnly)
  268. addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
  269. else
  270. addr.sin_addr.s_addr = htonl(INADDR_ANY);
  271. if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
  272. int e = errorNumber;
  273. closesocket(fd);
  274. throw SocketException("unable to bind listening socket", e);
  275. }
  276. // - Set it to be a listening socket
  277. if (listen(fd, 5) < 0) {
  278. int e = errorNumber;
  279. closesocket(fd);
  280. throw SocketException("unable to set socket to listening mode", e);
  281. }
  282. }
  283. TcpListener::~TcpListener() {
  284. if (closeFd) closesocket(fd);
  285. }
  286. void TcpListener::shutdown()
  287. {
  288. #ifdef WIN32
  289. closesocket(getFd());
  290. #else
  291. ::shutdown(getFd(), 2);
  292. #endif
  293. }
  294. Socket*
  295. TcpListener::accept() {
  296. int new_sock = -1;
  297. // Accept an incoming connection
  298. if ((new_sock = ::accept(fd, 0, 0)) < 0)
  299. throw SocketException("unable to accept new connection", errorNumber);
  300. #ifndef WIN32
  301. // - By default, close the socket on exec()
  302. fcntl(new_sock, F_SETFD, FD_CLOEXEC);
  303. #endif
  304. // Disable Nagle's algorithm, to reduce latency
  305. TcpSocket::enableNagles(new_sock, false);
  306. // Create the socket object & check connection is allowed
  307. TcpSocket* s = new TcpSocket(new_sock);
  308. if (filter && !filter->verifyConnection(s)) {
  309. delete s;
  310. return 0;
  311. }
  312. return s;
  313. }
  314. void TcpListener::getMyAddresses(std::list<char*>* result) {
  315. const hostent* addrs = gethostbyname(0);
  316. if (addrs == 0)
  317. throw rdr::SystemException("gethostbyname", errorNumber);
  318. if (addrs->h_addrtype != AF_INET)
  319. throw rdr::Exception("getMyAddresses: bad family");
  320. for (int i=0; addrs->h_addr_list[i] != 0; i++) {
  321. const char* addrC = inet_ntoa(*((struct in_addr*)addrs->h_addr_list[i]));
  322. char* addr = new char[strlen(addrC)+1];
  323. strcpy(addr, addrC);
  324. result->push_back(addr);
  325. }
  326. }
  327. int TcpListener::getMyPort() {
  328. return TcpSocket::getSockPort(getFd());
  329. }
  330. TcpFilter::TcpFilter(const char* spec) {
  331. rfb::CharArray tmp;
  332. tmp.buf = rfb::strDup(spec);
  333. while (tmp.buf) {
  334. rfb::CharArray first;
  335. rfb::strSplit(tmp.buf, ',', &first.buf, &tmp.buf);
  336. if (strlen(first.buf))
  337. filter.push_back(parsePattern(first.buf));
  338. }
  339. }
  340. TcpFilter::~TcpFilter() {
  341. }
  342. static bool
  343. patternMatchIP(const TcpFilter::Pattern& pattern, const char* value) {
  344. unsigned long address = inet_addr((char *)value);
  345. if (address == INADDR_NONE) return false;
  346. return ((pattern.address & pattern.mask) == (address & pattern.mask));
  347. }
  348. bool
  349. TcpFilter::verifyConnection(Socket* s) {
  350. rfb::CharArray name;
  351. name.buf = s->getPeerAddress();
  352. std::list<TcpFilter::Pattern>::iterator i;
  353. for (i=filter.begin(); i!=filter.end(); i++) {
  354. if (patternMatchIP(*i, name.buf)) {
  355. switch ((*i).action) {
  356. case Accept:
  357. vlog.debug("ACCEPT %s", name.buf);
  358. return true;
  359. case Query:
  360. vlog.debug("QUERY %s", name.buf);
  361. s->setRequiresQuery();
  362. return true;
  363. case Reject:
  364. vlog.debug("REJECT %s", name.buf);
  365. return false;
  366. }
  367. }
  368. }
  369. vlog.debug("[REJECT] %s", name.buf);
  370. return false;
  371. }
  372. TcpFilter::Pattern TcpFilter::parsePattern(const char* p) {
  373. TcpFilter::Pattern pattern;
  374. bool expandMask = false;
  375. rfb::CharArray addr, mask;
  376. if (rfb::strSplit(&p[1], '/', &addr.buf, &mask.buf)) {
  377. if (rfb::strContains(mask.buf, '.')) {
  378. pattern.mask = inet_addr(mask.buf);
  379. } else {
  380. pattern.mask = atoi(mask.buf);
  381. expandMask = true;
  382. }
  383. } else {
  384. pattern.mask = 32;
  385. expandMask = true;
  386. }
  387. if (expandMask) {
  388. unsigned long expanded = 0;
  389. // *** check endianness!
  390. for (int i=0; i<(int)pattern.mask; i++)
  391. expanded |= 1<<(31-i);
  392. pattern.mask = htonl(expanded);
  393. }
  394. pattern.address = inet_addr(addr.buf) & pattern.mask;
  395. if ((pattern.address == INADDR_NONE) ||
  396. (pattern.address == 0)) pattern.mask = 0;
  397. switch(p[0]) {
  398. case '+': pattern.action = TcpFilter::Accept; break;
  399. case '-': pattern.action = TcpFilter::Reject; break;
  400. case '?': pattern.action = TcpFilter::Query; break;
  401. };
  402. return pattern;
  403. }
  404. char* TcpFilter::patternToStr(const TcpFilter::Pattern& p) {
  405. in_addr tmp;
  406. rfb::CharArray addr, mask;
  407. tmp.s_addr = p.address;
  408. addr.buf = rfb::strDup(inet_ntoa(tmp));
  409. tmp.s_addr = p.mask;
  410. mask.buf = rfb::strDup(inet_ntoa(tmp));
  411. char* result = new char[strlen(addr.buf)+1+strlen(mask.buf)+1+1];
  412. switch (p.action) {
  413. case Accept: result[0] = '+'; break;
  414. case Reject: result[0] = '-'; break;
  415. case Query: result[0] = '?'; break;
  416. };
  417. result[1] = 0;
  418. strcat(result, addr.buf);
  419. strcat(result, "/");
  420. strcat(result, mask.buf);
  421. return result;
  422. }