Skip to content

Commit

Permalink
feat: add dont_frag option
Browse files Browse the repository at this point in the history
Signed-off-by: loongtao.zhang <loongtao.zhang@outlook.com>
  • Loading branch information
cathaysia committed Feb 21, 2025
1 parent bcc537f commit 0607601
Show file tree
Hide file tree
Showing 4 changed files with 232 additions and 0 deletions.
179 changes: 179 additions & 0 deletions src/socket.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1615,6 +1615,101 @@ impl Socket {
.map(|recv_tos| recv_tos > 0)
}
}

/// Set value for `IP_DONTFRAG` option of this socket
#[cfg(not(any(
target_os = "netbsd",
target_os = "openbsd",
target_os = "redox",
target_os = "vita",
target_os = "dragonfly",
target_os = "fuchsia",
)))]
pub fn dont_frag(&self) -> io::Result<bool> {
unsafe {
#[cfg(any(
target_os = "macos",
target_os = "ios",
target_os = "freebsd",
target_os = "netbsd",
target_os = "openbsd",
target_os = "redox",
target_os = "solaris",
target_os = "tvos",
target_os = "watchos",
target_os = "vita",
target_os = "dragonfly",
target_os = "fuchsia",
target_os = "illumos",
))]
return getsockopt::<c_int>(self.as_raw(), sys::IPPROTO_IP, libc::IP_DONTFRAG)
.map(|dont_frag| dont_frag > 0);
#[cfg(not(any(
target_os = "macos",
target_os = "ios",
target_os = "freebsd",
target_os = "netbsd",
target_os = "openbsd",
target_os = "redox",
target_os = "solaris",
target_os = "tvos",
target_os = "watchos",
target_os = "vita",
target_os = "dragonfly",
target_os = "fuchsia",
target_os = "illumos",
)))]
return getsockopt::<c_int>(self.as_raw(), sys::IPPROTO_IP, sys::IP_MTU_DISCOVER)
.map(|dont_frag| dont_frag == 0);
}
}
/// Set value for `IP_DONTFRAG` option on this socket
#[cfg(not(any(
target_os = "netbsd",
target_os = "openbsd",
target_os = "redox",
target_os = "vita",
target_os = "dragonfly",
target_os = "fuchsia",
)))]
pub fn set_dont_frag(&self, dont_frag: bool) -> io::Result<()> {
unsafe {
#[cfg(any(
target_os = "macos",
target_os = "ios",
target_os = "freebsd",
target_os = "solaris",
target_os = "tvos",
target_os = "watchos",
target_os = "illumos",
))]
return setsockopt(
self.as_raw(),
sys::IPPROTO_IP,
libc::IP_DONTFRAG,
dont_frag as c_int,
);
#[cfg(not(any(
target_os = "macos",
target_os = "ios",
target_os = "freebsd",
target_os = "solaris",
target_os = "tvos",
target_os = "watchos",
target_os = "illumos",
)))]
return setsockopt(
self.as_raw(),
sys::IPPROTO_IP,
sys::IP_MTU_DISCOVER,
if dont_frag {
sys::IP_PMTUDISC_DONT
} else {
sys::IP_PMTUDISC_DO
},
);
};
}
}

/// Socket options for IPv6 sockets, get/set using `IPPROTO_IPV6`.
Expand Down Expand Up @@ -2015,6 +2110,90 @@ impl Socket {
)
}
}

/// Get value for `IP_DONTFRAG` option on this socket.
#[cfg(not(any(
target_os = "netbsd",
target_os = "openbsd",
target_os = "redox",
target_os = "vita",
target_os = "dragonfly",
target_os = "fuchsia",
)))]
pub fn dont_frag_v6(&self) -> io::Result<bool> {
unsafe {
#[cfg(any(
target_os = "macos",
target_os = "ios",
target_os = "freebsd",
target_os = "solaris",
target_os = "tvos",
target_os = "watchos",
target_os = "illumos",
))]
return getsockopt::<c_int>(self.as_raw(), sys::IPPROTO_IPV6, libc::IPV6_DONTFRAG)
.map(|dont_frag| dont_frag > 0);
#[cfg(not(any(
target_os = "macos",
target_os = "ios",
target_os = "freebsd",
target_os = "solaris",
target_os = "tvos",
target_os = "watchos",
target_os = "illumos",
)))]
return getsockopt::<c_int>(self.as_raw(), sys::IPPROTO_IPV6, sys::IPV6_MTU_DISCOVER)
.map(|dont_frag| dont_frag == sys::IP_PMTUDISC_DONT);
}
}

