summaryrefslogtreecommitdiffstats
path: root/meta-openembedded/meta-networking/recipes-filter/nftables/files/0001-payload-explicit-network-ctx-assignment-for-icmp-icm.patch
blob: 86a3d53dfd1238266752169f8d3acffb38d92f0b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
From 0011985554e269e1cc8f8e5b41eb9dcd795ebe8c Mon Sep 17 00:00:00 2001
From: Arturo Borrero Gonzalez <arturo@debian.org>
Date: Wed, 25 Jan 2017 12:51:08 +0100
Subject: [PATCH] payload: explicit network ctx assignment for icmp/icmp6 in
 special families

In the inet, bridge and netdev families, we can add rules like these:

% nft add rule inet t c ip protocol icmp icmp type echo-request
% nft add rule inet t c ip6 nexthdr icmpv6 icmpv6 type echo-request

However, when we print the ruleset:

% nft list ruleset
table inet t {
	chain c {
		icmpv6 type echo-request
		icmp type echo-request
	}
}

These rules we obtain can't be added again:

% nft add rule inet t c icmp type echo-request
<cmdline>:1:19-27: Error: conflicting protocols specified: inet-service vs. icmp
add rule inet t c icmp type echo-request
                  ^^^^^^^^^

% nft add rule inet t c icmpv6 type echo-request
<cmdline>:1:19-29: Error: conflicting protocols specified: inet-service vs. icmpv6
add rule inet t c icmpv6 type echo-request
                  ^^^^^^^^^^^

Since I wouldn't expect an IP packet carrying ICMPv6, or IPv6 packet
carrying ICMP, if the link layer is inet, the network layer protocol context
can be safely update to 'ip' or 'ip6'.

Moreover, nft currently generates a 'meta nfproto ipvX' depedency when
using icmp or icmp6 in the inet family, and similar in netdev and bridge
families.

While at it, a bit of code factorization is introduced.

Fixes: https://bugzilla.netfilter.org/show_bug.cgi?id=1073
Signed-off-by: Arturo Borrero Gonzalez <arturo@debian.org>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
Upstream-Status: Backport
Signed-off-by: André Draszik <adraszik@tycoint.com>
 src/payload.c                       | 70 ++++++++++++++++---------------------
 tests/py/any/icmpX.t.netdev         |  8 +++++
 tests/py/any/icmpX.t.netdev.payload | 36 +++++++++++++++++++
 tests/py/bridge/icmpX.t             |  8 +++++
 tests/py/bridge/icmpX.t.payload     | 36 +++++++++++++++++++
 tests/py/inet/icmpX.t               |  8 +++++
 tests/py/inet/icmpX.t.payload       | 36 +++++++++++++++++++
 7 files changed, 162 insertions(+), 40 deletions(-)
 create mode 100644 tests/py/any/icmpX.t.netdev
 create mode 100644 tests/py/any/icmpX.t.netdev.payload
 create mode 100644 tests/py/bridge/icmpX.t
 create mode 100644 tests/py/bridge/icmpX.t.payload
 create mode 100644 tests/py/inet/icmpX.t
 create mode 100644 tests/py/inet/icmpX.t.payload

diff --git a/src/payload.c b/src/payload.c
index af533b2..74f8254 100644
--- a/src/payload.c
+++ b/src/payload.c
@@ -223,6 +223,34 @@ static int payload_add_dependency(struct eval_ctx *ctx,
 	return 0;
 }
 
+static const struct proto_desc *
+payload_gen_special_dependency(struct eval_ctx *ctx, const struct expr *expr)
+{
+	switch (expr->payload.base) {
+	case PROTO_BASE_LL_HDR:
+		switch (ctx->pctx.family) {
+		case NFPROTO_INET:
+			return &proto_inet;
+		case NFPROTO_BRIDGE:
+			return &proto_eth;
+		case NFPROTO_NETDEV:
+			return &proto_netdev;
+		default:
+			break;
+		}
+		break;
+	case PROTO_BASE_TRANSPORT_HDR:
+		if (expr->payload.desc == &proto_icmp)
+			return &proto_ip;
+		if (expr->payload.desc == &proto_icmp6)
+			return &proto_ip6;
+		return &proto_inet_service;
+	default:
+		break;
+	}
+	return NULL;
+}
+
 /**
  * payload_gen_dependency - generate match expression on payload dependency
  *
@@ -276,46 +304,8 @@ int payload_gen_dependency(struct eval_ctx *ctx, const struct expr *expr,
 
 	desc = ctx->pctx.protocol[expr->payload.base - 1].desc;
 	/* Special case for mixed IPv4/IPv6 and bridge tables */
