Commit | Line | Data |
---|---|---|
d2912cb1 | 1 | // SPDX-License-Identifier: GPL-2.0-only |
96518518 | 2 | /* |
ef1f7df9 | 3 | * Copyright (c) 2008-2009 Patrick McHardy <kaber@trash.net> |
96518518 | 4 | * |
96518518 PM |
5 | * Development of this code funded by Astaro AG (http://www.astaro.com/) |
6 | */ | |
7 | ||
8 | #include <linux/kernel.h> | |
9 | #include <linux/init.h> | |
10 | #include <linux/module.h> | |
11 | #include <linux/netlink.h> | |
12 | #include <linux/netfilter.h> | |
13 | #include <linux/netfilter/nf_tables.h> | |
14 | #include <net/netfilter/nf_tables_core.h> | |
15 | #include <net/netfilter/nf_tables.h> | |
16 | ||
10870dd8 FW |
17 | void nft_immediate_eval(const struct nft_expr *expr, |
18 | struct nft_regs *regs, | |
19 | const struct nft_pktinfo *pkt) | |
96518518 PM |
20 | { |
21 | const struct nft_immediate_expr *priv = nft_expr_priv(expr); | |
22 | ||
49499c3e | 23 | nft_data_copy(®s->data[priv->dreg], &priv->data, priv->dlen); |
96518518 PM |
24 | } |
25 | ||
26 | static const struct nla_policy nft_immediate_policy[NFTA_IMMEDIATE_MAX + 1] = { | |
27 | [NFTA_IMMEDIATE_DREG] = { .type = NLA_U32 }, | |
28 | [NFTA_IMMEDIATE_DATA] = { .type = NLA_NESTED }, | |
29 | }; | |
30 | ||
31 | static int nft_immediate_init(const struct nft_ctx *ctx, | |
32 | const struct nft_expr *expr, | |
33 | const struct nlattr * const tb[]) | |
34 | { | |
35 | struct nft_immediate_expr *priv = nft_expr_priv(expr); | |
36 | struct nft_data_desc desc; | |
37 | int err; | |
38 | ||
39 | if (tb[NFTA_IMMEDIATE_DREG] == NULL || | |
40 | tb[NFTA_IMMEDIATE_DATA] == NULL) | |
41 | return -EINVAL; | |
42 | ||
d0a11fc3 PM |
43 | err = nft_data_init(ctx, &priv->data, sizeof(priv->data), &desc, |
44 | tb[NFTA_IMMEDIATE_DATA]); | |
96518518 PM |
45 | if (err < 0) |
46 | return err; | |
36b701fa | 47 | |
96518518 PM |
48 | priv->dlen = desc.len; |
49 | ||
b1c96ed3 | 50 | priv->dreg = nft_parse_register(tb[NFTA_IMMEDIATE_DREG]); |
1ec10212 PM |
51 | err = nft_validate_register_store(ctx, priv->dreg, &priv->data, |
52 | desc.type, desc.len); | |
96518518 PM |
53 | if (err < 0) |
54 | goto err1; | |
55 | ||
56 | return 0; | |
57 | ||
58 | err1: | |
59105446 | 59 | nft_data_release(&priv->data, desc.type); |
96518518 PM |
60 | return err; |
61 | } | |
62 | ||
bb7b40ae PNA |
63 | static void nft_immediate_activate(const struct nft_ctx *ctx, |
64 | const struct nft_expr *expr) | |
65 | { | |
66 | const struct nft_immediate_expr *priv = nft_expr_priv(expr); | |
67 | ||
68 | return nft_data_hold(&priv->data, nft_dreg_to_type(priv->dreg)); | |
69 | } | |
70 | ||
71 | static void nft_immediate_deactivate(const struct nft_ctx *ctx, | |
f6ac8585 PNA |
72 | const struct nft_expr *expr, |
73 | enum nft_trans_phase phase) | |
96518518 PM |
74 | { |
75 | const struct nft_immediate_expr *priv = nft_expr_priv(expr); | |
59105446 | 76 | |
f6ac8585 PNA |
77 | if (phase == NFT_TRANS_COMMIT) |
78 | return; | |
79 | ||
59105446 | 80 | return nft_data_release(&priv->data, nft_dreg_to_type(priv->dreg)); |
96518518 PM |
81 | } |
82 | ||
83 | static int nft_immediate_dump(struct sk_buff *skb, const struct nft_expr *expr) | |
84 | { | |
85 | const struct nft_immediate_expr *priv = nft_expr_priv(expr); | |
86 | ||
b1c96ed3 | 87 | if (nft_dump_register(skb, NFTA_IMMEDIATE_DREG, priv->dreg)) |
96518518 PM |
88 | goto nla_put_failure; |
89 | ||
90 | return nft_data_dump(skb, NFTA_IMMEDIATE_DATA, &priv->data, | |
91 | nft_dreg_to_type(priv->dreg), priv->dlen); | |
92 | ||
93 | nla_put_failure: | |
94 | return -1; | |
95 | } | |
96 | ||
0ca743a5 PNA |
97 | static int nft_immediate_validate(const struct nft_ctx *ctx, |
98 | const struct nft_expr *expr, | |
a654de8f | 99 | const struct nft_data **d) |
20a69341 PM |
100 | { |
101 | const struct nft_immediate_expr *priv = nft_expr_priv(expr); | |
26b2f552 | 102 | struct nft_ctx *pctx = (struct nft_ctx *)ctx; |
a654de8f PNA |
103 | const struct nft_data *data; |
104 | int err; | |
20a69341 | 105 | |
a654de8f PNA |
106 | if (priv->dreg != NFT_REG_VERDICT) |
107 | return 0; | |
108 | ||
109 | data = &priv->data; | |
110 | ||
111 | switch (data->verdict.code) { | |
112 | case NFT_JUMP: | |
113 | case NFT_GOTO: | |
26b2f552 | 114 | pctx->level++; |
a654de8f PNA |
115 | err = nft_chain_validate(ctx, data->verdict.chain); |
116 | if (err < 0) | |
117 | return err; | |
26b2f552 | 118 | pctx->level--; |
a654de8f PNA |
119 | break; |
120 | default: | |
121 | break; | |
122 | } | |
0ca743a5 PNA |
123 | |
124 | return 0; | |
20a69341 PM |
125 | } |
126 | ||
ef1f7df9 PM |
127 | static const struct nft_expr_ops nft_imm_ops = { |
128 | .type = &nft_imm_type, | |
96518518 | 129 | .size = NFT_EXPR_SIZE(sizeof(struct nft_immediate_expr)), |
96518518 PM |
130 | .eval = nft_immediate_eval, |
131 | .init = nft_immediate_init, | |
bb7b40ae PNA |
132 | .activate = nft_immediate_activate, |
133 | .deactivate = nft_immediate_deactivate, | |
96518518 | 134 | .dump = nft_immediate_dump, |
0ca743a5 | 135 | .validate = nft_immediate_validate, |
ef1f7df9 PM |
136 | }; |
137 | ||
4e24877e | 138 | struct nft_expr_type nft_imm_type __read_mostly = { |
ef1f7df9 PM |
139 | .name = "immediate", |
140 | .ops = &nft_imm_ops, | |
96518518 PM |
141 | .policy = nft_immediate_policy, |
142 | .maxattr = NFTA_IMMEDIATE_MAX, | |
ef1f7df9 | 143 | .owner = THIS_MODULE, |
96518518 | 144 | }; |