This patch allows us to match on the tunnel metadata that is available of the packet. We can use this to validate if the packet comes from/goes to tunnel and the corresponding tunnel ID.
Unified · Split
| @@ -1647,4 +1647,19 @@ enum nft_tunnel_key_attributes { · 1646 unmodified lines | |||
| 1647 | }; | 1647 | }; |
| 1648 | #define NFTA_TUNNEL_KEY_MAX (__NFTA_TUNNEL_KEY_MAX - 1) | 1648 | #define NFTA_TUNNEL_KEY_MAX (__NFTA_TUNNEL_KEY_MAX - 1) |
| 1649 | 1649 | ||
| 1650 | enum nft_tunnel_keys { | ||
| 1651 | NFT_TUNNEL_PATH, | ||
| 1652 | NFT_TUNNEL_ID, | ||
| 1653 | __NFT_TUNNEL_MAX | ||
| 1654 | }; | ||
| 1655 | #define NFT_TUNNEL_MAX (__NFT_TUNNEL_MAX - 1) | ||
| 1656 | |||
| 1657 | enum nft_tunnel_attributes { | ||
| 1658 | NFTA_TUNNEL_UNSPEC, | ||
| 1659 | NFTA_TUNNEL_KEY, | ||
| 1660 | NFTA_TUNNEL_DREG, | ||
| 1661 | __NFTA_TUNNEL_MAX | ||
| 1662 | }; | ||
| 1663 | #define NFTA_TUNNEL_MAX (__NFTA_TUNNEL_MAX - 1) | ||
| 1664 | |||
| 1650 | #endif /* _LINUX_NF_TABLES_H */ | 1665 | #endif /* _LINUX_NF_TABLES_H */ |
| @@ -12,6 +12,104 @@ · 11 unmodified lines | |||
| 12 | #include <net/vxlan.h> | 12 | #include <net/vxlan.h> |
| 13 | #include <net/erspan.h> | 13 | #include <net/erspan.h> |
| 14 | 14 | ||
| 15 | struct nft_tunnel { | ||
| 16 | enum nft_tunnel_keys key:8; | ||
| 17 | enum nft_registers dreg:8; | ||
| 18 | }; | ||
| 19 | |||
| 20 | static void nft_tunnel_get_eval(const struct nft_expr *expr, | ||
| 21 | struct nft_regs *regs, | ||
| 22 | const struct nft_pktinfo *pkt) | ||
| 23 | { | ||
| 24 | const struct nft_tunnel *priv = nft_expr_priv(expr); | ||
| 25 | u32 *dest = ®s->data[priv->dreg]; | ||
| 26 | struct ip_tunnel_info *tun_info; | ||
| 27 | |||
| 28 | tun_info = skb_tunnel_info(pkt->skb); | ||
| 29 | |||
| 30 | switch (priv->key) { | ||
| 31 | case NFT_TUNNEL_PATH: | ||
| 32 | nft_reg_store8(dest, !!tun_info); | ||
| 33 | break; | ||
| 34 | case NFT_TUNNEL_ID: | ||
| 35 | if (!tun_info) { | ||
| 36 | regs->verdict.code = NFT_BREAK; | ||
| 37 | return; | ||
| 38 | } | ||
| 39 | *dest = ntohl(tunnel_id_to_key32(tun_info->key.tun_id)); | ||
| 40 | break; | ||
| 41 | default: | ||
| 42 | WARN_ON(1); | ||
| 43 | regs->verdict.code = NFT_BREAK; | ||
| 44 | } | ||
| 45 | } | ||
| 46 | |||
| 47 | static const struct nla_policy nft_tunnel_policy[NFTA_TUNNEL_MAX + 1] = { | ||
| 48 | [NFTA_TUNNEL_KEY] = { .type = NLA_U32 }, | ||
| 49 | [NFTA_TUNNEL_DREG] = { .type = NLA_U32 }, | ||
| 50 | }; | ||
| 51 | |||
| 52 | static int nft_tunnel_get_init(const struct nft_ctx *ctx, | ||
| 53 | const struct nft_expr *expr, | ||
| 54 | const struct nlattr * const tb[]) | ||
| 55 | { | ||
| 56 | struct nft_tunnel *priv = nft_expr_priv(expr); | ||
| 57 | u32 len; | ||
| 58 | |||
| 59 | if (!tb[NFTA_TUNNEL_KEY] && | ||
| 60 | !tb[NFTA_TUNNEL_DREG]) | ||
| 61 | return -EINVAL; | ||
| 62 | |||
| 63 | priv->key = ntohl(nla_get_be32(tb[NFTA_TUNNEL_KEY])); | ||
| 64 | switch (priv->key) { | ||
| 65 | case NFT_TUNNEL_PATH: | ||
| 66 | len = sizeof(u8); | ||
| 67 | break; | ||
| 68 | case NFT_TUNNEL_ID: | ||
| 69 | len = sizeof(u32); | ||
| 70 | break; | ||
| 71 | default: | ||
| 72 | return -EOPNOTSUPP; | ||
| 73 | } | ||
| 74 | |||
| 75 | priv->dreg = nft_parse_register(tb[NFTA_TUNNEL_DREG]); | ||
| 76 | |||
| 77 | return nft_validate_register_store(ctx, priv->dreg, NULL, | ||
| 78 | NFT_DATA_VALUE, len); | ||
| 79 | } | ||
| 80 | |||
| 81 | static int nft_tunnel_get_dump(struct sk_buff *skb, | ||
| 82 | const struct nft_expr *expr) | ||
| 83 | { | ||
| 84 | const struct nft_tunnel *priv = nft_expr_priv(expr); | ||
| 85 | |||
| 86 | if (nla_put_be32(skb, NFTA_TUNNEL_KEY, htonl(priv->key))) | ||
| 87 | goto nla_put_failure; | ||
| 88 | if (nft_dump_register(skb, NFTA_TUNNEL_DREG, priv->dreg)) | ||
| 89 | goto nla_put_failure; | ||
| 90 | return 0; | ||
| 91 | |||
| 92 | nla_put_failure: | ||
| 93 | return -1; | ||
| 94 | } | ||
| 95 | |||
| 96 | static struct nft_expr_type nft_tunnel_type; | ||
| 97 | static const struct nft_expr_ops nft_tunnel_get_ops = { | ||
| 98 | .type = &nft_tunnel_type, | ||
| 99 | .size = NFT_EXPR_SIZE(sizeof(struct nft_tunnel)), | ||
| 100 | .eval = nft_tunnel_get_eval, | ||
| 101 | .init = nft_tunnel_get_init, | ||
| 102 | .dump = nft_tunnel_get_dump, | ||
| 103 | }; | ||
| 104 | |||
| 105 | static struct nft_expr_type nft_tunnel_type __read_mostly = { | ||
| 106 | .name = "tunnel", | ||
| 107 | .ops = &nft_tunnel_get_ops, | ||
| 108 | .policy = nft_tunnel_policy, | ||
| 109 | .maxattr = NFTA_TUNNEL_MAX, | ||
| 110 | .owner = THIS_MODULE, | ||
| 111 | }; | ||
| 112 | |||
| 15 | struct nft_tunnel_opts { | 113 | struct nft_tunnel_opts { |
| 16 | union { | 114 | union { |
| 17 | struct vxlan_metadata vxlan; | 115 | struct vxlan_metadata vxlan; |
| @@ -442,12 +540,23 @@ static struct nft_object_type nft_tunnel_obj_type __read_mostly = { · 424 unmodified lines | |||
| 442 | 540 | ||
| 443 | static int __init nft_tunnel_module_init(void) | 541 | static int __init nft_tunnel_module_init(void) |
| 444 | { | 542 | { |
| 445 | return nft_register_obj(&nft_tunnel_obj_type); | 543 | int err; |
| 544 | |||
| 545 | err = nft_register_expr(&nft_tunnel_type); | ||
| 546 | if (err < 0) | ||
| 547 | return err; | ||
| 548 | |||
| 549 | err = nft_register_obj(&nft_tunnel_obj_type); | ||
| 550 | if (err < 0) | ||
| 551 | nft_unregister_expr(&nft_tunnel_type); | ||
| 552 | |||
| 553 | return err; | ||
| 446 | } | 554 | } |
| 447 | 555 | ||
| 448 | static void __exit nft_tunnel_module_exit(void) | 556 | static void __exit nft_tunnel_module_exit(void) |
| 449 | { | 557 | { |
| 450 | nft_unregister_obj(&nft_tunnel_obj_type); | 558 | nft_unregister_obj(&nft_tunnel_obj_type); |
| 559 | nft_unregister_expr(&nft_tunnel_type); | ||
| 451 | } | 560 | } |
| 452 | 561 | ||
| 453 | module_init(nft_tunnel_module_init); | 562 | module_init(nft_tunnel_module_init); |
| @@ -455,4 +564,5 @@ module_exit(nft_tunnel_module_exit); · 1 unmodified line | |||
| 455 | 564 | ||
| 456 | MODULE_LICENSE("GPL"); | 565 | MODULE_LICENSE("GPL"); |
| 457 | MODULE_AUTHOR("Pablo Neira Ayuso <pablo@netfilter.org>"); | 566 | MODULE_AUTHOR("Pablo Neira Ayuso <pablo@netfilter.org>"); |
| 567 | MODULE_ALIAS_NFT_EXPR("tunnel"); | ||
| 458 | MODULE_ALIAS_NFT_OBJ(NFT_OBJECT_TUNNEL); | 568 | MODULE_ALIAS_NFT_OBJ(NFT_OBJECT_TUNNEL); |