1use alloc::vec;
5use alloc::vec::Vec;
6
7use crate::types::EtherType;
8use crate::util::{internet_checksum, read_u16be, read_u32be, write_u16be};
9
10pub const GRE_MIN_LEN: usize = 4;
11
12const FLAG_CHECKSUM: u16 = 0x8000;
14const FLAG_ROUTING: u16 = 0x4000;
15const FLAG_KEY: u16 = 0x2000;
16const FLAG_SEQUENCE: u16 = 0x1000;
17const FLAG_STRICT_ROUTE: u16 = 0x0800;
18const FLAG_RECURSION_MASK: u16 = 0x0700;
19const FLAG_VERSION_MASK: u16 = 0x0007;
20const FLAG_RECURSION_SHIFT: u16 = 8;
21
22#[derive(Debug, Clone)]
24pub struct GrePacket<'a> {
25 buf: &'a [u8],
26}
27
28impl<'a> GrePacket<'a> {
29 pub fn new(buf: &'a [u8]) -> Option<Self> {
30 if buf.len() < GRE_MIN_LEN { return None; }
31 Some(Self { buf })
32 }
33
34 #[inline]
35 pub fn flags(&self) -> u16 {
36 read_u16be(&self.buf[..2])
37 }
38
39 #[inline] pub fn checksum_present(&self) -> bool { self.flags() & FLAG_CHECKSUM != 0 }
40 #[inline] pub fn routing_present(&self) -> bool { self.flags() & FLAG_ROUTING != 0 }
41 #[inline] pub fn key_present(&self) -> bool { self.flags() & FLAG_KEY != 0 }
42 #[inline] pub fn sequence_present(&self) -> bool { self.flags() & FLAG_SEQUENCE != 0 }
43 #[inline] pub fn strict_source_route(&self) -> bool { self.flags() & FLAG_STRICT_ROUTE != 0 }
44 #[inline] pub fn recursion_control(&self) -> u8 {
45 ((self.flags() & FLAG_RECURSION_MASK) >> FLAG_RECURSION_SHIFT) as u8
46 }
47 #[inline] pub fn version(&self) -> u8 {
48 (self.flags() & FLAG_VERSION_MASK) as u8
49 }
50
51 #[inline]
52 pub fn protocol_type(&self) -> EtherType {
53 EtherType::from(read_u16be(&self.buf[2..4]))
54 }
55
56 fn option_offset(&self) -> usize {
57 let mut off = GRE_MIN_LEN;
58 if self.checksum_present() { off += 4; }
59 if self.key_present() { off += 4; }
60 if self.sequence_present() { off += 4; }
61 if self.routing_present()
62 && off + 2 <= self.buf.len() {
63 let routing_len = read_u16be(&self.buf[off..off+2]) as usize;
64 off += routing_len;
65 }
66 off
67 }
68
69 pub fn checksum(&self) -> Option<u16> {
70 if self.checksum_present() && self.buf.len() >= 8 {
71 Some(read_u16be(&self.buf[4..6]))
72 } else { None }
73 }
74
75 pub fn key(&self) -> Option<u32> {
76 if !self.key_present() { return None; }
77 let mut off = GRE_MIN_LEN;
78 if self.checksum_present() { off += 4; }
79 if off + 4 <= self.buf.len() { Some(read_u32be(&self.buf[off..off+4])) } else { None }
80 }
81
82 pub fn sequence(&self) -> Option<u32> {
83 if !self.sequence_present() { return None; }
84 let mut off = GRE_MIN_LEN;
85 if self.checksum_present() { off += 4; }
86 if self.key_present() { off += 4; }
87 if off + 4 <= self.buf.len() { Some(read_u32be(&self.buf[off..off+4])) } else { None }
88 }
89
90 pub fn routing(&self) -> Option<&[u8]> {
91 if !self.routing_present() { return None; }
92 let mut off = GRE_MIN_LEN;
93 if self.checksum_present() { off += 4; }
94 if self.key_present() { off += 4; }
95 if self.sequence_present() { off += 4; }
96 if off + 2 <= self.buf.len() {
97 let len = read_u16be(&self.buf[off..off+2]) as usize;
98 let end = (off + len).min(self.buf.len());
99 Some(&self.buf[off..end])
100 } else { None }
101 }
102
103 #[inline]
104 pub fn header_length(&self) -> usize { self.option_offset() }
105
106 #[inline]
107 pub fn payload(&self) -> &'a [u8] { &self.buf[self.option_offset()..] }
108}
109
110pub struct GrePacketBuilder {
115 buf: Vec<u8>,
116 has_checksum: bool,
117 has_key: bool,
118 has_seq: bool,
119 key_val: u32,
120 seq_val: u32,
121 payload: Option<Vec<u8>>,
122}
123
124impl GrePacketBuilder {
125 pub fn new(protocol_type: EtherType) -> Self {
126 let mut buf = vec![0u8; GRE_MIN_LEN];
127 let pt: u16 = protocol_type.into();
128 write_u16be(&mut buf[2..4], pt);
129 Self {
130 buf, has_checksum: false, has_key: false, has_seq: false,
131 key_val: 0, seq_val: 0, payload: None,
132 }
133 }
134
135 pub fn key(mut self, key: u32) -> Self {
136 self.has_key = true; self.key_val = key; self
137 }
138
139 pub fn sequence(mut self, seq: u32) -> Self {
140 self.has_seq = true; self.seq_val = seq; self
141 }
142
143 pub fn checksum(mut self) -> Self {
144 self.has_checksum = true; self
145 }
146
147 pub fn recursion_control(mut self, v: u8) -> Self {
148 let flags = read_u16be(&self.buf[..2]);
149 let updated = (flags & !FLAG_RECURSION_MASK) | (((v as u16) << FLAG_RECURSION_SHIFT) & FLAG_RECURSION_MASK);
150 write_u16be(&mut self.buf[..2], updated);
151 self
152 }
153
154 pub fn version(mut self, v: u8) -> Self {
155 let flags = read_u16be(&self.buf[..2]);
156 write_u16be(&mut self.buf[..2], (flags & !FLAG_VERSION_MASK) | (v as u16 & FLAG_VERSION_MASK));
157 self
158 }
159
160 pub fn payload(mut self, data: &[u8]) -> Self {
161 self.payload = Some(data.to_vec());
162 self
163 }
164
165 pub fn build(mut self) -> Vec<u8> {
166 let mut flags = read_u16be(&self.buf[..2]);
167 if self.has_checksum { flags |= FLAG_CHECKSUM; }
168 if self.has_key { flags |= FLAG_KEY; }
169 if self.has_seq {
170 flags |= FLAG_SEQUENCE;
171 if !self.has_key { self.has_key = true; self.key_val = 0; flags |= FLAG_KEY; }
172 }
173 write_u16be(&mut self.buf[..2], flags);
174
175 let mut extras = Vec::new();
176 let csum_pos = if self.has_checksum { let p = extras.len() + GRE_MIN_LEN; extras.extend_from_slice(&[0u8; 4]); Some(p) } else { None };
178 if self.has_key { extras.extend_from_slice(&self.key_val.to_be_bytes()); }
180 if self.has_seq { extras.extend_from_slice(&self.seq_val.to_be_bytes()); }
182
183 let mut pkt = self.buf;
184 pkt.extend_from_slice(&extras);
185 if let Some(ref p) = self.payload { pkt.extend_from_slice(p); }
186
187 if let Some(pos) = csum_pos {
189 let csum = internet_checksum(&pkt);
190 write_u16be(&mut pkt[pos..pos+2], csum);
191 }
192
193 pkt
194 }
195}
196
197#[cfg(test)]
202mod tests {
203 use super::*;
204
205 #[test]
206 fn parse_basic_gre() {
207 let data = &[0x00u8, 0x00, 0x08, 0x00, 0xAA, 0xBB];
209 let pkt = GrePacket::new(data).unwrap();
210 assert!(!pkt.checksum_present());
211 assert!(!pkt.key_present());
212 assert!(!pkt.sequence_present());
213 assert_eq!(pkt.version(), 0);
214 assert_eq!(pkt.protocol_type(), EtherType::Ipv4);
215 assert_eq!(pkt.header_length(), 4);
216 assert_eq!(pkt.payload(), &[0xAA, 0xBB]);
217 assert_eq!(pkt.key(), None);
218 assert_eq!(pkt.sequence(), None);
219 }
220
221 #[test]
222 fn parse_gre_with_key() {
223 let mut data = vec![0x20u8, 0x00, 0x08, 0x00]; data.extend_from_slice(&0x12345678u32.to_be_bytes());
226 data.extend_from_slice(&[0xCC, 0xDD]);
227 let pkt = GrePacket::new(&data).unwrap();
228 assert!(pkt.key_present());
229 assert_eq!(pkt.key(), Some(0x12345678));
230 assert_eq!(pkt.header_length(), 8);
231 assert_eq!(pkt.payload(), &[0xCC, 0xDD]);
232 }
233
234 #[test]
235 fn parse_gre_with_key_seq() {
236 let mut data = vec![0x30u8, 0x00, 0x08, 0x00];
238 data.extend_from_slice(&1u32.to_be_bytes());
239 data.extend_from_slice(&42u32.to_be_bytes());
240 data.push(0xEE);
241 let pkt = GrePacket::new(&data).unwrap();
242 assert!(pkt.key_present());
243 assert!(pkt.sequence_present());
244 assert_eq!(pkt.key(), Some(1));
245 assert_eq!(pkt.sequence(), Some(42));
246 assert_eq!(pkt.header_length(), 12);
247 assert_eq!(pkt.payload(), &[0xEE]);
248 }
249
250 #[test]
251 fn build_roundtrip() {
252 let pkt = GrePacketBuilder::new(EtherType::Ipv4)
253 .key(0xABCD)
254 .sequence(100)
255 .payload(&[0x01, 0x02, 0x03])
256 .build();
257
258 let parsed = GrePacket::new(&pkt).unwrap();
259 assert_eq!(parsed.protocol_type(), EtherType::Ipv4);
260 assert_eq!(parsed.key(), Some(0xABCD));
261 assert_eq!(parsed.sequence(), Some(100));
262 assert!(parsed.key_present()); assert_eq!(parsed.payload(), &[0x01, 0x02, 0x03]);
264 }
265
266 #[test]
267 fn build_with_checksum() {
268 let pkt = GrePacketBuilder::new(EtherType::Ipv4)
269 .key(1)
270 .checksum()
271 .payload(&[0xAA])
272 .build();
273
274 let parsed = GrePacket::new(&pkt).unwrap();
275 assert!(parsed.checksum_present());
276 assert!(parsed.checksum().is_some());
277 assert_eq!(parsed.payload(), &[0xAA]);
278 }
279
280 #[test]
281 fn parse_too_short() {
282 assert!(GrePacket::new(&[]).is_none());
283 assert!(GrePacket::new(&[0u8; 3]).is_none());
284 assert!(GrePacket::new(&[0u8; 4]).is_some());
285 }
286
287 #[test]
288 fn header_length_variants() {
289 let basic = GrePacketBuilder::new(EtherType::Ipv4).build();
290 assert_eq!(GrePacket::new(&basic).unwrap().header_length(), 4);
291
292 let with_key = GrePacketBuilder::new(EtherType::Ipv4).key(1).build();
293 assert_eq!(GrePacket::new(&with_key).unwrap().header_length(), 8);
294
295 let with_key_seq = GrePacketBuilder::new(EtherType::Ipv4).key(1).sequence(1).build();
296 assert_eq!(GrePacket::new(&with_key_seq).unwrap().header_length(), 12);
297 }
298}