Compare commits

...

48 Commits

Author SHA1 Message Date
8a72f6eec0 switch to libsodium aegis256 implementation 2020-06-09 21:13:21 +02:00
47d8790409 switch to miegl's mud fork 2020-06-09 21:04:34 +02:00
Adrien Gallouët
dafc7e8106 Rework command set
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2020-04-17 21:36:41 +00:00
Adrien Gallouët
3622f928ca Better explain why the connection fails
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2020-04-03 09:35:43 +00:00
Adrien Gallouët
18b8229a93 Update mud
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2020-04-03 08:33:21 +00:00
Adrien Gallouët
1e62537ac3 Fix automake & meson
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2020-04-02 20:27:07 +00:00
Adrien Gallouët
6091853f46 Code cleanup
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2020-04-02 20:10:18 +00:00
Adrien Gallouët
392a493c17 Add a command to list all tunnels
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2020-04-02 16:23:44 +00:00
Adrien Gallouët
b80f1b6ac1 The path command should only show the conf
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2020-04-02 13:48:17 +00:00
Adrien Gallouët
c86bbf8bb7 Show libsodium major.minor version
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2020-03-31 11:49:07 +00:00
Adrien Gallouët
c113724eb0 Update mud
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2020-03-25 20:47:47 +00:00
Adrien Gallouët
b184ddedaa Code cleanup
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2020-03-25 10:33:47 +00:00
Adrien Gallouët
28a978f276 Fix the last fix :)
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2020-03-25 07:32:34 +00:00
Adrien Gallouët
e0546ec46a Fix build on OpenBSD
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2020-03-24 17:41:58 +00:00
Adrien Gallouët
50f002b7f8 Add variable X to cross build a static binary
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2020-03-24 09:27:36 +00:00
Adrien Gallouët
42faaf816f Update mud: losslimit per path
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2020-03-07 16:19:06 +00:00
Adrien Gallouët
eee6a22ccd Use strip -x
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2020-02-29 10:06:50 +00:00
Adrien Gallouët
ee2d7a2e07 Update mud
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2020-02-29 09:57:46 +00:00
Adrien Gallouët
e5949b409f Handle cross stripped binary
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2020-02-29 09:34:58 +00:00
Adrien Gallouët
13703fb15f Allow to setup beat without [back]up
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2020-02-21 16:40:22 +00:00
Adrien Gallouët
7f30cdc5ee Update mud
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2020-02-05 14:01:13 +00:00
Adrien Gallouët
b2077f5cd4 Use mud_set_conf()
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2020-01-16 17:48:02 +00:00
Adrien Gallouët
a9408e799d Show beat
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2020-01-11 15:04:55 +00:00
Adrien Gallouët
61c7b48e3f Add beat option in path command
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2020-01-11 09:55:17 +00:00
Adrien Gallouët
4db90b42b6 Use mud based keepalive
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2020-01-11 09:12:47 +00:00
Adrien Gallouët
3df542b6d7 Update mud
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2020-01-09 22:25:42 +00:00
Adrien Gallouët
4a0027e640 Update mud
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2020-01-09 17:39:58 +00:00
Adrien Gallouët
296d80782a Update mud
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2020-01-08 14:38:28 +00:00
Adrien Gallouët
1c38034265 Code cleanup
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2020-01-07 13:00:51 +00:00
Adrien Gallouët
0b26eb108d Add rate fixed|auto option
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2020-01-07 12:46:28 +00:00
Adrien Gallouët
ac167e74f5 Fix keepalive and use a small value for now
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2020-01-04 16:17:36 +00:00
Adrien Gallouët
203feba186 Update README.md about backup path
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2020-01-03 16:26:21 +00:00
Adrien Gallouët
3b938df408 Happy New Year
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2020-01-03 15:57:16 +00:00
Adrien Gallouët
0ccb3de68d Update mud
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2020-01-03 15:39:10 +00:00
Adrien Gallouët
020b115171 Add keepalive
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2020-01-03 15:28:27 +00:00
Adrien Gallouët
53e7a7ba0a Resize and align buf
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2020-01-03 15:09:06 +00:00
Adrien Gallouët
1ae7775ce1 Cleanup Makefile
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2019-12-31 20:04:52 +00:00
Adrien Gallouët
c75f5d5620 Do not allow mtu manipulation anymore
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2019-12-31 19:34:20 +00:00
Adrien Gallouët
5f72198a96 Fix upload-artifact
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2019-12-10 14:54:49 +00:00
Adrien Gallouët
c01dbe3e4b Update README.md
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2019-11-19 13:38:59 +00:00
Adrien Gallouët
6be944d7cb Update mud
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2019-11-19 12:00:07 +00:00
Adrien Gallouët
009d482fd1 Be careful with dirname()
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2019-11-15 10:43:41 +00:00
Adrien Gallouët
b9aaab661f Probe run/tmp directory at runtime
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2019-11-14 19:19:23 +00:00
Adrien Gallouët
a4f63ecf40 Add rundir option for make
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2019-11-13 14:12:58 +00:00
Adrien Gallouët
0ceedaec10 Update Makefile
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2019-11-13 13:54:15 +00:00
Adrien Gallouët
34486c20b1 Update EXTRA_DIST
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2019-11-13 13:39:07 +00:00
Adrien Gallouët
b1fca4c1d2 301 to wikis
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2019-11-12 11:19:56 +00:00
Adrien Gallouët
5e0900c8ee Add option losslimit in the set command
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2019-10-23 13:52:40 +00:00
26 changed files with 502 additions and 567 deletions

View File

@@ -20,5 +20,5 @@ jobs:
- uses: actions/upload-artifact@v1
with:
name: bin
name: ${{ matrix.os }}
path: ./bin

7
.gitmodules vendored
View File

@@ -1,8 +1,7 @@
[submodule "mud"]
path = mud
url = https://github.com/angt/mud.git
ignore = dirty
[submodule "argz"]
path = argz
url = https://github.com/angt/argz.git
ignore = dirty
[submodule "mud"]
path = mud
url = https://git.miegl.cz/miegl/mud.git

View File

@@ -1,4 +1,4 @@
Copyright (c) 2015-2019, Adrien Gallouët <adrien@gallouet.fr>
Copyright (c) 2015-2020, Adrien Gallouët <adrien@gallouet.fr>
All rights reserved.
Redistribution and use in source and binary forms, with or without

View File

