scalpel/layers/
mpls.rs

1//! Multi Label Protocol Switching
2
3use std::convert::TryInto;
4
5use serde::Serialize;
6
7use crate::errors::Error;
8use crate::layers::ethernet;
9use crate::types::{ETHERTYPE_MPLS_MULTICAST, ETHERTYPE_MPLS_UNICAST};
10use crate::Layer;
11
12use super::ipv4::IPv4;
13
14/// Default Header Length for MPLS Packets
15pub const MPLS_HEADER_LENGTH: usize = 4_usize;
16
17// Register Ourselves to the Ethernet layer, as this is a 2.5 layer protocol
18pub(crate) fn register_defaults() -> Result<(), Error> {
19    ethernet::register_ethertype(ETHERTYPE_MPLS_UNICAST, MPLS::creator)?;
20    ethernet::register_ethertype(ETHERTYPE_MPLS_MULTICAST, MPLS::creator)
21}
22
23#[derive(Debug, Default, Serialize, Copy, Clone)]
24pub struct MPLSLabel {
25    //Make built-in types
26    #[serde(serialize_with = "crate::types::hex::serialize_lower_hex_u32")]
27    label: u32, //This is only 20 bits
28    #[serde(serialize_with = "crate::types::hex::serialize_lower_hex_u8")]
29    exp: u8, //This is only 3 bits
30    // #[serde(serialize_with = "crate::types::hex::serialize_lower_hex_u8")]
31    bos: bool, //This is only 1 bit
32    #[serde(serialize_with = "crate::types::hex::serialize_lower_hex_u8")]
33    ttl: u8, //This is 1 byte
34}
35
36#[derive(Debug, Default, Serialize, Clone)]
37pub struct MPLS {
38    labels: Vec<MPLSLabel>,
39}
40
41impl MPLS {
42    pub fn creator() -> Box<dyn Layer + Send> {
43        Box::<MPLS>::default()
44    }
45}
46
47impl Layer for MPLS {
48    fn decode_bytes(
49        &mut self,
50        bytes: &[u8],
51    ) -> Result<(Option<Box<dyn Layer + Send>>, usize), Error> {
52        if bytes.len() < MPLS_HEADER_LENGTH {
53            return Err(Error::TooShort {
54                required: MPLS_HEADER_LENGTH,
55                available: bytes.len(),
56                data: hex::encode(bytes),
57            });
58        }
59
60        let mut byte_offset = 0;
61
62        loop {
63            //FIXME:For now the first few bits are not useful in label,exp and bos
64            let label =
65                u32::from_be_bytes(bytes[byte_offset..(byte_offset + 4)].try_into().unwrap()) >> 12;
66            let exp = u8::from_be(bytes[byte_offset + 2] << 4) >> 5;
67            let bos = bytes[byte_offset + 2] & 0x01 == 0x01;
68            let ttl = bytes[byte_offset + 3];
69
70            self.labels.push(MPLSLabel {
71                label,
72                exp,
73                bos,
74                ttl,
75            });
76            byte_offset += MPLS_HEADER_LENGTH;
77
78            if bos {
79                break;
80            }
81        }
82
83        //FIXME:Support IPV6
84        Ok((Some(IPv4::creator()), byte_offset))
85    }
86
87    fn name(&self) -> &'static str {
88        "MPLS"
89    }
90
91    fn short_name(&self) -> &'static str {
92        "mpls"
93    }
94}
95
96#[cfg(test)]
97mod tests {
98
99    use crate::layers;
100    use crate::{Layer, Packet, ENCAP_TYPE_ETH};
101
102    wasm_tests! {
103        #[test]
104        fn parse_valid_mpls_packet() {
105            let _ = layers::register_defaults();
106
107            let mpls_packet = vec![
108                0x00, 0x30, 0x96, 0xe6, 0xfc, 0x39, 0x00, 0x30, 0x96, 0x05, 0x28, 0x38, 0x88, 0x47,
109                0x00, 0x01, 0xdd, 0xff, 0x45, 0xc0, 0x00, 0x28, 0x00, 0x03, 0x00, 0x00, 0xff, 0x06,
110                0xa4, 0xe8, 0x0a, 0x01, 0x02, 0x01, 0x0a, 0x22, 0x00, 0x01, 0x2a, 0xf9, 0x00, 0x17,
111                0x98, 0x32, 0x10, 0x05, 0x8d, 0xd5, 0x8e, 0xa5, 0x50, 0x10, 0x10, 0x20, 0x99, 0xcd,
112                0x00, 0x00, 0x00, 0x00,
113            ];
114
115            let mut mpls: Box<dyn Layer> = Box::new(super::MPLS::default());
116
117            let p = mpls.decode_bytes(&mpls_packet[28..]);
118            assert!(p.is_ok(), "{:#?}", mpls);
119        }
120
121        #[test]
122        fn test_mpls_parse_regression() {
123            let _ = layers::register_defaults();
124
125            // testPacketMPLS is the packet:
126            //     Ethernet II, Src: Cisco_05:28:38 (00:30:96:05:28:38), Dst: Cisco_e6:fc:39 (00:30:96:e6:fc:39)
127            //     0x0000   00 30 96 e6 fc 39 00 30 96 05 28 38 88 47 00 01   .0...9.0..(8.G..
128            //     0x0010   dd ff 45 c0 00 28 00 03 00 00 ff 06 a4 e8 0a 01   ..E..(..........
129            //     0x0020   02 01 0a 22 00 01 2a f9 00 17 98 32 10 05 8d d5   ..."..*....2....
130            //     0x0030   8e a5 50 10 10 20 99 cd 00 00 00 00               ..P.. ......
131
132            let test_packet_mpls = vec![
133                0x00, 0x30, 0x96, 0xe6, 0xfc, 0x39, 0x00, 0x30, 0x96, 0x05, 0x28, 0x38, 0x88, 0x47,
134                0x00, 0x01, 0xdd, 0xff, 0x45, 0xc0, 0x00, 0x28, 0x00, 0x03, 0x00, 0x00, 0xff, 0x06,
135                0xa4, 0xe8, 0x0a, 0x01, 0x02, 0x01, 0x0a, 0x22, 0x00, 0x01, 0x2a, 0xf9, 0x00, 0x17,
136                0x98, 0x32, 0x10, 0x05, 0x8d, 0xd5, 0x8e, 0xa5, 0x50, 0x10, 0x10, 0x20, 0x99, 0xcd,
137                0x00, 0x00, 0x00, 0x00,
138            ];
139
140            let p = Packet::from_bytes(&test_packet_mpls, ENCAP_TYPE_ETH);
141            assert!(p.is_ok());
142            let p = p.unwrap();
143            assert!(p.layers.len() == 4, "{:#?}", p);
144        }
145    }
146}