c899b42d36
LinkDevice trait gains: - add_static_neighbor(ip, mac) → Result<(), String> - remove_neighbor(ip) → bool (true if removed) EthernetLink implements both with permanent entries (expires_at = i64::MAX/2). netcfg/ifaces/eth0/arp/ is now: list → read (existing) stats → read (existing) flush → write (existing) add → write NEW del → write NEW Usage: echo '192.168.1.1 00:11:22:33:44:55' > /scheme/netcfg/ifaces/eth0/arp/add echo '192.168.1.1' > /scheme/netcfg/ifaces/eth0/arp/del echo '10.0.0.0/24 gateway-01 11:22:33:44:55:66' > /scheme/netcfg/ifaces/eth0/arp/add Mirrors Linux 'ip neigh add' / 'ip neigh del'. MAC format accepts both colon (00:11:22:33:44:55) and dash (00-11-22-33-44-55). Unicast MAC validation rejects broadcast/multicast addresses.
133 lines
3.3 KiB
Rust
133 lines
3.3 KiB
Rust
pub mod bond;
|
|
pub mod bridge;
|
|
pub mod ethernet;
|
|
pub mod gre;
|
|
pub mod ipip;
|
|
pub mod loopback;
|
|
pub mod qdisc;
|
|
pub mod stp;
|
|
pub mod tun;
|
|
pub mod vlan;
|
|
pub mod vxlan;
|
|
|
|
use std::rc::Rc;
|
|
|
|
use smoltcp::time::Instant;
|
|
use smoltcp::wire::{EthernetAddress, IpAddress, IpCidr};
|
|
|
|
/// Represent a link layer device (eth0, loopback...)
|
|
pub trait LinkDevice {
|
|
/// Send the given packet to the machine with the `next_hop` ip address
|
|
/// This method cannot fail so it's the implementor responsability
|
|
/// to buffer packets which can't be sent immediatly or decide to
|
|
/// drop them if necessary
|
|
fn send(&mut self, next_hop: IpAddress, packet: &[u8], now: Instant);
|
|
|
|
/// Returns None if nothing is received.
|
|
/// Returns an Ip packet otherwise
|
|
fn recv(&mut self, now: Instant) -> Option<&[u8]>;
|
|
|
|
/// Returns the LinkDevice display name used to refer to it and for lookups
|
|
fn name(&self) -> &Rc<str>;
|
|
|
|
/// Returns wether this device have packets pending
|
|
fn can_recv(&self) -> bool;
|
|
|
|
fn mac_address(&self) -> Option<EthernetAddress>;
|
|
fn set_mac_address(&mut self, addr: EthernetAddress);
|
|
|
|
fn ip_address(&self) -> Option<IpCidr>;
|
|
fn set_ip_address(&mut self, addr: IpCidr);
|
|
|
|
fn arp_table(&self) -> String {
|
|
String::new()
|
|
}
|
|
|
|
fn flush_arp(&mut self) {}
|
|
|
|
fn arp_stats(&self) -> String {
|
|
String::new()
|
|
}
|
|
|
|
fn qdisc_info(&self) -> String {
|
|
"none\n".to_string()
|
|
}
|
|
|
|
fn set_qdisc(&mut self, _kind: &str) -> Result<(), String> {
|
|
Err("qdisc configuration not supported on this device\n".to_string())
|
|
}
|
|
|
|
fn add_static_neighbor(&mut self, _ip: IpAddress, _mac: [u8; 6]) -> Result<(), String> {
|
|
Err("static ARP entry not supported on this device\n".to_string())
|
|
}
|
|
|
|
fn remove_neighbor(&mut self, _ip: IpAddress) -> bool {
|
|
false
|
|
}
|
|
|
|
fn mtu(&self) -> usize {
|
|
1500
|
|
}
|
|
|
|
fn set_mtu(&mut self, _mtu: usize) {}
|
|
|
|
fn is_enabled(&self) -> bool {
|
|
true
|
|
}
|
|
|
|
fn set_enabled(&mut self, _enabled: bool) {}
|
|
|
|
fn link_state(&self) -> &'static str {
|
|
"unknown"
|
|
}
|
|
|
|
fn statistics(&self) -> Stats {
|
|
Stats::default()
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Default, Clone, Copy)]
|
|
pub struct Stats {
|
|
pub rx_bytes: u64,
|
|
pub rx_packets: u64,
|
|
pub tx_bytes: u64,
|
|
pub tx_packets: u64,
|
|
pub rx_errors: u64,
|
|
pub tx_errors: u64,
|
|
pub rx_dropped: u64,
|
|
pub tx_dropped: u64,
|
|
}
|
|
|
|
#[derive(Default)]
|
|
pub struct DeviceList {
|
|
inner: Vec<Box<dyn LinkDevice>>,
|
|
}
|
|
|
|
impl DeviceList {
|
|
pub fn push<T: LinkDevice + 'static>(&mut self, dev: T) {
|
|
self.inner.push(Box::new(dev))
|
|
}
|
|
|
|
pub fn get(&self, device_name: &str) -> Option<&dyn LinkDevice> {
|
|
self.inner
|
|
.iter()
|
|
.find(|dev| dev.name().as_ref() == device_name)
|
|
.map(|device| device.as_ref())
|
|
}
|
|
|
|
pub fn get_mut(&mut self, device_name: &str) -> Option<&mut (dyn LinkDevice + 'static)> {
|
|
self.inner
|
|
.iter_mut()
|
|
.find(|dev| dev.name().as_ref() == device_name)
|
|
.map(|device| device.as_mut())
|
|
}
|
|
|
|
pub fn iter(&self) -> impl Iterator<Item = &(dyn LinkDevice + 'static)> {
|
|
self.inner.iter().map(|b| b.as_ref())
|
|
}
|
|
|
|
pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut (dyn LinkDevice + 'static)> {
|
|
self.inner.iter_mut().map(|b| b.as_mut())
|
|
}
|
|
}
|