Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve socket API coverage #1248

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
203 changes: 199 additions & 4 deletions src/sys/socket/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -529,6 +529,17 @@ pub enum ControlMessageOwned {
#[cfg(target_os = "linux")]
UdpGroSegments(u16),

#[cfg(any(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should also enable the ORIGDSTADDR stuff for FreeBSD.

target_os = "linux",
target_os = "android",
))]
OrigDstAddrV4(libc::sockaddr_in),
#[cfg(any(
target_os = "linux",
target_os = "android",
))]
OrigDstAddrV6(libc::sockaddr_in6),

/// Catch-all variant for unimplemented cmsg types.
#[doc(hidden)]
Unknown(UnknownCmsg),
Expand Down Expand Up @@ -622,6 +633,16 @@ impl ControlMessageOwned {
let gso_size: u16 = ptr::read_unaligned(p as *const _);
ControlMessageOwned::UdpGroSegments(gso_size)
},
#[cfg(any(target_os = "android", target_os = "linux"))]
(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"))]
(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::<u8>::from(&sl[..]));
Expand Down Expand Up @@ -677,6 +698,52 @@ pub enum ControlMessage<'a> {
#[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
ScmCreds,

/// 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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you sure it works for TCP? In FreeBSD at least, it's only for UDP.

/// 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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the wrong man page link. I can't find the correct man page for Linux, but here's the link for FreeBSD: ip(4) (note that the section for IP_ORIGDSTADDR has some typos; I just fixed them upstream and in time the link target will be rebuilt).

#[cfg(any(
target_os = "linux",
target_os = "android",
))]
OrigDstAddrV4(&'a libc::sockaddr_in),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no point in defining ControlMessage::OrigDstAddrV[46]. ControlMessage is for use with sendmsg only. recvmsg uses ControlMessageOwned instead.


/// 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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also not a useful man page. I can't find any documentation on this control message type. Best not to include any man page link, then.

#[cfg(any(
target_os = "linux",
target_os = "android",
))]
OrigDstAddrV6(&'a libc::sockaddr_in6),

#[cfg(any(
target_os = "android",
target_os = "ios",
target_os = "linux",
target_os = "macos",
target_os = "netbsd",
))]
Ipv4PacketInfo(&'a libc::in_pktinfo),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you please add doc comments here?

#[cfg(any(
target_os = "android",
target_os = "dragonfly",
target_os = "freebsd",
target_os = "ios",
target_os = "linux",
target_os = "macos",
target_os = "openbsd",
target_os = "netbsd",
))]
Ipv6PacketInfo(&'a libc::in6_pktinfo),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And a doc comment here, too?


/// Set IV for `AF_ALG` crypto API.
///
/// For further information, please refer to the
Expand Down Expand Up @@ -754,14 +821,51 @@ impl<'a> ControlMessage<'a> {
#[cfg(any(target_os = "android", target_os = "linux"))]
ControlMessage::ScmCredentials(creds) => {
&creds.0 as *const libc::ucred as *const u8
}
},
#[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
ControlMessage::ScmCreds => {
// The kernel overwrites the data, we just zero it
// to make sure it's not uninitialized memory
unsafe { ptr::write_bytes(cmsg_data, 0, self.len()) };
return
}
},
#[cfg(any(
target_os = "linux",
target_os = "android",
))]
ControlMessage::OrigDstAddrV4(origaddr) => {
origaddr as *const libc::sockaddr_in as *const u8
},
#[cfg(any(
target_os = "linux",
target_os = "android",
))]
ControlMessage::OrigDstAddrV6(origaddr) => {
origaddr as *const libc::sockaddr_in6 as *const u8
},
#[cfg(any(
target_os = "android",
target_os = "ios",
target_os = "linux",
target_os = "macos",
target_os = "netbsd",
))]
ControlMessage::Ipv4PacketInfo(pktinfo) => {
pktinfo as *const libc::in_pktinfo as *const u8
},
#[cfg(any(
target_os = "android",
target_os = "dragonfly",
target_os = "freebsd",
target_os = "ios",
target_os = "linux",
target_os = "macos",
target_os = "openbsd",
target_os = "netbsd",
))]
ControlMessage::Ipv6PacketInfo(pktinfo) => {
pktinfo as *const libc::in6_pktinfo as *const u8
},
#[cfg(any(target_os = "android", target_os = "linux"))]
ControlMessage::AlgSetIv(iv) => {
let af_alg_iv = libc::af_alg_iv {
Expand Down Expand Up @@ -817,11 +921,48 @@ impl<'a> ControlMessage<'a> {
#[cfg(any(target_os = "android", target_os = "linux"))]
ControlMessage::ScmCredentials(creds) => {
mem::size_of_val(creds)
}
},
#[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
ControlMessage::ScmCreds => {
mem::size_of::<libc::cmsgcred>()
}
},
#[cfg(any(
target_os = "linux",
target_os = "android",
))]
ControlMessage::OrigDstAddrV4(origaddr) => {
mem::size_of_val(origaddr)
},
#[cfg(any(
target_os = "linux",
target_os = "android",
))]
ControlMessage::OrigDstAddrV6(origaddr) => {
mem::size_of_val(origaddr)
},
#[cfg(any(
target_os = "android",
target_os = "ios",
target_os = "linux",
target_os = "macos",
target_os = "netbsd",
))]
ControlMessage::Ipv4PacketInfo(pktinfo) => {
mem::size_of_val(pktinfo)
},
#[cfg(any(
target_os = "android",
target_os = "dragonfly",
target_os = "freebsd",
target_os = "ios",
target_os = "linux",
target_os = "macos",
target_os = "openbsd",
target_os = "netbsd",
))]
ControlMessage::Ipv6PacketInfo(pktinfo) => {
mem::size_of_val(pktinfo)
},
#[cfg(any(target_os = "android", target_os = "linux"))]
ControlMessage::AlgSetIv(iv) => {
mem::size_of::<libc::af_alg_iv>() + iv.len()
Expand Down Expand Up @@ -854,6 +995,29 @@ impl<'a> ControlMessage<'a> {
ControlMessage::AlgSetAeadAssoclen(_) => libc::SOL_ALG,
#[cfg(target_os = "linux")]
ControlMessage::UdpGsoSegments(_) => libc::SOL_UDP,
#[cfg(any(
target_os = "android",
target_os = "ios",
target_os = "linux",
target_os = "macos",
target_os = "netbsd",
))]
ControlMessage::Ipv4PacketInfo(_) => libc::IPPROTO_IP,
#[cfg(any(
target_os = "android",
target_os = "dragonfly",
target_os = "freebsd",
target_os = "ios",
target_os = "linux",
target_os = "macos",
target_os = "openbsd",
target_os = "netbsd",
))]
ControlMessage::Ipv6PacketInfo(_) => libc::IPPROTO_IPV6,
#[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,
}
}

