OpenVPN
sig.c
Go to the documentation of this 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-2018 OpenVPN 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 along
20  * with this program; if not, write to the Free Software Foundation, Inc.,
21  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22  */
23 
24 #ifdef HAVE_CONFIG_H
25 #include "config.h"
26 #elif defined(_MSC_VER)
27 #include "config-msvc.h"
28 #endif
29 
30 #include "syshead.h"
31 
32 #include "buffer.h"
33 #include "error.h"
34 #include "win32.h"
35 #include "init.h"
36 #include "status.h"
37 #include "sig.h"
38 #include "occ.h"
39 #include "manage.h"
40 #include "openvpn.h"
41 
42 #include "memdbg.h"
43 
44 /* Handle signals */
45 
46 struct signal_info siginfo_static; /* GLOBAL */
47 
48 struct signame {
49  int value;
50  const char *upper;
51  const char *lower;
52 };
53 
54 static const struct signame signames[] = {
55  { SIGINT, "SIGINT", "sigint"},
56  { SIGTERM, "SIGTERM", "sigterm" },
57  { SIGHUP, "SIGHUP", "sighup" },
58  { SIGUSR1, "SIGUSR1", "sigusr1" },
59  { SIGUSR2, "SIGUSR2", "sigusr2" }
60 };
61 
62 int
63 parse_signal(const char *signame)
64 {
65  int i;
66  for (i = 0; i < (int)SIZE(signames); ++i)
67  {
68  if (!strcmp(signame, signames[i].upper))
69  {
70  return signames[i].value;
71  }
72  }
73  return -1;
74 }
75 
76 const char *
77 signal_name(const int sig, const bool upper)
78 {
79  int i;
80  for (i = 0; i < (int)SIZE(signames); ++i)
81  {
82  if (sig == signames[i].value)
83  {
84  return upper ? signames[i].upper : signames[i].lower;
85  }
86  }
87  return "UNKNOWN";
88 }
89 
90 const char *
91 signal_description(const int signum, const char *sigtext)
92 {
93  if (sigtext)
94  {
95  return sigtext;
96  }
97  else
98  {
99  return signal_name(signum, false);
100  }
101 }
102 
103 void
104 throw_signal(const int signum)
105 {
108 }
109 
110 void
111 throw_signal_soft(const int signum, const char *signal_text)
112 {
115  siginfo_static.signal_text = signal_text;
116 }
117 
118 static void
120 {
121  if (si)
122  {
123  si->signal_received = 0;
124  si->signal_text = NULL;
125  si->source = SIG_SOURCE_SOFT;
126  }
127 }
128 
129 void
130 print_signal(const struct signal_info *si, const char *title, int msglevel)
131 {
132  if (si)
133  {
134  const char *type = (si->signal_text ? si->signal_text : "");
135  const char *t = (title ? title : "process");
136  const char *hs = NULL;
137  switch (si->source)
138  {
139  case SIG_SOURCE_SOFT:
140  hs = "soft";
141  break;
142 
143  case SIG_SOURCE_HARD:
144  hs = "hard";
145  break;
146 
148  hs = "connection failed(soft)";
149  break;
150 
151  default:
152  ASSERT(0);
153  }
154 
155  switch (si->signal_received)
156  {
157  case SIGINT:
158  case SIGTERM:
159  msg(msglevel, "%s[%s,%s] received, %s exiting",
160  signal_name(si->signal_received, true), hs, type, t);
161  break;
162 
163  case SIGHUP:
164  case SIGUSR1:
165  msg(msglevel, "%s[%s,%s] received, %s restarting",
166  signal_name(si->signal_received, true), hs, type, t);
167  break;
168 
169  default:
170  msg(msglevel, "Unknown signal %d [%s,%s] received by %s", si->signal_received, hs, type, t);
171  break;
172  }
173  }
174  else
175  {
176  msg(msglevel, "Unknown signal received");
177  }
178 }
179 
180 /*
181  * Call management interface with restart info
182  */
183 void
185 {
186 #ifdef ENABLE_MANAGEMENT
187  if (management)
188  {
189  int state = -1;
190  switch (si->signal_received)
191  {
192  case SIGINT:
193  case SIGTERM:
194  state = OPENVPN_STATE_EXITING;
195  break;
196 
197  case SIGHUP:
198  case SIGUSR1:
200  break;
201  }
202 
203  if (state >= 0)
204  {
206  state,
207  si->signal_text ? si->signal_text : signal_name(si->signal_received, true),
208  NULL,
209  NULL,
210  NULL,
211  NULL);
212  }
213  }
214 #endif /* ifdef ENABLE_MANAGEMENT */
215 }
216 
217 #ifdef HAVE_SIGNAL_H
218 
219 /* normal signal handler, when we are in event loop */
220 static void
221 signal_handler(const int signum)
222 {
223  throw_signal(signum);
224  signal(signum, signal_handler);
225 }
226 
227 #endif
228 
229 /* set handlers for unix signals */
230 
231 #ifdef HAVE_SIGNAL_H
232 #define SM_UNDEF 0
233 #define SM_PRE_INIT 1
234 #define SM_POST_INIT 2
235 static int signal_mode; /* GLOBAL */
236 #endif
237 
238 void
240 {
241 #ifndef _WIN32
242 #ifdef HAVE_SIGNAL_H
243  signal_mode = SM_PRE_INIT;
244  signal(SIGINT, signal_handler);
245  signal(SIGTERM, signal_handler);
246  signal(SIGHUP, SIG_IGN);
247  signal(SIGUSR1, SIG_IGN);
248  signal(SIGUSR2, SIG_IGN);
249  signal(SIGPIPE, SIG_IGN);
250 #endif /* HAVE_SIGNAL_H */
251 #endif /* _WIN32 */
252 }
253 
254 void
256 {
257 #ifndef _WIN32
258 #ifdef HAVE_SIGNAL_H
259  signal_mode = SM_POST_INIT;
260  signal(SIGINT, signal_handler);
261  signal(SIGTERM, signal_handler);
262  signal(SIGHUP, signal_handler);
263  signal(SIGUSR1, signal_handler);
264  signal(SIGUSR2, signal_handler);
265  signal(SIGPIPE, SIG_IGN);
266 #endif /* HAVE_SIGNAL_H */
267 #endif
268 }
269 
270 /* called after daemonization to retain signal settings */
271 void
273 {
274 #ifdef HAVE_SIGNAL_H
275  if (signal_mode == SM_PRE_INIT)
276  {
278  }
279  else if (signal_mode == SM_POST_INIT)
280  {
282  }
283 #endif
284 }
285 
286 /*
287  * Print statistics.
288  *
289  * Triggered by SIGUSR2 or F2 on Windows.
290  */
291 void
292 print_status(const struct context *c, struct status_output *so)
293 {
294  struct gc_arena gc = gc_new();
295 
296  status_reset(so);
297 
298  status_printf(so, "OpenVPN STATISTICS");
299  status_printf(so, "Updated,%s", time_string(0, 0, false, &gc));
300  status_printf(so, "TUN/TAP read bytes," counter_format, c->c2.tun_read_bytes);
301  status_printf(so, "TUN/TAP write bytes," counter_format, c->c2.tun_write_bytes);
302  status_printf(so, "TCP/UDP read bytes," counter_format, c->c2.link_read_bytes);
303  status_printf(so, "TCP/UDP write bytes," counter_format, c->c2.link_write_bytes);
304  status_printf(so, "Auth read bytes," counter_format, c->c2.link_read_bytes_auth);
305 #ifdef USE_COMP
306  if (c->c2.comp_context)
307  {
308  comp_print_stats(c->c2.comp_context, so);
309  }
310 #endif
311 #ifdef PACKET_TRUNCATION_CHECK
312  status_printf(so, "TUN read truncations," counter_format, c->c2.n_trunc_tun_read);
313  status_printf(so, "TUN write truncations," counter_format, c->c2.n_trunc_tun_write);
314  status_printf(so, "Pre-encrypt truncations," counter_format, c->c2.n_trunc_pre_encrypt);
315  status_printf(so, "Post-decrypt truncations," counter_format, c->c2.n_trunc_post_decrypt);
316 #endif
317 #ifdef _WIN32
318  if (tuntap_defined(c->c1.tuntap))
319  {
320  status_printf(so, "TAP-WIN32 driver status,\"%s\"",
321  tap_win_getinfo(c->c1.tuntap, &gc));
322  }
323 #endif
324 
325  status_printf(so, "END");
326  status_flush(so);
327  gc_free(&gc);
328 }
329 
330 #ifdef ENABLE_OCC
331 /*
332  * Handle the triggering and time-wait of explicit
333  * exit notification.
334  */
335 
336 static void
338 {
339  msg(M_INFO, "SIGTERM received, sending exit notification to peer");
342  signal_reset(c->sig);
345 }
346 
347 void
349 {
351  &c->c2.timeval,
352  ETT_DEFAULT))
353  {
356  {
359  c->sig->signal_text = "exit-with-notification";
360  }
361  else
362  {
363  c->c2.occ_op = OCC_EXIT;
364  }
365  }
366 }
367 #endif /* ifdef ENABLE_OCC */
368 
369 /*
370  * Process signals
371  */
372 
373 void
375 {
377  {
379  }
380 }
381 
382 static void
383 process_sigusr2(const struct context *c)
384 {
385  struct status_output *so = status_open(NULL, 0, M_INFO, NULL, 0);
386  print_status(c, so);
387  status_close(so);
388  signal_reset(c->sig);
389 }
390 
391 static bool
393 {
394  bool ret = true;
395 #ifdef ENABLE_OCC
398  {
400  ret = false;
401  }
402 #endif
403  return ret;
404 }
405 
411 static bool
413 {
414  bool ret = false;
415 #ifdef ENABLE_OCC
416  if ( (c->sig->signal_received == SIGUSR1 || c->sig->signal_received == SIGHUP)
418  {
419  if (c->sig->source == SIG_SOURCE_HARD)
420  {
421  msg(M_INFO, "Ignoring %s received during exit notification",
422  signal_name(c->sig->signal_received, true));
423  signal_reset(c->sig);
424  ret = true;
425  }
426  else
427  {
428  msg(M_INFO, "Converting soft %s received during exit notification to SIGTERM",
429  signal_name(c->sig->signal_received, true));
430  register_signal(c, SIGTERM, "exit-with-notification");
431  ret = false;
432  }
433  }
434 #endif
435  return ret;
436 }
437 
438 bool
440 {
441  bool ret = true;
442 
443  if (ignore_restart_signals(c))
444  {
445  ret = false;
446  }
447  else if (c->sig->signal_received == SIGTERM || c->sig->signal_received == SIGINT)
448  {
449  ret = process_sigterm(c);
450  }
451  else if (c->sig->signal_received == SIGUSR2)
452  {
453  process_sigusr2(c);
454  ret = false;
455  }
456  return ret;
457 }
458 
459 void
460 register_signal(struct context *c, int sig, const char *text)
461 {
462  if (c->sig->signal_received != SIGTERM)
463  {
464  c->sig->signal_received = sig;
465  }
466  c->sig->signal_text = text;
467 }
struct signal_info siginfo_static
Definition: sig.c:46
void print_signal(const struct signal_info *si, const char *title, int msglevel)
Definition: sig.c:130
counter_type tun_read_bytes
Definition: openvpn.h:281
#define ETT_DEFAULT
Definition: interval.h:213
const char * signal_description(const int signum, const char *sigtext)
Definition: sig.c:91
static void halt_non_edge_triggered_signals(void)
Definition: sig.h:98
struct options options
Options loaded from command line or configuration file.
Definition: openvpn.h:502
counter_type link_write_bytes
Definition: openvpn.h:285
#define OCC_EXIT
Definition: occ.h:69
const char * upper
Definition: sig.c:50
#define M_INFO
Definition: errlevel.h:55
Contains all state information for one tunnel.
Definition: openvpn.h:500
#define SIZE(x)
Definition: basic.h:30
void throw_signal_soft(const int signum, const char *signal_text)
Definition: sig.c:111
void remap_signal(struct context *c)
Definition: sig.c:374
static void gc_free(struct gc_arena *a)
Definition: buffer.h:1023
#define ASSERT(x)
Definition: error.h:221
#define SIGUSR1
Definition: config-msvc.h:116
int value
Definition: sig.c:49
static bool process_sigterm(struct context *c)
Definition: sig.c:392
static void event_timeout_clear(struct event_timeout *et)
Definition: interval.h:150
struct signal_info * sig
Internal error signaling object.
Definition: openvpn.h:525
void post_init_signal_catch(void)
Definition: sig.c:255
#define SIGTERM
Definition: config-msvc.h:118
#define SIGHUP
Definition: config-msvc.h:114
struct tuntap * tuntap
Tun/tap virtual network interface.
Definition: openvpn.h:167
int explicit_exit_notification
Definition: options.h:121
const char * tap_win_getinfo(const struct tuntap *tt, struct gc_arena *gc)
Definition: tun.c:6036
static bool tuntap_defined(const struct tuntap *tt)
Definition: tun.h:198
void status_printf(struct status_output *so, const char *format,...)
Definition: status.c:239
void restore_signal_state(void)
Definition: sig.c:272
void status_flush(struct status_output *so)
Definition: status.c:172
struct status_output * status_open(const char *filename, const int refresh_freq, const int msglevel, const struct virtual_output *vout, const unsigned int flags)
Definition: status.c:63
time_t explicit_exit_notification_time_wait
Definition: openvpn.h:422
int remap_sigusr1
Definition: options.h:305
bool status_close(struct status_output *so)
Definition: status.c:203
struct context_1 c1
Level 1 context.
Definition: openvpn.h:538
void pre_init_signal_catch(void)
Definition: sig.c:239
const char * signal_name(const int sig, const bool upper)
Definition: sig.c:77
static void process_sigusr2(const struct context *c)
Definition: sig.c:383
counter_type tun_write_bytes
Definition: openvpn.h:282
bool event_timeout_trigger(struct event_timeout *et, struct timeval *tv, const int et_const_retry)
Definition: interval.c:45
counter_type link_read_bytes
Definition: openvpn.h:283
#define counter_format
Definition: common.h:39
static struct gc_arena gc_new(void)
Definition: buffer.h:1015
time_t now
Definition: otime.c:36
static void signal_reset(struct signal_info *si)
Definition: sig.c:119
void process_explicit_exit_notification_timer_wakeup(struct context *c)
Definition: sig.c:348
static bool event_timeout_defined(const struct event_timeout *et)
Definition: interval.h:144
struct timeval timeval
Definition: openvpn.h:401
const char * time_string(time_t t, int usec, bool show_usec, struct gc_arena *gc)
Definition: otime.c:114
const char * lower
Definition: sig.c:51
#define SIG_SOURCE_HARD
Definition: sig.h:33
static bool ignore_restart_signals(struct context *c)
If a restart signal is received during exit-notification, reset the signal and return true...
Definition: sig.c:412
void reset_coarse_timers(struct context *c)
Definition: init.c:1305
struct connection_entry ce
Definition: options.h:213
struct context_2 c2
Level 2 context.
Definition: openvpn.h:539
void print_status(const struct context *c, struct status_output *so)
Definition: sig.c:292
static const struct signame signames[]
Definition: sig.c:54
volatile int source
Definition: sig.h:46
bool process_signal(struct context *c)
Definition: sig.c:439
void signal_restart_status(const struct signal_info *si)
Definition: sig.c:184
#define SIG_SOURCE_SOFT
Definition: sig.h:32
#define SIG_SOURCE_CONNECTION_FAILED
Definition: sig.h:37
#define OPENVPN_STATE_RECONNECTING
Definition: manage.h:487
int parse_signal(const char *signame)
Definition: sig.c:63
#define SIGINT
Definition: config-msvc.h:115
volatile int signal_received
Definition: sig.h:45
#define SIGUSR2
Definition: config-msvc.h:117
void register_signal(struct context *c, int sig, const char *text)
Definition: sig.c:460
#define msg
Definition: error.h:173
struct event_timeout explicit_exit_notification_interval
Definition: openvpn.h:423
void management_set_state(struct management *man, const int state, const char *detail, const in_addr_t *tun_local_ip, const struct in6_addr *tun_local_ip6, const struct openvpn_sockaddr *local, const struct openvpn_sockaddr *remote)
Definition: manage.c:2663
#define OPENVPN_STATE_EXITING
Definition: manage.h:488
void throw_signal(const int signum)
Definition: sig.c:104
Garbage collection arena used to keep track of dynamically allocated memory.
Definition: buffer.h:116
static void process_explicit_exit_notification_init(struct context *c)
Definition: sig.c:337
Definition: sig.c:48
int occ_op
Definition: openvpn.h:310
const char * signal_text
Definition: sig.h:47
void status_reset(struct status_output *so)
Definition: status.c:163
static void event_timeout_init(struct event_timeout *et, interval_t n, const time_t local_now)
Definition: interval.h:166
counter_type link_read_bytes_auth
Definition: openvpn.h:284