net_parser_rs/layer4/
vxlan.rs

1use crate::Error;
2use byteorder::{BigEndian as BE, WriteBytesExt};
3use nom::*;
4use std::mem::size_of;
5use std::io::{Cursor, Write};
6
7#[derive(Clone, Copy, Debug)]
8pub struct Vxlan<'a> {
9    pub flags: u16,
10    pub group_policy_id: u16,
11    pub raw_network_identifier: u32,
12    pub network_identifier: u32, // only can use 3 bytes
13    pub payload: &'a [u8],
14}
15
16impl<'a> Vxlan<'a> {
17    pub fn as_bytes(&self) -> Vec<u8> {
18        let inner = Vec::with_capacity(
19            size_of::<u16>() * 2
20                + size_of::<u32>()
21                + self.payload.len()
22        );
23        let mut writer = Cursor::new(inner);
24        writer.write_u16::<BE>(self.flags).unwrap();
25        writer.write_u16::<BE>(self.group_policy_id).unwrap();
26        writer.write_u32::<BE>(self.raw_network_identifier).unwrap();
27        writer.write(self.payload).unwrap();
28        writer.into_inner()
29    }
30
31    pub fn parse<'b>(input: &'b [u8], endianness: nom::Endianness) -> Result<(&'b [u8], Vxlan<'b>), Error> {
32        // TODO: Is Endianness really unknown?
33        do_parse!(input,
34            flags: u16!(endianness) >>
35            group_policy_id: u16!(endianness) >>
36            network_identifier: u32!(endianness) >> // actually u24 plus 8 reserved bits.
37            //reserved: be_u8 >> // accounted for in bytes captured under network_identifier
38            payload: rest >> (
39                Vxlan {
40                    flags: flags,
41                    group_policy_id: group_policy_id,
42                    raw_network_identifier: network_identifier,
43                    network_identifier: network_identifier>>8,
44                    payload: payload
45                }
46            )
47        ).map_err(Error::from)
48    }
49}
50
51#[cfg(test)]
52mod tests {
53    use crate::{
54        layer2::ethernet::Ethernet,
55        layer3::ipv4::IPv4,
56        layer4::{
57            udp::Udp,
58            vxlan::Vxlan,
59        },
60        tests::util::parse_hex_dump,
61    };
62
63    #[test]
64    fn encapsulated() {
65        // Packet sample came from https://www.cloudshark.org/captures/670aeb7bad79 
66        let bytes = parse_hex_dump(r##"
67            # Frame 3: 148 bytes on wire (1184 bits), 148 bytes captured (1184 bits) on interface 0
68            # Ethernet II, Src: CadmusCo_ae:4d:62 (08:00:27:ae:4d:62), Dst: CadmusCo_f2:1d:8c (08:00:27:f2:1d:8c)
69            # Internet Protocol Version 4, Src: 192.168.56.11, Dst: 192.168.56.12
70            # User Datagram Protocol, Src Port: 48134 (48134), Dst Port: 4789 (4789)
71            # Virtual eXtensible Local Area Network
72            # Ethernet II, Src: ba:09:2b:6e:f8:be (ba:09:2b:6e:f8:be), Dst: 4a:7f:01:3b:a2:71 (4a:7f:01:3b:a2:71)
73            # Internet Protocol Version 4, Src: 10.0.0.1, Dst: 10.0.0.2
74            # Internet Control Message Protocol
75            0000   08 00 27 f2 1d 8c 08 00 27 ae 4d 62 08 00 45 00  ..'.....'.Mb..E.
76            0010   00 86 d9 99 40 00 40 11 6f 65 c0 a8 38 0b c0 a8  ....@.@.oe..8...
77            0020   38 0c bc 06 12 b5 00 72 00 00 08 00 00 00 00 00  8......r........
78            0030   7b 00 4a 7f 01 3b a2 71 ba 09 2b 6e f8 be 08 00  {.J..;.q..+n....
79            0040   45 00 00 54 2f 4f 40 00 40 01 f7 57 0a 00 00 01  E..T/O@.@..W....
80            0050   0a 00 00 02 08 00 4c 8a 0d 3d 00 01 a3 8c 7c 57  ......L..=....|W
81            0060   00 00 00 00 b5 80 0a 00 00 00 00 00 10 11 12 13  ................
82            0070   14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 21 22 23  ............ !"#
83            0080   24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30 31 32 33  $%&'()*+,-./0123
84            0090   34 35 36 37                                      4567
85        "##).unwrap();
86        assert_eq!(bytes.len(), 148);
87
88        let enet = Ethernet::parse(bytes.as_slice()).expect("Invalid ethernet").1;
89        assert_eq!(format!("{}", enet.dst_mac), "08:00:27:f2:1d:8c");
90
91        let ip: IPv4 = IPv4::parse(enet.payload).expect("Invalid IPv4").1;
92        assert_eq!(format!("{}", ip.dst_ip), "192.168.56.12");
93
94        let udp: Udp = Udp::parse(ip.payload).expect("Invalid udp").1;
95        assert_eq!(udp.dst_port, 4789);
96
97        let (remainder, vxlan) = Vxlan::parse(&udp.payload, nom::Endianness::Big).expect("Invalid VXLAN");
98        assert_eq!(remainder.len(), 0);
99        assert_eq!(vxlan.flags, 0x0800);
100        assert_eq!(vxlan.network_identifier, 123);
101
102        assert_eq!(vxlan.as_bytes().as_slice(), udp.payload);
103
104        let enet2 = Ethernet::parse(vxlan.payload).expect("Invalid inner Ethernet").1;
105        assert_eq!(format!("{}", enet2.dst_mac), "4a:7f:01:3b:a2:71");
106
107        let ip2: IPv4 = IPv4::parse(enet2.payload).expect("Invalid Inner IPv4").1;
108        assert_eq!(format!("{}", ip2.dst_ip), "10.0.0.2");
109    }
110
111    #[test]
112    fn not_encapsulated() {
113        let bytes = parse_hex_dump(r##"
114            # Frame 4: 44 bytes on wire (352 bits), 44 bytes captured (352 bits) on interface 1
115            # Ethernet II, Src: Apple_b2:43:ff (68:5b:35:b2:43:ff), Dst: 00:86:9c:66:13:11 (00:86:9c:66:13:11)
116            # Internet Protocol Version 4, Src: 192.168.0.216, Dst: 1.1.1.1
117            # User Datagram Protocol, Src Port: 60406 (60406), Dst Port: 5300 (5300)
118            # Data (2 bytes)
119            0000   00 86 9c 66 13 11 68 5b 35 b2 43 ff 08 00 45 00  ...f..h[5.C...E.
120            0010   00 1e e2 7c 00 00 40 11 00 00 c0 a8 00 d8 01 01  ...|..@.........
121            0020   01 01 eb f6 14 b4 00 0a c3 9d 20 0a              .......... .
122        "##).unwrap();
123
124        assert_eq!(bytes.len(), 44);
125
126        let enet = Ethernet::parse(bytes.as_slice()).expect("Invalid ethernet").1;
127        assert_eq!(format!("{}", enet.dst_mac), "00:86:9c:66:13:11");
128
129        let ip: IPv4 = IPv4::parse(enet.payload).expect("Invalid IPv4").1;
130        assert_eq!(format!("{}", ip.dst_ip), "1.1.1.1");
131
132        let udp: Udp = Udp::parse(ip.payload).expect("Invalid udp").1;
133        assert_eq!(udp.dst_port, 5300);
134
135        let vxlan = Vxlan::parse(&udp.payload, nom::Endianness::Big);
136        assert!(vxlan.is_err(), "Should not parse as VXLan")
137
138    }
139}