@@ -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
@@ -246,6 +248,8 @@ impl<R> HttpConnector<R> {
246248 ) ) ]
247249 interface : None ,
248250 #[ cfg( any( target_os = "android" , target_os = "fuchsia" , target_os = "linux" ) ) ]
251+ mark : None ,
252+ #[ cfg( any( target_os = "android" , target_os = "fuchsia" , target_os = "linux" ) ) ]
249253 tcp_user_timeout : None ,
250254 } ) ,
251255 resolver,
@@ -422,6 +426,26 @@ impl<R> HttpConnector<R> {
422426 self
423427 }
424428
429+ /// Sets the mark on sockets produced by this connector.
430+ ///
431+ /// This sets the `SO_MARK` option on the socket (see [`man 7 socket`]
432+ /// for details). The mark can be matched by policy routing rules and
433+ /// packet filters.
434+ ///
435+ /// Setting the mark requires the binary to either have `CAP_NET_ADMIN`
436+ /// or to be run as root.
437+ ///
438+ /// This function is only available on the following operating systems:
439+ /// - Linux, including Android
440+ /// - Fuchsia
441+ ///
442+ /// [`man 7 socket`]: https://man7.org/linux/man-pages/man7/socket.7.html
443+ #[ cfg( any( target_os = "android" , target_os = "fuchsia" , target_os = "linux" ) ) ]
444+ #[ inline]
445+ pub fn set_mark ( & mut self , mark : Option < u32 > ) {
446+ self . config_mut ( ) . mark = mark;
447+ }
448+
425449 /// Sets the value of the TCP_USER_TIMEOUT option on the socket.
426450 #[ cfg( any( target_os = "android" , target_os = "fuchsia" , target_os = "linux" ) ) ]
427451 #[ inline]
@@ -894,6 +918,14 @@ fn connect(
894918 }
895919 }
896920
921+ // On Linux-like systems, set the packet mark using `SO_MARK`.
922+ #[ cfg( any( target_os = "android" , target_os = "fuchsia" , target_os = "linux" ) ) ]
923+ if let Some ( mark) = config. mark {
924+ socket
925+ . set_mark ( mark)
926+ . map_err ( ConnectError :: m ( "tcp set_mark error" ) ) ?;
927+ }
928+
897929 #[ cfg( any( target_os = "android" , target_os = "fuchsia" , target_os = "linux" ) ) ]
898930 if let Some ( tcp_user_timeout) = & config. tcp_user_timeout {
899931 if let Err ( e) = socket. set_tcp_user_timeout ( Some ( * tcp_user_timeout) ) {
@@ -1303,6 +1335,12 @@ mod tests {
13031335 target_os = "fuchsia" ,
13041336 target_os = "linux"
13051337 ) ) ]
1338+ mark : None ,
1339+ #[ cfg( any(
1340+ target_os = "android" ,
1341+ target_os = "fuchsia" ,
1342+ target_os = "linux"
1343+ ) ) ]
13061344 tcp_user_timeout : None ,
13071345 } ;
13081346 let connecting_tcp = ConnectingTcp :: new ( dns:: SocketAddrs :: new ( addrs) , & cfg) ;
0 commit comments