17 #include <arpa/inet.h>
19 #include <libmnl/libmnl.h>
20 #include <linux/netfilter/nf_tables.h>
21 #include <libnftnl/expr.h>
22 #include <libnftnl/rule.h>
27 enum nft_registers sreg;
28 enum nft_registers dreg;
30 union nft_data_reg mask;
31 union nft_data_reg xor;
35 nft_rule_expr_bitwise_set(
struct nft_rule_expr *e, uint16_t type,
36 const void *data, uint32_t data_len)
41 case NFT_EXPR_BITWISE_SREG:
42 bitwise->sreg = *((uint32_t *)data);
44 case NFT_EXPR_BITWISE_DREG:
45 bitwise->dreg = *((uint32_t *)data);
47 case NFT_EXPR_BITWISE_LEN:
48 bitwise->len = *((
unsigned int *)data);
50 case NFT_EXPR_BITWISE_MASK:
51 memcpy(&bitwise->mask.val, data, data_len);
52 bitwise->mask.len = data_len;
54 case NFT_EXPR_BITWISE_XOR:
55 memcpy(&bitwise->xor.val, data, data_len);
56 bitwise->xor.len = data_len;
65 nft_rule_expr_bitwise_get(
const struct nft_rule_expr *e, uint16_t type,
71 case NFT_EXPR_BITWISE_SREG:
72 *data_len =
sizeof(bitwise->sreg);
73 return &bitwise->sreg;
74 case NFT_EXPR_BITWISE_DREG:
75 *data_len =
sizeof(bitwise->dreg);
76 return &bitwise->dreg;
77 case NFT_EXPR_BITWISE_LEN:
78 *data_len =
sizeof(bitwise->len);
80 case NFT_EXPR_BITWISE_MASK:
81 *data_len = bitwise->mask.len;
82 return &bitwise->mask.val;
83 case NFT_EXPR_BITWISE_XOR:
84 *data_len = bitwise->xor.len;
85 return &bitwise->xor.val;
90 static int nft_rule_expr_bitwise_cb(
const struct nlattr *attr,
void *data)
92 const struct nlattr **tb = data;
93 int type = mnl_attr_get_type(attr);
95 if (mnl_attr_type_valid(attr, NFTA_BITWISE_MAX) < 0)
99 case NFTA_BITWISE_SREG:
100 case NFTA_BITWISE_DREG:
101 case NFTA_BITWISE_LEN:
102 if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) {
103 perror(
"mnl_attr_validate");
107 case NFTA_BITWISE_MASK:
108 case NFTA_BITWISE_XOR:
109 if (mnl_attr_validate(attr, MNL_TYPE_BINARY) < 0) {
110 perror(
"mnl_attr_validate");
121 nft_rule_expr_bitwise_build(
struct nlmsghdr *nlh,
struct nft_rule_expr *e)
125 if (e->flags & (1 << NFT_EXPR_BITWISE_SREG))
126 mnl_attr_put_u32(nlh, NFTA_BITWISE_SREG, htonl(bitwise->sreg));
127 if (e->flags & (1 << NFT_EXPR_BITWISE_DREG))
128 mnl_attr_put_u32(nlh, NFTA_BITWISE_DREG, htonl(bitwise->dreg));
129 if (e->flags & (1 << NFT_EXPR_BITWISE_LEN))
130 mnl_attr_put_u32(nlh, NFTA_BITWISE_LEN, htonl(bitwise->len));
131 if (e->flags & (1 << NFT_EXPR_BITWISE_MASK)) {
134 nest = mnl_attr_nest_start(nlh, NFTA_BITWISE_MASK);
135 mnl_attr_put(nlh, NFTA_DATA_VALUE, bitwise->mask.len,
137 mnl_attr_nest_end(nlh, nest);
139 if (e->flags & (1 << NFT_EXPR_BITWISE_XOR)) {
142 nest = mnl_attr_nest_start(nlh, NFTA_BITWISE_XOR);
143 mnl_attr_put(nlh, NFTA_DATA_VALUE, bitwise->xor.len,
145 mnl_attr_nest_end(nlh, nest);
150 nft_rule_expr_bitwise_parse(
struct nft_rule_expr *e,
struct nlattr *attr)
153 struct nlattr *tb[NFTA_BITWISE_MAX+1] = {};
156 if (mnl_attr_parse_nested(attr, nft_rule_expr_bitwise_cb, tb) < 0)
159 if (tb[NFTA_BITWISE_SREG]) {
160 bitwise->sreg = ntohl(mnl_attr_get_u32(tb[NFTA_BITWISE_SREG]));
161 e->flags |= (1 << NFT_EXPR_BITWISE_SREG);
163 if (tb[NFTA_BITWISE_DREG]) {
164 bitwise->dreg = ntohl(mnl_attr_get_u32(tb[NFTA_BITWISE_DREG]));
165 e->flags |= (1 << NFT_EXPR_BITWISE_DREG);
167 if (tb[NFTA_BITWISE_LEN]) {
168 bitwise->len = ntohl(mnl_attr_get_u32(tb[NFTA_BITWISE_LEN]));
169 e->flags |= (1 << NFT_EXPR_BITWISE_LEN);
171 if (tb[NFTA_BITWISE_MASK]) {
172 ret = nft_parse_data(&bitwise->mask, tb[NFTA_BITWISE_MASK], NULL);
173 e->flags |= (1 << NFTA_BITWISE_MASK);
175 if (tb[NFTA_BITWISE_XOR]) {
176 ret = nft_parse_data(&bitwise->xor, tb[NFTA_BITWISE_XOR], NULL);
177 e->flags |= (1 << NFTA_BITWISE_XOR);
184 nft_rule_expr_bitwise_json_parse(
struct nft_rule_expr *e, json_t *root,
185 struct nft_parse_err *err)
191 if (nft_jansson_parse_reg(root,
"sreg", NFT_TYPE_U32, ®, err) == 0)
192 nft_rule_expr_set_u32(e, NFT_EXPR_BITWISE_SREG, reg);
194 if (nft_jansson_parse_reg(root,
"dreg", NFT_TYPE_U32, ®, err) == 0)
195 nft_rule_expr_set_u32(e, NFT_EXPR_BITWISE_DREG, reg);
197 if (nft_jansson_parse_val(root,
"len", NFT_TYPE_U32, &len, err) == 0)
198 nft_rule_expr_set_u32(e, NFT_EXPR_BITWISE_LEN, len);
200 if (nft_jansson_data_reg_parse(root,
"mask", &bitwise->mask,
202 e->flags |= (1 << NFT_EXPR_BITWISE_MASK);
204 if (nft_jansson_data_reg_parse(root,
"xor", &bitwise->xor,
206 e->flags |= (1 << NFT_EXPR_BITWISE_XOR);
208 if (bitwise->mask.len != bitwise->xor.len)
219 nft_rule_expr_bitwise_xml_parse(
struct nft_rule_expr *e, mxml_node_t *tree,
220 struct nft_parse_err *err)
224 uint32_t sreg, dreg, len;
226 if (nft_mxml_reg_parse(tree,
"sreg", &sreg, MXML_DESCEND_FIRST,
227 NFT_XML_MAND, err) == 0)
228 nft_rule_expr_set_u32(e, NFT_EXPR_BITWISE_SREG, sreg);
230 if (nft_mxml_reg_parse(tree,
"dreg", &dreg, MXML_DESCEND_FIRST,
231 NFT_XML_MAND, err) == 0)
232 nft_rule_expr_set_u32(e, NFT_EXPR_BITWISE_DREG, dreg);
234 if (nft_mxml_num_parse(tree,
"len", MXML_DESCEND_FIRST, BASE_DEC,
235 &len, NFT_TYPE_U32, NFT_XML_MAND, err) == 0)
236 nft_rule_expr_set_u32(e, NFT_EXPR_BITWISE_LEN, len);
238 if (nft_mxml_data_reg_parse(tree,
"mask", &bitwise->mask, NFT_XML_MAND,
240 e->flags |= (1 << NFT_EXPR_BITWISE_MASK);
242 if (nft_mxml_data_reg_parse(tree,
"xor", &bitwise->xor, NFT_XML_MAND,
244 e->flags |= (1 << NFT_EXPR_BITWISE_XOR);
249 if (bitwise->mask.len != bitwise->xor.len)
259 static int nft_rule_expr_bitwise_snprintf_json(
char *buf,
size_t size,
260 struct nft_rule_expr *e)
262 int len = size, offset = 0, ret;
265 if (e->flags & (1 << NFT_EXPR_BITWISE_SREG)) {
266 ret = snprintf(buf + offset, len,
"\"sreg\":%u,",
268 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
270 if (e->flags & (1 << NFT_EXPR_BITWISE_DREG)) {
271 ret = snprintf(buf + offset, len,
"\"dreg\":%u,",
273 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
275 if (e->flags & (1 << NFT_EXPR_BITWISE_LEN)) {
276 ret = snprintf(buf + offset, len,
"\"len\":%u,",
278 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
280 if (e->flags & (1 << NFT_EXPR_BITWISE_MASK)) {
281 ret = snprintf(buf + offset, len,
"\"mask\":{");
282 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
284 ret = nft_data_reg_snprintf(buf+offset, len, &bitwise->mask,
285 NFT_OUTPUT_JSON, 0, DATA_VALUE);
286 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
288 ret = snprintf(buf + offset, len,
"},");
289 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
292 if (e->flags & (1 << NFT_EXPR_BITWISE_XOR)) {
293 ret = snprintf(buf+offset, len,
"\"xor\":{");
294 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
296 ret = nft_data_reg_snprintf(buf+offset, len, &bitwise->xor,
297 NFT_OUTPUT_JSON, 0, DATA_VALUE);
298 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
300 ret = snprintf(buf+offset, len,
"},");
301 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
310 static int nft_rule_expr_bitwise_snprintf_xml(
char *buf,
size_t size,
311 struct nft_rule_expr *e)
314 int len = size, offset = 0, ret;
316 if (e->flags & (1 << NFT_EXPR_BITWISE_SREG)) {
317 ret = snprintf(buf + offset, len,
"<sreg>%u</sreg>",
319 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
321 if (e->flags & (1 << NFT_EXPR_BITWISE_DREG)) {
322 ret = snprintf(buf + offset, len,
"<dreg>%u</dreg>",
324 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
326 if (e->flags & (1 << NFT_EXPR_BITWISE_LEN)) {
327 ret = snprintf(buf + offset, len,
"<len>%u</len>",
329 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
331 if (e->flags & (1 << NFT_EXPR_BITWISE_MASK)) {
332 ret = snprintf(buf + offset, len,
"<mask>");
333 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
335 ret = nft_data_reg_snprintf(buf + offset, len, &bitwise->mask,
336 NFT_OUTPUT_XML, 0, DATA_VALUE);
337 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
339 ret = snprintf(buf + offset, len,
"</mask>");
340 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
342 if (e->flags & (1 << NFT_EXPR_BITWISE_XOR)) {
343 ret = snprintf(buf + offset, len,
"<xor>");
344 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
346 ret = nft_data_reg_snprintf(buf + offset, len, &bitwise->xor,
347 NFT_OUTPUT_XML, 0, DATA_VALUE);
348 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
350 ret = snprintf(buf + offset, len,
"</xor>");
351 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
357 static int nft_rule_expr_bitwise_snprintf_default(
char *buf,
size_t size,
358 struct nft_rule_expr *e)
361 int len = size, offset = 0, ret;
363 ret = snprintf(buf, len,
"reg %u = (reg=%u & ",
364 bitwise->dreg, bitwise->sreg);
365 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
367 ret = nft_data_reg_snprintf(buf+offset, len, &bitwise->mask,
368 NFT_OUTPUT_DEFAULT, 0, DATA_VALUE);
369 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
371 ret = snprintf(buf+offset, len,
") ^ ");
372 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
374 ret = nft_data_reg_snprintf(buf+offset, len, &bitwise->xor,
375 NFT_OUTPUT_DEFAULT, 0, DATA_VALUE);
376 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
382 nft_rule_expr_bitwise_snprintf(
char *buf,
size_t size, uint32_t type,
383 uint32_t flags,
struct nft_rule_expr *e)
386 case NFT_OUTPUT_DEFAULT:
387 return nft_rule_expr_bitwise_snprintf_default(buf, size, e);
389 return nft_rule_expr_bitwise_snprintf_xml(buf, size, e);
390 case NFT_OUTPUT_JSON:
391 return nft_rule_expr_bitwise_snprintf_json(buf, size, e);
398 struct expr_ops expr_ops_bitwise = {
401 .max_attr = NFTA_BITWISE_MAX,
402 .set = nft_rule_expr_bitwise_set,
403 .get = nft_rule_expr_bitwise_get,
404 .parse = nft_rule_expr_bitwise_parse,
405 .build = nft_rule_expr_bitwise_build,
406 .snprintf = nft_rule_expr_bitwise_snprintf,
407 .xml_parse = nft_rule_expr_bitwise_xml_parse,
408 .json_parse = nft_rule_expr_bitwise_json_parse,
411 static void __init expr_bitwise(
void)
413 nft_expr_ops_register(&expr_ops_bitwise);