Build msg's ctrl only one time
This commit is contained in:
193
mud.c
193
mud.c
@@ -22,18 +22,14 @@ struct path_info {
|
|||||||
uint64_t count;
|
uint64_t count;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct path_addr {
|
|
||||||
unsigned index;
|
|
||||||
union {
|
|
||||||
struct in_addr in;
|
|
||||||
struct in6_addr in6;
|
|
||||||
} bind;
|
|
||||||
struct sockaddr_storage peer;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct path {
|
struct path {
|
||||||
int up;
|
int up;
|
||||||
struct path_addr addr;
|
unsigned index;
|
||||||
|
struct sockaddr_storage addr;
|
||||||
|
struct {
|
||||||
|
unsigned char data[256];
|
||||||
|
size_t size;
|
||||||
|
} ctrl;
|
||||||
uint64_t dt;
|
uint64_t dt;
|
||||||
uint64_t rdt;
|
uint64_t rdt;
|
||||||
uint64_t rtt;
|
uint64_t rtt;
|
||||||
@@ -106,56 +102,49 @@ uint64_t mud_now (struct mud *mud)
|
|||||||
return (now.tv_sec*UINT64_C(1000000)+now.tv_usec)-mud->base;
|
return (now.tv_sec*UINT64_C(1000000)+now.tv_usec)-mud->base;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
void mud_unmapv4 (struct sockaddr *addr)
|
||||||
|
{
|
||||||
|
if (addr->sa_family != AF_INET6)
|
||||||
|
return;
|
||||||
|
|
||||||
|
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)addr;
|
||||||
|
|
||||||
|
if (!IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr))
|
||||||
|
return;
|
||||||
|
|
||||||
|
struct sockaddr_in sin = {
|
||||||
|
.sin_family = AF_INET,
|
||||||
|
.sin_port = sin6->sin6_port,
|
||||||
|
};
|
||||||
|
|
||||||
|
memcpy(&sin.sin_addr.s_addr,
|
||||||
|
&sin6->sin6_addr.s6_addr[12],
|
||||||
|
sizeof(sin.sin_addr.s_addr));
|
||||||
|
|
||||||
|
memcpy(addr, &sin, sizeof(sin));
|
||||||
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
ssize_t mud_send_path (struct mud *mud, struct path *path, uint64_t now, void *data, size_t size)
|
ssize_t mud_send_path (struct mud *mud, struct path *path, uint64_t now, void *data, size_t size)
|
||||||
{
|
{
|
||||||
if (!size)
|
if (!size)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
unsigned char ctrl[1024];
|
|
||||||
|
|
||||||
struct iovec iov = {
|
struct iovec iov = {
|
||||||
.iov_base = data,
|
.iov_base = data,
|
||||||
.iov_len = size,
|
.iov_len = size,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct msghdr msg = {
|
struct msghdr msg = {
|
||||||
.msg_name = &path->addr.peer,
|
.msg_name = &path->addr,
|
||||||
.msg_namelen = sizeof(path->addr.peer),
|
.msg_namelen = sizeof(path->addr),
|
||||||
.msg_iov = &iov,
|
.msg_iov = &iov,
|
||||||
.msg_iovlen = 1,
|
.msg_iovlen = 1,
|
||||||
.msg_control = ctrl,
|
.msg_control = path->ctrl.data,
|
||||||
.msg_controllen = sizeof(ctrl),
|
.msg_controllen = path->ctrl.size,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);
|
|
||||||
|
|
||||||
if (path->addr.peer.ss_family == AF_INET) {
|
|
||||||
struct in_pktinfo ipi = {
|
|
||||||
.ipi_ifindex = path->addr.index,
|
|
||||||
.ipi_spec_dst = path->addr.bind.in,
|
|
||||||
};
|
|
||||||
|
|
||||||
cmsg->cmsg_level = IPPROTO_IP;
|
|
||||||
cmsg->cmsg_type = IP_PKTINFO;
|
|
||||||
cmsg->cmsg_len = CMSG_LEN(sizeof(ipi));
|
|
||||||
memcpy(CMSG_DATA(cmsg), &ipi, sizeof(ipi));
|
|
||||||
|
|
||||||
msg.msg_controllen = CMSG_SPACE(sizeof(ipi));
|
|
||||||
} else {
|
|
||||||
struct in6_pktinfo ipi6 = {
|
|
||||||
.ipi6_ifindex = path->addr.index,
|
|
||||||
.ipi6_addr = path->addr.bind.in6,
|
|
||||||
};
|
|
||||||
|
|
||||||
cmsg->cmsg_level = IPPROTO_IPV6;
|
|
||||||
cmsg->cmsg_type = IPV6_PKTINFO;
|
|
||||||
cmsg->cmsg_len = CMSG_LEN(sizeof(ipi6));
|
|
||||||
memcpy(CMSG_DATA(cmsg), &ipi6, sizeof(ipi6));
|
|
||||||
|
|
||||||
msg.msg_controllen = CMSG_SPACE(sizeof(ipi6));
|
|
||||||
}
|
|
||||||
|
|
||||||
ssize_t ret = sendmsg(mud->fd, &msg, 0);
|
ssize_t ret = sendmsg(mud->fd, &msg, 0);
|
||||||
|
|
||||||
if (ret > 0) {
|
if (ret > 0) {
|
||||||
@@ -262,8 +251,8 @@ struct path *mud_get_path (struct mud *mud, int index, struct sockaddr *addr)
|
|||||||
struct path *path;
|
struct path *path;
|
||||||
|
|
||||||
for (path = mud->path; path; path = path->next) {
|
for (path = mud->path; path; path = path->next) {
|
||||||
if ((path->addr.index == index) &&
|
if ((path->index == index) &&
|
||||||
(!mud_cmp_addr(addr, (struct sockaddr *)&path->addr.peer)))
|
(!mud_cmp_addr(addr, (struct sockaddr *)&path->addr)))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -295,6 +284,13 @@ struct path *mud_new_path (struct mud *mud, unsigned index, struct sockaddr *add
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct msghdr msg = {
|
||||||
|
.msg_control = path->ctrl.data,
|
||||||
|
.msg_controllen = sizeof(path->ctrl.data),
|
||||||
|
};
|
||||||
|
|
||||||
|
struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);
|
||||||
|
|
||||||
for (struct ifaddrs *ifa = ifaddrs; ifa; ifa = ifa->ifa_next) {
|
for (struct ifaddrs *ifa = ifaddrs; ifa; ifa = ifa->ifa_next) {
|
||||||
if (!ifa->ifa_addr)
|
if (!ifa->ifa_addr)
|
||||||
continue;
|
continue;
|
||||||
@@ -305,31 +301,56 @@ struct path *mud_new_path (struct mud *mud, unsigned index, struct sockaddr *add
|
|||||||
if (strncmp(sock->name, ifa->ifa_name, sizeof(sock->name)))
|
if (strncmp(sock->name, ifa->ifa_name, sizeof(sock->name)))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
switch (addr->sa_family) {
|
if (addr->sa_family == AF_INET) {
|
||||||
case AF_INET:
|
path->index = index;
|
||||||
memcpy(&path->addr.peer, addr, sizeof(struct sockaddr_in));
|
memcpy(&path->addr, addr, sizeof(struct sockaddr_in));
|
||||||
memcpy(&path->addr.bind.in,
|
|
||||||
|
struct in_pktinfo ipi = {
|
||||||
|
.ipi_ifindex = index,
|
||||||
|
};
|
||||||
|
|
||||||
|
memcpy(&ipi.ipi_spec_dst,
|
||||||
&((struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr,
|
&((struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr,
|
||||||
sizeof(struct in_addr));
|
sizeof(struct in_addr));
|
||||||
break;
|
|
||||||
case AF_INET6:
|
cmsg->cmsg_level = IPPROTO_IP;
|
||||||
memcpy(&path->addr.peer, addr, sizeof(struct sockaddr_in6));
|
cmsg->cmsg_type = IP_PKTINFO;
|
||||||
memcpy(&path->addr.bind.in6,
|
cmsg->cmsg_len = CMSG_LEN(sizeof(ipi));
|
||||||
|
memcpy(CMSG_DATA(cmsg), &ipi, sizeof(ipi));
|
||||||
|
|
||||||
|
path->ctrl.size = CMSG_SPACE(sizeof(ipi));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (addr->sa_family == AF_INET6) {
|
||||||
|
path->index = index;
|
||||||
|
memcpy(&path->addr, addr, sizeof(struct sockaddr_in6));
|
||||||
|
|
||||||
|
struct in6_pktinfo ipi6 = {
|
||||||
|
.ipi6_ifindex = index,
|
||||||
|
};
|
||||||
|
|
||||||
|
memcpy(&ipi6.ipi6_addr,
|
||||||
&((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr.s6_addr,
|
&((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr.s6_addr,
|
||||||
sizeof(struct in6_addr));
|
sizeof(struct in6_addr));
|
||||||
|
|
||||||
|
cmsg->cmsg_level = IPPROTO_IPV6;
|
||||||
|
cmsg->cmsg_type = IPV6_PKTINFO;
|
||||||
|
cmsg->cmsg_len = CMSG_LEN(sizeof(ipi6));
|
||||||
|
memcpy(CMSG_DATA(cmsg), &ipi6, sizeof(ipi6));
|
||||||
|
|
||||||
|
path->ctrl.size = CMSG_SPACE(sizeof(ipi6));
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
default:
|
}
|
||||||
|
|
||||||
freeifaddrs(ifaddrs);
|
freeifaddrs(ifaddrs);
|
||||||
|
|
||||||
|
if (!path->index) {
|
||||||
free(path);
|
free(path);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
freeifaddrs(ifaddrs);
|
|
||||||
|
|
||||||
path->addr.index = index;
|
|
||||||
path->next = mud->path;
|
path->next = mud->path;
|
||||||
mud->path = path;
|
mud->path = path;
|
||||||
|
|
||||||
@@ -411,7 +432,7 @@ int mud_bind (struct mud *mud, const char *name)
|
|||||||
struct path *path;
|
struct path *path;
|
||||||
|
|
||||||
for (path = mud->path; path; path = path->next)
|
for (path = mud->path; path; path = path->next)
|
||||||
mud_new_path(mud, ifr.ifr_ifindex, (struct sockaddr *)&path->addr.peer);
|
mud_new_path(mud, ifr.ifr_ifindex, (struct sockaddr *)&path->addr);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -626,26 +647,15 @@ int mud_pull (struct mud *mud)
|
|||||||
if (ret <= 0)
|
if (ret <= 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
mud_unmapv4((struct sockaddr *)&addr);
|
||||||
|
|
||||||
int cmsg_level = IPPROTO_IP;
|
int cmsg_level = IPPROTO_IP;
|
||||||
int cmsg_type = IP_PKTINFO;
|
int cmsg_type = IP_PKTINFO;
|
||||||
|
|
||||||
if (addr.ss_family == AF_INET6) {
|
if (addr.ss_family == AF_INET6) {
|
||||||
struct sockaddr_in6 *sin6 =(struct sockaddr_in6 *)&addr;
|
|
||||||
|
|
||||||
if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
|
|
||||||
struct sockaddr_in sin;
|
|
||||||
|
|
||||||
sin.sin_family = AF_INET;
|
|
||||||
sin.sin_port = sin6->sin6_port;
|
|
||||||
memcpy(&sin.sin_addr.s_addr,
|
|
||||||
sin6->sin6_addr.s6_addr+12,
|
|
||||||
sizeof(sin.sin_addr.s_addr));
|
|
||||||
memcpy(&addr, &sin, sizeof(sin));
|
|
||||||
} else {
|
|
||||||
cmsg_level = IPPROTO_IPV6;
|
cmsg_level = IPPROTO_IPV6;
|
||||||
cmsg_type = IPV6_PKTINFO;
|
cmsg_type = IPV6_PKTINFO;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);
|
struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);
|
||||||
|
|
||||||
@@ -672,7 +682,24 @@ int mud_pull (struct mud *mud)
|
|||||||
|
|
||||||
struct path *path = mud_get_path(mud, index, (struct sockaddr *)&addr);
|
struct path *path = mud_get_path(mud, index, (struct sockaddr *)&addr);
|
||||||
|
|
||||||
if (!path) {
|
if (path) {
|
||||||
|
struct msghdr send_msg = {
|
||||||
|
.msg_control = path->ctrl.data,
|
||||||
|
.msg_controllen = path->ctrl.size,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct cmsghdr *send_cmsg = CMSG_FIRSTHDR(&send_msg);
|
||||||
|
|
||||||
|
if (cmsg_level == IPPROTO_IP) {
|
||||||
|
memcpy(&((struct in_pktinfo *)CMSG_DATA(send_cmsg))->ipi_spec_dst,
|
||||||
|
&((struct in_pktinfo *)CMSG_DATA(cmsg))->ipi_addr,
|
||||||
|
sizeof(struct in_addr));
|
||||||
|
} else {
|
||||||
|
memcpy(&((struct in6_pktinfo *)CMSG_DATA(send_cmsg))->ipi6_addr,
|
||||||
|
&((struct in6_pktinfo *)CMSG_DATA(cmsg))->ipi6_addr,
|
||||||
|
sizeof(struct in6_addr));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
unsigned char tmp[sizeof(packet->data)];
|
unsigned char tmp[sizeof(packet->data)];
|
||||||
|
|
||||||
if (mud_decrypt(mud, NULL, tmp, sizeof(tmp),
|
if (mud_decrypt(mud, NULL, tmp, sizeof(tmp),
|
||||||
@@ -686,17 +713,6 @@ int mud_pull (struct mud *mud)
|
|||||||
}
|
}
|
||||||
|
|
||||||
path->up = 1;
|
path->up = 1;
|
||||||
path->addr.index = index;
|
|
||||||
|
|
||||||
if (cmsg_level == IPPROTO_IP) {
|
|
||||||
memcpy(&path->addr.bind.in,
|
|
||||||
&((struct in_pktinfo *)CMSG_DATA(cmsg))->ipi_addr,
|
|
||||||
sizeof(path->addr.bind.in));
|
|
||||||
} else {
|
|
||||||
memcpy(&path->addr.bind.in6,
|
|
||||||
&((struct in6_pktinfo *)CMSG_DATA(cmsg))->ipi6_addr,
|
|
||||||
sizeof(path->addr.bind.in6));
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t send_time = mud_read48(packet->data);
|
uint64_t send_time = mud_read48(packet->data);
|
||||||
int64_t dt = (now-path->recv.time)-(send_time-path->recv.send_time);
|
int64_t dt = (now-path->recv.time)-(send_time-path->recv.send_time);
|
||||||
@@ -727,7 +743,8 @@ int mud_pull (struct mud *mud)
|
|||||||
mud_write48(&pong[6*1], now);
|
mud_write48(&pong[6*1], now);
|
||||||
mud_write48(&pong[6*2], path->rdt);
|
mud_write48(&pong[6*2], path->rdt);
|
||||||
|
|
||||||
int ret = mud_encrypt(mud, 0, tmp, sizeof(tmp), pong, sizeof(pong), sizeof(pong));
|
int ret = mud_encrypt(mud, 0, tmp, sizeof(tmp),
|
||||||
|
pong, sizeof(pong), sizeof(pong));
|
||||||
|
|
||||||
if (ret > 0) {
|
if (ret > 0) {
|
||||||
mud_send_path(mud, path, now, tmp, (size_t)ret);
|
mud_send_path(mud, path, now, tmp, (size_t)ret);
|
||||||
|
|||||||
Reference in New Issue
Block a user