2014-07-21 05:22:06 +02:00
|
|
|
// OpenVPN -- An application to securely tunnel IP networks
|
|
|
|
// over a single port, with support for SSL/TLS-based
|
|
|
|
// session authentication and key exchange,
|
|
|
|
// packet encryption, packet authentication, and
|
|
|
|
// packet compression.
|
2012-08-24 23:13:42 +02:00
|
|
|
//
|
2015-01-06 20:56:21 +01:00
|
|
|
// Copyright (C) 2012-2015 OpenVPN Technologies, Inc.
|
2012-08-24 23:13:42 +02:00
|
|
|
//
|
2014-07-21 05:22:06 +02:00
|
|
|
// This program is free software: you can redistribute it and/or modify
|
|
|
|
// it under the terms of the GNU Affero General Public License Version 3
|
|
|
|
// as published by the Free Software Foundation.
|
2012-08-24 23:13:42 +02:00
|
|
|
//
|
2014-07-21 05:22:06 +02:00
|
|
|
// This program is distributed in the hope that it will be useful,
|
|
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
// GNU Affero General Public License for more details.
|
|
|
|
//
|
|
|
|
// You should have received a copy of the GNU Affero General Public License
|
|
|
|
// along with this program in the COPYING file.
|
|
|
|
// If not, see <http://www.gnu.org/licenses/>.
|
2012-08-24 23:13:42 +02:00
|
|
|
|
2011-09-25 00:51:28 +02:00
|
|
|
#ifndef OPENVPN_COMMON_SIGNAL_H
|
|
|
|
#define OPENVPN_COMMON_SIGNAL_H
|
|
|
|
|
2014-02-08 05:46:56 +01:00
|
|
|
#include <openvpn/common/platform.hpp>
|
|
|
|
|
|
|
|
#if !defined(OPENVPN_PLATFORM_WIN)
|
|
|
|
|
2012-11-26 02:51:24 +01:00
|
|
|
#include <signal.h>
|
2011-09-25 00:51:28 +02:00
|
|
|
|
2015-05-17 21:27:34 +02:00
|
|
|
#include <openvpn/common/size.hpp>
|
2012-11-26 02:51:24 +01:00
|
|
|
#include <openvpn/common/exception.hpp>
|
2012-01-25 09:32:27 +01:00
|
|
|
|
2011-09-25 00:51:28 +02:00
|
|
|
namespace openvpn {
|
2012-11-26 02:51:24 +01:00
|
|
|
class Signal
|
2011-09-25 00:51:28 +02:00
|
|
|
{
|
|
|
|
public:
|
2012-11-26 02:51:24 +01:00
|
|
|
OPENVPN_SIMPLE_EXCEPTION(signal_error);
|
2012-02-14 00:11:37 +01:00
|
|
|
|
2012-11-26 02:51:24 +01:00
|
|
|
typedef void (*handler_t)(int signum);
|
2011-09-25 00:51:28 +02:00
|
|
|
|
2011-10-08 08:20:49 +02:00
|
|
|
enum {
|
2012-11-26 02:51:24 +01:00
|
|
|
F_SIGINT = (1<<0),
|
|
|
|
F_SIGTERM = (1<<1),
|
|
|
|
F_SIGHUP = (1<<2),
|
2014-03-24 23:53:19 +01:00
|
|
|
F_SIGUSR1 = (1<<3),
|
|
|
|
F_SIGUSR2 = (1<<4),
|
2011-10-08 08:20:49 +02:00
|
|
|
};
|
|
|
|
|
2012-11-26 02:51:24 +01:00
|
|
|
Signal(const handler_t handler, const unsigned int flags)
|
2011-09-25 00:51:28 +02:00
|
|
|
{
|
2012-11-26 02:51:24 +01:00
|
|
|
struct sigaction sa;
|
|
|
|
sa.sa_handler = handler;
|
|
|
|
sigemptyset(&sa.sa_mask);
|
|
|
|
sa.sa_flags = SA_RESTART; // restart functions if interrupted by handler
|
|
|
|
sigconf(sa, flags_ = flags);
|
2011-09-25 00:51:28 +02:00
|
|
|
}
|
|
|
|
|
2012-11-26 02:51:24 +01:00
|
|
|
~Signal()
|
2012-01-02 02:58:00 +01:00
|
|
|
{
|
2012-11-26 02:51:24 +01:00
|
|
|
struct sigaction sa;
|
|
|
|
sa.sa_handler = SIG_DFL;
|
|
|
|
sigemptyset(&sa.sa_mask);
|
|
|
|
sa.sa_flags = 0;
|
|
|
|
sigconf(sa, flags_);
|
2012-01-02 02:58:00 +01:00
|
|
|
}
|
|
|
|
|
2012-02-14 00:11:37 +01:00
|
|
|
private:
|
2012-11-26 02:51:24 +01:00
|
|
|
static void sigconf(struct sigaction& sa, const unsigned int flags)
|
|
|
|
{
|
|
|
|
if (flags & F_SIGINT)
|
|
|
|
sigact(sa, SIGINT);
|
|
|
|
if (flags & F_SIGTERM)
|
|
|
|
sigact(sa, SIGTERM);
|
|
|
|
if (flags & F_SIGHUP)
|
|
|
|
sigact(sa, SIGHUP);
|
2014-03-24 23:53:19 +01:00
|
|
|
if (flags & F_SIGUSR1)
|
|
|
|
sigact(sa, SIGUSR1);
|
|
|
|
if (flags & F_SIGUSR2)
|
|
|
|
sigact(sa, SIGUSR2);
|
2012-11-26 02:51:24 +01:00
|
|
|
}
|
2011-09-25 00:51:28 +02:00
|
|
|
|
2012-11-26 02:51:24 +01:00
|
|
|
static void sigact(struct sigaction& sa, const int sig)
|
|
|
|
{
|
2015-05-17 10:53:37 +02:00
|
|
|
if (sigaction(sig, &sa, nullptr) == -1)
|
2012-11-26 02:51:24 +01:00
|
|
|
throw signal_error();
|
|
|
|
}
|
2011-09-25 00:51:28 +02:00
|
|
|
|
2012-11-26 02:51:24 +01:00
|
|
|
unsigned int flags_;
|
|
|
|
};
|
2014-08-18 06:35:51 +02:00
|
|
|
|
|
|
|
// Like Asio posix_signal_blocker, but only block certain signals
|
2015-04-23 23:10:43 +02:00
|
|
|
class SignalBlocker
|
2014-08-18 06:35:51 +02:00
|
|
|
{
|
2015-04-23 23:10:43 +02:00
|
|
|
SignalBlocker(const SignalBlocker&) = delete;
|
|
|
|
SignalBlocker& operator=(const SignalBlocker&) = delete;
|
|
|
|
|
2014-08-18 06:35:51 +02:00
|
|
|
public:
|
|
|
|
SignalBlocker(const unsigned int flags) // use signal mask from class Signal
|
|
|
|
: blocked_(false)
|
|
|
|
{
|
|
|
|
sigset_t new_mask;
|
|
|
|
sigemptyset(&new_mask);
|
|
|
|
if (flags & Signal::F_SIGINT)
|
|
|
|
sigaddset(&new_mask, SIGINT);
|
|
|
|
if (flags & Signal::F_SIGTERM)
|
|
|
|
sigaddset(&new_mask, SIGTERM);
|
|
|
|
if (flags & Signal::F_SIGHUP)
|
|
|
|
sigaddset(&new_mask, SIGHUP);
|
|
|
|
if (flags & Signal::F_SIGUSR1)
|
|
|
|
sigaddset(&new_mask, SIGUSR1);
|
|
|
|
if (flags & Signal::F_SIGUSR2)
|
|
|
|
sigaddset(&new_mask, SIGUSR2);
|
|
|
|
blocked_ = (pthread_sigmask(SIG_BLOCK, &new_mask, &old_mask_) == 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Destructor restores the previous signal mask.
|
|
|
|
~SignalBlocker()
|
|
|
|
{
|
|
|
|
if (blocked_)
|
|
|
|
pthread_sigmask(SIG_SETMASK, &old_mask_, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
// Have signals been blocked.
|
|
|
|
bool blocked_;
|
|
|
|
|
|
|
|
// The previous signal mask.
|
|
|
|
sigset_t old_mask_;
|
|
|
|
};
|
2015-03-19 20:58:31 +01:00
|
|
|
|
|
|
|
// Like SignalBlocker, but block specific signals in default constructor
|
|
|
|
struct SignalBlockerDefault : public SignalBlocker
|
|
|
|
{
|
|
|
|
SignalBlockerDefault()
|
|
|
|
: SignalBlocker( // these signals should be handled by parent thread
|
|
|
|
Signal::F_SIGINT|
|
|
|
|
Signal::F_SIGTERM|
|
|
|
|
Signal::F_SIGHUP|
|
|
|
|
Signal::F_SIGUSR1|
|
|
|
|
Signal::F_SIGUSR2)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
};
|
2012-11-26 02:51:24 +01:00
|
|
|
}
|
|
|
|
#endif
|
2014-02-08 05:46:56 +01:00
|
|
|
#endif
|