cyfs_util/net/
net_util.rs

1use super::get_if_addrs::get_if_addrs;
2use cyfs_base::{BuckyError, BuckyResult, BuckyErrorCode};
3
4use std::error::Error;
5use std::mem;
6use std::net::{IpAddr, SocketAddr, SocketAddrV4, SocketAddrV6};
7
8#[cfg(unix)]
9use async_std::net::UdpSocket;
10#[cfg(unix)]
11use async_std::os::unix::io::RawFd;
12#[cfg(unix)]
13extern crate libc;
14
15#[cfg(windows)]
16use std::os::windows::io::{AsRawSocket, RawSocket};
17#[cfg(windows)]
18extern crate libc;
19
20#[cfg(windows)]
21use std::ptr;
22
23#[cfg(windows)]
24use winapi::{
25    shared::minwindef::{BOOL, DWORD, FALSE, LPDWORD, LPVOID},
26    um::{
27        mswsock::SIO_UDP_CONNRESET,
28        winsock2::{WSAGetLastError, WSAIoctl, SOCKET, SOCKET_ERROR},
29    },
30};
31
32pub fn get_all_ips() -> BuckyResult<Vec<IpAddr>> {
33    let mut ret = Vec::new();
34    for iface in get_if_addrs()? {
35        ret.push(iface.ip())
36    }
37    Ok(ret)
38}
39
40#[cfg(unix)]
41pub fn set_socket_reuseaddr(fd: RawFd) -> Result<(), Box<dyn Error>> {
42    let ret;
43    unsafe {
44        let optval: libc::c_int = 1;
45        ret = libc::setsockopt(
46            fd,
47            libc::SOL_SOCKET,
48            libc::SO_REUSEADDR,
49            &optval as *const _ as *const libc::c_void,
50            mem::size_of_val(&optval) as libc::socklen_t,
51        );
52    }
53
54    if ret != 0 {
55        let msg = format!(
56            "set_socket_reuseaddr error! ret={}, err={}",
57            ret,
58            async_std::io::Error::last_os_error()
59        );
60        error!("{}", msg);
61
62        return Err(Box::<dyn Error>::from(msg));
63    }
64
65    Ok(())
66}
67
68#[cfg(unix)]
69pub fn set_socket_reuseport(fd: RawFd) -> Result<(), Box<dyn Error>> {
70    let ret;
71    unsafe {
72        let optval: libc::c_int = 1;
73        ret = libc::setsockopt(
74            fd,
75            libc::SOL_SOCKET,
76            libc::SO_REUSEPORT,
77            &optval as *const _ as *const libc::c_void,
78            mem::size_of_val(&optval) as libc::socklen_t,
79        );
80    }
81
82    if ret != 0 {
83        let msg = format!(
84            "set_socket_reuseport error! ret={}, err={}",
85            ret,
86            async_std::io::Error::last_os_error()
87        );
88        error!("{}", msg);
89
90        return Err(Box::<dyn Error>::from(msg));
91    }
92
93    Ok(())
94}
95
96#[cfg(unix)]
97pub fn set_socket_keepalive(fd: RawFd) -> Result<(), Box<dyn Error>> {
98    let ret;
99    unsafe {
100        let optval: libc::c_int = 1;
101        ret = libc::setsockopt(
102            fd,
103            libc::SOL_SOCKET,
104            libc::SO_KEEPALIVE,
105            &optval as *const _ as *const libc::c_void,
106            mem::size_of_val(&optval) as libc::socklen_t,
107        );
108    }
109
110    if ret != 0 {
111        let msg = format!(
112            "setsockopt error! ret={}, err={}",
113            ret,
114            async_std::io::Error::last_os_error()
115        );
116        error!("{}", msg);
117
118        return Err(Box::<dyn Error>::from(msg));
119    }
120
121    Ok(())
122}
123
124#[cfg(windows)]
125pub fn set_socket_keepalive(sock: RawSocket) -> Result<(), Box<dyn Error>> {
126    const SOL_SOCKET: i32 = 0xFFFF;
127    const SO_KEEPALIVE: i32 = 0x0008;
128
129    let ret;
130    unsafe {
131        let optval: libc::c_int = 1;
132        ret = libc::setsockopt(
133            sock as libc::SOCKET,
134            SOL_SOCKET,
135            SO_KEEPALIVE,
136            &optval as *const _ as *const libc::c_char,
137            mem::size_of_val(&optval) as libc::c_int,
138        );
139    }
140
141    if ret != 0 {
142        let msg = format!(
143            "setsockopt error! ret={}, err={}",
144            ret,
145            async_std::io::Error::last_os_error()
146        );
147        error!("{}", msg);
148
149        return Err(Box::<dyn Error>::from(msg));
150    }
151
152    Ok(())
153}
154
155#[cfg(not(windows))]
156pub fn init_udp_socket(_socket: &UdpSocket) -> Result<(), BuckyError> {
157    Ok(())
158}
159
160#[cfg(windows)]
161pub fn init_udp_socket<S: AsRawSocket>(socket: &S) -> Result<(), BuckyError> {
162    unsafe {
163        // Ignoring UdpSocket's WSAECONNRESET error
164        // https://github.com/shadowsocks/shadowsocks-rust/issues/179
165        // https://stackoverflow.com/questions/30749423/is-winsock-error-10054-wsaeconnreset-normal-with-udp-to-from-localhost
166        //
167        // This is because `UdpSocket::recv_from` may return WSAECONNRESET
168        // if you called `UdpSocket::send_to` a destination that is not existed (may be closed).
169        //
170        // It is not an error. Could be ignored completely.
171        // We have to ignore it here because it will crash the server.
172
173        let mut bytes_returned: DWORD = 0;
174        let mut enable: BOOL = FALSE;
175        let handle = socket.as_raw_socket() as SOCKET;
176
177        let ret = WSAIoctl(
178            handle,
179            SIO_UDP_CONNRESET,
180            &mut enable as *mut _ as LPVOID,
181            mem::size_of_val(&enable) as DWORD,
182            ptr::null_mut(),
183            0,
184            &mut bytes_returned as *mut _ as LPDWORD,
185            ptr::null_mut(),
186            None,
187        );
188
189        if ret == SOCKET_ERROR {
190            use std::io::Error;
191
192            let err_code = WSAGetLastError();
193            let err = Error::from_raw_os_error(err_code);
194
195            Err(BuckyError::from(err))
196        } else {
197            Ok(())
198        }
199    }
200}
201
202// 解析形如 port or host:port的格式
203pub fn parse_address(address: &str) -> Result<(String, u16), BuckyError> {
204    let parts: Vec<&str> = address.split(':').collect();
205    if parts.len() == 1 {
206        match parts[0].parse::<u16>() {
207            Ok(port) => Ok(("0.0.0.0".to_string(), port)),
208            Err(e) => {
209                error!("invalid address port, address={}, e={}", address, e);
210                Err(BuckyError::from(e))
211            }
212        }
213    } else {
214        match parts[1].parse::<u16>() {
215            Ok(port) => Ok((parts[0].to_string(), port)),
216            Err(e) => {
217                error!("invalid address port, address={}, e={}", address, e);
218                Err(BuckyError::from(e))
219            }
220        }
221    }
222}
223
224
225pub fn parse_port_from_toml_value(v: &toml::Value) -> BuckyResult<u16> {
226    let port: u16;
227
228    if v.is_integer() {
229        let v = v.as_integer().unwrap();
230        if v >= 65536 {
231            let msg = format!("invalid port number range: {}", v);
232            error!("{}", msg);
233
234            return Err(BuckyError::from(msg));
235        }
236        port = v as u16;
237    } else if v.is_str() {
238        let v = v.as_str().unwrap();
239        let ret = v.parse::<u16>();
240        if let Err(e) = ret {
241            error!("invalid port number! e={}", e);
242
243            return Err(BuckyError::from(e));
244        }
245
246        port = ret.unwrap();
247    } else {
248        let msg = format!("invalid port type: {:?}", v);
249        error!("{}", msg);
250
251        return Err(BuckyError::new(BuckyErrorCode::InvalidFormat, msg));
252    }
253
254    Ok(port)
255}
256
257pub fn is_invalid_ip(ip: &str) -> bool {
258    let parts: Vec<&str> = ip.split(".").collect();
259
260    // 过滤169.254.x.x  0.0.0.0
261    return (parts[0] == "169" && parts[1] == "254")
262        || (parts[0] == "0" && parts[1] == "0" && parts[2] == "0" && parts[3] == "0");
263}
264
265// 判断一个ip是不是内网私有ip
266pub fn is_private_ip(ip: &str) -> bool {
267    let parts: Vec<&str> = ip.split(".").collect();
268    return parts[0] == "10"
269        || (parts[0] == "172"
270            && (parts[1].parse::<u16>().unwrap_or(0) >= 16
271                && parts[1].parse::<u16>().unwrap_or(0) <= 31))
272        || (parts[0] == "192" && parts[1] == "168");
273}
274
275static SYSTEM_HOST_INFO: once_cell::sync::OnceCell<SystemHostInfo> = once_cell::sync::OnceCell::new();
276
277#[derive(Clone)]
278pub struct SystemHostInfo {
279    pub none_local_ip_v4: Vec<SocketAddr>,
280    pub private_ip_v4: Vec<SocketAddr>,
281    pub public_ip_v4: Vec<SocketAddr>,
282    pub ip_v6: Vec<SocketAddr>,
283}
284
285// 外部可以直接设置system_hosts
286pub fn bind_system_hosts(info: SystemHostInfo) {
287    if let Err(_e) = SYSTEM_HOST_INFO.set(info) {
288        error!("bind_system_hosts must be call only once or on startup before stack init!")
289    }
290}
291
292pub fn get_system_hosts() -> BuckyResult<SystemHostInfo> {
293    if SYSTEM_HOST_INFO.get().is_none() {
294        let info = init_system_hosts()?;
295        bind_system_hosts(info);
296    }
297
298    Ok(SYSTEM_HOST_INFO.get().unwrap().clone())
299}
300
301pub fn init_system_hosts() -> BuckyResult<SystemHostInfo> {
302    let ret = get_if_addrs();
303    if let Err(e) = ret {
304        let msg = format!("get_if_addrs error! err={}", e);
305        error!("{}", msg);
306
307        return Err(BuckyError::from(msg));
308    }
309
310    let mut result = SystemHostInfo {
311        none_local_ip_v4: Vec::new(),
312        private_ip_v4: Vec::new(),
313        public_ip_v4: Vec::new(),
314        ip_v6: Vec::new(),
315    };
316
317    for iface in ret.unwrap() {
318        info!("got iface={:?}", iface);
319
320        let addr = match iface.ip() {
321            IpAddr::V4(addr) => addr,
322            IpAddr::V6(addr) => {
323                let sock_addr = SocketAddrV6::new(addr, 0, 0, iface.scope_id);
324                result.ip_v6.push(SocketAddr::V6(sock_addr));
325                continue;
326            }
327        };
328
329        let ip_str = addr.to_string();
330        info!("got ip: {} {}", ip_str, iface.description);
331
332        if cfg!(windows) {
333            if iface.description.find("VMware").is_some() {
334                info!("will ignore as VMware addr: {}", ip_str);
335                continue;
336            }
337
338            if iface
339                .description
340                .find("Hyper-V Virtual Ethernet Adapter")
341                .is_some()
342            {
343                info!(
344                    "will ignore as Hyper-V Virtual Ethernet Adapter addr: {}",
345                    ip_str
346                );
347                continue;
348            }
349        }
350
351        if is_invalid_ip(&ip_str) {
352            info!("will ignore as invalid addr: {}", ip_str);
353            continue;
354        }
355
356        let addr = SocketAddr::V4(SocketAddrV4::new(addr, 0));
357        result.none_local_ip_v4.push(addr);
358        if is_private_ip(&ip_str) {
359            result.private_ip_v4.push(addr);
360        } else {
361            result.public_ip_v4.push(addr);
362        }
363    }
364
365    Ok(result)
366}