diff options
author | 2016-09-04 10:26:02 +0000 | |
---|---|---|
committer | 2016-09-04 10:26:02 +0000 | |
commit | 5ec2ede81e186cede1a9f2ca63fa4f000d89b6b0 (patch) | |
tree | c9eb28b04f4488e80fd4734b3bd1b887b5584c2e | |
parent | bha depends on the deleted aha.h, so it will follow it into the attic (diff) | |
download | wireguard-openbsd-5ec2ede81e186cede1a9f2ca63fa4f000d89b6b0.tar.xz wireguard-openbsd-5ec2ede81e186cede1a9f2ca63fa4f000d89b6b0.zip |
Now that we have IP_SENDSRCADDR, add sendtofrom().
Ok jca@ and reyk@
-rw-r--r-- | sbin/iked/iked.h | 4 | ||||
-rw-r--r-- | sbin/iked/ikev2_msg.c | 27 | ||||
-rw-r--r-- | sbin/iked/util.c | 54 |
3 files changed, 71 insertions, 14 deletions
diff --git a/sbin/iked/iked.h b/sbin/iked/iked.h index 6a6a3885bf2..f8c44fdd77f 100644 --- a/sbin/iked/iked.h +++ b/sbin/iked/iked.h @@ -1,4 +1,4 @@ -/* $OpenBSD: iked.h,v 1.97 2016/09/03 09:20:07 vgross Exp $ */ +/* $OpenBSD: iked.h,v 1.98 2016/09/04 10:26:02 vgross Exp $ */ /* * Copyright (c) 2010-2013 Reyk Floeter <reyk@openbsd.org> @@ -899,6 +899,8 @@ int socket_setport(struct sockaddr *, in_port_t); int socket_getaddr(int, struct sockaddr_storage *); int socket_bypass(int, struct sockaddr *); int udp_bind(struct sockaddr *, in_port_t); +ssize_t sendtofrom(int, void *, size_t, int, struct sockaddr *, + socklen_t, struct sockaddr *, socklen_t); ssize_t recvfromto(int, void *, size_t, int, struct sockaddr *, socklen_t *, struct sockaddr *, socklen_t *); const char * diff --git a/sbin/iked/ikev2_msg.c b/sbin/iked/ikev2_msg.c index 3fe71563752..c03bab11aa0 100644 --- a/sbin/iked/ikev2_msg.c +++ b/sbin/iked/ikev2_msg.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ikev2_msg.c,v 1.45 2015/10/19 11:25:35 reyk Exp $ */ +/* $OpenBSD: ikev2_msg.c,v 1.46 2016/09/04 10:26:02 vgross Exp $ */ /* * Copyright (c) 2010-2013 Reyk Floeter <reyk@openbsd.org> @@ -319,9 +319,10 @@ ikev2_msg_send(struct iked *env, struct iked_message *msg) msg->msg_offset += sizeof(natt); } - if ((sendto(msg->msg_fd, ibuf_data(buf), ibuf_size(buf), 0, - (struct sockaddr *)&msg->msg_peer, msg->msg_peerlen)) == -1) { - log_warn("%s: sendto", __func__); + if (sendtofrom(msg->msg_fd, ibuf_data(buf), ibuf_size(buf), 0, + (struct sockaddr *)&msg->msg_peer, msg->msg_peerlen, + (struct sockaddr *)&msg->msg_local, msg->msg_locallen) == -1) { + log_warn("%s: sendtofrom", __func__); return (-1); } @@ -969,10 +970,11 @@ int ikev2_msg_retransmit_response(struct iked *env, struct iked_sa *sa, struct iked_message *msg) { - if ((sendto(msg->msg_fd, ibuf_data(msg->msg_data), - ibuf_size(msg->msg_data), 0, (struct sockaddr *)&msg->msg_peer, - msg->msg_peerlen)) == -1) { - log_warn("%s: sendto", __func__); + if (sendtofrom(msg->msg_fd, ibuf_data(msg->msg_data), + ibuf_size(msg->msg_data), 0, + (struct sockaddr *)&msg->msg_peer, msg->msg_peerlen, + (struct sockaddr *)&msg->msg_local, msg->msg_locallen) == -1) { + log_warn("%s: sendtofrom", __func__); return (-1); } @@ -996,11 +998,12 @@ ikev2_msg_retransmit_timeout(struct iked *env, void *arg) struct iked_sa *sa = msg->msg_sa; if (msg->msg_tries < IKED_RETRANSMIT_TRIES) { - if ((sendto(msg->msg_fd, ibuf_data(msg->msg_data), + if (sendtofrom(msg->msg_fd, ibuf_data(msg->msg_data), ibuf_size(msg->msg_data), 0, - (struct sockaddr *)&msg->msg_peer, - msg->msg_peerlen)) == -1) { - log_warn("%s: sendto", __func__); + (struct sockaddr *)&msg->msg_peer, msg->msg_peerlen, + (struct sockaddr *)&msg->msg_local, + msg->msg_locallen) == -1) { + log_warn("%s: sendtofrom", __func__); sa_free(env, sa); return; } diff --git a/sbin/iked/util.c b/sbin/iked/util.c index bb6ae62fd4f..be2c46ba9d9 100644 --- a/sbin/iked/util.c +++ b/sbin/iked/util.c @@ -1,4 +1,4 @@ -/* $OpenBSD: util.c,v 1.30 2015/11/23 19:28:34 reyk Exp $ */ +/* $OpenBSD: util.c,v 1.31 2016/09/04 10:26:02 vgross Exp $ */ /* * Copyright (c) 2010-2013 Reyk Floeter <reyk@openbsd.org> @@ -287,6 +287,58 @@ sockaddr_cmp(struct sockaddr *a, struct sockaddr *b, int prefixlen) } ssize_t +sendtofrom(int s, void *buf, size_t len, int flags, struct sockaddr *to, + socklen_t tolen, struct sockaddr *from, socklen_t fromlen) +{ + struct iovec iov; + struct msghdr msg; + struct cmsghdr *cmsg; + struct in6_pktinfo *pkt6; + struct sockaddr_in *in; + struct sockaddr_in6 *in6; + union { + struct cmsghdr hdr; + char inbuf[CMSG_SPACE(sizeof(struct in_addr))]; + char in6buf[CMSG_SPACE(sizeof(struct in6_pktinfo))]; + } cmsgbuf; + + bzero(&msg, sizeof(msg)); + bzero(&cmsgbuf, sizeof(cmsgbuf)); + + iov.iov_base = buf; + iov.iov_len = len; + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + msg.msg_name = to; + msg.msg_namelen = tolen; + msg.msg_control = &cmsgbuf; + msg.msg_controllen = sizeof(cmsgbuf); + + cmsg = CMSG_FIRSTHDR(&msg); + switch (to->sa_family) { + case AF_INET: + msg.msg_controllen = sizeof(cmsgbuf.inbuf); + cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_addr)); + cmsg->cmsg_level = IPPROTO_IP; + cmsg->cmsg_type = IP_SENDSRCADDR; + in = (struct sockaddr_in *)from; + memcpy(CMSG_DATA(cmsg), &in->sin_addr, sizeof(struct in_addr)); + break; + case AF_INET6: + msg.msg_controllen = sizeof(cmsgbuf.in6buf); + cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo)); + cmsg->cmsg_level = IPPROTO_IPV6; + cmsg->cmsg_type = IPV6_PKTINFO; + in6 = (struct sockaddr_in6 *)from; + pkt6 = (struct in6_pktinfo *)CMSG_DATA(cmsg); + pkt6->ipi6_addr = in6->sin6_addr; + break; + } + + return sendmsg(s, &msg, flags); +} + +ssize_t recvfromto(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen, struct sockaddr *to, socklen_t *tolen) { |