trust_dns_proto/rr/rdata/hinfo.rs
1// Copyright 2015-2021 Benjamin Fry <benjaminfry@me.com>
2//
3// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
4// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
5// http://opensource.org/licenses/MIT>, at your option. This file may not be
6// copied, modified, or distributed except according to those terms.
7
8//! HINFO record for storing host information
9
10use std::fmt;
11
12#[cfg(feature = "serde-config")]
13use serde::{Deserialize, Serialize};
14
15use crate::error::*;
16use crate::serialize::binary::*;
17
18/// [RFC 1035, DOMAIN NAMES - IMPLEMENTATION AND SPECIFICATION, November 1987][rfc1035]
19///
20/// ```text
21/// 3.3.2. HINFO RDATA format
22///
23/// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
24/// / CPU /
25/// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
26/// / OS /
27/// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
28///
29/// where:
30///
31/// CPU A <character-string> which specifies the CPU type.
32///
33/// OS A <character-string> which specifies the operating
34/// system type.
35///
36/// Standard values for CPU and OS can be found in [RFC-1010].
37///
38/// HINFO records are used to acquire general information about a host. The
39/// main use is for protocols such as FTP that can use special procedures
40/// when talking between machines or operating systems of the same type.
41/// ```
42///
43/// [rfc1035]: https://tools.ietf.org/html/rfc1035
44#[cfg_attr(feature = "serde-config", derive(Deserialize, Serialize))]
45#[derive(Debug, PartialEq, Eq, Hash, Clone)]
46pub struct HINFO {
47 cpu: Box<[u8]>,
48 os: Box<[u8]>,
49}
50
51impl HINFO {
52 /// Creates a new HINFO record data.
53 ///
54 /// # Arguments
55 ///
56 /// * `cpu` - A <character-string> which specifies the CPU type.
57 /// * `os` - A <character-string> which specifies the operating system type.
58 ///
59 /// # Return value
60 ///
61 /// The new HINFO record data.
62 pub fn new(cpu: String, os: String) -> Self {
63 Self {
64 cpu: cpu.into_bytes().into_boxed_slice(),
65 os: os.into_bytes().into_boxed_slice(),
66 }
67 }
68
69 /// Creates a new HINFO record data from bytes.
70 /// Allows creating binary record data.
71 ///
72 /// # Arguments
73 ///
74 /// * `cpu` - A <character-string> which specifies the CPU type.
75 /// * `os` - A <character-string> which specifies the operating system type.
76 ///
77 /// # Return value
78 ///
79 /// The new HINFO record data.
80 pub fn from_bytes(cpu: Box<[u8]>, os: Box<[u8]>) -> Self {
81 Self { cpu, os }
82 }
83
84 /// A <character-string> which specifies the CPU type.
85 pub fn cpu(&self) -> &[u8] {
86 &self.cpu
87 }
88
89 /// A <character-string> which specifies the operating system type.
90 pub fn os(&self) -> &[u8] {
91 &self.os
92 }
93}
94
95/// Read the RData from the given Decoder
96pub fn read(decoder: &mut BinDecoder<'_>) -> ProtoResult<HINFO> {
97 let cpu = decoder.read_character_data()?
98 .unverified(/*any data should be validate in HINFO CPU usage*/)
99 .to_vec()
100 .into_boxed_slice();
101 let os = decoder.read_character_data()?
102 .unverified(/*any data should be validate in HINFO OS usage*/)
103 .to_vec()
104 .into_boxed_slice();
105
106 Ok(HINFO { cpu, os })
107}
108
109/// Write the RData from the given Decoder
110pub fn emit(encoder: &mut BinEncoder<'_>, hinfo: &HINFO) -> ProtoResult<()> {
111 encoder.emit_character_data(&hinfo.cpu)?;
112 encoder.emit_character_data(&hinfo.os)?;
113
114 Ok(())
115}
116
117/// [RFC 1033](https://tools.ietf.org/html/rfc1033), DOMAIN OPERATIONS GUIDE, November 1987
118///
119/// ```text
120/// HINFO (Host Info)
121///
122/// <host> [<ttl>] [<class>] HINFO <hardware> <software>
123///
124/// The HINFO record gives information about a particular host. The data
125/// is two strings separated by whitespace. The first string is a
126/// hardware description and the second is software. The hardware is
127/// usually a manufacturer name followed by a dash and model designation.
128/// The software string is usually the name of the operating system.
129///
130/// Official HINFO types can be found in the latest Assigned Numbers RFC,
131/// the latest of which is RFC-1010. The Hardware type is called the
132/// Machine name and the Software type is called the System name.
133///
134/// Some sample HINFO records:
135///
136/// SRI-NIC.ARPA. HINFO DEC-2060 TOPS20
137/// UCBARPA.Berkeley.EDU. HINFO VAX-11/780 UNIX
138/// ```
139impl fmt::Display for HINFO {
140 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
141 write!(
142 f,
143 "{cpu} {os}",
144 cpu = &String::from_utf8_lossy(&self.cpu),
145 os = &String::from_utf8_lossy(&self.os)
146 )?;
147 Ok(())
148 }
149}
150
151#[cfg(test)]
152mod tests {
153 #![allow(clippy::dbg_macro, clippy::print_stdout)]
154
155 use super::*;
156
157 #[test]
158 fn test() {
159 let rdata = HINFO::new("cpu".to_string(), "os".to_string());
160
161 let mut bytes = Vec::new();
162 let mut encoder: BinEncoder<'_> = BinEncoder::new(&mut bytes);
163 assert!(emit(&mut encoder, &rdata).is_ok());
164 let bytes = encoder.into_bytes();
165
166 println!("bytes: {:?}", bytes);
167
168 let mut decoder: BinDecoder<'_> = BinDecoder::new(bytes);
169 let read_rdata = read(&mut decoder).expect("Decoding error");
170 assert_eq!(rdata, read_rdata);
171 }
172
173 #[test]
174 fn test_binary() {
175 let bin_data = vec![0, 1, 2, 3, 4, 5, 6, 7, 8];
176 let rdata = HINFO::from_bytes(
177 b"cpu".to_vec().into_boxed_slice(),
178 bin_data.into_boxed_slice(),
179 );
180
181 let mut bytes = Vec::new();
182 let mut encoder: BinEncoder<'_> = BinEncoder::new(&mut bytes);
183 assert!(emit(&mut encoder, &rdata).is_ok());
184 let bytes = encoder.into_bytes();
185
186 println!("bytes: {:?}", bytes);
187
188 let mut decoder: BinDecoder<'_> = BinDecoder::new(bytes);
189 let read_rdata = read(&mut decoder).expect("Decoding error");
190 assert_eq!(rdata, read_rdata);
191 }
192}