From 7fe1bff392a23a84635dfaa314820e868930ad8f Mon Sep 17 00:00:00 2001 From: Juan Jose Nicola Date: Tue, 18 Jun 2024 06:31:55 -0300 Subject: [PATCH] Add: header_included_v6() and set_header_included_v6() Also, deprecate header_included() and set_header_included() in favor of header_included_v4() and set_header_included_v4(). --- src/socket.rs | 74 +++++++++++++++++++++++++++++++++++++++++++++++-- tests/socket.rs | 30 ++++++++++++++++++-- 2 files changed, 99 insertions(+), 5 deletions(-) diff --git a/src/socket.rs b/src/socket.rs index 19f269cf..e0ccf8e4 100644 --- a/src/socket.rs +++ b/src/socket.rs @@ -1138,6 +1138,16 @@ const fn into_linger(duration: Option) -> sys::linger { /// * Linux: /// * Windows: impl Socket { + /// This method is deprecated, use [`crate::Socket::header_included_v4`]. + #[cfg(all(feature = "all", not(any(target_os = "redox", target_os = "espidf"))))] + #[cfg_attr( + docsrs, + doc(cfg(all(feature = "all", not(any(target_os = "redox", target_os = "espidf"))))) + )] + #[deprecated = "Use `Socket::header_included_v4` instead"] + pub fn header_included(&self) -> io::Result { + self.header_included_v4() + } /// Get the value of the `IP_HDRINCL` option on this socket. /// /// For more information about this option, see [`set_header_included`]. @@ -1148,13 +1158,28 @@ impl Socket { docsrs, doc(cfg(all(feature = "all", not(any(target_os = "redox", target_os = "espidf"))))) )] - pub fn header_included(&self) -> io::Result { + pub fn header_included_v4(&self) -> io::Result { unsafe { getsockopt::(self.as_raw(), sys::IPPROTO_IP, sys::IP_HDRINCL) .map(|included| included != 0) } } + /// This method is deprecated, use [`crate::Socket::set_header_included_v4`]. + #[cfg_attr( + any(target_os = "fuchsia", target_os = "illumos", target_os = "solaris"), + allow(rustdoc::broken_intra_doc_links) + )] + #[cfg(all(feature = "all", not(any(target_os = "redox", target_os = "espidf"))))] + #[cfg_attr( + docsrs, + doc(cfg(all(feature = "all", not(any(target_os = "redox", target_os = "espidf"))))) + )] + #[deprecated = "Use `Socket::set_header_included_v4` instead"] + pub fn set_header_included(&self, included: bool) -> io::Result<()> { + self.set_header_included_v4(included) + } + /// Set the value of the `IP_HDRINCL` option on this socket. /// /// If enabled, the user supplies an IP header in front of the user data. @@ -1175,7 +1200,7 @@ impl Socket { docsrs, doc(cfg(all(feature = "all", not(any(target_os = "redox", target_os = "espidf"))))) )] - pub fn set_header_included(&self, included: bool) -> io::Result<()> { + pub fn set_header_included_v4(&self, included: bool) -> io::Result<()> { unsafe { setsockopt( self.as_raw(), @@ -1651,6 +1676,51 @@ impl Socket { /// * Linux: /// * Windows: impl Socket { + /// Get the value of the `IP_HDRINCL` option on this socket. + /// + /// For more information about this option, see [`set_header_included`]. + /// + /// [`set_header_included`]: Socket::set_header_included + #[cfg(all(feature = "all", not(any(target_os = "redox", target_os = "espidf"))))] + #[cfg_attr( + docsrs, + doc(cfg(all(feature = "all", not(any(target_os = "redox", target_os = "espidf"))))) + )] + pub fn header_included_v6(&self) -> io::Result { + unsafe { + getsockopt::(self.as_raw(), sys::IPPROTO_IPV6, sys::IP_HDRINCL) + .map(|included| included != 0) + } + } + + /// Set the value of the `IP_HDRINCL` option on this socket. + /// + /// If enabled, the user supplies an IP header in front of the user data. + /// Valid only for [`SOCK_RAW`] sockets; see [raw(7)] for more information. + /// When this flag is enabled, the values set by `IP_OPTIONS` are ignored. + /// + /// [`SOCK_RAW`]: Type::RAW + /// [raw(7)]: https://man7.org/linux/man-pages/man7/raw.7.html + #[cfg_attr( + any(target_os = "fuchsia", target_os = "illumos", target_os = "solaris"), + allow(rustdoc::broken_intra_doc_links) + )] + #[cfg(all(feature = "all", not(any(target_os = "redox", target_os = "espidf"))))] + #[cfg_attr( + docsrs, + doc(cfg(all(feature = "all", not(any(target_os = "redox", target_os = "espidf"))))) + )] + pub fn set_header_included_v6(&self, included: bool) -> io::Result<()> { + unsafe { + setsockopt( + self.as_raw(), + sys::IPPROTO_IPV6, + sys::IP_HDRINCL, + included as c_int, + ) + } + } + /// Join a multicast group using `IPV6_ADD_MEMBERSHIP` option on this socket. /// /// Some OSs use `IPV6_JOIN_GROUP` for this option. diff --git a/tests/socket.rs b/tests/socket.rs index 89b79f5f..8e22542d 100644 --- a/tests/socket.rs +++ b/tests/socket.rs @@ -1539,14 +1539,38 @@ fn header_included() { }; let initial = socket - .header_included() + .header_included_v4() .expect("failed to get initial value"); assert_eq!(initial, false, "initial value and argument are the same"); socket - .set_header_included(true) + .set_header_included_v4(true) .expect("failed to set option"); - let got = socket.header_included().expect("failed to get value"); + let got = socket.header_included_v4().expect("failed to get value"); + assert_eq!(got, true, "set and get values differ"); +} + +#[test] +#[cfg(all(feature = "all", not(target_os = "redox")))] +fn header_included_ipv6() { + let socket = match Socket::new(Domain::IPV6, Type::RAW, None) { + Ok(socket) => socket, + // Need certain permissions to create a raw sockets. + Err(ref err) if err.kind() == io::ErrorKind::PermissionDenied => return, + #[cfg(unix)] + Err(ref err) if err.raw_os_error() == Some(libc::EPROTONOSUPPORT) => return, + Err(err) => panic!("unexpected error creating socket: {}", err), + }; + + let initial = socket + .header_included_v6() + .expect("failed to get initial value"); + assert_eq!(initial, false, "initial value and argument are the same"); + + socket + .set_header_included_v6(true) + .expect("failed to set option"); + let got = socket.header_included_v6().expect("failed to get value"); assert_eq!(got, true, "set and get values differ"); }