* [RFC PATCH nf-next 0/1] payload mangling support
@ 2015-11-09 14:10 Patrick McHardy
2015-11-09 14:10 ` [RFC PATCH nf-next 1/1] netfilter: nft_payload: add packet " Patrick McHardy
` (2 more replies)
0 siblings, 3 replies; 10+ messages in thread
From: Patrick McHardy @ 2015-11-09 14:10 UTC (permalink / raw)
To: pablo; +Cc: netfilter-devel
The following patch adds support for payload mangling. It supports updating
all fields except those included in pseudo headers since it only supports a
single checksum update operation. So it can not be used for stateless NAT.
Checksum updates currently only support internet checksums and assume the
mangled data is actually covered by the checksum. Userspace only allows use
for these protocols.
So the main questions is basically, do we want to support stateless NAT?
The downside is that we have to add protocol specific checksumming functions.
Patrick McHardy (1):
netfilter: nft_payload: add packet mangling support
include/net/netfilter/nf_tables_core.h | 1 +
include/uapi/linux/netfilter/nf_tables.h | 4 ++
net/netfilter/nft_payload.c | 116 +++++++++++++++++++++++++++++--
3 files changed, 115 insertions(+), 6 deletions(-)
--
2.5.0
^ permalink raw reply [flat|nested] 10+ messages in thread* [RFC PATCH nf-next 1/1] netfilter: nft_payload: add packet mangling support 2015-11-09 14:10 [RFC PATCH nf-next 0/1] payload mangling support Patrick McHardy @ 2015-11-09 14:10 ` Patrick McHardy 2015-11-23 12:31 ` Pablo Neira Ayuso 2015-11-09 15:22 ` [RFC PATCH nf-next 0/1] payload " Jan Engelhardt 2015-11-09 15:30 ` Florian Westphal 2 siblings, 1 reply; 10+ messages in thread From: Patrick McHardy @ 2015-11-09 14:10 UTC (permalink / raw) To: pablo; +Cc: netfilter-devel Add support for mangling packet payload. Checksum for the specified base header is updated automatically, however no double updates (for pseudo headers) are supported, meaning no stateless NAT is supported. Signed-off-by: Patrick McHardy <kaber@trash.net> --- include/net/netfilter/nf_tables_core.h | 1 + include/uapi/linux/netfilter/nf_tables.h | 4 ++ net/netfilter/nft_payload.c | 116 +++++++++++++++++++++++++++++-- 3 files changed, 115 insertions(+), 6 deletions(-) diff --git a/include/net/netfilter/nf_tables_core.h b/include/net/netfilter/nf_tables_core.h index c6f400c..6d7a793 100644 --- a/include/net/netfilter/nf_tables_core.h +++ b/include/net/netfilter/nf_tables_core.h @@ -45,6 +45,7 @@ struct nft_payload { u8 offset; u8 len; enum nft_registers dreg:8; + u8 csum_offset; }; extern const struct nft_expr_ops nft_payload_fast_ops; diff --git a/include/uapi/linux/netfilter/nf_tables.h b/include/uapi/linux/netfilter/nf_tables.h index d8c8a7c..56e1706 100644 --- a/include/uapi/linux/netfilter/nf_tables.h +++ b/include/uapi/linux/netfilter/nf_tables.h @@ -604,6 +604,8 @@ enum nft_payload_bases { * @NFTA_PAYLOAD_BASE: payload base (NLA_U32: nft_payload_bases) * @NFTA_PAYLOAD_OFFSET: payload offset relative to base (NLA_U32) * @NFTA_PAYLOAD_LEN: payload length (NLA_U32) + * @NFTA_PAYLOAD_SREG: source register to load data from (NLA_U32: nft_registers) + * @NFTA_PAYLOAD_CSUM_OFFSET: checksum offset relative to base (NLA_U32) */ enum nft_payload_attributes { NFTA_PAYLOAD_UNSPEC, @@ -611,6 +613,8 @@ enum nft_payload_attributes { NFTA_PAYLOAD_BASE, NFTA_PAYLOAD_OFFSET, NFTA_PAYLOAD_LEN, + NFTA_PAYLOAD_SREG, + NFTA_PAYLOAD_CSUM_OFFSET, __NFTA_PAYLOAD_MAX }; #define NFTA_PAYLOAD_MAX (__NFTA_PAYLOAD_MAX - 1) diff --git a/net/netfilter/nft_payload.c b/net/netfilter/nft_payload.c index 09b4b07..d04a31c 100644 --- a/net/netfilter/nft_payload.c +++ b/net/netfilter/nft_payload.c @@ -107,10 +107,12 @@ err: } static const struct nla_policy nft_payload_policy[NFTA_PAYLOAD_MAX + 1] = { - [NFTA_PAYLOAD_DREG] = { .type = NLA_U32 }, - [NFTA_PAYLOAD_BASE] = { .type = NLA_U32 }, - [NFTA_PAYLOAD_OFFSET] = { .type = NLA_U32 }, - [NFTA_PAYLOAD_LEN] = { .type = NLA_U32 }, + [NFTA_PAYLOAD_SREG] = { .type = NLA_U32 }, + [NFTA_PAYLOAD_DREG] = { .type = NLA_U32 }, + [NFTA_PAYLOAD_BASE] = { .type = NLA_U32 }, + [NFTA_PAYLOAD_OFFSET] = { .type = NLA_U32 }, + [NFTA_PAYLOAD_LEN] = { .type = NLA_U32 }, + [NFTA_PAYLOAD_CSUM_OFFSET] = { .type = NLA_U32 }, }; static int nft_payload_init(const struct nft_ctx *ctx, @@ -160,6 +162,100 @@ const struct nft_expr_ops nft_payload_fast_ops = { .dump = nft_payload_dump, }; +static void nft_payload_set_eval(const struct nft_expr *expr, + struct nft_regs *regs, + const struct nft_pktinfo *pkt) +{ + const struct nft_payload *priv = nft_expr_priv(expr); + struct sk_buff *skb = pkt->skb; + const u32 *src = ®s->data[priv->dreg]; + int offset, csum_offset; + __wsum fsum, tsum; + __sum16 sum; + + switch (priv->base) { + case NFT_PAYLOAD_LL_HEADER: + if (!skb_mac_header_was_set(skb)) + goto err; + offset = skb_mac_header(skb) - skb->data; + break; + case NFT_PAYLOAD_NETWORK_HEADER: + offset = skb_network_offset(skb); + break; + case NFT_PAYLOAD_TRANSPORT_HEADER: + offset = pkt->xt.thoff; + break; + default: + BUG(); + } + + csum_offset = offset + priv->csum_offset; + offset += priv->offset; + + if (priv->base != NFT_PAYLOAD_TRANSPORT_HEADER || + skb->ip_summed != CHECKSUM_PARTIAL) { + if (skb_copy_bits(skb, csum_offset, &sum, sizeof(sum)) < 0) + goto err; + + fsum = skb_checksum(skb, offset, priv->len, 0); + tsum = csum_partial(src, priv->len, 0); + sum = csum_fold(csum_add(csum_sub(~csum_unfold(sum), fsum), + tsum)); + if (sum == 0) + sum = CSUM_MANGLED_0; + + skb_store_bits(skb, csum_offset, &sum, sizeof(sum)); + } + + if (!skb_make_writable(skb, offset + priv->len) || + skb_store_bits(skb, offset, src, priv->len) < 0) + goto err; + + return; +err: + regs->verdict.code = NFT_BREAK; +} + + +static int nft_payload_set_init(const struct nft_ctx *ctx, + const struct nft_expr *expr, + const struct nlattr * const tb[]) +{ + struct nft_payload *priv = nft_expr_priv(expr); + + priv->base = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_BASE])); + priv->offset = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_OFFSET])); + priv->len = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_LEN])); + priv->csum_offset = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_CSUM_OFFSET])); + priv->dreg = nft_parse_register(tb[NFTA_PAYLOAD_SREG]); + + return nft_validate_register_load(priv->dreg, priv->len); +} + +static int nft_payload_set_dump(struct sk_buff *skb, const struct nft_expr *expr) +{ + const struct nft_payload *priv = nft_expr_priv(expr); + + if (nft_dump_register(skb, NFTA_PAYLOAD_SREG, priv->dreg) || + nla_put_be32(skb, NFTA_PAYLOAD_BASE, htonl(priv->base)) || + nla_put_be32(skb, NFTA_PAYLOAD_OFFSET, htonl(priv->offset)) || + nla_put_be32(skb, NFTA_PAYLOAD_LEN, htonl(priv->len)) || + nla_put_be32(skb, NFTA_PAYLOAD_CSUM_OFFSET, htonl(priv->csum_offset))) + goto nla_put_failure; + return 0; + +nla_put_failure: + return -1; +} + +static const struct nft_expr_ops nft_payload_set_ops = { + .type = &nft_payload_type, + .size = NFT_EXPR_SIZE(sizeof(struct nft_payload)), + .eval = nft_payload_set_eval, + .init = nft_payload_set_init, + .dump = nft_payload_set_dump, +}; + static const struct nft_expr_ops * nft_payload_select_ops(const struct nft_ctx *ctx, const struct nlattr * const tb[]) @@ -167,8 +263,7 @@ nft_payload_select_ops(const struct nft_ctx *ctx, enum nft_payload_bases base; unsigned int offset, len; - if (tb[NFTA_PAYLOAD_DREG] == NULL || - tb[NFTA_PAYLOAD_BASE] == NULL || + if (tb[NFTA_PAYLOAD_BASE] == NULL || tb[NFTA_PAYLOAD_OFFSET] == NULL || tb[NFTA_PAYLOAD_LEN] == NULL) return ERR_PTR(-EINVAL); @@ -183,6 +278,15 @@ nft_payload_select_ops(const struct nft_ctx *ctx, return ERR_PTR(-EOPNOTSUPP); } + if (tb[NFTA_PAYLOAD_SREG] != NULL) { + if (tb[NFTA_PAYLOAD_DREG] != NULL) + return ERR_PTR(-EINVAL); + return &nft_payload_set_ops; + } + + if (tb[NFTA_PAYLOAD_DREG] == NULL) + return ERR_PTR(-EINVAL); + offset = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_OFFSET])); len = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_LEN])); -- 2.5.0 ^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [RFC PATCH nf-next 1/1] netfilter: nft_payload: add packet mangling support 2015-11-09 14:10 ` [RFC PATCH nf-next 1/1] netfilter: nft_payload: add packet " Patrick McHardy @ 2015-11-23 12:31 ` Pablo Neira Ayuso 2015-11-23 12:45 ` Patrick McHardy 0 siblings, 1 reply; 10+ messages in thread From: Pablo Neira Ayuso @ 2015-11-23 12:31 UTC (permalink / raw) To: Patrick McHardy; +Cc: netfilter-devel On Mon, Nov 09, 2015 at 02:10:34PM +0000, Patrick McHardy wrote: > Add support for mangling packet payload. Checksum for the specified > base header is updated automatically, however no double updates (for > pseudo headers) are supported, meaning no stateless NAT is supported. Patrick, if you have no concerns, I'll pass this to David in the next batch. Thanks. ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [RFC PATCH nf-next 1/1] netfilter: nft_payload: add packet mangling support 2015-11-23 12:31 ` Pablo Neira Ayuso @ 2015-11-23 12:45 ` Patrick McHardy 0 siblings, 0 replies; 10+ messages in thread From: Patrick McHardy @ 2015-11-23 12:45 UTC (permalink / raw) To: Pablo Neira Ayuso; +Cc: netfilter-devel On 23.11, Pablo Neira Ayuso wrote: > On Mon, Nov 09, 2015 at 02:10:34PM +0000, Patrick McHardy wrote: > > Add support for mangling packet payload. Checksum for the specified > > base header is updated automatically, however no double updates (for > > pseudo headers) are supported, meaning no stateless NAT is supported. > > Patrick, if you have no concerns, I'll pass this to David in the next > batch. It needs a minor fix to work with link layer headers. I'll try to get it ready tonight. ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [RFC PATCH nf-next 0/1] payload mangling support 2015-11-09 14:10 [RFC PATCH nf-next 0/1] payload mangling support Patrick McHardy 2015-11-09 14:10 ` [RFC PATCH nf-next 1/1] netfilter: nft_payload: add packet " Patrick McHardy @ 2015-11-09 15:22 ` Jan Engelhardt 2015-11-09 15:37 ` Patrick McHardy 2015-11-09 15:30 ` Florian Westphal 2 siblings, 1 reply; 10+ messages in thread From: Jan Engelhardt @ 2015-11-09 15:22 UTC (permalink / raw) To: Patrick McHardy; +Cc: pablo, netfilter-devel On Monday 2015-11-09 15:10, Patrick McHardy wrote: >The following patch adds support for payload mangling. It supports updating >all fields except those included in pseudo headers since it only supports a >single checksum update operation. So it can not be used for stateless NAT. > >Checksum updates currently only support internet checksums and assume the >mangled data is actually covered by the checksum. Userspace only allows use >for these protocols. > >So the main questions is basically, do we want to support stateless NAT? Some people ask for that sort of thing every now and then, so it depends on whether you want to please them. On the upside, they only seem to request L3 address editing and L3addrs-inside-ICMP(v6), so the amount of protocol handlers needed is small. ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [RFC PATCH nf-next 0/1] payload mangling support 2015-11-09 15:22 ` [RFC PATCH nf-next 0/1] payload " Jan Engelhardt @ 2015-11-09 15:37 ` Patrick McHardy 0 siblings, 0 replies; 10+ messages in thread From: Patrick McHardy @ 2015-11-09 15:37 UTC (permalink / raw) To: Jan Engelhardt; +Cc: pablo, netfilter-devel On 09.11, Jan Engelhardt wrote: > > On Monday 2015-11-09 15:10, Patrick McHardy wrote: > > >The following patch adds support for payload mangling. It supports updating > >all fields except those included in pseudo headers since it only supports a > >single checksum update operation. So it can not be used for stateless NAT. > > > >Checksum updates currently only support internet checksums and assume the > >mangled data is actually covered by the checksum. Userspace only allows use > >for these protocols. > > > >So the main questions is basically, do we want to support stateless NAT? > > Some people ask for that sort of thing every now and then, so it > depends on whether you want to please them. On the upside, they only > seem to request L3 address editing and L3addrs-inside-ICMP(v6), so > the amount of protocol handlers needed is small. Yeah, but the l3 addresses are embedded in the protocol specific pseudo header: There are basically two possibilities: * add a paremeterized pseudo header update function to the payload expression. Requires one rule per protocol so we can set the required parameters. * add automatic magic header updates, requires to add protocol knowledge of all protocols which are using this. I'm not against supporting this per se, but I tend to go in the direction of waiting for people that need this and describe their use cases. I don't see any problem in adding either way later on. ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [RFC PATCH nf-next 0/1] payload mangling support 2015-11-09 14:10 [RFC PATCH nf-next 0/1] payload mangling support Patrick McHardy 2015-11-09 14:10 ` [RFC PATCH nf-next 1/1] netfilter: nft_payload: add packet " Patrick McHardy 2015-11-09 15:22 ` [RFC PATCH nf-next 0/1] payload " Jan Engelhardt @ 2015-11-09 15:30 ` Florian Westphal 2015-11-09 15:41 ` Patrick McHardy 2 siblings, 1 reply; 10+ messages in thread From: Florian Westphal @ 2015-11-09 15:30 UTC (permalink / raw) To: Patrick McHardy; +Cc: pablo, netfilter-devel Patrick McHardy <kaber@trash.net> wrote: > So the main questions is basically, do we want to support stateless NAT? > The downside is that we have to add protocol specific checksumming functions. For now i'm only be interested in mangling MAC addresses for nft bridge to provide ebtables snat/dnat/redirect equivalents. ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [RFC PATCH nf-next 0/1] payload mangling support 2015-11-09 15:30 ` Florian Westphal @ 2015-11-09 15:41 ` Patrick McHardy 2015-11-09 15:50 ` Florian Westphal 0 siblings, 1 reply; 10+ messages in thread From: Patrick McHardy @ 2015-11-09 15:41 UTC (permalink / raw) To: Florian Westphal; +Cc: pablo, netfilter-devel On 09.11, Florian Westphal wrote: > Patrick McHardy <kaber@trash.net> wrote: > > So the main questions is basically, do we want to support stateless NAT? > > The downside is that we have to add protocol specific checksumming functions. > > For now i'm only be interested in mangling MAC addresses for nft bridge > to provide ebtables snat/dnat/redirect equivalents. I have not tested that, it probably needs some minor adjustments to skip checksum updates for NFT_PAYLOAD_LL_HEADER, but other than that, this will obviously work. ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [RFC PATCH nf-next 0/1] payload mangling support 2015-11-09 15:41 ` Patrick McHardy @ 2015-11-09 15:50 ` Florian Westphal 2015-11-09 16:00 ` Patrick McHardy 0 siblings, 1 reply; 10+ messages in thread From: Florian Westphal @ 2015-11-09 15:50 UTC (permalink / raw) To: Patrick McHardy; +Cc: Florian Westphal, pablo, netfilter-devel Patrick McHardy <kaber@trash.net> wrote: > On 09.11, Florian Westphal wrote: > > Patrick McHardy <kaber@trash.net> wrote: > > > So the main questions is basically, do we want to support stateless NAT? > > > The downside is that we have to add protocol specific checksumming functions. > > > > For now i'm only be interested in mangling MAC addresses for nft bridge > > to provide ebtables snat/dnat/redirect equivalents. > > I have not tested that, it probably needs some minor adjustments to skip > checksum updates for NFT_PAYLOAD_LL_HEADER, but other than that, this will > obviously work. For redirect we also need to alter skb->pkttype to PACKET_HOST. I can take care of this later if needed, I'd just need advice on how to add this (meta statement?). ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [RFC PATCH nf-next 0/1] payload mangling support 2015-11-09 15:50 ` Florian Westphal @ 2015-11-09 16:00 ` Patrick McHardy 0 siblings, 0 replies; 10+ messages in thread From: Patrick McHardy @ 2015-11-09 16:00 UTC (permalink / raw) To: Florian Westphal; +Cc: pablo, netfilter-devel On 09.11, Florian Westphal wrote: > Patrick McHardy <kaber@trash.net> wrote: > > On 09.11, Florian Westphal wrote: > > > Patrick McHardy <kaber@trash.net> wrote: > > > > So the main questions is basically, do we want to support stateless NAT? > > > > The downside is that we have to add protocol specific checksumming functions. > > > > > > For now i'm only be interested in mangling MAC addresses for nft bridge > > > to provide ebtables snat/dnat/redirect equivalents. > > > > I have not tested that, it probably needs some minor adjustments to skip > > checksum updates for NFT_PAYLOAD_LL_HEADER, but other than that, this will > > obviously work. > > For redirect we also need to alter skb->pkttype to PACKET_HOST. > > I can take care of this later if needed, I'd just need advice on > how to add this (meta statement?). Good point. I guess that would be the proper solution, I don't think we want to try to figure out whether an address is local in the payload module. ^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2015-11-23 12:45 UTC | newest] Thread overview: 10+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2015-11-09 14:10 [RFC PATCH nf-next 0/1] payload mangling support Patrick McHardy 2015-11-09 14:10 ` [RFC PATCH nf-next 1/1] netfilter: nft_payload: add packet " Patrick McHardy 2015-11-23 12:31 ` Pablo Neira Ayuso 2015-11-23 12:45 ` Patrick McHardy 2015-11-09 15:22 ` [RFC PATCH nf-next 0/1] payload " Jan Engelhardt 2015-11-09 15:37 ` Patrick McHardy 2015-11-09 15:30 ` Florian Westphal 2015-11-09 15:41 ` Patrick McHardy 2015-11-09 15:50 ` Florian Westphal 2015-11-09 16:00 ` Patrick McHardy
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).