Blame view

net/netfilter/nft_meta.c 11 KB
96518518c   Patrick McHardy   netfilter: add nf...
1
  /*
ef1f7df91   Patrick McHardy   netfilter: nf_tab...
2
   * Copyright (c) 2008-2009 Patrick McHardy <kaber@trash.net>
96518518c   Patrick McHardy   netfilter: add nf...
3
4
5
6
7
8
9
10
11
12
13
14
15
16
   *
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License version 2 as
   * published by the Free Software Foundation.
   *
   * Development of this code funded by Astaro AG (http://www.astaro.com/)
   */
  
  #include <linux/kernel.h>
  #include <linux/init.h>
  #include <linux/module.h>
  #include <linux/netlink.h>
  #include <linux/netfilter.h>
  #include <linux/netfilter/nf_tables.h>
e2a093ff0   Ana Rey   netfilter: nft_me...
17
18
19
  #include <linux/in.h>
  #include <linux/ip.h>
  #include <linux/ipv6.h>
afc5be307   Ana Rey   netfilter: nft_me...
20
  #include <linux/smp.h>
e639f7ab0   Florian Westphal   netfilter: nf_tab...
21
  #include <linux/static_key.h>
96518518c   Patrick McHardy   netfilter: add nf...
22
23
24
25
  #include <net/dst.h>
  #include <net/sock.h>
  #include <net/tcp_states.h> /* for TCP_TIME_WAIT */
  #include <net/netfilter/nf_tables.h>
e639f7ab0   Florian Westphal   netfilter: nf_tab...
26
  #include <net/netfilter/nf_tables_core.h>
aa45660c6   Tomasz Bursztyka   netfilter: nf_tab...
27
  #include <net/netfilter/nft_meta.h>
96518518c   Patrick McHardy   netfilter: add nf...
28

b4aae759c   Florian Westphal   netfilter: meta: ...
29
  #include <uapi/linux/netfilter_bridge.h> /* NF_BR_PRE_ROUTING */
b07edbe1c   Florian Westphal   netfilter: meta: ...
30
  static DEFINE_PER_CPU(struct rnd_state, nft_prandom_state);
aa45660c6   Tomasz Bursztyka   netfilter: nf_tab...
31
  void nft_meta_get_eval(const struct nft_expr *expr,
a55e22e92   Patrick McHardy   netfilter: nf_tab...
32
  		       struct nft_regs *regs,
aa45660c6   Tomasz Bursztyka   netfilter: nf_tab...
33
  		       const struct nft_pktinfo *pkt)
