summaryrefslogtreecommitdiffstats
path: root/src/obj
diff options
context:
space:
mode:
Diffstat (limited to 'src/obj')
-rw-r--r--src/obj/counter.c42
-rw-r--r--src/obj/ct_expect.c69
-rw-r--r--src/obj/ct_helper.c45
-rw-r--r--src/obj/ct_timeout.c67
-rw-r--r--src/obj/limit.c52
-rw-r--r--src/obj/quota.c46
-rw-r--r--src/obj/secmark.c38
-rw-r--r--src/obj/synproxy.c39
-rw-r--r--src/obj/tunnel.c680
9 files changed, 708 insertions, 370 deletions
diff --git a/src/obj/counter.c b/src/obj/counter.c
index 1baba4e..c9462cd 100644
--- a/src/obj/counter.c
+++ b/src/obj/counter.c
@@ -1,10 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* (C) 2012-2016 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 <stdio.h>
@@ -29,13 +25,11 @@ nftnl_obj_counter_set(struct nftnl_obj *e, uint16_t type,
switch(type) {
case NFTNL_OBJ_CTR_BYTES:
- memcpy(&ctr->bytes, data, sizeof(ctr->bytes));
+ memcpy(&ctr->bytes, data, data_len);
break;
case NFTNL_OBJ_CTR_PKTS:
- memcpy(&ctr->pkts, data, sizeof(ctr->pkts));
+ memcpy(&ctr->pkts, data, data_len);
break;
- default:
- return -1;
}
return 0;
}
@@ -109,8 +103,8 @@ nftnl_obj_counter_parse(struct nftnl_obj *e, struct nlattr *attr)
return 0;
}
-static int nftnl_obj_counter_snprintf_default(char *buf, size_t len,
- const struct nftnl_obj *e)
+static int nftnl_obj_counter_snprintf(char *buf, size_t len, uint32_t flags,
+ const struct nftnl_obj *e)
{
struct nftnl_obj_counter *ctr = nftnl_obj_data(e);
@@ -118,32 +112,20 @@ static int nftnl_obj_counter_snprintf_default(char *buf, size_t len,
ctr->pkts, ctr->bytes);
}
-static int nftnl_obj_counter_snprintf(char *buf, size_t len, uint32_t type,
- uint32_t flags,
- const struct nftnl_obj *e)
-{
- if (len)
- buf[0] = '\0';
-
- switch (type) {
- case NFTNL_OUTPUT_DEFAULT:
- return nftnl_obj_counter_snprintf_default(buf, len, e);
- case NFTNL_OUTPUT_XML:
- case NFTNL_OUTPUT_JSON:
- default:
- break;
- }
- return -1;
-}
+static struct attr_policy obj_ctr_attr_policy[__NFTNL_OBJ_CTR_MAX] = {
+ [NFTNL_OBJ_CTR_BYTES] = { .maxlen = sizeof(uint64_t) },
+ [NFTNL_OBJ_CTR_PKTS] = { .maxlen = sizeof(uint64_t) },
+};
struct obj_ops obj_ops_counter = {
.name = "counter",
.type = NFT_OBJECT_COUNTER,
.alloc_len = sizeof(struct nftnl_obj_counter),
- .max_attr = NFTA_COUNTER_MAX,
+ .nftnl_max_attr = __NFTNL_OBJ_CTR_MAX - 1,
+ .attr_policy = obj_ctr_attr_policy,
.set = nftnl_obj_counter_set,
.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 c0bb5ba..65c6d08 100644
--- a/src/obj/ct_expect.c
+++ b/src/obj/ct_expect.c
@@ -1,10 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* (C) 2019 by Stéphane Veyret <sveyret@gmail.com>
- *
- * 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 <arpa/inet.h>
@@ -21,22 +17,20 @@ static int nftnl_obj_ct_expect_set(struct nftnl_obj *e, uint16_t type,
switch (type) {
case NFTNL_OBJ_CT_EXPECT_L3PROTO:
- memcpy(&exp->l3proto, data, sizeof(exp->l3proto));
+ memcpy(&exp->l3proto, data, data_len);
break;
case NFTNL_OBJ_CT_EXPECT_L4PROTO:
- memcpy(&exp->l4proto, data, sizeof(exp->l4proto));
+ memcpy(&exp->l4proto, data, data_len);
break;
case NFTNL_OBJ_CT_EXPECT_DPORT:
- memcpy(&exp->dport, data, sizeof(exp->dport));
+ memcpy(&exp->dport, data, data_len);
break;
case NFTNL_OBJ_CT_EXPECT_TIMEOUT:
- memcpy(&exp->timeout, data, sizeof(exp->timeout));
+ memcpy(&exp->timeout, data, data_len);
break;
case NFTNL_OBJ_CT_EXPECT_SIZE:
- memcpy(&exp->size, data, sizeof(exp->size));
+ memcpy(&exp->size, data, data_len);
break;
- default:
- return -1;
}
return 0;
}
@@ -151,31 +145,35 @@ nftnl_obj_ct_expect_parse(struct nftnl_obj *e, struct nlattr *attr)
return 0;
}
-static int nftnl_obj_ct_expect_snprintf_default(char *buf, size_t len,
- const struct nftnl_obj *e)
+static int nftnl_obj_ct_expect_snprintf(char *buf, size_t remain,
+ uint32_t flags,
+ const struct nftnl_obj *e)
{
- int ret = 0;
- int offset = 0, remain = len;
struct nftnl_obj_ct_expect *exp = nftnl_obj_data(e);
+ int ret = 0, offset = 0;
if (e->flags & (1 << NFTNL_OBJ_CT_EXPECT_L3PROTO)) {
- ret = snprintf(buf + offset, len, "family %d ", exp->l3proto);
+ ret = snprintf(buf + offset, remain,
+ "family %d ", exp->l3proto);
SNPRINTF_BUFFER_SIZE(ret, remain, offset);
}
if (e->flags & (1 << NFTNL_OBJ_CT_EXPECT_L4PROTO)) {
- ret = snprintf(buf + offset, len, "protocol %d ", exp->l4proto);
+ ret = snprintf(buf + offset, remain,
+ "protocol %d ", exp->l4proto);
SNPRINTF_BUFFER_SIZE(ret, remain, offset);
}
if (e->flags & (1 << NFTNL_OBJ_CT_EXPECT_DPORT)) {
- ret = snprintf(buf + offset, len, "dport %d ", exp->dport);
+ ret = snprintf(buf + offset, remain,
+ "dport %d ", exp->dport);
SNPRINTF_BUFFER_SIZE(ret, remain, offset);
}
if (e->flags & (1 << NFTNL_OBJ_CT_EXPECT_TIMEOUT)) {
- ret = snprintf(buf + offset, len, "timeout %d ", exp->timeout);
+ ret = snprintf(buf + offset, remain,
+ "timeout %d ", exp->timeout);
SNPRINTF_BUFFER_SIZE(ret, remain, offset);
}
if (e->flags & (1 << NFTNL_OBJ_CT_EXPECT_SIZE)) {
- ret = snprintf(buf + offset, len, "size %d ", exp->size);
+ ret = snprintf(buf + offset, remain, "size %d ", exp->size);
SNPRINTF_BUFFER_SIZE(ret, remain, offset);
}
@@ -183,31 +181,24 @@ static int nftnl_obj_ct_expect_snprintf_default(char *buf, size_t len,
return offset;
}
-static int nftnl_obj_ct_expect_snprintf(char *buf, size_t len, uint32_t type,
- uint32_t flags,
- const struct nftnl_obj *e)
-{
- if (len)
- buf[0] = '\0';
-
- switch (type) {
- case NFTNL_OUTPUT_DEFAULT:
- return nftnl_obj_ct_expect_snprintf_default(buf, len, e);
- case NFTNL_OUTPUT_JSON:
- default:
- break;
- }
- return -1;
-}
+static struct attr_policy
+obj_ct_expect_attr_policy[__NFTNL_OBJ_CT_EXPECT_MAX] = {
+ [NFTNL_OBJ_CT_EXPECT_L3PROTO] = { .maxlen = sizeof(uint16_t) },
+ [NFTNL_OBJ_CT_EXPECT_L4PROTO] = { .maxlen = sizeof(uint8_t) },
+ [NFTNL_OBJ_CT_EXPECT_DPORT] = { .maxlen = sizeof(uint16_t) },
+ [NFTNL_OBJ_CT_EXPECT_TIMEOUT] = { .maxlen = sizeof(uint32_t) },
+ [NFTNL_OBJ_CT_EXPECT_SIZE] = { .maxlen = sizeof(uint8_t) },
+};
struct obj_ops obj_ops_ct_expect = {
.name = "ct_expect",
.type = NFT_OBJECT_CT_EXPECT,
.alloc_len = sizeof(struct nftnl_obj_ct_expect),
- .max_attr = NFTA_CT_EXPECT_MAX,
+ .nftnl_max_attr = __NFTNL_OBJ_CT_EXPECT_MAX - 1,
+ .attr_policy = obj_ct_expect_attr_policy,
.set = nftnl_obj_ct_expect_set,
.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 d91f636..6e16f08 100644
--- a/src/obj/ct_helper.c
+++ b/src/obj/ct_helper.c
@@ -1,11 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* (C) 2017 Red Hat GmbH
* Author: Florian Westphal <fw@strlen.de>
- *
- * 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>
@@ -32,13 +28,11 @@ static int nftnl_obj_ct_helper_set(struct nftnl_obj *e, uint16_t type,
snprintf(helper->name, sizeof(helper->name), "%s", (const char *)data);
break;
case NFTNL_OBJ_CT_HELPER_L3PROTO:
- memcpy(&helper->l3proto, data, sizeof(helper->l3proto));
+ memcpy(&helper->l3proto, data, data_len);
break;
case NFTNL_OBJ_CT_HELPER_L4PROTO:
- memcpy(&helper->l4proto, data, sizeof(helper->l4proto));
+ memcpy(&helper->l4proto, data, data_len);
break;
- default:
- return -1;
}
return 0;
}
@@ -131,8 +125,9 @@ nftnl_obj_ct_helper_parse(struct nftnl_obj *e, struct nlattr *attr)
return 0;
}
-static int nftnl_obj_ct_helper_snprintf_default(char *buf, size_t len,
- const struct nftnl_obj *e)
+static int nftnl_obj_ct_helper_snprintf(char *buf, size_t len,
+ uint32_t flags,
+ const struct nftnl_obj *e)
{
struct nftnl_obj_ct_helper *helper = nftnl_obj_data(e);
@@ -140,31 +135,25 @@ static int nftnl_obj_ct_helper_snprintf_default(char *buf, size_t len,
helper->name, helper->l3proto, helper->l4proto);
}
-static int nftnl_obj_ct_helper_snprintf(char *buf, size_t len, uint32_t type,
- uint32_t flags,
- const struct nftnl_obj *e)
-{
- if (len)
- buf[0] = '\0';
+/* from kernel's include/net/netfilter/nf_conntrack_helper.h */
+#define NF_CT_HELPER_NAME_LEN 16
- switch (type) {
- case NFTNL_OUTPUT_DEFAULT:
- return nftnl_obj_ct_helper_snprintf_default(buf, len, e);
- case NFTNL_OUTPUT_JSON:
- default:
- break;
- }
- return -1;
-}
+static struct attr_policy
+obj_ct_helper_attr_policy[__NFTNL_OBJ_CT_HELPER_MAX] = {
+ [NFTNL_OBJ_CT_HELPER_NAME] = { .maxlen = NF_CT_HELPER_NAME_LEN },
+ [NFTNL_OBJ_CT_HELPER_L3PROTO] = { .maxlen = sizeof(uint16_t) },
+ [NFTNL_OBJ_CT_HELPER_L4PROTO] = { .maxlen = sizeof(uint8_t) },
+};
struct obj_ops obj_ops_ct_helper = {
.name = "ct_helper",
.type = NFT_OBJECT_CT_HELPER,
.alloc_len = sizeof(struct nftnl_obj_ct_helper),
- .max_attr = NFTA_CT_HELPER_MAX,
+ .nftnl_max_attr = __NFTNL_OBJ_CT_HELPER_MAX - 1,
+ .attr_policy = obj_ct_helper_attr_policy,
.set = nftnl_obj_ct_helper_set,
.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 2662cac..22ce918 100644
--- a/src/obj/ct_timeout.c
+++ b/src/obj/ct_timeout.c
@@ -1,10 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* (C) 2018 by Harsha Sharma <harshasharmaiitr@gmail.com>
- *
- * 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>
@@ -21,7 +17,7 @@
#include "obj.h"
-static const char *const tcp_state_to_name[] = {
+static const char *const tcp_state_to_name[NFTNL_CTTIMEOUT_TCP_MAX] = {
[NFTNL_CTTIMEOUT_TCP_SYN_SENT] = "SYN_SENT",
[NFTNL_CTTIMEOUT_TCP_SYN_RECV] = "SYN_RECV",
[NFTNL_CTTIMEOUT_TCP_ESTABLISHED] = "ESTABLISHED",
@@ -35,7 +31,7 @@ static const char *const tcp_state_to_name[] = {
[NFTNL_CTTIMEOUT_TCP_UNACK] = "UNACKNOWLEDGED",
};
-static uint32_t tcp_dflt_timeout[] = {
+static uint32_t tcp_dflt_timeout[NFTNL_CTTIMEOUT_TCP_MAX] = {
[NFTNL_CTTIMEOUT_TCP_SYN_SENT] = 120,
[NFTNL_CTTIMEOUT_TCP_SYN_RECV] = 60,
[NFTNL_CTTIMEOUT_TCP_ESTABLISHED] = 432000,
@@ -49,12 +45,12 @@ static uint32_t tcp_dflt_timeout[] = {
[NFTNL_CTTIMEOUT_TCP_UNACK] = 300,
};
-static const char *const udp_state_to_name[] = {
+static const char *const udp_state_to_name[NFTNL_CTTIMEOUT_UDP_MAX] = {
[NFTNL_CTTIMEOUT_UDP_UNREPLIED] = "UNREPLIED",
[NFTNL_CTTIMEOUT_UDP_REPLIED] = "REPLIED",
};
-static uint32_t udp_dflt_timeout[] = {
+static uint32_t udp_dflt_timeout[NFTNL_CTTIMEOUT_UDP_MAX] = {
[NFTNL_CTTIMEOUT_UDP_UNREPLIED] = 30,
[NFTNL_CTTIMEOUT_UDP_REPLIED] = 180,
};
@@ -150,17 +146,18 @@ static int nftnl_obj_ct_timeout_set(struct nftnl_obj *e, uint16_t type,
switch (type) {
case NFTNL_OBJ_CT_TIMEOUT_L3PROTO:
- memcpy(&timeout->l3proto, data, sizeof(timeout->l3proto));
+ memcpy(&timeout->l3proto, data, data_len);
break;
case NFTNL_OBJ_CT_TIMEOUT_L4PROTO:
- memcpy(&timeout->l4proto, data, sizeof(timeout->l4proto));
+ memcpy(&timeout->l4proto, data, data_len);
break;
case NFTNL_OBJ_CT_TIMEOUT_ARRAY:
+ if (data_len < sizeof(uint32_t) * NFTNL_CTTIMEOUT_ARRAY_MAX)
+ return -1;
+
memcpy(timeout->timeout, data,
sizeof(uint32_t) * NFTNL_CTTIMEOUT_ARRAY_MAX);
break;
- default:
- return -1;
}
return 0;
}
@@ -257,21 +254,21 @@ nftnl_obj_ct_timeout_parse(struct nftnl_obj *e, struct nlattr *attr)
return 0;
}
-static int nftnl_obj_ct_timeout_snprintf_default(char *buf, size_t len,
- const struct nftnl_obj *e)
+static int nftnl_obj_ct_timeout_snprintf(char *buf, size_t remain,
+ uint32_t flags,
+ const struct nftnl_obj *e)
{
- int ret = 0;
- int offset = 0, remain = len;
+ int ret = 0, offset = 0;
struct nftnl_obj_ct_timeout *timeout = nftnl_obj_data(e);
if (e->flags & (1 << NFTNL_OBJ_CT_TIMEOUT_L3PROTO)) {
- ret = snprintf(buf + offset, len, "family %d ",
+ ret = snprintf(buf + offset, remain, "family %d ",
timeout->l3proto);
SNPRINTF_BUFFER_SIZE(ret, remain, offset);
}
if (e->flags & (1 << NFTNL_OBJ_CT_TIMEOUT_L4PROTO)) {
- ret = snprintf(buf + offset, len, "protocol %d ",
+ ret = snprintf(buf + offset, remain, "protocol %d ",
timeout->l4proto);
SNPRINTF_BUFFER_SIZE(ret, remain, offset);
}
@@ -283,7 +280,7 @@ static int nftnl_obj_ct_timeout_snprintf_default(char *buf, size_t len,
if (timeout_protocol[timeout->l4proto].attr_max == 0)
l4num = IPPROTO_RAW;
- ret = snprintf(buf + offset, len, "policy = {");
+ ret = snprintf(buf + offset, remain, "policy = {");
SNPRINTF_BUFFER_SIZE(ret, remain, offset);
for (i = 0; i < timeout_protocol[l4num].attr_max; i++) {
@@ -293,13 +290,13 @@ static int nftnl_obj_ct_timeout_snprintf_default(char *buf, size_t len,
"UNKNOWN";
if (timeout->timeout[i] != timeout_protocol[l4num].dflt_timeout[i]) {
- ret = snprintf(buf + offset, len,
+ ret = snprintf(buf + offset, remain,
"%s = %u,", state_name, timeout->timeout[i]);
SNPRINTF_BUFFER_SIZE(ret, remain, offset);
}
}
- ret = snprintf(buf + offset, len, "}");
+ ret = snprintf(buf + offset, remain, "}");
SNPRINTF_BUFFER_SIZE(ret, remain, offset);
}
buf[offset] = '\0';
@@ -307,31 +304,21 @@ static int nftnl_obj_ct_timeout_snprintf_default(char *buf, size_t len,
return offset;
}
-static int nftnl_obj_ct_timeout_snprintf(char *buf, size_t len, uint32_t type,
- uint32_t flags,
- const struct nftnl_obj *e)
-{
- if (len)
- buf[0] = '\0';
-
- switch (type) {
- case NFTNL_OUTPUT_DEFAULT:
- return nftnl_obj_ct_timeout_snprintf_default(buf, len, e);
- case NFTNL_OUTPUT_JSON:
- default:
- break;
- }
- return -1;
-}
+static struct attr_policy
+obj_ct_timeout_attr_policy[__NFTNL_OBJ_CT_TIMEOUT_MAX] = {
+ [NFTNL_OBJ_CT_TIMEOUT_L3PROTO] = { .maxlen = sizeof(uint16_t) },
+ [NFTNL_OBJ_CT_TIMEOUT_L4PROTO] = { .maxlen = sizeof(uint8_t) },
+};
struct obj_ops obj_ops_ct_timeout = {
.name = "ct_timeout",
.type = NFT_OBJECT_CT_TIMEOUT,
.alloc_len = sizeof(struct nftnl_obj_ct_timeout),
- .max_attr = NFTA_CT_TIMEOUT_MAX,
+ .nftnl_max_attr = __NFTNL_OBJ_CT_TIMEOUT_MAX - 1,
+ .attr_policy = obj_ct_timeout_attr_policy,
.set = nftnl_obj_ct_timeout_set,
.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 60b0159..fe1a88f 100644
--- a/src/obj/limit.c
+++ b/src/obj/limit.c
@@ -1,10 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* Copyright (c) 2017 Pablo M. Bermudo Garay <pablombg@gmail.com>
- *
- * 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>
@@ -28,22 +24,20 @@ static int nftnl_obj_limit_set(struct nftnl_obj *e, uint16_t type,
switch (type) {
case NFTNL_OBJ_LIMIT_RATE:
- memcpy(&limit->rate, data, sizeof(limit->rate));
+ memcpy(&limit->rate, data, data_len);
break;
case NFTNL_OBJ_LIMIT_UNIT:
- memcpy(&limit->unit, data, sizeof(limit->unit));
+ memcpy(&limit->unit, data, data_len);
break;
case NFTNL_OBJ_LIMIT_BURST:
- memcpy(&limit->burst, data, sizeof(limit->burst));
+ memcpy(&limit->burst, data, data_len);
break;
case NFTNL_OBJ_LIMIT_TYPE:
- memcpy(&limit->type, data, sizeof(limit->type));
+ memcpy(&limit->type, data, data_len);
break;
case NFTNL_OBJ_LIMIT_FLAGS:
- memcpy(&limit->flags, data, sizeof(limit->flags));
+ memcpy(&limit->flags, data, data_len);
break;
- default:
- return -1;
}
return 0;
}
@@ -148,8 +142,9 @@ static int nftnl_obj_limit_parse(struct nftnl_obj *e, struct nlattr *attr)
return 0;
}
-static int nftnl_obj_limit_snprintf_default(char *buf, size_t len,
- const struct nftnl_obj *e)
+static int nftnl_obj_limit_snprintf(char *buf, size_t len,
+ uint32_t flags,
+ const struct nftnl_obj *e)
{
struct nftnl_obj_limit *limit = nftnl_obj_data(e);
@@ -158,32 +153,23 @@ static int nftnl_obj_limit_snprintf_default(char *buf, size_t len,
limit->burst, limit->type, limit->flags);
}
-static int nftnl_obj_limit_snprintf(char *buf, size_t len, uint32_t type,
- uint32_t flags,
- const struct nftnl_obj *e)
-{
- if (len)
- buf[0] = '\0';
-
- switch (type) {
- case NFTNL_OUTPUT_DEFAULT:
- return nftnl_obj_limit_snprintf_default(buf, len, e);
- case NFTNL_OUTPUT_XML:
- case NFTNL_OUTPUT_JSON:
- default:
- break;
- }
- return -1;
-}
+static struct attr_policy obj_limit_attr_policy[__NFTNL_OBJ_LIMIT_MAX] = {
+ [NFTNL_OBJ_LIMIT_RATE] = { .maxlen = sizeof(uint64_t) },
+ [NFTNL_OBJ_LIMIT_UNIT] = { .maxlen = sizeof(uint64_t) },
+ [NFTNL_OBJ_LIMIT_BURST] = { .maxlen = sizeof(uint32_t) },
+ [NFTNL_OBJ_LIMIT_TYPE] = { .maxlen = sizeof(uint32_t) },
+ [NFTNL_OBJ_LIMIT_FLAGS] = { .maxlen = sizeof(uint32_t) },
+};
struct obj_ops obj_ops_limit = {
.name = "limit",
.type = NFT_OBJECT_LIMIT,
.alloc_len = sizeof(struct nftnl_obj_limit),
- .max_attr = NFTA_LIMIT_MAX,
+ .nftnl_max_attr = __NFTNL_OBJ_LIMIT_MAX - 1,
+ .attr_policy = obj_limit_attr_policy,
.set = nftnl_obj_limit_set,
.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 1914037..0eda0a5 100644
--- a/src/obj/quota.c
+++ b/src/obj/quota.c
@@ -1,10 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* (C) 2012-2016 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 <stdio.h>
@@ -28,16 +24,14 @@ static int nftnl_obj_quota_set(struct nftnl_obj *e, uint16_t type,
switch (type) {
case NFTNL_OBJ_QUOTA_BYTES:
- memcpy(&quota->bytes, data, sizeof(quota->bytes));
+ memcpy(&quota->bytes, data, data_len);
break;
case NFTNL_OBJ_QUOTA_CONSUMED:
- memcpy(&quota->consumed, data, sizeof(quota->consumed));
+ memcpy(&quota->consumed, data, data_len);
break;
case NFTNL_OBJ_QUOTA_FLAGS:
- memcpy(&quota->flags, data, sizeof(quota->flags));
+ memcpy(&quota->flags, data, data_len);
break;
- default:
- return -1;
}
return 0;
}
@@ -125,8 +119,9 @@ nftnl_obj_quota_parse(struct nftnl_obj *e, struct nlattr *attr)
return 0;
}
-static int nftnl_obj_quota_snprintf_default(char *buf, size_t len,
- const struct nftnl_obj *e)
+static int nftnl_obj_quota_snprintf(char *buf, size_t len,
+ uint32_t flags,
+ const struct nftnl_obj *e)
{
struct nftnl_obj_quota *quota = nftnl_obj_data(e);
@@ -134,32 +129,21 @@ static int nftnl_obj_quota_snprintf_default(char *buf, size_t len,
quota->bytes, quota->flags);
}
-static int nftnl_obj_quota_snprintf(char *buf, size_t len, uint32_t type,
- uint32_t flags,
- const struct nftnl_obj *e)
-{
- if (len)
- buf[0] = '\0';
-
- switch (type) {
- case NFTNL_OUTPUT_DEFAULT:
- return nftnl_obj_quota_snprintf_default(buf, len, e);
- case NFTNL_OUTPUT_XML:
- case NFTNL_OUTPUT_JSON:
- default:
- break;
- }
- return -1;
-}
+static struct attr_policy obj_quota_attr_policy[__NFTNL_OBJ_QUOTA_MAX] = {
+ [NFTNL_OBJ_QUOTA_BYTES] = { .maxlen = sizeof(uint64_t) },
+ [NFTNL_OBJ_QUOTA_CONSUMED] = { .maxlen = sizeof(uint64_t) },
+ [NFTNL_OBJ_QUOTA_FLAGS] = { .maxlen = sizeof(uint32_t) },
+};
struct obj_ops obj_ops_quota = {
.name = "quota",
.type = NFT_OBJECT_QUOTA,
.alloc_len = sizeof(struct nftnl_obj_quota),
- .max_attr = NFTA_QUOTA_MAX,
+ .nftnl_max_attr = __NFTNL_OBJ_QUOTA_MAX - 1,
+ .attr_policy = obj_quota_attr_policy,
.set = nftnl_obj_quota_set,
.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 e27b5fa..25b04e2 100644
--- a/src/obj/secmark.c
+++ b/src/obj/secmark.c
@@ -1,10 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* (C) 2012-2016 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 <stdio.h>
@@ -30,8 +26,6 @@ static int nftnl_obj_secmark_set(struct nftnl_obj *e, uint16_t type,
case NFTNL_OBJ_SECMARK_CTX:
snprintf(secmark->ctx, sizeof(secmark->ctx), "%s", (const char *)data);
break;
- default:
- return -1;
}
return 0;
}
@@ -98,40 +92,28 @@ nftnl_obj_secmark_parse(struct nftnl_obj *e, struct nlattr *attr)
return 0;
}
-static int nftnl_obj_secmark_snprintf_default(char *buf, size_t len,
- const struct nftnl_obj *e)
+static int nftnl_obj_secmark_snprintf(char *buf, size_t len,
+ uint32_t flags,
+ const struct nftnl_obj *e)
{
struct nftnl_obj_secmark *secmark = nftnl_obj_data(e);
return snprintf(buf, len, "context %s ", secmark->ctx);
}
-static int nftnl_obj_secmark_snprintf(char *buf, size_t len, uint32_t type,
- uint32_t flags,
- const struct nftnl_obj *e)
-{
- if (len)
- buf[0] = '\0';
-
- switch (type) {
- case NFTNL_OUTPUT_DEFAULT:
- return nftnl_obj_secmark_snprintf_default(buf, len, e);
- case NFTNL_OUTPUT_XML:
- case NFTNL_OUTPUT_JSON:
- default:
- break;
- }
- return -1;
-}
+static struct attr_policy obj_secmark_attr_policy[__NFTNL_OBJ_SECMARK_MAX] = {
+ [NFTNL_OBJ_SECMARK_CTX] = { .maxlen = NFT_SECMARK_CTX_MAXLEN },
+};
struct obj_ops obj_ops_secmark = {
.name = "secmark",
.type = NFT_OBJECT_SECMARK,
.alloc_len = sizeof(struct nftnl_obj_secmark),
- .max_attr = NFTA_SECMARK_MAX,
+ .nftnl_max_attr = __NFTNL_OBJ_SECMARK_MAX - 1,
+ .attr_policy = obj_secmark_attr_policy,
.set = nftnl_obj_secmark_set,
.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 56ebc85..65fbcf7 100644
--- a/src/obj/synproxy.c
+++ b/src/obj/synproxy.c
@@ -19,16 +19,14 @@ static int nftnl_obj_synproxy_set(struct nftnl_obj *e, uint16_t type,
switch (type) {
case NFTNL_OBJ_SYNPROXY_MSS:
- synproxy->mss = *((uint16_t *)data);
+ memcpy(&synproxy->mss, data, data_len);
break;
case NFTNL_OBJ_SYNPROXY_WSCALE:
- synproxy->wscale = *((uint8_t *)data);
+ memcpy(&synproxy->wscale, data, data_len);
break;
case NFTNL_OBJ_SYNPROXY_FLAGS:
- synproxy->flags = *((uint32_t *)data);
+ memcpy(&synproxy->flags, data, data_len);
break;
- default:
- return -1;
}
return 0;
}
@@ -117,11 +115,12 @@ static int nftnl_obj_synproxy_parse(struct nftnl_obj *e, struct nlattr *attr)
return 0;
}
-static int nftnl_obj_synproxy_snprintf_default(char *buf, size_t size,
- const struct nftnl_obj *e)
+static int nftnl_obj_synproxy_snprintf(char *buf, size_t len,
+ uint32_t flags,
+ const struct nftnl_obj *e)
{
struct nftnl_obj_synproxy *synproxy = nftnl_obj_data(e);
- int ret, offset = 0, len = size;
+ int ret, offset = 0;
if (e->flags & (1 << NFTNL_OBJ_SYNPROXY_MSS) &&
e->flags & (1 << NFTNL_OBJ_SYNPROXY_WSCALE)) {
@@ -133,29 +132,21 @@ static int nftnl_obj_synproxy_snprintf_default(char *buf, size_t size,
return offset;
}
-static int nftnl_obj_synproxy_snprintf(char *buf, size_t len, uint32_t type,
- uint32_t flags,
- const struct nftnl_obj *e)
-{
- switch (type) {
- case NFTNL_OUTPUT_DEFAULT:
- return nftnl_obj_synproxy_snprintf_default(buf, len, e);
- case NFTNL_OUTPUT_XML:
- case NFTNL_OUTPUT_JSON:
- default:
- break;
- }
- return -1;
-}
+static struct attr_policy obj_synproxy_attr_policy[__NFTNL_OBJ_SYNPROXY_MAX] = {
+ [NFTNL_OBJ_SYNPROXY_MSS] = { .maxlen = sizeof(uint16_t) },
+ [NFTNL_OBJ_SYNPROXY_WSCALE] = { .maxlen = sizeof(uint8_t) },
+ [NFTNL_OBJ_SYNPROXY_FLAGS] = { .maxlen = sizeof(uint32_t) },
+};
struct obj_ops obj_ops_synproxy = {
.name = "synproxy",
.type = NFT_OBJECT_SYNPROXY,
.alloc_len = sizeof(struct nftnl_obj_synproxy),
- .max_attr = NFTA_SYNPROXY_MAX,
+ .nftnl_max_attr = __NFTNL_OBJ_SYNPROXY_MAX - 1,
+ .attr_policy = obj_synproxy_attr_policy,
.set = nftnl_obj_synproxy_set,
.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 100aa09..ea9cb02 100644
--- a/src/obj/tunnel.c
+++ b/src/obj/tunnel.c
@@ -1,10 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* (C) 2018 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 <stdio.h>
@@ -29,55 +25,41 @@ nftnl_obj_tunnel_set(struct nftnl_obj *e, uint16_t type,
switch (type) {
case NFTNL_OBJ_TUNNEL_ID:
- memcpy(&tun->id, data, sizeof(tun->id));
+ memcpy(&tun->id, data, data_len);
break;
case NFTNL_OBJ_TUNNEL_IPV4_SRC:
- memcpy(&tun->src_v4, data, sizeof(tun->src_v4));
+ memcpy(&tun->src_v4, data, data_len);
break;
case NFTNL_OBJ_TUNNEL_IPV4_DST:
- memcpy(&tun->dst_v4, data, sizeof(tun->dst_v4));
+ memcpy(&tun->dst_v4, data, data_len);
break;
case NFTNL_OBJ_TUNNEL_IPV6_SRC:
- memcpy(&tun->src_v6, data, sizeof(struct in6_addr));
+ memcpy(&tun->src_v6, data, data_len);
break;
case NFTNL_OBJ_TUNNEL_IPV6_DST:
- memcpy(&tun->dst_v6, data, sizeof(struct in6_addr));
+ memcpy(&tun->dst_v6, data, data_len);
break;
case NFTNL_OBJ_TUNNEL_IPV6_FLOWLABEL:
- memcpy(&tun->flowlabel, data, sizeof(tun->flowlabel));
+ memcpy(&tun->flowlabel, data, data_len);
break;
case NFTNL_OBJ_TUNNEL_SPORT:
- memcpy(&tun->sport, data, sizeof(tun->sport));
+ memcpy(&tun->sport, data, data_len);
break;
case NFTNL_OBJ_TUNNEL_DPORT:
- memcpy(&tun->dport, data, sizeof(tun->dport));
+ memcpy(&tun->dport, data, data_len);
break;
case NFTNL_OBJ_TUNNEL_FLAGS:
- memcpy(&tun->tun_flags, data, sizeof(tun->tun_flags));
+ memcpy(&tun->tun_flags, data, data_len);
break;
case NFTNL_OBJ_TUNNEL_TOS:
- memcpy(&tun->tun_tos, data, sizeof(tun->tun_tos));
+ memcpy(&tun->tun_tos, data, data_len);
break;
case NFTNL_OBJ_TUNNEL_TTL:
- memcpy(&tun->tun_ttl, data, sizeof(tun->tun_ttl));
+ memcpy(&tun->tun_ttl, data, data_len);
break;
- case NFTNL_OBJ_TUNNEL_VXLAN_GBP:
- memcpy(&tun->u.tun_vxlan.gbp, data, sizeof(tun->u.tun_vxlan.gbp));
+ case NFTNL_OBJ_TUNNEL_OPTS:
+ memcpy(&tun->tun_opts, data, data_len);
break;
- case NFTNL_OBJ_TUNNEL_ERSPAN_VERSION:
- memcpy(&tun->u.tun_erspan.version, data, sizeof(tun->u.tun_erspan.version));
- break;
- case NFTNL_OBJ_TUNNEL_ERSPAN_V1_INDEX:
- memcpy(&tun->u.tun_erspan.u.v1_index, data, sizeof(tun->u.tun_erspan.u.v1_index));
- break;
- case NFTNL_OBJ_TUNNEL_ERSPAN_V2_HWID:
- memcpy(&tun->u.tun_erspan.u.v2.hwid, data, sizeof(tun->u.tun_erspan.u.v2.hwid));
- break;
- case NFTNL_OBJ_TUNNEL_ERSPAN_V2_DIR:
- memcpy(&tun->u.tun_erspan.u.v2.dir, data, sizeof(tun->u.tun_erspan.u.v2.dir));
- break;
- default:
- return -1;
}
return 0;
}
@@ -122,21 +104,9 @@ nftnl_obj_tunnel_get(const struct nftnl_obj *e, uint16_t type,
case NFTNL_OBJ_TUNNEL_TTL:
*data_len = sizeof(tun->tun_ttl);
return &tun->tun_ttl;
- case NFTNL_OBJ_TUNNEL_VXLAN_GBP:
- *data_len = sizeof(tun->u.tun_vxlan.gbp);
- return &tun->u.tun_vxlan.gbp;
- case NFTNL_OBJ_TUNNEL_ERSPAN_VERSION:
- *data_len = sizeof(tun->u.tun_erspan.version);
- return &tun->u.tun_erspan.version;
- case NFTNL_OBJ_TUNNEL_ERSPAN_V1_INDEX:
- *data_len = sizeof(tun->u.tun_erspan.u.v1_index);
- return &tun->u.tun_erspan.u.v1_index;
- case NFTNL_OBJ_TUNNEL_ERSPAN_V2_HWID:
- *data_len = sizeof(tun->u.tun_erspan.u.v2.hwid);
- return &tun->u.tun_erspan.u.v2.hwid;
- case NFTNL_OBJ_TUNNEL_ERSPAN_V2_DIR:
- *data_len = sizeof(tun->u.tun_erspan.u.v2.dir);
- return &tun->u.tun_erspan.u.v2.dir;
+ case NFTNL_OBJ_TUNNEL_OPTS:
+ *data_len = sizeof(tun->tun_opts);
+ return &tun->tun_opts;
}
return NULL;
}
@@ -177,6 +147,9 @@ static int nftnl_obj_tunnel_cb(const struct nlattr *attr, void *data)
return MNL_CB_OK;
}
+static void nftnl_tunnel_opts_build(struct nlmsghdr *nlh,
+ struct nftnl_tunnel_opts *opts);
+
static void
nftnl_obj_tunnel_build(struct nlmsghdr *nlh, const struct nftnl_obj *e)
{
@@ -218,34 +191,8 @@ nftnl_obj_tunnel_build(struct nlmsghdr *nlh, const struct nftnl_obj *e)
mnl_attr_put_u8(nlh, NFTA_TUNNEL_KEY_TTL, tun->tun_ttl);
if (e->flags & (1 << NFTNL_OBJ_TUNNEL_FLAGS))
mnl_attr_put_u32(nlh, NFTA_TUNNEL_KEY_FLAGS, htonl(tun->tun_flags));
- if (e->flags & (1 << NFTNL_OBJ_TUNNEL_VXLAN_GBP)) {
- nest = mnl_attr_nest_start(nlh, NFTA_TUNNEL_KEY_OPTS);
- mnl_attr_put_u32(nlh, NFTA_TUNNEL_KEY_VXLAN_GBP,
- htonl(tun->u.tun_vxlan.gbp));
- mnl_attr_nest_end(nlh, nest);
- }
- if (e->flags & (1 << NFTNL_OBJ_TUNNEL_ERSPAN_VERSION) &&
- (e->flags & (1 << NFTNL_OBJ_TUNNEL_ERSPAN_V1_INDEX) ||
- (e->flags & (1 << NFTNL_OBJ_TUNNEL_ERSPAN_V2_HWID) &&
- e->flags & (1u << NFTNL_OBJ_TUNNEL_ERSPAN_V2_DIR)))) {
- struct nlattr *nest_inner;
-
- nest = mnl_attr_nest_start(nlh, NFTA_TUNNEL_KEY_OPTS);
- nest_inner = mnl_attr_nest_start(nlh, NFTA_TUNNEL_KEY_OPTS_ERSPAN);
- mnl_attr_put_u32(nlh, NFTA_TUNNEL_KEY_ERSPAN_VERSION,
- htonl(tun->u.tun_erspan.version));
- if (e->flags & (1 << NFTNL_OBJ_TUNNEL_ERSPAN_V1_INDEX))
- mnl_attr_put_u32(nlh, NFTA_TUNNEL_KEY_ERSPAN_V1_INDEX,
- htonl(tun->u.tun_erspan.u.v1_index));
- if (e->flags & (1 << NFTNL_OBJ_TUNNEL_ERSPAN_V2_HWID))
- mnl_attr_put_u8(nlh, NFTA_TUNNEL_KEY_ERSPAN_V2_HWID,
- tun->u.tun_erspan.u.v2.hwid);
- if (e->flags & (1u << NFTNL_OBJ_TUNNEL_ERSPAN_V2_DIR))
- mnl_attr_put_u8(nlh, NFTA_TUNNEL_KEY_ERSPAN_V2_DIR,
- tun->u.tun_erspan.u.v2.dir);
- mnl_attr_nest_end(nlh, nest_inner);
- mnl_attr_nest_end(nlh, nest);
- }
+ if (e->flags & (1 << NFTNL_OBJ_TUNNEL_OPTS))
+ nftnl_tunnel_opts_build(nlh, tun->tun_opts);
}
static int nftnl_obj_tunnel_ip_cb(const struct nlattr *attr, void *data)
@@ -341,6 +288,150 @@ static int nftnl_obj_tunnel_parse_ip6(struct nftnl_obj *e, struct nlattr *attr,
return 0;
}
+struct nftnl_tunnel_opt {
+ struct list_head list;
+
+ enum nftnl_tunnel_type type;
+ uint32_t flags;
+
+ union {
+ struct {
+ uint32_t gbp;
+ } vxlan;
+ struct {
+ uint32_t version;
+ struct {
+ uint32_t index;
+ } v1;
+ struct {
+ uint8_t hwid;
+ uint8_t dir;
+ } v2;
+ } erspan;
+ struct {
+ uint16_t geneve_class;
+ uint8_t type;
+ uint8_t data[NFTNL_TUNNEL_GENEVE_DATA_MAXLEN];
+ uint32_t data_len;
+ } geneve;
+ };
+};
+
+struct nftnl_tunnel_opts {
+ enum nftnl_tunnel_type type;
+ uint32_t num;
+ struct list_head opts_list;
+};
+
+EXPORT_SYMBOL(nftnl_tunnel_opt_get_data);
+const void *nftnl_tunnel_opt_get_data(const struct nftnl_tunnel_opt *ne,
+ uint16_t attr, uint32_t *data_len)
+{
+ if (!(ne->flags & (1 << attr)))
+ return NULL;
+
+ switch (ne->type) {
+ case NFTNL_TUNNEL_TYPE_ERSPAN:
+ switch (attr) {
+ case NFTNL_TUNNEL_ERSPAN_VERSION:
+ *data_len = sizeof(uint32_t);
+ return &ne->erspan.version;
+ case NFTNL_TUNNEL_ERSPAN_V1_INDEX:
+ *data_len = sizeof(uint32_t);
+ return &ne->erspan.v1.index;
+ case NFTNL_TUNNEL_ERSPAN_V2_HWID:
+ *data_len = sizeof(uint8_t);
+ return &ne->erspan.v2.hwid;
+ case NFTNL_TUNNEL_ERSPAN_V2_DIR:
+ *data_len = sizeof(uint8_t);
+ return &ne->erspan.v2.dir;
+ }
+ break;
+ case NFTNL_TUNNEL_TYPE_VXLAN:
+ switch (attr) {
+ case NFTNL_TUNNEL_VXLAN_GBP:
+ *data_len = sizeof(uint32_t);
+ return &ne->vxlan.gbp;
+ }
+ break;
+ case NFTNL_TUNNEL_TYPE_GENEVE:
+ switch (attr) {
+ case NFTNL_TUNNEL_GENEVE_CLASS:
+ *data_len = sizeof(uint16_t);
+ return &ne->geneve.geneve_class;
+ case NFTNL_TUNNEL_GENEVE_TYPE:
+ *data_len = sizeof(uint8_t);
+ return &ne->geneve.type;
+ case NFTNL_TUNNEL_GENEVE_DATA:
+ *data_len = ne->geneve.data_len;
+ return &ne->geneve.data;
+ }
+ break;
+ }
+
+ errno = EOPNOTSUPP;
+ return NULL;
+}
+
+EXPORT_SYMBOL(nftnl_tunnel_opt_get);
+const void *
+nftnl_tunnel_opt_get(const struct nftnl_tunnel_opt *ne, uint16_t attr)
+{
+ uint32_t data_len;
+ return nftnl_tunnel_opt_get_data(ne, attr, &data_len);
+}
+
+EXPORT_SYMBOL(nftnl_tunnel_opt_get_u8);
+uint8_t nftnl_tunnel_opt_get_u8(const struct nftnl_tunnel_opt *ne, uint16_t attr)
+{
+ const void *ret = nftnl_tunnel_opt_get(ne, attr);
+ return ret == NULL ? 0 : *((uint8_t *)ret);
+}
+
+EXPORT_SYMBOL(nftnl_tunnel_opt_get_u16);
+uint16_t nftnl_tunnel_opt_get_u16(const struct nftnl_tunnel_opt *ne, uint16_t attr)
+{
+ const void *ret = nftnl_tunnel_opt_get(ne, attr);
+ return ret == NULL ? 0 : *((uint16_t *)ret);
+}
+
+EXPORT_SYMBOL(nftnl_tunnel_opt_get_u32);
+uint32_t nftnl_tunnel_opt_get_u32(const struct nftnl_tunnel_opt *ne, uint16_t attr)
+{
+ const void *ret = nftnl_tunnel_opt_get(ne, attr);
+ return ret == NULL ? 0 : *((uint32_t *)ret);
+}
+
+EXPORT_SYMBOL(nftnl_tunnel_opt_get_type);
+enum nftnl_tunnel_type nftnl_tunnel_opt_get_type(const struct nftnl_tunnel_opt *ne)
+{
+ return ne->type;
+}
+
+EXPORT_SYMBOL(nftnl_tunnel_opt_get_flags);
+uint32_t nftnl_tunnel_opt_get_flags(const struct nftnl_tunnel_opt *ne)
+{
+ return ne->flags;
+}
+
+EXPORT_SYMBOL(nftnl_obj_tunnel_opts_foreach);
+int nftnl_obj_tunnel_opts_foreach(const struct nftnl_obj *ne,
+ int (*cb)(struct nftnl_tunnel_opt *opt, void *data),
+ void *data)
+{
+ struct nftnl_obj_tunnel *tun = nftnl_obj_data(ne);
+ struct nftnl_tunnel_opt *cur, *tmp;
+ int ret;
+
+ list_for_each_entry_safe(cur, tmp, &tun->tun_opts->opts_list, list) {
+ ret = cb(cur, data);
+ if (ret < 0)
+ return ret;
+ }
+
+ return 0;
+}
+
static int nftnl_obj_tunnel_vxlan_cb(const struct nlattr *attr, void *data)
{
const struct nlattr **tb = data;
@@ -360,21 +451,29 @@ static int nftnl_obj_tunnel_vxlan_cb(const struct nlattr *attr, void *data)
return MNL_CB_OK;
}
+struct nftnl_tunnel_opt *nftnl_tunnel_opt_alloc(enum nftnl_tunnel_type type);
+
static int
-nftnl_obj_tunnel_parse_vxlan(struct nftnl_obj *e, struct nlattr *attr,
- struct nftnl_obj_tunnel *tun)
+nftnl_obj_tunnel_parse_vxlan(struct nftnl_tunnel_opts *opts, struct nlattr *attr)
{
struct nlattr *tb[NFTA_TUNNEL_KEY_VXLAN_MAX + 1] = {};
+ struct nftnl_tunnel_opt *opt;
if (mnl_attr_parse_nested(attr, nftnl_obj_tunnel_vxlan_cb, tb) < 0)
return -1;
+ opt = nftnl_tunnel_opt_alloc(NFTNL_TUNNEL_TYPE_VXLAN);
+ if (!opt)
+ return -1;
+
if (tb[NFTA_TUNNEL_KEY_VXLAN_GBP]) {
- tun->u.tun_vxlan.gbp =
+ opt->vxlan.gbp =
ntohl(mnl_attr_get_u32(tb[NFTA_TUNNEL_KEY_VXLAN_GBP]));
- e->flags |= (1 << NFTNL_OBJ_TUNNEL_VXLAN_GBP);
+ opt->flags |= (1 << NFTNL_TUNNEL_VXLAN_GBP);
}
+ list_add_tail(&opt->list, &opts->opts_list);
+
return 0;
}
@@ -404,50 +503,63 @@ static int nftnl_obj_tunnel_erspan_cb(const struct nlattr *attr, void *data)
}
static int
-nftnl_obj_tunnel_parse_erspan(struct nftnl_obj *e, struct nlattr *attr,
- struct nftnl_obj_tunnel *tun)
+nftnl_obj_tunnel_parse_erspan(struct nftnl_tunnel_opts *opts, struct nlattr *attr)
{
struct nlattr *tb[NFTA_TUNNEL_KEY_ERSPAN_MAX + 1] = {};
+ struct nftnl_tunnel_opt *opt;
if (mnl_attr_parse_nested(attr, nftnl_obj_tunnel_erspan_cb, tb) < 0)
return -1;
+ opt = nftnl_tunnel_opt_alloc(NFTNL_TUNNEL_TYPE_ERSPAN);
+ if (!opt)
+ return -1;
+
if (tb[NFTA_TUNNEL_KEY_ERSPAN_VERSION]) {
- tun->u.tun_erspan.version =
+ opt->erspan.version =
ntohl(mnl_attr_get_u32(tb[NFTA_TUNNEL_KEY_ERSPAN_VERSION]));
- e->flags |= (1 << NFTNL_OBJ_TUNNEL_ERSPAN_VERSION);
+ opt->flags |= (1 << NFTNL_TUNNEL_ERSPAN_VERSION);
}
if (tb[NFTA_TUNNEL_KEY_ERSPAN_V1_INDEX]) {
- tun->u.tun_erspan.u.v1_index =
+ opt->erspan.v1.index =
ntohl(mnl_attr_get_u32(tb[NFTA_TUNNEL_KEY_ERSPAN_V1_INDEX]));
- e->flags |= (1 << NFTNL_OBJ_TUNNEL_ERSPAN_V1_INDEX);
+ opt->flags |= (1 << NFTNL_TUNNEL_ERSPAN_V1_INDEX);
}
if (tb[NFTA_TUNNEL_KEY_ERSPAN_V2_HWID]) {
- tun->u.tun_erspan.u.v2.hwid =
+ opt->erspan.v2.hwid =
mnl_attr_get_u8(tb[NFTA_TUNNEL_KEY_ERSPAN_V2_HWID]);
- e->flags |= (1 << NFTNL_OBJ_TUNNEL_ERSPAN_V2_HWID);
+ opt->flags |= (1 << NFTNL_TUNNEL_ERSPAN_V2_HWID);
}
if (tb[NFTA_TUNNEL_KEY_ERSPAN_V2_DIR]) {
- tun->u.tun_erspan.u.v2.dir =
+ opt->erspan.v2.dir =
mnl_attr_get_u8(tb[NFTA_TUNNEL_KEY_ERSPAN_V2_DIR]);
- e->flags |= (1u << NFTNL_OBJ_TUNNEL_ERSPAN_V2_DIR);
+ opt->flags |= (1 << NFTNL_TUNNEL_ERSPAN_V2_DIR);
}
+ list_add_tail(&opt->list, &opts->opts_list);
+
return 0;
}
-static int nftnl_obj_tunnel_opts_cb(const struct nlattr *attr, void *data)
+static int nftnl_obj_tunnel_geneve_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_TUNNEL_KEY_OPTS_MAX) < 0)
+ if (mnl_attr_type_valid(attr, NFTA_TUNNEL_KEY_GENEVE_MAX) < 0)
return MNL_CB_OK;
switch (type) {
- case NFTA_TUNNEL_KEY_OPTS_VXLAN:
- case NFTA_TUNNEL_KEY_OPTS_ERSPAN:
- if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0)
+ case NFTA_TUNNEL_KEY_GENEVE_CLASS:
+ if (mnl_attr_validate(attr, MNL_TYPE_U16) < 0)
+ abi_breakage();
+ break;
+ case NFTA_TUNNEL_KEY_GENEVE_TYPE:
+ if (mnl_attr_validate(attr, MNL_TYPE_U8) < 0)
+ abi_breakage();
+ break;
+ case NFTA_TUNNEL_KEY_GENEVE_DATA:
+ if (mnl_attr_validate(attr, MNL_TYPE_BINARY) < 0)
abi_breakage();
break;
}
@@ -457,21 +569,89 @@ static int nftnl_obj_tunnel_opts_cb(const struct nlattr *attr, void *data)
}
static int
-nftnl_obj_tunnel_parse_opts(struct nftnl_obj *e, struct nlattr *attr,
+nftnl_obj_tunnel_parse_geneve(struct nftnl_tunnel_opts *opts, struct nlattr *attr)
+{
+ struct nlattr *tb[NFTA_TUNNEL_KEY_GENEVE_MAX + 1] = {};
+ struct nftnl_tunnel_opt *opt;
+
+ if (mnl_attr_parse_nested(attr, nftnl_obj_tunnel_geneve_cb, tb) < 0)
+ return -1;
+
+ opt = nftnl_tunnel_opt_alloc(NFTNL_TUNNEL_TYPE_GENEVE);
+ if (!opt)
+ return -1;
+
+ if (tb[NFTA_TUNNEL_KEY_GENEVE_CLASS]) {
+ opt->geneve.geneve_class =
+ ntohs(mnl_attr_get_u16(tb[NFTA_TUNNEL_KEY_GENEVE_CLASS]));
+ opt->flags |= (1 << NFTNL_TUNNEL_GENEVE_CLASS);
+ }
+
+ if (tb[NFTA_TUNNEL_KEY_GENEVE_TYPE]) {
+ opt->geneve.type =
+ mnl_attr_get_u8(tb[NFTA_TUNNEL_KEY_GENEVE_TYPE]);
+ opt->flags |= (1 << NFTNL_TUNNEL_GENEVE_TYPE);
+ }
+
+ if (tb[NFTA_TUNNEL_KEY_GENEVE_DATA]) {
+ uint32_t len = mnl_attr_get_payload_len(tb[NFTA_TUNNEL_KEY_GENEVE_DATA]);
+
+ memcpy(opt->geneve.data,
+ mnl_attr_get_payload(tb[NFTA_TUNNEL_KEY_GENEVE_DATA]),
+ len);
+ opt->geneve.data_len = len;
+ opt->flags |= (1 << NFTNL_TUNNEL_GENEVE_DATA);
+ }
+
+ list_add_tail(&opt->list, &opts->opts_list);
+
+ return 0;
+}
+
+struct nftnl_tunnel_opts *nftnl_tunnel_opts_alloc(enum nftnl_tunnel_type type);
+
+static int
+nftnl_obj_tunnel_parse_opts(struct nftnl_obj *e, struct nlattr *nest,
struct nftnl_obj_tunnel *tun)
{
- struct nlattr *tb[NFTA_TUNNEL_KEY_OPTS_MAX + 1] = {};
+ struct nlattr *attr;
+ struct nftnl_tunnel_opts *opts = NULL;
int err = 0;
- if (mnl_attr_parse_nested(attr, nftnl_obj_tunnel_opts_cb, tb) < 0)
- return -1;
+ mnl_attr_for_each_nested(attr, nest) {
+ if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0)
+ abi_breakage();
+
+ switch(mnl_attr_get_type(attr)) {
+ case NFTA_TUNNEL_KEY_OPTS_VXLAN:
+ opts = nftnl_tunnel_opts_alloc(NFTNL_TUNNEL_TYPE_VXLAN);
+ if (!opts)
+ return -1;
+
+ err = nftnl_obj_tunnel_parse_vxlan(opts, attr);
+ break;
+ case NFTA_TUNNEL_KEY_OPTS_ERSPAN:
+ opts = nftnl_tunnel_opts_alloc(NFTNL_TUNNEL_TYPE_ERSPAN);
+ if (!opts)
+ return -1;
+
+ err = nftnl_obj_tunnel_parse_erspan(opts, attr);
+ break;
+ case NFTA_TUNNEL_KEY_OPTS_GENEVE:
+ if (!opts)
+ opts = nftnl_tunnel_opts_alloc(NFTNL_TUNNEL_TYPE_GENEVE);
+
+ if (!opts)
+ return -1;
+
+ err = nftnl_obj_tunnel_parse_geneve(opts, attr);
+ break;
+ }
+ }
- if (tb[NFTA_TUNNEL_KEY_OPTS_VXLAN]) {
- err = nftnl_obj_tunnel_parse_vxlan(e, tb[NFTA_TUNNEL_KEY_OPTS_VXLAN],
- tun);
- } else if (tb[NFTA_TUNNEL_KEY_OPTS_ERSPAN]) {
- err = nftnl_obj_tunnel_parse_erspan(e, tb[NFTA_TUNNEL_KEY_OPTS_ERSPAN],
- tun);
+ if (opts) {
+ tun->tun_opts = opts;
+ e->flags |= (1 << NFTNL_OBJ_TUNNEL_OPTS);
}
return err;
@@ -530,39 +710,305 @@ nftnl_obj_tunnel_parse(struct nftnl_obj *e, struct nlattr *attr)
return 0;
}
-static int nftnl_obj_tunnel_snprintf_default(char *buf, size_t len,
- const struct nftnl_obj *e)
+static int nftnl_obj_tunnel_snprintf(char *buf, size_t len,
+ uint32_t flags, const struct nftnl_obj *e)
{
struct nftnl_obj_tunnel *tun = nftnl_obj_data(e);
return snprintf(buf, len, "id %u ", tun->id);
}
-static int nftnl_obj_tunnel_snprintf(char *buf, size_t len, uint32_t type,
- uint32_t flags, const struct nftnl_obj *e)
+EXPORT_SYMBOL(nftnl_tunnel_opts_alloc);
+struct nftnl_tunnel_opts *nftnl_tunnel_opts_alloc(enum nftnl_tunnel_type type)
+{
+ struct nftnl_tunnel_opts *opts;
+
+ switch (type) {
+ case NFTNL_TUNNEL_TYPE_VXLAN:
+ case NFTNL_TUNNEL_TYPE_ERSPAN:
+ case NFTNL_TUNNEL_TYPE_GENEVE:
+ break;
+ default:
+ errno = EOPNOTSUPP;
+ return NULL;
+ }
+
+ opts = calloc(1, sizeof(struct nftnl_tunnel_opts));
+ if (!opts)
+ return NULL;
+
+ opts->type = type;
+ INIT_LIST_HEAD(&opts->opts_list);
+
+ return opts;
+}
+
+EXPORT_SYMBOL(nftnl_tunnel_opts_add);
+int nftnl_tunnel_opts_add(struct nftnl_tunnel_opts *opts,
+ struct nftnl_tunnel_opt *opt)
+{
+ if (opt->type != opts->type) {
+ errno = EOPNOTSUPP;
+ return -1;
+ }
+
+ switch (opts->type) {
+ case NFTNL_TUNNEL_TYPE_VXLAN:
+ case NFTNL_TUNNEL_TYPE_ERSPAN:
+ if (opts->num > 0) {
+ errno = EEXIST;
+ return -1;
+ }
+ break;
+ case NFTNL_TUNNEL_TYPE_GENEVE:
+ break;
+ default:
+ errno = EOPNOTSUPP;
+ return -1;
+ }
+
+ list_add_tail(&opt->list, &opts->opts_list);
+
+ return 0;
+}
+
+EXPORT_SYMBOL(nftnl_tunnel_opts_free);
+void nftnl_tunnel_opts_free(struct nftnl_tunnel_opts *opts)
+{
+ struct nftnl_tunnel_opt *opt, *next;
+
+ list_for_each_entry_safe(opt, next, &opts->opts_list, list) {
+ switch(opts->type) {
+ case NFTNL_TUNNEL_TYPE_VXLAN:
+ case NFTNL_TUNNEL_TYPE_ERSPAN:
+ case NFTNL_TUNNEL_TYPE_GENEVE:
+ list_del(&opt->list);
+ xfree(opt);
+ break;
+ }
+ }
+}
+
+EXPORT_SYMBOL(nftnl_tunnel_opt_alloc);
+struct nftnl_tunnel_opt *nftnl_tunnel_opt_alloc(enum nftnl_tunnel_type type)
+{
+ struct nftnl_tunnel_opt *opt;
+
+ switch (type) {
+ case NFTNL_TUNNEL_TYPE_VXLAN:
+ case NFTNL_TUNNEL_TYPE_ERSPAN:
+ case NFTNL_TUNNEL_TYPE_GENEVE:
+ break;
+ default:
+ errno = EOPNOTSUPP;
+ return NULL;
+ }
+
+ opt = calloc(1, sizeof(struct nftnl_tunnel_opt));
+ if (!opt)
+ return NULL;
+
+ opt->type = type;
+
+ return opt;
+}
+
+static int nftnl_tunnel_opt_vxlan_set(struct nftnl_tunnel_opt *opt, uint16_t type,
+ const void *data, uint32_t data_len)
{
- if (len)
- buf[0] = '\0';
+ switch (type) {
+ case NFTNL_TUNNEL_VXLAN_GBP:
+ memcpy(&opt->vxlan.gbp, data, data_len);
+ break;
+ default:
+ errno = EOPNOTSUPP;
+ return -1;
+ }
+ opt->flags |= (1 << type);
+
+ return 0;
+}
+
+static int nftnl_tunnel_opt_erspan_set(struct nftnl_tunnel_opt *opt, uint16_t type,
+ const void *data, uint32_t data_len)
+{
switch (type) {
- case NFTNL_OUTPUT_DEFAULT:
- return nftnl_obj_tunnel_snprintf_default(buf, len, e);
- case NFTNL_OUTPUT_XML:
- case NFTNL_OUTPUT_JSON:
+ case NFTNL_TUNNEL_ERSPAN_VERSION:
+ memcpy(&opt->erspan.version, data, data_len);
+ break;
+ case NFTNL_TUNNEL_ERSPAN_V1_INDEX:
+ memcpy(&opt->erspan.v1.index, data, data_len);
+ break;
+ case NFTNL_TUNNEL_ERSPAN_V2_HWID:
+ memcpy(&opt->erspan.v2.hwid, data, data_len);
+ break;
+ case NFTNL_TUNNEL_ERSPAN_V2_DIR:
+ memcpy(&opt->erspan.v2.dir, data, data_len);
+ break;
default:
+ errno = EOPNOTSUPP;
+ return -1;
+ }
+
+ opt->flags |= (1 << type);
+
+ return 0;
+}
+
+static int nftnl_tunnel_opt_geneve_set(struct nftnl_tunnel_opt *opt, uint16_t type,
+ const void *data, uint32_t data_len)
+{
+ switch(type) {
+ case NFTNL_TUNNEL_GENEVE_CLASS:
+ memcpy(&opt->geneve.geneve_class, data, data_len);
break;
+ case NFTNL_TUNNEL_GENEVE_TYPE:
+ memcpy(&opt->geneve.type, data, data_len);
+ break;
+ case NFTNL_TUNNEL_GENEVE_DATA:
+ if (data_len > NFTNL_TUNNEL_GENEVE_DATA_MAXLEN) {
+ errno = EINVAL;
+ return -1;
+ }
+ memcpy(&opt->geneve.data, data, data_len);
+ opt->geneve.data_len = data_len;
+ break;
+ default:
+ errno = EOPNOTSUPP;
+ return -1;
+ }
+
+ opt->flags |= (1 << type);
+
+ return 0;
+}
+
+EXPORT_SYMBOL(nftnl_tunnel_opt_set);
+int nftnl_tunnel_opt_set(struct nftnl_tunnel_opt *opt, uint16_t type,
+ const void *data, uint32_t data_len)
+{
+ switch (opt->type) {
+ case NFTNL_TUNNEL_TYPE_VXLAN:
+ return nftnl_tunnel_opt_vxlan_set(opt, type, data, data_len);
+ case NFTNL_TUNNEL_TYPE_ERSPAN:
+ return nftnl_tunnel_opt_erspan_set(opt, type, data, data_len);
+ case NFTNL_TUNNEL_TYPE_GENEVE:
+ return nftnl_tunnel_opt_geneve_set(opt, type, data, data_len);
+ default:
+ errno = EOPNOTSUPP;
+ return -1;
+ }
+
+ return 0;
+}
+
+static void nftnl_tunnel_opt_build_vxlan(struct nlmsghdr *nlh,
+ const struct nftnl_tunnel_opt *opt)
+{
+ struct nlattr *nest_inner;
+
+ if (opt->flags & (1 << NFTNL_TUNNEL_VXLAN_GBP)) {
+ nest_inner = mnl_attr_nest_start(nlh, NFTA_TUNNEL_KEY_OPTS_VXLAN);
+ mnl_attr_put_u32(nlh, NFTA_TUNNEL_KEY_VXLAN_GBP,
+ htonl(opt->vxlan.gbp));
+ mnl_attr_nest_end(nlh, nest_inner);
+ }
+}
+
+static void nftnl_tunnel_opt_build_erspan(struct nlmsghdr *nlh,
+ const struct nftnl_tunnel_opt *opt)
+{
+ struct nlattr *nest_inner;
+
+ if (opt->flags & (1 << NFTNL_TUNNEL_ERSPAN_VERSION) &&
+ (opt->flags & (1 << NFTNL_TUNNEL_ERSPAN_V1_INDEX) ||
+ (opt->flags & (1 << NFTNL_TUNNEL_ERSPAN_V2_HWID) &&
+ opt->flags & (1 << NFTNL_TUNNEL_ERSPAN_V2_DIR)))) {
+ nest_inner = mnl_attr_nest_start(nlh, NFTA_TUNNEL_KEY_OPTS_ERSPAN);
+ mnl_attr_put_u32(nlh, NFTA_TUNNEL_KEY_ERSPAN_VERSION,
+ htonl(opt->erspan.version));
+ if (opt->flags & (1 << NFTNL_TUNNEL_ERSPAN_V1_INDEX))
+ mnl_attr_put_u32(nlh, NFTA_TUNNEL_KEY_ERSPAN_V1_INDEX,
+ htonl(opt->erspan.v1.index));
+ if (opt->flags & (1 << NFTNL_TUNNEL_ERSPAN_V2_HWID))
+ mnl_attr_put_u8(nlh, NFTA_TUNNEL_KEY_ERSPAN_V2_HWID,
+ opt->erspan.v2.hwid);
+ if (opt->flags & (1 << NFTNL_TUNNEL_ERSPAN_V2_DIR))
+ mnl_attr_put_u8(nlh, NFTA_TUNNEL_KEY_ERSPAN_V2_DIR,
+ opt->erspan.v2.dir);
+ mnl_attr_nest_end(nlh, nest_inner);
}
- return -1;
}
+static void nftnl_tunnel_opt_build_geneve(struct nlmsghdr *nlh,
+ const struct nftnl_tunnel_opt *opt)
+{
+ struct nlattr *nest_inner;
+
+ if (opt->flags & (1 << NFTNL_TUNNEL_GENEVE_CLASS) &&
+ opt->flags & (1 << NFTNL_TUNNEL_GENEVE_TYPE) &&
+ opt->flags & (1 << NFTNL_TUNNEL_GENEVE_DATA)) {
+ nest_inner = mnl_attr_nest_start(nlh, NFTA_TUNNEL_KEY_OPTS_GENEVE);
+ mnl_attr_put_u16(nlh, NFTA_TUNNEL_KEY_GENEVE_CLASS,
+ htons(opt->geneve.geneve_class));
+ mnl_attr_put_u8(nlh, NFTA_TUNNEL_KEY_GENEVE_TYPE,
+ opt->geneve.type);
+ mnl_attr_put(nlh, NFTA_TUNNEL_KEY_GENEVE_DATA,
+ opt->geneve.data_len,
+ opt->geneve.data);
+ mnl_attr_nest_end(nlh, nest_inner);
+ }
+}
+
+void nftnl_tunnel_opts_build(struct nlmsghdr *nlh,
+ struct nftnl_tunnel_opts *opts)
+{
+ const struct nftnl_tunnel_opt *opt;
+ struct nlattr *nest;
+
+ nest = mnl_attr_nest_start(nlh, NFTA_TUNNEL_KEY_OPTS);
+
+ list_for_each_entry(opt, &opts->opts_list, list) {
+ switch (opts->type) {
+ case NFTNL_TUNNEL_TYPE_VXLAN:
+ nftnl_tunnel_opt_build_vxlan(nlh, opt);
+ break;
+ case NFTNL_TUNNEL_TYPE_ERSPAN:
+ nftnl_tunnel_opt_build_erspan(nlh, opt);
+ break;
+ case NFTNL_TUNNEL_TYPE_GENEVE:
+ nftnl_tunnel_opt_build_geneve(nlh, opt);
+ break;
+ }
+ }
+ mnl_attr_nest_end(nlh, nest);
+}
+
+static struct attr_policy obj_tunnel_attr_policy[__NFTNL_OBJ_TUNNEL_MAX] = {
+ [NFTNL_OBJ_TUNNEL_ID] = { .maxlen = sizeof(uint32_t) },
+ [NFTNL_OBJ_TUNNEL_IPV4_SRC] = { .maxlen = sizeof(uint32_t) },
+ [NFTNL_OBJ_TUNNEL_IPV4_DST] = { .maxlen = sizeof(uint32_t) },
+ [NFTNL_OBJ_TUNNEL_IPV6_SRC] = { .maxlen = sizeof(struct in6_addr) },
+ [NFTNL_OBJ_TUNNEL_IPV6_DST] = { .maxlen = sizeof(struct in6_addr) },
+ [NFTNL_OBJ_TUNNEL_IPV6_FLOWLABEL] = { .maxlen = sizeof(uint32_t) },
+ [NFTNL_OBJ_TUNNEL_SPORT] = { .maxlen = sizeof(uint16_t) },
+ [NFTNL_OBJ_TUNNEL_DPORT] = { .maxlen = sizeof(uint16_t) },
+ [NFTNL_OBJ_TUNNEL_FLAGS] = { .maxlen = sizeof(uint32_t) },
+ [NFTNL_OBJ_TUNNEL_TOS] = { .maxlen = sizeof(uint8_t) },
+ [NFTNL_OBJ_TUNNEL_TTL] = { .maxlen = sizeof(uint8_t) },
+ [NFTNL_OBJ_TUNNEL_OPTS] = { .maxlen = sizeof(struct nftnl_tunnel_opts *) },
+};
+
struct obj_ops obj_ops_tunnel = {
.name = "tunnel",
.type = NFT_OBJECT_TUNNEL,
.alloc_len = sizeof(struct nftnl_obj_tunnel),
- .max_attr = NFTA_TUNNEL_KEY_MAX,
+ .nftnl_max_attr = __NFTNL_OBJ_TUNNEL_MAX - 1,
+ .attr_policy = obj_tunnel_attr_policy,
.set = nftnl_obj_tunnel_set,
.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,
};