Compare commits

..

39 Commits

Author SHA1 Message Date
Adrien Gallouët
a3bb488fd5 Update README.md
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-05-16 22:07:13 +00:00
Adrien Gallouët
022e478fb9 Update README.md
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-05-16 21:41:39 +00:00
Adrien Gallouët
f3b44e2f45 Option bufsize is no longer useful
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-05-15 06:48:02 +00:00
Adrien Gallouët
23b7aeb68f Code cleanup
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-05-15 06:44:55 +00:00
Adrien Gallouët
1e2004c7dd Ask for a keyfile
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-05-15 06:42:51 +00:00
Adrien Gallouët
e12d136ba3 Update README.md
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-05-14 13:11:20 +00:00
Adrien Gallouët
ca96be5fe5 Update README.md
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-05-11 16:55:44 +00:00
Adrien Gallouët
d0a9c69f7c Update argz
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-05-11 16:51:05 +00:00
Adrien Gallouët
3ffce5da1b Add a compatibility note in the README
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-05-10 20:24:14 +00:00
Adrien Gallouët
aeb33342a4 Remove useless mtu log
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-05-10 19:53:06 +00:00
Adrien Gallouët
ca71508e5c Show pid
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-05-10 19:51:18 +00:00
Adrien Gallouët
36be8008d8 Update README.md
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-05-10 14:05:34 +00:00
Adrien Gallouët
be17650555 Not using ICMP Next-hop MTU is a feature
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-05-10 13:49:42 +00:00
Adrien Gallouët
873efb4f82 Show help when no arguments
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-05-10 13:48:20 +00:00
Adrien Gallouët
357d5a0859 Update README.md
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-05-10 10:22:16 +00:00
Adrien Gallouët
5c532b2e56 Be more verbose
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-05-09 15:27:57 +00:00
Adrien Gallouët
0cce48e9fd Update mud
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-05-05 19:35:42 +00:00
Adrien Gallouët
ee9ed7e3a6 Use full hash as version if no tags
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-05-05 13:17:55 +00:00
Adrien Gallouët
841c2afed0 Update mud (new proto)
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-05-05 12:57:49 +00:00
Adrien Gallouët
60a5b3e00a Update mud
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-04-26 20:25:49 +00:00
Adrien Gallouët
e243d8371a Update mud
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-04-26 05:40:21 +00:00
Adrien Gallouët
767aff211f Update mud (bw probing)
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-04-25 09:10:37 +00:00
Adrien Gallouët
eb04190c58 Update mud
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-04-23 20:54:34 +00:00
Adrien Gallouët
d25957b108 Show latency-smoothed maxrate per path
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-04-21 12:29:02 +00:00
Adrien Gallouët
a5f634ee28 Show rate per path
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-04-18 16:37:20 +00:00
Adrien Gallouët
1736b6e043 Show rttvar per path
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-04-06 16:46:55 +00:00
Adrien Gallouët
8401b7c112 Show number of packets per path
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-04-03 09:49:00 +00:00
Adrien Gallouët
7276305906 Update mud
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-03-26 13:22:46 +00:00
Adrien Gallouët
6e75f4282d Don't forget BSD..
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-03-19 09:53:43 +00:00
Adrien Gallouët
7999344c39 Code cleanup
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-03-19 09:38:18 +00:00
Adrien Gallouët
7a9f6fc8b8 Remove old packet aggregation
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-03-17 13:21:16 +00:00
Adrien Gallouët
dabd16e4b4 Improve output of show/path
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-03-16 21:15:10 +00:00
Adrien Gallouët
1698a08b08 Update mud
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-03-15 22:07:48 +00:00
Adrien Gallouët
4646cbb15e Code cleanup
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-03-15 22:07:12 +00:00
Adrien Gallouët
c2bd415382 Sanitize memory
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-03-15 22:06:23 +00:00
Adrien Gallouët
245b8e671e Fix ctl_connect()
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-03-15 22:05:42 +00:00
Adrien Gallouët
c06abdbe3c Add set option kxtimeout
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-03-14 07:57:32 +00:00
Adrien Gallouët
b0a589b792 Use GT_RUNDIR for local sockets
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-03-14 07:06:25 +00:00
Adrien Gallouët
66cdcf2ee3 Update mud
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-03-14 06:55:37 +00:00
17 changed files with 297 additions and 251 deletions

