packet_strata/packet/tunnel/
gre.rs

1//! GRE (Generic Routing Encapsulation) protocol parser
2//!
3//! This module implements parsing for GRE tunnels as defined in:
4//! - RFC 2784: Generic Routing Encapsulation (GRE)
5//! - RFC 2890: Key and Sequence Number Extensions to GRE
6//! - RFC 2637: Point-to-Point Tunneling Protocol (PPTP) - Enhanced GRE
7//!
8//! # GRE Header Format (RFC 2784 + RFC 2890)
9//!
10//! ```text
11//!  0                   1                   2                   3
12//!  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
13//! +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
14//! |C|R|K|S|s|Recur|  Flags  | Ver |         Protocol Type         |
15//! +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
16//! |      Checksum (optional)      |       Offset (optional)       |
17//! +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
18//! |                         Key (optional)                        |
19//! +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
20//! |                  Sequence Number (optional)                   |
21//! +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
22//! ```
23//!
24//! # Key characteristics
25//!
26//! - Minimum header size: 4 bytes (no optional fields)
27//! - Maximum header size: 16 bytes (all optional fields present)
28//! - C flag: Checksum present
29//! - K flag: Key present
30//! - S flag: Sequence number present
31//! - Version: 0 for standard GRE, 1 for Enhanced GRE (PPTP)
32//! - Protocol Type: EtherType of encapsulated payload
33//!
34//! # Examples
35//!
36//! ## GRE with key field
37//!
38//! ```
39//! use packet_strata::packet::tunnel::gre::GreHeader;
40//! use packet_strata::packet::protocol::EtherProto;
41//! use packet_strata::packet::HeaderParser;
42//!
43//! // GRE packet with key field
44//! let packet = vec![
45//!     0x20, 0x00,  // flags_version (Key present, version 0)
46//!     0x08, 0x00,  // protocol_type (IPv4)
47//!     0x00, 0x00, 0x00, 0x2A,  // key = 42
48//!     // ... encapsulated payload follows ...
49//! ];
50//!
51//! let (header, payload) = GreHeader::from_bytes(&packet).unwrap();
52//! assert_eq!(header.version(), 0);
53//! assert_eq!(header.protocol_type(), EtherProto::IPV4);
54//! assert!(header.has_key());
55//! assert_eq!(header.key().unwrap(), 42);
56//! ```
57//!
58//! ## GRE with checksum and sequence number
59//!
60//! ```
61//! use packet_strata::packet::tunnel::gre::GreHeader;
62//! use packet_strata::packet::protocol::EtherProto;
63//! use packet_strata::packet::HeaderParser;
64//!
65//! // GRE packet with checksum and sequence number
66//! let packet = vec![
67//!     0xB0, 0x00,  // flags_version (C=1, K=1, S=1, version 0)
68//!     0x08, 0x00,  // protocol_type (IPv4)
69//!     0x12, 0x34,  // checksum
70//!     0x00, 0x00,  // offset (reserved)
71//!     0x00, 0x00, 0x00, 0x64,  // key = 100
72//!     0x00, 0x00, 0x00, 0x01,  // sequence number = 1
73//!     // ... encapsulated payload follows ...
74//! ];
75//!
76//! let (header, payload) = GreHeader::from_bytes(&packet).unwrap();
77//! assert!(header.has_checksum());
78//! assert!(header.has_key());
79//! assert!(header.has_sequence());
80//! assert_eq!(header.checksum().unwrap(), 0x1234);
81//! assert_eq!(header.key().unwrap(), 100);
82//! assert_eq!(header.sequence_number().unwrap(), 1);
83//! ```
84
85use std::fmt::{self, Formatter};
86
87use zerocopy::byteorder::{BigEndian, U16};
88use zerocopy::{FromBytes, IntoBytes, Unaligned};
89
90use crate::packet::protocol::EtherProto;
91use crate::packet::{HeaderParser, PacketHeader};
92
93/// GRE Header structure as defined in RFC 2784 and RFC 2890
94///
95/// Basic GRE header format (4 bytes minimum):
96/// ```text
97///  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
98/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
99/// |C|R|K|S|s|Recur|A| Flags | Ver |         Protocol Type         |
100/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
101/// |      Checksum (optional)      |       Offset (optional)       |
102/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
103/// |                         Key (optional)                        |
104/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
105/// |                 Sequence Number (optional)                    |
106/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
107/// ```
108#[repr(C, packed)]
109#[derive(
110    FromBytes, IntoBytes, Unaligned, Debug, Clone, Copy, zerocopy::KnownLayout, zerocopy::Immutable,
111)]
112pub struct GreHeader {
113    flags_version: U16<BigEndian>,
114    protocol_type: U16<BigEndian>,
115}
116
117impl GreHeader {
118    // GRE Flags (in the high byte of flags_version)
119    pub const FLAG_CHECKSUM: u16 = 0x8000; // Checksum Present (C bit)
120    pub const FLAG_ROUTING: u16 = 0x4000; // Routing Present (R bit) - deprecated
121    pub const FLAG_KEY: u16 = 0x2000; // Key Present (K bit)
122    pub const FLAG_SEQUENCE: u16 = 0x1000; // Sequence Number Present (S bit)
123    pub const FLAG_STRICT_ROUTE: u16 = 0x0800; // Strict Source Route (s bit) - deprecated
124    pub const FLAG_ACK: u16 = 0x0080; // Acknowledgment Present (A bit) - PPTP extension
125
126    pub const VERSION_MASK: u16 = 0x0007; // Version field (bits 13-15)
127    pub const RECUR_MASK: u16 = 0x0700; // Recursion control (bits 5-7) - deprecated
128    pub const FLAGS_MASK: u16 = 0x00F8; // Reserved flags (bits 8-12)
129
130    pub const VERSION_0: u16 = 0x0000; // GRE version 0 (RFC 2784)
131    pub const VERSION_1: u16 = 0x0001; // Enhanced GRE (RFC 2637 - PPTP)
132
133    #[allow(unused)]
134    const NAME: &'static str = "GreHeader";
135
136    /// Returns the flags and version field
137    #[inline]
138    pub fn flags_version(&self) -> u16 {
139        self.flags_version.get()
140    }
141
142    /// Returns the GRE version number (0 or 1)
143    #[inline]
144    pub fn version(&self) -> u8 {
145        (self.flags_version() & Self::VERSION_MASK) as u8
146    }
147
148    /// Returns the protocol type field (indicates the protocol type of the payload)
149    #[inline]
150    pub fn protocol_type(&self) -> EtherProto {
151        self.protocol_type.get().into()
152    }
153
154    /// Check if Checksum Present flag is set
155    #[inline]
156    pub fn has_checksum(&self) -> bool {
157        self.flags_version() & Self::FLAG_CHECKSUM != 0
158    }
159
160    /// Check if Routing Present flag is set (deprecated)
161    #[inline]
162    pub fn has_routing(&self) -> bool {
163        self.flags_version() & Self::FLAG_ROUTING != 0
164    }
165
166    /// Check if Key Present flag is set
167    #[inline]
168    pub fn has_key(&self) -> bool {
169        self.flags_version() & Self::FLAG_KEY != 0
170    }
171
172    /// Check if Sequence Number Present flag is set
173    #[inline]
174    pub fn has_sequence(&self) -> bool {
175        self.flags_version() & Self::FLAG_SEQUENCE != 0
176    }
177
178    /// Check if Strict Source Route flag is set (deprecated)
179    #[inline]
180    pub fn has_strict_route(&self) -> bool {
181        self.flags_version() & Self::FLAG_STRICT_ROUTE != 0
182    }
183
184    /// Check if Acknowledgment flag is set (PPTP extension)
185    #[inline]
186    pub fn has_ack(&self) -> bool {
187        self.flags_version() & Self::FLAG_ACK != 0
188    }
189
190    /// Returns the recursion control value (deprecated)
191    #[inline]
192    pub fn recursion_control(&self) -> u8 {
193        ((self.flags_version() & Self::RECUR_MASK) >> 8) as u8
194    }
195
196    /// Validates the GRE header
197    #[inline]
198    fn is_valid(&self) -> bool {
199        let version = self.version();
200
201        // Only version 0 and 1 are defined
202        if version > 1 {
203            return false;
204        }
205
206        // Version 0 (RFC 2784) - standard GRE
207        // Version 1 (RFC 2637) - Enhanced GRE (PPTP)
208        // Reserved flags must be zero for version 0
209        if version == 0 {
210            let reserved = self.flags_version() & Self::FLAGS_MASK;
211            if reserved != 0 {
212                return false;
213            }
214        }
215
216        true
217    }
218
219    /// Calculate the total header length including optional fields
220    #[inline]
221    pub fn header_length(&self) -> usize {
222        let mut len = Self::FIXED_LEN; // 4 bytes for basic header
223
224        // Add 4 bytes for checksum + offset (if present)
225        if self.has_checksum() || self.has_routing() {
226            len += 4;
227        }
228
229        // Add 4 bytes for key (if present)
230        if self.has_key() {
231            len += 4;
232        }
233
234        // Add 4 bytes for sequence number (if present)
235        if self.has_sequence() {
236            len += 4;
237        }
238
239        // Enhanced GRE (version 1) has acknowledgment number
240        if self.version() == 1 && self.has_ack() {
241            len += 4;
242        }
243
244        len
245    }
246
247    /// Returns a string representation of active flags
248    pub fn flags_string(&self) -> String {
249        let mut flags = Vec::new();
250
251        if self.has_checksum() {
252            flags.push("C");
253        }
254        if self.has_routing() {
255            flags.push("R");
256        }
257        if self.has_key() {
258            flags.push("K");
259        }
260        if self.has_sequence() {
261            flags.push("S");
262        }
263        if self.has_strict_route() {
264            flags.push("s");
265        }
266        if self.has_ack() {
267            flags.push("A");
268        }
269
270        if flags.is_empty() {
271            "none".to_string()
272        } else {
273            flags.join("")
274        }
275    }
276}
277
278/// GRE Header with optional fields parsed
279#[derive(Debug, Clone)]
280pub struct GreHeaderOpt<'a> {
281    pub header: &'a GreHeader,
282    pub raw_options: &'a [u8],
283}
284
285impl<'a> GreHeaderOpt<'a> {
286    /// Get the checksum value if present
287    pub fn checksum(&self) -> Option<u16> {
288        if !self.header.has_checksum() && !self.header.has_routing() {
289            return None;
290        }
291
292        if self.raw_options.len() < 2 {
293            return None;
294        }
295
296        Some(u16::from_be_bytes([
297            self.raw_options[0],
298            self.raw_options[1],
299        ]))
300    }
301
302    /// Get the offset value if present (only meaningful if routing is present)
303    pub fn offset(&self) -> Option<u16> {
304        if !self.header.has_checksum() && !self.header.has_routing() {
305            return None;
306        }
307
308        if self.raw_options.len() < 4 {
309            return None;
310        }
311
312        Some(u16::from_be_bytes([
313            self.raw_options[2],
314            self.raw_options[3],
315        ]))
316    }
317
318    /// Get the key value if present
319    pub fn key(&self) -> Option<u32> {
320        if !self.header.has_key() {
321            return None;
322        }
323
324        let mut offset = 0;
325        if self.header.has_checksum() || self.header.has_routing() {
326            offset += 4;
327        }
328
329        if self.raw_options.len() < offset + 4 {
330            return None;
331        }
332
333        let key_bytes = &self.raw_options[offset..offset + 4];
334        Some(u32::from_be_bytes([
335            key_bytes[0],
336            key_bytes[1],
337            key_bytes[2],
338            key_bytes[3],
339        ]))
340    }
341
342    /// Get the sequence number if present
343    pub fn sequence_number(&self) -> Option<u32> {
344        if !self.header.has_sequence() {
345            return None;
346        }
347
348        let mut offset = 0;
349        if self.header.has_checksum() || self.header.has_routing() {
350            offset += 4;
351        }
352        if self.header.has_key() {
353            offset += 4;
354        }
355
356        if self.raw_options.len() < offset + 4 {
357            return None;
358        }
359
360        let seq_bytes = &self.raw_options[offset..offset + 4];
361        Some(u32::from_be_bytes([
362            seq_bytes[0],
363            seq_bytes[1],
364            seq_bytes[2],
365            seq_bytes[3],
366        ]))
367    }
368
369    /// Get the acknowledgment number if present (Enhanced GRE - version 1 only)
370    pub fn acknowledgment_number(&self) -> Option<u32> {
371        if self.header.version() != 1 || !self.header.has_ack() {
372            return None;
373        }
374
375        let mut offset = 0;
376        if self.header.has_checksum() || self.header.has_routing() {
377            offset += 4;
378        }
379        if self.header.has_key() {
380            offset += 4;
381        }
382        if self.header.has_sequence() {
383            offset += 4;
384        }
385
386        if self.raw_options.len() < offset + 4 {
387            return None;
388        }
389
390        let ack_bytes = &self.raw_options[offset..offset + 4];
391        Some(u32::from_be_bytes([
392            ack_bytes[0],
393            ack_bytes[1],
394            ack_bytes[2],
395            ack_bytes[3],
396        ]))
397    }
398}
399
400impl std::ops::Deref for GreHeaderOpt<'_> {
401    type Target = GreHeader;
402
403    #[inline]
404    fn deref(&self) -> &Self::Target {
405        self.header
406    }
407}
408
409impl PacketHeader for GreHeader {
410    const NAME: &'static str = "GreHeader";
411    type InnerType = EtherProto;
412
413    #[inline]
414    fn inner_type(&self) -> Self::InnerType {
415        self.protocol_type()
416    }
417
418    /// Returns the total header length in bytes (including optional fields)
419    #[inline]
420    fn total_len(&self, _buf: &[u8]) -> usize {
421        self.header_length()
422    }
423
424    /// Validates the GRE header
425    #[inline]
426    fn is_valid(&self) -> bool {
427        self.is_valid()
428    }
429}
430
431impl HeaderParser for GreHeader {
432    type Output<'a> = GreHeaderOpt<'a>;
433
434    #[inline]
435    fn into_view<'a>(header: &'a Self, raw_options: &'a [u8]) -> Self::Output<'a> {
436        GreHeaderOpt {
437            header,
438            raw_options,
439        }
440    }
441}
442
443impl fmt::Display for GreHeader {
444    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
445        write!(
446            f,
447            "GRE v{} proto={}(0x{:04x}) flags={}",
448            self.version(),
449            self.protocol_type(),
450            self.protocol_type().0,
451            self.flags_string()
452        )
453    }
454}
455
456impl fmt::Display for GreHeaderOpt<'_> {
457    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
458        write!(
459            f,
460            "GRE v{} proto={} flags={}",
461            self.version(),
462            self.protocol_type(),
463            self.flags_string()
464        )?;
465
466        if let Some(key) = self.key() {
467            write!(f, " key={}", key)?;
468        }
469
470        if let Some(seq) = self.sequence_number() {
471            write!(f, " seq={}", seq)?;
472        }
473
474        if let Some(ack) = self.acknowledgment_number() {
475            write!(f, " ack={}", ack)?;
476        }
477
478        Ok(())
479    }
480}
481
482#[cfg(test)]
483mod tests {
484    use super::*;
485
486    #[test]
487    fn test_gre_header_size() {
488        assert_eq!(std::mem::size_of::<GreHeader>(), 4);
489        assert_eq!(GreHeader::FIXED_LEN, 4);
490    }
491
492    #[test]
493    fn test_gre_basic_header() {
494        let header = GreHeader {
495            flags_version: U16::new(0x0000), // No flags, version 0
496            protocol_type: U16::new(0x0800), // IPv4
497        };
498
499        assert_eq!(header.version(), 0);
500        assert_eq!(header.protocol_type(), EtherProto::IPV4);
501        assert!(!header.has_checksum());
502        assert!(!header.has_key());
503        assert!(!header.has_sequence());
504        assert!(header.is_valid());
505        assert_eq!(header.header_length(), 4);
506    }
507
508    #[test]
509    fn test_gre_with_key() {
510        let header = GreHeader {
511            flags_version: U16::new(0x2000), // Key present
512            protocol_type: U16::new(0x0800), // IPv4
513        };
514
515        assert!(header.has_key());
516        assert!(!header.has_checksum());
517        assert!(!header.has_sequence());
518        assert_eq!(header.header_length(), 8); // 4 + 4 for key
519    }
520
521    #[test]
522    fn test_gre_with_sequence() {
523        let header = GreHeader {
524            flags_version: U16::new(0x1000), // Sequence present
525            protocol_type: U16::new(0x0800), // IPv4
526        };
527
528        assert!(header.has_sequence());
529        assert!(!header.has_checksum());
530        assert!(!header.has_key());
531        assert_eq!(header.header_length(), 8); // 4 + 4 for sequence
532    }
533
534    #[test]
535    fn test_gre_with_checksum() {
536        let header = GreHeader {
537            flags_version: U16::new(0x8000), // Checksum present
538            protocol_type: U16::new(0x0800), // IPv4
539        };
540
541        assert!(header.has_checksum());
542        assert!(!header.has_key());
543        assert!(!header.has_sequence());
544        assert_eq!(header.header_length(), 8); // 4 + 4 for checksum+offset
545    }
546
547    #[test]
548    fn test_gre_all_flags() {
549        let header = GreHeader {
550            flags_version: U16::new(0xB000), // Checksum + Key + Sequence
551            protocol_type: U16::new(0x0800), // IPv4
552        };
553
554        assert!(header.has_checksum());
555        assert!(header.has_key());
556        assert!(header.has_sequence());
557        assert_eq!(header.header_length(), 16); // 4 + 4 + 4 + 4
558    }
559
560    #[test]
561    fn test_gre_version_validation() {
562        // Valid version 0
563        let header_v0 = GreHeader {
564            flags_version: U16::new(0x0000),
565            protocol_type: U16::new(0x0800),
566        };
567        assert!(header_v0.is_valid());
568        assert_eq!(header_v0.version(), 0);
569
570        // Valid version 1 (Enhanced GRE)
571        let header_v1 = GreHeader {
572            flags_version: U16::new(0x0001),
573            protocol_type: U16::new(0x880B), // PPP
574        };
575        assert!(header_v1.is_valid());
576        assert_eq!(header_v1.version(), 1);
577
578        // Invalid version
579        let header_invalid = GreHeader {
580            flags_version: U16::new(0x0002), // Version 2 - invalid
581            protocol_type: U16::new(0x0800),
582        };
583        assert!(!header_invalid.is_valid());
584    }
585
586    #[test]
587    fn test_gre_parsing_basic() {
588        let mut packet = Vec::new();
589
590        // GRE header: no flags, version 0, protocol IPv4
591        packet.extend_from_slice(&0x0000u16.to_be_bytes()); // flags_version
592        packet.extend_from_slice(&0x0800u16.to_be_bytes()); // protocol_type
593
594        // Add some payload
595        packet.extend_from_slice(b"payload");
596
597        let result = GreHeader::from_bytes(&packet);
598        assert!(result.is_ok());
599
600        let (header, payload) = result.unwrap();
601        assert_eq!(header.version(), 0);
602        assert_eq!(header.protocol_type(), EtherProto::IPV4);
603        assert_eq!(payload, b"payload");
604    }
605
606    #[test]
607    fn test_gre_parsing_with_key() {
608        let mut packet = Vec::new();
609
610        // GRE header with key
611        packet.extend_from_slice(&0x2000u16.to_be_bytes()); // flags_version (key present)
612        packet.extend_from_slice(&0x0800u16.to_be_bytes()); // protocol_type
613        packet.extend_from_slice(&0x12345678u32.to_be_bytes()); // key
614
615        // Add payload
616        packet.extend_from_slice(b"test");
617
618        let result = GreHeader::from_bytes(&packet);
619        assert!(result.is_ok());
620
621        let (header, payload) = result.unwrap();
622        assert!(header.has_key());
623        assert_eq!(header.key().unwrap(), 0x12345678);
624        assert_eq!(payload, b"test");
625    }
626
627    #[test]
628    fn test_gre_parsing_with_sequence() {
629        let mut packet = Vec::new();
630
631        // GRE header with sequence
632        packet.extend_from_slice(&0x1000u16.to_be_bytes()); // flags_version (sequence present)
633        packet.extend_from_slice(&0x0800u16.to_be_bytes()); // protocol_type
634        packet.extend_from_slice(&0x00000042u32.to_be_bytes()); // sequence number
635
636        let result = GreHeader::from_bytes(&packet);
637        assert!(result.is_ok());
638
639        let (header, _) = result.unwrap();
640        assert!(header.has_sequence());
641        assert_eq!(header.sequence_number().unwrap(), 0x42);
642    }
643
644    #[test]
645    fn test_gre_parsing_with_checksum() {
646        let mut packet = Vec::new();
647
648        // GRE header with checksum
649        packet.extend_from_slice(&0x8000u16.to_be_bytes()); // flags_version (checksum present)
650        packet.extend_from_slice(&0x0800u16.to_be_bytes()); // protocol_type
651        packet.extend_from_slice(&0xABCDu16.to_be_bytes()); // checksum
652        packet.extend_from_slice(&0x0000u16.to_be_bytes()); // offset
653
654        let result = GreHeader::from_bytes(&packet);
655        assert!(result.is_ok());
656
657        let (header, _) = result.unwrap();
658        assert!(header.has_checksum());
659        assert_eq!(header.checksum().unwrap(), 0xABCD);
660    }
661
662    #[test]
663    fn test_gre_parsing_all_options() {
664        let mut packet = Vec::new();
665
666        // GRE header with all options
667        packet.extend_from_slice(&0xB000u16.to_be_bytes()); // C + K + S flags
668        packet.extend_from_slice(&0x0800u16.to_be_bytes()); // protocol_type
669        packet.extend_from_slice(&0x1234u16.to_be_bytes()); // checksum
670        packet.extend_from_slice(&0x0000u16.to_be_bytes()); // offset
671        packet.extend_from_slice(&0xDEADBEEFu32.to_be_bytes()); // key
672        packet.extend_from_slice(&0x00000100u32.to_be_bytes()); // sequence
673
674        let result = GreHeader::from_bytes(&packet);
675        assert!(result.is_ok());
676
677        let (header, _) = result.unwrap();
678        assert!(header.has_checksum());
679        assert!(header.has_key());
680        assert!(header.has_sequence());
681        assert_eq!(header.checksum().unwrap(), 0x1234);
682        assert_eq!(header.key().unwrap(), 0xDEADBEEF);
683        assert_eq!(header.sequence_number().unwrap(), 0x100);
684    }
685
686    #[test]
687    fn test_gre_parsing_too_small() {
688        let packet = vec![0u8; 3]; // Only 3 bytes, need 4
689
690        let result = GreHeader::from_bytes(&packet);
691        assert!(result.is_err());
692    }
693
694    #[test]
695    fn test_gre_flags_string() {
696        let header1 = GreHeader {
697            flags_version: U16::new(0x0000),
698            protocol_type: U16::new(0x0800),
699        };
700        assert_eq!(header1.flags_string(), "none");
701
702        let header2 = GreHeader {
703            flags_version: U16::new(0x8000), // C
704            protocol_type: U16::new(0x0800),
705        };
706        assert_eq!(header2.flags_string(), "C");
707
708        let header3 = GreHeader {
709            flags_version: U16::new(0xB000), // C + K + S
710            protocol_type: U16::new(0x0800),
711        };
712        assert_eq!(header3.flags_string(), "CKS");
713    }
714
715    #[test]
716    fn test_gre_nvgre_scenario() {
717        // NVGRE uses protocol type 0x6558 (Transparent Ethernet Bridging)
718        let mut packet = Vec::new();
719
720        packet.extend_from_slice(&0x2000u16.to_be_bytes()); // Key present
721        packet.extend_from_slice(&0x6558u16.to_be_bytes()); // TEB protocol
722        packet.extend_from_slice(&0x00010001u32.to_be_bytes()); // VSID in key field
723
724        let result = GreHeader::from_bytes(&packet);
725        assert!(result.is_ok());
726
727        let (header, _) = result.unwrap();
728        assert_eq!(header.protocol_type(), EtherProto::TEB);
729        assert!(header.has_key());
730        assert_eq!(header.key().unwrap(), 0x00010001);
731    }
732
733    #[test]
734    fn test_gre_enhanced_version_1() {
735        // Enhanced GRE (PPTP) - version 1
736        let mut packet = Vec::new();
737
738        packet.extend_from_slice(&0x3081u16.to_be_bytes()); // K + S + A flags, version 1
739        packet.extend_from_slice(&0x880Bu16.to_be_bytes()); // PPP protocol
740        packet.extend_from_slice(&0x0004u16.to_be_bytes()); // Payload length (in key field)
741        packet.extend_from_slice(&0x0001u16.to_be_bytes()); // Call ID
742        packet.extend_from_slice(&0x00000001u32.to_be_bytes()); // Sequence number
743        packet.extend_from_slice(&0x00000000u32.to_be_bytes()); // Acknowledgment number
744
745        let result = GreHeader::from_bytes(&packet);
746        assert!(result.is_ok());
747
748        let (header, _) = result.unwrap();
749        assert_eq!(header.version(), 1);
750        assert!(header.has_key());
751        assert!(header.has_sequence());
752        assert!(header.has_ack());
753    }
754
755    #[test]
756    fn test_gre_protocol_types() {
757        // Test various protocol types
758        let protocols = vec![
759            (EtherProto::IPV4, "IPv4"),
760            (EtherProto::IPV6, "IPv6"),
761            (EtherProto::TEB, "TEB"),
762            (EtherProto::PPP_MP, "PPP"),
763            (EtherProto::MPLS_UC, "MPLS unicast"),
764        ];
765
766        for (proto_type, _name) in protocols {
767            let header = GreHeader {
768                flags_version: U16::new(0x0000),
769                protocol_type: U16::new(proto_type.0.get()),
770            };
771
772            assert_eq!(header.protocol_type(), proto_type);
773            assert!(header.is_valid());
774        }
775    }
776
777    #[test]
778    fn test_gre_header_length_calculation() {
779        // No options
780        let h1 = GreHeader {
781            flags_version: U16::new(0x0000),
782            protocol_type: U16::new(0x0800),
783        };
784        assert_eq!(h1.header_length(), 4);
785
786        // Checksum only
787        let h2 = GreHeader {
788            flags_version: U16::new(0x8000),
789            protocol_type: U16::new(0x0800),
790        };
791        assert_eq!(h2.header_length(), 8);
792
793        // Key only
794        let h3 = GreHeader {
795            flags_version: U16::new(0x2000),
796            protocol_type: U16::new(0x0800),
797        };
798        assert_eq!(h3.header_length(), 8);
799
800        // Sequence only
801        let h4 = GreHeader {
802            flags_version: U16::new(0x1000),
803            protocol_type: U16::new(0x0800),
804        };
805        assert_eq!(h4.header_length(), 8);
806
807        // Checksum + Key
808        let h5 = GreHeader {
809            flags_version: U16::new(0xA000),
810            protocol_type: U16::new(0x0800),
811        };
812        assert_eq!(h5.header_length(), 12);
813
814        // All options (C + K + S)
815        let h6 = GreHeader {
816            flags_version: U16::new(0xB000),
817            protocol_type: U16::new(0x0800),
818        };
819        assert_eq!(h6.header_length(), 16);
820    }
821}