History

Merge git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf-next

Pablo Neira Ayuso says: ==================== Netfilter updates for net-next The following patchset contains Netfilter updates for net-next: 1) Remove #ifdef pollution around nf_ingress(), from Lukas Wunner. 2) Document ingress hook in netdevice, also from Lukas. 3) Remove htons() in tunnel metadata port netlink attributes, from Xin Long. 4) Missing erspan netlink attribute validation also from Xin Long. 5) Missing erspan version in tunnel, from Xin Long. 6) Missing attribute nest in NFTA_TUNNEL_KEY_OPTS_{VXLAN,ERSPAN} Patch from Xin Long. 7) Missing nla_nest_cancel() in tunnel netlink dump path, from Xin Long. 8) Remove two exported conntrack symbols with no clients, from Florian Westphal. 9) Add nft_meta_get_eval_time() helper to nft_meta, from Florian. 10) Add nft_meta_pkttype helper for loopback, also from Florian. 11) Add nft_meta_socket uid helper, from Florian Westphal. 12) Add nft_meta_cgroup helper, from Florian. 13) Add nft_meta_ifkind helper, from Florian. 14) Group all interface related meta selector, from Florian. 15) Add nft_prandom_u32() helper, from Florian. 16) Add nft_meta_rtclassid helper, from Florian. 17) Add support for matching on the slave device index, from Florian. This batch, among other things, contains updates for the netfilter tunnel netlink interface: This extension is still incomplete and lacking proper userspace support which is actually my fault, I did not find the time to go back and finish this. This update is breaking tunnel UAPI in some aspects to fix it but do it better sooner than never. ====================

David S. Miller committed 6 years ago

Commit ba402812 parents 1a1fda5 c14ceb07 files · +357 −144Browse files

Unified · Split

7 files
  1. include/linux/netdevice.h +1 −0
  2. include/uapi/linux/netfilter/nf_tables.h +4 −0
  3. net/core/dev.c +0 −2
  4. net/netfilter/nf_conntrack_core.c +0 −1
  5. net/netfilter/nf_conntrack_extend.c +0 −1
  6. net/netfilter/nft_meta.c +313 −127
  7. net/netfilter/nft_tunnel.c +39 −13