96518518c   Patrick McHardy   netfilter: add nf...
34
35
36
  {
  	const struct nft_meta *priv = nft_expr_priv(expr);
  	const struct sk_buff *skb = pkt->skb;
0e5a1c7eb   Pablo Neira Ayuso   netfilter: nf_tab...
37
  	const struct net_device *in = nft_in(pkt), *out = nft_out(pkt);
3aed82259   Eric Dumazet   netfilter: nft_me...
38
  	struct sock *sk;
49499c3e6   Patrick McHardy   netfilter: nf_tab...
39
  	u32 *dest = &regs->data[priv->dreg];
96518518c   Patrick McHardy   netfilter: add nf...
40
41
42
  
  	switch (priv->key) {
  	case NFT_META_LEN:
fad136ea0   Patrick McHardy   netfilter: nf_tab...
43
  		*dest = skb->len;
96518518c   Patrick McHardy   netfilter: add nf...
44
45
  		break;
  	case NFT_META_PROTOCOL:
10596608c   Liping Zhang   netfilter: nf_tab...
46
  		nft_reg_store16(dest, (__force u16)skb->protocol);
96518518c   Patrick McHardy   netfilter: add nf...
47
  		break;
124edfa9e   Patrick McHardy   netfilter: nf_tab...
48
  	case NFT_META_NFPROTO:
10596608c   Liping Zhang   netfilter: nf_tab...
49
  		nft_reg_store8(dest, nft_pf(pkt));
124edfa9e   Patrick McHardy   netfilter: nf_tab...
50
  		break;
4566bf270   Patrick McHardy   netfilter: nft_me...
51
  	case NFT_META_L4PROTO:
beac5afa2   Pablo Neira Ayuso   netfilter: nf_tab...
52
53
  		if (!pkt->tprot_set)
  			goto err;
10596608c   Liping Zhang   netfilter: nf_tab...
54
  		nft_reg_store8(dest, pkt->tprot);
4566bf270   Patrick McHardy   netfilter: nft_me...
55
  		break;
96518518c   Patrick McHardy   netfilter: add nf...
56
  	case NFT_META_PRIORITY:
fad136ea0   Patrick McHardy   netfilter: nf_tab...
57
  		*dest = skb->priority;
96518518c   Patrick McHardy   netfilter: add nf...
58
59
  		break;
  	case NFT_META_MARK:
fad136ea0   Patrick McHardy   netfilter: nf_tab...
60
  		*dest = skb->mark;
96518518c   Patrick McHardy   netfilter: add nf...
61
62
63
64
  		break;
  	case NFT_META_IIF:
  		if (in == NULL)
  			goto err;
fad136ea0   Patrick McHardy   netfilter: nf_tab...
65
  		*dest = in->ifindex;
96518518c   Patrick McHardy   netfilter: add nf...
66
67
68
69
  		break;
  	case NFT_META_OIF:
  		if (out == NULL)
  			goto err;
fad136ea0   Patrick McHardy   netfilter: nf_tab...
70
  		*dest = out->ifindex;
96518518c   Patrick McHardy   netfilter: add nf...
71
72
73
74
  		break;
  	case NFT_META_IIFNAME:
  		if (in == NULL)
  			goto err;
fad136ea0   Patrick McHardy   netfilter: nf_tab...
75
  		strncpy((char *)dest, in->name, IFNAMSIZ);
96518518c   Patrick McHardy   netfilter: add nf...
76
77
78
79
  		break;
  	case NFT_META_OIFNAME:
  		if (out == NULL)
  			goto err;
fad136ea0   Patrick McHardy   netfilter: nf_tab...
80
  		strncpy((char *)dest, out->name, IFNAMSIZ);
96518518c   Patrick McHardy   netfilter: add nf...
81
82
83
84
  		break;
  	case NFT_META_IIFTYPE:
  		if (in == NULL)
  			goto err;
10596608c   Liping Zhang   netfilter: nf_tab...
85
  		nft_reg_store16(dest, in->type);
96518518c   Patrick McHardy   netfilter: add nf...
86
87
88
89
  		break;
  	case NFT_META_OIFTYPE:
  		if (out == NULL)
  			goto err;
10596608c   Liping Zhang   netfilter: nf_tab...
90
  		nft_reg_store16(dest, out->type);
96518518c   Patrick McHardy   netfilter: add nf...
91
92
  		break;
  	case NFT_META_SKUID:
3aed82259   Eric Dumazet   netfilter: nft_me...
93
94
  		sk = skb_to_full_sk(skb);
  		if (!sk || !sk_fullsock(sk))
96518518c   Patrick McHardy   netfilter: add nf...
95
  			goto err;
3aed82259   Eric Dumazet   netfilter: nft_me...
96
97
98
99
  		read_lock_bh(&sk->sk_callback_lock);
  		if (sk->sk_socket == NULL ||
  		    sk->sk_socket->file == NULL) {
  			read_unlock_bh(&sk->sk_callback_lock);
96518518c   Patrick McHardy   netfilter: add nf...
100
101
  			goto err;
  		}
fad136ea0   Patrick McHardy   netfilter: nf_tab...
102
  		*dest =	from_kuid_munged(&init_user_ns,
3aed82259   Eric Dumazet   netfilter: nft_me...
103
104
  				sk->sk_socket->file->f_cred->fsuid);
  		read_unlock_bh(&sk->sk_callback_lock);
96518518c   Patrick McHardy   netfilter: add nf...
105
106
  		break;
  	case NFT_META_SKGID:
3aed82259   Eric Dumazet   netfilter: nft_me...
107
108
  		sk = skb_to_full_sk(skb);
  		if (!sk || !sk_fullsock(sk))
96518518c   Patrick McHardy   netfilter: add nf...
109
  			goto err;
3aed82259   Eric Dumazet   netfilter: nft_me...
110
111
112
113
  		read_lock_bh(&sk->sk_callback_lock);
  		if (sk->sk_socket == NULL ||
  		    sk->sk_socket->file == NULL) {
  			read_unlock_bh(&sk->sk_callback_lock);
96518518c   Patrick McHardy   netfilter: add nf...
114
115
  			goto err;
  		}
fad136ea0   Patrick McHardy   netfilter: nf_tab...
116
  		*dest =	from_kgid_munged(&init_user_ns,
3aed82259   Eric Dumazet   netfilter: nft_me...
117
118
  				 sk->sk_socket->file->f_cred->fsgid);
  		read_unlock_bh(&sk->sk_callback_lock);
96518518c   Patrick McHardy   netfilter: add nf...
119
  		break;
06efbd6d5   Paul Bolle   netfilter: nft_me...
120
  #ifdef CONFIG_IP_ROUTE_CLASSID
96518518c   Patrick McHardy   netfilter: add nf...
121
122
123
124
125
  	case NFT_META_RTCLASSID: {
  		const struct dst_entry *dst = skb_dst(skb);
  
  		if (dst == NULL)
  			goto err;
fad136ea0   Patrick McHardy   netfilter: nf_tab...
126
  		*dest = dst->tclassid;
96518518c   Patrick McHardy   netfilter: add nf...
127
128
129
130
131
  		break;
  	}
  #endif
  #ifdef CONFIG_NETWORK_SECMARK
  	case NFT_META_SECMARK:
fad136ea0   Patrick McHardy   netfilter: nf_tab...
132
  		*dest = skb->secmark;
96518518c   Patrick McHardy   netfilter: add nf...
133
134
  		break;
  #endif
e2a093ff0   Ana Rey   netfilter: nft_me...
135
136
  	case NFT_META_PKTTYPE:
  		if (skb->pkt_type != PACKET_LOOPBACK) {
10596608c   Liping Zhang   netfilter: nf_tab...
137
  			nft_reg_store8(dest, skb->pkt_type);
e2a093ff0   Ana Rey   netfilter: nft_me...
138
139
  			break;
  		}
0e5a1c7eb   Pablo Neira Ayuso   netfilter: nf_tab...
140
  		switch (nft_pf(pkt)) {
e2a093ff0   Ana Rey   netfilter: nft_me...
141
142
  		case NFPROTO_IPV4:
  			if (ipv4_is_multicast(ip_hdr(skb)->daddr))
10596608c   Liping Zhang   netfilter: nf_tab...
143
  				nft_reg_store8(dest, PACKET_MULTICAST);
e2a093ff0   Ana Rey   netfilter: nft_me...
144
  			else
10596608c   Liping Zhang   netfilter: nf_tab...
145
  				nft_reg_store8(dest, PACKET_BROADCAST);
e2a093ff0   Ana Rey   netfilter: nft_me...
146
147
  			break;
  		case NFPROTO_IPV6:
10596608c   Liping Zhang   netfilter: nf_tab...
148
  			nft_reg_store8(dest, PACKET_MULTICAST);
e2a093ff0   Ana Rey   netfilter: nft_me...
149
  			break;
f169fd695   Liping Zhang   netfilter: nft_me...
150
151
152
153
154
155
156
157
158
159
160
161
  		case NFPROTO_NETDEV:
  			switch (skb->protocol) {
  			case htons(ETH_P_IP): {
  				int noff = skb_network_offset(skb);
  				struct iphdr *iph, _iph;
  
  				iph = skb_header_pointer(skb, noff,
  							 sizeof(_iph), &_iph);
  				if (!iph)
  					goto err;
  
  				if (ipv4_is_multicast(iph->daddr))
10596608c   Liping Zhang   netfilter: nf_tab...
162
  					nft_reg_store8(dest, PACKET_MULTICAST);
f169fd695   Liping Zhang   netfilter: nft_me...
163
  				else
10596608c   Liping Zhang   netfilter: nf_tab...
164
  					nft_reg_store8(dest, PACKET_BROADCAST);
f169fd695   Liping Zhang   netfilter: nft_me...
165
166
167
168
  
  				break;
  			}
  			case htons(ETH_P_IPV6):
10596608c   Liping Zhang   netfilter: nf_tab...
169
  				nft_reg_store8(dest, PACKET_MULTICAST);
f169fd695   Liping Zhang   netfilter: nft_me...
170
171
172
173
174
175
  				break;
  			default:
  				WARN_ON_ONCE(1);
  				goto err;
  			}
  			break;
e2a093ff0   Ana Rey   netfilter: nft_me...
176
  		default:
f169fd695   Liping Zhang   netfilter: nft_me...
177
  			WARN_ON_ONCE(1);
e2a093ff0   Ana Rey   netfilter: nft_me...
178
179
180
  			goto err;
  		}
  		break;
afc5be307   Ana Rey   netfilter: nft_me...
181
  	case NFT_META_CPU:
fad136ea0   Patrick McHardy   netfilter: nf_tab...
182
  		*dest = raw_smp_processor_id();
afc5be307   Ana Rey   netfilter: nft_me...
183
  		break;
3045d7607   Ana Rey   netfilter: nf_tab...
184
185
186
  	case NFT_META_IIFGROUP:
  		if (in == NULL)
  			goto err;
fad136ea0   Patrick McHardy   netfilter: nf_tab...
187
  		*dest = in->group;
3045d7607   Ana Rey   netfilter: nf_tab...
188
189
190
191
  		break;
  	case NFT_META_OIFGROUP:
  		if (out == NULL)
  			goto err;
fad136ea0   Patrick McHardy   netfilter: nf_tab...
192
  		*dest = out->group;
3045d7607   Ana Rey   netfilter: nf_tab...
193
  		break;
e181a5430   Mathias Krause   net: #ifdefify sk...
194
  #ifdef CONFIG_CGROUP_NET_CLASSID
ce674173e   Ana Rey   netfilter: nft_me...
195
  	case NFT_META_CGROUP:
3aed82259   Eric Dumazet   netfilter: nft_me...
196
197
  		sk = skb_to_full_sk(skb);
  		if (!sk || !sk_fullsock(sk))
c5035c77f   Pablo Neira Ayuso   netfilter: nft_me...
198
  			goto err;
2a56a1fec   Tejun Heo   net: wrap sock->s...
199
  		*dest = sock_cgroup_classid(&sk->sk_cgrp_data);
ce674173e   Ana Rey   netfilter: nft_me...
200
  		break;
e181a5430   Mathias Krause   net: #ifdefify sk...
201
  #endif
b07edbe1c   Florian Westphal   netfilter: meta: ...
202
203
204
205
206
  	case NFT_META_PRANDOM: {
  		struct rnd_state *state = this_cpu_ptr(&nft_prandom_state);
  		*dest = prandom_u32_state(state);
  		break;
  	}
96518518c   Patrick McHardy   netfilter: add nf...
207
208
209
210
211
212
213
  	default:
  		WARN_ON(1);
  		goto err;
  	}
  	return;
  
  err:
a55e22e92   Patrick McHardy   netfilter: nf_tab...
214
  	regs->verdict.code = NFT_BREAK;
96518518c   Patrick McHardy   netfilter: add nf...
215
  }
