2 * Copyright (c) 2008-2009 Patrick McHardy <kaber@trash.net>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
8 * Development of this code funded by Astaro AG (http://www.astaro.com/)
11 #include <linux/kernel.h>
12 #include <linux/init.h>
13 #include <linux/module.h>
14 #include <linux/netlink.h>
15 #include <linux/netfilter.h>
16 #include <linux/netfilter/nf_tables.h>
17 #include <net/netfilter/nf_tables_core.h>
18 #include <net/netfilter/nf_tables.h>
21 enum nft_payload_bases base:8;
24 enum nft_registers dreg:8;
27 static void nft_payload_eval(const struct nft_expr *expr,
28 struct nft_data data[NFT_REG_MAX + 1],
29 const struct nft_pktinfo *pkt)
31 const struct nft_payload *priv = nft_expr_priv(expr);
32 const struct sk_buff *skb = pkt->skb;
33 struct nft_data *dest = &data[priv->dreg];
37 case NFT_PAYLOAD_LL_HEADER:
38 if (!skb_mac_header_was_set(skb))
40 offset = skb_mac_header(skb) - skb->data;
42 case NFT_PAYLOAD_NETWORK_HEADER:
43 offset = skb_network_offset(skb);
45 case NFT_PAYLOAD_TRANSPORT_HEADER:
46 offset = skb_transport_offset(skb);
51 offset += priv->offset;
53 if (skb_copy_bits(skb, offset, dest->data, priv->len) < 0)
57 data[NFT_REG_VERDICT].verdict = NFT_BREAK;
60 static const struct nla_policy nft_payload_policy[NFTA_PAYLOAD_MAX + 1] = {
61 [NFTA_PAYLOAD_DREG] = { .type = NLA_U32 },
62 [NFTA_PAYLOAD_BASE] = { .type = NLA_U32 },
63 [NFTA_PAYLOAD_OFFSET] = { .type = NLA_U32 },
64 [NFTA_PAYLOAD_LEN] = { .type = NLA_U32 },
67 static int nft_payload_init(const struct nft_ctx *ctx,
68 const struct nft_expr *expr,
69 const struct nlattr * const tb[])
71 struct nft_payload *priv = nft_expr_priv(expr);
74 if (tb[NFTA_PAYLOAD_DREG] == NULL ||
75 tb[NFTA_PAYLOAD_BASE] == NULL ||
76 tb[NFTA_PAYLOAD_OFFSET] == NULL ||
77 tb[NFTA_PAYLOAD_LEN] == NULL)
80 priv->base = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_BASE]));
82 case NFT_PAYLOAD_LL_HEADER:
83 case NFT_PAYLOAD_NETWORK_HEADER:
84 case NFT_PAYLOAD_TRANSPORT_HEADER:
90 priv->offset = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_OFFSET]));
91 priv->len = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_LEN]));
93 priv->len > FIELD_SIZEOF(struct nft_data, data))
96 priv->dreg = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_DREG]));
97 err = nft_validate_output_register(priv->dreg);
100 return nft_validate_data_load(ctx, priv->dreg, NULL, NFT_DATA_VALUE);
103 static int nft_payload_dump(struct sk_buff *skb, const struct nft_expr *expr)
105 const struct nft_payload *priv = nft_expr_priv(expr);
107 if (nla_put_be32(skb, NFTA_PAYLOAD_DREG, htonl(priv->dreg)) ||
108 nla_put_be32(skb, NFTA_PAYLOAD_BASE, htonl(priv->base)) ||
109 nla_put_be32(skb, NFTA_PAYLOAD_OFFSET, htonl(priv->offset)) ||
110 nla_put_be32(skb, NFTA_PAYLOAD_LEN, htonl(priv->len)))
111 goto nla_put_failure;
118 static struct nft_expr_type nft_payload_type;
119 static const struct nft_expr_ops nft_payload_ops = {
120 .type = &nft_payload_type,
121 .size = NFT_EXPR_SIZE(sizeof(struct nft_payload)),
122 .eval = nft_payload_eval,
123 .init = nft_payload_init,
124 .dump = nft_payload_dump,
127 static struct nft_expr_type nft_payload_type __read_mostly = {
129 .ops = &nft_payload_ops,
130 .policy = nft_payload_policy,
131 .maxattr = NFTA_PAYLOAD_MAX,
132 .owner = THIS_MODULE,
135 int __init nft_payload_module_init(void)
137 return nft_register_expr(&nft_payload_type);
140 void nft_payload_module_exit(void)
142 nft_unregister_expr(&nft_payload_type);