Files
RedBear-OS/netstack/src/link/mod.rs
T
Red Bear OS 19199096c5 promiscuous: per-interface toggle via netcfg (ip link set promisc)
LinkDevice trait gains is_promiscuous() and set_promiscuous().
EthernetLink stores promiscuous flag (default: false).
Receive path bypasses MAC check when promiscuous enabled —
captures all frames regardless of destination MAC.

netcfg/ifaces/eth0/promiscuous rw:
  cat /scheme/netcfg/ifaces/eth0/promiscuous  →  'off' or 'on'
  echo on  > .../promiscuous  →  enable promiscuous mode
  echo off > .../promiscuous  →  disable

Accepts: on/off/1/0/yes/no/true/false.

Mirrors Linux 'ip link set dev promisc on/off'.
Required for packet capture tools that need to see all traffic.
2026-07-08 19:03:53 +03:00

139 lines
3.4 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 is_promiscuous(&self) -> bool {
false
}
fn set_promiscuous(&mut self, _enabled: bool) {}
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())
}
}