renet/examples/dhcp_client.rs

101 lines
3.8 KiB
Rust

mod utils;
use std::collections::BTreeMap;
use std::os::unix::io::AsRawFd;
use smoltcp::phy::wait as phy_wait;
use smoltcp::wire::{EthernetAddress, Ipv4Address, IpCidr, Ipv4Cidr};
use smoltcp::iface::{NeighborCache, EthernetInterfaceBuilder, Routes};
use smoltcp::socket::{SocketSet, RawSocketBuffer, RawPacketMetadata};
use smoltcp::time::Instant;
use smoltcp::dhcp::Dhcpv4Client;
fn main() {
#[cfg(feature = "log")]
utils::setup_logging("");
let (mut opts, mut free) = utils::create_options();
utils::add_tap_options(&mut opts, &mut free);
utils::add_middleware_options(&mut opts, &mut free);
let mut matches = utils::parse_options(&opts, free);
let device = utils::parse_tap_options(&mut matches);
let fd = device.as_raw_fd();
let device = utils::parse_middleware_options(&mut matches, device, /*loopback=*/false);
let neighbor_cache = NeighborCache::new(BTreeMap::new());
let ethernet_addr = EthernetAddress([0x02, 0x00, 0x00, 0x00, 0x00, 0x01]);
let ip_addrs = [IpCidr::new(Ipv4Address::UNSPECIFIED.into(), 0)];
let mut routes_storage = [None; 1];
let routes = Routes::new(&mut routes_storage[..]);
let mut iface = EthernetInterfaceBuilder::new(device)
.ethernet_addr(ethernet_addr)
.neighbor_cache(neighbor_cache)
.ip_addrs(ip_addrs)
.routes(routes)
.finalize();
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 mut dhcp = Dhcpv4Client::new(&mut sockets, dhcp_rx_buffer, dhcp_tx_buffer, Instant::now());
let mut prev_cidr = Ipv4Cidr::new(Ipv4Address::UNSPECIFIED, 0);
loop {
let timestamp = Instant::now();
iface.poll(&mut sockets, timestamp)
.map(|_| ())
.unwrap_or_else(|e| println!("Poll: {:?}", e));
let config = dhcp.poll(&mut iface, &mut sockets, timestamp)
.unwrap_or_else(|e| {
println!("DHCP: {:?}", e);
None
});
config.map(|config| {
println!("DHCP config: {:?}", 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;
println!("Assigned a new IPv4 address: {}", 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| {
println!("Default gateway: {}", default_route.via_router);
});
});
if config.dns_servers.iter().any(|s| s.is_some()) {
println!("DNS servers:");
for dns_server in config.dns_servers.iter().filter_map(|s| *s) {
println!("- {}", dns_server);
}
}
});
let mut timeout = dhcp.next_poll(timestamp);
iface.poll_delay(&sockets, timestamp)
.map(|sockets_timeout| timeout = sockets_timeout);
phy_wait(fd, Some(timeout))
.unwrap_or_else(|e| println!("Wait: {:?}", e));;
}
}