/// Set value for `IP_DONTFRAG` option on this socket
#[cfg(not(any(
target_os = "netbsd",
target_os = "openbsd",
target_os = "redox",
target_os = "vita",
target_os = "dragonfly",
target_os = "fuchsia",
)))]
pub fn set_dont_frag_v6(&self, dont_frag: bool) -> io::Result<()> {
unsafe {
#[cfg(any(
target_os = "macos",
target_os = "ios",
target_os = "freebsd",
target_os = "solaris",
target_os = "tvos",
target_os = "watchos",
target_os = "illumos",
))]
return setsockopt(
self.as_raw(),
sys::IPPROTO_IPV6,
libc::IPV6_DONTFRAG,
dont_frag as c_int,
);
#[cfg(not(any(
target_os = "macos",
target_os = "ios",
target_os = "freebsd",
target_os = "solaris",
target_os = "tvos",
target_os = "watchos",
target_os = "illumos",
)))]
setsockopt(
self.as_raw(),
sys::IPPROTO_IPV6,
sys::IPV6_MTU_DISCOVER,
if dont_frag {
sys::IP_PMTUDISC_DONT
} else {
sys::IP_PMTUDISC_DO
},
)
}
}
}

/// Socket options for TCP sockets, get/set using `IPPROTO_TCP`.
Expand Down
18 changes: 18 additions & 0 deletions src/sys/unix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,24 @@ pub(crate) use libc::{
SO_BROADCAST, SO_ERROR, SO_KEEPALIVE, SO_RCVBUF, SO_RCVTIMEO, SO_REUSEADDR, SO_SNDBUF,
SO_SNDTIMEO, SO_TYPE, TCP_NODELAY,
};

#[cfg(not(any(
target_os = "macos",
target_os = "ios",
target_os = "freebsd",
target_os = "netbsd",
target_os = "openbsd",
target_os = "redox",
target_os = "solaris",
target_os = "tvos",
target_os = "watchos",
target_os = "vita",
target_os = "dragonfly",
target_os = "fuchsia",
target_os = "illumos",
)))]
pub(crate) use libc::{IPV6_MTU_DISCOVER, IP_MTU_DISCOVER, IP_PMTUDISC_DO, IP_PMTUDISC_DONT};

#[cfg(not(any(
target_os = "dragonfly",
target_os = "haiku",
Expand Down
13 changes: 13 additions & 0 deletions src/sys/windows.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,19 @@ pub(crate) use windows_sys::Win32::Networking::WinSock::{
pub(crate) const IPPROTO_IP: c_int = windows_sys::Win32::Networking::WinSock::IPPROTO_IP as c_int;
pub(crate) const SOL_SOCKET: c_int = windows_sys::Win32::Networking::WinSock::SOL_SOCKET as c_int;

macro_rules! export_constants {
($id:ident, $ref:ident) => {
pub(crate) const $id: c_int = windows_sys::Win32::Networking::WinSock::$ref as c_int;
};
($id:ident) => {
export_constants!($id, $id);
};
}

export_constants!(IPV6_MTU_DISCOVER);
export_constants!(IP_MTU_DISCOVER);
export_constants!(IP_PMTUDISC_DO);
export_constants!(IP_PMTUDISC_DONT);
/// Type used in set/getsockopt to retrieve the `TCP_NODELAY` option.
///
/// NOTE: <https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-getsockopt>
Expand Down
22 changes: 22 additions & 0 deletions tests/socket.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1350,6 +1350,28 @@ test!(
#[cfg(not(target_os = "redox"))]
test!(out_of_band_inline, set_out_of_band_inline(true));
test!(reuse_address, set_reuse_address(true));

#[cfg(not(any(
target_os = "netbsd",
target_os = "openbsd",
target_os = "redox",
target_os = "vita",
target_os = "dragonfly",
target_os = "fuchsia",
)))]
test!(IPv4 dont_frag, set_dont_frag(cfg!(not(target_os = "windows"))));
// TODO: macos can only set on udp socket.
#[cfg(not(any(
target_os = "macos",
target_os = "netbsd",
target_os = "openbsd",
target_os = "redox",
target_os = "vita",
target_os = "dragonfly",
target_os = "fuchsia",
)))]
test!(IPv6 dont_frag_v6, set_dont_frag_v6(true));

#[cfg(all(
feature = "all",
not(any(windows, target_os = "solaris", target_os = "illumos"))
Expand Down

0 comments on commit 0607601

Please sign in to comment.