aa45660c6   Tomasz Bursztyka   netfilter: nf_tab...
216
  EXPORT_SYMBOL_GPL(nft_meta_get_eval);
96518518c   Patrick McHardy   netfilter: add nf...
217

aa45660c6   Tomasz Bursztyka   netfilter: nf_tab...
218
  void nft_meta_set_eval(const struct nft_expr *expr,
a55e22e92   Patrick McHardy   netfilter: nf_tab...
219
  		       struct nft_regs *regs,
aa45660c6   Tomasz Bursztyka   netfilter: nf_tab...
220
  		       const struct nft_pktinfo *pkt)
e035b77ac   Arturo Borrero Gonzalez   netfilter: nf_tab...
221
222
223
  {
  	const struct nft_meta *meta = nft_expr_priv(expr);
  	struct sk_buff *skb = pkt->skb;
10596608c   Liping Zhang   netfilter: nf_tab...
224
225
  	u32 *sreg = &regs->data[meta->sreg];
  	u32 value = *sreg;
491b1a866   Taehee Yoo   netfilter: nft_me...
226
  	u8 value8;
e035b77ac   Arturo Borrero Gonzalez   netfilter: nf_tab...
227
228
229
230
231
232
233
234
  
  	switch (meta->key) {
  	case NFT_META_MARK:
  		skb->mark = value;
  		break;
  	case NFT_META_PRIORITY:
  		skb->priority = value;
  		break;
b4aae759c   Florian Westphal   netfilter: meta: ...
235
  	case NFT_META_PKTTYPE:
491b1a866   Taehee Yoo   netfilter: nft_me...
236
  		value8 = nft_reg_load8(sreg);
10596608c   Liping Zhang   netfilter: nf_tab...
237

491b1a866   Taehee Yoo   netfilter: nft_me...
238
239
  		if (skb->pkt_type != value8 &&
  		    skb_pkt_type_ok(value8) &&
10596608c   Liping Zhang   netfilter: nf_tab...
240
  		    skb_pkt_type_ok(skb->pkt_type))
491b1a866   Taehee Yoo   netfilter: nft_me...
241
  			skb->pkt_type = value8;
b4aae759c   Florian Westphal   netfilter: meta: ...
242
  		break;
e035b77ac   Arturo Borrero Gonzalez   netfilter: nf_tab...
243
  	case NFT_META_NFTRACE:
491b1a866   Taehee Yoo   netfilter: nft_me...
244
245
246
  		value8 = nft_reg_load8(sreg);
  
  		skb->nf_trace = !!value8;
e035b77ac   Arturo Borrero Gonzalez   netfilter: nf_tab...
247
248
249
250
251
  		break;
  	default:
  		WARN_ON(1);
  	}
  }
