diff options
author | Jake McGinty <me@jake.su> | 2018-04-11 03:05:39 -0700 |
---|---|---|
committer | Jake McGinty <me@jake.su> | 2018-04-11 03:05:39 -0700 |
commit | 94d936f42ef368fbc76ec84fffa576c6820e5291 (patch) | |
tree | 8b4bc7d909cfadbe254ea5c43431e8442913d9b2 /src | |
parent | tests: add little sleep when setting up interfaces (diff) | |
download | wireguard-rs-94d936f42ef368fbc76ec84fffa576c6820e5291.tar.xz wireguard-rs-94d936f42ef368fbc76ec84fffa576c6820e5291.zip |
udp: set IPV6_RECVPKTINFO sockopt (darwin)
Diffstat (limited to 'src')
-rw-r--r-- | src/lib.rs | 1 | ||||
-rw-r--r-- | src/udp/mod.rs | 37 |
2 files changed, 36 insertions, 2 deletions
@@ -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) } |