5d3a830ce7
- Use EthernetInterfaceBuilder instead of EthernetInterface::new - smoltcp removed the ArpCache trait in favor of ManagedMap. NB: This breaks the use of loopback and sending packets to yourself.
153 lines
4.1 KiB
Rust
153 lines
4.1 KiB
Rust
#![feature(drain_filter)]
|
|
|
|
extern crate event;
|
|
#[macro_use]
|
|
extern crate log;
|
|
extern crate netutils;
|
|
extern crate smoltcp;
|
|
extern crate syscall;
|
|
|
|
use std::cell::RefCell;
|
|
use std::fs::File;
|
|
use std::os::unix::io::{FromRawFd, RawFd};
|
|
use std::process;
|
|
use std::rc::Rc;
|
|
|
|
use error::{Error, Result};
|
|
use event::EventQueue;
|
|
use scheme::Smolnetd;
|
|
|
|
mod buffer_pool;
|
|
mod device;
|
|
mod error;
|
|
mod logger;
|
|
mod port_set;
|
|
mod scheme;
|
|
|
|
fn run() -> Result<()> {
|
|
use syscall::flag::*;
|
|
|
|
trace!("opening network:");
|
|
let network_fd = syscall::open("network:", O_RDWR | O_NONBLOCK)
|
|
.map_err(|e| Error::from_syscall_error(e, "failed to open network:"))?
|
|
as RawFd;
|
|
|
|
trace!("opening :ip");
|
|
let ip_fd = syscall::open(":ip", O_RDWR | O_CREAT | O_NONBLOCK)
|
|
.map_err(|e| Error::from_syscall_error(e, "failed to open :ip"))? as RawFd;
|
|
|
|
trace!("opening :udp");
|
|
let udp_fd = syscall::open(":udp", O_RDWR | O_CREAT | O_NONBLOCK)
|
|
.map_err(|e| Error::from_syscall_error(e, "failed to open :udp"))?
|
|
as RawFd;
|
|
|
|
trace!("opening :tcp");
|
|
let tcp_fd = syscall::open(":tcp", O_RDWR | O_CREAT | O_NONBLOCK)
|
|
.map_err(|e| Error::from_syscall_error(e, "failed to open :tcp"))?
|
|
as RawFd;
|
|
|
|
trace!("opening :icmp");
|
|
let icmp_fd = syscall::open(":icmp", O_RDWR | O_CREAT | O_NONBLOCK)
|
|
.map_err(|e| Error::from_syscall_error(e, "failed to open :icmp"))?
|
|
as RawFd;
|
|
|
|
let time_path = format!("time:{}", syscall::CLOCK_MONOTONIC);
|
|
let time_fd = syscall::open(&time_path, syscall::O_RDWR)
|
|
.map_err(|e| Error::from_syscall_error(e, "failed to open time:"))?
|
|
as RawFd;
|
|
|
|
let (network_file, ip_file, time_file, udp_file, tcp_file, icmp_file) = unsafe {
|
|
(
|
|
File::from_raw_fd(network_fd),
|
|
File::from_raw_fd(ip_fd),
|
|
File::from_raw_fd(time_fd),
|
|
File::from_raw_fd(udp_fd),
|
|
File::from_raw_fd(tcp_fd),
|
|
File::from_raw_fd(icmp_fd),
|
|
)
|
|
};
|
|
|
|
let smolnetd = Rc::new(RefCell::new(Smolnetd::new(
|
|
network_file,
|
|
ip_file,
|
|
udp_file,
|
|
tcp_file,
|
|
icmp_file,
|
|
time_file,
|
|
)));
|
|
|
|
let mut event_queue = EventQueue::<(), Error>::new()
|
|
.map_err(|e| Error::from_io_error(e, "failed to create event queue"))?;
|
|
|
|
syscall::setrens(0, 0).expect("smolnetd: failed to enter null namespace");
|
|
|
|
let smolnetd_ = Rc::clone(&smolnetd);
|
|
|
|
event_queue
|
|
.add(network_fd, move |_| {
|
|
smolnetd_.borrow_mut().on_network_scheme_event()
|
|
})
|
|
.map_err(|e| {
|
|
Error::from_io_error(e, "failed to listen to network events")
|
|
})?;
|
|
|
|
let smolnetd_ = Rc::clone(&smolnetd);
|
|
|
|
event_queue
|
|
.add(ip_fd, move |_| smolnetd_.borrow_mut().on_ip_scheme_event())
|
|
.map_err(|e| Error::from_io_error(e, "failed to listen to ip events"))?;
|
|
|
|
let smolnetd_ = Rc::clone(&smolnetd);
|
|
|
|
event_queue
|
|
.add(
|
|
udp_fd,
|
|
move |_| smolnetd_.borrow_mut().on_udp_scheme_event(),
|
|
)
|
|
.map_err(|e| {
|
|
Error::from_io_error(e, "failed to listen to udp events")
|
|
})?;
|
|
|
|
let smolnetd_ = Rc::clone(&smolnetd);
|
|
|
|
event_queue
|
|
.add(
|
|
tcp_fd,
|
|
move |_| smolnetd_.borrow_mut().on_tcp_scheme_event(),
|
|
)
|
|
.map_err(|e| {
|
|
Error::from_io_error(e, "failed to listen to tcp events")
|
|
})?;
|
|
|
|
let smolnetd_ = Rc::clone(&smolnetd);
|
|
|
|
event_queue
|
|
.add(icmp_fd, move |_| {
|
|
smolnetd_.borrow_mut().on_icmp_scheme_event()
|
|
})
|
|
.map_err(|e| {
|
|
Error::from_io_error(e, "failed to listen to icmp events")
|
|
})?;
|
|
|
|
event_queue
|
|
.add(time_fd, move |_| smolnetd.borrow_mut().on_time_event())
|
|
.map_err(|e| {
|
|
Error::from_io_error(e, "failed to listen to time events")
|
|
})?;
|
|
|
|
event_queue.trigger_all(0)?;
|
|
|
|
event_queue.run()
|
|
}
|
|
|
|
fn main() {
|
|
if unsafe { syscall::clone(0).unwrap() } == 0 {
|
|
logger::init_logger();
|
|
|
|
if let Err(err) = run() {
|
|
error!("smoltcpd: {}", err);
|
|
process::exit(1);
|
|
}
|
|
}
|
|
}
|