1#![allow(non_camel_case_types)]
2#![allow(non_snake_case)]
3#![allow(non_upper_case_globals)]
4
5use crate::common::errcode;
6use std::net::{IpAddr,SocketAddr,Ipv4Addr,Ipv6Addr};
7#[cfg(unix)]
8use std::os::raw::{c_int};
9use std::process::Command;
10#[cfg(unix)]
11use std::fs::{OpenOptions};
12
13#[cfg(unix)]
14use std::os::unix::io::{RawFd};
15#[cfg(windows)]
16use std::os::windows::io::{RawHandle};
17#[cfg(windows)]
18use std::os::windows::io::{RawSocket};
19use std::ptr;
20
21pub mod arp;
22pub mod mac_addr;
23pub use mac_addr::mac_addr_t;
24
25pub mod ethernet_pkt;
26
27pub mod rawpacket;
28pub mod pktbuf;
29pub mod fec;
30pub mod ipnetwork;
31pub use ipnetwork::IpNetwork;
32
33pub mod netinterface;
34pub mod iprt;
35pub mod restserver;
36
37#[cfg(windows)]
38pub mod windows;
39#[cfg(unix)]
40pub mod unix;
41
42
43#[cfg(unix)]
44pub type RawFdType = RawFd;
45#[cfg(windows)]
46pub type RawFdType = RawSocket;
47
48#[cfg(unix)]
49pub type RawFileFd = RawFd;
50#[cfg(windows)]
51pub type RawFileFd = RawHandle;
52
53pub const MAC_ADDR_SIZE:usize = 6;
54pub const ETHERNET_HDR_SIZE:usize = 14;
55pub const IPV4_HDR_SIZE:usize = 20;
56pub const IPV6_HDR_SIZE:usize = 40;
57pub const UDP_HDR_SIZE:usize = 8;
58pub const TCP_HDR_SIZE:usize = 20;
59pub const ARP_PACKET_SIZE:usize = 28;
60pub const DEFAULT_ETHERNET_MTU:u16 = 1500;
61const MAX_PKT_BUF_SIZE:u16 = 2048;
63
64pub const AF_INET:u16=2;
65pub const AF_INET6:u16=23;
66
67pub mod EthernetTypes {
68 pub const Ethernet_Ipv4: u16 = 0x0800;
69 pub const Ethernet_ARP: u16 = 0x0806;
70 pub const Ethernet_RARP: u16 = 0x8035;
72
73 pub const Ethernet_Ipv6: u16 = 0x86dd;
74 pub const Ethernet_Vlan: u16 = 0x8100;
75 pub const Ethernet_SVlan: u16 = 0x88a8;
76
77 pub const Ethernet_STP: u16 = 0x8181;
78 pub const Ethernet_LLDP: u16 = 0x88cc;
79
80 pub const Ethernet_MPLS: u16 = 0x8847;
81 pub const Ethernet_MPLS_USL: u16 = 0x8848;
82
83 pub const Ethernet_PPPoE_Discovery: u16 = 0x8863;
84 pub const Ethernet_PPPoE_Session: u16 = 0x8864;
85}
86
87pub const IPV4_ADDR_LEN:usize = 4;
88pub const IPV6_ADDR_LEN:usize = 16;
89
90pub mod IpProtos {
91 pub const Ip_Proto_ICMP: u8 = 1;
92 pub const Ip_Proto_IGMP: u8 = 2;
93 pub const Ip_Proto_IPv4inIP: u8 = 4;
94 pub const Ip_Proto_TCP: u8 = 6;
95 pub const Ip_Proto_UDP: u8 = 17;
96 pub const Ip_Proto_DCCP: u8 = 33;
97 pub const Ip_Proto_IPv6_Route: u8 = 43;
98 pub const Ip_Proto_IPv6_Frag: u8 = 44;
99
100 pub const Ip_Proto_RSVP: u8 = 46;
101 pub const Ip_Proto_GRE: u8 = 47;
102
103 pub const Ip_Proto_ESP: u8 = 50;
104 pub const Ip_Proto_AH: u8 = 51;
105
106 pub const Ip_Proto_ICMPv6: u8 = 58;
107
108 pub const Ip_Proto_EIGRP: u8 = 88;
109 pub const Ip_Proto_OSPF: u8 = 89;
110
111 pub const Ip_Proto_PIM: u8 = 103; pub const Ip_Proto_L2TP: u8 = 115;
113 pub const Ip_Proto_ISIS_IPv4: u8 = 124;
114 pub const Ip_Proto_SCTP: u8 = 132;
115 pub const Ip_Proto_MANET: u8 = 138;
116 pub const Ip_Proto_HIP: u8 = 139;
117 pub const Ip_Proto_ROHC: u8 = 142;
118}
119
120pub mod ServicePorts {
122 pub const TP_PORT_FTP_DATA: u16 = 20;
123 pub const TP_PORT_FTP: u16 = 21;
124 pub const TP_PORT_SSH: u16 = 22;
125 pub const TP_PORT_TELNET: u16 = 23;
126 pub const TP_PORT_TACACS: u16 = 49;
127 pub const TP_PORT_DNS: u16 = 53;
128 pub const TP_PORT_DHCP_CLIENT: u16 = 67;
129 pub const TP_PORT_DHCP_SERVER: u16 = 68;
130 pub const TP_PORT_HTTP: u16 = 80;
131
132 pub const TP_PORT_POP3: u16 = 110;
133 pub const TP_PORT_SFTP: u16 = 115;
134 pub const TP_PORT_NTP: u16 = 123;
135
136 pub const TP_PORT_SNMP: u16 = 161;
137 pub const TP_PORT_SNMP_TRAP: u16 = 162;
138
139 pub const TP_PORT_BGP: u16 = 179;
140 pub const TP_PORT_LDAP: u16 = 389;
141 pub const TP_PORT_HTTPS: u16 = 443;
142 pub const TP_PORT_HTTPS_PCSYNC: u16 = 8443;
143 pub const TP_PORT_IKE: u16 = 500;
144 pub const TP_PORT_IPSEC_NAT: u16 = 4500;
145
146 pub const TP_PORT_SYSLOG: u16 = 514;
147 pub const TP_PORT_RIPNG: u16 = 521;
148 pub const TP_PORT_DHCPv6_CLIENT: u16 = 546;
149 pub const TP_PORT_DHCPv6_SERVER: u16 = 547;
150 pub const TP_PORT_RTSP: u16 = 554; pub const TP_PORT_LDAPS: u16 = 636; pub const TP_PORT_NETCONF_SSH: u16 = 830; pub const TP_PORT_NETCONF_HTTPS: u16 = 832; pub const TP_PORT_TWAMP: u16 = 862;
155 pub const TP_PORT_FTPS: u16 = 990; pub const TP_PORT_OPEN_VPN: u16 = 1194; pub const TP_PORT_L2TP: u16 = 1701; pub const TP_PORT_RADIUS: u16 = 1812; pub const TP_PORT_RADIUS_ACCT: u16 = 1813; pub const TP_PORT_SIP: u16 = 5060;
162 pub const TP_PORT_SIPS: u16 = 5061;
163
164 pub const TP_PORT_BFD_CTRL: u16 = 3784;
165 pub const TP_PORT_BFD_ECHO: u16 = 785;
166 pub const TP_PORT_BFD_LAG: u16 = 6784;
167
168 pub const TP_PORT_WOT: u16 = 38000;
170}
171
172pub fn default_socket_addr() -> SocketAddr {
173 return SocketAddr::new(IpAddr::from([0, 0, 0, 0]), 0);
174}
175pub fn ipaddr_to_array(ip:&IpAddr)->(usize,[u8;IPV6_ADDR_LEN]) {
177 let mut ip_addr:[u8;IPV6_ADDR_LEN]=[0;IPV6_ADDR_LEN];
178 match ip{
179 IpAddr::V4(addr)=> {
180 let a = addr.octets();
181 unsafe {
182 std::ptr::copy(&a[0] as *const u8, &mut ip_addr[0] as *mut u8,IPV4_ADDR_LEN);
183 }
184 (IPV4_ADDR_LEN,ip_addr)
185 }
186 IpAddr::V6(addr)=> {
187 (IPV6_ADDR_LEN, addr.octets())
188 }
189 }
190}
191pub fn copy_ipaddr_to_slice(src:&IpAddr,buf:&mut[u8])->Result<usize,errcode::RESULT> {
193 match src {
194 IpAddr::V4(ip)=> {
195 if buf.len()<IPV4_ADDR_LEN {
196 return Err(errcode::ERROR_OUTOF_MEM)
197 }
198 unsafe {
199 ptr::copy_nonoverlapping(ip.octets().as_ptr(), buf.as_mut_ptr(), IPV4_ADDR_LEN);
200 }
201 return Ok(IPV4_ADDR_LEN)
202 },
203 IpAddr::V6(ip)=> {
204 if buf.len()<IPV6_ADDR_LEN {
205 return Err(errcode::ERROR_OUTOF_MEM)
206 }
207 unsafe {
208 ptr::copy_nonoverlapping(ip.octets().as_ptr(), buf.as_mut_ptr(), IPV6_ADDR_LEN);
209 }
210 return Ok(IPV6_ADDR_LEN)
211 }
212 }
213}
214pub fn bytes_array_to_ipaddr(ip:&[u8])->IpAddr {
216 let ip_addr = match ip.len() {
217 IPV4_ADDR_LEN=>{
218 IpAddr::from([ip[0],ip[1],ip[2],ip[3]])
219 },
220 IPV6_ADDR_LEN=>{
221 let mut a:[u8;IPV6_ADDR_LEN]=[0;IPV6_ADDR_LEN];
222 unsafe {
223 std::ptr::copy(&ip[0] as *const u8, &mut a[0] as *mut u8, IPV6_ADDR_LEN);
224 }
225 IpAddr::from(a)
226 },
227 _=>IpAddr::from([0,0,0,0]),
228 };
229 return ip_addr;
230}
231
232pub fn ipv4_to_u32(ipv4: &Ipv4Addr) -> u32 {
233 let u8a = ipv4.octets();
234 return u32::from_be_bytes(u8a);
235}
236
237pub fn ipv6_to_u64(ipv6: &Ipv6Addr) -> (u64, u64) {
239 let u8a = ipv6.octets();
240 let v128 = u128::from_be_bytes(u8a);
241
242 let h64 = (v128 >> 64) as u64;
243 let l64 = (v128 & 0xFFFFFFFFFFFFFFFF) as u64;
244 return (l64, h64);
245}
246
247pub fn get_ip_address_family(ip:&IpAddr)->u16 {
248 if ip.is_ipv6() {
249 AF_INET6
250 } else {
251 AF_INET
252 }
253}
254pub fn ip_pool_size(ip_start:&IpAddr,ip_end:&IpAddr)->u128 {
256 match (ip_start,ip_end) {
257 (IpAddr::V4(ip1),IpAddr::V4(ip2))=> {
258 let v1=u32::from_be_bytes(ip1.octets());
259 let v2 = u32::from_be_bytes(ip2.octets());
260 if v1>v2 {
261 0
262 } else {
263 (v2-v1+1) as u128
264 }
265 },
266 (IpAddr::V6(ip1),IpAddr::V6(ip2))=> {
267 let v1=u128::from_be_bytes(ip1.octets());
268 let v2 = u128::from_be_bytes(ip2.octets());
269 if v1>v2 {
270 0
271 } else {
272 v2-v1+1
273 }
274 },
275 _=>return 0,
276 }
277}
278
279#[cfg(unix)]
280#[link(name = "os_linux", kind = "static")]
281extern "C" {
282 pub fn tuntap_setup(fd: c_int, name: *mut u8, mode: c_int, packet_info: c_int) -> c_int;
283}
284#[cfg(unix)]
285pub fn create_tap_if(
286 name: &str,
287 mtu: u16,
288 ip_addrs: &[IpNetwork],
289 pkt_info: bool,
290) -> errcode::RESULT {
291 use std::os::unix::io::{AsRawFd};
292
293 let fd = match OpenOptions::new()
294 .read(true)
295 .write(true)
296 .open("/dev/net/tun")
297 {
298 Err(_) => return errcode::ERROR_OPEN_FILE,
299 Ok(f) => f,
300 };
301
302 let mut name_buffer = Vec::new();
304 name_buffer.extend_from_slice(name.as_bytes());
305 name_buffer.extend_from_slice(&[0; 33]);
306 let name_ptr: *mut u8 = name_buffer.as_mut_ptr();
307 let result = unsafe {
308 tuntap_setup(
309 fd.as_raw_fd(),
310 name_ptr,
311 2 as c_int,
312 if pkt_info { 1 } else { 0 },
313 )
314 };
315 if result < 0 {
316 return errcode::ERROR_OS_CALL_FAILED;
317 }
318 if ip_addrs.len() > 0 {
320 let addr_str = format!("{}/{}", ip_addrs[0].ip(), ip_addrs[0].prefix());
321 let _ = Command::new("ifconfig")
322 .args([
323 name,
324 "mtu",
325 format!("{}", mtu).as_str(),
326 "add",
327 addr_str.as_str(),
328 "up",
329 ])
330 .spawn();
331 } else {
332 let _= Command::new("ifconfig")
333 .args([name, "mtu", format!("{}", mtu).as_str(), "up"])
334 .spawn();
335 }
336
337 errcode::RESULT_SUCCESS
338}
339
340pub fn get_pnetif_by_name(name: &String) -> Result<netinterface::NetworkInterface, errcode::RESULT> {
341 return netinterface::NetworkInterface::get_interface_by_name(name);
342}
343
344
345#[cfg(windows)]
346pub fn create_tap_if(
347 name: &str,
348 mtu: u16,
349 ip_addrs: &[ipnetwork::IpNetwork],
350 _pkt_info: bool,
351) -> errcode::RESULT {
352 let mtu_cmd = format!("mtu={}", mtu);
353 if ip_addrs.len() > 0 {
354 match Command::new("netsh")
355 .args([
356 "interface",
357 "ip",
358 "set",
359 "address",
360 name,
361 "static",
362 format!("{}", ip_addrs[0].ip()).as_str(),
363 format!("{}", ip_addrs[0].mask()).as_str(),
364 ])
365 .spawn() {
366 Ok(_)=>(),
367 Err(_)=> {
368 return errcode::ERROR_OS_CALL_FAILED
369 },
370 }
371
372 match Command::new("netsh")
373 .args([
374 "interface",
375 "ip",
376 "set",
377 "interface",
378 name,
379 mtu_cmd.as_str(),
380 ])
381 .spawn() {
382 Ok(_)=>(),
383 Err(_)=> return errcode::ERROR_OS_CALL_FAILED,
384 }
385 } else {
386 match Command::new("netsh")
387 .args([name, "mtu", format!("{}", mtu).as_str(), "up"])
388 .spawn() {
389 Ok(_)=>(),
390 Err(_)=> return errcode::ERROR_OS_CALL_FAILED,
391 }
392 }
393
394 errcode::RESULT_SUCCESS
395}
396