Skip to content

Additions from the managarm port #1

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Mar 12, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 29 additions & 7 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ use simple_endian::BigEndian;
/// [RFC 8200 § 2]: https://www.rfc-editor.org/rfc/rfc791#section-3.2
pub const ADDR_SIZE: usize = 4;

pub const DHCP_SERVER_PORT: u16 = 67;
pub const DHCP_CLIENT_PORT: u16 = 68;

#[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Default)]
pub struct Ipv4Addr(pub [u8; ADDR_SIZE]);

Expand Down Expand Up @@ -59,7 +62,6 @@ enum HType {
Ethernet = 1u8.swap_bytes(),
}

#[derive(Debug, Clone)]
#[repr(C, packed)]
struct Header {
op: DhcpType,
Expand Down Expand Up @@ -368,13 +370,26 @@ pub fn cvt(t: i32) -> io::Result<i32> {
}
}

fn get_nicname<'a>() -> &'a str {
static CACHED: Once<String> = Once::new();

CACHED.call_once(|| {
let nic_name = std::env::args().nth(1).unwrap_or(DEFAULT_NIC.to_string());

get_index(&nic_name)
.unwrap_or_else(|nic_name| panic!("[ DHCPD ] (EE) invalid NIC name {}", nic_name));

nic_name
})
}

fn get_macaddress<'a>() -> &'a [u8; 6] {
static CACHED: Once<[u8; 6]> = Once::new();
CACHED
.try_call_once(|| unsafe {
let fd = cvt(libc::socket(libc::AF_INET, libc::SOCK_DGRAM, 0))?;

let macaddr = IfReq::new(DEFAULT_NIC);
let macaddr = IfReq::new(get_nicname());
cvt(libc::ioctl(fd, libc::SIOCGIFHWADDR, &macaddr))?;

Ok::<[u8; 6], io::Error>(macaddr.macaddr())
Expand Down Expand Up @@ -467,9 +482,16 @@ fn configure(interface: &str, ip: Ipv4Addr, subnet_mask: Ipv4Addr) -> io::Result

const DEFAULT_NIC: &str = "eth0"; // FIXME: retrieve the default NIC from the kernel

fn get_index(nic: &str) -> io::Result<libc::c_uint> {
let ifname = std::ffi::CString::new(nic)?;
match unsafe { libc::if_nametoindex(ifname.as_ptr()) } {
0 => Err(io::Error::last_os_error()),
index => Ok(index),
}
}

pub fn main() -> Result<(), Box<dyn Error>> {
let socket = UdpSocket::bind(("0.0.0.0", 68))?;
socket.connect(("255.255.255.255", 67))?;
let socket = UdpSocket::bind(("0.0.0.0", DHCP_CLIENT_PORT))?;

let mut discover_header = Header::new(HType::Ethernet);
discover_header
Expand All @@ -479,7 +501,7 @@ pub fn main() -> Result<(), Box<dyn Error>> {
.set_host_name("Aero")
.set_parameter_request_list();

socket.send(discover_header.as_slice())?;
socket.send_to(discover_header.as_slice(), "255.255.255.255:67")?;

let mut offer = Header::new(HType::Ethernet);
socket.recv(offer.as_slice_mut())?;
Expand All @@ -495,7 +517,7 @@ pub fn main() -> Result<(), Box<dyn Error>> {
.set_host_name("Aero")
.set_parameter_request_list();

socket.send(request_header.as_slice())?;
socket.send_to(request_header.as_slice(), "255.255.255.255:67")?;

let mut ack = Header::new(HType::Ethernet);
socket.recv(ack.as_slice_mut())?;
Expand All @@ -519,7 +541,7 @@ pub fn main() -> Result<(), Box<dyn Error>> {
let subnet_mask = subnet_mask.unwrap();
let dns = dns.unwrap();

configure(DEFAULT_NIC, ack.your_ip, subnet_mask)?;
configure(get_nicname(), ack.your_ip, subnet_mask)?;

println!("[ DHCPD ] (!!) Configured:");
println!("[ DHCPD ] (!!) IP: {}", ack.your_ip);
Expand Down