blob: 86a3d53dfd1238266752169f8d3acffb38d92f0b [file] [log] [blame]
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001From 0011985554e269e1cc8f8e5b41eb9dcd795ebe8c Mon Sep 17 00:00:00 2001
2From: Arturo Borrero Gonzalez <arturo@debian.org>
3Date: Wed, 25 Jan 2017 12:51:08 +0100
4Subject: [PATCH] payload: explicit network ctx assignment for icmp/icmp6 in
5 special families
6
7In the inet, bridge and netdev families, we can add rules like these:
8
9% nft add rule inet t c ip protocol icmp icmp type echo-request
10% nft add rule inet t c ip6 nexthdr icmpv6 icmpv6 type echo-request
11
12However, when we print the ruleset:
13
14% nft list ruleset
15table inet t {
16 chain c {
17 icmpv6 type echo-request
18 icmp type echo-request
19 }
20}
21
22These rules we obtain can't be added again:
23
24% nft add rule inet t c icmp type echo-request
25<cmdline>:1:19-27: Error: conflicting protocols specified: inet-service vs. icmp
26add rule inet t c icmp type echo-request
27 ^^^^^^^^^
28
29% nft add rule inet t c icmpv6 type echo-request
30<cmdline>:1:19-29: Error: conflicting protocols specified: inet-service vs. icmpv6
31add rule inet t c icmpv6 type echo-request
32 ^^^^^^^^^^^
33
34Since I wouldn't expect an IP packet carrying ICMPv6, or IPv6 packet
35carrying ICMP, if the link layer is inet, the network layer protocol context
36can be safely update to 'ip' or 'ip6'.
37
38Moreover, nft currently generates a 'meta nfproto ipvX' depedency when
39using icmp or icmp6 in the inet family, and similar in netdev and bridge
40families.
41
42While at it, a bit of code factorization is introduced.
43
44Fixes: https://bugzilla.netfilter.org/show_bug.cgi?id=1073
45Signed-off-by: Arturo Borrero Gonzalez <arturo@debian.org>
46Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
47---
48Upstream-Status: Backport
49Signed-off-by: André Draszik <adraszik@tycoint.com>
50 src/payload.c | 70 ++++++++++++++++---------------------
51 tests/py/any/icmpX.t.netdev | 8 +++++
52 tests/py/any/icmpX.t.netdev.payload | 36 +++++++++++++++++++
53 tests/py/bridge/icmpX.t | 8 +++++
54 tests/py/bridge/icmpX.t.payload | 36 +++++++++++++++++++
55 tests/py/inet/icmpX.t | 8 +++++
56 tests/py/inet/icmpX.t.payload | 36 +++++++++++++++++++
57 7 files changed, 162 insertions(+), 40 deletions(-)
58 create mode 100644 tests/py/any/icmpX.t.netdev
59 create mode 100644 tests/py/any/icmpX.t.netdev.payload
60 create mode 100644 tests/py/bridge/icmpX.t
61 create mode 100644 tests/py/bridge/icmpX.t.payload
62 create mode 100644 tests/py/inet/icmpX.t
63 create mode 100644 tests/py/inet/icmpX.t.payload
64
65diff --git a/src/payload.c b/src/payload.c
66index af533b2..74f8254 100644
67--- a/src/payload.c
68+++ b/src/payload.c
69@@ -223,6 +223,34 @@ static int payload_add_dependency(struct eval_ctx *ctx,
70 return 0;
71 }
72
73+static const struct proto_desc *
74+payload_gen_special_dependency(struct eval_ctx *ctx, const struct expr *expr)
75+{
76+ switch (expr->payload.base) {
77+ case PROTO_BASE_LL_HDR:
78+ switch (ctx->pctx.family) {
79+ case NFPROTO_INET:
80+ return &proto_inet;
81+ case NFPROTO_BRIDGE:
82+ return &proto_eth;
83+ case NFPROTO_NETDEV:
84+ return &proto_netdev;
85+ default:
86+ break;
87+ }
88+ break;
89+ case PROTO_BASE_TRANSPORT_HDR:
90+ if (expr->payload.desc == &proto_icmp)
91+ return &proto_ip;
92+ if (expr->payload.desc == &proto_icmp6)
93+ return &proto_ip6;
94+ return &proto_inet_service;
95+ default:
96+ break;
97+ }
98+ return NULL;
99+}
100+
101 /**
102 * payload_gen_dependency - generate match expression on payload dependency
103 *
104@@ -276,46 +304,8 @@ int payload_gen_dependency(struct eval_ctx *ctx, const struct expr *expr,
105
106 desc = ctx->pctx.protocol[expr->payload.base - 1].desc;
107 /* Special case for mixed IPv4/IPv6 and bridge tables */
108- if (desc == NULL) {
109- switch (ctx->pctx.family) {
110- case NFPROTO_INET:
111- switch (expr->payload.base) {
112- case PROTO_BASE_LL_HDR:
113- desc = &proto_inet;
114- break;
115- case PROTO_BASE_TRANSPORT_HDR:
116- desc = &proto_inet_service;
117- break;
118- default:
119- break;
120- }
121- break;
122- case NFPROTO_BRIDGE:
123- switch (expr->payload.base) {
124- case PROTO_BASE_LL_HDR:
125- desc = &proto_eth;
126- break;
127- case PROTO_BASE_TRANSPORT_HDR:
128- desc = &proto_inet_service;
129- break;
130- default:
131- break;
132- }
133- break;
134- case NFPROTO_NETDEV:
135- switch (expr->payload.base) {
136- case PROTO_BASE_LL_HDR:
137- desc = &proto_netdev;
138- break;
139- case PROTO_BASE_TRANSPORT_HDR:
140- desc = &proto_inet_service;
141- break;
142- default:
143- break;
144- }
145- break;
146- }
147- }
148+ if (desc == NULL)
149+ desc = payload_gen_special_dependency(ctx, expr);
150
151 if (desc == NULL)
152 return expr_error(ctx->msgs, expr,
153diff --git a/tests/py/any/icmpX.t.netdev b/tests/py/any/icmpX.t.netdev
154new file mode 100644
155index 0000000..a327ce6
156--- /dev/null
157+++ b/tests/py/any/icmpX.t.netdev
158@@ -0,0 +1,8 @@
159+:ingress;type filter hook ingress device lo priority 0
160+
161+*netdev;test-netdev;ingress
162+
163+ip protocol icmp icmp type echo-request;ok;icmp type echo-request
164+icmp type echo-request;ok
165+ip6 nexthdr icmpv6 icmpv6 type echo-request;ok;icmpv6 type echo-request
166+icmpv6 type echo-request;ok
167diff --git a/tests/py/any/icmpX.t.netdev.payload b/tests/py/any/icmpX.t.netdev.payload
168new file mode 100644
169index 0000000..8b8107c
170--- /dev/null
171+++ b/tests/py/any/icmpX.t.netdev.payload
172@@ -0,0 +1,36 @@
173+# ip protocol icmp icmp type echo-request
174+netdev test-netdev ingress
175+ [ meta load protocol => reg 1 ]
176+ [ cmp eq reg 1 0x00000008 ]
177+ [ payload load 1b @ network header + 9 => reg 1 ]
178+ [ cmp eq reg 1 0x00000001 ]
179+ [ payload load 1b @ transport header + 0 => reg 1 ]
180+ [ cmp eq reg 1 0x00000008 ]
181+
182+# icmp type echo-request
183+netdev test-netdev ingress
184+ [ meta load protocol => reg 1 ]
185+ [ cmp eq reg 1 0x00000008 ]
186+ [ payload load 1b @ network header + 9 => reg 1 ]
187+ [ cmp eq reg 1 0x00000001 ]
188+ [ payload load 1b @ transport header + 0 => reg 1 ]
189+ [ cmp eq reg 1 0x00000008 ]
190+
191+# ip6 nexthdr icmpv6 icmpv6 type echo-request
192+netdev test-netdev ingress
193+ [ meta load protocol => reg 1 ]
194+ [ cmp eq reg 1 0x0000dd86 ]
195+ [ payload load 1b @ network header + 6 => reg 1 ]
196+ [ cmp eq reg 1 0x0000003a ]
197+ [ payload load 1b @ transport header + 0 => reg 1 ]
198+ [ cmp eq reg 1 0x00000080 ]
199+
200+# icmpv6 type echo-request
201+netdev test-netdev ingress
202+ [ meta load protocol => reg 1 ]
203+ [ cmp eq reg 1 0x0000dd86 ]
204+ [ payload load 1b @ network header + 6 => reg 1 ]
205+ [ cmp eq reg 1 0x0000003a ]
206+ [ payload load 1b @ transport header + 0 => reg 1 ]
207+ [ cmp eq reg 1 0x00000080 ]
208+
209diff --git a/tests/py/bridge/icmpX.t b/tests/py/bridge/icmpX.t
210new file mode 100644
211index 0000000..8c0a597
212--- /dev/null
213+++ b/tests/py/bridge/icmpX.t
214@@ -0,0 +1,8 @@
215+:input;type filter hook input priority 0
216+
217+*bridge;test-bridge;input
218+
219+ip protocol icmp icmp type echo-request;ok;icmp type echo-request
220+icmp type echo-request;ok
221+ip6 nexthdr icmpv6 icmpv6 type echo-request;ok;icmpv6 type echo-request
222+icmpv6 type echo-request;ok
223diff --git a/tests/py/bridge/icmpX.t.payload b/tests/py/bridge/icmpX.t.payload
224new file mode 100644
225index 0000000..19efdd8
226--- /dev/null
227+++ b/tests/py/bridge/icmpX.t.payload
228@@ -0,0 +1,36 @@
229+# ip protocol icmp icmp type echo-request
230+bridge test-bridge input
231+ [ payload load 2b @ link header + 12 => reg 1 ]
232+ [ cmp eq reg 1 0x00000008 ]
233+ [ payload load 1b @ network header + 9 => reg 1 ]
234+ [ cmp eq reg 1 0x00000001 ]
235+ [ payload load 1b @ transport header + 0 => reg 1 ]
236+ [ cmp eq reg 1 0x00000008 ]
237+
238+# icmp type echo-request
239+bridge test-bridge input
240+ [ payload load 2b @ link header + 12 => reg 1 ]
241+ [ cmp eq reg 1 0x00000008 ]
242+ [ payload load 1b @ network header + 9 => reg 1 ]
243+ [ cmp eq reg 1 0x00000001 ]
244+ [ payload load 1b @ transport header + 0 => reg 1 ]
245+ [ cmp eq reg 1 0x00000008 ]
246+
247+# ip6 nexthdr icmpv6 icmpv6 type echo-request
248+bridge test-bridge input
249+ [ payload load 2b @ link header + 12 => reg 1 ]
250+ [ cmp eq reg 1 0x0000dd86 ]
251+ [ payload load 1b @ network header + 6 => reg 1 ]
252+ [ cmp eq reg 1 0x0000003a ]
253+ [ payload load 1b @ transport header + 0 => reg 1 ]
254+ [ cmp eq reg 1 0x00000080 ]
255+
256+# icmpv6 type echo-request
257+bridge test-bridge input
258+ [ payload load 2b @ link header + 12 => reg 1 ]
259+ [ cmp eq reg 1 0x0000dd86 ]
260+ [ payload load 1b @ network header + 6 => reg 1 ]
261+ [ cmp eq reg 1 0x0000003a ]
262+ [ payload load 1b @ transport header + 0 => reg 1 ]
263+ [ cmp eq reg 1 0x00000080 ]
264+
265diff --git a/tests/py/inet/icmpX.t b/tests/py/inet/icmpX.t
266new file mode 100644
267index 0000000..1b467a1
268--- /dev/null
269+++ b/tests/py/inet/icmpX.t
270@@ -0,0 +1,8 @@
271+:input;type filter hook input priority 0
272+
273+*inet;test-inet;input
274+
275+ip protocol icmp icmp type echo-request;ok;icmp type echo-request
276+icmp type echo-request;ok
277+ip6 nexthdr icmpv6 icmpv6 type echo-request;ok;icmpv6 type echo-request
278+icmpv6 type echo-request;ok
279diff --git a/tests/py/inet/icmpX.t.payload b/tests/py/inet/icmpX.t.payload
280new file mode 100644
281index 0000000..81ca774
282--- /dev/null
283+++ b/tests/py/inet/icmpX.t.payload
284@@ -0,0 +1,36 @@
285+# ip protocol icmp icmp type echo-request
286+inet test-inet input
287+ [ meta load nfproto => reg 1 ]
288+ [ cmp eq reg 1 0x00000002 ]
289+ [ payload load 1b @ network header + 9 => reg 1 ]
290+ [ cmp eq reg 1 0x00000001 ]
291+ [ payload load 1b @ transport header + 0 => reg 1 ]
292+ [ cmp eq reg 1 0x00000008 ]
293+
294+# icmp type echo-request
295+inet test-inet input
296+ [ meta load nfproto => reg 1 ]
297+ [ cmp eq reg 1 0x00000002 ]
298+ [ payload load 1b @ network header + 9 => reg 1 ]
299+ [ cmp eq reg 1 0x00000001 ]
300+ [ payload load 1b @ transport header + 0 => reg 1 ]
301+ [ cmp eq reg 1 0x00000008 ]
302+
303+# ip6 nexthdr icmpv6 icmpv6 type echo-request
304+inet test-inet input
305+ [ meta load nfproto => reg 1 ]
306+ [ cmp eq reg 1 0x0000000a ]
307+ [ payload load 1b @ network header + 6 => reg 1 ]
308+ [ cmp eq reg 1 0x0000003a ]
309+ [ payload load 1b @ transport header + 0 => reg 1 ]
310+ [ cmp eq reg 1 0x00000080 ]
311+
312+# icmpv6 type echo-request
313+inet test-inet input
314+ [ meta load nfproto => reg 1 ]
315+ [ cmp eq reg 1 0x0000000a ]
316+ [ payload load 1b @ network header + 6 => reg 1 ]
317+ [ cmp eq reg 1 0x0000003a ]
318+ [ payload load 1b @ transport header + 0 => reg 1 ]
319+ [ cmp eq reg 1 0x00000080 ]
320+
321--
3222.11.0
323