rip_rs/
parser.rs

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
34/// Parsed is a tuple type which has a T-typed value end a cursor for bytes reading.
35pub 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, //
132                0, 2, 0, 0, //
133                192, 0, 2, 100, //
134                0, 0, 0, 0, //
135                0, 0, 0, 0, //
136                4, 3, 2, 1, //
137            ]
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, //
170                0, 2, 0, 0, //
171                192, 0, 2, 100, //
172                0, 0, 0, 0, //
173                0, 0, 0, 0, //
174                4, 3, 2, 1, //
175                0, 2, 0, 0, //
176                192, 0, 2, 101, //
177                0, 0, 0, 0, //
178                0, 0, 0, 0, //
179                0, 0, 0, 1, //
180                0, 2, 0, 0, //
181                192, 0, 2, 102, //
182                0, 0, 0, 0, //
183                0, 0, 0, 0, //
184                0, 0, 0, 2, //
185            ]
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, //
229                0, 2, 1, 2, //
230                192, 0, 2, 100, //
231                255, 255, 255, 0, //
232                192, 0, 2, 111, //
233                4, 3, 2, 1, //
234            ]
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, //
270                0, 2, 1, 2, //
271                192, 0, 2, 100, //
272                255, 255, 255, 0, //
273                192, 0, 2, 200, //
274                4, 3, 2, 1, //
275                0, 2, 0, 1, //
276                192, 0, 2, 101, //
277                255, 255, 255, 0, //
278                192, 0, 2, 201, //
279                0, 0, 0, 1, //
280                0, 2, 0, 2, //
281                192, 0, 2, 102, //
282                255, 255, 255, 0, //
283                192, 0, 2, 202, //
284                0, 0, 0, 2, //
285            ]
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, //
338                0, 2, 0, 0, //
339                192, 0, 2, 100, //
340                0, 0, 0, 0, //
341                0, 0, 0, 0, //
342                4, 3, 2, // missing a trailing byte
343            ]
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, //
358                0, 2, 0, 0, //
359                192, 0, 2, 100, //
360                255, 255, 255, 0, //
361                0, 0, 0, 0, //
362                4, 3, 2, // missing a trailing byte
363            ]
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, // version byte is 0 (must be discarded)
378                0, 2, 0, 0, //
379                192, 0, 2, 100, //
380                255, 255, 255, 0, //
381                0, 0, 0, 0, //
382                4, 3, 2, 1, //
383            ]
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, // version byte is 255 (unknown)
395                0, 2, 0, 0, //
396                192, 0, 2, 100, //
397                255, 255, 255, 0, //
398                0, 0, 0, 0, //
399                4, 3, 2, 1, //
400            ]
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, //
419                0, 2, 1, 2, 192, 0, 2, 101, 255, 255, 255, 0, 192, 0, 2, 200, 0, 0, 0, 1, //
420                0, 2, 1, 2, 192, 0, 2, 102, 255, 255, 255, 0, 192, 0, 2, 200, 0, 0, 0, 2, //
421                0, 2, 1, 2, 192, 0, 2, 103, 255, 255, 255, 0, 192, 0, 2, 200, 0, 0, 0, 3, //
422                0, 2, 1, 2, 192, 0, 2, 104, 255, 255, 255, 0, 192, 0, 2, 200, 0, 0, 0, 4, //
423                0, 2, 1, 2, 192, 0, 2, 105, 255, 255, 255, 0, 192, 0, 2, 200, 0, 0, 0, 5, //
424                0, 2, 1, 2, 192, 0, 2, 106, 255, 255, 255, 0, 192, 0, 2, 200, 0, 0, 0, 6, //
425                0, 2, 1, 2, 192, 0, 2, 107, 255, 255, 255, 0, 192, 0, 2, 200, 0, 0, 0, 7, //
426                0, 2, 1, 2, 192, 0, 2, 108, 255, 255, 255, 0, 192, 0, 2, 200, 0, 0, 0, 8, //
427                0, 2, 1, 2, 192, 0, 2, 109, 255, 255, 255, 0, 192, 0, 2, 200, 0, 0, 0, 9, //
428                0, 2, 1, 2, 192, 0, 2, 110, 255, 255, 255, 0, 192, 0, 2, 200, 0, 0, 0, 10, //
429                0, 2, 1, 2, 192, 0, 2, 111, 255, 255, 255, 0, 192, 0, 2, 200, 0, 0, 0, 11, //
430                0, 2, 1, 2, 192, 0, 2, 112, 255, 255, 255, 0, 192, 0, 2, 200, 0, 0, 0, 12, //
431                0, 2, 1, 2, 192, 0, 2, 113, 255, 255, 255, 0, 192, 0, 2, 200, 0, 0, 0, 13, //
432                0, 2, 1, 2, 192, 0, 2, 114, 255, 255, 255, 0, 192, 0, 2, 200, 0, 0, 0, 14, //
433                0, 2, 1, 2, 192, 0, 2, 115, 255, 255, 255, 0, 192, 0, 2, 200, 0, 0, 0, 15, //
434                0, 2, 1, 2, 192, 0, 2, 116, 255, 255, 255, 0, 192, 0, 2, 200, 0, 0, 0, 16, //
435                0, 2, 1, 2, 192, 0, 2, 117, 255, 255, 255, 0, 192, 0, 2, 200, 0, 0, 0, 17, //
436                0, 2, 1, 2, 192, 0, 2, 118, 255, 255, 255, 0, 192, 0, 2, 200, 0, 0, 0, 18, //
437                0, 2, 1, 2, 192, 0, 2, 119, 255, 255, 255, 0, 192, 0, 2, 200, 0, 0, 0, 19, //
438                0, 2, 1, 2, 192, 0, 2, 120, 255, 255, 255, 0, 192, 0, 2, 200, 0, 0, 0, 20, //
439                0, 2, 1, 2, 192, 0, 2, 121, 255, 255, 255, 0, 192, 0, 2, 200, 0, 0, 0, 21, //
440                0, 2, 1, 2, 192, 0, 2, 122, 255, 255, 255, 0, 192, 0, 2, 200, 0, 0, 0, 22, //
441                0, 2, 1, 2, 192, 0, 2, 123, 255, 255, 255, 0, 192, 0, 2, 200, 0, 0, 0, 23, //
442                0, 2, 1, 2, 192, 0, 2, 124, 255, 255, 255, 0, 192, 0, 2, 200, 0, 0, 0, 24, //
443                0, 2, 1, 2, 192, 0, 2, 125, 255, 255, 255, 0, 192, 0, 2, 200, 0, 0, 0, 25, //
444                0, 2, 1, 2, 192, 0, 2, 126, 255, 255, 255, 0, 192, 0, 2, 200, 0, 0, 0, 26, //
445            ]
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, //
460                0, 2, 0, 0, //
461                192, 0, 2, 100, //
462                0, 0, 0, 0, //
463                0, 0, 0, 0, //
464                4, 3, 2, 1, //
465            ]
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, // the second byte is 2 (i.e version 2)
486                0, 2, 0, 0, //
487                192, 0, 2, 100, //
488                0, 0, 0, 0, //
489                0, 0, 0, 0, //
490                4, 3, 2, 1, //
491            ]
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, //
505                0, 2, 0, 0, //
506                192, 0, 2, 100, //
507                0, 0, 0, 0, //
508                0, 0, 0, 0, //
509                4, 3, 2, // trailing byte is missing
510            ]
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, //
521                0, 2, 0, 0, //
522                192, 0, 2, 100, //
523                255, 255, 255, 0, //
524                0, 0, 0, 0, //
525                4, 3, 2, 1, //
526            ]
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, // the second byte is 1 (i.e version 1)
550                0, 2, 0, 0, //
551                192, 0, 2, 100, //
552                255, 255, 255, 0, //
553                0, 0, 0, 0, //
554                4, 3, 2, 1, //
555            ]
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, //
569                0, 2, 0, 0, //
570                192, 0, 2, 100, //
571                0, 0, 0, 0, //
572                0, 0, 0, 0, //
573                4, 3, 2, // trailing byte is missing
574            ]
575            .as_slice(),
576        );
577        assert_eq!(result.unwrap_err(), InsufficientInputBytesLength(23));
578    }
579}