netfilter/
grammar.rs
1use fidl_fuchsia_net_filter_ext as filter_ext;
6use pest_derive::Parser;
7
8#[derive(Parser)]
9#[grammar_inline = r#"
10rules = { SOI ~ (rule ~ ";")+ ~ EOI }
11
12rule = {
13 action ~
14 direction ~
15 proto ~
16 devclass ~
17 src ~
18 dst ~
19 log ~
20 state
21}
22
23nat_rules = { SOI ~ (nat ~ ";")+ ~ EOI }
24
25nat = {
26 "nat" ~
27 proto ~
28 "from" ~ subnet ~
29 "->" ~
30 "from" ~ ipaddr
31}
32
33rdr_rules = { SOI ~ (rdr ~ ";")+ ~ EOI }
34
35rdr = {
36 "rdr" ~
37 proto ~
38 "to" ~ ipaddr ~ port_range ~
39 "->" ~
40 "to" ~ ipaddr ~ port_range
41}
42
43action = { pass | drop | dropreset }
44 pass = { "pass" }
45 drop = { "drop" }
46 dropreset = { "dropreset" }
47
48direction = { incoming | outgoing }
49 incoming = { "in" }
50 outgoing = { "out" }
51
52proto = { ("proto" ~ (tcp | udp | icmp))? }
53 tcp = { "tcp" }
54 udp = { "udp" }
55 icmp = { "icmp" }
56
57devclass = { ("devclass" ~ (virt | ethernet | wlan | ppp | bridge | ap | lowpan))? }
58 virt = { "virt" }
59 ethernet = { "ethernet" }
60 wlan = { "wlan" }
61 ppp = { "ppp" }
62 bridge = { "bridge" }
63 ap = { "ap" }
64 lowpan = { "lowpan" }
65
66src = { ("from" ~ invertible_subnet? ~ port_range?)? }
67dst = { ("to" ~ invertible_subnet? ~ port_range?)? }
68
69invertible_subnet = { not? ~ subnet }
70 not = { "!" }
71
72subnet = ${ ipaddr ~ "/" ~ prefix_len }
73
74ipaddr = { ipv4addr | ipv6addr }
75 ipv4addr = @{ ASCII_DIGIT{1,3} ~ ("." ~ ASCII_DIGIT{1,3}){3} }
76 ipv6addr = @{ (ASCII_HEX_DIGIT | ":")+ }
77
78prefix_len = @{ ASCII_DIGIT+ }
79
80port_range = { port ~ port_num | range ~ port_num ~ ":" ~ port_num }
81 port = { "port" }
82 range = { "range" }
83 port_num = @{ ASCII_DIGIT+ }
84
85log = { ("log")? }
86
87state = { (state_adj ~ "state")? }
88 state_adj = { "keep" | "no" }
89
90WHITESPACE = _{ " " }
91"#]
92
93pub struct FilterRuleParser;
94
95#[derive(Debug, PartialEq)]
96pub enum Error {
97 Pest(Box<pest::error::Error<Rule>>),
99 Addr(std::net::AddrParseError),
100 Num(std::num::ParseIntError),
101 Invalid(InvalidReason),
102 RoutineNotProvided(crate::parser::Direction),
103 Fidl(filter_ext::FidlConversionError),
104}
105
106#[derive(Debug, PartialEq)]
107pub enum InvalidReason {
108 MixedIPVersions,
109 InvalidPortRange,
110 PortRangeLengthMismatch,
111}
112
113impl std::fmt::Display for InvalidReason {
114 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
115 match self {
116 Self::MixedIPVersions => write!(f, "mixed IP versions"),
117 Self::InvalidPortRange => write!(f, "invalid port range"),
118 Self::PortRangeLengthMismatch => write!(f, "port range length mismatch"),
119 }
120 }
121}
122
123impl std::fmt::Display for Error {
124 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
125 match self {
126 Self::Pest(e) => write!(f, "pest error: {}", e),
127 Self::Addr(e) => std::fmt::Display::fmt(e, f),
128 Self::Num(e) => std::fmt::Display::fmt(e, f),
129 Self::Invalid(e) => write!(f, "invalid: {}", e),
130 Self::RoutineNotProvided(e) => write!(f, "expected routine for direction: {:?}", e),
131 Self::Fidl(e) => std::fmt::Display::fmt(e, f),
132 }
133 }
134}
135
136impl std::error::Error for Error {}