ppp_packet/
ipv4.rs
1use crate::records::options::{OptionsImpl, OptionsImplLayout, OptionsSerializerImpl};
8use byteorder::{ByteOrder, NetworkEndian};
9
10#[derive(Clone, Eq, Hash, PartialEq, Debug)]
12pub enum ControlOption {
13 Unrecognized(u8, Vec<u8>),
15 IpCompressionProtocol(u16, Vec<u8>),
18 IpAddress(u32),
20}
21
22pub struct ControlOptionsImpl;
24
25impl ControlOptionsImpl {
26 const TYPE_IP_COMPRESSION_PROTOCOL: u8 = 2;
27 const TYPE_IP_ADDRESS: u8 = 3;
28}
29
30impl OptionsImplLayout for ControlOptionsImpl {
31 type Error = ();
32 const END_OF_OPTIONS: Option<u8> = None;
33 const NOP: Option<u8> = None;
34}
35
36impl<'a> OptionsImpl<'a> for ControlOptionsImpl {
37 type Option = ControlOption;
38
39 fn parse(kind: u8, data: &[u8]) -> Result<Option<ControlOption>, ()> {
40 match kind {
41 Self::TYPE_IP_COMPRESSION_PROTOCOL => {
42 if data.len() >= 2 {
43 Ok(Some(ControlOption::IpCompressionProtocol(
44 NetworkEndian::read_u16(&data),
45 data[2..].to_vec(),
46 )))
47 } else {
48 Err(())
49 }
50 }
51 Self::TYPE_IP_ADDRESS => {
52 if data.len() == 4 {
53 Ok(Some(ControlOption::IpAddress(NetworkEndian::read_u32(&data))))
54 } else {
55 Err(())
56 }
57 }
58 unrecognized => Ok(Some(ControlOption::Unrecognized(unrecognized, data[..].to_vec()))),
59 }
60 }
61}
62
63impl<'a> OptionsSerializerImpl<'a> for ControlOptionsImpl {
64 type Option = ControlOption;
65
66 fn get_option_length(option: &Self::Option) -> usize {
67 match option {
68 ControlOption::Unrecognized(_, data) => data.len(),
69 ControlOption::IpCompressionProtocol(_, data) => 2 + data.len(),
70 ControlOption::IpAddress(_) => 4,
71 }
72 }
73
74 fn get_option_kind(option: &Self::Option) -> u8 {
75 match option {
76 ControlOption::Unrecognized(kind, _) => *kind,
77 ControlOption::IpCompressionProtocol(_, _) => Self::TYPE_IP_COMPRESSION_PROTOCOL,
78 ControlOption::IpAddress(_) => Self::TYPE_IP_ADDRESS,
79 }
80 }
81
82 fn serialize(data: &mut [u8], option: &Self::Option) {
83 match option {
84 ControlOption::Unrecognized(_, unrecognized_data) => {
85 data.copy_from_slice(&unrecognized_data);
86 }
87 ControlOption::IpCompressionProtocol(protocol, protocol_data) => {
88 NetworkEndian::write_u16(data, *protocol);
89 data[2..].copy_from_slice(&protocol_data);
90 }
91 ControlOption::IpAddress(address) => NetworkEndian::write_u32(data, *address),
92 }
93 }
94}