domain_core/bits/opt/
rfc7871.rs1use std::net::IpAddr;
4use bytes::BufMut;
5use ::bits::compose::Compose;
6use ::bits::message_builder::OptBuilder;
7use ::bits::parse::{ParseAll, Parser, ShortBuf};
8use ::iana::OptionCode;
9use super::CodeOptData;
10
11
12#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
15pub struct ClientSubnet {
16 source_prefix_len: u8,
17 scope_prefix_len: u8,
18 addr: IpAddr,
19}
20
21
22impl ClientSubnet {
23 pub fn new(source_prefix_len: u8, scope_prefix_len: u8, addr: IpAddr)
24 -> ClientSubnet {
25 ClientSubnet { source_prefix_len, scope_prefix_len, addr }
26 }
27
28 pub fn push(builder: &mut OptBuilder, source_prefix_len: u8,
29 scope_prefix_len: u8, addr: IpAddr) -> Result<(), ShortBuf> {
30 builder.push(&Self::new(source_prefix_len, scope_prefix_len, addr))
31 }
32
33 pub fn source_prefix_len(&self) -> u8 { self.source_prefix_len }
34 pub fn scope_prefix_len(&self) -> u8 { self.scope_prefix_len }
35 pub fn addr(&self) -> IpAddr { self.addr }
36}
37
38
39impl ParseAll for ClientSubnet {
43 type Err = OptionParseError;
44
45 fn parse_all(parser: &mut Parser, len: usize) -> Result<Self, Self::Err> {
46 let family = parser.parse_u16()?;
47 let source_prefix_len = parser.parse_u8()?;
48 let scope_prefix_len = parser.parse_u8()?;
49 let addr = match family {
50 1 => {
51 if len != 8 {
52 return Err(OptionParseError::InvalidV4Length(len))
53 }
54 let bytes: &[u8; 4] = unsafe {
55 &*(parser.peek(4)?.as_ptr() as *const [u8; 4])
56 };
57 parser.advance(4)?;
58 IpAddr::from(*bytes)
59 }
60 2 => {
61 if len != 20 {
62 return Err(OptionParseError::InvalidV6Length(len))
63 }
64 let bytes: &[u8; 16] = unsafe {
65 &*(parser.peek(16)?.as_ptr() as *const [u8; 16])
66 };
67 parser.advance(16)?;
68 IpAddr::from(*bytes)
69 }
70 _ => return Err(OptionParseError::InvalidFamily(family))
71 };
72 Ok(ClientSubnet::new(source_prefix_len, scope_prefix_len, addr))
73 }
74}
75
76impl Compose for ClientSubnet {
77 fn compose_len(&self) -> usize {
78 match self.addr {
79 IpAddr::V4(_) => 8,
80 IpAddr::V6(_) => 20,
81 }
82 }
83
84 fn compose<B: BufMut>(&self, buf: &mut B) {
85 match self.addr {
86 IpAddr::V4(addr) => {
87 1u16.compose(buf);
88 self.source_prefix_len.compose(buf);
89 self.scope_prefix_len.compose(buf);
90 buf.put_slice(&addr.octets());
91 }
92 IpAddr::V6(addr) => {
93 2u16.compose(buf);
94 self.source_prefix_len.compose(buf);
95 self.scope_prefix_len.compose(buf);
96 buf.put_slice(&addr.octets());
97 }
98 }
99 }
100}
101
102
103impl CodeOptData for ClientSubnet {
106 const CODE: OptionCode = OptionCode::ClientSubnet;
107}
108
109
110#[derive(Clone, Copy, Debug, Eq, Fail, PartialEq)]
113pub enum OptionParseError {
114 #[fail(display="invalid family {}", _0)]
115 InvalidFamily(u16),
116
117 #[fail(display="invalid length {} for IPv4 address", _0)]
118 InvalidV4Length(usize),
119
120 #[fail(display="invalid length {} for IPv6 address", _0)]
121 InvalidV6Length(usize),
122
123 #[fail(display="unexpected end of buffer")]
124 ShortBuf,
125}
126
127impl From<ShortBuf> for OptionParseError {
128 fn from(_: ShortBuf) -> Self {
129 OptionParseError::ShortBuf
130 }
131}
132