simple_dns/dns/rdata/
ipseckey.rs1use crate::{bytes_buffer::BytesBuffer, dns::WireFormat, Name};
2use std::{
3 borrow::Cow,
4 net::{Ipv4Addr, Ipv6Addr},
5};
6
7use super::RR;
8
9#[derive(Debug, PartialEq, Eq, Hash, Clone)]
11pub struct IPSECKEY<'a> {
12 pub precedence: u8,
14 pub algorithm: u8,
16 pub gateway: Gateway<'a>,
18 pub public_key: Cow<'a, [u8]>,
20}
21
22#[derive(Debug, PartialEq, Eq, Hash, Clone)]
24pub enum Gateway<'a> {
25 None,
27 IPv4(Ipv4Addr),
29 IPv6(Ipv6Addr),
31 Domain(Name<'a>),
33}
34
35impl Gateway<'_> {
36 pub fn into_owned<'b>(self) -> Gateway<'b> {
38 match self {
39 Gateway::None => Gateway::None,
40 Gateway::IPv4(x) => Gateway::IPv4(x),
41 Gateway::IPv6(x) => Gateway::IPv6(x),
42 Gateway::Domain(x) => Gateway::Domain(x.into_owned()),
43 }
44 }
45}
46
47impl RR for IPSECKEY<'_> {
48 const TYPE_CODE: u16 = 45;
49}
50
51impl<'a> WireFormat<'a> for IPSECKEY<'a> {
52 const MINIMUM_LEN: usize = 5;
53
54 fn parse(data: &mut BytesBuffer<'a>) -> crate::Result<Self>
55 where
56 Self: Sized,
57 {
58 let precedence = data.get_u8()?;
59 let gateway_type = data.get_u8()?;
60 let algorithm = data.get_u8()?;
61 let gateway = match gateway_type {
62 0 => Gateway::None,
63 1 => Gateway::IPv4(data.get_u32()?.into()),
64 2 => Gateway::IPv6(data.get_u128()?.into()),
65 3 => Gateway::Domain(Name::parse(data)?),
66 _ => return Err(crate::SimpleDnsError::AttemptedInvalidOperation),
67 };
68 let public_key = data.get_remaining();
69 Ok(Self {
70 precedence,
71 algorithm,
72 gateway,
73 public_key: Cow::Borrowed(public_key),
74 })
75 }
76
77 fn write_to<T: std::io::Write>(&self, out: &mut T) -> crate::Result<()> {
78 match &self.gateway {
79 Gateway::None => {
80 out.write_all(&[self.precedence, 0, self.algorithm])?;
81 }
82 Gateway::IPv4(ipv4_addr) => {
83 out.write_all(&[self.precedence, 1, self.algorithm])?;
84 out.write_all(&ipv4_addr.octets())?
85 }
86 Gateway::IPv6(ipv6_addr) => {
87 out.write_all(&[self.precedence, 2, self.algorithm])?;
88 out.write_all(&ipv6_addr.octets())?
89 }
90 Gateway::Domain(name) => {
91 out.write_all(&[self.precedence, 3, self.algorithm])?;
92 name.write_to(out)?
93 }
94 };
95 out.write_all(&self.public_key)?;
96 Ok(())
97 }
98
99 fn len(&self) -> usize {
100 (match &self.gateway {
101 Gateway::None => 0,
102 Gateway::IPv4(_) => 4,
103 Gateway::IPv6(_) => 16,
104 Gateway::Domain(name) => name.len(),
105 }) + self.public_key.len()
106 + Self::MINIMUM_LEN
107 }
108}
109
110impl IPSECKEY<'_> {
111 pub fn into_owned<'b>(self) -> IPSECKEY<'b> {
113 IPSECKEY {
114 precedence: self.precedence,
115 algorithm: self.algorithm,
116 gateway: self.gateway.into_owned(),
117 public_key: self.public_key.into_owned().into(),
118 }
119 }
120}
121
122#[cfg(test)]
123mod tests {
124 use crate::{rdata::RData, ResourceRecord};
125
126 use super::*;
127
128 #[test]
129 fn parse_and_write_ipseckey() {
130 let ipseckey = IPSECKEY {
131 precedence: 10,
132 algorithm: 2,
133 gateway: Gateway::IPv4(Ipv4Addr::new(192,0,2,38)),
134 public_key: Cow::Borrowed(b"\x01\x03\x51\x53\x79\x86\xed\x35\x53\x3b\x60\x64\x47\x8e\xee\xb2\x7b\x5b\xd7\x4d\xae\x14\x9b\x6e\x81\xba\x3a\x05\x21\xaf\x82\xab\x78\x01"),
135 };
136
137 let mut data = Vec::new();
138 ipseckey.write_to(&mut data).unwrap();
139
140 let ipseckey = IPSECKEY::parse(&mut (&data[..]).into()).unwrap();
141 assert_eq!(ipseckey.precedence, 10);
142 assert_eq!(ipseckey.algorithm, 2);
143 assert_eq!(
144 ipseckey.gateway,
145 Gateway::IPv4(Ipv4Addr::new(192, 0, 2, 38))
146 );
147 assert_eq!(*ipseckey.public_key, *b"\x01\x03\x51\x53\x79\x86\xed\x35\x53\x3b\x60\x64\x47\x8e\xee\xb2\x7b\x5b\xd7\x4d\xae\x14\x9b\x6e\x81\xba\x3a\x05\x21\xaf\x82\xab\x78\x01");
148 }
149
150 #[test]
151 fn parse_sample() -> Result<(), Box<dyn std::error::Error>> {
152 let sample_file = std::fs::read("samples/zonefile/IPSECKEY.sample")?;
153
154 let sample_rdata = match ResourceRecord::parse(&mut (&sample_file[..]).into())?.rdata {
155 RData::IPSECKEY(rdata) => rdata,
156 _ => unreachable!(),
157 };
158
159 assert_eq!(sample_rdata.precedence, 10);
160 assert_eq!(sample_rdata.algorithm, 2);
161 assert_eq!(
162 sample_rdata.gateway,
163 Gateway::IPv4(Ipv4Addr::new(192, 0, 2, 38))
164 );
165 assert_eq!(*sample_rdata.public_key, *b"\x01\x03\x51\x53\x79\x86\xed\x35\x53\x3b\x60\x64\x47\x8e\xee\xb2\x7b\x5b\xd7\x4d\xae\x14\x9b\x6e\x81\xba\x3a\x05\x21\xaf\x82\xab\x78\x01");
166
167 Ok(())
168 }
169}