zero_packet/network/extensions/
routing.rs1use core::fmt;
2
3pub const ROUTING_HEADER_MIN_LEN: usize = 8;
5
6pub struct RoutingHeaderWriter<'a> {
8 pub bytes: &'a mut [u8],
9}
10
11impl<'a> RoutingHeaderWriter<'a> {
12 #[inline]
14 pub fn new(bytes: &'a mut [u8]) -> Result<Self, &'static str> {
15 if bytes.len() < ROUTING_HEADER_MIN_LEN {
16 return Err("Slice is too short to contain a Routing extension header.");
17 }
18
19 Ok(Self { bytes })
20 }
21
22 #[inline]
24 pub fn header_len(&self) -> usize {
25 (self.bytes[1] as usize + 1) * 8
26 }
27
28 #[inline]
32 pub fn set_next_header(&mut self, next_header: u8) {
33 self.bytes[0] = next_header;
34 }
35
36 #[inline]
42 pub fn set_header_ext_len(&mut self, header_ext_len: u8) {
43 self.bytes[1] = header_ext_len;
44 }
45
46 #[inline]
55 pub fn set_routing_type(&mut self, routing_type: u8) {
56 self.bytes[2] = routing_type;
57 }
58
59 #[inline]
63 pub fn set_segments_left(&mut self, segments_left: u8) {
64 self.bytes[3] = segments_left;
65 }
66
67 #[inline]
75 pub fn set_data(&mut self, data: &[u8]) -> Result<(), &'static str> {
76 if data.len() < 4 {
77 return Err("Type-specific data must be at least 4 bytes long.");
78 }
79
80 let extension_len = self.bytes[1] as usize * 8;
81
82 if extension_len != data.len() {
83 return Err("Type-specific data length must match the header extension length.");
84 }
85
86 let start_offset = 8;
87 let end_offset = start_offset + data.len();
88
89 if end_offset > self.bytes.len() {
90 return Err("Type-specific data exceeds the allocated header length.");
91 }
92
93 self.bytes[start_offset..end_offset].copy_from_slice(data);
94
95 Ok(())
96 }
97}
98
99pub struct RoutingHeaderReader<'a> {
101 pub bytes: &'a [u8],
102}
103
104impl<'a> RoutingHeaderReader<'a> {
105 #[inline]
107 pub fn new(bytes: &'a [u8]) -> Result<Self, &'static str> {
108 if bytes.len() < ROUTING_HEADER_MIN_LEN {
109 return Err("Slice is too short to contain a Routing extension header.");
110 }
111
112 Ok(Self { bytes })
113 }
114
115 #[inline]
119 pub fn next_header(&self) -> u8 {
120 self.bytes[0]
121 }
122
123 #[inline]
129 pub fn header_ext_len(&self) -> u8 {
130 self.bytes[1]
131 }
132
133 #[inline]
142 pub fn routing_type(&self) -> u8 {
143 self.bytes[2]
144 }
145
146 #[inline]
150 pub fn segments_left(&self) -> u8 {
151 self.bytes[3]
152 }
153
154 #[inline]
156 pub fn data(&self) -> &[u8] {
157 let start = 4;
158 let end = self.header_len();
159 &self.bytes[start..end]
160 }
161
162 #[inline]
164 pub fn header_len(&self) -> usize {
165 (self.bytes[1] as usize + 1) * 8
166 }
167
168 #[inline]
172 pub fn header(&self) -> Result<&'a [u8], &'static str> {
173 let end = self.header_len();
174
175 if end > self.bytes.len() {
176 return Err("Indicated IPv6 routing header length exceeds the allocated buffer.");
177 }
178
179 Ok(&self.bytes[..end])
180 }
181
182 #[inline]
186 pub fn payload(&self) -> Result<&'a [u8], &'static str> {
187 let start = self.header_len();
188
189 if start > self.bytes.len() {
190 return Err("Indicated IPv6 routing header length exceeds the allocated buffer.");
191 }
192
193 Ok(&self.bytes[self.header_len()..])
194 }
195}
196
197impl fmt::Debug for RoutingHeaderReader<'_> {
198 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
199 f.debug_struct("RoutingExtensionHeader")
200 .field("next_header", &self.next_header())
201 .field("header_ext_len", &self.header_ext_len())
202 .field("routing_type", &self.routing_type())
203 .field("segments_left", &self.segments_left())
204 .field("data", &self.data())
205 .finish()
206 }
207}
208
209#[cfg(test)]
210pub mod tests {
211 use super::*;
212
213 #[test]
214 fn getters_and_setters() {
215 let mut bytes = [0u8; 16];
217
218 let next_header = 6;
220 let header_ext_len = 1; let routing_type = 2;
222 let segments_left = 3;
223 let data = [4, 5, 6, 7, 8, 9, 10, 11];
224
225 let mut writer = RoutingHeaderWriter::new(&mut bytes).unwrap();
227 writer.set_next_header(next_header);
228 writer.set_header_ext_len(header_ext_len);
229 writer.set_routing_type(routing_type);
230 writer.set_segments_left(segments_left);
231 writer.set_data(&data).unwrap();
232
233 let reader = RoutingHeaderReader::new(&bytes).unwrap();
235 assert_eq!(reader.next_header(), next_header);
236 assert_eq!(reader.header_ext_len(), header_ext_len);
237 assert_eq!(reader.routing_type(), routing_type);
238 assert_eq!(reader.segments_left(), segments_left);
239 assert_eq!(reader.data(), [0, 0, 0, 0, 4, 5, 6, 7, 8, 9, 10, 11]);
240 }
241}