zero_packet/network/extensions/
headers.rs1use super::{
2 authentication::AuthenticationHeaderReader, fragment::FragmentHeaderReader,
3 options::OptionsHeaderReader, routing::RoutingHeaderReader,
4};
5use crate::misc::NextHeader;
6
7#[derive(Debug)]
19pub struct ExtensionHeaders<'a> {
20 pub hop_by_hop: Option<OptionsHeaderReader<'a>>,
21 pub routing: Option<RoutingHeaderReader<'a>>,
22 pub fragment: Option<FragmentHeaderReader<'a>>,
23 pub auth_header: Option<AuthenticationHeaderReader<'a>>,
24 pub destination_1st: Option<OptionsHeaderReader<'a>>,
25 pub destination_2nd: Option<OptionsHeaderReader<'a>>,
26 pub total_headers_len: usize,
27 pub final_next_header: u8,
28}
29
30impl<'a> ExtensionHeaders<'a> {
31 #[inline]
33 fn new() -> Self {
34 Self {
35 hop_by_hop: None,
36 routing: None,
37 fragment: None,
38 auth_header: None,
39 destination_1st: None,
40 destination_2nd: None,
41 total_headers_len: 0,
42 final_next_header: 0,
43 }
44 }
45 #[inline]
51 pub fn parse(bytes: &'a [u8], next_header: u8) -> Result<Option<Self>, &'static str> {
52 let mut headers = Self::new();
53
54 let mut current_header = next_header;
55 let mut current_bytes = bytes;
56
57 while let Some((next_header, payload)) =
58 headers.parse_next_header(current_header, current_bytes)?
59 {
60 current_header = next_header;
61 current_bytes = payload;
62 }
63
64 if headers.is_empty() {
65 Ok(None)
66 } else {
67 Ok(Some(headers))
68 }
69 }
70
71 #[inline]
73 fn parse_next_header(
74 &mut self,
75 next_header: u8,
76 bytes: &'a [u8],
77 ) -> Result<Option<(u8, &'a [u8])>, &'static str> {
78 match NextHeader::from(next_header) {
79 NextHeader::HopByHop => self.parse_hop_by_hop_options(bytes),
80 NextHeader::Routing => self.parse_routing_header(bytes),
81 NextHeader::Fragment => self.parse_fragment_header(bytes),
82 NextHeader::AuthHeader => self.parse_auth_header(bytes),
83 NextHeader::Destination => self.parse_destination_options(bytes),
84 _ => Ok(None),
85 }
86 }
87
88 #[inline]
90 fn parse_hop_by_hop_options(
91 &mut self,
92 bytes: &'a [u8],
93 ) -> Result<Option<(u8, &'a [u8])>, &'static str> {
94 if self.hop_by_hop.is_some() {
95 return Ok(None);
96 }
97
98 if !self.is_empty() {
99 return Err(
100 "If Hop-by-Hop Options is present, then it must be the first extension header.",
101 );
102 }
103
104 let reader = OptionsHeaderReader::new(bytes)?;
105 let next_header = reader.next_header();
106 let payload = reader.payload()?;
107
108 self.total_headers_len += reader.header_len();
109 self.final_next_header = next_header;
110 self.hop_by_hop = Some(reader);
111
112 Ok(Some((next_header, payload)))
113 }
114
115 #[inline]
117 fn parse_routing_header(
118 &mut self,
119 bytes: &'a [u8],
120 ) -> Result<Option<(u8, &'a [u8])>, &'static str> {
121 if self.routing.is_some() {
122 return Ok(None);
123 }
124
125 let reader = RoutingHeaderReader::new(bytes)?;
126 let next_header = reader.next_header();
127 let payload = reader.payload()?;
128
129 self.total_headers_len += reader.header_len();
130 self.final_next_header = next_header;
131 self.routing = Some(reader);
132
133 Ok(Some((next_header, payload)))
134 }
135
136 #[inline]
138 fn parse_fragment_header(
139 &mut self,
140 bytes: &'a [u8],
141 ) -> Result<Option<(u8, &'a [u8])>, &'static str> {
142 if self.fragment.is_some() {
143 return Ok(None);
144 }
145
146 let reader = FragmentHeaderReader::new(bytes)?;
147 let next_header = reader.next_header();
148 let payload = reader.payload();
149
150 self.total_headers_len += reader.header_len();
151 self.final_next_header = next_header;
152 self.fragment = Some(reader);
153
154 Ok(Some((next_header, payload)))
155 }
156
157 #[inline]
159 fn parse_auth_header(
160 &mut self,
161 bytes: &'a [u8],
162 ) -> Result<Option<(u8, &'a [u8])>, &'static str> {
163 if self.auth_header.is_some() {
164 return Ok(None);
165 }
166
167 let reader = AuthenticationHeaderReader::new(bytes)?;
168 let next_header = reader.next_header();
169 let payload = reader.payload()?;
170
171 self.total_headers_len += reader.header_len();
172 self.final_next_header = next_header;
173 self.auth_header = Some(reader);
174
175 Ok(Some((next_header, payload)))
176 }
177
178 #[inline]
180 fn parse_destination_options(
181 &mut self,
182 bytes: &'a [u8],
183 ) -> Result<Option<(u8, &'a [u8])>, &'static str> {
184 if self.destination_2nd.is_some() {
185 return Ok(None);
186 }
187
188 let reader = OptionsHeaderReader::new(bytes)?;
189 let next_header = reader.next_header();
190 let payload = reader.payload()?;
191
192 self.total_headers_len += reader.header_len();
193 self.final_next_header = next_header;
194
195 if self.destination_1st.is_none() {
196 self.destination_1st = Some(reader);
197 } else {
198 self.destination_2nd = Some(reader);
199 }
200
201 Ok(Some((next_header, payload)))
202 }
203
204 #[inline]
206 fn is_empty(&self) -> bool {
207 self.hop_by_hop.is_none()
208 && self.routing.is_none()
209 && self.fragment.is_none()
210 && self.auth_header.is_none()
211 && self.destination_1st.is_none()
212 && self.destination_2nd.is_none()
213 }
214}