1use crate::packet::PacketError;
2use crate::parser::ParseError::InvalidPacket;
3use crate::{header, packet, v1, v2, version};
4use thiserror::Error;
5
6#[derive(Error, Debug, PartialEq)]
7pub enum ParseError {
8 #[error("insufficient input bytes length; at {0} byte")]
9 InsufficientInputBytesLength(usize),
10 #[error("unknown command kind {0} has given; at {1} byte")]
11 UnknownCommandKind(u8, usize),
12 #[error("unknown version has given; at {0} byte")]
13 UnknownVersion(usize),
14 #[error("version which indicates \"must be discarded\" has given; at {0} byte")]
15 MustBeDiscardedVersion(usize),
16 #[error("the byte must be zero but was {0} at {1} byte")]
17 NotZeroByte(u8, usize),
18 #[error("encountered the unknown address family identifier {0}; at {1} byte")]
19 UnknownAddressFamilyIdentifier(u16, usize),
20 #[error("given packet doesn't have the RIP entry part at; {0} byte")]
21 EmptyRIPEntry(usize),
22 #[error("the number of RIP entries exceeds the maximum number. it allows to have the entries up to 25 in a packet; at {0} byte")]
23 MaxRIPEntriesNumberExceeded(usize),
24 #[error("invalid packet: {0}")]
25 InvalidPacket(PacketError),
26}
27
28#[derive(Debug)]
29pub enum ParsedPacket {
30 V1(packet::Packet<v1::Entry>),
31 V2(packet::Packet<v2::Entry>),
32}
33
34pub type Parsed<T> = (T, usize);
36
37pub fn parse(bytes: &[u8]) -> Result<ParsedPacket, ParseError> {
38 let (header, cursor) = header::parse(0, bytes)?;
39
40 match header.get_version() {
41 version::Version::Version1 => match parse_entries(&v1::EntriesParser {}, cursor, bytes) {
42 Ok(entries) => Ok(ParsedPacket::V1(
43 packet::Packet::make_v1_packet(header, entries).unwrap(),
44 )),
45 Err(e) => Err(e),
46 },
47 version::Version::Version2 => match parse_entries(&v2::EntriesParser {}, cursor, bytes) {
48 Ok(entries) => Ok(ParsedPacket::V2(
49 packet::Packet::make_v2_packet(header, entries).unwrap(),
50 )),
51 Err(e) => Err(e),
52 },
53 version::Version::MustBeDiscarded => Err(ParseError::MustBeDiscardedVersion(2)),
54 version::Version::Unknown => Err(ParseError::UnknownVersion(2)),
55 }
56}
57
58pub fn parse_v1(bytes: &[u8]) -> Result<packet::Packet<v1::Entry>, ParseError> {
59 let (header, cursor) = header::parse(0, bytes)?;
60
61 match parse_entries(&v1::EntriesParser {}, cursor, bytes) {
62 Ok(entries) => match packet::Packet::make_v1_packet(header, entries) {
63 Ok(p) => Ok(p),
64 Err(e) => Err(InvalidPacket(e)),
65 },
66 Err(e) => Err(e),
67 }
68}
69
70pub fn parse_v2(bytes: &[u8]) -> Result<packet::Packet<v2::Entry>, ParseError> {
71 let (header, cursor) = header::parse(0, bytes)?;
72
73 match parse_entries(&v2::EntriesParser {}, cursor, bytes) {
74 Ok(entries) => match packet::Packet::make_v2_packet(header, entries) {
75 Ok(p) => Ok(p),
76 Err(e) => Err(InvalidPacket(e)),
77 },
78 Err(e) => Err(e),
79 }
80}
81
82pub(crate) fn parse_entries<T>(
83 parser: &dyn PacketParsable<T>,
84 mut cursor: usize,
85 bytes: &[u8],
86) -> Result<Vec<T>, ParseError> {
87 let mut entries: Vec<T> = vec![];
88
89 if (bytes.len() - 1) <= cursor {
90 return Err(ParseError::EmptyRIPEntry(cursor));
91 }
92
93 loop {
94 if entries.len() >= 25 {
95 return Err(ParseError::MaxRIPEntriesNumberExceeded(cursor));
96 }
97
98 let res = match parser.parse_entry(cursor, bytes) {
99 Ok(result) => result,
100 Err(e) => {
101 return Err(e);
102 }
103 };
104 entries.push(res.0);
105 cursor = res.1;
106
107 if cursor >= bytes.len() {
108 break;
109 }
110 }
111
112 Ok(entries)
113}
114
115pub(crate) trait PacketParsable<T> {
116 fn parse_entry<'a>(&'a self, cursor: usize, bytes: &'a [u8]) -> Result<(T, usize), ParseError>;
117}
118
119#[cfg(test)]
120mod tests {
121 use crate::packet::PacketError::VersionInHeaderConflicted;
122 use crate::parser::ParseError;
123 use crate::parser::ParseError::{InsufficientInputBytesLength, InvalidPacket};
124 use crate::{address_family, command, header::Header, packet::Packet, parser, v1, v2, version};
125 use std::net::Ipv4Addr;
126
127 #[test]
128 fn test_parse_v1_packet_for_single_entry() {
129 let result = parser::parse(
130 vec![
131 2, 1, 0, 0, 0, 2, 0, 0, 192, 0, 2, 100, 0, 0, 0, 0, 0, 0, 0, 0, 4, 3, 2, 1, ]
138 .as_slice(),
139 );
140
141 assert_eq!(result.is_ok(), true);
142
143 let packet = match result.unwrap() {
144 parser::ParsedPacket::V1(p) => p,
145 parser::ParsedPacket::V2(_) => {
146 assert_eq!(
147 false, false,
148 "unexpected because given packet is not the v2 packet"
149 );
150 return;
151 }
152 };
153 let expected_packet = Packet::make_v1_packet(
154 Header::new(command::Kind::Response, version::Version::Version1),
155 vec![v1::Entry::new(
156 address_family::Identifier::IP,
157 Ipv4Addr::new(192, 0, 2, 100),
158 67305985,
159 )],
160 )
161 .unwrap();
162 assert_eq!(packet, expected_packet);
163 }
164
165 #[test]
166 fn test_parse_v1_packet_for_multiple_entry() {
167 let result = parser::parse(
168 vec![
169 2, 1, 0, 0, 0, 2, 0, 0, 192, 0, 2, 100, 0, 0, 0, 0, 0, 0, 0, 0, 4, 3, 2, 1, 0, 2, 0, 0, 192, 0, 2, 101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 192, 0, 2, 102, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, ]
186 .as_slice(),
187 );
188 assert_eq!(result.is_ok(), true);
189
190 let packet = match result.unwrap() {
191 parser::ParsedPacket::V1(p) => p,
192 parser::ParsedPacket::V2(_) => {
193 assert_eq!(
194 false, false,
195 "unexpected because given packet is not the v2 packet"
196 );
197 return;
198 }
199 };
200 let expected_packet = Packet::make_v1_packet(
201 Header::new(command::Kind::Response, version::Version::Version1),
202 vec![
203 v1::Entry::new(
204 address_family::Identifier::IP,
205 Ipv4Addr::new(192, 0, 2, 100),
206 67305985,
207 ),
208 v1::Entry::new(
209 address_family::Identifier::IP,
210 Ipv4Addr::new(192, 0, 2, 101),
211 1,
212 ),
213 v1::Entry::new(
214 address_family::Identifier::IP,
215 Ipv4Addr::new(192, 0, 2, 102),
216 2,
217 ),
218 ],
219 )
220 .unwrap();
221 assert_eq!(packet, expected_packet);
222 }
223
224 #[test]
225 fn test_parse_v2_packet_for_single_entry() {
226 let result = parser::parse(
227 vec![
228 2, 2, 0, 0, 0, 2, 1, 2, 192, 0, 2, 100, 255, 255, 255, 0, 192, 0, 2, 111, 4, 3, 2, 1, ]
235 .as_slice(),
236 );
237
238 assert_eq!(result.is_ok(), true);
239
240 let packet = match result.unwrap() {
241 parser::ParsedPacket::V1(_) => {
242 assert_eq!(
243 false, false,
244 "unexpected because given packet is not the v1 packet"
245 );
246 return;
247 }
248 parser::ParsedPacket::V2(p) => p,
249 };
250 let expected_packet = Packet::make_v2_packet(
251 Header::new(command::Kind::Response, version::Version::Version2),
252 vec![v2::Entry::new(
253 address_family::Identifier::IP,
254 258,
255 Ipv4Addr::new(192, 0, 2, 100),
256 Ipv4Addr::new(255, 255, 255, 0),
257 Ipv4Addr::new(192, 0, 2, 111),
258 67305985,
259 )],
260 )
261 .unwrap();
262 assert_eq!(packet, expected_packet);
263 }
264
265 #[test]
266 fn test_parse_v2_packet_for_multiple_entry() {
267 let result = parser::parse(
268 vec![
269 2, 2, 0, 0, 0, 2, 1, 2, 192, 0, 2, 100, 255, 255, 255, 0, 192, 0, 2, 200, 4, 3, 2, 1, 0, 2, 0, 1, 192, 0, 2, 101, 255, 255, 255, 0, 192, 0, 2, 201, 0, 0, 0, 1, 0, 2, 0, 2, 192, 0, 2, 102, 255, 255, 255, 0, 192, 0, 2, 202, 0, 0, 0, 2, ]
286 .as_slice(),
287 );
288 assert_eq!(result.is_ok(), true);
289
290 let packet = match result.unwrap() {
291 parser::ParsedPacket::V1(_) => {
292 assert_eq!(
293 false, false,
294 "unexpected because given packet is not the v1 packet"
295 );
296 return;
297 }
298 parser::ParsedPacket::V2(p) => p,
299 };
300 let expected_packet = Packet::make_v2_packet(
301 Header::new(command::Kind::Response, version::Version::Version2),
302 vec![
303 v2::Entry::new(
304 address_family::Identifier::IP,
305 258,
306 Ipv4Addr::new(192, 0, 2, 100),
307 Ipv4Addr::new(255, 255, 255, 0),
308 Ipv4Addr::new(192, 0, 2, 200),
309 67305985,
310 ),
311 v2::Entry::new(
312 address_family::Identifier::IP,
313 1,
314 Ipv4Addr::new(192, 0, 2, 101),
315 Ipv4Addr::new(255, 255, 255, 0),
316 Ipv4Addr::new(192, 0, 2, 201),
317 1,
318 ),
319 v2::Entry::new(
320 address_family::Identifier::IP,
321 2,
322 Ipv4Addr::new(192, 0, 2, 102),
323 Ipv4Addr::new(255, 255, 255, 0),
324 Ipv4Addr::new(192, 0, 2, 202),
325 2,
326 ),
327 ],
328 )
329 .unwrap();
330 assert_eq!(packet, expected_packet);
331 }
332
333 #[test]
334 fn test_parse_insufficient_length_bytes_for_v1() {
335 let result = parser::parse(
336 vec![
337 2, 1, 0, 0, 0, 2, 0, 0, 192, 0, 2, 100, 0, 0, 0, 0, 0, 0, 0, 0, 4, 3, 2, ]
344 .as_slice(),
345 );
346
347 assert_eq!(
348 result.unwrap_err(),
349 ParseError::InsufficientInputBytesLength(23)
350 );
351 }
352
353 #[test]
354 fn test_parse_insufficient_length_bytes_for_v2() {
355 let result = parser::parse(
356 vec![
357 2, 2, 0, 0, 0, 2, 0, 0, 192, 0, 2, 100, 255, 255, 255, 0, 0, 0, 0, 0, 4, 3, 2, ]
364 .as_slice(),
365 );
366
367 assert_eq!(
368 result.unwrap_err(),
369 ParseError::InsufficientInputBytesLength(23)
370 );
371 }
372
373 #[test]
374 fn test_parse_bytes_must_be_discarded() {
375 let result = parser::parse(
376 vec![
377 2, 0, 0, 0, 0, 2, 0, 0, 192, 0, 2, 100, 255, 255, 255, 0, 0, 0, 0, 0, 4, 3, 2, 1, ]
384 .as_slice(),
385 );
386
387 assert_eq!(result.unwrap_err(), ParseError::MustBeDiscardedVersion(2),);
388 }
389
390 #[test]
391 fn test_parse_bytes_of_unknown_version() {
392 let result = parser::parse(
393 vec![
394 2, 255, 0, 0, 0, 2, 0, 0, 192, 0, 2, 100, 255, 255, 255, 0, 0, 0, 0, 0, 4, 3, 2, 1, ]
401 .as_slice(),
402 );
403
404 assert_eq!(result.unwrap_err(), ParseError::UnknownVersion(2));
405 }
406
407 #[test]
408 fn test_parse_empty_entry_part() {
409 let result = parser::parse(vec![2, 2, 0, 0].as_slice());
410
411 assert_eq!(result.unwrap_err(), ParseError::EmptyRIPEntry(4));
412 }
413
414 #[test]
415 fn test_parse_bytes_which_has_the_number_of_entries_that_exceeds_max_limit() {
416 let result = parser::parse(
417 vec![
418 2, 2, 0, 0, 0, 2, 1, 2, 192, 0, 2, 101, 255, 255, 255, 0, 192, 0, 2, 200, 0, 0, 0, 1, 0, 2, 1, 2, 192, 0, 2, 102, 255, 255, 255, 0, 192, 0, 2, 200, 0, 0, 0, 2, 0, 2, 1, 2, 192, 0, 2, 103, 255, 255, 255, 0, 192, 0, 2, 200, 0, 0, 0, 3, 0, 2, 1, 2, 192, 0, 2, 104, 255, 255, 255, 0, 192, 0, 2, 200, 0, 0, 0, 4, 0, 2, 1, 2, 192, 0, 2, 105, 255, 255, 255, 0, 192, 0, 2, 200, 0, 0, 0, 5, 0, 2, 1, 2, 192, 0, 2, 106, 255, 255, 255, 0, 192, 0, 2, 200, 0, 0, 0, 6, 0, 2, 1, 2, 192, 0, 2, 107, 255, 255, 255, 0, 192, 0, 2, 200, 0, 0, 0, 7, 0, 2, 1, 2, 192, 0, 2, 108, 255, 255, 255, 0, 192, 0, 2, 200, 0, 0, 0, 8, 0, 2, 1, 2, 192, 0, 2, 109, 255, 255, 255, 0, 192, 0, 2, 200, 0, 0, 0, 9, 0, 2, 1, 2, 192, 0, 2, 110, 255, 255, 255, 0, 192, 0, 2, 200, 0, 0, 0, 10, 0, 2, 1, 2, 192, 0, 2, 111, 255, 255, 255, 0, 192, 0, 2, 200, 0, 0, 0, 11, 0, 2, 1, 2, 192, 0, 2, 112, 255, 255, 255, 0, 192, 0, 2, 200, 0, 0, 0, 12, 0, 2, 1, 2, 192, 0, 2, 113, 255, 255, 255, 0, 192, 0, 2, 200, 0, 0, 0, 13, 0, 2, 1, 2, 192, 0, 2, 114, 255, 255, 255, 0, 192, 0, 2, 200, 0, 0, 0, 14, 0, 2, 1, 2, 192, 0, 2, 115, 255, 255, 255, 0, 192, 0, 2, 200, 0, 0, 0, 15, 0, 2, 1, 2, 192, 0, 2, 116, 255, 255, 255, 0, 192, 0, 2, 200, 0, 0, 0, 16, 0, 2, 1, 2, 192, 0, 2, 117, 255, 255, 255, 0, 192, 0, 2, 200, 0, 0, 0, 17, 0, 2, 1, 2, 192, 0, 2, 118, 255, 255, 255, 0, 192, 0, 2, 200, 0, 0, 0, 18, 0, 2, 1, 2, 192, 0, 2, 119, 255, 255, 255, 0, 192, 0, 2, 200, 0, 0, 0, 19, 0, 2, 1, 2, 192, 0, 2, 120, 255, 255, 255, 0, 192, 0, 2, 200, 0, 0, 0, 20, 0, 2, 1, 2, 192, 0, 2, 121, 255, 255, 255, 0, 192, 0, 2, 200, 0, 0, 0, 21, 0, 2, 1, 2, 192, 0, 2, 122, 255, 255, 255, 0, 192, 0, 2, 200, 0, 0, 0, 22, 0, 2, 1, 2, 192, 0, 2, 123, 255, 255, 255, 0, 192, 0, 2, 200, 0, 0, 0, 23, 0, 2, 1, 2, 192, 0, 2, 124, 255, 255, 255, 0, 192, 0, 2, 200, 0, 0, 0, 24, 0, 2, 1, 2, 192, 0, 2, 125, 255, 255, 255, 0, 192, 0, 2, 200, 0, 0, 0, 25, 0, 2, 1, 2, 192, 0, 2, 126, 255, 255, 255, 0, 192, 0, 2, 200, 0, 0, 0, 26, ]
446 .as_slice(),
447 );
448
449 assert_eq!(
450 result.unwrap_err(),
451 ParseError::MaxRIPEntriesNumberExceeded(504)
452 );
453 }
454
455 #[test]
456 fn test_parse_v1() {
457 let result = parser::parse_v1(
458 vec![
459 2, 1, 0, 0, 0, 2, 0, 0, 192, 0, 2, 100, 0, 0, 0, 0, 0, 0, 0, 0, 4, 3, 2, 1, ]
466 .as_slice(),
467 );
468
469 let expected_packet = Packet::make_v1_packet(
470 Header::new(command::Kind::Response, version::Version::Version1),
471 vec![v1::Entry::new(
472 address_family::Identifier::IP,
473 Ipv4Addr::new(192, 0, 2, 100),
474 67305985,
475 )],
476 )
477 .unwrap();
478 assert_eq!(result.unwrap(), expected_packet);
479 }
480
481 #[test]
482 fn test_parse_v1_with_conflict_version() {
483 let result = parser::parse_v1(
484 vec![
485 2, 2, 0, 0, 0, 2, 0, 0, 192, 0, 2, 100, 0, 0, 0, 0, 0, 0, 0, 0, 4, 3, 2, 1, ]
492 .as_slice(),
493 );
494 assert_eq!(
495 result.unwrap_err(),
496 InvalidPacket(VersionInHeaderConflicted)
497 );
498 }
499
500 #[test]
501 fn test_parse_v1_with_insufficient_bytes() {
502 let result = parser::parse_v1(
503 vec![
504 2, 1, 0, 0, 0, 2, 0, 0, 192, 0, 2, 100, 0, 0, 0, 0, 0, 0, 0, 0, 4, 3, 2, ]
511 .as_slice(),
512 );
513 assert_eq!(result.unwrap_err(), InsufficientInputBytesLength(23));
514 }
515
516 #[test]
517 fn test_parse_v2() {
518 let result = parser::parse_v2(
519 vec![
520 2, 2, 0, 0, 0, 2, 0, 0, 192, 0, 2, 100, 255, 255, 255, 0, 0, 0, 0, 0, 4, 3, 2, 1, ]
527 .as_slice(),
528 );
529
530 let expected_packet = Packet::make_v2_packet(
531 Header::new(command::Kind::Response, version::Version::Version2),
532 vec![v2::Entry::new(
533 address_family::Identifier::IP,
534 0,
535 Ipv4Addr::new(192, 0, 2, 100),
536 Ipv4Addr::new(255, 255, 255, 0),
537 Ipv4Addr::new(0, 0, 0, 0),
538 67305985,
539 )],
540 )
541 .unwrap();
542 assert_eq!(result.unwrap(), expected_packet);
543 }
544
545 #[test]
546 fn test_parse_v2_with_conflict_version() {
547 let result = parser::parse_v2(
548 vec![
549 2, 1, 0, 0, 0, 2, 0, 0, 192, 0, 2, 100, 255, 255, 255, 0, 0, 0, 0, 0, 4, 3, 2, 1, ]
556 .as_slice(),
557 );
558 assert_eq!(
559 result.unwrap_err(),
560 InvalidPacket(VersionInHeaderConflicted)
561 );
562 }
563
564 #[test]
565 fn test_parse_v2_with_insufficient_bytes() {
566 let result = parser::parse_v2(
567 vec![
568 2, 2, 0, 0, 0, 2, 0, 0, 192, 0, 2, 100, 0, 0, 0, 0, 0, 0, 0, 0, 4, 3, 2, ]
575 .as_slice(),
576 );
577 assert_eq!(result.unwrap_err(), InsufficientInputBytesLength(23));
578 }
579}