@@ -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