Skip to content

Commit bbb4813

Browse files
committed
feat: add dont_frag option
Signed-off-by: loongtao.zhang <[email protected]>
1 parent bcc537f commit bbb4813

File tree

4 files changed

+219
-0
lines changed

4 files changed

+219
-0
lines changed

src/socket.rs

Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1615,6 +1615,97 @@ impl Socket {
16151615
.map(|recv_tos| recv_tos > 0)
16161616
}
16171617
}
1618+
1619+
/// Set value for `IP_DONTFRAG` option of this socket
1620+
pub fn dont_frag(&self) -> io::Result<bool> {
1621+
unsafe {
1622+
#[cfg(any(
1623+
target_os = "macos",
1624+
target_os = "ios",
1625+
target_os = "freebsd",
1626+
target_os = "netbsd",
1627+
target_os = "openbsd",
1628+
target_os = "redox",
1629+
target_os = "solaris",
1630+
target_os = "tvos",
1631+
target_os = "watchos",
1632+
target_os = "vita",
1633+
target_os = "dragonfly",
1634+
target_os = "fuchsia",
1635+
target_os = "illumos",
1636+
))]
1637+
return getsockopt::<c_int>(self.as_raw(), sys::IPPROTO_IP, libc::IP_DONTFRAG)
1638+
.map(|dont_frag| dont_frag > 0);
1639+
#[cfg(not(any(
1640+
target_os = "macos",
1641+
target_os = "ios",
1642+
target_os = "freebsd",
1643+
target_os = "netbsd",
1644+
target_os = "openbsd",
1645+
target_os = "redox",
1646+
target_os = "solaris",
1647+
target_os = "tvos",
1648+
target_os = "watchos",
1649+
target_os = "vita",
1650+
target_os = "dragonfly",
1651+
target_os = "fuchsia",
1652+
target_os = "illumos",
1653+
)))]
1654+
return getsockopt::<c_int>(self.as_raw(), sys::IPPROTO_IP, sys::IP_MTU_DISCOVER)
1655+
.map(|dont_frag| dont_frag == 0);
1656+
}
1657+
}
1658+
/// Set value for `IP_DONTFRAG` option on this socket
1659+
pub fn set_dont_frag(&self, dont_frag: bool) -> io::Result<()> {
1660+
unsafe {
1661+
#[cfg(any(
1662+
target_os = "macos",
1663+
target_os = "ios",
1664+
target_os = "freebsd",
1665+
target_os = "netbsd",
1666+
target_os = "openbsd",
1667+
target_os = "redox",
1668+
target_os = "solaris",
1669+
target_os = "tvos",
1670+
target_os = "watchos",
1671+
target_os = "vita",
1672+
target_os = "dragonfly",
1673+
target_os = "fuchsia",
1674+
target_os = "illumos",
1675+
))]
1676+
return setsockopt(
1677+
self.as_raw(),
1678+
sys::IPPROTO_IP,
1679+
libc::IP_DONTFRAG,
1680+
dont_frag as c_int,
1681+
);
1682+
#[cfg(not(any(
1683+
target_os = "macos",
1684+
target_os = "ios",
1685+
target_os = "freebsd",
1686+
target_os = "netbsd",
1687+
target_os = "openbsd",
1688+
target_os = "redox",
1689+
target_os = "solaris",
1690+
target_os = "tvos",
1691+
target_os = "watchos",
1692+
target_os = "vita",
1693+
target_os = "dragonfly",
1694+
target_os = "fuchsia",
1695+
target_os = "illumos",
1696+
)))]
1697+
return setsockopt(
1698+
self.as_raw(),
1699+
sys::IPPROTO_IP,
1700+
sys::IP_MTU_DISCOVER,
1701+
if dont_frag {
1702+
sys::IP_PMTUDISC_DONT
1703+
} else {
1704+
sys::IP_PMTUDISC_DO
1705+
},
1706+
);
1707+
};
1708+
}
16181709
}
16191710

