Compare commits
9 Commits
2f966bb365
...
e4988b9e9c
| Author | SHA1 | Date | |
|---|---|---|---|
|
e4988b9e9c
|
|||
|
0183b35acf
|
|||
|
|
faeb599a19 | ||
|
|
a4e72918df | ||
|
|
d7e8dbe0e7 | ||
|
|
71d16f25ff | ||
|
|
c426cef08b | ||
|
|
bda2c6eaa7 | ||
|
|
d68aee8249 |
4
.gitmodules
vendored
4
.gitmodules
vendored
@@ -1,4 +0,0 @@
|
||||
[submodule "aegis256"]
|
||||
path = aegis256
|
||||
url = https://github.com/angt/aegis256
|
||||
ignore = dirty
|
||||
1
aegis256
1
aegis256
Submodule aegis256 deleted from 42b0b3da1d
409
mud.c
409
mud.c
@@ -22,7 +22,6 @@
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include <sodium.h>
|
||||
#include "aegis256/aegis256.h"
|
||||
|
||||
#if !defined MSG_CONFIRM
|
||||
#define MSG_CONFIRM 0
|
||||
@@ -125,12 +124,12 @@ struct mud_msg {
|
||||
unsigned char mtu[2];
|
||||
unsigned char loss;
|
||||
unsigned char fixed_rate;
|
||||
unsigned char loss_limit;
|
||||
struct mud_addr addr;
|
||||
};
|
||||
|
||||
struct mud_keyx {
|
||||
uint64_t time;
|
||||
uint64_t timeout;
|
||||
unsigned char secret[crypto_scalarmult_SCALARBYTES];
|
||||
unsigned char remote[MUD_PUBKEY_SIZE];
|
||||
unsigned char local[MUD_PUBKEY_SIZE];
|
||||
@@ -142,16 +141,13 @@ struct mud_keyx {
|
||||
struct mud {
|
||||
int fd;
|
||||
int backup;
|
||||
uint64_t keepalive;
|
||||
uint64_t time_tolerance;
|
||||
uint64_t loss_limit;
|
||||
struct mud_conf conf;
|
||||
struct sockaddr_storage addr;
|
||||
struct mud_path *paths;
|
||||
unsigned count;
|
||||
struct mud_keyx keyx;
|
||||
uint64_t last_recv_time;
|
||||
size_t mtu;
|
||||
int tc;
|
||||
struct {
|
||||
int set;
|
||||
struct sockaddr_storage addr;
|
||||
@@ -161,36 +157,29 @@ struct mud {
|
||||
uint64_t window;
|
||||
uint64_t window_time;
|
||||
uint64_t base_time;
|
||||
#if defined __APPLE__
|
||||
mach_timebase_info_data_t mtid;
|
||||
#endif
|
||||
};
|
||||
|
||||
static int
|
||||
mud_addr_is_v6(struct mud_addr *addr)
|
||||
{
|
||||
static const unsigned char v4mapped[] = {
|
||||
[10] = 255,
|
||||
[11] = 255,
|
||||
};
|
||||
|
||||
return memcmp(addr->v6, v4mapped, sizeof(v4mapped));
|
||||
}
|
||||
|
||||
static int
|
||||
static inline int
|
||||
mud_encrypt_opt(const struct mud_crypto_key *k,
|
||||
const struct mud_crypto_opt *c)
|
||||
{
|
||||
if (k->aes) {
|
||||
unsigned char npub[AEGIS256_NPUBBYTES];
|
||||
unsigned char npub[crypto_aead_aegis256_NPUBBYTES];
|
||||
|
||||
memcpy(npub, c->dst, MUD_TIME_SIZE);
|
||||
memset(npub + MUD_TIME_SIZE, 0, sizeof(npub) - MUD_TIME_SIZE);
|
||||
|
||||
return aegis256_encrypt(
|
||||
return crypto_aead_aegis256_encrypt(
|
||||
c->dst + MUD_TIME_SIZE,
|
||||
NULL,
|
||||
c->src,
|
||||
c->size,
|
||||
c->dst,
|
||||
MUD_TIME_SIZE,
|
||||
NULL, // nsec
|
||||
npub,
|
||||
k->encrypt.key
|
||||
);
|
||||
@@ -214,19 +203,20 @@ mud_encrypt_opt(const struct mud_crypto_key *k,
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
static inline int
|
||||
mud_decrypt_opt(const struct mud_crypto_key *k,
|
||||
const struct mud_crypto_opt *c)
|
||||
{
|
||||
if (k->aes) {
|
||||
unsigned char npub[AEGIS256_NPUBBYTES];
|
||||
unsigned char npub[crypto_aead_aegis256_NPUBBYTES];
|
||||
|
||||
memcpy(npub, c->src, MUD_TIME_SIZE);
|
||||
memset(npub + MUD_TIME_SIZE, 0, sizeof(npub) - MUD_TIME_SIZE);
|
||||
|
||||
return aegis256_decrypt(
|
||||
return crypto_aead_aegis256_decrypt(
|
||||
c->dst,
|
||||
NULL,
|
||||
NULL, // nsec
|
||||
c->src + MUD_TIME_SIZE,
|
||||
c->size - MUD_TIME_SIZE,
|
||||
c->src, MUD_TIME_SIZE,
|
||||
@@ -252,47 +242,39 @@ mud_decrypt_opt(const struct mud_crypto_key *k,
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
static inline void
|
||||
mud_store(unsigned char *dst, uint64_t src, size_t size)
|
||||
{
|
||||
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||
memcpy(dst, &src, size);
|
||||
#else
|
||||
dst[0] = (unsigned char)(src);
|
||||
dst[1] = (unsigned char)(src >> 8);
|
||||
if (size < 48) return;
|
||||
if (size <= 2) return;
|
||||
dst[2] = (unsigned char)(src >> 16);
|
||||
dst[3] = (unsigned char)(src >> 24);
|
||||
dst[4] = (unsigned char)(src >> 32);
|
||||
dst[5] = (unsigned char)(src >> 40);
|
||||
if (size < 64) return;
|
||||
if (size <= 6) return;
|
||||
dst[6] = (unsigned char)(src >> 48);
|
||||
dst[7] = (unsigned char)(src >> 56);
|
||||
#endif
|
||||
}
|
||||
|
||||
static uint64_t
|
||||
static inline uint64_t
|
||||
mud_load(const unsigned char *src, size_t size)
|
||||
{
|
||||
uint64_t ret = 0;
|
||||
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||
memcpy(&ret, src, size);
|
||||
#else
|
||||
ret = src[0];
|
||||
ret |= ((uint64_t)src[1]) << 8;
|
||||
if (size < 48) return ret;
|
||||
if (size <= 2) return ret;
|
||||
ret |= ((uint64_t)src[2]) << 16;
|
||||
ret |= ((uint64_t)src[3]) << 24;
|
||||
ret |= ((uint64_t)src[4]) << 32;
|
||||
ret |= ((uint64_t)src[5]) << 40;
|
||||
if (size < 64) return ret;
|
||||
if (size <= 6) return ret;
|
||||
ret |= ((uint64_t)src[6]) << 48;
|
||||
ret |= ((uint64_t)src[7]) << 56;
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
static uint64_t
|
||||
static inline uint64_t
|
||||
mud_time(void)
|
||||
{
|
||||
#if defined CLOCK_REALTIME
|
||||
@@ -310,15 +292,12 @@ mud_time(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
static uint64_t
|
||||
static inline uint64_t
|
||||
mud_now(struct mud *mud)
|
||||
{
|
||||
#if defined __APPLE__
|
||||
static mach_timebase_info_data_t mtid;
|
||||
if (!mtid.denom)
|
||||
mach_timebase_info(&mtid);
|
||||
return MUD_TIME_MASK(mud->base_time
|
||||
+ (mach_absolute_time() * mtid.numer / mtid.denom)
|
||||
+ (mach_absolute_time() * mud->mtid.numer / mud->mtid.denom)
|
||||
/ 1000ULL);
|
||||
#elif defined CLOCK_MONOTONIC
|
||||
struct timespec tv;
|
||||
@@ -331,19 +310,19 @@ mud_now(struct mud *mud)
|
||||
#endif
|
||||
}
|
||||
|
||||
static uint64_t
|
||||
static inline uint64_t
|
||||
mud_abs_diff(uint64_t a, uint64_t b)
|
||||
{
|
||||
return (a >= b) ? a - b : b - a;
|
||||
}
|
||||
|
||||
static int
|
||||
static inline int
|
||||
mud_timeout(uint64_t now, uint64_t last, uint64_t timeout)
|
||||
{
|
||||
return (!last) || (MUD_TIME_MASK(now - last) >= timeout);
|
||||
}
|
||||
|
||||
static void
|
||||
static inline void
|
||||
mud_unmapv4(struct sockaddr_storage *addr)
|
||||
{
|
||||
if (addr->ss_family != AF_INET6)
|
||||
@@ -427,7 +406,7 @@ mud_send_path(struct mud *mud, struct mud_path *path, uint64_t now,
|
||||
cmsg->cmsg_level = IPPROTO_IP;
|
||||
cmsg->cmsg_type = IP_TOS;
|
||||
cmsg->cmsg_len = CMSG_LEN(sizeof(int));
|
||||
memcpy(CMSG_DATA(cmsg), &mud->tc, sizeof(int));
|
||||
memcpy(CMSG_DATA(cmsg), &mud->conf.tc, sizeof(int));
|
||||
|
||||
} else if (path->addr.ss_family == AF_INET6) {
|
||||
msg.msg_namelen = sizeof(struct sockaddr_in6);
|
||||
@@ -449,7 +428,7 @@ mud_send_path(struct mud *mud, struct mud_path *path, uint64_t now,
|
||||
cmsg->cmsg_level = IPPROTO_IPV6;
|
||||
cmsg->cmsg_type = IPV6_TCLASS;
|
||||
cmsg->cmsg_len = CMSG_LEN(sizeof(int));
|
||||
memcpy(CMSG_DATA(cmsg), &mud->tc, sizeof(int));
|
||||
memcpy(CMSG_DATA(cmsg), &mud->conf.tc, sizeof(int));
|
||||
} else {
|
||||
errno = EAFNOSUPPORT;
|
||||
return -1;
|
||||
@@ -476,35 +455,6 @@ mud_sso_int(int fd, int level, int optname, int opt)
|
||||
return setsockopt(fd, level, optname, &opt, sizeof(opt));
|
||||
}
|
||||
|
||||
static int
|
||||
mud_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_port, &_b->sin_port,
|
||||
sizeof(_a->sin_port))) ||
|
||||
(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_port, &_b->sin6_port,
|
||||
sizeof(_a->sin6_port))) ||
|
||||
(memcmp(&_a->sin6_addr, &_b->sin6_addr,
|
||||
sizeof(_a->sin6_addr))));
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
struct mud_path *
|
||||
mud_get_paths(struct mud *mud, unsigned *ret_count)
|
||||
{
|
||||
@@ -548,34 +498,6 @@ mud_get_paths(struct mud *mud, unsigned *ret_count)
|
||||
return paths;
|
||||
}
|
||||
|
||||
static void
|
||||
mud_copy_port(struct sockaddr_storage *d, struct sockaddr_storage *s)
|
||||
{
|
||||
void *port;
|
||||
|
||||
switch (s->ss_family) {
|
||||
case AF_INET:
|
||||
port = &((struct sockaddr_in *)s)->sin_port;
|
||||
break;
|
||||
case AF_INET6:
|
||||
port = &((struct sockaddr_in6 *)s)->sin6_port;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
switch (d->ss_family) {
|
||||
case AF_INET:
|
||||
memcpy(&((struct sockaddr_in *)d)->sin_port,
|
||||
port, sizeof(in_port_t));
|
||||
break;
|
||||
case AF_INET6:
|
||||
memcpy(&((struct sockaddr_in6 *)d)->sin6_port,
|
||||
port, sizeof(in_port_t));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
mud_reset_path(struct mud_path *path)
|
||||
{
|
||||
@@ -584,6 +506,48 @@ mud_reset_path(struct mud_path *path)
|
||||
path->mtu.last = 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
mud_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 inline int
|
||||
mud_cmp_port(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_port, &_b->sin_port, sizeof(_a->sin_port));
|
||||
}
|
||||
|
||||
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_port, &_b->sin6_port, sizeof(_a->sin6_port));
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct mud_path *
|
||||
mud_get_path(struct mud *mud, struct sockaddr_storage *local_addr,
|
||||
struct sockaddr_storage *addr, int create)
|
||||
@@ -593,15 +557,18 @@ mud_get_path(struct mud *mud, struct sockaddr_storage *local_addr,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mud_copy_port(local_addr, &mud->addr);
|
||||
|
||||
for (unsigned i = 0; i < mud->count; i++) {
|
||||
struct mud_path *path = &mud->paths[i];
|
||||
|
||||
if ((path->state != MUD_EMPTY) &&
|
||||
(!mud_cmp_addr(local_addr, &path->local_addr)) &&
|
||||
(!mud_cmp_addr(addr, &path->addr)))
|
||||
return path;
|
||||
if (path->state == MUD_EMPTY)
|
||||
continue;
|
||||
|
||||
if (mud_cmp_addr(local_addr, &path->local_addr) ||
|
||||
mud_cmp_addr(addr, &path->addr) ||
|
||||
mud_cmp_port(addr, &path->addr))
|
||||
continue;
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
if (!create) {
|
||||
@@ -644,6 +611,7 @@ mud_get_path(struct mud *mud, struct sockaddr_storage *local_addr,
|
||||
path->state = MUD_UP;
|
||||
path->conf.beat = 100 * MUD_ONE_MSEC;
|
||||
path->conf.fixed_rate = 1;
|
||||
path->conf.loss_limit = 255;
|
||||
path->idle = mud_now(mud);
|
||||
|
||||
return path;
|
||||
@@ -738,69 +706,36 @@ mud_set_key(struct mud *mud, unsigned char *key, size_t size)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
mud_set_msec(uint64_t *dst, unsigned long msec)
|
||||
{
|
||||
if (!msec)
|
||||
return 0;
|
||||
|
||||
const uint64_t x = msec * MUD_ONE_MSEC;
|
||||
|
||||
if ((x >> MUD_TIME_BITS) ||
|
||||
((uint64_t)msec != x / MUD_ONE_MSEC)) {
|
||||
errno = ERANGE;
|
||||
return -1;
|
||||
}
|
||||
|
||||
*dst = x;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
mud_set_conf(struct mud *mud, struct mud_conf *conf)
|
||||
{
|
||||
uint64_t keepalive = mud->keepalive;
|
||||
uint64_t timetolerance = mud->time_tolerance;
|
||||
uint64_t kxtimeout = mud->keyx.timeout;
|
||||
uint64_t losslimit = mud->loss_limit;
|
||||
int tc = mud->tc;
|
||||
struct mud_conf c = mud->conf;
|
||||
int ret = 0;
|
||||
|
||||
if (mud_set_msec(&keepalive, conf->keepalive))
|
||||
return -1;
|
||||
if (conf->keepalive)
|
||||
c.keepalive = conf->keepalive;
|
||||
|
||||
if (mud_set_msec(&timetolerance, conf->timetolerance))
|
||||
return -2;
|
||||
if (conf->timetolerance)
|
||||
c.timetolerance = conf->timetolerance;
|
||||
|
||||
if (mud_set_msec(&kxtimeout, conf->kxtimeout))
|
||||
return -3;
|
||||
|
||||
if (conf->losslimit) {
|
||||
if (conf->losslimit > 100) {
|
||||
errno = ERANGE;
|
||||
return -4;
|
||||
}
|
||||
losslimit = conf->losslimit * 255U / 100U;
|
||||
}
|
||||
if (conf->kxtimeout)
|
||||
c.kxtimeout = conf->kxtimeout;
|
||||
|
||||
if (conf->tc & 1) {
|
||||
tc = conf->tc >> 1;
|
||||
int tc = conf->tc >> 1;
|
||||
if (tc < 0 || tc > 255) {
|
||||
errno = ERANGE;
|
||||
return -5;
|
||||
ret = -1;
|
||||
}
|
||||
c.tc = tc;
|
||||
} else if (conf->tc) {
|
||||
errno = EINVAL;
|
||||
return -5;
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
mud->keepalive = keepalive;
|
||||
mud->time_tolerance = timetolerance;
|
||||
mud->keyx.timeout = kxtimeout;
|
||||
mud->loss_limit = losslimit;
|
||||
mud->tc = tc;
|
||||
*conf = mud->conf = c;
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
size_t
|
||||
@@ -869,9 +804,11 @@ mud_keyx(struct mud_keyx *kx, unsigned char *remote, int aes)
|
||||
}
|
||||
|
||||
static int
|
||||
mud_keyx_init(struct mud_keyx *kx, uint64_t now)
|
||||
mud_keyx_init(struct mud *mud, uint64_t now)
|
||||
{
|
||||
if (!mud_timeout(now, kx->time, kx->timeout))
|
||||
struct mud_keyx *kx = &mud->keyx;
|
||||
|
||||
if (!mud_timeout(now, kx->time, mud->conf.kxtimeout))
|
||||
return 1;
|
||||
|
||||
static const unsigned char test[crypto_scalarmult_BYTES] = {
|
||||
@@ -896,7 +833,7 @@ mud_keyx_init(struct mud_keyx *kx, uint64_t now)
|
||||
int
|
||||
mud_set_aes(struct mud *mud)
|
||||
{
|
||||
if (!aegis256_is_available()) {
|
||||
if (!crypto_aead_aegis256_is_available()) {
|
||||
errno = ENOTSUP;
|
||||
return -1;
|
||||
}
|
||||
@@ -948,14 +885,17 @@ mud_create(struct sockaddr *addr)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mud->keepalive = 25 * MUD_ONE_SEC;
|
||||
mud->time_tolerance = 10 * MUD_ONE_MIN;
|
||||
mud->keyx.timeout = 60 * MUD_ONE_MIN;
|
||||
mud->tc = 192; // CS6
|
||||
mud->loss_limit = 25;
|
||||
mud->conf.keepalive = 25 * MUD_ONE_SEC;
|
||||
mud->conf.timetolerance = 10 * MUD_ONE_MIN;
|
||||
mud->conf.kxtimeout = 60 * MUD_ONE_MIN;
|
||||
mud->conf.tc = 192; // CS6
|
||||
|
||||
memcpy(&mud->addr, addr, addrlen);
|
||||
|
||||
#if defined __APPLE__
|
||||
mach_timebase_info(&mud->mtid);
|
||||
#endif
|
||||
|
||||
uint64_t now = mud_now(mud);
|
||||
uint64_t base_time = mud_time();
|
||||
|
||||
@@ -1054,32 +994,25 @@ mud_localaddr(struct sockaddr_storage *addr, struct msghdr *msg)
|
||||
|
||||
for (; cmsg; cmsg = CMSG_NXTHDR(msg, cmsg)) {
|
||||
if ((cmsg->cmsg_level == IPPROTO_IP) &&
|
||||
(cmsg->cmsg_type == MUD_PKTINFO))
|
||||
break;
|
||||
(cmsg->cmsg_type == MUD_PKTINFO)) {
|
||||
addr->ss_family = AF_INET;
|
||||
memcpy(&((struct sockaddr_in *)addr)->sin_addr,
|
||||
MUD_PKTINFO_SRC(CMSG_DATA(cmsg)),
|
||||
sizeof(struct in_addr));
|
||||
return 0;
|
||||
}
|
||||
if ((cmsg->cmsg_level == IPPROTO_IPV6) &&
|
||||
(cmsg->cmsg_type == IPV6_PKTINFO))
|
||||
break;
|
||||
(cmsg->cmsg_type == IPV6_PKTINFO)) {
|
||||
addr->ss_family = AF_INET6;
|
||||
memcpy(&((struct sockaddr_in6 *)addr)->sin6_addr,
|
||||
&((struct in6_pktinfo *)CMSG_DATA(cmsg))->ipi6_addr,
|
||||
sizeof(struct in6_addr));
|
||||
mud_unmapv4(addr);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!cmsg)
|
||||
return 1;
|
||||
|
||||
memset(addr, 0, sizeof(struct sockaddr_storage));
|
||||
|
||||
if (cmsg->cmsg_level == IPPROTO_IP) {
|
||||
addr->ss_family = AF_INET;
|
||||
memcpy(&((struct sockaddr_in *)addr)->sin_addr,
|
||||
MUD_PKTINFO_SRC(CMSG_DATA(cmsg)),
|
||||
sizeof(struct in_addr));
|
||||
} else {
|
||||
addr->ss_family = AF_INET6;
|
||||
memcpy(&((struct sockaddr_in6 *)addr)->sin6_addr,
|
||||
&((struct in6_pktinfo *)CMSG_DATA(cmsg))->ipi6_addr,
|
||||
sizeof(struct in6_addr));
|
||||
mud_unmapv4(addr);
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -1135,6 +1068,7 @@ mud_send_msg(struct mud *mud, struct mud_path *path, uint64_t now,
|
||||
|
||||
msg->loss = (unsigned char)path->tx.loss;
|
||||
msg->fixed_rate = path->conf.fixed_rate;
|
||||
msg->loss_limit = path->conf.loss_limit;
|
||||
|
||||
const struct mud_crypto_opt opt = {
|
||||
.dst = dst,
|
||||
@@ -1170,34 +1104,6 @@ mud_decrypt_msg(struct mud *mud,
|
||||
return size;
|
||||
}
|
||||
|
||||
static void
|
||||
mud_update_stat(struct mud_stat *stat, const uint64_t val)
|
||||
{
|
||||
if (stat->setup) {
|
||||
const uint64_t var = mud_abs_diff(stat->val, val);
|
||||
stat->var = ((stat->var << 1) + stat->var + var) >> 2;
|
||||
stat->val = ((stat->val << 3) - stat->val + val) >> 3;
|
||||
} else {
|
||||
stat->setup = 1;
|
||||
stat->var = val >> 1;
|
||||
stat->val = val;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
mud_ss_from_packet(struct sockaddr_storage *ss, struct mud_msg *pkt)
|
||||
{
|
||||
if (mud_addr_is_v6(&pkt->addr)) {
|
||||
ss->ss_family = AF_INET6;
|
||||
memcpy(&((struct sockaddr_in6 *)ss)->sin6_addr, pkt->addr.v6, 16);
|
||||
memcpy(&((struct sockaddr_in6 *)ss)->sin6_port, pkt->addr.port, 2);
|
||||
} else {
|
||||
ss->ss_family = AF_INET;
|
||||
memcpy(&((struct sockaddr_in *)ss)->sin_addr, pkt->addr.v4, 4);
|
||||
memcpy(&((struct sockaddr_in *)ss)->sin_port, pkt->addr.port, 2);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
mud_update_window(struct mud *mud, struct mud_path *path, uint64_t now,
|
||||
uint64_t tx_dt, uint64_t tx_bytes, uint64_t tx_pkt,
|
||||
@@ -1210,12 +1116,11 @@ mud_update_window(struct mud *mud, struct mud_path *path, uint64_t now,
|
||||
uint64_t tx_acc = path->msg.tx.acc + tx_pkt;
|
||||
uint64_t rx_acc = path->msg.rx.acc + rx_pkt;
|
||||
|
||||
if (tx_acc >= rx_acc)
|
||||
path->tx.loss = (tx_acc - rx_acc) * 255U / tx_acc;
|
||||
|
||||
if (tx_acc > 10000) {
|
||||
path->msg.tx.acc = tx_acc - (tx_acc >> 3);
|
||||
path->msg.rx.acc = rx_acc - (rx_acc >> 3);
|
||||
if (tx_acc > 1000) {
|
||||
if (tx_acc >= rx_acc)
|
||||
path->tx.loss = (tx_acc - rx_acc) * 255U / tx_acc;
|
||||
path->msg.tx.acc = tx_acc - (tx_acc >> 4);
|
||||
path->msg.rx.acc = rx_acc - (rx_acc >> 4);
|
||||
} else {
|
||||
path->msg.tx.acc = tx_acc;
|
||||
path->msg.rx.acc = rx_acc;
|
||||
@@ -1259,6 +1164,45 @@ mud_update_mtu(struct mud_path *path, size_t size)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
mud_update_stat(struct mud_stat *stat, const uint64_t val)
|
||||
{
|
||||
if (stat->setup) {
|
||||
const uint64_t var = mud_abs_diff(stat->val, val);
|
||||
stat->var = ((stat->var << 1) + stat->var + var) >> 2;
|
||||
stat->val = ((stat->val << 3) - stat->val + val) >> 3;
|
||||
} else {
|
||||
stat->setup = 1;
|
||||
stat->var = val >> 1;
|
||||
stat->val = val;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
mud_addr_is_v6(struct mud_addr *addr)
|
||||
{
|
||||
static const unsigned char v4mapped[] = {
|
||||
[10] = 255,
|
||||
[11] = 255,
|
||||
};
|
||||
|
||||
return memcmp(addr->v6, v4mapped, sizeof(v4mapped));
|
||||
}
|
||||
|
||||
static void
|
||||
mud_ss_from_packet(struct sockaddr_storage *ss, struct mud_msg *pkt)
|
||||
{
|
||||
if (mud_addr_is_v6(&pkt->addr)) {
|
||||
ss->ss_family = AF_INET6;
|
||||
memcpy(&((struct sockaddr_in6 *)ss)->sin6_addr, pkt->addr.v6, 16);
|
||||
memcpy(&((struct sockaddr_in6 *)ss)->sin6_port, pkt->addr.port, 2);
|
||||
} else {
|
||||
ss->ss_family = AF_INET;
|
||||
memcpy(&((struct sockaddr_in *)ss)->sin_addr, pkt->addr.v4, 4);
|
||||
memcpy(&((struct sockaddr_in *)ss)->sin_port, pkt->addr.port, 2);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
mud_recv_msg(struct mud *mud, struct mud_path *path,
|
||||
uint64_t now, uint64_t sent_time,
|
||||
@@ -1322,6 +1266,7 @@ mud_recv_msg(struct mud *mud, struct mud_path *path,
|
||||
|
||||
path->conf.tx_max_rate = max_rate;
|
||||
path->conf.fixed_rate = msg->fixed_rate;
|
||||
path->conf.loss_limit = msg->loss_limit;
|
||||
|
||||
path->msg.sent++;
|
||||
path->msg.time = now;
|
||||
@@ -1329,7 +1274,7 @@ mud_recv_msg(struct mud *mud, struct mud_path *path,
|
||||
|
||||
if (memcmp(msg->pkey, mud->keyx.remote, MUD_PUBKEY_SIZE)) {
|
||||
if (!mud->peer.set)
|
||||
mud_keyx_init(&mud->keyx, now);
|
||||
mud_keyx_init(mud, now);
|
||||
if (mud_keyx(&mud->keyx, msg->pkey, msg->aes)) {
|
||||
mud->bad.keyx.addr = path->addr;
|
||||
mud->bad.keyx.time = now;
|
||||
@@ -1379,8 +1324,8 @@ mud_recv(struct mud *mud, void *data, size_t size)
|
||||
|
||||
mud_unmapv4(&addr);
|
||||
|
||||
if ((MUD_TIME_MASK(now - sent_time) > mud->time_tolerance) &&
|
||||
(MUD_TIME_MASK(sent_time - now) > mud->time_tolerance)) {
|
||||
if ((MUD_TIME_MASK(now - sent_time) > mud->conf.timetolerance) &&
|
||||
(MUD_TIME_MASK(sent_time - now) > mud->conf.timetolerance)) {
|
||||
mud->bad.difftime.addr = addr;
|
||||
mud->bad.difftime.time = now;
|
||||
mud->bad.difftime.count++;
|
||||
@@ -1446,7 +1391,7 @@ mud_path_is_ok(struct mud *mud, struct mud_path *path)
|
||||
if (!path->mtu.ok)
|
||||
return 0;
|
||||
|
||||
if (path->tx.loss > mud->loss_limit)
|
||||
if (path->tx.loss > path->conf.loss_limit)
|
||||
return 0;
|
||||
|
||||
if (mud->peer.set)
|
||||
@@ -1465,7 +1410,7 @@ mud_update(struct mud *mud)
|
||||
|
||||
uint64_t now = mud_now(mud);
|
||||
|
||||
if (mud->peer.set && !mud_keyx_init(&mud->keyx, now))
|
||||
if (mud->peer.set && !mud_keyx_init(mud, now))
|
||||
now = mud_now(mud);
|
||||
|
||||
for (unsigned i = 0; i < mud->count; i++) {
|
||||
@@ -1507,7 +1452,7 @@ mud_update(struct mud *mud)
|
||||
if (path->msg.sent >= MUD_MSG_SENT_MAX) {
|
||||
timeout = 2 * MUD_MSG_SENT_MAX * timeout;
|
||||
} else if (path->ok && mud_timeout(now, path->idle, MUD_ONE_SEC)) {
|
||||
timeout = mud->keepalive;
|
||||
timeout = mud->conf.keepalive;
|
||||
}
|
||||
|
||||
if (mud_timeout(now, path->msg.time, timeout)) {
|
||||
@@ -1546,7 +1491,8 @@ mud_set_state(struct mud *mud, struct sockaddr *addr,
|
||||
unsigned long tx_max_rate,
|
||||
unsigned long rx_max_rate,
|
||||
unsigned long beat,
|
||||
unsigned char fixed_rate)
|
||||
unsigned char fixed_rate,
|
||||
unsigned char loss_limit)
|
||||
{
|
||||
if (!mud->peer.set || state > MUD_UP) {
|
||||
errno = EINVAL;
|
||||
@@ -1576,6 +1522,9 @@ mud_set_state(struct mud *mud, struct sockaddr *addr,
|
||||
if (fixed_rate)
|
||||
path->conf.fixed_rate = fixed_rate >> 1;
|
||||
|
||||
if (loss_limit)
|
||||
path->conf.loss_limit = loss_limit;
|
||||
|
||||
if (state && path->state != state) {
|
||||
path->state = state;
|
||||
mud_reset_path(path);
|
||||
|
||||
11
mud.h
11
mud.h
@@ -23,10 +23,9 @@ struct mud_stat {
|
||||
};
|
||||
|
||||
struct mud_conf {
|
||||
unsigned long keepalive;
|
||||
unsigned long timetolerance;
|
||||
unsigned long kxtimeout;
|
||||
unsigned losslimit;
|
||||
uint64_t keepalive;
|
||||
uint64_t timetolerance;
|
||||
uint64_t kxtimeout;
|
||||
int tc;
|
||||
};
|
||||
|
||||
@@ -65,6 +64,7 @@ struct mud_path {
|
||||
uint64_t rx_max_rate;
|
||||
uint64_t beat;
|
||||
unsigned char fixed_rate;
|
||||
unsigned char loss_limit;
|
||||
} conf;
|
||||
uint64_t idle;
|
||||
unsigned char ok;
|
||||
@@ -95,7 +95,8 @@ int mud_set_aes (struct mud *);
|
||||
int mud_set_conf (struct mud *, struct mud_conf *);
|
||||
|
||||
int mud_set_state (struct mud *, struct sockaddr *, enum mud_state,
|
||||
unsigned long, unsigned long, unsigned long, unsigned char);
|
||||
unsigned long, unsigned long, unsigned long,
|
||||
unsigned char, unsigned char);
|
||||
|
||||
int mud_peer (struct mud *, struct sockaddr *);
|
||||
|
||||
|
||||
3
test.c
3
test.c
@@ -1,5 +1,4 @@
|
||||
#include "mud.c"
|
||||
#include "aegis256/aegis256.c"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <poll.h>
|
||||
@@ -52,7 +51,7 @@ main(int argc, char **argv)
|
||||
|
||||
// ...from loopback at 1MBps (not 1Mbps)
|
||||
if (mud_set_state(mud, (struct sockaddr *)&local,
|
||||
MUD_UP, 1000 * 1000, 1000 * 1000, 0, 0)) {
|
||||
MUD_UP, 1000 * 1000, 1000 * 1000, 0, 0, 0)) {
|
||||
perror("mud_set_state");
|
||||
return -1;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user