Allow client to add the first path
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
This commit is contained in:
147
mud.c
147
mud.c
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user