stun

simple point to point tunnel
git clone git://git.2f30.org/stun.git
Log | Files | Refs | README

commit 18cde7a78cba8c54788d4a1f98c01f41020a79ae
parent efe80acb840c5b6fcbf17163553587f393897cb1
Author: sin <sin@2f30.org>
Date:   Thu Apr 28 11:51:42 +0100

Add tcp option configuration block in config file

Diffstat:
WHATSNEW | 8+++++---
client.c | 24+++++++++++++++++++++---
parse.y | 64++++++++++++++++++++++++++++++++++++++++++++++++++++++----------
server.c | 24+++++++++++++++++++++---
stun.conf.5 | 25+++++++++++++++++++++++++
stun.h | 16++++++++++++----
6 files changed, 138 insertions(+), 23 deletions(-)
diff --git a/WHATSNEW b/WHATSNEW @@ -1,8 +1,10 @@ 0.3 release notes - * multi-network support. - * stun is now configurable through a config file. - * logging facility has been improved. + * Multi-network support. + * Daemon configurable through a config file. + * Logging facility has been improved. + * TCP nodelay and keepalive disabled by default. The options + can be enabled in the config file. 0.2 release notes - April 17 2016 diff --git a/client.c b/client.c @@ -15,7 +15,7 @@ int clientconnect(char *host, char *port) { struct addrinfo hints, *ai, *p; - int ret, netfd; + int ret, netfd, val; memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_UNSPEC; @@ -44,8 +44,26 @@ clientconnect(char *host, char *port) } setnonblock(netfd, 1); - setsockopt(netfd, SOL_SOCKET, SO_KEEPALIVE, (int []){1}, sizeof(int)); - setsockopt(netfd, IPPROTO_TCP, TCP_NODELAY, (int []){1}, sizeof(int)); + + val = !!(netconfig.tcpflags & TCPFLAG_KEEPALIVE); + if (setsockopt(netfd, SOL_SOCKET, SO_KEEPALIVE, &val, sizeof(val)) < 0) + logwarn("setsockopt SO_KEEPALIVE"); + val = !!(netconfig.tcpflags & TCPFLAG_NODELAY); + if (setsockopt(netfd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val)) < 0) + logwarn("setsockopt TCP_NODELAY"); + + if (netconfig.tcpflags & TCPFLAG_RCVBUFSZ) { + val = netconfig.rcvbufsz; + if (setsockopt(netfd, SOL_SOCKET, SO_RCVBUF, &val, + sizeof(val)) < 0) + logwarn("setsockopt SO_RCVBUF"); + } + if (netconfig.tcpflags & TCPFLAG_SNDBUFSZ) { + val = netconfig.sndbufsz; + if (setsockopt(netfd, SOL_SOCKET, SO_SNDBUF, &val, + sizeof(val)) < 0) + logwarn("setsockopt SO_SNDBUF"); + } if (response(netfd) < 0 || challenge(netfd) < 0) { close(netfd); diff --git a/parse.y b/parse.y @@ -61,15 +61,16 @@ static struct netcfg curnet; typedef struct { union { - int64_t number; + int number; char *string; } v; int lineno; } YYSTYPE; %} -%token CIPHER CONNECT DEVTYPE ERROR INCLUDE -%token INTERFACE LISTEN NETWORK ON PASSWD PORT PROTO TIMEOUT USER +%token BUF CIPHER CONNECT DEVTYPE ERROR INCLUDE +%token INTERFACE KEEPALIVE LISTEN NETWORK NODELAY ON +%token PASSWD PORT PROTO RCV SND TCP TIMEOUT USER %token <v.string> STRING %token <v.number> NUMBER %% @@ -261,6 +262,43 @@ networkopts : CIPHER STRING { } free($2); } + | tcpip { + } + ; + +tcpip : TCP optnl tcpip_b { + } + ; + +tcpip_b : '{' optnl_l tcpflags_l optnl_l '}' + ; + +tcpflags_l : tcpflags_l nl tcpflags + | tcpflags + ; + +tcpflags : KEEPALIVE { + curnet.tcpflags |= TCPFLAG_KEEPALIVE; + } + | NODELAY { + curnet.tcpflags |= TCPFLAG_NODELAY; + } + | RCV BUF NUMBER { + if ($3 < 0) { + yyerror("invalid receive buffer size"); + YYERROR; + } + curnet.tcpflags |= TCPFLAG_RCVBUFSZ; + curnet.rcvbufsz = $3; + } + | SND BUF NUMBER { + if ($3 < 0) { + yyerror("invalid send buffer size"); + YYERROR; + } + curnet.tcpflags |= TCPFLAG_SNDBUFSZ; + curnet.sndbufsz = $3; + } ; %% @@ -295,19 +333,25 @@ lookup(char *s) { /* this has to be sorted always */ static const struct keywords keywords[] = { - { "cipher", CIPHER }, /* optional */ + { "buf", BUF }, + { "cipher", CIPHER }, { "connect", CONNECT }, - { "devtype", DEVTYPE }, /* optional */ - { "include", INCLUDE }, /* optional */ + { "devtype", DEVTYPE }, + { "include", INCLUDE }, { "interface", INTERFACE }, + { "keepalive", KEEPALIVE }, { "listen", LISTEN }, { "network", NETWORK }, + { "nodelay", NODELAY }, { "on", ON }, { "passwd", PASSWD }, - { "port", PORT }, /* optional */ - { "proto", PROTO }, /* optional */ - { "timeout", TIMEOUT }, /* optional */ - { "user", USER } /* optional */ + { "port", PORT }, + { "proto", PROTO }, + { "rcv", RCV }, + { "snd", SND }, + { "tcp", TCP }, + { "timeout", TIMEOUT }, + { "user", USER } }; const struct keywords *p; diff --git a/server.c b/server.c @@ -55,7 +55,7 @@ int serveraccept(int listenfd) { struct sockaddr_storage remote; - int netfd; + int netfd, val; netfd = accept(listenfd, (struct sockaddr *)&remote, (socklen_t []){sizeof(remote)}); @@ -66,8 +66,26 @@ serveraccept(int listenfd) } setnonblock(netfd, 1); - setsockopt(netfd, SOL_SOCKET, SO_KEEPALIVE, (int []){1}, sizeof(int)); - setsockopt(netfd, IPPROTO_TCP, TCP_NODELAY, (int []){1}, sizeof(int)); + + val = !!(netconfig.tcpflags & TCPFLAG_KEEPALIVE); + if (setsockopt(netfd, SOL_SOCKET, SO_KEEPALIVE, &val, sizeof(val)) < 0) + logwarn("setsockopt SO_KEEPALIVE"); + val = !!(netconfig.tcpflags & TCPFLAG_NODELAY); + if (setsockopt(netfd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val)) < 0) + logwarn("setsockopt TCP_NODELAY"); + + if (netconfig.tcpflags & TCPFLAG_RCVBUFSZ) { + val = netconfig.rcvbufsz; + if (setsockopt(netfd, SOL_SOCKET, SO_RCVBUF, &val, + sizeof(val)) < 0) + logwarn("setsockopt SO_RCVBUF"); + } + if (netconfig.tcpflags & TCPFLAG_SNDBUFSZ) { + val = netconfig.sndbufsz; + if (setsockopt(netfd, SOL_SOCKET, SO_SNDBUF, &val, + sizeof(val)) < 0) + logwarn("setsockopt SO_SNDBUF"); + } if (challenge(netfd) < 0 || response(netfd) < 0) { close(netfd); diff --git a/stun.conf.5 b/stun.conf.5 @@ -120,6 +120,23 @@ The default port .Ar number is .Ar 12080 . +.It Ic tcp Brq ... +Enable TCP/IP options. These options are all disabled by default. +.Bl -tag -width Ds +.It Ic keepalive +Enable TCP KEEPALIVE option. +.It Ic nodelay +Enable TCP NODELAY option. This is recommended to avoid delays in the +data stream. +.It Ic snd buf Ar size +Set the send buffer +.Ar size +for the socket. +.It Ic rcv buf Ar size +Set the receive buffer +.Ar size +for the socket. +.El .It Ic include Ar file Include another configuration .Ar file . @@ -141,6 +158,10 @@ network "net2-srv" { interface "tun1" cipher "aes-128-gcm" password "changeme2" + tcp { + nodelay + keepalive + } } .Ed .Pp @@ -157,6 +178,10 @@ network "net2-cli" { interface "tun1" cipher "aes-128-gcm" password "changeme2" + tcp { + nodelay + keepalive + } } .Ed .Pp diff --git a/stun.h b/stun.h @@ -5,6 +5,11 @@ #include "queue.h" +#undef MIN +#define MIN(x,y) ((x) < (y) ? (x) : (y)) +#undef MAX +#define MAX(x,y) ((x) > (y) ? (x) : (y)) + #define STUNUSER "nobody" #define AUTHTIMEO 10 /* in seconds */ #define RECONNECTTIMEO 60 /* in seconds */ @@ -15,10 +20,10 @@ #define DEFCIPHER "chacha20-poly1305" #define PATHCONFIG "/etc/stun.conf" -#undef MIN -#define MIN(x,y) ((x) < (y) ? (x) : (y)) -#undef MAX -#define MAX(x,y) ((x) > (y) ? (x) : (y)) +#define TCPFLAG_KEEPALIVE 0x01 +#define TCPFLAG_NODELAY 0x02 +#define TCPFLAG_RCVBUFSZ 0x04 +#define TCPFLAG_SNDBUFSZ 0x08 enum { PKTFAILED, @@ -33,6 +38,9 @@ enum { struct netcfg { TAILQ_ENTRY(netcfg) entry; + int tcpflags; + int sndbufsz; + int rcvbufsz; int proto; int devtype; int timeout;