1#![allow(non_camel_case_types)]
2#![allow(non_snake_case)]
3#![allow(non_upper_case_globals)]
4#![allow(dead_code)]
5
6use std::mem;
7use super::mac_addr::mac_addr_t;
8use super::ipnetwork::IpNetwork;
9use crate::common::rawstring;
10use std::net::IpAddr;
11#[cfg(unix)]
12use std::collections::HashMap;
13#[cfg(unix)]
14use libc;
15use std::io::Error;
16use super::*;
17
18#[cfg(windows)]
19use windows_sys::Win32::NetworkManagement::IpHelper::{GetAdaptersAddresses,IP_ADAPTER_ADDRESSES_LH,GetAdapterIndex};
20#[cfg(windows)]
21use windows_sys::Win32::NetworkManagement::IpHelper::{CreateUnicastIpAddressEntry,
22 MIB_UNICASTIPADDRESS_ROW,SetIfEntry,MIB_IFROW,MIB_IF_ADMIN_STATUS_UP,MIB_IF_ADMIN_STATUS_DOWN};
23#[cfg(windows)]
24use windows_sys::Win32::Networking::WinSock;
25#[cfg(windows)]
26use crate::net_ext::windows::rawsocket;
27
28#[cfg(unix)]
29use super::unix::rawsocket;
30#[derive(Clone,Debug)]
32pub struct NetworkInterface {
33 index:u32,
34 name:String,
35 mac_addr:mac_addr_t,
36 ips:Vec<IpNetwork>,
37 mtu:u16,
38}
39
40impl NetworkInterface {
41 pub fn new(if_index:u32,name:&String,mac_addr:&mac_addr_t,ipnet:IpNetwork,mtu:u16)->Self {
42 let mut ips=Vec::new();
43 ips.push(ipnet);
44 return Self {
45 index:if_index,
46 name:name.clone(),
47 mac_addr:mac_addr.clone(),
48 ips:ips,
49 mtu:mtu,
50 };
51 }
52 pub fn get_sys_interfaces()->Option<Vec<NetworkInterface>> {
53 return get_network_interfaces()
54 }
55
56 pub fn get_interface_by_name(ifname:&String)->Result<NetworkInterface,errcode::RESULT> {
57 let ifs = match get_network_interfaces() {
58 None=>return Err(errcode::ERROR_NOT_FOUND),
59 Some(vifs)=>vifs,
60 };
61
62 for nif in ifs {
63 if nif.name.eq(ifname) {
64 return Ok(nif)
65 }
66 }
67 Err(errcode::ERROR_NOT_FOUND)
68 }
69
70 pub fn get_ip_list(&self)->Vec<IpNetwork> {
72 self.ips.clone()
73 }
74 pub fn get_first_ip(&self)->Option<IpNetwork> {
76 if self.ips.len()>0 {
77 return Some(self.ips[0].clone());
78 }
79 None
80 }
81
82 pub fn get_mtu(&self)->u16 {
83 self.mtu
84 }
85
86 pub fn get_mac_addr(&self)->mac_addr_t {
87 self.mac_addr
88 }
89
90 pub fn get_if_index(&self)->u32 {
91 self.index
92 }
93
94 pub fn get_if_name(&self)->String {
95 self.name.clone()
96 }
97
98 pub fn set_ip_addr(&mut self,ip:&IpAddr,mask_len:u8)->errcode::RESULT {
99
100 let res = add_ip_address(self.index,&self.name,ip,mask_len);
101 if res!=errcode::RESULT_SUCCESS {
102 return res
103 }
104 match IpNetwork::new(ip.clone(), mask_len) {
105 Ok(ip1)=> {
106 let mut index=usize::MAX;
107 if ip.is_ipv4() {
109 for i in 0..self.ips.len() {
110 if self.ips[i].get_ip_addr().is_ipv4() {
111 index=i;
112 break;
113 }
114 }
115 }
116
117 if index==usize::MAX {
118 self.ips.push(ip1);
119 } else {
120 self.ips[index]=ip1;
121 }
122
123 },
124 Err(ec)=>return ec,
125 }
126 errcode::RESULT_SUCCESS
128 }
129
130 pub fn set_mac_addr(&mut self,new_mac:&mac_addr_t)->errcode::RESULT {
131 let res=set_macaddr_by_name(&self.name, new_mac,self.index);
132 if res==errcode::RESULT_SUCCESS {
133 self.mac_addr=new_mac.clone();
134 }
135 return res
136 }
137
138 pub fn to_string(&self)->String {
139 format!("name:{},if_index:{},mac:{},mtu:{},ip:{:?}",self.name,self.index,self.mac_addr,self.mtu,self.ips)
140 }
141
142}
143
144pub type Interfaces = Vec<NetworkInterface>;
145
146#[cfg(unix)]
147fn get_network_interfaces()->Option<Interfaces> {
148 let mut netifs:Vec<NetworkInterface> = Vec::new();
149 let mut ifmap:HashMap<String,NetworkInterface>=HashMap::new();
150
151 let mut unix_ifs = std::ptr::null_mut() as *mut libc::ifaddrs;
152 let res = unsafe { libc::getifaddrs(&mut unix_ifs as *mut *mut libc::ifaddrs) };
153 if res<0 {
154 return None;
155 }
156 let mut unix_if = unix_ifs;
157 while !unix_if.is_null() {
158 let if_ref = unsafe { &*(unix_if) };
159 if if_ref.ifa_addr.is_null() {
160 unix_if = if_ref.ifa_next;
161 continue;
162 }
163 get_one_addr(&mut ifmap,if_ref);
164 unix_if = if_ref.ifa_next;
165 }
166
167 if !unix_ifs.is_null() {
168 unsafe {
169 libc::freeifaddrs(unix_ifs);
170 }
171 }
172
173 for (_,v) in ifmap {
174 netifs.push(v);
175 }
176 Some(netifs)
177}
178
179#[cfg(unix)]
181fn get_one_addr(ifmap:&mut HashMap<String,NetworkInterface>,unix_addr:&libc::ifaddrs) {
182
183 let ifname = rawstring::array_to_string(unix_addr.ifa_name as *const u8, 33);
184 let mut if_ip = IpAddr::from([0,0,0,0]);
185 let mut if_mask = IpAddr::from([0,0,0,0]);
186 let mut mac = mac_addr_t::zero();
187
188 let mut af = 0;
189 if !unix_addr.ifa_addr.is_null() {
190 af = unsafe { (&*unix_addr.ifa_addr).sa_family as i32 };
191 if af != libc::AF_INET && af!=libc::AF_INET6 && af!=libc::AF_PACKET {
192 return
193 }
194 }
195 if af== libc::AF_INET || af==libc::AF_INET6 {
196 if_ip = match unsafe { rawsocket::to_socket_addr(unix_addr.ifa_addr as *const _ as *const rawsocket::sockaddr_t) } {
197 Err(_)=>IpAddr::from([0,0,0,0]),
198 Ok(a)=>a.ip(),
199 };
200
201 if_mask = match unsafe {rawsocket::to_socket_addr(unix_addr.ifa_netmask as *const _ as *const rawsocket::sockaddr_t)} {
202 Err(_)=>IpAddr::from([0,0,0,0]),
203 Ok(a)=>a.ip(),
204 };
205 } else if af== libc::AF_PACKET {
206 let laddr = unsafe { &(*(unix_addr.ifa_addr as *const libc::sockaddr_ll)) };
207 mac = mac_addr_t::from_slice(&laddr.sll_addr);
208 }
209
210 let ipnet = IpNetwork::from(if_ip,if_mask);
211 if !ifmap.contains_key(&ifname) {
212 let mut ips=Vec::new();
213 if af==libc::AF_INET || af==libc::AF_INET6 {
214 ips.push(ipnet);
215 }
216 let mtu = match get_mtu_by_name(&ifname) {
217 Ok(m)=>m,
218 Err(_)=> {
219 DEFAULT_ETHERNET_MTU
220 },
221 };
222 let if_index = match get_ifindex_by_name(&ifname) {
223 None=>0,
224 Some(r)=>r,
225 };
226
227 let netif = NetworkInterface {
228 index:if_index,
229 name:ifname.clone(),
230 mac_addr:mac,
231 mtu:mtu,
232 ips:ips,
233 };
234 ifmap.insert(ifname.clone(), netif);
235 } else {
236 if let Some(mut if_info) = ifmap.get_mut(&ifname) {
237 if af==libc::AF_INET || af==libc::AF_INET6 {
238 if_info.ips.push(ipnet);
239 } else if af==libc::AF_PACKET {
240 if_info.mac_addr = mac;
241 }
242 }
243
244 }
245}
246
247#[cfg(windows)]
248fn get_network_interfaces()->Option<Interfaces> {
249 const MAX_BUFFER_SIZE:usize=32768;
250 let mut netifs:Vec<NetworkInterface> = Vec::new();
251 let mut netif_buffer:Vec<u8> = Vec::with_capacity(MAX_BUFFER_SIZE);
252 netif_buffer.resize(MAX_BUFFER_SIZE,0);
253 unsafe {
254
255 let mut buffer_len:u32=MAX_BUFFER_SIZE as u32;
256 let res = GetAdaptersAddresses(WinSock::AF_UNSPEC,0,std::ptr::null_mut(),
257 netif_buffer.as_mut_ptr() as *mut IP_ADAPTER_ADDRESSES_LH,
258 &mut buffer_len as *mut u32);
259 if res!=0 {
260 return None;
261 }
262
263 let mut win_if = netif_buffer.as_mut_ptr() as *mut IP_ADAPTER_ADDRESSES_LH;
264 while win_if != std::ptr::null_mut() {
265 let if_ref = &*(win_if);
266 let ifname = rawstring::unicode_str_to_string(if_ref.FriendlyName);
267 let if_index =if_ref.Anonymous1.Anonymous.IfIndex;
268 let mut ips:Vec<IpNetwork>=Vec::new();
269 let mut paddr = if_ref.FirstUnicastAddress;
270 while paddr != std::ptr::null_mut(){
271 let ref_addr = &*(paddr);
272 let if_ip = match rawsocket::to_socket_addr(ref_addr.Address.lpSockaddr as *const _ as *const rawsocket::sockaddr_t) {
273 Err(_)=>IpAddr::from([0,0,0,0]),
274 Ok(a)=>a.ip(),
275 };
276
277 if let Ok(ipnet) = IpNetwork::new(if_ip,ref_addr.OnLinkPrefixLength as u8) {
278 ips.push(ipnet);
279 }
280
281 paddr = ref_addr.Next;
282 }
283 let netif = NetworkInterface {
284 index:if_index,
285 name:ifname,
286 mac_addr:mac_addr_t::from_slice(&if_ref.PhysicalAddress),
287 ips:ips,
288 mtu:if_ref.Mtu as u16,
289 };
290 netifs.push(netif);
291 win_if = if_ref.Next;
292 }
293
294 }
295 Some(netifs)
296}
297
298#[cfg(unix)]
299use unix::rawsocket::sockaddr_t;
300#[cfg(windows)]
301use windows::rawsocket::sockaddr_t;
302extern "C" {
303 pub fn c_get_if_mac(name:*const u8, mac:*mut u8)->i32;
304 pub fn c_set_if_mac(name:*const u8, mac:*const u8)->i32;
305 pub fn c_get_if_mtu(name:*const u8, mtu:*mut i32)->i32;
306 pub fn c_set_if_ip(name:*const u8, ip:*const sockaddr_t,mask:*const sockaddr_t)->i32;
307}
308
309#[cfg(unix)]
310const MAX_NAME_LEN:usize = 33;
311#[cfg(unix)]
312pub fn get_macaddr_by_name(ifname:&String)->Result<mac_addr_t,errcode::RESULT> {
313
314 let mut mac=[0u8;MAC_ADDR_SIZE];
315 let mut name_buf = [0u8;MAX_NAME_LEN];
316 if ifname.len()>=MAX_NAME_LEN {
317 return Err(errcode::ERROR_INVALID_PARAM)
318 }
319 name_buf[0..ifname.len()].copy_from_slice(ifname.as_bytes());
320
321 let res = unsafe { c_get_if_mac(name_buf.as_ptr(), mac.as_mut_ptr()) };
322 if res!= 0 {
323 return Err(errcode::ERROR_OS_CALL_FAILED);
324 }
325 Ok(mac_addr_t::from_slice(&mac))
326}
327
328#[cfg(unix)]
329pub fn set_macaddr_by_name(ifname:&String,mac:&mac_addr_t,_index:u32)->errcode::RESULT {
330
331 let mut name_buf = [0u8;MAX_NAME_LEN];
332 if ifname.len()>=MAX_NAME_LEN {
333 return errcode::ERROR_INVALID_PARAM
334 }
335 name_buf[0..ifname.len()].copy_from_slice(ifname.as_bytes());
336
337 let res = unsafe { c_set_if_mac(name_buf.as_ptr(), mac.as_ptr()) };
338 if res!= 0 {
339 return errcode::ERROR_OS_CALL_FAILED;
340 }
341 errcode::RESULT_SUCCESS
342}
343
344#[cfg(unix)]
345pub fn get_mtu_by_name(ifname:&String)->Result<u16,errcode::RESULT> {
346 let mut mtu=DEFAULT_ETHERNET_MTU as i32;
347 let mut name_buf = [0u8;MAX_NAME_LEN];
348 if ifname.len()>=MAX_NAME_LEN {
349 return Err(errcode::ERROR_INVALID_PARAM)
350 }
351 name_buf[0..ifname.len()].copy_from_slice(ifname.as_bytes());
352
353 let res = unsafe { c_get_if_mtu(name_buf.as_ptr(), &mut mtu as *mut i32) };
354 if res!= 0 {
355 return Err(errcode::ERROR_OS_CALL_FAILED);
356 }
357 Ok(mtu as u16)
358}
359
360#[cfg(unix)]
361pub fn get_ifindex_by_name(ifname:&String)->Option<u32> {
362 let mut name_buf = [0u8;MAX_NAME_LEN];
363 if ifname.len()>=MAX_NAME_LEN {
364 return None
365 }
366 name_buf[0..ifname.len()].copy_from_slice(ifname.as_bytes());
367 #[cfg(target_arch = "x86_64")]
368 let res = unsafe { libc::if_nametoindex(name_buf.as_ptr() as *const i8) };
369 #[cfg(target_arch = "aarch64")]
370 let res = unsafe { libc::if_nametoindex(name_buf.as_ptr() as *const u8) };
371 if res>0 {
372 return Some(res);
373 }
374 None
375}
376
377#[cfg(windows)]
378pub fn get_macaddr_by_name(_ifname:&String)->Result<mac_addr_t,errcode::RESULT> {
379 Err(errcode::ERROR_NOT_SUPPORT)
380}
381#[cfg(windows)]
382pub fn get_ifindex_by_name(name:*const u16)->Option<u32> {
383 let mut index = 0;
384 let res = unsafe { GetAdapterIndex(name,&mut index as *mut u32) };
385 if res==0 {
386
387 return Some(index)
388 } else {
389 println!("ret={},err={}",res,std::io::Error::last_os_error());
390 return None;
391 }
392}
393
394fn remove_non_hex_char(slice_str:&mut [u8])->usize {
396 let len = slice_str.len();
397 let mut used:usize=0;
398 for i in 0..len {
399 if slice_str[i]==b'-' || slice_str[i]==b':' {
400 continue;
401 }
402 slice_str[used]=slice_str[i];
403 used+=1;
404 if slice_str[i]==0 {
405 break;
406 }
407 }
408 used
409}
410
411#[cfg(windows)]
412pub fn set_macaddr_by_name(_ifname:&String,mac:&mac_addr_t,index:u32)->errcode::RESULT {
413 use windows_sys::Win32::System::Registry;
414 let key_name = "NetworkAddress";
415 let reg_path = "SYSTEM\\CurrentControlSet\\Control\\Class\\{4d36e972-e325-11ce-bfc1-08002be10318}";
416 let reg_mac_key = format!("{}\\{:04}",reg_path,index);
417 let mut hKey:Registry::HKEY=0;
418 let mut OpRes:u32=0;
419 let res = unsafe { Registry::RegCreateKeyExA(Registry::HKEY_LOCAL_MACHINE, reg_mac_key.as_ptr(),
420 0, std::ptr::null(), 0, Registry::KEY_ALL_ACCESS,
421 std::ptr::null(), &mut hKey as *mut Registry::HKEY, &mut OpRes as *mut u32) };
422 if res!=0 {
423 println!("open mac address registry failed,key_path={},ret={},err={}",reg_mac_key,res,Error::last_os_error());
424 return errcode::ERROR_OS_CALL_FAILED;
425 }
426 let mut sz_mac=[0u8;18];
427 let mut sz_name=[0u8;32];
428 sz_mac[0..17].copy_from_slice(mac.to_string().as_bytes());
429 let vlen = remove_non_hex_char(&mut sz_mac[0..17]);
430 sz_name[0..key_name.len()].copy_from_slice(key_name.as_bytes());
431 let res2=unsafe { Registry::RegSetValueExA(hKey, sz_name.as_ptr(), 0, Registry::REG_SZ,
432 sz_mac.as_ptr(), vlen as u32) };
433 if res2!=0 {
434 println!("set mac address registry failed,key_path={},err={}",reg_mac_key,Error::last_os_error());
435 }
436 unsafe {
437 Registry::RegCloseKey(hKey);
438 }
439 if res2==0 {
440 set_interface_admin_status(index,false);
441 set_interface_admin_status(index,true);
442 errcode::RESULT_SUCCESS
443 } else {
444 errcode::ERROR_OS_CALL_FAILED
445 }
446
447
448}
449
450#[cfg(windows)]
451fn set_interface_admin_status(index:u32,isUp:bool)->errcode::RESULT {
452 let mut if_info = unsafe { mem::zeroed::<MIB_IFROW>() };
453 if_info.dwIndex = index;
454 if_info.dwAdminStatus = if isUp {MIB_IF_ADMIN_STATUS_UP} else {MIB_IF_ADMIN_STATUS_DOWN};
455 let res = unsafe {SetIfEntry(&if_info as *const MIB_IFROW) };
457 if res!=0 {
458 println!("Set interface state error,res={},os err={},if_index={}",res,Error::last_os_error(),index);
459 return errcode::ERROR_OS_CALL_FAILED
460 }
461 errcode::RESULT_SUCCESS
462}
463
464#[cfg(windows)]
465pub fn add_ip_address(if_index:u32,_name:&String,ip:&IpAddr,mask_len:u8)->errcode::RESULT {
466 let mut ip_rec:MIB_UNICASTIPADDRESS_ROW = unsafe { mem::zeroed::<MIB_UNICASTIPADDRESS_ROW>() };
467 let winIp = rawsocket::rust_ipaddr_to_windows(ip);
468 ip_rec.Address=winIp;
469 ip_rec.OnLinkPrefixLength = mask_len;
470 ip_rec.InterfaceIndex = if_index;
471 ip_rec.PreferredLifetime = 0xFFFFFFFF;
472 ip_rec.ValidLifetime = 0xFFFFFFFF;
473 let res = unsafe { CreateUnicastIpAddressEntry(&ip_rec as *const MIB_UNICASTIPADDRESS_ROW) };
474 if res!=0 {
475 println!("Add Ip address failed,ip={},mask={},error={}",ip,mask_len,Error::last_os_error());
476
477 return errcode::ERROR_OS_CALL_FAILED
478 }
479 errcode::RESULT_SUCCESS
480}
481
482#[cfg(unix)]
483pub fn add_ip_address(_if_index:u32,name:&String,ip:&IpAddr,mask_len:u8)->errcode::RESULT {
484 let (ip_addr,_) = sockaddr_t::from_socket_addr(&SocketAddr::new(ip.clone(), 0));
485 let mask = match IpNetwork::get_ip_mask(ip.is_ipv6(), mask_len) {
486 None=>return errcode::ERROR_INVALID_PARAM,
487 Some(m)=>m,
488 };
489 let (raw_mask,_) = sockaddr_t::from_socket_addr(&SocketAddr::new(mask,0));
490
491 let res = unsafe { c_set_if_ip(name.as_ptr(), &ip_addr as *const sockaddr_t, &raw_mask as *const sockaddr_t) };
492 if res!=0 {
493 return errcode::ERROR_OS_CALL_FAILED;
494 }
495 errcode::RESULT_SUCCESS
496}