Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 369 lines (330 sloc) 8.955 kB
93e359e import of openvpn source tree.
Friedrich Schaeuffelhut authored
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 *
0a99d82 @Kali- openvpn update to 2.1.3
Kali- authored
8 * Copyright (C) 2002-2010 OpenVPN Technologies, Inc. <sales@openvpn.net>
93e359e import of openvpn source tree.
Friedrich Schaeuffelhut authored
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
25 #include "syshead.h"
26
27 #include "buffer.h"
28 #include "error.h"
29 #include "win32.h"
30 #include "init.h"
31 #include "status.h"
32 #include "sig.h"
33 #include "occ.h"
34 #include "manage.h"
35 #include "openvpn.h"
36
37 #include "memdbg.h"
38
39 /* Handle signals */
40
41 struct signal_info siginfo_static; /* GLOBAL */
42
43 struct signame {
44 int value;
45 const char *upper;
46 const char *lower;
47 };
48
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" }
55 };
56
57 int
58 parse_signal (const char *signame)
59 {
60 int i;
61 for (i = 0; i < (int)SIZE (signames); ++i)
62 {
63 if (!strcmp (signame, signames[i].upper))
64 return signames[i].value;
65 }
66 return -1;
67 }
68
69 const char *
70 signal_name (const int sig, const bool upper)
71 {
72 int i;
73 for (i = 0; i < (int)SIZE (signames); ++i)
74 {
75 if (sig == signames[i].value)
76 return upper ? signames[i].upper : signames[i].lower;
77 }
78 return "UNKNOWN";
79 }
80
81 const char *
82 signal_description (const int signum, const char *sigtext)
83 {
84 if (sigtext)
85 return sigtext;
86 else
87 return signal_name (signum, false);
88 }
89
90 void
91 throw_signal (const int signum)
92 {
93 siginfo_static.signal_received = signum;
94 siginfo_static.hard = true;
95 }
96
97 void
98 throw_signal_soft (const int signum, const char *signal_text)
99 {
100 siginfo_static.signal_received = signum;
101 siginfo_static.hard = false;
102 siginfo_static.signal_text = signal_text;
103 }
104
105 static void
106 signal_reset (struct signal_info *si)
107 {
108 if (si)
109 {
110 si->signal_received = 0;
111 si->signal_text = NULL;
112 si->hard = false;
113 }
114 }
115
116 void
117 print_signal (const struct signal_info *si, const char *title, int msglevel)
118 {
119 if (si)
120 {
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");
124
125 switch (si->signal_received)
126 {
127 case SIGINT:
128 case SIGTERM:
129 msg (msglevel, "%s[%s,%s] received, %s exiting",
130 signal_name (si->signal_received, true), hs, type, t);
131 break;
132 case SIGHUP:
133 case SIGUSR1:
134 msg (msglevel, "%s[%s,%s] received, %s restarting",
135 signal_name (si->signal_received, true), hs, type, t);
136 break;
137 default:
138 msg (msglevel, "Unknown signal %d [%s,%s] received by %s", si->signal_received, hs, type, t);
139 break;
140 }
141 }
142 else
143 msg (msglevel, "Unknown signal received");
144 }
145
146 /*
147 * Call management interface with restart info
148 */
149 void
150 signal_restart_status (const struct signal_info *si)
151 {
152 #ifdef ENABLE_MANAGEMENT
153 if (management)
154 {
155 int state = -1;
156 switch (si->signal_received)
157 {
158 case SIGINT:
159 case SIGTERM:
160 state = OPENVPN_STATE_EXITING;
161 break;
162 case SIGHUP:
163 case SIGUSR1:
164 state = OPENVPN_STATE_RECONNECTING;
165 break;
166 }
167
168 if (state >= 0)
169 management_set_state (management,
170 state,
171 si->signal_text ? si->signal_text : signal_name (si->signal_received, true),
172 (in_addr_t)0,
173 (in_addr_t)0);
174 }
175 #endif
176 }
177
178 #ifdef HAVE_SIGNAL_H
179
180 /* normal signal handler, when we are in event loop */
181 static void
182 signal_handler (const int signum)
183 {
184 throw_signal (signum);
185 signal (signum, signal_handler);
186 }
187
188 #endif
189
190 /* set handlers for unix signals */
191
192 #ifdef HAVE_SIGNAL_H
193 #define SM_UNDEF 0
194 #define SM_PRE_INIT 1
195 #define SM_POST_INIT 2
196 static int signal_mode; /* GLOBAL */
197 #endif
198
199 void
200 pre_init_signal_catch (void)
201 {
202 #ifdef HAVE_SIGNAL_H
203 signal_mode = SM_PRE_INIT;
204 signal (SIGINT, signal_handler);
205 signal (SIGTERM, signal_handler);
206 signal (SIGHUP, SIG_IGN);
207 signal (SIGUSR1, SIG_IGN);
208 signal (SIGUSR2, SIG_IGN);
209 signal (SIGPIPE, SIG_IGN);
210 #endif /* HAVE_SIGNAL_H */
211 }
212
213 void
214 post_init_signal_catch (void)
215 {
216 #ifdef HAVE_SIGNAL_H
217 signal_mode = SM_POST_INIT;
218 signal (SIGINT, signal_handler);
219 signal (SIGTERM, signal_handler);
220 signal (SIGHUP, signal_handler);
221 signal (SIGUSR1, signal_handler);
222 signal (SIGUSR2, signal_handler);
223 signal (SIGPIPE, SIG_IGN);
224 #endif /* HAVE_SIGNAL_H */
225 }
226
227 /* called after daemonization to retain signal settings */
228 void
229 restore_signal_state (void)
230 {
231 #ifdef HAVE_SIGNAL_H
232 if (signal_mode == SM_PRE_INIT)
233 pre_init_signal_catch ();
234 else if (signal_mode == SM_POST_INIT)
235 post_init_signal_catch ();
236 #endif
237 }
238
239 /*
240 * Print statistics.
241 *
242 * Triggered by SIGUSR2 or F2 on Windows.
243 */
244 void
245 print_status (const struct context *c, struct status_output *so)
246 {
247 struct gc_arena gc = gc_new ();
248
249 status_reset (so);
250
0a99d82 @Kali- openvpn update to 2.1.3
Kali- authored
251 status_printf (so, "OpenVPN STATISTICS");
93e359e import of openvpn source tree.
Friedrich Schaeuffelhut authored
252 status_printf (so, "Updated,%s", time_string (0, 0, false, &gc));
253 status_printf (so, "TUN/TAP read bytes," counter_format, c->c2.tun_read_bytes);
254 status_printf (so, "TUN/TAP write bytes," counter_format, c->c2.tun_write_bytes);
255 status_printf (so, "TCP/UDP read bytes," counter_format, c->c2.link_read_bytes);
256 status_printf (so, "TCP/UDP write bytes," counter_format, c->c2.link_write_bytes);
257 status_printf (so, "Auth read bytes," counter_format, c->c2.link_read_bytes_auth);
258 #ifdef USE_LZO
259 if (lzo_defined (&c->c2.lzo_compwork))
260 lzo_print_stats (&c->c2.lzo_compwork, so);
261 #endif
262 #ifdef PACKET_TRUNCATION_CHECK
263 status_printf (so, "TUN read truncations," counter_format, c->c2.n_trunc_tun_read);
264 status_printf (so, "TUN write truncations," counter_format, c->c2.n_trunc_tun_write);
265 status_printf (so, "Pre-encrypt truncations," counter_format, c->c2.n_trunc_pre_encrypt);
266 status_printf (so, "Post-decrypt truncations," counter_format, c->c2.n_trunc_post_decrypt);
267 #endif
268 #ifdef WIN32
269 if (tuntap_defined (c->c1.tuntap))
270 status_printf (so, "TAP-WIN32 driver status,\"%s\"",
271 tap_win32_getinfo (c->c1.tuntap, &gc));
272 #endif
273
274 status_printf (so, "END");
275 status_flush (so);
276 gc_free (&gc);
277 }
278
279 #ifdef ENABLE_OCC
280 /*
281 * Handle the triggering and time-wait of explicit
282 * exit notification.
283 */
284
285 static void
286 process_explicit_exit_notification_init (struct context *c)
287 {
288 msg (M_INFO, "SIGTERM received, sending exit notification to peer");
289 event_timeout_init (&c->c2.explicit_exit_notification_interval, 1, 0);
290 reset_coarse_timers (c);
291 signal_reset (c->sig);
292 halt_non_edge_triggered_signals ();
293 c->c2.explicit_exit_notification_time_wait = now;
294 }
295
296 void
297 process_explicit_exit_notification_timer_wakeup (struct context *c)
298 {
299 if (event_timeout_trigger (&c->c2.explicit_exit_notification_interval,
300 &c->c2.timeval,
301 ETT_DEFAULT))
302 {
303 ASSERT (c->c2.explicit_exit_notification_time_wait && c->options.explicit_exit_notification);
304 if (now >= c->c2.explicit_exit_notification_time_wait + c->options.explicit_exit_notification)
305 {
306 event_timeout_clear (&c->c2.explicit_exit_notification_interval);
307 c->sig->signal_received = SIGTERM;
308 c->sig->signal_text = "exit-with-notification";
309 }
310 else
311 {
312 c->c2.occ_op = OCC_EXIT;
313 }
314 }
315 }
316 #endif
317
318 /*
319 * Process signals
320 */
321
322 void
323 remap_signal (struct context *c)
324 {
325 if (c->sig->signal_received == SIGUSR1 && c->options.remap_sigusr1)
326 c->sig->signal_received = c->options.remap_sigusr1;
327 }
328
329 static void
330 process_sigusr2 (const struct context *c)
331 {
332 struct status_output *so = status_open (NULL, 0, M_INFO, NULL, 0);
333 print_status (c, so);
334 status_close (so);
335 signal_reset (c->sig);
336 }
337
338 static bool
339 process_sigterm (struct context *c)
340 {
341 bool ret = true;
342 #ifdef ENABLE_OCC
343 if (c->options.explicit_exit_notification
344 && !c->c2.explicit_exit_notification_time_wait)
345 {
346 process_explicit_exit_notification_init (c);
347 ret = false;
348 }
349 #endif
350 return ret;
351 }
352
353 bool
354 process_signal (struct context *c)
355 {
356 bool ret = true;
357
358 if (c->sig->signal_received == SIGTERM || c->sig->signal_received == SIGINT)
359 {
360 ret = process_sigterm (c);
361 }
362 else if (c->sig->signal_received == SIGUSR2)
363 {
364 process_sigusr2 (c);
365 ret = false;
366 }
367 return ret;
368 }
Something went wrong with that request. Please try again.