1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
|
use std::{
ffi::{c_char, c_void},
net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr},
};
use talpid_types::net::proxy::{Shadowsocks, Socks5Remote, SocksAuth};
use super::get_string;
/// Constructs a new IP address from a pointer containing bytes representing an IP address.
///
/// SAFETY: `addr` pointer must be non-null, aligned, and point to at least addr_len bytes
pub(crate) unsafe fn parse_ip_addr(addr: *const u8, addr_len: usize) -> Option<IpAddr> {
match addr_len {
4 => {
// SAFETY: `addr` pointer must be non-null, aligned, and point to at least addr_len bytes
let bytes = unsafe { std::slice::from_raw_parts(addr, addr_len) };
Some(Ipv4Addr::new(bytes[0], bytes[1], bytes[2], bytes[3]).into())
}
16 => {
// SAFETY: `addr` pointer must be non-null, aligned, and point to at least addr_len bytes
let bytes = unsafe { std::slice::from_raw_parts(addr, addr_len) };
let mut addr_arr = [0u8; 16];
addr_arr.as_mut_slice().copy_from_slice(bytes);
Some(Ipv6Addr::from(addr_arr).into())
}
anything_else => {
log::error!("Bad IP address length {anything_else}");
None
}
}
}
/// Converts parameters into a boxed `Shadowsocks` configuration that is safe
/// to send across the FFI boundary
///
/// # SAFETY
/// `address` must be a pointer to at least `address_len` bytes.
/// `c_password` and `c_cipher` must be pointers to null terminated strings
#[unsafe(no_mangle)]
pub unsafe extern "C" fn new_shadowsocks_access_method_setting(
address: *const u8,
address_len: usize,
port: u16,
c_password: *const c_char,
c_cipher: *const c_char,
) -> *const c_void {
let endpoint: SocketAddr =
if let Some(ip_address) = unsafe { parse_ip_addr(address, address_len) } {
SocketAddr::new(ip_address, port)
} else {
return std::ptr::null();
};
let password = unsafe { get_string(c_password) };
let cipher = unsafe { get_string(c_cipher) };
let shadowsocks_configuration = Shadowsocks {
endpoint,
password,
cipher,
};
Box::into_raw(Box::new(shadowsocks_configuration)) as *mut c_void
}
/// Converts parameters into a boxed `Socks5Remote` configuration that is safe
///
/// to send across the FFI boundary
///
/// # SAFETY
/// `address` must be a pointer to at least `address_len` bytes.
/// `c_username` and `c_password` must be pointers to null terminated strings, or null
#[unsafe(no_mangle)]
pub unsafe extern "C" fn new_socks5_access_method_setting(
address: *const u8,
address_len: usize,
port: u16,
c_username: *const c_char,
c_password: *const c_char,
) -> *const c_void {
let endpoint: SocketAddr =
if let Some(ip_address) = unsafe { parse_ip_addr(address, address_len) } {
SocketAddr::new(ip_address, port)
} else {
return std::ptr::null();
};
let auth = {
if c_username.is_null() || c_password.is_null() {
None
} else {
let username = unsafe { get_string(c_username) };
let password = unsafe { get_string(c_password) };
SocksAuth::new(username, password).ok()
}
};
let socks5_configuration = Socks5Remote { endpoint, auth };
Box::into_raw(Box::new(socks5_configuration)) as *mut c_void
}
|