include/linux/netdevice.h+1−0
@@ -1709,6 +1709,7 @@ enum netdev_priv_flags { · 1708 unmodified lines
1709 * @miniq_ingress: ingress/clsact qdisc specific data for1709 * @miniq_ingress: ingress/clsact qdisc specific data for
1710 * ingress processing1710 * ingress processing
1711 * @ingress_queue: XXX: need comments on this one1711 * @ingress_queue: XXX: need comments on this one
1712 * @nf_hooks_ingress: netfilter hooks executed for ingress packets
1712 * @broadcast: hw bcast address1713 * @broadcast: hw bcast address
1713 *1714 *
1714 * @rx_cpu_rmap: CPU reverse-mapping for RX completion interrupts,1715 * @rx_cpu_rmap: CPU reverse-mapping for RX completion interrupts,
include/uapi/linux/netfilter/nf_tables.h+4−0
@@ -805,6 +805,8 @@ enum nft_exthdr_attributes { · 804 unmodified lines
805 * @NFT_META_TIME_NS: time since epoch (in nanoseconds)805 * @NFT_META_TIME_NS: time since epoch (in nanoseconds)
806 * @NFT_META_TIME_DAY: day of week (from 0 = Sunday to 6 = Saturday)806 * @NFT_META_TIME_DAY: day of week (from 0 = Sunday to 6 = Saturday)
807 * @NFT_META_TIME_HOUR: hour of day (in seconds)807 * @NFT_META_TIME_HOUR: hour of day (in seconds)
808 * @NFT_META_SDIF: slave device interface index
809 * @NFT_META_SDIFNAME: slave device interface name
808 */810 */
809enum nft_meta_keys {811enum nft_meta_keys {
810 NFT_META_LEN,812 NFT_META_LEN,
@@ -840,6 +842,8 @@ enum nft_meta_keys { · 29 unmodified lines
840 NFT_META_TIME_NS,842 NFT_META_TIME_NS,
841 NFT_META_TIME_DAY,843 NFT_META_TIME_DAY,
842 NFT_META_TIME_HOUR,844 NFT_META_TIME_HOUR,
845 NFT_META_SDIF,
846 NFT_META_SDIFNAME,
843};847};
844 848
845/**849/**
net/core/dev.c+0−2
@@ -4932,7 +4932,6 @@ static bool skb_pfmemalloc_protocol(struct sk_buff *skb) · 4931 unmodified lines
4932static inline int nf_ingress(struct sk_buff *skb, struct packet_type **pt_prev,4932static inline int nf_ingress(struct sk_buff *skb, struct packet_type **pt_prev,
4933 int *ret, struct net_device *orig_dev)4933 int *ret, struct net_device *orig_dev)
4934{4934{
4935#ifdef CONFIG_NETFILTER_INGRESS
4936 if (nf_hook_ingress_active(skb)) {4935 if (nf_hook_ingress_active(skb)) {
4937 int ingress_retval;4936 int ingress_retval;
4938 4937
@@ -4946,7 +4945,6 @@ static inline int nf_ingress(struct sk_buff *skb, struct packet_type **pt_prev, · 7 unmodified lines
4946 rcu_read_unlock();4945 rcu_read_unlock();
4947 return ingress_retval;4946 return ingress_retval;
4948 }4947 }
4949#endif /* CONFIG_NETFILTER_INGRESS */
4950 return 0;4948 return 0;
4951}4949}
4952 4950
net/netfilter/nf_conntrack_core.c+0−1
@@ -2334,7 +2334,6 @@ int nf_conntrack_set_hashsize(const char *val, const struct kernel_param *kp) · 2333 unmodified lines
2334 2334
2335 return nf_conntrack_hash_resize(hashsize);2335 return nf_conntrack_hash_resize(hashsize);
2336}2336}
2337EXPORT_SYMBOL_GPL(nf_conntrack_set_hashsize);
2338 2337
2339static __always_inline unsigned int total_extension_size(void)2338static __always_inline unsigned int total_extension_size(void)
2340{2339{
net/netfilter/nf_conntrack_extend.c+0−1
@@ -37,7 +37,6 @@ void nf_ct_ext_destroy(struct nf_conn *ct) · 36 unmodified lines
37 37
38 kfree(ct->ext);38 kfree(ct->ext);
39}39}
40EXPORT_SYMBOL(nf_ct_ext_destroy);
41 40
42void *nf_ct_ext_add(struct nf_conn *ct, enum nf_ct_ext_id id, gfp_t gfp)41void *nf_ct_ext_add(struct nf_conn *ct, enum nf_ct_ext_id id, gfp_t gfp)
43{42{
net/netfilter/nft_meta.c+313−127
@@ -17,6 +17,7 @@ · 16 unmodified lines
17#include <linux/smp.h>17#include <linux/smp.h>
18#include <linux/static_key.h>18#include <linux/static_key.h>
19#include <net/dst.h>19#include <net/dst.h>
20#include <net/ip.h>
20#include <net/sock.h>21#include <net/sock.h>
21#include <net/tcp_states.h> /* for TCP_TIME_WAIT */22#include <net/tcp_states.h> /* for TCP_TIME_WAIT */
22#include <net/netfilter/nf_tables.h>23#include <net/netfilter/nf_tables.h>
@@ -33,8 +34,9 @@ · 10 unmodified lines
33 34
34static DEFINE_PER_CPU(struct rnd_state, nft_prandom_state);35static DEFINE_PER_CPU(struct rnd_state, nft_prandom_state);
35 36
36static u8 nft_meta_weekday(time64_t secs)37static u8 nft_meta_weekday(void)
37{38{
39 time64_t secs = ktime_get_real_seconds();
38 unsigned int dse;40 unsigned int dse;
39 u8 wday;41 u8 wday;
40 42
@@ -56,14 +58,264 @@ static u32 nft_meta_hour(time64_t secs) · 15 unmodified lines
56 + tm.tm_sec;58 + tm.tm_sec;
57}59}
58 60
61static noinline_for_stack void
62nft_meta_get_eval_time(enum nft_meta_keys key,
63 u32 *dest)
64{
65 switch (key) {
66 case NFT_META_TIME_NS:
67 nft_reg_store64(dest, ktime_get_real_ns());
68 break;
69 case NFT_META_TIME_DAY:
70 nft_reg_store8(dest, nft_meta_weekday());
71 break;
72 case NFT_META_TIME_HOUR:
73 *dest = nft_meta_hour(ktime_get_real_seconds());
74 break;
75 default:
76 break;
77 }
78}
79
80static noinline bool
81nft_meta_get_eval_pkttype_lo(const struct nft_pktinfo *pkt,
82 u32 *dest)
83{
84 const struct sk_buff *skb = pkt->skb;
85
86 switch (nft_pf(pkt)) {
87 case NFPROTO_IPV4:
88 if (ipv4_is_multicast(ip_hdr(skb)->daddr))
89 nft_reg_store8(dest, PACKET_MULTICAST);
90 else
91 nft_reg_store8(dest, PACKET_BROADCAST);
92 break;
93 case NFPROTO_IPV6:
94 nft_reg_store8(dest, PACKET_MULTICAST);
95 break;
96 case NFPROTO_NETDEV:
97 switch (skb->protocol) {
98 case htons(ETH_P_IP): {
99 int noff = skb_network_offset(skb);
100 struct iphdr *iph, _iph;
101
102 iph = skb_header_pointer(skb, noff,
103 sizeof(_iph), &_iph);
104 if (!iph)
105 return false;
106
107 if (ipv4_is_multicast(iph->daddr))
108 nft_reg_store8(dest, PACKET_MULTICAST);
109 else
110 nft_reg_store8(dest, PACKET_BROADCAST);
111
112 break;
113 }
114 case htons(ETH_P_IPV6):
115 nft_reg_store8(dest, PACKET_MULTICAST);
116 break;
117 default:
118 WARN_ON_ONCE(1);
119 return false;
120 }
121 break;
122 default:
123 WARN_ON_ONCE(1);
124 return false;
125 }
126
127 return true;
128}
129
130static noinline bool
131nft_meta_get_eval_skugid(enum nft_meta_keys key,
132 u32 *dest,
133 const struct nft_pktinfo *pkt)
134{
135 struct sock *sk = skb_to_full_sk(pkt->skb);
136 struct socket *sock;
137
138 if (!sk || !sk_fullsock(sk) || !net_eq(nft_net(pkt), sock_net(sk)))
139 return false;
140
141 read_lock_bh(&sk->sk_callback_lock);
142 sock = sk->sk_socket;
143 if (!sock || !sock->file) {
144 read_unlock_bh(&sk->sk_callback_lock);
145 return false;
146 }
147
148 switch (key) {
149 case NFT_META_SKUID:
150 *dest = from_kuid_munged(&init_user_ns,
151 sock->file->f_cred->fsuid);
152 break;
153 case NFT_META_SKGID:
154 *dest = from_kgid_munged(&init_user_ns,
155 sock->file->f_cred->fsgid);
156 break;
157 default:
158 break;
159 }
160
161 read_unlock_bh(&sk->sk_callback_lock);
162 return true;
163}
164
165#ifdef CONFIG_CGROUP_NET_CLASSID
166static noinline bool
167nft_meta_get_eval_cgroup(u32 *dest, const struct nft_pktinfo *pkt)
168{
169 struct sock *sk = skb_to_full_sk(pkt->skb);
170
171 if (!sk || !sk_fullsock(sk) || !net_eq(nft_net(pkt), sock_net(sk)))
172 return false;
173
174 *dest = sock_cgroup_classid(&sk->sk_cgrp_data);
175 return true;
176}
177#endif
178
179static noinline bool nft_meta_get_eval_kind(enum nft_meta_keys key,
180 u32 *dest,
181 const struct nft_pktinfo *pkt)
182{
183 const struct net_device *in = nft_in(pkt), *out = nft_out(pkt);
184
185 switch (key) {
186 case NFT_META_IIFKIND:
187 if (!in || !in->rtnl_link_ops)
188 return false;
189 strncpy((char *)dest, in->rtnl_link_ops->kind, IFNAMSIZ);
190 break;
191 case NFT_META_OIFKIND:
192 if (!out || !out->rtnl_link_ops)
193 return false;
194 strncpy((char *)dest, out->rtnl_link_ops->kind, IFNAMSIZ);
195 break;
196 default:
197 return false;
198 }
199
200 return true;
201}
202
203static void nft_meta_store_ifindex(u32 *dest, const struct net_device *dev)
204{
205 *dest = dev ? dev->ifindex : 0;
206}
207
208static void nft_meta_store_ifname(u32 *dest, const struct net_device *dev)
209{
210 strncpy((char *)dest, dev ? dev->name : "", IFNAMSIZ);
211}
212
213static bool nft_meta_store_iftype(u32 *dest, const struct net_device *dev)
214{
215 if (!dev)
216 return false;
217
218 nft_reg_store16(dest, dev->type);
219 return true;
220}
221
222static bool nft_meta_store_ifgroup(u32 *dest, const struct net_device *dev)
223{
224 if (!dev)
225 return false;
226
227 *dest = dev->group;
228 return true;
229}
230
231static bool nft_meta_get_eval_ifname(enum nft_meta_keys key, u32 *dest,
232 const struct nft_pktinfo *pkt)
233{
234 switch (key) {
235 case NFT_META_IIFNAME:
236 nft_meta_store_ifname(dest, nft_in(pkt));
237 break;
238 case NFT_META_OIFNAME:
239 nft_meta_store_ifname(dest, nft_out(pkt));
240 break;
241 case NFT_META_IIF:
242 nft_meta_store_ifindex(dest, nft_in(pkt));
243 break;
244 case NFT_META_OIF:
245 nft_meta_store_ifindex(dest, nft_out(pkt));
246 break;
247 case NFT_META_IIFTYPE:
248 if (!nft_meta_store_iftype(dest, nft_in(pkt)))
249 return false;
250 break;
251 case NFT_META_OIFTYPE:
252 if (!nft_meta_store_iftype(dest, nft_out(pkt)))
253 return false;
254 break;
255 case NFT_META_IIFGROUP:
256 if (!nft_meta_store_ifgroup(dest, nft_out(pkt)))
257 return false;
258 break;
259 case NFT_META_OIFGROUP:
260 if (!nft_meta_store_ifgroup(dest, nft_out(pkt)))
261 return false;
262 break;
263 default:
264 return false;
265 }
266
267 return true;
268}
269
270static noinline u32 nft_prandom_u32(void)
271{
272 struct rnd_state *state = this_cpu_ptr(&nft_prandom_state);
273
274 return prandom_u32_state(state);
275}
276
277#ifdef CONFIG_IP_ROUTE_CLASSID
278static noinline bool
279nft_meta_get_eval_rtclassid(const struct sk_buff *skb, u32 *dest)
280{
281 const struct dst_entry *dst = skb_dst(skb);
282
283 if (!dst)
284 return false;
285
286 *dest = dst->tclassid;
287 return true;
288}
289#endif
290
291static noinline u32 nft_meta_get_eval_sdif(const struct nft_pktinfo *pkt)
292{
293 switch (nft_pf(pkt)) {
294 case NFPROTO_IPV4:
295 return inet_sdif(pkt->skb);
296 case NFPROTO_IPV6:
297 return inet6_sdif(pkt->skb);
298 }
299
300 return 0;
301}
302
303static noinline void
304nft_meta_get_eval_sdifname(u32 *dest, const struct nft_pktinfo *pkt)
305{
306 u32 sdif = nft_meta_get_eval_sdif(pkt);
307 const struct net_device *dev;
308
309 dev = sdif ? dev_get_by_index_rcu(nft_net(pkt), sdif) : NULL;
310 nft_meta_store_ifname(dest, dev);
311}
312
59void nft_meta_get_eval(const struct nft_expr *expr,313void nft_meta_get_eval(const struct nft_expr *expr,
60 struct nft_regs *regs,314 struct nft_regs *regs,
61 const struct nft_pktinfo *pkt)315 const struct nft_pktinfo *pkt)
62{316{
63 const struct nft_meta *priv = nft_expr_priv(expr);317 const struct nft_meta *priv = nft_expr_priv(expr);
64 const struct sk_buff *skb = pkt->skb;318 const struct sk_buff *skb = pkt->skb;
65 const struct net_device *in = nft_in(pkt), *out = nft_out(pkt);
66 struct sock *sk;
67 u32 *dest = &regs->data[priv->dreg];319 u32 *dest = &regs->data[priv->dreg];
68 320
69 switch (priv->key) {321 switch (priv->key) {
@@ -88,69 +340,26 @@ void nft_meta_get_eval(const struct nft_expr *expr, · 18 unmodified lines
88 *dest = skb->mark;340 *dest = skb->mark;
89 break;341 break;
90 case NFT_META_IIF:342 case NFT_META_IIF:
91 *dest = in ? in->ifindex : 0;
92 break;
93 case NFT_META_OIF:343 case NFT_META_OIF:
94 *dest = out ? out->ifindex : 0;
95 break;
96 case NFT_META_IIFNAME:344 case NFT_META_IIFNAME:
97 strncpy((char *)dest, in ? in->name : "", IFNAMSIZ);
98 break;
99 case NFT_META_OIFNAME:345 case NFT_META_OIFNAME:
100 strncpy((char *)dest, out ? out->name : "", IFNAMSIZ);
101 break;
102 case NFT_META_IIFTYPE:346 case NFT_META_IIFTYPE:
103 if (in == NULL)
104 goto err;
105 nft_reg_store16(dest, in->type);
106 break;
107 case NFT_META_OIFTYPE:347 case NFT_META_OIFTYPE:
108 if (out == NULL)348 case NFT_META_IIFGROUP:
349 case NFT_META_OIFGROUP:
350 if (!nft_meta_get_eval_ifname(priv->key, dest, pkt))
109 goto err;351 goto err;
110 nft_reg_store16(dest, out->type);
111 break;352 break;
112 case NFT_META_SKUID:353 case NFT_META_SKUID:
113 sk = skb_to_full_sk(skb);
114 if (!sk || !sk_fullsock(sk) ||
115 !net_eq(nft_net(pkt), sock_net(sk)))
116 goto err;
117
118 read_lock_bh(&sk->sk_callback_lock);
119 if (sk->sk_socket == NULL ||
120 sk->sk_socket->file == NULL) {
121 read_unlock_bh(&sk->sk_callback_lock);
122 goto err;
123 }
124
125 *dest = from_kuid_munged(&init_user_ns,
126 sk->sk_socket->file->f_cred->fsuid);
127 read_unlock_bh(&sk->sk_callback_lock);
128 break;
129 case NFT_META_SKGID:354 case NFT_META_SKGID:
130 sk = skb_to_full_sk(skb);355 if (!nft_meta_get_eval_skugid(priv->key, dest, pkt))
131 if (!sk || !sk_fullsock(sk) ||
132 !net_eq(nft_net(pkt), sock_net(sk)))
133 goto err;356 goto err;
134
135 read_lock_bh(&sk->sk_callback_lock);
136 if (sk->sk_socket == NULL ||
137 sk->sk_socket->file == NULL) {
138 read_unlock_bh(&sk->sk_callback_lock);
139 goto err;
140 }
141 *dest = from_kgid_munged(&init_user_ns,
142 sk->sk_socket->file->f_cred->fsgid);
143 read_unlock_bh(&sk->sk_callback_lock);
144 break;357 break;
145#ifdef CONFIG_IP_ROUTE_CLASSID358#ifdef CONFIG_IP_ROUTE_CLASSID
146 case NFT_META_RTCLASSID: {359 case NFT_META_RTCLASSID:
147 const struct dst_entry *dst = skb_dst(skb);360 if (!nft_meta_get_eval_rtclassid(skb, dest))
148
149 if (dst == NULL)
150 goto err;361 goto err;
151 *dest = dst->tclassid;
152 break;362 break;
153 }
154#endif363#endif
155#ifdef CONFIG_NETWORK_SECMARK364#ifdef CONFIG_NETWORK_SECMARK
156 case NFT_META_SECMARK:365 case NFT_META_SECMARK:
@@ -163,97 +372,41 @@ void nft_meta_get_eval(const struct nft_expr *expr, · 6 unmodified lines
163 break;372 break;
164 }373 }
165 374
166 switch (nft_pf(pkt)) {375 if (!nft_meta_get_eval_pkttype_lo(pkt, dest))
167 case NFPROTO_IPV4:
168 if (ipv4_is_multicast(ip_hdr(skb)->daddr))
169 nft_reg_store8(dest, PACKET_MULTICAST);
170 else
171 nft_reg_store8(dest, PACKET_BROADCAST);
172 break;
173 case NFPROTO_IPV6:
174 nft_reg_store8(dest, PACKET_MULTICAST);
175 break;
176 case NFPROTO_NETDEV:
177 switch (skb->protocol) {
178 case htons(ETH_P_IP): {
179 int noff = skb_network_offset(skb);
180 struct iphdr *iph, _iph;
181
182 iph = skb_header_pointer(skb, noff,
183 sizeof(_iph), &_iph);
184 if (!iph)
185 goto err;
186
187 if (ipv4_is_multicast(iph->daddr))
188 nft_reg_store8(dest, PACKET_MULTICAST);
189 else
190 nft_reg_store8(dest, PACKET_BROADCAST);
191
192 break;
193 }
194 case htons(ETH_P_IPV6):
195 nft_reg_store8(dest, PACKET_MULTICAST);
196 break;
197 default:
198 WARN_ON_ONCE(1);
199 goto err;
200 }
201 break;
202 default:
203 WARN_ON_ONCE(1);
204 goto err;376 goto err;
205 }
206 break;377 break;
207 case NFT_META_CPU:378 case NFT_META_CPU:
208 *dest = raw_smp_processor_id();379 *dest = raw_smp_processor_id();
209 break;380 break;
210 case NFT_META_IIFGROUP:
211 if (in == NULL)
212 goto err;
213 *dest = in->group;
214 break;
215 case NFT_META_OIFGROUP:
216 if (out == NULL)
217 goto err;
218 *dest = out->group;
219 break;
220#ifdef CONFIG_CGROUP_NET_CLASSID381#ifdef CONFIG_CGROUP_NET_CLASSID
221 case NFT_META_CGROUP:382 case NFT_META_CGROUP:
222 sk = skb_to_full_sk(skb);383 if (!nft_meta_get_eval_cgroup(dest, pkt))
223 if (!sk || !sk_fullsock(sk) ||
224 !net_eq(nft_net(pkt), sock_net(sk)))
225 goto err;384 goto err;
226 *dest = sock_cgroup_classid(&sk->sk_cgrp_data);
227 break;385 break;
228#endif386#endif
229 case NFT_META_PRANDOM: {387 case NFT_META_PRANDOM:
230 struct rnd_state *state = this_cpu_ptr(&nft_prandom_state);388 *dest = nft_prandom_u32();
231 *dest = prandom_u32_state(state);
232 break;389 break;
233 }
234#ifdef CONFIG_XFRM390#ifdef CONFIG_XFRM
235 case NFT_META_SECPATH:391 case NFT_META_SECPATH:
236 nft_reg_store8(dest, secpath_exists(skb));392 nft_reg_store8(dest, secpath_exists(skb));
237 break;393 break;
238#endif394#endif
239 case NFT_META_IIFKIND:395 case NFT_META_IIFKIND:
240 if (in == NULL || in->rtnl_link_ops == NULL)
241 goto err;
242 strncpy((char *)dest, in->rtnl_link_ops->kind, IFNAMSIZ);
243 break;
244 case NFT_META_OIFKIND:396 case NFT_META_OIFKIND:
245 if (out == NULL || out->rtnl_link_ops == NULL)397 if (!nft_meta_get_eval_kind(priv->key, dest, pkt))
246 goto err;398 goto err;
247 strncpy((char *)dest, out->rtnl_link_ops->kind, IFNAMSIZ);
248 break;399 break;
249 case NFT_META_TIME_NS:400 case NFT_META_TIME_NS:
250 nft_reg_store64(dest, ktime_get_real_ns());
251 break;
252 case NFT_META_TIME_DAY:401 case NFT_META_TIME_DAY:
253 nft_reg_store8(dest, nft_meta_weekday(ktime_get_real_seconds()));
254 break;
255 case NFT_META_TIME_HOUR:402 case NFT_META_TIME_HOUR:
256 *dest = nft_meta_hour(ktime_get_real_seconds());403 nft_meta_get_eval_time(priv->key, dest);
404 break;
405 case NFT_META_SDIF:
406 *dest = nft_meta_get_eval_sdif(pkt);
407 break;
408 case NFT_META_SDIFNAME:
409 nft_meta_get_eval_sdifname(dest, pkt);
257 break;410 break;
258 default:411 default:
259 WARN_ON(1);412 WARN_ON(1);
@@ -335,6 +488,7 @@ int nft_meta_get_init(const struct nft_ctx *ctx, · 75 unmodified lines
335 case NFT_META_MARK:488 case NFT_META_MARK:
336 case NFT_META_IIF:489 case NFT_META_IIF:
337 case NFT_META_OIF:490 case NFT_META_OIF:
491 case NFT_META_SDIF:
338 case NFT_META_SKUID:492 case NFT_META_SKUID:
339 case NFT_META_SKGID:493 case NFT_META_SKGID:
340#ifdef CONFIG_IP_ROUTE_CLASSID494#ifdef CONFIG_IP_ROUTE_CLASSID
@@ -356,6 +510,7 @@ int nft_meta_get_init(const struct nft_ctx *ctx, · 15 unmodified lines
356 case NFT_META_OIFNAME:510 case NFT_META_OIFNAME:
357 case NFT_META_IIFKIND:511 case NFT_META_IIFKIND:
358 case NFT_META_OIFKIND:512 case NFT_META_OIFKIND:
513 case NFT_META_SDIFNAME:
359 len = IFNAMSIZ;514 len = IFNAMSIZ;
360 break;515 break;
361 case NFT_META_PRANDOM:516 case NFT_META_PRANDOM:
@@ -386,16 +541,28 @@ int nft_meta_get_init(const struct nft_ctx *ctx, · 24 unmodified lines
386}541}
387EXPORT_SYMBOL_GPL(nft_meta_get_init);542EXPORT_SYMBOL_GPL(nft_meta_get_init);
388 543
389static int nft_meta_get_validate(const struct nft_ctx *ctx,544static int nft_meta_get_validate_sdif(const struct nft_ctx *ctx)
390 const struct nft_expr *expr,
391 const struct nft_data **data)
392{545{
393#ifdef CONFIG_XFRM
394 const struct nft_meta *priv = nft_expr_priv(expr);
395 unsigned int hooks;546 unsigned int hooks;
396 547
397 if (priv->key != NFT_META_SECPATH)548 switch (ctx->family) {
398 return 0;549 case NFPROTO_IPV4:
550 case NFPROTO_IPV6:
551 case NFPROTO_INET:
552 hooks = (1 << NF_INET_LOCAL_IN) |
553 (1 << NF_INET_FORWARD);
554 break;
555 default:
556 return -EOPNOTSUPP;
557 }
558
559 return nft_chain_validate_hooks(ctx->chain, hooks);
560}
561
562static int nft_meta_get_validate_xfrm(const struct nft_ctx *ctx)
563{
564#ifdef CONFIG_XFRM
565 unsigned int hooks;
399 566
400 switch (ctx->family) {567 switch (ctx->family) {
401 case NFPROTO_NETDEV:568 case NFPROTO_NETDEV:
@@ -418,6 +585,25 @@ static int nft_meta_get_validate(const struct nft_ctx *ctx, · 16 unmodified lines
418#endif585#endif
419}586}
420 587
588static int nft_meta_get_validate(const struct nft_ctx *ctx,
589 const struct nft_expr *expr,
590 const struct nft_data **data)
591{
592 const struct nft_meta *priv = nft_expr_priv(expr);
593
594 switch (priv->key) {
595 case NFT_META_SECPATH:
596 return nft_meta_get_validate_xfrm(ctx);
597 case NFT_META_SDIF:
598 case NFT_META_SDIFNAME:
599 return nft_meta_get_validate_sdif(ctx);
600 default:
601 break;
602 }
603
604 return 0;
605}
606
421int nft_meta_set_validate(const struct nft_ctx *ctx,607int nft_meta_set_validate(const struct nft_ctx *ctx,
422 const struct nft_expr *expr,608 const struct nft_expr *expr,
423 const struct nft_data **data)609 const struct nft_data **data)
net/netfilter/nft_tunnel.c+39−13
@@ -248,8 +248,9 @@ static int nft_tunnel_obj_vxlan_init(const struct nlattr *attr, · 247 unmodified lines
248}248}
249 249
250static const struct nla_policy nft_tunnel_opts_erspan_policy[NFTA_TUNNEL_KEY_ERSPAN_MAX + 1] = {250static const struct nla_policy nft_tunnel_opts_erspan_policy[NFTA_TUNNEL_KEY_ERSPAN_MAX + 1] = {
251 [NFTA_TUNNEL_KEY_ERSPAN_VERSION] = { .type = NLA_U32 },
251 [NFTA_TUNNEL_KEY_ERSPAN_V1_INDEX] = { .type = NLA_U32 },252 [NFTA_TUNNEL_KEY_ERSPAN_V1_INDEX] = { .type = NLA_U32 },
252 [NFTA_TUNNEL_KEY_ERSPAN_V2_DIR] = { .type = NLA_U8 },253 [NFTA_TUNNEL_KEY_ERSPAN_V2_DIR] = { .type = NLA_U8 },
253 [NFTA_TUNNEL_KEY_ERSPAN_V2_HWID] = { .type = NLA_U8 },254 [NFTA_TUNNEL_KEY_ERSPAN_V2_HWID] = { .type = NLA_U8 },
254};255};
255 256
@@ -442,10 +443,15 @@ static int nft_tunnel_ip_dump(struct sk_buff *skb, struct ip_tunnel_info *info) · 186 unmodified lines
442 if (!nest)443 if (!nest)
443 return -1;444 return -1;
444 445
445 if (nla_put_in6_addr(skb, NFTA_TUNNEL_KEY_IP6_SRC, &info->key.u.ipv6.src) < 0 ||446 if (nla_put_in6_addr(skb, NFTA_TUNNEL_KEY_IP6_SRC,
446 nla_put_in6_addr(skb, NFTA_TUNNEL_KEY_IP6_DST, &info->key.u.ipv6.dst) < 0 ||447 &info->key.u.ipv6.src) < 0 ||
447 nla_put_be32(skb, NFTA_TUNNEL_KEY_IP6_FLOWLABEL, info->key.label))448 nla_put_in6_addr(skb, NFTA_TUNNEL_KEY_IP6_DST,
449 &info->key.u.ipv6.dst) < 0 ||
450 nla_put_be32(skb, NFTA_TUNNEL_KEY_IP6_FLOWLABEL,
451 info->key.label)) {
452 nla_nest_cancel(skb, nest);
448 return -1;453 return -1;
454 }
449 455
450 nla_nest_end(skb, nest);456 nla_nest_end(skb, nest);
451 } else {457 } else {
@@ -453,9 +459,13 @@ static int nft_tunnel_ip_dump(struct sk_buff *skb, struct ip_tunnel_info *info) · 1 unmodified line
453 if (!nest)459 if (!nest)
454 return -1;460 return -1;
455 461
456 if (nla_put_in_addr(skb, NFTA_TUNNEL_KEY_IP_SRC, info->key.u.ipv4.src) < 0 ||462 if (nla_put_in_addr(skb, NFTA_TUNNEL_KEY_IP_SRC,
457 nla_put_in_addr(skb, NFTA_TUNNEL_KEY_IP_DST, info->key.u.ipv4.dst) < 0)463 info->key.u.ipv4.src) < 0 ||
464 nla_put_in_addr(skb, NFTA_TUNNEL_KEY_IP_DST,
465 info->key.u.ipv4.dst) < 0) {
466 nla_nest_cancel(skb, nest);
458 return -1;467 return -1;
468 }
459 469
460 nla_nest_end(skb, nest);470 nla_nest_end(skb, nest);
461 }471 }
@@ -467,42 +477,58 @@ static int nft_tunnel_opts_dump(struct sk_buff *skb, · 5 unmodified lines
467 struct nft_tunnel_obj *priv)477 struct nft_tunnel_obj *priv)
468{478{
469 struct nft_tunnel_opts *opts = &priv->opts;479 struct nft_tunnel_opts *opts = &priv->opts;
470 struct nlattr *nest;480 struct nlattr *nest, *inner;
471 481
472 nest = nla_nest_start_noflag(skb, NFTA_TUNNEL_KEY_OPTS);482 nest = nla_nest_start_noflag(skb, NFTA_TUNNEL_KEY_OPTS);
473 if (!nest)483 if (!nest)
474 return -1;484 return -1;
475 485
476 if (opts->flags & TUNNEL_VXLAN_OPT) {486 if (opts->flags & TUNNEL_VXLAN_OPT) {
487 inner = nla_nest_start_noflag(skb, NFTA_TUNNEL_KEY_OPTS_VXLAN);
488 if (!inner)
489 goto failure;
477 if (nla_put_be32(skb, NFTA_TUNNEL_KEY_VXLAN_GBP,490 if (nla_put_be32(skb, NFTA_TUNNEL_KEY_VXLAN_GBP,
478 htonl(opts->u.vxlan.gbp)))491 htonl(opts->u.vxlan.gbp)))
479 return -1;492 goto inner_failure;
493 nla_nest_end(skb, inner);
480 } else if (opts->flags & TUNNEL_ERSPAN_OPT) {494 } else if (opts->flags & TUNNEL_ERSPAN_OPT) {
495 inner = nla_nest_start_noflag(skb, NFTA_TUNNEL_KEY_OPTS_ERSPAN);
496 if (!inner)
497 goto failure;
498 if (nla_put_be32(skb, NFTA_TUNNEL_KEY_ERSPAN_VERSION,
499 htonl(opts->u.erspan.version)))
500 goto inner_failure;
481 switch (opts->u.erspan.version) {501 switch (opts->u.erspan.version) {
482 case ERSPAN_VERSION:502 case ERSPAN_VERSION:
483 if (nla_put_be32(skb, NFTA_TUNNEL_KEY_ERSPAN_V1_INDEX,503 if (nla_put_be32(skb, NFTA_TUNNEL_KEY_ERSPAN_V1_INDEX,
484 opts->u.erspan.u.index))504 opts->u.erspan.u.index))
485 return -1;505 goto inner_failure;
486 break;506 break;
487 case ERSPAN_VERSION2:507 case ERSPAN_VERSION2:
488 if (nla_put_u8(skb, NFTA_TUNNEL_KEY_ERSPAN_V2_HWID,508 if (nla_put_u8(skb, NFTA_TUNNEL_KEY_ERSPAN_V2_HWID,
489 get_hwid(&opts->u.erspan.u.md2)) ||509 get_hwid(&opts->u.erspan.u.md2)) ||
490 nla_put_u8(skb, NFTA_TUNNEL_KEY_ERSPAN_V2_DIR,510 nla_put_u8(skb, NFTA_TUNNEL_KEY_ERSPAN_V2_DIR,
491 opts->u.erspan.u.md2.dir))511 opts->u.erspan.u.md2.dir))
492 return -1;512 goto inner_failure;
493 break;513 break;
494 }514 }
515 nla_nest_end(skb, inner);
495 }516 }
496 nla_nest_end(skb, nest);517 nla_nest_end(skb, nest);
497
498 return 0;518 return 0;
519
520inner_failure:
521 nla_nest_cancel(skb, inner);
522failure:
523 nla_nest_cancel(skb, nest);
524 return -1;
499}525}
500 526
501static int nft_tunnel_ports_dump(struct sk_buff *skb,527static int nft_tunnel_ports_dump(struct sk_buff *skb,
502 struct ip_tunnel_info *info)528 struct ip_tunnel_info *info)
503{529{
504 if (nla_put_be16(skb, NFTA_TUNNEL_KEY_SPORT, htons(info->key.tp_src)) < 0 ||530 if (nla_put_be16(skb, NFTA_TUNNEL_KEY_SPORT, info->key.tp_src) < 0 ||
505 nla_put_be16(skb, NFTA_TUNNEL_KEY_DPORT, htons(info->key.tp_dst)) < 0)531 nla_put_be16(skb, NFTA_TUNNEL_KEY_DPORT, info->key.tp_dst) < 0)
506 return -1;532 return -1;
507 533
508 return 0;534 return 0;