History

netfilter: nf_tables: match on tunnel metadata

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.

Pablo Neira Ayuso committed 8 years ago

Commit aaecfdb1 parent af308b92 files · +126 −1Browse files

Unified · Split

2 files
  1. include/uapi/linux/netfilter/nf_tables.h +15 −0
  2. net/netfilter/nft_tunnel.c +111 −1
include/uapi/linux/netfilter/nf_tables.h+15−0
@@ -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
1650enum 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
1657enum 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 */
net/netfilter/nft_tunnel.c+111−1
@@ -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
15struct nft_tunnel {
16 enum nft_tunnel_keys key:8;
17 enum nft_registers dreg:8;
18};
19
20static 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 = &regs->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
47static 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
52static 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
81static 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
92nla_put_failure:
93 return -1;
94}
95
96static struct nft_expr_type nft_tunnel_type;
97static 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
105static 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
15struct nft_tunnel_opts {113struct 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
443static int __init nft_tunnel_module_init(void)541static 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
448static void __exit nft_tunnel_module_exit(void)556static 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
453module_init(nft_tunnel_module_init);562module_init(nft_tunnel_module_init);
@@ -455,4 +564,5 @@ module_exit(nft_tunnel_module_exit); · 1 unmodified line
455 564
456MODULE_LICENSE("GPL");565MODULE_LICENSE("GPL");
457MODULE_AUTHOR("Pablo Neira Ayuso <pablo@netfilter.org>");566MODULE_AUTHOR("Pablo Neira Ayuso <pablo@netfilter.org>");
567MODULE_ALIAS_NFT_EXPR("tunnel");
458MODULE_ALIAS_NFT_OBJ(NFT_OBJECT_TUNNEL);568MODULE_ALIAS_NFT_OBJ(NFT_OBJECT_TUNNEL);