aa45660c6   Tomasz Bursztyka   netfilter: nf_tab...
252
  EXPORT_SYMBOL_GPL(nft_meta_set_eval);
e035b77ac   Arturo Borrero Gonzalez   netfilter: nf_tab...
253

aa45660c6   Tomasz Bursztyka   netfilter: nf_tab...
254
  const struct nla_policy nft_meta_policy[NFTA_META_MAX + 1] = {
96518518c   Patrick McHardy   netfilter: add nf...
255
256
  	[NFTA_META_DREG]	= { .type = NLA_U32 },
  	[NFTA_META_KEY]		= { .type = NLA_U32 },
e035b77ac   Arturo Borrero Gonzalez   netfilter: nf_tab...
257
  	[NFTA_META_SREG]	= { .type = NLA_U32 },
96518518c   Patrick McHardy   netfilter: add nf...
258
  };
aa45660c6   Tomasz Bursztyka   netfilter: nf_tab...
259
  EXPORT_SYMBOL_GPL(nft_meta_policy);
96518518c   Patrick McHardy   netfilter: add nf...
260

aa45660c6   Tomasz Bursztyka   netfilter: nf_tab...
261
262
263
  int nft_meta_get_init(const struct nft_ctx *ctx,
  		      const struct nft_expr *expr,
  		      const struct nlattr * const tb[])
96518518c   Patrick McHardy   netfilter: add nf...
264
  {
d2caa696a   Patrick McHardy   netfilter: nft_me...
265
  	struct nft_meta *priv = nft_expr_priv(expr);
45d9bcda2   Patrick McHardy   netfilter: nf_tab...
266
  	unsigned int len;
96518518c   Patrick McHardy   netfilter: add nf...
267

d2caa696a   Patrick McHardy   netfilter: nft_me...
268
269
  	priv->key = ntohl(nla_get_be32(tb[NFTA_META_KEY]));
  	switch (priv->key) {
96518518c   Patrick McHardy   netfilter: add nf...
270
  	case NFT_META_PROTOCOL:
45d9bcda2   Patrick McHardy   netfilter: nf_tab...
271
272
273
274
  	case NFT_META_IIFTYPE:
  	case NFT_META_OIFTYPE:
  		len = sizeof(u16);
  		break;
124edfa9e   Patrick McHardy   netfilter: nf_tab...
275
  	case NFT_META_NFPROTO:
4566bf270   Patrick McHardy   netfilter: nft_me...
276
  	case NFT_META_L4PROTO:
45d9bcda2   Patrick McHardy   netfilter: nf_tab...
277
  	case NFT_META_LEN:
96518518c   Patrick McHardy   netfilter: add nf...
278
279
280
281
  	case NFT_META_PRIORITY:
  	case NFT_META_MARK:
  	case NFT_META_IIF:
  	case NFT_META_OIF:
96518518c   Patrick McHardy   netfilter: add nf...
282
283
  	case NFT_META_SKUID:
  	case NFT_META_SKGID:
06efbd6d5   Paul Bolle   netfilter: nft_me...
284
  #ifdef CONFIG_IP_ROUTE_CLASSID
96518518c   Patrick McHardy   netfilter: add nf...
285
286
287
288
289
  	case NFT_META_RTCLASSID:
  #endif
  #ifdef CONFIG_NETWORK_SECMARK
  	case NFT_META_SECMARK:
  #endif
e2a093ff0   Ana Rey   netfilter: nft_me...
290
  	case NFT_META_PKTTYPE:
afc5be307   Ana Rey   netfilter: nft_me...
291
  	case NFT_META_CPU:
3045d7607   Ana Rey   netfilter: nf_tab...
292
293
  	case NFT_META_IIFGROUP:
  	case NFT_META_OIFGROUP:
e181a5430   Mathias Krause   net: #ifdefify sk...
294
  #ifdef CONFIG_CGROUP_NET_CLASSID
ce674173e   Ana Rey   netfilter: nft_me...
295
  	case NFT_META_CGROUP:
e181a5430   Mathias Krause   net: #ifdefify sk...
296
  #endif
45d9bcda2   Patrick McHardy   netfilter: nf_tab...
297
298
299
300
301
  		len = sizeof(u32);
  		break;
  	case NFT_META_IIFNAME:
  	case NFT_META_OIFNAME:
  		len = IFNAMSIZ;
d2caa696a   Patrick McHardy   netfilter: nft_me...
302
  		break;
b07edbe1c   Florian Westphal   netfilter: meta: ...
303
304
305
306
  	case NFT_META_PRANDOM:
  		prandom_init_once(&nft_prandom_state);
  		len = sizeof(u32);
  		break;
96518518c   Patrick McHardy   netfilter: add nf...
307
308
309
  	default:
  		return -EOPNOTSUPP;
  	}
b1c96ed37   Patrick McHardy   netfilter: nf_tab...
310
  	priv->dreg = nft_parse_register(tb[NFTA_META_DREG]);
27e6d2017   Patrick McHardy   netfilter: nf_tab...
311
312
  	return nft_validate_register_store(ctx, priv->dreg, NULL,
  					   NFT_DATA_VALUE, len);
e035b77ac   Arturo Borrero Gonzalez   netfilter: nf_tab...
313
  }
aa45660c6   Tomasz Bursztyka   netfilter: nf_tab...
314
  EXPORT_SYMBOL_GPL(nft_meta_get_init);
e035b77ac   Arturo Borrero Gonzalez   netfilter: nf_tab...
315

960fa72f6   Liping Zhang   netfilter: nft_me...
316
317
318
  int nft_meta_set_validate(const struct nft_ctx *ctx,
  			  const struct nft_expr *expr,
  			  const struct nft_data **data)
b4aae759c   Florian Westphal   netfilter: meta: ...
319
  {
960fa72f6   Liping Zhang   netfilter: nft_me...
320
  	struct nft_meta *priv = nft_expr_priv(expr);
b4aae759c   Florian Westphal   netfilter: meta: ...
321
  	unsigned int hooks;
960fa72f6   Liping Zhang   netfilter: nft_me...
322
323
  	if (priv->key != NFT_META_PKTTYPE)
  		return 0;
b4aae759c   Florian Westphal   netfilter: meta: ...
324
325
326
327
328
329
330
  	switch (ctx->afi->family) {
  	case NFPROTO_BRIDGE:
  		hooks = 1 << NF_BR_PRE_ROUTING;
  		break;
  	case NFPROTO_NETDEV:
  		hooks = 1 << NF_NETDEV_INGRESS;
  		break;
96d9f2a72   Liping Zhang   netfilter: nft_me...
331
332
333
334
335
  	case NFPROTO_IPV4:
  	case NFPROTO_IPV6:
  	case NFPROTO_INET:
  		hooks = 1 << NF_INET_PRE_ROUTING;
  		break;
b4aae759c   Florian Westphal   netfilter: meta: ...
336
337
338
339
340
341
  	default:
  		return -EOPNOTSUPP;
  	}
  
  	return nft_chain_validate_hooks(ctx->chain, hooks);
  }
960fa72f6   Liping Zhang   netfilter: nft_me...
342
  EXPORT_SYMBOL_GPL(nft_meta_set_validate);
b4aae759c   Florian Westphal   netfilter: meta: ...
343

aa45660c6   Tomasz Bursztyka   netfilter: nf_tab...
344
345
346
  int nft_meta_set_init(const struct nft_ctx *ctx,
  		      const struct nft_expr *expr,
  		      const struct nlattr * const tb[])
e035b77ac   Arturo Borrero Gonzalez   netfilter: nf_tab...
347
348
  {
  	struct nft_meta *priv = nft_expr_priv(expr);
d07db9884   Patrick McHardy   netfilter: nf_tab...
349
  	unsigned int len;
e035b77ac   Arturo Borrero Gonzalez   netfilter: nf_tab...
350
351
352
  	int err;
  
  	priv->key = ntohl(nla_get_be32(tb[NFTA_META_KEY]));
d2caa696a   Patrick McHardy   netfilter: nft_me...
353
354
355
  	switch (priv->key) {
  	case NFT_META_MARK:
  	case NFT_META_PRIORITY:
d07db9884   Patrick McHardy   netfilter: nf_tab...
356
357
  		len = sizeof(u32);
  		break;
d2caa696a   Patrick McHardy   netfilter: nft_me...
358
  	case NFT_META_NFTRACE:
d07db9884   Patrick McHardy   netfilter: nf_tab...
359
  		len = sizeof(u8);
d2caa696a   Patrick McHardy   netfilter: nft_me...
360
  		break;
b4aae759c   Florian Westphal   netfilter: meta: ...
361
  	case NFT_META_PKTTYPE:
b4aae759c   Florian Westphal   netfilter: meta: ...
362
363
  		len = sizeof(u8);
  		break;
d2caa696a   Patrick McHardy   netfilter: nft_me...
364
365
  	default:
  		return -EOPNOTSUPP;
e035b77ac   Arturo Borrero Gonzalez   netfilter: nf_tab...
366
  	}
b1c96ed37   Patrick McHardy   netfilter: nf_tab...
367
  	priv->sreg = nft_parse_register(tb[NFTA_META_SREG]);
d07db9884   Patrick McHardy   netfilter: nf_tab...
368
  	err = nft_validate_register_load(priv->sreg, len);
b38895c57   Pablo Neira Ayuso   netfilter: nft_me...
369
370
  	if (err < 0)
  		return err;
e035b77ac   Arturo Borrero Gonzalez   netfilter: nf_tab...
371

e639f7ab0   Florian Westphal   netfilter: nf_tab...
372
373
  	if (priv->key == NFT_META_NFTRACE)
  		static_branch_inc(&nft_trace_enabled);
e035b77ac   Arturo Borrero Gonzalez   netfilter: nf_tab...
374
  	return 0;
96518518c   Patrick McHardy   netfilter: add nf...
375
  }
aa45660c6   Tomasz Bursztyka   netfilter: nf_tab...
376
  EXPORT_SYMBOL_GPL(nft_meta_set_init);
96518518c   Patrick McHardy   netfilter: add nf...
377

aa45660c6   Tomasz Bursztyka   netfilter: nf_tab...
378
379
  int nft_meta_get_dump(struct sk_buff *skb,
  		      const struct nft_expr *expr)
96518518c   Patrick McHardy   netfilter: add nf...
380
381
  {
  	const struct nft_meta *priv = nft_expr_priv(expr);
e035b77ac   Arturo Borrero Gonzalez   netfilter: nf_tab...
382
383
  	if (nla_put_be32(skb, NFTA_META_KEY, htonl(priv->key)))
  		goto nla_put_failure;
b1c96ed37   Patrick McHardy   netfilter: nf_tab...
384
  	if (nft_dump_register(skb, NFTA_META_DREG, priv->dreg))
96518518c   Patrick McHardy   netfilter: add nf...
385
  		goto nla_put_failure;
e035b77ac   Arturo Borrero Gonzalez   netfilter: nf_tab...
386
387
388
389
390
  	return 0;
  
  nla_put_failure:
  	return -1;
  }
aa45660c6   Tomasz Bursztyka   netfilter: nf_tab...
391
  EXPORT_SYMBOL_GPL(nft_meta_get_dump);
e035b77ac   Arturo Borrero Gonzalez   netfilter: nf_tab...
392

aa45660c6   Tomasz Bursztyka   netfilter: nf_tab...
393
394
  int nft_meta_set_dump(struct sk_buff *skb,
  		      const struct nft_expr *expr)
e035b77ac   Arturo Borrero Gonzalez   netfilter: nf_tab...
395
396
  {
  	const struct nft_meta *priv = nft_expr_priv(expr);
96518518c   Patrick McHardy   netfilter: add nf...
397
398
  	if (nla_put_be32(skb, NFTA_META_KEY, htonl(priv->key)))
  		goto nla_put_failure;
b1c96ed37   Patrick McHardy   netfilter: nf_tab...
399
  	if (nft_dump_register(skb, NFTA_META_SREG, priv->sreg))
e035b77ac   Arturo Borrero Gonzalez   netfilter: nf_tab...
400
  		goto nla_put_failure;
96518518c   Patrick McHardy   netfilter: add nf...
401
402
403
404
405
  	return 0;
  
  nla_put_failure:
  	return -1;
  }
aa45660c6   Tomasz Bursztyka   netfilter: nf_tab...
406
  EXPORT_SYMBOL_GPL(nft_meta_set_dump);
96518518c   Patrick McHardy   netfilter: add nf...
407

