Add mud_get_paths() to export all paths
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
This commit is contained in:
197
mud.c
197
mud.c
@@ -1,5 +1,3 @@
|
|||||||
#include "mud.h"
|
|
||||||
|
|
||||||
#if defined __APPLE__
|
#if defined __APPLE__
|
||||||
#define __APPLE_USE_RFC_3542
|
#define __APPLE_USE_RFC_3542
|
||||||
#endif
|
#endif
|
||||||
@@ -8,15 +6,15 @@
|
|||||||
#define _GNU_SOURCE
|
#define _GNU_SOURCE
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "mud.h"
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <inttypes.h>
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
|
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
@@ -65,7 +63,6 @@
|
|||||||
#define MUD_KEY_SIZE (32U)
|
#define MUD_KEY_SIZE (32U)
|
||||||
#define MUD_MAC_SIZE (16U)
|
#define MUD_MAC_SIZE (16U)
|
||||||
#define MUD_PUB_SIZE (crypto_scalarmult_BYTES)
|
#define MUD_PUB_SIZE (crypto_scalarmult_BYTES)
|
||||||
#define MUD_SID_SIZE (8U)
|
|
||||||
|
|
||||||
#define MUD_PACKET_MIN_SIZE (MUD_U48_SIZE + MUD_MAC_SIZE)
|
#define MUD_PACKET_MIN_SIZE (MUD_U48_SIZE + MUD_MAC_SIZE)
|
||||||
#define MUD_PACKET_MAX_SIZE (1500U)
|
#define MUD_PACKET_MAX_SIZE (1500U)
|
||||||
@@ -80,33 +77,6 @@
|
|||||||
#define MUD_SEND_TIMEOUT (MUD_ONE_SEC)
|
#define MUD_SEND_TIMEOUT (MUD_ONE_SEC)
|
||||||
#define MUD_TIME_TOLERANCE (10 * MUD_ONE_MIN)
|
#define MUD_TIME_TOLERANCE (10 * MUD_ONE_MIN)
|
||||||
|
|
||||||
struct mud_path {
|
|
||||||
enum mud_state state;
|
|
||||||
struct sockaddr_storage local_addr, addr;
|
|
||||||
struct {
|
|
||||||
uint64_t send_time;
|
|
||||||
int remote;
|
|
||||||
struct {
|
|
||||||
size_t remote;
|
|
||||||
size_t local;
|
|
||||||
} mtu;
|
|
||||||
unsigned char kiss[MUD_SID_SIZE];
|
|
||||||
} conf;
|
|
||||||
uint64_t rdt;
|
|
||||||
uint64_t rtt;
|
|
||||||
uint64_t sdt;
|
|
||||||
uint64_t rst;
|
|
||||||
uint64_t r_sdt;
|
|
||||||
uint64_t r_rdt;
|
|
||||||
uint64_t r_rst;
|
|
||||||
int64_t r_dt;
|
|
||||||
uint64_t limit;
|
|
||||||
uint64_t recv_time;
|
|
||||||
uint64_t send_time;
|
|
||||||
uint64_t stat_time;
|
|
||||||
struct mud_path *next;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct mud_crypto_opt {
|
struct mud_crypto_opt {
|
||||||
unsigned char *dst;
|
unsigned char *dst;
|
||||||
struct {
|
struct {
|
||||||
@@ -142,7 +112,7 @@ struct mud_packet {
|
|||||||
} hdr;
|
} hdr;
|
||||||
union {
|
union {
|
||||||
struct {
|
struct {
|
||||||
unsigned char kiss[MUD_SID_SIZE];
|
unsigned char kiss[MUD_KISS_SIZE];
|
||||||
unsigned char mtu[MUD_U48_SIZE];
|
unsigned char mtu[MUD_U48_SIZE];
|
||||||
unsigned char state;
|
unsigned char state;
|
||||||
struct mud_public public;
|
struct mud_public public;
|
||||||
@@ -161,7 +131,8 @@ struct mud {
|
|||||||
int fd;
|
int fd;
|
||||||
uint64_t send_timeout;
|
uint64_t send_timeout;
|
||||||
uint64_t time_tolerance;
|
uint64_t time_tolerance;
|
||||||
struct mud_path *path;
|
struct mud_path *paths;
|
||||||
|
unsigned count;
|
||||||
struct {
|
struct {
|
||||||
uint64_t time;
|
uint64_t time;
|
||||||
unsigned char secret[crypto_scalarmult_SCALARBYTES];
|
unsigned char secret[crypto_scalarmult_SCALARBYTES];
|
||||||
@@ -177,7 +148,7 @@ struct mud {
|
|||||||
int set;
|
int set;
|
||||||
struct sockaddr_storage addr;
|
struct sockaddr_storage addr;
|
||||||
} peer;
|
} peer;
|
||||||
unsigned char kiss[MUD_SID_SIZE];
|
unsigned char kiss[MUD_KISS_SIZE];
|
||||||
};
|
};
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@@ -392,41 +363,92 @@ mud_cmp_addr(struct sockaddr_storage *a, struct sockaddr_storage *b)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct mud_path *
|
||||||
|
mud_get_paths(struct mud *mud, unsigned *ret_count)
|
||||||
|
{
|
||||||
|
unsigned count = 0;
|
||||||
|
|
||||||
|
if (!ret_count)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < mud->count; i++) {
|
||||||
|
struct mud_path *path = &mud->paths[i];
|
||||||
|
|
||||||
|
if (path->state != MUD_EMPTY)
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t size = count * sizeof(struct mud_path);
|
||||||
|
|
||||||
|
if (!size)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
struct mud_path *paths = malloc(size);
|
||||||
|
|
||||||
|
if (!paths)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
count = 0;
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < mud->count; i++) {
|
||||||
|
struct mud_path *path = &mud->paths[i];
|
||||||
|
|
||||||
|
if (path->state != MUD_EMPTY)
|
||||||
|
memcpy(&paths[count++], path, sizeof(struct mud_path));
|
||||||
|
}
|
||||||
|
|
||||||
|
*ret_count = count;
|
||||||
|
|
||||||
|
return paths;
|
||||||
|
}
|
||||||
|
|
||||||
static struct mud_path *
|
static struct mud_path *
|
||||||
mud_get_path(struct mud *mud, struct sockaddr_storage *local_addr,
|
mud_get_path(struct mud *mud, struct sockaddr_storage *local_addr,
|
||||||
struct sockaddr_storage *addr, int create)
|
struct sockaddr_storage *addr, int create)
|
||||||
{
|
{
|
||||||
struct mud_path *path;
|
|
||||||
|
|
||||||
if (local_addr->ss_family != addr->ss_family) {
|
if (local_addr->ss_family != addr->ss_family) {
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (path = mud->path; path; path = path->next) {
|
for (unsigned i = 0; i < mud->count; i++) {
|
||||||
if (mud_cmp_addr(local_addr, &path->local_addr))
|
struct mud_path *path = &mud->paths[i];
|
||||||
continue;
|
|
||||||
|
|
||||||
if (mud_cmp_addr(addr, &path->addr))
|
if (path->state &&
|
||||||
continue;
|
!mud_cmp_addr(local_addr, &path->local_addr) &&
|
||||||
|
!mud_cmp_addr(addr, &path->addr))
|
||||||
break;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (path || !create)
|
if (!create)
|
||||||
return path;
|
|
||||||
|
|
||||||
path = calloc(1, sizeof(struct mud_path));
|
|
||||||
|
|
||||||
if (!path)
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
memmove(&path->local_addr, local_addr, sizeof(*local_addr));
|
struct mud_path *path = NULL;
|
||||||
memmove(&path->addr, addr, sizeof(*addr));
|
|
||||||
|
for (unsigned i = 0; i < mud->count; i++) {
|
||||||
|
if (mud->paths[i].state == MUD_EMPTY) {
|
||||||
|
path = &mud->paths[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!path) {
|
||||||
|
struct mud_path *paths = realloc(mud->paths,
|
||||||
|
(mud->count + 1) * sizeof(struct mud_path));
|
||||||
|
|
||||||
|
if (!paths)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
mud->count++;
|
||||||
|
mud->paths = paths;
|
||||||
|
|
||||||
|
path = &paths[mud->count - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(&path->local_addr, local_addr, sizeof(*local_addr));
|
||||||
|
memcpy(&path->addr, addr, sizeof(*addr));
|
||||||
|
|
||||||
path->conf.mtu.local = mud->mtu; // XXX
|
path->conf.mtu.local = mud->mtu; // XXX
|
||||||
path->next = mud->path;
|
|
||||||
mud->path = path;
|
|
||||||
|
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
@@ -564,7 +586,8 @@ mud_set_time_tolerance(struct mud *mud, unsigned long msec)
|
|||||||
int
|
int
|
||||||
mud_set_state(struct mud *mud, struct sockaddr *peer, enum mud_state state)
|
mud_set_state(struct mud *mud, struct sockaddr *peer, enum mud_state state)
|
||||||
{
|
{
|
||||||
if (!mud->peer.set || (state >= MUD_LAST)) {
|
if (!mud->peer.set ||
|
||||||
|
(state < MUD_DOWN) || (state > MUD_UP)) {
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -574,7 +597,7 @@ mud_set_state(struct mud *mud, struct sockaddr *peer, enum mud_state state)
|
|||||||
if (mud_ss_from_sa(&addr, peer))
|
if (mud_ss_from_sa(&addr, peer))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
struct mud_path *path = mud_get_path(mud, &addr, &mud->peer.addr, state != MUD_DOWN);
|
struct mud_path *path = mud_get_path(mud, &addr, &mud->peer.addr, state > MUD_DOWN);
|
||||||
|
|
||||||
if (!path)
|
if (!path)
|
||||||
return -1;
|
return -1;
|
||||||
@@ -591,11 +614,13 @@ size_t
|
|||||||
mud_get_mtu(struct mud *mud)
|
mud_get_mtu(struct mud *mud)
|
||||||
{
|
{
|
||||||
size_t mtu = mud->mtu;
|
size_t mtu = mud->mtu;
|
||||||
struct mud_path *path;
|
|
||||||
|
|
||||||
for (path = mud->path; path; path = path->next) {
|
for (unsigned i = 0; i < mud->count; i++) {
|
||||||
|
struct mud_path *path = &mud->paths[i];
|
||||||
|
|
||||||
if (path->conf.mtu.local && path->conf.mtu.local < mtu)
|
if (path->conf.mtu.local && path->conf.mtu.local < mtu)
|
||||||
mtu = path->conf.mtu.local;
|
mtu = path->conf.mtu.local;
|
||||||
|
|
||||||
if (path->conf.mtu.remote && path->conf.mtu.remote < mtu)
|
if (path->conf.mtu.remote && path->conf.mtu.remote < mtu)
|
||||||
mtu = path->conf.mtu.remote;
|
mtu = path->conf.mtu.remote;
|
||||||
}
|
}
|
||||||
@@ -614,11 +639,12 @@ mud_set_mtu(struct mud *mud, size_t mtu)
|
|||||||
|
|
||||||
mtu -= MUD_PACKET_MIN_SIZE;
|
mtu -= MUD_PACKET_MIN_SIZE;
|
||||||
|
|
||||||
struct mud_path *path;
|
for (unsigned i = 0; i < mud->count; i++) {
|
||||||
|
struct mud_path *path = &mud->paths[i];
|
||||||
|
|
||||||
for (path = mud->path; path; path = path->next) {
|
|
||||||
if (path->conf.mtu.local == mtu)
|
if (path->conf.mtu.local == mtu)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
path->conf.mtu.local = mtu;
|
path->conf.mtu.local = mtu;
|
||||||
path->conf.remote = 0;
|
path->conf.remote = 0;
|
||||||
}
|
}
|
||||||
@@ -789,17 +815,11 @@ mud_delete(struct mud *mud)
|
|||||||
if (!mud)
|
if (!mud)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
while (mud->path) {
|
if (mud->paths)
|
||||||
struct mud_path *path = mud->path;
|
free(mud->paths);
|
||||||
mud->path = path->next;
|
|
||||||
free(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mud->fd != -1) {
|
if (mud->fd >= 0)
|
||||||
int err = errno;
|
|
||||||
close(mud->fd);
|
close(mud->fd);
|
||||||
errno = err;
|
|
||||||
}
|
|
||||||
|
|
||||||
sodium_free(mud);
|
sodium_free(mud);
|
||||||
}
|
}
|
||||||
@@ -962,21 +982,13 @@ mud_packet_send(struct mud *mud, enum mud_packet_code code,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
mud_kiss_path(struct mud *mud, struct mud_path *path)
|
mud_kiss_path(struct mud *mud, unsigned char *kiss)
|
||||||
{
|
{
|
||||||
struct mud_path **p = &mud->path;
|
for (unsigned i = 0; i < mud->count; i++) {
|
||||||
|
struct mud_path *path = &mud->paths[i];
|
||||||
|
|
||||||
while (*p) {
|
if (memcmp(path->conf.kiss, kiss, sizeof(path->conf.kiss)))
|
||||||
struct mud_path *t = *p;
|
memset(path, 0, sizeof(struct mud_path));
|
||||||
|
|
||||||
if ((t == path) ||
|
|
||||||
!memcmp(t->conf.kiss, path->conf.kiss, sizeof(path->conf.kiss))) {
|
|
||||||
p = &t->next;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
*p = t->next;
|
|
||||||
free(t);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1037,7 +1049,7 @@ mud_packet_recv(struct mud *mud, struct mud_path *path,
|
|||||||
mud->crypto.use_next = 1;
|
mud->crypto.use_next = 1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
mud_kiss_path(mud, path);
|
mud_kiss_path(mud, path->conf.kiss);
|
||||||
mud_keyx(mud, packet->data.conf.public.local,
|
mud_keyx(mud, packet->data.conf.public.local,
|
||||||
packet->data.conf.aes);
|
packet->data.conf.aes);
|
||||||
path->state = (enum mud_state)packet->data.conf.state;
|
path->state = (enum mud_state)packet->data.conf.state;
|
||||||
@@ -1156,10 +1168,10 @@ mud_update(struct mud *mud)
|
|||||||
uint64_t now = mud_now();
|
uint64_t now = mud_now();
|
||||||
int update_keyx = !mud_keyx_init(mud, now);
|
int update_keyx = !mud_keyx_init(mud, now);
|
||||||
|
|
||||||
struct mud_path *path = mud->path;
|
for (unsigned i = 0; i < mud->count; i++) {
|
||||||
|
struct mud_path *path = &mud->paths[i];
|
||||||
|
|
||||||
for (; path; path = path->next) {
|
if (path->state < MUD_DOWN)
|
||||||
if (path->state == MUD_DOWN)
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (update_keyx || mud_timeout(now, path->recv_time, mud->send_timeout + MUD_ONE_SEC))
|
if (update_keyx || mud_timeout(now, path->recv_time, mud->send_timeout + MUD_ONE_SEC))
|
||||||
@@ -1196,17 +1208,18 @@ mud_send(struct mud *mud, const void *data, size_t size, int tc)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct mud_path *path;
|
|
||||||
struct mud_path *path_min = NULL;
|
struct mud_path *path_min = NULL;
|
||||||
struct mud_path *path_backup = NULL;
|
struct mud_path *path_backup = NULL;
|
||||||
|
|
||||||
int64_t limit_min = INT64_MAX;
|
int64_t limit_min = INT64_MAX;
|
||||||
|
|
||||||
for (path = mud->path; path; path = path->next) {
|
for (unsigned i = 0; i < mud->count; i++) {
|
||||||
switch (path->state) {
|
struct mud_path *path = &mud->paths[i];
|
||||||
case MUD_BACKUP: path_backup = path; /* FALLTHRU */
|
|
||||||
case MUD_DOWN: continue;
|
if (path->state <= MUD_DOWN) {
|
||||||
default: break;
|
if (path->state == MUD_BACKUP)
|
||||||
|
path_backup = path;
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t limit = path->limit;
|
int64_t limit = path->limit;
|
||||||
|
|||||||
39
mud.h
39
mud.h
@@ -1,15 +1,44 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
|
||||||
|
#define MUD_KISS_SIZE (8U)
|
||||||
|
|
||||||
struct mud;
|
struct mud;
|
||||||
struct sockaddr;
|
|
||||||
|
|
||||||
enum mud_state {
|
enum mud_state {
|
||||||
MUD_UP = 0,
|
MUD_EMPTY = 0,
|
||||||
MUD_BACKUP,
|
|
||||||
MUD_DOWN,
|
MUD_DOWN,
|
||||||
MUD_LAST,
|
MUD_BACKUP,
|
||||||
|
MUD_UP,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct mud_path {
|
||||||
|
enum mud_state state;
|
||||||
|
struct sockaddr_storage local_addr, addr;
|
||||||
|
struct {
|
||||||
|
uint64_t send_time;
|
||||||
|
int remote;
|
||||||
|
struct {
|
||||||
|
size_t remote;
|
||||||
|
size_t local;
|
||||||
|
} mtu;
|
||||||
|
unsigned char kiss[MUD_KISS_SIZE];
|
||||||
|
} conf;
|
||||||
|
uint64_t rdt;
|
||||||
|
uint64_t rtt;
|
||||||
|
uint64_t sdt;
|
||||||
|
uint64_t rst;
|
||||||
|
uint64_t r_sdt;
|
||||||
|
uint64_t r_rdt;
|
||||||
|
uint64_t r_rst;
|
||||||
|
int64_t r_dt;
|
||||||
|
uint64_t limit;
|
||||||
|
uint64_t recv_time;
|
||||||
|
uint64_t send_time;
|
||||||
|
uint64_t stat_time;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct mud *mud_create (struct sockaddr *);
|
struct mud *mud_create (struct sockaddr *);
|
||||||
@@ -34,3 +63,5 @@ int mud_peer (struct mud *, struct sockaddr *);
|
|||||||
|
|
||||||
int mud_recv (struct mud *, void *, size_t);
|
int mud_recv (struct mud *, void *, size_t);
|
||||||
int mud_send (struct mud *, const void *, size_t, int);
|
int mud_send (struct mud *, const void *, size_t, int);
|
||||||
|
|
||||||
|
struct mud_path *mud_get_paths(struct mud *, unsigned *);
|
||||||
|
|||||||
Reference in New Issue
Block a user