+ array = json_object_get(root, "userdata");
+ if (array == NULL) {
+ err->error = NFTNL_PARSE_EMISSINGNODE;
+ err->node_name = "userdata";
+ goto err;
+ }
+
+ attrbuf = nftnl_attrbuf_alloc(NFT_USERDATA_MAXLEN);
+ if (!attrbuf) {
+ perror("nftnl_jansson_parse_rule");
+ exit(EXIT_FAILURE);
+ }
+
+ for (i = 0; i < json_array_size(array); ++i) {
+ if (nftnl_jansson_attr_parse(attrbuf,
+ json_array_get(array, i),
+ err,
+ set_list) < 0)
+ goto err;
+ }
+
+ nftnl_rule_set_data(r, NFTNL_RULE_USERDATA,
+ nftnl_attrbuf_get_data(attrbuf),
+ nftnl_attrbuf_get_len(attrbuf));
+
return 0;
err:
return -1;
@@ -592,7 +629,7 @@ int nftnl_mxml_rule_parse(mxml_node_t *tree, struct nftnl_rule *r,
struct nftnl_parse_err *err,
struct nftnl_set_list *set_list)
{
- mxml_node_t *node;
+ mxml_node_t *node, *node_ud;
struct nftnl_expr *e;
const char *table, *chain;
int family;
@@ -649,6 +686,35 @@ int nftnl_mxml_rule_parse(mxml_node_t *tree, struct nftnl_rule *r,
nftnl_rule_add_expr(r, e);
}
+ node_ud = mxmlFindElement(tree, tree, "userdata", NULL, NULL,
+ MXML_DESCEND);
+ if (node_ud) {
+ struct nftnl_attrbuf *attrbuf;
+
+ attrbuf = nftnl_attrbuf_alloc(NFT_USERDATA_MAXLEN);
+ if (!attrbuf) {
+ perror("nftnl_mxml_rule_parse");
+ exit(EXIT_FAILURE);
+ }
+
+ /* Iterate over attributes */
+ for (
+ node = mxmlFindElement(node_ud, node_ud, "attr", NULL,
+ NULL, MXML_DESCEND);
+ node != NULL;
+ node = mxmlFindElement(node, node_ud, "attr", NULL,
+ NULL, MXML_DESCEND)
+ ) {
+ if (nftnl_mxml_attr_parse(attrbuf, node,
+ MXML_DESCEND_FIRST, r->flags, err) < 0)
+ return -1;
+ }
+
+ nftnl_rule_set_data(r, NFTNL_RULE_USERDATA,
+ nftnl_attrbuf_get_data(attrbuf),
+ nftnl_attrbuf_get_len(attrbuf));
+ }
+
return 0;
}
#endif
@@ -711,6 +777,21 @@ int nftnl_rule_parse_file(struct nftnl_rule *r, enum nftnl_parse_type type,
}
EXPORT_SYMBOL_ALIAS(nftnl_rule_parse_file, nft_rule_parse_file);
+static size_t nftnl_rule_snprintf_data2str(char *buf, size_t size,
+ const void *data, size_t datalen)
+{
+ int i;
+ size_t ret, len = size, offset = 0;
+ const unsigned char *str = data;
+
+ for (i = 0; i < datalen; i++) {
+ ret = snprintf(buf+offset, len, "%02X", str[i]);
+ SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
+ }
+
+ return offset;
+}
+
static int nftnl_rule_snprintf_json(char *buf, size_t size, struct nftnl_rule *r,
uint32_t type, uint32_t flags)
{
@@ -757,6 +838,31 @@ static int nftnl_rule_snprintf_json(char *buf, size_t size, struct nftnl_rule *r
SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
}
+ if (r->flags & (1 << NFTNL_RULE_USERDATA)) {
+ const struct nftnl_attr *attr;
+
+ ret = snprintf(buf+offset, len, "\"userdata\":[");
+ SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
+
+ nftnl_attr_for_each(attr, r->userdata) {
+ ret = nftnl_rule_snprintf_json_attr(buf+offset, len,
+ attr);
+ SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
+
+ ret = snprintf(buf+offset, len, ",");
+ SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
+ }
+ /* delete last comma */
+ buf[offset-1] = '\0';
+ offset--;
+ size--;
+ len++;
+
+ ret = snprintf(buf+offset, len, "],\n");
+ SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
+
+ }
+
ret = snprintf(buf+offset, len, "\"expr\":[");
SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
@@ -849,17 +955,123 @@ static int nftnl_rule_snprintf_xml(char *buf, size_t size, struct nftnl_rule *r,
SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
}
+
+ if (r->flags & (1 << NFTNL_RULE_USERDATA)) {
+ const struct nftnl_attr *attr;
+
+ ret = snprintf(buf+offset, len, "<userdata>");
+ SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
+
+ nftnl_attr_for_each(attr, r->userdata) {
+ ret = snprintf(buf+offset, len, "<attr>");
+ SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
+
+ ret = nftnl_rule_snprintf_xml_attr(buf+offset, len,
+ attr);
+ SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
+
+ ret = snprintf(buf+offset, len, "</attr>");
+ SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
+ }
+
+ ret = snprintf(buf+offset, len, "</userdata>");
+ SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
+ }
+
ret = snprintf(buf+offset, len, "</rule>");
SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
return offset;
}
+static size_t nftnl_rule_snprintf_xml_attr(char *buf, size_t size,
+ const struct nftnl_attr *attr)