e639f7ab0   Florian Westphal   netfilter: nf_tab...
408
409
410
411
412
413
414
415
416
  void nft_meta_set_destroy(const struct nft_ctx *ctx,
  			  const struct nft_expr *expr)
  {
  	const struct nft_meta *priv = nft_expr_priv(expr);
  
  	if (priv->key == NFT_META_NFTRACE)
  		static_branch_dec(&nft_trace_enabled);
  }
  EXPORT_SYMBOL_GPL(nft_meta_set_destroy);
ef1f7df91   Patrick McHardy   netfilter: nf_tab...
417
  static struct nft_expr_type nft_meta_type;
e035b77ac   Arturo Borrero Gonzalez   netfilter: nf_tab...
418
  static const struct nft_expr_ops nft_meta_get_ops = {
ef1f7df91   Patrick McHardy   netfilter: nf_tab...
419
  	.type		= &nft_meta_type,
96518518c   Patrick McHardy   netfilter: add nf...
420
  	.size		= NFT_EXPR_SIZE(sizeof(struct nft_meta)),
e035b77ac   Arturo Borrero Gonzalez   netfilter: nf_tab...
421
  	.eval		= nft_meta_get_eval,
d2caa696a   Patrick McHardy   netfilter: nft_me...
422
  	.init		= nft_meta_get_init,
e035b77ac   Arturo Borrero Gonzalez   netfilter: nf_tab...
423
  	.dump		= nft_meta_get_dump,
ef1f7df91   Patrick McHardy   netfilter: nf_tab...
424
  };
e035b77ac   Arturo Borrero Gonzalez   netfilter: nf_tab...
425
426
427
428
  static const struct nft_expr_ops nft_meta_set_ops = {
  	.type		= &nft_meta_type,
  	.size		= NFT_EXPR_SIZE(sizeof(struct nft_meta)),
  	.eval		= nft_meta_set_eval,
d2caa696a   Patrick McHardy   netfilter: nft_me...
429
  	.init		= nft_meta_set_init,
e639f7ab0   Florian Westphal   netfilter: nf_tab...
430
  	.destroy	= nft_meta_set_destroy,
e035b77ac   Arturo Borrero Gonzalez   netfilter: nf_tab...
431
  	.dump		= nft_meta_set_dump,
960fa72f6   Liping Zhang   netfilter: nft_me...
432
  	.validate	= nft_meta_set_validate,
e035b77ac   Arturo Borrero Gonzalez   netfilter: nf_tab...
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
  };
  
  static const struct nft_expr_ops *
  nft_meta_select_ops(const struct nft_ctx *ctx,
  		    const struct nlattr * const tb[])
  {
  	if (tb[NFTA_META_KEY] == NULL)
  		return ERR_PTR(-EINVAL);
  
  	if (tb[NFTA_META_DREG] && tb[NFTA_META_SREG])
  		return ERR_PTR(-EINVAL);
  
  	if (tb[NFTA_META_DREG])
  		return &nft_meta_get_ops;
  
  	if (tb[NFTA_META_SREG])
  		return &nft_meta_set_ops;
  
  	return ERR_PTR(-EINVAL);
  }
ef1f7df91   Patrick McHardy   netfilter: nf_tab...
453
454
  static struct nft_expr_type nft_meta_type __read_mostly = {
  	.name		= "meta",
d4ef38354   Arushi Singhal   netfilter: Remove...
455
  	.select_ops	= nft_meta_select_ops,
96518518c   Patrick McHardy   netfilter: add nf...
456
457
  	.policy		= nft_meta_policy,
  	.maxattr	= NFTA_META_MAX,
ef1f7df91   Patrick McHardy   netfilter: nf_tab...
458
  	.owner		= THIS_MODULE,
96518518c   Patrick McHardy   netfilter: add nf...
459
460
461
462
  };
  
  static int __init nft_meta_module_init(void)
  {
ef1f7df91   Patrick McHardy   netfilter: nf_tab...
463
  	return nft_register_expr(&nft_meta_type);
96518518c   Patrick McHardy   netfilter: add nf...
464
465
466
467
  }
  
  static void __exit nft_meta_module_exit(void)
  {
ef1f7df91   Patrick McHardy   netfilter: nf_tab...
468
  	nft_unregister_expr(&nft_meta_type);
96518518c   Patrick McHardy   netfilter: add nf...
469
470
471
472
473
474
475
476
  }
  
  module_init(nft_meta_module_init);
  module_exit(nft_meta_module_exit);
  
  MODULE_LICENSE("GPL");
  MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
  MODULE_ALIAS_NFT_EXPR("meta");