PageRenderTime 23ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/release/src/router/openvpn/src/openvpn/sig.c

https://gitlab.com/envieidoc/advancedtomato2
C | 386 lines | 304 code | 40 blank | 42 comment | 36 complexity | b7e4233612d3cfec38d8a215df7f5a26 MD5 | raw file
  1. /*
  2. * OpenVPN -- An application to securely tunnel IP networks
  3. * over a single TCP/UDP port, with support for SSL/TLS-based
  4. * session authentication and key exchange,
  5. * packet encryption, packet authentication, and
  6. * packet compression.
  7. *
  8. * Copyright (C) 2002-2010 OpenVPN Technologies, Inc. <sales@openvpn.net>
  9. *
  10. * This program is free software; you can redistribute it and/or modify
  11. * it under the terms of the GNU General Public License version 2
  12. * as published by the Free Software Foundation.
  13. *
  14. * This program is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU General Public License
  20. * along with this program (see the file COPYING included with this
  21. * distribution); if not, write to the Free Software Foundation, Inc.,
  22. * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  23. */
  24. #ifdef HAVE_CONFIG_H
  25. #include "config.h"
  26. #elif defined(_MSC_VER)
  27. #include "config-msvc.h"
  28. #endif
  29. #include "syshead.h"
  30. #include "buffer.h"
  31. #include "error.h"
  32. #include "win32.h"
  33. #include "init.h"
  34. #include "status.h"
  35. #include "sig.h"
  36. #include "occ.h"
  37. #include "manage.h"
  38. #include "openvpn.h"
  39. #include "memdbg.h"
  40. /* Handle signals */
  41. struct signal_info siginfo_static; /* GLOBAL */
  42. struct signame {
  43. int value;
  44. const char *upper;
  45. const char *lower;
  46. };
  47. static const struct signame signames[] = {
  48. { SIGINT, "SIGINT", "sigint"},
  49. { SIGTERM, "SIGTERM", "sigterm" },
  50. { SIGHUP, "SIGHUP", "sighup" },
  51. { SIGUSR1, "SIGUSR1", "sigusr1" },
  52. { SIGUSR2, "SIGUSR2", "sigusr2" }
  53. };
  54. int
  55. parse_signal (const char *signame)
  56. {
  57. int i;
  58. for (i = 0; i < (int)SIZE (signames); ++i)
  59. {
  60. if (!strcmp (signame, signames[i].upper))
  61. return signames[i].value;
  62. }
  63. return -1;
  64. }
  65. const char *
  66. signal_name (const int sig, const bool upper)
  67. {
  68. int i;
  69. for (i = 0; i < (int)SIZE (signames); ++i)
  70. {
  71. if (sig == signames[i].value)
  72. return upper ? signames[i].upper : signames[i].lower;
  73. }
  74. return "UNKNOWN";
  75. }
  76. const char *
  77. signal_description (const int signum, const char *sigtext)
  78. {
  79. if (sigtext)
  80. return sigtext;
  81. else
  82. return signal_name (signum, false);
  83. }
  84. void
  85. throw_signal (const int signum)
  86. {
  87. siginfo_static.signal_received = signum;
  88. siginfo_static.hard = true;
  89. }
  90. void
  91. throw_signal_soft (const int signum, const char *signal_text)
  92. {
  93. siginfo_static.signal_received = signum;
  94. siginfo_static.hard = false;
  95. siginfo_static.signal_text = signal_text;
  96. }
  97. static void
  98. signal_reset (struct signal_info *si)
  99. {
  100. if (si)
  101. {
  102. si->signal_received = 0;
  103. si->signal_text = NULL;
  104. si->hard = false;
  105. }
  106. }
  107. void
  108. print_signal (const struct signal_info *si, const char *title, int msglevel)
  109. {
  110. if (si)
  111. {
  112. const char *hs = (si->hard ? "hard" : "soft");
  113. const char *type = (si->signal_text ? si->signal_text : "");
  114. const char *t = (title ? title : "process");
  115. switch (si->signal_received)
  116. {
  117. case SIGINT:
  118. case SIGTERM:
  119. msg (msglevel, "%s[%s,%s] received, %s exiting",
  120. signal_name (si->signal_received, true), hs, type, t);
  121. break;
  122. case SIGHUP:
  123. case SIGUSR1:
  124. msg (msglevel, "%s[%s,%s] received, %s restarting",
  125. signal_name (si->signal_received, true), hs, type, t);
  126. break;
  127. default:
  128. msg (msglevel, "Unknown signal %d [%s,%s] received by %s", si->signal_received, hs, type, t);
  129. break;
  130. }
  131. }
  132. else
  133. msg (msglevel, "Unknown signal received");
  134. }
  135. /*
  136. * Call management interface with restart info
  137. */
  138. void
  139. signal_restart_status (const struct signal_info *si)
  140. {
  141. #ifdef ENABLE_MANAGEMENT
  142. if (management)
  143. {
  144. int state = -1;
  145. switch (si->signal_received)
  146. {
  147. case SIGINT:
  148. case SIGTERM:
  149. state = OPENVPN_STATE_EXITING;
  150. break;
  151. case SIGHUP:
  152. case SIGUSR1:
  153. state = OPENVPN_STATE_RECONNECTING;
  154. break;
  155. }
  156. if (state >= 0)
  157. management_set_state (management,
  158. state,
  159. si->signal_text ? si->signal_text : signal_name (si->signal_received, true),
  160. (in_addr_t)0,
  161. (in_addr_t)0);
  162. }
  163. #endif
  164. }
  165. #ifdef HAVE_SIGNAL_H
  166. /* normal signal handler, when we are in event loop */
  167. static void
  168. signal_handler (const int signum)
  169. {
  170. throw_signal (signum);
  171. signal (signum, signal_handler);
  172. }
  173. #endif
  174. /* set handlers for unix signals */
  175. #ifdef HAVE_SIGNAL_H
  176. #define SM_UNDEF 0
  177. #define SM_PRE_INIT 1
  178. #define SM_POST_INIT 2
  179. static int signal_mode; /* GLOBAL */
  180. #endif
  181. void
  182. pre_init_signal_catch (void)
  183. {
  184. #ifndef WIN32
  185. #ifdef HAVE_SIGNAL_H
  186. signal_mode = SM_PRE_INIT;
  187. signal (SIGINT, signal_handler);
  188. signal (SIGTERM, signal_handler);
  189. signal (SIGHUP, SIG_IGN);
  190. signal (SIGUSR1, SIG_IGN);
  191. signal (SIGUSR2, SIG_IGN);
  192. signal (SIGPIPE, SIG_IGN);
  193. #endif /* HAVE_SIGNAL_H */
  194. #endif /* WIN32 */
  195. }
  196. void
  197. post_init_signal_catch (void)
  198. {
  199. #ifndef WIN32
  200. #ifdef HAVE_SIGNAL_H
  201. signal_mode = SM_POST_INIT;
  202. signal (SIGINT, signal_handler);
  203. signal (SIGTERM, signal_handler);
  204. signal (SIGHUP, signal_handler);
  205. signal (SIGUSR1, signal_handler);
  206. signal (SIGUSR2, signal_handler);
  207. signal (SIGPIPE, SIG_IGN);
  208. #endif /* HAVE_SIGNAL_H */
  209. #endif
  210. }
  211. /* called after daemonization to retain signal settings */
  212. void
  213. restore_signal_state (void)
  214. {
  215. #ifdef HAVE_SIGNAL_H
  216. if (signal_mode == SM_PRE_INIT)
  217. pre_init_signal_catch ();
  218. else if (signal_mode == SM_POST_INIT)
  219. post_init_signal_catch ();
  220. #endif
  221. }
  222. /*
  223. * Print statistics.
  224. *
  225. * Triggered by SIGUSR2 or F2 on Windows.
  226. */
  227. void
  228. print_status (const struct context *c, struct status_output *so)
  229. {
  230. struct gc_arena gc = gc_new ();
  231. status_reset (so);
  232. status_printf (so, "OpenVPN STATISTICS");
  233. status_printf (so, "Updated,%s", time_string (0, 0, false, &gc));
  234. status_printf (so, "TUN/TAP read bytes," counter_format, c->c2.tun_read_bytes);
  235. status_printf (so, "TUN/TAP write bytes," counter_format, c->c2.tun_write_bytes);
  236. status_printf (so, "TCP/UDP read bytes," counter_format, c->c2.link_read_bytes);
  237. status_printf (so, "TCP/UDP write bytes," counter_format, c->c2.link_write_bytes);
  238. status_printf (so, "Auth read bytes," counter_format, c->c2.link_read_bytes_auth);
  239. #ifdef ENABLE_LZO
  240. if (lzo_defined (&c->c2.lzo_compwork))
  241. lzo_print_stats (&c->c2.lzo_compwork, so);
  242. #endif
  243. #ifdef PACKET_TRUNCATION_CHECK
  244. status_printf (so, "TUN read truncations," counter_format, c->c2.n_trunc_tun_read);
  245. status_printf (so, "TUN write truncations," counter_format, c->c2.n_trunc_tun_write);
  246. status_printf (so, "Pre-encrypt truncations," counter_format, c->c2.n_trunc_pre_encrypt);
  247. status_printf (so, "Post-decrypt truncations," counter_format, c->c2.n_trunc_post_decrypt);
  248. #endif
  249. #ifdef WIN32
  250. if (tuntap_defined (c->c1.tuntap))
  251. status_printf (so, "TAP-WIN32 driver status,\"%s\"",
  252. tap_win_getinfo (c->c1.tuntap, &gc));
  253. #endif
  254. status_printf (so, "END");
  255. status_flush (so);
  256. gc_free (&gc);
  257. }
  258. #ifdef ENABLE_OCC
  259. /*
  260. * Handle the triggering and time-wait of explicit
  261. * exit notification.
  262. */
  263. static void
  264. process_explicit_exit_notification_init (struct context *c)
  265. {
  266. msg (M_INFO, "SIGTERM received, sending exit notification to peer");
  267. event_timeout_init (&c->c2.explicit_exit_notification_interval, 1, 0);
  268. reset_coarse_timers (c);
  269. signal_reset (c->sig);
  270. halt_non_edge_triggered_signals ();
  271. c->c2.explicit_exit_notification_time_wait = now;
  272. }
  273. void
  274. process_explicit_exit_notification_timer_wakeup (struct context *c)
  275. {
  276. if (event_timeout_trigger (&c->c2.explicit_exit_notification_interval,
  277. &c->c2.timeval,
  278. ETT_DEFAULT))
  279. {
  280. ASSERT (c->c2.explicit_exit_notification_time_wait && c->options.ce.explicit_exit_notification);
  281. if (now >= c->c2.explicit_exit_notification_time_wait + c->options.ce.explicit_exit_notification)
  282. {
  283. event_timeout_clear (&c->c2.explicit_exit_notification_interval);
  284. c->sig->signal_received = SIGTERM;
  285. c->sig->signal_text = "exit-with-notification";
  286. }
  287. else
  288. {
  289. c->c2.occ_op = OCC_EXIT;
  290. }
  291. }
  292. }
  293. #endif
  294. /*
  295. * Process signals
  296. */
  297. void
  298. remap_signal (struct context *c)
  299. {
  300. if (c->sig->signal_received == SIGUSR1 && c->options.remap_sigusr1)
  301. c->sig->signal_received = c->options.remap_sigusr1;
  302. }
  303. static void
  304. process_sigusr2 (const struct context *c)
  305. {
  306. struct status_output *so = status_open (NULL, 0, M_INFO, NULL, 0);
  307. print_status (c, so);
  308. status_close (so);
  309. signal_reset (c->sig);
  310. }
  311. static bool
  312. process_sigterm (struct context *c)
  313. {
  314. bool ret = true;
  315. #ifdef ENABLE_OCC
  316. if (c->options.ce.explicit_exit_notification
  317. && !c->c2.explicit_exit_notification_time_wait)
  318. {
  319. process_explicit_exit_notification_init (c);
  320. ret = false;
  321. }
  322. #endif
  323. return ret;
  324. }
  325. bool
  326. process_signal (struct context *c)
  327. {
  328. bool ret = true;
  329. if (c->sig->signal_received == SIGTERM || c->sig->signal_received == SIGINT)
  330. {
  331. ret = process_sigterm (c);
  332. }
  333. else if (c->sig->signal_received == SIGUSR2)
  334. {
  335. process_sigusr2 (c);
  336. ret = false;
  337. }
  338. return ret;
  339. }
  340. void
  341. register_signal (struct context *c, int sig, const char *text)
  342. {
  343. if (c->sig->signal_received != SIGTERM)
  344. c->sig->signal_received = sig;
  345. c->sig->signal_text = text;
  346. }