xref: /openbmc/linux/net/netfilter/nft_meta.c (revision b30669fd)
1d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
296518518SPatrick McHardy /*
3ef1f7df9SPatrick McHardy  * Copyright (c) 2008-2009 Patrick McHardy <kaber@trash.net>
4bd2bbdb4SFlorian Westphal  * Copyright (c) 2014 Intel Corporation
5bd2bbdb4SFlorian Westphal  * Author: Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com>
696518518SPatrick McHardy  *
796518518SPatrick McHardy  * Development of this code funded by Astaro AG (http://www.astaro.com/)
896518518SPatrick McHardy  */
996518518SPatrick McHardy 
1096518518SPatrick McHardy #include <linux/kernel.h>
1196518518SPatrick McHardy #include <linux/netlink.h>
1296518518SPatrick McHardy #include <linux/netfilter.h>
1396518518SPatrick McHardy #include <linux/netfilter/nf_tables.h>
14e2a093ffSAna Rey #include <linux/in.h>
15e2a093ffSAna Rey #include <linux/ip.h>
16e2a093ffSAna Rey #include <linux/ipv6.h>
17b1fd94e7SFlorian Westphal #include <linux/random.h>
18afc5be30SAna Rey #include <linux/smp.h>
19e639f7abSFlorian Westphal #include <linux/static_key.h>
2096518518SPatrick McHardy #include <net/dst.h>
21c14ceb0eSFlorian Westphal #include <net/ip.h>
2296518518SPatrick McHardy #include <net/sock.h>
2396518518SPatrick McHardy #include <net/tcp_states.h> /* for TCP_TIME_WAIT */
2496518518SPatrick McHardy #include <net/netfilter/nf_tables.h>
25e639f7abSFlorian Westphal #include <net/netfilter/nf_tables_core.h>
2630e103feSwenxu #include <net/netfilter/nft_meta.h>
27c9626a2cSPablo Neira Ayuso #include <net/netfilter/nf_tables_offload.h>
2896518518SPatrick McHardy 
29b4aae759SFlorian Westphal #include <uapi/linux/netfilter_bridge.h> /* NF_BR_PRE_ROUTING */
30b4aae759SFlorian Westphal 
3163d10e12SAnder Juaristi #define NFT_META_SECS_PER_MINUTE	60
3263d10e12SAnder Juaristi #define NFT_META_SECS_PER_HOUR		3600
3363d10e12SAnder Juaristi #define NFT_META_SECS_PER_DAY		86400
3463d10e12SAnder Juaristi #define NFT_META_DAYS_PER_WEEK		7
3563d10e12SAnder Juaristi 
nft_meta_weekday(void)36db8f6f5cSFlorian Westphal static u8 nft_meta_weekday(void)
3763d10e12SAnder Juaristi {
38db8f6f5cSFlorian Westphal 	time64_t secs = ktime_get_real_seconds();
3963d10e12SAnder Juaristi 	unsigned int dse;
4063d10e12SAnder Juaristi 	u8 wday;
4163d10e12SAnder Juaristi 
4263d10e12SAnder Juaristi 	secs -= NFT_META_SECS_PER_MINUTE * sys_tz.tz_minuteswest;
436408c40cSArnd Bergmann 	dse = div_u64(secs, NFT_META_SECS_PER_DAY);
4463d10e12SAnder Juaristi 	wday = (4 + dse) % NFT_META_DAYS_PER_WEEK;
4563d10e12SAnder Juaristi 
4663d10e12SAnder Juaristi 	return wday;
4763d10e12SAnder Juaristi }
4863d10e12SAnder Juaristi 
nft_meta_hour(time64_t secs)496408c40cSArnd Bergmann static u32 nft_meta_hour(time64_t secs)
5063d10e12SAnder Juaristi {
5163d10e12SAnder Juaristi 	struct tm tm;
5263d10e12SAnder Juaristi 
5363d10e12SAnder Juaristi 	time64_to_tm(secs, 0, &tm);
5463d10e12SAnder Juaristi 
5563d10e12SAnder Juaristi 	return tm.tm_hour * NFT_META_SECS_PER_HOUR
5663d10e12SAnder Juaristi 		+ tm.tm_min * NFT_META_SECS_PER_MINUTE
5763d10e12SAnder Juaristi 		+ tm.tm_sec;
5863d10e12SAnder Juaristi }
5963d10e12SAnder Juaristi 
60db8f6f5cSFlorian Westphal static noinline_for_stack void
nft_meta_get_eval_time(enum nft_meta_keys key,u32 * dest)61db8f6f5cSFlorian Westphal nft_meta_get_eval_time(enum nft_meta_keys key,
62db8f6f5cSFlorian Westphal 		       u32 *dest)
63db8f6f5cSFlorian Westphal {
64db8f6f5cSFlorian Westphal 	switch (key) {
65db8f6f5cSFlorian Westphal 	case NFT_META_TIME_NS:
66013deed3SDan Carpenter 		nft_reg_store64((u64 *)dest, ktime_get_real_ns());
67db8f6f5cSFlorian Westphal 		break;
68db8f6f5cSFlorian Westphal 	case NFT_META_TIME_DAY:
69db8f6f5cSFlorian Westphal 		nft_reg_store8(dest, nft_meta_weekday());
70db8f6f5cSFlorian Westphal 		break;
71db8f6f5cSFlorian Westphal 	case NFT_META_TIME_HOUR:
72db8f6f5cSFlorian Westphal 		*dest = nft_meta_hour(ktime_get_real_seconds());
73db8f6f5cSFlorian Westphal 		break;
74db8f6f5cSFlorian Westphal 	default:
75db8f6f5cSFlorian Westphal 		break;
76db8f6f5cSFlorian Westphal 	}
77db8f6f5cSFlorian Westphal }
78db8f6f5cSFlorian Westphal 
794a54594aSFlorian Westphal static noinline bool
nft_meta_get_eval_pkttype_lo(const struct nft_pktinfo * pkt,u32 * dest)804a54594aSFlorian Westphal nft_meta_get_eval_pkttype_lo(const struct nft_pktinfo *pkt,
814a54594aSFlorian Westphal 			     u32 *dest)
824a54594aSFlorian Westphal {
834a54594aSFlorian Westphal 	const struct sk_buff *skb = pkt->skb;
844a54594aSFlorian Westphal 
854a54594aSFlorian Westphal 	switch (nft_pf(pkt)) {
864a54594aSFlorian Westphal 	case NFPROTO_IPV4:
874a54594aSFlorian Westphal 		if (ipv4_is_multicast(ip_hdr(skb)->daddr))
884a54594aSFlorian Westphal 			nft_reg_store8(dest, PACKET_MULTICAST);
894a54594aSFlorian Westphal 		else
904a54594aSFlorian Westphal 			nft_reg_store8(dest, PACKET_BROADCAST);
914a54594aSFlorian Westphal 		break;
924a54594aSFlorian Westphal 	case NFPROTO_IPV6:
934a54594aSFlorian Westphal 		nft_reg_store8(dest, PACKET_MULTICAST);
944a54594aSFlorian Westphal 		break;
954a54594aSFlorian Westphal 	case NFPROTO_NETDEV:
964a54594aSFlorian Westphal 		switch (skb->protocol) {
974a54594aSFlorian Westphal 		case htons(ETH_P_IP): {
984a54594aSFlorian Westphal 			int noff = skb_network_offset(skb);
994a54594aSFlorian Westphal 			struct iphdr *iph, _iph;
1004a54594aSFlorian Westphal 
1014a54594aSFlorian Westphal 			iph = skb_header_pointer(skb, noff,
1024a54594aSFlorian Westphal 						 sizeof(_iph), &_iph);
1034a54594aSFlorian Westphal 			if (!iph)
1044a54594aSFlorian Westphal 				return false;
1054a54594aSFlorian Westphal 
1064a54594aSFlorian Westphal 			if (ipv4_is_multicast(iph->daddr))
1074a54594aSFlorian Westphal 				nft_reg_store8(dest, PACKET_MULTICAST);
1084a54594aSFlorian Westphal 			else
1094a54594aSFlorian Westphal 				nft_reg_store8(dest, PACKET_BROADCAST);
1104a54594aSFlorian Westphal 
1114a54594aSFlorian Westphal 			break;
1124a54594aSFlorian Westphal 		}
1134a54594aSFlorian Westphal 		case htons(ETH_P_IPV6):
1144a54594aSFlorian Westphal 			nft_reg_store8(dest, PACKET_MULTICAST);
1154a54594aSFlorian Westphal 			break;
1164a54594aSFlorian Westphal 		default:
1174a54594aSFlorian Westphal 			WARN_ON_ONCE(1);
1184a54594aSFlorian Westphal 			return false;
1194a54594aSFlorian Westphal 		}
1204a54594aSFlorian Westphal 		break;
1214a54594aSFlorian Westphal 	default:
1224a54594aSFlorian Westphal 		WARN_ON_ONCE(1);
1234a54594aSFlorian Westphal 		return false;
1244a54594aSFlorian Westphal 	}
1254a54594aSFlorian Westphal 
1264a54594aSFlorian Westphal 	return true;
1274a54594aSFlorian Westphal }
1284a54594aSFlorian Westphal 
129726b44f0SFlorian Westphal static noinline bool
nft_meta_get_eval_skugid(enum nft_meta_keys key,u32 * dest,const struct nft_pktinfo * pkt)130726b44f0SFlorian Westphal nft_meta_get_eval_skugid(enum nft_meta_keys key,
131726b44f0SFlorian Westphal 			 u32 *dest,
132726b44f0SFlorian Westphal 			 const struct nft_pktinfo *pkt)
133726b44f0SFlorian Westphal {
134726b44f0SFlorian Westphal 	struct sock *sk = skb_to_full_sk(pkt->skb);
135726b44f0SFlorian Westphal 	struct socket *sock;
136726b44f0SFlorian Westphal 
137726b44f0SFlorian Westphal 	if (!sk || !sk_fullsock(sk) || !net_eq(nft_net(pkt), sock_net(sk)))
138726b44f0SFlorian Westphal 		return false;
139726b44f0SFlorian Westphal 
140726b44f0SFlorian Westphal 	read_lock_bh(&sk->sk_callback_lock);
141726b44f0SFlorian Westphal 	sock = sk->sk_socket;
142726b44f0SFlorian Westphal 	if (!sock || !sock->file) {
143726b44f0SFlorian Westphal 		read_unlock_bh(&sk->sk_callback_lock);
144726b44f0SFlorian Westphal 		return false;
145726b44f0SFlorian Westphal 	}
146726b44f0SFlorian Westphal 
147726b44f0SFlorian Westphal 	switch (key) {
148726b44f0SFlorian Westphal 	case NFT_META_SKUID:
1490c92411bSPablo Neira Ayuso 		*dest = from_kuid_munged(sock_net(sk)->user_ns,
150726b44f0SFlorian Westphal 					 sock->file->f_cred->fsuid);
151726b44f0SFlorian Westphal 		break;
152726b44f0SFlorian Westphal 	case NFT_META_SKGID:
1530c92411bSPablo Neira Ayuso 		*dest =	from_kgid_munged(sock_net(sk)->user_ns,
154726b44f0SFlorian Westphal 					 sock->file->f_cred->fsgid);
155726b44f0SFlorian Westphal 		break;
156726b44f0SFlorian Westphal 	default:
157726b44f0SFlorian Westphal 		break;
158726b44f0SFlorian Westphal 	}
159726b44f0SFlorian Westphal 
160726b44f0SFlorian Westphal 	read_unlock_bh(&sk->sk_callback_lock);
161726b44f0SFlorian Westphal 	return true;
162726b44f0SFlorian Westphal }
163726b44f0SFlorian Westphal 
164b1327fbcSFlorian Westphal #ifdef CONFIG_CGROUP_NET_CLASSID
165b1327fbcSFlorian Westphal static noinline bool
nft_meta_get_eval_cgroup(u32 * dest,const struct nft_pktinfo * pkt)166b1327fbcSFlorian Westphal nft_meta_get_eval_cgroup(u32 *dest, const struct nft_pktinfo *pkt)
167b1327fbcSFlorian Westphal {
168b1327fbcSFlorian Westphal 	struct sock *sk = skb_to_full_sk(pkt->skb);
169b1327fbcSFlorian Westphal 
170b1327fbcSFlorian Westphal 	if (!sk || !sk_fullsock(sk) || !net_eq(nft_net(pkt), sock_net(sk)))
171b1327fbcSFlorian Westphal 		return false;
172b1327fbcSFlorian Westphal 
173b1327fbcSFlorian Westphal 	*dest = sock_cgroup_classid(&sk->sk_cgrp_data);
174b1327fbcSFlorian Westphal 	return true;
175b1327fbcSFlorian Westphal }
176b1327fbcSFlorian Westphal #endif
177b1327fbcSFlorian Westphal 
nft_meta_get_eval_kind(enum nft_meta_keys key,u32 * dest,const struct nft_pktinfo * pkt)178a4150a1fSFlorian Westphal static noinline bool nft_meta_get_eval_kind(enum nft_meta_keys key,
179a4150a1fSFlorian Westphal 					    u32 *dest,
180a4150a1fSFlorian Westphal 					    const struct nft_pktinfo *pkt)
181a4150a1fSFlorian Westphal {
182a4150a1fSFlorian Westphal 	const struct net_device *in = nft_in(pkt), *out = nft_out(pkt);
183a4150a1fSFlorian Westphal 
184a4150a1fSFlorian Westphal 	switch (key) {
185a4150a1fSFlorian Westphal 	case NFT_META_IIFKIND:
186a4150a1fSFlorian Westphal 		if (!in || !in->rtnl_link_ops)
187a4150a1fSFlorian Westphal 			return false;
188ad156c23SJustin Stitt 		strscpy_pad((char *)dest, in->rtnl_link_ops->kind, IFNAMSIZ);
189a4150a1fSFlorian Westphal 		break;
190a4150a1fSFlorian Westphal 	case NFT_META_OIFKIND:
191a4150a1fSFlorian Westphal 		if (!out || !out->rtnl_link_ops)
192a4150a1fSFlorian Westphal 			return false;
193ad156c23SJustin Stitt 		strscpy_pad((char *)dest, out->rtnl_link_ops->kind, IFNAMSIZ);
194a4150a1fSFlorian Westphal 		break;
195a4150a1fSFlorian Westphal 	default:
196a4150a1fSFlorian Westphal 		return false;
197a4150a1fSFlorian Westphal 	}
198a4150a1fSFlorian Westphal 
199a4150a1fSFlorian Westphal 	return true;
200a4150a1fSFlorian Westphal }
201a4150a1fSFlorian Westphal 
nft_meta_store_ifindex(u32 * dest,const struct net_device * dev)2028724e819SFlorian Westphal static void nft_meta_store_ifindex(u32 *dest, const struct net_device *dev)
2038724e819SFlorian Westphal {
2048724e819SFlorian Westphal 	*dest = dev ? dev->ifindex : 0;
2058724e819SFlorian Westphal }
2068724e819SFlorian Westphal 
nft_meta_store_ifname(u32 * dest,const struct net_device * dev)2078724e819SFlorian Westphal static void nft_meta_store_ifname(u32 *dest, const struct net_device *dev)
2088724e819SFlorian Westphal {
209ad156c23SJustin Stitt 	strscpy_pad((char *)dest, dev ? dev->name : "", IFNAMSIZ);
2108724e819SFlorian Westphal }
2118724e819SFlorian Westphal 
nft_meta_store_iftype(u32 * dest,const struct net_device * dev)2128724e819SFlorian Westphal static bool nft_meta_store_iftype(u32 *dest, const struct net_device *dev)
2138724e819SFlorian Westphal {
2148724e819SFlorian Westphal 	if (!dev)
2158724e819SFlorian Westphal 		return false;
2168724e819SFlorian Westphal 
2178724e819SFlorian Westphal 	nft_reg_store16(dest, dev->type);
2188724e819SFlorian Westphal 	return true;
2198724e819SFlorian Westphal }
2208724e819SFlorian Westphal 
nft_meta_store_ifgroup(u32 * dest,const struct net_device * dev)2218724e819SFlorian Westphal static bool nft_meta_store_ifgroup(u32 *dest, const struct net_device *dev)
2228724e819SFlorian Westphal {
2238724e819SFlorian Westphal 	if (!dev)
2248724e819SFlorian Westphal 		return false;
2258724e819SFlorian Westphal 
2268724e819SFlorian Westphal 	*dest = dev->group;
2278724e819SFlorian Westphal 	return true;
2288724e819SFlorian Westphal }
2298724e819SFlorian Westphal 
nft_meta_get_eval_ifname(enum nft_meta_keys key,u32 * dest,const struct nft_pktinfo * pkt)2308724e819SFlorian Westphal static bool nft_meta_get_eval_ifname(enum nft_meta_keys key, u32 *dest,
2318724e819SFlorian Westphal 				     const struct nft_pktinfo *pkt)
2328724e819SFlorian Westphal {
2338724e819SFlorian Westphal 	switch (key) {
2348724e819SFlorian Westphal 	case NFT_META_IIFNAME:
2358724e819SFlorian Westphal 		nft_meta_store_ifname(dest, nft_in(pkt));
2368724e819SFlorian Westphal 		break;
2378724e819SFlorian Westphal 	case NFT_META_OIFNAME:
2388724e819SFlorian Westphal 		nft_meta_store_ifname(dest, nft_out(pkt));
2398724e819SFlorian Westphal 		break;
2408724e819SFlorian Westphal 	case NFT_META_IIF:
2418724e819SFlorian Westphal 		nft_meta_store_ifindex(dest, nft_in(pkt));
2428724e819SFlorian Westphal 		break;
2438724e819SFlorian Westphal 	case NFT_META_OIF:
2448724e819SFlorian Westphal 		nft_meta_store_ifindex(dest, nft_out(pkt));
2458724e819SFlorian Westphal 		break;
24656fa9501SPablo Neira Ayuso 	case NFT_META_IFTYPE:
24756fa9501SPablo Neira Ayuso 		if (!nft_meta_store_iftype(dest, pkt->skb->dev))
24856fa9501SPablo Neira Ayuso 			return false;
24956fa9501SPablo Neira Ayuso 		break;
25056fa9501SPablo Neira Ayuso 	case __NFT_META_IIFTYPE:
2518724e819SFlorian Westphal 		if (!nft_meta_store_iftype(dest, nft_in(pkt)))
2528724e819SFlorian Westphal 			return false;
2538724e819SFlorian Westphal 		break;
2548724e819SFlorian Westphal 	case NFT_META_OIFTYPE:
2558724e819SFlorian Westphal 		if (!nft_meta_store_iftype(dest, nft_out(pkt)))
2568724e819SFlorian Westphal 			return false;
2578724e819SFlorian Westphal 		break;
2588724e819SFlorian Westphal 	case NFT_META_IIFGROUP:
25978470d9dSFlorian Westphal 		if (!nft_meta_store_ifgroup(dest, nft_in(pkt)))
2608724e819SFlorian Westphal 			return false;
2618724e819SFlorian Westphal 		break;
2628724e819SFlorian Westphal 	case NFT_META_OIFGROUP:
2638724e819SFlorian Westphal 		if (!nft_meta_store_ifgroup(dest, nft_out(pkt)))
2648724e819SFlorian Westphal 			return false;
2658724e819SFlorian Westphal 		break;
2668724e819SFlorian Westphal 	default:
2678724e819SFlorian Westphal 		return false;
2688724e819SFlorian Westphal 	}
2698724e819SFlorian Westphal 
2708724e819SFlorian Westphal 	return true;
2718724e819SFlorian Westphal }
2728724e819SFlorian Westphal 
27301a0fc82SFlorian Westphal #ifdef CONFIG_IP_ROUTE_CLASSID
27401a0fc82SFlorian Westphal static noinline bool
nft_meta_get_eval_rtclassid(const struct sk_buff * skb,u32 * dest)27501a0fc82SFlorian Westphal nft_meta_get_eval_rtclassid(const struct sk_buff *skb, u32 *dest)
27601a0fc82SFlorian Westphal {
27701a0fc82SFlorian Westphal 	const struct dst_entry *dst = skb_dst(skb);
27801a0fc82SFlorian Westphal 
27901a0fc82SFlorian Westphal 	if (!dst)
28001a0fc82SFlorian Westphal 		return false;
28101a0fc82SFlorian Westphal 
28201a0fc82SFlorian Westphal 	*dest = dst->tclassid;
28301a0fc82SFlorian Westphal 	return true;
28401a0fc82SFlorian Westphal }
28501a0fc82SFlorian Westphal #endif
28601a0fc82SFlorian Westphal 
nft_meta_get_eval_sdif(const struct nft_pktinfo * pkt)287c14ceb0eSFlorian Westphal static noinline u32 nft_meta_get_eval_sdif(const struct nft_pktinfo *pkt)
288c14ceb0eSFlorian Westphal {
289c14ceb0eSFlorian Westphal 	switch (nft_pf(pkt)) {
290c14ceb0eSFlorian Westphal 	case NFPROTO_IPV4:
291c14ceb0eSFlorian Westphal 		return inet_sdif(pkt->skb);
292c14ceb0eSFlorian Westphal 	case NFPROTO_IPV6:
293c14ceb0eSFlorian Westphal 		return inet6_sdif(pkt->skb);
294c14ceb0eSFlorian Westphal 	}
295c14ceb0eSFlorian Westphal 
296c14ceb0eSFlorian Westphal 	return 0;
297c14ceb0eSFlorian Westphal }
298c14ceb0eSFlorian Westphal 
299c14ceb0eSFlorian Westphal static noinline void
nft_meta_get_eval_sdifname(u32 * dest,const struct nft_pktinfo * pkt)300c14ceb0eSFlorian Westphal nft_meta_get_eval_sdifname(u32 *dest, const struct nft_pktinfo *pkt)
301c14ceb0eSFlorian Westphal {
302c14ceb0eSFlorian Westphal 	u32 sdif = nft_meta_get_eval_sdif(pkt);
303c14ceb0eSFlorian Westphal 	const struct net_device *dev;
304c14ceb0eSFlorian Westphal 
305c14ceb0eSFlorian Westphal 	dev = sdif ? dev_get_by_index_rcu(nft_net(pkt), sdif) : NULL;
306c14ceb0eSFlorian Westphal 	nft_meta_store_ifname(dest, dev);
307c14ceb0eSFlorian Westphal }
308c14ceb0eSFlorian Westphal 
nft_meta_get_eval(const struct nft_expr * expr,struct nft_regs * regs,const struct nft_pktinfo * pkt)309222440b4SFlorian Westphal void nft_meta_get_eval(const struct nft_expr *expr,
310a55e22e9SPatrick McHardy 		       struct nft_regs *regs,
31196518518SPatrick McHardy 		       const struct nft_pktinfo *pkt)
31296518518SPatrick McHardy {
31396518518SPatrick McHardy 	const struct nft_meta *priv = nft_expr_priv(expr);
31496518518SPatrick McHardy 	const struct sk_buff *skb = pkt->skb;
31549499c3eSPatrick McHardy 	u32 *dest = &regs->data[priv->dreg];
31696518518SPatrick McHardy 
31796518518SPatrick McHardy 	switch (priv->key) {
31896518518SPatrick McHardy 	case NFT_META_LEN:
319fad136eaSPatrick McHardy 		*dest = skb->len;
32096518518SPatrick McHardy 		break;
32196518518SPatrick McHardy 	case NFT_META_PROTOCOL:
32210596608SLiping Zhang 		nft_reg_store16(dest, (__force u16)skb->protocol);
32396518518SPatrick McHardy 		break;
324124edfa9SPatrick McHardy 	case NFT_META_NFPROTO:
32510596608SLiping Zhang 		nft_reg_store8(dest, nft_pf(pkt));
326124edfa9SPatrick McHardy 		break;
3274566bf27SPatrick McHardy 	case NFT_META_L4PROTO:
328b5bdc6f9SPablo Neira Ayuso 		if (!(pkt->flags & NFT_PKTINFO_L4PROTO))
329beac5afaSPablo Neira Ayuso 			goto err;
33010596608SLiping Zhang 		nft_reg_store8(dest, pkt->tprot);
3314566bf27SPatrick McHardy 		break;
33296518518SPatrick McHardy 	case NFT_META_PRIORITY:
333fad136eaSPatrick McHardy 		*dest = skb->priority;
33496518518SPatrick McHardy 		break;
33596518518SPatrick McHardy 	case NFT_META_MARK:
336fad136eaSPatrick McHardy 		*dest = skb->mark;
33796518518SPatrick McHardy 		break;
33896518518SPatrick McHardy 	case NFT_META_IIF:
33996518518SPatrick McHardy 	case NFT_META_OIF:
34096518518SPatrick McHardy 	case NFT_META_IIFNAME:
34196518518SPatrick McHardy 	case NFT_META_OIFNAME:
34296518518SPatrick McHardy 	case NFT_META_IIFTYPE:
34396518518SPatrick McHardy 	case NFT_META_OIFTYPE:
3448724e819SFlorian Westphal 	case NFT_META_IIFGROUP:
3458724e819SFlorian Westphal 	case NFT_META_OIFGROUP:
3468724e819SFlorian Westphal 		if (!nft_meta_get_eval_ifname(priv->key, dest, pkt))
34796518518SPatrick McHardy 			goto err;
34896518518SPatrick McHardy 		break;
34996518518SPatrick McHardy 	case NFT_META_SKUID:
35096518518SPatrick McHardy 	case NFT_META_SKGID:
351726b44f0SFlorian Westphal 		if (!nft_meta_get_eval_skugid(priv->key, dest, pkt))
35296518518SPatrick McHardy 			goto err;
35396518518SPatrick McHardy 		break;
35406efbd6dSPaul Bolle #ifdef CONFIG_IP_ROUTE_CLASSID
35501a0fc82SFlorian Westphal 	case NFT_META_RTCLASSID:
35601a0fc82SFlorian Westphal 		if (!nft_meta_get_eval_rtclassid(skb, dest))
35796518518SPatrick McHardy 			goto err;
35896518518SPatrick McHardy 		break;
35996518518SPatrick McHardy #endif
36096518518SPatrick McHardy #ifdef CONFIG_NETWORK_SECMARK
36196518518SPatrick McHardy 	case NFT_META_SECMARK:
362fad136eaSPatrick McHardy 		*dest = skb->secmark;
36396518518SPatrick McHardy 		break;
36496518518SPatrick McHardy #endif
365e2a093ffSAna Rey 	case NFT_META_PKTTYPE:
366e2a093ffSAna Rey 		if (skb->pkt_type != PACKET_LOOPBACK) {
36710596608SLiping Zhang 			nft_reg_store8(dest, skb->pkt_type);
368e2a093ffSAna Rey 			break;
369e2a093ffSAna Rey 		}
370e2a093ffSAna Rey 
3714a54594aSFlorian Westphal 		if (!nft_meta_get_eval_pkttype_lo(pkt, dest))
372f169fd69SLiping Zhang 			goto err;
373e2a093ffSAna Rey 		break;
374afc5be30SAna Rey 	case NFT_META_CPU:
375fad136eaSPatrick McHardy 		*dest = raw_smp_processor_id();
376afc5be30SAna Rey 		break;
377e181a543SMathias Krause #ifdef CONFIG_CGROUP_NET_CLASSID
378ce674173SAna Rey 	case NFT_META_CGROUP:
379b1327fbcSFlorian Westphal 		if (!nft_meta_get_eval_cgroup(dest, pkt))
380c5035c77SPablo Neira Ayuso 			goto err;
381ce674173SAna Rey 		break;
382e181a543SMathias Krause #endif
3836b2faee0SFlorian Westphal 	case NFT_META_PRANDOM:
384b1fd94e7SFlorian Westphal 		*dest = get_random_u32();
385b07edbe1SFlorian Westphal 		break;
386f6931f5fSFlorian Westphal #ifdef CONFIG_XFRM
387f6931f5fSFlorian Westphal 	case NFT_META_SECPATH:
3887af8f4caSFlorian Westphal 		nft_reg_store8(dest, secpath_exists(skb));
389f6931f5fSFlorian Westphal 		break;
390f6931f5fSFlorian Westphal #endif
3910fb4d219Swenxu 	case NFT_META_IIFKIND:
3920fb4d219Swenxu 	case NFT_META_OIFKIND:
393a4150a1fSFlorian Westphal 		if (!nft_meta_get_eval_kind(priv->key, dest, pkt))
3940fb4d219Swenxu 			goto err;
3950fb4d219Swenxu 		break;
39663d10e12SAnder Juaristi 	case NFT_META_TIME_NS:
39763d10e12SAnder Juaristi 	case NFT_META_TIME_DAY:
39863d10e12SAnder Juaristi 	case NFT_META_TIME_HOUR:
399db8f6f5cSFlorian Westphal 		nft_meta_get_eval_time(priv->key, dest);
40063d10e12SAnder Juaristi 		break;
401c14ceb0eSFlorian Westphal 	case NFT_META_SDIF:
402c14ceb0eSFlorian Westphal 		*dest = nft_meta_get_eval_sdif(pkt);
403c14ceb0eSFlorian Westphal 		break;
404c14ceb0eSFlorian Westphal 	case NFT_META_SDIFNAME:
405c14ceb0eSFlorian Westphal 		nft_meta_get_eval_sdifname(dest, pkt);
406c14ceb0eSFlorian Westphal 		break;
40796518518SPatrick McHardy 	default:
40896518518SPatrick McHardy 		WARN_ON(1);
40996518518SPatrick McHardy 		goto err;
41096518518SPatrick McHardy 	}
41196518518SPatrick McHardy 	return;
41296518518SPatrick McHardy 
41396518518SPatrick McHardy err:
414a55e22e9SPatrick McHardy 	regs->verdict.code = NFT_BREAK;
41596518518SPatrick McHardy }
41630e103feSwenxu EXPORT_SYMBOL_GPL(nft_meta_get_eval);
41796518518SPatrick McHardy 
nft_meta_set_eval(const struct nft_expr * expr,struct nft_regs * regs,const struct nft_pktinfo * pkt)41830e103feSwenxu void nft_meta_set_eval(const struct nft_expr *expr,
419a55e22e9SPatrick McHardy 		       struct nft_regs *regs,
420e035b77aSArturo Borrero Gonzalez 		       const struct nft_pktinfo *pkt)
421e035b77aSArturo Borrero Gonzalez {
422e035b77aSArturo Borrero Gonzalez 	const struct nft_meta *meta = nft_expr_priv(expr);
423e035b77aSArturo Borrero Gonzalez 	struct sk_buff *skb = pkt->skb;
42410596608SLiping Zhang 	u32 *sreg = &regs->data[meta->sreg];
42510596608SLiping Zhang 	u32 value = *sreg;
42697a0549bSTaehee Yoo 	u8 value8;
427e035b77aSArturo Borrero Gonzalez 
428e035b77aSArturo Borrero Gonzalez 	switch (meta->key) {
429e035b77aSArturo Borrero Gonzalez 	case NFT_META_MARK:
430e035b77aSArturo Borrero Gonzalez 		skb->mark = value;
431e035b77aSArturo Borrero Gonzalez 		break;
432e035b77aSArturo Borrero Gonzalez 	case NFT_META_PRIORITY:
433e035b77aSArturo Borrero Gonzalez 		skb->priority = value;
434e035b77aSArturo Borrero Gonzalez 		break;
435b4aae759SFlorian Westphal 	case NFT_META_PKTTYPE:
43697a0549bSTaehee Yoo 		value8 = nft_reg_load8(sreg);
43710596608SLiping Zhang 
43897a0549bSTaehee Yoo 		if (skb->pkt_type != value8 &&
43997a0549bSTaehee Yoo 		    skb_pkt_type_ok(value8) &&
44010596608SLiping Zhang 		    skb_pkt_type_ok(skb->pkt_type))
44197a0549bSTaehee Yoo 			skb->pkt_type = value8;
442b4aae759SFlorian Westphal 		break;
443e035b77aSArturo Borrero Gonzalez 	case NFT_META_NFTRACE:
44497a0549bSTaehee Yoo 		value8 = nft_reg_load8(sreg);
44597a0549bSTaehee Yoo 
44697a0549bSTaehee Yoo 		skb->nf_trace = !!value8;
447e035b77aSArturo Borrero Gonzalez 		break;
448b473a1f5SChristian Göttsche #ifdef CONFIG_NETWORK_SECMARK
449b473a1f5SChristian Göttsche 	case NFT_META_SECMARK:
450b473a1f5SChristian Göttsche 		skb->secmark = value;
451b473a1f5SChristian Göttsche 		break;
452b473a1f5SChristian Göttsche #endif
453e035b77aSArturo Borrero Gonzalez 	default:
454e035b77aSArturo Borrero Gonzalez 		WARN_ON(1);
455e035b77aSArturo Borrero Gonzalez 	}
456e035b77aSArturo Borrero Gonzalez }
45730e103feSwenxu EXPORT_SYMBOL_GPL(nft_meta_set_eval);
458e035b77aSArturo Borrero Gonzalez 
45930e103feSwenxu const struct nla_policy nft_meta_policy[NFTA_META_MAX + 1] = {
46096518518SPatrick McHardy 	[NFTA_META_DREG]	= { .type = NLA_U32 },
461a412dbf4SFlorian Westphal 	[NFTA_META_KEY]		= NLA_POLICY_MAX(NLA_BE32, 255),
462e035b77aSArturo Borrero Gonzalez 	[NFTA_META_SREG]	= { .type = NLA_U32 },
46396518518SPatrick McHardy };
46430e103feSwenxu EXPORT_SYMBOL_GPL(nft_meta_policy);
46596518518SPatrick McHardy 
nft_meta_get_init(const struct nft_ctx * ctx,const struct nft_expr * expr,const struct nlattr * const tb[])46630e103feSwenxu int nft_meta_get_init(const struct nft_ctx *ctx,
467d2caa696SPatrick McHardy 		      const struct nft_expr *expr,
468d2caa696SPatrick McHardy 		      const struct nlattr * const tb[])
46996518518SPatrick McHardy {
470d2caa696SPatrick McHardy 	struct nft_meta *priv = nft_expr_priv(expr);
47145d9bcdaSPatrick McHardy 	unsigned int len;
47296518518SPatrick McHardy 
473d2caa696SPatrick McHardy 	priv->key = ntohl(nla_get_be32(tb[NFTA_META_KEY]));
474d2caa696SPatrick McHardy 	switch (priv->key) {
47596518518SPatrick McHardy 	case NFT_META_PROTOCOL:
47645d9bcdaSPatrick McHardy 	case NFT_META_IIFTYPE:
47745d9bcdaSPatrick McHardy 	case NFT_META_OIFTYPE:
47845d9bcdaSPatrick McHardy 		len = sizeof(u16);
47945d9bcdaSPatrick McHardy 		break;
480124edfa9SPatrick McHardy 	case NFT_META_NFPROTO:
4814566bf27SPatrick McHardy 	case NFT_META_L4PROTO:
48245d9bcdaSPatrick McHardy 	case NFT_META_LEN:
48396518518SPatrick McHardy 	case NFT_META_PRIORITY:
48496518518SPatrick McHardy 	case NFT_META_MARK:
48596518518SPatrick McHardy 	case NFT_META_IIF:
48696518518SPatrick McHardy 	case NFT_META_OIF:
487c14ceb0eSFlorian Westphal 	case NFT_META_SDIF:
48896518518SPatrick McHardy 	case NFT_META_SKUID:
48996518518SPatrick McHardy 	case NFT_META_SKGID:
49006efbd6dSPaul Bolle #ifdef CONFIG_IP_ROUTE_CLASSID
49196518518SPatrick McHardy 	case NFT_META_RTCLASSID:
49296518518SPatrick McHardy #endif
49396518518SPatrick McHardy #ifdef CONFIG_NETWORK_SECMARK
49496518518SPatrick McHardy 	case NFT_META_SECMARK:
49596518518SPatrick McHardy #endif
496e2a093ffSAna Rey 	case NFT_META_PKTTYPE:
497afc5be30SAna Rey 	case NFT_META_CPU:
4983045d760SAna Rey 	case NFT_META_IIFGROUP:
4993045d760SAna Rey 	case NFT_META_OIFGROUP:
500e181a543SMathias Krause #ifdef CONFIG_CGROUP_NET_CLASSID
501ce674173SAna Rey 	case NFT_META_CGROUP:
502e181a543SMathias Krause #endif
50345d9bcdaSPatrick McHardy 		len = sizeof(u32);
50445d9bcdaSPatrick McHardy 		break;
50545d9bcdaSPatrick McHardy 	case NFT_META_IIFNAME:
50645d9bcdaSPatrick McHardy 	case NFT_META_OIFNAME:
5070fb4d219Swenxu 	case NFT_META_IIFKIND:
5080fb4d219Swenxu 	case NFT_META_OIFKIND:
509c14ceb0eSFlorian Westphal 	case NFT_META_SDIFNAME:
51045d9bcdaSPatrick McHardy 		len = IFNAMSIZ;
511d2caa696SPatrick McHardy 		break;
512b07edbe1SFlorian Westphal 	case NFT_META_PRANDOM:
513b07edbe1SFlorian Westphal 		len = sizeof(u32);
514b07edbe1SFlorian Westphal 		break;
515f6931f5fSFlorian Westphal #ifdef CONFIG_XFRM
516f6931f5fSFlorian Westphal 	case NFT_META_SECPATH:
517f6931f5fSFlorian Westphal 		len = sizeof(u8);
518f6931f5fSFlorian Westphal 		break;
519f6931f5fSFlorian Westphal #endif
52063d10e12SAnder Juaristi 	case NFT_META_TIME_NS:
52163d10e12SAnder Juaristi 		len = sizeof(u64);
52263d10e12SAnder Juaristi 		break;
52363d10e12SAnder Juaristi 	case NFT_META_TIME_DAY:
52463d10e12SAnder Juaristi 		len = sizeof(u8);
52563d10e12SAnder Juaristi 		break;
52663d10e12SAnder Juaristi 	case NFT_META_TIME_HOUR:
52763d10e12SAnder Juaristi 		len = sizeof(u32);
52863d10e12SAnder Juaristi 		break;
52996518518SPatrick McHardy 	default:
53096518518SPatrick McHardy 		return -EOPNOTSUPP;
53196518518SPatrick McHardy 	}
53296518518SPatrick McHardy 
53334cc9e52SPablo Neira Ayuso 	priv->len = len;
534345023b0SPablo Neira Ayuso 	return nft_parse_register_store(ctx, tb[NFTA_META_DREG], &priv->dreg,
535345023b0SPablo Neira Ayuso 					NULL, NFT_DATA_VALUE, len);
536d2caa696SPatrick McHardy }
53730e103feSwenxu EXPORT_SYMBOL_GPL(nft_meta_get_init);
538d2caa696SPatrick McHardy 
nft_meta_get_validate_sdif(const struct nft_ctx * ctx)539c14ceb0eSFlorian Westphal static int nft_meta_get_validate_sdif(const struct nft_ctx *ctx)
540f6931f5fSFlorian Westphal {
541f6931f5fSFlorian Westphal 	unsigned int hooks;
542f6931f5fSFlorian Westphal 
543c14ceb0eSFlorian Westphal 	switch (ctx->family) {
544c14ceb0eSFlorian Westphal 	case NFPROTO_IPV4:
545c14ceb0eSFlorian Westphal 	case NFPROTO_IPV6:
546c14ceb0eSFlorian Westphal 	case NFPROTO_INET:
547c14ceb0eSFlorian Westphal 		hooks = (1 << NF_INET_LOCAL_IN) |
548c14ceb0eSFlorian Westphal 			(1 << NF_INET_FORWARD);
549c14ceb0eSFlorian Westphal 		break;
550c14ceb0eSFlorian Westphal 	default:
551c14ceb0eSFlorian Westphal 		return -EOPNOTSUPP;
552c14ceb0eSFlorian Westphal 	}
553c14ceb0eSFlorian Westphal 
554c14ceb0eSFlorian Westphal 	return nft_chain_validate_hooks(ctx->chain, hooks);
555c14ceb0eSFlorian Westphal }
556c14ceb0eSFlorian Westphal 
nft_meta_get_validate_xfrm(const struct nft_ctx * ctx)557c14ceb0eSFlorian Westphal static int nft_meta_get_validate_xfrm(const struct nft_ctx *ctx)
558c14ceb0eSFlorian Westphal {
559c14ceb0eSFlorian Westphal #ifdef CONFIG_XFRM
560c14ceb0eSFlorian Westphal 	unsigned int hooks;
561f6931f5fSFlorian Westphal 
56236596dadSPablo Neira Ayuso 	switch (ctx->family) {
563f6931f5fSFlorian Westphal 	case NFPROTO_NETDEV:
564f6931f5fSFlorian Westphal 		hooks = 1 << NF_NETDEV_INGRESS;
565f6931f5fSFlorian Westphal 		break;
566f6931f5fSFlorian Westphal 	case NFPROTO_IPV4:
567f6931f5fSFlorian Westphal 	case NFPROTO_IPV6:
568f6931f5fSFlorian Westphal 	case NFPROTO_INET:
569f6931f5fSFlorian Westphal 		hooks = (1 << NF_INET_PRE_ROUTING) |
570f6931f5fSFlorian Westphal 			(1 << NF_INET_LOCAL_IN) |
571f6931f5fSFlorian Westphal 			(1 << NF_INET_FORWARD);
572f6931f5fSFlorian Westphal 		break;
573f6931f5fSFlorian Westphal 	default:
574f6931f5fSFlorian Westphal 		return -EOPNOTSUPP;
575f6931f5fSFlorian Westphal 	}
576f6931f5fSFlorian Westphal 
577f6931f5fSFlorian Westphal 	return nft_chain_validate_hooks(ctx->chain, hooks);
578f6931f5fSFlorian Westphal #else
579f6931f5fSFlorian Westphal 	return 0;
580f6931f5fSFlorian Westphal #endif
581f6931f5fSFlorian Westphal }
582f6931f5fSFlorian Westphal 
nft_meta_get_validate(const struct nft_ctx * ctx,const struct nft_expr * expr,const struct nft_data ** data)583c14ceb0eSFlorian Westphal static int nft_meta_get_validate(const struct nft_ctx *ctx,
584c14ceb0eSFlorian Westphal 				 const struct nft_expr *expr,
585c14ceb0eSFlorian Westphal 				 const struct nft_data **data)
586c14ceb0eSFlorian Westphal {
587c14ceb0eSFlorian Westphal 	const struct nft_meta *priv = nft_expr_priv(expr);
588c14ceb0eSFlorian Westphal 
589c14ceb0eSFlorian Westphal 	switch (priv->key) {
590c14ceb0eSFlorian Westphal 	case NFT_META_SECPATH:
591c14ceb0eSFlorian Westphal 		return nft_meta_get_validate_xfrm(ctx);
592c14ceb0eSFlorian Westphal 	case NFT_META_SDIF:
593c14ceb0eSFlorian Westphal 	case NFT_META_SDIFNAME:
594c14ceb0eSFlorian Westphal 		return nft_meta_get_validate_sdif(ctx);
595c14ceb0eSFlorian Westphal 	default:
596c14ceb0eSFlorian Westphal 		break;
597c14ceb0eSFlorian Westphal 	}
598c14ceb0eSFlorian Westphal 
599c14ceb0eSFlorian Westphal 	return 0;
600c14ceb0eSFlorian Westphal }
601c14ceb0eSFlorian Westphal 
nft_meta_set_validate(const struct nft_ctx * ctx,const struct nft_expr * expr,const struct nft_data ** data)60230e103feSwenxu int nft_meta_set_validate(const struct nft_ctx *ctx,
603960fa72fSLiping Zhang 			  const struct nft_expr *expr,
604960fa72fSLiping Zhang 			  const struct nft_data **data)
605b4aae759SFlorian Westphal {
606960fa72fSLiping Zhang 	struct nft_meta *priv = nft_expr_priv(expr);
607b4aae759SFlorian Westphal 	unsigned int hooks;
608b4aae759SFlorian Westphal 
609960fa72fSLiping Zhang 	if (priv->key != NFT_META_PKTTYPE)
610960fa72fSLiping Zhang 		return 0;
611960fa72fSLiping Zhang 
61236596dadSPablo Neira Ayuso 	switch (ctx->family) {
613b4aae759SFlorian Westphal 	case NFPROTO_BRIDGE:
614b4aae759SFlorian Westphal 		hooks = 1 << NF_BR_PRE_ROUTING;
615b4aae759SFlorian Westphal 		break;
616b4aae759SFlorian Westphal 	case NFPROTO_NETDEV:
617b4aae759SFlorian Westphal 		hooks = 1 << NF_NETDEV_INGRESS;
618b4aae759SFlorian Westphal 		break;
61996d9f2a7SLiping Zhang 	case NFPROTO_IPV4:
62096d9f2a7SLiping Zhang 	case NFPROTO_IPV6:
62196d9f2a7SLiping Zhang 	case NFPROTO_INET:
62296d9f2a7SLiping Zhang 		hooks = 1 << NF_INET_PRE_ROUTING;
62396d9f2a7SLiping Zhang 		break;
624b4aae759SFlorian Westphal 	default:
625b4aae759SFlorian Westphal 		return -EOPNOTSUPP;
626b4aae759SFlorian Westphal 	}
627b4aae759SFlorian Westphal 
628b4aae759SFlorian Westphal 	return nft_chain_validate_hooks(ctx->chain, hooks);
629b4aae759SFlorian Westphal }
63030e103feSwenxu EXPORT_SYMBOL_GPL(nft_meta_set_validate);
631b4aae759SFlorian Westphal 
nft_meta_set_init(const struct nft_ctx * ctx,const struct nft_expr * expr,const struct nlattr * const tb[])63230e103feSwenxu int nft_meta_set_init(const struct nft_ctx *ctx,
633d2caa696SPatrick McHardy 		      const struct nft_expr *expr,
634d2caa696SPatrick McHardy 		      const struct nlattr * const tb[])
635d2caa696SPatrick McHardy {
636d2caa696SPatrick McHardy 	struct nft_meta *priv = nft_expr_priv(expr);
637d07db988SPatrick McHardy 	unsigned int len;
638d2caa696SPatrick McHardy 	int err;
639d2caa696SPatrick McHardy 
640d2caa696SPatrick McHardy 	priv->key = ntohl(nla_get_be32(tb[NFTA_META_KEY]));
641d2caa696SPatrick McHardy 	switch (priv->key) {
642d2caa696SPatrick McHardy 	case NFT_META_MARK:
643d2caa696SPatrick McHardy 	case NFT_META_PRIORITY:
644b473a1f5SChristian Göttsche #ifdef CONFIG_NETWORK_SECMARK
645b473a1f5SChristian Göttsche 	case NFT_META_SECMARK:
646b473a1f5SChristian Göttsche #endif
647d07db988SPatrick McHardy 		len = sizeof(u32);
648d07db988SPatrick McHardy 		break;
649d2caa696SPatrick McHardy 	case NFT_META_NFTRACE:
650d07db988SPatrick McHardy 		len = sizeof(u8);
651d2caa696SPatrick McHardy 		break;
652b4aae759SFlorian Westphal 	case NFT_META_PKTTYPE:
653b4aae759SFlorian Westphal 		len = sizeof(u8);
654b4aae759SFlorian Westphal 		break;
655d2caa696SPatrick McHardy 	default:
656d2caa696SPatrick McHardy 		return -EOPNOTSUPP;
657d2caa696SPatrick McHardy 	}
658d2caa696SPatrick McHardy 
65934cc9e52SPablo Neira Ayuso 	priv->len = len;
6604f16d25cSPablo Neira Ayuso 	err = nft_parse_register_load(tb[NFTA_META_SREG], &priv->sreg, len);
661b38895c5SPablo Neira Ayuso 	if (err < 0)
662b38895c5SPablo Neira Ayuso 		return err;
663e035b77aSArturo Borrero Gonzalez 
664e639f7abSFlorian Westphal 	if (priv->key == NFT_META_NFTRACE)
665e639f7abSFlorian Westphal 		static_branch_inc(&nft_trace_enabled);
666e639f7abSFlorian Westphal 
667e035b77aSArturo Borrero Gonzalez 	return 0;
668e035b77aSArturo Borrero Gonzalez }
66930e103feSwenxu EXPORT_SYMBOL_GPL(nft_meta_set_init);
670e035b77aSArturo Borrero Gonzalez 
nft_meta_get_dump(struct sk_buff * skb,const struct nft_expr * expr,bool reset)67130e103feSwenxu int nft_meta_get_dump(struct sk_buff *skb,
6727d34aa3eSPhil Sutter 		      const struct nft_expr *expr, bool reset)
67396518518SPatrick McHardy {
67496518518SPatrick McHardy 	const struct nft_meta *priv = nft_expr_priv(expr);
67596518518SPatrick McHardy 
67696518518SPatrick McHardy 	if (nla_put_be32(skb, NFTA_META_KEY, htonl(priv->key)))
67796518518SPatrick McHardy 		goto nla_put_failure;
678b1c96ed3SPatrick McHardy 	if (nft_dump_register(skb, NFTA_META_DREG, priv->dreg))
679e035b77aSArturo Borrero Gonzalez 		goto nla_put_failure;
68096518518SPatrick McHardy 	return 0;
68196518518SPatrick McHardy 
68296518518SPatrick McHardy nla_put_failure:
68396518518SPatrick McHardy 	return -1;
68496518518SPatrick McHardy }
68530e103feSwenxu EXPORT_SYMBOL_GPL(nft_meta_get_dump);
68696518518SPatrick McHardy 
nft_meta_set_dump(struct sk_buff * skb,const struct nft_expr * expr,bool reset)6877d34aa3eSPhil Sutter int nft_meta_set_dump(struct sk_buff *skb,
6887d34aa3eSPhil Sutter 		      const struct nft_expr *expr, bool reset)
689e035b77aSArturo Borrero Gonzalez {
690e035b77aSArturo Borrero Gonzalez 	const struct nft_meta *priv = nft_expr_priv(expr);
691e035b77aSArturo Borrero Gonzalez 
692e035b77aSArturo Borrero Gonzalez 	if (nla_put_be32(skb, NFTA_META_KEY, htonl(priv->key)))
693e035b77aSArturo Borrero Gonzalez 		goto nla_put_failure;
694b1c96ed3SPatrick McHardy 	if (nft_dump_register(skb, NFTA_META_SREG, priv->sreg))
695e035b77aSArturo Borrero Gonzalez 		goto nla_put_failure;
696e035b77aSArturo Borrero Gonzalez 
697e035b77aSArturo Borrero Gonzalez 	return 0;
698e035b77aSArturo Borrero Gonzalez 
699e035b77aSArturo Borrero Gonzalez nla_put_failure:
700e035b77aSArturo Borrero Gonzalez 	return -1;
701e035b77aSArturo Borrero Gonzalez }
70230e103feSwenxu EXPORT_SYMBOL_GPL(nft_meta_set_dump);
703e035b77aSArturo Borrero Gonzalez 
nft_meta_set_destroy(const struct nft_ctx * ctx,const struct nft_expr * expr)70430e103feSwenxu void nft_meta_set_destroy(const struct nft_ctx *ctx,
705e639f7abSFlorian Westphal 			  const struct nft_expr *expr)
706e639f7abSFlorian Westphal {
707e639f7abSFlorian Westphal 	const struct nft_meta *priv = nft_expr_priv(expr);
708e639f7abSFlorian Westphal 
709e639f7abSFlorian Westphal 	if (priv->key == NFT_META_NFTRACE)
710e639f7abSFlorian Westphal 		static_branch_dec(&nft_trace_enabled);
711e639f7abSFlorian Westphal }
71230e103feSwenxu EXPORT_SYMBOL_GPL(nft_meta_set_destroy);
713e639f7abSFlorian Westphal 
nft_meta_get_offload(struct nft_offload_ctx * ctx,struct nft_flow_rule * flow,const struct nft_expr * expr)714c9626a2cSPablo Neira Ayuso static int nft_meta_get_offload(struct nft_offload_ctx *ctx,
715c9626a2cSPablo Neira Ayuso 				struct nft_flow_rule *flow,
716c9626a2cSPablo Neira Ayuso 				const struct nft_expr *expr)
717c9626a2cSPablo Neira Ayuso {
718c9626a2cSPablo Neira Ayuso 	const struct nft_meta *priv = nft_expr_priv(expr);
719c9626a2cSPablo Neira Ayuso 	struct nft_offload_reg *reg = &ctx->regs[priv->dreg];
720c9626a2cSPablo Neira Ayuso 
721c9626a2cSPablo Neira Ayuso 	switch (priv->key) {
722c9626a2cSPablo Neira Ayuso 	case NFT_META_PROTOCOL:
723a5d45bc0SPablo Neira Ayuso 		NFT_OFFLOAD_MATCH_EXACT(FLOW_DISSECTOR_KEY_BASIC, basic, n_proto,
724c9626a2cSPablo Neira Ayuso 					sizeof(__u16), reg);
725c9626a2cSPablo Neira Ayuso 		nft_offload_set_dependency(ctx, NFT_OFFLOAD_DEP_NETWORK);
726c9626a2cSPablo Neira Ayuso 		break;
727c9626a2cSPablo Neira Ayuso 	case NFT_META_L4PROTO:
728a5d45bc0SPablo Neira Ayuso 		NFT_OFFLOAD_MATCH_EXACT(FLOW_DISSECTOR_KEY_BASIC, basic, ip_proto,
729c9626a2cSPablo Neira Ayuso 					sizeof(__u8), reg);
730c9626a2cSPablo Neira Ayuso 		nft_offload_set_dependency(ctx, NFT_OFFLOAD_DEP_TRANSPORT);
731c9626a2cSPablo Neira Ayuso 		break;
73225da5eb3SPablo Neira Ayuso 	case NFT_META_IIF:
733a5d45bc0SPablo Neira Ayuso 		NFT_OFFLOAD_MATCH_EXACT(FLOW_DISSECTOR_KEY_META, meta,
73425da5eb3SPablo Neira Ayuso 					ingress_ifindex, sizeof(__u32), reg);
73525da5eb3SPablo Neira Ayuso 		break;
7368819efc9SPablo Neira Ayuso 	case NFT_META_IIFTYPE:
737a5d45bc0SPablo Neira Ayuso 		NFT_OFFLOAD_MATCH_EXACT(FLOW_DISSECTOR_KEY_META, meta,
7388819efc9SPablo Neira Ayuso 					ingress_iftype, sizeof(__u16), reg);
7398819efc9SPablo Neira Ayuso 		break;
740c9626a2cSPablo Neira Ayuso 	default:
741c9626a2cSPablo Neira Ayuso 		return -EOPNOTSUPP;
742c9626a2cSPablo Neira Ayuso 	}
743c9626a2cSPablo Neira Ayuso 
744c9626a2cSPablo Neira Ayuso 	return 0;
745c9626a2cSPablo Neira Ayuso }
746c9626a2cSPablo Neira Ayuso 
nft_meta_get_reduce(struct nft_regs_track * track,const struct nft_expr * expr)747aaa7b20bSFlorian Westphal bool nft_meta_get_reduce(struct nft_regs_track *track,
7489b17afb2SPablo Neira Ayuso 			 const struct nft_expr *expr)
7499b17afb2SPablo Neira Ayuso {
7509b17afb2SPablo Neira Ayuso 	const struct nft_meta *priv = nft_expr_priv(expr);
7519b17afb2SPablo Neira Ayuso 	const struct nft_meta *meta;
7529b17afb2SPablo Neira Ayuso 
75334cc9e52SPablo Neira Ayuso 	if (!nft_reg_track_cmp(track, expr, priv->dreg)) {
75434cc9e52SPablo Neira Ayuso 		nft_reg_track_update(track, expr, priv->dreg, priv->len);
7559b17afb2SPablo Neira Ayuso 		return false;
7569b17afb2SPablo Neira Ayuso 	}
7579b17afb2SPablo Neira Ayuso 
7589b17afb2SPablo Neira Ayuso 	meta = nft_expr_priv(track->regs[priv->dreg].selector);
7599b17afb2SPablo Neira Ayuso 	if (priv->key != meta->key ||
7609b17afb2SPablo Neira Ayuso 	    priv->dreg != meta->dreg) {
76134cc9e52SPablo Neira Ayuso 		nft_reg_track_update(track, expr, priv->dreg, priv->len);
7629b17afb2SPablo Neira Ayuso 		return false;
7639b17afb2SPablo Neira Ayuso 	}
7649b17afb2SPablo Neira Ayuso 
7659b17afb2SPablo Neira Ayuso 	if (!track->regs[priv->dreg].bitwise)
7669b17afb2SPablo Neira Ayuso 		return true;
7679b17afb2SPablo Neira Ayuso 
768be5650f8SPablo Neira Ayuso 	return nft_expr_reduce_bitwise(track, expr);
7699b17afb2SPablo Neira Ayuso }
770aaa7b20bSFlorian Westphal EXPORT_SYMBOL_GPL(nft_meta_get_reduce);
7719b17afb2SPablo Neira Ayuso 
772e035b77aSArturo Borrero Gonzalez static const struct nft_expr_ops nft_meta_get_ops = {
773ef1f7df9SPatrick McHardy 	.type		= &nft_meta_type,
77496518518SPatrick McHardy 	.size		= NFT_EXPR_SIZE(sizeof(struct nft_meta)),
775e035b77aSArturo Borrero Gonzalez 	.eval		= nft_meta_get_eval,
776d2caa696SPatrick McHardy 	.init		= nft_meta_get_init,
777e035b77aSArturo Borrero Gonzalez 	.dump		= nft_meta_get_dump,
7789b17afb2SPablo Neira Ayuso 	.reduce		= nft_meta_get_reduce,
779f6931f5fSFlorian Westphal 	.validate	= nft_meta_get_validate,
780c9626a2cSPablo Neira Ayuso 	.offload	= nft_meta_get_offload,
781ef1f7df9SPatrick McHardy };
782ef1f7df9SPatrick McHardy 
nft_meta_set_reduce(struct nft_regs_track * track,const struct nft_expr * expr)7834a80e026SPablo Neira Ayuso static bool nft_meta_set_reduce(struct nft_regs_track *track,
7844a80e026SPablo Neira Ayuso 				const struct nft_expr *expr)
7854a80e026SPablo Neira Ayuso {
7864a80e026SPablo Neira Ayuso 	int i;
7874a80e026SPablo Neira Ayuso 
7884a80e026SPablo Neira Ayuso 	for (i = 0; i < NFT_REG32_NUM; i++) {
7894a80e026SPablo Neira Ayuso 		if (!track->regs[i].selector)
7904a80e026SPablo Neira Ayuso 			continue;
7914a80e026SPablo Neira Ayuso 
7924a80e026SPablo Neira Ayuso 		if (track->regs[i].selector->ops != &nft_meta_get_ops)
7934a80e026SPablo Neira Ayuso 			continue;
7944a80e026SPablo Neira Ayuso 
79534cc9e52SPablo Neira Ayuso 		__nft_reg_track_cancel(track, i);
7964a80e026SPablo Neira Ayuso 	}
7974a80e026SPablo Neira Ayuso 
7984a80e026SPablo Neira Ayuso 	return false;
7994a80e026SPablo Neira Ayuso }
8004a80e026SPablo Neira Ayuso 
801e035b77aSArturo Borrero Gonzalez static const struct nft_expr_ops nft_meta_set_ops = {
802e035b77aSArturo Borrero Gonzalez 	.type		= &nft_meta_type,
803e035b77aSArturo Borrero Gonzalez 	.size		= NFT_EXPR_SIZE(sizeof(struct nft_meta)),
804e035b77aSArturo Borrero Gonzalez 	.eval		= nft_meta_set_eval,
805d2caa696SPatrick McHardy 	.init		= nft_meta_set_init,
806e639f7abSFlorian Westphal 	.destroy	= nft_meta_set_destroy,
807e035b77aSArturo Borrero Gonzalez 	.dump		= nft_meta_set_dump,
8084a80e026SPablo Neira Ayuso 	.reduce		= nft_meta_set_reduce,
809960fa72fSLiping Zhang 	.validate	= nft_meta_set_validate,
810e035b77aSArturo Borrero Gonzalez };
811e035b77aSArturo Borrero Gonzalez 
812e035b77aSArturo Borrero Gonzalez static const struct nft_expr_ops *
nft_meta_select_ops(const struct nft_ctx * ctx,const struct nlattr * const tb[])813e035b77aSArturo Borrero Gonzalez nft_meta_select_ops(const struct nft_ctx *ctx,
814e035b77aSArturo Borrero Gonzalez 		    const struct nlattr * const tb[])
815e035b77aSArturo Borrero Gonzalez {
816e035b77aSArturo Borrero Gonzalez 	if (tb[NFTA_META_KEY] == NULL)
817e035b77aSArturo Borrero Gonzalez 		return ERR_PTR(-EINVAL);
818e035b77aSArturo Borrero Gonzalez 
819e035b77aSArturo Borrero Gonzalez 	if (tb[NFTA_META_DREG] && tb[NFTA_META_SREG])
820e035b77aSArturo Borrero Gonzalez 		return ERR_PTR(-EINVAL);
821e035b77aSArturo Borrero Gonzalez 
822dfee0e99SArnd Bergmann #if IS_ENABLED(CONFIG_NF_TABLES_BRIDGE) && IS_MODULE(CONFIG_NFT_BRIDGE_META)
8230ef1efd1SPablo Neira Ayuso 	if (ctx->family == NFPROTO_BRIDGE)
8240ef1efd1SPablo Neira Ayuso 		return ERR_PTR(-EAGAIN);
8250ef1efd1SPablo Neira Ayuso #endif
826e035b77aSArturo Borrero Gonzalez 	if (tb[NFTA_META_DREG])
827e035b77aSArturo Borrero Gonzalez 		return &nft_meta_get_ops;
828e035b77aSArturo Borrero Gonzalez 
829e035b77aSArturo Borrero Gonzalez 	if (tb[NFTA_META_SREG])
830e035b77aSArturo Borrero Gonzalez 		return &nft_meta_set_ops;
831e035b77aSArturo Borrero Gonzalez 
832e035b77aSArturo Borrero Gonzalez 	return ERR_PTR(-EINVAL);
833e035b77aSArturo Borrero Gonzalez }
834e035b77aSArturo Borrero Gonzalez 
nft_meta_inner_init(const struct nft_ctx * ctx,const struct nft_expr * expr,const struct nlattr * const tb[])835a150d122SPablo Neira Ayuso static int nft_meta_inner_init(const struct nft_ctx *ctx,
836a150d122SPablo Neira Ayuso 			       const struct nft_expr *expr,
837a150d122SPablo Neira Ayuso 			       const struct nlattr * const tb[])
838a150d122SPablo Neira Ayuso {
839a150d122SPablo Neira Ayuso 	struct nft_meta *priv = nft_expr_priv(expr);
840a150d122SPablo Neira Ayuso 	unsigned int len;
841a150d122SPablo Neira Ayuso 
842b30669fdSDavide Ornaghi 	if (!tb[NFTA_META_KEY] || !tb[NFTA_META_DREG])
843b30669fdSDavide Ornaghi 		return -EINVAL;
844b30669fdSDavide Ornaghi 
845a150d122SPablo Neira Ayuso 	priv->key = ntohl(nla_get_be32(tb[NFTA_META_KEY]));
846a150d122SPablo Neira Ayuso 	switch (priv->key) {
847a150d122SPablo Neira Ayuso 	case NFT_META_PROTOCOL:
848a150d122SPablo Neira Ayuso 		len = sizeof(u16);
849a150d122SPablo Neira Ayuso 		break;
850a150d122SPablo Neira Ayuso 	case NFT_META_L4PROTO:
851a150d122SPablo Neira Ayuso 		len = sizeof(u32);
852a150d122SPablo Neira Ayuso 		break;
853a150d122SPablo Neira Ayuso 	default:
854a150d122SPablo Neira Ayuso 		return -EOPNOTSUPP;
855a150d122SPablo Neira Ayuso 	}
856a150d122SPablo Neira Ayuso 	priv->len = len;
857a150d122SPablo Neira Ayuso 
858a150d122SPablo Neira Ayuso 	return nft_parse_register_store(ctx, tb[NFTA_META_DREG], &priv->dreg,
859a150d122SPablo Neira Ayuso 					NULL, NFT_DATA_VALUE, len);
860a150d122SPablo Neira Ayuso }
861a150d122SPablo Neira Ayuso 
nft_meta_inner_eval(const struct nft_expr * expr,struct nft_regs * regs,const struct nft_pktinfo * pkt,struct nft_inner_tun_ctx * tun_ctx)862a150d122SPablo Neira Ayuso void nft_meta_inner_eval(const struct nft_expr *expr,
863a150d122SPablo Neira Ayuso 			 struct nft_regs *regs,
864a150d122SPablo Neira Ayuso 			 const struct nft_pktinfo *pkt,
865a150d122SPablo Neira Ayuso 			 struct nft_inner_tun_ctx *tun_ctx)
866a150d122SPablo Neira Ayuso {
867a150d122SPablo Neira Ayuso 	const struct nft_meta *priv = nft_expr_priv(expr);
868a150d122SPablo Neira Ayuso 	u32 *dest = &regs->data[priv->dreg];
869a150d122SPablo Neira Ayuso 
870a150d122SPablo Neira Ayuso 	switch (priv->key) {
871a150d122SPablo Neira Ayuso 	case NFT_META_PROTOCOL:
872a150d122SPablo Neira Ayuso 		nft_reg_store16(dest, (__force u16)tun_ctx->llproto);
873a150d122SPablo Neira Ayuso 		break;
874a150d122SPablo Neira Ayuso 	case NFT_META_L4PROTO:
875a150d122SPablo Neira Ayuso 		if (!(tun_ctx->flags & NFT_PAYLOAD_CTX_INNER_TH))
876a150d122SPablo Neira Ayuso 			goto err;
877a150d122SPablo Neira Ayuso 
878a150d122SPablo Neira Ayuso 		nft_reg_store8(dest, tun_ctx->l4proto);
879a150d122SPablo Neira Ayuso 		break;
880a150d122SPablo Neira Ayuso 	default:
881a150d122SPablo Neira Ayuso 		WARN_ON_ONCE(1);
882a150d122SPablo Neira Ayuso 		goto err;
883a150d122SPablo Neira Ayuso 	}
884a150d122SPablo Neira Ayuso 	return;
885a150d122SPablo Neira Ayuso 
886a150d122SPablo Neira Ayuso err:
887a150d122SPablo Neira Ayuso 	regs->verdict.code = NFT_BREAK;
888a150d122SPablo Neira Ayuso }
889a150d122SPablo Neira Ayuso EXPORT_SYMBOL_GPL(nft_meta_inner_eval);
890a150d122SPablo Neira Ayuso 
891a150d122SPablo Neira Ayuso static const struct nft_expr_ops nft_meta_inner_ops = {
892a150d122SPablo Neira Ayuso 	.type		= &nft_meta_type,
893a150d122SPablo Neira Ayuso 	.size		= NFT_EXPR_SIZE(sizeof(struct nft_meta)),
894a150d122SPablo Neira Ayuso 	.init		= nft_meta_inner_init,
895a150d122SPablo Neira Ayuso 	.dump		= nft_meta_get_dump,
896a150d122SPablo Neira Ayuso 	/* direct call to nft_meta_inner_eval(). */
897a150d122SPablo Neira Ayuso };
898a150d122SPablo Neira Ayuso 
8998a22543cSFlorian Westphal struct nft_expr_type nft_meta_type __read_mostly = {
900ef1f7df9SPatrick McHardy 	.name		= "meta",
901d4ef3835SArushi Singhal 	.select_ops	= nft_meta_select_ops,
902a150d122SPablo Neira Ayuso 	.inner_ops	= &nft_meta_inner_ops,
90396518518SPatrick McHardy 	.policy		= nft_meta_policy,
90496518518SPatrick McHardy 	.maxattr	= NFTA_META_MAX,
905ef1f7df9SPatrick McHardy 	.owner		= THIS_MODULE,
90696518518SPatrick McHardy };
907fb961945SChristian Göttsche 
908fb961945SChristian Göttsche #ifdef CONFIG_NETWORK_SECMARK
909fb961945SChristian Göttsche struct nft_secmark {
910fb961945SChristian Göttsche 	u32 secid;
911fb961945SChristian Göttsche 	char *ctx;
912fb961945SChristian Göttsche };
913fb961945SChristian Göttsche 
914fb961945SChristian Göttsche static const struct nla_policy nft_secmark_policy[NFTA_SECMARK_MAX + 1] = {
915fb961945SChristian Göttsche 	[NFTA_SECMARK_CTX]     = { .type = NLA_STRING, .len = NFT_SECMARK_CTX_MAXLEN },
916fb961945SChristian Göttsche };
917fb961945SChristian Göttsche 
nft_secmark_compute_secid(struct nft_secmark * priv)918fb961945SChristian Göttsche static int nft_secmark_compute_secid(struct nft_secmark *priv)
919fb961945SChristian Göttsche {
920fb961945SChristian Göttsche 	u32 tmp_secid = 0;
921fb961945SChristian Göttsche 	int err;
922fb961945SChristian Göttsche 
923fb961945SChristian Göttsche 	err = security_secctx_to_secid(priv->ctx, strlen(priv->ctx), &tmp_secid);
924fb961945SChristian Göttsche 	if (err)
925fb961945SChristian Göttsche 		return err;
926fb961945SChristian Göttsche 
927fb961945SChristian Göttsche 	if (!tmp_secid)
928fb961945SChristian Göttsche 		return -ENOENT;
929fb961945SChristian Göttsche 
930fb961945SChristian Göttsche 	err = security_secmark_relabel_packet(tmp_secid);
931fb961945SChristian Göttsche 	if (err)
932fb961945SChristian Göttsche 		return err;
933fb961945SChristian Göttsche 
934fb961945SChristian Göttsche 	priv->secid = tmp_secid;
935fb961945SChristian Göttsche 	return 0;
936fb961945SChristian Göttsche }
937fb961945SChristian Göttsche 
nft_secmark_obj_eval(struct nft_object * obj,struct nft_regs * regs,const struct nft_pktinfo * pkt)938fb961945SChristian Göttsche static void nft_secmark_obj_eval(struct nft_object *obj, struct nft_regs *regs,
939fb961945SChristian Göttsche 				 const struct nft_pktinfo *pkt)
940fb961945SChristian Göttsche {
941fb961945SChristian Göttsche 	const struct nft_secmark *priv = nft_obj_data(obj);
942fb961945SChristian Göttsche 	struct sk_buff *skb = pkt->skb;
943fb961945SChristian Göttsche 
944fb961945SChristian Göttsche 	skb->secmark = priv->secid;
945fb961945SChristian Göttsche }
946fb961945SChristian Göttsche 
nft_secmark_obj_init(const struct nft_ctx * ctx,const struct nlattr * const tb[],struct nft_object * obj)947fb961945SChristian Göttsche static int nft_secmark_obj_init(const struct nft_ctx *ctx,
948fb961945SChristian Göttsche 				const struct nlattr * const tb[],
949fb961945SChristian Göttsche 				struct nft_object *obj)
950fb961945SChristian Göttsche {
951fb961945SChristian Göttsche 	struct nft_secmark *priv = nft_obj_data(obj);
952fb961945SChristian Göttsche 	int err;
953fb961945SChristian Göttsche 
954fb961945SChristian Göttsche 	if (tb[NFTA_SECMARK_CTX] == NULL)
955fb961945SChristian Göttsche 		return -EINVAL;
956fb961945SChristian Göttsche 
957fb961945SChristian Göttsche 	priv->ctx = nla_strdup(tb[NFTA_SECMARK_CTX], GFP_KERNEL);
958fb961945SChristian Göttsche 	if (!priv->ctx)
959fb961945SChristian Göttsche 		return -ENOMEM;
960fb961945SChristian Göttsche 
961fb961945SChristian Göttsche 	err = nft_secmark_compute_secid(priv);
962fb961945SChristian Göttsche 	if (err) {
963fb961945SChristian Göttsche 		kfree(priv->ctx);
964fb961945SChristian Göttsche 		return err;
965fb961945SChristian Göttsche 	}
966fb961945SChristian Göttsche 
967fb961945SChristian Göttsche 	security_secmark_refcount_inc();
968fb961945SChristian Göttsche 
969fb961945SChristian Göttsche 	return 0;
970fb961945SChristian Göttsche }
971fb961945SChristian Göttsche 
nft_secmark_obj_dump(struct sk_buff * skb,struct nft_object * obj,bool reset)972fb961945SChristian Göttsche static int nft_secmark_obj_dump(struct sk_buff *skb, struct nft_object *obj,
973fb961945SChristian Göttsche 				bool reset)
974fb961945SChristian Göttsche {
975fb961945SChristian Göttsche 	struct nft_secmark *priv = nft_obj_data(obj);
976fb961945SChristian Göttsche 	int err;
977fb961945SChristian Göttsche 
978fb961945SChristian Göttsche 	if (nla_put_string(skb, NFTA_SECMARK_CTX, priv->ctx))
979fb961945SChristian Göttsche 		return -1;
980fb961945SChristian Göttsche 
981fb961945SChristian Göttsche 	if (reset) {
982fb961945SChristian Göttsche 		err = nft_secmark_compute_secid(priv);
983fb961945SChristian Göttsche 		if (err)
984fb961945SChristian Göttsche 			return err;
985fb961945SChristian Göttsche 	}
986fb961945SChristian Göttsche 
987fb961945SChristian Göttsche 	return 0;
988fb961945SChristian Göttsche }
989fb961945SChristian Göttsche 
nft_secmark_obj_destroy(const struct nft_ctx * ctx,struct nft_object * obj)990fb961945SChristian Göttsche static void nft_secmark_obj_destroy(const struct nft_ctx *ctx, struct nft_object *obj)
991fb961945SChristian Göttsche {
992fb961945SChristian Göttsche 	struct nft_secmark *priv = nft_obj_data(obj);
993fb961945SChristian Göttsche 
994fb961945SChristian Göttsche 	security_secmark_refcount_dec();
995fb961945SChristian Göttsche 
996fb961945SChristian Göttsche 	kfree(priv->ctx);
997fb961945SChristian Göttsche }
998fb961945SChristian Göttsche 
999fb961945SChristian Göttsche static const struct nft_object_ops nft_secmark_obj_ops = {
1000fb961945SChristian Göttsche 	.type		= &nft_secmark_obj_type,
1001fb961945SChristian Göttsche 	.size		= sizeof(struct nft_secmark),
1002fb961945SChristian Göttsche 	.init		= nft_secmark_obj_init,
1003fb961945SChristian Göttsche 	.eval		= nft_secmark_obj_eval,
1004fb961945SChristian Göttsche 	.dump		= nft_secmark_obj_dump,
1005fb961945SChristian Göttsche 	.destroy	= nft_secmark_obj_destroy,
1006fb961945SChristian Göttsche };
1007fb961945SChristian Göttsche struct nft_object_type nft_secmark_obj_type __read_mostly = {
1008fb961945SChristian Göttsche 	.type		= NFT_OBJECT_SECMARK,
1009fb961945SChristian Göttsche 	.ops		= &nft_secmark_obj_ops,
1010fb961945SChristian Göttsche 	.maxattr	= NFTA_SECMARK_MAX,
1011fb961945SChristian Göttsche 	.policy		= nft_secmark_policy,
1012fb961945SChristian Göttsche 	.owner		= THIS_MODULE,
1013fb961945SChristian Göttsche };
1014fb961945SChristian Göttsche #endif /* CONFIG_NETWORK_SECMARK */
1015