Skip to content

Commit 5ebd04f

Browse files
feat(client): add HttpConnector::set_mark for SO_MARK
1 parent 8805922 commit 5ebd04f

1 file changed

Lines changed: 38 additions & 0 deletions

File tree

src/client/legacy/connect/http.rs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,8 @@ struct Config {
8989
))]
9090
interface: Option<std::ffi::CString>,
9191
#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
92+
mark: Option<u32>,
93+
#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
9294
tcp_user_timeout: Option<Duration>,
9395
}
9496

@@ -250,6 +252,8 @@ impl<R> HttpConnector<R> {
250252
))]
251253
interface: None,
252254
#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
255+
mark: None,
256+
#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
253257
tcp_user_timeout: None,
254258
}),
255259
resolver,
@@ -426,6 +430,26 @@ impl<R> HttpConnector<R> {
426430
self
427431
}
428432

433+
/// Sets the mark on sockets produced by this connector.
434+
///
435+
/// This sets the `SO_MARK` option on the socket (see [`man 7 socket`]
436+
/// for details). The mark can be matched by policy routing rules and
437+
/// packet filters.
438+
///
439+
/// Setting the mark requires the binary to either have `CAP_NET_ADMIN`
440+
/// or to be run as root.
441+
///
442+
/// This function is only available on the following operating systems:
443+
/// - Linux, including Android
444+
/// - Fuchsia
445+
///
446+
/// [`man 7 socket`]: https://man7.org/linux/man-pages/man7/socket.7.html
447+
#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
448+
#[inline]
449+
pub fn set_mark(&mut self, mark: Option<u32>) {
450+
self.config_mut().mark = mark;
451+
}
452+
429453
/// Sets the value of the TCP_USER_TIMEOUT option on the socket.
430454
#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
431455
#[inline]
@@ -896,6 +920,14 @@ fn connect(
896920
}
897921
}
898922

923+
// On Linux-like systems, set the packet mark using `SO_MARK`.
924+
#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
925+
if let Some(mark) = config.mark {
926+
socket
927+
.set_mark(mark)
928+
.map_err(ConnectError::m("tcp set_mark error"))?;
929+
}
930+
899931
#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
900932
if let Some(tcp_user_timeout) = &config.tcp_user_timeout {
901933
if let Err(e) = socket.set_tcp_user_timeout(Some(*tcp_user_timeout)) {
@@ -1328,6 +1360,12 @@ mod tests {
13281360
target_os = "fuchsia",
13291361
target_os = "linux"
13301362
))]
1363+
mark: None,
1364+
#[cfg(any(
1365+
target_os = "android",
1366+
target_os = "fuchsia",
1367+
target_os = "linux"
1368+
))]
13311369
tcp_user_timeout: None,
13321370
};
13331371
let connecting_tcp = ConnectingTcp::new(dns::SocketAddrs::new(addrs), &cfg);

0 commit comments

Comments
 (0)