Add rust kext to the mono repo

This commit is contained in:
Vladimir Stoilov
2024-04-29 17:04:08 +03:00
parent 740ef1ad32
commit b0f664047b
98 changed files with 13811 additions and 84 deletions

193
windows_kext/protocol/Cargo.lock generated Normal file
View File

@@ -0,0 +1,193 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "autocfg"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "getrandom"
version = "0.2.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5"
dependencies = [
"cfg-if",
"libc",
"wasi",
]
[[package]]
name = "libc"
version = "0.2.153"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd"
[[package]]
name = "num"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b05180d69e3da0e530ba2a1dae5110317e49e3b7f3d41be227dc5f92e49ee7af"
dependencies = [
"num-complex",
"num-integer",
"num-iter",
"num-rational",
"num-traits",
]
[[package]]
name = "num-complex"
version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ba157ca0885411de85d6ca030ba7e2a83a28636056c7c699b07c8b6f7383214"
dependencies = [
"num-traits",
]
[[package]]
name = "num-derive"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cfb77679af88f8b125209d354a202862602672222e7f2313fdd6dc349bad4712"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "num-integer"
version = "0.1.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9"
dependencies = [
"autocfg",
"num-traits",
]
[[package]]
name = "num-iter"
version = "0.1.43"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252"
dependencies = [
"autocfg",
"num-integer",
"num-traits",
]
[[package]]
name = "num-rational"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0"
dependencies = [
"autocfg",
"num-integer",
"num-traits",
]
[[package]]
name = "num-traits"
version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c"
dependencies = [
"autocfg",
]
[[package]]
name = "ppv-lite86"
version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
[[package]]
name = "proc-macro2"
version = "1.0.78"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae"
dependencies = [
"unicode-ident",
]
[[package]]
name = "protocol"
version = "0.1.0"
dependencies = [
"num",
"num-derive",
"num-traits",
"rand",
]
[[package]]
name = "quote"
version = "1.0.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef"
dependencies = [
"proc-macro2",
]
[[package]]
name = "rand"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
dependencies = [
"libc",
"rand_chacha",
"rand_core",
]
[[package]]
name = "rand_chacha"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
dependencies = [
"ppv-lite86",
"rand_core",
]
[[package]]
name = "rand_core"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
dependencies = [
"getrandom",
]
[[package]]
name = "syn"
version = "2.0.48"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "unicode-ident"
version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
[[package]]
name = "wasi"
version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"

View File

@@ -0,0 +1,14 @@
[package]
name = "protocol"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
num = { version = "0.4", default-features = false }
num-derive = { version = "0.4", default-features = false }
num-traits = { version = "0.2", default-features = false }
[dev-dependencies]
rand = "0.8.5"

View File

@@ -0,0 +1,4 @@
# Protocol
Defines protocol that communicates with `kext_interface` / Portmaster.

View File

