Compare commits

..

22 Commits

Author SHA1 Message Date
Adrien Gallouët
fd7ddf7814 Update mud
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2019-09-24 09:57:21 +00:00
Adrien Gallouët
7e7b52f9fd Try to limit pkt drops
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2019-09-19 14:00:00 +00:00
Adrien Gallouët
97784c43ac Revert "Try to use submodules"
This reverts commit bccc9945f4.
2019-09-17 17:07:45 +00:00
Adrien Gallouët
4b4c080cc4 Use aegis256
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2019-09-17 16:48:42 +00:00
Adrien Gallouët
43e1dfe86f Update argz
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2019-09-16 15:20:58 +00:00
Adrien Gallouët
ed1cf51af2 Don't use -j alone for portability
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2019-09-16 15:20:41 +00:00
Adrien Gallouët
264f26286d Move static build files in .static
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2019-09-11 21:08:59 +00:00
Adrien Gallouët
7c17e16fea Block on sendmsg and revert 4a68866
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2019-09-09 16:25:35 +00:00
Adrien Gallouët
38d31c0637 Upload artifact
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2019-09-04 10:33:01 +00:00
Adrien Gallouët
bccc9945f4 Try to use submodules
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2019-09-04 09:59:59 +00:00
Adrien Gallouët
9c9f679497 Update mud
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2019-09-03 16:56:50 +00:00
Adrien Gallouët
9177778d0f Add .github/workflows/ccpp.yml
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2019-09-03 16:27:57 +00:00
Adrien Gallouët
6853b59dc3 Add sodium.sh
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2019-09-03 16:27:57 +00:00
Adrien Gallouët
d451bc75b0 Doll up
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2019-07-23 13:17:59 +00:00
Adrien Gallouët
1f82b15373 Code cleanup
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2019-07-22 13:08:17 +00:00
Adrien Gallouët
56b5a41633 Code cleanup
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2019-07-21 15:05:48 +00:00
Adrien Gallouët
004380827f A more friendly command path
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2019-07-21 15:05:48 +00:00
Adrien Gallouët
a7f57de42a Remove useless tests in ctl
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2019-07-21 15:05:48 +00:00
Adrien Gallouët
2f3f9e7e86 Update desc of show
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2019-07-20 08:53:47 +00:00
Adrien Gallouët
0528adcfe2 Code cleanup
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2019-07-20 08:19:55 +00:00
Adrien Gallouët
67ea65b1a8 Don't show all tunnels
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2019-07-19 22:40:31 +00:00
Adrien Gallouët
ed82531fc0 Always unlink ctl socket
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2019-07-19 21:51:28 +00:00
17 changed files with 258 additions and 164 deletions

24
.github/workflows/build.yml vendored Normal file
View File

@@ -0,0 +1,24 @@
name: Build
on: [push]
jobs:
build:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, macOS-latest]
steps:
- uses: actions/checkout@v1
- name: Build glorytun
run: |
git submodule update --init --recursive
./sodium.sh
make prefix=. install
- uses: actions/upload-artifact@v1
with:
name: bin
path: ./bin

1
.gitignore vendored
View File

@@ -10,6 +10,7 @@ configure
build-aux build-aux
.deps .deps
.dirstamp .dirstamp
.static
glorytun glorytun
build* build*
VERSION VERSION

View File