@@ -2,34 +2,39 @@ NAME := glorytun
VERSION := $(shell ./version.sh)
DIST := $(NAME)-$(VERSION)
DESTDIR ?=
CC ?= gcc
INSTALL ?= install
prefix ?= /usr
CFLAGS ?= -std=c11 -O2 -Wall -fstack-protector-strong
FLAGS := $(CFLAGS) $(LDFLAGS) $(CPPFLAGS)
CC ?= cc
prefix ?= /usr
Q := @
ifneq ($(X),)
H = $(X)-
FLAGS += -static
endif
FLAGS := $(CFLAGS) $(LDFLAGS) $(CPPFLAGS)
FLAGS += -DPACKAGE_NAME=\"$(NAME)\" -DPACKAGE_VERSION=\"$(VERSION)\"
FLAGS += -I.static/$(X)/libsodium-stable/src/libsodium/include
FLAGS += -L.static/$(X)/libsodium-stable/src/libsodium/.libs
FLAGS += -I.static/$(CROSS)/libsodium-stable/src/libsodium/include
FLAGS += -L.static/$(CROSS)/libsodium-stable/src/libsodium/.libs
SRC := argz/argz.c mud/mud.c $(wildcard src/*.c)
HDR := argz/argz.h mud/mud.h $(wildcard src/*.h)
SRC := argz/argz.c mud/mud.c mud/aegis256/aegis256.c $(wildcard src/*.c)
$(NAME): $(SRC) $(HDR)
$(Q)$(H)$(CC) $(FLAGS) -o $(NAME) $(SRC) -lsodium
.PHONY: $(NAME)
$(NAME):
@echo "Building $(NAME)"
@$(CC) $(FLAGS) -o $(NAME) $(SRC) -lsodium
$(NAME)-strip: $(NAME)
$(Q)cp $< $@
$(Q)$(H)strip -x $@
.PHONY: install
install: $(NAME)
@echo "Installing $(NAME)"
@$(INSTALL) -m 755 -d $(DESTDIR)$(prefix)/bin
@$(INSTALL) -m 755 -s $(NAME) $(DESTDIR)$(prefix)/bin
install: $(NAME)-strip
@echo "$(DESTDIR)$(prefix)/bin/$(NAME)"
$(Q)install -m 755 -d $(DESTDIR)$(prefix)/bin
$(Q)install -m 755 $(NAME)-strip $(DESTDIR)$(prefix)/bin/$(NAME)
.PHONY: dist
dist:
@echo "Building $(DIST).tar.gz"
@(git --git-dir=.git ls-files --recurse-submodules -- ':!:.*' ':!:**/.*' && echo VERSION) | ( \
tar zcf $(DIST).tar.gz -T- --transform 's:^:$(DIST)/:' || \
tar zcf $(DIST).tar.gz -T- -s ':^:$(DIST)/:' ) 2>/dev/null
.PHONY: clean
clean:
$(Q)rm -f "$(NAME)"
$(Q)rm -f "$(DIST).tar.gz"

View File

@@ -9,8 +9,6 @@ glorytun_SOURCES = \
argz/argz.h \
mud/mud.c \
mud/mud.h \
mud/aegis256/aegis256.c \
mud/aegis256/aegis256.h \
src/bench.c \
src/bind.c \
src/common.c \
@@ -21,21 +19,25 @@ glorytun_SOURCES = \
src/iface.h \
src/ip.h \
src/keygen.c \
src/list.c \
src/main.c \
src/path.c \
src/set.c \
src/show.c \
src/str.h \
src/tun.c \
src/tun.h
src/tun.h \
src/version.c
EXTRA_DIST = \
LICENSE \
Makefile \
README.md \
VERSION \
autogen.sh \
meson.build \
mud/LICENSE \
mud/README.md \
sodium.sh \
systemd \
version.sh

View File

@@ -2,6 +2,8 @@
Glorytun is a small, simple and secure VPN over [mud](https://github.com/angt/mud).
Please visit the [wiki](https://github.com/angt/glorytun/wiki) for how-to guides, tutorials, etc.
## Compatibility
Glorytun only depends on [libsodium](https://github.com/jedisct1/libsodium) version >= 1.0.4.
@@ -19,17 +21,19 @@ The key features of Glorytun come directly from mud:
* **Fast and highly secure**
The use of UDP and libsodium allows you to secure your communications without impacting performance.
Glorytun uses AEGIS-256 (a new and very fast AEAD construction) only if AES-NI is available otherwise ChaCha20-Poly1305 is used.
Glorytun uses a new and very fast AEAD construction called AEGIS-256 if AES-NI is available otherwise ChaCha20-Poly1305 is used.
Of course, you can force the use of ChaCha20-Poly1305 for higher security.
All messages are encrypted, authenticated and timestamped to mitigate a large set of attacks.
This implies that the client and the server must be synchronized, an offset of 10min is accepted by default.
Perfect forward secrecy is also implemented with ECDH over Curve25519. Keys are rotated every hours.
* **Multipath and active failover**
* **Multipath and failover**
Connectivity is now crucial, especially in the SD-WAN world.
This feature allows a TCP connection (and all other protocols) to explore and exploit all available links without being disconnected.
Aggregation should work on all conventional links, only very high latency (+500ms) links are not recommended for now.
Aggregation should work on all conventional links.
Only very high latency (+500ms) links are not recommended for now.
Backup paths are also supported, they will be used only in case of emergency, it is useful when aggregation is not your priority.
* **Traffic shaping**
@@ -44,87 +48,6 @@ The key features of Glorytun come directly from mud:
It doesn't rely on Next-hop MTU to avoid ICMP black holes.
In asymmetric situations the minimum MTU is selected.
## Caveats
Glorytun is strongly secure by default and protects against replay attacks,
the clock between the client and the server must be synchronized.
By default, an offset of 10min is accepted.
## Build and Install
You will need `git`, `make`, `gcc` and `libsodium`:
$ sudo apt install git make gcc libsodium-dev # debian based
$ sudo yum install git make gcc libsodium-devel # redhat based
To build and install the latest release from github:
$ git clone https://github.com/angt/glorytun --recursive
$ cd glorytun
$ sudo make install
This will install the binary in `/usr/bin` by default.
The more classical autotools suite is also available.
## Usage
Just run `glorytun` with no arguments to view the list of available commands:
$ glorytun
available commands:
show show tunnel info
bench start a crypto bench
bind start a new tunnel
set change tunnel properties
keygen generate a new secret key
path manage paths
version show version
Use the keyword `help` after a command to show its usage.
## Mini HowTo
Glorytun does not touch the configuration of its network interface (except for the MTU),
It is up to the user to do it according to the tools available
on his system (systemd-networkd, netifd, ...).
This also allows a wide variety of configurations.
To start a server:
# (umask 066; glorytun keygen > my_secret_key)
# glorytun bind 0.0.0.0 keyfile my_secret_key &
You should now have an unconfigured network interface (let's say `tun0`).
For example, the simplest setup with `ifconfig`:
# ifconfig tun0 10.0.1.1 pointopoint 10.0.1.2 up
To check if the server is running, simply call `glorytun show`.
It will show you all of the running tunnels.
To start a new client, you need to get the secret key generated for the server.
Then simply call:
# glorytun bind 0.0.0.0 to SERVER_IP keyfile my_secret_key &
# ifconfig tun0 10.0.1.2 pointopoint 10.0.1.1 up
Now you have to setup your path, let's say you have an ADSL link that can do 1Mbit upload and 20Mbit download then call:
# glorytun path up LOCAL_IPADDR rate tx 1mbit rx 20mbit
Again, to check if your path is working, you can watch its status with `glorytun path`.
You should now be able to ping your server with `ping 10.0.1.1`.
If you use systemd-networkd, you can easily setup your tunnels with the helper program `glorytun-setup`.
## Thanks
* @jedisct1 for all his help and the code for MacOS/BSD.
* The team OTB (@bessa, @gregdel, @pouulet, @sduponch and @simon) for all tests and discussions.
* OVH to support this soft :)
---
For feature requests and bug reports, please create an [issue](https://github.com/angt/glorytun/issues).

2
argz

Submodule argz updated: ff7bc660e2...f88a280d2b

View File

@@ -23,18 +23,19 @@ executable('glorytun', install: true,
sources: [
'argz/argz.c',
'mud/mud.c',
'mud/aegis256/aegis256.c',
'src/bench.c',
'src/bind.c',
'src/common.c',
'src/ctl.c',
'src/iface.c',
'src/keygen.c',
'src/list.c',
'src/main.c',
'src/path.c',
'src/set.c',
'src/show.c',
'src/tun.c',
'src/version.c',
],
dependencies: [
dependency('libsodium', version : '>=1.0.4'),

2
mud

Submodule mud updated: d0dc6076c8...e4988b9e9c

View File

@@ -1,14 +1,12 @@
#include "common.h"
#include <sodium.h>
#include <string.h>
#include <stdio.h>
#include <time.h>
#include <unistd.h>
#include <inttypes.h>
#include <sodium.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include "../argz/argz.h"
#include "../mud/aegis256/aegis256.h"
#define NPUBBYTES 32
#define KEYBYTES 32
@@ -33,7 +31,7 @@ gt_bench(int argc, char **argv)
int aes = argz_is_set(bench_argz, "aes");
int chacha = argz_is_set(bench_argz, "chacha");
if (!aegis256_is_available()) {
if (!crypto_aead_aegis256_is_available()) {
if (aes) {
gt_log("aes is not available on your platform\n");
return 1;
@@ -60,7 +58,7 @@ gt_bench(int argc, char **argv)
for (int i = 0; !gt_quit && size <= 1450; i++) {
struct {
int64_t min, mean, max, n;
} mbps = { .n = 0 };
} mbps = {.n = 0};
int64_t bytes_max = (int64_t)1 << 24;
@@ -71,9 +69,9 @@ gt_bench(int argc, char **argv)
while (!gt_quit && bytes <= bytes_max) {
if (chacha) {
crypto_aead_chacha20poly1305_encrypt(
buf, NULL, buf, size, NULL, 0, NULL, npub, key);
buf, NULL, buf, size, NULL, 0, NULL, npub, key);
} else {
aegis256_encrypt(buf, NULL, buf, size, NULL, 0, npub, key);
crypto_aead_aegis256_encrypt(buf, NULL, buf, size, NULL, 0, NULL, npub, key);
}
bytes += size;
}

View File

@@ -2,11 +2,9 @@
#include "ctl.h"
#include "iface.h"
#include "ip.h"
#include "str.h"
#include "tun.h"
#include <fcntl.h>
#include <stdio.h>
#include <sys/select.h>
#include "../argz/argz.h"
@@ -91,7 +89,7 @@ gt_setup_mtu(struct mud *mud, size_t old, const char *tun_name)
{
size_t mtu = mud_get_mtu(mud);
if (mtu == old)
if (!mtu || mtu == old)
return mtu;
if (iface_set_mtu(tun_name, mtu) == -1)
@@ -103,8 +101,8 @@ gt_setup_mtu(struct mud *mud, size_t old, const char *tun_name)
int
gt_bind(int argc, char **argv)
{
struct sockaddr_storage bind_addr = { .ss_family = AF_INET };
struct sockaddr_storage peer_addr = { 0 };
struct sockaddr_storage bind_addr = {.ss_family = AF_INET};
struct sockaddr_storage peer_addr = {0};
unsigned short bind_port = 5000;
unsigned short peer_port = bind_port;
const char *dev = NULL;
@@ -128,7 +126,7 @@ gt_bind(int argc, char **argv)
if (argz(bindz, argc, argv))
return 1;
if (str_empty(keyfile)) {
if (EMPTY(keyfile)) {
gt_log("a keyfile is needed!\n");
return 1;
}
@@ -175,7 +173,7 @@ gt_bind(int argc, char **argv)
if (tun_set_persist(tun_fd, persist) == -1) {
gt_log("couldn't %sable persist mode on device %s\n",
persist ? "en" : "dis", tun_name);
persist ? "en" : "dis", tun_name);
}
if (peer_addr.ss_family) {
@@ -185,11 +183,16 @@ gt_bind(int argc, char **argv)
}
}
const int ctl_fd = ctl_create(GT_RUNDIR, tun_name);
const int ctl_fd = ctl_create(tun_name);
if (ctl_fd == -1) {
gt_log("couldn't create "GT_RUNDIR"/%s: %s\n",
tun_name, strerror(errno));
char dir[64];
if (ctl_rundir(dir, sizeof(dir))) {
gt_log("couldn't create %s/%s: %s\n",
dir, tun_name, strerror(errno));
} else {
gt_log("couldn't find a writable run/tmp directory\n");
}
return 1;
}
@@ -216,48 +219,31 @@ gt_bind(int argc, char **argv)
int last_fd = MAX(tun_fd, mud_fd);
last_fd = 1 + MAX(last_fd, ctl_fd);
unsigned char buf[4096];
__attribute__((aligned(16)))
unsigned char buf[1500];
while (!gt_quit) {
if (tun_can_write) {
FD_CLR(tun_fd, &wfds);
} else {
FD_SET(tun_fd, &wfds);
}
if (mud_can_write) {
FD_CLR(mud_fd, &wfds);
} else {
FD_SET(mud_fd, &wfds);
}
if (tun_can_read) {
FD_CLR(tun_fd, &rfds);
} else {
FD_SET(tun_fd, &rfds);
}
if (mud_can_read) {
FD_CLR(mud_fd, &rfds);
} else {
FD_SET(mud_fd, &rfds);
}
if (tun_can_write) FD_CLR(tun_fd, &wfds); else FD_SET(tun_fd, &wfds);
if (mud_can_write) FD_CLR(mud_fd, &wfds); else FD_SET(mud_fd, &wfds);
if (tun_can_read) FD_CLR(tun_fd, &rfds); else FD_SET(tun_fd, &rfds);
if (mud_can_read) FD_CLR(mud_fd, &rfds); else FD_SET(mud_fd, &rfds);
FD_SET(ctl_fd, &rfds);
struct timeval tv = {
.tv_usec = 100000,
};
struct timeval tv = {0};
int update = mud_update(mud);
if (mud_can_read && tun_can_write) {
tv.tv_usec = 0;
} else if (tun_can_read && mud_can_write) {
long send_wait = mud_send_wait(mud);
if (send_wait >= 0)
tv.tv_usec = send_wait * 1000;
if (update >= 0) {
if (mud_can_read && tun_can_write) {
} else if (tun_can_read && mud_can_write) {
if (update)
tv.tv_usec = 1000;
} else {
tv.tv_usec = 100000;
}
}
const int ret = select(last_fd, &rfds, &wfds, NULL, &tv);
const int ret = select(last_fd, &rfds, &wfds, NULL, update < 0 ? NULL : &tv);
if (ret == -1) {
if (errno == EBADF) {
@@ -267,17 +253,10 @@ gt_bind(int argc, char **argv)
continue;
}
if (FD_ISSET(tun_fd, &rfds))
tun_can_read = 1;
if (FD_ISSET(tun_fd, &wfds))
tun_can_write = 1;
if (FD_ISSET(mud_fd, &rfds))
mud_can_read = 1;
if (FD_ISSET(mud_fd, &wfds))
mud_can_write = 1;
if (FD_ISSET(tun_fd, &rfds)) tun_can_read = 1;
if (FD_ISSET(tun_fd, &wfds)) tun_can_write = 1;
if (FD_ISSET(mud_fd, &rfds)) mud_can_read = 1;
if (FD_ISSET(mud_fd, &wfds)) mud_can_write = 1;
mtu = gt_setup_mtu(mud, mtu, tun_name);
@@ -286,14 +265,14 @@ gt_bind(int argc, char **argv)
int r = tun_read(tun_fd, buf, sizeof(buf));
if (r > 0 && !ip_get_common(&ic, buf, r)) {
mud_send(mud, buf, (size_t)r, ic.tc);
mud_send(mud, buf, (size_t)r);
mud_can_write = 0;
}
tun_can_read = 0;
}
if (mud_can_read && tun_can_write) {
if (mud_can_read && tun_can_write) {
int r = mud_recv(mud, buf, sizeof(buf));
if (r > 0 && ip_is_valid(buf, r)) {
@@ -320,47 +299,18 @@ gt_bind(int argc, char **argv)
break;
case CTL_STATE:
if (mud_set_state(mud, (struct sockaddr *)&req.path.addr,
req.path.state, req.path.rate_tx, req.path.rate_rx))
req.path.state,
req.path.rate_tx,
req.path.rate_rx,
req.path.beat,
req.path.fixed_rate,
req.path.loss_limit))
res.ret = errno;
break;
case CTL_PATH_STATUS:
{
unsigned count = 0;
struct mud_path *paths = mud_get_paths(mud, &count);
if (!paths) {
res.ret = errno;
break;
}
res.ret = EAGAIN;
for (unsigned i = 0; i < count; i++) {
memcpy(&res.path_status, &paths[i], sizeof(struct mud_path));
if (sendto(ctl_fd, &res, sizeof(res), 0,
(const struct sockaddr *)&ss, sl) == -1)
perror("sendto(ctl)");
}
free(paths);
res.ret = 0;
}
break;
case CTL_MTU:
mud_set_mtu(mud, req.mtu);
res.mtu = mtu = gt_setup_mtu(mud, mtu, tun_name);
break;
case CTL_TC:
if (mud_set_tc(mud, req.tc))
res.ret = errno;
break;
case CTL_KXTIMEOUT:
if (mud_set_keyx_timeout(mud, req.ms))
res.ret = errno;
break;
case CTL_TIMETOLERANCE:
if (mud_set_time_tolerance(mud, req.ms))
case CTL_CONF:
if (mud_set_conf(mud, &req.conf))
res.ret = errno;
res.conf = req.conf;
break;
case CTL_STATUS:
memcpy(res.status.tun_name, tun_name, sizeof(tun_name)); // XXX
@@ -370,6 +320,27 @@ gt_bind(int argc, char **argv)
res.status.bind = bind_addr;
res.status.peer = peer_addr;
break;
case CTL_PATH_STATUS: {
unsigned count = 0;
struct mud_path *paths = mud_get_paths(mud, &count);
if (!paths) {
res.ret = errno;
break;
}
res.ret = EAGAIN;
for (unsigned i = 0; i < count; i++) {
memcpy(&res.path_status, &paths[i], sizeof(struct mud_path));
if (sendto(ctl_fd, &res, sizeof(res), 0,
(const struct sockaddr *)&ss, sl) == -1)
perror("sendto(ctl)");
}
free(paths);
res.ret = 0;
} break;
case CTL_BAD:
if (mud_get_bad(mud, &res.bad))
res.ret = errno;

View File

@@ -114,3 +114,79 @@ gt_toaddr(char *str, size_t size, struct sockaddr *sa)
errno = EAFNOSUPPORT;
return -1;
}
int
gt_totime(char *str, size_t size, unsigned long long t)
{
if (!str || size < 4) {
errno = EINVAL;
return -1;
}
if (!t) {
memcpy(str, "now", 4);
return 0;
}
struct {
unsigned long long v;
unsigned long long n;
char *name;
} u[] = {
{0, 1000, "ms"},
{0, 60, "s"},
{0, 60, "m"},
{0, 24, "h"},
{0, 0, "d"},
};
size_t len = 0;
unsigned i = 0;
while (u[i].n) {
u[i].v = t % u[i].n;
t /= u[i].n;
i++;
}
u[i++].v = t;
while (i--)
if (u[i].v) {
int ret = snprintf(str + len, size - len, "%llu%s", u[i].v, u[i].name);
if (ret <= 0 || (size_t)ret >= size - len) {
errno = EINVAL;
return -1;
}
len += ret;
}
return 0;
}
int
gt_torate(char *str, size_t size, unsigned long long r)
{
if (!str || size < 5) {
errno = EINVAL;
return -1;
}
unsigned k = 0;
while (r && k < 4 && !(r % 1000)) {
r /= 1000;
k++;
}
int ret = snprintf(str, size, "%llu%sbit%s", r,
&"\0\0k\0M\0G\0T"[k << 1],
&"s"[r <= 1]);
if (ret <= 0 || (size_t)ret >= size) {
errno = EINVAL;
return -1;
}
return 0;
}

View File

@@ -4,14 +4,17 @@
#define _GNU_SOURCE
#endif
#include <stdlib.h>
#include <errno.h>
#include <signal.h>
#include <stdint.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <errno.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/socket.h>
#ifndef PACKAGE_NAME
#define PACKAGE_NAME "glorytun"
@@ -21,58 +24,51 @@
#define PACKAGE_VERSION "0.0.0"
#endif
#ifndef GT_RUNDIR
#define GT_RUNDIR "/run/" PACKAGE_NAME
#endif
#define COUNT(x) (sizeof(x) / sizeof(x[0]))
#define COUNT(x) (sizeof(x)/sizeof(x[0]))
#define _1_(x) (__builtin_expect((x), 1))
#define _0_(x) (__builtin_expect((x), 0))
#define CLZ(x) (__builtin_clz(x))
#define ALIGN_SIZE (1<<4)
#define ALIGN_MASK (ALIGN_SIZE-1)
#define ALIGN(x) (((x)+ALIGN_MASK)&~ALIGN_MASK)
#define ALIGN_DOWN(x) ((x)&~ALIGN_MASK)
#define PALIGN(x) ((void *)ALIGN((size_t)(x)))
#define PALIGN_DOWN(x) ((void *)ALIGN_DOWN((size_t)(x)))
#define _1_(x) (__builtin_expect((x), 1))
#define _0_(x) (__builtin_expect((x), 0))
#define CLZ(x) (__builtin_clz(x))
#define _printf_(A,B) __attribute__ ((format(printf,A,B)))
#define _noreturn_ __attribute__ ((noreturn))
#define _unused_ __attribute__ ((unused))
#define _pure_ __attribute__ ((pure))
#define _const_ __attribute__ ((const))
#define _align_(...) __attribute__ ((aligned(__VA_ARGS__)))
#define _printf_(A, B) __attribute__((format(printf, A, B)))
#define _noreturn_ __attribute__((noreturn))
#define _unused_ __attribute__((unused))
#define _pure_ __attribute__((pure))
#define _const_ __attribute__((const))
#define _align_(...) __attribute__((aligned(__VA_ARGS__)))
#undef MAX
#define MAX(x,y) ({ __typeof__(x) X=(x); __typeof__(y) Y=(y); X > Y ? X : Y; })
#define MAX(x, y) ({ __typeof__(x) X=(x); __typeof__(y) Y=(y); X > Y ? X : Y; })
#undef MIN
#define MIN(x,y) ({ __typeof__(x) X=(x); __typeof__(y) Y=(y); X < Y ? X : Y; })
#define MIN(x, y) ({ __typeof__(x) X=(x); __typeof__(y) Y=(y); X < Y ? X : Y; })
#define GT_CIPHER(x) ((x) ? "chacha20poly1305" : "aegis256")
#define EMPTY(x) ({ __typeof__(x) X=(x); !X || !X[0]; })
#define GT_CIPHER(x) ((x) ? "chacha20poly1305" : "aegis256")
extern volatile sig_atomic_t gt_alarm;
extern volatile sig_atomic_t gt_reload;
extern volatile sig_atomic_t gt_quit;
int gt_print (const char *, ...) _printf_(1,2);
void gt_log (const char *, ...) _printf_(1,2);
int gt_print (const char *, ...) _printf_(1, 2);
void gt_log (const char *, ...) _printf_(1, 2);
int gt_tohex (char *, size_t, const uint8_t *, size_t);
int gt_fromhex (uint8_t *, size_t, const char *, size_t);
void gt_set_port (struct sockaddr *, uint16_t);
uint16_t gt_get_port (struct sockaddr *);
int gt_toaddr (char *, size_t, struct sockaddr *);
int gt_show (int, char **);
int gt_bind (int, char **);
int gt_path (int, char **);
int gt_keygen (int, char **);
int gt_bench (int, char **);
int gt_set (int, char **);
int gt_toaddr (char *, size_t, struct sockaddr *);
int gt_totime (char *, size_t, unsigned long long);
int gt_torate (char *, size_t, unsigned long long);
int gt_list (int, char **);
int gt_show (int, char **);
int gt_bind (int, char **);
int gt_path (int, char **);
int gt_keygen (int, char **);
int gt_bench (int, char **);
int gt_set (int, char **);
int gt_version (int, char **);

View File

@@ -1,15 +1,45 @@
#include "common.h"
#include "ctl.h"
#include "str.h"
#include "common.h"
#include <stdio.h>
#include <unistd.h>
#include <dirent.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <libgen.h>
#include <stdio.h>
#include <sys/stat.h>
#include <sys/un.h>
char *
ctl_rundir(char *dst, size_t size)
{
if (dst && size)
dst[0] = 0;
const char *fmt[] = {
"/run/user/%u/" PACKAGE_NAME,
"/run/" PACKAGE_NAME ".%u",
"/var/run/" PACKAGE_NAME ".%u",
"/tmp/" PACKAGE_NAME ".%u",
};
for (unsigned i = 0; i < COUNT(fmt); i++) {
char path[128];
int ret = snprintf(dst, size, fmt[i], geteuid());
if ((ret <= 0) ||
((size_t)ret >= size) ||
((size_t)ret >= sizeof(path)))
continue;
memcpy(path, dst, (size_t)ret + 1);
char *p = dirname(path);
if (p && !access(p, W_OK))
return dst;
}
errno = EPERM;
return NULL;
}
int
ctl_reply(int fd, struct ctl_msg *res, struct ctl_msg *req)
{
@@ -53,10 +83,10 @@ ctl_setsun(struct sockaddr_un *dst, const char *dir, const char *file)
static int
ctl_bind(int fd, const char *dir, const char *file)
{
char name[10] = { [0] = '.' };
char name[10] = {[0] = '.'};
struct sockaddr_un sun;
if (str_empty(file)) {
if (EMPTY(file)) {
unsigned pid = (unsigned)getpid();
for (size_t i = 1; i < sizeof(name) - 1; i++, pid >>= 4)
@@ -77,7 +107,7 @@ ctl_bind(int fd, const char *dir, const char *file)
void
ctl_delete(int fd)
{
struct sockaddr_storage ss = { 0 };
struct sockaddr_storage ss = {0};
socklen_t sslen = sizeof(ss);
if ((getsockname(fd, (struct sockaddr *)&ss, &sslen) == 0) &&
@@ -88,12 +118,12 @@ ctl_delete(int fd)
}
int
ctl_create(const char *dir, const char *file)
ctl_create(const char *file)
{
if (str_empty(dir)) {
errno = EINVAL;
char dir[64];
if (!ctl_rundir(dir, sizeof(dir)))
return -1;
}
if (mkdir(dir, 0700) == -1 && errno != EEXIST)
return -1;
@@ -111,18 +141,17 @@ ctl_create(const char *dir, const char *file)
}
int
ctl_connect(const char *dir, const char *file)
ctl_connect(const char *file)
{
char dir[64];
DIR *dp = NULL;
if (str_empty(dir)) {
errno = EINVAL;
if (!ctl_rundir(dir, sizeof(dir)))
return -1;
}
if (!file) {
if (dp = opendir(dir), !dp)
return -1;
return CTL_ERROR_NONE;
struct dirent *d = NULL;
@@ -156,9 +185,10 @@ ctl_connect(const char *dir, const char *file)
if (ret)
return -1;
int fd = ctl_create(dir, NULL);
int fd = socket(AF_UNIX, SOCK_DGRAM, 0);
if (connect(fd, (struct sockaddr *)&sun, sizeof(sun))) {
if (ctl_bind(fd, dir, NULL) ||
connect(fd, (struct sockaddr *)&sun, sizeof(sun))) {
int err = errno;
ctl_delete(fd);
errno = err;
@@ -167,3 +197,23 @@ ctl_connect(const char *dir, const char *file)
return fd;
}
void
ctl_explain_connect(int ret)
{
switch (ret) {
case 0:
break;
case CTL_ERROR_MANY:
gt_log("please select a tunnel\n");
break;
case CTL_ERROR_NONE:
gt_log("no active tunnel\n");
break;
default:
gt_log("unknown error\n"); /* FALLTHRU */
case -1:
if (errno)
perror("connect");
}
}

View File

@@ -10,11 +10,8 @@
enum ctl_type {
CTL_NONE = 0,
CTL_STATE,
CTL_CONF,
CTL_STATUS,
CTL_MTU,
CTL_TC,
CTL_KXTIMEOUT,
CTL_TIMETOLERANCE,
CTL_PATH_STATUS,
CTL_BAD,
};
@@ -28,8 +25,10 @@ struct ctl_msg {
enum mud_state state;
unsigned long rate_tx;
unsigned long rate_rx;
unsigned long beat;
unsigned char fixed_rate;
unsigned char loss_limit;
} path;
struct mud_path path_status;
struct {
char tun_name[64];
long pid;
@@ -38,14 +37,16 @@ struct ctl_msg {
struct sockaddr_storage bind;
struct sockaddr_storage peer;
} status;
struct mud_conf conf;
struct mud_path path_status;
struct mud_bad bad;
size_t mtu;
int tc;
unsigned long ms;
};
};
int ctl_create (const char *, const char *);
int ctl_connect (const char *, const char *);
int ctl_reply (int, struct ctl_msg *, struct ctl_msg *);
void ctl_delete (int);
char *ctl_rundir (char *, size_t);
int ctl_create (const char *);
int ctl_connect (const char *);
int ctl_reply (int, struct ctl_msg *, struct ctl_msg *);
void ctl_delete (int);
void ctl_explain_connect (int);

View File

@@ -1,8 +1,8 @@
#include "common.h"
#include "iface.h"
#include "common.h"
#include <stdio.h>
#include <net/if.h>
#include <stdio.h>
#include <sys/ioctl.h>
int

View File

@@ -1,3 +1,5 @@
#pragma once
#include <stddef.h>
int iface_set_mtu (const char *, size_t);

47
src/list.c Normal file
View File

@@ -0,0 +1,47 @@
#include "common.h"
#include "ctl.h"
#include "../argz/argz.h"
#include <dirent.h>
#include <stdio.h>
int
gt_list(int argc, char **argv)
{
struct argz showz[] = {
{"list", NULL, NULL, argz_option},
{NULL}};
if (argz(showz, argc, argv))
return 1;
char dir[64];
if (!ctl_rundir(dir, sizeof(dir)))
return 0;
DIR *dp = opendir(dir);
if (!dp)
return 0;
struct dirent *d = NULL;
while (d = readdir(dp), d) {
if (d->d_name[0] == '.')
continue;
int fd = ctl_connect(d->d_name);
if (fd < 0)
continue;
printf("%s\n", d->d_name);
close(fd);
}
closedir(dp);
return 0;
}

View File

@@ -1,7 +1,5 @@
#include "common.h"
#include "str.h"
#include <sodium.h>
#include <stdio.h>
#include "../argz/argz.h"
@@ -46,25 +44,6 @@ gt_set_signal(void)
sigaction(SIGUSR2, &sa, NULL);
}
static int
gt_version(int argc, char **argv)
{
struct argz version_argz[] = {
{"libsodium", NULL, NULL, argz_option},
{NULL}};
if (argz(version_argz, argc, argv))
return 1;
if (argz_is_set(version_argz, "libsodium")) {
printf("%s\n", sodium_version_string());
} else {
printf("%s\n", PACKAGE_VERSION);
}
return 0;
}
int
main(int argc, char **argv)
{
@@ -75,7 +54,8 @@ main(int argc, char **argv)
char *help;
int (*call)(int, char **);
} cmd[] = {
{"show", "show tunnel info", gt_show},
{"list", "list all tunnels", gt_list},
{"show", "show tunnel information", gt_show},
{"bench", "start a crypto bench", gt_bench},
{"bind", "start a new tunnel", gt_bind},
{"set", "change tunnel properties", gt_set},
@@ -86,7 +66,7 @@ main(int argc, char **argv)
if (argv[1]) {
for (int k = 0; cmd[k].name; k++) {
if (!str_cmp(cmd[k].name, argv[1]))
if (!strcmp(cmd[k].name, argv[1]))
return cmd[k].call(argc - 1, argv + 1);
}
}
@@ -96,10 +76,10 @@ main(int argc, char **argv)
int len = 0;
for (int k = 0; cmd[k].name; k++)
len = MAX(len, (int)str_len(cmd[k].name, 32));
len = MAX(len, (int)strlen(cmd[k].name));
for (int k = 0; cmd[k].name; k++)
printf(" %-*s %s\n", len, cmd[k].name, cmd[k].help);
printf(" %-*s %s\n", len, cmd[k].name, cmd[k].help);
printf("\n");

View File

@@ -1,77 +1,46 @@
#include "common.h"
#include "ctl.h"
#include "str.h"
#include <stdio.h>
#include <sys/socket.h>
#include <unistd.h>
#include "../argz/argz.h"
static void
gt_path_print_status(struct mud_path *path, int term)
gt_path_print(struct mud_path *path, int term)
{
char bindstr[INET6_ADDRSTRLEN];
char publstr[INET6_ADDRSTRLEN];
char peerstr[INET6_ADDRSTRLEN];
gt_toaddr(bindstr, sizeof(bindstr),
(struct sockaddr *)&path->local_addr);
gt_toaddr(publstr, sizeof(publstr),
(struct sockaddr *)&path->r_addr);
gt_toaddr(peerstr, sizeof(peerstr),
(struct sockaddr *)&path->addr);
const char *statestr = NULL;
char bindstr[INET6_ADDRSTRLEN];
char beatstr[32];
char txstr[32], rxstr[32];
switch (path->state) {
case MUD_UP: statestr = "UP"; break;
case MUD_BACKUP: statestr = "BACKUP"; break;
case MUD_DOWN: statestr = "DOWN"; break;
case MUD_UP: statestr = "up"; break;
case MUD_BACKUP: statestr = "backup"; break;
case MUD_DOWN: statestr = "down"; break;
default: return;
}
const char *statusstr = path->ok ? "OK" : "DEGRADED";
if (gt_toaddr(bindstr, sizeof(bindstr),
(struct sockaddr *)&path->local_addr))
return;
printf(term ? "path %s\n"
" status: %s\n"
" bind: %s port %"PRIu16"\n"
" public: %s port %"PRIu16"\n"
" peer: %s port %"PRIu16"\n"
" mtu: %zu bytes\n"
" rtt: %.3f ms\n"
" rttvar: %.3f ms\n"
" tx:\n"
" rate: %"PRIu64" bytes/sec\n"
" loss: %"PRIu64" percent\n"
" total: %"PRIu64" packets\n"
" rx:\n"
" rate: %"PRIu64" bytes/sec\n"
" loss: %"PRIu64" percent\n"
" total: %"PRIu64" packets\n"
: "path %s %s"
" %s %"PRIu16" %s %"PRIu16" %s %"PRIu16
" %zu %.3f %.3f"
" %"PRIu64" %"PRIu64" %"PRIu64
" %"PRIu64" %"PRIu64" %"PRIu64
"\n",
statestr,
statusstr,
bindstr[0] ? bindstr : "-",
gt_get_port((struct sockaddr *)&path->local_addr),
publstr[0] ? publstr : "-",
gt_get_port((struct sockaddr *)&path->r_addr),
peerstr[0] ? peerstr : "-",
gt_get_port((struct sockaddr *)&path->addr),
path->mtu.ok,
(double)path->rtt.val / 1e3,
(double)path->rtt.var / 1e3,
path->tx.rate,
path->tx.loss,
path->tx.total,
path->rx.rate,
path->rx.loss,
path->rx.total);
if (gt_totime(beatstr, sizeof(beatstr), path->conf.beat / 1000))
return;
if (gt_torate(txstr, sizeof(txstr), path->conf.tx_max_rate * 8))
return;
if (gt_torate(rxstr, sizeof(rxstr), path->conf.rx_max_rate * 8))
return;
printf(term ? "path %s %s losslimit %u%% beat %s "
"rate %s tx %s rx %s\n"
: "path %s %s %u %s %s %s %s\n",
statestr, bindstr,
path->conf.loss_limit * 100U / 255U,
beatstr,
path->conf.fixed_rate ? "fixed" : "auto",
txstr, rxstr);
}
static int
@@ -96,7 +65,7 @@ gt_path_cmp_addr(struct sockaddr_storage *a, struct sockaddr_storage *b)
}
static int
gt_path_status(int fd, int state, struct sockaddr_storage *addr)
gt_path_print_all(int fd, enum mud_state state, struct sockaddr_storage *addr)
{
struct ctl_msg req = {
.type = CTL_PATH_STATUS,
@@ -128,10 +97,15 @@ gt_path_status(int fd, int state, struct sockaddr_storage *addr)
int term = isatty(1);
if (!term)
printf("# STATE ADDR LOSSLIMIT BEAT RATE TX RX\n");
for (int i = 0; i < count; i++) {
if ((state == MUD_EMPTY || path[i].state == state) &&
(!addr->ss_family || !gt_path_cmp_addr(addr, &path[i].local_addr)))
gt_path_print_status(&path[i], term);
if (state && path[i].state != state)
continue;
if (addr->ss_family && gt_path_cmp_addr(addr, &path[i].local_addr))
continue;
gt_path_print(&path[i], term);
}
return 0;
@@ -141,6 +115,7 @@ int
gt_path(int argc, char **argv)
{
const char *dev = NULL;
unsigned int loss_limit = 0;
struct ctl_msg req = {
.type = CTL_STATE,
@@ -150,6 +125,7 @@ gt_path(int argc, char **argv)
}, res = {0};
struct argz ratez[] = {
{"fixed|auto", NULL, NULL, argz_option},
{"tx", "BYTES/SEC", &req.path.rate_tx, argz_bytes},
{"rx", "BYTES/SEC", &req.path.rate_rx, argz_bytes},
{NULL}};
@@ -159,33 +135,25 @@ gt_path(int argc, char **argv)
{"dev", "NAME", &dev, argz_str},
{"up|backup|down", NULL, NULL, argz_option},
{"rate", NULL, &ratez, argz_option},
{"beat", "SECONDS", &req.path.beat, argz_time},
{"losslimit", "PERCENT", &loss_limit, argz_percent},
{NULL}};
if (argz(pathz, argc, argv))
return 1;
int fd = ctl_connect(GT_RUNDIR, dev);
int fd = ctl_connect(dev);
if (fd < 0) {
switch (fd) {
case -1:
perror("path");
break;
case CTL_ERROR_NONE:
gt_log("no device\n");
break;
case CTL_ERROR_MANY:
gt_log("please choose a device\n");
break;
default:
gt_log("couldn't connect\n");
}
ctl_explain_connect(fd);
return 1;
}
int set_rate = argz_is_set(pathz, "rate");
int set = argz_is_set(pathz, "rate")
|| argz_is_set(pathz, "beat")
|| argz_is_set(pathz, "losslimit");
if (set_rate && !req.path.addr.ss_family) {
if (set && !req.path.addr.ss_family) {
gt_log("please specify a path\n");
return 1;
}
@@ -198,15 +166,23 @@ gt_path(int argc, char **argv)
req.path.state = MUD_DOWN;
}
int ret;
if (loss_limit)
req.path.loss_limit = loss_limit * 255 / 100;
if (!req.path.addr.ss_family ||
(req.path.state == MUD_EMPTY && !set_rate)) {
ret = gt_path_status(fd, req.path.state, &req.path.addr);
} else {
ret = ctl_reply(fd, &res, &req);
if (argz_is_set(ratez, "fixed")) {
req.path.fixed_rate = 3;
} else if (argz_is_set(ratez, "auto")) {
req.path.fixed_rate = 1;
}
int ret = 0;
if (req.path.addr.ss_family && (req.path.state || set))
ret = ctl_reply(fd, &res, &req);
if (!ret)
ret = gt_path_print_all(fd, req.path.state, &req.path.addr);
if (ret == -1)
perror("path");

129
src/set.c
View File

@@ -1,86 +1,10 @@
#include "common.h"
#include "ctl.h"
#include "str.h"
#include <stdio.h>
#include <sys/socket.h>
#include "../argz/argz.h"
static int
gt_set_mtu(int fd, size_t mtu)
{
struct ctl_msg res, req = {
.type = CTL_MTU,
.mtu = mtu,
};
int ret = ctl_reply(fd, &res, &req);
if (ret) {
perror("set mtu");
return 1;
}
printf("mtu set to %zu\n", res.mtu);
return 0;
}
static int
gt_set_kxtimeout(int fd, unsigned long ms)
{
struct ctl_msg res, req = {
.type = CTL_KXTIMEOUT,
.ms = ms,
};
int ret = ctl_reply(fd, &res, &req);
if (ret) {
perror("set kxtimeout");
return 1;
}
return 0;
}
static int
gt_set_timetolerance(int fd, unsigned long ms)
{
struct ctl_msg res, req = {
.type = CTL_TIMETOLERANCE,
.ms = ms,
};
int ret = ctl_reply(fd, &res, &req);
if (ret) {
perror("set timetolerance");
return 1;
}
return 0;
}
static int
gt_set_tc(int fd, int tc)
{
struct ctl_msg res, req = {
.type = CTL_TC,
.tc = tc,
};
int ret = ctl_reply(fd, &res, &req);
if (ret) {
perror("set tc");
return 1;
}
return 0;
}
static int
gt_argz_tc(void *data, int argc, char **argv)
{
@@ -111,56 +35,55 @@ int
gt_set(int argc, char **argv)
{
const char *dev = NULL;
size_t mtu;
int tc;
unsigned long kxtimeout;
unsigned long timetolerance;
unsigned long keepalive;
int tc;
struct argz pathz[] = {
{"dev", "NAME", &dev, argz_str},
{"mtu", "BYTES", &mtu, argz_bytes},
{"tc", "CS|AF|EF", &tc, gt_argz_tc},
{"kxtimeout", "SECONDS", &kxtimeout, argz_time},
{"timetolerance", "SECONDS", &timetolerance, argz_time},
{"keepalive", "SECONDS", &keepalive, argz_time},
{NULL}};
if (argz(pathz, argc, argv))
return 1;
int fd = ctl_connect(GT_RUNDIR, dev);
struct ctl_msg req = {
.type = CTL_CONF,
.conf = {
.tc = tc ? (tc << 1) | 1 : 0,
.kxtimeout = kxtimeout * UINT64_C(1000),
.timetolerance = timetolerance * UINT64_C(1000),
.keepalive = keepalive * UINT64_C(1000),
},
}, res = {0};
int fd = ctl_connect(dev);
if (fd < 0) {
switch (fd) {
case -1:
perror("set");
break;
case CTL_ERROR_NONE:
gt_log("no device\n");
break;
case CTL_ERROR_MANY:
gt_log("please choose a device\n");
break;
default:
gt_log("couldn't connect\n");
}
ctl_explain_connect(fd);
return 1;
}
int ret = 0;
int ret = ctl_reply(fd, &res, &req);
if (argz_is_set(pathz, "mtu"))
ret |= gt_set_mtu(fd, mtu);
char t0[32];
char t1[32];
char t2[32];
if (argz_is_set(pathz, "tc"))
ret |= gt_set_tc(fd, tc);
gt_totime(t0, sizeof(t0), res.conf.kxtimeout / 1000);
gt_totime(t1, sizeof(t1), res.conf.timetolerance / 1000);
gt_totime(t2, sizeof(t2), res.conf.keepalive / 1000);
if (argz_is_set(pathz, "kxtimeout"))
ret |= gt_set_kxtimeout(fd, kxtimeout);
printf("set kxtimeout %s timetolerance %s keepalive %s tc %i\n", t0, t1, t2, res.conf.tc);
if (argz_is_set(pathz, "timetolerance"))
ret |= gt_set_timetolerance(fd, timetolerance);
if (ret)
perror("set");
ctl_delete(fd);
return ret;
return !!ret;
}

View File

@@ -1,15 +1,9 @@
#include "common.h"
#include "ctl.h"
#include "str.h"
#include "../argz/argz.h"
#include <stdio.h>
#include <sys/socket.h>
#include <dirent.h>
#include <sys/un.h>
#include <arpa/inet.h>
#include <unistd.h>
static void
gt_show_bad_line(int term, char *name, uint64_t count,
@@ -129,22 +123,10 @@ gt_show(int argc, char **argv)
if (argz(showz, argc, argv))
return 1;
int fd = ctl_connect(GT_RUNDIR, dev);
int fd = ctl_connect(dev);
if (fd < 0) {
switch (fd) {
case -1:
perror("show");
break;
case CTL_ERROR_NONE:
gt_log("no device\n");
break;
case CTL_ERROR_MANY:
gt_log("please choose a device\n");
break;
default:
gt_log("couldn't connect\n");
}
ctl_explain_connect(fd);
return 1;
}

View File

@@ -1,33 +0,0 @@
#pragma once
#include "common.h"
_pure_ static inline int
str_empty(const char *restrict str)
{
return !str || !str[0];
}
_pure_ static inline size_t
str_cmp(const char *restrict sa, const char *restrict sb)
{
if (!sa || !sb)
return 1;
size_t i = 0;
while (sa[i] == sb[i])
if (!sa[i++])
return 0;
return i + 1;
}
_pure_ static inline size_t
str_len(const char *restrict str, size_t len)
{
if (!str)
return 0;
return strnlen(str, len);
}

View File

@@ -1,14 +1,13 @@
#include "tun.h"
#include "common.h"
#include "ip.h"
#include "str.h"
#include "tun.h"
#include <fcntl.h>
#include <net/if.h>
#include <stdio.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/uio.h>
#include <net/if.h>
#ifdef __linux__
#define IFF_TUN 0x0001
@@ -131,13 +130,21 @@ tun_create_by_name(char *name, size_t len, const char *dev_name)
static int
tun_create_by_name(char *name, size_t len, const char *dev_name)
{
int ret = snprintf(name, len, "/dev/%s", dev_name);
int ret = snprintf(name, len, "%s", dev_name);
if (ret <= 0 || (size_t)ret >= len) {
errno = EINVAL;
return -1;
}
char tmp[64];
ret = snprintf(tmp, sizeof(tmp), "/dev/%s", dev_name);
if (ret <= 0 || (size_t)ret >= sizeof(tmp)) {
errno = EINVAL;
return -1;
}
return open(tmp, O_RDWR);
}
@@ -164,7 +171,7 @@ tun_create(char *name, size_t len, const char *dev_name)
{
int fd = -1;
if (str_empty(dev_name)) {
if (EMPTY(dev_name)) {
for (unsigned id = 0; id < 32 && fd == -1; id++)
fd = tun_create_by_id(name, len, id);
} else {

View File

@@ -1,5 +1,7 @@
#pragma once
#include <stddef.h>
int tun_create (char *, size_t, const char *);
int tun_read (int, void *, size_t);
int tun_write (int, const void *, size_t);

27
src/version.c Normal file
View File

@@ -0,0 +1,27 @@
#include "common.h"
#include <sodium.h>
#include "../argz/argz.h"
int
gt_version(int argc, char **argv)
{
struct argz version_argz[] = {
{"libsodium", NULL, NULL, argz_option},
{NULL}};
if (argz(version_argz, argc, argv))
return 1;
if (argz_is_set(version_argz, "libsodium")) {
printf("%i.%i (%s)\n",
sodium_library_version_major(),
sodium_library_version_minor(),
sodium_version_string());
} else {
printf("%s\n", PACKAGE_VERSION);
}
return 0;
}