Skip to main content

routecore/
flowspec.rs

1//! FlowSpec v1 parsing.
2
3use inetnum::addr::Prefix;
4use crate::bgp::{nlri::common::prefix_bits_to_bytes, types::Afi};
5use crate::util::parser::ParseError;
6use log::debug;
7use octseq::{Octets, Parser};
8
9use std::net::IpAddr;
10
11fn op_to_len(op: u8) -> usize {
12    match (op & 0b00110000) >> 4 {
13        0b00 => 1,
14        0b01 => 2,
15        0b10 => 4,
16        0b11 => 8,
17        _ => panic!("impossible len bits in NumericOp")
18    }
19}
20
21pub struct NumericOp(u8, u64);
22impl NumericOp {
23    pub fn end_of_list(&self) -> bool {
24        self.0 & 0x80 == 0x80
25    }
26
27    pub fn and(&self) -> bool {
28        self.0 & 0x40 == 0x40
29    }
30
31    pub fn length(&self) -> usize {
32        op_to_len(self.0)
33    }
34
35    pub fn value(&self) -> u64 {
36        self.1
37    }
38}
39
40pub struct BitmaskOp(u8, u64);
41impl BitmaskOp {
42    pub fn end_of_list(&self) -> bool {
43        self.0 & 0x80 == 0x80
44    }
45
46    pub fn value(&self) -> u64 {
47        self.1
48    }
49}
50
51
52#[derive(Copy, Clone, Debug)]
53pub enum Component<Octets> {
54    DestinationPrefix(Prefix),
55    SourcePrefix(Prefix),
56    IpProtocol(Octets),
57    Port(Octets),
58    DestinationPort(Octets),
59    SourcePort(Octets),
60    IcmpType(Octets),
61    IcmpCode(Octets),
62    TcpFlags(Octets), // list of (bitmask_op , value)
63    PacketLength(Octets),
64    DSCP(Octets),
65    Fragment(Octets),
66}
67
68impl NumericOp {
69    fn parse<R: Octets + ?Sized>(parser: &mut Parser<'_, R>)
70        -> Result<Self, ParseError>
71    {
72        let op = parser.parse_u8()?;
73        let value = match op_to_len(op) {
74            1 => parser.parse_u8()? as u64,
75            2 => parser.parse_u16_be()? as u64,
76            4 => parser.parse_u32_be()? as u64,
77            8 => parser.parse_u64_be()?,
78            _ => panic!("illegal case"),
79        };
80        Ok(Self(op, value))
81    }
82}
83
84impl BitmaskOp {
85    fn parse<R: Octets + ?Sized>(parser: &mut Parser<'_, R>)
86        -> Result<Self, ParseError>
87    {
88        let op = parser.parse_u8()?;
89        let value = match op_to_len(op) {
90            1 => parser.parse_u8()? as u64,
91            2 => parser.parse_u16_be()? as u64,
92            4 => parser.parse_u32_be()? as u64,
93            8 => parser.parse_u64_be()?,
94            _ => panic!("illegal case"),
95        };
96        Ok(Self(op, value))
97    }
98}
99
100fn parse_prefix<R: Octets + ?Sized>(
101    parser: &mut Parser<'_, R>,
102    afi: Afi,
103    prefix_bits: u8
104) -> Result<Prefix, ParseError>
105{
106    let prefix_bytes = prefix_bits_to_bytes(prefix_bits);
107    let prefix = match (afi, prefix_bytes) {
108        (Afi::Ipv4, 0) => {
109            Prefix::new_v4(0.into(), 0)?
110        },
111        (Afi::Ipv4, _b @ 5..) => { 
112            return Err(ParseError::form_error("illegal byte size for IPv4 NLRI"))
113        },
114        (Afi::Ipv4, _) => {
115            let mut b = [0u8; 4];
116            b[..prefix_bytes].copy_from_slice(parser.peek(prefix_bytes)?);
117            parser.advance(prefix_bytes)?;
118            Prefix::new(IpAddr::from(b), prefix_bits).map_err(|_e| 
119                    ParseError::form_error("prefix parsing failed")
120            )?
121        }
122        (Afi::Ipv6, 0) => {
123            Prefix::new_v6(0.into(), 0)?
124        },
125        (Afi::Ipv6, _b @ 17..) => { 
126            return Err(ParseError::form_error("illegal byte size for IPv6 NLRI"))
127        },
128        (Afi::Ipv6, _) => {
129            let mut b = [0u8; 16];
130            b[..prefix_bytes].copy_from_slice(parser.peek(prefix_bytes)?);
131            parser.advance(prefix_bytes)?;
132            Prefix::new(IpAddr::from(b), prefix_bits).map_err(|_e| 
133                    ParseError::form_error("prefix parsing failed")
134            )?
135        },
136        (_, _) => {
137            panic!("unimplemented")
138        }
139    };
140    Ok(prefix)
141}
142
143impl<Octs: Octets> Component<Octs> {
144    pub(crate) fn parse<'a, R>(parser: &mut Parser<'a, R>)
145        -> Result<Self, ParseError>
146    where
147        R: Octets<Range<'a> = Octs> + ?Sized
148    {
149        let typ = parser.parse_u8()?;
150        let res = match typ {
151            1 => {
152                let prefix_bits = parser.parse_u8()?;
153                let pfx = parse_prefix(parser, Afi::Ipv4, prefix_bits)?;
154                Component::DestinationPrefix(pfx)
155            },
156            2 => {
157                let prefix_bits = parser.parse_u8()?;
158                let pfx = parse_prefix(parser, Afi::Ipv4, prefix_bits)?;
159                Component::SourcePrefix(pfx)
160            },
161            3 => {
162                let pos = parser.pos();
163                let mut done = false;
164                while !done {
165                    let op = NumericOp::parse(parser)?;
166                    done = op.end_of_list();
167                }
168                let octets_len = parser.pos() - pos;
169                parser.seek(pos)?;
170                Component::IpProtocol(
171                    parser.parse_octets(octets_len)?
172                )
173            },
174            4 => {
175                let pos = parser.pos();
176                let mut done = false;
177                while !done {
178                    let op = NumericOp::parse(parser)?;
179                    done = op.end_of_list();
180                }
181                let octets_len = parser.pos() - pos;
182                parser.seek(pos)?;
183                Component::Port(
184                    parser.parse_octets(octets_len)?
185                )
186            },
187            5 => {
188                let pos = parser.pos();
189                let mut done = false;
190                while !done {
191                    let op = NumericOp::parse(parser)?;
192                    done = op.end_of_list();
193                }
194                let octets_len = parser.pos() - pos;
195                parser.seek(pos)?;
196                Component::DestinationPort(
197                    parser.parse_octets(octets_len)?
198                )
199            },
200            6 => {
201                let pos = parser.pos();
202                let mut done = false;
203                while !done {
204                    let op = NumericOp::parse(parser)?;
205                    done = op.end_of_list();
206                }
207                let octets_len = parser.pos() - pos;
208                parser.seek(pos)?;
209                Component::SourcePort(
210                    parser.parse_octets(octets_len)?
211                )
212            },
213            7 => {
214                let pos = parser.pos();
215                let mut done = false;
216                while !done {
217                    let op = NumericOp::parse(parser)?;
218                    done = op.end_of_list();
219                }
220                let octets_len = parser.pos() - pos;
221                parser.seek(pos)?;
222                Component::IcmpType(
223                    parser.parse_octets(octets_len)?
224                )
225            },
226            8 => {
227                let pos = parser.pos();
228                let mut done = false;
229                while !done {
230                    let op = NumericOp::parse(parser)?;
231                    done = op.end_of_list();
232                }
233                let octets_len = parser.pos() - pos;
234                parser.seek(pos)?;
235                Component::IcmpCode(
236                    parser.parse_octets(octets_len)?
237                )
238            },
239            9 => {
240                let pos = parser.pos();
241                let mut done = false;
242                while !done {
243                    let op = BitmaskOp::parse(parser)?;
244                    done = op.end_of_list();
245                }
246                let octets_len = parser.pos() - pos;
247                parser.seek(pos)?;
248                Component::TcpFlags(
249                    parser.parse_octets(octets_len)?
250                )
251            },
252            10 => {
253                let pos = parser.pos();
254                let mut done = false;
255                while !done {
256                    let op = NumericOp::parse(parser)?;
257                    done = op.end_of_list();
258                }
259                let octets_len = parser.pos() - pos;
260                parser.seek(pos)?;
261                Component::PacketLength(
262                    parser.parse_octets(octets_len)?
263                )
264            },
265            11 => {
266                let pos = parser.pos();
267                let mut done = false;
268                while !done {
269                    let op = NumericOp::parse(parser)?;
270                    done = op.end_of_list();
271                }
272                let octets_len = parser.pos() - pos;
273                parser.seek(pos)?;
274                Component::DSCP(
275                    parser.parse_octets(octets_len)?
276                )
277            },
278            12 => {
279                let pos = parser.pos();
280                let mut done = false;
281                while !done {
282                    let op = BitmaskOp::parse(parser)?;
283                    done = op.end_of_list();
284                }
285                let octets_len = parser.pos() - pos;
286                parser.seek(pos)?;
287                Component::Fragment(
288                    parser.parse_octets(octets_len)?
289                )
290            },
291            _ => { 
292                debug!("unimplemented flowspec type {}", typ);
293                return Err(ParseError::Unsupported)
294            }
295        };
296
297        Ok(res)
298    }
299}
300
301
302