@@ -11,7 +11,10 @@ CFLAGS ?= -std=c11 -O2 -Wall -fstack-protector-strong
FLAGS := $(CFLAGS) $(LDFLAGS) $(CPPFLAGS) FLAGS := $(CFLAGS) $(LDFLAGS) $(CPPFLAGS)
FLAGS += -DPACKAGE_NAME=\"$(NAME)\" -DPACKAGE_VERSION=\"$(VERSION)\" FLAGS += -DPACKAGE_NAME=\"$(NAME)\" -DPACKAGE_VERSION=\"$(VERSION)\"
SRC := argz/argz.c mud/mud.c $(wildcard src/*.c) 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)
.PHONY: $(NAME) .PHONY: $(NAME)
$(NAME): $(NAME):

View File

@@ -9,6 +9,8 @@ glorytun_SOURCES = \
argz/argz.h \ argz/argz.h \
mud/mud.c \ mud/mud.c \
mud/mud.h \ mud/mud.h \
mud/aegis256/aegis256.c \
mud/aegis256/aegis256.h \
src/bench.c \ src/bench.c \
src/bind.c \ src/bind.c \
src/common.c \ src/common.c \

View File

@@ -20,8 +20,8 @@ The key features of Glorytun come directly from mud:
The use of UDP and [libsodium](https://github.com/jedisct1/libsodium) allows you to secure The use of UDP and [libsodium](https://github.com/jedisct1/libsodium) allows you to secure
your communications without impacting performance. your communications without impacting performance.
Glorytun uses AES only if AES-NI is available otherwise ChaCha20 is used. Glorytun uses AEGIS-256 only if AES-NI is available otherwise ChaCha20Poly1305 is used.
If you are not cpu bounded, you can force the use of ChaCha20 for higher security. If you are not cpu bounded, you can force the use of ChaCha20Poly1305 for higher security.
All messages are encrypted, authenticated and marked with a timestamp. All messages are encrypted, authenticated and marked with a timestamp.
Perfect forward secrecy is also implemented with ECDH over Curve25519. Perfect forward secrecy is also implemented with ECDH over Curve25519.
@@ -75,7 +75,7 @@ Just run `glorytun` with no arguments to view the list of available commands:
$ glorytun $ glorytun
available commands: available commands:
show show all running tunnels show show tunnel info
bench start a crypto bench bench start a crypto bench
bind start a new tunnel bind start a new tunnel
set change tunnel properties set change tunnel properties

2
argz

Submodule argz updated: 31f3c44d9b...47ad9daf43

View File

@@ -23,6 +23,7 @@ executable('glorytun', install: true,
sources: [ sources: [
'argz/argz.c', 'argz/argz.c',
'mud/mud.c', 'mud/mud.c',
'mud/aegis256/aegis256.c',
'src/bench.c', 'src/bench.c',
'src/bind.c', 'src/bind.c',
'src/common.c', 'src/common.c',

2
mud

Submodule mud updated: a91f8e2971...4d14689ff1

29
sodium.sh Executable file
View File

@@ -0,0 +1,29 @@
#!/bin/sh
mkdir -p .static
cd .static || exit 1
file=LATEST.tar.gz
url=https://download.libsodium.org/libsodium/releases
dir="$PWD"
[ -f "$file" ] || wget -q "$url/$file" -O "$file"
[ -f "$file" ] || curl -SsfLO "$url/$file"
[ -f "$file" ] || {
echo "Couldn't download $url/$file"
exit 1
}
if [ "$1" ]; then
mkdir -p "$1"
cd "$1" || exit 1
fi
rm -rf libsodium-stable
tar zxf "$dir/$file"
cd libsodium-stable || exit 1
NPROC=$(sysctl -n hw.ncpu || nproc) 2>/dev/null
./configure ${1+--host=$1} --enable-minimal --disable-dependency-tracking --enable-static --disable-shared
make "-j$((NPROC+1))"

View File

@@ -13,9 +13,14 @@
#endif #endif
#include "../argz/argz.h" #include "../argz/argz.h"
#include "../mud/aegis256/aegis256.h"
#define STR_S(X) (((X) > 1) ? "s" : "") #define STR_S(X) (((X) > 1) ? "s" : "")
#define NPUBBYTES 32
#define KEYBYTES 32
#define ABYTES 16
static unsigned long long static unsigned long long
gt_now(void) gt_now(void)
{ {
@@ -68,7 +73,7 @@ gt_bench(int argc, char **argv)
int aes = argz_is_set(bench_argz, "aes"); int aes = argz_is_set(bench_argz, "aes");
int chacha = argz_is_set(bench_argz, "chacha"); int chacha = argz_is_set(bench_argz, "chacha");
if (!crypto_aead_aes256gcm_is_available()) { if (!aegis256_is_available()) {
if (aes) { if (aes) {
gt_log("aes is not available on your platform\n"); gt_log("aes is not available on your platform\n");
return 1; return 1;
@@ -76,22 +81,22 @@ gt_bench(int argc, char **argv)
chacha = 1; chacha = 1;
} }
unsigned char *buf = calloc(1, bufsize + crypto_aead_aes256gcm_ABYTES); unsigned char *buf = calloc(1, bufsize + ABYTES);
if (!buf) { if (!buf) {
perror("calloc"); perror("calloc");
return 1; return 1;
} }
unsigned char npub[crypto_aead_aes256gcm_NPUBBYTES]; unsigned char npub[NPUBBYTES];
unsigned char key[crypto_aead_aes256gcm_KEYBYTES]; unsigned char key[KEYBYTES];
randombytes_buf(npub, sizeof(npub)); randombytes_buf(npub, sizeof(npub));
randombytes_buf(key, sizeof(key)); randombytes_buf(key, sizeof(key));
if (term) { if (term) {
printf("\n"); printf("\n");
printf(" %-10s %s\n", "bench", chacha ? "chacha20poly1305" : "aes256gcm"); printf(" %-10s %s\n", "bench", chacha ? "chacha20poly1305" : "aegis256");
printf(" %-10s %s\n", "libsodium", sodium_version_string()); printf(" %-10s %s\n", "libsodium", sodium_version_string());
printf("\n"); printf("\n");
printf(" %-10s 2^(-%lu)\n", "precision", precision); printf(" %-10s 2^(-%lu)\n", "precision", precision);
@@ -112,11 +117,6 @@ gt_bench(int argc, char **argv)
double mbps_dlt = INFINITY; double mbps_dlt = INFINITY;
while (!gt_quit && mbps_dlt > ldexp(mbps, -(int)precision)) { while (!gt_quit && mbps_dlt > ldexp(mbps, -(int)precision)) {
crypto_aead_aes256gcm_state ctx;
if (!chacha)
crypto_aead_aes256gcm_beforenm(&ctx, key);
unsigned long long now = gt_now(); unsigned long long now = gt_now();
double mbps_old = mbps; double mbps_old = mbps;
size_t bytes = 0; size_t bytes = 0;
@@ -129,9 +129,8 @@ gt_bench(int argc, char **argv)
crypto_aead_chacha20poly1305_encrypt( crypto_aead_chacha20poly1305_encrypt(
buf, NULL, buf, 1ULL << i, NULL, 0, NULL, npub, key); buf, NULL, buf, 1ULL << i, NULL, 0, NULL, npub, key);
} else { } else {
crypto_aead_aes256gcm_encrypt_afternm( aegis256_encrypt(
buf, NULL, buf, 1ULL << i, NULL, 0, NULL, npub, buf, NULL, buf, 1ULL << i, NULL, 0, npub, key);
(const crypto_aead_aes256gcm_state *)&ctx);
} }
bytes += 1ULL << i; bytes += 1ULL << i;
} }

View File

@@ -193,8 +193,8 @@ gt_bind(int argc, char **argv)
return 1; return 1;
} }
if (fd_set_nonblock(tun_fd) || if (//fd_set_nonblock(tun_fd) ||
fd_set_nonblock(mud_fd) || //fd_set_nonblock(mud_fd) ||
fd_set_nonblock(ctl_fd)) { fd_set_nonblock(ctl_fd)) {
gt_log("couldn't setup non-blocking fds\n"); gt_log("couldn't setup non-blocking fds\n");
return 1; return 1;
@@ -204,31 +204,60 @@ gt_bind(int argc, char **argv)
gt_log("running on device %s as pid %li\n", tun_name, pid); gt_log("running on device %s as pid %li\n", tun_name, pid);
fd_set rfds; fd_set rfds, wfds;
FD_ZERO(&rfds); FD_ZERO(&rfds);
FD_ZERO(&wfds);
const int last_fd = 1 + MAX(tun_fd, MAX(mud_fd, ctl_fd)); int tun_can_read = 0;
int tun_can_write = 0;
int mud_can_read = 0;
int mud_can_write = 0;
int last_fd = MAX(tun_fd, mud_fd);
last_fd = 1 + MAX(last_fd, ctl_fd);
unsigned char buf[4096]; unsigned char buf[4096];
while (!gt_quit) { while (!gt_quit) {
long send_wait = mud_send_wait(mud); if (tun_can_write) {
FD_CLR(tun_fd, &wfds);
} else {
FD_SET(tun_fd, &wfds);
}
if (send_wait) { if (mud_can_write) {
FD_CLR(mud_fd, &wfds);
} else {
FD_SET(mud_fd, &wfds);
}
if (tun_can_read) {
FD_CLR(tun_fd, &rfds); FD_CLR(tun_fd, &rfds);
} else { } else {
FD_SET(tun_fd, &rfds); FD_SET(tun_fd, &rfds);
} }
FD_SET(mud_fd, &rfds); if (mud_can_read) {
FD_CLR(mud_fd, &rfds);
} else {
FD_SET(mud_fd, &rfds);
}
FD_SET(ctl_fd, &rfds); FD_SET(ctl_fd, &rfds);
struct timeval tv = { struct timeval tv = {
.tv_sec = 0, .tv_usec = 100000,
.tv_usec = send_wait,
}; };
const int ret = select(last_fd, &rfds, NULL, NULL, send_wait > 0 ? &tv : NULL); 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;
}
const int ret = select(last_fd, &rfds, &wfds, NULL, &tv);
if (ret == -1) { if (ret == -1) {
if (errno == EBADF) { if (errno == EBADF) {
@@ -238,8 +267,43 @@ gt_bind(int argc, char **argv)
continue; 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;
mtu = gt_setup_mtu(mud, mtu, tun_name); mtu = gt_setup_mtu(mud, mtu, tun_name);
if (tun_can_read && mud_can_write && !mud_send_wait(mud)) {
struct ip_common ic;
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_can_write = 0;
}
tun_can_read = 0;
}
if (mud_can_read && tun_can_write) {
int r = mud_recv(mud, buf, sizeof(buf));
if (r > 0 && ip_is_valid(buf, r)) {
tun_write(tun_fd, buf, (size_t)r);
tun_can_write = 0;
}
mud_can_read = 0;
}
if (FD_ISSET(ctl_fd, &rfds)) { if (FD_ISSET(ctl_fd, &rfds)) {
struct ctl_msg req, res = {.reply = 1}; struct ctl_msg req, res = {.reply = 1};
struct sockaddr_storage ss; struct sockaddr_storage ss;
@@ -299,6 +363,7 @@ gt_bind(int argc, char **argv)
res.ret = errno; res.ret = errno;
break; break;
case CTL_STATUS: case CTL_STATUS:
memcpy(res.status.tun_name, tun_name, sizeof(tun_name)); // XXX
res.status.pid = pid; res.status.pid = pid;
res.status.mtu = mtu; res.status.mtu = mtu;
res.status.chacha = chacha; res.status.chacha = chacha;
@@ -313,36 +378,6 @@ gt_bind(int argc, char **argv)
perror("recvfrom(ctl)"); perror("recvfrom(ctl)");
} }
} }
if (FD_ISSET(mud_fd, &rfds)) {
int n = 1000;
while (n--) {
const int r = mud_recv(mud, buf, sizeof(buf));
if (r <= 0)
break;
if (ip_is_valid(buf, r))
tun_write(tun_fd, buf, (size_t)r);
}
}
if (FD_ISSET(tun_fd, &rfds) && !mud_send_wait(mud)) {
struct ip_common ic;
const int r = tun_read(tun_fd, buf, sizeof(buf));
if (r > 0 && !ip_get_common(&ic, buf, r)) {
// TODO: disable hash for now
// unsigned char hash[crypto_shorthash_BYTES];
// crypto_shorthash(hash, (const unsigned char *)&ic, sizeof(ic), hashkey);
unsigned h = 0;
// memcpy(&h, hash, sizeof(h));
mud_send(mud, buf, (size_t)r, (h << 8) | ic.tc);
}
}
} }
if (gt_reload && tun_fd >= 0) if (gt_reload && tun_fd >= 0)

View File

@@ -13,17 +13,12 @@
int int
ctl_reply(int fd, struct ctl_msg *res, struct ctl_msg *req) ctl_reply(int fd, struct ctl_msg *res, struct ctl_msg *req)
{ {
if (fd == -1) {
errno = EINVAL;
return -1;
}
if ((send(fd, req, sizeof(struct ctl_msg), 0) == -1) || if ((send(fd, req, sizeof(struct ctl_msg), 0) == -1) ||
(recv(fd, res, sizeof(struct ctl_msg), 0) == -1)) (recv(fd, res, sizeof(struct ctl_msg), 0) == -1))
return -1; return -1;
if (res->type != req->type || !res->reply) { if (res->type != req->type || !res->reply) {
errno = EINVAL; errno = EBADMSG;
return -1; return -1;
} }
@@ -58,33 +53,30 @@ ctl_setsun(struct sockaddr_un *dst, const char *dir, const char *file)
static int static int
ctl_bind(int fd, const char *dir, const char *file) ctl_bind(int fd, const char *dir, const char *file)
{ {
char name[10] = { [0] = '.' };
struct sockaddr_un sun; struct sockaddr_un sun;
if (str_empty(file)) { if (str_empty(file)) {
char name[10] = { [0] = '.' };
unsigned pid = (unsigned)getpid(); unsigned pid = (unsigned)getpid();
for (size_t i = 1; i < sizeof(name) - 1; i++, pid >>= 4) for (size_t i = 1; i < sizeof(name) - 1; i++, pid >>= 4)
name[i] = "uncopyrightables"[pid & 15]; name[i] = "uncopyrightables"[pid & 15];
if (ctl_setsun(&sun, dir, name)) file = name;
return -1;
} else {
if (ctl_setsun(&sun, dir, file))
return -1;
unlink(sun.sun_path);
} }
if (ctl_setsun(&sun, dir, file))
return -1;
if (unlink(sun.sun_path) && errno != ENOENT)
return -1;
return bind(fd, (struct sockaddr *)&sun, sizeof(sun)); return bind(fd, (struct sockaddr *)&sun, sizeof(sun));
} }
void void
ctl_delete(int fd) ctl_delete(int fd)
{ {
if (fd == -1)
return;
struct sockaddr_storage ss = { 0 }; struct sockaddr_storage ss = { 0 };
socklen_t sslen = sizeof(ss); socklen_t sslen = sizeof(ss);
@@ -108,9 +100,6 @@ ctl_create(const char *dir, const char *file)
int fd = socket(AF_UNIX, SOCK_DGRAM, 0); int fd = socket(AF_UNIX, SOCK_DGRAM, 0);
if (fd == -1)
return -1;
if (ctl_bind(fd, dir, file)) { if (ctl_bind(fd, dir, file)) {
int err = errno; int err = errno;
close(fd); close(fd);
@@ -132,9 +121,7 @@ ctl_connect(const char *dir, const char *file)
} }
if (!file) { if (!file) {
dp = opendir(dir); if (dp = opendir(dir), !dp)
if (!dp)
return -1; return -1;
struct dirent *d = NULL; struct dirent *d = NULL;
@@ -145,7 +132,7 @@ ctl_connect(const char *dir, const char *file)
if (file) { if (file) {
closedir(dp); closedir(dp);
return -3; return CTL_ERROR_MANY;
} }
file = &d->d_name[0]; file = &d->d_name[0];
@@ -153,7 +140,7 @@ ctl_connect(const char *dir, const char *file)
if (!file) { if (!file) {
closedir(dp); closedir(dp);
return -2; return CTL_ERROR_NONE;
} }
} }
@@ -171,9 +158,6 @@ ctl_connect(const char *dir, const char *file)
int fd = ctl_create(dir, NULL); int fd = ctl_create(dir, NULL);
if (fd == -1)
return -1;
if (connect(fd, (struct sockaddr *)&sun, sizeof(sun))) { if (connect(fd, (struct sockaddr *)&sun, sizeof(sun))) {
int err = errno; int err = errno;
ctl_delete(fd); ctl_delete(fd);

View File

@@ -4,6 +4,9 @@
#include <sys/socket.h> #include <sys/socket.h>
#define CTL_ERROR_NONE (-2)
#define CTL_ERROR_MANY (-3)
enum ctl_type { enum ctl_type {
CTL_NONE = 0, CTL_NONE = 0,
CTL_STATE, CTL_STATE,
@@ -27,6 +30,7 @@ struct ctl_msg {
} path; } path;
struct mud_path path_status; struct mud_path path_status;
struct { struct {
char tun_name[64];
long pid; long pid;
size_t mtu; size_t mtu;
int chacha; int chacha;

View File

@@ -75,7 +75,7 @@ main(int argc, char **argv)
char *help; char *help;
int (*call)(int, char **); int (*call)(int, char **);
} cmd[] = { } cmd[] = {
{"show", "show all running tunnels", gt_show}, {"show", "show tunnel info", gt_show},
{"bench", "start a crypto bench", gt_bench}, {"bench", "start a crypto bench", gt_bench},
{"bind", "start a new tunnel", gt_bind}, {"bind", "start a new tunnel", gt_bind},
{"set", "change tunnel properties", gt_set}, {"set", "change tunnel properties", gt_set},

View File

@@ -74,7 +74,28 @@ gt_path_print_status(struct mud_path *path, int term)
} }
static int static int
gt_path_status(int fd) gt_path_cmp_addr(struct sockaddr_storage *a, struct sockaddr_storage *b)
{
if (a->ss_family != b->ss_family)
return 1;
if (a->ss_family == AF_INET) {
struct sockaddr_in *A = (struct sockaddr_in *)a;
struct sockaddr_in *B = (struct sockaddr_in *)b;
return ((memcmp(&A->sin_addr, &B->sin_addr, sizeof(A->sin_addr))));
}
if (a->ss_family == AF_INET6) {
struct sockaddr_in6 *A = (struct sockaddr_in6 *)a;
struct sockaddr_in6 *B = (struct sockaddr_in6 *)b;
return ((memcmp(&A->sin6_addr, &B->sin6_addr, sizeof(A->sin6_addr))));
}
return 1;
}
static int
gt_path_status(int fd, int state, struct sockaddr_storage *addr)
{ {
struct ctl_msg req = { struct ctl_msg req = {
.type = CTL_PATH_STATUS, .type = CTL_PATH_STATUS,
@@ -90,8 +111,10 @@ gt_path_status(int fd)
if (recv(fd, &res, sizeof(struct ctl_msg), 0) == -1) if (recv(fd, &res, sizeof(struct ctl_msg), 0) == -1)
return -1; return -1;
if (res.type != req.type) if (res.type != req.type) {
return -2; errno = EBADMSG;
return -1;
}
if (res.ret == EAGAIN) { if (res.ret == EAGAIN) {
memcpy(&path[count], &res.path_status, sizeof(struct mud_path)); memcpy(&path[count], &res.path_status, sizeof(struct mud_path));
@@ -104,8 +127,11 @@ gt_path_status(int fd)
int term = isatty(1); int term = isatty(1);
for (int i = 0; i < count; i++) for (int i = 0; i < count; i++) {
gt_path_print_status(&path[i], term); 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);
}
return 0; return 0;
} }
@@ -117,6 +143,9 @@ gt_path(int argc, char **argv)
struct ctl_msg req = { struct ctl_msg req = {
.type = CTL_STATE, .type = CTL_STATE,
.path = {
.state = MUD_EMPTY,
},
}, res = {0}; }, res = {0};
struct argz ratez[] = { struct argz ratez[] = {
@@ -141,10 +170,10 @@ gt_path(int argc, char **argv)
case -1: case -1:
perror("path"); perror("path");
break; break;
case -2: case CTL_ERROR_NONE:
gt_log("no device\n"); gt_log("no device\n");
break; break;
case -3: case CTL_ERROR_MANY:
gt_log("please choose a device\n"); gt_log("please choose a device\n");
break; break;
default: default:
@@ -153,24 +182,27 @@ gt_path(int argc, char **argv)
return 1; return 1;
} }
int ret = 0; int set_rate = argz_is_set(pathz, "rate");
if (!req.path.addr.ss_family) { if (set_rate && !req.path.addr.ss_family) {
ret = gt_path_status(fd); gt_log("please specify a path\n");
return 1;
}
if (ret == -2) if (argz_is_set(pathz, "up")) {
gt_log("bad reply from server\n"); req.path.state = MUD_UP;
} else if (argz_is_set(pathz, "backup")) {
req.path.state = MUD_BACKUP;
} else if (argz_is_set(pathz, "down")) {
req.path.state = MUD_DOWN;
}
int ret;
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 { } else {
req.path.state = MUD_EMPTY;
if (argz_is_set(pathz, "up")) {
req.path.state = MUD_UP;
} else if (argz_is_set(pathz, "backup")) {
req.path.state = MUD_BACKUP;
} else if (argz_is_set(pathz, "down")) {
req.path.state = MUD_DOWN;
}
ret = ctl_reply(fd, &res, &req); ret = ctl_reply(fd, &res, &req);
} }

View File

@@ -134,10 +134,10 @@ gt_set(int argc, char **argv)
case -1: case -1:
perror("set"); perror("set");
break; break;
case -2: case CTL_ERROR_NONE:
gt_log("no device\n"); gt_log("no device\n");
break; break;
case -3: case CTL_ERROR_MANY:
gt_log("please choose a device\n"); gt_log("please choose a device\n");
break; break;
default: default:

View File

@@ -12,7 +12,7 @@
#include <unistd.h> #include <unistd.h>
static int static int
gt_show_dev_status(int fd, const char *dev) gt_show_status(int fd)
{ {
struct ctl_msg res, req = {.type = CTL_STATUS}; struct ctl_msg res, req = {.type = CTL_STATUS};
@@ -32,17 +32,17 @@ gt_show_dev_status(int fd, const char *dev)
if (server) { if (server) {
printf(term ? "server %s:\n" printf(term ? "server %s:\n"
" pid: %li\n" " pid: %li\n"
" bind: %s port %"PRIu16"\n" " bind: %s port %"PRIu16"\n"
" mtu: %zu\n" " mtu: %zu\n"
" cipher: %s\n" " cipher: %s\n"
: "server %s" : "server %s"
" %li" " %li"
" %s %"PRIu16 " %s %"PRIu16
" %zu" " %zu"
" %s" " %s"
"\n", "\n",
dev, res.status.tun_name,
res.status.pid, res.status.pid,
bindstr[0] ? bindstr : "-", bindstr[0] ? bindstr : "-",
gt_get_port((struct sockaddr *)&res.status.bind), gt_get_port((struct sockaddr *)&res.status.bind),
@@ -50,11 +50,11 @@ gt_show_dev_status(int fd, const char *dev)
res.status.chacha ? "chacha20poly1305" : "aes256gcm"); res.status.chacha ? "chacha20poly1305" : "aes256gcm");
} else { } else {
printf(term ? "client %s:\n" printf(term ? "client %s:\n"
" pid: %li\n" " pid: %li\n"
" bind: %s port %"PRIu16"\n" " bind: %s port %"PRIu16"\n"
" peer: %s port %"PRIu16"\n" " peer: %s port %"PRIu16"\n"
" mtu: %zu\n" " mtu: %zu\n"
" cipher: %s\n" " cipher: %s\n"
: "client %s" : "client %s"
" %li" " %li"
" %s %"PRIu16 " %s %"PRIu16
@@ -62,7 +62,7 @@ gt_show_dev_status(int fd, const char *dev)
" %zu" " %zu"
" %s" " %s"
"\n", "\n",
dev, res.status.tun_name,
res.status.pid, res.status.pid,
bindstr[0] ? bindstr : "-", bindstr[0] ? bindstr : "-",
gt_get_port((struct sockaddr *)&res.status.bind), gt_get_port((struct sockaddr *)&res.status.bind),
@@ -75,30 +75,6 @@ gt_show_dev_status(int fd, const char *dev)
return 0; return 0;
} }
static int
gt_show_dev(const char *dev)
{
int fd = ctl_connect(GT_RUNDIR, dev);
if (fd < 0) {
if (fd == -1)
perror("show");
return -1;
}
int ret = gt_show_dev_status(fd, dev);
if (ret == -1)
perror(dev);
if (ret == -2)
gt_log("%s: bad reply from server\n", dev);
ctl_delete(fd);
return ret;
}
int int
gt_show(int argc, char **argv) gt_show(int argc, char **argv)
{ {
@@ -111,27 +87,31 @@ gt_show(int argc, char **argv)
if (argz(showz, argc, argv)) if (argz(showz, argc, argv))
return 1; return 1;
if (dev) int fd = ctl_connect(GT_RUNDIR, dev);
return !!gt_show_dev(dev);
DIR *dp = opendir(GT_RUNDIR); if (fd < 0) {
switch (fd) {
if (!dp) { case -1:
if (errno == ENOENT) perror("show");
return 0; break;
perror("show"); 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");
}
return 1; return 1;
} }
int ret = 0; int ret = gt_show_status(fd);
struct dirent *d = NULL;
while (d = readdir(dp), d) { if (ret == -1)
if (d->d_name[0] != '.') perror("show");
ret |= !!gt_show_dev(d->d_name);
}
closedir(dp); ctl_delete(fd);
return ret; return !!ret;
} }