Skip to main content

nex_packet/
gre.rs

1//! GRE Packet abstraction.
2
3use crate::packet::{GenericMutablePacket, Packet};
4use bytes::{Buf, Bytes};
5use nex_core::bitfield::{u1, u3, u5, u16be, u32be};
6
7/// GRE (Generic Routing Encapsulation) Packet.
8///
9/// See RFCs 1701, 2784, 2890, 7676, 2637
10#[derive(Clone, Debug, PartialEq, Eq)]
11pub struct GrePacket {
12    pub checksum_present: u1,
13    pub routing_present: u1,
14    pub key_present: u1,
15    pub sequence_present: u1,
16    pub strict_source_route: u1,
17    pub recursion_control: u3,
18    pub zero_flags: u5,
19    pub version: u3,
20    pub protocol_type: u16be, // 0x800 for IPv4
21    pub checksum: Vec<u16be>,
22    pub offset: Vec<u16be>,
23    pub key: Vec<u32be>,
24    pub sequence: Vec<u32be>,
25    pub routing: Vec<u8>,
26    pub payload: Bytes,
27}
28
29impl Packet for GrePacket {
30    type Header = ();
31
32    fn from_buf(mut bytes: &[u8]) -> Option<Self> {
33        if bytes.remaining() < 4 {
34            return None;
35        }
36
37        let flags = bytes.get_u16();
38        let protocol_type = bytes.get_u16();
39
40        let checksum_present = ((flags >> 15) & 0x1) as u1;
41        let routing_present = ((flags >> 14) & 0x1) as u1;
42        let key_present = ((flags >> 13) & 0x1) as u1;
43        let sequence_present = ((flags >> 12) & 0x1) as u1;
44        let strict_source_route = ((flags >> 11) & 0x1) as u1;
45        let recursion_control = ((flags >> 8) & 0x7) as u3;
46        let zero_flags = ((flags >> 3) & 0x1f) as u5;
47        let version = (flags & 0x7) as u3;
48
49        // Retrieve optional fields in order
50        let mut checksum = Vec::new();
51        let mut offset = Vec::new();
52        let mut key = Vec::new();
53        let mut sequence = Vec::new();
54        let routing = Vec::new();
55
56        if checksum_present != 0 || routing_present != 0 {
57            if bytes.remaining() < 4 {
58                return None;
59            }
60            checksum.push(bytes.get_u16());
61            offset.push(bytes.get_u16());
62        }
63
64        if key_present != 0 {
65            if bytes.remaining() < 4 {
66                return None;
67            }
68            key.push(bytes.get_u32());
69        }
70
71        if sequence_present != 0 {
72            if bytes.remaining() < 4 {
73                return None;
74            }
75            sequence.push(bytes.get_u32());
76        }
77
78        if routing_present != 0 {
79            // Source-routed GRE parsing is not yet supported.
80            return None;
81        }
82
83        let payload = Bytes::copy_from_slice(bytes);
84
85        Some(Self {
86            checksum_present,
87            routing_present,
88            key_present,
89            sequence_present,
90            strict_source_route,
91            recursion_control,
92            zero_flags,
93            version,
94            protocol_type: protocol_type.into(),
95            checksum,
96            offset,
97            key,
98            sequence,
99            routing,
100            payload,
101        })
102    }
103
104    fn from_bytes(bytes: Bytes) -> Option<Self> {
105        Self::from_buf(&bytes)
106    }
107
108    fn to_bytes(&self) -> Bytes {
109        use bytes::{BufMut, BytesMut};
110
111        let mut buf = BytesMut::with_capacity(self.header_len());
112
113        // Build the flags field
114        let mut flags: u16 = 0;
115        flags |= (self.checksum_present as u16) << 15;
116        flags |= (self.routing_present as u16) << 14;
117        flags |= (self.key_present as u16) << 13;
118        flags |= (self.sequence_present as u16) << 12;
119        flags |= (self.strict_source_route as u16) << 11;
120        flags |= (self.recursion_control as u16) << 8;
121        flags |= (self.zero_flags as u16) << 3;
122        flags |= self.version as u16;
123
124        buf.put_u16(flags);
125        buf.put_u16(self.protocol_type.into());
126
127        if self.checksum_present != 0 || self.routing_present != 0 {
128            for c in &self.checksum {
129                buf.put_u16(*c);
130            }
131            for o in &self.offset {
132                buf.put_u16(*o);
133            }
134        }
135
136        if self.key_present != 0 {
137            for k in &self.key {
138                buf.put_u32(*k);
139            }
140        }
141
142        if self.sequence_present != 0 {
143            for s in &self.sequence {
144                buf.put_u32(*s);
145            }
146        }
147
148        if self.routing_present != 0 {
149            buf.put_slice(&self.routing);
150        }
151
152        buf.put_slice(&self.payload);
153
154        buf.freeze()
155    }
156    fn header(&self) -> Bytes {
157        use bytes::{BufMut, BytesMut};
158
159        let mut buf = BytesMut::with_capacity(self.header_len());
160
161        // Build the flags field
162        let mut flags: u16 = 0;
163        flags |= (self.checksum_present as u16) << 15;
164        flags |= (self.routing_present as u16) << 14;
165        flags |= (self.key_present as u16) << 13;
166        flags |= (self.sequence_present as u16) << 12;
167        flags |= (self.strict_source_route as u16) << 11;
168        flags |= (self.recursion_control as u16) << 8;
169        flags |= (self.zero_flags as u16) << 3;
170        flags |= self.version as u16;
171
172        buf.put_u16(flags);
173        buf.put_u16(self.protocol_type.into());
174
175        if self.checksum_present != 0 || self.routing_present != 0 {
176            for c in &self.checksum {
177                buf.put_u16(*c);
178            }
179            for o in &self.offset {
180                buf.put_u16(*o);
181            }
182        }
183
184        if self.key_present != 0 {
185            for k in &self.key {
186                buf.put_u32(*k);
187            }
188        }
189
190        if self.sequence_present != 0 {
191            for s in &self.sequence {
192                buf.put_u32(*s);
193            }
194        }
195
196        if self.routing_present != 0 {
197            buf.put_slice(&self.routing);
198        }
199
200        buf.freeze()
201    }
202
203    fn payload(&self) -> Bytes {
204        self.payload.clone()
205    }
206
207    fn header_len(&self) -> usize {
208        4 // base header: 2 bytes flags + 2 bytes protocol_type
209            + self.checksum_length()
210            + self.offset_length()
211            + self.key_length()
212            + self.sequence_length()
213            + self.routing_length()
214    }
215
216    fn payload_len(&self) -> usize {
217        self.payload.len()
218    }
219
220    fn total_len(&self) -> usize {
221        self.header_len() + self.payload_len()
222    }
223
224    fn into_parts(self) -> (Self::Header, Bytes) {
225        ((), self.to_bytes())
226    }
227}
228
229impl GrePacket {
230    pub fn checksum_length(&self) -> usize {
231        (self.checksum_present | self.routing_present) as usize * 2
232    }
233
234    pub fn offset_length(&self) -> usize {
235        (self.checksum_present | self.routing_present) as usize * 2
236    }
237
238    pub fn key_length(&self) -> usize {
239        self.key_present as usize * 4
240    }
241
242    pub fn sequence_length(&self) -> usize {
243        self.sequence_present as usize * 4
244    }
245
246    pub fn routing_length(&self) -> usize {
247        if 0 == self.routing_present {
248            0
249        } else {
250            self.routing.len()
251        }
252    }
253}
254
255/// Represents a mutable GRE packet.
256pub type MutableGrePacket<'a> = GenericMutablePacket<'a, GrePacket>;
257
258#[cfg(test)]
259mod tests {
260    use super::*;
261    use crate::packet::MutablePacket;
262
263    #[test]
264    fn gre_packet_test() {
265        let packet = Bytes::from_static(&[
266            0x00, /* no flags */
267            0x00, /* no flags, version 0 */
268            0x08, /* protocol 0x0800 */
269            0x00,
270        ]);
271
272        let gre_packet = GrePacket::from_buf(&mut packet.clone()).unwrap();
273
274        assert_eq!(&gre_packet.to_bytes(), &packet);
275    }
276
277    #[test]
278    fn gre_checksum_test() {
279        let packet = Bytes::from_static(&[
280            0x80, /* checksum on */
281            0x00, /* no flags, version 0 */
282            0x00, /* protocol 0x0000 */
283            0x00, 0x00, /* 16 bits of checksum */
284            0x00, 0x00, /* 16 bits of offset */
285            0x00,
286        ]);
287
288        let gre_packet = GrePacket::from_buf(&mut packet.clone()).unwrap();
289
290        assert_eq!(&gre_packet.to_bytes(), &packet);
291    }
292
293    #[test]
294    fn test_mutable_gre_packet_alias() {
295        let mut raw = [
296            0x00, 0x00, // flags
297            0x08, 0x00, // protocol type
298            0xaa, 0xbb,
299        ];
300
301        let mut packet = <MutableGrePacket as MutablePacket>::new(&mut raw).expect("mutable gre");
302        packet.header_mut()[2] = 0x86;
303        packet.header_mut()[3] = 0xdd; // IPv6 protocol
304        packet.payload_mut()[0] = 0xff;
305
306        let frozen = packet.freeze().expect("freeze");
307        assert_eq!(frozen.protocol_type, 0x86dd);
308        assert_eq!(frozen.payload[0], 0xff);
309    }
310
311    #[test]
312    fn gre_with_routing_present_is_not_parsed() {
313        let packet = Bytes::from_static(&[
314            0x40, 0x00, // routing flag on
315            0x08, 0x00, // protocol type
316            0x00, 0x00, // checksum
317            0x00, 0x00, // offset
318            0xaa, 0xbb, // routing data (unsupported)
319            0xcc, 0xdd, // payload
320        ]);
321
322        assert!(GrePacket::from_buf(&packet).is_none());
323    }
324
325    #[test]
326    fn gre_to_bytes_with_routing_present_does_not_panic() {
327        let packet = GrePacket {
328            checksum_present: 0,
329            routing_present: 1,
330            key_present: 0,
331            sequence_present: 0,
332            strict_source_route: 0,
333            recursion_control: 0,
334            zero_flags: 0,
335            version: 0,
336            protocol_type: 0x0800,
337            checksum: vec![0x1111],
338            offset: vec![0x2222],
339            key: vec![],
340            sequence: vec![],
341            routing: vec![0xaa, 0xbb],
342            payload: Bytes::from_static(&[0xcc]),
343        };
344
345        let bytes = packet.to_bytes();
346        assert_eq!(
347            bytes.as_ref(),
348            &[
349                0x40, 0x00, 0x08, 0x00, 0x11, 0x11, 0x22, 0x22, 0xaa, 0xbb, 0xcc
350            ]
351        );
352        assert_eq!(
353            packet.header().as_ref(),
354            &[0x40, 0x00, 0x08, 0x00, 0x11, 0x11, 0x22, 0x22, 0xaa, 0xbb]
355        );
356    }
357}