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
16471647 };
16481648 #define NFTA_TUNNEL_KEY_MAX (__NFTA_TUNNEL_KEY_MAX - 1)
16491649
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+
16501665 #endif /* _LINUX_NF_TABLES_H */
net/netfilter/nft_tunnel.c+111−1
@@ -12,6 +12,104 @@ · 11 unmodified lines
1212 #include <net/vxlan.h>
1313 #include <net/erspan.h>
1414
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 = &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+
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+
15113 struct nft_tunnel_opts {
16114 union {
17115 struct vxlan_metadata vxlan;
@@ -442,12 +540,23 @@ static struct nft_object_type nft_tunnel_obj_type __read_mostly = { · 424 unmodified lines
442540
443541 static int __init nft_tunnel_module_init(void)
444542 {
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;
446554 }
447555
448556 static void __exit nft_tunnel_module_exit(void)
449557 {
450558 nft_unregister_obj(&nft_tunnel_obj_type);
559+ nft_unregister_expr(&nft_tunnel_type);
451560 }
452561
453562 module_init(nft_tunnel_module_init);
@@ -455,4 +564,5 @@ module_exit(nft_tunnel_module_exit); · 1 unmodified line
455564
456565 MODULE_LICENSE("GPL");
457566 MODULE_AUTHOR("Pablo Neira Ayuso <pablo@netfilter.org>");
567+MODULE_ALIAS_NFT_EXPR("tunnel");
458568 MODULE_ALIAS_NFT_OBJ(NFT_OBJECT_TUNNEL);