1use crate::ip::IpNextHeaderProtocol;
12use crate::{types::*, Packet};
13use std::net::Ipv6Addr;
14
15#[derive(Debug, Packet)]
17pub struct Ipv6 {
18 pub version: u4,
19 pub traffic_class: u8,
20 pub flow_label: u20be,
21 pub payload_length: u16be,
22 #[construct_with(u8)]
23 pub next_header: IpNextHeaderProtocol,
24 pub hop_limit: u8,
25 #[construct_with(u16, u16, u16, u16, u16, u16, u16, u16)]
26 pub source: Ipv6Addr,
27 #[construct_with(u16, u16, u16, u16, u16, u16, u16, u16)]
28 pub destination: Ipv6Addr,
29 #[length = "payload_length"]
30 #[payload]
31 pub payload: Vec<u8>,
32}
33
34impl<'p> ExtensionIterable<'p> {
35 pub fn new(buf: &[u8]) -> ExtensionIterable {
36 ExtensionIterable { buf: buf }
37 }
38}
39
40#[derive(Debug, Packet)]
42pub struct Extension {
43 #[construct_with(u8)]
44 pub next_header: IpNextHeaderProtocol,
45 pub hdr_ext_len: u8,
46 #[length = "ipv6_extension_length(hdr_ext_len)"]
47 #[payload]
48 pub options: Vec<u8>,
49}
50
51fn ipv6_extension_length(hdr_ext_len: u8) -> usize {
52 hdr_ext_len as usize * 8 + 8 - 2
53}
54
55pub type HopByHop = Extension;
57pub type HopByHopPacket<'p> = ExtensionPacket<'p>;
59pub type MutableHopByHopPacket<'p> = MutableExtensionPacket<'p>;
61
62#[derive(Debug, Packet)]
64pub struct Routing {
65 #[construct_with(u8)]
66 pub next_header: IpNextHeaderProtocol,
67 pub hdr_ext_len: u8,
68 pub routing_type: u8,
69 pub segments_left: u8,
70 #[length = "routing_extension_length(hdr_ext_len)"]
71 #[payload]
72 pub data: Vec<u8>,
73}
74
75fn routing_extension_length(hdr_ext_len: u8) -> usize {
76 hdr_ext_len as usize * 8 + 8 - 4
77}
78
79#[derive(Debug, Packet)]
81pub struct Fragment {
82 #[construct_with(u8)]
83 pub next_header: IpNextHeaderProtocol,
84 pub reserved: u8,
85 pub fragment_offset_with_flags: u16be,
86 pub id: u32be,
87 #[length = "0"]
88 #[payload]
89 pub payload: Vec<u8>,
90}
91
92const FRAGMENT_FLAGS_MASK: u16 = 0x03;
93const FRAGMENT_FLAGS_MORE_FRAGMENTS: u16 = 0x01;
94const FRAGMENT_OFFSET_MASK: u16 = !FRAGMENT_FLAGS_MASK;
95
96impl<'p> FragmentPacket<'p> {
97 pub fn get_fragment_offset(&self) -> u16 {
98 self.get_fragment_offset_with_flags() & FRAGMENT_OFFSET_MASK
99 }
100
101 pub fn is_last_fragment(&self) -> bool {
102 (self.get_fragment_offset_with_flags() & FRAGMENT_FLAGS_MORE_FRAGMENTS) == 0
103 }
104}
105
106impl<'p> MutableFragmentPacket<'p> {
107 pub fn get_fragment_offset(&self) -> u16 {
108 self.get_fragment_offset_with_flags() & FRAGMENT_OFFSET_MASK
109 }
110
111 pub fn is_last_fragment(&self) -> bool {
112 (self.get_fragment_offset_with_flags() & FRAGMENT_FLAGS_MORE_FRAGMENTS) == 0
113 }
114
115 pub fn set_fragment_offset(&mut self, offset: u16) {
116 let fragment_offset_with_flags = self.get_fragment_offset_with_flags();
117
118 self.set_fragment_offset_with_flags(
119 (offset & FRAGMENT_OFFSET_MASK) | (fragment_offset_with_flags & FRAGMENT_FLAGS_MASK),
120 );
121 }
122
123 pub fn set_last_fragment(&mut self, is_last: bool) {
124 let fragment_offset_with_flags = self.get_fragment_offset_with_flags();
125
126 self.set_fragment_offset_with_flags(if is_last {
127 fragment_offset_with_flags & !FRAGMENT_FLAGS_MORE_FRAGMENTS
128 } else {
129 fragment_offset_with_flags | FRAGMENT_FLAGS_MORE_FRAGMENTS
130 });
131 }
132}
133
134pub type Destination = Extension;
136pub type DestinationPacket<'p> = ExtensionPacket<'p>;
138pub type MutableDestinationPacket<'p> = MutableExtensionPacket<'p>;
140
141#[test]
142fn ipv6_header_test() {
143 use crate::ip::IpNextHeaderProtocols;
144 use crate::{MutablePacket, Packet, PacketSize};
145
146 let mut packet = [0u8; 0x200];
147 {
148 let mut ip_header = MutableIpv6Packet::new(&mut packet[..]).unwrap();
149 ip_header.set_version(6);
150 assert_eq!(ip_header.get_version(), 6);
151
152 ip_header.set_traffic_class(17);
153 assert_eq!(ip_header.get_traffic_class(), 17);
154
155 ip_header.set_flow_label(0x10101);
156 assert_eq!(ip_header.get_flow_label(), 0x10101);
157
158 ip_header.set_payload_length(0x0101);
159 assert_eq!(ip_header.get_payload_length(), 0x0101);
160 assert_eq!(0x0101, ip_header.payload().len());
161
162 ip_header.set_next_header(IpNextHeaderProtocols::Hopopt);
163 assert_eq!(ip_header.get_next_header(), IpNextHeaderProtocols::Hopopt);
164
165 ip_header.set_hop_limit(1);
166 assert_eq!(ip_header.get_hop_limit(), 1);
167
168 let source = Ipv6Addr::new(0x110, 0x1001, 0x110, 0x1001, 0x110, 0x1001, 0x110, 0x1001);
169 ip_header.set_source(source);
170 assert_eq!(ip_header.get_source(), source);
171
172 let dest = Ipv6Addr::new(0x110, 0x1001, 0x110, 0x1001, 0x110, 0x1001, 0x110, 0x1001);
173 ip_header.set_destination(dest);
174 assert_eq!(ip_header.get_destination(), dest);
175
176 let mut pos = {
177 let mut hopopt = MutableHopByHopPacket::new(ip_header.payload_mut()).unwrap();
178
179 hopopt.set_next_header(IpNextHeaderProtocols::Ipv6Opts);
180 assert_eq!(hopopt.get_next_header(), IpNextHeaderProtocols::Ipv6Opts);
181
182 hopopt.set_hdr_ext_len(1);
183 assert_eq!(hopopt.get_hdr_ext_len(), 1);
184
185 hopopt.set_options(&[b'A'; 14][..]);
186 assert_eq!(hopopt.payload(), b"AAAAAAAAAAAAAA");
187
188 hopopt.packet_size()
189 };
190
191 pos += {
192 let mut dstopt =
193 MutableDestinationPacket::new(&mut ip_header.payload_mut()[pos..]).unwrap();
194
195 dstopt.set_next_header(IpNextHeaderProtocols::Ipv6Route);
196 assert_eq!(dstopt.get_next_header(), IpNextHeaderProtocols::Ipv6Route);
197
198 dstopt.set_hdr_ext_len(1);
199 assert_eq!(dstopt.get_hdr_ext_len(), 1);
200
201 dstopt.set_options(&[b'B'; 14][..]);
202 assert_eq!(dstopt.payload(), b"BBBBBBBBBBBBBB");
203
204 dstopt.packet_size()
205 };
206
207 pos += {
208 let mut routing =
209 MutableRoutingPacket::new(&mut ip_header.payload_mut()[pos..]).unwrap();
210
211 routing.set_next_header(IpNextHeaderProtocols::Ipv6Frag);
212 assert_eq!(routing.get_next_header(), IpNextHeaderProtocols::Ipv6Frag);
213
214 routing.set_hdr_ext_len(1);
215 assert_eq!(routing.get_hdr_ext_len(), 1);
216
217 routing.set_routing_type(4);
218 assert_eq!(routing.get_routing_type(), 4);
219
220 routing.set_segments_left(2);
221 assert_eq!(routing.get_segments_left(), 2);
222
223 routing.set_data(&[b'C'; 12][..]);
224 assert_eq!(routing.payload(), b"CCCCCCCCCCCC");
225
226 routing.packet_size()
227 };
228
229 pos += {
230 let mut frag = MutableFragmentPacket::new(&mut ip_header.payload_mut()[pos..]).unwrap();
231
232 frag.set_next_header(IpNextHeaderProtocols::Udp);
233 assert_eq!(frag.get_next_header(), IpNextHeaderProtocols::Udp);
234
235 frag.set_fragment_offset(1024);
236 assert_eq!(frag.get_fragment_offset(), 1024);
237
238 frag.set_last_fragment(false);
239 assert!(!frag.is_last_fragment());
240
241 frag.set_id(1234);
242 assert_eq!(frag.get_id(), 1234);
243
244 frag.packet_size()
245 };
246
247 assert_eq!(
248 ExtensionIterable::new(&ip_header.payload()[..pos])
249 .map(|ext| (
250 ext.get_next_header(),
251 ext.get_hdr_ext_len(),
252 ext.packet_size()
253 ))
254 .collect::<Vec<_>>(),
255 vec![
256 (IpNextHeaderProtocols::Ipv6Opts, 1, 16),
257 (IpNextHeaderProtocols::Ipv6Route, 1, 16),
258 (IpNextHeaderProtocols::Ipv6Frag, 1, 16),
259 (IpNextHeaderProtocols::Udp, 0, 8),
260 ]
261 );
262 }
263
264 let ref_packet = [
265 0x61, 0x11, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x10, 0x10, 0x01, 0x01, 0x10, 0x10, 0x01, 0x01, 0x10, 0x10, 0x01, 0x01, 0x10, 0x10,
273 0x01, 0x01, 0x10, 0x10, 0x01, 0x01, 0x10, 0x10, 0x01, 0x01, 0x10, 0x10, 0x01, 0x01, 0x10, 0x10,
275 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',
279 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',
283 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',
289 0x11, 0x00, 0x04, 0x01, 0x00, 0x00, 0x04, 0xd2, ];
295 assert_eq!(&ref_packet[..], &packet[..ref_packet.len()]);
296}