Skip to content

Commit 8977bbd

Browse files
committed
SIGHUP support
1 parent 661724e commit 8977bbd

8 files changed

Lines changed: 171 additions & 102 deletions

File tree

README.md

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,33 @@
11
# tuninetd
22

3-
Is a simple Linux daemon for tun/tap devices, similar to inetd by its logic, but for mentioned interfaceces, instead of a ports.
3+
Simple yet powerful tun/tap event emitter. Could be used like VPN dispatcher...
44

55
### How it works:
6-
First, you create and configure tun/tap device, then run **tuninetd**. It start listening on that interface, until network packet will be received.
7-
Next, interface will be released and certain command is executed. From now on, daemon in monitoring state.
8-
After N seconds of interface idle, tuninetd send "stop" command by path, that you define, and start listening interface by its own again.
9-
10-
Since, **tuninetd** based on **libpcap**, you can specify filter to trigging "start" event and monitoring iddle (i.e. cutoff unwanted traffic).
11-
To test/debug filters rules - use tcpdump, because it built upon the same library.
6+
You should create and configure tun/tap device, then run **tuninetd**. It starts listening on that interface until network traffic will be detected. After that, interface will be released and certain command executed. From now on daemon is in monitoring state.
7+
After N seconds of interface idle, tuninetd send "stop" command by path that you define and start listening interface by its own again.
8+
9+
Since **tuninetd** based on **libpcap**, you can specify filter to trigging "start" and monitoring iddle (i.e. cutoff unwanted traffic). To test/debug pcap rules you might use tcpdump which is based on the same library.
1210

1311
**! OR !**
1412

15-
You can simply use netfilter nfgroup (*iptables NFLOG target*), for reading packets from. No binding to interface and no libpcap usage. This is more lightweight mode and because of that - more reliable. Option available since v1.1.0.
13+
You can simply use netfilter nfgroup (*iptables NFLOG target*), for reading packets from. No need binding to tun/tap interface nor heavy libpcap sensor. This is more lightweight mode and because of that - more reliable. Option available since v1.1.0.
1614

1715

18-
**tuninetd** allows you deploy "VPN by demand" or any other "by demand" services, which is the main idea of the project.
16+
**tuninetd** allows deploy "VPN by demand" or any other "by demand" services, which is the main idea of the project.
1917

2018
### Installation:
21-
If you're using Debian/Ubuntu, check deb-packages folder. Choose appropriate architecture, then run following command with root privileges:
19+
If you're using Debian/Ubuntu please check deb-packages folder. Choose appropriate architecture, then run following command with root privileges:
2220
```sh
2321
# dpkg -i tuninetd_ver_arch.deb
2422
# apt-get -f install
2523
```
26-
To install it from sources, download src folder. In case Debian/Ubuntu, you should also install **build-essential**, **libpcap-dev** and **libnetfilter-log-dev** packages first. To build tuninetd, run:<br/>
24+
To install from sources download src folder. In case Debian/Ubuntu, you should also install **build-essential**, **libpcap-dev** and **libnetfilter-log-dev** packages first. To build tuninetd just run:<br/>
2725
```sh
2826
# cd /download/folder/src
2927
# make
3028
```
31-
After that, bin folder should appears, which contains tuninetd.
29+
30+
Congrats! Tuninend is ready to use. Check ./bin folder. :)
3231

3332
### Usage:
3433

