From: Pablo Neira Ayuso <pablo@netfilter•org>
To: netfilter-devel@vger•kernel.org
Cc: davem@davemloft•net, netdev@vger•kernel.org
Subject: [PATCH 06/31] netfilter: nf_tables: add xfrm expression
Date: Tue, 9 Oct 2018 01:01:00 +0200 [thread overview]
Message-ID: <20181008230125.2330-7-pablo@netfilter.org> (raw)
In-Reply-To: <20181008230125.2330-1-pablo@netfilter.org>
From: Florian Westphal <fw@strlen•de>
supports fetching saddr/daddr of tunnel mode states, request id and spi.
If direction is 'in', use inbound skb secpath, else dst->xfrm.
Joint work with Máté Eckl.
Signed-off-by: Florian Westphal <fw@strlen•de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter•org>
---
include/uapi/linux/netfilter/nf_tables.h | 29 +++
net/netfilter/Kconfig | 7 +
net/netfilter/Makefile | 1 +
net/netfilter/nft_xfrm.c | 293 +++++++++++++++++++++++++++++++
4 files changed, 330 insertions(+)
create mode 100644 net/netfilter/nft_xfrm.c
diff --git a/include/uapi/linux/netfilter/nf_tables.h b/include/uapi/linux/netfilter/nf_tables.h
index 6c44cbbb2cda..702e4f0bec56 100644
--- a/include/uapi/linux/netfilter/nf_tables.h
+++ b/include/uapi/linux/netfilter/nf_tables.h
@@ -1514,6 +1514,35 @@ enum nft_devices_attributes {
};
#define NFTA_DEVICE_MAX (__NFTA_DEVICE_MAX - 1)
+/*
+ * enum nft_xfrm_attributes - nf_tables xfrm expr netlink attributes
+ *
+ * @NFTA_XFRM_DREG: destination register (NLA_U32)
+ * @NFTA_XFRM_KEY: enum nft_xfrm_keys (NLA_U32)
+ * @NFTA_XFRM_DIR: direction (NLA_U8)
+ * @NFTA_XFRM_SPNUM: index in secpath array (NLA_U32)
+ */
+enum nft_xfrm_attributes {
+ NFTA_XFRM_UNSPEC,
+ NFTA_XFRM_DREG,
+ NFTA_XFRM_KEY,
+ NFTA_XFRM_DIR,
+ NFTA_XFRM_SPNUM,
+ __NFTA_XFRM_MAX
+};
+#define NFTA_XFRM_MAX (__NFTA_XFRM_MAX - 1)
+
+enum nft_xfrm_keys {
+ NFT_XFRM_KEY_UNSPEC,
+ NFT_XFRM_KEY_DADDR_IP4,
+ NFT_XFRM_KEY_DADDR_IP6,
+ NFT_XFRM_KEY_SADDR_IP4,
+ NFT_XFRM_KEY_SADDR_IP6,
+ NFT_XFRM_KEY_REQID,
+ NFT_XFRM_KEY_SPI,
+ __NFT_XFRM_KEY_MAX,
+};
+#define NFT_XFRM_KEY_MAX (__NFT_XFRM_KEY_MAX - 1)
/**
* enum nft_trace_attributes - nf_tables trace netlink attributes
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
index f61c306de1d0..2ab870ef233a 100644
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
@@ -625,6 +625,13 @@ config NFT_FIB_INET
The lookup will be delegated to the IPv4 or IPv6 FIB depending
on the protocol of the packet.
+config NFT_XFRM
+ tristate "Netfilter nf_tables xfrm/IPSec security association matching"
+ depends on XFRM
+ help
+ This option adds an expression that you can use to extract properties
+ of a packets security association.
+
config NFT_SOCKET
tristate "Netfilter nf_tables socket match support"
depends on IPV6 || IPV6=n
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
index 16895e045b66..4ddf3ef51ece 100644
--- a/net/netfilter/Makefile
+++ b/net/netfilter/Makefile
@@ -113,6 +113,7 @@ obj-$(CONFIG_NFT_FIB_NETDEV) += nft_fib_netdev.o
obj-$(CONFIG_NFT_SOCKET) += nft_socket.o
obj-$(CONFIG_NFT_OSF) += nft_osf.o
obj-$(CONFIG_NFT_TPROXY) += nft_tproxy.o
+obj-$(CONFIG_NFT_XFRM) += nft_xfrm.o
# nf_tables netdev
obj-$(CONFIG_NFT_DUP_NETDEV) += nft_dup_netdev.o
diff --git a/net/netfilter/nft_xfrm.c b/net/netfilter/nft_xfrm.c
new file mode 100644
index 000000000000..3cf71a2e375b
--- /dev/null
+++ b/net/netfilter/nft_xfrm.c
@@ -0,0 +1,293 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Generic part shared by ipv4 and ipv6 backends.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/netlink.h>
+#include <linux/netfilter.h>
+#include <linux/netfilter/nf_tables.h>
+#include <net/netfilter/nf_tables_core.h>
+#include <net/netfilter/nf_tables.h>
+#include <linux/in.h>
+#include <net/xfrm.h>
+
+static const struct nla_policy nft_xfrm_policy[NFTA_XFRM_MAX + 1] = {
+ [NFTA_XFRM_KEY] = { .type = NLA_U32 },
+ [NFTA_XFRM_DIR] = { .type = NLA_U8 },
+ [NFTA_XFRM_SPNUM] = { .type = NLA_U32 },
+ [NFTA_XFRM_DREG] = { .type = NLA_U32 },
+};
+
+struct nft_xfrm {
+ enum nft_xfrm_keys key:8;
+ enum nft_registers dreg:8;
+ u8 dir;
+ u8 spnum;
+};
+
+static int nft_xfrm_get_init(const struct nft_ctx *ctx,
+ const struct nft_expr *expr,
+ const struct nlattr * const tb[])
+{
+ struct nft_xfrm *priv = nft_expr_priv(expr);
+ unsigned int len = 0;
+ u32 spnum = 0;
+ u8 dir;
+
+ if (!tb[NFTA_XFRM_KEY] || !tb[NFTA_XFRM_DIR] || !tb[NFTA_XFRM_DREG])
+ return -EINVAL;
+
+ switch (ctx->family) {
+ case NFPROTO_IPV4:
+ case NFPROTO_IPV6:
+ case NFPROTO_INET:
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ priv->key = ntohl(nla_get_u32(tb[NFTA_XFRM_KEY]));
+ switch (priv->key) {
+ case NFT_XFRM_KEY_REQID:
+ case NFT_XFRM_KEY_SPI:
+ len = sizeof(u32);
+ break;
+ case NFT_XFRM_KEY_DADDR_IP4:
+ case NFT_XFRM_KEY_SADDR_IP4:
+ len = sizeof(struct in_addr);
+ break;
+ case NFT_XFRM_KEY_DADDR_IP6:
+ case NFT_XFRM_KEY_SADDR_IP6:
+ len = sizeof(struct in6_addr);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ dir = nla_get_u8(tb[NFTA_XFRM_DIR]);
+ switch (dir) {
+ case XFRM_POLICY_IN:
+ case XFRM_POLICY_OUT:
+ priv->dir = dir;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (tb[NFTA_XFRM_SPNUM])
+ spnum = ntohl(nla_get_be32(tb[NFTA_XFRM_SPNUM]));
+
+ if (spnum >= XFRM_MAX_DEPTH)
+ return -ERANGE;
+
+ priv->spnum = spnum;
+
+ priv->dreg = nft_parse_register(tb[NFTA_XFRM_DREG]);
+ return nft_validate_register_store(ctx, priv->dreg, NULL,
+ NFT_DATA_VALUE, len);
+}
+
+/* Return true if key asks for daddr/saddr and current
+ * state does have a valid address (BEET, TUNNEL).
+ */
+static bool xfrm_state_addr_ok(enum nft_xfrm_keys k, u8 family, u8 mode)
+{
+ switch (k) {
+ case NFT_XFRM_KEY_DADDR_IP4:
+ case NFT_XFRM_KEY_SADDR_IP4:
+ if (family == NFPROTO_IPV4)
+ break;
+ return false;
+ case NFT_XFRM_KEY_DADDR_IP6:
+ case NFT_XFRM_KEY_SADDR_IP6:
+ if (family == NFPROTO_IPV6)
+ break;
+ return false;
+ default:
+ return true;
+ }
+
+ return mode == XFRM_MODE_BEET || mode == XFRM_MODE_TUNNEL;
+}
+
+static void nft_xfrm_state_get_key(const struct nft_xfrm *priv,
+ struct nft_regs *regs,
+ const struct xfrm_state *state,
+ u8 family)
+{
+ u32 *dest = ®s->data[priv->dreg];
+
+ if (!xfrm_state_addr_ok(priv->key, family, state->props.mode)) {
+ regs->verdict.code = NFT_BREAK;
+ return;
+ }
+
+ switch (priv->key) {
+ case NFT_XFRM_KEY_UNSPEC:
+ case __NFT_XFRM_KEY_MAX:
+ WARN_ON_ONCE(1);
+ break;
+ case NFT_XFRM_KEY_DADDR_IP4:
+ *dest = state->id.daddr.a4;
+ return;
+ case NFT_XFRM_KEY_DADDR_IP6:
+ memcpy(dest, &state->id.daddr.in6, sizeof(struct in6_addr));
+ return;
+ case NFT_XFRM_KEY_SADDR_IP4:
+ *dest = state->props.saddr.a4;
+ return;
+ case NFT_XFRM_KEY_SADDR_IP6:
+ memcpy(dest, &state->props.saddr.in6, sizeof(struct in6_addr));
+ return;
+ case NFT_XFRM_KEY_REQID:
+ *dest = state->props.reqid;
+ return;
+ case NFT_XFRM_KEY_SPI:
+ *dest = state->id.spi;
+ return;
+ }
+
+ regs->verdict.code = NFT_BREAK;
+}
+
+static void nft_xfrm_get_eval_in(const struct nft_xfrm *priv,
+ struct nft_regs *regs,
+ const struct nft_pktinfo *pkt)
+{
+ const struct sec_path *sp = pkt->skb->sp;
+ const struct xfrm_state *state;
+
+ if (sp == NULL || sp->len <= priv->spnum) {
+ regs->verdict.code = NFT_BREAK;
+ return;
+ }
+
+ state = sp->xvec[priv->spnum];
+ nft_xfrm_state_get_key(priv, regs, state, nft_pf(pkt));
+}
+
+static void nft_xfrm_get_eval_out(const struct nft_xfrm *priv,
+ struct nft_regs *regs,
+ const struct nft_pktinfo *pkt)
+{
+ const struct dst_entry *dst = skb_dst(pkt->skb);
+ int i;
+
+ for (i = 0; dst && dst->xfrm;
+ dst = ((const struct xfrm_dst *)dst)->child, i++) {
+ if (i < priv->spnum)
+ continue;
+
+ nft_xfrm_state_get_key(priv, regs, dst->xfrm, nft_pf(pkt));
+ return;
+ }
+
+ regs->verdict.code = NFT_BREAK;
+}
+
+static void nft_xfrm_get_eval(const struct nft_expr *expr,
+ struct nft_regs *regs,
+ const struct nft_pktinfo *pkt)
+{
+ const struct nft_xfrm *priv = nft_expr_priv(expr);
+
+ switch (priv->dir) {
+ case XFRM_POLICY_IN:
+ nft_xfrm_get_eval_in(priv, regs, pkt);
+ break;
+ case XFRM_POLICY_OUT:
+ nft_xfrm_get_eval_out(priv, regs, pkt);
+ break;
+ default:
+ WARN_ON_ONCE(1);
+ regs->verdict.code = NFT_BREAK;
+ break;
+ }
+}
+
+static int nft_xfrm_get_dump(struct sk_buff *skb,
+ const struct nft_expr *expr)
+{
+ const struct nft_xfrm *priv = nft_expr_priv(expr);
+
+ if (nft_dump_register(skb, NFTA_XFRM_DREG, priv->dreg))
+ return -1;
+
+ if (nla_put_be32(skb, NFTA_XFRM_KEY, htonl(priv->key)))
+ return -1;
+ if (nla_put_u8(skb, NFTA_XFRM_DIR, priv->dir))
+ return -1;
+ if (nla_put_be32(skb, NFTA_XFRM_SPNUM, htonl(priv->spnum)))
+ return -1;
+
+ return 0;
+}
+
+static int nft_xfrm_validate(const struct nft_ctx *ctx, const struct nft_expr *expr,
+ const struct nft_data **data)
+{
+ const struct nft_xfrm *priv = nft_expr_priv(expr);
+ unsigned int hooks;
+
+ switch (priv->dir) {
+ case XFRM_POLICY_IN:
+ hooks = (1 << NF_INET_FORWARD) |
+ (1 << NF_INET_LOCAL_IN) |
+ (1 << NF_INET_PRE_ROUTING);
+ break;
+ case XFRM_POLICY_OUT:
+ hooks = (1 << NF_INET_FORWARD) |
+ (1 << NF_INET_LOCAL_OUT) |
+ (1 << NF_INET_POST_ROUTING);
+ break;
+ default:
+ WARN_ON_ONCE(1);
+ return -EINVAL;
+ }
+
+ return nft_chain_validate_hooks(ctx->chain, hooks);
+}
+
+
+static struct nft_expr_type nft_xfrm_type;
+static const struct nft_expr_ops nft_xfrm_get_ops = {
+ .type = &nft_xfrm_type,
+ .size = NFT_EXPR_SIZE(sizeof(struct nft_xfrm)),
+ .eval = nft_xfrm_get_eval,
+ .init = nft_xfrm_get_init,
+ .dump = nft_xfrm_get_dump,
+ .validate = nft_xfrm_validate,
+};
+
+static struct nft_expr_type nft_xfrm_type __read_mostly = {
+ .name = "xfrm",
+ .ops = &nft_xfrm_get_ops,
+ .policy = nft_xfrm_policy,
+ .maxattr = NFTA_XFRM_MAX,
+ .owner = THIS_MODULE,
+};
+
+static int __init nft_xfrm_module_init(void)
+{
+ return nft_register_expr(&nft_xfrm_type);
+}
+
+static void __exit nft_xfrm_module_exit(void)
+{
+ nft_unregister_expr(&nft_xfrm_type);
+}
+
+module_init(nft_xfrm_module_init);
+module_exit(nft_xfrm_module_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("nf_tables: xfrm/IPSec matching");
+MODULE_AUTHOR("Florian Westphal <fw@strlen•de>");
+MODULE_AUTHOR("Máté Eckl <ecklm94@gmail•com>");
+MODULE_ALIAS_NFT_EXPR("xfrm");
--
2.11.0
next prev parent reply other threads:[~2018-10-09 6:15 UTC|newest]
Thread overview: 53+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-10-08 23:00 [PATCH 00/31] Netfilter updates for net-next Pablo Neira Ayuso
2018-10-08 23:00 ` [PATCH 01/31] netfilter: nf_tables: rt: allow checking if dst has xfrm attached Pablo Neira Ayuso
2018-10-08 23:00 ` [PATCH 02/31] netfilter: nf_tables: split set destruction in deactivate and destroy phase Pablo Neira Ayuso
2018-10-08 23:00 ` [PATCH 03/31] netfilter: nf_tables: warn when expr implements only one of activate/deactivate Pablo Neira Ayuso
2018-10-08 23:00 ` [PATCH 04/31] netfilter: nf_tables: asynchronous release Pablo Neira Ayuso
2018-10-08 23:00 ` [PATCH 05/31] netfilter: remove obsolete need_conntrack stub Pablo Neira Ayuso
2018-10-08 23:01 ` Pablo Neira Ayuso [this message]
2018-10-10 11:39 ` [PATCH 06/31] netfilter: nf_tables: add xfrm expression Eyal Birger
2018-10-10 12:53 ` Florian Westphal
2018-10-08 23:01 ` [PATCH 07/31] netfilter: ctnetlink: Support L3 protocol-filter on flush Pablo Neira Ayuso
2019-04-25 10:07 ` Nicolas Dichtel
2019-04-25 15:41 ` Nicolas Dichtel
2019-04-26 19:25 ` Pablo Neira Ayuso
2019-04-29 14:53 ` Nicolas Dichtel
2019-04-29 15:23 ` Pablo Neira Ayuso
2019-04-29 15:39 ` Nicolas Dichtel
2019-05-01 8:47 ` Kristian Evensen
2019-05-02 7:28 ` Nicolas Dichtel
2019-05-02 7:46 ` Florian Westphal
2019-05-02 8:09 ` Kristian Evensen
2019-05-02 8:27 ` Nicolas Dichtel
2019-05-02 11:31 ` Pablo Neira Ayuso
2019-05-02 12:56 ` Nicolas Dichtel
2019-05-02 15:06 ` Pablo Neira Ayuso
2019-05-03 7:02 ` Nicolas Dichtel
2019-05-03 7:14 ` Kristian Evensen
2018-10-08 23:01 ` [PATCH 08/31] netfilter: xt_cgroup: shrink size of v2 path Pablo Neira Ayuso
2018-10-08 23:01 ` [PATCH 09/31] netfilter: nf_tables: avoid BUG_ON usage Pablo Neira Ayuso
2018-10-08 23:01 ` [PATCH 10/31] netfilter: xtables: avoid BUG_ON Pablo Neira Ayuso
2018-10-08 23:01 ` [PATCH 11/31] netfilter: nf_nat_ipv4: remove obsolete EXPORT_SYMBOL Pablo Neira Ayuso
2018-10-08 23:01 ` [PATCH 12/31] netfilter: cttimeout: remove superfluous check on layer 4 netlink functions Pablo Neira Ayuso
2018-11-01 14:57 ` Eric Dumazet
2018-11-01 23:26 ` Pablo Neira Ayuso
2018-10-08 23:01 ` [PATCH 13/31] netfilter: nat: remove unnecessary rcu_read_lock in nf_nat_redirect_ipv{4/6} Pablo Neira Ayuso
2018-10-08 23:01 ` [PATCH 14/31] netfilter: conntrack: pass nf_hook_state to packet and error handlers Pablo Neira Ayuso
2018-10-08 23:01 ` [PATCH 15/31] netfilter: conntrack: remove the l4proto->new() function Pablo Neira Ayuso
2018-10-08 23:01 ` [PATCH 16/31] netfilter: conntrack: deconstify packet callback skb pointer Pablo Neira Ayuso
2018-10-08 23:01 ` [PATCH 17/31] netfilter: conntrack: avoid using ->error callback if possible Pablo Neira Ayuso
2018-10-08 23:01 ` [PATCH 18/31] netfilter: conntrack: remove error callback and handle icmp from core Pablo Neira Ayuso
2018-10-08 23:01 ` [PATCH 19/31] netfilter: conntrack: remove unused proto arg from netns init functions Pablo Neira Ayuso
2018-10-08 23:01 ` [PATCH 20/31] netfilter: conntrack: remove l3->l4 mapping information Pablo Neira Ayuso
2018-10-08 23:01 ` [PATCH 21/31] netfilter: conntrack: clamp l4proto array size at largers supported protocol Pablo Neira Ayuso
2018-10-08 23:01 ` [PATCH 22/31] netfilter: nat: remove duplicate skb_is_nonlinear() in __nf_nat_mangle_tcp_packet() Pablo Neira Ayuso
2018-10-08 23:01 ` [PATCH 23/31] netfilter: nf_tables: use rhashtable_walk_enter instead of rhashtable_walk_init Pablo Neira Ayuso
2018-10-08 23:01 ` [PATCH 24/31] netfilter: ctnetlink: must check mark attributes vs NULL Pablo Neira Ayuso
2018-10-08 23:01 ` [PATCH 25/31] netfilter: masquerade: don't flush all conntracks if only one address deleted on device Pablo Neira Ayuso
2018-10-08 23:01 ` [PATCH 26/31] netfilter: nf_tables: add SECMARK support Pablo Neira Ayuso
2018-10-08 23:01 ` [PATCH 27/31] netfilter: nf_tables: add requirements for connsecmark support Pablo Neira Ayuso
2018-10-08 23:01 ` [PATCH 28/31] netfilter: nf_flow_table: remove unnecessary nat flag check code Pablo Neira Ayuso
2018-10-08 23:01 ` [PATCH 29/31] netfilter: nf_tables: use rhashtable_lookup() instead of rhashtable_lookup_fast() Pablo Neira Ayuso
2018-10-08 23:01 ` [PATCH 30/31] netfilter: xt_quota: fix the behavior of xt_quota module Pablo Neira Ayuso
2018-10-08 23:01 ` [PATCH 31/31] netfilter: xt_quota: Don't use aligned attribute in sizeof Pablo Neira Ayuso
2018-10-09 4:29 ` [PATCH 00/31] Netfilter updates for net-next David Miller
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20181008230125.2330-7-pablo@netfilter.org \
--to=pablo@netfilter$(echo .)org \
--cc=davem@davemloft$(echo .)net \
--cc=netdev@vger$(echo .)kernel.org \
--cc=netfilter-devel@vger$(echo .)kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox