1use crate::ospfv2::*;
2use crate::ospfv3::*;
3use nom::bytes::streaming::take;
4use nom::combinator::{complete, map, peek};
5use nom::error::{make_error, ErrorKind};
6use nom::multi::many0;
7use nom::number::complete::be_u32 as be_u32_complete;
8use nom::number::streaming::{be_u16, be_u32};
9pub use nom::IResult;
10use nom_derive::Parse;
11
12pub fn parse_ospfv2_packet(input: &[u8]) -> IResult<&[u8], Ospfv2Packet> {
13 let (_, word) = peek(be_u16)(input)?;
14 let b0 = (word >> 8) as u8;
15 let b1 = (word & 0xff) as u8;
16 if b0 != 2 {
17 return Err(nom::Err::Error(make_error(input, ErrorKind::Tag)));
18 }
19 match OspfPacketType(b1) {
20 OspfPacketType::Hello => map(OspfHelloPacket::parse, Ospfv2Packet::Hello)(input),
21 OspfPacketType::DatabaseDescription => map(
22 OspfDatabaseDescriptionPacket::parse,
23 Ospfv2Packet::DatabaseDescription,
24 )(input),
25 OspfPacketType::LinkStateRequest => map(
26 OspfLinkStateRequestPacket::parse,
27 Ospfv2Packet::LinkStateRequest,
28 )(input),
29 OspfPacketType::LinkStateUpdate => map(
30 OspfLinkStateUpdatePacket::parse,
31 Ospfv2Packet::LinkStateUpdate,
32 )(input),
33 OspfPacketType::LinkStateAcknowledgment => map(
34 OspfLinkStateAcknowledgmentPacket::parse,
35 Ospfv2Packet::LinkStateAcknowledgment,
36 )(input),
37 _ => Err(nom::Err::Error(make_error(input, ErrorKind::Tag))),
38 }
39}
40
41pub fn parse_ospfv3_packet(input: &[u8]) -> IResult<&[u8], Ospfv3Packet> {
42 let (_, word) = peek(be_u16)(input)?;
43 let b0 = (word >> 8) as u8;
44 let b1 = (word & 0xff) as u8;
45 if b0 != 3 {
46 return Err(nom::Err::Error(make_error(input, ErrorKind::Tag)));
47 }
48 match OspfPacketType(b1) {
49 OspfPacketType::Hello => map(OspfHellov3Packet::parse, Ospfv3Packet::Hello)(input),
50 OspfPacketType::DatabaseDescription => map(
51 Ospfv3DatabaseDescriptionPacket::parse,
52 Ospfv3Packet::DatabaseDescription,
53 )(input),
54 OspfPacketType::LinkStateRequest => map(
55 Ospfv3LinkStateRequestPacket::parse,
56 Ospfv3Packet::LinkStateRequest,
57 )(input),
58 OspfPacketType::LinkStateUpdate => map(
59 Ospfv3LinkStateUpdatePacket::parse,
60 Ospfv3Packet::LinkStateUpdate,
61 )(input),
62 OspfPacketType::LinkStateAcknowledgment => map(
63 Ospfv3LinkStateAcknowledgmentPacket::parse,
64 Ospfv3Packet::LinkStateAcknowledgment,
65 )(input),
66 _ => Err(nom::Err::Error(make_error(input, ErrorKind::Tag))),
67 }
68}
69
70pub fn parse_ospfv2_packet_header(input: &[u8]) -> IResult<&[u8], Ospfv2PacketHeader> {
71 Ospfv2PacketHeader::parse(input)
72}
73
74pub fn parse_ospfv2_hello_packet(input: &[u8]) -> IResult<&[u8], OspfHelloPacket> {
75 OspfHelloPacket::parse(input)
76}
77
78pub fn parse_ospfv2_database_description_packet(
79 input: &[u8],
80) -> IResult<&[u8], OspfDatabaseDescriptionPacket> {
81 OspfDatabaseDescriptionPacket::parse(input)
82}
83
84pub fn parse_ospfv2_link_state_request_packet(
85 input: &[u8],
86) -> IResult<&[u8], OspfLinkStateRequestPacket> {
87 OspfLinkStateRequestPacket::parse(input)
88}
89
90impl<'a> Parse<&'a [u8]> for OspfLinkStateAdvertisement {
91 fn parse(input: &[u8]) -> IResult<&[u8], OspfLinkStateAdvertisement> {
92 let (_, word) = peek(be_u32)(input)?;
93 let ls_type = (word & 0xff) as u8;
94 match OspfLinkStateType(ls_type) {
95 OspfLinkStateType::RouterLinks => map(
96 OspfRouterLinksAdvertisement::parse,
97 OspfLinkStateAdvertisement::RouterLinks,
98 )(input),
99 OspfLinkStateType::NetworkLinks => map(
100 OspfNetworkLinksAdvertisement::parse,
101 OspfLinkStateAdvertisement::NetworkLinks,
102 )(input),
103 OspfLinkStateType::SummaryLinkIpNetwork => map(
104 OspfSummaryLinkAdvertisement::parse,
105 OspfLinkStateAdvertisement::SummaryLinkIpNetwork,
106 )(input),
107 OspfLinkStateType::SummaryLinkAsbr => map(
108 OspfSummaryLinkAdvertisement::parse,
109 OspfLinkStateAdvertisement::SummaryLinkAsbr,
110 )(input),
111 OspfLinkStateType::ASExternalLink => map(
112 OspfASExternalLinkAdvertisement::parse,
113 OspfLinkStateAdvertisement::ASExternalLink,
114 )(input),
115 OspfLinkStateType::NSSAASExternal => map(
116 OspfNSSAExternalLinkAdvertisement::parse,
117 OspfLinkStateAdvertisement::NSSAASExternal,
118 )(input),
119 OspfLinkStateType::OpaqueLinkLocalScope => map(
120 OspfOpaqueLinkAdvertisement::parse,
121 OspfLinkStateAdvertisement::OpaqueLinkLocalScope,
122 )(input),
123 OspfLinkStateType::OpaqueAreaLocalScope => map(
124 OspfOpaqueLinkAdvertisement::parse,
125 OspfLinkStateAdvertisement::OpaqueAreaLocalScope,
126 )(input),
127 OspfLinkStateType::OpaqueASWideScope => map(
128 OspfOpaqueLinkAdvertisement::parse,
129 OspfLinkStateAdvertisement::OpaqueASWideScope,
130 )(input),
131 _ => Err(nom::Err::Error(make_error(input, ErrorKind::Tag))),
132 }
133 }
134}
135
136impl<'a> Parse<&'a [u8]> for Ospfv3LinkStateAdvertisement {
137 fn parse(input: &[u8]) -> IResult<&[u8], Ospfv3LinkStateAdvertisement> {
138 let (_, word) = peek(be_u32)(input)?;
139 let ls_type = (word & 0xffff) as u16;
140 match Ospfv3LinkStateType(ls_type) {
141 Ospfv3LinkStateType::RouterLSA => {
142 map(Ospfv3RouterLSA::parse, Ospfv3LinkStateAdvertisement::Router)(input)
143 }
144 Ospfv3LinkStateType::NetworkLSA => map(
145 Ospfv3NetworkLSA::parse,
146 Ospfv3LinkStateAdvertisement::Network,
147 )(input),
148 Ospfv3LinkStateType::InterAreaPrefixLSA => map(
149 Ospfv3InterAreaPrefixLSA::parse,
150 Ospfv3LinkStateAdvertisement::InterAreaPrefix,
151 )(input),
152 Ospfv3LinkStateType::InterAreaRouterLSA => map(
153 Ospfv3InterAreaRouterLSA::parse,
154 Ospfv3LinkStateAdvertisement::InterAreaRouter,
155 )(input),
156 Ospfv3LinkStateType::ASExternalLSA => map(
157 Ospfv3ASExternalLSA::parse,
158 Ospfv3LinkStateAdvertisement::ASExternal,
159 )(input),
160 Ospfv3LinkStateType::NSSALSA => map(
161 Ospfv3ASExternalLSA::parse,
162 Ospfv3LinkStateAdvertisement::NSSA,
163 )(input),
164 Ospfv3LinkStateType::LinkLSA => {
165 map(Ospfv3LinkLSA::parse, Ospfv3LinkStateAdvertisement::Link)(input)
166 }
167 Ospfv3LinkStateType::IntraAreaPrefixLSA => map(
168 Ospfv3IntraAreaPrefixLSA::parse,
169 Ospfv3LinkStateAdvertisement::IntraAreaPrefix,
170 )(input),
171 _ => Err(nom::Err::Error(make_error(input, ErrorKind::Tag))),
172 }
173 }
174}
175
176pub(crate) fn parse_ospf_vec_u32(
177 packet_length: u16,
178 offset: usize,
179) -> impl Fn(&[u8]) -> IResult<&[u8], Vec<u32>> {
180 move |input: &[u8]| parse_ospf_vec_u32_f(input, packet_length, offset)
181}
182
183fn parse_ospf_vec_u32_f(
184 input: &[u8],
185 packet_length: u16,
186 offset: usize,
187) -> IResult<&[u8], Vec<u32>> {
188 if packet_length as usize == offset {
189 return Ok((input, Vec::new()));
190 }
191 if (packet_length as usize) < offset || packet_length as usize - offset > input.len() {
192 return Err(nom::Err::Error(make_error(input, ErrorKind::LengthValue)));
193 }
194 let (data, rem) = input.split_at(packet_length as usize - offset);
195 let (_, routers) = many0(be_u32_complete)(data)?;
196 Ok((rem, routers))
197}
198
199pub(crate) fn parse_ospf_external_tos_routes(
200 packet_length: u16,
201) -> impl Fn(&[u8]) -> IResult<&[u8], Vec<OspfExternalTosRoute>> {
202 move |input: &[u8]| parse_ospf_external_tos_routes_f(input, packet_length)
203}
204
205fn parse_ospf_external_tos_routes_f(
206 input: &[u8],
207 packet_length: u16,
208) -> IResult<&[u8], Vec<OspfExternalTosRoute>> {
209 if packet_length == 36 {
210 return Ok((input, Vec::new()));
211 }
212 if packet_length < 36 || packet_length as usize - 36 > input.len() {
214 return Err(nom::Err::Error(make_error(input, ErrorKind::LengthValue)));
215 }
216 let (data_routes, rem) = input.split_at(packet_length as usize - 36);
217 let (_, routes) = many0(complete(OspfExternalTosRoute::parse))(data_routes)?;
218 Ok((rem, routes))
219}
220
221pub(crate) fn parse_ospf_tos_routes(
222 packet_length: u16,
223) -> impl Fn(&[u8]) -> IResult<&[u8], Vec<OspfTosRoute>> {
224 move |input: &[u8]| parse_ospf_tos_routes_f(input, packet_length)
225}
226
227fn parse_ospf_tos_routes_f(input: &[u8], packet_length: u16) -> IResult<&[u8], Vec<OspfTosRoute>> {
228 if packet_length == 28 {
229 return Ok((input, Vec::new()));
230 }
231 if packet_length < 28 || packet_length as usize - 28 > input.len() {
233 return Err(nom::Err::Error(make_error(input, ErrorKind::LengthValue)));
234 }
235 let (data_routes, rem) = input.split_at(packet_length as usize - 28);
236 let (_, routes) = many0(complete(OspfTosRoute::parse))(data_routes)?;
237 Ok((rem, routes))
238}
239
240pub(crate) fn parse_ospfv3_router_links(
241 packet_length: u16,
242) -> impl Fn(&[u8]) -> IResult<&[u8], Vec<Ospfv3RouterLink>> {
243 move |input: &[u8]| parse_ospfv3_router_links_f(input, packet_length)
244}
245
246fn parse_ospfv3_router_links_f(
247 input: &[u8],
248 packet_length: u16,
249) -> IResult<&[u8], Vec<Ospfv3RouterLink>> {
250 if packet_length == 24 {
251 return Ok((input, Vec::new()));
252 }
253 if packet_length < 24 || packet_length as usize - 24 > input.len() {
254 return Err(nom::Err::Error(make_error(input, ErrorKind::LengthValue)));
255 }
256 let (data, rem) = input.split_at(packet_length as usize - 24);
257 let (_, v) = many0(complete(Ospfv3RouterLink::parse))(data)?;
258 Ok((rem, v))
259}
260
261pub(crate) fn take_vec_u8(length: u8) -> impl Fn(&[u8]) -> IResult<&[u8], Vec<u8>> {
262 move |input: &[u8]| map(take(length), |b: &[u8]| b.to_vec())(input)
263}