diff options
Diffstat (limited to 'src')
57 files changed, 329 insertions, 90 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index c3b0ab9..3cd259c 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -40,6 +40,7 @@ libnftnl_la_SOURCES = utils.c \ expr/lookup.c \ expr/dynset.c \ expr/immediate.c \ + expr/inner.c \ expr/match.c \ expr/meta.c \ expr/numgen.c \ diff --git a/src/common.c b/src/common.c index 2d83c12..ec84fa0 100644 --- a/src/common.c +++ b/src/common.c @@ -10,6 +10,7 @@ #include <stdlib.h> #include <sys/socket.h> #include <time.h> +#include <arpa/inet.h> #include <linux/netlink.h> #include <linux/netfilter/nfnetlink.h> #include <linux/netfilter/nf_tables.h> @@ -37,7 +38,7 @@ static struct nlmsghdr *__nftnl_nlmsg_build_hdr(char *buf, uint16_t type, nfh = mnl_nlmsg_put_extra_header(nlh, sizeof(struct nfgenmsg)); nfh->nfgen_family = family; nfh->version = NFNETLINK_V0; - nfh->res_id = res_id; + nfh->res_id = htons(res_id); return nlh; } @@ -126,9 +127,8 @@ int nftnl_batch_is_supported(void) mnl_nlmsg_batch_next(b); req_seq = seq; - nftnl_set_nlmsg_build_hdr(mnl_nlmsg_batch_current(b), - NFT_MSG_NEWSET, AF_INET, - NLM_F_ACK, seq++); + nftnl_nlmsg_build_hdr(mnl_nlmsg_batch_current(b), NFT_MSG_NEWSET, + AF_INET, NLM_F_ACK, seq++); mnl_nlmsg_batch_next(b); nftnl_batch_end(mnl_nlmsg_batch_current(b), seq++); @@ -279,10 +279,10 @@ int nftnl_expr_snprintf(char *buf, size_t remain, const struct nftnl_expr *expr, if (remain) buf[0] = '\0'; - if (!expr->ops->snprintf || type != NFTNL_OUTPUT_DEFAULT) + if (!expr->ops->output || type != NFTNL_OUTPUT_DEFAULT) return 0; - ret = expr->ops->snprintf(buf + offset, remain, flags, expr); + ret = expr->ops->output(buf + offset, remain, flags, expr); SNPRINTF_BUFFER_SIZE(ret, remain, offset); return offset; diff --git a/src/expr/bitwise.c b/src/expr/bitwise.c index d0c7827..2d27233 100644 --- a/src/expr/bitwise.c +++ b/src/expr/bitwise.c @@ -282,5 +282,5 @@ struct expr_ops expr_ops_bitwise = { .get = nftnl_expr_bitwise_get, .parse = nftnl_expr_bitwise_parse, .build = nftnl_expr_bitwise_build, - .snprintf = nftnl_expr_bitwise_snprintf, + .output = nftnl_expr_bitwise_snprintf, }; diff --git a/src/expr/byteorder.c b/src/expr/byteorder.c index d299745..89ed0a8 100644 --- a/src/expr/byteorder.c +++ b/src/expr/byteorder.c @@ -220,5 +220,5 @@ struct expr_ops expr_ops_byteorder = { .get = nftnl_expr_byteorder_get, .parse = nftnl_expr_byteorder_parse, .build = nftnl_expr_byteorder_build, - .snprintf = nftnl_expr_byteorder_snprintf, + .output = nftnl_expr_byteorder_snprintf, }; diff --git a/src/expr/cmp.c b/src/expr/cmp.c index 6030693..f9d15bb 100644 --- a/src/expr/cmp.c +++ b/src/expr/cmp.c @@ -202,5 +202,5 @@ struct expr_ops expr_ops_cmp = { .get = nftnl_expr_cmp_get, .parse = nftnl_expr_cmp_parse, .build = nftnl_expr_cmp_build, - .snprintf = nftnl_expr_cmp_snprintf, + .output = nftnl_expr_cmp_snprintf, }; diff --git a/src/expr/connlimit.c b/src/expr/connlimit.c index 3b37587..549417b 100644 --- a/src/expr/connlimit.c +++ b/src/expr/connlimit.c @@ -135,5 +135,5 @@ struct expr_ops expr_ops_connlimit = { .get = nftnl_expr_connlimit_get, .parse = nftnl_expr_connlimit_parse, .build = nftnl_expr_connlimit_build, - .snprintf = nftnl_expr_connlimit_snprintf, + .output = nftnl_expr_connlimit_snprintf, }; diff --git a/src/expr/counter.c b/src/expr/counter.c index 1676d70..d139a5f 100644 --- a/src/expr/counter.c +++ b/src/expr/counter.c @@ -133,5 +133,5 @@ struct expr_ops expr_ops_counter = { .get = nftnl_expr_counter_get, .parse = nftnl_expr_counter_parse, .build = nftnl_expr_counter_build, - .snprintf = nftnl_expr_counter_snprintf, + .output = nftnl_expr_counter_snprintf, }; diff --git a/src/expr/ct.c b/src/expr/ct.c index d5dfc81..f4a2aea 100644 --- a/src/expr/ct.c +++ b/src/expr/ct.c @@ -258,5 +258,5 @@ struct expr_ops expr_ops_ct = { .get = nftnl_expr_ct_get, .parse = nftnl_expr_ct_parse, .build = nftnl_expr_ct_build, - .snprintf = nftnl_expr_ct_snprintf, + .output = nftnl_expr_ct_snprintf, }; diff --git a/src/expr/dup.c b/src/expr/dup.c index f041b55..a239ff3 100644 --- a/src/expr/dup.c +++ b/src/expr/dup.c @@ -138,5 +138,5 @@ struct expr_ops expr_ops_dup = { .get = nftnl_expr_dup_get, .parse = nftnl_expr_dup_parse, .build = nftnl_expr_dup_build, - .snprintf = nftnl_expr_dup_snprintf, + .output = nftnl_expr_dup_snprintf, }; diff --git a/src/expr/dynset.c b/src/expr/dynset.c index 85d64bb..5bcf1c6 100644 --- a/src/expr/dynset.c +++ b/src/expr/dynset.c @@ -373,5 +373,5 @@ struct expr_ops expr_ops_dynset = { .get = nftnl_expr_dynset_get, .parse = nftnl_expr_dynset_parse, .build = nftnl_expr_dynset_build, - .snprintf = nftnl_expr_dynset_snprintf, + .output = nftnl_expr_dynset_snprintf, }; diff --git a/src/expr/exthdr.c b/src/expr/exthdr.c index 1b813b1..739c7ff 100644 --- a/src/expr/exthdr.c +++ b/src/expr/exthdr.c @@ -247,10 +247,15 @@ nftnl_expr_exthdr_snprintf(char *buf, size_t len, exthdr->offset, exthdr->flags & NFT_EXTHDR_F_PRESENT ? " present" : "", exthdr->dreg); - else + else if (e->flags & (1 << NFTNL_EXPR_EXTHDR_SREG)) return snprintf(buf, len, "write%s reg %u => %ub @ %u + %u ", op2str(exthdr->op), exthdr->sreg, exthdr->len, exthdr->type, exthdr->offset); + else if (exthdr->op == NFT_EXTHDR_OP_TCPOPT && exthdr->len == 0) + return snprintf(buf, len, "reset tcpopt %u ", exthdr->type); + else + return snprintf(buf, len, "op %u len %u type %u offset %u ", + exthdr->op, exthdr->len, exthdr->type, exthdr->offset); } @@ -262,5 +267,5 @@ struct expr_ops expr_ops_exthdr = { .get = nftnl_expr_exthdr_get, .parse = nftnl_expr_exthdr_parse, .build = nftnl_expr_exthdr_build, - .snprintf = nftnl_expr_exthdr_snprintf, + .output = nftnl_expr_exthdr_snprintf, }; diff --git a/src/expr/fib.c b/src/expr/fib.c index aaff52a..957f929 100644 --- a/src/expr/fib.c +++ b/src/expr/fib.c @@ -198,5 +198,5 @@ struct expr_ops expr_ops_fib = { .get = nftnl_expr_fib_get, .parse = nftnl_expr_fib_parse, .build = nftnl_expr_fib_build, - .snprintf = nftnl_expr_fib_snprintf, + .output = nftnl_expr_fib_snprintf, }; diff --git a/src/expr/flow_offload.c b/src/expr/flow_offload.c index a826202..4fc0563 100644 --- a/src/expr/flow_offload.c +++ b/src/expr/flow_offload.c @@ -120,5 +120,5 @@ struct expr_ops expr_ops_flow = { .get = nftnl_expr_flow_get, .parse = nftnl_expr_flow_parse, .build = nftnl_expr_flow_build, - .snprintf = nftnl_expr_flow_snprintf, + .output = nftnl_expr_flow_snprintf, }; diff --git a/src/expr/fwd.c b/src/expr/fwd.c index 82e5a41..51f6612 100644 --- a/src/expr/fwd.c +++ b/src/expr/fwd.c @@ -158,5 +158,5 @@ struct expr_ops expr_ops_fwd = { .get = nftnl_expr_fwd_get, .parse = nftnl_expr_fwd_parse, .build = nftnl_expr_fwd_build, - .snprintf = nftnl_expr_fwd_snprintf, + .output = nftnl_expr_fwd_snprintf, }; diff --git a/src/expr/hash.c b/src/expr/hash.c index 10b4a72..6e2dd19 100644 --- a/src/expr/hash.c +++ b/src/expr/hash.c @@ -226,5 +226,5 @@ struct expr_ops expr_ops_hash = { .get = nftnl_expr_hash_get, .parse = nftnl_expr_hash_parse, .build = nftnl_expr_hash_build, - .snprintf = nftnl_expr_hash_snprintf, + .output = nftnl_expr_hash_snprintf, }; diff --git a/src/expr/immediate.c b/src/expr/immediate.c index 94b043c..5d477a8 100644 --- a/src/expr/immediate.c +++ b/src/expr/immediate.c @@ -229,5 +229,5 @@ struct expr_ops expr_ops_immediate = { .get = nftnl_expr_immediate_get, .parse = nftnl_expr_immediate_parse, .build = nftnl_expr_immediate_build, - .snprintf = nftnl_expr_immediate_snprintf, + .output = nftnl_expr_immediate_snprintf, }; diff --git a/src/expr/inner.c b/src/expr/inner.c new file mode 100644 index 0000000..7daae4f --- /dev/null +++ b/src/expr/inner.c @@ -0,0 +1,214 @@ +/* + * (C) 2012-2022 by Pablo Neira Ayuso <pablo@netfilter.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 "internal.h" + +#include <stdio.h> +#include <stdint.h> +#include <string.h> +#include <limits.h> +#include <arpa/inet.h> +#include <errno.h> +#include <libmnl/libmnl.h> + +#include <linux/netfilter/nf_tables.h> + +#include <libnftnl/expr.h> +#include <libnftnl/rule.h> + +struct nftnl_expr_inner { + uint32_t type; + uint32_t flags; + uint32_t hdrsize; + struct nftnl_expr *expr; +}; + +static void nftnl_expr_inner_free(const struct nftnl_expr *e) +{ + struct nftnl_expr_inner *inner = nftnl_expr_data(e); + + if (inner->expr) + nftnl_expr_free(inner->expr); +} + +static int +nftnl_expr_inner_set(struct nftnl_expr *e, uint16_t type, + const void *data, uint32_t data_len) +{ + struct nftnl_expr_inner *inner = nftnl_expr_data(e); + + switch(type) { + case NFTNL_EXPR_INNER_TYPE: + memcpy(&inner->type, data, sizeof(inner->type)); + break; + case NFTNL_EXPR_INNER_FLAGS: + memcpy(&inner->flags, data, sizeof(inner->flags)); + break; + case NFTNL_EXPR_INNER_HDRSIZE: + memcpy(&inner->hdrsize, data, sizeof(inner->hdrsize)); + break; + case NFTNL_EXPR_INNER_EXPR: + if (inner->expr) + nftnl_expr_free(inner->expr); + + inner->expr = (void *)data; + break; + default: + return -1; + } + return 0; +} + +static const void * +nftnl_expr_inner_get(const struct nftnl_expr *e, uint16_t type, + uint32_t *data_len) +{ + struct nftnl_expr_inner *inner = nftnl_expr_data(e); + + switch(type) { + case NFTNL_EXPR_INNER_FLAGS: + *data_len = sizeof(inner->flags); + return &inner->flags; + case NFTNL_EXPR_INNER_TYPE: + *data_len = sizeof(inner->type); + return &inner->type; + case NFTNL_EXPR_INNER_HDRSIZE: + *data_len = sizeof(inner->hdrsize); + return &inner->hdrsize; + case NFTNL_EXPR_INNER_EXPR: + return inner->expr; + } + return NULL; +} + +static void +nftnl_expr_inner_build(struct nlmsghdr *nlh, const struct nftnl_expr *e) +{ + struct nftnl_expr_inner *inner = nftnl_expr_data(e); + struct nlattr *nest; + + mnl_attr_put_u32(nlh, NFTA_INNER_NUM, htonl(0)); + if (e->flags & (1 << NFTNL_EXPR_INNER_TYPE)) + mnl_attr_put_u32(nlh, NFTA_INNER_TYPE, htonl(inner->type)); + if (e->flags & (1 << NFTNL_EXPR_INNER_FLAGS)) + mnl_attr_put_u32(nlh, NFTA_INNER_FLAGS, htonl(inner->flags)); + if (e->flags & (1 << NFTNL_EXPR_INNER_HDRSIZE)) + mnl_attr_put_u32(nlh, NFTA_INNER_HDRSIZE, htonl(inner->hdrsize)); + if (e->flags & (1 << NFTNL_EXPR_INNER_EXPR)) { + nest = mnl_attr_nest_start(nlh, NFTA_INNER_EXPR); + nftnl_expr_build_payload(nlh, inner->expr); + mnl_attr_nest_end(nlh, nest); + } +} + +static int nftnl_inner_parse_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_INNER_MAX) < 0) + return MNL_CB_OK; + + switch(type) { + case NFTA_INNER_NUM: + case NFTA_INNER_TYPE: + case NFTA_INNER_HDRSIZE: + case NFTA_INNER_FLAGS: + if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) + abi_breakage(); + break; + case NFTA_INNER_EXPR: + if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0) + abi_breakage(); + break; + } + + tb[type] = attr; + + return MNL_CB_OK; +} + +static int +nftnl_expr_inner_parse(struct nftnl_expr *e, struct nlattr *attr) +{ + struct nftnl_expr_inner *inner = nftnl_expr_data(e); + struct nlattr *tb[NFTA_INNER_MAX + 1] = {}; + struct nftnl_expr *expr; + int err; + + err = mnl_attr_parse_nested(attr, nftnl_inner_parse_cb, tb); + if (err < 0) + return err; + + if (tb[NFTA_INNER_HDRSIZE]) { + inner->hdrsize = + ntohl(mnl_attr_get_u32(tb[NFTA_INNER_HDRSIZE])); + e->flags |= (1 << NFTNL_EXPR_INNER_HDRSIZE); + } + if (tb[NFTA_INNER_FLAGS]) { + inner->flags = + ntohl(mnl_attr_get_u32(tb[NFTA_INNER_FLAGS])); + e->flags |= (1 << NFTNL_EXPR_INNER_FLAGS); + } + if (tb[NFTA_INNER_TYPE]) { + inner->type = + ntohl(mnl_attr_get_u32(tb[NFTA_INNER_TYPE])); + e->flags |= (1 << NFTNL_EXPR_INNER_TYPE); + } + if (tb[NFTA_INNER_EXPR]) { + expr = nftnl_expr_parse(tb[NFTA_INNER_EXPR]); + if (!expr) + return -1; + + if (inner->expr) + nftnl_expr_free(inner->expr); + + inner->expr = expr; + e->flags |= (1 << NFTNL_EXPR_INNER_EXPR); + } + + return 0; +} + +static int +nftnl_expr_inner_snprintf(char *buf, size_t remain, uint32_t flags, + const struct nftnl_expr *e) +{ + struct nftnl_expr_inner *inner = nftnl_expr_data(e); + uint32_t offset = 0; + int ret; + + ret = snprintf(buf, remain, "type %u hdrsize %u flags %x [", + inner->type, inner->hdrsize, inner->flags); + SNPRINTF_BUFFER_SIZE(ret, remain, offset); + + ret = snprintf(buf + offset, remain, " %s ", inner->expr->ops->name); + SNPRINTF_BUFFER_SIZE(ret, remain, offset); + + ret = nftnl_expr_snprintf(buf + offset, remain, inner->expr, + NFTNL_OUTPUT_DEFAULT, 0); + SNPRINTF_BUFFER_SIZE(ret, remain, offset); + + ret = snprintf(buf + offset, remain, "] "); + SNPRINTF_BUFFER_SIZE(ret, remain, offset); + + return offset; +} + +struct expr_ops expr_ops_inner = { + .name = "inner", + .alloc_len = sizeof(struct nftnl_expr_inner), + .max_attr = NFTA_INNER_MAX, + .free = nftnl_expr_inner_free, + .set = nftnl_expr_inner_set, + .get = nftnl_expr_inner_get, + .parse = nftnl_expr_inner_parse, + .build = nftnl_expr_inner_build, + .output = nftnl_expr_inner_snprintf, +}; diff --git a/src/expr/last.c b/src/expr/last.c index 0020fbc..641b713 100644 --- a/src/expr/last.c +++ b/src/expr/last.c @@ -22,6 +22,7 @@ struct nftnl_expr_last { uint64_t msecs; + uint32_t set; }; static int nftnl_expr_last_set(struct nftnl_expr *e, uint16_t type, @@ -33,6 +34,9 @@ static int nftnl_expr_last_set(struct nftnl_expr *e, uint16_t type, case NFTNL_EXPR_LAST_MSECS: memcpy(&last->msecs, data, sizeof(last->msecs)); break; + case NFTNL_EXPR_LAST_SET: + memcpy(&last->set, data, sizeof(last->set)); + break; default: return -1; } @@ -48,6 +52,9 @@ static const void *nftnl_expr_last_get(const struct nftnl_expr *e, case NFTNL_EXPR_LAST_MSECS: *data_len = sizeof(last->msecs); return &last->msecs; + case NFTNL_EXPR_LAST_SET: + *data_len = sizeof(last->set); + return &last->set; } return NULL; } @@ -65,6 +72,10 @@ static int nftnl_expr_last_cb(const struct nlattr *attr, void *data) if (mnl_attr_validate(attr, MNL_TYPE_U64) < 0) abi_breakage(); break; + case NFTA_LAST_SET: + if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) + abi_breakage(); + break; } tb[type] = attr; @@ -78,6 +89,8 @@ nftnl_expr_last_build(struct nlmsghdr *nlh, const struct nftnl_expr *e) if (e->flags & (1 << NFTNL_EXPR_LAST_MSECS)) mnl_attr_put_u64(nlh, NFTA_LAST_MSECS, htobe64(last->msecs)); + if (e->flags & (1 << NFTNL_EXPR_LAST_SET)) + mnl_attr_put_u32(nlh, NFTA_LAST_SET, htonl(last->set)); } static int @@ -93,6 +106,10 @@ nftnl_expr_last_parse(struct nftnl_expr *e, struct nlattr *attr) last->msecs = be64toh(mnl_attr_get_u64(tb[NFTA_LAST_MSECS])); e->flags |= (1 << NFTNL_EXPR_LAST_MSECS); } + if (tb[NFTA_LAST_SET]) { + last->set = ntohl(mnl_attr_get_u32(tb[NFTA_LAST_SET])); + e->flags |= (1 << NFTNL_EXPR_LAST_SET); + } return 0; } @@ -103,7 +120,10 @@ static int nftnl_expr_last_snprintf(char *buf, size_t len, { struct nftnl_expr_last *last = nftnl_expr_data(e); - return snprintf(buf, len, "last %"PRIu64" ", last->msecs); + if (!last->set) + return snprintf(buf, len, "never "); + + return snprintf(buf, len, "%"PRIu64" ", last->msecs); } struct expr_ops expr_ops_last = { @@ -114,5 +134,5 @@ struct expr_ops expr_ops_last = { .get = nftnl_expr_last_get, .parse = nftnl_expr_last_parse, .build = nftnl_expr_last_build, - .snprintf = nftnl_expr_last_snprintf, + .output = nftnl_expr_last_snprintf, }; diff --git a/src/expr/limit.c b/src/expr/limit.c index 3dfd54a..1870e0e 100644 --- a/src/expr/limit.c +++ b/src/expr/limit.c @@ -202,5 +202,5 @@ struct expr_ops expr_ops_limit = { .get = nftnl_expr_limit_get, .parse = nftnl_expr_limit_parse, .build = nftnl_expr_limit_build, - .snprintf = nftnl_expr_limit_snprintf, + .output = nftnl_expr_limit_snprintf, }; diff --git a/src/expr/log.c b/src/expr/log.c index 86db548..180d839 100644 --- a/src/expr/log.c +++ b/src/expr/log.c @@ -253,5 +253,5 @@ struct expr_ops expr_ops_log = { .get = nftnl_expr_log_get, .parse = nftnl_expr_log_parse, .build = nftnl_expr_log_build, - .snprintf = nftnl_expr_log_snprintf, + .output = nftnl_expr_log_snprintf, }; diff --git a/src/expr/lookup.c b/src/expr/lookup.c index 83adce9..a06c338 100644 --- a/src/expr/lookup.c +++ b/src/expr/lookup.c @@ -206,5 +206,5 @@ struct expr_ops expr_ops_lookup = { .get = nftnl_expr_lookup_get, .parse = nftnl_expr_lookup_parse, .build = nftnl_expr_lookup_build, - .snprintf = nftnl_expr_lookup_snprintf, + .output = nftnl_expr_lookup_snprintf, }; diff --git a/src/expr/masq.c b/src/expr/masq.c index 684708c..e6e528d 100644 --- a/src/expr/masq.c +++ b/src/expr/masq.c @@ -163,5 +163,5 @@ struct expr_ops expr_ops_masq = { .get = nftnl_expr_masq_get, .parse = nftnl_expr_masq_parse, .build = nftnl_expr_masq_build, - .snprintf = nftnl_expr_masq_snprintf, + .output = nftnl_expr_masq_snprintf, }; diff --git a/src/expr/match.c b/src/expr/match.c index 533fdf5..f472add 100644 --- a/src/expr/match.c +++ b/src/expr/match.c @@ -189,5 +189,5 @@ struct expr_ops expr_ops_match = { .get = nftnl_expr_match_get, .parse = nftnl_expr_match_parse, .build = nftnl_expr_match_build, - .snprintf = nftnl_expr_match_snprintf, + .output = nftnl_expr_match_snprintf, }; diff --git a/src/expr/meta.c b/src/expr/meta.c index 34fbb9b..96544a4 100644 --- a/src/expr/meta.c +++ b/src/expr/meta.c @@ -216,5 +216,5 @@ struct expr_ops expr_ops_meta = { .get = nftnl_expr_meta_get, .parse = nftnl_expr_meta_parse, .build = nftnl_expr_meta_build, - .snprintf = nftnl_expr_meta_snprintf, + .output = nftnl_expr_meta_snprintf, }; diff --git a/src/expr/nat.c b/src/expr/nat.c index 0a9cdd7..ca727be 100644 --- a/src/expr/nat.c +++ b/src/expr/nat.c @@ -274,5 +274,5 @@ struct expr_ops expr_ops_nat = { .get = nftnl_expr_nat_get, .parse = nftnl_expr_nat_parse, .build = nftnl_expr_nat_build, - .snprintf = nftnl_expr_nat_snprintf, + .output = nftnl_expr_nat_snprintf, }; diff --git a/src/expr/numgen.c b/src/expr/numgen.c index 159dfec..d4020a6 100644 --- a/src/expr/numgen.c +++ b/src/expr/numgen.c @@ -180,5 +180,5 @@ struct expr_ops expr_ops_ng = { .get = nftnl_expr_ng_get, .parse = nftnl_expr_ng_parse, .build = nftnl_expr_ng_build, - .snprintf = nftnl_expr_ng_snprintf, + .output = nftnl_expr_ng_snprintf, }; diff --git a/src/expr/objref.c b/src/expr/objref.c index a4b6470..ad0688f 100644 --- a/src/expr/objref.c +++ b/src/expr/objref.c @@ -205,5 +205,5 @@ struct expr_ops expr_ops_objref = { .get = nftnl_expr_objref_get, .parse = nftnl_expr_objref_parse, .build = nftnl_expr_objref_build, - .snprintf = nftnl_expr_objref_snprintf, + .output = nftnl_expr_objref_snprintf, }; diff --git a/src/expr/osf.c b/src/expr/osf.c index 215a681..f15a722 100644 --- a/src/expr/osf.c +++ b/src/expr/osf.c @@ -147,5 +147,5 @@ struct expr_ops expr_ops_osf = { .get = nftnl_expr_osf_get, .parse = nftnl_expr_osf_parse, .build = nftnl_expr_osf_build, - .snprintf = nftnl_expr_osf_snprintf, + .output = nftnl_expr_osf_snprintf, }; diff --git a/src/expr/payload.c b/src/expr/payload.c index 9ccb78e..c633e33 100644 --- a/src/expr/payload.c +++ b/src/expr/payload.c @@ -203,34 +203,22 @@ nftnl_expr_payload_parse(struct nftnl_expr *e, struct nlattr *attr) return 0; } -static const char *base2str_array[NFT_PAYLOAD_TRANSPORT_HEADER+1] = { +static const char *base2str_array[NFT_PAYLOAD_TUN_HEADER + 1] = { [NFT_PAYLOAD_LL_HEADER] = "link", [NFT_PAYLOAD_NETWORK_HEADER] = "network", [NFT_PAYLOAD_TRANSPORT_HEADER] = "transport", + [NFT_PAYLOAD_INNER_HEADER] = "inner", + [NFT_PAYLOAD_TUN_HEADER] = "tunnel", }; static const char *base2str(enum nft_payload_bases base) { - if (base > NFT_PAYLOAD_TRANSPORT_HEADER) + if (base > NFT_PAYLOAD_INNER_HEADER) return "unknown"; return base2str_array[base]; } -static inline int nftnl_str2base(const char *base) -{ - if (strcmp(base, "link") == 0) - return NFT_PAYLOAD_LL_HEADER; - else if (strcmp(base, "network") == 0) - return NFT_PAYLOAD_NETWORK_HEADER; - else if (strcmp(base, "transport") == 0) - return NFT_PAYLOAD_TRANSPORT_HEADER; - else { - errno = EINVAL; - return -1; - } -} - static int nftnl_expr_payload_snprintf(char *buf, size_t len, uint32_t flags, const struct nftnl_expr *e) @@ -258,5 +246,5 @@ struct expr_ops expr_ops_payload = { .get = nftnl_expr_payload_get, .parse = nftnl_expr_payload_parse, .build = nftnl_expr_payload_build, - .snprintf = nftnl_expr_payload_snprintf, + .output = nftnl_expr_payload_snprintf, }; diff --git a/src/expr/queue.c b/src/expr/queue.c index 8f70977..de287f2 100644 --- a/src/expr/queue.c +++ b/src/expr/queue.c @@ -193,5 +193,5 @@ struct expr_ops expr_ops_queue = { .get = nftnl_expr_queue_get, .parse = nftnl_expr_queue_parse, .build = nftnl_expr_queue_build, - .snprintf = nftnl_expr_queue_snprintf, + .output = nftnl_expr_queue_snprintf, }; diff --git a/src/expr/quota.c b/src/expr/quota.c index 8c841d8..835729c 100644 --- a/src/expr/quota.c +++ b/src/expr/quota.c @@ -147,5 +147,5 @@ struct expr_ops expr_ops_quota = { .get = nftnl_expr_quota_get, .parse = nftnl_expr_quota_parse, .build = nftnl_expr_quota_build, - .snprintf = nftnl_expr_quota_snprintf, + .output = nftnl_expr_quota_snprintf, }; diff --git a/src/expr/range.c b/src/expr/range.c index f76843a..473add8 100644 --- a/src/expr/range.c +++ b/src/expr/range.c @@ -213,5 +213,5 @@ struct expr_ops expr_ops_range = { .get = nftnl_expr_range_get, .parse = nftnl_expr_range_parse, .build = nftnl_expr_range_build, - .snprintf = nftnl_expr_range_snprintf, + .output = nftnl_expr_range_snprintf, }; diff --git a/src/expr/redir.c b/src/expr/redir.c index 4f56cb4..87c2acc 100644 --- a/src/expr/redir.c +++ b/src/expr/redir.c @@ -167,5 +167,5 @@ struct expr_ops expr_ops_redir = { .get = nftnl_expr_redir_get, .parse = nftnl_expr_redir_parse, .build = nftnl_expr_redir_build, - .snprintf = nftnl_expr_redir_snprintf, + .output = nftnl_expr_redir_snprintf, }; diff --git a/src/expr/reject.c b/src/expr/reject.c index 716d25c..c7c9441 100644 --- a/src/expr/reject.c +++ b/src/expr/reject.c @@ -134,5 +134,5 @@ struct expr_ops expr_ops_reject = { .get = nftnl_expr_reject_get, .parse = nftnl_expr_reject_parse, .build = nftnl_expr_reject_build, - .snprintf = nftnl_expr_reject_snprintf, + .output = nftnl_expr_reject_snprintf, }; diff --git a/src/expr/rt.c b/src/expr/rt.c index 1ad9b2a..695a658 100644 --- a/src/expr/rt.c +++ b/src/expr/rt.c @@ -162,5 +162,5 @@ struct expr_ops expr_ops_rt = { .get = nftnl_expr_rt_get, .parse = nftnl_expr_rt_parse, .build = nftnl_expr_rt_build, - .snprintf = nftnl_expr_rt_snprintf, + .output = nftnl_expr_rt_snprintf, }; diff --git a/src/expr/socket.c b/src/expr/socket.c index 02d86f8..83045c0 100644 --- a/src/expr/socket.c +++ b/src/expr/socket.c @@ -165,5 +165,5 @@ struct expr_ops expr_ops_socket = { .get = nftnl_expr_socket_get, .parse = nftnl_expr_socket_parse, .build = nftnl_expr_socket_build, - .snprintf = nftnl_expr_socket_snprintf, + .output = nftnl_expr_socket_snprintf, }; diff --git a/src/expr/synproxy.c b/src/expr/synproxy.c index 630f3f4..47fcaef 100644 --- a/src/expr/synproxy.c +++ b/src/expr/synproxy.c @@ -152,5 +152,5 @@ struct expr_ops expr_ops_synproxy = { .get = nftnl_expr_synproxy_get, .parse = nftnl_expr_synproxy_parse, .build = nftnl_expr_synproxy_build, - .snprintf = nftnl_expr_synproxy_snprintf, + .output = nftnl_expr_synproxy_snprintf, }; diff --git a/src/expr/target.c b/src/expr/target.c index b7c595a..2a3fe8a 100644 --- a/src/expr/target.c +++ b/src/expr/target.c @@ -189,5 +189,5 @@ struct expr_ops expr_ops_target = { .get = nftnl_expr_target_get, .parse = nftnl_expr_target_parse, .build = nftnl_expr_target_build, - .snprintf = nftnl_expr_target_snprintf, + .output = nftnl_expr_target_snprintf, }; diff --git a/src/expr/tproxy.c b/src/expr/tproxy.c index d3ee8f8..bd5ffbf 100644 --- a/src/expr/tproxy.c +++ b/src/expr/tproxy.c @@ -170,5 +170,5 @@ struct expr_ops expr_ops_tproxy = { .get = nftnl_expr_tproxy_get, .parse = nftnl_expr_tproxy_parse, .build = nftnl_expr_tproxy_build, - .snprintf = nftnl_expr_tproxy_snprintf, + .output = nftnl_expr_tproxy_snprintf, }; diff --git a/src/expr/tunnel.c b/src/expr/tunnel.c index 1460fd2..a00f620 100644 --- a/src/expr/tunnel.c +++ b/src/expr/tunnel.c @@ -145,5 +145,5 @@ struct expr_ops expr_ops_tunnel = { .get = nftnl_expr_tunnel_get, .parse = nftnl_expr_tunnel_parse, .build = nftnl_expr_tunnel_build, - .snprintf = nftnl_expr_tunnel_snprintf, + .output = nftnl_expr_tunnel_snprintf, }; diff --git a/src/expr/xfrm.c b/src/expr/xfrm.c index c81d14d..2db00d5 100644 --- a/src/expr/xfrm.c +++ b/src/expr/xfrm.c @@ -196,5 +196,5 @@ struct expr_ops expr_ops_xfrm = { .get = nftnl_expr_xfrm_get, .parse = nftnl_expr_xfrm_parse, .build = nftnl_expr_xfrm_build, - .snprintf = nftnl_expr_xfrm_snprintf, + .output = nftnl_expr_xfrm_snprintf, }; diff --git a/src/expr_ops.c b/src/expr_ops.c index 7248e4f..b85f472 100644 --- a/src/expr_ops.c +++ b/src/expr_ops.c @@ -14,6 +14,7 @@ extern struct expr_ops expr_ops_dup; extern struct expr_ops expr_ops_exthdr; extern struct expr_ops expr_ops_fwd; extern struct expr_ops expr_ops_immediate; +extern struct expr_ops expr_ops_inner; extern struct expr_ops expr_ops_last; extern struct expr_ops expr_ops_limit; extern struct expr_ops expr_ops_log; @@ -58,6 +59,7 @@ static struct expr_ops *expr_ops[] = { &expr_ops_exthdr, &expr_ops_fwd, &expr_ops_immediate, + &expr_ops_inner, &expr_ops_last, &expr_ops_limit, &expr_ops_log, diff --git a/src/libnftnl.map b/src/libnftnl.map index e707b89..ad8f2af 100644 --- a/src/libnftnl.map +++ b/src/libnftnl.map @@ -383,3 +383,7 @@ LIBNFTNL_16 { nftnl_expr_add_expr; nftnl_expr_expr_foreach; } LIBNFTNL_15; + +LIBNFTNL_17 { + nftnl_set_elem_nlmsg_build; +} LIBNFTNL_16; diff --git a/src/obj/counter.c b/src/obj/counter.c index ef0cd20..ebf3e74 100644 --- a/src/obj/counter.c +++ b/src/obj/counter.c @@ -127,5 +127,5 @@ struct obj_ops obj_ops_counter = { .get = nftnl_obj_counter_get, .parse = nftnl_obj_counter_parse, .build = nftnl_obj_counter_build, - .snprintf = nftnl_obj_counter_snprintf, + .output = nftnl_obj_counter_snprintf, }; diff --git a/src/obj/ct_expect.c b/src/obj/ct_expect.c index 8136ad9..810ba9a 100644 --- a/src/obj/ct_expect.c +++ b/src/obj/ct_expect.c @@ -196,5 +196,5 @@ struct obj_ops obj_ops_ct_expect = { .get = nftnl_obj_ct_expect_get, .parse = nftnl_obj_ct_expect_parse, .build = nftnl_obj_ct_expect_build, - .snprintf = nftnl_obj_ct_expect_snprintf, + .output = nftnl_obj_ct_expect_snprintf, }; diff --git a/src/obj/ct_helper.c b/src/obj/ct_helper.c index c52032a..a31bd6f 100644 --- a/src/obj/ct_helper.c +++ b/src/obj/ct_helper.c @@ -150,5 +150,5 @@ struct obj_ops obj_ops_ct_helper = { .get = nftnl_obj_ct_helper_get, .parse = nftnl_obj_ct_helper_parse, .build = nftnl_obj_ct_helper_build, - .snprintf = nftnl_obj_ct_helper_snprintf, + .output = nftnl_obj_ct_helper_snprintf, }; diff --git a/src/obj/ct_timeout.c b/src/obj/ct_timeout.c index 1d4f8fb..65b48bd 100644 --- a/src/obj/ct_timeout.c +++ b/src/obj/ct_timeout.c @@ -316,5 +316,5 @@ struct obj_ops obj_ops_ct_timeout = { .get = nftnl_obj_ct_timeout_get, .parse = nftnl_obj_ct_timeout_parse, .build = nftnl_obj_ct_timeout_build, - .snprintf = nftnl_obj_ct_timeout_snprintf, + .output = nftnl_obj_ct_timeout_snprintf, }; diff --git a/src/obj/limit.c b/src/obj/limit.c index 8b40f9d..d7b1aed 100644 --- a/src/obj/limit.c +++ b/src/obj/limit.c @@ -168,5 +168,5 @@ struct obj_ops obj_ops_limit = { .get = nftnl_obj_limit_get, .parse = nftnl_obj_limit_parse, .build = nftnl_obj_limit_build, - .snprintf = nftnl_obj_limit_snprintf, + .output = nftnl_obj_limit_snprintf, }; diff --git a/src/obj/quota.c b/src/obj/quota.c index 8ab3300..6c7559a 100644 --- a/src/obj/quota.c +++ b/src/obj/quota.c @@ -144,5 +144,5 @@ struct obj_ops obj_ops_quota = { .get = nftnl_obj_quota_get, .parse = nftnl_obj_quota_parse, .build = nftnl_obj_quota_build, - .snprintf = nftnl_obj_quota_snprintf, + .output = nftnl_obj_quota_snprintf, }; diff --git a/src/obj/secmark.c b/src/obj/secmark.c index 2ccc803..e5c24b3 100644 --- a/src/obj/secmark.c +++ b/src/obj/secmark.c @@ -116,5 +116,5 @@ struct obj_ops obj_ops_secmark = { .get = nftnl_obj_secmark_get, .parse = nftnl_obj_secmark_parse, .build = nftnl_obj_secmark_build, - .snprintf = nftnl_obj_secmark_snprintf, + .output = nftnl_obj_secmark_snprintf, }; diff --git a/src/obj/synproxy.c b/src/obj/synproxy.c index d689fee..baef5c2 100644 --- a/src/obj/synproxy.c +++ b/src/obj/synproxy.c @@ -143,5 +143,5 @@ struct obj_ops obj_ops_synproxy = { .get = nftnl_obj_synproxy_get, .parse = nftnl_obj_synproxy_parse, .build = nftnl_obj_synproxy_build, - .snprintf = nftnl_obj_synproxy_snprintf, + .output = nftnl_obj_synproxy_snprintf, }; diff --git a/src/obj/tunnel.c b/src/obj/tunnel.c index 5ede6bd..d2503dc 100644 --- a/src/obj/tunnel.c +++ b/src/obj/tunnel.c @@ -547,5 +547,5 @@ struct obj_ops obj_ops_tunnel = { .get = nftnl_obj_tunnel_get, .parse = nftnl_obj_tunnel_parse, .build = nftnl_obj_tunnel_build, - .snprintf = nftnl_obj_tunnel_snprintf, + .output = nftnl_obj_tunnel_snprintf, }; diff --git a/src/object.c b/src/object.c index 46e208b..232b97a 100644 --- a/src/object.c +++ b/src/object.c @@ -396,7 +396,7 @@ static int nftnl_obj_snprintf_dflt(char *buf, size_t remain, SNPRINTF_BUFFER_SIZE(ret, remain, offset); if (obj->ops) { - ret = obj->ops->snprintf(buf + offset, remain, flags, obj); + ret = obj->ops->output(buf + offset, remain, flags, obj); SNPRINTF_BUFFER_SIZE(ret, remain, offset); } ret = snprintf(buf + offset, remain, "]"); @@ -622,12 +622,13 @@ static int nftnl_rule_snprintf_default(char *buf, size_t remain, for (i = 0; i < r->user.len; i++) { char *c = r->user.data; - ret = snprintf(buf + offset, remain, "%c", - isalnum(c[i]) ? c[i] : 0); + ret = snprintf(buf + offset, remain, + isprint(c[i]) ? "%c" : "\\x%02hhx", + c[i]); SNPRINTF_BUFFER_SIZE(ret, remain, offset); } - ret = snprintf(buf + offset, remain, " }\n"); + ret = snprintf(buf + offset, remain, " }"); SNPRINTF_BUFFER_SIZE(ret, remain, offset); } @@ -829,7 +829,7 @@ static int nftnl_set_snprintf_default(char *buf, size_t remain, SNPRINTF_BUFFER_SIZE(ret, remain, offset); ret = nftnl_set_elem_snprintf_default(buf + offset, remain, - elem, s->data_type); + elem); SNPRINTF_BUFFER_SIZE(ret, remain, offset); } diff --git a/src/set_elem.c b/src/set_elem.c index 90632a2..884faff 100644 --- a/src/set_elem.c +++ b/src/set_elem.c @@ -300,6 +300,7 @@ err: return NULL; } +EXPORT_SYMBOL(nftnl_set_elem_nlmsg_build_payload); void nftnl_set_elem_nlmsg_build_payload(struct nlmsghdr *nlh, struct nftnl_set_elem *e) { @@ -388,8 +389,9 @@ static void nftnl_set_elem_nlmsg_build_def(struct nlmsghdr *nlh, mnl_attr_put_strz(nlh, NFTA_SET_ELEM_LIST_TABLE, s->table); } -static struct nlattr *nftnl_set_elem_build(struct nlmsghdr *nlh, - struct nftnl_set_elem *elem, int i) +EXPORT_SYMBOL(nftnl_set_elem_nlmsg_build); +struct nlattr *nftnl_set_elem_nlmsg_build(struct nlmsghdr *nlh, + struct nftnl_set_elem *elem, int i) { struct nlattr *nest2; @@ -414,7 +416,7 @@ void nftnl_set_elems_nlmsg_build_payload(struct nlmsghdr *nlh, struct nftnl_set nest1 = mnl_attr_nest_start(nlh, NFTA_SET_ELEM_LIST_ELEMENTS); list_for_each_entry(elem, &s->element_list, head) - nftnl_set_elem_build(nlh, elem, ++i); + nftnl_set_elem_nlmsg_build(nlh, elem, ++i); mnl_attr_nest_end(nlh, nest1); } @@ -699,11 +701,9 @@ int nftnl_set_elem_parse_file(struct nftnl_set_elem *e, enum nftnl_parse_type ty } int nftnl_set_elem_snprintf_default(char *buf, size_t remain, - const struct nftnl_set_elem *e, - enum nft_data_types dtype) + const struct nftnl_set_elem *e) { - int dregtype = (dtype == NFT_DATA_VERDICT) ? DATA_VERDICT : DATA_VALUE; - int ret, offset = 0, i; + int ret, dregtype = DATA_VALUE, offset = 0, i; ret = snprintf(buf, remain, "element "); SNPRINTF_BUFFER_SIZE(ret, remain, offset); @@ -724,6 +724,9 @@ int nftnl_set_elem_snprintf_default(char *buf, size_t remain, ret = snprintf(buf + offset, remain, " : "); SNPRINTF_BUFFER_SIZE(ret, remain, offset); + if (e->flags & (1 << NFTNL_SET_ELEM_VERDICT)) + dregtype = DATA_VERDICT; + ret = nftnl_data_reg_snprintf(buf + offset, remain, &e->data, DATA_F_NOPFX, dregtype); SNPRINTF_BUFFER_SIZE(ret, remain, offset); @@ -732,18 +735,19 @@ int nftnl_set_elem_snprintf_default(char *buf, size_t remain, SNPRINTF_BUFFER_SIZE(ret, remain, offset); if (e->user.len) { - ret = snprintf(buf + offset, remain, " userdata = {"); + ret = snprintf(buf + offset, remain, " userdata = { "); SNPRINTF_BUFFER_SIZE(ret, remain, offset); for (i = 0; i < e->user.len; i++) { char *c = e->user.data; - ret = snprintf(buf + offset, remain, "%c", - isalnum(c[i]) ? c[i] : 0); + ret = snprintf(buf + offset, remain, + isprint(c[i]) ? "%c" : "\\x%02hhx", + c[i]); SNPRINTF_BUFFER_SIZE(ret, remain, offset); } - ret = snprintf(buf + offset, remain, " }\n"); + ret = snprintf(buf + offset, remain, " }"); SNPRINTF_BUFFER_SIZE(ret, remain, offset); } @@ -760,9 +764,9 @@ static int nftnl_set_elem_cmd_snprintf(char *buf, size_t remain, if (type != NFTNL_OUTPUT_DEFAULT) return -1; - ret = nftnl_set_elem_snprintf_default(buf + offset, remain, e, - NFT_DATA_VALUE); + ret = nftnl_set_elem_snprintf_default(buf + offset, remain, e); SNPRINTF_BUFFER_SIZE(ret, remain, offset); + return offset; } @@ -898,7 +902,7 @@ int nftnl_set_elems_nlmsg_build_payload_iter(struct nlmsghdr *nlh, nest1 = mnl_attr_nest_start(nlh, NFTA_SET_ELEM_LIST_ELEMENTS); elem = nftnl_set_elems_iter_next(iter); while (elem != NULL) { - nest2 = nftnl_set_elem_build(nlh, elem, ++i); + nest2 = nftnl_set_elem_nlmsg_build(nlh, elem, ++i); if (nftnl_attr_nest_overflow(nlh, nest1, nest2)) { /* Go back to previous not to miss this element */ iter->cur = list_entry(iter->cur->head.prev, |