summaryrefslogtreecommitdiffstats
path: root/src/ct.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/ct.c')
-rw-r--r--src/ct.c95
1 files changed, 82 insertions, 13 deletions
diff --git a/src/ct.c b/src/ct.c
index ed458e6b..67934648 100644
--- a/src/ct.c
+++ b/src/ct.c
@@ -10,11 +10,11 @@
* Development of this code funded by Astaro AG (http://www.astaro.com/)
*/
+#include <nft.h>
+
#include <stddef.h>
-#include <stdlib.h>
#include <stdio.h>
#include <inttypes.h>
-#include <string.h>
#include <netinet/ip.h>
#include <linux/netfilter.h>
@@ -131,7 +131,7 @@ static const struct symbol_table ct_events_tbl = {
},
};
-static const struct datatype ct_event_type = {
+const struct datatype ct_event_type = {
.type = TYPE_CT_EVENTBIT,
.name = "ct_event",
.desc = "conntrack event bits",
@@ -176,7 +176,7 @@ static struct error_record *ct_label_type_parse(struct parse_ctx *ctx,
{
const struct symbolic_constant *s;
const struct datatype *dtype;
- uint8_t data[CT_LABEL_BIT_SIZE];
+ uint8_t data[CT_LABEL_BIT_SIZE / BITS_PER_BYTE];
uint64_t bit;
mpz_t value;
@@ -211,16 +211,22 @@ static struct error_record *ct_label_type_parse(struct parse_ctx *ctx,
mpz_export_data(data, value, BYTEORDER_HOST_ENDIAN, sizeof(data));
*res = constant_expr_alloc(&sym->location, dtype,
- dtype->byteorder, sizeof(data),
- data);
+ dtype->byteorder, CT_LABEL_BIT_SIZE, data);
mpz_clear(value);
return NULL;
}
-static const struct datatype ct_label_type = {
+static void ct_label_type_describe(struct output_ctx *octx)
+{
+ rt_symbol_table_describe(octx, CONNLABEL_CONF,
+ octx->tbl.ct_label, &ct_label_type);
+}
+
+const struct datatype ct_label_type = {
.type = TYPE_CT_LABEL,
.name = "ct_label",
.desc = "conntrack label",
+ .describe = ct_label_type_describe,
.byteorder = BYTEORDER_HOST_ENDIAN,
.size = CT_LABEL_BIT_SIZE,
.basetype = &bitmask_type,
@@ -272,10 +278,10 @@ const struct ct_template ct_templates[__NFT_CT_MAX] = {
[NFT_CT_PROTOCOL] = CT_TEMPLATE("protocol", &inet_protocol_type,
BYTEORDER_BIG_ENDIAN,
BITS_PER_BYTE),
- [NFT_CT_PROTO_SRC] = CT_TEMPLATE("proto-src", &invalid_type,
+ [NFT_CT_PROTO_SRC] = CT_TEMPLATE("proto-src", &inet_service_type,
BYTEORDER_BIG_ENDIAN,
2 * BITS_PER_BYTE),
- [NFT_CT_PROTO_DST] = CT_TEMPLATE("proto-dst", &invalid_type,
+ [NFT_CT_PROTO_DST] = CT_TEMPLATE("proto-dst", &inet_service_type,
BYTEORDER_BIG_ENDIAN,
2 * BITS_PER_BYTE),
[NFT_CT_LABELS] = CT_TEMPLATE("label", &ct_label_type,
@@ -299,6 +305,10 @@ const struct ct_template ct_templates[__NFT_CT_MAX] = {
BYTEORDER_BIG_ENDIAN, 128),
[NFT_CT_DST_IP6] = CT_TEMPLATE("ip6 daddr", &ip6addr_type,
BYTEORDER_BIG_ENDIAN, 128),
+ [NFT_CT_SECMARK] = CT_TEMPLATE("secmark", &integer_type,
+ BYTEORDER_HOST_ENDIAN, 32),
+ [NFT_CT_ID] = CT_TEMPLATE("id", &integer_type,
+ BYTEORDER_BIG_ENDIAN, 32),
};
static void ct_print(enum nft_ct_keys key, int8_t dir, uint8_t nfproto,
@@ -347,9 +357,11 @@ static void ct_expr_clone(struct expr *new, const struct expr *expr)
new->ct = expr->ct;
}
-static void ct_expr_pctx_update(struct proto_ctx *ctx, const struct expr *expr)
+static void ct_expr_pctx_update(struct proto_ctx *ctx,
+ const struct location *loc,
+ const struct expr *left,
+ const struct expr *right)
{
- const struct expr *left = expr->left, *right = expr->right;
const struct proto_desc *base = NULL, *desc;
uint32_t nhproto;
@@ -362,7 +374,61 @@ static void ct_expr_pctx_update(struct proto_ctx *ctx, const struct expr *expr)
if (!desc)
return;
- proto_ctx_update(ctx, left->ct.base + 1, &expr->location, desc);
+ proto_ctx_update(ctx, left->ct.base + 1, loc, desc);
+}
+
+#define NFTNL_UDATA_CT_KEY 0
+#define NFTNL_UDATA_CT_DIR 1
+#define NFTNL_UDATA_CT_MAX 2
+
+static int ct_expr_build_udata(struct nftnl_udata_buf *udbuf,
+ const struct expr *expr)
+{
+ nftnl_udata_put_u32(udbuf, NFTNL_UDATA_CT_KEY, expr->ct.key);
+ nftnl_udata_put_u32(udbuf, NFTNL_UDATA_CT_DIR, expr->ct.direction);
+
+ return 0;
+}
+
+static int ct_parse_udata(const struct nftnl_udata *attr, void *data)
+{
+ const struct nftnl_udata **ud = data;
+ uint8_t type = nftnl_udata_type(attr);
+ uint8_t len = nftnl_udata_len(attr);
+
+ switch (type) {
+ case NFTNL_UDATA_CT_KEY:
+ case NFTNL_UDATA_CT_DIR:
+ if (len != sizeof(uint32_t))
+ return -1;
+ break;
+ default:
+ return 0;
+ }
+
+ ud[type] = attr;
+ return 0;
+}
+
+static struct expr *ct_expr_parse_udata(const struct nftnl_udata *attr)
+{
+ const struct nftnl_udata *ud[NFTNL_UDATA_CT_MAX + 1] = {};
+ uint32_t key, dir;
+ int err;
+
+ err = nftnl_udata_parse(nftnl_udata_get(attr), nftnl_udata_len(attr),
+ ct_parse_udata, ud);
+ if (err < 0)
+ return NULL;
+
+ if (!ud[NFTNL_UDATA_CT_KEY] ||
+ !ud[NFTNL_UDATA_CT_DIR])
+ return NULL;
+
+ key = nftnl_udata_get_u32(ud[NFTNL_UDATA_CT_KEY]);
+ dir = nftnl_udata_get_u32(ud[NFTNL_UDATA_CT_DIR]);
+
+ return ct_expr_alloc(&internal_location, key, dir);
}
const struct expr_ops ct_expr_ops = {
@@ -373,6 +439,8 @@ const struct expr_ops ct_expr_ops = {
.cmp = ct_expr_cmp,
.clone = ct_expr_clone,
.pctx_update = ct_expr_pctx_update,
+ .parse_udata = ct_expr_parse_udata,
+ .build_udata = ct_expr_build_udata,
};
struct expr *ct_expr_alloc(const struct location *loc, enum nft_ct_keys key,
@@ -509,7 +577,7 @@ static void flow_offload_stmt_print(const struct stmt *stmt,
static void flow_offload_stmt_destroy(struct stmt *stmt)
{
- xfree(stmt->flow.table_name);
+ free_const(stmt->flow.table_name);
}
static const struct stmt_ops flow_offload_stmt_ops = {
@@ -517,6 +585,7 @@ static const struct stmt_ops flow_offload_stmt_ops = {
.name = "flow_offload",
.print = flow_offload_stmt_print,
.destroy = flow_offload_stmt_destroy,
+ .json = flow_offload_stmt_json,
};
struct stmt *flow_offload_stmt_alloc(const struct location *loc,