Added support for Classless Static Routes

This commit is contained in:
Xnoe 2022-10-25 23:15:46 +01:00
parent 3ed9374216
commit 6516224e32
Signed by: xnoe
GPG Key ID: 45AC398F44F0DAFE
3 changed files with 43 additions and 4 deletions

2
Cargo.lock generated
View File

@ -13,7 +13,7 @@ dependencies = [
[[package]]
name = "dhcprs"
version = "0.1.2"
version = "0.1.3"
dependencies = [
"eui48",
]

View File

@ -1,6 +1,6 @@
[package]
name = "dhcprs"
version = "0.1.2"
version = "0.1.3"
edition = "2021"
description = "A library for encoding and decoding DHCP/BOOTP packets"
license-file = "LICENSE"

View File

@ -166,10 +166,10 @@ pub enum DHCPOption {
/*// RFC4833
TimezonePOSIX(String), // 100 N IEEE 1003.1 String
TimezoneDB(String), // 101 N Reference to TZ Database
TimezoneDB(String), // 101 N Reference to TZ Database*/
// RFC3442
ClasslessStaticRoute(Vec<(Ipv4Addr, u32, Ipv4Addr)>), // 121 n d1 ... dN r1 r2 r3 r4 d1 ... dN r1 r2 r3 r4*/
ClasslessStaticRoute(Vec<(Ipv4Addr, u8, Ipv4Addr)>), // 121 n d1 ... dN r1 r2 r3 r4 d1 ... dN r1 r2 r3 r4
// Catchall
Option(u8, Vec<u8>),
@ -184,6 +184,12 @@ macro_rules! break_unwrap {
};
}
macro_rules! div_ceil {
($lhs:expr, $rhs:expr) => {
$lhs / $rhs + if $lhs % $rhs != 0 { 1 } else { 0 }
}
}
impl DHCPOption {
pub fn from_bytes(bytes: &[u8]) -> Vec<DHCPOption> {
let mut options: Vec<DHCPOption> = Vec::new();
@ -1230,6 +1236,28 @@ impl DHCPOption {
options.push(DHCPOption::STDAServer(addresses));
}
121 => {
let mut length = break_unwrap!(iterator.next());
let mut routes: Vec<(Ipv4Addr, u8, Ipv4Addr)> = Vec::new();
while length > 0 {
let prefix_length = break_unwrap!(iterator.next());
let descriptor_length = div_ceil!(prefix_length, 8);
let mut prefix_octets: [u8; 4] = [0;4];
for count in 0..descriptor_length {
prefix_octets[count as usize] = break_unwrap!(iterator.next());
}
let router = Ipv4Addr::new(break_unwrap!(iterator.next()),break_unwrap!(iterator.next()),break_unwrap!(iterator.next()),break_unwrap!(iterator.next()));
routes.push((Ipv4Addr::from(prefix_octets), prefix_length, router));
length -= 1 + descriptor_length + 4;
}
options.push(DHCPOption::ClasslessStaticRoute(routes));
}
// Catchall for if we cannot decode the option to a specific enum variant.
n => {
let count = break_unwrap!(iterator.next());
@ -1801,6 +1829,17 @@ impl DHCPOption {
bytes.push(b.len() as u8);
bytes.extend_from_slice(&b);
}
DHCPOption::ClasslessStaticRoute(routes) => {
bytes.push(121);
bytes.push(routes.iter().fold(0, |acc, (_, prefix_length, _)| acc + 1 + div_ceil!(prefix_length, 8) + 4));
for (prefix, prefix_length, router) in routes {
let descriptor_length = div_ceil!(prefix_length, 8);
bytes.push(prefix_length);
bytes.extend_from_slice(&prefix.octets()[..descriptor_length as usize]);
bytes.extend_from_slice(&router.octets());
}
}
}
}