summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Pointner <equinox@anytun.org>2015-01-06 21:31:10 +0000
committerChristian Pointner <equinox@anytun.org>2015-01-06 21:31:10 +0000
commitef19b2d2d034a4092755dceb8cf9d2aab0b85445 (patch)
tree3ff7d377e0a1d5c2f7655a3caa2f7c4013b54ab8
parentstarted branch for config file parser (diff)
added first version for config file parser
-rw-r--r--src/Makefile12
-rw-r--r--src/cfg_parser.h56
-rw-r--r--src/cfg_parser.rl197
-rwxr-xr-xsrc/configure1
-rw-r--r--src/options.c12
-rw-r--r--src/options.h1
-rw-r--r--src/uanytun.c16
7 files changed, 286 insertions, 9 deletions
diff --git a/src/Makefile b/src/Makefile
index feccbaa..3332997 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -59,6 +59,7 @@ OBJ := log.o \
sig_handler.o \
sysexec.o \
options.o \
+ cfg_parser.o \
tun.o \
udp.o \
plain_packet.o \
@@ -78,6 +79,15 @@ SRC := $(OBJ:%.o=%.c)
all: $(EXECUTABLE)
+cfg_parser.c: cfg_parser.rl
+ $(RAGEL) -C -G2 -o $@ $<
+
+cfg_parser.dot: cfg_parser.rl
+ $(RAGEL) -V -p -o $@ $<
+
+cfg_parser.png: cfg_parser.dot
+ @dot -Tpng $< > $@
+
%.d: %.c
@set -e; rm -f $@; \
$(CC) -MM $(CFLAGS) $< > $@.$$$$; \
@@ -109,6 +119,8 @@ clean:
rm -f *.o
rm -f *.d
rm -f *.d.*
+ rm -f cfg_parser.c
+ rm -f cfg_parser.png cfg_parser.dot
rm -f $(EXECUTABLE)
cleanall: clean
diff --git a/src/cfg_parser.h b/src/cfg_parser.h
new file mode 100644
index 0000000..1c030c0
--- /dev/null
+++ b/src/cfg_parser.h
@@ -0,0 +1,56 @@
+/*
+ * uAnytun
+ *
+ * uAnytun is a tiny implementation of SATP. Unlike Anytun which is a full
+ * featured implementation uAnytun has no support for multiple connections
+ * or synchronisation. It is a small single threaded implementation intended
+ * to act as a client on small platforms.
+ * The secure anycast tunneling protocol (satp) defines a protocol used
+ * for communication between any combination of unicast and anycast
+ * tunnel endpoints. It has less protocol overhead than IPSec in Tunnel
+ * mode and allows tunneling of every ETHER TYPE protocol (e.g.
+ * ethernet, ip, arp ...). satp directly includes cryptography and
+ * message authentication based on the methods used by SRTP. It is
+ * intended to deliver a generic, scaleable and secure solution for
+ * tunneling and relaying of packets of any protocol.
+ *
+ *
+ * Copyright (C) 2007-2014 Christian Pointner <equinox@anytun.org>
+ *
+ * This file is part of uAnytun.
+ *
+ * uAnytun is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * any later version.
+ *
+ * uAnytun 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with uAnytun. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL. If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so. If you
+ * do not wish to do so, delete this exception statement from your
+ * version. If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+
+#ifndef UANYTUN_cfg_parser_h_INCLUDED
+#define UANYTUN_cfg_parser_h_INCLUDED
+
+#include "options.h"
+
+int read_configfile(const char* filename, options_t* opt);
+
+#endif
diff --git a/src/cfg_parser.rl b/src/cfg_parser.rl
new file mode 100644
index 0000000..98118a7
--- /dev/null
+++ b/src/cfg_parser.rl
@@ -0,0 +1,197 @@
+/*
+ * uAnytun
+ *
+ * uAnytun is a tiny implementation of SATP. Unlike Anytun which is a full
+ * featured implementation uAnytun has no support for multiple connections
+ * or synchronisation. It is a small single threaded implementation intended
+ * to act as a client on small platforms.
+ * The secure anycast tunneling protocol (satp) defines a protocol used
+ * for communication between any combination of unicast and anycast
+ * tunnel endpoints. It has less protocol overhead than IPSec in Tunnel
+ * mode and allows tunneling of every ETHER TYPE protocol (e.g.
+ * ethernet, ip, arp ...). satp directly includes cryptography and
+ * message authentication based on the methods used by SRTP. It is
+ * intended to deliver a generic, scaleable and secure solution for
+ * tunneling and relaying of packets of any protocol.
+ *
+ *
+ * Copyright (C) 2007-2014 Christian Pointner <equinox@anytun.org>
+ *
+ * This file is part of uAnytun.
+ *
+ * uAnytun is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * any later version.
+ *
+ * uAnytun 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with uAnytun. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL. If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so. If you
+ * do not wish to do so, delete this exception statement from your
+ * version. If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <stdio.h>
+
+#include "datatypes.h"
+#include "options.h"
+
+static int owrt_string(char** dest, char* start, char* end)
+{
+ if(!dest || start >= end)
+ return -1;
+
+ if(*dest) free(*dest);
+ int n = end - start;
+ *dest = malloc(n+1);
+ if(!(*dest))
+ return -2;
+
+ memcpy(*dest, start, n);
+ (*dest)[n] = 0;
+
+ return 0;
+}
+
+%%{
+ machine cfg_parser;
+
+ action set_cpy_start { cpy_start = fpc; }
+ action set_local_addr { ret = owrt_string(&(opt->local_addr_), cpy_start, fpc); cpy_start = NULL; }
+ action set_local_port { ret = owrt_string(&(opt->local_port_), cpy_start, fpc); cpy_start = NULL; }
+ action set_remote_addr { ret = owrt_string(&(opt->remote_addr_), cpy_start, fpc); cpy_start = NULL; }
+ action set_remote_port { ret = owrt_string(&(opt->remote_port_), cpy_start, fpc); cpy_start = NULL; }
+ action logerror {
+ if(fpc == eof)
+ fprintf(stderr, "config file syntax error: unexpected end of file\n");
+ else
+ fprintf(stderr, "config file syntax error at line %d\n", cur_line);
+
+ fgoto *cfg_parser_error;
+ }
+
+ newline = '\n' @{cur_line++;};
+ ws = [ \t];
+ comment = '#' [^\n]* newline;
+ ign = ( ws | comment | newline | [\v\f\r] );
+
+ number = [0-9]+;
+ ipv4_addr = [0-9.]+;
+ ipv6_addr = [0-9a-fA-F:]+;
+ name = [a-zA-Z0-9\-]+;
+ host_name = [a-zA-Z0-9\-.]+;
+
+ host_or_addr = ( host_name | ipv4_addr | ipv6_addr );
+ service = ( number | name );
+
+ local_addr = ( '*' | host_or_addr >set_cpy_start %set_local_addr );
+ local_port = service >set_cpy_start %set_local_port;
+ remote_addr = host_or_addr >set_cpy_start %set_remote_addr;
+ remote_port = service >set_cpy_start %set_remote_port;
+
+ opt_laddr = "interface" ws* "=" ws* local_addr ign* newline;
+ opt_lport = "port" ws* "=" ws* local_port ign* newline;
+ opt_raddr = "remote-host" ws* "=" ws* remote_addr ign* newline;
+ opt_rport = "remote-port" ws* "=" ws* remote_port ign* newline;
+
+ option = ( opt_laddr | opt_lport | opt_raddr | opt_rport );
+
+ section_head = '[' name ']';
+ section_body = ( ign | option )+;
+
+ main := ( section_head ign* section_body | ign+ )* $!logerror;
+}%%
+
+
+static int parse_options(char* p, char* pe, options_t* opt)
+{
+ int cs, ret = 0, cur_line = 1;
+
+ %% write data;
+ %% write init;
+
+ char* cpy_start = NULL;
+ char* eof = pe;
+ %% write exec;
+
+ if(cs == cfg_parser_error) {
+ /* revert config updates */
+ ret = -1;
+ }
+ else {
+ /* TODO: apply config update */
+ ret = 0;
+ }
+
+ return ret;
+}
+
+int read_configfile(const char* filename, options_t* opt)
+{
+ int fd = open(filename, 0);
+ if(fd < 0) {
+ fprintf(stderr, "config: open('%s') failed: %s\n", filename, strerror(errno));
+ return -1;
+ }
+
+ struct stat sb;
+ if(fstat(fd, &sb) == -1) {
+ fprintf(stderr, "config: fstat() error: %s\n", strerror(errno));
+ close(fd);
+ return -1;
+ }
+
+ if(!sb.st_size) {
+ fprintf(stderr, "config: '%s' is empty\n", filename);
+ close(fd);
+ return -1;
+ }
+
+ if(!S_ISREG(sb.st_mode)) {
+ fprintf(stderr, "config: '%s' is not a regular file\n", filename);
+ close(fd);
+ return -1;
+ }
+
+ char* p = (char*)mmap(NULL, sb.st_size, PROT_READ, MAP_SHARED, fd, 0);
+ if(p == MAP_FAILED) {
+ fprintf(stderr, "config: mmap() error: %s\n", strerror(errno));
+ close(fd);
+ return -1;
+ }
+ close(fd);
+
+ fprintf(stderr, "config: mapped %ld bytes from file %s at address 0x%08lX\n", sb.st_size, filename, (unsigned long int)p);
+ int ret = parse_options(p, p + sb.st_size, opt);
+
+ if(munmap(p, sb.st_size) == -1) {
+ fprintf(stderr, "config: munmap() error: %s\n", strerror(errno));
+ return -1;
+ }
+ fprintf(stderr, "config: unmapped '%s'\n", filename);
+
+ return ret;
+}
diff --git a/src/configure b/src/configure
index 16d5cc7..8b051c3 100755
--- a/src/configure
+++ b/src/configure
@@ -238,6 +238,7 @@ CFLAGS := $CFLAGS
LDFLAGS := $LDFLAGS
STRIP := strip
INSTALL := install
+RAGEL := ragel
PREFIX := $PREFIX
SBINDIR := $SBINDIR
diff --git a/src/options.c b/src/options.c
index c3038bb..7f44c41 100644
--- a/src/options.c
+++ b/src/options.c
@@ -57,6 +57,7 @@
#include <ctype.h>
#include "log.h"
+#include "cfg_parser.h"
#ifndef NO_CRYPT
#include "auth_algo.h"
@@ -250,6 +251,12 @@ int options_parse(options_t* opt, int argc, char* argv[])
return -1;
else if(!strcmp(str,"-v") || !strcmp(str,"--version"))
return -5;
+ else if(!strcmp(str,"-F") || !strcmp(str,"--config-file")) {
+ if(argc < 1) return i;
+ if(read_configfile(argv[i+1], opt)) return -6;
+ argc--;
+ i++;
+ }
PARSE_INVERSE_BOOL_PARAM("-D","--nodaemonize", opt->daemonize_)
PARSE_STRING_PARAM("-u","--username", opt->username_)
PARSE_STRING_PARAM("-g","--groupname", opt->groupname_)
@@ -351,6 +358,7 @@ void options_default(options_t* opt)
return;
opt->progname_ = strdup("uanytun");
+ opt->config_file_ = NULL;
opt->daemonize_ = 1;
opt->username_ = NULL;
opt->groupname_ = NULL;
@@ -395,6 +403,8 @@ void options_clear(options_t* opt)
if(opt->progname_)
free(opt->progname_);
+ if(opt->config_file_)
+ free(opt->config_file_);
if(opt->username_)
free(opt->username_);
if(opt->groupname_)
@@ -441,6 +451,7 @@ void options_print_usage()
printf("USAGE:\n");
printf("uanytun [-h|--help] prints this...\n");
printf(" [-v|--version] print version info and exit\n");
+ printf(" [-F|--config-file] <path> path to the configuration file\n");
printf(" [-D|--nodaemonize] don't run in background\n");
printf(" [-u|--username] <username> change to this user\n");
printf(" [-g|--groupname] <groupname> change to this group\n");
@@ -496,6 +507,7 @@ void options_print(options_t* opt)
return;
printf("progname: '%s'\n", opt->progname_);
+ printf("config-file: '%s'\n", opt->config_file_);
printf("daemonize: %d\n", opt->daemonize_);
printf("username: '%s'\n", opt->username_);
printf("groupname: '%s'\n", opt->groupname_);
diff --git a/src/options.h b/src/options.h
index 8f3593f..8a7290d 100644
--- a/src/options.h
+++ b/src/options.h
@@ -65,6 +65,7 @@ typedef enum role_enum role_t;
struct options_struct {
char* progname_;
+ char* config_file_;
int daemonize_;
char* username_;
char* groupname_;
diff --git a/src/uanytun.c b/src/uanytun.c
index 159f773..3baea2c 100644
--- a/src/uanytun.c
+++ b/src/uanytun.c
@@ -307,21 +307,17 @@ int main(int argc, char* argv[])
if(ret) {
if(ret > 0) {
fprintf(stderr, "syntax error near: %s\n\n", argv[ret]);
- }
- if(ret == -2) {
+ } else if(ret == -2) {
fprintf(stderr, "memory error on options_parse, exitting\n");
- }
- if(ret == -3) {
+ } else if(ret == -3) {
fprintf(stderr, "syntax error: -4 and -6 are mutual exclusive\n\n");
- }
- if(ret == -4) {
+ } else if(ret == -4) {
fprintf(stderr, "syntax error: unknown role name\n\n");
- }
- if(ret == -5) {
+ } else if(ret == -5) {
options_print_version();
}
- if(ret != -2 && ret != -5)
+ if(ret != -2 && ret != -5 && ret != -6)
options_print_usage();
if(ret == -1 || ret == -5)
@@ -352,6 +348,8 @@ int main(int argc, char* argv[])
log_printf(NOTICE, "just started...");
options_parse_post(&opt);
+ options_print(&opt);
+
priv_info_t priv;
if(opt.username_)
if(priv_init(&priv, opt.username_, opt.groupname_)) {