diff options
author | Yves-Alexis Perez <corsac@debian.org> | 2015-11-18 14:49:27 +0100 |
---|---|---|
committer | Yves-Alexis Perez <corsac@debian.org> | 2015-11-18 14:49:27 +0100 |
commit | 1e980d6be0ef0e243c6fe82b5e855454b97e24a4 (patch) | |
tree | 0d59eec2ce2ed332434ae80fc78a44db9ad293c5 /src/libcharon/plugins/socket_dynamic | |
parent | 5dca9ea0e2931f0e2a056c7964d311bcc30a01b8 (diff) | |
download | vyos-strongswan-1e980d6be0ef0e243c6fe82b5e855454b97e24a4.tar.gz vyos-strongswan-1e980d6be0ef0e243c6fe82b5e855454b97e24a4.zip |
Imported Upstream version 5.3.4
Diffstat (limited to 'src/libcharon/plugins/socket_dynamic')
-rw-r--r-- | src/libcharon/plugins/socket_dynamic/socket_dynamic_socket.c | 94 |
1 files changed, 62 insertions, 32 deletions
diff --git a/src/libcharon/plugins/socket_dynamic/socket_dynamic_socket.c b/src/libcharon/plugins/socket_dynamic/socket_dynamic_socket.c index b82a69e1b..a032134c3 100644 --- a/src/libcharon/plugins/socket_dynamic/socket_dynamic_socket.c +++ b/src/libcharon/plugins/socket_dynamic/socket_dynamic_socket.c @@ -527,6 +527,62 @@ static dynsock_t *find_socket(private_socket_dynamic_socket_t *this, return skt; } +/** + * Generic function to send a message. + */ +static ssize_t send_msg_generic(int skt, struct msghdr *msg) +{ + return sendmsg(skt, msg, 0); +} + +/** + * Send a message with the IPv4 source address set. + */ +static ssize_t send_msg_v4(int skt, struct msghdr *msg, host_t *src) +{ + char buf[CMSG_SPACE(sizeof(struct in_pktinfo))] = {}; + struct cmsghdr *cmsg; + struct in_addr *addr; + struct in_pktinfo *pktinfo; + struct sockaddr_in *sin; + + msg->msg_control = buf; + msg->msg_controllen = sizeof(buf); + cmsg = CMSG_FIRSTHDR(msg); + cmsg->cmsg_level = SOL_IP; + cmsg->cmsg_type = IP_PKTINFO; + cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo)); + + pktinfo = (struct in_pktinfo*)CMSG_DATA(cmsg); + addr = &pktinfo->ipi_spec_dst; + + sin = (struct sockaddr_in*)src->get_sockaddr(src); + memcpy(addr, &sin->sin_addr, sizeof(struct in_addr)); + return send_msg_generic(skt, msg); +} + +/** + * Send a message with the IPv6 source address set. + */ +static ssize_t send_msg_v6(int skt, struct msghdr *msg, host_t *src) +{ + char buf[CMSG_SPACE(sizeof(struct in6_pktinfo))] = {}; + struct cmsghdr *cmsg; + struct in6_pktinfo *pktinfo; + struct sockaddr_in6 *sin; + + msg->msg_control = buf; + msg->msg_controllen = sizeof(buf); + cmsg = CMSG_FIRSTHDR(msg); + cmsg->cmsg_level = SOL_IPV6; + cmsg->cmsg_type = IPV6_PKTINFO; + cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo)); + pktinfo = (struct in6_pktinfo*)CMSG_DATA(cmsg); + sin = (struct sockaddr_in6*)src->get_sockaddr(src); + memcpy(&pktinfo->ipi6_addr, &sin->sin6_addr, sizeof(struct in6_addr)); + return send_msg_generic(skt, msg); +} + METHOD(socket_t, sender, status_t, private_socket_dynamic_socket_t *this, packet_t *packet) { @@ -536,7 +592,6 @@ METHOD(socket_t, sender, status_t, ssize_t len; chunk_t data; struct msghdr msg; - struct cmsghdr *cmsg; struct iovec iov; src = packet->get_source(packet); @@ -564,43 +619,18 @@ METHOD(socket_t, sender, status_t, { if (family == AF_INET) { - struct in_addr *addr; - struct sockaddr_in *sin; - char buf[CMSG_SPACE(sizeof(struct in_pktinfo))]; - struct in_pktinfo *pktinfo; - - memset(buf, 0, sizeof(buf)); - msg.msg_control = buf; - msg.msg_controllen = sizeof(buf); - cmsg = CMSG_FIRSTHDR(&msg); - cmsg->cmsg_level = SOL_IP; - cmsg->cmsg_type = IP_PKTINFO; - cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo)); - pktinfo = (struct in_pktinfo*)CMSG_DATA(cmsg); - addr = &pktinfo->ipi_spec_dst; - sin = (struct sockaddr_in*)src->get_sockaddr(src); - memcpy(addr, &sin->sin_addr, sizeof(struct in_addr)); + len = send_msg_v4(skt->fd, &msg, src); } else { - char buf[CMSG_SPACE(sizeof(struct in6_pktinfo))]; - struct in6_pktinfo *pktinfo; - struct sockaddr_in6 *sin; - - memset(buf, 0, sizeof(buf)); - msg.msg_control = buf; - msg.msg_controllen = sizeof(buf); - cmsg = CMSG_FIRSTHDR(&msg); - cmsg->cmsg_level = SOL_IPV6; - cmsg->cmsg_type = IPV6_PKTINFO; - cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo)); - pktinfo = (struct in6_pktinfo*)CMSG_DATA(cmsg); - sin = (struct sockaddr_in6*)src->get_sockaddr(src); - memcpy(&pktinfo->ipi6_addr, &sin->sin6_addr, sizeof(struct in6_addr)); + len = send_msg_v6(skt->fd, &msg, src); } } + else + { + len = send_msg_generic(skt->fd, &msg); + } - len = sendmsg(skt->fd, &msg, 0); if (len != data.len) { DBG1(DBG_NET, "error writing to socket: %s", strerror(errno)); |