base: apply Red Bear patches on latest upstream/main

251 files: init, acpid, ipcd, netcfg, ihdgd, virtio-gpud, scheme-utils,
inputd, block driver, ptyd, ramfs, randd, initfs bootstrap, path deps,
version +rb0.3.1, author attribution
This commit is contained in:
Red Bear OS
2026-07-11 11:39:24 +03:00
parent 1b17b3fc24
commit bd595851e2
251 changed files with 24641 additions and 5993 deletions
+98 -16
View File
@@ -1,6 +1,7 @@
use crate::link::ethernet::EthernetLink;
use crate::link::LinkDevice;
use crate::link::{loopback::LoopbackDevice, DeviceList};
use crate::observer::{Observer, ObserverRef};
use crate::router::route_table::{RouteTable, Rule};
use crate::router::Router;
use crate::scheme::smoltcp::iface::SocketSet as SmoltcpSocketSet;
@@ -33,19 +34,25 @@ use syscall::Error as SyscallError;
use self::icmp::IcmpScheme;
use self::ip::IpScheme;
use self::netcfg::NetCfgScheme;
use self::netfilter::NetFilterScheme;
use self::tcp::TcpScheme;
use self::tun::TunScheme;
use self::udp::UdpScheme;
use crate::error::{Error, Result};
use crate::filter::{FilterTable, PacketContext, Verdict};
mod icmp;
mod ip;
mod netcfg;
mod netfilter;
mod socket;
mod tcp;
mod tun;
mod udp;
type SocketSet = SmoltcpSocketSet<'static>;
type Interface = Rc<RefCell<SmoltcpInterface>>;
type FilterTableRef = Rc<RefCell<FilterTable>>;
const MAX_DURATION: Duration = Duration::from_micros(u64::MAX);
const MIN_DURATION: Duration = Duration::from_micros(0);
@@ -70,6 +77,10 @@ pub struct Smolnetd {
tcp_scheme: TcpScheme,
icmp_scheme: IcmpScheme,
netcfg_scheme: NetCfgScheme,
netfilter_scheme: NetFilterScheme,
tun_scheme: TunScheme,
filter_table: FilterTableRef,
observer: ObserverRef,
}
impl Smolnetd {
@@ -79,41 +90,66 @@ impl Smolnetd {
pub const MAX_CHECK_TIMEOUT: Duration = Duration::from_millis(500);
pub fn new(
network_file: Fd,
hardware_addr: EthernetAddress,
network_files: Vec<(Fd, EthernetAddress, String)>,
ip_file: Socket,
udp_file: Socket,
tcp_file: Socket,
icmp_file: Socket,
time_file: Fd,
netcfg_file: Socket,
netfilter_file: Socket,
tun_file: Socket,
) -> Result<Smolnetd> {
let protocol_addrs = vec![
//This is a placeholder IP for DHCP
IpCidr::new(IpAddress::v4(0, 0, 0, 0), 8),
IpCidr::new(IpAddress::v4(127, 0, 0, 1), 8),
IpCidr::new(IpAddress::v6(0, 0, 0, 0, 0, 0, 0, 1), 128),
];
let default_gw = Ipv4Address::from_str(getcfg("ip_router").unwrap().trim())
.expect("Can't parse the 'ip_router' cfg.");
// Default gateway from /etc/net/ip_router. If the file is missing
// or malformed, fall back to 0.0.0.0 and emit a warning rather
// than panicking. The route lookup below will return None for
// an invalid gateway, which is the correct degraded behavior.
let default_gw = match getcfg("ip_router") {
Ok(s) => Ipv4Address::from_str(s.trim()).unwrap_or_else(|_| {
log::warn!("smolnetd: invalid ip_router '{}' in cfg, using 0.0.0.0", s);
Ipv4Address::new(0, 0, 0, 0)
}),
Err(e) => {
log::warn!("smolnetd: ip_router not set in cfg ({:?}), using 0.0.0.0", e);
Ipv4Address::new(0, 0, 0, 0)
}
};
let devices = Rc::new(RefCell::new(DeviceList::default()));
let route_table = Rc::new(RefCell::new(RouteTable::default()));
let observer = Observer::new();
let mut network_device = Tracer::new(
Router::new(Rc::clone(&devices), Rc::clone(&route_table)),
Router::new(Rc::clone(&devices), Rc::clone(&route_table), Rc::clone(&observer)),
|_timestamp, printer| trace!("{}", printer),
);
let ip_forward = network_device.get_mut().ip_forward.clone();
let config = Config::new(HardwareAddress::Ip);
let mut iface = SmoltcpInterface::new(config, &mut network_device, Instant::now());
iface.update_ip_addrs(|ip_addrs| ip_addrs.extend(protocol_addrs));
iface
.routes_mut()
.add_default_ipv4_route(default_gw)
.expect("Failed to add default gateway");
// Skip the default route if the gateway is 0.0.0.0 (no gateway
// configured). smoltcp rejects a default route with 0.0.0.0 as
// gateway. Falling back to no default route is correct behavior.
if !default_gw.is_unspecified() {
if let Err(e) = iface
.routes_mut()
.add_default_ipv4_route(default_gw)
{
log::warn!("smolnetd: failed to add default route: {:?}", e);
}
}
let iface = Rc::new(RefCell::new(iface));
let socket_set = Rc::new(RefCell::new(SocketSet::new(vec![])));
let filter_table = Rc::new(RefCell::new(FilterTable::new()));
let loopback = LoopbackDevice::default();
route_table.borrow_mut().insert_rule(Rule::new(
@@ -122,14 +158,26 @@ impl Smolnetd {
Rc::clone(loopback.name()),
"127.0.0.1".parse().unwrap(),
));
let mut eth0 = EthernetLink::new("eth0", unsafe {
File::from_raw_fd(network_file.into_raw() as RawFd)
});
eth0.set_mac_address(hardware_addr);
route_table.borrow_mut().insert_rule(Rule::new(
"::1/128".parse().unwrap(),
None,
Rc::clone(loopback.name()),
"::1".parse().unwrap(),
));
devices.borrow_mut().push(loopback);
devices.borrow_mut().push(eth0);
for (i, (nf, hw_addr, name)) in network_files.into_iter().enumerate() {
let dev_name = if name.is_empty() {
format!("eth{}", i)
} else {
name
};
let mut link = EthernetLink::new(&dev_name, unsafe {
File::from_raw_fd(nf.into_raw() as RawFd)
});
link.set_mac_address(hw_addr);
devices.borrow_mut().push(link);
}
Ok(Smolnetd {
iface: Rc::clone(&iface),
@@ -170,7 +218,18 @@ impl Smolnetd {
netcfg_file,
Rc::clone(&route_table),
Rc::clone(&devices),
Rc::clone(&socket_set),
ip_forward,
Rc::clone(&observer),
Rc::clone(&filter_table),
)?,
netfilter_scheme: NetFilterScheme::new(
netfilter_file,
Rc::clone(&filter_table),
)?,
tun_scheme: TunScheme::new(tun_file, Rc::clone(&devices))?,
filter_table,
observer,
})
}
@@ -215,6 +274,17 @@ impl Smolnetd {
Ok(())
}
pub fn on_netfilter_scheme_event(&mut self) -> Result<()> {
self.netfilter_scheme.on_scheme_event()?;
Ok(())
}
pub fn on_tun_scheme_event(&mut self) -> Result<()> {
self.tun_scheme.on_scheme_event()?;
let _ = self.poll()?;
Ok(())
}
fn schedule_time_event(&mut self, timeout: Duration) -> Result<()> {
let mut time = TimeSpec::default();
if self.time_file.read(&mut time)? < size_of::<TimeSpec>() {
@@ -248,10 +318,22 @@ impl Smolnetd {
self.router_device.get_mut().poll(timestamp);
self.router_device.get_mut().forward_packets(&self.filter_table, timestamp);
// INPUT filter hook: drop packets before smoltcp processing.
// Mirrors Linux's NF_INET_LOCAL_IN hook in iptable_filter.c.
self.router_device.get_mut().filter_input(&self.filter_table, timestamp);
// TODO: Check what if the bool returned by poll can be useful
iface.poll(timestamp, &mut self.router_device, &mut socket_set);
self.router_device.get_mut().dispatch(timestamp);
self.router_device.get_mut().dispatch(timestamp, &self.filter_table);
self.filter_table
.borrow_mut()
.conntrack
.as_mut()
.map(|ct| ct.clean_expired(timestamp));
if !self.router_device.get_ref().can_recv() {
match iface.poll_delay(timestamp, &socket_set) {