domain_core/bits/opt/
rfc7871.rs

1//! EDNS Options from RFC 7871
2
3use 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//------------ ClientSubnet --------------------------------------------------
13
14#[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
39//--- ParseAll and Compose
40
41
42impl 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
103//--- CodeOptData
104
105impl CodeOptData for ClientSubnet {
106    const CODE: OptionCode = OptionCode::ClientSubnet;
107}
108
109
110//------------ ClientSubnetParseError ----------------------------------------
111
112#[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