Compare commits

..

19 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
22 changed files with 383 additions and 304 deletions

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

@@ -2,31 +2,37 @@ NAME := glorytun
VERSION := $(shell ./version.sh)
DIST := $(NAME)-$(VERSION)
CFLAGS ?= -std=c11 -O2 -Wall -fstack-protector-strong
FLAGS := $(CFLAGS) $(LDFLAGS) $(CPPFLAGS)
CC ?= cc
DESTDIR ?=
prefix ?= /usr
Q := @
CFLAGS := -std=c11 -O2 -Wall -fstack-protector-strong
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 mud/aegis256/aegis256.c $(wildcard src/*.c)
HDR := argz/argz.h mud/mud.h mud/aegis256/aegis256.h $(wildcard src/*.h)
SRC := argz/argz.c mud/mud.c $(wildcard src/*.c)
HDR := argz/argz.h mud/mud.h $(wildcard src/*.h)
$(NAME): $(SRC) $(HDR)
@echo "$(NAME)"
$(Q)$(CC) $(FLAGS) -o $(NAME) $(SRC) -lsodium
$(Q)$(H)$(CC) $(FLAGS) -o $(NAME) $(SRC) -lsodium
$(NAME)-strip: $(NAME)
$(Q)cp $< $@
$(Q)$(H)strip -x $@
.PHONY: install
install: $(NAME)
install: $(NAME)-strip
@echo "$(DESTDIR)$(prefix)/bin/$(NAME)"
$(Q)install -m 755 -d $(DESTDIR)$(prefix)/bin
$(Q)install -m 755 -s $(NAME) $(DESTDIR)$(prefix)/bin
$(Q)install -m 755 $(NAME)-strip $(DESTDIR)$(prefix)/bin/$(NAME)
.PHONY: clean
clean:

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,13 +19,15 @@ 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 \

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: 4a7740f70f...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"
@@ -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) {
@@ -191,7 +189,7 @@ gt_bind(int argc, char **argv)
char dir[64];
if (ctl_rundir(dir, sizeof(dir))) {
gt_log("couldn't create %s/%s: %s\n",
dir, tun_name, strerror(errno));
dir, tun_name, strerror(errno));
} else {
gt_log("couldn't find a writable run/tmp directory\n");
}
@@ -232,7 +230,7 @@ gt_bind(int argc, char **argv)
FD_SET(ctl_fd, &rfds);
struct timeval tv = { 0 };
struct timeval tv = {0};
int update = mud_update(mud);
if (update >= 0) {
@@ -274,7 +272,7 @@ gt_bind(int argc, char **argv)
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)) {
@@ -305,12 +303,14 @@ gt_bind(int argc, char **argv)
req.path.rate_tx,
req.path.rate_rx,
req.path.beat,
req.path.fixed_rate))
req.path.fixed_rate,
req.path.loss_limit))
res.ret = errno;
break;
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
@@ -320,29 +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);
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;
if (!paths) {
res.ret = errno;
break;
}
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,54 +24,51 @@
#define PACKAGE_VERSION "0.0.0"
#endif
#define COUNT(x) (sizeof(x)/sizeof(x[0]))
#define COUNT(x) (sizeof(x) / sizeof(x[0]))
#define ALIGN_SIZE (1<<4)
#define ALIGN_MASK (ALIGN_SIZE-1)
#define _1_(x) (__builtin_expect((x), 1))
#define _0_(x) (__builtin_expect((x), 0))
#define CLZ(x) (__builtin_clz(x))
#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,13 +1,9 @@
#include "common.h"
#include "ctl.h"
#include "str.h"
#include "common.h"
#include <stdio.h>
#include <unistd.h>
#include <dirent.h>
#include <libgen.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <stdio.h>
#include <sys/stat.h>
#include <sys/un.h>
@@ -40,7 +36,7 @@ ctl_rundir(char *dst, size_t size)
return dst;
}
errno = EINTR;
errno = EPERM;
return NULL;
}
@@ -87,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)
@@ -111,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) &&
@@ -155,7 +151,7 @@ ctl_connect(const char *file)
if (!file) {
if (dp = opendir(dir), !dp)
return -1;
return CTL_ERROR_NONE;
struct dirent *d = NULL;
@@ -201,3 +197,23 @@ ctl_connect(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

@@ -27,6 +27,7 @@ struct ctl_msg {
unsigned long rate_rx;
unsigned long beat;
unsigned char fixed_rate;
unsigned char loss_limit;
} path;
struct {
char tun_name[64];
@@ -47,3 +48,5 @@ 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,81 +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;
}
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"
" rate: %s\n"
" beat: %"PRIu64" 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"
" %s"
" %"PRIu64
" %"PRIu64" %"PRIu64" %"PRIu64
" %"PRIu64" %"PRIu64" %"PRIu64
"\n",
statestr,
path->ok ? "OK" : "DEGRADED",
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->conf.fixed_rate ? "fixed" : "auto",
path->conf.beat / 1000,
path->tx.rate,
path->tx.loss * 100 / 255,
path->tx.total,
path->rx.rate,
path->rx.loss * 100 / 255,
path->rx.total);
if (gt_toaddr(bindstr, sizeof(bindstr),
(struct sockaddr *)&path->local_addr))
return;
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
@@ -100,7 +65,7 @@ gt_path_cmp_addr(struct sockaddr_storage *a, struct sockaddr_storage *b)
}
static int
gt_path_status(int fd, enum mud_state 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,
@@ -132,10 +97,15 @@ gt_path_status(int fd, enum mud_state 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;
@@ -145,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,
@@ -165,6 +136,7 @@ gt_path(int argc, char **argv)
{"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))
@@ -173,24 +145,13 @@ gt_path(int argc, char **argv)
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 = argz_is_set(pathz, "rate")
|| argz_is_set(pathz, "beat");
|| argz_is_set(pathz, "beat")
|| argz_is_set(pathz, "losslimit");
if (set && !req.path.addr.ss_family) {
gt_log("please specify a path\n");
@@ -205,20 +166,22 @@ gt_path(int argc, char **argv)
req.path.state = MUD_DOWN;
}
if (loss_limit)
req.path.loss_limit = loss_limit * 255 / 100;
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;
int ret = 0;
if (!req.path.addr.ss_family ||
(req.path.state == MUD_EMPTY && !set)) {
ret = gt_path_status(fd, req.path.state, &req.path.addr);
} else {
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");

View File

@@ -1,9 +1,7 @@
#include "common.h"
#include "ctl.h"
#include "str.h"
#include <stdio.h>
#include <sys/socket.h>
#include "../argz/argz.h"
@@ -28,7 +26,7 @@ gt_argz_tc(void *data, int argc, char **argv)
} else return -1;
if (data)
*(int *)data = (val << 1) | 1;
*(int *)data = val;
return 1;
}
@@ -37,44 +35,51 @@ int
gt_set(int argc, char **argv)
{
const char *dev = NULL;
struct ctl_msg req = {
.type = CTL_CONF,
}, res = {0};
unsigned long kxtimeout;
unsigned long timetolerance;
unsigned long keepalive;
int tc;
struct argz pathz[] = {
{"dev", "NAME", &dev, argz_str},
{"tc", "CS|AF|EF", &req.conf.tc, gt_argz_tc},
{"kxtimeout", "SECONDS", &req.conf.kxtimeout, argz_time},
{"timetolerance", "SECONDS", &req.conf.timetolerance, argz_time},
{"losslimit", "PERCENT", &req.conf.losslimit, argz_percent},
{"keepalive", "SECONDS", &req.conf.keepalive, argz_time},
{"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;
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 = ctl_reply(fd, &res, &req);
char t0[32];
char t1[32];
char t2[32];
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);
printf("set kxtimeout %s timetolerance %s keepalive %s tc %i\n", t0, t1, t2, res.conf.tc);
if (ret)
perror("set");

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,
@@ -132,19 +126,7 @@ gt_show(int argc, char **argv)
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;
}