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
8 * Copyright (C) 2002-2009 OpenVPN Technologies, Inc. <sales@openvpn.net>
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.
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.
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
41 struct signal_info siginfo_static
; /* GLOBAL */
49 static const struct signame signames
[] = {
50 { SIGINT
, "SIGINT", "sigint"},
51 { SIGTERM
, "SIGTERM", "sigterm" },
52 { SIGHUP
, "SIGHUP", "sighup" },
53 { SIGUSR1
, "SIGUSR1", "sigusr1" },
54 { SIGUSR2
, "SIGUSR2", "sigusr2" }
58 parse_signal (const char *signame
)
61 for (i
= 0; i
< (int)SIZE (signames
); ++i
)
63 if (!strcmp (signame
, signames
[i
].upper
))
64 return signames
[i
].value
;
70 signal_name (const int sig
, const bool upper
)
73 for (i
= 0; i
< (int)SIZE (signames
); ++i
)
75 if (sig
== signames
[i
].value
)
76 return upper
? signames
[i
].upper
: signames
[i
].lower
;
82 signal_description (const int signum
, const char *sigtext
)
87 return signal_name (signum
, false);
91 throw_signal (const int signum
)
93 siginfo_static
.signal_received
= signum
;
94 siginfo_static
.hard
= true;
98 throw_signal_soft (const int signum
, const char *signal_text
)
100 siginfo_static
.signal_received
= signum
;
101 siginfo_static
.hard
= false;
102 siginfo_static
.signal_text
= signal_text
;
106 signal_reset (struct signal_info
*si
)
110 si
->signal_received
= 0;
111 si
->signal_text
= NULL
;
117 print_signal (const struct signal_info
*si
, const char *title
, int msglevel
)
121 const char *hs
= (si
->hard
? "hard" : "soft");
122 const char *type
= (si
->signal_text
? si
->signal_text
: "");
123 const char *t
= (title
? title
: "process");
125 switch (si
->signal_received
)
129 msg (msglevel
, "%s[%s,%s] received, %s exiting",
130 signal_name (si
->signal_received
, true), hs
, type
, t
);
134 msg (msglevel
, "%s[%s,%s] received, %s restarting",
135 signal_name (si
->signal_received
, true), hs
, type
, t
);
138 msg (msglevel
, "Unknown signal %d [%s,%s] received by %s", si
->signal_received
, hs
, type
, t
);
143 msg (msglevel
, "Unknown signal received");
147 * Call management interface with restart info
150 signal_restart_status (const struct signal_info
*si
)
152 #ifdef ENABLE_MANAGEMENT
156 switch (si
->signal_received
)
160 state
= OPENVPN_STATE_EXITING
;
164 state
= OPENVPN_STATE_RECONNECTING
;
169 management_set_state (management
,
171 si
->signal_text
? si
->signal_text
: signal_name (si
->signal_received
, true),
180 /* normal signal handler, when we are in event loop */
182 signal_handler (const int signum
)
184 throw_signal (signum
);
185 signal (signum
, signal_handler
);
188 /* temporary signal handler, before we are fully initialized */
190 signal_handler_exit (const int signum
)
193 "Signal %d (%s) received during initialization, exiting",
194 signum
, signal_description (signum
, NULL
));
199 /* set handlers for unix signals */
203 #define SM_PRE_INIT 1
204 #define SM_POST_INIT 2
205 static int signal_mode
; /* GLOBAL */
209 pre_init_signal_catch (void)
212 signal_mode
= SM_PRE_INIT
;
213 signal (SIGINT
, signal_handler
);
214 signal (SIGTERM
, signal_handler
);
215 signal (SIGHUP
, SIG_IGN
);
216 signal (SIGUSR1
, SIG_IGN
);
217 signal (SIGUSR2
, SIG_IGN
);
218 signal (SIGPIPE
, SIG_IGN
);
219 #endif /* HAVE_SIGNAL_H */
223 post_init_signal_catch (void)
226 signal_mode
= SM_POST_INIT
;
227 signal (SIGINT
, signal_handler
);
228 signal (SIGTERM
, signal_handler
);
229 signal (SIGHUP
, signal_handler
);
230 signal (SIGUSR1
, signal_handler
);
231 signal (SIGUSR2
, signal_handler
);
232 signal (SIGPIPE
, SIG_IGN
);
233 #endif /* HAVE_SIGNAL_H */
236 /* called after daemonization to retain signal settings */
238 restore_signal_state (void)
241 if (signal_mode
== SM_PRE_INIT
)
242 pre_init_signal_catch ();
243 else if (signal_mode
== SM_POST_INIT
)
244 post_init_signal_catch ();
251 * Triggered by SIGUSR2 or F2 on Windows.
254 print_status (const struct context
*c
, struct status_output
*so
)
256 struct gc_arena gc
= gc_new ();
260 status_printf (so
, PACKAGE_NAME
" STATISTICS");
261 status_printf (so
, "Updated,%s", time_string (0, 0, false, &gc
));
262 status_printf (so
, "TUN/TAP read bytes," counter_format
, c
->c2
.tun_read_bytes
);
263 status_printf (so
, "TUN/TAP write bytes," counter_format
, c
->c2
.tun_write_bytes
);
264 status_printf (so
, "TCP/UDP read bytes," counter_format
, c
->c2
.link_read_bytes
);
265 status_printf (so
, "TCP/UDP write bytes," counter_format
, c
->c2
.link_write_bytes
);
266 status_printf (so
, "Auth read bytes," counter_format
, c
->c2
.link_read_bytes_auth
);
268 if (lzo_defined (&c
->c2
.lzo_compwork
))
269 lzo_print_stats (&c
->c2
.lzo_compwork
, so
);
271 #ifdef PACKET_TRUNCATION_CHECK
272 status_printf (so
, "TUN read truncations," counter_format
, c
->c2
.n_trunc_tun_read
);
273 status_printf (so
, "TUN write truncations," counter_format
, c
->c2
.n_trunc_tun_write
);
274 status_printf (so
, "Pre-encrypt truncations," counter_format
, c
->c2
.n_trunc_pre_encrypt
);
275 status_printf (so
, "Post-decrypt truncations," counter_format
, c
->c2
.n_trunc_post_decrypt
);
278 if (tuntap_defined (c
->c1
.tuntap
))
279 status_printf (so
, "TAP-WIN32 driver status,\"%s\"",
280 tap_win32_getinfo (c
->c1
.tuntap
, &gc
));
283 status_printf (so
, "END");
290 * Handle the triggering and time-wait of explicit
295 process_explicit_exit_notification_init (struct context
*c
)
297 msg (M_INFO
, "SIGTERM received, sending exit notification to peer");
298 event_timeout_init (&c
->c2
.explicit_exit_notification_interval
, 1, 0);
299 reset_coarse_timers (c
);
300 signal_reset (c
->sig
);
301 halt_non_edge_triggered_signals ();
302 c
->c2
.explicit_exit_notification_time_wait
= now
;
306 process_explicit_exit_notification_timer_wakeup (struct context
*c
)
308 if (event_timeout_trigger (&c
->c2
.explicit_exit_notification_interval
,
312 ASSERT (c
->c2
.explicit_exit_notification_time_wait
&& c
->options
.explicit_exit_notification
);
313 if (now
>= c
->c2
.explicit_exit_notification_time_wait
+ c
->options
.explicit_exit_notification
)
315 event_timeout_clear (&c
->c2
.explicit_exit_notification_interval
);
316 c
->sig
->signal_received
= SIGTERM
;
317 c
->sig
->signal_text
= "exit-with-notification";
321 c
->c2
.occ_op
= OCC_EXIT
;
332 remap_signal (struct context
*c
)
334 if (c
->sig
->signal_received
== SIGUSR1
&& c
->options
.remap_sigusr1
)
335 c
->sig
->signal_received
= c
->options
.remap_sigusr1
;
339 process_sigusr2 (const struct context
*c
)
341 struct status_output
*so
= c
->c1
.status_output
? c
->c1
.status_output
: status_open (NULL
, 0, M_INFO
, NULL
, 0);
342 print_status (c
, so
);
343 if (so
!= c
->c1
.status_output
) status_close (so
);
344 signal_reset (c
->sig
);
348 process_sigterm (struct context
*c
)
352 if (c
->options
.explicit_exit_notification
353 && !c
->c2
.explicit_exit_notification_time_wait
)
355 process_explicit_exit_notification_init (c
);
363 process_signal (struct context
*c
)
367 if (c
->sig
->signal_received
== SIGTERM
|| c
->sig
->signal_received
== SIGINT
)
369 ret
= process_sigterm (c
);
371 else if (c
->sig
->signal_received
== SIGUSR2
)