rust_rsm/net_ext/
netinterface.rs

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///网络接口
31#[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    ///获取Interface的IP列表
71    pub fn get_ip_list(&self)->Vec<IpNetwork> {
72        self.ips.clone()
73    }
74    ///获取接口的第一个IP地址
75    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                  //ipv4只允许配置一个Ip地址,进行替代
108                  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        //println!("set ip success,ip={},ips={:?}",ip,self.ips);
127        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///读取一个getifaddrs中的内容
180#[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
394///移除一个0结尾的字符串中"-"he ":""
395fn 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    //rawstring::ansi_str_to_unicode(ifname.as_bytes(),&mut if_info.wszName[..]);
456    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}