summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorvgross <vgross@openbsd.org>2016-09-04 10:26:02 +0000
committervgross <vgross@openbsd.org>2016-09-04 10:26:02 +0000
commit5ec2ede81e186cede1a9f2ca63fa4f000d89b6b0 (patch)
treec9eb28b04f4488e80fd4734b3bd1b887b5584c2e
parentbha depends on the deleted aha.h, so it will follow it into the attic (diff)
downloadwireguard-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.h4
-rw-r--r--sbin/iked/ikev2_msg.c27
-rw-r--r--sbin/iked/util.c54
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)
{