Expand All @@ -869,6 +1033,37 @@ impl<'a> ControlMessage<'a> {
ControlMessage::AlgSetIv(_) => {
libc::ALG_SET_IV
},
#[cfg(any(
target_os = "android",
target_os = "ios",
target_os = "linux",
target_os = "macos",
target_os = "netbsd",
))]
ControlMessage::Ipv4PacketInfo(_) => {
libc::IP_PKTINFO
},
#[cfg(any(
target_os = "android",
target_os = "dragonfly",
target_os = "freebsd",
target_os = "ios",
target_os = "linux",
target_os = "macos",
target_os = "openbsd",
target_os = "netbsd",
))]
ControlMessage::Ipv6PacketInfo(_) => {
libc::IPV6_PKTINFO
},
#[cfg(any(target_os = "android", target_os = "linux"))]
ControlMessage::OrigDstAddrV4(_) => {
libc::IP_ORIGDSTADDR
},
#[cfg(any(target_os = "android", target_os = "linux"))]
ControlMessage::OrigDstAddrV6(_) => {
libc::IPV6_ORIGDSTADDR
},
#[cfg(any(target_os = "android", target_os = "linux"))]
ControlMessage::AlgSetOp(_) => {
libc::ALG_SET_OP
Expand Down
6 changes: 6 additions & 0 deletions src/sys/socket/sockopt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,12 @@ 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, IncludeIpHeaders, libc::IPPROTO_IP, libc::IP_HDRINCL, bool);
#[cfg(any(target_os = "android", target_os = "linux"))]
sockopt_impl!(Both, RecvOrigDstAddrV4, libc::SOL_IP, libc::IP_RECVORIGDSTADDR, bool);
#[cfg(any(target_os = "android", target_os = "linux"))]
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")]
Expand Down