ppp_packet/
ipv6.rs

1// Copyright 2019 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5//! Utilities for parsing and serializing IPV6CP options.
6
7use crate::records::options::{OptionsImpl, OptionsImplLayout, OptionsSerializerImpl};
8use byteorder::{ByteOrder, NetworkEndian};
9
10/// An IPV6CP control option.
11#[derive(Clone, Eq, Hash, PartialEq, Debug)]
12pub enum ControlOption {
13    /// Any sequence of bytes not recognized as a valid option.
14    Unrecognized(u8, Vec<u8>),
15    /// 64-bit identifier which is very likely to be unique on the link.
16    InterfaceIdentifier(u64),
17}
18
19/// Implementation of the IPV6CP control options parsing and serialization.
20pub struct ControlOptionsImpl;
21
22impl ControlOptionsImpl {
23    const TYPE_INTERFACE_IDENTIFIER: u8 = 1;
24}
25
26impl OptionsImplLayout for ControlOptionsImpl {
27    type Error = ();
28    const END_OF_OPTIONS: Option<u8> = None;
29    const NOP: Option<u8> = None;
30}
31
32impl<'a> OptionsImpl<'a> for ControlOptionsImpl {
33    type Option = ControlOption;
34
35    fn parse(kind: u8, data: &[u8]) -> Result<Option<ControlOption>, ()> {
36        match kind {
37            Self::TYPE_INTERFACE_IDENTIFIER => {
38                if data.len() == 8 {
39                    Ok(Some(ControlOption::InterfaceIdentifier(NetworkEndian::read_u64(&data))))
40                } else {
41                    Err(())
42                }
43            }
44            unrecognized => Ok(Some(ControlOption::Unrecognized(unrecognized, data.to_vec()))),
45        }
46    }
47}
48
49impl<'a> OptionsSerializerImpl<'a> for ControlOptionsImpl {
50    type Option = ControlOption;
51
52    fn get_option_length(option: &Self::Option) -> usize {
53        match option {
54            ControlOption::Unrecognized(_, data) => data.len(),
55            ControlOption::InterfaceIdentifier(_) => 8,
56        }
57    }
58
59    fn get_option_kind(option: &Self::Option) -> u8 {
60        match option {
61            ControlOption::Unrecognized(kind, _) => *kind,
62            ControlOption::InterfaceIdentifier(_) => Self::TYPE_INTERFACE_IDENTIFIER,
63        }
64    }
65
66    fn serialize(data: &mut [u8], option: &Self::Option) {
67        match option {
68            ControlOption::Unrecognized(_, unrecognized_data) => {
69                data.copy_from_slice(&unrecognized_data);
70            }
71            ControlOption::InterfaceIdentifier(identifier) => {
72                NetworkEndian::write_u64(data, *identifier)
73            }
74        }
75    }
76}