| @@ -17,6 +17,7 @@ · 16 unmodified lines |
| 17 | 17 | #include <linux/smp.h> |
| 18 | 18 | #include <linux/static_key.h> |
| 19 | 19 | #include <net/dst.h> |
| 20 | +#include <net/ip.h> |
| 20 | 21 | #include <net/sock.h> |
| 21 | 22 | #include <net/tcp_states.h> /* for TCP_TIME_WAIT */ |
| 22 | 23 | #include <net/netfilter/nf_tables.h> |
| @@ -33,8 +34,9 @@ · 10 unmodified lines |
| 33 | 34 | |
| 34 | 35 | static DEFINE_PER_CPU(struct rnd_state, nft_prandom_state); |
| 35 | 36 | |
| 36 | | −static u8 nft_meta_weekday(time64_t secs) |
| 37 | +static u8 nft_meta_weekday(void) |
| 37 | 38 | { |
| 39 | + time64_t secs = ktime_get_real_seconds(); |
| 38 | 40 | unsigned int dse; |
| 39 | 41 | u8 wday; |
| 40 | 42 | |
| @@ -56,14 +58,264 @@ static u32 nft_meta_hour(time64_t secs) · 15 unmodified lines |
| 56 | 58 | + tm.tm_sec; |
| 57 | 59 | } |
| 58 | 60 | |
| 61 | +static noinline_for_stack void |
| 62 | +nft_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 | + |
| 80 | +static noinline bool |
| 81 | +nft_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 | + |
| 130 | +static noinline bool |
| 131 | +nft_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 |
| 166 | +static noinline bool |
| 167 | +nft_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 | + |
| 179 | +static 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 | + |
| 203 | +static void nft_meta_store_ifindex(u32 *dest, const struct net_device *dev) |
| 204 | +{ |
| 205 | + *dest = dev ? dev->ifindex : 0; |
| 206 | +} |
| 207 | + |
| 208 | +static void nft_meta_store_ifname(u32 *dest, const struct net_device *dev) |
| 209 | +{ |
| 210 | + strncpy((char *)dest, dev ? dev->name : "", IFNAMSIZ); |
| 211 | +} |
| 212 | + |
| 213 | +static 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 | + |
| 222 | +static 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 | + |
| 231 | +static 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 | + |
| 270 | +static 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 |
| 278 | +static noinline bool |
| 279 | +nft_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 | + |
| 291 | +static 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 | + |
| 303 | +static noinline void |
| 304 | +nft_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 | + |
| 59 | 313 | void nft_meta_get_eval(const struct nft_expr *expr, |
| 60 | 314 | struct nft_regs *regs, |
| 61 | 315 | const struct nft_pktinfo *pkt) |
| 62 | 316 | { |
| 63 | 317 | const struct nft_meta *priv = nft_expr_priv(expr); |
| 64 | 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 | 319 | u32 *dest = ®s->data[priv->dreg]; |
| 68 | 320 | |
| 69 | 321 | switch (priv->key) { |
| @@ -88,69 +340,26 @@ void nft_meta_get_eval(const struct nft_expr *expr, · 18 unmodified lines |
| 88 | 340 | *dest = skb->mark; |
| 89 | 341 | break; |
| 90 | 342 | case NFT_META_IIF: |
| 91 | | − *dest = in ? in->ifindex : 0; |
| 92 | | − break; |
| 93 | 343 | case NFT_META_OIF: |
| 94 | | − *dest = out ? out->ifindex : 0; |
| 95 | | − break; |
| 96 | 344 | case NFT_META_IIFNAME: |
| 97 | | − strncpy((char *)dest, in ? in->name : "", IFNAMSIZ); |
| 98 | | − break; |
| 99 | 345 | case NFT_META_OIFNAME: |
| 100 | | − strncpy((char *)dest, out ? out->name : "", IFNAMSIZ); |
| 101 | | − break; |
| 102 | 346 | case NFT_META_IIFTYPE: |
| 103 | | − if (in == NULL) |
| 104 | | − goto err; |
| 105 | | − nft_reg_store16(dest, in->type); |
| 106 | | − break; |
| 107 | 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 | 351 | goto err; |
| 110 | | − nft_reg_store16(dest, out->type); |
| 111 | 352 | break; |
| 112 | 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 | 354 | case NFT_META_SKGID: |
| 130 | | − sk = skb_to_full_sk(skb); |
| 131 | | − if (!sk || !sk_fullsock(sk) || |
| 132 | | − !net_eq(nft_net(pkt), sock_net(sk))) |
| 355 | + if (!nft_meta_get_eval_skugid(priv->key, dest, pkt)) |
| 133 | 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 | 357 | break; |
| 145 | 358 | #ifdef CONFIG_IP_ROUTE_CLASSID |
| 146 | | − case NFT_META_RTCLASSID: { |
| 147 | | − const struct dst_entry *dst = skb_dst(skb); |
| 148 | | − |
| 149 | | − if (dst == NULL) |
| 359 | + case NFT_META_RTCLASSID: |
| 360 | + if (!nft_meta_get_eval_rtclassid(skb, dest)) |
| 150 | 361 | goto err; |
| 151 | | − *dest = dst->tclassid; |
| 152 | 362 | break; |
| 153 | | − } |
| 154 | 363 | #endif |
| 155 | 364 | #ifdef CONFIG_NETWORK_SECMARK |
| 156 | 365 | case NFT_META_SECMARK: |
| @@ -163,97 +372,41 @@ void nft_meta_get_eval(const struct nft_expr *expr, · 6 unmodified lines |
| 163 | 372 | break; |
| 164 | 373 | } |
| 165 | 374 | |
| 166 | | − switch (nft_pf(pkt)) { |
| 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); |
| 375 | + if (!nft_meta_get_eval_pkttype_lo(pkt, dest)) |
| 204 | 376 | goto err; |
| 205 | | − } |
| 206 | 377 | break; |
| 207 | 378 | case NFT_META_CPU: |
| 208 | 379 | *dest = raw_smp_processor_id(); |
| 209 | 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 | 381 | #ifdef CONFIG_CGROUP_NET_CLASSID |
| 221 | 382 | case NFT_META_CGROUP: |
| 222 | | − sk = skb_to_full_sk(skb); |
| 223 | | − if (!sk || !sk_fullsock(sk) || |
| 224 | | − !net_eq(nft_net(pkt), sock_net(sk))) |
| 383 | + if (!nft_meta_get_eval_cgroup(dest, pkt)) |
| 225 | 384 | goto err; |
| 226 | | − *dest = sock_cgroup_classid(&sk->sk_cgrp_data); |
| 227 | 385 | break; |
| 228 | 386 | #endif |
| 229 | | − case NFT_META_PRANDOM: { |
| 230 | | − struct rnd_state *state = this_cpu_ptr(&nft_prandom_state); |
| 231 | | − *dest = prandom_u32_state(state); |
| 387 | + case NFT_META_PRANDOM: |
| 388 | + *dest = nft_prandom_u32(); |
| 232 | 389 | break; |
| 233 | | − } |
| 234 | 390 | #ifdef CONFIG_XFRM |
| 235 | 391 | case NFT_META_SECPATH: |
| 236 | 392 | nft_reg_store8(dest, secpath_exists(skb)); |
| 237 | 393 | break; |
| 238 | 394 | #endif |
| 239 | 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 | 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 | 398 | goto err; |
| 247 | | − strncpy((char *)dest, out->rtnl_link_ops->kind, IFNAMSIZ); |
| 248 | 399 | break; |
| 249 | 400 | case NFT_META_TIME_NS: |
| 250 | | − nft_reg_store64(dest, ktime_get_real_ns()); |
| 251 | | − break; |
| 252 | 401 | case NFT_META_TIME_DAY: |
| 253 | | − nft_reg_store8(dest, nft_meta_weekday(ktime_get_real_seconds())); |
| 254 | | − break; |
| 255 | 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 | 410 | break; |
| 258 | 411 | default: |
| 259 | 412 | WARN_ON(1); |
| @@ -335,6 +488,7 @@ int nft_meta_get_init(const struct nft_ctx *ctx, · 75 unmodified lines |
| 335 | 488 | case NFT_META_MARK: |
| 336 | 489 | case NFT_META_IIF: |
| 337 | 490 | case NFT_META_OIF: |
| 491 | + case NFT_META_SDIF: |
| 338 | 492 | case NFT_META_SKUID: |
| 339 | 493 | case NFT_META_SKGID: |
| 340 | 494 | #ifdef CONFIG_IP_ROUTE_CLASSID |
| @@ -356,6 +510,7 @@ int nft_meta_get_init(const struct nft_ctx *ctx, · 15 unmodified lines |
| 356 | 510 | case NFT_META_OIFNAME: |
| 357 | 511 | case NFT_META_IIFKIND: |
| 358 | 512 | case NFT_META_OIFKIND: |
| 513 | + case NFT_META_SDIFNAME: |
| 359 | 514 | len = IFNAMSIZ; |
| 360 | 515 | break; |
| 361 | 516 | case NFT_META_PRANDOM: |
| @@ -386,16 +541,28 @@ int nft_meta_get_init(const struct nft_ctx *ctx, · 24 unmodified lines |
| 386 | 541 | } |
| 387 | 542 | EXPORT_SYMBOL_GPL(nft_meta_get_init); |
| 388 | 543 | |
| 389 | | −static int nft_meta_get_validate(const struct nft_ctx *ctx, |
| 390 | | − const struct nft_expr *expr, |
| 391 | | − const struct nft_data **data) |
| 544 | +static int nft_meta_get_validate_sdif(const struct nft_ctx *ctx) |
| 392 | 545 | { |
| 393 | | −#ifdef CONFIG_XFRM |
| 394 | | − const struct nft_meta *priv = nft_expr_priv(expr); |
| 395 | 546 | unsigned int hooks; |
| 396 | 547 | |
| 397 | | − if (priv->key != NFT_META_SECPATH) |
| 398 | | − return 0; |
| 548 | + switch (ctx->family) { |
| 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 | + |
| 562 | +static int nft_meta_get_validate_xfrm(const struct nft_ctx *ctx) |
| 563 | +{ |
| 564 | +#ifdef CONFIG_XFRM |
| 565 | + unsigned int hooks; |
| 399 | 566 | |
| 400 | 567 | switch (ctx->family) { |
| 401 | 568 | case NFPROTO_NETDEV: |
| @@ -418,6 +585,25 @@ static int nft_meta_get_validate(const struct nft_ctx *ctx, · 16 unmodified lines |
| 418 | 585 | #endif |
| 419 | 586 | } |
| 420 | 587 | |
| 588 | +static 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 | + |
| 421 | 607 | int nft_meta_set_validate(const struct nft_ctx *ctx, |
| 422 | 608 | const struct nft_expr *expr, |
| 423 | 609 | const struct nft_data **data) |