When parsing an LinkStateRequestPacket with authentication, the parser incorrectly swallows 12 bytes of authentication and thinks it's an additional LinkStateRequest.
Example code
let lsa_request_bytes = create_lsa_request_with_auth_bytes();
let (remaining, ospfv2_packet) = ospf_parser::parse_ospfv2_packet(lsa_request_bytes.as_slice()).unwrap();
let Ospfv2Packet::LinkStateRequest(lsa_request) = ospfv2_packet else {
panic!("failed to parse Ospfv2");
};
pub fn create_lsa_request_with_auth_bytes() -> Vec<u8> {
vec![
0x2, // version
0x3, // packet type
0x0, 0x24, // packet length (36)
0x2, 0x2, 0x2, 0x2, // router
0x0, 0x0, 0x0, 0x0, // area
0x0, 0x0, // checksum
0x0, 0x2, // au type
0x0, 0x0, 0x1, 0x10, // authentication
0x69, 0xa, 0xc0, 0xb2,
// -----
0x0, 0x0, 0x0, 0x1, // LS type
0x1, 0x1, 0x1, 0x1, // link state ID
0x1, 0x1, 0x1, 0x1, // adv. router
// -----
// signature
0x98, 0x35, 0xda, 0x13, 0xd5, 0x3f, 0xe9, 0x51,
0xd8, 0x40, 0xf4, 0xab, 0x10, 0x17, 0xc0, 0x2c]
}
parses as:
LinkStateRequest(
OspfLinkStateRequestPacket {
header: Ospfv2PacketHeader {
version: 2,
packet_type: OspfPacketType(
3,
),
packet_length: 36,
router_id: 33686018,
area_id: 0,
checksum: 0,
au_type: 2,
authentication: 1169993416882,
},
requests: [
OspfLinkStateRequest {
link_state_type: 1,
link_state_id: 16843009,
advertising_router: 16843009,
},
OspfLinkStateRequest {
link_state_type: 2553666067,
link_state_id: 3577735505,
advertising_router: 3628135595,
},
],
},
)
remaining: 0x1017c02c
The solution is to limit the parsing to the packet length:
use nom::bytes::complete::take;
use nom::combinator::complete;
use nom::combinator::map_parser;
use nom::multi::many0;
#[derive(Debug, NomBE)]
pub struct OspfLinkStateRequestPacket {
#[nom(Verify = "header.packet_type == OspfPacketType::LinkStateRequest")]
pub header: Ospfv2PacketHeader,
// Subtract the 24-byte OSPF header from total packet_length
#[nom(Parse = "{
let len = (header.packet_length as usize).saturating_sub(24);
map_parser(take(len), many0(complete(OspfLinkStateRequest::parse_be)))
}")]
pub requests: Vec<OspfLinkStateRequest>,
}
With this patch, the output is:
LinkStateRequest(
OspfLinkStateRequestPacket {
header: Ospfv2PacketHeader {
version: 2,
packet_type: OspfPacketType(
3,
),
packet_length: 36,
router_id: 33686018,
area_id: 0,
checksum: 0,
au_type: 2,
authentication: 1169993416882,
},
requests: [
OspfLinkStateRequest {
link_state_type: 1,
link_state_id: 16843009,
advertising_router: 16843009,
},
],
},
)
"9835da13d53fe951d840f4ab1017c02c"
When parsing an LinkStateRequestPacket with authentication, the parser incorrectly swallows 12 bytes of authentication and thinks it's an additional LinkStateRequest.
Example code
parses as:
The solution is to limit the parsing to the packet length:
With this patch, the output is: