17 #include <arpa/inet.h>
20 #include <libmnl/libmnl.h>
21 #include <linux/netfilter/nf_tables.h>
22 #include <libnftnl/expr.h>
23 #include <libnftnl/rule.h>
28 union nft_data_reg data;
29 enum nft_registers sreg;
34 nft_rule_expr_cmp_set(
struct nft_rule_expr *e, uint16_t type,
35 const void *data, uint32_t data_len)
40 case NFT_EXPR_CMP_SREG:
41 cmp->sreg = *((uint32_t *)data);
44 cmp->op = *((uint32_t *)data);
46 case NFT_EXPR_CMP_DATA:
47 memcpy(&cmp->data.val, data, data_len);
48 cmp->data.len = data_len;
57 nft_rule_expr_cmp_get(
const struct nft_rule_expr *e, uint16_t type,
63 case NFT_EXPR_CMP_SREG:
64 *data_len =
sizeof(cmp->sreg);
67 *data_len =
sizeof(cmp->op);
69 case NFT_EXPR_CMP_DATA:
70 *data_len = cmp->data.len;
71 return &cmp->data.val;
76 static int nft_rule_expr_cmp_cb(
const struct nlattr *attr,
void *data)
78 const struct nlattr **tb = data;
79 int type = mnl_attr_get_type(attr);
81 if (mnl_attr_type_valid(attr, NFTA_CMP_MAX) < 0)
87 if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) {
88 perror(
"mnl_attr_validate");
93 if (mnl_attr_validate(attr, MNL_TYPE_BINARY) < 0) {
94 perror(
"mnl_attr_validate");
105 nft_rule_expr_cmp_build(
struct nlmsghdr *nlh,
struct nft_rule_expr *e)
109 if (e->flags & (1 << NFT_EXPR_CMP_SREG))
110 mnl_attr_put_u32(nlh, NFTA_CMP_SREG, htonl(cmp->sreg));
111 if (e->flags & (1 << NFT_EXPR_CMP_OP))
112 mnl_attr_put_u32(nlh, NFTA_CMP_OP, htonl(cmp->op));
113 if (e->flags & (1 << NFT_EXPR_CMP_DATA)) {
116 nest = mnl_attr_nest_start(nlh, NFTA_CMP_DATA);
117 mnl_attr_put(nlh, NFTA_DATA_VALUE, cmp->data.len, cmp->data.val);
118 mnl_attr_nest_end(nlh, nest);
123 nft_rule_expr_cmp_parse(
struct nft_rule_expr *e,
struct nlattr *attr)
126 struct nlattr *tb[NFTA_CMP_MAX+1] = {};
129 if (mnl_attr_parse_nested(attr, nft_rule_expr_cmp_cb, tb) < 0)
132 if (tb[NFTA_CMP_SREG]) {
133 cmp->sreg = ntohl(mnl_attr_get_u32(tb[NFTA_CMP_SREG]));
134 e->flags |= (1 << NFTA_CMP_SREG);
136 if (tb[NFTA_CMP_OP]) {
137 cmp->op = ntohl(mnl_attr_get_u32(tb[NFTA_CMP_OP]));
138 e->flags |= (1 << NFTA_CMP_OP);
140 if (tb[NFTA_CMP_DATA]) {
141 ret = nft_parse_data(&cmp->data, tb[NFTA_CMP_DATA], NULL);
142 e->flags |= (1 << NFTA_CMP_DATA);
148 static char *expr_cmp_str[] = {
150 [NFT_CMP_NEQ] =
"neq",
152 [NFT_CMP_LTE] =
"lte",
154 [NFT_CMP_GTE] =
"gte",
157 static inline int nft_str2cmp(
const char *op)
159 if (strcmp(op,
"eq") == 0)
161 else if (strcmp(op,
"neq") == 0)
163 else if (strcmp(op,
"lt") == 0)
165 else if (strcmp(op,
"lte") == 0)
167 else if (strcmp(op,
"gt") == 0)
169 else if (strcmp(op,
"gte") == 0)
177 static int nft_rule_expr_cmp_json_parse(
struct nft_rule_expr *e, json_t *root,
178 struct nft_parse_err *err)
186 if (nft_jansson_parse_val(root,
"sreg", NFT_TYPE_U32, &uval32,
188 nft_rule_expr_set_u32(e, NFT_EXPR_CMP_SREG, uval32);
190 op = nft_jansson_parse_str(root,
"op", err);
192 base = nft_str2cmp(op);
196 nft_rule_expr_set_u32(e, NFT_EXPR_CMP_OP, base);
199 if (nft_jansson_data_reg_parse(root,
"cmpdata",
200 &cmp->data, err) == DATA_VALUE)
201 e->flags |= (1 << NFT_EXPR_CMP_DATA);
210 static int nft_rule_expr_cmp_xml_parse(
struct nft_rule_expr *e, mxml_node_t *tree,
211 struct nft_parse_err *err)
219 if (nft_mxml_reg_parse(tree,
"sreg", &sreg, MXML_DESCEND_FIRST,
220 NFT_XML_MAND, err) == 0)
221 nft_rule_expr_set_u32(e, NFT_EXPR_CMP_SREG, sreg);
223 op = nft_mxml_str_parse(tree,
"op", MXML_DESCEND_FIRST, NFT_XML_MAND,
226 op_value = nft_str2cmp(op);
230 nft_rule_expr_set_u32(e, NFT_EXPR_CMP_OP, op_value);
233 if (nft_mxml_data_reg_parse(tree,
"cmpdata",
234 &cmp->data, NFT_XML_MAND,
236 e->flags |= (1 << NFT_EXPR_CMP_DATA);
245 static int nft_rule_expr_cmp_snprintf_json(
char *buf,
size_t size,
246 struct nft_rule_expr *e)
249 int len = size, offset = 0, ret;
251 if (e->flags & (1 << NFT_EXPR_CMP_SREG)) {
252 ret = snprintf(buf + offset, len,
"\"sreg\":%u,", cmp->sreg);
253 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
255 if (e->flags & (1 << NFT_EXPR_CMP_OP)) {
256 ret = snprintf(buf + offset, len,
"\"op\":\"%s\",",
257 expr_cmp_str[cmp->op]);
258 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
260 ret = nft_data_reg_snprintf(buf + offset, len, &cmp->data,
261 NFT_OUTPUT_JSON, 0, DATA_VALUE);
262 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
267 static int nft_rule_expr_cmp_snprintf_xml(
char *buf,
size_t size,
268 struct nft_rule_expr *e)
271 int len = size, offset = 0, ret;
273 if (e->flags & (1 << NFT_EXPR_CMP_SREG)) {
274 ret = snprintf(buf, len,
"<sreg>%u</sreg>",
276 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
279 if (e->flags & (1 << NFT_EXPR_CMP_SREG)) {
280 ret = snprintf(buf + offset, len,
"<op>%s</op>",
281 expr_cmp_str[cmp->op]);
282 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
285 ret = nft_data_reg_snprintf(buf + offset, len, &cmp->data,
286 NFT_OUTPUT_XML, 0, DATA_VALUE);
287 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
292 static int nft_rule_expr_cmp_snprintf_default(
char *buf,
size_t size,
293 struct nft_rule_expr *e)
296 int len = size, offset = 0, ret;
298 ret = snprintf(buf, len,
"%s reg %u ",
299 expr_cmp_str[cmp->op], cmp->sreg);
300 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
302 ret = nft_data_reg_snprintf(buf+offset, len, &cmp->data,
303 NFT_OUTPUT_DEFAULT, 0, DATA_VALUE);
304 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
310 nft_rule_expr_cmp_snprintf(
char *buf,
size_t size, uint32_t type,
311 uint32_t flags,
struct nft_rule_expr *e)
314 case NFT_OUTPUT_DEFAULT:
315 return nft_rule_expr_cmp_snprintf_default(buf, size, e);
317 return nft_rule_expr_cmp_snprintf_xml(buf, size, e);
318 case NFT_OUTPUT_JSON:
319 return nft_rule_expr_cmp_snprintf_json(buf, size, e);
326 struct expr_ops expr_ops_cmp = {
329 .max_attr = NFTA_CMP_MAX,
330 .set = nft_rule_expr_cmp_set,
331 .get = nft_rule_expr_cmp_get,
332 .parse = nft_rule_expr_cmp_parse,
333 .build = nft_rule_expr_cmp_build,
334 .snprintf = nft_rule_expr_cmp_snprintf,
335 .xml_parse = nft_rule_expr_cmp_xml_parse,
336 .json_parse = nft_rule_expr_cmp_json_parse,
338 static void __init expr_cmp_init(
void)
340 nft_expr_ops_register(&expr_ops_cmp);