ptunnel.c 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871
  1. /*
  2. * ptunnel.c
  3. * ptunnel is licensed under the BSD license:
  4. *
  5. * Copyright (c) 2004-2011, Daniel Stoedle <daniels@cs.uit.no>,
  6. * Yellow Lemon Software. All rights reserved.
  7. *
  8. * Copyright (c) 2017-2019, Toni Uhlig <matzeton@googlemail.com>
  9. *
  10. * Redistribution and use in source and binary forms, with or without
  11. * modification, are permitted provided that the following conditions are met:
  12. *
  13. * - Redistributions of source code must retain the above copyright notice,
  14. * this list of conditions and the following disclaimer.
  15. *
  16. * - Redistributions in binary form must reproduce the above copyright notice,
  17. * this list of conditions and the following disclaimer in the documentation
  18. * and/or other materials provided with the distribution.
  19. *
  20. * - Neither the name of the Yellow Lemon Software nor the names of its
  21. * contributors may be used to endorse or promote products derived from this
  22. * software without specific prior written permission.
  23. *
  24. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  25. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  26. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  27. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  28. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  29. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  30. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  31. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  32. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  33. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  34. * POSSIBILITY OF SUCH DAMAGE.
  35. *
  36. * Contacting the author:
  37. * You can get in touch with me, Daniel Stoedle (that's the Norwegian letter oe,
  38. * in case your text editor didn't realize), here: <daniels@cs.uit.no>
  39. *
  40. * The official ptunnel website is here:
  41. * <http://www.cs.uit.no/~daniels/PingTunnel/>
  42. *
  43. * Note that the source code is best viewed with tabs set to 4 spaces.
  44. */
  45. #ifdef HAVE_CONFIG_H
  46. #include "config.h"
  47. #endif
  48. #include "ptunnel.h"
  49. #include "options.h"
  50. #include "utils.h"
  51. #include "md5.h"
  52. #ifdef HAVE_SELINUX
  53. #include <selinux/selinux.h>
  54. #endif
  55. #ifndef PACKAGE_STRING
  56. #define PACKAGE_STRING "ptunnel-ng"
  57. #endif
  58. #ifdef WIN32
  59. #include <tchar.h>
  60. #include <winsock2.h>
  61. /* Map errno (which Winsock doesn't use) to GetLastError; include the code in the strerror */
  62. #ifdef errno
  63. #undef errno
  64. #endif /* errno */
  65. #define errno GetLastError()
  66. /** Local error string storage */
  67. static char errorstr[255];
  68. static char * print_last_windows_error() {
  69. char last_errorstr[255];
  70. DWORD last_error = GetLastError();
  71. memset(last_errorstr, 0, sizeof(last_errorstr));
  72. FormatMessage(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM,
  73. NULL, last_error, 0, last_errorstr, sizeof(last_errorstr), NULL);
  74. snprintf(errorstr, sizeof(errorstr), "%s (%lu)", last_errorstr, last_error);
  75. return errorstr;
  76. }
  77. #define strerror(x) print_last_windows_error()
  78. #endif /* WIN32 */
  79. #ifdef HAVE_NPCAP
  80. static BOOL LoadNpcapDlls()
  81. {
  82. TCHAR npcap_dir[512];
  83. UINT len;
  84. len = GetSystemDirectory(npcap_dir, 480);
  85. if (!len) {
  86. pt_log(kLog_error, "Error in GetSystemDirectory: %x", GetLastError());
  87. return FALSE;
  88. }
  89. _tcscat_s(npcap_dir, 512, _T("\\Npcap"));
  90. if (SetDllDirectory(npcap_dir) == 0) {
  91. pt_log(kLog_error, "Error in SetDllDirectory: %x", GetLastError());
  92. return FALSE;
  93. }
  94. return TRUE;
  95. }
  96. #endif
  97. /* globals */
  98. /** Lock protecting the chain of connections */
  99. pthread_mutex_t chain_lock;
  100. /** Lock protecting the num_threads variable */
  101. pthread_mutex_t num_threads_lock;
  102. /** Current thread count */
  103. int num_threads = 0;
  104. /** Current tunnel count */
  105. uint32_t num_tunnels = 0;
  106. /** Table indicating when a connection ID is allowable (used by proxy) */
  107. time_t *seq_expiry_tbl = NULL;
  108. /* Some buffer constants */
  109. const int tcp_receive_buf_len = kDefault_buf_size;
  110. const int icmp_receive_buf_len = kDefault_buf_size + kIP_header_size +
  111. kICMP_header_size + sizeof(ping_tunnel_pkt_t);
  112. const int pcap_buf_size = (kDefault_buf_size + kIP_header_size +
  113. kICMP_header_size + sizeof(ping_tunnel_pkt_t)+64)*64;
  114. /** (icmp[icmptype] = icmp-echo || icmp[icmptype] = icmp-echoreply) */
  115. char pcap_filter_program[] = "icmp";
  116. /** The chain of client/proxy connections */
  117. proxy_desc_t *chain = 0;
  118. const char *state_name[kNum_proto_types] = { "start", "ack ", "data ",
  119. "close", "authenticate" };
  120. #ifdef HAVE_PCAP
  121. static void print_pcap_devices(void) {
  122. pcap_if_t *devs, *cur_dev;
  123. pcap_addr_t *cur_addr;
  124. char errbuf[PCAP_ERRBUF_SIZE+1];
  125. if (pcap_findalldevs(&devs, errbuf)) {
  126. pt_log(kLog_error, "List all available pcap devices failed: %s.\n", errbuf);
  127. }
  128. printf("Available pcap devices:\n");
  129. for (cur_dev = devs; cur_dev; cur_dev = cur_dev->next) {
  130. if (cur_dev->description)
  131. printf("\n\t%s%c '%s'\n", cur_dev->name, (cur_dev->addresses ? ':' : ' '),
  132. cur_dev->description);
  133. else
  134. printf("\n\t%s%c\n", cur_dev->name, (cur_dev->addresses ? ':' : ' '));
  135. for (cur_addr = cur_dev->addresses; cur_addr; cur_addr = cur_addr->next) {
  136. if (cur_addr->addr->sa_family == AF_INET)
  137. printf("\t\t%s\n", inet_ntoa(((struct sockaddr_in*)cur_addr->addr)->sin_addr));
  138. }
  139. }
  140. pcap_freealldevs(devs);
  141. }
  142. #endif
  143. /* Let the fun begin! */
  144. int main(int argc, char *argv[]) {
  145. #ifndef WIN32
  146. pid_t pid;
  147. #endif
  148. #ifdef WIN32
  149. WORD wVersionRequested;
  150. WSADATA wsaData;
  151. int err;
  152. wVersionRequested = MAKEWORD(2, 2);
  153. err = WSAStartup( wVersionRequested, &wsaData );
  154. if ( err != 0 ) {
  155. return -1;
  156. }
  157. if (LOBYTE( wsaData.wVersion ) != 2 ||
  158. HIBYTE( wsaData.wVersion ) != 2)
  159. {
  160. WSACleanup();
  161. return -1;
  162. }
  163. #endif /* WIN32 */
  164. #ifdef HAVE_NPCAP
  165. if (!LoadNpcapDlls())
  166. return -1;
  167. #endif
  168. memset(opts.md5_password_digest, 0, kMD5_digest_size);
  169. memset(opts.sha512_password_digest, 0, kSHA512_digest_size);
  170. /* The seq_expiry_tbl is used to prevent the remote ends from prematurely
  171. * re-using a sequence number.
  172. */
  173. seq_expiry_tbl = (time_t *) calloc(65536, sizeof(time_t));
  174. /* Parse options */
  175. if (parse_options(argc, argv))
  176. return -1;
  177. /* Init ptunnel RNG */
  178. pt_random();
  179. if (opts.list_pcap_devices) {
  180. #ifdef HAVE_PCAP
  181. print_pcap_devices();
  182. return 0;
  183. #else
  184. pt_log(kLog_error, "Pcap not available!\n");
  185. return 1;
  186. #endif
  187. }
  188. #ifdef HAVE_PCAP
  189. if (opts.pcap && opts.udp) {
  190. pt_log(kLog_error, "Packet capture is not supported (or needed) when using UDP for transport.\n");
  191. opts.pcap = 0;
  192. }
  193. #ifdef WIN32
  194. if (!opts.pcap && !opts.udp) {
  195. pt_log(kLog_info, "Running ptunnel-ng on Windows in ICMP mode without WinPcap/Npcap enabled is not supported and may not work!\n");
  196. pt_log(kLog_info, "If you encounter problems, install WinPCAP/Npcap from:\n");
  197. pt_log(kLog_info, "https://www.winpcap.org/install/default.htm or Npcap for WIN10: https://nmap.org/npcap/windows-10.html\n");
  198. pt_log(kLog_info, "After WinPCAP is installed, you can list pcap devices with: --list-pcap-devices\n");
  199. }
  200. #endif
  201. #endif
  202. pt_log(kLog_info, "Starting %s.\n", PACKAGE_STRING);
  203. pt_log(kLog_info, "(c) 2004-2011 Daniel Stoedle, <daniels@cs.uit.no>\n");
  204. pt_log(kLog_info, "(c) 2017-2019 Toni Uhlig, <matzeton@googlemail.com>\n");
  205. #ifdef WIN32
  206. pt_log(kLog_info, "Windows version by Mike Miller, <mike@mikeage.net>\n");
  207. #else
  208. pt_log(kLog_info, "Security features by Sebastien Raveau, <sebastien.raveau@epita.fr>\n");
  209. #endif
  210. pt_log(kLog_info, "%s.\n", (opts.mode == kMode_forward ? "Relaying packets from incoming TCP streams" :
  211. "Forwarding incoming ping packets over TCP"));
  212. if (opts.udp)
  213. pt_log(kLog_info, "UDP transport enabled.\n");
  214. pt_log(kLog_debug, "Destination at %s:%u\n", opts.given_dst_hostname, opts.given_dst_port);
  215. /* TODO: Maybe give the user the opportunity to bind to certain addresses e.g. 127.0.0.1 ? */
  216. if (opts.mode == kMode_forward)
  217. pt_log(kLog_debug, "Listen for incoming connections at 0.0.0.0:%u\n", opts.tcp_listen_port);
  218. #ifndef WIN32
  219. signal(SIGPIPE, SIG_IGN);
  220. if (opts.use_syslog) {
  221. if (opts.log_file != stdout) {
  222. pt_log(kLog_error, "Logging using syslog overrides the use of a specified logfile (using -f).\n");
  223. fclose(opts.log_file);
  224. opts.log_file = stdout;
  225. }
  226. openlog("ptunnel", LOG_PID, LOG_USER);
  227. }
  228. if (opts.chroot) {
  229. pt_log(kLog_info, "Restricting file access to %s\n", opts.root_dir);
  230. if (-1 == chdir(opts.root_dir) || -1 == chroot(".") || -1 == chdir("/")) {
  231. pt_log(kLog_error, "chdir/chroot `%s': %s\n", opts.root_dir, strerror(errno));
  232. exit(1);
  233. }
  234. }
  235. if (opts.daemonize) {
  236. pt_log(kLog_info, "Going to the background.\n");
  237. if (0 < (pid = fork()))
  238. exit(0);
  239. if (0 > pid)
  240. pt_log(kLog_error, "fork: %s\n", strerror(errno));
  241. else
  242. if (-1 == setsid())
  243. pt_log(kLog_error, "setsid: %s\n", strerror(errno));
  244. else {
  245. if (0 < (pid = fork()))
  246. exit(0);
  247. if (0 > pid)
  248. pt_log(kLog_error, "fork: %s\n", strerror(errno));
  249. else {
  250. if (NULL != opts.pid_file) {
  251. fprintf(opts.pid_file, "%d\n", getpid());
  252. fclose(opts.pid_file);
  253. }
  254. if (! freopen("/dev/null", "r", stdin) ||
  255. ! freopen("/dev/null", "w", stdout) ||
  256. ! freopen("/dev/null", "w", stderr))
  257. pt_log(kLog_error, "freopen `%s': %s\n", "/dev/null", strerror(errno));
  258. }
  259. }
  260. }
  261. #endif /* !WIN32 */
  262. pthread_mutex_init(&chain_lock, 0);
  263. pthread_mutex_init(&num_threads_lock, 0);
  264. // Check mode, validate arguments and start either client or proxy.
  265. if (opts.mode == kMode_forward) {
  266. if (!opts.given_proxy_ip || !opts.given_dst_ip || !opts.given_dst_port || !opts.tcp_listen_port) {
  267. printf("One of the options are missing or invalid.\n");
  268. print_usage(argv[0]);
  269. return -1;
  270. }
  271. pt_forwarder();
  272. }
  273. else
  274. pt_proxy(0);
  275. #ifdef WIN32
  276. WSACleanup();
  277. #else
  278. if (opts.root_dir)
  279. free(opts.root_dir);
  280. #ifdef HAVE_SELINUX
  281. if (NULL != opts.selinux_context)
  282. free(opts.selinux_context);
  283. #endif
  284. #endif /* WIN32 */
  285. pt_log(kLog_info, "ptunnel is exiting.\n");
  286. return 0;
  287. }
  288. /** pt_forwarder:
  289. * Sets up a listening TCP socket, and forwards incoming connections
  290. * over ping packets.
  291. */
  292. void pt_forwarder(void) {
  293. int server_sock, new_sock, sock, yes = 1;
  294. fd_set set;
  295. struct timeval time;
  296. struct sockaddr_in addr, dest_addr;
  297. socklen_t addr_len;
  298. pthread_t pid;
  299. uint16_t rand_id;
  300. struct in_addr in_addr;
  301. pt_log(kLog_debug, "Starting forwarder..\n");
  302. /** Open our listening socket */
  303. sock = socket(AF_INET, SOCK_STREAM, 0);
  304. if (sock < 0) {
  305. pt_log(kLog_error, "Failed to create socket: %s\n", strerror(errno));
  306. return;
  307. }
  308. if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const void *) &yes, sizeof(int)) == -1) {
  309. pt_log(kLog_error, "Failed to set SO_REUSEADDR option on listening socket: %s\n", strerror(errno));
  310. close(sock);
  311. return;
  312. }
  313. addr.sin_family = AF_INET;
  314. addr.sin_port = htons(opts.tcp_listen_port);
  315. addr.sin_addr.s_addr = INADDR_ANY;
  316. memset(&(addr.sin_zero), 0, 8);
  317. if (bind(sock, (struct sockaddr*)&addr, sizeof(struct sockaddr)) == -1) {
  318. pt_log(kLog_error, "Failed to bind listening socket to port %u: %s\n", opts.tcp_listen_port, strerror(errno));
  319. close(sock);
  320. return;
  321. }
  322. server_sock = sock;
  323. /* Fill out address structure */
  324. memset(&dest_addr, 0, sizeof(struct sockaddr_in));
  325. dest_addr.sin_family = AF_INET;
  326. if (opts.udp)
  327. dest_addr.sin_port = htons(kDNS_port /* dns port.. */);
  328. else
  329. dest_addr.sin_port = 0;
  330. in_addr.s_addr = opts.given_proxy_ip;
  331. dest_addr.sin_addr.s_addr = opts.given_proxy_ip;
  332. pt_log(kLog_verbose, "Proxy IP address: %s\n", inet_ntoa(in_addr));
  333. listen(server_sock, 10);
  334. while (1) {
  335. FD_ZERO(&set);
  336. FD_SET(server_sock, &set);
  337. time.tv_sec = 1;
  338. time.tv_usec = 0;
  339. if (select(server_sock+1, &set, 0, 0, &time) > 0) {
  340. pt_log(kLog_info, "Incoming connection.\n");
  341. addr_len = sizeof(struct sockaddr_in);
  342. new_sock = accept(server_sock, (struct sockaddr*)&addr, &addr_len);
  343. if (new_sock < 0) {
  344. pt_log(kLog_error, "Accepting incoming connection failed.\n");
  345. continue;
  346. }
  347. pthread_mutex_lock(&num_threads_lock);
  348. if (num_threads <= 0) {
  349. pt_log(kLog_event, "No running proxy thread - starting it.\n");
  350. #ifndef WIN32
  351. if (pthread_create(&pid, 0, pt_proxy, 0) != 0)
  352. #else
  353. if (0 == (pid = _beginthreadex(0, 0, pt_proxy, 0, 0, 0)))
  354. #endif
  355. {
  356. pt_log(kLog_error, "Couldn't create thread! Dropping incoming connection.\n");
  357. close(new_sock);
  358. pthread_mutex_unlock(&num_threads_lock);
  359. continue;
  360. }
  361. }
  362. addr = dest_addr;
  363. rand_id = pt_random();
  364. create_and_insert_proxy_desc(rand_id, rand_id, new_sock, &addr, opts.given_dst_ip, opts.given_dst_port, kProxy_start, kUser_flag);
  365. pthread_mutex_unlock(&num_threads_lock);
  366. }
  367. }
  368. }
  369. int pt_create_udp_socket(int port) {
  370. struct sockaddr_in addr;
  371. int sock, yes = 1;
  372. sock = socket(AF_INET, SOCK_DGRAM, 0);
  373. if (sock < 0) {
  374. pt_log(kLog_error, "Failed to set create UDP socket..\n");
  375. return 0;
  376. }
  377. if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const void*)&yes, sizeof(int)) < 0) {
  378. pt_log(kLog_error, "Failed to set UDP REUSEADDR socket option. (Not fatal, hopefully.)\n");
  379. close(sock);
  380. return 0;
  381. }
  382. #ifdef SO_REUSEPORT
  383. yes = 1;
  384. if (setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, (const void*)&yes, sizeof(int)) < 0)
  385. pt_log(kLog_error, "Failed to set UDP REUSEPORT socket option. (Not fatal, hopefully.)\n");
  386. #endif /* SO_REUSEPORT */
  387. memset(&addr, 0, sizeof(struct sockaddr_in));
  388. addr.sin_family = AF_INET;
  389. addr.sin_addr.s_addr = htonl(INADDR_ANY);
  390. addr.sin_port = htons(port);
  391. if (bind(sock, (struct sockaddr*) &addr, sizeof(struct sockaddr_in)) < 0) {
  392. pt_log(kLog_error, "Failed to bind UDP socket to port %d (try running as root).\n", port);
  393. close(sock);
  394. return 0;
  395. }
  396. return sock;
  397. }
  398. /* pt_proxy: This function does all the client and proxy stuff.
  399. */
  400. #ifndef WIN32
  401. void * pt_proxy(void *args)
  402. #else
  403. unsigned int __stdcall pt_proxy(void *args)
  404. #endif
  405. {
  406. (void) args;
  407. fd_set set;
  408. struct timeval timeout;
  409. int bytes;
  410. struct sockaddr_in addr;
  411. socklen_t addr_len;
  412. int fwd_sock = 0,
  413. max_sock = 0,
  414. idx;
  415. char *buf;
  416. double now, last_status_update = 0.0;
  417. proxy_desc_t *cur, *prev, *tmp;
  418. #ifdef HAVE_PCAP
  419. pcap_info_t pc;
  420. pcap_if_t *alldevs = 0, *pdev;
  421. #endif
  422. xfer_stats_t xfer;
  423. #ifdef HAVE_PCAP
  424. ip_packet_t *pkt;
  425. uint32_t ip;
  426. in_addr_t *adr;
  427. #endif
  428. struct in_addr in_addr;
  429. #ifdef HAVE_ICMPFILTER
  430. struct icmp_filter filt;
  431. #endif
  432. /* Start the thread, initialize protocol and ring states. */
  433. pt_log(kLog_debug, "Starting ping proxy..\n");
  434. if (opts.udp) {
  435. pt_log(kLog_debug, "Creating UDP socket..\n");
  436. if (opts.mode == kMode_proxy)
  437. fwd_sock = pt_create_udp_socket(kDNS_port);
  438. else
  439. fwd_sock = pt_create_udp_socket(0);
  440. if (!fwd_sock) {
  441. pt_log(kLog_error, "Failed to create UDP socket.\n");
  442. return 0;
  443. }
  444. }
  445. else {
  446. if (opts.unprivileged)
  447. {
  448. pt_log(kLog_debug, "Attempting to create unprivileged ICMP datagram socket..\n");
  449. fwd_sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_ICMP);
  450. } else {
  451. pt_log(kLog_debug, "Attempting to create privileged ICMP raw socket..\n");
  452. fwd_sock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
  453. #ifdef HAVE_ICMPFILTER
  454. if (opts.mode == kMode_forward)
  455. filt.data = ~(1<<ICMP_ECHOREPLY);
  456. else
  457. filt.data = ~(1<<ICMP_ECHO);
  458. if (fwd_sock >= 0 &&
  459. setsockopt(fwd_sock, SOL_RAW, ICMP_FILTER, &filt, sizeof filt) == -1)
  460. {
  461. pt_log(kLog_error, "setockopt for ICMP_FILTER: %s\n", strerror(errno));
  462. }
  463. #endif
  464. }
  465. if (fwd_sock < 0) {
  466. pt_log(kLog_error, "Couldn't create %s socket: %s\n",
  467. (opts.unprivileged ? "unprivileged datagram" :
  468. "privileged raw"), strerror(errno));
  469. return 0;
  470. }
  471. }
  472. max_sock = fwd_sock+1;
  473. #ifdef HAVE_PCAP
  474. if (opts.pcap) {
  475. if (opts.udp) {
  476. pt_log(kLog_error, "Packet capture is not useful with UDP [should not get here!]!\n");
  477. close(fwd_sock);
  478. return 0;
  479. }
  480. if (!opts.unprivileged) {
  481. memset(&pc, 0, sizeof(pc));
  482. pt_log(kLog_info, "Initializing pcap.\n");
  483. pc.pcap_err_buf = (char *) malloc(PCAP_ERRBUF_SIZE);
  484. pc.pcap_data_buf = (char *) malloc(pcap_buf_size);
  485. pc.pcap_desc = pcap_open_live(opts.pcap_device,
  486. pcap_buf_size, 0 /* promiscous */,
  487. 50 /* ms */, pc.pcap_err_buf);
  488. if (pc.pcap_desc) {
  489. if (pcap_lookupnet(opts.pcap_device, &pc.netp,
  490. &pc.netmask, pc.pcap_err_buf) == -1)
  491. {
  492. pt_log(kLog_error, "pcap error: %s\n", pc.pcap_err_buf);
  493. opts.pcap = 0;
  494. }
  495. in_addr.s_addr = pc.netp;
  496. pt_log(kLog_verbose, "Network: %s\n", inet_ntoa(in_addr));
  497. in_addr.s_addr = pc.netmask;
  498. pt_log(kLog_verbose, "Netmask: %s\n", inet_ntoa(in_addr));
  499. if (pcap_compile(pc.pcap_desc, &pc.fp, pcap_filter_program, 0, pc.netp) == -1) {
  500. pt_log(kLog_error, "Failed to compile pcap filter program.\n");
  501. pcap_close(pc.pcap_desc);
  502. opts.pcap = 0;
  503. }
  504. else if (pcap_setfilter(pc.pcap_desc, &pc.fp) == -1) {
  505. pt_log(kLog_error, "Failed to set pcap filter program.\n");
  506. pcap_close(pc.pcap_desc);
  507. opts.pcap = 0;
  508. }
  509. }
  510. else {
  511. pt_log(kLog_error, "pcap error: %s\n", pc.pcap_err_buf);
  512. opts.pcap = 0;
  513. if (pcap_findalldevs(&alldevs, pc.pcap_err_buf) == 0) {
  514. idx = 0;
  515. pt_log(kLog_error, "Available pcap devices:\n");
  516. for (pdev = alldevs; pdev != NULL; pdev = pdev->next) {
  517. pt_log(kLog_error, "[%d] \"%s\": \"%s\"\n", ++idx,
  518. pdev->name, (pdev->description ? pdev->description : "UNKNOWN"));
  519. }
  520. pcap_freealldevs(alldevs);
  521. }
  522. }
  523. pc.pkt_q.head = 0;
  524. pc.pkt_q.tail = 0;
  525. pc.pkt_q.elems = 0;
  526. /* Check if we have succeeded, and free stuff if not */
  527. if (!opts.pcap) {
  528. pt_log(kLog_error, "There were errors enabling pcap - pcap has been disabled.\n");
  529. free(pc.pcap_err_buf);
  530. free(pc.pcap_data_buf);
  531. return 0;
  532. }
  533. }
  534. else
  535. pt_log(kLog_info, "pcap disabled since we're running in unprivileged mode.\n");
  536. }
  537. #endif
  538. pthread_mutex_lock(&num_threads_lock);
  539. num_threads++;
  540. pthread_mutex_unlock(&num_threads_lock);
  541. /* Allocate icmp receive buffer */
  542. buf = (char *) malloc(icmp_receive_buf_len);
  543. /* Start forwarding :) */
  544. pt_log(kLog_info, "Ping proxy is listening in %s mode.\n",
  545. (opts.unprivileged ? "unprivileged" : "privileged"));
  546. #ifndef WIN32
  547. #ifdef HAVE_SELINUX
  548. if (opts.uid || opts.gid || opts.selinux_context)
  549. #else
  550. if (opts.uid || opts.gid)
  551. #endif
  552. pt_log(kLog_info, "Dropping privileges now.\n");
  553. if (opts.gid && -1 == setgid(opts.gid))
  554. pt_log(kLog_error, "setgid(%d): %s\n", opts.gid, strerror(errno));
  555. if (opts.uid && -1 == setuid(opts.uid))
  556. pt_log(kLog_error, "setuid(%d): %s\n", opts.uid, strerror(errno));
  557. #ifdef HAVE_SELINUX
  558. if (opts.selinux) {
  559. if (NULL != opts.selinux_context && -1 == setcon(opts.selinux_context))
  560. pt_log(kLog_error, "setcon(%s) failed: %s\n", opts.selinux_context, strerror(errno));
  561. }
  562. #endif
  563. #endif
  564. while (1) {
  565. FD_ZERO(&set);
  566. FD_SET(fwd_sock, &set);
  567. max_sock = fwd_sock+1;
  568. pthread_mutex_lock(&chain_lock);
  569. for (cur = chain; cur; cur = cur->next) {
  570. /* Only handle traffic if there is traffic on the socket, we have
  571. * room in our send window AND we either don't use a password, or
  572. * have been authenticated.
  573. */
  574. if (cur->sock && cur->send_wait_ack < cur->window_size &&
  575. (!opts.password || cur->authenticated))
  576. {
  577. FD_SET(cur->sock, &set);
  578. if (cur->sock >= max_sock)
  579. max_sock = cur->sock+1;
  580. }
  581. }
  582. pthread_mutex_unlock(&chain_lock);
  583. timeout.tv_sec = 0;
  584. timeout.tv_usec = 10000;
  585. /* Don't care about return val, since we need to check for new states anyway.. */
  586. select(max_sock, &set, 0, 0, &timeout);
  587. pthread_mutex_lock(&chain_lock);
  588. for (prev = 0, cur = chain; cur && cur->sock; cur = tmp) {
  589. /* Client: If we're starting up, send a message to the remote end saying so,
  590. * causing him to connect to our desired endpoint.
  591. */
  592. if (cur->state == kProxy_start) {
  593. pt_log(kLog_verbose, "Sending proxy request.\n");
  594. cur->last_ack = time_as_double();
  595. queue_packet(fwd_sock, cur, NULL, 0, cur->dst_ip, cur->dst_port, cur->state | cur->type_flag);
  596. cur->xfer.icmp_out++;
  597. cur->state = kProto_data;
  598. }
  599. if (cur->should_remove) {
  600. pt_log(kLog_info, "\nSession statistics:\n");
  601. print_statistics(&cur->xfer, 0);
  602. pt_log(kLog_info, "\n");
  603. tmp = cur->next;
  604. remove_proxy_desc(cur, prev);
  605. continue;
  606. }
  607. /* Handle TCP traffic */
  608. if (FD_ISSET(cur->sock, &set)) {
  609. bytes = recv(cur->sock, cur->buf, tcp_receive_buf_len, 0);
  610. if (bytes <= 0) {
  611. pt_log(kLog_info, "Connection closed or lost.\n");
  612. tmp = cur->next;
  613. send_termination_msg(cur, fwd_sock);
  614. pt_log(kLog_info, "Session statistics:\n");
  615. print_statistics(&cur->xfer, 0);
  616. remove_proxy_desc(cur, prev);
  617. /* No need to update prev */
  618. continue;
  619. }
  620. cur->xfer.bytes_out += bytes;
  621. cur->xfer.icmp_out++;
  622. queue_packet(fwd_sock, cur, cur->buf, bytes, 0, 0, cur->state | cur->type_flag);
  623. }
  624. prev = cur;
  625. tmp = cur->next;
  626. }
  627. pthread_mutex_unlock(&chain_lock);
  628. if (FD_ISSET(fwd_sock, &set)) {
  629. /* Handle ping traffic */
  630. addr_len = sizeof(struct sockaddr);
  631. bytes = recvfrom(fwd_sock, buf, icmp_receive_buf_len, 0, (struct sockaddr*)&addr, &addr_len);
  632. if (bytes < 0) {
  633. pt_log(kLog_error, "Error receiving packet on ICMP socket: %s\n", strerror(errno));
  634. break;
  635. }
  636. handle_packet(buf, bytes, 0, &addr, fwd_sock);
  637. }
  638. /* Check for packets needing resend, and figure out if any connections
  639. * should be closed down due to inactivity.
  640. */
  641. pthread_mutex_lock(&chain_lock);
  642. now = time_as_double();
  643. for (cur = chain; cur; cur = cur->next) {
  644. in_addr.s_addr = cur->dst_ip;
  645. if (cur->last_activity + kAutomatic_close_timeout < now) {
  646. pt_log(kLog_info, "Dropping tunnel %u to %s:%u due to inactivity.\n", cur->id_no, inet_ntoa(in_addr), cur->dst_port);
  647. cur->should_remove = 1;
  648. continue;
  649. }
  650. if (cur->recv_wait_send && cur->sock)
  651. cur->xfer.bytes_in += send_packets(cur->recv_ring, &cur->recv_xfer_idx, &cur->recv_wait_send, &cur->sock, cur->window_size);
  652. /* Check for any icmp packets requiring resend, and resend _only_ the first packet. */
  653. idx = cur->send_first_ack;
  654. if (cur->send_ring[idx].pkt && cur->send_ring[idx].last_resend+cur->resend_interval < now) {
  655. pt_log(kLog_debug, "Resending packet with seq-no %d.\n", cur->send_ring[idx].seq_no);
  656. cur->send_ring[idx].last_resend = now;
  657. cur->send_ring[idx].pkt->identifier = htons(cur->icmp_id);
  658. cur->send_ring[idx].pkt->seq = htons(cur->ping_seq);
  659. cur->ping_seq++;
  660. cur->send_ring[idx].pkt->checksum = 0;
  661. cur->send_ring[idx].pkt->checksum = htons(calc_icmp_checksum((uint16_t*)cur->send_ring[idx].pkt, cur->send_ring[idx].pkt_len));
  662. /* printf("ID: %d\n", htons(cur->send_ring[idx].pkt->identifier)); */
  663. sendto(fwd_sock, (const void*)cur->send_ring[idx].pkt, cur->send_ring[idx].pkt_len,
  664. 0, (struct sockaddr*)&cur->dest_addr, sizeof(struct sockaddr));
  665. cur->xfer.icmp_resent++;
  666. }
  667. /* Figure out if it's time to send an explicit acknowledgement */
  668. if (cur->last_ack+cur->ack_interval < now && cur->send_wait_ack < cur->window_size &&
  669. cur->remote_ack_val+1 != cur->next_remote_seq)
  670. {
  671. queue_packet(fwd_sock, cur, NULL, 0, cur->dst_ip, cur->dst_port, kProto_ack | cur->type_flag);
  672. cur->last_ack = now;
  673. cur->xfer.icmp_ack_out++;
  674. }
  675. }
  676. pthread_mutex_unlock(&chain_lock);
  677. #ifdef HAVE_PCAP
  678. if (opts.pcap) {
  679. if (pcap_dispatch(pc.pcap_desc, 32, pcap_packet_handler, (u_char*)&pc.pkt_q) > 0) {
  680. pqueue_elem_t *cur;
  681. pt_log(kLog_verbose, "pcap captured %d packets - handling them..\n", pc.pkt_q.elems);
  682. while (pc.pkt_q.head) {
  683. cur = pc.pkt_q.head;
  684. memset(&addr, 0, sizeof(struct sockaddr));
  685. addr.sin_family = AF_INET;
  686. pkt = (ip_packet_t*)&cur->data[0];
  687. ip = pkt->src_ip;
  688. adr = (in_addr_t*)&ip;
  689. addr.sin_addr.s_addr = *adr;
  690. handle_packet(cur->data, cur->bytes, 1, &addr, fwd_sock);
  691. pc.pkt_q.head = cur->next;
  692. free(cur);
  693. pc.pkt_q.elems--;
  694. }
  695. pc.pkt_q.tail = 0;
  696. pc.pkt_q.head = 0;
  697. }
  698. }
  699. #endif
  700. /* Update running statistics, if requested (only once every second) */
  701. if (opts.print_stats && opts.mode == kMode_forward && now > last_status_update+1) {
  702. pthread_mutex_lock(&chain_lock);
  703. memset(&xfer, 0, sizeof(xfer_stats_t));
  704. for (cur = chain; cur; cur = cur->next) {
  705. xfer.bytes_in += cur->xfer.bytes_in;
  706. xfer.bytes_out += cur->xfer.bytes_out;
  707. xfer.icmp_in += cur->xfer.icmp_in;
  708. xfer.icmp_out += cur->xfer.icmp_out;
  709. xfer.icmp_resent += cur->xfer.icmp_resent;
  710. }
  711. pthread_mutex_unlock(&chain_lock);
  712. print_statistics(&xfer, (opts.log_level >= kLog_verbose ? 0 : 1));
  713. last_status_update = now;
  714. }
  715. }
  716. pt_log(kLog_debug, "Proxy exiting..\n");
  717. if (fwd_sock)
  718. close(fwd_sock);
  719. /* TODO: Clean up the other descs. Not really a priority since there's no
  720. * real way to quit ptunnel in the first place..
  721. */
  722. free(buf);
  723. pt_log(kLog_debug, "Ping proxy done\n");
  724. return 0;
  725. }
  726. /* print_statistics: Prints transfer statistics for the given xfer block. The
  727. * is_continuous variable controls the output mode, either printing a new line
  728. * or overwriting the old line.
  729. */
  730. void print_statistics(xfer_stats_t *xfer, int is_continuous) {
  731. const double mb = 1024.0*1024.0;
  732. double loss = 0.0;
  733. if (xfer->icmp_out > 0)
  734. loss = (double)xfer->icmp_resent/(double)xfer->icmp_out;
  735. if (is_continuous)
  736. printf("\r");
  737. printf("[inf]: I/O: %6.2f/%6.2f mb ICMP I/O/R: %8u/%8u/%8u Loss: %4.1f%%",
  738. xfer->bytes_in/mb, xfer->bytes_out/mb, xfer->icmp_in, xfer->icmp_out, xfer->icmp_resent, loss);
  739. if (!is_continuous)
  740. printf("\n");
  741. else
  742. fflush(stdout);
  743. }
  744. #ifdef HAVE_PCAP
  745. /* pcap_packet_handler:
  746. * This is our callback function handling captured packets. We already know that the packets
  747. * are ICMP echo or echo-reply messages, so all we need to do is strip off the ethernet header
  748. * and append it to the queue descriptor (the refcon argument).
  749. *
  750. * Ok, the above isn't entirely correct (we can get other ICMP types as well). This function
  751. * also has problems when it captures packets on the loopback interface. The moral of the
  752. * story: Don't do ping forwarding over the loopback interface.
  753. *
  754. * Also, we currently don't support anything else than ethernet when in pcap mode. The reason
  755. * is that I haven't read up on yet on how to remove the frame header from the packet..
  756. */
  757. void pcap_packet_handler(u_char *refcon, const struct pcap_pkthdr *hdr, const u_char* pkt) {
  758. pqueue_t *q;
  759. pqueue_elem_t *elem;
  760. ip_packet_t *ip;
  761. /* pt_log(kLog_verbose, "Packet handler: %d =? %d\n", hdr->caplen, hdr->len); */
  762. q = (pqueue_t*)refcon;
  763. elem = (pqueue_elem_t *) malloc(sizeof(pqueue_elem_t)+hdr->caplen-sizeof(struct ether_header));
  764. memcpy(elem->data, pkt+sizeof(struct ether_header), hdr->caplen-sizeof(struct ether_header));
  765. ip = (ip_packet_t*)elem->data;
  766. /* TODO: Add fragment support */
  767. elem->bytes = ntohs(ip->pkt_len);
  768. if (elem->bytes > hdr->caplen-sizeof(struct ether_header)) {
  769. pt_log(kLog_error, "Received fragmented packet - unable to reconstruct!\n");
  770. pt_log(kLog_error, "This error usually occurs because pcap is used on "
  771. "devices that are not wlan or ethernet.\n");
  772. free(elem);
  773. return;
  774. }
  775. /* elem->bytes = hdr->caplen-sizeof(struct ether_header); */
  776. elem->next = 0;
  777. if (q->tail) {
  778. q->tail->next = elem;
  779. q->tail = elem;
  780. }
  781. else {
  782. q->head = elem;
  783. q->tail = elem;
  784. }
  785. q->elems++;
  786. }
  787. #endif
  788. uint16_t calc_icmp_checksum(uint16_t *data, int bytes) {
  789. uint32_t sum;
  790. int i;
  791. sum = 0;
  792. for (i = 0; i < bytes / 2; i++) {
  793. /* WARNING; this might be a bug, but might explain why I occasionally
  794. * see buggy checksums.. (added htons, that might be the correct behaviour)
  795. */
  796. sum += data[i];
  797. }
  798. sum = (sum & 0xFFFF) + (sum >> 16);
  799. sum = htons(0xFFFF - sum);
  800. return sum;
  801. }
  802. /* send_termination_msg: Sends two packets to the remote end, informing it that
  803. * the tunnel is being closed down.
  804. */
  805. void send_termination_msg(proxy_desc_t *cur, int icmp_sock) {
  806. size_t i;
  807. const size_t max_termination_msgs = 3;
  808. /* Send packet twice, hoping at least one of them makes it through.. */
  809. for (i = 0; i < max_termination_msgs; ++i) {
  810. queue_packet(icmp_sock, cur, NULL, 0, cur->dst_ip, cur->dst_port, kProto_close | cur->type_flag);
  811. }
  812. cur->xfer.icmp_out += max_termination_msgs;
  813. }