blob: a64b8d66df769fdfc03befbd64b1c68db06b60cd [file] [log] [blame]
// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//! Utilities for parsing and serializing IPV6CP options.
use {
crate::records::options::{OptionsImpl, OptionsImplLayout, OptionsSerializerImpl},
byteorder::{ByteOrder, NetworkEndian},
};
/// An IPV6CP control option.
#[derive(Clone, Eq, Hash, PartialEq, Debug)]
pub enum ControlOption {
/// Any sequence of bytes not recognized as a valid option.
Unrecognized(u8, Vec<u8>),
/// 64-bit identifier which is very likely to be unique on the link.
InterfaceIdentifier(u64),
}
/// Implementation of the IPV6CP control options parsing and serialization.
pub struct ControlOptionsImpl;
impl ControlOptionsImpl {
const TYPE_INTERFACE_IDENTIFIER: u8 = 1;
}
impl OptionsImplLayout for ControlOptionsImpl {
type Error = ();
const END_OF_OPTIONS: Option<u8> = None;
const NOP: Option<u8> = None;
}
impl<'a> OptionsImpl<'a> for ControlOptionsImpl {
type Option = ControlOption;
fn parse(kind: u8, data: &[u8]) -> Result<Option<ControlOption>, ()> {
match kind {
Self::TYPE_INTERFACE_IDENTIFIER => {
if data.len() == 8 {
Ok(Some(ControlOption::InterfaceIdentifier(NetworkEndian::read_u64(&data))))
} else {
Err(())
}
}
unrecognized => Ok(Some(ControlOption::Unrecognized(unrecognized, data.to_vec()))),
}
}
}
impl<'a> OptionsSerializerImpl<'a> for ControlOptionsImpl {
type Option = ControlOption;
fn get_option_length(option: &Self::Option) -> usize {
match option {
ControlOption::Unrecognized(_, data) => data.len(),
ControlOption::InterfaceIdentifier(_) => 8,
}
}
fn get_option_kind(option: &Self::Option) -> u8 {
match option {
ControlOption::Unrecognized(kind, _) => *kind,
ControlOption::InterfaceIdentifier(_) => Self::TYPE_INTERFACE_IDENTIFIER,
}
}
fn serialize(data: &mut [u8], option: &Self::Option) {
match option {
ControlOption::Unrecognized(_, unrecognized_data) => {
data.copy_from_slice(&unrecognized_data);
}
ControlOption::InterfaceIdentifier(identifier) => {
NetworkEndian::write_u64(data, *identifier)
}
}
}
}