1#![deny(missing_docs)]
11
12use packet_dissector_core::dissector::{DispatchHint, DissectResult, Dissector};
13use packet_dissector_core::error::PacketError;
14use packet_dissector_core::field::{FieldDescriptor, FieldType, FieldValue};
15use packet_dissector_core::packet::DissectBuffer;
16use packet_dissector_core::util::{read_be_u16, read_be_u32};
17
18const MIN_HEADER_SIZE: usize = 4;
23
24const RESERVED_MUST_BE_ZERO_MASK: u16 = 0x4C00;
35
36const FD_CHECKSUM_PRESENT: usize = 0;
38const FD_KEY_PRESENT: usize = 1;
39const FD_SEQUENCE_NUMBER_PRESENT: usize = 2;
40const FD_RESERVED0: usize = 3;
41const FD_VERSION: usize = 4;
42const FD_PROTOCOL_TYPE: usize = 5;
43const FD_CHECKSUM: usize = 6;
44const FD_RESERVED1: usize = 7;
45const FD_KEY: usize = 8;
46const FD_SEQUENCE_NUMBER: usize = 9;
47
48static FIELD_DESCRIPTORS: &[FieldDescriptor] = &[
49 FieldDescriptor::new("checksum_present", "Checksum Present", FieldType::U8),
50 FieldDescriptor::new("key_present", "Key Present", FieldType::U8),
51 FieldDescriptor::new(
52 "sequence_number_present",
53 "Sequence Number Present",
54 FieldType::U8,
55 ),
56 FieldDescriptor::new("reserved0", "Reserved0", FieldType::U16),
57 FieldDescriptor::new("version", "Version", FieldType::U8),
58 FieldDescriptor::new("protocol_type", "Protocol Type", FieldType::U16),
59 FieldDescriptor::new("checksum", "Checksum", FieldType::U16).optional(),
60 FieldDescriptor::new("reserved1", "Reserved1", FieldType::U16).optional(),
61 FieldDescriptor::new("key", "Key", FieldType::U32).optional(),
62 FieldDescriptor::new("sequence_number", "Sequence Number", FieldType::U32).optional(),
63];
64
65pub struct GreDissector;
67
68impl Dissector for GreDissector {
69 fn name(&self) -> &'static str {
70 "Generic Routing Encapsulation"
71 }
72
73 fn short_name(&self) -> &'static str {
74 "GRE"
75 }
76
77 fn field_descriptors(&self) -> &'static [FieldDescriptor] {
78 FIELD_DESCRIPTORS
79 }
80
81 fn dissect<'pkt>(
82 &self,
83 data: &'pkt [u8],
84 buf: &mut DissectBuffer<'pkt>,
85 offset: usize,
86 ) -> Result<DissectResult, PacketError> {
87 if data.len() < MIN_HEADER_SIZE {
88 return Err(PacketError::Truncated {
89 expected: MIN_HEADER_SIZE,
90 actual: data.len(),
91 });
92 }
93
94 let flags_ver = read_be_u16(data, 0)?;
97
98 let c_flag = ((flags_ver >> 15) & 1) as u8;
101 let k_flag = ((flags_ver >> 13) & 1) as u8;
104 let s_flag = ((flags_ver >> 12) & 1) as u8;
107 let reserved0 = (flags_ver >> 3) & 0x01FF;
112 let version = (flags_ver & 0x0007) as u8;
115
116 if flags_ver & RESERVED_MUST_BE_ZERO_MASK != 0 {
121 return Err(PacketError::InvalidFieldValue {
122 field: "reserved0",
123 value: (flags_ver & RESERVED_MUST_BE_ZERO_MASK) as u32,
124 });
125 }
126
127 if version != 0 {
128 return Err(PacketError::InvalidFieldValue {
129 field: "version",
130 value: version as u32,
131 });
132 }
133
134 let mut header_len = MIN_HEADER_SIZE;
136 if c_flag != 0 {
137 header_len += 4; }
139 if k_flag != 0 {
140 header_len += 4; }
142 if s_flag != 0 {
143 header_len += 4; }
145
146 if data.len() < header_len {
147 return Err(PacketError::Truncated {
148 expected: header_len,
149 actual: data.len(),
150 });
151 }
152
153 let protocol_type = read_be_u16(data, 2)?;
154
155 buf.begin_layer(
156 self.short_name(),
157 None,
158 FIELD_DESCRIPTORS,
159 offset..offset + header_len,
160 );
161
162 buf.push_field(
163 &FIELD_DESCRIPTORS[FD_CHECKSUM_PRESENT],
164 FieldValue::U8(c_flag),
165 offset..offset + 1,
166 );
167 buf.push_field(
168 &FIELD_DESCRIPTORS[FD_KEY_PRESENT],
169 FieldValue::U8(k_flag),
170 offset..offset + 1,
171 );
172 buf.push_field(
173 &FIELD_DESCRIPTORS[FD_SEQUENCE_NUMBER_PRESENT],
174 FieldValue::U8(s_flag),
175 offset..offset + 1,
176 );
177 buf.push_field(
178 &FIELD_DESCRIPTORS[FD_RESERVED0],
179 FieldValue::U16(reserved0),
180 offset..offset + 2,
181 );
182 buf.push_field(
183 &FIELD_DESCRIPTORS[FD_VERSION],
184 FieldValue::U8(version),
185 offset..offset + 2,
186 );
187 buf.push_field(
188 &FIELD_DESCRIPTORS[FD_PROTOCOL_TYPE],
189 FieldValue::U16(protocol_type),
190 offset + 2..offset + 4,
191 );
192
193 let mut pos = MIN_HEADER_SIZE;
195
196 if c_flag != 0 {
200 let checksum = read_be_u16(data, pos)?;
201 let reserved1 = read_be_u16(data, pos + 2)?;
202 buf.push_field(
203 &FIELD_DESCRIPTORS[FD_CHECKSUM],
204 FieldValue::U16(checksum),
205 offset + pos..offset + pos + 2,
206 );
207 buf.push_field(
208 &FIELD_DESCRIPTORS[FD_RESERVED1],
209 FieldValue::U16(reserved1),
210 offset + pos + 2..offset + pos + 4,
211 );
212 pos += 4;
213 }
214
215 if k_flag != 0 {
218 let key = read_be_u32(data, pos)?;
219 buf.push_field(
220 &FIELD_DESCRIPTORS[FD_KEY],
221 FieldValue::U32(key),
222 offset + pos..offset + pos + 4,
223 );
224 pos += 4;
225 }
226
227 if s_flag != 0 {
230 let seq = read_be_u32(data, pos)?;
231 buf.push_field(
232 &FIELD_DESCRIPTORS[FD_SEQUENCE_NUMBER],
233 FieldValue::U32(seq),
234 offset + pos..offset + pos + 4,
235 );
236 }
237
238 buf.end_layer();
239
240 Ok(DissectResult::new(
243 header_len,
244 DispatchHint::ByEtherType(protocol_type),
245 ))
246 }
247}
248
249#[cfg(test)]
250mod tests {
251 use super::*;
252
253 fn dissect(data: &[u8]) -> Result<(DissectBuffer<'_>, DissectResult), PacketError> {
274 let mut buf = DissectBuffer::new();
275 let result = GreDissector.dissect(data, &mut buf, 0)?;
276 Ok((buf, result))
277 }
278
279 #[test]
280 fn parse_gre_basic() {
281 let raw: &[u8] = &[
283 0x00, 0x00, 0x08, 0x00, ];
286 let (buf, result) = dissect(raw).unwrap();
287 assert_eq!(result.bytes_consumed, 4);
288 assert_eq!(result.next, DispatchHint::ByEtherType(0x0800));
289
290 let layer = buf.layer_by_name("GRE").unwrap();
291 assert_eq!(
292 buf.field_by_name(layer, "checksum_present").unwrap().value,
293 FieldValue::U8(0)
294 );
295 assert_eq!(
296 buf.field_by_name(layer, "key_present").unwrap().value,
297 FieldValue::U8(0)
298 );
299 assert_eq!(
300 buf.field_by_name(layer, "sequence_number_present")
301 .unwrap()
302 .value,
303 FieldValue::U8(0)
304 );
305 assert_eq!(
306 buf.field_by_name(layer, "reserved0").unwrap().value,
307 FieldValue::U16(0)
308 );
309 assert_eq!(
310 buf.field_by_name(layer, "version").unwrap().value,
311 FieldValue::U8(0)
312 );
313 assert_eq!(
314 buf.field_by_name(layer, "protocol_type").unwrap().value,
315 FieldValue::U16(0x0800)
316 );
317 assert!(buf.field_by_name(layer, "checksum").is_none());
318 assert!(buf.field_by_name(layer, "key").is_none());
319 assert!(buf.field_by_name(layer, "sequence_number").is_none());
320 }
321
322 #[test]
323 fn parse_gre_with_checksum() {
324 let raw: &[u8] = &[
326 0x80, 0x00, 0x08, 0x00, 0xAB, 0xCD, 0x00, 0x00, ];
331 let (buf, result) = dissect(raw).unwrap();
332 assert_eq!(result.bytes_consumed, 8);
333
334 let layer = buf.layer_by_name("GRE").unwrap();
335 assert_eq!(
336 buf.field_by_name(layer, "checksum_present").unwrap().value,
337 FieldValue::U8(1)
338 );
339 assert_eq!(
340 buf.field_by_name(layer, "checksum").unwrap().value,
341 FieldValue::U16(0xABCD)
342 );
343 assert_eq!(
344 buf.field_by_name(layer, "reserved1").unwrap().value,
345 FieldValue::U16(0)
346 );
347 }
348
349 #[test]
350 fn parse_gre_with_key() {
351 let raw: &[u8] = &[
353 0x20, 0x00, 0x08, 0x00, 0x00, 0x01, 0x02, 0x03, ];
357 let (buf, result) = dissect(raw).unwrap();
358 assert_eq!(result.bytes_consumed, 8);
359
360 let layer = buf.layer_by_name("GRE").unwrap();
361 assert_eq!(
362 buf.field_by_name(layer, "key_present").unwrap().value,
363 FieldValue::U8(1)
364 );
365 assert_eq!(
366 buf.field_by_name(layer, "key").unwrap().value,
367 FieldValue::U32(0x00010203)
368 );
369 assert!(buf.field_by_name(layer, "checksum").is_none());
370 }
371
372 #[test]
373 fn parse_gre_with_sequence_number() {
374 let raw: &[u8] = &[
376 0x10, 0x00, 0x86, 0xDD, 0x00, 0x00, 0x00, 0x2A, ];
380 let (buf, result) = dissect(raw).unwrap();
381 assert_eq!(result.bytes_consumed, 8);
382 assert_eq!(result.next, DispatchHint::ByEtherType(0x86DD));
383
384 let layer = buf.layer_by_name("GRE").unwrap();
385 assert_eq!(
386 buf.field_by_name(layer, "sequence_number_present")
387 .unwrap()
388 .value,
389 FieldValue::U8(1)
390 );
391 assert_eq!(
392 buf.field_by_name(layer, "sequence_number").unwrap().value,
393 FieldValue::U32(42)
394 );
395 }
396
397 #[test]
398 fn parse_gre_all_options() {
399 let raw: &[u8] = &[
401 0xB0, 0x00, 0x08, 0x00, 0x12, 0x34, 0x00, 0x00, 0xDE, 0xAD, 0xBE, 0xEF, 0x00, 0x00, 0x00, 0x01, ];
408 let (buf, result) = dissect(raw).unwrap();
409 assert_eq!(result.bytes_consumed, 16);
410
411 let layer = buf.layer_by_name("GRE").unwrap();
412 assert_eq!(
413 buf.field_by_name(layer, "checksum_present").unwrap().value,
414 FieldValue::U8(1)
415 );
416 assert_eq!(
417 buf.field_by_name(layer, "key_present").unwrap().value,
418 FieldValue::U8(1)
419 );
420 assert_eq!(
421 buf.field_by_name(layer, "sequence_number_present")
422 .unwrap()
423 .value,
424 FieldValue::U8(1)
425 );
426 assert_eq!(
427 buf.field_by_name(layer, "checksum").unwrap().value,
428 FieldValue::U16(0x1234)
429 );
430 assert_eq!(
431 buf.field_by_name(layer, "key").unwrap().value,
432 FieldValue::U32(0xDEADBEEF)
433 );
434 assert_eq!(
435 buf.field_by_name(layer, "sequence_number").unwrap().value,
436 FieldValue::U32(1)
437 );
438 }
439
440 #[test]
441 fn parse_gre_truncated() {
442 let raw: &[u8] = &[0x00, 0x00, 0x08]; let err = GreDissector
444 .dissect(raw, &mut DissectBuffer::new(), 0)
445 .unwrap_err();
446 assert!(matches!(
447 err,
448 PacketError::Truncated {
449 expected: 4,
450 actual: 3
451 }
452 ));
453 }
454
455 #[test]
456 fn parse_gre_invalid_version() {
457 let raw: &[u8] = &[
459 0x00, 0x01, 0x08, 0x00, ];
462 let err = GreDissector
463 .dissect(raw, &mut DissectBuffer::new(), 0)
464 .unwrap_err();
465 assert!(matches!(
466 err,
467 PacketError::InvalidFieldValue {
468 field: "version",
469 value: 1,
470 }
471 ));
472 }
473
474 #[test]
475 fn parse_gre_truncated_optional_fields() {
476 let raw: &[u8] = &[
478 0x80, 0x00, 0x08, 0x00, ];
481 let err = GreDissector
482 .dissect(raw, &mut DissectBuffer::new(), 0)
483 .unwrap_err();
484 assert!(matches!(
485 err,
486 PacketError::Truncated {
487 expected: 8,
488 actual: 4
489 }
490 ));
491 }
492
493 #[test]
494 fn parse_gre_dispatch_ipv6() {
495 let raw: &[u8] = &[
496 0x00, 0x00, 0x86, 0xDD, ];
499 let (_, result) = dissect(raw).unwrap();
500 assert_eq!(result.next, DispatchHint::ByEtherType(0x86DD));
501 }
502
503 #[test]
509 fn parse_gre_rejects_reserved_bit1() {
510 let raw: &[u8] = &[0x40, 0x00, 0x08, 0x00];
512 let err = GreDissector
513 .dissect(raw, &mut DissectBuffer::new(), 0)
514 .unwrap_err();
515 assert!(matches!(
516 err,
517 PacketError::InvalidFieldValue {
518 field: "reserved0",
519 value: 0x4000,
520 }
521 ));
522 }
523
524 #[test]
527 fn parse_gre_rejects_reserved_bit4() {
528 let raw: &[u8] = &[0x08, 0x00, 0x08, 0x00];
530 let err = GreDissector
531 .dissect(raw, &mut DissectBuffer::new(), 0)
532 .unwrap_err();
533 assert!(matches!(
534 err,
535 PacketError::InvalidFieldValue {
536 field: "reserved0",
537 value: 0x0800,
538 }
539 ));
540 }
541
542 #[test]
545 fn parse_gre_rejects_reserved_bit5() {
546 let raw: &[u8] = &[0x04, 0x00, 0x08, 0x00];
548 let err = GreDissector
549 .dissect(raw, &mut DissectBuffer::new(), 0)
550 .unwrap_err();
551 assert!(matches!(
552 err,
553 PacketError::InvalidFieldValue {
554 field: "reserved0",
555 value: 0x0400,
556 }
557 ));
558 }
559
560 #[test]
565 fn parse_gre_reserved_bits_6_to_12() {
566 let raw: &[u8] = &[0x03, 0xF8, 0x08, 0x00];
571 let (buf, result) = dissect(raw).unwrap();
572 assert_eq!(result.bytes_consumed, 4);
573
574 let layer = buf.layer_by_name("GRE").unwrap();
575 assert_eq!(
576 buf.field_by_name(layer, "reserved0").unwrap().value,
577 FieldValue::U16(0x7F)
578 );
579 assert_eq!(
580 buf.field_by_name(layer, "version").unwrap().value,
581 FieldValue::U8(0)
582 );
583 }
584
585 #[test]
586 fn parse_gre_with_offset() {
587 let raw: &[u8] = &[
589 0x20, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x01, ];
593 let mut buf = DissectBuffer::new();
594 let result = GreDissector.dissect(raw, &mut buf, 100).unwrap();
595 assert_eq!(result.bytes_consumed, 8);
596
597 let layer = buf.layer_by_name("GRE").unwrap();
598 assert_eq!(layer.range, 100..108);
599 assert_eq!(
600 buf.field_by_name(layer, "protocol_type").unwrap().range,
601 102..104
602 );
603 assert_eq!(buf.field_by_name(layer, "key").unwrap().range, 104..108);
604 }
605
606 #[test]
607 fn field_descriptors_consistent() {
608 let descs = GreDissector.field_descriptors();
609 assert_eq!(descs.len(), 10);
610 assert_eq!(descs[FD_CHECKSUM_PRESENT].name, "checksum_present");
611 assert_eq!(descs[FD_KEY_PRESENT].name, "key_present");
612 assert_eq!(
613 descs[FD_SEQUENCE_NUMBER_PRESENT].name,
614 "sequence_number_present"
615 );
616 assert_eq!(descs[FD_RESERVED0].name, "reserved0");
617 assert_eq!(descs[FD_VERSION].name, "version");
618 assert_eq!(descs[FD_PROTOCOL_TYPE].name, "protocol_type");
619 assert_eq!(descs[FD_CHECKSUM].name, "checksum");
620 assert_eq!(descs[FD_RESERVED1].name, "reserved1");
621 assert_eq!(descs[FD_KEY].name, "key");
622 assert_eq!(descs[FD_SEQUENCE_NUMBER].name, "sequence_number");
623 }
624}