File tree Expand file tree Collapse file tree 6 files changed +82
-0
lines changed Expand file tree Collapse file tree 6 files changed +82
-0
lines changed Original file line number Diff line number Diff line change @@ -1021,6 +1021,9 @@ pub struct Config {
10211021 /// Set `SO_MARK` socket option for outbound sockets
10221022 #[ cfg( any( target_os = "linux" , target_os = "android" ) ) ]
10231023 pub outbound_fwmark : Option < u32 > ,
1024+ /// Set `SO_USER_COOKIE` socket option for outbound sockets
1025+ #[ cfg( target_os = "freebsd" ) ]
1026+ pub outbound_user_cookie : Option < u32 > ,
10241027 /// Set `SO_BINDTODEVICE` (Linux), `IP_BOUND_IF` (BSD), `IP_UNICAST_IF` (Windows) socket option for outbound sockets
10251028 pub outbound_bind_interface : Option < String > ,
10261029 /// Outbound sockets will `bind` to this address
@@ -1146,6 +1149,8 @@ impl Config {
11461149
11471150 #[ cfg( any( target_os = "linux" , target_os = "android" ) ) ]
11481151 outbound_fwmark : None ,
1152+ #[ cfg( target_os = "freebsd" ) ]
1153+ outbound_user_cookie : None ,
11491154 outbound_bind_interface : None ,
11501155 outbound_bind_addr : None ,
11511156 #[ cfg( target_os = "android" ) ]
Original file line number Diff line number Diff line change @@ -29,6 +29,11 @@ pub struct ConnectOpts {
2929 #[ cfg( any( target_os = "linux" , target_os = "android" ) ) ]
3030 pub fwmark : Option < u32 > ,
3131
32+ /// FreeBSD SO_USER_COOKIE
33+ /// https://www.freebsd.org/cgi/man.cgi?query=setsockopt&sektion=2
34+ #[ cfg( target_os = "freebsd" ) ]
35+ pub user_cookie : Option < u32 > ,
36+
3237 /// An IPC unix socket path for sending file descriptors to call `VpnService.protect`
3338 ///
3439 /// This is an [Android shadowsocks implementation](https://github.com/shadowsocks/shadowsocks-android) specific feature
Original file line number Diff line number Diff line change @@ -35,6 +35,24 @@ impl TcpStream {
3535 SocketAddr :: V6 ( ..) => TcpSocket :: new_v6 ( ) ?,
3636 } ;
3737
38+ // Set SO_USER_COOKIE for mark-based routing on FreeBSD
39+ if let Some ( user_cookie) = opts. user_cookie {
40+ let ret = unsafe {
41+ libc:: setsockopt (
42+ socket. as_raw_fd ( ) ,
43+ libc:: SOL_SOCKET ,
44+ libc:: SO_USER_COOKIE ,
45+ & user_cookie as * const _ as * const _ ,
46+ mem:: size_of_val ( & user_cookie) as libc:: socklen_t ,
47+ )
48+ } ;
49+ if ret != 0 {
50+ let err = io:: Error :: last_os_error ( ) ;
51+ error ! ( "set SO_USER_COOKIE error: {}" , err) ;
52+ return Err ( err) ;
53+ }
54+ }
55+
3856 set_common_sockopt_for_connect ( addr, & socket, opts) ?;
3957
4058 if !opts. tcp . fastopen {
Original file line number Diff line number Diff line change @@ -213,6 +213,17 @@ pub fn define_command_line_options(mut app: App<'_>) -> App<'_> {
213213 ) ;
214214 }
215215
216+ #[ cfg( target_os = "freebsd" ) ]
217+ {
218+ app = app. arg (
219+ Arg :: new ( "OUTBOUND_USER_COOKIE" )
220+ . long ( "outbound-user-cookie" )
221+ . takes_value ( true )
222+ . validator ( validator:: validate_u32)
223+ . help ( "Set SO_USER_COOKIE option for outbound sockets" ) ,
224+ ) ;
225+ }
226+
216227 #[ cfg( feature = "local-redir" ) ]
217228 {
218229 if RedirType :: tcp_default ( ) != RedirType :: NotSupported {
@@ -637,6 +648,13 @@ pub fn main(matches: &ArgMatches) {
637648 Err ( err) => err. exit ( ) ,
638649 }
639650
651+ #[ cfg( target_os = "freebsd" ) ]
652+ match matches. value_of_t :: < u32 > ( "OUTBOUND_USER_COOKIE" ) {
653+ Ok ( user_cookie) => config. outbound_user_cookie = Some ( user_cookie) ,
654+ Err ( ref err) if err. kind == ClapErrorKind :: ArgumentNotFound => { }
655+ Err ( err) => err. exit ( ) ,
656+ }
657+
640658 match matches. value_of_t :: < String > ( "OUTBOUND_BIND_INTERFACE" ) {
641659 Ok ( iface) => config. outbound_bind_interface = Some ( iface) ,
642660 Err ( ref err) if err. kind == ClapErrorKind :: ArgumentNotFound => { }
Original file line number Diff line number Diff line change @@ -176,6 +176,17 @@ pub fn define_command_line_options(mut app: App<'_>) -> App<'_> {
176176 ) ;
177177 }
178178
179+ #[ cfg( target_os = "freebsd" ) ]
180+ {
181+ app = app. arg (
182+ Arg :: new ( "OUTBOUND_USER_COOKIE" )
183+ . long ( "outbound-user-cookie" )
184+ . takes_value ( true )
185+ . validator ( validator:: validate_u32)
186+ . help ( "Set SO_USER_COOKIE option for outbound sockets" ) ,
187+ ) ;
188+ }
189+
179190 #[ cfg( feature = "multi-threaded" ) ]
180191 {
181192 app = app
@@ -269,6 +280,13 @@ pub fn main(matches: &ArgMatches) {
269280 Err ( err) => err. exit ( ) ,
270281 }
271282
283+ #[ cfg( target_os = "freebsd" ) ]
284+ match matches. value_of_t :: < u32 > ( "OUTBOUND_USER_COOKIE" ) {
285+ Ok ( user_cookie) => config. outbound_user_cookie = Some ( user_cookie) ,
286+ Err ( ref err) if err. kind == ClapErrorKind :: ArgumentNotFound => { }
287+ Err ( err) => err. exit ( ) ,
288+ }
289+
272290 match matches. value_of_t :: < String > ( "OUTBOUND_BIND_INTERFACE" ) {
273291 Ok ( iface) => config. outbound_bind_interface = Some ( iface) ,
274292 Err ( ref err) if err. kind == ClapErrorKind :: ArgumentNotFound => { }
Original file line number Diff line number Diff line change @@ -189,6 +189,17 @@ pub fn define_command_line_options(mut app: App<'_>) -> App<'_> {
189189 ) ;
190190 }
191191
192+ #[ cfg( target_os = "freebsd" ) ]
193+ {
194+ app = app. arg (
195+ Arg :: new ( "OUTBOUND_USER_COOKIE" )
196+ . long ( "outbound-user-cookie" )
197+ . takes_value ( true )
198+ . validator ( validator:: validate_u32)
199+ . help ( "Set SO_USER_COOKIE option for outbound sockets" ) ,
200+ ) ;
201+ }
202+
192203 #[ cfg( feature = "multi-threaded" ) ]
193204 {
194205 app = app
@@ -331,6 +342,13 @@ pub fn main(matches: &ArgMatches) {
331342 Err ( err) => err. exit ( ) ,
332343 }
333344
345+ #[ cfg( target_os = "freebsd" ) ]
346+ match matches. value_of_t :: < u32 > ( "OUTBOUND_USER_COOKIE" ) {
347+ Ok ( user_cookie) => config. outbound_user_cookie = Some ( user_cookie) ,
348+ Err ( ref err) if err. kind == ClapErrorKind :: ArgumentNotFound => { }
349+ Err ( err) => err. exit ( ) ,
350+ }
351+
334352 match matches. value_of_t :: < String > ( "OUTBOUND_BIND_INTERFACE" ) {
335353 Ok ( iface) => config. outbound_bind_interface = Some ( iface) ,
336354 Err ( ref err) if err. kind == ClapErrorKind :: ArgumentNotFound => { }
You can’t perform that action at this time.
0 commit comments