Setup cmsg directly in mud_send_path()

Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
This commit is contained in:
Adrien Gallouët
2018-02-24 14:54:44 +00:00
parent 7303dea98c
commit ac1ba977f4

142
mud.c
View File

@@ -86,10 +86,6 @@ struct mud_path {
unsigned backup : 1; unsigned backup : 1;
} state; } state;
struct sockaddr_storage local_addr, addr; struct sockaddr_storage local_addr, addr;
struct {
unsigned char data[256];
size_t size;
} ctrl;
struct { struct {
uint64_t send_time; uint64_t send_time;
int remote; int remote;
@@ -99,7 +95,6 @@ struct mud_path {
} mtu; } mtu;
unsigned char kiss[MUD_SID_SIZE]; unsigned char kiss[MUD_SID_SIZE];
} conf; } conf;
unsigned char *tc;
uint64_t rdt; uint64_t rdt;
uint64_t rtt; uint64_t rtt;
uint64_t sdt; uint64_t sdt;
@@ -299,9 +294,7 @@ mud_send_path(struct mud *mud, struct mud_path *path, uint64_t now,
if (!size) if (!size)
return 0; return 0;
const socklen_t addrlen = path->addr.ss_family == AF_INET unsigned char ctrl[256];
? sizeof(struct sockaddr_in)
: sizeof(struct sockaddr_in6);
struct iovec iov = { struct iovec iov = {
.iov_base = data, .iov_base = data,
@@ -310,15 +303,55 @@ mud_send_path(struct mud *mud, struct mud_path *path, uint64_t now,
struct msghdr msg = { struct msghdr msg = {
.msg_name = &path->addr, .msg_name = &path->addr,
.msg_namelen = addrlen,
.msg_iov = &iov, .msg_iov = &iov,
.msg_iovlen = 1, .msg_iovlen = 1,
.msg_control = path->ctrl.data, .msg_control = ctrl,
.msg_controllen = path->ctrl.size, .msg_controllen = sizeof(ctrl),
}; };
if (path->tc) struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);
memcpy(path->tc, &tc, sizeof(tc));
if (path->addr.ss_family == AF_INET) {
cmsg->cmsg_level = IPPROTO_IP;
cmsg->cmsg_type = MUD_PKTINFO;
cmsg->cmsg_len = CMSG_LEN(MUD_PKTINFO_SIZE);
memcpy(MUD_PKTINFO_DST(CMSG_DATA(cmsg)),
&((struct sockaddr_in *)&path->local_addr)->sin_addr,
sizeof(struct in_addr));
cmsg = CMSG_NXTHDR(&msg, cmsg);
cmsg->cmsg_level = IPPROTO_IP;
cmsg->cmsg_type = IP_TOS;
cmsg->cmsg_len = CMSG_LEN(sizeof(int));
memcpy(CMSG_DATA(cmsg), &tc, sizeof(int));
msg.msg_namelen = sizeof(struct sockaddr_in);
msg.msg_controllen = CMSG_SPACE(MUD_PKTINFO_SIZE)
+ CMSG_SPACE(sizeof(int));
}
if (path->addr.ss_family == AF_INET6) {
cmsg->cmsg_level = IPPROTO_IPV6;
cmsg->cmsg_type = IPV6_PKTINFO;
cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
memcpy(&((struct in6_pktinfo *)CMSG_DATA(cmsg))->ipi6_addr,
&((struct sockaddr_in6 *)&path->local_addr)->sin6_addr,
sizeof(struct in6_addr));
cmsg = CMSG_NXTHDR(&msg, cmsg);
cmsg->cmsg_level = IPPROTO_IPV6;
cmsg->cmsg_type = IPV6_TCLASS;
cmsg->cmsg_len = CMSG_LEN(sizeof(int));
memcpy(CMSG_DATA(cmsg), &tc, sizeof(int));
msg.msg_namelen = sizeof(struct sockaddr_in6);
msg.msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo))
+ CMSG_SPACE(sizeof(int));
}
ssize_t ret = sendmsg(mud->fd, &msg, flags); ssize_t ret = sendmsg(mud->fd, &msg, flags);
path->send_time = now; path->send_time = now;
@@ -362,82 +395,6 @@ mud_cmp_addr(struct sockaddr_storage *a, struct sockaddr_storage *b)
return 1; return 1;
} }
static int
mud_set_path(struct mud_path *path, struct sockaddr_storage *local_addr,
struct sockaddr_storage *addr)
{
struct msghdr msg = {
.msg_control = path->ctrl.data,
.msg_controllen = sizeof(path->ctrl.data),
};
struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);
if (!cmsg)
return -1;
memset(&path->ctrl, 0, sizeof(path->ctrl));
if (local_addr)
memmove(&path->local_addr, local_addr, sizeof(*local_addr));
memmove(&path->addr, addr, sizeof(*addr));
if (addr->ss_family == AF_INET) {
if (local_addr) {
cmsg->cmsg_level = IPPROTO_IP;
cmsg->cmsg_type = MUD_PKTINFO;
cmsg->cmsg_len = CMSG_LEN(MUD_PKTINFO_SIZE);
memcpy(MUD_PKTINFO_DST(CMSG_DATA(cmsg)),
&((struct sockaddr_in *)local_addr)->sin_addr,
sizeof(struct in_addr));
cmsg = CMSG_NXTHDR(&msg, cmsg);
if (!cmsg)
return -1;
path->ctrl.size += CMSG_SPACE(MUD_PKTINFO_SIZE);
}
cmsg->cmsg_level = IPPROTO_IP;
cmsg->cmsg_type = IP_TOS;
cmsg->cmsg_len = CMSG_LEN(sizeof(int));
path->tc = CMSG_DATA(cmsg);
path->ctrl.size += CMSG_SPACE(sizeof(int));
}
if (addr->ss_family == AF_INET6) {
if (local_addr) {
cmsg->cmsg_level = IPPROTO_IPV6;
cmsg->cmsg_type = IPV6_PKTINFO;
cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
memcpy(&((struct in6_pktinfo *)CMSG_DATA(cmsg))->ipi6_addr,
&((struct sockaddr_in6 *)local_addr)->sin6_addr,
sizeof(struct in6_addr));
cmsg = CMSG_NXTHDR(&msg, cmsg);
if (!cmsg)
return -1;
path->ctrl.size += CMSG_SPACE(sizeof(struct in6_pktinfo));
}
cmsg->cmsg_level = IPPROTO_IPV6;
cmsg->cmsg_type = IPV6_TCLASS;
cmsg->cmsg_len = CMSG_LEN(sizeof(int));
path->tc = CMSG_DATA(cmsg);
path->ctrl.size += CMSG_SPACE(sizeof(int));
}
return 0;
}
static struct mud_path * static struct mud_path *
mud_path(struct mud *mud, struct sockaddr_storage *local_addr, mud_path(struct mud *mud, struct sockaddr_storage *local_addr,
struct sockaddr_storage *addr, int create) struct sockaddr_storage *addr, int create)
@@ -467,11 +424,8 @@ mud_path(struct mud *mud, struct sockaddr_storage *local_addr,
if (!path) if (!path)
return NULL; return NULL;
if (mud_set_path(path, local_addr, addr)) { memmove(&path->local_addr, local_addr, sizeof(*local_addr));
free(path); memmove(&path->addr, addr, sizeof(*addr));
errno = EINVAL;
return NULL;
}
path->conf.mtu.local = mud->mtu; // XXX path->conf.mtu.local = mud->mtu; // XXX
path->next = mud->path; path->next = mud->path;