@@ -41,30 +40,32 @@ tuninetd {-i \<ifname> | -n \<nflog-group>} -c \<path> [-m \<iftype>] [-f \<filt
4140
**-f \<filter>**: specify pcap filter, similar to tcpdump<br/>
4241
**-t \<ttl>**: seconds of interface (traffic) idle, before 'stop' command (default is 600).<br/>
4342
**-d**: demonize process<br/>
44-
**-h**: prints this help text
43+
**-h**: prints this help
44+
45+
`--- If tuninetd stuck in start condition for any reason, you can reset to "standby" (i.e. stop state) with SIGHUP. ---`
4546

4647
### Examples:
47-
Before launching as daemon, make sure there is no errors occurs. In daemon mode, tuninetd write status messages and errors to syslog.
48+
Before launching as daemon make sure there is no errors occurs. In daemon mode tuninetd write status messages and errors to syslog.
4849

4950
```sh
5051
# tuninetd -i tun0 -c /test/runtunnel.sh -f "! host 1.2.3.4" -t 3600 -d
5152
# tuninetd -n 2 -c /test/runtunnel.sh -t 3600 -d
5253
```
5354

54-
You can find example script 'runtunnel.sh', within examples folder.
55+
Check ```example``` folder to find some shell scripts.
5556

56-
To create and up tun device, could be used next commands:
57+
To create and bring up ```tun``` device, could be used following commands:
5758
```sh
5859
# ip tuntap add name tun0 mode tun
59-
# ip link tun0 up
60+
# ip link set tun0 up
6061
```
6162

62-
For more information about routing and configuring net devices, please check official documentation.
63+
For more information about routing and configuring net devices, I strongly suggest LARCT how-to.
6364

64-
*! Notice, that the modern Linux distributions periodically send 'icmpv6 router solicitation' packets, which cause tuninetd state changing (call of 'start' script). This situation affects to tun/tap mode without filter (-f) applied.*
65+
*! Notice ! Modern Linux distributions periodically send 'icmpv6 router solicitation' packets, which cause tuninetd keep or change its status (calling 'start' script for example). This situation appears in tun/tap mode without pcap filter applied.*
6566

6667
### License:
6768
MIT
6869
### Author:
6970
Paul aka root4root \<root4root at gmail dot com><br/>
70-
**Any suggestions will be appreciated.**
71+
**Any comment/suggestions are welcomed.**
7.09 KB
Binary file not shown.

src/Makefile

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1-
first: main.c
1+
all: default
2+
default: main.c
23
[ -d ./bin ] || mkdir -p ./bin
34
gcc -o ./bin/tuninetd main.c -lpthread -lpcap -lnetfilter_log
5+
clean:
6+
rm -rf ./bin

src/main.c

Lines changed: 23 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,13 @@
1-
#include <fcntl.h>
2-
#include <pthread.h>
3-
#include <pcap.h>
4-
#include <stdio.h>
5-
#include <stdlib.h>
6-
#include <string.h>
7-
#include <net/if.h>
8-
#include <linux/if_tun.h>
9-
#include <sys/ioctl.h>
10-
#include <stdarg.h>
11-
#include <syslog.h>
12-
#include <unistd.h>
13-
14-
//#include <sys/types.h>
15-
#include <libnetfilter_log/libnetfilter_log.h>
16-
//#include <sys/socket.h>
17-
18-
#define BUFSIZE 2000
19-
20-
short int debug = 0;
21-
short int status = 0;
22-
unsigned long ts = 0;
23-
unsigned long curts = 0;
24-
25-
char progname[] = "tuninetd";
26-
27-
struct globcfg_t {
28-
short int isdaemon;
29-
pid_t pid;
30-
char *cmd_path;
31-
char *cmd_path_start;
32-
char *cmd_path_stop;
33-
char *pcap_filter;
34-
char *dev_name;
35-
long nf_group;
36-
int dev_mode;
37-
int ttl;
38-
} globcfg;
39-
40-
#include "utils.c"
41-
#include "tun.c"
42-
#include "pcap.c"
43-
#include "nflog.c"
1+
#include "main.h"
442

453
int main(int argc, char *argv[])
464
{
47-
int x, y, opt=0;
5+
int opt = 0;
6+
7+
struct timespec tim;
8+
9+
tim.tv_sec = 1;
10+
tim.tv_nsec = 0;
4811

4912
static const char *optString = "i:t:c:f:m:n:dh";
5013

@@ -117,6 +80,12 @@ int main(int argc, char *argv[])
11780
exit(1);
11881
}
11982

83+
if (pthread_mutex_init(&lock, NULL) != 0)
84+
{
85+
my_err("Mutex init failed. Abort.");
86+
exit(1);
87+
}
88+
12089
if (globcfg.isdaemon == 1) {
12190
globcfg.pid = fork();
12291

@@ -138,14 +107,10 @@ int main(int argc, char *argv[])
138107
close(STDIN_FILENO);
139108
close(STDOUT_FILENO);
140109
close(STDERR_FILENO);
141-
}
110+
} else
111+
my_info("Started with pid %d", getpid());
142112

143-
pthread_t pcap_x_thread;
144-
pthread_t tun_x_thread;
145-
pthread_t nflog_x_thread;
146113

147-
pthread_attr_t attr;
148-
149114
pthread_attr_init(&attr);
150115
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
151116

@@ -158,22 +123,19 @@ int main(int argc, char *argv[])
158123
pthread_create(&nflog_x_thread, &attr, nflog_x, &y);
159124
}
160125

126+
if (signal(SIGHUP, sig_handler) == SIG_ERR)
127+
my_info("Can't catch SIGHUP\n");
128+
129+
161130
while (1) {
162-
usleep(1000000);
131+
132+
nanosleep(&tim, NULL);
133+
163134
curts = time(NULL);
164135

165136
if (ts != 0 && status == 1 && ((curts - ts) >= globcfg.ttl) ) {
166137
my_info("CORE: executing STOP command...");
167-
168-
if (system(globcfg.cmd_path_stop) != 0) {
169-
my_err("Warning! Executable command doesn't return 0 (%s)", globcfg.cmd_path_stop);
170-
}
171-
172-
status = 0;
173-
174-
if (globcfg.nf_group < 0) {
175-
pthread_create(&tun_x_thread, &attr, tun_x, &y);
176-
}
138+
switch_guard(OFF);
177139
}
178140
}
179141