116
README.md
View File

@@ -1,54 +1,112 @@
# Glorytun
Small, Simple and Stupid VPN over [mud](https://github.com/angt/mud).
Glorytun is a small, simple and secure VPN over [mud](https://github.com/angt/mud).
It runs on Linux, OpenBSD, FreeBSD and MacOS.
### Build and Install
## Features
The key features of Glorytun come directly from mud:
* **Fast and highly secure**
The use of UDP and [libsodium](https://github.com/jedisct1/libsodium) allows you to secure
your communications without impacting performance.
Glorytun uses AES only if AES-NI is available otherwise ChaCha20 is used.
You can force the use of ChaCha20 for higher security.
All messages are encrypted, authenticated and marked with a timestamp.
Perfect forward secrecy is also implemented with ECDH over Curve25519.
* **Multipath and active failover**
This is the main feature of Glorytun that allows to build an SD-WAN like service.
This allows a TCP connection to explore and exploit multiple links without being disconnected.
* **Path MTU discovery without ICMP**
Bad MTU configuration is a very common problem in the world of VPN.
As it is critical, Glorytun will try to setup it correctly by guessing its value.
It doesn't rely on ICMP Next-hop MTU to avoid black holes.
## Build and Install
Glorytun depends on [libsodium](https://github.com/jedisct1/libsodium) version >= 1.0.4.
We recommend the use of [meson](http://mesonbuild.com) for building instead of
the more classical autotools suite (also available for old systems).
On Ubuntu, the following command should be sufficient:
On Ubuntu, the following command should be sufficient to get all the necessary build dependencies:
$ sudo apt-get install meson libsodium-dev pkg-config
Grab the latest release from github:
To build and install the latest release from github:
$ git clone https://github.com/angt/glorytun --recursive
$ cd glorytun
$ meson glorytun glorytun/build
$ sudo ninja -C glorytun/build install
To build and install the latest version with [meson](http://mesonbuild.com):
This will install all binaries in `/usr/local/bin` by default.
$ meson build
$ sudo ninja -C build install
You can easily customize your setup with meson (see `meson help`).
The more classical autotools suite is also available.
## Usage
### Easy setup with systemd
Just run `glorytun` with no arguments to view the list of available commands:
Just call `glorytun-setup` and follow the instructions.
```
$ glorytun
available commands:
First, setup the server:
show show all running tunnels
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
$ sudo glorytun-setup
Config filename (tun0):
Server ip (enter for server conf):
Bind to port (5000):
Server key (enter to generate a new one):
Your new key: NEW_KEY
Start glorytun now ? (enter to skip): y
```
Copy the new generated key and use it when configuring the client:
Use the keyword `help` after a command to show its usage.
$ sudo glorytun-setup
Config filename (tun0):
Server ip (enter for server conf): SERVER_IP
Server port (5000):
Server key (enter to generate a new one): NEW_KEY
Start glorytun now ? (enter to skip): y
## Mini HowTo
You can check easily if it works by looking at your public ip.
To stop the service:
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.
$ sudo systemctl stop glorytun@tun0
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 exemple, 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 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
Here the tricky part... You need to specify your paths or glorytun will not send anything, it's easy:
# glorytun path LOCAL_IPADDR up
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 have systemd-networkd, you can use 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
---

2
argz

Submodule argz updated: 2d6a6d635f...3ee68b227f

View File

@@ -4,7 +4,6 @@ AC_INIT([glorytun],
[https://github.com/angt/glorytun/issues],
[glorytun],
[https://github.com/angt/glorytun])
AC_DEFINE_UNQUOTED([VERSION_MAJOR], [m4_esyscmd([./version.sh major])])
AC_CONFIG_SRCDIR([src/common.h])
AC_CONFIG_AUX_DIR([build-aux])
AC_CONFIG_MACRO_DIR([m4])

2
mud

Submodule mud updated: b53248b6da...964672adb5

View File

@@ -105,7 +105,7 @@ gt_bench(int argc, char **argv)
double mbps_max = 0.0;
double mbps_dlt = INFINITY;
while (!gt_quit && mbps_dlt > ldexp(mbps, -precision)) {
while (!gt_quit && mbps_dlt > ldexp(mbps, -(int)precision)) {
crypto_aead_aes256gcm_state ctx;
if (!chacha)

View File

@@ -94,8 +94,6 @@ gt_setup_mtu(struct mud *mud, const char *tun_name)
if (mtu == oldmtu)
return mtu;
gt_log("setup MTU to %zu on interface %s\n", mtu, tun_name);
if (iface_set_mtu(tun_name, mtu) == -1)
perror("tun_set_mtu");
@@ -113,8 +111,6 @@ gt_bind(int argc, char **argv)
unsigned short peer_port = bind_port;
const char *dev = NULL;
const char *keyfile = NULL;
size_t bufsize = 64 * 1024 * 1024;
size_t mtu = 1330;
struct argz toz[] = {
{NULL, "IPADDR", &peer_addr, argz_addr},
@@ -126,19 +122,23 @@ gt_bind(int argc, char **argv)
{NULL, "PORT", &bind_port, argz_ushort},
{"to", NULL, &toz, argz_option},
{"dev", "NAME", &dev, argz_str},
{"mtu", "BYTES", &mtu, argz_bytes},
{"keyfile", "FILE", &keyfile, argz_str},
{"chacha", NULL, NULL, argz_option},
{"persist", NULL, NULL, argz_option},
{"bufsize", "BYTES", &bufsize, argz_bytes},
{NULL}};
if (argz(bindz, argc, argv))
return 1;
if (str_empty(keyfile)) {
gt_log("a keyfile is needed!\n");
return 1;
}
gt_set_port((struct sockaddr *)&bind_addr, bind_port);
gt_set_port((struct sockaddr *)&peer_addr, peer_port);
const size_t bufsize = 4096U;
unsigned char *buf = malloc(bufsize);
if (!buf) {
@@ -156,31 +156,23 @@ gt_bind(int argc, char **argv)
return 1;
}
if (str_empty(keyfile)) {
if (mud_set_key(mud, NULL, 0)) {
gt_log("couldn't generate a new key\n");
return 1;
}
} else {
if (gt_setup_secretkey(mud, keyfile))
return 1;
}
if (!chacha && mud_set_aes(mud)) {
gt_log("AES is not available\n");
gt_log("AES is not available, enjoy ChaCha20!\n");
chacha = 1;
}
char tun_name[64];
int tun_fd = tun_create(tun_name, sizeof(tun_name) - 1, dev);
const int tun_fd = tun_create(tun_name, sizeof(tun_name) - 1, dev);
if (tun_fd == -1) {
gt_log("couldn't create tun device\n");
return 1;
}
mud_set_mtu(mud, mtu);
mtu = gt_setup_mtu(mud, tun_name);
size_t mtu = gt_setup_mtu(mud, tun_name);
if (tun_set_persist(tun_fd, persist) == -1)
perror("tun_set_persist");
@@ -192,25 +184,27 @@ gt_bind(int argc, char **argv)
}
}
int ctl_fd = ctl_create("/run/" PACKAGE_NAME, tun_name);
const int ctl_fd = ctl_create(GT_RUNDIR, tun_name);
if (ctl_fd == -1) {
perror("ctl_create");
return 1;
}
int mud_fd = mud_get_fd(mud);
const int mud_fd = mud_get_fd(mud);
fd_set_nonblock(tun_fd);
fd_set_nonblock(mud_fd);
fd_set_nonblock(ctl_fd);
gt_log("running...\n");
const long pid = (long)getpid();
gt_log("running on device %s as pid %li\n", tun_name, pid);
fd_set rfds;
FD_ZERO(&rfds);
int last_fd = 1 + MAX(tun_fd, MAX(mud_fd, ctl_fd));
const int last_fd = 1 + MAX(tun_fd, MAX(mud_fd, ctl_fd));
while (!gt_quit) {
FD_SET(tun_fd, &rfds);
@@ -263,11 +257,12 @@ gt_bind(int argc, char **argv)
perror("sendto(ctl)");
}
free(paths);
res.ret = 0;
}
break;
case CTL_MTU:
mud_set_mtu(mud, (size_t)req.mtu);
mud_set_mtu(mud, req.mtu);
mtu = gt_setup_mtu(mud, tun_name);
res.mtu = mtu;
break;
@@ -275,15 +270,20 @@ gt_bind(int argc, char **argv)
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_TIMEOUT:
if (mud_set_send_timeout(mud, req.timeout))
if (mud_set_send_timeout(mud, req.ms))
res.ret = errno;
break;
case CTL_TIMETOLERANCE:
if (mud_set_time_tolerance(mud, req.timetolerance))
if (mud_set_time_tolerance(mud, req.ms))
res.ret = errno;
break;
case CTL_STATUS:
res.status.pid = pid;
res.status.mtu = mtu;
res.status.chacha = chacha;
res.status.bind = bind_addr;
@@ -299,88 +299,30 @@ gt_bind(int argc, char **argv)
}
if (FD_ISSET(tun_fd, &rfds)) {
size_t size = 0;
while (bufsize - size >= mtu) {
const int r = tun_read(tun_fd, &buf[size], bufsize - size);
if (r <= 0 || r > mtu)
break;
struct ip_common ic;
const int r = tun_read(tun_fd, buf, bufsize);
if (ip_get_common(&ic, &buf[size], r) || ic.size != r)
break;
size += r;
}
size_t p = 0;
while (p < size) {
size_t q = p;
int tc = 0;
while (q < size) {
struct ip_common ic;
if ((ip_get_common(&ic, &buf[q], size - q)) ||
(ic.size > size - q))
break;
if (q + ic.size > p + mtu)
break;
q += ic.size;
if (tc < (ic.tc & 0xFC))
tc = ic.tc & 0xFC;
}
if (p >= q)
break;
int r = mud_send(mud, &buf[p], q - p, tc);
if (r == -1) {
if (errno == EMSGSIZE) {
mtu = gt_setup_mtu(mud, tun_name);
} else if (errno != EAGAIN) {
if (r <= 0) {
if (r == -1 && errno != EAGAIN)
perror("tun_read");
} else if ((!ip_get_common(&ic, buf, r)) &&
(mud_send(mud, buf, r, ic.tc) == -1)) {
if (errno != EAGAIN)
perror("mud_send");
}
}
p = q;
}
}
if (FD_ISSET(mud_fd, &rfds)) {
size_t size = 0;
while (bufsize - size >= mtu) {
const int r = mud_recv(mud, &buf[size], bufsize - size);
struct ip_common ic;
const int r = mud_recv(mud, buf, bufsize);
if (r <= 0) {
if (r == -1 && errno != EAGAIN)
perror("mud_recv");
break;
}
size += r;
}
size_t p = 0;
while (p < size) {
struct ip_common ic;
if ((ip_get_common(&ic, &buf[p], size - p)) ||
(ic.size > size - p))
break;
tun_write(tun_fd, &buf[p], ic.size);
p += ic.size;
} else if ((!ip_get_common(&ic, buf, r)) &&
(tun_write(tun_fd, buf, r) == -1)) {
if (errno != EAGAIN)
perror("tun_write");
}
}
}
@@ -390,7 +332,9 @@ gt_bind(int argc, char **argv)
perror("tun_set_persist");
}
mud_delete(mud);
ctl_delete(ctl_fd);
free(buf);
return 0;
}

View File

@@ -99,6 +99,9 @@ gt_get_port(struct sockaddr *sa)
int
gt_toaddr(char *str, size_t size, struct sockaddr *sa)
{
if (str)
str[0] = 0;
switch (sa->sa_family) {
case AF_INET:
return -!inet_ntop(AF_INET,

View File

@@ -21,6 +21,10 @@
#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 ALIGN_SIZE (1<<4)

View File

@@ -133,13 +133,15 @@ ctl_create(const char *dir, const char *file)
int
ctl_connect(const char *dir, const char *file)
{
DIR *dp = NULL;
if (str_empty(dir)) {
errno = EINVAL;
return -1;
}
if (!file) {
DIR *dp = opendir(dir);
dp = opendir(dir);
if (!dp)
return -1;
@@ -152,19 +154,28 @@ ctl_connect(const char *dir, const char *file)
if (file) {
closedir(dp);
errno = ENOENT;
return -1;
return -3;
}
file = &d->d_name[0];
}
if (!file) {
closedir(dp);
return -2;
}
}
struct sockaddr_un sun;
const int ret = ctl_setsun(&sun, dir, file);
if (ctl_setsun(&sun, dir, file))
if (dp) {
int err = errno;
closedir(dp);
errno = err;
}
if (ret)
return -1;
int fd = ctl_create(dir, NULL);

View File

@@ -10,6 +10,7 @@ enum ctl_type {
CTL_STATUS,
CTL_MTU,
CTL_TC,
CTL_KXTIMEOUT,
CTL_TIMEOUT,
CTL_TIMETOLERANCE,
CTL_PATH_STATUS,
@@ -25,15 +26,15 @@ struct ctl_msg {
} path;
struct mud_path path_status;
struct {
long pid;
size_t mtu;
int chacha;
struct sockaddr_storage bind;
struct sockaddr_storage peer;
} status;
int mtu;
size_t mtu;
int tc;
unsigned long timeout;
unsigned long timetolerance;
unsigned long ms;
};
};

View File

@@ -3,32 +3,16 @@
#include <stdint.h>
struct ip_common {
uint8_t version;
uint8_t tc;
uint8_t proto;
uint8_t hdr_size;
uint16_t size;
};
_pure_ static inline uint8_t
ip_get_version(const uint8_t *data, size_t size)
static inline uint8_t
ip_get_version(const uint8_t *data)
{
if (size < 20)
return 0;
return data[0] >> 4;
}
static inline uint32_t
ip_read32(const uint8_t *src)
{
uint32_t ret = src[3];
ret |= ((uint32_t)src[2]) << 8;
ret |= ((uint32_t)src[1]) << 16;
ret |= ((uint32_t)src[0]) << 24;
return ret;
}
static inline uint16_t
ip_read16(const uint8_t *src)
{
@@ -37,45 +21,22 @@ ip_read16(const uint8_t *src)
return ret;
}
static inline size_t
ip_get_mtu(struct ip_common *ic, const uint8_t *data, size_t size)
{
if (ic->hdr_size <= 0 || ic->hdr_size + 8 > size)
return 0;
const uint8_t *p = &data[ic->hdr_size];
if (ic->version == 4 && ic->proto == 1 && p[0] == 3)
return ip_read16(&p[6]);
// not tested..
// if (ic->version == 6 && ic->proto == 58 && p[0] == 2)
// return ip_read32(&p[4]);
return 0;
}
static inline int
ip_get_common(struct ip_common *ic, const uint8_t *data, size_t size)
{
ic->version = ip_get_version(data, size);
if (size < 20)
return 1;
switch (ic->version) {
switch (ip_get_version(data)) {
case 4:
ic->tc = data[1];
ic->proto = data[9];
ic->hdr_size = (data[0] & 0xF) << 2;
ic->size = ip_read16(&data[2]);
if (ic->size >= 20)
return 0;
break;
return size != ip_read16(&data[2]);
case 6:
ic->tc = ((data[0] & 0xF) << 4) | (data[1] >> 4);
ic->proto = data[6];
ic->hdr_size = 40;
ic->size = ip_read16(&data[4]) + 40;
return 0;
return size != ip_read16(&data[4]) + 40;
}
return -1;
return 1;
}

View File

@@ -69,15 +69,14 @@ main(int argc, char **argv)
{"version", "show version", gt_version},
{NULL}};
if (argc < 2)
return gt_show(argc, argv);
if (argv[1]) {
for (int k = 0; cmd[k].name; k++) {
if (!str_cmp(cmd[k].name, argv[1]))
return cmd[k].call(argc - 1, argv + 1);
}
}
printf("unknown command `%s', available commands:\n\n", argv[1]);
printf("available commands:\n\n");
int len = 0;

View File

@@ -27,17 +27,16 @@ gt_path_status(int fd)
if (!res.ret)
return 0;
char bindstr[INET6_ADDRSTRLEN] = {0};
char publstr[INET6_ADDRSTRLEN] = {0};
char peerstr[INET6_ADDRSTRLEN] = {0};
char bindstr[INET6_ADDRSTRLEN];
char publstr[INET6_ADDRSTRLEN];
char peerstr[INET6_ADDRSTRLEN];
if (gt_toaddr(bindstr, sizeof(bindstr),
(struct sockaddr *)&res.path_status.local_addr) ||
gt_toaddr(bindstr, sizeof(bindstr),
(struct sockaddr *)&res.path_status.local_addr);
gt_toaddr(publstr, sizeof(publstr),
(struct sockaddr *)&res.path_status.r_addr) ||
(struct sockaddr *)&res.path_status.r_addr);
gt_toaddr(peerstr, sizeof(peerstr),
(struct sockaddr *)&res.path_status.addr))
return -2;
(struct sockaddr *)&res.path_status.addr);
const char *statestr = NULL;
@@ -49,17 +48,32 @@ gt_path_status(int fd)
}
printf("path %s\n"
" bind: %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",
statestr, bindstr,
publstr, gt_get_port((struct sockaddr *)&res.path_status.r_addr),
peerstr, gt_get_port((struct sockaddr *)&res.path_status.addr),
res.path_status.mtu.ok + 28U, /* ip+udp hdr */
res.path_status.rtt/(double)1e3);
" rtt: %.3f ms\n"
" rttvar: %.3f ms\n"
" upload: %"PRIu64" bytes/s (max: %"PRIu64")\n"
" download: %"PRIu64" bytes/s (max: %"PRIu64")\n"
" output: %"PRIu64" packets\n"
" input: %"PRIu64" packets\n",
statestr,
bindstr[0] ? bindstr : "-",
gt_get_port((struct sockaddr *)&res.path_status.local_addr),
publstr[0] ? publstr : "-",
gt_get_port((struct sockaddr *)&res.path_status.r_addr),
peerstr[0] ? peerstr : "-",
gt_get_port((struct sockaddr *)&res.path_status.addr),
res.path_status.mtu.ok,
res.path_status.rtt/(double)1e3,
res.path_status.rttvar/(double)1e3,
res.path_status.r_rate,
res.path_status.r_ratemax,
res.path_status.recv.rate,
res.path_status.recv.ratemax,
res.path_status.send.total,
res.path_status.recv.total);
} while (res.ret == EAGAIN);
return 0;
@@ -83,11 +97,22 @@ gt_path(int argc, char **argv)
if (argz(pathz, argc, argv))
return 1;
int fd = ctl_connect("/run/" PACKAGE_NAME, dev);
int fd = ctl_connect(GT_RUNDIR, dev);
if (fd == -1) {
if (fd < 0) {
switch (fd) {
case -1:
perror("path");
ctl_delete(fd);
break;
case -2:
gt_log("no device\n");
break;
case -3:
gt_log("please choose a device\n");
break;
default:
gt_log("couldn't connect\n");
}
return 1;
}

View File

@@ -22,17 +22,35 @@ gt_set_mtu(int fd, size_t mtu)
return 1;
}
printf("mtu set to %i\n", res.mtu);
printf("mtu set to %zu\n", res.mtu);
return 0;
}
static int
gt_set_timeout(int fd, unsigned long timeout)
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_timeout(int fd, unsigned long ms)
{
struct ctl_msg res, req = {
.type = CTL_TIMEOUT,
.timeout = timeout,
.ms = ms,
};
int ret = ctl_reply(fd, &res, &req);
@@ -46,11 +64,11 @@ gt_set_timeout(int fd, unsigned long timeout)
}
static int
gt_set_timetolerance(int fd, unsigned long timetolerance)
gt_set_timetolerance(int fd, unsigned long ms)
{
struct ctl_msg res, req = {
.type = CTL_TIMETOLERANCE,
.timetolerance = timetolerance,
.ms = ms,
};
int ret = ctl_reply(fd, &res, &req);
@@ -113,13 +131,15 @@ gt_set(int argc, char **argv)
const char *dev = NULL;
size_t mtu;
int tc;
unsigned long timetolerance;
unsigned long kxtimeout;
unsigned long timeout;
unsigned long timetolerance;
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},
{"timeout", "SECONDS", &timeout, argz_time},
{"timetolerance", "SECONDS", &timetolerance, argz_time},
{NULL}};
@@ -127,10 +147,22 @@ gt_set(int argc, char **argv)
if (argz(pathz, argc, argv))
return 1;
int fd = ctl_connect("/run/" PACKAGE_NAME, dev);
int fd = ctl_connect(GT_RUNDIR, dev);
if (fd == -1) {
if (fd < 0) {
switch (fd) {
case -1:
perror("set");
break;
case -2:
gt_log("no device\n");
break;
case -3:
gt_log("please choose a device\n");
break;
default:
gt_log("couldn't connect\n");
}
return 1;
}
@@ -142,6 +174,9 @@ gt_set(int argc, char **argv)
if (argz_is_set(pathz, "tc"))
ret |= gt_set_tc(fd, tc);
if (argz_is_set(pathz, "kxtimeout"))
ret |= gt_set_kxtimeout(fd, kxtimeout);
if (argz_is_set(pathz, "timeout"))
ret |= gt_set_timeout(fd, timeout);

View File

@@ -18,34 +18,40 @@ gt_show_dev_status(int fd, const char *dev)
if (ctl_reply(fd, &res, &req))
return -1;
char bindstr[INET6_ADDRSTRLEN] = {0};
char peerstr[INET6_ADDRSTRLEN] = {0};
char bindstr[INET6_ADDRSTRLEN];
char peerstr[INET6_ADDRSTRLEN];
if (gt_toaddr(bindstr, sizeof(bindstr),
(struct sockaddr *)&res.status.bind))
return -2;
gt_toaddr(bindstr, sizeof(bindstr),
(struct sockaddr *)&res.status.bind);
int server = gt_toaddr(peerstr, sizeof(peerstr),
(struct sockaddr *)&res.status.peer);
if (server) {
printf("server %s:\n"
" pid: %li\n"
" bind: %s port %"PRIu16"\n"
" mtu: %zu\n"
" cipher: %s\n",
dev,
bindstr, gt_get_port((struct sockaddr *)&res.status.bind),
res.status.pid,
bindstr[0] ? bindstr : "-",
gt_get_port((struct sockaddr *)&res.status.bind),
res.status.mtu,
res.status.chacha ? "chacha20poly1305" : "aes256gcm");
} else {
printf("client %s:\n"
" pid: %li\n"
" bind: %s port %"PRIu16"\n"
" peer: %s port %"PRIu16"\n"
" mtu: %zu\n"
" cipher: %s\n",
dev,
bindstr, gt_get_port((struct sockaddr *)&res.status.bind),
peerstr, gt_get_port((struct sockaddr *)&res.status.peer),
res.status.pid,
bindstr[0] ? bindstr : "-",
gt_get_port((struct sockaddr *)&res.status.bind),
peerstr[0] ? peerstr : "-",
gt_get_port((struct sockaddr *)&res.status.peer),
res.status.mtu,
res.status.chacha ? "chacha20poly1305" : "aes256gcm");
}
@@ -56,10 +62,11 @@ gt_show_dev_status(int fd, const char *dev)
static int
gt_show_dev(const char *dev)
{
int fd = ctl_connect("/run/" PACKAGE_NAME, dev);
int fd = ctl_connect(GT_RUNDIR, dev);
if (fd == -1) {
perror(dev);
if (fd < 0) {
if (fd == -1)
perror("show");
return -1;
}
@@ -93,7 +100,7 @@ gt_show(int argc, char **argv)
return 0;
}
DIR *dp = opendir("/run/" PACKAGE_NAME);
DIR *dp = opendir(GT_RUNDIR);
if (!dp) {
if (errno == ENOENT)

View File

@@ -224,7 +224,7 @@ tun_write(int fd, const void *data, size_t size)
#ifdef GT_BSD_TUN
uint32_t family;
switch (ip_get_version(data, size)) {
switch (ip_get_version(data)) {
case 4:
family = htonl(AF_INET);
break;

View File

@@ -1,13 +1,12 @@
#!/bin/sh
[ -z "${VERSION}" ] && VERSION=`git describe --tags --match='v[0-9].*' 2>/dev/null` \
&& VERSION=${VERSION#v}
[ -z "${VERSION}" ] && VERSION="$(git describe --tags --match='v[0-9].*' 2>/dev/null)" \
&& VERSION="${VERSION#v}"
[ -z "${VERSION}" ] && VERSION=`cat VERSION 2>/dev/null`
[ -z "${VERSION}" ] && VERSION="$(git rev-parse HEAD 2>/dev/null)"
[ -z "${VERSION}" ] && VERSION=0.0.0
[ -z "${VERSION}" ] && VERSION="$(cat VERSION 2>/dev/null)"
[ "$1" = "major" ] && printf ${VERSION%%.*} \
&& exit 0
[ -z "${VERSION}" ] && VERSION="0.0.0"
printf ${VERSION} | tee VERSION
printf "%s" "${VERSION}" | tee VERSION