1 /*
2 * tcpproxy
3 *
4 * tcpproxy is a simple tcp connection proxy which combines the
5 * features of rinetd and 6tunnel. tcpproxy supports IPv4 and
6 * IPv6 and also supports connections from IPv6 to IPv4
7 * endpoints and vice versa.
8 *
9 *
10 * Copyright (C) 2010-2015 Christian Pointner <equinox@spreadspace.org>
11 *
12 * This file is part of tcpproxy.
13 *
14 * tcpproxy is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation, either version 3 of the License, or
17 * any later version.
18 *
19 * tcpproxy is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with tcpproxy. If not, see <http://www.gnu.org/licenses/>.
26 */
27
28 #include "datatypes.h"
29
30 #include "log.h"
31 #include "sig_handler.h"
32
33 #include <signal.h>
34 #include <unistd.h>
35 #include <fcntl.h>
36 #include <errno.h>
37 #include <string.h>
38
39 static int sig_pipe_fds[2];
40
sig_handler(int sig)41 static void sig_handler(int sig)
42 {
43 sigset_t set;
44 int ret = read(sig_pipe_fds[0], &set, sizeof(sigset_t));
45 if(ret != sizeof(sigset_t))
46 sigemptyset(&set);
47
48 sigaddset(&set, sig);
49 ret = write(sig_pipe_fds[1], &set, sizeof(sigset_t));
50 }
51
52
signal_init()53 int signal_init()
54 {
55 if(pipe(sig_pipe_fds)) {
56 log_printf(ERROR, "signal handling init failed (pipe error: %s)", strerror(errno));
57 return -1;
58 }
59
60 int i;
61 for(i=0; i<2; ++i) {
62 int fd_flags = fcntl(sig_pipe_fds[i], F_GETFL);
63 if(fd_flags == -1) {
64 log_printf(ERROR, "signal handling init failed (pipe fd[%d] read flags error: %s)", i, strerror(errno));
65 return -1;
66 }
67 if(fcntl(sig_pipe_fds[i], F_SETFL, fd_flags | O_NONBLOCK) == -1){
68 log_printf(ERROR, "signal handling init failed (pipe fd[%d] write flags error: %s)", i, strerror(errno));
69 return -1;
70 }
71 }
72
73 struct sigaction act, act_ign;
74 act.sa_handler = sig_handler;
75 sigfillset(&act.sa_mask);
76 act.sa_flags = 0;
77 act_ign.sa_handler = SIG_IGN;
78 sigfillset(&act_ign.sa_mask);
79 act_ign.sa_flags = 0;
80
81 if((sigaction(SIGINT, &act, NULL) < 0) ||
82 (sigaction(SIGQUIT, &act, NULL) < 0) ||
83 (sigaction(SIGTERM, &act, NULL) < 0) ||
84 (sigaction(SIGHUP, &act, NULL) < 0) ||
85 (sigaction(SIGUSR1, &act, NULL) < 0) ||
86 (sigaction(SIGUSR2, &act, NULL) < 0) ||
87 (sigaction(SIGPIPE, &act_ign, NULL) < 0)) {
88
89 log_printf(ERROR, "signal handling init failed (sigaction error: %s)", strerror(errno));
90 close(sig_pipe_fds[0]);
91 close(sig_pipe_fds[1]);
92 }
93
94 return sig_pipe_fds[0];
95 }
96
signal_handle()97 int signal_handle()
98 {
99 sigset_t set, oldset, tmpset;
100
101 sigemptyset(&tmpset);
102 sigaddset(&tmpset, SIGINT);
103 sigaddset(&tmpset, SIGQUIT);
104 sigaddset(&tmpset, SIGTERM);
105 sigaddset(&tmpset, SIGHUP);
106 sigaddset(&tmpset, SIGUSR1);
107 sigaddset(&tmpset, SIGUSR2);
108 sigprocmask(SIG_BLOCK, &tmpset, &oldset);
109
110 int ret = read(sig_pipe_fds[0], &set, sizeof(sigset_t));
111 if(ret != sizeof(sigset_t))
112 sigemptyset(&set);
113
114 int return_value = 0;
115 int sig;
116 for(sig=1; sig < NSIG; ++sig) {
117 if(sigismember(&set, sig)) {
118 switch(sig) {
119 case SIGINT: log_printf(NOTICE, "SIG-Int caught, exitting"); return_value = SIGINT; break;
120 case SIGQUIT: log_printf(NOTICE, "SIG-Quit caught, exitting"); return_value = SIGQUIT; break;
121 case SIGTERM: log_printf(NOTICE, "SIG-Term caught, exitting"); return_value = SIGTERM; break;
122 case SIGHUP: log_printf(NOTICE, "SIG-Hup caught"); return_value = SIGHUP; break;
123 case SIGUSR1: log_printf(NOTICE, "SIG-Usr1 caught"); return_value = SIGUSR1; break;
124 case SIGUSR2: log_printf(NOTICE, "SIG-Usr2 caught"); return_value = SIGUSR2; break;
125 default: log_printf(WARNING, "unknown signal %d caught, ignoring", sig); break;
126 }
127 sigdelset(&set, sig);
128 }
129 }
130
131 sigprocmask(SIG_SETMASK, &oldset, NULL);
132 return return_value;
133 }
134
signal_stop()135 void signal_stop()
136 {
137 struct sigaction act;
138 act.sa_handler = SIG_DFL;
139 sigemptyset(&act.sa_mask);
140 act.sa_flags = 0;
141
142 sigaction(SIGINT, &act, NULL);
143 sigaction(SIGQUIT, &act, NULL);
144 sigaction(SIGTERM, &act, NULL);
145 sigaction(SIGHUP, &act, NULL);
146 sigaction(SIGUSR1, &act, NULL);
147 sigaction(SIGUSR2, &act, NULL);
148 sigaction(SIGPIPE, &act, NULL);
149
150 close(sig_pipe_fds[0]);
151 close(sig_pipe_fds[1]);
152 }
153