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:
+98
-16
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user