diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/chain.c | 1 | ||||
-rw-r--r-- | src/expr/ct.c | 95 | ||||
-rw-r--r-- | src/expr/meta.c | 147 | ||||
-rw-r--r-- | src/expr/queue.c | 254 | ||||
-rw-r--r-- | src/table.c | 35 | ||||
-rw-r--r-- | src/utils.c | 4 |
6 files changed, 487 insertions, 49 deletions
diff --git a/src/chain.c b/src/chain.c index e26200d..2cc7c61 100644 --- a/src/chain.c +++ b/src/chain.c @@ -50,6 +50,7 @@ static const char *nft_hooknum2str(int family, int hooknum) switch (family) { case NFPROTO_IPV4: case NFPROTO_IPV6: + case NFPROTO_INET: case NFPROTO_BRIDGE: switch (hooknum) { case NF_INET_PRE_ROUTING: diff --git a/src/expr/ct.c b/src/expr/ct.c index 051a1c5..2df761c 100644 --- a/src/expr/ct.c +++ b/src/expr/ct.c @@ -25,6 +25,7 @@ struct nft_expr_ct { enum nft_ct_keys key; enum nft_registers dreg; + enum nft_registers sreg; uint8_t dir; }; @@ -51,6 +52,9 @@ nft_rule_expr_ct_set(struct nft_rule_expr *e, uint16_t type, case NFT_EXPR_CT_DREG: ct->dreg = *((uint32_t *)data); break; + case NFT_EXPR_CT_SREG: + ct->sreg = *((uint32_t *)data); + break; default: return -1; } @@ -73,6 +77,9 @@ nft_rule_expr_ct_get(const struct nft_rule_expr *e, uint16_t type, case NFT_EXPR_CT_DREG: *data_len = sizeof(ct->dreg); return &ct->dreg; + case NFT_EXPR_CT_SREG: + *data_len = sizeof(ct->sreg); + return &ct->sreg; } return NULL; } @@ -88,6 +95,7 @@ static int nft_rule_expr_ct_cb(const struct nlattr *attr, void *data) switch(type) { case NFTA_CT_KEY: case NFTA_CT_DREG: + case NFTA_CT_SREG: if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) { perror("mnl_attr_validate"); return MNL_CB_ERROR; @@ -116,6 +124,8 @@ nft_rule_expr_ct_build(struct nlmsghdr *nlh, struct nft_rule_expr *e) mnl_attr_put_u32(nlh, NFTA_CT_DREG, htonl(ct->dreg)); if (e->flags & (1 << NFT_EXPR_CT_DIR)) mnl_attr_put_u8(nlh, NFTA_CT_DIRECTION, ct->dir); + if (e->flags & (1 << NFT_EXPR_CT_SREG)) + mnl_attr_put_u32(nlh, NFTA_CT_SREG, htonl(ct->sreg)); } static int @@ -135,6 +145,10 @@ nft_rule_expr_ct_parse(struct nft_rule_expr *e, struct nlattr *attr) ct->dreg = ntohl(mnl_attr_get_u32(tb[NFTA_CT_DREG])); e->flags |= (1 << NFT_EXPR_CT_DREG); } + if (tb[NFTA_CT_SREG]) { + ct->sreg = ntohl(mnl_attr_get_u32(tb[NFTA_CT_SREG])); + e->flags |= (1 << NFT_EXPR_CT_SREG); + } if (tb[NFTA_CT_DIRECTION]) { ct->dir = mnl_attr_get_u8(tb[NFTA_CT_DIRECTION]); e->flags |= (1 << NFT_EXPR_CT_DIR); @@ -215,10 +229,19 @@ static int nft_rule_expr_ct_json_parse(struct nft_rule_expr *e, json_t *root, uint8_t dir; int key; - if (nft_jansson_parse_reg(root, "dreg", NFT_TYPE_U32, ®, err) < 0) - return -1; + if (nft_jansson_node_exist(root, "dreg")) { + if (nft_jansson_parse_reg(root, "dreg", NFT_TYPE_U32, ®, err) < 0) + return -1; - nft_rule_expr_set_u32(e, NFT_EXPR_CT_DREG, reg); + nft_rule_expr_set_u32(e, NFT_EXPR_CT_DREG, reg); + } + + if (nft_jansson_node_exist(root, "sreg")) { + if (nft_jansson_parse_reg(root, "sreg", NFT_TYPE_U32, ®, err) < 0) + return -1; + + nft_rule_expr_set_u32(e, NFT_EXPR_CT_SREG, reg); + } if (nft_jansson_node_exist(root, "key")) { key_str = nft_jansson_parse_str(root, "key", err); @@ -269,11 +292,16 @@ static int nft_rule_expr_ct_xml_parse(struct nft_rule_expr *e, mxml_node_t *tree uint32_t reg; if (nft_mxml_reg_parse(tree, "dreg", ®, MXML_DESCEND_FIRST, - NFT_XML_MAND, err) != 0) - return -1; + NFT_XML_OPT, err) >= 0) { + ct->dreg = reg; + e->flags |= (1 << NFT_EXPR_CT_DREG); + } - ct->dreg = reg; - e->flags |= (1 << NFT_EXPR_CT_DREG); + if (nft_mxml_reg_parse(tree, "sreg", ®, MXML_DESCEND_FIRST, + NFT_XML_OPT, err) >= 0) { + ct->sreg = reg; + e->flags |= (1 << NFT_EXPR_CT_SREG); + } key_str = nft_mxml_str_parse(tree, "key", MXML_DESCEND_FIRST, NFT_XML_MAND, err); @@ -315,22 +343,32 @@ nft_expr_ct_snprintf_json(char *buf, size_t size, struct nft_rule_expr *e) int ret, len = size, offset = 0; struct nft_expr_ct *ct = nft_expr_data(e); - ret = snprintf(buf, len, "\"dreg\":%u", ct->dreg); - SNPRINTF_BUFFER_SIZE(ret, size, len, offset); + if (e->flags & (1 << NFT_EXPR_CT_DREG)) { + ret = snprintf(buf+offset, len, "\"dreg\":%u,", ct->dreg); + SNPRINTF_BUFFER_SIZE(ret, size, len, offset); + } + + if (e->flags & (1 << NFT_EXPR_CT_SREG)) { + ret = snprintf(buf+offset, len, "\"sreg:\":%u,", ct->sreg); + SNPRINTF_BUFFER_SIZE(ret, size, len, offset); + } if (e->flags & (1 << NFT_EXPR_CT_KEY)) { - ret = snprintf(buf+offset, len, ",\"key\":\"%s\"", + ret = snprintf(buf+offset, len, "\"key\":\"%s\",", ctkey2str(ct->key)); SNPRINTF_BUFFER_SIZE(ret, size, len, offset); } if (nft_rule_expr_is_set(e, NFT_EXPR_CT_DIR)) { - ret = snprintf(buf+offset, len, ",\"dir\":\"%s\"", + ret = snprintf(buf+offset, len, "\"dir\":\"%s\",", ctdir2str(ct->dir)); SNPRINTF_BUFFER_SIZE(ret, size, len, offset); } - return offset; + /* Remove the last separator characther */ + buf[offset-1] = '\0'; + + return offset-1; } static int @@ -339,12 +377,21 @@ nft_expr_ct_snprintf_xml(char *buf, size_t size, struct nft_rule_expr *e) int ret, len = size, offset = 0; struct nft_expr_ct *ct = nft_expr_data(e); - ret = snprintf(buf, len, "<dreg>%u</dreg>", ct->dreg); - SNPRINTF_BUFFER_SIZE(ret, size, len, offset); + if (e->flags & (1 << NFT_EXPR_CT_DREG)) { + ret = snprintf(buf+offset, len, "<dreg>%u</dreg>", ct->dreg); + SNPRINTF_BUFFER_SIZE(ret, size, len, offset); + } + + if (e->flags & (1 << NFT_EXPR_CT_SREG)) { + ret = snprintf(buf+offset, len, "<sreg>%u</sreg>", ct->sreg); + SNPRINTF_BUFFER_SIZE(ret, size, len, offset); + } - ret = snprintf(buf+offset, len, "<key>%s</key>", - ctkey2str(ct->key)); - SNPRINTF_BUFFER_SIZE(ret, size, len, offset); + if (e->flags & (1 << NFT_EXPR_CT_KEY)) { + ret = snprintf(buf+offset, len, "<key>%s</key>", + ctkey2str(ct->key)); + SNPRINTF_BUFFER_SIZE(ret, size, len, offset); + } if (nft_rule_expr_is_set(e, NFT_EXPR_CT_DIR)) { ret = snprintf(buf+offset, len, "<dir>%s</dir>", @@ -361,9 +408,17 @@ nft_expr_ct_snprintf_default(char *buf, size_t size, struct nft_rule_expr *e) int ret, len = size, offset = 0; struct nft_expr_ct *ct = nft_expr_data(e); - ret = snprintf(buf, len, "load %s => reg %u ", - ctkey2str(ct->key), ct->dreg); - SNPRINTF_BUFFER_SIZE(ret, size, len, offset); + if (e->flags & (1 << NFT_EXPR_CT_SREG)) { + ret = snprintf(buf, size, "set %s with reg %u ", + ctkey2str(ct->key), ct->sreg); + SNPRINTF_BUFFER_SIZE(ret, size, len, offset); + } + + if (e->flags & (1 << NFT_EXPR_CT_DREG)) { + ret = snprintf(buf, len, "load %s => reg %u ", + ctkey2str(ct->key), ct->dreg); + SNPRINTF_BUFFER_SIZE(ret, size, len, offset); + } if (nft_rule_expr_is_set(e, NFT_EXPR_CT_DIR)) { ret = snprintf(buf+offset, len, ", dir %s ", diff --git a/src/expr/meta.c b/src/expr/meta.c index e2a198a..bee2f4c 100644 --- a/src/expr/meta.c +++ b/src/expr/meta.c @@ -23,12 +23,13 @@ #include "expr_ops.h" #ifndef NFT_META_MAX -#define NFT_META_MAX (NFT_META_SECMARK + 1) +#define NFT_META_MAX (NFT_META_L4PROTO + 1) #endif struct nft_expr_meta { enum nft_meta_keys key; enum nft_registers dreg; + enum nft_registers sreg; }; static int @@ -44,6 +45,9 @@ nft_rule_expr_meta_set(struct nft_rule_expr *e, uint16_t type, case NFT_EXPR_META_DREG: meta->dreg = *((uint32_t *)data); break; + case NFT_EXPR_META_SREG: + meta->sreg = *((uint32_t *)data); + break; default: return -1; } @@ -63,6 +67,9 @@ nft_rule_expr_meta_get(const struct nft_rule_expr *e, uint16_t type, case NFT_EXPR_META_DREG: *data_len = sizeof(meta->dreg); return &meta->dreg; + case NFT_EXPR_META_SREG: + *data_len = sizeof(meta->sreg); + return &meta->sreg; } return NULL; } @@ -78,6 +85,7 @@ static int nft_rule_expr_meta_cb(const struct nlattr *attr, void *data) switch(type) { case NFTA_META_KEY: case NFTA_META_DREG: + case NFTA_META_SREG: if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) { perror("mnl_attr_validate"); return MNL_CB_ERROR; @@ -98,6 +106,8 @@ nft_rule_expr_meta_build(struct nlmsghdr *nlh, struct nft_rule_expr *e) mnl_attr_put_u32(nlh, NFTA_META_KEY, htonl(meta->key)); if (e->flags & (1 << NFT_EXPR_META_DREG)) mnl_attr_put_u32(nlh, NFTA_META_DREG, htonl(meta->dreg)); + if (e->flags & (1 << NFT_EXPR_META_SREG)) + mnl_attr_put_u32(nlh, NFTA_META_SREG, htonl(meta->sreg)); } static int @@ -117,6 +127,10 @@ nft_rule_expr_meta_parse(struct nft_rule_expr *e, struct nlattr *attr) meta->dreg = ntohl(mnl_attr_get_u32(tb[NFTA_META_DREG])); e->flags |= (1 << NFT_EXPR_META_DREG); } + if (tb[NFTA_META_SREG]) { + meta->sreg = ntohl(mnl_attr_get_u32(tb[NFTA_META_SREG])); + e->flags |= (1 << NFT_EXPR_META_SREG); + } return 0; } @@ -124,6 +138,8 @@ nft_rule_expr_meta_parse(struct nft_rule_expr *e, struct nlattr *attr) static const char *meta_key2str_array[NFT_META_MAX] = { [NFT_META_LEN] = "len", [NFT_META_PROTOCOL] = "protocol", + [NFT_META_NFPROTO] = "nfproto", + [NFT_META_L4PROTO] = "l4proto", [NFT_META_PRIORITY] = "priority", [NFT_META_MARK] = "mark", [NFT_META_IIF] = "iif", @@ -168,11 +184,6 @@ static int nft_rule_expr_meta_json_parse(struct nft_rule_expr *e, json_t *root, uint32_t reg; int key; - if (nft_jansson_parse_reg(root, "dreg", NFT_TYPE_U32, ®, err) < 0) - return -1; - - nft_rule_expr_set_u32(e, NFT_EXPR_META_DREG, reg); - key_str = nft_jansson_parse_str(root, "key", err); if (key_str == NULL) return -1; @@ -183,6 +194,22 @@ static int nft_rule_expr_meta_json_parse(struct nft_rule_expr *e, json_t *root, nft_rule_expr_set_u32(e, NFT_EXPR_META_KEY, key); + if (nft_jansson_node_exist(root, "dreg")) { + if (nft_jansson_parse_reg(root, "dreg", NFT_TYPE_U32, ®, + err) < 0) + return -1; + + nft_rule_expr_set_u32(e, NFT_EXPR_META_DREG, reg); + } + + if (nft_jansson_node_exist(root, "sreg")) { + if (nft_jansson_parse_reg(root, "sreg", NFT_TYPE_U32, ®, + err) < 0) + return -1; + + nft_rule_expr_set_u32(e, NFT_EXPR_META_SREG, reg); + } + return 0; #else errno = EOPNOTSUPP; @@ -200,13 +227,6 @@ static int nft_rule_expr_meta_xml_parse(struct nft_rule_expr *e, mxml_node_t *tr int key; uint32_t reg; - if (nft_mxml_reg_parse(tree, "dreg", ®, MXML_DESCEND_FIRST, - NFT_XML_MAND, err) < 0) - return -1; - - meta->dreg = reg; - e->flags |= (1 << NFT_EXPR_META_DREG); - key_str = nft_mxml_str_parse(tree, "key", MXML_DESCEND_FIRST, NFT_XML_MAND, err); if (key_str == NULL) @@ -219,6 +239,18 @@ static int nft_rule_expr_meta_xml_parse(struct nft_rule_expr *e, mxml_node_t *tr meta->key = key; e->flags |= (1 << NFT_EXPR_META_KEY); + if (nft_mxml_reg_parse(tree, "dreg", ®, MXML_DESCEND_FIRST, + NFT_XML_OPT, err) >= 0) { + meta->dreg = reg; + e->flags |= (1 << NFT_EXPR_META_DREG); + } + + if (nft_mxml_reg_parse(tree, "sreg", ®, MXML_DESCEND_FIRST, + NFT_XML_OPT, err) >= 0) { + meta->sreg = reg; + e->flags |= (1 << NFT_EXPR_META_SREG); + } + return 0; #else errno = EOPNOTSUPP; @@ -227,23 +259,92 @@ static int nft_rule_expr_meta_xml_parse(struct nft_rule_expr *e, mxml_node_t *tr } static int -nft_rule_expr_meta_snprintf(char *buf, size_t len, uint32_t type, - uint32_t flags, struct nft_rule_expr *e) +nft_rule_expr_meta_snprintf_default(char *buf, size_t len, + struct nft_rule_expr *e) { struct nft_expr_meta *meta = nft_expr_data(e); - switch(type) { - case NFT_OUTPUT_DEFAULT: + if (e->flags & (1 << NFT_EXPR_META_SREG)) { + return snprintf(buf, len, "set %s with reg %u ", + meta_key2str(meta->key), meta->sreg); + } + if (e->flags & (1 << NFT_EXPR_META_DREG)) { return snprintf(buf, len, "load %s => reg %u ", meta_key2str(meta->key), meta->dreg); + } + return 0; +} + +static int +nft_rule_expr_meta_snprintf_xml(char *buf, size_t size, + struct nft_rule_expr *e) +{ + int ret, len = size, offset = 0; + struct nft_expr_meta *meta = nft_expr_data(e); + + if (e->flags & (1 << NFT_EXPR_META_DREG)) { + ret = snprintf(buf+offset, len, "<dreg>%u</dreg>", + meta->dreg); + SNPRINTF_BUFFER_SIZE(ret, size, len, offset); + } + + if (e->flags & (1 << NFT_EXPR_META_KEY)) { + ret = snprintf(buf+offset, len, "<key>%s</key>", + meta_key2str(meta->key)); + SNPRINTF_BUFFER_SIZE(ret, size, len, offset); + } + + if (e->flags & (1 << NFT_EXPR_META_SREG)) { + ret = snprintf(buf+offset, len, "<sreg>%u</sreg>", + meta->sreg); + SNPRINTF_BUFFER_SIZE(ret, size, len, offset); + } + + return offset; +} + +static int +nft_rule_expr_meta_snprintf_json(char *buf, size_t size, + struct nft_rule_expr *e) +{ + int ret, len = size, offset = 0; + struct nft_expr_meta *meta = nft_expr_data(e); + + if (e->flags & (1 << NFT_EXPR_META_DREG)) { + ret = snprintf(buf+offset, len, "\"dreg\":%u,", + meta->dreg); + SNPRINTF_BUFFER_SIZE(ret, size, len, offset); + } + + if (e->flags & (1 << NFT_EXPR_META_KEY)) { + ret = snprintf(buf+offset, len, "\"key\":\"%s\",", + meta_key2str(meta->key)); + SNPRINTF_BUFFER_SIZE(ret, size, len, offset); + } + + if (e->flags & (1 << NFT_EXPR_META_SREG)) { + ret = snprintf(buf+offset, len, "\"sreg\":%u,", + meta->sreg); + SNPRINTF_BUFFER_SIZE(ret, size, len, offset); + } + + /* Remove the last separator characther */ + buf[offset-1] = '\0'; + + return offset-1; +} + +static int +nft_rule_expr_meta_snprintf(char *buf, size_t len, uint32_t type, + uint32_t flags, struct nft_rule_expr *e) +{ + switch(type) { + case NFT_OUTPUT_DEFAULT: + return nft_rule_expr_meta_snprintf_default(buf, len, e); case NFT_OUTPUT_XML: - return snprintf(buf, len, "<dreg>%u</dreg>" - "<key>%s</key>", - meta->dreg, meta_key2str(meta->key)); + return nft_rule_expr_meta_snprintf_xml(buf, len, e); case NFT_OUTPUT_JSON: - return snprintf(buf, len, "\"dreg\":%u," - "\"key\":\"%s\"", - meta->dreg, meta_key2str(meta->key)); + return nft_rule_expr_meta_snprintf_json(buf, len, e); default: break; } diff --git a/src/expr/queue.c b/src/expr/queue.c new file mode 100644 index 0000000..c3d0e19 --- /dev/null +++ b/src/expr/queue.c @@ -0,0 +1,254 @@ +/* + * (C) 2013 by Eric Leblond <eric@regit.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + */ + +#include <stdio.h> +#include <stdint.h> +#include <string.h> +#include <arpa/inet.h> +#include <errno.h> +#include <linux/netfilter/nf_tables.h> + +#include "internal.h" +#include <libmnl/libmnl.h> +#include <libnftnl/expr.h> +#include <libnftnl/rule.h> +#include "expr_ops.h" + +struct nft_expr_queue { + uint16_t queuenum; + uint16_t queues_total; + uint16_t flags; +}; + +static int nft_rule_expr_queue_set(struct nft_rule_expr *e, uint16_t type, + const void *data, uint32_t data_len) +{ + struct nft_expr_queue *queue = nft_expr_data(e); + + switch(type) { + case NFT_EXPR_QUEUE_NUM: + queue->queuenum = *((uint16_t *)data); + break; + case NFT_EXPR_QUEUE_TOTAL: + queue->queues_total = *((uint16_t *)data); + break; + case NFT_EXPR_QUEUE_FLAGS: + queue->flags = *((uint16_t *)data); + break; + default: + return -1; + } + return 0; +} + +static const void * +nft_rule_expr_queue_get(const struct nft_rule_expr *e, uint16_t type, + uint32_t *data_len) +{ + struct nft_expr_queue *queue = nft_expr_data(e); + + switch(type) { + case NFT_EXPR_QUEUE_NUM: + *data_len = sizeof(queue->queuenum); + return &queue->queuenum; + case NFT_EXPR_QUEUE_TOTAL: + *data_len = sizeof(queue->queues_total); + return &queue->queues_total; + case NFT_EXPR_QUEUE_FLAGS: + *data_len = sizeof(queue->flags); + return &queue->flags; + } + return NULL; +} + +static int nft_rule_expr_queue_cb(const struct nlattr *attr, void *data) +{ + const struct nlattr **tb = data; + int type = mnl_attr_get_type(attr); + + if (mnl_attr_type_valid(attr, NFTA_QUEUE_MAX) < 0) + return MNL_CB_OK; + + switch(type) { + case NFTA_QUEUE_NUM: + case NFTA_QUEUE_TOTAL: + case NFTA_QUEUE_FLAGS: + if (mnl_attr_validate(attr, MNL_TYPE_U16) < 0) { + perror("mnl_attr_validate"); + return MNL_CB_ERROR; + } + break; + } + + tb[type] = attr; + return MNL_CB_OK; +} + +static void +nft_rule_expr_queue_build(struct nlmsghdr *nlh, struct nft_rule_expr *e) +{ + struct nft_expr_queue *queue = nft_expr_data(e); + + if (e->flags & (1 << NFT_EXPR_QUEUE_NUM)) + mnl_attr_put_u16(nlh, NFTA_QUEUE_NUM, htons(queue->queuenum)); + if (e->flags & (1 << NFT_EXPR_QUEUE_TOTAL)) + mnl_attr_put_u16(nlh, NFTA_QUEUE_TOTAL, htons(queue->queues_total)); + if (e->flags & (1 << NFT_EXPR_QUEUE_FLAGS)) + mnl_attr_put_u16(nlh, NFTA_QUEUE_FLAGS, htons(queue->flags)); +} + +static int +nft_rule_expr_queue_parse(struct nft_rule_expr *e, struct nlattr *attr) +{ + struct nft_expr_queue *queue = nft_expr_data(e); + struct nlattr *tb[NFTA_QUEUE_MAX+1] = {}; + + if (mnl_attr_parse_nested(attr, nft_rule_expr_queue_cb, tb) < 0) + return -1; + + if (tb[NFTA_QUEUE_NUM]) { + queue->queuenum = ntohs(mnl_attr_get_u16(tb[NFTA_QUEUE_NUM])); + e->flags |= (1 << NFT_EXPR_QUEUE_NUM); + } + if (tb[NFTA_QUEUE_TOTAL]) { + queue->queues_total = ntohs(mnl_attr_get_u16(tb[NFTA_QUEUE_TOTAL])); + e->flags |= (1 << NFT_EXPR_QUEUE_TOTAL); + } + if (tb[NFTA_QUEUE_FLAGS]) { + queue->flags = ntohs(mnl_attr_get_u16(tb[NFTA_QUEUE_FLAGS])); + e->flags |= (1 << NFT_EXPR_QUEUE_FLAGS); + } + + return 0; +} + +static int +nft_rule_expr_queue_json_parse(struct nft_rule_expr *e, json_t *root) +{ +#ifdef JSON_PARSING + uint32_t type; + uint16_t code; + + if (nft_jansson_parse_val(root, "num", NFT_TYPE_U16, &type) < 0) + return -1; + + nft_rule_expr_set_u32(e, NFT_EXPR_QUEUE_NUM, type); + + if (nft_jansson_parse_val(root, "total", NFT_TYPE_U16, &code) < 0) + return -1; + + nft_rule_expr_set_u16(e, NFT_EXPR_QUEUE_TOTAL, code); + + if (nft_jansson_parse_val(root, "flags", NFT_TYPE_U16, &code) < 0) + return -1; + + nft_rule_expr_set_u16(e, NFT_EXPR_QUEUE_FLAGS, code); + + return 0; +#else + errno = EOPNOTSUPP; + return -1; +#endif +} + +static int +nft_rule_expr_queue_xml_parse(struct nft_rule_expr *e, mxml_node_t *tree) +{ +#ifdef XML_PARSING + struct nft_expr_queue *queue = nft_expr_data(e); + + if (nft_mxml_num_parse(tree, "num", MXML_DESCEND_FIRST, BASE_DEC, + &queue->queuenum, NFT_TYPE_U16, NFT_XML_MAND) != 0) + return -1; + + e->flags |= (1 << NFT_EXPR_QUEUE_NUM); + + if (nft_mxml_num_parse(tree, "total", MXML_DESCEND_FIRST, BASE_DEC, + &queue->queues_total, NFT_TYPE_U8, NFT_XML_MAND) != 0) + return -1; + + e->flags |= (1 << NFT_EXPR_QUEUE_TOTAL); + + if (nft_mxml_num_parse(tree, "flags", MXML_DESCEND_FIRST, BASE_DEC, + &queue->flags, NFT_TYPE_U8, NFT_XML_MAND) != 0) + return -1; + + e->flags |= (1 << NFT_EXPR_QUEUE_FLAGS); + + return 0; +#else + errno = EOPNOTSUPP; + return -1; +#endif +} + +static int +nft_rule_expr_queue_snprintf(char *buf, size_t len, uint32_t type, + uint32_t flags, struct nft_rule_expr *e) +{ + struct nft_expr_queue *queue = nft_expr_data(e); + int ret; + int one = 0; + + switch(type) { + case NFT_OUTPUT_DEFAULT: + ret = snprintf(buf, len, "num %u total %u", + queue->queuenum, queue->queues_total); + if (queue->flags) { + ret += snprintf(buf + ret , len - ret, " options "); + if (queue->flags & NFT_QUEUE_FLAG_BYPASS) { + ret += snprintf(buf + ret , + len - ret, "bypass"); + one = 1; + } + if (queue->flags & NFT_QUEUE_FLAG_CPU_FANOUT) { + if (one) + ret += snprintf(buf + ret , + len - ret, ","); + ret += snprintf(buf + ret , + len - ret, "fanout"); + } + } + return ret; + case NFT_OUTPUT_XML: + return snprintf(buf, len, "<num>%u</num>" + "<total>%u</total>" + "<flags>%u</flags>", + queue->queuenum, queue->queues_total, + queue->flags); + case NFT_OUTPUT_JSON: + return snprintf(buf, len, "\"num\":%u," + "\"total\":%u," + "\"flags\":%u,", + queue->queuenum, queue->queues_total, + queue->flags); + default: + break; + } + return -1; +} + +struct expr_ops expr_ops_queue = { + .name = "queue", + .alloc_len = sizeof(struct nft_expr_queue), + .max_attr = NFTA_QUEUE_MAX, + .set = nft_rule_expr_queue_set, + .get = nft_rule_expr_queue_get, + .parse = nft_rule_expr_queue_parse, + .build = nft_rule_expr_queue_build, + .snprintf = nft_rule_expr_queue_snprintf, + .xml_parse = nft_rule_expr_queue_xml_parse, + .json_parse = nft_rule_expr_queue_json_parse, +}; + +static void __init expr_queue_init(void) +{ + nft_expr_ops_register(&expr_ops_queue); +} diff --git a/src/table.c b/src/table.c index f50a968..c834a4e 100644 --- a/src/table.c +++ b/src/table.c @@ -31,6 +31,7 @@ struct nft_table { const char *name; uint8_t family; uint32_t table_flags; + uint32_t use; uint32_t flags; }; @@ -70,6 +71,9 @@ void nft_table_attr_unset(struct nft_table *t, uint16_t attr) case NFT_TABLE_ATTR_FLAGS: case NFT_TABLE_ATTR_FAMILY: break; + case NFT_TABLE_ATTR_USE: + /* Cannot be unset, ignoring it */ + return; } t->flags &= ~(1 << attr); } @@ -93,6 +97,9 @@ void nft_table_attr_set(struct nft_table *t, uint16_t attr, const void *data) t->family = *((uint8_t *)data); t->flags |= (1 << NFT_TABLE_ATTR_FAMILY); break; + case NFT_TABLE_ATTR_USE: + /* Cannot be unset, ignoring it */ + break; } } EXPORT_SYMBOL(nft_table_attr_set); @@ -127,6 +134,8 @@ const void *nft_table_attr_get(struct nft_table *t, uint16_t attr) return &t->table_flags; case NFT_TABLE_ATTR_FAMILY: return &t->family; + case NFT_TABLE_ATTR_USE: + return &t->use; } return NULL; } @@ -182,6 +191,12 @@ static int nft_table_parse_attr_cb(const struct nlattr *attr, void *data) return MNL_CB_ERROR; } break; + case NFTA_TABLE_USE: + if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) { + perror("mnl_attr_validate"); + return MNL_CB_ERROR; + } + break; } tb[type] = attr; @@ -202,6 +217,10 @@ int nft_table_nlmsg_parse(const struct nlmsghdr *nlh, struct nft_table *t) t->table_flags = ntohl(mnl_attr_get_u32(tb[NFTA_TABLE_FLAGS])); t->flags |= (1 << NFT_TABLE_ATTR_FLAGS); } + if (tb[NFTA_TABLE_USE]) { + t->use = ntohl(mnl_attr_get_u32(tb[NFTA_TABLE_USE])); + t->flags |= (1 << NFT_TABLE_ATTR_USE); + } t->family = nfg->nfgen_family; t->flags |= (1 << NFT_TABLE_ATTR_FAMILY); @@ -368,23 +387,27 @@ static int nft_table_snprintf_json(char *buf, size_t size, struct nft_table *t) "{\"table\":{" "\"name\":\"%s\"," "\"family\":\"%s\"," - "\"flags\":%d" + "\"flags\":%d," + "\"use\":%d" "}" "}" , - t->name, nft_family2str(t->family), t->table_flags); + t->name, nft_family2str(t->family), + t->table_flags, t->use); } static int nft_table_snprintf_xml(char *buf, size_t size, struct nft_table *t) { return snprintf(buf, size, "<table><name>%s</name><family>%s</family>" - "<flags>%d</flags></table>", - t->name, nft_family2str(t->family), t->table_flags); + "<flags>%d</flags><use>%d</use></table>", + t->name, nft_family2str(t->family), + t->table_flags, t->use); } static int nft_table_snprintf_default(char *buf, size_t size, struct nft_table *t) { - return snprintf(buf, size, "table %s %s flags %x", - t->name, nft_family2str(t->family), t->table_flags); + return snprintf(buf, size, "table %s %s flags %x use %d", + t->name, nft_family2str(t->family), + t->table_flags, t->use); } int nft_table_snprintf(char *buf, size_t size, struct nft_table *t, diff --git a/src/utils.c b/src/utils.c index dd7fd1d..9691c4c 100644 --- a/src/utils.c +++ b/src/utils.c @@ -27,6 +27,8 @@ const char *nft_family2str(uint32_t family) return "ip"; case AF_INET6: return "ip6"; + case 1: + return "inet"; case AF_BRIDGE: return "bridge"; case 3: /* NFPROTO_ARP */ @@ -42,6 +44,8 @@ int nft_str2family(const char *family) return AF_INET; else if (strcmp(family, "ip6") == 0) return AF_INET6; + else if (strcmp(family, "inet") == 0) + return 1; else if (strcmp(family, "bridge") == 0) return AF_BRIDGE; else if (strcmp(family, "arp") == 0) |