1use alloc::vec;
5use alloc::vec::Vec;
6
7use crate::types::EtherType;
8use crate::util::{seal_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 crate::parser_new!(GRE_MIN_LEN);
30
31 #[inline]
33 pub fn as_bytes(&self) -> &'a [u8] { self.buf }
34
35 #[inline]
36 pub fn flags(&self) -> u16 {
37 read_u16be(&self.buf[..2])
38 }
39
40 #[inline] pub fn checksum_present(&self) -> bool { self.flags() & FLAG_CHECKSUM != 0 }
41 #[inline] pub fn routing_present(&self) -> bool { self.flags() & FLAG_ROUTING != 0 }
42 #[inline] pub fn key_present(&self) -> bool { self.flags() & FLAG_KEY != 0 }
43 #[inline] pub fn sequence_present(&self) -> bool { self.flags() & FLAG_SEQUENCE != 0 }
44 #[inline] pub fn strict_source_route(&self) -> bool { self.flags() & FLAG_STRICT_ROUTE != 0 }
45 #[inline] pub fn recursion_control(&self) -> u8 {
46 ((self.flags() & FLAG_RECURSION_MASK) >> FLAG_RECURSION_SHIFT) as u8
47 }
48 #[inline] pub fn version(&self) -> u8 {
49 (self.flags() & FLAG_VERSION_MASK) as u8
50 }
51
52 #[inline]
53 pub fn protocol_type(&self) -> EtherType {
54 EtherType::from(read_u16be(&self.buf[2..4]))
55 }
56
57 fn option_offset(&self) -> usize {
58 let mut off = GRE_MIN_LEN;
59 if self.checksum_present() { off += 4; }
60 if self.key_present() { off += 4; }
61 if self.sequence_present() { off += 4; }
62 if self.routing_present()
63 && off + 2 <= self.buf.len() {
64 let routing_len = read_u16be(&self.buf[off..off+2]) as usize;
65 off += routing_len;
66 }
67 off
68 }
69
70 pub fn checksum(&self) -> Option<u16> {
71 if self.checksum_present() && self.buf.len() >= 8 {
72 Some(read_u16be(&self.buf[4..6]))
73 } else { None }
74 }
75
76 pub fn key(&self) -> Option<u32> {
77 if !self.key_present() { return None; }
78 let mut off = GRE_MIN_LEN;
79 if self.checksum_present() { off += 4; }
80 if off + 4 <= self.buf.len() { Some(read_u32be(&self.buf[off..off+4])) } else { None }
81 }
82
83 pub fn sequence(&self) -> Option<u32> {
84 if !self.sequence_present() { return None; }
85 let mut off = GRE_MIN_LEN;
86 if self.checksum_present() { off += 4; }
87 if self.key_present() { off += 4; }
88 if off + 4 <= self.buf.len() { Some(read_u32be(&self.buf[off..off+4])) } else { None }
89 }
90
91 pub fn routing(&self) -> Option<&[u8]> {
92 if !self.routing_present() { return None; }
93 let mut off = GRE_MIN_LEN;
94 if self.checksum_present() { off += 4; }
95 if self.key_present() { off += 4; }
96 if self.sequence_present() { off += 4; }
97 if off + 2 <= self.buf.len() {
98 let len = read_u16be(&self.buf[off..off+2]) as usize;
99 let end = (off + len).min(self.buf.len());
100 Some(&self.buf[off..end])
101 } else { None }
102 }
103
104 #[inline]
105 pub fn header_length(&self) -> usize { self.option_offset() }
106
107 #[inline]
108 pub fn payload(&self) -> &'a [u8] { &self.buf[self.option_offset()..] }
109}
110
111pub struct GrePacketBuilder {
116 buf: Vec<u8>,
117 has_checksum: bool,
118 has_key: bool,
119 has_seq: bool,
120 key_val: u32,
121 seq_val: u32,
122 payload: Option<Vec<u8>>,
123}
124
125impl GrePacketBuilder {
126 pub fn new(protocol_type: EtherType) -> Self {
127 let mut buf = vec![0u8; GRE_MIN_LEN];
128 let pt: u16 = protocol_type.into();
129 write_u16be(&mut buf[2..4], pt);
130 Self {
131 buf, has_checksum: false, has_key: false, has_seq: false,
132 key_val: 0, seq_val: 0, payload: None,
133 }
134 }
135
136 pub fn key(mut self, key: u32) -> Self {
137 self.has_key = true; self.key_val = key; self
138 }
139
140 pub fn sequence(mut self, seq: u32) -> Self {
141 self.has_seq = true; self.seq_val = seq; self
142 }
143
144 pub fn checksum(mut self) -> Self {
145 self.has_checksum = true; self
146 }
147
148 pub fn recursion_control(mut self, v: u8) -> Self {
149 let flags = read_u16be(&self.buf[..2]);
150 let updated = (flags & !FLAG_RECURSION_MASK) | (((v as u16) << FLAG_RECURSION_SHIFT) & FLAG_RECURSION_MASK);
151 write_u16be(&mut self.buf[..2], updated);
152 self
153 }
154
155 pub fn version(mut self, v: u8) -> Self {
156 let flags = read_u16be(&self.buf[..2]);
157 write_u16be(&mut self.buf[..2], (flags & !FLAG_VERSION_MASK) | (v as u16 & FLAG_VERSION_MASK));
158 self
159 }
160
161 pub fn payload(mut self, data: &[u8]) -> Self {
162 self.payload = Some(data.to_vec());
163 self
164 }
165
166 pub fn build(mut self) -> Vec<u8> {
167 let mut flags = read_u16be(&self.buf[..2]);
168 if self.has_checksum { flags |= FLAG_CHECKSUM; }
169 if self.has_key { flags |= FLAG_KEY; }
170 if self.has_seq {
171 flags |= FLAG_SEQUENCE;
172 if !self.has_key { self.has_key = true; self.key_val = 0; flags |= FLAG_KEY; }
173 }
174 write_u16be(&mut self.buf[..2], flags);
175
176 let mut extras = Vec::new();
177 let csum_pos = if self.has_checksum { let p = extras.len() + GRE_MIN_LEN; extras.extend_from_slice(&[0u8; 4]); Some(p) } else { None };
179 if self.has_key { extras.extend_from_slice(&self.key_val.to_be_bytes()); }
181 if self.has_seq { extras.extend_from_slice(&self.seq_val.to_be_bytes()); }
183
184 let mut pkt = self.buf;
185 pkt.extend_from_slice(&extras);
186 if let Some(ref p) = self.payload { pkt.extend_from_slice(p); }
187
188 if let Some(pos) = csum_pos {
190 seal_internet_checksum(&mut pkt, pos);
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}