Allow client to add the first path

Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
This commit is contained in:
Adrien Gallouët
2018-01-23 23:04:03 +00:00
parent 368ab1b710
commit 8d861c9682

147
mud.c
View File

@@ -185,6 +185,7 @@ struct mud {
} crypto; } crypto;
int mtu; int mtu;
int tc; int tc;
struct mud_path *peer;
unsigned char kiss[MUD_SID_SIZE]; unsigned char kiss[MUD_SID_SIZE];
}; };
@@ -425,57 +426,65 @@ mud_set_path(struct mud_path *path, struct mud_ipaddr *local_addr,
if (!cmsg) if (!cmsg)
return -1; return -1;
memset(path->ctrl.data, 0, sizeof(path->ctrl.data)); memset(&path->ctrl, 0, sizeof(path->ctrl));
memmove(&path->local_addr, local_addr, sizeof(struct mud_ipaddr));
if (local_addr)
memmove(&path->local_addr, local_addr, sizeof(struct mud_ipaddr));
if (addr->sa_family == AF_INET) { if (addr->sa_family == AF_INET) {
memmove(&path->addr, addr, sizeof(struct sockaddr_in)); memmove(&path->addr, addr, sizeof(struct sockaddr_in));
cmsg->cmsg_level = IPPROTO_IP; if (local_addr) {
cmsg->cmsg_type = MUD_PKTINFO; cmsg->cmsg_level = IPPROTO_IP;
cmsg->cmsg_len = CMSG_LEN(MUD_PKTINFO_SIZE); cmsg->cmsg_type = MUD_PKTINFO;
cmsg->cmsg_len = CMSG_LEN(MUD_PKTINFO_SIZE);
memcpy(MUD_PKTINFO_DST(CMSG_DATA(cmsg)), memcpy(MUD_PKTINFO_DST(CMSG_DATA(cmsg)),
&local_addr->ip.v4, &local_addr->ip.v4,
sizeof(struct in_addr)); sizeof(struct in_addr));
cmsg = CMSG_NXTHDR(&msg, cmsg); cmsg = CMSG_NXTHDR(&msg, cmsg);
if (!cmsg) if (!cmsg)
return -1; return -1;
path->ctrl.size += CMSG_SPACE(MUD_PKTINFO_SIZE);
}
cmsg->cmsg_level = IPPROTO_IP; cmsg->cmsg_level = IPPROTO_IP;
cmsg->cmsg_type = IP_TOS; cmsg->cmsg_type = IP_TOS;
cmsg->cmsg_len = CMSG_LEN(sizeof(int)); cmsg->cmsg_len = CMSG_LEN(sizeof(int));
path->tc = CMSG_DATA(cmsg); path->tc = CMSG_DATA(cmsg);
path->ctrl.size = CMSG_SPACE(MUD_PKTINFO_SIZE) + path->ctrl.size += CMSG_SPACE(sizeof(int));
CMSG_SPACE(sizeof(int));
} }
if (addr->sa_family == AF_INET6) { if (addr->sa_family == AF_INET6) {
memmove(&path->addr, addr, sizeof(struct sockaddr_in6)); memmove(&path->addr, addr, sizeof(struct sockaddr_in6));
cmsg->cmsg_level = IPPROTO_IPV6; if (local_addr) {
cmsg->cmsg_type = IPV6_PKTINFO; cmsg->cmsg_level = IPPROTO_IPV6;
cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo)); cmsg->cmsg_type = IPV6_PKTINFO;
cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
memcpy(&((struct in6_pktinfo *)CMSG_DATA(cmsg))->ipi6_addr, memcpy(&((struct in6_pktinfo *)CMSG_DATA(cmsg))->ipi6_addr,
&local_addr->ip.v6, &local_addr->ip.v6,
sizeof(struct in6_addr)); sizeof(struct in6_addr));
cmsg = CMSG_NXTHDR(&msg, cmsg); cmsg = CMSG_NXTHDR(&msg, cmsg);
if (!cmsg) if (!cmsg)
return -1; return -1;
path->ctrl.size += CMSG_SPACE(sizeof(struct in6_pktinfo));
}
cmsg->cmsg_level = IPPROTO_IPV6; cmsg->cmsg_level = IPPROTO_IPV6;
cmsg->cmsg_type = IPV6_TCLASS; cmsg->cmsg_type = IPV6_TCLASS;
cmsg->cmsg_len = CMSG_LEN(sizeof(int)); cmsg->cmsg_len = CMSG_LEN(sizeof(int));
path->tc = CMSG_DATA(cmsg); path->tc = CMSG_DATA(cmsg);
path->ctrl.size = CMSG_SPACE(sizeof(struct in6_pktinfo)) + path->ctrl.size += CMSG_SPACE(sizeof(int));
CMSG_SPACE(sizeof(int));
} }
return 0; return 0;
@@ -485,21 +494,25 @@ static struct mud_path *
mud_path(struct mud *mud, struct mud_ipaddr *local_addr, mud_path(struct mud *mud, struct mud_ipaddr *local_addr,
struct sockaddr *addr, int create) struct sockaddr *addr, int create)
{ {
if (local_addr->family != addr->sa_family) {
errno = EINVAL;
return NULL;
}
struct mud_path *path; struct mud_path *path;
for (path = mud->path; path; path = path->next) { if (local_addr) {
if (mud_cmp_ipaddr(local_addr, &path->local_addr)) if (local_addr->family != addr->sa_family) {
continue; errno = EINVAL;
return NULL;
}
if (mud_cmp_addr(addr, (struct sockaddr *)&path->addr)) for (path = mud->path; path; path = path->next) {
continue; if (mud_cmp_ipaddr(local_addr, &path->local_addr))
continue;
break; if (mud_cmp_addr(addr, (struct sockaddr *)&path->addr))
continue;
break;
}
} else {
path = mud->peer;
} }
if (path || !create) if (path || !create)
@@ -518,8 +531,12 @@ mud_path(struct mud *mud, struct mud_ipaddr *local_addr,
path->conf.mtu.local = mud->mtu; // XXX path->conf.mtu.local = mud->mtu; // XXX
path->next = mud->path; if (local_addr) {
mud->path = path; path->next = mud->path;
mud->path = path;
} else {
mud->peer = path;
}
return path; return path;
} }
@@ -528,22 +545,25 @@ int
mud_peer(struct mud *mud, const char *name, const char *host, int port, mud_peer(struct mud *mud, const char *name, const char *host, int port,
int backup) int backup)
{ {
if (!name || !host || !port) { if (!host || !port) {
errno = EINVAL; errno = EINVAL;
return -1; return -1;
} }
struct mud_ipaddr local_addr; struct mud_ipaddr ipaddr, *local_addr = NULL;
if (inet_pton(AF_INET, name, &local_addr.ip.v4) == 1) { if (name) {
local_addr.family = AF_INET; if (inet_pton(AF_INET, name, &ipaddr.ip.v4) == 1) {
} else { ipaddr.family = AF_INET;
if (inet_pton(AF_INET6, name, &local_addr.ip.v6) == 1) {
local_addr.family = AF_INET6;
} else { } else {
errno = EINVAL; if (inet_pton(AF_INET6, name, &ipaddr.ip.v6) == 1) {
return -1; ipaddr.family = AF_INET6;
} else {
errno = EINVAL;
return -1;
}
} }
local_addr = &ipaddr;
} }
struct sockaddr_storage addr; struct sockaddr_storage addr;
@@ -553,13 +573,15 @@ mud_peer(struct mud *mud, const char *name, const char *host, int port,
mud_unmapv4((struct sockaddr *)&addr); mud_unmapv4((struct sockaddr *)&addr);
struct mud_path *path = mud_path(mud, &local_addr, (struct sockaddr *)&addr, 1); struct mud_path *path = mud_path(mud, local_addr, (struct sockaddr *)&addr, 1);
if (!path) if (!path)
return -1; return -1;
path->state.active = 1; path->state.active = 1;
path->state.backup = !!backup;
if (name)
path->state.backup = !!backup;
return 0; return 0;
} }
@@ -978,10 +1000,9 @@ static void
mud_packet_send(struct mud *mud, enum mud_packet_code code, mud_packet_send(struct mud *mud, enum mud_packet_code code,
struct mud_path *path, uint64_t now, int flags) struct mud_path *path, uint64_t now, int flags)
{ {
struct mud_packet packet; struct mud_packet packet = { 0 };
size_t size = 0; size_t size = 0;
memset(packet.hdr.zero, 0, MUD_U48_SIZE);
mud_write48(packet.hdr.time, now); mud_write48(packet.hdr.time, now);
packet.hdr.code = (unsigned char)code; packet.hdr.code = (unsigned char)code;
@@ -1088,7 +1109,7 @@ mud_packet_recv(struct mud *mud, struct mud_path *path,
memcpy(path->conf.kiss, packet->data.conf.kiss, memcpy(path->conf.kiss, packet->data.conf.kiss,
sizeof(path->conf.kiss)); sizeof(path->conf.kiss));
path->conf.mtu.remote = mud_read48(packet->data.conf.mtu); path->conf.mtu.remote = mud_read48(packet->data.conf.mtu);
if (path->state.active) { if (path->state.active || mud->peer) {
if (!memcmp(mud->crypto.public.local, if (!memcmp(mud->crypto.public.local,
packet->data.conf.public.remote, MUD_PUB_SIZE)) { packet->data.conf.public.remote, MUD_PUB_SIZE)) {
mud_keyx(mud, packet->data.conf.public.local, mud_keyx(mud, packet->data.conf.public.local,
@@ -1215,20 +1236,24 @@ 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; struct mud_path *path = mud->path;
for (path = mud->path; path; path = path->next) { if (path) {
if (!path->state.active) for (; path; path = path->next) {
continue; if (!path->state.active)
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))
path->conf.remote = 0; path->conf.remote = 0;
if ((!path->conf.remote) && if ((!path->conf.remote) &&
(mud_timeout(now, path->conf.send_time, mud->send_timeout))) { (mud_timeout(now, path->conf.send_time, mud->send_timeout))) {
mud_packet_send(mud, mud_conf, path, now, 0); mud_packet_send(mud, mud_conf, path, now, 0);
path->conf.send_time = now; path->conf.send_time = now;
}
} }
} else if (mud->peer) {
mud_packet_send(mud, mud_conf, mud->peer, now, 0);
} }
} }