File tree 6 files changed +82
-0
lines changed 6 files changed +82
-0
lines changed Original file line number Diff line number Diff line change @@ -1021,6 +1021,9 @@ pub struct Config {
1021
1021
/// Set `SO_MARK` socket option for outbound sockets
1022
1022
#[ cfg( any( target_os = "linux" , target_os = "android" ) ) ]
1023
1023
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 > ,
1024
1027
/// Set `SO_BINDTODEVICE` (Linux), `IP_BOUND_IF` (BSD), `IP_UNICAST_IF` (Windows) socket option for outbound sockets
1025
1028
pub outbound_bind_interface : Option < String > ,
1026
1029
/// Outbound sockets will `bind` to this address
@@ -1146,6 +1149,8 @@ impl Config {
1146
1149
1147
1150
#[ cfg( any( target_os = "linux" , target_os = "android" ) ) ]
1148
1151
outbound_fwmark : None ,
1152
+ #[ cfg( target_os = "freebsd" ) ]
1153
+ outbound_user_cookie : None ,
1149
1154
outbound_bind_interface : None ,
1150
1155
outbound_bind_addr : None ,
1151
1156
#[ cfg( target_os = "android" ) ]
Original file line number Diff line number Diff line change @@ -29,6 +29,11 @@ pub struct ConnectOpts {
29
29
#[ cfg( any( target_os = "linux" , target_os = "android" ) ) ]
30
30
pub fwmark : Option < u32 > ,
31
31
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
+
32
37
/// An IPC unix socket path for sending file descriptors to call `VpnService.protect`
33
38
///
34
39
/// 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 {
35
35
SocketAddr :: V6 ( ..) => TcpSocket :: new_v6 ( ) ?,
36
36
} ;
37
37
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
+
38
56
set_common_sockopt_for_connect ( addr, & socket, opts) ?;
39
57
40
58
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<'_> {
213
213
) ;
214
214
}
215
215
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
+
216
227
#[ cfg( feature = "local-redir" ) ]
217
228
{
218
229
if RedirType :: tcp_default ( ) != RedirType :: NotSupported {
@@ -637,6 +648,13 @@ pub fn main(matches: &ArgMatches) {
637
648
Err ( err) => err. exit ( ) ,
638
649
}
639
650
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
+
640
658
match matches. value_of_t :: < String > ( "OUTBOUND_BIND_INTERFACE" ) {
641
659
Ok ( iface) => config. outbound_bind_interface = Some ( iface) ,
642
660
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<'_> {
176
176
) ;
177
177
}
178
178
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
+
179
190
#[ cfg( feature = "multi-threaded" ) ]
180
191
{
181
192
app = app
@@ -269,6 +280,13 @@ pub fn main(matches: &ArgMatches) {
269
280
Err ( err) => err. exit ( ) ,
270
281
}
271
282
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
+
272
290
match matches. value_of_t :: < String > ( "OUTBOUND_BIND_INTERFACE" ) {
273
291
Ok ( iface) => config. outbound_bind_interface = Some ( iface) ,
274
292
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<'_> {
189
189
) ;
190
190
}
191
191
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
+
192
203
#[ cfg( feature = "multi-threaded" ) ]
193
204
{
194
205
app = app
@@ -331,6 +342,13 @@ pub fn main(matches: &ArgMatches) {
331
342
Err ( err) => err. exit ( ) ,
332
343
}
333
344
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
+
334
352
match matches. value_of_t :: < String > ( "OUTBOUND_BIND_INTERFACE" ) {
335
353
Ok ( iface) => config. outbound_bind_interface = Some ( iface) ,
336
354
Err ( ref err) if err. kind == ClapErrorKind :: ArgumentNotFound => { }
You can’t perform that action at this time.
0 commit comments