diff --git a/src/sys/socket/mod.rs b/src/sys/socket/mod.rs index aa280747ac..20b47b8993 100644 --- a/src/sys/socket/mod.rs +++ b/src/sys/socket/mod.rs @@ -463,6 +463,19 @@ pub enum ControlMessageOwned { target_os = "openbsd", ))] Ipv4RecvDstAddr(libc::in_addr), + #[cfg(any( + target_os = "linux", + target_os = "android", + target_os = "freebsd", + ))] + OrigDstAddrV4(libc::sockaddr_in), + #[cfg(any( + target_os = "linux", + target_os = "android", + target_os = "freebsd", + ))] + OrigDstAddrV6(libc::sockaddr_in6), + /// Catch-all variant for unimplemented cmsg types. #[doc(hidden)] Unknown(UnknownCmsg), @@ -546,6 +559,16 @@ impl ControlMessageOwned { let dl = ptr::read_unaligned(p as *const libc::in_addr); ControlMessageOwned::Ipv4RecvDstAddr(dl) }, + #[cfg(any(target_os = "android", target_os = "linux", target_os = "freebsd"))] + (libc::IPPROTO_IP, libc::IP_ORIGDSTADDR) => { + let dl = ptr::read_unaligned(p as *const libc::sockaddr_in); + ControlMessageOwned::OrigDstAddrV4(dl) + }, + #[cfg(any(target_os = "android", target_os = "linux", target_os = "freebsd"))] + (libc::IPPROTO_IPV6, libc::IPV6_ORIGDSTADDR) => { + let dl = ptr::read_unaligned(p as *const libc::sockaddr_in6); + ControlMessageOwned::OrigDstAddrV6(dl) + }, (_, _) => { let sl = slice::from_raw_parts(p, len); let ucmsg = UnknownCmsg(*header, Vec::::from(&sl[..])); @@ -587,6 +610,34 @@ pub enum ControlMessage<'a> { #[cfg(any(target_os = "android", target_os = "linux"))] ScmCredentials(&'a UnixCredentials), + /// A message of type `IP_ORIGDSTADDR` which is triggered by setting + /// `RecvOrigDstAddrV4` socket option and is used to get original IPv4 + /// UDP or TCP destination address when actual destination address + /// is overwritten by [`TPROXY`][1], which in turn may be used to + /// make a transparent proxy server. + /// + /// [1]:https://www.kernel.org/doc/Documentation/networking/tproxy.txt + #[cfg(any( + target_os = "linux", + target_os = "android", + target_os = "freebsd", + ))] + OrigDstAddrV4(&'a libc::sockaddr_in), + + /// A message of type `IPV6_ORIGDSTADDR` which is triggered by setting + /// `RecvOrigDstAddrV6` socket option and is used to get original IPv6 + /// UDP or TCP destination address when actual destination address + /// is overwritten by [`TPROXY`][1], which in turn may be used to + /// make a transparent proxy server. + /// + /// [1]:https://www.kernel.org/doc/Documentation/networking/tproxy.txt + #[cfg(any( + target_os = "linux", + target_os = "android", + target_os = "freebsd", + ))] + OrigDstAddrV6(&'a libc::sockaddr_in6), + /// Set IV for `AF_ALG` crypto API. /// /// For further information, please refer to the @@ -655,6 +706,22 @@ impl<'a> ControlMessage<'a> { ControlMessage::ScmCredentials(creds) => { &creds.0 as *const libc::ucred as *const u8 } + #[cfg(any( + target_os = "linux", + target_os = "android", + target_os = "freebsd", + ))] + ControlMessage::OrigDstAddrV4(origaddr) => { + origaddr as *const libc::sockaddr_in as *const u8 + }, + #[cfg(any( + target_os = "linux", + target_os = "android", + target_os = "freebsd", + ))] + ControlMessage::OrigDstAddrV6(origaddr) => { + origaddr as *const libc::sockaddr_in6 as *const u8 + }, #[cfg(any(target_os = "android", target_os = "linux"))] ControlMessage::AlgSetIv(iv) => { unsafe { @@ -696,6 +763,22 @@ impl<'a> ControlMessage<'a> { ControlMessage::ScmCredentials(creds) => { mem::size_of_val(creds) } + #[cfg(any( + target_os = "linux", + target_os = "android", + target_os = "freebsd", + ))] + ControlMessage::OrigDstAddrV4(origaddr) => { + mem::size_of_val(origaddr) + }, + #[cfg(any( + target_os = "linux", + target_os = "android", + target_os = "freebsd", + ))] + ControlMessage::OrigDstAddrV6(origaddr) => { + mem::size_of_val(origaddr) + }, #[cfg(any(target_os = "android", target_os = "linux"))] ControlMessage::AlgSetIv(iv) => { mem::size_of::() + iv.len() @@ -720,6 +803,10 @@ impl<'a> ControlMessage<'a> { #[cfg(any(target_os = "android", target_os = "linux"))] ControlMessage::AlgSetIv(_) | ControlMessage::AlgSetOp(_) | ControlMessage::AlgSetAeadAssoclen(_) => libc::SOL_ALG , + #[cfg(any(target_os = "android", target_os = "linux", target_os = "freebsd"))] + ControlMessage::OrigDstAddrV4(_) => libc::IPPROTO_IP, + #[cfg(any(target_os = "android", target_os = "linux", target_os = "freebsd"))] + ControlMessage::OrigDstAddrV6(_) => libc::IPPROTO_IPV6, } } @@ -733,6 +820,14 @@ impl<'a> ControlMessage<'a> { ControlMessage::AlgSetIv(_) => { libc::ALG_SET_IV }, + #[cfg(any(target_os = "android", target_os = "linux", target_os = "freebsd"))] + ControlMessage::OrigDstAddrV4(_) => { + libc::IP_ORIGDSTADDR + }, + #[cfg(any(target_os = "android", target_os = "linux", target_os = "freebsd"))] + ControlMessage::OrigDstAddrV6(_) => { + libc::IPV6_ORIGDSTADDR + }, #[cfg(any(target_os = "android", target_os = "linux"))] ControlMessage::AlgSetOp(_) => { libc::ALG_SET_OP diff --git a/src/sys/socket/sockopt.rs b/src/sys/socket/sockopt.rs index 691f66ddcc..0369cf88b1 100644 --- a/src/sys/socket/sockopt.rs +++ b/src/sys/socket/sockopt.rs @@ -261,6 +261,10 @@ sockopt_impl!(GetOnly, OriginalDst, libc::SOL_IP, libc::SO_ORIGINAL_DST, libc::s sockopt_impl!(Both, ReceiveTimestamp, libc::SOL_SOCKET, libc::SO_TIMESTAMP, bool); #[cfg(any(target_os = "android", target_os = "linux"))] sockopt_impl!(Both, IpTransparent, libc::SOL_IP, libc::IP_TRANSPARENT, bool); +#[cfg(any(target_os = "android", target_os = "linux", target_os = "freebsd"))] +sockopt_impl!(Both, RecvOrigDstAddrV4, libc::SOL_IP, libc::IP_RECVORIGDSTADDR, bool); +#[cfg(any(target_os = "android", target_os = "linux", target_os = "freebsd"))] +sockopt_impl!(Both, RecvOrigDstAddrV6, libc::SOL_IPV6, libc::IPV6_RECVORIGDSTADDR, bool); #[cfg(target_os = "openbsd")] sockopt_impl!(Both, BindAny, libc::SOL_SOCKET, libc::SO_BINDANY, bool); #[cfg(target_os = "freebsd")]