Compare commits

..

10 Commits

Author SHA1 Message Date
e4988b9e9c switch to libsodium implementation of aegis256 2020-06-09 20:59:55 +02:00
0183b35acf remove aegis256 submodule 2020-06-09 20:44:38 +02:00
Adrien Gallouët
faeb599a19 Rework mud_set_conf()
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2020-04-17 21:25:08 +00:00
Adrien Gallouët
a4e72918df Inline and move some functions
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2020-04-03 08:32:20 +00:00
Adrien Gallouët
d7e8dbe0e7 Code cleanup
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2020-03-30 20:43:49 +00:00
Adrien Gallouët
71d16f25ff Don't use a static mtid
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2020-03-26 22:31:33 +00:00
Adrien Gallouët
c426cef08b Fix non little endian arch
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2020-03-25 20:43:54 +00:00
Adrien Gallouët
bda2c6eaa7 Wait a few packets before computing the loss
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2020-03-07 15:13:37 +00:00
Adrien Gallouët
d68aee8249 Allow a different loss_limit per path
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2020-03-07 14:27:47 +00:00
Adrien Gallouët
2f966bb365 Fix fixed rate
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2020-02-29 09:57:08 +00:00
5 changed files with 188 additions and 243 deletions

4
.gitmodules vendored
View File

@@ -1,4 +0,0 @@
[submodule "aegis256"]
path = aegis256
url = https://github.com/angt/aegis256
ignore = dirty

Submodule aegis256 deleted from 42b0b3da1d

412
mud.c
View File

@@ -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,51 +1104,23 @@ 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,
uint64_t rx_dt, uint64_t rx_bytes, uint64_t rx_pkt)
{
if (rx_dt && rx_dt > tx_dt + (tx_dt >> 3)) {
path->tx.rate = (7 * rx_bytes * MUD_ONE_SEC) / (8 * rx_dt);
if (!path->conf.fixed_rate)
path->tx.rate = (7 * rx_bytes * MUD_ONE_SEC) / (8 * rx_dt);
} else {
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;
@@ -1258,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,
@@ -1321,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;
@@ -1328,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;
@@ -1378,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++;
@@ -1445,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)
@@ -1464,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++) {
@@ -1506,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)) {
@@ -1545,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;
@@ -1575,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
View File

@@ -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
View File

@@ -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;
}