Skip to content

Commit 81f6989

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

File tree

4 files changed

+84
-3
lines changed

4 files changed

+84
-3
lines changed

src/socket.rs

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1615,6 +1615,41 @@ 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(target_os = "macos")]
1623+
return getsockopt::<c_int>(self.as_raw(), sys::IPPROTO_IP, libc::IP_DONTFRAG)
1624+
.map(|dont_frag| dont_frag > 0);
1625+
#[cfg(not(target_os = "macos"))]
1626+
return getsockopt::<c_int>(self.as_raw(), sys::IPPROTO_IP, sys::IP_MTU_DISCOVER)
1627+
.map(|dont_frag| dont_frag == 0);
1628+
}
1629+
}
1630+
/// Set value for `IP_DONTFRAG` option on this socket
1631+
pub fn set_dont_frag(&self, dont_frag: bool) -> io::Result<()> {
1632+
unsafe {
1633+
#[cfg(target_os = "macos")]
1634+
return setsockopt(
1635+
self.as_raw(),
1636+
sys::IPPROTO_IP,
1637+
libc::IP_DONTFRAG,
1638+
dont_frag as c_int,
1639+
);
1640+
#[cfg(not(target_os = "macos"))]
1641+
return setsockopt(
1642+
self.as_raw(),
1643+
sys::IPPROTO_IP,
1644+
sys::IP_MTU_DISCOVER,
1645+
if dont_frag {
1646+
sys::IP_PMTUDISC_DONT
1647+
} else {
1648+
sys::IP_PMTUDISC_DO
1649+
},
1650+
);
1651+
};
1652+
}
16181653
}
16191654

16201655
/// Socket options for IPv6 sockets, get/set using `IPPROTO_IPV6`.
@@ -2015,6 +2050,42 @@ impl Socket {
20152050
)
20162051
}
20172052
}
2053+
2054+
/// Get value for `IP_DONTFRAG` option on this socket.
2055+
pub fn dont_frag_v6(&self) -> io::Result<bool> {
2056+
unsafe {
2057+
#[cfg(target_os = "macos")]
2058+
return getsockopt::<c_int>(self.as_raw(), sys::IPPROTO_IPV6, libc::IPV6_DONTFRAG)
2059+
.map(|dont_frag| dont_frag > 0);
2060+
#[cfg(not(target_os = "macos"))]
2061+
return getsockopt::<c_int>(self.as_raw(), sys::IPPROTO_IPV6, sys::IPV6_MTU_DISCOVER)
2062+
.map(|dont_frag| dont_frag == sys::IP_PMTUDISC_DONT);
2063+
}
2064+
}
2065+
2066+
/// Set value for `IP_DONTFRAG` option on this socket
2067+
pub fn set_dont_frag_v6(&self, dont_frag: bool) -> io::Result<()> {
2068+
unsafe {
2069+
#[cfg(target_os = "macos")]
2070+
return setsockopt(
2071+
self.as_raw(),
2072+
sys::IPPROTO_IPV6,
2073+
libc::IPV6_DONTFRAG,
2074+
dont_frag as c_int,
2075+
);
2076+
#[cfg(not(target_os = "macos"))]
2077+
setsockopt(
2078+
self.as_raw(),
2079+
sys::IPPROTO_IPV6,
2080+
sys::IPV6_MTU_DISCOVER,
2081+
if dont_frag {
2082+
sys::IP_PMTUDISC_DONT
2083+
} else {
2084+
sys::IP_PMTUDISC_DO
2085+
},
2086+
)
2087+
}
2088+
}
20182089
}
20192090

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

src/sys/unix.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,10 @@ 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(target_os = "macos"))]
209+
pub(crate) use libc::{IPV6_MTU_DISCOVER, IP_MTU_DISCOVER, IP_PMTUDISC_DO, IP_PMTUDISC_DONT};
210+
207211
#[cfg(not(any(
208212
target_os = "dragonfly",
209213
target_os = "haiku",

src/sys/windows.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,10 @@ use std::{process, ptr, slice};
2222
use windows_sys::Win32::Foundation::{SetHandleInformation, HANDLE, HANDLE_FLAG_INHERIT};
2323
use windows_sys::Win32::Networking::WinSock::{
2424
self, tcp_keepalive, FIONBIO, IN6_ADDR, IN6_ADDR_0, INVALID_SOCKET, IN_ADDR, IN_ADDR_0,
25-
POLLERR, POLLHUP, POLLRDNORM, POLLWRNORM, SD_BOTH, SD_RECEIVE, SD_SEND, SIO_KEEPALIVE_VALS,
26-
SOCKET_ERROR, WSABUF, WSAEMSGSIZE, WSAESHUTDOWN, WSAPOLLFD, WSAPROTOCOL_INFOW,
27-
WSA_FLAG_NO_HANDLE_INHERIT, WSA_FLAG_OVERLAPPED,
25+
IPV6_MTU_DISCOVER, IP_MTU_DISCOVER, IP_PMTUDISC_DO, IP_PMTUDISC_DONT, POLLERR, POLLHUP,
26+
POLLRDNORM, POLLWRNORM, SD_BOTH, SD_RECEIVE, SD_SEND, SIO_KEEPALIVE_VALS, SOCKET_ERROR, WSABUF,
27+
WSAEMSGSIZE, WSAESHUTDOWN, WSAPOLLFD, WSAPROTOCOL_INFOW, WSA_FLAG_NO_HANDLE_INHERIT,
28+
WSA_FLAG_OVERLAPPED,
2829
};
2930
#[cfg(feature = "all")]
3031
use windows_sys::Win32::Networking::WinSock::{

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)