| @@ -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 | |
| 34 | static DEFINE_PER_CPU(struct rnd_state, nft_prandom_state); | 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 | 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 | |
| | 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 | void nft_meta_get_eval(const struct nft_expr *expr, | 313 | void 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 = ®s->data[priv->dreg]; | 319 | u32 *dest = ®s->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_CLASSID | 358 | #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 | #endif | 363 | #endif |
| 155 | #ifdef CONFIG_NETWORK_SECMARK | 364 | #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_CLASSID | 381 | #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 | #endif | 386 | #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_XFRM | 390 | #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 | #endif | 394 | #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_CLASSID | 494 | #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 | } |
| 387 | EXPORT_SYMBOL_GPL(nft_meta_get_init); | 542 | EXPORT_SYMBOL_GPL(nft_meta_get_init); |
| 388 | | 543 | |
| 389 | static int nft_meta_get_validate(const struct nft_ctx *ctx, | 544 | static 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 | |
| | 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 | 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 | #endif | 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 | int nft_meta_set_validate(const struct nft_ctx *ctx, | 607 | int 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) |