@@ -0,0 +1,158 @@
// Commands from user space
use num_derive::FromPrimitive;
use num_traits::FromPrimitive;
#[repr(u8)]
#[derive(Clone, Copy, FromPrimitive)]
#[rustfmt::skip]
pub enum CommandType {
Shutdown = 0,
Verdict = 1,
UpdateV4 = 2,
UpdateV6 = 3,
ClearCache = 4,
GetLogs = 5,
GetBandwidthStats = 6,
PrintMemoryStats = 7,
CleanEndedConnections = 8,
}
#[repr(C, packed)]
pub struct Command {
pub command_type: CommandType,
value: [u8; 0],
}
#[repr(C, packed)]
#[derive(Debug, PartialEq, Eq)]
pub struct Verdict {
pub id: u64,
pub verdict: u8,
}
#[repr(C, packed)]
#[derive(Debug, PartialEq, Eq)]
pub struct UpdateV4 {
pub protocol: u8,
pub local_address: [u8; 4],
pub local_port: u16,
pub remote_address: [u8; 4],
pub remote_port: u16,
pub verdict: u8,
}
#[repr(C, packed)]
#[derive(Debug, PartialEq, Eq)]
pub struct UpdateV6 {
pub protocol: u8,
pub local_address: [u8; 16],
pub local_port: u16,
pub remote_address: [u8; 16],
pub remote_port: u16,
pub verdict: u8,
}
pub fn parse_type(bytes: &[u8]) -> Option<CommandType> {
FromPrimitive::from_u8(bytes[0])
}
pub fn parse_verdict(bytes: &[u8]) -> &Verdict {
as_type(bytes)
}
pub fn parse_update_v4(bytes: &[u8]) -> &UpdateV4 {
as_type(bytes)
}
pub fn parse_update_v6(bytes: &[u8]) -> &UpdateV6 {
as_type(bytes)
}
fn as_type<T>(bytes: &[u8]) -> &T {
let ptr: *const u8 = &bytes[0];
let t_ptr: *const T = ptr as _;
unsafe { t_ptr.as_ref().unwrap() }
}
#[cfg(test)]
use std::fs::File;
#[cfg(test)]
use std::io::Read;
#[cfg(test)]
use std::mem::size_of;
#[cfg(test)]
use std::panic;
#[test]
fn test_go_command_file() {
let mut file = File::open("../kext_interface/go_command_test.bin").unwrap();
loop {
let mut command: [u8; 1] = [0];
let bytes_count = file.read(&mut command).unwrap();
if bytes_count == 0 {
return;
}
if let Some(command) = parse_type(&command) {
match command {
CommandType::Shutdown => {}
CommandType::Verdict => {
let mut buf = [0; size_of::<Verdict>()];
let bytes_count = file.read(&mut buf).unwrap();
if bytes_count != size_of::<Verdict>() {
panic!("unexpected bytes count")
}
assert_eq!(parse_verdict(&buf), &Verdict { id: 1, verdict: 2 })
}
CommandType::UpdateV4 => {
let mut buf = [0; size_of::<UpdateV4>()];
let bytes_count = file.read(&mut buf).unwrap();
if bytes_count != size_of::<UpdateV4>() {
panic!("unexpected bytes count")
}
assert_eq!(
parse_update_v4(&buf),
&UpdateV4 {
protocol: 1,
local_address: [1, 2, 3, 4],
local_port: 2,
remote_address: [2, 3, 4, 5],
remote_port: 3,
verdict: 4
}
)
}
CommandType::UpdateV6 => {
let mut buf = [0; size_of::<UpdateV6>()];
let bytes_count = file.read(&mut buf).unwrap();
if bytes_count != size_of::<UpdateV6>() {
panic!("unexpected bytes count")
}
assert_eq!(
parse_update_v6(&buf),
&UpdateV6 {
protocol: 1,
local_address: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16],
local_port: 2,
remote_address: [
2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17
],
remote_port: 3,
verdict: 4
}
)
}
CommandType::ClearCache => {}
CommandType::GetLogs => {}
CommandType::GetBandwidthStats => {}
CommandType::PrintMemoryStats => {}
CommandType::CleanEndedConnections => {}
}
} else {
panic!("Unknown command: {}", command[0]);
}
}
}

View File

