blob: 55d2d49c34259c52cdfdd8e011712d0921fec58b [file] [log] [blame]
Thomas Gleixnerd2912cb2019-06-04 10:11:33 +02001// SPDX-License-Identifier: GPL-2.0-only
Patrick McHardy96518512013-10-14 11:00:02 +02002/*
Patrick McHardyef1f7df2013-10-10 11:41:20 +02003 * Copyright (c) 2008-2009 Patrick McHardy <kaber@trash.net>
Florian Westphalbd2bbdb2018-04-16 19:15:53 +02004 * Copyright (c) 2014 Intel Corporation
5 * Author: Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com>
Patrick McHardy96518512013-10-14 11:00:02 +02006 *
Patrick McHardy96518512013-10-14 11:00:02 +02007 * Development of this code funded by Astaro AG (http://www.astaro.com/)
8 */
9
10#include <linux/kernel.h>
Patrick McHardy96518512013-10-14 11:00:02 +020011#include <linux/netlink.h>
12#include <linux/netfilter.h>
13#include <linux/netfilter/nf_tables.h>
Ana Reye2a093f2014-08-06 13:52:49 +020014#include <linux/in.h>
15#include <linux/ip.h>
16#include <linux/ipv6.h>
Florian Westphalb1fd94e2022-05-18 20:15:31 +020017#include <linux/random.h>
Ana Reyafc5be302014-08-24 14:08:36 +020018#include <linux/smp.h>
Florian Westphale639f7a2015-11-28 21:53:05 +010019#include <linux/static_key.h>
Patrick McHardy96518512013-10-14 11:00:02 +020020#include <net/dst.h>
Florian Westphalc14ceb02019-12-18 12:05:21 +010021#include <net/ip.h>
Patrick McHardy96518512013-10-14 11:00:02 +020022#include <net/sock.h>
23#include <net/tcp_states.h> /* for TCP_TIME_WAIT */
24#include <net/netfilter/nf_tables.h>
Florian Westphale639f7a2015-11-28 21:53:05 +010025#include <net/netfilter/nf_tables_core.h>
wenxu30e103f2019-07-05 21:16:32 +080026#include <net/netfilter/nft_meta.h>
Pablo Neira Ayusoc9626a22019-07-09 23:00:43 +020027#include <net/netfilter/nf_tables_offload.h>
Patrick McHardy96518512013-10-14 11:00:02 +020028
Florian Westphalb4aae752015-12-10 18:04:07 +010029#include <uapi/linux/netfilter_bridge.h> /* NF_BR_PRE_ROUTING */
30
Ander Juaristi63d10e12019-08-17 13:17:53 +020031#define NFT_META_SECS_PER_MINUTE 60
32#define NFT_META_SECS_PER_HOUR 3600
33#define NFT_META_SECS_PER_DAY 86400
34#define NFT_META_DAYS_PER_WEEK 7
35
Florian Westphaldb8f6f52019-12-18 12:05:13 +010036static u8 nft_meta_weekday(void)
Ander Juaristi63d10e12019-08-17 13:17:53 +020037{
Florian Westphaldb8f6f52019-12-18 12:05:13 +010038 time64_t secs = ktime_get_real_seconds();
Ander Juaristi63d10e12019-08-17 13:17:53 +020039 unsigned int dse;
40 u8 wday;
41
42 secs -= NFT_META_SECS_PER_MINUTE * sys_tz.tz_minuteswest;
Arnd Bergmann6408c402019-11-08 22:32:47 +010043 dse = div_u64(secs, NFT_META_SECS_PER_DAY);
Ander Juaristi63d10e12019-08-17 13:17:53 +020044 wday = (4 + dse) % NFT_META_DAYS_PER_WEEK;
45
46 return wday;
47}
48
Arnd Bergmann6408c402019-11-08 22:32:47 +010049static u32 nft_meta_hour(time64_t secs)
Ander Juaristi63d10e12019-08-17 13:17:53 +020050{
51 struct tm tm;
52
53 time64_to_tm(secs, 0, &tm);
54
55 return tm.tm_hour * NFT_META_SECS_PER_HOUR
56 + tm.tm_min * NFT_META_SECS_PER_MINUTE
57 + tm.tm_sec;
58}
59
Florian Westphaldb8f6f52019-12-18 12:05:13 +010060static noinline_for_stack void
61nft_meta_get_eval_time(enum nft_meta_keys key,
62 u32 *dest)
63{
64 switch (key) {
65 case NFT_META_TIME_NS:
66 nft_reg_store64(dest, ktime_get_real_ns());
67 break;
68 case NFT_META_TIME_DAY:
69 nft_reg_store8(dest, nft_meta_weekday());
70 break;
71 case NFT_META_TIME_HOUR:
72 *dest = nft_meta_hour(ktime_get_real_seconds());
73 break;
74 default:
75 break;
76 }
77}
78
Florian Westphal4a545942019-12-18 12:05:14 +010079static noinline bool
80nft_meta_get_eval_pkttype_lo(const struct nft_pktinfo *pkt,
81 u32 *dest)
82{
83 const struct sk_buff *skb = pkt->skb;
84
85 switch (nft_pf(pkt)) {
86 case NFPROTO_IPV4:
87 if (ipv4_is_multicast(ip_hdr(skb)->daddr))
88 nft_reg_store8(dest, PACKET_MULTICAST);
89 else
90 nft_reg_store8(dest, PACKET_BROADCAST);
91 break;
92 case NFPROTO_IPV6:
93 nft_reg_store8(dest, PACKET_MULTICAST);
94 break;
95 case NFPROTO_NETDEV:
96 switch (skb->protocol) {
97 case htons(ETH_P_IP): {
98 int noff = skb_network_offset(skb);
99 struct iphdr *iph, _iph;
100
101 iph = skb_header_pointer(skb, noff,
102 sizeof(_iph), &_iph);
103 if (!iph)
104 return false;
105
106 if (ipv4_is_multicast(iph->daddr))
107 nft_reg_store8(dest, PACKET_MULTICAST);
108 else
109 nft_reg_store8(dest, PACKET_BROADCAST);
110
111 break;
112 }
113 case htons(ETH_P_IPV6):
114 nft_reg_store8(dest, PACKET_MULTICAST);
115 break;
116 default:
117 WARN_ON_ONCE(1);
118 return false;
119 }
120 break;
121 default:
122 WARN_ON_ONCE(1);
123 return false;
124 }
125
126 return true;
127}
128
Florian Westphal726b44f2019-12-18 12:05:15 +0100129static noinline bool
130nft_meta_get_eval_skugid(enum nft_meta_keys key,
131 u32 *dest,
132 const struct nft_pktinfo *pkt)
133{
134 struct sock *sk = skb_to_full_sk(pkt->skb);
135 struct socket *sock;
136
137 if (!sk || !sk_fullsock(sk) || !net_eq(nft_net(pkt), sock_net(sk)))
138 return false;
139
140 read_lock_bh(&sk->sk_callback_lock);
141 sock = sk->sk_socket;
142 if (!sock || !sock->file) {
143 read_unlock_bh(&sk->sk_callback_lock);
144 return false;
145 }
146
147 switch (key) {
148 case NFT_META_SKUID:
Pablo Neira Ayuso0c924112020-09-03 19:00:52 +0200149 *dest = from_kuid_munged(sock_net(sk)->user_ns,
Florian Westphal726b44f2019-12-18 12:05:15 +0100150 sock->file->f_cred->fsuid);
151 break;
152 case NFT_META_SKGID:
Pablo Neira Ayuso0c924112020-09-03 19:00:52 +0200153 *dest = from_kgid_munged(sock_net(sk)->user_ns,
Florian Westphal726b44f2019-12-18 12:05:15 +0100154 sock->file->f_cred->fsgid);
155 break;
156 default:
157 break;
158 }
159
160 read_unlock_bh(&sk->sk_callback_lock);
161 return true;
162}
163
Florian Westphalb1327fb2019-12-18 12:05:16 +0100164#ifdef CONFIG_CGROUP_NET_CLASSID
165static noinline bool
166nft_meta_get_eval_cgroup(u32 *dest, const struct nft_pktinfo *pkt)
167{
168 struct sock *sk = skb_to_full_sk(pkt->skb);
169
170 if (!sk || !sk_fullsock(sk) || !net_eq(nft_net(pkt), sock_net(sk)))
171 return false;
172
173 *dest = sock_cgroup_classid(&sk->sk_cgrp_data);
174 return true;
175}
176#endif
177
Florian Westphala4150a12019-12-18 12:05:17 +0100178static noinline bool nft_meta_get_eval_kind(enum nft_meta_keys key,
179 u32 *dest,
180 const struct nft_pktinfo *pkt)
181{
182 const struct net_device *in = nft_in(pkt), *out = nft_out(pkt);
183
184 switch (key) {
185 case NFT_META_IIFKIND:
186 if (!in || !in->rtnl_link_ops)
187 return false;
188 strncpy((char *)dest, in->rtnl_link_ops->kind, IFNAMSIZ);
189 break;
190 case NFT_META_OIFKIND:
191 if (!out || !out->rtnl_link_ops)
192 return false;
193 strncpy((char *)dest, out->rtnl_link_ops->kind, IFNAMSIZ);
194 break;
195 default:
196 return false;
197 }
198
199 return true;
200}
201
Florian Westphal8724e812019-12-18 12:05:18 +0100202static void nft_meta_store_ifindex(u32 *dest, const struct net_device *dev)
203{
204 *dest = dev ? dev->ifindex : 0;
205}
206
207static void nft_meta_store_ifname(u32 *dest, const struct net_device *dev)
208{
209 strncpy((char *)dest, dev ? dev->name : "", IFNAMSIZ);
210}
211
212static bool nft_meta_store_iftype(u32 *dest, const struct net_device *dev)
213{
214 if (!dev)
215 return false;
216
217 nft_reg_store16(dest, dev->type);
218 return true;
219}
220
221static bool nft_meta_store_ifgroup(u32 *dest, const struct net_device *dev)
222{
223 if (!dev)
224 return false;
225
226 *dest = dev->group;
227 return true;
228}
229
230static bool nft_meta_get_eval_ifname(enum nft_meta_keys key, u32 *dest,
231 const struct nft_pktinfo *pkt)
232{
233 switch (key) {
234 case NFT_META_IIFNAME:
235 nft_meta_store_ifname(dest, nft_in(pkt));
236 break;
237 case NFT_META_OIFNAME:
238 nft_meta_store_ifname(dest, nft_out(pkt));
239 break;
240 case NFT_META_IIF:
241 nft_meta_store_ifindex(dest, nft_in(pkt));
242 break;
243 case NFT_META_OIF:
244 nft_meta_store_ifindex(dest, nft_out(pkt));
245 break;
Pablo Neira Ayuso56fa9502021-10-25 15:43:29 +0200246 case NFT_META_IFTYPE:
247 if (!nft_meta_store_iftype(dest, pkt->skb->dev))
248 return false;
249 break;
250 case __NFT_META_IIFTYPE:
Florian Westphal8724e812019-12-18 12:05:18 +0100251 if (!nft_meta_store_iftype(dest, nft_in(pkt)))
252 return false;
253 break;
254 case NFT_META_OIFTYPE:
255 if (!nft_meta_store_iftype(dest, nft_out(pkt)))
256 return false;
257 break;
258 case NFT_META_IIFGROUP:
Florian Westphal78470d92020-08-02 03:27:03 +0200259 if (!nft_meta_store_ifgroup(dest, nft_in(pkt)))
Florian Westphal8724e812019-12-18 12:05:18 +0100260 return false;
261 break;
262 case NFT_META_OIFGROUP:
263 if (!nft_meta_store_ifgroup(dest, nft_out(pkt)))
264 return false;
265 break;
266 default:
267 return false;
268 }
269
270 return true;
271}
272
Florian Westphal01a0fc82019-12-18 12:05:20 +0100273#ifdef CONFIG_IP_ROUTE_CLASSID
274static noinline bool
275nft_meta_get_eval_rtclassid(const struct sk_buff *skb, u32 *dest)
276{
277 const struct dst_entry *dst = skb_dst(skb);
278
279 if (!dst)
280 return false;
281
282 *dest = dst->tclassid;
283 return true;
284}
285#endif
286
Florian Westphalc14ceb02019-12-18 12:05:21 +0100287static noinline u32 nft_meta_get_eval_sdif(const struct nft_pktinfo *pkt)
288{
289 switch (nft_pf(pkt)) {
290 case NFPROTO_IPV4:
291 return inet_sdif(pkt->skb);
292 case NFPROTO_IPV6:
293 return inet6_sdif(pkt->skb);
294 }
295
296 return 0;
297}
298
299static noinline void
300nft_meta_get_eval_sdifname(u32 *dest, const struct nft_pktinfo *pkt)
301{
302 u32 sdif = nft_meta_get_eval_sdif(pkt);
303 const struct net_device *dev;
304
305 dev = sdif ? dev_get_by_index_rcu(nft_net(pkt), sdif) : NULL;
306 nft_meta_store_ifname(dest, dev);
307}
308
Florian Westphal222440b2018-07-04 12:48:04 +0200309void nft_meta_get_eval(const struct nft_expr *expr,
310 struct nft_regs *regs,
311 const struct nft_pktinfo *pkt)
Patrick McHardy96518512013-10-14 11:00:02 +0200312{
313 const struct nft_meta *priv = nft_expr_priv(expr);
314 const struct sk_buff *skb = pkt->skb;
Patrick McHardy49499c32015-04-11 02:27:37 +0100315 u32 *dest = &regs->data[priv->dreg];
Patrick McHardy96518512013-10-14 11:00:02 +0200316
317 switch (priv->key) {
318 case NFT_META_LEN:
Patrick McHardyfad136e2015-04-11 02:27:33 +0100319 *dest = skb->len;
Patrick McHardy96518512013-10-14 11:00:02 +0200320 break;
321 case NFT_META_PROTOCOL:
Liping Zhang10596602017-03-08 22:54:18 +0800322 nft_reg_store16(dest, (__force u16)skb->protocol);
Patrick McHardy96518512013-10-14 11:00:02 +0200323 break;
Patrick McHardy124edfa2014-01-03 12:16:17 +0000324 case NFT_META_NFPROTO:
Liping Zhang10596602017-03-08 22:54:18 +0800325 nft_reg_store8(dest, nft_pf(pkt));
Patrick McHardy124edfa2014-01-03 12:16:17 +0000326 break;
Patrick McHardy4566bf22014-01-03 12:16:18 +0000327 case NFT_META_L4PROTO:
Pablo Neira Ayusob5bdc6f2021-10-28 21:47:55 +0200328 if (!(pkt->flags & NFT_PKTINFO_L4PROTO))
Pablo Neira Ayusobeac5af2016-09-09 12:42:49 +0200329 goto err;
Liping Zhang10596602017-03-08 22:54:18 +0800330 nft_reg_store8(dest, pkt->tprot);
Patrick McHardy4566bf22014-01-03 12:16:18 +0000331 break;
Patrick McHardy96518512013-10-14 11:00:02 +0200332 case NFT_META_PRIORITY:
Patrick McHardyfad136e2015-04-11 02:27:33 +0100333 *dest = skb->priority;
Patrick McHardy96518512013-10-14 11:00:02 +0200334 break;
335 case NFT_META_MARK:
Patrick McHardyfad136e2015-04-11 02:27:33 +0100336 *dest = skb->mark;
Patrick McHardy96518512013-10-14 11:00:02 +0200337 break;
338 case NFT_META_IIF:
Patrick McHardy96518512013-10-14 11:00:02 +0200339 case NFT_META_OIF:
Patrick McHardy96518512013-10-14 11:00:02 +0200340 case NFT_META_IIFNAME:
Patrick McHardy96518512013-10-14 11:00:02 +0200341 case NFT_META_OIFNAME:
Patrick McHardy96518512013-10-14 11:00:02 +0200342 case NFT_META_IIFTYPE:
Patrick McHardy96518512013-10-14 11:00:02 +0200343 case NFT_META_OIFTYPE:
Florian Westphal8724e812019-12-18 12:05:18 +0100344 case NFT_META_IIFGROUP:
345 case NFT_META_OIFGROUP:
346 if (!nft_meta_get_eval_ifname(priv->key, dest, pkt))
Patrick McHardy96518512013-10-14 11:00:02 +0200347 goto err;
Patrick McHardy96518512013-10-14 11:00:02 +0200348 break;
349 case NFT_META_SKUID:
Patrick McHardy96518512013-10-14 11:00:02 +0200350 case NFT_META_SKGID:
Florian Westphal726b44f2019-12-18 12:05:15 +0100351 if (!nft_meta_get_eval_skugid(priv->key, dest, pkt))
Patrick McHardy96518512013-10-14 11:00:02 +0200352 goto err;
Patrick McHardy96518512013-10-14 11:00:02 +0200353 break;
Paul Bolle06efbd62014-02-12 10:53:01 +0100354#ifdef CONFIG_IP_ROUTE_CLASSID
Florian Westphal01a0fc82019-12-18 12:05:20 +0100355 case NFT_META_RTCLASSID:
356 if (!nft_meta_get_eval_rtclassid(skb, dest))
Patrick McHardy96518512013-10-14 11:00:02 +0200357 goto err;
Patrick McHardy96518512013-10-14 11:00:02 +0200358 break;
Patrick McHardy96518512013-10-14 11:00:02 +0200359#endif
360#ifdef CONFIG_NETWORK_SECMARK
361 case NFT_META_SECMARK:
Patrick McHardyfad136e2015-04-11 02:27:33 +0100362 *dest = skb->secmark;
Patrick McHardy96518512013-10-14 11:00:02 +0200363 break;
364#endif
Ana Reye2a093f2014-08-06 13:52:49 +0200365 case NFT_META_PKTTYPE:
366 if (skb->pkt_type != PACKET_LOOPBACK) {
Liping Zhang10596602017-03-08 22:54:18 +0800367 nft_reg_store8(dest, skb->pkt_type);
Ana Reye2a093f2014-08-06 13:52:49 +0200368 break;
369 }
370
Florian Westphal4a545942019-12-18 12:05:14 +0100371 if (!nft_meta_get_eval_pkttype_lo(pkt, dest))
Ana Reye2a093f2014-08-06 13:52:49 +0200372 goto err;
Ana Reye2a093f2014-08-06 13:52:49 +0200373 break;
Ana Reyafc5be302014-08-24 14:08:36 +0200374 case NFT_META_CPU:
Patrick McHardyfad136e2015-04-11 02:27:33 +0100375 *dest = raw_smp_processor_id();
Ana Reyafc5be302014-08-24 14:08:36 +0200376 break;
Mathias Krausee181a542015-07-19 22:21:13 +0200377#ifdef CONFIG_CGROUP_NET_CLASSID
Ana Reyce674172014-11-03 18:10:50 +0100378 case NFT_META_CGROUP:
Florian Westphalb1327fb2019-12-18 12:05:16 +0100379 if (!nft_meta_get_eval_cgroup(dest, pkt))
Pablo Neira Ayusoc5035c72015-03-27 12:14:13 +0100380 goto err;
Ana Reyce674172014-11-03 18:10:50 +0100381 break;
Mathias Krausee181a542015-07-19 22:21:13 +0200382#endif
Florian Westphal6b2faee2019-12-18 12:05:19 +0100383 case NFT_META_PRANDOM:
Florian Westphalb1fd94e2022-05-18 20:15:31 +0200384 *dest = get_random_u32();
Florian Westphalb07edbe2016-02-16 17:24:08 +0100385 break;
Florian Westphalf6931f52017-12-06 16:18:16 +0100386#ifdef CONFIG_XFRM
387 case NFT_META_SECPATH:
Florian Westphal7af8f4c2018-12-18 17:15:19 +0100388 nft_reg_store8(dest, secpath_exists(skb));
Florian Westphalf6931f52017-12-06 16:18:16 +0100389 break;
390#endif
wenxu0fb4d212019-01-16 07:53:51 +0800391 case NFT_META_IIFKIND:
wenxu0fb4d212019-01-16 07:53:51 +0800392 case NFT_META_OIFKIND:
Florian Westphala4150a12019-12-18 12:05:17 +0100393 if (!nft_meta_get_eval_kind(priv->key, dest, pkt))
wenxu0fb4d212019-01-16 07:53:51 +0800394 goto err;
wenxu0fb4d212019-01-16 07:53:51 +0800395 break;
Ander Juaristi63d10e12019-08-17 13:17:53 +0200396 case NFT_META_TIME_NS:
Ander Juaristi63d10e12019-08-17 13:17:53 +0200397 case NFT_META_TIME_DAY:
Ander Juaristi63d10e12019-08-17 13:17:53 +0200398 case NFT_META_TIME_HOUR:
Florian Westphaldb8f6f52019-12-18 12:05:13 +0100399 nft_meta_get_eval_time(priv->key, dest);
Ander Juaristi63d10e12019-08-17 13:17:53 +0200400 break;
Florian Westphalc14ceb02019-12-18 12:05:21 +0100401 case NFT_META_SDIF:
402 *dest = nft_meta_get_eval_sdif(pkt);
403 break;
404 case NFT_META_SDIFNAME:
405 nft_meta_get_eval_sdifname(dest, pkt);
406 break;
Patrick McHardy96518512013-10-14 11:00:02 +0200407 default:
408 WARN_ON(1);
409 goto err;
410 }
411 return;
412
413err:
Patrick McHardya55e22e2015-04-11 02:27:31 +0100414 regs->verdict.code = NFT_BREAK;
Patrick McHardy96518512013-10-14 11:00:02 +0200415}
wenxu30e103f2019-07-05 21:16:32 +0800416EXPORT_SYMBOL_GPL(nft_meta_get_eval);
Patrick McHardy96518512013-10-14 11:00:02 +0200417
wenxu30e103f2019-07-05 21:16:32 +0800418void nft_meta_set_eval(const struct nft_expr *expr,
419 struct nft_regs *regs,
420 const struct nft_pktinfo *pkt)
Arturo Borrero Gonzaleze035b772013-12-26 16:38:01 +0100421{
422 const struct nft_meta *meta = nft_expr_priv(expr);
423 struct sk_buff *skb = pkt->skb;
Liping Zhang10596602017-03-08 22:54:18 +0800424 u32 *sreg = &regs->data[meta->sreg];
425 u32 value = *sreg;
Taehee Yoo97a05492018-05-17 22:49:49 +0900426 u8 value8;
Arturo Borrero Gonzaleze035b772013-12-26 16:38:01 +0100427
428 switch (meta->key) {
429 case NFT_META_MARK:
430 skb->mark = value;
431 break;
432 case NFT_META_PRIORITY:
433 skb->priority = value;
434 break;
Florian Westphalb4aae752015-12-10 18:04:07 +0100435 case NFT_META_PKTTYPE:
Taehee Yoo97a05492018-05-17 22:49:49 +0900436 value8 = nft_reg_load8(sreg);
Liping Zhang10596602017-03-08 22:54:18 +0800437
Taehee Yoo97a05492018-05-17 22:49:49 +0900438 if (skb->pkt_type != value8 &&
439 skb_pkt_type_ok(value8) &&
Liping Zhang10596602017-03-08 22:54:18 +0800440 skb_pkt_type_ok(skb->pkt_type))
Taehee Yoo97a05492018-05-17 22:49:49 +0900441 skb->pkt_type = value8;
Florian Westphalb4aae752015-12-10 18:04:07 +0100442 break;
Arturo Borrero Gonzaleze035b772013-12-26 16:38:01 +0100443 case NFT_META_NFTRACE:
Taehee Yoo97a05492018-05-17 22:49:49 +0900444 value8 = nft_reg_load8(sreg);
445
446 skb->nf_trace = !!value8;
Arturo Borrero Gonzaleze035b772013-12-26 16:38:01 +0100447 break;
Christian Göttscheb473a1f2018-09-23 20:26:16 +0200448#ifdef CONFIG_NETWORK_SECMARK
449 case NFT_META_SECMARK:
450 skb->secmark = value;
451 break;
452#endif
Arturo Borrero Gonzaleze035b772013-12-26 16:38:01 +0100453 default:
454 WARN_ON(1);
455 }
456}
wenxu30e103f2019-07-05 21:16:32 +0800457EXPORT_SYMBOL_GPL(nft_meta_set_eval);
Arturo Borrero Gonzaleze035b772013-12-26 16:38:01 +0100458
wenxu30e103f2019-07-05 21:16:32 +0800459const struct nla_policy nft_meta_policy[NFTA_META_MAX + 1] = {
Patrick McHardy96518512013-10-14 11:00:02 +0200460 [NFTA_META_DREG] = { .type = NLA_U32 },
461 [NFTA_META_KEY] = { .type = NLA_U32 },
Arturo Borrero Gonzaleze035b772013-12-26 16:38:01 +0100462 [NFTA_META_SREG] = { .type = NLA_U32 },
Patrick McHardy96518512013-10-14 11:00:02 +0200463};
wenxu30e103f2019-07-05 21:16:32 +0800464EXPORT_SYMBOL_GPL(nft_meta_policy);
Patrick McHardy96518512013-10-14 11:00:02 +0200465
wenxu30e103f2019-07-05 21:16:32 +0800466int nft_meta_get_init(const struct nft_ctx *ctx,
467 const struct nft_expr *expr,
468 const struct nlattr * const tb[])
Patrick McHardy96518512013-10-14 11:00:02 +0200469{
Patrick McHardyd2caa692014-03-29 10:43:02 +0000470 struct nft_meta *priv = nft_expr_priv(expr);
Patrick McHardy45d9bcd2015-04-11 02:27:26 +0100471 unsigned int len;
Patrick McHardy96518512013-10-14 11:00:02 +0200472
Patrick McHardyd2caa692014-03-29 10:43:02 +0000473 priv->key = ntohl(nla_get_be32(tb[NFTA_META_KEY]));
474 switch (priv->key) {
Patrick McHardy96518512013-10-14 11:00:02 +0200475 case NFT_META_PROTOCOL:
Patrick McHardy45d9bcd2015-04-11 02:27:26 +0100476 case NFT_META_IIFTYPE:
477 case NFT_META_OIFTYPE:
478 len = sizeof(u16);
479 break;
Patrick McHardy124edfa2014-01-03 12:16:17 +0000480 case NFT_META_NFPROTO:
Patrick McHardy4566bf22014-01-03 12:16:18 +0000481 case NFT_META_L4PROTO:
Patrick McHardy45d9bcd2015-04-11 02:27:26 +0100482 case NFT_META_LEN:
Patrick McHardy96518512013-10-14 11:00:02 +0200483 case NFT_META_PRIORITY:
484 case NFT_META_MARK:
485 case NFT_META_IIF:
486 case NFT_META_OIF:
Florian Westphalc14ceb02019-12-18 12:05:21 +0100487 case NFT_META_SDIF:
Patrick McHardy96518512013-10-14 11:00:02 +0200488 case NFT_META_SKUID:
489 case NFT_META_SKGID:
Paul Bolle06efbd62014-02-12 10:53:01 +0100490#ifdef CONFIG_IP_ROUTE_CLASSID
Patrick McHardy96518512013-10-14 11:00:02 +0200491 case NFT_META_RTCLASSID:
492#endif
493#ifdef CONFIG_NETWORK_SECMARK
494 case NFT_META_SECMARK:
495#endif
Ana Reye2a093f2014-08-06 13:52:49 +0200496 case NFT_META_PKTTYPE:
Ana Reyafc5be302014-08-24 14:08:36 +0200497 case NFT_META_CPU:
Ana Rey3045d762014-09-02 20:36:14 +0200498 case NFT_META_IIFGROUP:
499 case NFT_META_OIFGROUP:
Mathias Krausee181a542015-07-19 22:21:13 +0200500#ifdef CONFIG_CGROUP_NET_CLASSID
Ana Reyce674172014-11-03 18:10:50 +0100501 case NFT_META_CGROUP:
Mathias Krausee181a542015-07-19 22:21:13 +0200502#endif
Patrick McHardy45d9bcd2015-04-11 02:27:26 +0100503 len = sizeof(u32);
504 break;
505 case NFT_META_IIFNAME:
506 case NFT_META_OIFNAME:
wenxu0fb4d212019-01-16 07:53:51 +0800507 case NFT_META_IIFKIND:
508 case NFT_META_OIFKIND:
Florian Westphalc14ceb02019-12-18 12:05:21 +0100509 case NFT_META_SDIFNAME:
Patrick McHardy45d9bcd2015-04-11 02:27:26 +0100510 len = IFNAMSIZ;
Patrick McHardyd2caa692014-03-29 10:43:02 +0000511 break;
Florian Westphalb07edbe2016-02-16 17:24:08 +0100512 case NFT_META_PRANDOM:
Florian Westphalb07edbe2016-02-16 17:24:08 +0100513 len = sizeof(u32);
514 break;
Florian Westphalf6931f52017-12-06 16:18:16 +0100515#ifdef CONFIG_XFRM
516 case NFT_META_SECPATH:
517 len = sizeof(u8);
518 break;
519#endif
Ander Juaristi63d10e12019-08-17 13:17:53 +0200520 case NFT_META_TIME_NS:
521 len = sizeof(u64);
522 break;
523 case NFT_META_TIME_DAY:
524 len = sizeof(u8);
525 break;
526 case NFT_META_TIME_HOUR:
527 len = sizeof(u32);
528 break;
Patrick McHardy96518512013-10-14 11:00:02 +0200529 default:
530 return -EOPNOTSUPP;
531 }
532
Pablo Neira Ayuso34cc9e52022-03-14 18:23:01 +0100533 priv->len = len;
Pablo Neira Ayuso345023b2021-01-25 18:27:22 +0100534 return nft_parse_register_store(ctx, tb[NFTA_META_DREG], &priv->dreg,
535 NULL, NFT_DATA_VALUE, len);
Patrick McHardy96518512013-10-14 11:00:02 +0200536}
wenxu30e103f2019-07-05 21:16:32 +0800537EXPORT_SYMBOL_GPL(nft_meta_get_init);
Patrick McHardy96518512013-10-14 11:00:02 +0200538
Florian Westphalc14ceb02019-12-18 12:05:21 +0100539static int nft_meta_get_validate_sdif(const struct nft_ctx *ctx)
Florian Westphalf6931f52017-12-06 16:18:16 +0100540{
Florian Westphalf6931f52017-12-06 16:18:16 +0100541 unsigned int hooks;
542
Florian Westphalc14ceb02019-12-18 12:05:21 +0100543 switch (ctx->family) {
544 case NFPROTO_IPV4:
545 case NFPROTO_IPV6:
546 case NFPROTO_INET:
547 hooks = (1 << NF_INET_LOCAL_IN) |
548 (1 << NF_INET_FORWARD);
549 break;
550 default:
551 return -EOPNOTSUPP;
552 }
553
554 return nft_chain_validate_hooks(ctx->chain, hooks);
555}
556
557static int nft_meta_get_validate_xfrm(const struct nft_ctx *ctx)
558{
559#ifdef CONFIG_XFRM
560 unsigned int hooks;
Florian Westphalf6931f52017-12-06 16:18:16 +0100561
Pablo Neira Ayuso36596da2018-01-09 02:38:03 +0100562 switch (ctx->family) {
Florian Westphalf6931f52017-12-06 16:18:16 +0100563 case NFPROTO_NETDEV:
564 hooks = 1 << NF_NETDEV_INGRESS;
565 break;
566 case NFPROTO_IPV4:
567 case NFPROTO_IPV6:
568 case NFPROTO_INET:
569 hooks = (1 << NF_INET_PRE_ROUTING) |
570 (1 << NF_INET_LOCAL_IN) |
571 (1 << NF_INET_FORWARD);
572 break;
573 default:
574 return -EOPNOTSUPP;
575 }
576
577 return nft_chain_validate_hooks(ctx->chain, hooks);
578#else
579 return 0;
580#endif
581}
582
Florian Westphalc14ceb02019-12-18 12:05:21 +0100583static int nft_meta_get_validate(const struct nft_ctx *ctx,
584 const struct nft_expr *expr,
585 const struct nft_data **data)
586{
587 const struct nft_meta *priv = nft_expr_priv(expr);
588
589 switch (priv->key) {
590 case NFT_META_SECPATH:
591 return nft_meta_get_validate_xfrm(ctx);
592 case NFT_META_SDIF:
593 case NFT_META_SDIFNAME:
594 return nft_meta_get_validate_sdif(ctx);
595 default:
596 break;
597 }
598
599 return 0;
600}
601
wenxu30e103f2019-07-05 21:16:32 +0800602int nft_meta_set_validate(const struct nft_ctx *ctx,
603 const struct nft_expr *expr,
604 const struct nft_data **data)
Florian Westphalb4aae752015-12-10 18:04:07 +0100605{
Liping Zhang960fa722016-08-22 22:57:56 +0800606 struct nft_meta *priv = nft_expr_priv(expr);
Florian Westphalb4aae752015-12-10 18:04:07 +0100607 unsigned int hooks;
608
Liping Zhang960fa722016-08-22 22:57:56 +0800609 if (priv->key != NFT_META_PKTTYPE)
610 return 0;
611
Pablo Neira Ayuso36596da2018-01-09 02:38:03 +0100612 switch (ctx->family) {
Florian Westphalb4aae752015-12-10 18:04:07 +0100613 case NFPROTO_BRIDGE:
614 hooks = 1 << NF_BR_PRE_ROUTING;
615 break;
616 case NFPROTO_NETDEV:
617 hooks = 1 << NF_NETDEV_INGRESS;
618 break;
Liping Zhang96d9f2a2016-10-19 23:31:29 +0800619 case NFPROTO_IPV4:
620 case NFPROTO_IPV6:
621 case NFPROTO_INET:
622 hooks = 1 << NF_INET_PRE_ROUTING;
623 break;
Florian Westphalb4aae752015-12-10 18:04:07 +0100624 default:
625 return -EOPNOTSUPP;
626 }
627
628 return nft_chain_validate_hooks(ctx->chain, hooks);
629}
wenxu30e103f2019-07-05 21:16:32 +0800630EXPORT_SYMBOL_GPL(nft_meta_set_validate);
Florian Westphalb4aae752015-12-10 18:04:07 +0100631
wenxu30e103f2019-07-05 21:16:32 +0800632int nft_meta_set_init(const struct nft_ctx *ctx,
633 const struct nft_expr *expr,
634 const struct nlattr * const tb[])
Arturo Borrero Gonzaleze035b772013-12-26 16:38:01 +0100635{
636 struct nft_meta *priv = nft_expr_priv(expr);
Patrick McHardyd07db982015-04-11 02:27:30 +0100637 unsigned int len;
Arturo Borrero Gonzaleze035b772013-12-26 16:38:01 +0100638 int err;
639
640 priv->key = ntohl(nla_get_be32(tb[NFTA_META_KEY]));
Patrick McHardyd2caa692014-03-29 10:43:02 +0000641 switch (priv->key) {
642 case NFT_META_MARK:
643 case NFT_META_PRIORITY:
Christian Göttscheb473a1f2018-09-23 20:26:16 +0200644#ifdef CONFIG_NETWORK_SECMARK
645 case NFT_META_SECMARK:
646#endif
Patrick McHardyd07db982015-04-11 02:27:30 +0100647 len = sizeof(u32);
648 break;
Patrick McHardyd2caa692014-03-29 10:43:02 +0000649 case NFT_META_NFTRACE:
Patrick McHardyd07db982015-04-11 02:27:30 +0100650 len = sizeof(u8);
Patrick McHardyd2caa692014-03-29 10:43:02 +0000651 break;
Florian Westphalb4aae752015-12-10 18:04:07 +0100652 case NFT_META_PKTTYPE:
Florian Westphalb4aae752015-12-10 18:04:07 +0100653 len = sizeof(u8);
654 break;
Patrick McHardyd2caa692014-03-29 10:43:02 +0000655 default:
656 return -EOPNOTSUPP;
Arturo Borrero Gonzaleze035b772013-12-26 16:38:01 +0100657 }
658
Pablo Neira Ayuso34cc9e52022-03-14 18:23:01 +0100659 priv->len = len;
Pablo Neira Ayuso4f16d252021-01-25 17:28:18 +0100660 err = nft_parse_register_load(tb[NFTA_META_SREG], &priv->sreg, len);
Pablo Neira Ayusob38895c2014-01-09 20:03:55 +0100661 if (err < 0)
662 return err;
Arturo Borrero Gonzaleze035b772013-12-26 16:38:01 +0100663
Florian Westphale639f7a2015-11-28 21:53:05 +0100664 if (priv->key == NFT_META_NFTRACE)
665 static_branch_inc(&nft_trace_enabled);
666
Arturo Borrero Gonzaleze035b772013-12-26 16:38:01 +0100667 return 0;
668}
wenxu30e103f2019-07-05 21:16:32 +0800669EXPORT_SYMBOL_GPL(nft_meta_set_init);
Arturo Borrero Gonzaleze035b772013-12-26 16:38:01 +0100670
wenxu30e103f2019-07-05 21:16:32 +0800671int nft_meta_get_dump(struct sk_buff *skb,
672 const struct nft_expr *expr)
Patrick McHardy96518512013-10-14 11:00:02 +0200673{
674 const struct nft_meta *priv = nft_expr_priv(expr);
675
Patrick McHardy96518512013-10-14 11:00:02 +0200676 if (nla_put_be32(skb, NFTA_META_KEY, htonl(priv->key)))
677 goto nla_put_failure;
Patrick McHardyb1c96ed2015-04-11 02:27:36 +0100678 if (nft_dump_register(skb, NFTA_META_DREG, priv->dreg))
Arturo Borrero Gonzaleze035b772013-12-26 16:38:01 +0100679 goto nla_put_failure;
Patrick McHardy96518512013-10-14 11:00:02 +0200680 return 0;
681
682nla_put_failure:
683 return -1;
684}
wenxu30e103f2019-07-05 21:16:32 +0800685EXPORT_SYMBOL_GPL(nft_meta_get_dump);
Patrick McHardy96518512013-10-14 11:00:02 +0200686
wenxu30e103f2019-07-05 21:16:32 +0800687int nft_meta_set_dump(struct sk_buff *skb, const struct nft_expr *expr)
Arturo Borrero Gonzaleze035b772013-12-26 16:38:01 +0100688{
689 const struct nft_meta *priv = nft_expr_priv(expr);
690
691 if (nla_put_be32(skb, NFTA_META_KEY, htonl(priv->key)))
692 goto nla_put_failure;
Patrick McHardyb1c96ed2015-04-11 02:27:36 +0100693 if (nft_dump_register(skb, NFTA_META_SREG, priv->sreg))
Arturo Borrero Gonzaleze035b772013-12-26 16:38:01 +0100694 goto nla_put_failure;
695
696 return 0;
697
698nla_put_failure:
699 return -1;
700}
wenxu30e103f2019-07-05 21:16:32 +0800701EXPORT_SYMBOL_GPL(nft_meta_set_dump);
Arturo Borrero Gonzaleze035b772013-12-26 16:38:01 +0100702
wenxu30e103f2019-07-05 21:16:32 +0800703void nft_meta_set_destroy(const struct nft_ctx *ctx,
704 const struct nft_expr *expr)
Florian Westphale639f7a2015-11-28 21:53:05 +0100705{
706 const struct nft_meta *priv = nft_expr_priv(expr);
707
708 if (priv->key == NFT_META_NFTRACE)
709 static_branch_dec(&nft_trace_enabled);
710}
wenxu30e103f2019-07-05 21:16:32 +0800711EXPORT_SYMBOL_GPL(nft_meta_set_destroy);
Florian Westphale639f7a2015-11-28 21:53:05 +0100712
Pablo Neira Ayusoc9626a22019-07-09 23:00:43 +0200713static int nft_meta_get_offload(struct nft_offload_ctx *ctx,
714 struct nft_flow_rule *flow,
715 const struct nft_expr *expr)
716{
717 const struct nft_meta *priv = nft_expr_priv(expr);
718 struct nft_offload_reg *reg = &ctx->regs[priv->dreg];
719
720 switch (priv->key) {
721 case NFT_META_PROTOCOL:
Pablo Neira Ayusoa5d45bc2020-11-25 23:50:17 +0100722 NFT_OFFLOAD_MATCH_EXACT(FLOW_DISSECTOR_KEY_BASIC, basic, n_proto,
723 sizeof(__u16), reg);
Pablo Neira Ayusoc9626a22019-07-09 23:00:43 +0200724 nft_offload_set_dependency(ctx, NFT_OFFLOAD_DEP_NETWORK);
725 break;
726 case NFT_META_L4PROTO:
Pablo Neira Ayusoa5d45bc2020-11-25 23:50:17 +0100727 NFT_OFFLOAD_MATCH_EXACT(FLOW_DISSECTOR_KEY_BASIC, basic, ip_proto,
728 sizeof(__u8), reg);
Pablo Neira Ayusoc9626a22019-07-09 23:00:43 +0200729 nft_offload_set_dependency(ctx, NFT_OFFLOAD_DEP_TRANSPORT);
730 break;
Pablo Neira Ayuso25da5eb2019-10-28 16:02:50 +0100731 case NFT_META_IIF:
Pablo Neira Ayusoa5d45bc2020-11-25 23:50:17 +0100732 NFT_OFFLOAD_MATCH_EXACT(FLOW_DISSECTOR_KEY_META, meta,
733 ingress_ifindex, sizeof(__u32), reg);
Pablo Neira Ayuso25da5eb2019-10-28 16:02:50 +0100734 break;
Pablo Neira Ayuso8819efc2019-11-19 23:05:53 +0100735 case NFT_META_IIFTYPE:
Pablo Neira Ayusoa5d45bc2020-11-25 23:50:17 +0100736 NFT_OFFLOAD_MATCH_EXACT(FLOW_DISSECTOR_KEY_META, meta,
737 ingress_iftype, sizeof(__u16), reg);
Pablo Neira Ayuso8819efc2019-11-19 23:05:53 +0100738 break;
Pablo Neira Ayusoc9626a22019-07-09 23:00:43 +0200739 default:
740 return -EOPNOTSUPP;
741 }
742
743 return 0;
744}
745
Florian Westphalaaa7b202022-03-14 18:23:04 +0100746bool nft_meta_get_reduce(struct nft_regs_track *track,
747 const struct nft_expr *expr)
Pablo Neira Ayuso9b17afb2022-01-09 17:11:23 +0100748{
749 const struct nft_meta *priv = nft_expr_priv(expr);
750 const struct nft_meta *meta;
751
Pablo Neira Ayuso34cc9e52022-03-14 18:23:01 +0100752 if (!nft_reg_track_cmp(track, expr, priv->dreg)) {
753 nft_reg_track_update(track, expr, priv->dreg, priv->len);
Pablo Neira Ayuso9b17afb2022-01-09 17:11:23 +0100754 return false;
755 }
756
757 meta = nft_expr_priv(track->regs[priv->dreg].selector);
758 if (priv->key != meta->key ||
759 priv->dreg != meta->dreg) {
Pablo Neira Ayuso34cc9e52022-03-14 18:23:01 +0100760 nft_reg_track_update(track, expr, priv->dreg, priv->len);
Pablo Neira Ayuso9b17afb2022-01-09 17:11:23 +0100761 return false;
762 }
763
764 if (!track->regs[priv->dreg].bitwise)
765 return true;
766
Pablo Neira Ayusobe5650f2022-01-09 17:11:24 +0100767 return nft_expr_reduce_bitwise(track, expr);
Pablo Neira Ayuso9b17afb2022-01-09 17:11:23 +0100768}
Florian Westphalaaa7b202022-03-14 18:23:04 +0100769EXPORT_SYMBOL_GPL(nft_meta_get_reduce);
Pablo Neira Ayuso9b17afb2022-01-09 17:11:23 +0100770
Arturo Borrero Gonzaleze035b772013-12-26 16:38:01 +0100771static const struct nft_expr_ops nft_meta_get_ops = {
Patrick McHardyef1f7df2013-10-10 11:41:20 +0200772 .type = &nft_meta_type,
Patrick McHardy96518512013-10-14 11:00:02 +0200773 .size = NFT_EXPR_SIZE(sizeof(struct nft_meta)),
Arturo Borrero Gonzaleze035b772013-12-26 16:38:01 +0100774 .eval = nft_meta_get_eval,
Patrick McHardyd2caa692014-03-29 10:43:02 +0000775 .init = nft_meta_get_init,
Arturo Borrero Gonzaleze035b772013-12-26 16:38:01 +0100776 .dump = nft_meta_get_dump,
Pablo Neira Ayuso9b17afb2022-01-09 17:11:23 +0100777 .reduce = nft_meta_get_reduce,
Florian Westphalf6931f52017-12-06 16:18:16 +0100778 .validate = nft_meta_get_validate,
Pablo Neira Ayusoc9626a22019-07-09 23:00:43 +0200779 .offload = nft_meta_get_offload,
Patrick McHardyef1f7df2013-10-10 11:41:20 +0200780};
781
Pablo Neira Ayuso4a80e0262022-01-09 17:11:26 +0100782static bool nft_meta_set_reduce(struct nft_regs_track *track,
783 const struct nft_expr *expr)
784{
785 int i;
786
787 for (i = 0; i < NFT_REG32_NUM; i++) {
788 if (!track->regs[i].selector)
789 continue;
790
791 if (track->regs[i].selector->ops != &nft_meta_get_ops)
792 continue;
793
Pablo Neira Ayuso34cc9e52022-03-14 18:23:01 +0100794 __nft_reg_track_cancel(track, i);
Pablo Neira Ayuso4a80e0262022-01-09 17:11:26 +0100795 }
796
797 return false;
798}
799
Arturo Borrero Gonzaleze035b772013-12-26 16:38:01 +0100800static const struct nft_expr_ops nft_meta_set_ops = {
801 .type = &nft_meta_type,
802 .size = NFT_EXPR_SIZE(sizeof(struct nft_meta)),
803 .eval = nft_meta_set_eval,
Patrick McHardyd2caa692014-03-29 10:43:02 +0000804 .init = nft_meta_set_init,
Florian Westphale639f7a2015-11-28 21:53:05 +0100805 .destroy = nft_meta_set_destroy,
Arturo Borrero Gonzaleze035b772013-12-26 16:38:01 +0100806 .dump = nft_meta_set_dump,
Pablo Neira Ayuso4a80e0262022-01-09 17:11:26 +0100807 .reduce = nft_meta_set_reduce,
Liping Zhang960fa722016-08-22 22:57:56 +0800808 .validate = nft_meta_set_validate,
Arturo Borrero Gonzaleze035b772013-12-26 16:38:01 +0100809};
810
811static const struct nft_expr_ops *
812nft_meta_select_ops(const struct nft_ctx *ctx,
813 const struct nlattr * const tb[])
814{
815 if (tb[NFTA_META_KEY] == NULL)
816 return ERR_PTR(-EINVAL);
817
818 if (tb[NFTA_META_DREG] && tb[NFTA_META_SREG])
819 return ERR_PTR(-EINVAL);
820
Arnd Bergmanndfee0e92019-07-10 10:08:20 +0200821#if IS_ENABLED(CONFIG_NF_TABLES_BRIDGE) && IS_MODULE(CONFIG_NFT_BRIDGE_META)
Pablo Neira Ayuso0ef1efd2019-07-05 23:38:54 +0200822 if (ctx->family == NFPROTO_BRIDGE)
823 return ERR_PTR(-EAGAIN);
824#endif
Arturo Borrero Gonzaleze035b772013-12-26 16:38:01 +0100825 if (tb[NFTA_META_DREG])
826 return &nft_meta_get_ops;
827
828 if (tb[NFTA_META_SREG])
829 return &nft_meta_set_ops;
830
831 return ERR_PTR(-EINVAL);
832}
833
Florian Westphal8a225432018-04-16 19:15:54 +0200834struct nft_expr_type nft_meta_type __read_mostly = {
Patrick McHardyef1f7df2013-10-10 11:41:20 +0200835 .name = "meta",
Arushi Singhald4ef3832017-04-02 14:52:12 +0530836 .select_ops = nft_meta_select_ops,
Patrick McHardy96518512013-10-14 11:00:02 +0200837 .policy = nft_meta_policy,
838 .maxattr = NFTA_META_MAX,
Patrick McHardyef1f7df2013-10-10 11:41:20 +0200839 .owner = THIS_MODULE,
Patrick McHardy96518512013-10-14 11:00:02 +0200840};
Christian Göttschefb961942018-09-23 20:26:15 +0200841
842#ifdef CONFIG_NETWORK_SECMARK
843struct nft_secmark {
844 u32 secid;
845 char *ctx;
846};
847
848static const struct nla_policy nft_secmark_policy[NFTA_SECMARK_MAX + 1] = {
849 [NFTA_SECMARK_CTX] = { .type = NLA_STRING, .len = NFT_SECMARK_CTX_MAXLEN },
850};
851
852static int nft_secmark_compute_secid(struct nft_secmark *priv)
853{
854 u32 tmp_secid = 0;
855 int err;
856
857 err = security_secctx_to_secid(priv->ctx, strlen(priv->ctx), &tmp_secid);
858 if (err)
859 return err;
860
861 if (!tmp_secid)
862 return -ENOENT;
863
864 err = security_secmark_relabel_packet(tmp_secid);
865 if (err)
866 return err;
867
868 priv->secid = tmp_secid;
869 return 0;
870}
871
872static void nft_secmark_obj_eval(struct nft_object *obj, struct nft_regs *regs,
873 const struct nft_pktinfo *pkt)
874{
875 const struct nft_secmark *priv = nft_obj_data(obj);
876 struct sk_buff *skb = pkt->skb;
877
878 skb->secmark = priv->secid;
879}
880
881static int nft_secmark_obj_init(const struct nft_ctx *ctx,
882 const struct nlattr * const tb[],
883 struct nft_object *obj)
884{
885 struct nft_secmark *priv = nft_obj_data(obj);
886 int err;
887
888 if (tb[NFTA_SECMARK_CTX] == NULL)
889 return -EINVAL;
890
891 priv->ctx = nla_strdup(tb[NFTA_SECMARK_CTX], GFP_KERNEL);
892 if (!priv->ctx)
893 return -ENOMEM;
894
895 err = nft_secmark_compute_secid(priv);
896 if (err) {
897 kfree(priv->ctx);
898 return err;
899 }
900
901 security_secmark_refcount_inc();
902
903 return 0;
904}
905
906static int nft_secmark_obj_dump(struct sk_buff *skb, struct nft_object *obj,
907 bool reset)
908{
909 struct nft_secmark *priv = nft_obj_data(obj);
910 int err;
911
912 if (nla_put_string(skb, NFTA_SECMARK_CTX, priv->ctx))
913 return -1;
914
915 if (reset) {
916 err = nft_secmark_compute_secid(priv);
917 if (err)
918 return err;
919 }
920
921 return 0;
922}
923
924static void nft_secmark_obj_destroy(const struct nft_ctx *ctx, struct nft_object *obj)
925{
926 struct nft_secmark *priv = nft_obj_data(obj);
927
928 security_secmark_refcount_dec();
929
930 kfree(priv->ctx);
931}
932
933static const struct nft_object_ops nft_secmark_obj_ops = {
934 .type = &nft_secmark_obj_type,
935 .size = sizeof(struct nft_secmark),
936 .init = nft_secmark_obj_init,
937 .eval = nft_secmark_obj_eval,
938 .dump = nft_secmark_obj_dump,
939 .destroy = nft_secmark_obj_destroy,
940};
941struct nft_object_type nft_secmark_obj_type __read_mostly = {
942 .type = NFT_OBJECT_SECMARK,
943 .ops = &nft_secmark_obj_ops,
944 .maxattr = NFTA_SECMARK_MAX,
945 .policy = nft_secmark_policy,
946 .owner = THIS_MODULE,
947};
948#endif /* CONFIG_NETWORK_SECMARK */