Update protocol

Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
This commit is contained in:
Adrien Gallouët
2020-01-03 12:29:49 +00:00
parent e56abf5eaa
commit 6e8a3cef1e

161
mud.c
View File

@@ -62,7 +62,10 @@
#define MUD_ONE_SEC (1000 * MUD_ONE_MSEC)
#define MUD_ONE_MIN (60 * MUD_ONE_SEC)
#define MUD_U48_SIZE (6U)
#define MUD_TIME_SIZE (6U)
#define MUD_TIME_BITS (MUD_TIME_SIZE * 8U)
#define MUD_TIME_MASK(X) ((X) & ((UINT64_C(1) << MUD_TIME_BITS) - 2))
#define MUD_KEY_SIZE (32U)
#define MUD_MAC_SIZE (16U)
@@ -71,19 +74,19 @@
#define MUD_MSG_SENT_MAX (5)
#define MUD_MSG_TIMEOUT (100 * MUD_ONE_MSEC)
#define MUD_PKT_MIN_SIZE (MUD_U48_SIZE + MUD_MAC_SIZE)
#define MUD_PKT_MIN_SIZE (MUD_TIME_SIZE + MUD_MAC_SIZE)
#define MUD_PKT_MAX_SIZE (1500U)
#define MUD_MTU_MIN (1280U + MUD_PKT_MIN_SIZE)
#define MUD_MTU_MAX (1450U + MUD_PKT_MIN_SIZE)
#define MUD_TIME_BITS (48)
#define MUD_TIME_MASK(X) ((X) & ((UINT64_C(1) << MUD_TIME_BITS) - 2))
#define MUD_CTRL_SIZE (CMSG_SPACE(MUD_PKTINFO_SIZE) + \
CMSG_SPACE(sizeof(struct in6_pktinfo)) + \
CMSG_SPACE(sizeof(int)))
#define MUD_STORE_MSG(D,S) mud_store((D),(S),sizeof(D))
#define MUD_LOAD_MSG(S) mud_load((S),sizeof(S))
struct mud_crypto_opt {
unsigned char *dst;
const unsigned char *src;
@@ -110,21 +113,19 @@ struct mud_addr {
};
struct mud_msg {
unsigned char sent_time[MUD_U48_SIZE];
unsigned char sent_time[MUD_TIME_SIZE];
unsigned char state;
struct mud_addr addr;
unsigned char pkey[MUD_PUBKEY_SIZE];
unsigned char aes;
unsigned char mtu[MUD_U48_SIZE];
unsigned char fwd_total[MUD_U48_SIZE];
unsigned char fwd_bytes[MUD_U48_SIZE];
unsigned char tx_bytes[MUD_U48_SIZE];
unsigned char tx_total[MUD_U48_SIZE];
unsigned char rx_bytes[MUD_U48_SIZE];
unsigned char rx_total[MUD_U48_SIZE];
unsigned char tx_max_rate[MUD_U48_SIZE];
unsigned char msg_timeout[MUD_U48_SIZE];
unsigned char pkey[MUD_PUBKEY_SIZE];
struct {
unsigned char bytes[sizeof(uint64_t)];
unsigned char total[sizeof(uint64_t)];
} tx, rx, fw;
unsigned char max_rate[sizeof(uint64_t)];
unsigned char timeout[MUD_TIME_SIZE];
unsigned char mtu[2];
unsigned char loss;
struct mud_addr addr;
};
struct mud_keyx {
@@ -179,32 +180,32 @@ mud_encrypt_opt(const struct mud_crypto_key *k,
if (k->aes) {
unsigned char npub[AEGIS256_NPUBBYTES];
memcpy(npub, c->dst, MUD_U48_SIZE);
memset(npub + MUD_U48_SIZE, 0, sizeof(npub) - MUD_U48_SIZE);
memcpy(npub, c->dst, MUD_TIME_SIZE);
memset(npub + MUD_TIME_SIZE, 0, sizeof(npub) - MUD_TIME_SIZE);
return aegis256_encrypt(
c->dst + MUD_U48_SIZE,
c->dst + MUD_TIME_SIZE,
NULL,
c->src,
c->size,
c->dst,
MUD_U48_SIZE,
MUD_TIME_SIZE,
npub,
k->encrypt.key
);
} else {
unsigned char npub[crypto_aead_chacha20poly1305_NPUBBYTES];
memcpy(npub, c->dst, MUD_U48_SIZE);
memset(npub + MUD_U48_SIZE, 0, sizeof(npub) - MUD_U48_SIZE);
memcpy(npub, c->dst, MUD_TIME_SIZE);
memset(npub + MUD_TIME_SIZE, 0, sizeof(npub) - MUD_TIME_SIZE);
return crypto_aead_chacha20poly1305_encrypt(
c->dst + MUD_U48_SIZE,
c->dst + MUD_TIME_SIZE,
NULL,
c->src,
c->size,
c->dst,
MUD_U48_SIZE,
MUD_TIME_SIZE,
NULL,
npub,
k->encrypt.key
@@ -219,31 +220,31 @@ mud_decrypt_opt(const struct mud_crypto_key *k,
if (k->aes) {
unsigned char npub[AEGIS256_NPUBBYTES];
memcpy(npub, c->src, MUD_U48_SIZE);
memset(npub + MUD_U48_SIZE, 0, sizeof(npub) - MUD_U48_SIZE);
memcpy(npub, c->src, MUD_TIME_SIZE);
memset(npub + MUD_TIME_SIZE, 0, sizeof(npub) - MUD_TIME_SIZE);
return aegis256_decrypt(
c->dst,
NULL,
c->src + MUD_U48_SIZE,
c->size - MUD_U48_SIZE,
c->src, MUD_U48_SIZE,
c->src + MUD_TIME_SIZE,
c->size - MUD_TIME_SIZE,
c->src, MUD_TIME_SIZE,
npub,
k->decrypt.key
);
} else {
unsigned char npub[crypto_aead_chacha20poly1305_NPUBBYTES];
memcpy(npub, c->src, MUD_U48_SIZE);
memset(npub + MUD_U48_SIZE, 0, sizeof(npub) - MUD_U48_SIZE);
memcpy(npub, c->src, MUD_TIME_SIZE);
memset(npub + MUD_TIME_SIZE, 0, sizeof(npub) - MUD_TIME_SIZE);
return crypto_aead_chacha20poly1305_decrypt(
c->dst,
NULL,
NULL,
c->src + MUD_U48_SIZE,
c->size - MUD_U48_SIZE,
c->src, MUD_U48_SIZE,
c->src + MUD_TIME_SIZE,
c->size - MUD_TIME_SIZE,
c->src, MUD_TIME_SIZE,
npub,
k->decrypt.key
);
@@ -251,25 +252,42 @@ mud_decrypt_opt(const struct mud_crypto_key *k,
}
static void
mud_write48(unsigned char *dst, uint64_t src)
mud_store(unsigned char *dst, uint64_t src, size_t size)
{
dst[0] = (unsigned char)(UINT64_C(255) & (src));
dst[1] = (unsigned char)(UINT64_C(255) & (src >> 8));
dst[2] = (unsigned char)(UINT64_C(255) & (src >> 16));
dst[3] = (unsigned char)(UINT64_C(255) & (src >> 24));
dst[4] = (unsigned char)(UINT64_C(255) & (src >> 32));
dst[5] = (unsigned char)(UINT64_C(255) & (src >> 40));
#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;
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;
dst[6] = (unsigned char)(src >> 48);
dst[7] = (unsigned char)(src >> 56);
#endif
}
static uint64_t
mud_read48(const unsigned char *src)
mud_load(const unsigned char *src, size_t size)
{
uint64_t ret = src[0];
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;
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;
ret |= ((uint64_t)src[6]) << 48;
ret |= ((uint64_t)src[7]) << 56;
#endif
return ret;
}
@@ -976,7 +994,7 @@ mud_encrypt(struct mud *mud, uint64_t now,
.size = src_size,
};
mud_write48(dst, now);
mud_store(dst, now, MUD_TIME_SIZE);
if (mud->keyx.use_next) {
mud_encrypt_opt(&mud->keyx.next, &opt);
@@ -1055,7 +1073,7 @@ mud_localaddr(struct sockaddr_storage *addr, struct msghdr *msg)
static int
mud_send_msg(struct mud *mud, struct mud_path *path, uint64_t now,
uint64_t sent_time, uint64_t fwd_bytes, uint64_t fwd_total,
uint64_t sent_time, uint64_t fw_bytes, uint64_t fw_total,
size_t size)
{
unsigned char dst[MUD_PKT_MAX_SIZE];
@@ -1067,8 +1085,8 @@ mud_send_msg(struct mud *mud, struct mud_path *path, uint64_t now,
if (size < MUD_PKT_MIN_SIZE + sizeof(struct mud_msg))
size = MUD_PKT_MIN_SIZE + sizeof(struct mud_msg);
mud_write48(dst, MUD_MSG_MARK(now));
mud_write48(msg->sent_time, sent_time);
mud_store(dst, MUD_MSG_MARK(now), MUD_TIME_SIZE);
MUD_STORE_MSG(msg->sent_time, sent_time);
if (path->addr.ss_family == AF_INET) {
msg->addr.ff[0] = 0xFF;
@@ -1093,16 +1111,17 @@ mud_send_msg(struct mud *mud, struct mud_path *path, uint64_t now,
msg->aes = (unsigned char)mud->keyx.aes;
if (!path->mtu.probe)
mud_write48(msg->mtu, path->mtu.ok);
MUD_STORE_MSG(msg->mtu, path->mtu.ok);
MUD_STORE_MSG(msg->tx.bytes, path->tx.bytes);
MUD_STORE_MSG(msg->rx.bytes, path->rx.bytes);
MUD_STORE_MSG(msg->tx.total, path->tx.total);
MUD_STORE_MSG(msg->rx.total, path->rx.total);
MUD_STORE_MSG(msg->fw.bytes, fw_bytes);
MUD_STORE_MSG(msg->fw.total, fw_total);
MUD_STORE_MSG(msg->max_rate, path->conf.rx_max_rate);
MUD_STORE_MSG(msg->timeout, path->conf.msg_timeout);
mud_write48(msg->tx_bytes, path->tx.bytes);
mud_write48(msg->rx_bytes, path->rx.bytes);
mud_write48(msg->tx_total, path->tx.total);
mud_write48(msg->rx_total, path->rx.total);
mud_write48(msg->fwd_bytes, fwd_bytes);
mud_write48(msg->fwd_total, fwd_total);
mud_write48(msg->tx_max_rate, path->conf.rx_max_rate);
mud_write48(msg->msg_timeout, path->conf.msg_timeout);
msg->loss = (unsigned char)path->tx.loss;
const struct mud_crypto_opt opt = {
@@ -1231,15 +1250,15 @@ mud_recv_msg(struct mud *mud, struct mud_path *path,
mud_ss_from_packet(&path->r_addr, msg);
const uint64_t tx_time = mud_read48(msg->sent_time);
const uint64_t tx_time = MUD_LOAD_MSG(msg->sent_time);
if (tx_time) {
mud_update_stat(&path->rtt, MUD_TIME_MASK(now - tx_time));
const uint64_t tx_bytes = mud_read48(msg->fwd_bytes);
const uint64_t tx_total = mud_read48(msg->fwd_total);
const uint64_t rx_bytes = mud_read48(msg->rx_bytes);
const uint64_t rx_total = mud_read48(msg->rx_total);
const uint64_t tx_bytes = MUD_LOAD_MSG(msg->fw.bytes);
const uint64_t tx_total = MUD_LOAD_MSG(msg->fw.total);
const uint64_t rx_bytes = MUD_LOAD_MSG(msg->rx.bytes);
const uint64_t rx_total = MUD_LOAD_MSG(msg->rx.total);
const uint64_t rx_time = sent_time;
if ((tx_time > path->msg.tx.time) && (tx_bytes > path->msg.tx.bytes) &&
@@ -1272,14 +1291,14 @@ mud_recv_msg(struct mud *mud, struct mud_path *path,
}
} else {
path->state = (enum mud_state)msg->state;
path->mtu.ok = mud_read48(msg->mtu);
path->conf.msg_timeout = mud_read48(msg->msg_timeout);
path->mtu.ok = MUD_LOAD_MSG(msg->mtu);
path->conf.msg_timeout = MUD_LOAD_MSG(msg->timeout);
const uint64_t tx_max_rate = mud_read48(msg->tx_max_rate);
const uint64_t max_rate = MUD_LOAD_MSG(msg->max_rate);
if (path->conf.tx_max_rate != tx_max_rate) {
path->conf.tx_max_rate = tx_max_rate;
path->tx.rate = tx_max_rate;
if (path->conf.tx_max_rate != max_rate) {
path->conf.tx_max_rate = max_rate;
path->tx.rate = max_rate;
}
path->msg.sent++;
@@ -1300,8 +1319,8 @@ mud_recv_msg(struct mud *mud, struct mud_path *path,
}
mud_send_msg(mud, path, now, sent_time,
mud_read48(msg->tx_bytes),
mud_read48(msg->tx_total),
MUD_LOAD_MSG(msg->tx.bytes),
MUD_LOAD_MSG(msg->tx.total),
size);
}
@@ -1334,7 +1353,7 @@ mud_recv(struct mud *mud, void *data, size_t size)
return 0;
const uint64_t now = mud_now(mud);
const uint64_t sent_time = mud_read48(packet);
const uint64_t sent_time = mud_load(packet, MUD_TIME_SIZE);
mud_unmapv4(&addr);