1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (c) 2008-2009 Patrick McHardy <kaber@trash.net>
5 * Development of this code funded by Astaro AG (http://www.astaro.com/)
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 #include <net/netfilter/nf_tables_offload.h>
19 enum nft_registers sreg
:8;
20 enum nft_registers dreg
:8;
21 enum nft_bitwise_ops op
:8;
28 static void nft_bitwise_eval_bool(u32
*dst
, const u32
*src
,
29 const struct nft_bitwise
*priv
)
33 for (i
= 0; i
< DIV_ROUND_UP(priv
->len
, 4); i
++)
34 dst
[i
] = (src
[i
] & priv
->mask
.data
[i
]) ^ priv
->xor.data
[i
];
37 static void nft_bitwise_eval_lshift(u32
*dst
, const u32
*src
,
38 const struct nft_bitwise
*priv
)
40 u32 shift
= priv
->data
.data
[0];
44 for (i
= DIV_ROUND_UP(priv
->len
, sizeof(u32
)); i
> 0; i
--) {
45 dst
[i
- 1] = (src
[i
- 1] << shift
) | carry
;
46 carry
= src
[i
- 1] >> (BITS_PER_TYPE(u32
) - shift
);
50 static void nft_bitwise_eval_rshift(u32
*dst
, const u32
*src
,
51 const struct nft_bitwise
*priv
)
53 u32 shift
= priv
->data
.data
[0];
57 for (i
= 0; i
< DIV_ROUND_UP(priv
->len
, sizeof(u32
)); i
++) {
58 dst
[i
] = carry
| (src
[i
] >> shift
);
59 carry
= src
[i
] << (BITS_PER_TYPE(u32
) - shift
);
63 void nft_bitwise_eval(const struct nft_expr
*expr
,
64 struct nft_regs
*regs
, const struct nft_pktinfo
*pkt
)
66 const struct nft_bitwise
*priv
= nft_expr_priv(expr
);
67 const u32
*src
= ®s
->data
[priv
->sreg
];
68 u32
*dst
= ®s
->data
[priv
->dreg
];
71 case NFT_BITWISE_BOOL
:
72 nft_bitwise_eval_bool(dst
, src
, priv
);
74 case NFT_BITWISE_LSHIFT
:
75 nft_bitwise_eval_lshift(dst
, src
, priv
);
77 case NFT_BITWISE_RSHIFT
:
78 nft_bitwise_eval_rshift(dst
, src
, priv
);
83 static const struct nla_policy nft_bitwise_policy
[NFTA_BITWISE_MAX
+ 1] = {
84 [NFTA_BITWISE_SREG
] = { .type
= NLA_U32
},
85 [NFTA_BITWISE_DREG
] = { .type
= NLA_U32
},
86 [NFTA_BITWISE_LEN
] = { .type
= NLA_U32
},
87 [NFTA_BITWISE_MASK
] = { .type
= NLA_NESTED
},
88 [NFTA_BITWISE_XOR
] = { .type
= NLA_NESTED
},
89 [NFTA_BITWISE_OP
] = { .type
= NLA_U32
},
90 [NFTA_BITWISE_DATA
] = { .type
= NLA_NESTED
},
93 static int nft_bitwise_init_bool(struct nft_bitwise
*priv
,
94 const struct nlattr
*const tb
[])
96 struct nft_data_desc mask
, xor;
99 if (tb
[NFTA_BITWISE_DATA
])
102 if (!tb
[NFTA_BITWISE_MASK
] ||
103 !tb
[NFTA_BITWISE_XOR
])
106 err
= nft_data_init(NULL
, &priv
->mask
, sizeof(priv
->mask
), &mask
,
107 tb
[NFTA_BITWISE_MASK
]);
110 if (mask
.type
!= NFT_DATA_VALUE
|| mask
.len
!= priv
->len
) {
115 err
= nft_data_init(NULL
, &priv
->xor, sizeof(priv
->xor), &xor,
116 tb
[NFTA_BITWISE_XOR
]);
119 if (xor.type
!= NFT_DATA_VALUE
|| xor.len
!= priv
->len
) {
126 nft_data_release(&priv
->xor, xor.type
);
128 nft_data_release(&priv
->mask
, mask
.type
);
132 static int nft_bitwise_init_shift(struct nft_bitwise
*priv
,
133 const struct nlattr
*const tb
[])
135 struct nft_data_desc d
;
138 if (tb
[NFTA_BITWISE_MASK
] ||
139 tb
[NFTA_BITWISE_XOR
])
142 if (!tb
[NFTA_BITWISE_DATA
])
145 err
= nft_data_init(NULL
, &priv
->data
, sizeof(priv
->data
), &d
,
146 tb
[NFTA_BITWISE_DATA
]);
149 if (d
.type
!= NFT_DATA_VALUE
|| d
.len
!= sizeof(u32
) ||
150 priv
->data
.data
[0] >= BITS_PER_TYPE(u32
)) {
151 nft_data_release(&priv
->data
, d
.type
);
158 static int nft_bitwise_init(const struct nft_ctx
*ctx
,
159 const struct nft_expr
*expr
,
160 const struct nlattr
* const tb
[])
162 struct nft_bitwise
*priv
= nft_expr_priv(expr
);
166 err
= nft_parse_u32_check(tb
[NFTA_BITWISE_LEN
], U8_MAX
, &len
);
172 priv
->sreg
= nft_parse_register(tb
[NFTA_BITWISE_SREG
]);
173 err
= nft_validate_register_load(priv
->sreg
, priv
->len
);
177 priv
->dreg
= nft_parse_register(tb
[NFTA_BITWISE_DREG
]);
178 err
= nft_validate_register_store(ctx
, priv
->dreg
, NULL
,
179 NFT_DATA_VALUE
, priv
->len
);
183 if (tb
[NFTA_BITWISE_OP
]) {
184 priv
->op
= ntohl(nla_get_be32(tb
[NFTA_BITWISE_OP
]));
186 case NFT_BITWISE_BOOL
:
187 case NFT_BITWISE_LSHIFT
:
188 case NFT_BITWISE_RSHIFT
:
194 priv
->op
= NFT_BITWISE_BOOL
;
198 case NFT_BITWISE_BOOL
:
199 err
= nft_bitwise_init_bool(priv
, tb
);
201 case NFT_BITWISE_LSHIFT
:
202 case NFT_BITWISE_RSHIFT
:
203 err
= nft_bitwise_init_shift(priv
, tb
);
210 static int nft_bitwise_dump_bool(struct sk_buff
*skb
,
211 const struct nft_bitwise
*priv
)
213 if (nft_data_dump(skb
, NFTA_BITWISE_MASK
, &priv
->mask
,
214 NFT_DATA_VALUE
, priv
->len
) < 0)
217 if (nft_data_dump(skb
, NFTA_BITWISE_XOR
, &priv
->xor,
218 NFT_DATA_VALUE
, priv
->len
) < 0)
224 static int nft_bitwise_dump_shift(struct sk_buff
*skb
,
225 const struct nft_bitwise
*priv
)
227 if (nft_data_dump(skb
, NFTA_BITWISE_DATA
, &priv
->data
,
228 NFT_DATA_VALUE
, sizeof(u32
)) < 0)
233 static int nft_bitwise_dump(struct sk_buff
*skb
, const struct nft_expr
*expr
)
235 const struct nft_bitwise
*priv
= nft_expr_priv(expr
);
238 if (nft_dump_register(skb
, NFTA_BITWISE_SREG
, priv
->sreg
))
240 if (nft_dump_register(skb
, NFTA_BITWISE_DREG
, priv
->dreg
))
242 if (nla_put_be32(skb
, NFTA_BITWISE_LEN
, htonl(priv
->len
)))
244 if (nla_put_be32(skb
, NFTA_BITWISE_OP
, htonl(priv
->op
)))
248 case NFT_BITWISE_BOOL
:
249 err
= nft_bitwise_dump_bool(skb
, priv
);
251 case NFT_BITWISE_LSHIFT
:
252 case NFT_BITWISE_RSHIFT
:
253 err
= nft_bitwise_dump_shift(skb
, priv
);
260 static struct nft_data zero
;
262 static int nft_bitwise_offload(struct nft_offload_ctx
*ctx
,
263 struct nft_flow_rule
*flow
,
264 const struct nft_expr
*expr
)
266 const struct nft_bitwise
*priv
= nft_expr_priv(expr
);
267 struct nft_offload_reg
*reg
= &ctx
->regs
[priv
->dreg
];
269 if (priv
->op
!= NFT_BITWISE_BOOL
)
272 if (memcmp(&priv
->xor, &zero
, sizeof(priv
->xor)) ||
273 priv
->sreg
!= priv
->dreg
|| priv
->len
!= reg
->len
)
276 memcpy(®
->mask
, &priv
->mask
, sizeof(priv
->mask
));
281 static const struct nft_expr_ops nft_bitwise_ops
= {
282 .type
= &nft_bitwise_type
,
283 .size
= NFT_EXPR_SIZE(sizeof(struct nft_bitwise
)),
284 .eval
= nft_bitwise_eval
,
285 .init
= nft_bitwise_init
,
286 .dump
= nft_bitwise_dump
,
287 .offload
= nft_bitwise_offload
,
291 nft_bitwise_extract_u32_data(const struct nlattr
* const tb
, u32
*out
)
293 struct nft_data_desc desc
;
294 struct nft_data data
;
297 err
= nft_data_init(NULL
, &data
, sizeof(data
), &desc
, tb
);
301 if (desc
.type
!= NFT_DATA_VALUE
|| desc
.len
!= sizeof(u32
)) {
307 nft_data_release(&data
, desc
.type
);
311 static int nft_bitwise_fast_init(const struct nft_ctx
*ctx
,
312 const struct nft_expr
*expr
,
313 const struct nlattr
* const tb
[])
315 struct nft_bitwise_fast_expr
*priv
= nft_expr_priv(expr
);
318 priv
->sreg
= nft_parse_register(tb
[NFTA_BITWISE_SREG
]);
319 err
= nft_validate_register_load(priv
->sreg
, sizeof(u32
));
323 priv
->dreg
= nft_parse_register(tb
[NFTA_BITWISE_DREG
]);
324 err
= nft_validate_register_store(ctx
, priv
->dreg
, NULL
,
325 NFT_DATA_VALUE
, sizeof(u32
));
329 if (tb
[NFTA_BITWISE_DATA
])
332 if (!tb
[NFTA_BITWISE_MASK
] ||
333 !tb
[NFTA_BITWISE_XOR
])
336 err
= nft_bitwise_extract_u32_data(tb
[NFTA_BITWISE_MASK
], &priv
->mask
);
340 err
= nft_bitwise_extract_u32_data(tb
[NFTA_BITWISE_XOR
], &priv
->xor);
348 nft_bitwise_fast_dump(struct sk_buff
*skb
, const struct nft_expr
*expr
)
350 const struct nft_bitwise_fast_expr
*priv
= nft_expr_priv(expr
);
351 struct nft_data data
;
353 if (nft_dump_register(skb
, NFTA_BITWISE_SREG
, priv
->sreg
))
355 if (nft_dump_register(skb
, NFTA_BITWISE_DREG
, priv
->dreg
))
357 if (nla_put_be32(skb
, NFTA_BITWISE_LEN
, htonl(sizeof(u32
))))
359 if (nla_put_be32(skb
, NFTA_BITWISE_OP
, htonl(NFT_BITWISE_BOOL
)))
362 data
.data
[0] = priv
->mask
;
363 if (nft_data_dump(skb
, NFTA_BITWISE_MASK
, &data
,
364 NFT_DATA_VALUE
, sizeof(u32
)) < 0)
367 data
.data
[0] = priv
->xor;
368 if (nft_data_dump(skb
, NFTA_BITWISE_XOR
, &data
,
369 NFT_DATA_VALUE
, sizeof(u32
)) < 0)
375 static int nft_bitwise_fast_offload(struct nft_offload_ctx
*ctx
,
376 struct nft_flow_rule
*flow
,
377 const struct nft_expr
*expr
)
379 const struct nft_bitwise_fast_expr
*priv
= nft_expr_priv(expr
);
380 struct nft_offload_reg
*reg
= &ctx
->regs
[priv
->dreg
];
382 if (priv
->xor || priv
->sreg
!= priv
->dreg
|| reg
->len
!= sizeof(u32
))
385 reg
->mask
.data
[0] = priv
->mask
;
389 const struct nft_expr_ops nft_bitwise_fast_ops
= {
390 .type
= &nft_bitwise_type
,
391 .size
= NFT_EXPR_SIZE(sizeof(struct nft_bitwise_fast_expr
)),
392 .eval
= NULL
, /* inlined */
393 .init
= nft_bitwise_fast_init
,
394 .dump
= nft_bitwise_fast_dump
,
395 .offload
= nft_bitwise_fast_offload
,
398 static const struct nft_expr_ops
*
399 nft_bitwise_select_ops(const struct nft_ctx
*ctx
,
400 const struct nlattr
* const tb
[])
405 if (!tb
[NFTA_BITWISE_LEN
] ||
406 !tb
[NFTA_BITWISE_SREG
] ||
407 !tb
[NFTA_BITWISE_DREG
])
408 return ERR_PTR(-EINVAL
);
410 err
= nft_parse_u32_check(tb
[NFTA_BITWISE_LEN
], U8_MAX
, &len
);
414 if (len
!= sizeof(u32
))
415 return &nft_bitwise_ops
;
417 if (tb
[NFTA_BITWISE_OP
] &&
418 ntohl(nla_get_be32(tb
[NFTA_BITWISE_OP
])) != NFT_BITWISE_BOOL
)
419 return &nft_bitwise_ops
;
421 return &nft_bitwise_fast_ops
;
424 struct nft_expr_type nft_bitwise_type __read_mostly
= {
426 .select_ops
= nft_bitwise_select_ops
,
427 .policy
= nft_bitwise_policy
,
428 .maxattr
= NFTA_BITWISE_MAX
,
429 .owner
= THIS_MODULE
,