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 pub const fn new(start: usize, end: usize) -> Self {
48 Self {
49 index: LayerIndex::new(LayerKind::Ipv6, start, end),
50 }
51 }
52
53 #[inline]
55 pub const fn at_start() -> Self {
56 Self::new(0, IPV6_HEADER_LEN)
57 }
58
59 #[inline]
61 pub const fn at_offset(offset: usize) -> Self {
62 Self::new(offset, offset + IPV6_HEADER_LEN)
63 }
64
65 #[inline]
69 pub fn version(&self, buf: &[u8]) -> Result<u8, FieldError> {
70 let slice = self.index.slice(buf);
71 if slice.is_empty() {
72 return Err(FieldError::BufferTooShort {
73 offset: self.index.start + offsets::VERSION_TC_FL,
74 need: 1,
75 have: 0,
76 });
77 }
78 Ok((slice[0] >> 4) & 0x0F)
79 }
80
81 #[inline]
83 pub fn traffic_class(&self, buf: &[u8]) -> Result<u8, FieldError> {
84 let slice = self.index.slice(buf);
85 if slice.len() < 2 {
86 return Err(FieldError::BufferTooShort {
87 offset: self.index.start + offsets::VERSION_TC_FL,
88 need: 2,
89 have: slice.len(),
90 });
91 }
92 Ok(((slice[0] & 0x0F) << 4) | ((slice[1] >> 4) & 0x0F))
93 }
94
95 #[inline]
97 pub fn flow_label(&self, buf: &[u8]) -> Result<u32, FieldError> {
98 let slice = self.index.slice(buf);
99 if slice.len() < 4 {
100 return Err(FieldError::BufferTooShort {
101 offset: self.index.start + offsets::VERSION_TC_FL,
102 need: 4,
103 have: slice.len(),
104 });
105 }
106 let fl = ((slice[1] as u32 & 0x0F) << 16) | ((slice[2] as u32) << 8) | (slice[3] as u32);
107 Ok(fl)
108 }
109
110 #[inline]
112 pub fn payload_len(&self, buf: &[u8]) -> Result<u16, FieldError> {
113 let slice = self.index.slice(buf);
114 if slice.len() < offsets::PAYLOAD_LEN + 2 {
115 return Err(FieldError::BufferTooShort {
116 offset: self.index.start + offsets::PAYLOAD_LEN,
117 need: 2,
118 have: slice.len().saturating_sub(offsets::PAYLOAD_LEN),
119 });
120 }
121 Ok(u16::from_be_bytes([
122 slice[offsets::PAYLOAD_LEN],
123 slice[offsets::PAYLOAD_LEN + 1],
124 ]))
125 }
126
127 #[inline]
129 pub fn next_header(&self, buf: &[u8]) -> Result<u8, FieldError> {
130 let slice = self.index.slice(buf);
131 if slice.len() <= offsets::NEXT_HEADER {
132 return Err(FieldError::BufferTooShort {
133 offset: self.index.start + offsets::NEXT_HEADER,
134 need: 1,
135 have: slice.len().saturating_sub(offsets::NEXT_HEADER),
136 });
137 }
138 Ok(slice[offsets::NEXT_HEADER])
139 }
140
141 #[inline]
143 pub fn hop_limit(&self, buf: &[u8]) -> Result<u8, FieldError> {
144 let slice = self.index.slice(buf);
145 if slice.len() <= offsets::HOP_LIMIT {
146 return Err(FieldError::BufferTooShort {
147 offset: self.index.start + offsets::HOP_LIMIT,
148 need: 1,
149 have: slice.len().saturating_sub(offsets::HOP_LIMIT),
150 });
151 }
152 Ok(slice[offsets::HOP_LIMIT])
153 }
154
155 #[inline]
157 pub fn src(&self, buf: &[u8]) -> Result<Ipv6Addr, FieldError> {
158 Ipv6Addr::read(buf, self.index.start + offsets::SRC)
159 }
160
161 #[inline]
163 pub fn dst(&self, buf: &[u8]) -> Result<Ipv6Addr, FieldError> {
164 Ipv6Addr::read(buf, self.index.start + offsets::DST)
165 }
166
167 #[inline]
171 pub fn set_version(&self, buf: &mut [u8], version: u8) -> Result<(), FieldError> {
172 let offset = self.index.start + offsets::VERSION_TC_FL;
173 if buf.len() <= offset {
174 return Err(FieldError::BufferTooShort {
175 offset,
176 need: 1,
177 have: buf.len().saturating_sub(offset),
178 });
179 }
180 buf[offset] = (buf[offset] & 0x0F) | ((version & 0x0F) << 4);
181 Ok(())
182 }
183
184 #[inline]
186 pub fn set_traffic_class(&self, buf: &mut [u8], tc: u8) -> Result<(), FieldError> {
187 let offset = self.index.start + offsets::VERSION_TC_FL;
188 if buf.len() < offset + 2 {
189 return Err(FieldError::BufferTooShort {
190 offset,
191 need: 2,
192 have: buf.len().saturating_sub(offset),
193 });
194 }
195 buf[offset] = (buf[offset] & 0xF0) | ((tc >> 4) & 0x0F);
197 buf[offset + 1] = (buf[offset + 1] & 0x0F) | ((tc & 0x0F) << 4);
199 Ok(())
200 }
201
202 #[inline]
204 pub fn set_flow_label(&self, buf: &mut [u8], fl: u32) -> Result<(), FieldError> {
205 let offset = self.index.start + offsets::VERSION_TC_FL;
206 if buf.len() < offset + 4 {
207 return Err(FieldError::BufferTooShort {
208 offset,
209 need: 4,
210 have: buf.len().saturating_sub(offset),
211 });
212 }
213 buf[offset + 1] = (buf[offset + 1] & 0xF0) | (((fl >> 16) & 0x0F) as u8);
215 buf[offset + 2] = ((fl >> 8) & 0xFF) as u8;
217 buf[offset + 3] = (fl & 0xFF) as u8;
218 Ok(())
219 }
220
221 #[inline]
223 pub fn set_payload_len(&self, buf: &mut [u8], len: u16) -> Result<(), FieldError> {
224 let offset = self.index.start + offsets::PAYLOAD_LEN;
225 if buf.len() < offset + 2 {
226 return Err(FieldError::BufferTooShort {
227 offset,
228 need: 2,
229 have: buf.len().saturating_sub(offset),
230 });
231 }
232 buf[offset..offset + 2].copy_from_slice(&len.to_be_bytes());
233 Ok(())
234 }
235
236 #[inline]
238 pub fn set_next_header(&self, buf: &mut [u8], nh: u8) -> Result<(), FieldError> {
239 let offset = self.index.start + offsets::NEXT_HEADER;
240 if buf.len() <= offset {
241 return Err(FieldError::BufferTooShort {
242 offset,
243 need: 1,
244 have: buf.len().saturating_sub(offset),
245 });
246 }
247 buf[offset] = nh;
248 Ok(())
249 }
250
251 #[inline]
253 pub fn set_hop_limit(&self, buf: &mut [u8], hlim: u8) -> Result<(), FieldError> {
254 let offset = self.index.start + offsets::HOP_LIMIT;
255 if buf.len() <= offset {
256 return Err(FieldError::BufferTooShort {
257 offset,
258 need: 1,
259 have: buf.len().saturating_sub(offset),
260 });
261 }
262 buf[offset] = hlim;
263 Ok(())
264 }
265
266 #[inline]
268 pub fn set_src(&self, buf: &mut [u8], src: Ipv6Addr) -> Result<(), FieldError> {
269 src.write(buf, self.index.start + offsets::SRC)
270 }
271
272 #[inline]
274 pub fn set_dst(&self, buf: &mut [u8], dst: Ipv6Addr) -> Result<(), FieldError> {
275 dst.write(buf, self.index.start + offsets::DST)
276 }
277
278 pub fn get_field(&self, buf: &[u8], name: &str) -> Option<Result<FieldValue, FieldError>> {
282 match name {
283 "version" => Some(self.version(buf).map(FieldValue::U8)),
284 "tc" | "traffic_class" => Some(self.traffic_class(buf).map(FieldValue::U8)),
285 "fl" | "flow_label" => Some(self.flow_label(buf).map(FieldValue::U32)),
286 "plen" | "payload_len" => Some(self.payload_len(buf).map(FieldValue::U16)),
287 "nh" | "next_header" => Some(self.next_header(buf).map(FieldValue::U8)),
288 "hlim" | "hop_limit" => Some(self.hop_limit(buf).map(FieldValue::U8)),
289 "src" => Some(self.src(buf).map(FieldValue::Ipv6)),
290 "dst" => Some(self.dst(buf).map(FieldValue::Ipv6)),
291 _ => None,
292 }
293 }
294
295 pub fn set_field(
297 &self,
298 buf: &mut [u8],
299 name: &str,
300 value: FieldValue,
301 ) -> Option<Result<(), FieldError>> {
302 match (name, value) {
303 ("version", FieldValue::U8(v)) => Some(self.set_version(buf, v)),
304 ("tc" | "traffic_class", FieldValue::U8(v)) => Some(self.set_traffic_class(buf, v)),
305 ("fl" | "flow_label", FieldValue::U32(v)) => Some(self.set_flow_label(buf, v)),
306 ("plen" | "payload_len", FieldValue::U16(v)) => Some(self.set_payload_len(buf, v)),
307 ("nh" | "next_header", FieldValue::U8(v)) => Some(self.set_next_header(buf, v)),
308 ("hlim" | "hop_limit", FieldValue::U8(v)) => Some(self.set_hop_limit(buf, v)),
309 ("src", FieldValue::Ipv6(v)) => Some(self.set_src(buf, v)),
310 ("dst", FieldValue::Ipv6(v)) => Some(self.set_dst(buf, v)),
311 _ => None,
312 }
313 }
314
315 pub fn field_names() -> &'static [&'static str] {
317 &["version", "tc", "fl", "plen", "nh", "hlim", "src", "dst"]
318 }
319
320 pub fn summary(&self, buf: &[u8]) -> String {
324 let src = self
325 .src(buf)
326 .map(|a| a.to_string())
327 .unwrap_or_else(|_| "?".to_string());
328 let dst = self
329 .dst(buf)
330 .map(|a| a.to_string())
331 .unwrap_or_else(|_| "?".to_string());
332 format!("IPv6 {} > {}", src, dst)
333 }
334
335 pub fn header_len(&self, _buf: &[u8]) -> usize {
337 IPV6_HEADER_LEN
338 }
339
340 pub fn next_layer(&self, buf: &[u8]) -> Option<LayerKind> {
342 use crate::layer::ipv4::protocol;
343 self.next_header(buf).ok().and_then(|nh| match nh {
344 protocol::TCP => Some(LayerKind::Tcp),
345 protocol::UDP => Some(LayerKind::Udp),
346 protocol::ICMPV6 => Some(LayerKind::Icmpv6),
347 _ => None,
348 })
349 }
350
351 pub fn hashret(&self, buf: &[u8]) -> Vec<u8> {
353 let src = self.src(buf).map(|ip| ip.octets()).unwrap_or([0; 16]);
354 let dst = self.dst(buf).map(|ip| ip.octets()).unwrap_or([0; 16]);
355 let nh = self.next_header(buf).unwrap_or(0);
356
357 let mut result = Vec::with_capacity(17);
358 for i in 0..16 {
359 result.push(src[i] ^ dst[i]);
360 }
361 result.push(nh);
362 result
363 }
364
365 pub fn answers(&self, buf: &[u8], other: &Ipv6Layer, other_buf: &[u8]) -> bool {
367 let self_src = self.src(buf).ok();
368 let self_dst = self.dst(buf).ok();
369 let other_src = other.src(other_buf).ok();
370 let other_dst = other.dst(other_buf).ok();
371
372 if self_src != other_dst {
374 return false;
375 }
376 if self_dst != other_src {
378 return false;
379 }
380 true
381 }
382}
383
384impl Layer for Ipv6Layer {
385 fn kind(&self) -> LayerKind {
386 LayerKind::Ipv6
387 }
388
389 fn summary(&self, data: &[u8]) -> String {
390 self.summary(data)
391 }
392
393 fn header_len(&self, data: &[u8]) -> usize {
394 self.header_len(data)
395 }
396
397 fn hashret(&self, data: &[u8]) -> Vec<u8> {
398 self.hashret(data)
399 }
400
401 fn answers(&self, data: &[u8], other: &Self, other_data: &[u8]) -> bool {
402 self.answers(data, other, other_data)
403 }
404
405 fn field_names(&self) -> &'static [&'static str] {
406 Self::field_names()
407 }
408}
409
410#[cfg(test)]
411mod tests {
412 use super::*;
413
414 fn make_ipv6_buf(src: Ipv6Addr, dst: Ipv6Addr, nh: u8) -> Vec<u8> {
415 let mut buf = vec![0u8; 40];
416 buf[0] = 0x60;
418 buf[1] = 0x00;
419 buf[2] = 0x00;
420 buf[3] = 0x00;
421 buf[4] = 0;
423 buf[5] = 0;
424 buf[6] = nh;
426 buf[7] = 64;
428 buf[8..24].copy_from_slice(&src.octets());
430 buf[24..40].copy_from_slice(&dst.octets());
432 buf
433 }
434
435 #[test]
436 fn test_ipv6_version() {
437 let src = Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1);
438 let dst = Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 2);
439 let buf = make_ipv6_buf(src, dst, 58);
440 let layer = Ipv6Layer::at_start();
441 assert_eq!(layer.version(&buf).unwrap(), 6);
442 }
443
444 #[test]
445 fn test_ipv6_addresses() {
446 let src = Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1);
447 let dst = Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 2);
448 let buf = make_ipv6_buf(src, dst, 58);
449 let layer = Ipv6Layer::at_start();
450 assert_eq!(layer.src(&buf).unwrap(), src);
451 assert_eq!(layer.dst(&buf).unwrap(), dst);
452 }
453
454 #[test]
455 fn test_ipv6_next_header() {
456 let src = Ipv6Addr::LOCALHOST;
457 let dst = Ipv6Addr::LOCALHOST;
458 let buf = make_ipv6_buf(src, dst, 58); let layer = Ipv6Layer::at_start();
460 assert_eq!(layer.next_header(&buf).unwrap(), 58);
461 }
462
463 #[test]
464 fn test_ipv6_hop_limit() {
465 let src = Ipv6Addr::LOCALHOST;
466 let dst = Ipv6Addr::LOCALHOST;
467 let buf = make_ipv6_buf(src, dst, 6);
468 let layer = Ipv6Layer::at_start();
469 assert_eq!(layer.hop_limit(&buf).unwrap(), 64);
470 }
471
472 #[test]
473 fn test_ipv6_traffic_class() {
474 let mut buf = vec![0u8; 40];
475 buf[0] = 0x60 | ((0xABu8 >> 4) & 0x0F); buf[1] = ((0xABu8 & 0x0F) << 4) | 0x00; let layer = Ipv6Layer::at_start();
479 assert_eq!(layer.traffic_class(&buf).unwrap(), 0xAB);
480 }
481
482 #[test]
483 fn test_ipv6_flow_label() {
484 let mut buf = vec![0u8; 40];
485 buf[0] = 0x60;
487 buf[1] = 0x01; buf[2] = 0x23; buf[3] = 0x45; let layer = Ipv6Layer::at_start();
491 assert_eq!(layer.flow_label(&buf).unwrap(), 0x12345);
492 }
493
494 #[test]
495 fn test_ipv6_summary() {
496 let src = Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1);
497 let dst = Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 2);
498 let buf = make_ipv6_buf(src, dst, 58);
499 let layer = Ipv6Layer::at_start();
500 let summary = layer.summary(&buf);
501 assert!(summary.contains("IPv6"));
502 assert!(summary.contains("2001:db8::1"));
503 assert!(summary.contains("2001:db8::2"));
504 }
505
506 #[test]
507 fn test_ipv6_get_field() {
508 let src = Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1);
509 let dst = Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 2);
510 let buf = make_ipv6_buf(src, dst, 17); let layer = Ipv6Layer::at_start();
512
513 if let Some(Ok(FieldValue::U8(v))) = layer.get_field(&buf, "version") {
514 assert_eq!(v, 6);
515 } else {
516 panic!("expected version = 6");
517 }
518
519 if let Some(Ok(FieldValue::U8(v))) = layer.get_field(&buf, "nh") {
520 assert_eq!(v, 17); } else {
522 panic!("expected nh = 17");
523 }
524 }
525
526 #[test]
527 fn test_ipv6_set_field() {
528 let src = Ipv6Addr::LOCALHOST;
529 let dst = Ipv6Addr::LOCALHOST;
530 let mut buf = make_ipv6_buf(src, dst, 6);
531 let layer = Ipv6Layer::at_start();
532
533 layer
535 .set_field(&mut buf, "hlim", FieldValue::U8(128))
536 .unwrap()
537 .unwrap();
538 assert_eq!(layer.hop_limit(&buf).unwrap(), 128);
539 }
540
541 #[test]
542 fn test_ipv6_set_addresses() {
543 let src = Ipv6Addr::LOCALHOST;
544 let dst = Ipv6Addr::LOCALHOST;
545 let mut buf = make_ipv6_buf(src, dst, 6);
546 let layer = Ipv6Layer::at_start();
547
548 let new_src = Ipv6Addr::new(0xfe80, 0, 0, 0, 0, 0, 0, 1);
549 layer.set_src(&mut buf, new_src).unwrap();
550 assert_eq!(layer.src(&buf).unwrap(), new_src);
551 }
552
553 #[test]
554 fn test_ipv6_payload_len() {
555 let src = Ipv6Addr::LOCALHOST;
556 let dst = Ipv6Addr::LOCALHOST;
557 let mut buf = make_ipv6_buf(src, dst, 58);
558 buf[4] = 0x00;
559 buf[5] = 0x28; let layer = Ipv6Layer::at_start();
561 assert_eq!(layer.payload_len(&buf).unwrap(), 40);
562 }
563
564 #[test]
565 fn test_ipv6_header_len() {
566 let buf = vec![0u8; 40];
567 let layer = Ipv6Layer::at_start();
568 assert_eq!(layer.header_len(&buf), IPV6_HEADER_LEN);
569 assert_eq!(IPV6_HEADER_LEN, 40);
570 }
571}