mainloop.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509
  1. /*
  2. * OpenConnect (SSL + DTLS) VPN client
  3. *
  4. * Copyright © 2008-2015 Intel Corporation.
  5. *
  6. * Author: David Woodhouse <dwmw2@infradead.org>
  7. *
  8. * This program is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU Lesser General Public License
  10. * version 2.1, as published by the Free Software Foundation.
  11. *
  12. * This program is distributed in the hope that it will be useful, but
  13. * WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * Lesser General Public License for more details.
  16. */
  17. #include <config.h>
  18. #include "openconnect-internal.h"
  19. #include <unistd.h>
  20. #ifndef _WIN32
  21. /* for setgroups() */
  22. # include <sys/types.h>
  23. # include <grp.h>
  24. #endif
  25. #include <errno.h>
  26. #include <limits.h>
  27. #include <stdlib.h>
  28. #include <string.h>
  29. int queue_new_packet(struct openconnect_info *vpninfo,
  30. struct pkt_q *q, void *buf, int len)
  31. {
  32. struct pkt *new = alloc_pkt(vpninfo, len);
  33. if (!new)
  34. return -ENOMEM;
  35. new->len = len;
  36. new->next = NULL;
  37. memcpy(new->data, buf, len);
  38. queue_packet(q, new);
  39. return 0;
  40. }
  41. /* This is here because it's generic and hence can't live in either of the
  42. tun*.c files for specific platforms */
  43. int tun_mainloop(struct openconnect_info *vpninfo, int *timeout, int readable, int did_work)
  44. {
  45. struct pkt *this;
  46. int work_done = 0;
  47. if (readable && read_fd_monitored(vpninfo, tun)) {
  48. struct pkt *out_pkt = vpninfo->tun_pkt;
  49. while (1) {
  50. int len = vpninfo->ip_info.mtu;
  51. if (!out_pkt) {
  52. out_pkt = alloc_pkt(vpninfo, len + vpninfo->pkt_trailer);
  53. if (!out_pkt) {
  54. vpn_progress(vpninfo, PRG_ERR, _("Allocation failed\n"));
  55. break;
  56. }
  57. out_pkt->len = len;
  58. }
  59. if (os_read_tun(vpninfo, out_pkt))
  60. break;
  61. vpninfo->stats.tx_pkts++;
  62. vpninfo->stats.tx_bytes += out_pkt->len;
  63. work_done = 1;
  64. if (queue_packet(&vpninfo->outgoing_queue, out_pkt) +
  65. vpninfo->tcp_control_queue.count >= vpninfo->max_qlen) {
  66. out_pkt = NULL;
  67. unmonitor_read_fd(vpninfo, tun);
  68. break;
  69. }
  70. out_pkt = NULL;
  71. }
  72. vpninfo->tun_pkt = out_pkt;
  73. } else if (vpninfo->outgoing_queue.count + vpninfo->tcp_control_queue.count < vpninfo->max_qlen) {
  74. monitor_read_fd(vpninfo, tun);
  75. }
  76. while ((this = dequeue_packet(&vpninfo->incoming_queue))) {
  77. unmonitor_write_fd(vpninfo, tun);
  78. if (os_write_tun(vpninfo, this)) {
  79. requeue_packet(&vpninfo->incoming_queue, this);
  80. break;
  81. }
  82. vpninfo->stats.rx_pkts++;
  83. vpninfo->stats.rx_bytes += this->len;
  84. free_pkt(vpninfo, this);
  85. }
  86. /* Work is not done if we just got rid of packets off the queue */
  87. return work_done;
  88. }
  89. static int setup_tun_device(struct openconnect_info *vpninfo)
  90. {
  91. int ret;
  92. if (vpninfo->setup_tun) {
  93. vpninfo->setup_tun(vpninfo->cbdata);
  94. if (tun_is_up(vpninfo))
  95. return 0;
  96. }
  97. #ifndef _WIN32
  98. if (vpninfo->use_tun_script) {
  99. ret = openconnect_setup_tun_script(vpninfo, vpninfo->vpnc_script);
  100. if (ret) {
  101. vpn_progress(vpninfo, PRG_ERR, _("Set up tun script failed\n"));
  102. return ret;
  103. }
  104. } else
  105. #endif
  106. ret = openconnect_setup_tun_device(vpninfo, vpninfo->vpnc_script, vpninfo->ifname);
  107. if (ret) {
  108. vpn_progress(vpninfo, PRG_ERR, _("Set up tun device failed\n"));
  109. if (!vpninfo->quit_reason)
  110. vpninfo->quit_reason = "Set up tun device failed";
  111. return ret;
  112. }
  113. #if !defined(_WIN32) && !defined(__native_client__)
  114. if (vpninfo->uid != getuid()) {
  115. if (setgid(vpninfo->gid)) {
  116. vpn_progress(vpninfo, PRG_ERR, _("Failed to set gid %ld: %s\n"),
  117. (long)vpninfo->gid, strerror(errno));
  118. return -EPERM;
  119. }
  120. if (setgroups(1, &vpninfo->gid)) {
  121. vpn_progress(vpninfo, PRG_ERR, _("Failed to set groups to %ld: %s\n"),
  122. (long)vpninfo->gid, strerror(errno));
  123. return -EPERM;
  124. }
  125. if (setuid(vpninfo->uid)) {
  126. vpn_progress(vpninfo, PRG_ERR, _("Failed to set uid %ld: %s\n"),
  127. (long)vpninfo->uid, strerror(errno));
  128. return -EPERM;
  129. }
  130. }
  131. #endif
  132. return 0;
  133. }
  134. /* Return value:
  135. * = 0, when successfully paused (may call again)
  136. * = -EINTR, if aborted locally via OC_CMD_CANCEL
  137. * = -ECONNABORTED, if aborted locally via OC_CMD_DETACH
  138. * = -EPIPE, if the remote end explicitly terminated the session
  139. * = -EPERM, if the gateway sent 401 Unauthorized (cookie expired)
  140. * < 0, for any other error
  141. */
  142. int openconnect_mainloop(struct openconnect_info *vpninfo,
  143. int reconnect_timeout,
  144. int reconnect_interval)
  145. {
  146. int ret = 0;
  147. int tun_r = 1, udp_r = 1, tcp_r = 1;
  148. #ifdef HAVE_VHOST
  149. int vhost_r = 0;
  150. #endif
  151. vpninfo->reconnect_timeout = reconnect_timeout;
  152. vpninfo->reconnect_interval = reconnect_interval;
  153. if (vpninfo->cmd_fd != -1) {
  154. monitor_fd_new(vpninfo, cmd);
  155. monitor_read_fd(vpninfo, cmd);
  156. }
  157. while (!vpninfo->quit_reason) {
  158. int did_work = 0;
  159. int timeout;
  160. #ifdef _WIN32
  161. HANDLE events[4];
  162. int nr_events = 0;
  163. #else
  164. struct timeval tv;
  165. fd_set rfds, wfds, efds;
  166. #endif
  167. /* If tun is not up, loop more often to detect
  168. * a DTLS timeout (due to a firewall block) as soon. */
  169. if (tun_is_up(vpninfo))
  170. timeout = INT_MAX;
  171. else
  172. timeout = 1000;
  173. if (!tun_is_up(vpninfo)) {
  174. if (vpninfo->delay_tunnel_reason) {
  175. vpn_progress(vpninfo, PRG_TRACE, _("Delaying tunnel with reason: %s\n"),
  176. vpninfo->delay_tunnel_reason);
  177. /* XX: don't let this spin forever */
  178. vpninfo->delay_tunnel_reason = NULL;
  179. } else {
  180. /* No DTLS, or DTLS failed; setup TUN device unconditionally */
  181. ret = setup_tun_device(vpninfo);
  182. if (ret)
  183. break;
  184. }
  185. }
  186. if (vpninfo->dtls_state > DTLS_DISABLED) {
  187. ret = vpninfo->proto->udp_mainloop(vpninfo, &timeout, udp_r);
  188. if (vpninfo->quit_reason)
  189. break;
  190. did_work += ret;
  191. }
  192. ret = vpninfo->proto->tcp_mainloop(vpninfo, &timeout, tcp_r);
  193. if (vpninfo->quit_reason)
  194. break;
  195. did_work += ret;
  196. /* Tun must be last because it will set/clear its bit
  197. in the select_rfds according to the queue length */
  198. if (!tun_is_up(vpninfo)) {
  199. struct pkt *this;
  200. /* no tun yet; clear any queued packets */
  201. while ((this = dequeue_packet(&vpninfo->incoming_queue)))
  202. free_pkt(vpninfo, this);
  203. #ifdef HAVE_VHOST
  204. } else if (vpninfo->vhost_fd != -1) {
  205. did_work += vhost_tun_mainloop(vpninfo, &timeout, vhost_r, did_work);
  206. /* If it returns zero *then* it will have read the eventfd
  207. * and there's no need to do so again until we poll again. */
  208. if (!did_work)
  209. vhost_r = 0;
  210. #endif
  211. } else {
  212. did_work += tun_mainloop(vpninfo, &timeout, tun_r, did_work);
  213. }
  214. if (vpninfo->quit_reason)
  215. break;
  216. if (vpninfo->need_poll_cmd_fd)
  217. poll_cmd_fd(vpninfo, 0);
  218. if (vpninfo->got_cancel_cmd) {
  219. if (vpninfo->delay_close != NO_DELAY_CLOSE) {
  220. if (vpninfo->delay_close == DELAY_CLOSE_IMMEDIATE_CALLBACK) {
  221. vpn_progress(vpninfo, PRG_TRACE, _("Delaying cancel (immediate callback).\n"));
  222. did_work++;
  223. } else
  224. vpn_progress(vpninfo, PRG_TRACE, _("Delaying cancel.\n"));
  225. /* XX: don't let this spin forever */
  226. vpninfo->delay_close = NO_DELAY_CLOSE;
  227. } else if (vpninfo->cancel_type == OC_CMD_CANCEL) {
  228. vpninfo->quit_reason = "Aborted by caller";
  229. vpninfo->got_cancel_cmd = 0;
  230. ret = -EINTR;
  231. break;
  232. } else {
  233. vpninfo->got_cancel_cmd = 0;
  234. ret = -ECONNABORTED;
  235. break;
  236. }
  237. }
  238. if (vpninfo->got_pause_cmd) {
  239. if (vpninfo->delay_close != NO_DELAY_CLOSE) {
  240. /* XX: don't let this spin forever */
  241. if (vpninfo->delay_close == DELAY_CLOSE_IMMEDIATE_CALLBACK) {
  242. vpn_progress(vpninfo, PRG_TRACE, _("Delaying pause (immediate callback).\n"));
  243. did_work++;
  244. } else
  245. vpn_progress(vpninfo, PRG_TRACE, _("Delaying pause.\n"));
  246. /* XX: don't let this spin forever */
  247. vpninfo->delay_close = NO_DELAY_CLOSE;
  248. } else {
  249. /* close all connections and wait for the user to call
  250. openconnect_mainloop() again */
  251. openconnect_close_https(vpninfo, 0);
  252. if (vpninfo->dtls_state > DTLS_DISABLED) {
  253. vpninfo->proto->udp_close(vpninfo);
  254. vpninfo->new_dtls_started = 0;
  255. }
  256. vpninfo->got_pause_cmd = 0;
  257. vpn_progress(vpninfo, PRG_INFO, _("Caller paused the connection\n"));
  258. if (vpninfo->cmd_fd >= 0)
  259. unmonitor_fd(vpninfo, cmd);
  260. return 0;
  261. }
  262. }
  263. if (did_work)
  264. continue;
  265. vpn_progress(vpninfo, PRG_TRACE,
  266. _("No work to do; sleeping for %d ms...\n"), timeout);
  267. #ifdef _WIN32
  268. if (vpninfo->dtls_monitored) {
  269. WSAEventSelect(vpninfo->dtls_fd, vpninfo->dtls_event, vpninfo->dtls_monitored);
  270. events[nr_events++] = vpninfo->dtls_event;
  271. }
  272. if (vpninfo->ssl_monitored) {
  273. WSAEventSelect(vpninfo->ssl_fd, vpninfo->ssl_event, vpninfo->ssl_monitored);
  274. events[nr_events++] = vpninfo->ssl_event;
  275. }
  276. if (vpninfo->cmd_monitored) {
  277. WSAEventSelect(vpninfo->cmd_fd, vpninfo->cmd_event, vpninfo->cmd_monitored);
  278. events[nr_events++] = vpninfo->cmd_event;
  279. }
  280. if (vpninfo->tun_monitored) {
  281. events[nr_events++] = vpninfo->tun_rd_overlap.hEvent;
  282. }
  283. if (WaitForMultipleObjects(nr_events, events, FALSE, timeout) == WAIT_FAILED) {
  284. char *errstr = openconnect__win32_strerror(GetLastError());
  285. vpn_progress(vpninfo, PRG_ERR,
  286. _("WaitForMultipleObjects failed: %s\n"),
  287. errstr);
  288. free(errstr);
  289. }
  290. #else
  291. #ifdef HAVE_EPOLL
  292. if (vpninfo->epoll_fd >= 0) {
  293. struct epoll_event evs[5];
  294. /* During busy periods, monitor_read_fd() and unmonitor_read_fd()
  295. * may get called multiple times as we go round and round the
  296. * loop and queues get full then have space again. In the past
  297. * with the select() loop, that was only a bitflip in the fd_set
  298. * and didn't cost much. With epoll() it's actually a system
  299. * call, so don't do it every time. Wait until we're about to
  300. * sleep, and *then* ensure that we call epoll_ctl() to sync the
  301. * set of events that we care about, if it's changed. */
  302. if (vpninfo->epoll_update) {
  303. update_epoll_fd(vpninfo, tun);
  304. update_epoll_fd(vpninfo, ssl);
  305. update_epoll_fd(vpninfo, cmd);
  306. update_epoll_fd(vpninfo, dtls);
  307. #ifdef HAVE_VHOST
  308. update_epoll_fd(vpninfo, vhost_call);
  309. #endif
  310. }
  311. tun_r = udp_r = tcp_r = 0;
  312. #ifdef HAVE_VHOST
  313. vhost_r = 0;
  314. #endif
  315. int nfds = epoll_wait(vpninfo->epoll_fd, evs, 5, timeout);
  316. if (nfds < 0) {
  317. if (errno != EINTR) {
  318. ret = -errno;
  319. vpn_perror(vpninfo, _("Failed epoll_wait() in mainloop"));
  320. break;
  321. }
  322. nfds = 0;
  323. }
  324. while (nfds--) {
  325. if (evs[nfds].events & (EPOLLIN|EPOLLERR)) {
  326. if (evs[nfds].data.fd == vpninfo->tun_fd)
  327. tun_r = 1;
  328. else if (evs[nfds].data.fd == vpninfo->ssl_fd)
  329. tcp_r = 1;
  330. else if (evs[nfds].data.fd == vpninfo->dtls_fd)
  331. udp_r = 1;
  332. #ifdef HAVE_VHOST
  333. else if (evs[nfds].data.fd == vpninfo->vhost_call_fd)
  334. vhost_r = 1;
  335. #endif
  336. }
  337. }
  338. continue;
  339. }
  340. #endif
  341. memcpy(&rfds, &vpninfo->_select_rfds, sizeof(rfds));
  342. memcpy(&wfds, &vpninfo->_select_wfds, sizeof(wfds));
  343. memcpy(&efds, &vpninfo->_select_efds, sizeof(efds));
  344. tv.tv_sec = timeout / 1000;
  345. tv.tv_usec = (timeout % 1000) * 1000;
  346. if (select(vpninfo->_select_nfds, &rfds, &wfds, &efds, &tv) < 0 &&
  347. errno != EINTR) {
  348. ret = -errno;
  349. vpn_perror(vpninfo, _("Failed select() in mainloop"));
  350. break;
  351. }
  352. #ifdef HAVE_VHOST
  353. if (vpninfo->vhost_call_fd >= 0)
  354. vhost_r = FD_ISSET(vpninfo->vhost_call_fd, &rfds);
  355. #endif
  356. if (vpninfo->tun_fd >= 0)
  357. tun_r = FD_ISSET(vpninfo->tun_fd, &rfds);
  358. if (vpninfo->dtls_fd >= 0)
  359. udp_r = FD_ISSET(vpninfo->dtls_fd, &rfds);
  360. if (vpninfo->ssl_fd >= 0)
  361. tcp_r = FD_ISSET(vpninfo->ssl_fd, &rfds);
  362. #endif
  363. }
  364. if (vpninfo->quit_reason && vpninfo->proto->vpn_close_session)
  365. vpninfo->proto->vpn_close_session(vpninfo, vpninfo->quit_reason);
  366. if (tun_is_up(vpninfo))
  367. os_shutdown_tun(vpninfo);
  368. if (vpninfo->cmd_fd >= 0)
  369. unmonitor_fd(vpninfo, cmd);
  370. return ret < 0 ? ret : -EIO;
  371. }
  372. int ka_check_deadline(int *timeout, time_t now, time_t due)
  373. {
  374. if (now >= due)
  375. return 1;
  376. if (*timeout > (due - now) * 1000)
  377. *timeout = (due - now) * 1000;
  378. return 0;
  379. }
  380. /* Called when the socket is unwritable, to get the deadline for DPD.
  381. Returns 1 if DPD deadline has already arrived. */
  382. int ka_stalled_action(struct keepalive_info *ka, int *timeout)
  383. {
  384. time_t now = time(NULL);
  385. /* We only support the new-tunnel rekey method for now. */
  386. if (ka->rekey_method != REKEY_NONE &&
  387. ka_check_deadline(timeout, now, ka->last_rekey + ka->rekey)) {
  388. ka->last_rekey = now;
  389. return KA_REKEY;
  390. }
  391. if (ka->dpd &&
  392. ka_check_deadline(timeout, now, ka->last_rx + (2 * ka->dpd)))
  393. return KA_DPD_DEAD;
  394. return KA_NONE;
  395. }
  396. int keepalive_action(struct keepalive_info *ka, int *timeout)
  397. {
  398. time_t now = time(NULL);
  399. if (ka->rekey_method != REKEY_NONE &&
  400. ka_check_deadline(timeout, now, ka->last_rekey + ka->rekey)) {
  401. ka->last_rekey = now;
  402. return KA_REKEY;
  403. }
  404. /* DPD is bidirectional -- PKT 3 out, PKT 4 back */
  405. if (ka->dpd) {
  406. time_t due = ka->last_rx + ka->dpd;
  407. time_t overdue = ka->last_rx + (2 * ka->dpd);
  408. /* Peer didn't respond */
  409. if (now > overdue)
  410. return KA_DPD_DEAD;
  411. /* If we already have DPD outstanding, don't flood. Repeat by
  412. all means, but only after half the DPD period. */
  413. if (ka->last_dpd > ka->last_rx)
  414. due = ka->last_dpd + ka->dpd / 2;
  415. /* We haven't seen a packet from this host for $DPD seconds.
  416. Prod it to see if it's still alive */
  417. if (ka_check_deadline(timeout, now, due)) {
  418. ka->last_dpd = now;
  419. return KA_DPD;
  420. }
  421. }
  422. /* Keepalive is just client -> server.
  423. If we haven't sent anything for $KEEPALIVE seconds, send a
  424. dummy packet (which the server will discard) */
  425. if (ka->keepalive &&
  426. ka_check_deadline(timeout, now, ka->last_tx + ka->keepalive))
  427. return KA_KEEPALIVE;
  428. return KA_NONE;
  429. }
  430. int trojan_check_deadline(struct openconnect_info *vpninfo, int *timeout)
  431. {
  432. time_t now = time(NULL);
  433. if (vpninfo->trojan_interval &&
  434. ka_check_deadline(timeout, now,
  435. vpninfo->last_trojan + vpninfo->trojan_interval)) {
  436. vpninfo->last_trojan = now;
  437. return 1;
  438. } else {
  439. return 0;
  440. }
  441. }