mirror of https://github.com/vinc/moros.git
93 lines
3.6 KiB
Rust
93 lines
3.6 KiB
Rust
use alloc::vec;
|
|
use alloc::vec::Vec;
|
|
use alloc::string::ToString;
|
|
use core::time::Duration;
|
|
use crate::{print, kernel, user};
|
|
use smoltcp::dhcp::Dhcpv4Client;
|
|
use smoltcp::socket::{SocketSet, RawSocketBuffer, RawPacketMetadata};
|
|
use smoltcp::time::Instant;
|
|
use smoltcp::wire::{Ipv4Address, IpCidr, Ipv4Cidr};
|
|
|
|
pub fn main(_args: &[&str]) -> user::shell::ExitCode {
|
|
if let Some(ref mut iface) = *kernel::rtl8139::IFACE.lock() {
|
|
let mut iface = iface;
|
|
let mut sockets = SocketSet::new(vec![]);
|
|
let dhcp_rx_buffer = RawSocketBuffer::new(
|
|
[RawPacketMetadata::EMPTY; 1],
|
|
vec![0; 900]
|
|
);
|
|
let dhcp_tx_buffer = RawSocketBuffer::new(
|
|
[RawPacketMetadata::EMPTY; 1],
|
|
vec![0; 600]
|
|
);
|
|
|
|
let timestamp = Instant::from_millis((kernel::clock::clock_monotonic() * 1000.0) as i64);
|
|
let mut dhcp = Dhcpv4Client::new(&mut sockets, dhcp_rx_buffer, dhcp_tx_buffer, timestamp);
|
|
|
|
let mut prev_cidr = match iface.ip_addrs().first() {
|
|
Some(IpCidr::Ipv4(ip_addr)) => ip_addr.clone().into(),
|
|
_ => Ipv4Cidr::new(Ipv4Address::UNSPECIFIED, 0),
|
|
};
|
|
|
|
print!("DHCP Discover transmitted\n");
|
|
let time = kernel::clock::clock_monotonic();
|
|
loop {
|
|
if kernel::clock::clock_monotonic() - time > 60.0 {
|
|
print!("Timeout reached\n");
|
|
return user::shell::ExitCode::CommandError;
|
|
}
|
|
|
|
let timestamp = Instant::from_millis((kernel::clock::clock_monotonic() * 1000.0) as i64);
|
|
iface.poll(&mut sockets, timestamp).map(|_| ()).unwrap_or_else(|e| print!("Error: {:?}\n", e));
|
|
let config = dhcp.poll(&mut iface, &mut sockets, timestamp).unwrap_or_else(|e| {
|
|
print!("DHCP: {:?}\n", e);
|
|
None
|
|
});
|
|
let mut success = false;
|
|
config.map(|config| {
|
|
print!("DHCP Offer received\n");
|
|
//print!("DHCP config: {:?}\n", config);
|
|
match config.address {
|
|
Some(cidr) => if cidr != prev_cidr {
|
|
iface.update_ip_addrs(|addrs| {
|
|
addrs.iter_mut().nth(0).map(|addr| {
|
|
*addr = IpCidr::Ipv4(cidr);
|
|
});
|
|
});
|
|
prev_cidr = cidr;
|
|
print!("Leased: {}\n", cidr);
|
|
}
|
|
_ => {}
|
|
}
|
|
|
|
config.router.map(|router| {
|
|
iface.routes_mut().add_default_ipv4_route(router.into()).unwrap()
|
|
});
|
|
iface.routes_mut().update(|routes_map| {
|
|
routes_map.get(&IpCidr::new(Ipv4Address::UNSPECIFIED.into(), 0)).map(|default_route| {
|
|
print!("Router: {}\n", default_route.via_router);
|
|
});
|
|
});
|
|
|
|
let dns_servers: Vec<_> = config.dns_servers.iter().filter_map(|s| *s).map(|s| s.to_string()).collect();
|
|
if dns_servers.len() > 0 {
|
|
print!("DNS: {}\n", dns_servers.join(", "));
|
|
}
|
|
|
|
success = true;
|
|
});
|
|
|
|
if success {
|
|
return user::shell::ExitCode::CommandSuccessful;
|
|
}
|
|
|
|
let mut timeout = dhcp.next_poll(timestamp);
|
|
iface.poll_delay(&sockets, timestamp).map(|sockets_timeout| timeout = sockets_timeout);
|
|
let wait_duration: Duration = timeout.into();
|
|
kernel::time::sleep(wait_duration.as_secs_f64());
|
|
}
|
|
}
|
|
|
|
user::shell::ExitCode::CommandError
|
|
}
|