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;
29 enum nft_byteorder_ops op;
35 nft_rule_expr_byteorder_set(
struct nft_rule_expr *e, uint16_t type,
36 const void *data, uint32_t data_len)
41 case NFT_EXPR_BYTEORDER_SREG:
42 byteorder->sreg = *((uint32_t *)data);
44 case NFT_EXPR_BYTEORDER_DREG:
45 byteorder->dreg = *((uint32_t *)data);
47 case NFT_EXPR_BYTEORDER_OP:
48 byteorder->op = *((uint32_t *)data);
50 case NFT_EXPR_BYTEORDER_LEN:
51 byteorder->len = *((
unsigned int *)data);
53 case NFT_EXPR_BYTEORDER_SIZE:
54 byteorder->size = *((
unsigned int *)data);
63 nft_rule_expr_byteorder_get(
const struct nft_rule_expr *e, uint16_t type,
69 case NFT_EXPR_BYTEORDER_SREG:
70 *data_len =
sizeof(byteorder->sreg);
71 return &byteorder->sreg;
72 case NFT_EXPR_BYTEORDER_DREG:
73 *data_len =
sizeof(byteorder->dreg);
74 return &byteorder->dreg;
75 case NFT_EXPR_BYTEORDER_OP:
76 *data_len =
sizeof(byteorder->op);
77 return &byteorder->op;
78 case NFT_EXPR_BYTEORDER_LEN:
79 *data_len =
sizeof(byteorder->len);
80 return &byteorder->len;
81 case NFT_EXPR_BYTEORDER_SIZE:
82 *data_len =
sizeof(byteorder->size);
83 return &byteorder->size;
88 static int nft_rule_expr_byteorder_cb(
const struct nlattr *attr,
void *data)
90 const struct nlattr **tb = data;
91 int type = mnl_attr_get_type(attr);
93 if (mnl_attr_type_valid(attr, NFTA_BYTEORDER_MAX) < 0)
97 case NFTA_BYTEORDER_SREG:
98 case NFTA_BYTEORDER_DREG:
99 case NFTA_BYTEORDER_OP:
100 case NFTA_BYTEORDER_LEN:
101 case NFTA_BYTEORDER_SIZE:
102 if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) {
103 perror(
"mnl_attr_validate");
114 nft_rule_expr_byteorder_build(
struct nlmsghdr *nlh,
struct nft_rule_expr *e)
118 if (e->flags & (1 << NFT_EXPR_BYTEORDER_SREG)) {
119 mnl_attr_put_u32(nlh, NFTA_BYTEORDER_SREG,
120 htonl(byteorder->sreg));
122 if (e->flags & (1 << NFT_EXPR_BYTEORDER_DREG)) {
123 mnl_attr_put_u32(nlh, NFTA_BYTEORDER_DREG,
124 htonl(byteorder->dreg));
126 if (e->flags & (1 << NFT_EXPR_BYTEORDER_OP)) {
127 mnl_attr_put_u32(nlh, NFTA_BYTEORDER_OP,
128 htonl(byteorder->op));
130 if (e->flags & (1 << NFT_EXPR_BYTEORDER_LEN)) {
131 mnl_attr_put_u32(nlh, NFTA_BYTEORDER_LEN,
132 htonl(byteorder->len));
134 if (e->flags & (1 << NFT_EXPR_BYTEORDER_SIZE)) {
135 mnl_attr_put_u32(nlh, NFTA_BYTEORDER_SIZE,
136 htonl(byteorder->size));
141 nft_rule_expr_byteorder_parse(
struct nft_rule_expr *e,
struct nlattr *attr)
144 struct nlattr *tb[NFTA_BYTEORDER_MAX+1] = {};
147 if (mnl_attr_parse_nested(attr, nft_rule_expr_byteorder_cb, tb) < 0)
150 if (tb[NFTA_BYTEORDER_SREG]) {
152 ntohl(mnl_attr_get_u32(tb[NFTA_BYTEORDER_SREG]));
153 e->flags |= (1 << NFT_EXPR_BYTEORDER_SREG);
155 if (tb[NFTA_BYTEORDER_DREG]) {
157 ntohl(mnl_attr_get_u32(tb[NFTA_BYTEORDER_DREG]));
158 e->flags |= (1 << NFT_EXPR_BYTEORDER_DREG);
160 if (tb[NFTA_BYTEORDER_OP]) {
162 ntohl(mnl_attr_get_u32(tb[NFTA_BYTEORDER_OP]));
163 e->flags |= (1 << NFT_EXPR_BYTEORDER_OP);
165 if (tb[NFTA_BYTEORDER_LEN]) {
167 ntohl(mnl_attr_get_u32(tb[NFTA_BYTEORDER_LEN]));
168 e->flags |= (1 << NFT_EXPR_BYTEORDER_LEN);
170 if (tb[NFTA_BYTEORDER_SIZE]) {
172 ntohl(mnl_attr_get_u32(tb[NFTA_BYTEORDER_SIZE]));
173 e->flags |= (1 << NFT_EXPR_BYTEORDER_SIZE);
179 static char *expr_byteorder_str[] = {
180 [NFT_BYTEORDER_HTON] =
"hton",
181 [NFT_BYTEORDER_NTOH] =
"ntoh",
184 static inline int nft_str2ntoh(
const char *op)
186 if (strcmp(op,
"ntoh") == 0)
187 return NFT_BYTEORDER_NTOH;
188 else if (strcmp(op,
"hton") == 0)
189 return NFT_BYTEORDER_HTON;
197 nft_rule_expr_byteorder_json_parse(
struct nft_rule_expr *e, json_t *root,
198 struct nft_parse_err *err)
202 uint32_t sreg, dreg, len, size;
205 if (nft_jansson_parse_reg(root,
"sreg", NFT_TYPE_U32, &sreg, err) == 0)
206 nft_rule_expr_set_u32(e, NFT_EXPR_BYTEORDER_SREG, sreg);
208 if (nft_jansson_parse_reg(root,
"dreg", NFT_TYPE_U32, &dreg, err) == 0)
209 nft_rule_expr_set_u32(e, NFT_EXPR_BYTEORDER_DREG, dreg);
211 op = nft_jansson_parse_str(root,
"op", err);
213 ntoh = nft_str2ntoh(op);
217 nft_rule_expr_set_u32(e, NFT_EXPR_BYTEORDER_OP, ntoh);
220 if (nft_jansson_parse_val(root,
"len", NFT_TYPE_U32, &len, err) == 0)
221 nft_rule_expr_set_u32(e, NFT_EXPR_BYTEORDER_LEN, len);
223 if (nft_jansson_parse_val(root,
"size", NFT_TYPE_U32, &size, err) == 0)
224 nft_rule_expr_set_u32(e, NFT_EXPR_BYTEORDER_SIZE, size);
234 nft_rule_expr_byteorder_xml_parse(
struct nft_rule_expr *e, mxml_node_t *tree,
235 struct nft_parse_err *err)
240 uint32_t sreg, dreg, len, size;
242 if (nft_mxml_reg_parse(tree,
"sreg", &sreg, MXML_DESCEND_FIRST,
243 NFT_XML_MAND, err) == 0)
244 nft_rule_expr_set_u32(e, NFT_EXPR_BYTEORDER_SREG, sreg);
246 if (nft_mxml_reg_parse(tree,
"dreg", &dreg, MXML_DESCEND, NFT_XML_MAND,
248 nft_rule_expr_set_u32(e, NFT_EXPR_BYTEORDER_DREG, dreg);
250 op = nft_mxml_str_parse(tree,
"op", MXML_DESCEND_FIRST, NFT_XML_MAND,
253 ntoh = nft_str2ntoh(op);
257 nft_rule_expr_set_u32(e, NFT_EXPR_BYTEORDER_OP, ntoh);
260 if (nft_mxml_num_parse(tree,
"len", MXML_DESCEND_FIRST, BASE_DEC,
261 &len, NFT_TYPE_U32, NFT_XML_MAND, err) == 0)
262 nft_rule_expr_set_u32(e, NFT_EXPR_BYTEORDER_LEN, len);
264 if (nft_mxml_num_parse(tree,
"size", MXML_DESCEND_FIRST, BASE_DEC,
265 &size, NFT_TYPE_U32, NFT_XML_MAND, err) == 0)
266 nft_rule_expr_set_u32(e, NFT_EXPR_BYTEORDER_SIZE, size);
275 static int nft_rule_expr_byteorder_snprintf_json(
char *buf,
size_t size,
276 struct nft_rule_expr *e)
279 int len = size, offset = 0, ret;
281 if (e->flags & (1 << NFT_EXPR_BYTEORDER_SREG)) {
282 ret = snprintf(buf + offset, len,
"\"sreg\":%u,",
284 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
286 if (e->flags & (1 << NFT_EXPR_BYTEORDER_DREG)) {
287 ret = snprintf(buf + offset, len,
"\"dreg\":%u,",
289 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
291 if (e->flags & (1 << NFT_EXPR_BYTEORDER_OP)) {
292 ret = snprintf(buf + offset, len,
"\"op\":\"%s\",",
293 expr_byteorder_str[byteorder->op]);
294 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
296 if (e->flags & (1 << NFT_EXPR_BYTEORDER_LEN)) {
297 ret = snprintf(buf + offset, len,
"\"len\":%u,",
299 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
301 if (e->flags & (1 << NFT_EXPR_BYTEORDER_SIZE)) {
302 ret = snprintf(buf + offset, len,
"\"size\":%u,",
304 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
313 static int nft_rule_expr_byteorder_snprintf_xml(
char *buf,
size_t size,
314 struct nft_rule_expr *e)
317 int len = size, offset = 0, ret;
319 if (e->flags & (1 << NFT_EXPR_BYTEORDER_SREG)) {
320 ret = snprintf(buf + offset, len,
"<sreg>%u</sreg>",
322 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
324 if (e->flags & (1 << NFT_EXPR_BYTEORDER_DREG)) {
325 ret = snprintf(buf + offset, len,
"<dreg>%u</dreg>",
327 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
329 if (e->flags & (1 << NFT_EXPR_BYTEORDER_OP)) {
330 ret = snprintf(buf + offset, len,
"<op>%s</op>",
331 expr_byteorder_str[byteorder->op]);
332 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
334 if (e->flags & (1 << NFT_EXPR_BYTEORDER_LEN)) {
335 ret = snprintf(buf + offset, len,
"<len>%u</len>",
337 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
339 if (e->flags & (1 << NFT_EXPR_BYTEORDER_SIZE)) {
340 ret = snprintf(buf + offset, len,
"<size>%u</size>",
342 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
348 static int nft_rule_expr_byteorder_snprintf_default(
char *buf,
size_t size,
349 struct nft_rule_expr *e)
352 int len = size, offset = 0, ret;
354 ret = snprintf(buf, len,
"reg %u = %s(reg %u, %u, %u) ",
355 byteorder->dreg, expr_byteorder_str[byteorder->op],
356 byteorder->sreg, byteorder->size, byteorder->len);
357 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
363 nft_rule_expr_byteorder_snprintf(
char *buf,
size_t size, uint32_t type,
364 uint32_t flags,
struct nft_rule_expr *e)
367 case NFT_OUTPUT_DEFAULT:
368 return nft_rule_expr_byteorder_snprintf_default(buf, size, e);
370 return nft_rule_expr_byteorder_snprintf_xml(buf, size, e);
371 case NFT_OUTPUT_JSON:
372 return nft_rule_expr_byteorder_snprintf_json(buf, size, e);
379 struct expr_ops expr_ops_byteorder = {
382 .max_attr = NFTA_BYTEORDER_MAX,
383 .set = nft_rule_expr_byteorder_set,
384 .get = nft_rule_expr_byteorder_get,
385 .parse = nft_rule_expr_byteorder_parse,
386 .build = nft_rule_expr_byteorder_build,
387 .snprintf = nft_rule_expr_byteorder_snprintf,
388 .xml_parse = nft_rule_expr_byteorder_xml_parse,
389 .json_parse = nft_rule_expr_byteorder_json_parse,
392 static void __init expr_byteorder_init(
void)
394 nft_expr_ops_register(&expr_ops_byteorder);