From f5d47a8287b7d20d9521c07db71742083c9fdea2 Mon Sep 17 00:00:00 2001 From: Giuseppe Longo Date: Tue, 11 Aug 2026 09:23:49 +0200 Subject: [PATCH] dhcp: parse pad option as single byte DHCP option 0 is a one-byte padding field, but it was parsed as a generic TLV. This consumed the following option code as its length and could prevent later options from being inspected. Handle PAD explicitly so parsing resumes at the next option. Ticket #8819 (cherry picked from commit a06e7c742259bb8e89faabf34873dc7f9e3e99f3) --- rust/src/dhcp/dhcp.rs | 1 + rust/src/dhcp/parser.rs | 11 ++++++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/rust/src/dhcp/dhcp.rs b/rust/src/dhcp/dhcp.rs index 0650ba6a59..f8bb4bbff0 100644 --- a/rust/src/dhcp/dhcp.rs +++ b/rust/src/dhcp/dhcp.rs @@ -37,6 +37,7 @@ pub const BOOTP_REPLY: u8 = 2; // DHCP option types. Names based on IANA naming: // https://www.iana.org/assignments/bootp-dhcp-parameters/bootp-dhcp-parameters.xhtml +pub const DHCP_OPT_PAD: u8 = 0; pub const DHCP_OPT_SUBNET_MASK: u8 = 1; pub const DHCP_OPT_ROUTERS: u8 = 3; pub const DHCP_OPT_DNS_SERVER: u8 = 6; diff --git a/rust/src/dhcp/parser.rs b/rust/src/dhcp/parser.rs index 63e55d7cf3..527ccb8bb4 100644 --- a/rust/src/dhcp/parser.rs +++ b/rust/src/dhcp/parser.rs @@ -73,6 +73,7 @@ pub enum DHCPOptionWrapper { ClientId(DHCPOptClientId), TimeValue(DHCPOptTimeValue), Generic(DHCPOptGeneric), + Pad, End, } @@ -171,8 +172,16 @@ pub fn parse_generic_option(i: &[u8]) -> IResult<&[u8], DHCPOption> { // Parse a single DHCP option. When option 255 (END) is parsed, the remaining // data will be consumed. pub fn parse_option(i: &[u8]) -> IResult<&[u8], DHCPOption> { - let (_, opt) = be_u8(i)?; + let (rem, opt) = be_u8(i)?; match opt { + DHCP_OPT_PAD => Ok(( + rem, + DHCPOption { + code: opt, + data: None, + option: DHCPOptionWrapper::Pad, + }, + )), DHCP_OPT_END => { // End of options case. We consume the rest of the data // so the parser is not called again. But is there a