aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJake McGinty <me@jake.su>2018-04-11 03:05:39 -0700
committerJake McGinty <me@jake.su>2018-04-11 03:05:39 -0700
commit94d936f42ef368fbc76ec84fffa576c6820e5291 (patch)
tree8b4bc7d909cfadbe254ea5c43431e8442913d9b2 /src
parenttests: add little sleep when setting up interfaces (diff)
downloadwireguard-rs-94d936f42ef368fbc76ec84fffa576c6820e5291.tar.xz
wireguard-rs-94d936f42ef368fbc76ec84fffa576c6820e5291.zip
udp: set IPV6_RECVPKTINFO sockopt (darwin)
Diffstat (limited to 'src')
-rw-r--r--src/lib.rs1
-rw-r--r--src/udp/mod.rs37
2 files changed, 36 insertions, 2 deletions
diff --git a/src/lib.rs b/src/lib.rs
index a693518..d39ba78 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -20,6 +20,7 @@ extern crate byteorder;
extern crate bytes;
extern crate chacha20_poly1305_aead;
extern crate hex;
+extern crate libc;
extern crate mio;
extern crate nix;
extern crate notify;
diff --git a/src/udp/mod.rs b/src/udp/mod.rs
index 4916e31..f75a05d 100644
--- a/src/udp/mod.rs
+++ b/src/udp/mod.rs
@@ -1,11 +1,14 @@
#![allow(unused)]
-use std::io;
+use std::{fmt, io, mem};
use std::net::{self, SocketAddr, Ipv4Addr, Ipv6Addr};
-use std::fmt;
+use std::os::unix::io::AsRawFd;
use futures::{Async, Future, Poll};
+use libc;
use mio;
+use nix::{self, errno::Errno};
+use nix::sys::{uio::IoVec, socket::{CmsgSpace, MsgFlags, SockAddr, recvmsg}};
use socket2::{Socket, Domain, Type, Protocol};
use tokio_core::reactor::{Handle, PollEvented};
@@ -16,6 +19,22 @@ pub struct UdpSocket {
handle: Handle,
}
+/// IPV6_RECVPKTINFO is missing from the libc crate. Value taken from https://git.io/vxNel.
+pub const IPV6_RECVPKTINFO: i32 = 61;
+
+/*
+struct in6_pktinfo {
+ struct in6_addr ipi6_addr; /* src/dst IPv6 address */
+ unsigned int ipi6_ifindex; /* send/recv interface index */
+};
+*/
+
+#[repr(C)]
+struct in6_pktinfo {
+ ipi6_addr : libc::in6_addr,
+ ipi6_ifindex : libc::c_uint
+}
+
mod frame;
pub use self::frame::{UdpChannel, UdpFramed, VecUdpCodec, PeerServerMessage};
@@ -40,6 +59,20 @@ impl UdpSocket {
socket.set_only_v6(false)?;
socket.set_nonblocking(true)?;
socket.set_reuse_port(true)?;
+
+ unsafe {
+ let optval: libc::c_int = 1;
+ let ret = libc::setsockopt(socket.as_raw_fd(),
+ libc::IPPROTO_IPV6,
+ IPV6_RECVPKTINFO,
+ &optval as *const _ as *const libc::c_void,
+ mem::size_of_val(&optval) as libc::socklen_t);
+ if ret != 0 {
+ let err: Result<(), _> = Err(io::Error::last_os_error());
+ err.expect("setsockopt failed");
+ }
+ }
+
socket.bind(&addr.into())?;
Self::from_socket(socket.into_udp_socket(), handle)
}