src/main.h

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
#include <fcntl.h>
2+
#include <pthread.h>
3+
#include <pcap.h>
4+
#include <stdio.h>
5+
#include <stdlib.h>
6+
#include <string.h>
7+
#include <net/if.h>
8+
#include <linux/if_tun.h>
9+
#include <sys/ioctl.h>
10+
#include <stdarg.h>
11+
#include <syslog.h>
12+
#include <unistd.h>
13+
#include <signal.h>
14+
#include <time.h>
15+
16+
#include <libnetfilter_log/libnetfilter_log.h>
17+
18+
19+
#define BUFSIZE 2000
20+
#define ON 1
21+
#define OFF 0
22+
23+
int x, y;
24+
25+
short int debug = 0;
26+
short int status = 0;
27+
unsigned long ts = 0;
28+
unsigned long curts = 0;
29+
30+
char progname[] = "tuninetd";
31+
32+
struct globcfg_t {
33+
short int isdaemon;
34+
pid_t pid;
35+
char *cmd_path;
36+
char *cmd_path_start;
37+
char *cmd_path_stop;
38+
char *pcap_filter;
39+
char *dev_name;
40+
long nf_group;
41+
int dev_mode;
42+
int ttl;
43+
} globcfg;
44+
45+
pthread_t pcap_x_thread;
46+
pthread_t tun_x_thread;
47+
pthread_t nflog_x_thread;
48+
49+
pthread_attr_t attr;
50+
pthread_mutex_t lock;
51+
52+
void do_debug(char *msg, ...);
53+
void my_err(char *msg, ...);
54+
void my_info(char *msg, ...);
55+
void switch_state(short action);
56+
void switch_guard(short action);
57+
58+
void *tun_x(void *x_void_ptr);
59+
void *nflog_x(void *x_void_ptr);
60+
void *pcap_x(void *x_void_ptr);
61+
62+
#include "utils.c"
63+
#include "tun.c"
64+
#include "pcap.c"
65+
#include "nflog.c"

src/nflog.c

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,11 @@
11
static int callback(struct nflog_g_handle *gh, struct nfgenmsg *nfmsg, struct nflog_data *ldata, void *data)
22
{
3-
if (status == 0) {
4-
3+
if (status == OFF) {
54
my_info("NFLOG module: executing START command...");
6-
7-
if (system(globcfg.cmd_path_start) != 0) {
8-
my_err("Warning! Executable command doesn't return 0 (%s)", globcfg.cmd_path_start);
9-
}
10-
11-
status = 1;
5+
switch_guard(ON);
126
}
137

148
ts = curts;
15-
169
}
1710

1811
void *nflog_x(void *x_void_ptr)
@@ -41,7 +34,7 @@ void *nflog_x(void *x_void_ptr)
4134
}
4235
qh = nflog_bind_group(h, globcfg.nf_group);
4336
if (!qh) {
44-
my_err("no handle for group 0");
37+
my_err("no handle for group %i", globcfg.nf_group);
4538
exit(1);
4639
}
4740

src/tun.c

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,11 @@ void *tun_x(void *x_void_ptr)
4343
int nread;
4444
char buffer[BUFSIZE];
4545

46+
struct timespec tim;
47+
48+
tim.tv_sec = 0;
49+
tim.tv_nsec = 15000000;
50+
4651

4752
if ( (tap_fd = tun_alloc(globcfg.dev_name, globcfg.dev_mode | IFF_NO_PI)) < 0 ) {
4853
my_err("Fatal error. Connecting to tun/tap interface %s failed.", globcfg.dev_name);
@@ -53,27 +58,21 @@ void *tun_x(void *x_void_ptr)
5358
nread = cread(tap_fd, buffer, BUFSIZE);
5459

5560
if (globcfg.pcap_filter != NULL) {
56-
usleep(15000); //Wait for libpcap timeout.
61+
nanosleep(&tim, NULL);
5762
if ( (curts - ts) < 2 ) {
5863
do_debug("Read %d bytes from the tap interface\n", nread);
5964
break;
6065
}
6166
} else {
62-
break;
67+
break;
6368
}
6469
}
6570

66-
ts = time(NULL);
67-
68-
status = 1;
69-
7071
close(tap_fd);
7172

7273
my_info("TUN/TAP module: executing START command...");
7374

74-
if (system(globcfg.cmd_path_start) != 0) {
75-
my_err("Warning! Executable command doesn't return 0 (%s)", globcfg.cmd_path_start);
76-
}
77-
75+
switch_guard(ON);
76+
7877
return 0;
7978
}

0 commit comments

Comments
 (0)