16 #include <arpa/inet.h>
18 #include <netinet/in.h>
20 #include <libmnl/libmnl.h>
21 #include <linux/netfilter.h>
22 #include <linux/netfilter/nf_tables.h>
23 #include <libnftnl/expr.h>
24 #include <libnftnl/rule.h>
30 static int nft_data_reg_verdict_json_parse(
union nft_data_reg *reg, json_t *data,
31 struct nft_parse_err *err)
34 const char *verdict_str;
37 verdict_str = nft_jansson_parse_str(data,
"verdict", err);
38 if (verdict_str == NULL)
41 if (nft_str2verdict(verdict_str, &verdict) != 0) {
42 err->node_name =
"verdict";
43 err->error = NFT_PARSE_EBADTYPE;
48 reg->verdict = (uint32_t)verdict;
50 if (nft_jansson_node_exist(data,
"chain")) {
51 chain = nft_jansson_parse_str(data,
"chain", err);
55 reg->chain = strdup(chain);
61 static int nft_data_reg_value_json_parse(
union nft_data_reg *reg, json_t *data,
62 struct nft_parse_err *err)
67 if (nft_jansson_parse_val(data,
"len", NFT_TYPE_U8, ®->len, err) < 0)
70 for (i = 0; i < div_round_up(reg->len,
sizeof(uint32_t)); i++) {
71 sprintf(node_name,
"data%d", i);
73 if (nft_jansson_str2num(data, node_name, BASE_HEX,
74 ®->val[i], NFT_TYPE_U32, err) != 0)
82 int nft_data_reg_json_parse(
union nft_data_reg *reg, json_t *data,
83 struct nft_parse_err *err)
89 type = nft_jansson_parse_str(data,
"type", err);
94 if (strcmp(type,
"value") == 0)
95 return nft_data_reg_value_json_parse(reg, data, err);
96 else if (strcmp(type,
"verdict") == 0)
97 return nft_data_reg_verdict_json_parse(reg, data, err);
107 static int nft_data_reg_verdict_xml_parse(
union nft_data_reg *reg,
109 struct nft_parse_err *err)
112 const char *verdict_str;
115 verdict_str = nft_mxml_str_parse(tree,
"verdict", MXML_DESCEND_FIRST,
117 if (verdict_str == NULL)
120 if (nft_str2verdict(verdict_str, &verdict) != 0) {
121 err->node_name =
"verdict";
122 err->error = NFT_PARSE_EBADTYPE;
127 reg->verdict = (uint32_t)verdict;
129 chain = nft_mxml_str_parse(tree,
"chain", MXML_DESCEND_FIRST,
135 reg->chain = strdup(chain);
141 static int nft_data_reg_value_xml_parse(
union nft_data_reg *reg,
143 struct nft_parse_err *err)
158 if (nft_mxml_num_parse(tree,
"len", MXML_DESCEND_FIRST, BASE_DEC,
159 ®->len, NFT_TYPE_U8, NFT_XML_MAND, err) != 0)
163 for (i = 0; i < div_round_up(reg->len,
sizeof(uint32_t)); i++) {
164 sprintf(node_name,
"data%d", i);
166 if (nft_mxml_num_parse(tree, node_name, MXML_DESCEND_FIRST,
167 BASE_HEX, ®->val[i], NFT_TYPE_U32,
168 NFT_XML_MAND, err) != 0)
176 int nft_data_reg_xml_parse(
union nft_data_reg *reg, mxml_node_t *tree,
177 struct nft_parse_err *err)
183 node = mxmlFindElement(tree, tree,
"data_reg",
"type", NULL,
188 type = mxmlElementGetAttr(node,
"type");
193 if (strcmp(type,
"value") == 0)
194 return nft_data_reg_value_xml_parse(reg, node, err);
195 else if (strcmp(type,
"verdict") == 0)
196 return nft_data_reg_verdict_xml_parse(reg, node, err);
201 err->node_name =
"data_reg";
202 err->error = NFT_PARSE_EMISSINGNODE;
211 nft_data_reg_value_snprintf_json(
char *buf,
size_t size,
212 union nft_data_reg *reg,
215 int len = size, offset = 0, ret, i, j;
219 ret = snprintf(buf, len,
"\"data_reg\":{\"type\":\"value\",");
220 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
222 ret = snprintf(buf+offset, len,
"\"len\":%u,", reg->len);
223 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
225 for (i = 0; i < div_round_up(reg->len,
sizeof(uint32_t)); i++) {
226 ret = snprintf(buf+offset, len,
"\"data%d\":\"0x", i);
227 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
229 utemp = htonl(reg->val[i]);
230 tmp = (uint8_t *)&utemp;
232 for (j = 0; j<
sizeof(uint32_t); j++) {
233 ret = snprintf(buf+offset, len,
"%.02x", tmp[j]);
234 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
237 ret = snprintf(buf+offset, len,
"\",");
238 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
241 ret = snprintf(buf+offset, len,
"}");
242 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
248 int nft_data_reg_value_snprintf_xml(
char *buf,
size_t size,
249 union nft_data_reg *reg, uint32_t flags)
251 int len = size, offset = 0, ret, i, j;
255 ret = snprintf(buf, len,
"<data_reg type=\"value\">");
256 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
258 ret = snprintf(buf+offset, len,
"<len>%u</len>", reg->len);
259 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
261 for (i = 0; i < div_round_up(reg->len,
sizeof(uint32_t)); i++) {
262 ret = snprintf(buf+offset, len,
"<data%d>0x", i);
263 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
265 be = htonl(reg->val[i]);
266 tmp = (uint8_t *)&be;
268 for (j = 0; j <
sizeof(uint32_t); j++) {
269 ret = snprintf(buf+offset, len,
"%.02x", tmp[j]);
270 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
273 ret = snprintf(buf+offset, len,
"</data%d>", i);
274 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
277 ret = snprintf(buf+offset, len,
"</data_reg>");
278 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
284 nft_data_reg_value_snprintf_default(
char *buf,
size_t size,
285 union nft_data_reg *reg, uint32_t flags)
287 int len = size, offset = 0, ret, i;
289 for (i = 0; i < div_round_up(reg->len,
sizeof(uint32_t)); i++) {
290 ret = snprintf(buf+offset, len,
"0x%.8x ", reg->val[i]);
291 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
298 nft_data_reg_verdict_snprintf_def(
char *buf,
size_t size,
299 union nft_data_reg *reg, uint32_t flags)
301 int len = size, offset = 0, ret = 0;
303 ret = snprintf(buf, size,
"%s ", nft_verdict2str(reg->verdict));
304 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
306 if (reg->chain != NULL) {
307 ret = snprintf(buf+offset, len,
"-> %s ", reg->chain);
308 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
315 nft_data_reg_verdict_snprintf_xml(
char *buf,
size_t size,
316 union nft_data_reg *reg, uint32_t flags)
318 int len = size, offset = 0, ret = 0;
320 ret = snprintf(buf, size,
"<data_reg type=\"verdict\">"
321 "<verdict>%s</verdict>", nft_verdict2str(reg->verdict));
322 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
324 if (reg->chain != NULL) {
325 ret = snprintf(buf+offset, len,
"<chain>%s</chain>",
327 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
330 ret = snprintf(buf+offset, len,
"</data_reg>");
331 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
337 nft_data_reg_verdict_snprintf_json(
char *buf,
size_t size,
338 union nft_data_reg *reg, uint32_t flags)
340 int len = size, offset = 0, ret = 0;
342 ret = snprintf(buf, size,
"\"data_reg\":{\"type\":\"verdict\","
343 "\"verdict\":\"%s\"", nft_verdict2str(reg->verdict));
344 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
346 if (reg->chain != NULL) {
347 ret = snprintf(buf+offset, len,
",\"chain\":\"%s\"",
349 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
352 ret = snprintf(buf+offset, len,
"}");
353 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
358 int nft_data_reg_snprintf(
char *buf,
size_t size,
union nft_data_reg *reg,
359 uint32_t output_format, uint32_t flags,
int reg_type)
363 switch(output_format) {
364 case NFT_OUTPUT_DEFAULT:
365 return nft_data_reg_value_snprintf_default(buf, size,
368 return nft_data_reg_value_snprintf_xml(buf, size,
370 case NFT_OUTPUT_JSON:
371 return nft_data_reg_value_snprintf_json(buf, size,
378 switch(output_format) {
379 case NFT_OUTPUT_DEFAULT:
380 return nft_data_reg_verdict_snprintf_def(buf, size,
383 return nft_data_reg_verdict_snprintf_xml(buf, size,
385 case NFT_OUTPUT_JSON:
386 return nft_data_reg_verdict_snprintf_json(buf, size,
398 static int nft_data_parse_cb(
const struct nlattr *attr,
void *data)
400 const struct nlattr **tb = data;
401 int type = mnl_attr_get_type(attr);
403 if (mnl_attr_type_valid(attr, NFTA_DATA_MAX) < 0)
407 case NFTA_DATA_VALUE:
408 if (mnl_attr_validate(attr, MNL_TYPE_BINARY) < 0) {
409 perror(
"mnl_attr_validate");
413 case NFTA_DATA_VERDICT:
414 if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0) {
415 perror(
"mnl_attr_validate");
424 static int nft_verdict_parse_cb(
const struct nlattr *attr,
void *data)
426 const struct nlattr **tb = data;
427 int type = mnl_attr_get_type(attr);
429 if (mnl_attr_type_valid(attr, NFTA_VERDICT_MAX) < 0)
433 case NFTA_VERDICT_CODE:
434 if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) {
435 perror(
"mnl_attr_validate");
439 case NFTA_VERDICT_CHAIN:
440 if (mnl_attr_validate(attr, MNL_TYPE_STRING) < 0) {
441 perror(
"mnl_attr_validate");
451 nft_parse_verdict(
union nft_data_reg *data,
const struct nlattr *attr,
int *type)
453 struct nlattr *tb[NFTA_VERDICT_MAX+1];
455 if (mnl_attr_parse_nested(attr, nft_verdict_parse_cb, tb) < 0) {
456 perror(
"mnl_attr_parse_nested");
460 if (!tb[NFTA_VERDICT_CODE])
463 data->verdict = ntohl(mnl_attr_get_u32(tb[NFTA_VERDICT_CODE]));
465 switch(data->verdict) {
473 *type = DATA_VERDICT;
474 data->len =
sizeof(data->verdict);
478 if (!tb[NFTA_VERDICT_CHAIN])
481 data->chain = strdup(mnl_attr_get_str(tb[NFTA_VERDICT_CHAIN]));
493 __nft_parse_data(
union nft_data_reg *data,
const struct nlattr *attr)
495 void *orig = mnl_attr_get_payload(attr);
496 uint32_t data_len = mnl_attr_get_payload_len(attr);
501 if (data_len >
sizeof(uint32_t) * 4)
504 memcpy(data->val, orig, data_len);
505 data->len = data_len;
510 int nft_parse_data(
union nft_data_reg *data,
struct nlattr *attr,
int *type)
512 struct nlattr *tb[NFTA_DATA_MAX+1] = {};
515 if (mnl_attr_parse_nested(attr, nft_data_parse_cb, tb) < 0) {
516 perror(
"mnl_attr_parse_nested");
519 if (tb[NFTA_DATA_VALUE]) {
523 ret = __nft_parse_data(data, tb[NFTA_DATA_VALUE]);
527 if (tb[NFTA_DATA_VERDICT])
528 ret = nft_parse_verdict(data, tb[NFTA_DATA_VERDICT], type);