-	if (desc == NULL) {
-		switch (ctx->pctx.family) {
-		case NFPROTO_INET:
-			switch (expr->payload.base) {
-			case PROTO_BASE_LL_HDR:
-				desc = &proto_inet;
-				break;
-			case PROTO_BASE_TRANSPORT_HDR:
-				desc = &proto_inet_service;
-				break;
-			default:
-				break;
-			}
-			break;
-		case NFPROTO_BRIDGE:
-			switch (expr->payload.base) {
-			case PROTO_BASE_LL_HDR:
-				desc = &proto_eth;
-				break;
-			case PROTO_BASE_TRANSPORT_HDR:
-				desc = &proto_inet_service;
-				break;
-			default:
-				break;
-			}
-			break;
-		case NFPROTO_NETDEV:
-			switch (expr->payload.base) {
-			case PROTO_BASE_LL_HDR:
-				desc = &proto_netdev;
-				break;
-			case PROTO_BASE_TRANSPORT_HDR:
-				desc = &proto_inet_service;
-				break;
-			default:
-				break;
-			}
-			break;
-		}
-	}
+	if (desc == NULL)
+		desc = payload_gen_special_dependency(ctx, expr);
 
 	if (desc == NULL)
 		return expr_error(ctx->msgs, expr,
diff --git a/tests/py/any/icmpX.t.netdev b/tests/py/any/icmpX.t.netdev
new file mode 100644
index 0000000..a327ce6
--- /dev/null
+++ b/tests/py/any/icmpX.t.netdev
@@ -0,0 +1,8 @@
+:ingress;type filter hook ingress device lo priority 0
+
+*netdev;test-netdev;ingress
+
+ip protocol icmp icmp type echo-request;ok;icmp type echo-request
+icmp type echo-request;ok
+ip6 nexthdr icmpv6 icmpv6 type echo-request;ok;icmpv6 type echo-request
+icmpv6 type echo-request;ok
diff --git a/tests/py/any/icmpX.t.netdev.payload b/tests/py/any/icmpX.t.netdev.payload
new file mode 100644
index 0000000..8b8107c
--- /dev/null
+++ b/tests/py/any/icmpX.t.netdev.payload
@@ -0,0 +1,36 @@
+# ip protocol icmp icmp type echo-request
+netdev test-netdev ingress
+  [ meta load protocol => reg 1 ]
+  [ cmp eq reg 1 0x00000008 ]
+  [ payload load 1b @ network header + 9 => reg 1 ]
+  [ cmp eq reg 1 0x00000001 ]
+  [ payload load 1b @ transport header + 0 => reg 1 ]
+  [ cmp eq reg 1 0x00000008 ]
+
+# icmp type echo-request
+netdev test-netdev ingress
+  [ meta load protocol => reg 1 ]
+  [ cmp eq reg 1 0x00000008 ]
+  [ payload load 1b @ network header + 9 => reg 1 ]
+  [ cmp eq reg 1 0x00000001 ]
+  [ payload load 1b @ transport header + 0 => reg 1 ]
+  [ cmp eq reg 1 0x00000008 ]
+
+# ip6 nexthdr icmpv6 icmpv6 type echo-request
+netdev test-netdev ingress
+  [ meta load protocol => reg 1 ]
+  [ cmp eq reg 1 0x0000dd86 ]
+  [ payload load 1b @ network header + 6 => reg 1 ]
+  [ cmp eq reg 1 0x0000003a ]
+  [ payload load 1b @ transport header + 0 => reg 1 ]
+  [ cmp eq reg 1 0x00000080 ]
+
+# icmpv6 type echo-request
+netdev test-netdev ingress
+  [ meta load protocol => reg 1 ]
+  [ cmp eq reg 1 0x0000dd86 ]
+  [ payload load 1b @ network header + 6 => reg 1 ]
+  [ cmp eq reg 1 0x0000003a ]
+  [ payload load 1b @ transport header + 0 => reg 1 ]
+  [ cmp eq reg 1 0x00000080 ]
+
diff --git a/tests/py/bridge/icmpX.t b/tests/py/bridge/icmpX.t
new file mode 100644
index 0000000..8c0a597
--- /dev/null
+++ b/tests/py/bridge/icmpX.t
@@ -0,0 +1,8 @@
+:input;type filter hook input priority 0
+
+*bridge;test-bridge;input
+
+ip protocol icmp icmp type echo-request;ok;icmp type echo-request
+icmp type echo-request;ok
+ip6 nexthdr icmpv6 icmpv6 type echo-request;ok;icmpv6 type echo-request
+icmpv6 type echo-request;ok
diff --git a/tests/py/bridge/icmpX.t.payload b/tests/py/bridge/icmpX.t.payload
new file mode 100644
index 0000000..19efdd8
--- /dev/null
+++ b/tests/py/bridge/icmpX.t.payload
@@ -0,0 +1,36 @@
+# ip protocol icmp icmp type echo-request
+bridge test-bridge input
+  [ payload load 2b @ link header + 12 => reg 1 ]
+  [ cmp eq reg 1 0x00000008 ]
+  [ payload load 1b @ network header + 9 => reg 1 ]
+  [ cmp eq reg 1 0x00000001 ]
+  [ payload load 1b @ transport header + 0 => reg 1 ]
+  [ cmp eq reg 1 0x00000008 ]
+
+# icmp type echo-request
+bridge test-bridge input
+  [ payload load 2b @ link header + 12 => reg 1 ]
+  [ cmp eq reg 1 0x00000008 ]
+  [ payload load 1b @ network header + 9 => reg 1 ]
+  [ cmp eq reg 1 0x00000001 ]
+  [ payload load 1b @ transport header + 0 => reg 1 ]
+  [ cmp eq reg 1 0x00000008 ]
+
+# ip6 nexthdr icmpv6 icmpv6 type echo-request
+bridge test-bridge input
+  [ payload load 2b @ link header + 12 => reg 1 ]
+  [ cmp eq reg 1 0x0000dd86 ]
+  [ payload load 1b @ network header + 6 => reg 1 ]
+  [ cmp eq reg 1 0x0000003a ]
+  [ payload load 1b @ transport header + 0 => reg 1 ]
+  [ cmp eq reg 1 0x00000080 ]
+
+# icmpv6 type echo-request
+bridge test-bridge input
+  [ payload load 2b @ link header + 12 => reg 1 ]
+  [ cmp eq reg 1 0x0000dd86 ]
+  [ payload load 1b @ network header + 6 => reg 1 ]
+  [ cmp eq reg 1 0x0000003a ]
+  [ payload load 1b @ transport header + 0 => reg 1 ]
+  [ cmp eq reg 1 0x00000080 ]
+
diff --git a/tests/py/inet/icmpX.t b/tests/py/inet/icmpX.t
new file mode 100644
index 0000000..1b467a1
--- /dev/null
+++ b/tests/py/inet/icmpX.t
@@ -0,0 +1,8 @@
+:input;type filter hook input priority 0
+
+*inet;test-inet;input
+
+ip protocol icmp icmp type echo-request;ok;icmp type echo-request
+icmp type echo-request;ok
+ip6 nexthdr icmpv6 icmpv6 type echo-request;ok;icmpv6 type echo-request
+icmpv6 type echo-request;ok
diff --git a/tests/py/inet/icmpX.t.payload b/tests/py/inet/icmpX.t.payload
new file mode 100644
index 0000000..81ca774
--- /dev/null
+++ b/tests/py/inet/icmpX.t.payload
@@ -0,0 +1,36 @@
+# ip protocol icmp icmp type echo-request
+inet test-inet input
+  [ meta load nfproto => reg 1 ]
+  [ cmp eq reg 1 0x00000002 ]
+  [ payload load 1b @ network header + 9 => reg 1 ]
+  [ cmp eq reg 1 0x00000001 ]
+  [ payload load 1b @ transport header + 0 => reg 1 ]
+  [ cmp eq reg 1 0x00000008 ]
+
+# icmp type echo-request
+inet test-inet input
+  [ meta load nfproto => reg 1 ]
+  [ cmp eq reg 1 0x00000002 ]
+  [ payload load 1b @ network header + 9 => reg 1 ]
+  [ cmp eq reg 1 0x00000001 ]
+  [ payload load 1b @ transport header + 0 => reg 1 ]
+  [ cmp eq reg 1 0x00000008 ]
+
+# ip6 nexthdr icmpv6 icmpv6 type echo-request
+inet test-inet input
+  [ meta load nfproto => reg 1 ]
+  [ cmp eq reg 1 0x0000000a ]
+  [ payload load 1b @ network header + 6 => reg 1 ]
+  [ cmp eq reg 1 0x0000003a ]
+  [ payload load 1b @ transport header + 0 => reg 1 ]
+  [ cmp eq reg 1 0x00000080 ]
+
+# icmpv6 type echo-request
+inet test-inet input
+  [ meta load nfproto => reg 1 ]
+  [ cmp eq reg 1 0x0000000a ]
+  [ payload load 1b @ network header + 6 => reg 1 ]
+  [ cmp eq reg 1 0x0000003a ]
+  [ payload load 1b @ transport header + 0 => reg 1 ]
+  [ cmp eq reg 1 0x00000080 ]
+
-- 
2.11.0

OpenPOWER on IntegriCloud