simple_dns/dns/
header_buffer.rs1use crate::{PacketFlag, OPCODE, RCODE};
15
16use super::header::masks;
17
18pub fn id(buffer: &[u8]) -> crate::Result<u16> {
20 buffer[..2]
21 .try_into()
22 .map(u16::from_be_bytes)
23 .map_err(|_| crate::SimpleDnsError::InvalidHeaderData)
24}
25
26pub fn questions(buffer: &[u8]) -> crate::Result<u16> {
28 buffer[4..6]
29 .try_into()
30 .map(u16::from_be_bytes)
31 .map_err(|_| crate::SimpleDnsError::InvalidHeaderData)
32}
33
34#[cfg(test)]
35pub(crate) fn set_questions(buffer: &mut [u8], question_count: u16) {
37 buffer[4..6].copy_from_slice(&question_count.to_be_bytes());
38}
39
40pub fn answers(buffer: &[u8]) -> crate::Result<u16> {
42 buffer[6..8]
43 .try_into()
44 .map(u16::from_be_bytes)
45 .map_err(|_| crate::SimpleDnsError::InvalidHeaderData)
46}
47
48#[cfg(test)]
49pub(crate) fn set_answers(buffer: &mut [u8], answers_count: u16) {
51 buffer[6..8].copy_from_slice(&answers_count.to_be_bytes());
52}
53
54pub fn name_servers(buffer: &[u8]) -> crate::Result<u16> {
56 buffer[8..10]
57 .try_into()
58 .map(u16::from_be_bytes)
59 .map_err(|_| crate::SimpleDnsError::InvalidHeaderData)
60}
61
62#[cfg(test)]
63pub(crate) fn set_name_servers(buffer: &mut [u8], name_servers_count: u16) {
65 buffer[8..10].copy_from_slice(&name_servers_count.to_be_bytes());
66}
67
68pub fn additional_records(buffer: &[u8]) -> crate::Result<u16> {
70 buffer[10..12]
71 .try_into()
72 .map(u16::from_be_bytes)
73 .map_err(|_| crate::SimpleDnsError::InvalidHeaderData)
74}
75
76#[cfg(test)]
77pub(crate) fn set_additional_records(buffer: &mut [u8], additional_records_count: u16) {
79 buffer[10..12].copy_from_slice(&additional_records_count.to_be_bytes());
80}
81
82#[allow(dead_code)]
83pub(crate) fn set_flags(buffer: &mut [u8], flags: PacketFlag) -> crate::Result<()> {
85 let mut current_flags = buffer[2..4]
86 .try_into()
87 .map(u16::from_be_bytes)
88 .map_err(|_| crate::SimpleDnsError::InvalidHeaderData)?;
89
90 current_flags |= flags.bits();
91
92 buffer[2..4].copy_from_slice(¤t_flags.to_be_bytes());
93
94 Ok(())
95}
96
97#[allow(dead_code)]
98pub(crate) fn remove_flags(buffer: &mut [u8], flags: PacketFlag) -> crate::Result<()> {
100 let mut current_flags = buffer[2..4]
101 .try_into()
102 .map(u16::from_be_bytes)
103 .map_err(|_| crate::SimpleDnsError::InvalidHeaderData)?;
104
105 current_flags ^= flags.bits();
106
107 buffer[2..4].copy_from_slice(¤t_flags.to_be_bytes());
108
109 Ok(())
110}
111
112pub fn has_flags(buffer: &[u8], flags: PacketFlag) -> crate::Result<bool> {
115 buffer[2..4]
116 .try_into()
117 .map(u16::from_be_bytes)
118 .map(|bits| PacketFlag::from_bits_truncate(bits).contains(flags))
119 .map_err(|_| crate::SimpleDnsError::InvalidHeaderData)
120}
121
122pub fn rcode(buffer: &[u8]) -> crate::Result<RCODE> {
125 buffer[2..4]
126 .try_into()
127 .map(u16::from_be_bytes)
128 .map(|flags| (flags & masks::RESPONSE_CODE_MASK).into())
129 .map_err(|_| crate::SimpleDnsError::InvalidHeaderData)
130}
131
132pub fn opcode(buffer: &[u8]) -> crate::Result<OPCODE> {
134 buffer[2..4]
135 .try_into()
136 .map(u16::from_be_bytes)
137 .map(|flags| ((flags & masks::OPCODE_MASK) >> masks::OPCODE_MASK.trailing_zeros()).into())
138 .map_err(|_| crate::SimpleDnsError::InvalidHeaderData)
139}
140
141#[cfg(test)]
142mod tests {
143 use super::*;
144
145 #[test]
146 fn read_write_questions_count() {
147 let mut buffer = [0u8; 12];
148 set_questions(&mut buffer, 1);
149 assert_eq!(1, questions(&buffer).unwrap());
150 }
151
152 #[test]
153 fn read_write_answers_count() {
154 let mut buffer = [0u8; 12];
155 set_answers(&mut buffer, 1);
156 assert_eq!(1, answers(&buffer).unwrap());
157 }
158
159 #[test]
160 fn read_write_name_servers_count() {
161 let mut buffer = [0u8; 12];
162 set_name_servers(&mut buffer, 1);
163 assert_eq!(1, name_servers(&buffer).unwrap());
164 }
165
166 #[test]
167 fn read_write_additional_records_count() {
168 let mut buffer = [0u8; 12];
169 set_additional_records(&mut buffer, 1);
170 assert_eq!(1, additional_records(&buffer).unwrap());
171 }
172}