1use crate::ip::IpNextLevelProtocol;
4
5use alloc::vec::Vec;
6
7use xenet_macro::packet;
8use xenet_macro_helper::types::*;
9
10use std::net::Ipv6Addr;
11
12#[cfg(feature = "serde")]
13use serde::{Deserialize, Serialize};
14
15pub const IPV6_HEADER_LEN: usize = MutableIpv6Packet::minimum_packet_size();
17
18#[derive(Clone, Debug, PartialEq, Eq)]
20#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
21pub struct Ipv6Header {
22 pub version: u4,
23 pub traffic_class: u8,
24 pub flow_label: u20be,
25 pub payload_length: u16be,
26 pub next_header: IpNextLevelProtocol,
27 pub hop_limit: u8,
28 pub source: Ipv6Addr,
29 pub destination: Ipv6Addr,
30}
31
32impl Ipv6Header {
33 pub fn from_bytes(packet: &[u8]) -> Result<Ipv6Header, String> {
35 if packet.len() < IPV6_HEADER_LEN {
36 return Err("Packet is too small for IPv6 header".to_string());
37 }
38 match Ipv6Packet::new(packet) {
39 Some(ipv6_packet) => Ok(Ipv6Header {
40 version: ipv6_packet.get_version(),
41 traffic_class: ipv6_packet.get_traffic_class(),
42 flow_label: ipv6_packet.get_flow_label(),
43 payload_length: ipv6_packet.get_payload_length(),
44 next_header: ipv6_packet.get_next_header(),
45 hop_limit: ipv6_packet.get_hop_limit(),
46 source: ipv6_packet.get_source(),
47 destination: ipv6_packet.get_destination(),
48 }),
49 None => Err("Failed to parse IPv6 packet".to_string()),
50 }
51 }
52 pub(crate) fn from_packet(ipv6_packet: &Ipv6Packet) -> Ipv6Header {
54 Ipv6Header {
55 version: ipv6_packet.get_version(),
56 traffic_class: ipv6_packet.get_traffic_class(),
57 flow_label: ipv6_packet.get_flow_label(),
58 payload_length: ipv6_packet.get_payload_length(),
59 next_header: ipv6_packet.get_next_header(),
60 hop_limit: ipv6_packet.get_hop_limit(),
61 source: ipv6_packet.get_source(),
62 destination: ipv6_packet.get_destination(),
63 }
64 }
65}
66
67#[packet]
69pub struct Ipv6 {
70 pub version: u4,
71 pub traffic_class: u8,
72 pub flow_label: u20be,
73 pub payload_length: u16be,
74 #[construct_with(u8)]
75 pub next_header: IpNextLevelProtocol,
76 pub hop_limit: u8,
77 #[construct_with(u16, u16, u16, u16, u16, u16, u16, u16)]
78 pub source: Ipv6Addr,
79 #[construct_with(u16, u16, u16, u16, u16, u16, u16, u16)]
80 pub destination: Ipv6Addr,
81 #[length = "payload_length"]
82 #[payload]
83 pub payload: Vec<u8>,
84}
85
86impl<'p> ExtensionIterable<'p> {
87 pub fn new(buf: &[u8]) -> ExtensionIterable {
88 ExtensionIterable { buf: buf }
89 }
90}
91
92#[packet]
94pub struct Extension {
95 #[construct_with(u8)]
96 pub next_header: IpNextLevelProtocol,
97 pub hdr_ext_len: u8,
98 #[length_fn = "ipv6_extension_length"]
99 #[payload]
100 pub options: Vec<u8>,
101}
102
103fn ipv6_extension_length(ext: &ExtensionPacket) -> usize {
104 ext.get_hdr_ext_len() as usize * 8 + 8 - 2
105}
106
107pub type HopByHop = Extension;
109pub type HopByHopPacket<'p> = ExtensionPacket<'p>;
111pub type MutableHopByHopPacket<'p> = MutableExtensionPacket<'p>;
113
114#[packet]
116pub struct Routing {
117 #[construct_with(u8)]
118 pub next_header: IpNextLevelProtocol,
119 pub hdr_ext_len: u8,
120 pub routing_type: u8,
121 pub segments_left: u8,
122 #[length_fn = "routing_extension_length"]
123 #[payload]
124 pub data: Vec<u8>,
125}
126
127fn routing_extension_length(ext: &RoutingPacket) -> usize {
128 ext.get_hdr_ext_len() as usize * 8 + 8 - 4
129}
130
131#[packet]
133pub struct Fragment {
134 #[construct_with(u8)]
135 pub next_header: IpNextLevelProtocol,
136 pub reserved: u8,
137 pub fragment_offset_with_flags: u16be,
138 pub id: u32be,
139 #[length = "0"]
140 #[payload]
141 pub payload: Vec<u8>,
142}
143
144const FRAGMENT_FLAGS_MASK: u16 = 0x03;
145const FRAGMENT_FLAGS_MORE_FRAGMENTS: u16 = 0x01;
146const FRAGMENT_OFFSET_MASK: u16 = !FRAGMENT_FLAGS_MASK;
147
148impl<'p> FragmentPacket<'p> {
149 pub fn get_fragment_offset(&self) -> u16 {
150 self.get_fragment_offset_with_flags() & FRAGMENT_OFFSET_MASK
151 }
152
153 pub fn is_last_fragment(&self) -> bool {
154 (self.get_fragment_offset_with_flags() & FRAGMENT_FLAGS_MORE_FRAGMENTS) == 0
155 }
156}
157
158impl<'p> MutableFragmentPacket<'p> {
159 pub fn get_fragment_offset(&self) -> u16 {
160 self.get_fragment_offset_with_flags() & FRAGMENT_OFFSET_MASK
161 }
162
163 pub fn is_last_fragment(&self) -> bool {
164 (self.get_fragment_offset_with_flags() & FRAGMENT_FLAGS_MORE_FRAGMENTS) == 0
165 }
166
167 pub fn set_fragment_offset(&mut self, offset: u16) {
168 let fragment_offset_with_flags = self.get_fragment_offset_with_flags();
169
170 self.set_fragment_offset_with_flags(
171 (offset & FRAGMENT_OFFSET_MASK) | (fragment_offset_with_flags & FRAGMENT_FLAGS_MASK),
172 );
173 }
174
175 pub fn set_last_fragment(&mut self, is_last: bool) {
176 let fragment_offset_with_flags = self.get_fragment_offset_with_flags();
177
178 self.set_fragment_offset_with_flags(if is_last {
179 fragment_offset_with_flags & !FRAGMENT_FLAGS_MORE_FRAGMENTS
180 } else {
181 fragment_offset_with_flags | FRAGMENT_FLAGS_MORE_FRAGMENTS
182 });
183 }
184}
185
186pub type Destination = Extension;
188pub type DestinationPacket<'p> = ExtensionPacket<'p>;
190pub type MutableDestinationPacket<'p> = MutableExtensionPacket<'p>;
192
193#[test]
194fn ipv6_header_test() {
195 use crate::ip::IpNextLevelProtocol;
196 use crate::{MutablePacket, Packet, PacketSize};
197 use alloc::vec;
198
199 let mut packet = [0u8; 0x200];
200 {
201 let mut ip_header = MutableIpv6Packet::new(&mut packet[..]).unwrap();
202 ip_header.set_version(6);
203 assert_eq!(ip_header.get_version(), 6);
204
205 ip_header.set_traffic_class(17);
206 assert_eq!(ip_header.get_traffic_class(), 17);
207
208 ip_header.set_flow_label(0x10101);
209 assert_eq!(ip_header.get_flow_label(), 0x10101);
210
211 ip_header.set_payload_length(0x0101);
212 assert_eq!(ip_header.get_payload_length(), 0x0101);
213 assert_eq!(0x0101, ip_header.payload().len());
214
215 ip_header.set_next_header(IpNextLevelProtocol::Hopopt);
216 assert_eq!(ip_header.get_next_header(), IpNextLevelProtocol::Hopopt);
217
218 ip_header.set_hop_limit(1);
219 assert_eq!(ip_header.get_hop_limit(), 1);
220
221 let source = Ipv6Addr::new(0x110, 0x1001, 0x110, 0x1001, 0x110, 0x1001, 0x110, 0x1001);
222 ip_header.set_source(source);
223 assert_eq!(ip_header.get_source(), source);
224
225 let dest = Ipv6Addr::new(0x110, 0x1001, 0x110, 0x1001, 0x110, 0x1001, 0x110, 0x1001);
226 ip_header.set_destination(dest);
227 assert_eq!(ip_header.get_destination(), dest);
228
229 let mut pos = {
230 let mut hopopt = MutableHopByHopPacket::new(ip_header.payload_mut()).unwrap();
231
232 hopopt.set_next_header(IpNextLevelProtocol::Ipv6Opts);
233 assert_eq!(hopopt.get_next_header(), IpNextLevelProtocol::Ipv6Opts);
234
235 hopopt.set_hdr_ext_len(1);
236 assert_eq!(hopopt.get_hdr_ext_len(), 1);
237
238 hopopt.set_options(&[b'A'; 14][..]);
239 assert_eq!(hopopt.payload(), b"AAAAAAAAAAAAAA");
240
241 hopopt.packet_size()
242 };
243
244 pos += {
245 let mut dstopt =
246 MutableDestinationPacket::new(&mut ip_header.payload_mut()[pos..]).unwrap();
247
248 dstopt.set_next_header(IpNextLevelProtocol::Ipv6Route);
249 assert_eq!(dstopt.get_next_header(), IpNextLevelProtocol::Ipv6Route);
250
251 dstopt.set_hdr_ext_len(1);
252 assert_eq!(dstopt.get_hdr_ext_len(), 1);
253
254 dstopt.set_options(&[b'B'; 14][..]);
255 assert_eq!(dstopt.payload(), b"BBBBBBBBBBBBBB");
256
257 dstopt.packet_size()
258 };
259
260 pos += {
261 let mut routing =
262 MutableRoutingPacket::new(&mut ip_header.payload_mut()[pos..]).unwrap();
263
264 routing.set_next_header(IpNextLevelProtocol::Ipv6Frag);
265 assert_eq!(routing.get_next_header(), IpNextLevelProtocol::Ipv6Frag);
266
267 routing.set_hdr_ext_len(1);
268 assert_eq!(routing.get_hdr_ext_len(), 1);
269
270 routing.set_routing_type(4);
271 assert_eq!(routing.get_routing_type(), 4);
272
273 routing.set_segments_left(2);
274 assert_eq!(routing.get_segments_left(), 2);
275
276 routing.set_data(&[b'C'; 12][..]);
277 assert_eq!(routing.payload(), b"CCCCCCCCCCCC");
278
279 routing.packet_size()
280 };
281
282 pos += {
283 let mut frag = MutableFragmentPacket::new(&mut ip_header.payload_mut()[pos..]).unwrap();
284
285 frag.set_next_header(IpNextLevelProtocol::Udp);
286 assert_eq!(frag.get_next_header(), IpNextLevelProtocol::Udp);
287
288 frag.set_fragment_offset(1024);
289 assert_eq!(frag.get_fragment_offset(), 1024);
290
291 frag.set_last_fragment(false);
292 assert!(!frag.is_last_fragment());
293
294 frag.set_id(1234);
295 assert_eq!(frag.get_id(), 1234);
296
297 frag.packet_size()
298 };
299
300 assert_eq!(
301 ExtensionIterable::new(&ip_header.payload()[..pos])
302 .map(|ext| (
303 ext.get_next_header(),
304 ext.get_hdr_ext_len(),
305 ext.packet_size()
306 ))
307 .collect::<Vec<_>>(),
308 vec![
309 (IpNextLevelProtocol::Ipv6Opts, 1, 16),
310 (IpNextLevelProtocol::Ipv6Route, 1, 16),
311 (IpNextLevelProtocol::Ipv6Frag, 1, 16),
312 (IpNextLevelProtocol::Udp, 0, 8),
313 ]
314 );
315 }
316
317 let ref_packet = [
318 0x61, 0x11, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x10, 0x10, 0x01, 0x01, 0x10, 0x10, 0x01, 0x01, 0x10, 0x10, 0x01, 0x01, 0x10, 0x10,
326 0x01, 0x01, 0x10, 0x10, 0x01, 0x01, 0x10, 0x10, 0x01, 0x01, 0x10, 0x10, 0x01, 0x01, 0x10, 0x10,
328 0x01, 0x3c, 0x01, b'A', b'A', b'A', b'A', b'A', b'A', b'A', b'A', b'A', b'A', b'A', b'A', b'A', b'A',
332 0x2b, 0x01, b'B', b'B', b'B', b'B', b'B', b'B', b'B', b'B', b'B', b'B', b'B', b'B', b'B', b'B',
336 0x2c, 0x01, 0x04, 0x02, b'C', b'C', b'C', b'C', b'C', b'C', b'C', b'C', b'C', b'C', b'C', b'C',
342 0x11, 0x00, 0x04, 0x01, 0x00, 0x00, 0x04, 0xd2, ];
348 assert_eq!(&ref_packet[..], &packet[..ref_packet.len()]);
349}