@@ -0,0 +1,552 @@
use alloc::vec::Vec;
#[repr(u8)]
#[derive(Clone, Copy)]
enum InfoType {
LogLine = 0,
ConnectionIpv4 = 1,
ConnectionIpv6 = 2,
ConnectionEndEventV4 = 3,
ConnectionEndEventV6 = 4,
BandwidthStatsV4 = 5,
BandwidthStatsV6 = 6,
}
// Fallow this pattern when adding new packets: [InfoType: u8, data_size_in_bytes: u32, data: ...]
trait PushBytes {
fn push(self, vec: &mut Vec<u8>);
}
impl PushBytes for u8 {
fn push(self, vec: &mut Vec<u8>) {
vec.push(self);
}
}
impl PushBytes for InfoType {
fn push(self, vec: &mut Vec<u8>) {
vec.push(self as u8);
}
}
impl PushBytes for u16 {
fn push(self, vec: &mut Vec<u8>) {
vec.extend_from_slice(&u16::to_le_bytes(self));
}
}
impl PushBytes for u32 {
fn push(self, vec: &mut Vec<u8>) {
vec.extend_from_slice(&u32::to_le_bytes(self));
}
}
impl PushBytes for u64 {
fn push(self, vec: &mut Vec<u8>) {
vec.extend_from_slice(&u64::to_le_bytes(self));
}
}
impl PushBytes for usize {
fn push(self, vec: &mut Vec<u8>) {
vec.extend_from_slice(&usize::to_le_bytes(self));
}
}
impl PushBytes for [u8; 4] {
fn push(self, vec: &mut Vec<u8>) {
vec.extend_from_slice(&self);
}
}
impl PushBytes for [u8; 16] {
fn push(self, vec: &mut Vec<u8>) {
vec.extend_from_slice(&self);
}
}
impl PushBytes for &[u8] {
fn push(self, vec: &mut Vec<u8>) {
vec.extend_from_slice(self);
}
}
macro_rules! push_bytes {
($vec:expr,$value:expr) => {
PushBytes::push($value, $vec);
};
}
macro_rules! get_combined_size{
($($a:expr),*)=>{{0 $(+core::mem::size_of_val(&$a))*}}
}
pub struct Info(Vec<u8>);
impl Info {
fn new(info_type: InfoType, size: usize) -> Self {
let mut vec = Vec::with_capacity(size + 5); // +1 for the info type +4 for the size.
push_bytes!(&mut vec, info_type);
push_bytes!(&mut vec, size as u32);
Self(vec)
}
fn with_capacity(info_type: InfoType, capacity: usize) -> Self {
let mut vec = Vec::with_capacity(capacity + 5); // +1 for the info type + 4 for the size.
push_bytes!(&mut vec, info_type);
push_bytes!(&mut vec, 0 as u32);
Self(vec)
}
#[cfg(test)]
fn assert_size(&self) {
let size = u32::from_le_bytes([self.0[1], self.0[2], self.0[3], self.0[4]]) as usize;
assert_eq!(size, self.0.len() - 5);
}
fn update_size(&mut self) {
let size = self.0.len() - 5;
let bytes = &mut self.0;
bytes[1] = size as u8;
bytes[2] = (size >> 8) as u8;
bytes[3] = (size >> 16) as u8;
bytes[4] = (size >> 24) as u8;
}
pub fn as_bytes(&self) -> &[u8] {
return self.0.as_slice();
}
}
impl core::fmt::Write for Info {
fn write_str(&mut self, s: &str) -> Result<(), core::fmt::Error> {
const MAX_CAPACITY: usize = 500;
let space_left = self.0.capacity() - self.0.len();
if s.len() > space_left {
if self.0.capacity() < MAX_CAPACITY {
self.0.reserve(MAX_CAPACITY);
} else {
return Ok(());
}
}
self.0.extend_from_slice(s.as_bytes());
self.update_size();
Ok(())
}
}
pub fn connection_info_v4(
id: u64,
process_id: u64,
direction: u8,
protocol: u8,
local_ip: [u8; 4],
remote_ip: [u8; 4],
local_port: u16,
remote_port: u16,
payload_layer: u8,
payload: &[u8],
) -> Info {
let mut size = get_combined_size!(
id,
process_id,
direction,
protocol,
local_ip,
remote_ip,
local_port,
remote_port,
payload_layer,
payload.len() as u32
);
size += payload.len();
let mut info = Info::new(InfoType::ConnectionIpv4, size);
let vec = &mut info.0;
push_bytes!(vec, id);
push_bytes!(vec, process_id);
push_bytes!(vec, direction);
push_bytes!(vec, protocol);
push_bytes!(vec, local_ip);
push_bytes!(vec, remote_ip);
push_bytes!(vec, local_port);
push_bytes!(vec, remote_port);
push_bytes!(vec, payload_layer);
push_bytes!(vec, payload.len() as u32);
push_bytes!(vec, payload);
info
}
pub fn connection_info_v6(
id: u64,
process_id: u64,
direction: u8,
protocol: u8,
local_ip: [u8; 16],
remote_ip: [u8; 16],
local_port: u16,
remote_port: u16,
payload_layer: u8,
payload: &[u8],
) -> Info {
let mut size = get_combined_size!(
id,
process_id,
direction,
protocol,
local_ip,
remote_ip,
local_port,
remote_port,
payload_layer,
payload.len() as u32
);
size += payload.len();
let mut info = Info::new(InfoType::ConnectionIpv6, size);
let vec = &mut info.0;
push_bytes!(vec, id);
push_bytes!(vec, process_id);
push_bytes!(vec, direction);
push_bytes!(vec, protocol);
push_bytes!(vec, local_ip);
push_bytes!(vec, remote_ip);
push_bytes!(vec, local_port);
push_bytes!(vec, remote_port);
push_bytes!(vec, payload_layer);
push_bytes!(vec, payload.len() as u32);
if !payload.is_empty() {
push_bytes!(vec, payload);
}
info
}
pub fn connection_end_event_v4_info(
process_id: u64,
direction: u8,
protocol: u8,
local_ip: [u8; 4],
remote_ip: [u8; 4],
local_port: u16,
remote_port: u16,
) -> Info {
let size = get_combined_size!(
process_id,
direction,
protocol,
local_ip,
remote_ip,
local_port,
remote_port
);
let mut info = Info::new(InfoType::ConnectionEndEventV4, size);
let vec = &mut info.0;
push_bytes!(vec, process_id);
push_bytes!(vec, direction);
push_bytes!(vec, protocol);
push_bytes!(vec, local_ip);
push_bytes!(vec, remote_ip);
push_bytes!(vec, local_port);
push_bytes!(vec, remote_port);
info
}
pub fn connection_end_event_v6_info(
process_id: u64,
direction: u8,
protocol: u8,
local_ip: [u8; 16],
remote_ip: [u8; 16],
local_port: u16,
remote_port: u16,
) -> Info {
let size = get_combined_size!(
process_id,
direction,
protocol,
local_ip,
remote_ip,
local_port,
remote_port
);
let mut info = Info::new(InfoType::ConnectionEndEventV6, size);
let vec = &mut info.0;
push_bytes!(vec, process_id);
push_bytes!(vec, direction);
push_bytes!(vec, protocol);
push_bytes!(vec, local_ip);
push_bytes!(vec, remote_ip);
push_bytes!(vec, local_port);
push_bytes!(vec, remote_port);
info
}
#[repr(u8)]
#[derive(Clone, Copy)]
pub enum Severity {
Trace = 1,
Debug = 2,
Info = 3,
Warning = 4,
Error = 5,
Critical = 6,
Disabled = 7,
}
// pub fn log_line(severity: Severity, prefix: String, line: String) -> Info {
// let mut size = get_combined_size!(severity);
// size += prefix.len() + line.len();
// let mut info = Info::new(InfoType::LogLine, size);
// let vec = &mut info.0;
// push_bytes!(vec, severity as u8);
// push_bytes!(vec, prefix.as_bytes());
// push_bytes!(vec, line.as_bytes());
// info
// }
pub fn log_line(severity: Severity, capacity: usize) -> Info {
let mut info = Info::with_capacity(InfoType::LogLine, capacity);
let vec = &mut info.0;
push_bytes!(vec, severity as u8);
info
}
// Special struct for Bandwidth stats
pub struct BandwidthValueV4 {
pub local_ip: [u8; 4],
pub local_port: u16,
pub remote_ip: [u8; 4],
pub remote_port: u16,
pub transmitted_bytes: u64,
pub received_bytes: u64,
}
impl BandwidthValueV4 {
fn get_size(&self) -> usize {
get_combined_size!(
self.local_ip,
self.local_port,
self.remote_ip,
self.remote_port,
self.transmitted_bytes,
self.received_bytes
)
}
}
impl PushBytes for BandwidthValueV4 {
fn push(self, vec: &mut Vec<u8>) {
push_bytes!(vec, self.local_ip);
push_bytes!(vec, self.local_port);
push_bytes!(vec, self.remote_ip);
push_bytes!(vec, self.remote_port);
push_bytes!(vec, self.transmitted_bytes);
push_bytes!(vec, self.received_bytes);
}
}
pub struct BandwidthValueV6 {
pub local_ip: [u8; 16],
pub local_port: u16,
pub remote_ip: [u8; 16],
pub remote_port: u16,
pub transmitted_bytes: u64,
pub received_bytes: u64,
}
impl BandwidthValueV6 {
fn get_size(&self) -> usize {
get_combined_size!(
self.local_ip,
self.local_port,
self.remote_ip,
self.remote_port,
self.transmitted_bytes,
self.received_bytes
)
}
}
impl PushBytes for BandwidthValueV6 {
fn push(self, vec: &mut Vec<u8>) {
push_bytes!(vec, self.local_ip);
push_bytes!(vec, self.local_port);
push_bytes!(vec, self.remote_ip);
push_bytes!(vec, self.remote_port);
push_bytes!(vec, self.transmitted_bytes);
push_bytes!(vec, self.received_bytes);
}
}
pub fn bandiwth_stats_array_v4(protocol: u8, values: Vec<BandwidthValueV4>) -> Info {
let mut size = get_combined_size!(protocol, values.len() as u32);
if !values.is_empty() {
size += values[0].get_size() * values.len();
}
let mut info = Info::new(InfoType::BandwidthStatsV4, size);
let vec = &mut info.0;
push_bytes!(vec, protocol);
push_bytes!(vec, values.len() as u32);
for v in values {
push_bytes!(vec, v);
}
info
}
pub fn bandiwth_stats_array_v6(protocol: u8, values: Vec<BandwidthValueV6>) -> Info {
let mut size = get_combined_size!(protocol, values.len() as u32);
if !values.is_empty() {
size += values[0].get_size() * values.len();
}
let mut info = Info::new(InfoType::BandwidthStatsV6, size);
let vec = &mut info.0;
push_bytes!(vec, protocol);
push_bytes!(vec, values.len() as u32);
for v in values {
push_bytes!(vec, v);
}
info
}
#[cfg(test)]
use std::fs::File;
#[cfg(test)]
use std::io::Write;
#[cfg(test)]
use rand::seq::SliceRandom;
#[test]
fn generate_test_info_file() -> Result<(), std::io::Error> {
let mut file = File::create("rust_info_test.bin")?;
let enums = [
InfoType::LogLine,
InfoType::ConnectionIpv4,
InfoType::ConnectionIpv6,
InfoType::ConnectionEndEventV4,
InfoType::ConnectionEndEventV6,
InfoType::BandwidthStatsV4,
InfoType::BandwidthStatsV6,
];
let mut selected: Vec<InfoType> = Vec::with_capacity(1000);
let mut rng = rand::thread_rng();
for _ in 0..selected.capacity() {
selected.push(enums.choose(&mut rng).unwrap().clone());
}
for value in selected {
file.write_all(&match value {
InfoType::LogLine => {
let mut info = log_line(Severity::Trace, 5);
use std::fmt::Write;
_ = write!(info, "prefix: test log");
info.assert_size();
info.0
}
InfoType::ConnectionIpv4 => {
let info = connection_info_v4(
1,
2,
3,
4,
[1, 2, 3, 4],
[2, 3, 4, 5],
5,
6,
7,
&[1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
);
info.assert_size();
info.0
}
InfoType::ConnectionIpv6 => {
let info = connection_info_v6(
1,
2,
3,
4,
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16],
[2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17],
5,
6,
7,
&[1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
);
info.assert_size();
info.0
}
InfoType::ConnectionEndEventV4 => {
let info = connection_end_event_v4_info(1, 2, 3, [1, 2, 3, 4], [2, 3, 4, 5], 4, 5);
info.assert_size();
info.0
}
InfoType::ConnectionEndEventV6 => {
let info = connection_end_event_v6_info(
1,
2,
3,
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16],
[2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17],
4,
5,
);
info.assert_size();
info.0
}
InfoType::BandwidthStatsV4 => {
let mut vec = Vec::new();
vec.push(BandwidthValueV4 {
local_ip: [1, 2, 3, 4],
local_port: 1,
remote_ip: [2, 3, 4, 5],
remote_port: 2,
transmitted_bytes: 3,
received_bytes: 4,
});
vec.push(BandwidthValueV4 {
local_ip: [1, 2, 3, 4],
local_port: 5,
remote_ip: [2, 3, 4, 5],
remote_port: 6,
transmitted_bytes: 7,
received_bytes: 8,
});
let info = bandiwth_stats_array_v4(1, vec);
info.assert_size();
info.0
}
InfoType::BandwidthStatsV6 => {
let mut vec = Vec::new();
vec.push(BandwidthValueV6 {
local_ip: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16],
local_port: 1,
remote_ip: [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17],
remote_port: 2,
transmitted_bytes: 3,
received_bytes: 4,
});
vec.push(BandwidthValueV6 {
local_ip: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16],
local_port: 5,
remote_ip: [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17],
remote_port: 6,
transmitted_bytes: 7,
received_bytes: 8,
});
let info = bandiwth_stats_array_v6(1, vec);
info.assert_size();
info.0
}
})?;
}
return Ok(());
}

View File

@@ -0,0 +1,5 @@
#![cfg_attr(not(test), no_std)]
extern crate alloc;
pub mod command;
pub mod info;