1pub mod builder;
7pub mod ext_headers;
8
9pub use builder::Ipv6Builder;
10pub use ext_headers::{ExtHeader, ExtHeaderKind, parse_ext_headers};
11
12use crate::layer::field::{Field, FieldError, FieldValue};
13use crate::layer::{Layer, LayerIndex, LayerKind};
14use std::net::Ipv6Addr;
15
16pub const IPV6_HEADER_LEN: usize = 40;
18
19pub mod offsets {
21 pub const VERSION_TC_FL: usize = 0;
23 pub const PAYLOAD_LEN: usize = 4;
25 pub const NEXT_HEADER: usize = 6;
27 pub const HOP_LIMIT: usize = 7;
29 pub const SRC: usize = 8;
31 pub const DST: usize = 24;
33}
34
35#[derive(Debug, Clone)]
40pub struct Ipv6Layer {
41 pub index: LayerIndex,
42}
43
44impl Ipv6Layer {
45 #[inline]
47 #[must_use]
48 pub const fn new(start: usize, end: usize) -> Self {
49 Self {
50 index: LayerIndex::new(LayerKind::Ipv6, start, end),
51 }
52 }
53
54 #[inline]
56 #[must_use]
57 pub const fn at_start() -> Self {
58 Self::new(0, IPV6_HEADER_LEN)
59 }
60
61 #[inline]
63 #[must_use]
64 pub const fn at_offset(offset: usize) -> Self {
65 Self::new(offset, offset + IPV6_HEADER_LEN)
66 }
67
68 #[inline]
72 pub fn version(&self, buf: &[u8]) -> Result<u8, FieldError> {
73 let slice = self.index.slice(buf);
74 if slice.is_empty() {
75 return Err(FieldError::BufferTooShort {
76 offset: self.index.start + offsets::VERSION_TC_FL,
77 need: 1,
78 have: 0,
79 });
80 }
81 Ok((slice[0] >> 4) & 0x0F)
82 }
83
84 #[inline]
86 pub fn traffic_class(&self, buf: &[u8]) -> Result<u8, FieldError> {
87 let slice = self.index.slice(buf);
88 if slice.len() < 2 {
89 return Err(FieldError::BufferTooShort {
90 offset: self.index.start + offsets::VERSION_TC_FL,
91 need: 2,
92 have: slice.len(),
93 });
94 }
95 Ok(((slice[0] & 0x0F) << 4) | ((slice[1] >> 4) & 0x0F))
96 }
97
98 #[inline]
100 pub fn flow_label(&self, buf: &[u8]) -> Result<u32, FieldError> {
101 let slice = self.index.slice(buf);
102 if slice.len() < 4 {
103 return Err(FieldError::BufferTooShort {
104 offset: self.index.start + offsets::VERSION_TC_FL,
105 need: 4,
106 have: slice.len(),
107 });
108 }
109 let fl =
110 ((u32::from(slice[1]) & 0x0F) << 16) | (u32::from(slice[2]) << 8) | u32::from(slice[3]);
111 Ok(fl)
112 }
113
114 #[inline]
116 pub fn payload_len(&self, buf: &[u8]) -> Result<u16, FieldError> {
117 let slice = self.index.slice(buf);
118 if slice.len() < offsets::PAYLOAD_LEN + 2 {
119 return Err(FieldError::BufferTooShort {
120 offset: self.index.start + offsets::PAYLOAD_LEN,
121 need: 2,
122 have: slice.len().saturating_sub(offsets::PAYLOAD_LEN),
123 });
124 }
125 Ok(u16::from_be_bytes([
126 slice[offsets::PAYLOAD_LEN],
127 slice[offsets::PAYLOAD_LEN + 1],
128 ]))
129 }
130
131 #[inline]
133 pub fn next_header(&self, buf: &[u8]) -> Result<u8, FieldError> {
134 let slice = self.index.slice(buf);
135 if slice.len() <= offsets::NEXT_HEADER {
136 return Err(FieldError::BufferTooShort {
137 offset: self.index.start + offsets::NEXT_HEADER,
138 need: 1,
139 have: slice.len().saturating_sub(offsets::NEXT_HEADER),
140 });
141 }
142 Ok(slice[offsets::NEXT_HEADER])
143 }
144
145 #[inline]
147 pub fn hop_limit(&self, buf: &[u8]) -> Result<u8, FieldError> {
148 let slice = self.index.slice(buf);
149 if slice.len() <= offsets::HOP_LIMIT {
150 return Err(FieldError::BufferTooShort {
151 offset: self.index.start + offsets::HOP_LIMIT,
152 need: 1,
153 have: slice.len().saturating_sub(offsets::HOP_LIMIT),
154 });
155 }
156 Ok(slice[offsets::HOP_LIMIT])
157 }
158
159 #[inline]
161 pub fn src(&self, buf: &[u8]) -> Result<Ipv6Addr, FieldError> {
162 Ipv6Addr::read(buf, self.index.start + offsets::SRC)
163 }
164
165 #[inline]
167 pub fn dst(&self, buf: &[u8]) -> Result<Ipv6Addr, FieldError> {
168 Ipv6Addr::read(buf, self.index.start + offsets::DST)
169 }
170
171 #[inline]
175 pub fn set_version(&self, buf: &mut [u8], version: u8) -> Result<(), FieldError> {
176 let offset = self.index.start + offsets::VERSION_TC_FL;
177 if buf.len() <= offset {
178 return Err(FieldError::BufferTooShort {
179 offset,
180 need: 1,
181 have: buf.len().saturating_sub(offset),
182 });
183 }
184 buf[offset] = (buf[offset] & 0x0F) | ((version & 0x0F) << 4);
185 Ok(())
186 }
187
188 #[inline]
190 pub fn set_traffic_class(&self, buf: &mut [u8], tc: u8) -> Result<(), FieldError> {
191 let offset = self.index.start + offsets::VERSION_TC_FL;
192 if buf.len() < offset + 2 {
193 return Err(FieldError::BufferTooShort {
194 offset,
195 need: 2,
196 have: buf.len().saturating_sub(offset),
197 });
198 }
199 buf[offset] = (buf[offset] & 0xF0) | ((tc >> 4) & 0x0F);
201 buf[offset + 1] = (buf[offset + 1] & 0x0F) | ((tc & 0x0F) << 4);
203 Ok(())
204 }
205
206 #[inline]
208 pub fn set_flow_label(&self, buf: &mut [u8], fl: u32) -> Result<(), FieldError> {
209 let offset = self.index.start + offsets::VERSION_TC_FL;
210 if buf.len() < offset + 4 {
211 return Err(FieldError::BufferTooShort {
212 offset,
213 need: 4,
214 have: buf.len().saturating_sub(offset),
215 });
216 }
217 buf[offset + 1] = (buf[offset + 1] & 0xF0) | (((fl >> 16) & 0x0F) as u8);
219 buf[offset + 2] = ((fl >> 8) & 0xFF) as u8;
221 buf[offset + 3] = (fl & 0xFF) as u8;
222 Ok(())
223 }
224
225 #[inline]
227 pub fn set_payload_len(&self, buf: &mut [u8], len: u16) -> Result<(), FieldError> {
228 let offset = self.index.start + offsets::PAYLOAD_LEN;
229 if buf.len() < offset + 2 {
230 return Err(FieldError::BufferTooShort {
231 offset,
232 need: 2,
233 have: buf.len().saturating_sub(offset),
234 });
235 }
236 buf[offset..offset + 2].copy_from_slice(&len.to_be_bytes());
237 Ok(())
238 }
239
240 #[inline]
242 pub fn set_next_header(&self, buf: &mut [u8], nh: u8) -> Result<(), FieldError> {
243 let offset = self.index.start + offsets::NEXT_HEADER;
244 if buf.len() <= offset {
245 return Err(FieldError::BufferTooShort {
246 offset,
247 need: 1,
248 have: buf.len().saturating_sub(offset),
249 });
250 }
251 buf[offset] = nh;
252 Ok(())
253 }
254
255 #[inline]
257 pub fn set_hop_limit(&self, buf: &mut [u8], hlim: u8) -> Result<(), FieldError> {
258 let offset = self.index.start + offsets::HOP_LIMIT;
259 if buf.len() <= offset {
260 return Err(FieldError::BufferTooShort {
261 offset,
262 need: 1,
263 have: buf.len().saturating_sub(offset),
264 });
265 }
266 buf[offset] = hlim;
267 Ok(())
268 }
269
270 #[inline]
272 pub fn set_src(&self, buf: &mut [u8], src: Ipv6Addr) -> Result<(), FieldError> {
273 src.write(buf, self.index.start + offsets::SRC)
274 }
275
276 #[inline]
278 pub fn set_dst(&self, buf: &mut [u8], dst: Ipv6Addr) -> Result<(), FieldError> {
279 dst.write(buf, self.index.start + offsets::DST)
280 }
281
282 pub fn get_field(&self, buf: &[u8], name: &str) -> Option<Result<FieldValue, FieldError>> {
286 match name {
287 "version" => Some(self.version(buf).map(FieldValue::U8)),
288 "tc" | "traffic_class" => Some(self.traffic_class(buf).map(FieldValue::U8)),
289 "fl" | "flow_label" => Some(self.flow_label(buf).map(FieldValue::U32)),
290 "plen" | "payload_len" => Some(self.payload_len(buf).map(FieldValue::U16)),
291 "nh" | "next_header" => Some(self.next_header(buf).map(FieldValue::U8)),
292 "hlim" | "hop_limit" => Some(self.hop_limit(buf).map(FieldValue::U8)),
293 "src" => Some(self.src(buf).map(FieldValue::Ipv6)),
294 "dst" => Some(self.dst(buf).map(FieldValue::Ipv6)),
295 _ => None,
296 }
297 }
298
299 pub fn set_field(
301 &self,
302 buf: &mut [u8],
303 name: &str,
304 value: FieldValue,
305 ) -> Option<Result<(), FieldError>> {
306 match (name, value) {
307 ("version", FieldValue::U8(v)) => Some(self.set_version(buf, v)),
308 ("tc" | "traffic_class", FieldValue::U8(v)) => Some(self.set_traffic_class(buf, v)),
309 ("fl" | "flow_label", FieldValue::U32(v)) => Some(self.set_flow_label(buf, v)),
310 ("plen" | "payload_len", FieldValue::U16(v)) => Some(self.set_payload_len(buf, v)),
311 ("nh" | "next_header", FieldValue::U8(v)) => Some(self.set_next_header(buf, v)),
312 ("hlim" | "hop_limit", FieldValue::U8(v)) => Some(self.set_hop_limit(buf, v)),
313 ("src", FieldValue::Ipv6(v)) => Some(self.set_src(buf, v)),
314 ("dst", FieldValue::Ipv6(v)) => Some(self.set_dst(buf, v)),
315 _ => None,
316 }
317 }
318
319 #[must_use]
321 pub fn field_names() -> &'static [&'static str] {
322 &["version", "tc", "fl", "plen", "nh", "hlim", "src", "dst"]
323 }
324
325 #[must_use]
329 pub fn summary(&self, buf: &[u8]) -> String {
330 let src = self
331 .src(buf)
332 .map_or_else(|_| "?".to_string(), |a| a.to_string());
333 let dst = self
334 .dst(buf)
335 .map_or_else(|_| "?".to_string(), |a| a.to_string());
336 format!("IPv6 {src} > {dst}")
337 }
338
339 #[must_use]
341 pub fn header_len(&self, _buf: &[u8]) -> usize {
342 IPV6_HEADER_LEN
343 }
344
345 #[must_use]
347 pub fn next_layer(&self, buf: &[u8]) -> Option<LayerKind> {
348 use crate::layer::ipv4::protocol;
349 self.next_header(buf).ok().and_then(|nh| match nh {
350 protocol::TCP => Some(LayerKind::Tcp),
351 protocol::UDP => Some(LayerKind::Udp),
352 protocol::ICMPV6 => Some(LayerKind::Icmpv6),
353 _ => None,
354 })
355 }
356
357 #[must_use]
359 pub fn hashret(&self, buf: &[u8]) -> Vec<u8> {
360 let src = self.src(buf).map(|ip| ip.octets()).unwrap_or([0; 16]);
361 let dst = self.dst(buf).map(|ip| ip.octets()).unwrap_or([0; 16]);
362 let nh = self.next_header(buf).unwrap_or(0);
363
364 let mut result = Vec::with_capacity(17);
365 for i in 0..16 {
366 result.push(src[i] ^ dst[i]);
367 }
368 result.push(nh);
369 result
370 }
371
372 #[must_use]
374 pub fn answers(&self, buf: &[u8], other: &Ipv6Layer, other_buf: &[u8]) -> bool {
375 let self_src = self.src(buf).ok();
376 let self_dst = self.dst(buf).ok();
377 let other_src = other.src(other_buf).ok();
378 let other_dst = other.dst(other_buf).ok();
379
380 if self_src != other_dst {
382 return false;
383 }
384 if self_dst != other_src {
386 return false;
387 }
388 true
389 }
390}
391
392impl Layer for Ipv6Layer {
393 fn kind(&self) -> LayerKind {
394 LayerKind::Ipv6
395 }
396
397 fn summary(&self, data: &[u8]) -> String {
398 self.summary(data)
399 }
400
401 fn header_len(&self, data: &[u8]) -> usize {
402 self.header_len(data)
403 }
404
405 fn hashret(&self, data: &[u8]) -> Vec<u8> {
406 self.hashret(data)
407 }
408
409 fn answers(&self, data: &[u8], other: &Self, other_data: &[u8]) -> bool {
410 self.answers(data, other, other_data)
411 }
412
413 fn field_names(&self) -> &'static [&'static str] {
414 Self::field_names()
415 }
416}
417
418#[cfg(test)]
419mod tests {
420 use super::*;
421
422 fn make_ipv6_buf(src: Ipv6Addr, dst: Ipv6Addr, nh: u8) -> Vec<u8> {
423 let mut buf = vec![0u8; 40];
424 buf[0] = 0x60;
426 buf[1] = 0x00;
427 buf[2] = 0x00;
428 buf[3] = 0x00;
429 buf[4] = 0;
431 buf[5] = 0;
432 buf[6] = nh;
434 buf[7] = 64;
436 buf[8..24].copy_from_slice(&src.octets());
438 buf[24..40].copy_from_slice(&dst.octets());
440 buf
441 }
442
443 #[test]
444 fn test_ipv6_version() {
445 let src = Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1);
446 let dst = Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 2);
447 let buf = make_ipv6_buf(src, dst, 58);
448 let layer = Ipv6Layer::at_start();
449 assert_eq!(layer.version(&buf).unwrap(), 6);
450 }
451
452 #[test]
453 fn test_ipv6_addresses() {
454 let src = Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1);
455 let dst = Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 2);
456 let buf = make_ipv6_buf(src, dst, 58);
457 let layer = Ipv6Layer::at_start();
458 assert_eq!(layer.src(&buf).unwrap(), src);
459 assert_eq!(layer.dst(&buf).unwrap(), dst);
460 }
461
462 #[test]
463 fn test_ipv6_next_header() {
464 let src = Ipv6Addr::LOCALHOST;
465 let dst = Ipv6Addr::LOCALHOST;
466 let buf = make_ipv6_buf(src, dst, 58); let layer = Ipv6Layer::at_start();
468 assert_eq!(layer.next_header(&buf).unwrap(), 58);
469 }
470
471 #[test]
472 fn test_ipv6_hop_limit() {
473 let src = Ipv6Addr::LOCALHOST;
474 let dst = Ipv6Addr::LOCALHOST;
475 let buf = make_ipv6_buf(src, dst, 6);
476 let layer = Ipv6Layer::at_start();
477 assert_eq!(layer.hop_limit(&buf).unwrap(), 64);
478 }
479
480 #[test]
481 fn test_ipv6_traffic_class() {
482 let mut buf = vec![0u8; 40];
483 buf[0] = 0x60 | ((0xABu8 >> 4) & 0x0F); buf[1] = ((0xABu8 & 0x0F) << 4) | 0x00; let layer = Ipv6Layer::at_start();
487 assert_eq!(layer.traffic_class(&buf).unwrap(), 0xAB);
488 }
489
490 #[test]
491 fn test_ipv6_flow_label() {
492 let mut buf = vec![0u8; 40];
493 buf[0] = 0x60;
495 buf[1] = 0x01; buf[2] = 0x23; buf[3] = 0x45; let layer = Ipv6Layer::at_start();
499 assert_eq!(layer.flow_label(&buf).unwrap(), 0x12345);
500 }
501
502 #[test]
503 fn test_ipv6_summary() {
504 let src = Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1);
505 let dst = Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 2);
506 let buf = make_ipv6_buf(src, dst, 58);
507 let layer = Ipv6Layer::at_start();
508 let summary = layer.summary(&buf);
509 assert!(summary.contains("IPv6"));
510 assert!(summary.contains("2001:db8::1"));
511 assert!(summary.contains("2001:db8::2"));
512 }
513
514 #[test]
515 fn test_ipv6_get_field() {
516 let src = Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1);
517 let dst = Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 2);
518 let buf = make_ipv6_buf(src, dst, 17); let layer = Ipv6Layer::at_start();
520
521 if let Some(Ok(FieldValue::U8(v))) = layer.get_field(&buf, "version") {
522 assert_eq!(v, 6);
523 } else {
524 panic!("expected version = 6");
525 }
526
527 if let Some(Ok(FieldValue::U8(v))) = layer.get_field(&buf, "nh") {
528 assert_eq!(v, 17); } else {
530 panic!("expected nh = 17");
531 }
532 }
533
534 #[test]
535 fn test_ipv6_set_field() {
536 let src = Ipv6Addr::LOCALHOST;
537 let dst = Ipv6Addr::LOCALHOST;
538 let mut buf = make_ipv6_buf(src, dst, 6);
539 let layer = Ipv6Layer::at_start();
540
541 layer
543 .set_field(&mut buf, "hlim", FieldValue::U8(128))
544 .unwrap()
545 .unwrap();
546 assert_eq!(layer.hop_limit(&buf).unwrap(), 128);
547 }
548
549 #[test]
550 fn test_ipv6_set_addresses() {
551 let src = Ipv6Addr::LOCALHOST;
552 let dst = Ipv6Addr::LOCALHOST;
553 let mut buf = make_ipv6_buf(src, dst, 6);
554 let layer = Ipv6Layer::at_start();
555
556 let new_src = Ipv6Addr::new(0xfe80, 0, 0, 0, 0, 0, 0, 1);
557 layer.set_src(&mut buf, new_src).unwrap();
558 assert_eq!(layer.src(&buf).unwrap(), new_src);
559 }
560
561 #[test]
562 fn test_ipv6_payload_len() {
563 let src = Ipv6Addr::LOCALHOST;
564 let dst = Ipv6Addr::LOCALHOST;
565 let mut buf = make_ipv6_buf(src, dst, 58);
566 buf[4] = 0x00;
567 buf[5] = 0x28; let layer = Ipv6Layer::at_start();
569 assert_eq!(layer.payload_len(&buf).unwrap(), 40);
570 }
571
572 #[test]
573 fn test_ipv6_header_len() {
574 let buf = vec![0u8; 40];
575 let layer = Ipv6Layer::at_start();
576 assert_eq!(layer.header_len(&buf), IPV6_HEADER_LEN);
577 assert_eq!(IPV6_HEADER_LEN, 40);
578 }
579}