parse server name and file name
This commit is contained in:
parent
e189168144
commit
e0cc79198f
66
src/lib.rs
66
src/lib.rs
@ -1,7 +1,8 @@
|
|||||||
|
#![allow(unused)]
|
||||||
use std::{net::Ipv4Addr, path::Path};
|
use std::{net::Ipv4Addr, path::Path};
|
||||||
|
|
||||||
use nom::{
|
use nom::{
|
||||||
bytes::complete::take,
|
bytes::complete::{take, take_until},
|
||||||
number::complete::{be_u16, be_u32, be_u8},
|
number::complete::{be_u16, be_u32, be_u8},
|
||||||
IResult,
|
IResult,
|
||||||
};
|
};
|
||||||
@ -14,15 +15,18 @@ struct DhcpMessage<'a> {
|
|||||||
hops: u8,
|
hops: u8,
|
||||||
transaction_id: u32,
|
transaction_id: u32,
|
||||||
seconds: u16,
|
seconds: u16,
|
||||||
flags: u16,
|
flags: Flags,
|
||||||
client_address: Ipv4Addr,
|
client_address: Ipv4Addr,
|
||||||
server_address: Ipv4Addr,
|
server_address: Ipv4Addr,
|
||||||
gateway_address: Ipv4Addr,
|
gateway_address: Ipv4Addr,
|
||||||
client_hardware_address: &'a [u8],
|
client_hardware_address: &'a [u8],
|
||||||
server_hostname: &'a str,
|
server_name: &'a str,
|
||||||
boot_file_name: &'a Path,
|
file_name: &'a Path,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct Flags(u16);
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
enum Operation {
|
enum Operation {
|
||||||
Request = 1,
|
Request = 1,
|
||||||
@ -61,6 +65,10 @@ fn parse_dhcp_operation(i: &[u8]) -> IResult<&[u8], Operation> {
|
|||||||
be_u8(i).map(|(i, v)| (i, v.into()))
|
be_u8(i).map(|(i, v)| (i, v.into()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn parse_dhcp_flags(i: &[u8]) -> IResult<&[u8], Flags> {
|
||||||
|
be_u16(i).map(|(i, v)| (i, Flags(v)))
|
||||||
|
}
|
||||||
|
|
||||||
fn parse_dhcp_hardware_type(i: &[u8]) -> IResult<&[u8], HardwareType> {
|
fn parse_dhcp_hardware_type(i: &[u8]) -> IResult<&[u8], HardwareType> {
|
||||||
be_u8(i).map(|(i, v)| (i, v.into()))
|
be_u8(i).map(|(i, v)| (i, v.into()))
|
||||||
}
|
}
|
||||||
@ -71,6 +79,28 @@ fn parse_ipv4_address(i: &[u8]) -> IResult<&[u8], Ipv4Addr> {
|
|||||||
Ok((i, ip))
|
Ok((i, ip))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn parse_client_hardware_address(i: &[u8], hardware_address_length: u8) -> IResult<&[u8], &[u8]> {
|
||||||
|
let (i, val) = take(hardware_address_length)(i)?;
|
||||||
|
let (i, _padding) = take(0x10 - hardware_address_length)(i)?;
|
||||||
|
Ok((i, val))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_server_name(i: &[u8]) -> IResult<&[u8], &str> {
|
||||||
|
let (i, val) = take(64usize)(i)?;
|
||||||
|
let nullbyte_position = val.iter().position(|v| *v == b'\0').unwrap_or(64);
|
||||||
|
let val = unsafe { std::str::from_utf8_unchecked(&val[..nullbyte_position]) };
|
||||||
|
|
||||||
|
Ok((i, val))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_file(i: &[u8]) -> IResult<&[u8], &Path> {
|
||||||
|
let (i, val) = take(128usize)(i)?;
|
||||||
|
let nullbyte_position = val.iter().position(|v| *v == b'\0').unwrap_or(128);
|
||||||
|
let val = unsafe { std::str::from_utf8_unchecked(&val[..nullbyte_position]) };
|
||||||
|
|
||||||
|
Ok((i, Path::new(val)))
|
||||||
|
}
|
||||||
|
|
||||||
fn parse_dhcp_packet(packet: &[u8]) -> IResult<&[u8], DhcpMessage> {
|
fn parse_dhcp_packet(packet: &[u8]) -> IResult<&[u8], DhcpMessage> {
|
||||||
let (packet, operation) = parse_dhcp_operation(packet)?;
|
let (packet, operation) = parse_dhcp_operation(packet)?;
|
||||||
let (packet, hardware_type) = parse_dhcp_hardware_type(packet)?;
|
let (packet, hardware_type) = parse_dhcp_hardware_type(packet)?;
|
||||||
@ -78,11 +108,16 @@ fn parse_dhcp_packet(packet: &[u8]) -> IResult<&[u8], DhcpMessage> {
|
|||||||
let (packet, hops) = be_u8(packet)?;
|
let (packet, hops) = be_u8(packet)?;
|
||||||
let (packet, transaction_id) = be_u32(packet)?;
|
let (packet, transaction_id) = be_u32(packet)?;
|
||||||
let (packet, seconds) = be_u16(packet)?;
|
let (packet, seconds) = be_u16(packet)?;
|
||||||
let (packet, flags) = be_u16(packet)?;
|
let (packet, flags) = parse_dhcp_flags(packet)?;
|
||||||
let (packet, client_address) = parse_ipv4_address(packet)?;
|
let (packet, client_address) = parse_ipv4_address(packet)?;
|
||||||
let (packet, server_address) = parse_ipv4_address(packet)?;
|
let (packet, server_address) = parse_ipv4_address(packet)?;
|
||||||
let (packet, gateway_address) = parse_ipv4_address(packet)?;
|
let (packet, gateway_address) = parse_ipv4_address(packet)?;
|
||||||
let (packet, client_hardware_address) = take(6usize)(packet)?;
|
let (packet, client_hardware_address) =
|
||||||
|
parse_client_hardware_address(packet, hardware_address_length)?;
|
||||||
|
let potential_options = packet;
|
||||||
|
|
||||||
|
let (packet, server_name) = parse_server_name(packet)?;
|
||||||
|
let (packet, file_name) = parse_file(packet)?;
|
||||||
|
|
||||||
Ok((
|
Ok((
|
||||||
packet,
|
packet,
|
||||||
@ -98,8 +133,8 @@ fn parse_dhcp_packet(packet: &[u8]) -> IResult<&[u8], DhcpMessage> {
|
|||||||
server_address,
|
server_address,
|
||||||
gateway_address,
|
gateway_address,
|
||||||
client_hardware_address,
|
client_hardware_address,
|
||||||
server_hostname: "",
|
server_name,
|
||||||
boot_file_name: Path::new(""),
|
file_name,
|
||||||
},
|
},
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
@ -110,6 +145,21 @@ mod tests {
|
|||||||
static DHCP_PACKET2: &'static [u8] = &[
|
static DHCP_PACKET2: &'static [u8] = &[
|
||||||
0x01, 0x01, 0x06, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x7f, 0x00, 0x00,
|
0x01, 0x01, 0x06, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x7f, 0x00, 0x00,
|
||||||
0x01, 0x7f, 0x00, 0x00, 0x01, 0x7f, 0x00, 0x00, 0x01, 0x54, 0x05, 0xdb, 0xa6, 0x96, 0xd0,
|
0x01, 0x7f, 0x00, 0x00, 0x01, 0x7f, 0x00, 0x00, 0x01, 0x54, 0x05, 0xdb, 0xa6, 0x96, 0xd0,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //CHADDR padding
|
||||||
|
0x49, 0x20, 0x62, 0x69, 0x6D, 0x73, 0x20, 0x31, 0x20, 0x44, 0x48, 0x43, 0x50, 0x20, 0x53,
|
||||||
|
0x65, 0x72, 0x76, 0x65, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, // server name with padding
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // file with padding
|
||||||
];
|
];
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user