diff options
Diffstat (limited to 'src/expr/ct.c')
-rw-r--r-- | src/expr/ct.c | 167 |
1 files changed, 109 insertions, 58 deletions
diff --git a/src/expr/ct.c b/src/expr/ct.c index 49d8495..2df761c 100644 --- a/src/expr/ct.c +++ b/src/expr/ct.c @@ -18,8 +18,8 @@ #include "internal.h" #include <libmnl/libmnl.h> -#include <libnftables/expr.h> -#include <libnftables/rule.h> +#include <libnftnl/expr.h> +#include <libnftnl/rule.h> #include "expr_ops.h" struct nft_expr_ct { @@ -141,10 +141,6 @@ nft_rule_expr_ct_parse(struct nft_rule_expr *e, struct nlattr *attr) ct->key = ntohl(mnl_attr_get_u32(tb[NFTA_CT_KEY])); e->flags |= (1 << NFT_EXPR_CT_KEY); } - if (tb[NFTA_CT_DIRECTION]) { - ct->dir = mnl_attr_get_u8(tb[NFTA_CT_DIRECTION]); - e->flags |= (1 << NFT_EXPR_CT_DIR); - } if (tb[NFTA_CT_DREG]) { ct->dreg = ntohl(mnl_attr_get_u32(tb[NFTA_CT_DREG])); e->flags |= (1 << NFT_EXPR_CT_DREG); @@ -153,6 +149,10 @@ nft_rule_expr_ct_parse(struct nft_rule_expr *e, struct nlattr *attr) 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); + } return 0; } @@ -165,6 +165,7 @@ const char *ctkey2str_array[NFT_CT_MAX] = { [NFT_CT_SECMARK] = "secmark", [NFT_CT_EXPIRATION] = "expiration", [NFT_CT_HELPER] = "helper", + [NFT_CT_L3PROTOCOL] = "l3protocol", [NFT_CT_PROTOCOL] = "protocol", [NFT_CT_SRC] = "src", [NFT_CT_DST] = "dst", @@ -192,30 +193,58 @@ static inline int str2ctkey(const char *ctkey) return -1; } -static int nft_rule_expr_ct_json_parse(struct nft_rule_expr *e, json_t *root) +static const char *ctdir2str(uint8_t ctdir) +{ + switch (ctdir) { + case IP_CT_DIR_ORIGINAL: + return "original"; + case IP_CT_DIR_REPLY: + return "reply"; + default: + return "unknow"; + } +} + +static inline int str2ctdir(const char *str, uint8_t *ctdir) +{ + if (strcmp(str, "original") == 0) { + *ctdir = IP_CT_DIR_ORIGINAL; + return 0; + } + + if (strcmp(str, "reply") == 0) { + *ctdir = IP_CT_DIR_REPLY; + return 0; + } + + return -1; +} + +static int nft_rule_expr_ct_json_parse(struct nft_rule_expr *e, json_t *root, + struct nft_parse_err *err) { #ifdef JSON_PARSING - const char *key_str; + const char *key_str, *dir_str; uint32_t reg; uint8_t dir; int key; if (nft_jansson_node_exist(root, "dreg")) { - if (nft_jansson_parse_reg(root, "dreg", NFT_TYPE_U32, ®) < 0) + 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); } if (nft_jansson_node_exist(root, "sreg")) { - if (nft_jansson_parse_reg(root, "sreg", NFT_TYPE_U32, ®) < 0) + 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"); + key_str = nft_jansson_parse_str(root, "key", err); if (key_str == NULL) return -1; @@ -228,11 +257,15 @@ static int nft_rule_expr_ct_json_parse(struct nft_rule_expr *e, json_t *root) } if (nft_jansson_node_exist(root, "dir")) { - if (nft_jansson_parse_val(root, "dir", NFT_TYPE_U8, &dir) < 0) + dir_str = nft_jansson_parse_str(root, "dir", err); + if (dir_str == NULL) return -1; - if (dir != IP_CT_DIR_ORIGINAL && dir != IP_CT_DIR_REPLY) + if (str2ctdir(dir_str, &dir) != 0) { + err->node_name = "dir"; + err->error = NFT_PARSE_EBADTYPE; goto err; + } nft_rule_expr_set_u8(e, NFT_EXPR_CT_DIR, dir); } @@ -248,29 +281,30 @@ err: } -static int nft_rule_expr_ct_xml_parse(struct nft_rule_expr *e, mxml_node_t *tree) +static int nft_rule_expr_ct_xml_parse(struct nft_rule_expr *e, mxml_node_t *tree, + struct nft_parse_err *err) { #ifdef XML_PARSING struct nft_expr_ct *ct = nft_expr_data(e); - const char *key_str; - int32_t reg; + const char *key_str, *dir_str; int key; uint8_t dir; + uint32_t reg; - reg = nft_mxml_reg_parse(tree, "dreg", MXML_DESCEND_FIRST); - if (reg >= 0) { + if (nft_mxml_reg_parse(tree, "dreg", ®, MXML_DESCEND_FIRST, + NFT_XML_OPT, err) >= 0) { ct->dreg = reg; e->flags |= (1 << NFT_EXPR_CT_DREG); } - reg = nft_mxml_reg_parse(tree, "sreg", MXML_DESCEND_FIRST); - if (reg >= 0) { + 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); + NFT_XML_MAND, err); if (key_str == NULL) return -1; @@ -281,15 +315,17 @@ static int nft_rule_expr_ct_xml_parse(struct nft_rule_expr *e, mxml_node_t *tree ct->key = key; e->flags |= (1 << NFT_EXPR_CT_KEY); - if (nft_mxml_num_parse(tree, "dir", MXML_DESCEND_FIRST, BASE_DEC, - &dir, NFT_TYPE_U8, NFT_XML_MAND) != 0) - return -1; - - if (dir != IP_CT_DIR_ORIGINAL && dir != IP_CT_DIR_REPLY) - goto err; + dir_str = nft_mxml_str_parse(tree, "dir", MXML_DESCEND_FIRST, + NFT_XML_OPT, err); + if (dir_str != NULL) { + if (str2ctdir(dir_str, &dir) != 0) { + err->node_name = "dir"; + err->error = NFT_PARSE_EBADTYPE; + goto err; + } - ct->dir = dir; - e->flags |= (1 << NFT_EXPR_CT_DIR); + nft_rule_expr_set_u8(e, NFT_EXPR_CT_DIR, dir); + } return 0; err: @@ -302,21 +338,41 @@ err: } static int -nft_rule_expr_ct_snprintf_default(char *buf, size_t size, - struct nft_rule_expr *e) +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); - if (e->flags & (1 << NFT_EXPR_CT_SREG)) - return snprintf(buf, size, "set %s with reg %u ", - ctkey2str(ct->key), ct->sreg); + 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\",", + 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\",", + ctdir2str(ct->dir)); + SNPRINTF_BUFFER_SIZE(ret, size, len, offset); + } + + /* Remove the last separator characther */ + buf[offset-1] = '\0'; - return snprintf(buf, size, "load %s => reg %u dir %u ", - ctkey2str(ct->key), ct->dreg, ct->dir); + return offset-1; } static int -nft_rule_expr_ct_snprintf_xml(char *buf, size_t size, struct nft_rule_expr *e) +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); @@ -337,8 +393,9 @@ nft_rule_expr_ct_snprintf_xml(char *buf, size_t size, struct nft_rule_expr *e) SNPRINTF_BUFFER_SIZE(ret, size, len, offset); } - if (e->flags & (1 << NFT_EXPR_CT_DIR)) { - ret = snprintf(buf+offset, len, "<dir>%u</dir>", ct->dir); + if (nft_rule_expr_is_set(e, NFT_EXPR_CT_DIR)) { + ret = snprintf(buf+offset, len, "<dir>%s</dir>", + ctdir2str(ct->dir)); SNPRINTF_BUFFER_SIZE(ret, size, len, offset); } @@ -346,36 +403,30 @@ nft_rule_expr_ct_snprintf_xml(char *buf, size_t size, struct nft_rule_expr *e) } static int -nft_rule_expr_ct_snprintf_json(char *buf, size_t size, struct nft_rule_expr *e) +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); - 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); + 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_KEY)) { - ret = snprintf(buf+offset, len, "\"key\":\"%s\",", - ctkey2str(ct->key)); + 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 (e->flags & (1 << NFT_EXPR_CT_DIR)) { - ret = snprintf(buf+offset, len, "\"dir\":%u,", ct->dir); + if (nft_rule_expr_is_set(e, NFT_EXPR_CT_DIR)) { + ret = snprintf(buf+offset, len, ", dir %s ", + ctdir2str(ct->dir)); SNPRINTF_BUFFER_SIZE(ret, size, len, offset); } - /* Remove the last separator characther */ - buf[offset-1] = '\0'; - - return offset-1; + return offset; } static int @@ -384,11 +435,11 @@ nft_rule_expr_ct_snprintf(char *buf, size_t len, uint32_t type, { switch(type) { case NFT_OUTPUT_DEFAULT: - return nft_rule_expr_ct_snprintf_default(buf, len, e); + return nft_expr_ct_snprintf_default(buf, len, e); case NFT_OUTPUT_XML: - return nft_rule_expr_ct_snprintf_xml(buf, len, e); + return nft_expr_ct_snprintf_xml(buf, len, e); case NFT_OUTPUT_JSON: - return nft_rule_expr_ct_snprintf_json(buf, len, e); + return nft_expr_ct_snprintf_json(buf, len, e); default: break; } |