16201711
/// Socket options for IPv6 sockets, get/set using `IPPROTO_IPV6`.
@@ -2015,6 +2106,98 @@ impl Socket {
20152106
)
20162107
}
20172108
}
2109+
2110+
/// Get value for `IP_DONTFRAG` option on this socket.
2111+
pub fn dont_frag_v6(&self) -> io::Result<bool> {
2112+
unsafe {
2113+
#[cfg(any(
2114+
target_os = "macos",
2115+
target_os = "ios",
2116+
target_os = "freebsd",
2117+
target_os = "netbsd",
2118+
target_os = "openbsd",
2119+
target_os = "redox",
2120+
target_os = "solaris",
2121+
target_os = "tvos",
2122+
target_os = "watchos",
2123+
target_os = "vita",
2124+
target_os = "dragonfly",
2125+
target_os = "fuchsia",
2126+
target_os = "illumos",
2127+
))]
2128+
return getsockopt::<c_int>(self.as_raw(), sys::IPPROTO_IPV6, libc::IPV6_DONTFRAG)
2129+
.map(|dont_frag| dont_frag > 0);
2130+
#[cfg(not(any(
2131+
target_os = "macos",
2132+
target_os = "ios",
2133+
target_os = "freebsd",
2134+
target_os = "netbsd",
2135+
target_os = "openbsd",
2136+
target_os = "redox",
2137+
target_os = "solaris",
2138+
target_os = "tvos",
2139+
target_os = "watchos",
2140+
target_os = "vita",
2141+
target_os = "dragonfly",
2142+
target_os = "fuchsia",
2143+
target_os = "illumos",
2144+
)))]
2145+
return getsockopt::<c_int>(self.as_raw(), sys::IPPROTO_IPV6, sys::IPV6_MTU_DISCOVER)
2146+
.map(|dont_frag| dont_frag == sys::IP_PMTUDISC_DONT);
2147+
}
2148+
}
2149+
2150+
/// Set value for `IP_DONTFRAG` option on this socket
2151+
pub fn set_dont_frag_v6(&self, dont_frag: bool) -> io::Result<()> {
2152+
unsafe {
2153+
#[cfg(any(
2154+
target_os = "macos",
2155+
target_os = "ios",
2156+
target_os = "freebsd",
2157+
target_os = "netbsd",
2158+
target_os = "openbsd",
2159+
target_os = "redox",
2160+
target_os = "solaris",
2161+
target_os = "tvos",
2162+
target_os = "watchos",
2163+
target_os = "vita",
2164+
target_os = "dragonfly",
2165+
target_os = "fuchsia",
2166+
target_os = "illumos",
2167+
))]
2168+
return setsockopt(
2169+
self.as_raw(),
2170+
sys::IPPROTO_IPV6,
2171+
libc::IPV6_DONTFRAG,
2172+
dont_frag as c_int,
2173+
);
2174+
#[cfg(not(any(
2175+
target_os = "macos",
2176+
target_os = "ios",
2177+
target_os = "freebsd",
2178+
target_os = "netbsd",
2179+
target_os = "openbsd",
2180+
target_os = "redox",
2181+
target_os = "solaris",
2182+
target_os = "tvos",
2183+
target_os = "watchos",
2184+
target_os = "vita",
2185+
target_os = "dragonfly",
2186+
target_os = "fuchsia",
2187+
target_os = "illumos",
2188+
)))]
2189+
setsockopt(
2190+
self.as_raw(),
2191+
sys::IPPROTO_IPV6,
2192+
sys::IPV6_MTU_DISCOVER,
2193+
if dont_frag {
2194+
sys::IP_PMTUDISC_DONT
2195+
} else {
2196+
sys::IP_PMTUDISC_DO
2197+
},
2198+
)
2199+
}
2200+
}
20182201
}
20192202

20202203
/// Socket options for TCP sockets, get/set using `IPPROTO_TCP`.

src/sys/unix.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,24 @@ pub(crate) use libc::{
204204
SO_BROADCAST, SO_ERROR, SO_KEEPALIVE, SO_RCVBUF, SO_RCVTIMEO, SO_REUSEADDR, SO_SNDBUF,
205205
SO_SNDTIMEO, SO_TYPE, TCP_NODELAY,
206206
};
207+
208+
#[cfg(not(any(
209+
target_os = "macos",
210+
target_os = "ios",
211+
target_os = "freebsd",
212+
target_os = "netbsd",
213+
target_os = "openbsd",
214+
target_os = "redox",
215+
target_os = "solaris",
216+
target_os = "tvos",
217+
target_os = "watchos",
218+
target_os = "vita",
219+
target_os = "dragonfly",
220+
target_os = "fuchsia",
221+
target_os = "illumos",
222+
)))]
223+
pub(crate) use libc::{IPV6_MTU_DISCOVER, IP_MTU_DISCOVER, IP_PMTUDISC_DO, IP_PMTUDISC_DONT};
224+
207225
#[cfg(not(any(
208226
target_os = "dragonfly",
209227
target_os = "haiku",

src/sys/windows.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,19 @@ pub(crate) use windows_sys::Win32::Networking::WinSock::{
8484
pub(crate) const IPPROTO_IP: c_int = windows_sys::Win32::Networking::WinSock::IPPROTO_IP as c_int;
8585
pub(crate) const SOL_SOCKET: c_int = windows_sys::Win32::Networking::WinSock::SOL_SOCKET as c_int;
8686

87+
macro_rules! export_constants {
88+
($id:ident, $ref:ident) => {
89+
pub(crate) const $id: c_int = windows_sys::Win32::Networking::WinSock::$ref as c_int;
90+
};
91+
($id:ident) => {
92+
export_constants!($id, $id);
93+
};
94+
}
95+
96+
export_constants!(IPV6_MTU_DISCOVER);
97+
export_constants!(IP_MTU_DISCOVER);
98+
export_constants!(IP_PMTUDISC_DO);
99+
export_constants!(IP_PMTUDISC_DONT);
87100
/// Type used in set/getsockopt to retrieve the `TCP_NODELAY` option.
88101
///
89102
/// NOTE: <https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-getsockopt>

tests/socket.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1350,6 +1350,11 @@ test!(
13501350
#[cfg(not(target_os = "redox"))]
13511351
test!(out_of_band_inline, set_out_of_band_inline(true));
13521352
test!(reuse_address, set_reuse_address(true));
1353+
test!(IPv4 dont_frag, set_dont_frag(true));
1354+
// TODO: macos can only set on udp socket.
1355+
#[cfg(not(target_os = "macos"))]
1356+
test!(IPv6 dont_frag_v6, set_dont_frag_v6(true));
1357+
13531358
#[cfg(all(
13541359
feature = "all",
13551360
not(any(windows, target_os = "solaris", target_os = "illumos"))

0 commit comments

Comments
 (0)