summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/regs.h38
-rw-r--r--src/expr/ct.c82
-rw-r--r--src/expr/exthdr.c37
-rw-r--r--src/expr/fib.c45
-rw-r--r--src/expr/osf.c32
-rw-r--r--src/expr/rt.c46
-rw-r--r--src/expr/socket.c47
-rw-r--r--src/expr/xfrm.c51
-rw-r--r--src/regs.c16
9 files changed, 393 insertions, 1 deletions
diff --git a/include/regs.h b/include/regs.h
index 5312f60..dcbb0f4 100644
--- a/include/regs.h
+++ b/include/regs.h
@@ -5,6 +5,13 @@ enum nftnl_expr_type {
NFT_EXPR_UNSPEC = 0,
NFT_EXPR_PAYLOAD,
NFT_EXPR_META,
+ NFT_EXPR_CT,
+ NFT_EXPR_EXTHDR,
+ NFT_EXPR_FIB,
+ NFT_EXPR_OSF,
+ NFT_EXPR_RT,
+ NFT_EXPR_XFRM,
+ NFT_EXPR_SOCKET,
};
struct nftnl_reg {
@@ -20,6 +27,37 @@ struct nftnl_reg {
enum nft_payload_bases base;
uint32_t offset;
} payload;
+ struct {
+ enum nft_ct_keys key;
+ uint8_t dir;
+ } ct;
+ struct {
+ uint32_t offset;
+ uint32_t len;
+ uint8_t type;
+ uint32_t op;
+ uint32_t flags;
+ } exthdr;
+ struct {
+ uint32_t flags;
+ uint32_t result;
+ } fib;
+ struct {
+ uint8_t ttl;
+ uint32_t flags;
+ } osf;
+ struct {
+ enum nft_rt_keys key;
+ } rt;
+ struct {
+ enum nft_socket_keys key;
+ uint32_t level;
+ } socket;
+ struct {
+ enum nft_xfrm_keys key;
+ uint32_t spnum;
+ uint8_t dir;
+ } xfrm;
};
};
diff --git a/src/expr/ct.c b/src/expr/ct.c
index d5dfc81..f17491c 100644
--- a/src/expr/ct.c
+++ b/src/expr/ct.c
@@ -14,6 +14,7 @@
#include <stdint.h>
#include <arpa/inet.h>
#include <errno.h>
+#include <assert.h>
#include <linux/netfilter/nf_tables.h>
#include "internal.h"
@@ -148,6 +149,82 @@ nftnl_expr_ct_parse(struct nftnl_expr *e, struct nlattr *attr)
return 0;
}
+#ifndef XT_CONNLABEL_MAXBIT
+#define XT_CONNLABEL_MAXBIT 127
+#endif
+
+#ifndef NF_CT_LABELS_MAX_SIZE
+#define NF_CT_LABELS_MAX_SIZE ((XT_CONNLABEL_MAXBIT + 1) / 8)
+#endif
+
+#ifndef NF_CT_HELPER_NAME_LEN
+#define NF_CT_HELPER_NAME_LEN 16
+#endif
+
+static int
+nftnl_expr_ct_reg_len(const struct nftnl_expr *e)
+{
+ const struct nftnl_expr_ct *ct = nftnl_expr_data(e);
+
+ switch (ct->key) {
+ case NFT_CT_DIRECTION:
+ case NFT_CT_PROTOCOL:
+ case NFT_CT_L3PROTOCOL:
+ return sizeof(uint8_t);
+ case NFT_CT_ZONE:
+ case NFT_CT_LABELS:
+ return NF_CT_LABELS_MAX_SIZE;
+ case NFT_CT_HELPER:
+ return NF_CT_HELPER_NAME_LEN;
+ case NFT_CT_PROTO_SRC:
+ case NFT_CT_PROTO_DST:
+ return sizeof(uint16_t);
+ case NFT_CT_ID:
+ case NFT_CT_STATE:
+ case NFT_CT_STATUS:
+ case NFT_CT_MARK:
+ case NFT_CT_SECMARK:
+ case NFT_CT_EXPIRATION:
+ case NFT_CT_EVENTMASK:
+ case NFT_CT_SRC_IP:
+ case NFT_CT_DST_IP:
+ return sizeof(uint32_t);
+ case NFT_CT_BYTES:
+ case NFT_CT_PKTS:
+ case NFT_CT_AVGPKT:
+ return sizeof(uint64_t);
+ case NFT_CT_SRC:
+ case NFT_CT_DST:
+ case NFT_CT_SRC_IP6:
+ case NFT_CT_DST_IP6:
+ return sizeof(uint32_t) * 4;
+ default:
+ assert(0);
+ }
+
+ return sizeof(uint32_t);
+}
+
+static bool
+nftnl_expr_ct_reg_cmp(const struct nftnl_reg *reg,
+ const struct nftnl_expr *e)
+{
+ const struct nftnl_expr_ct *ct = nftnl_expr_data(e);
+
+ return reg->ct.key == ct->key &&
+ reg->ct.dir == ct->dir;
+}
+
+static void
+nftnl_expr_ct_reg_update(struct nftnl_reg *reg,
+ const struct nftnl_expr *e)
+{
+ const struct nftnl_expr_ct *ct = nftnl_expr_data(e);
+
+ reg->ct.key = ct->key;
+ reg->ct.dir = ct->dir;
+}
+
static const char *ctkey2str_array[NFT_CT_MAX + 1] = {
[NFT_CT_STATE] = "state",
[NFT_CT_DIRECTION] = "direction",
@@ -259,4 +336,9 @@ struct expr_ops expr_ops_ct = {
.parse = nftnl_expr_ct_parse,
.build = nftnl_expr_ct_build,
.snprintf = nftnl_expr_ct_snprintf,
+ .reg = {
+ .len = nftnl_expr_ct_reg_len,
+ .cmp = nftnl_expr_ct_reg_cmp,
+ .update = nftnl_expr_ct_reg_update,
+ },
};
diff --git a/src/expr/exthdr.c b/src/expr/exthdr.c
index 625dd5d..53a2a80 100644
--- a/src/expr/exthdr.c
+++ b/src/expr/exthdr.c
@@ -194,6 +194,38 @@ nftnl_expr_exthdr_parse(struct nftnl_expr *e, struct nlattr *attr)
return 0;
}
+static int
+nftnl_expr_exthdr_reg_len(const struct nftnl_expr *e)
+{
+ const struct nftnl_expr_exthdr *exthdr = nftnl_expr_data(e);
+
+ return exthdr->len;
+}
+
+static bool
+nftnl_expr_exthdr_reg_cmp(const struct nftnl_reg *reg,
+ const struct nftnl_expr *e)
+{
+ const struct nftnl_expr_exthdr *exthdr = nftnl_expr_data(e);
+
+ return reg->exthdr.offset == exthdr->offset &&
+ reg->exthdr.type == exthdr->type &&
+ reg->exthdr.op == exthdr->op &&
+ reg->exthdr.flags == exthdr->flags;
+}
+
+static void
+nftnl_expr_exthdr_reg_update(struct nftnl_reg *reg,
+ const struct nftnl_expr *e)
+{
+ const struct nftnl_expr_exthdr *exthdr = nftnl_expr_data(e);
+
+ reg->exthdr.offset = exthdr->offset;
+ reg->exthdr.type = exthdr->type;
+ reg->exthdr.op = exthdr->op;
+ reg->exthdr.flags = exthdr->flags;
+}
+
static const char *op2str(uint8_t op)
{
switch (op) {
@@ -268,4 +300,9 @@ struct expr_ops expr_ops_exthdr = {
.parse = nftnl_expr_exthdr_parse,
.build = nftnl_expr_exthdr_build,
.snprintf = nftnl_expr_exthdr_snprintf,
+ .reg = {
+ .len = nftnl_expr_exthdr_reg_len,
+ .cmp = nftnl_expr_exthdr_reg_cmp,
+ .update = nftnl_expr_exthdr_reg_update,
+ },
};
diff --git a/src/expr/fib.c b/src/expr/fib.c
index aaff52a..59b335a 100644
--- a/src/expr/fib.c
+++ b/src/expr/fib.c
@@ -14,6 +14,7 @@
#include <string.h>
#include <arpa/inet.h>
#include <errno.h>
+#include <net/if.h>
#include <linux/netfilter/nf_tables.h>
#include "internal.h"
@@ -128,6 +129,45 @@ nftnl_expr_fib_parse(struct nftnl_expr *e, struct nlattr *attr)
return ret;
}
+static int
+nftnl_expr_fib_reg_len(const struct nftnl_expr *e)
+{
+ const struct nftnl_expr_fib *fib = nftnl_expr_data(e);
+
+ switch (fib->result) {
+ case NFT_FIB_RESULT_OIF:
+ return sizeof(int);
+ case NFT_FIB_RESULT_OIFNAME:
+ return IFNAMSIZ;
+ case NFT_FIB_RESULT_ADDRTYPE:
+ return sizeof(uint32_t);
+ default:
+ assert(0);
+ break;
+ }
+ return sizeof(uint32_t);
+}
+
+static bool
+nftnl_expr_fib_reg_cmp(const struct nftnl_reg *reg,
+ const struct nftnl_expr *e)
+{
+ const struct nftnl_expr_fib *fib = nftnl_expr_data(e);
+
+ return reg->fib.result == fib->result &&
+ reg->fib.flags == fib->flags;
+}
+
+static void
+nftnl_expr_fib_reg_update(struct nftnl_reg *reg,
+ const struct nftnl_expr *e)
+{
+ const struct nftnl_expr_fib *fib = nftnl_expr_data(e);
+
+ reg->fib.result = fib->result;
+ reg->fib.flags = fib->flags;
+}
+
static const char *fib_type[NFT_FIB_RESULT_MAX + 1] = {
[NFT_FIB_RESULT_OIF] = "oif",
[NFT_FIB_RESULT_OIFNAME] = "oifname",
@@ -199,4 +239,9 @@ struct expr_ops expr_ops_fib = {
.parse = nftnl_expr_fib_parse,
.build = nftnl_expr_fib_build,
.snprintf = nftnl_expr_fib_snprintf,
+ .reg = {
+ .len = nftnl_expr_fib_reg_len,
+ .cmp = nftnl_expr_fib_reg_cmp,
+ .update = nftnl_expr_fib_reg_update,
+ },
};
diff --git a/src/expr/osf.c b/src/expr/osf.c
index 215a681..666b6b7 100644
--- a/src/expr/osf.c
+++ b/src/expr/osf.c
@@ -11,6 +11,7 @@
#include <libnftnl/rule.h>
#define OSF_GENRE_SIZE 32
+#define NFT_OSF_MAXGENRELEN 16
struct nftnl_expr_osf {
enum nft_registers dreg;
@@ -125,6 +126,32 @@ nftnl_expr_osf_parse(struct nftnl_expr *e, struct nlattr *attr)
}
static int
+nftnl_expr_osf_reg_len(const struct nftnl_expr *e)
+{
+ return NFT_OSF_MAXGENRELEN;
+}
+
+static bool
+nftnl_expr_osf_reg_cmp(const struct nftnl_reg *reg,
+ const struct nftnl_expr *e)
+{
+ const struct nftnl_expr_osf *osf = nftnl_expr_data(e);
+
+ return reg->osf.ttl == osf->ttl &&
+ reg->osf.flags == osf->flags;
+}
+
+static void
+nftnl_expr_osf_reg_update(struct nftnl_reg *reg,
+ const struct nftnl_expr *e)
+{
+ const struct nftnl_expr_osf *osf = nftnl_expr_data(e);
+
+ reg->osf.ttl = osf->ttl;
+ reg->osf.flags = osf->flags;
+}
+
+static int
nftnl_expr_osf_snprintf(char *buf, size_t len,
uint32_t flags, const struct nftnl_expr *e)
{
@@ -148,4 +175,9 @@ struct expr_ops expr_ops_osf = {
.parse = nftnl_expr_osf_parse,
.build = nftnl_expr_osf_build,
.snprintf = nftnl_expr_osf_snprintf,
+ .reg = {
+ .len = nftnl_expr_osf_reg_len,
+ .cmp = nftnl_expr_osf_reg_cmp,
+ .update = nftnl_expr_osf_reg_update,
+ },
};
diff --git a/src/expr/rt.c b/src/expr/rt.c
index 1ad9b2a..16a1aff 100644
--- a/src/expr/rt.c
+++ b/src/expr/rt.c
@@ -12,6 +12,7 @@
#include <string.h>
#include <arpa/inet.h>
#include <errno.h>
+#include <assert.h>
#include <linux/netfilter/nf_tables.h>
#include "internal.h"
@@ -112,6 +113,46 @@ nftnl_expr_rt_parse(struct nftnl_expr *e, struct nlattr *attr)
return 0;
}
+static int nftnl_expr_rt_reg_len(const struct nftnl_expr *e)
+{
+ const struct nftnl_expr_rt *rt = nftnl_expr_data(e);
+
+ switch (rt->key) {
+ case NFT_RT_CLASSID:
+ case NFT_RT_NEXTHOP4:
+ return sizeof(uint32_t);
+ case NFT_RT_NEXTHOP6:
+ return sizeof(uint32_t) * 4;
+ case NFT_RT_TCPMSS:
+ return sizeof(uint16_t);
+ case NFT_RT_XFRM:
+ return sizeof(uint8_t);
+ default:
+ assert(0);
+ break;
+ }
+
+ return sizeof(uint32_t);
+}
+
+static bool
+nftnl_expr_rt_reg_cmp(const struct nftnl_reg *reg,
+ const struct nftnl_expr *e)
+{
+ const struct nftnl_expr_rt *rt = nftnl_expr_data(e);
+
+ return reg->rt.key == rt->key;
+}
+
+static void
+nftnl_expr_rt_reg_update(struct nftnl_reg *reg,
+ const struct nftnl_expr *e)
+{
+ const struct nftnl_expr_rt *rt = nftnl_expr_data(e);
+
+ reg->rt.key = rt->key;
+}
+
static const char *rt_key2str_array[NFT_RT_MAX + 1] = {
[NFT_RT_CLASSID] = "classid",
[NFT_RT_NEXTHOP4] = "nexthop4",
@@ -163,4 +204,9 @@ struct expr_ops expr_ops_rt = {
.parse = nftnl_expr_rt_parse,
.build = nftnl_expr_rt_build,
.snprintf = nftnl_expr_rt_snprintf,
+ .reg = {
+ .len = nftnl_expr_rt_reg_len,
+ .cmp = nftnl_expr_rt_reg_cmp,
+ .update = nftnl_expr_rt_reg_update,
+ },
};
diff --git a/src/expr/socket.c b/src/expr/socket.c
index 02d86f8..edd28ca 100644
--- a/src/expr/socket.c
+++ b/src/expr/socket.c
@@ -12,6 +12,7 @@
#include <string.h>
#include <arpa/inet.h>
#include <errno.h>
+#include <assert.h>
#include <linux/netfilter/nf_tables.h>
#include "internal.h"
@@ -126,6 +127,47 @@ nftnl_expr_socket_parse(struct nftnl_expr *e, struct nlattr *attr)
return 0;
}
+static int
+nftnl_expr_socket_reg_len(const struct nftnl_expr *e)
+{
+ const struct nftnl_expr_socket *socket = nftnl_expr_data(e);
+
+ switch(socket->key) {
+ case NFT_SOCKET_TRANSPARENT:
+ case NFT_SOCKET_WILDCARD:
+ return sizeof(uint8_t);
+ case NFT_SOCKET_MARK:
+ return sizeof(uint32_t);
+ case NFT_SOCKET_CGROUPV2:
+ return sizeof(uint64_t);
+ default:
+ assert(0);
+ break;
+ }
+
+ return sizeof(uint32_t);
+}
+
+static bool
+nftnl_expr_socket_reg_cmp(const struct nftnl_reg *reg,
+ const struct nftnl_expr *e)
+{
+ const struct nftnl_expr_socket *socket = nftnl_expr_data(e);
+
+ return reg->socket.key == socket->key &&
+ reg->socket.level == socket->level;
+}
+
+static void
+nftnl_expr_socket_reg_update(struct nftnl_reg *reg,
+ const struct nftnl_expr *e)
+{
+ const struct nftnl_expr_socket *socket = nftnl_expr_data(e);
+
+ reg->socket.key = socket->key;
+ reg->socket.level = socket->level;
+}
+
static const char *socket_key2str_array[NFT_SOCKET_MAX + 1] = {
[NFT_SOCKET_TRANSPARENT] = "transparent",
[NFT_SOCKET_MARK] = "mark",
@@ -166,4 +208,9 @@ struct expr_ops expr_ops_socket = {
.parse = nftnl_expr_socket_parse,
.build = nftnl_expr_socket_build,
.snprintf = nftnl_expr_socket_snprintf,
+ .reg = {
+ .len = nftnl_expr_socket_reg_len,
+ .cmp = nftnl_expr_socket_reg_cmp,
+ .update = nftnl_expr_socket_reg_update,
+ },
};
diff --git a/src/expr/xfrm.c b/src/expr/xfrm.c
index c81d14d..7f6d7fe 100644
--- a/src/expr/xfrm.c
+++ b/src/expr/xfrm.c
@@ -10,6 +10,7 @@
#include <stdint.h>
#include <arpa/inet.h>
#include <errno.h>
+#include <assert.h>
#include <linux/netfilter/nf_tables.h>
#include <linux/xfrm.h>
@@ -141,6 +142,51 @@ nftnl_expr_xfrm_parse(struct nftnl_expr *e, struct nlattr *attr)
return 0;
}
+static int
+nftnl_expr_xfrm_reg_len(const struct nftnl_expr *e)
+{
+ const struct nftnl_expr_xfrm *xfrm = nftnl_expr_data(e);
+
+ switch (xfrm->key) {
+ case NFT_XFRM_KEY_REQID:
+ case NFT_XFRM_KEY_SPI:
+ return sizeof(uint32_t);
+ case NFT_XFRM_KEY_DADDR_IP4:
+ case NFT_XFRM_KEY_SADDR_IP4:
+ return sizeof(struct in_addr);
+ case NFT_XFRM_KEY_DADDR_IP6:
+ case NFT_XFRM_KEY_SADDR_IP6:
+ return sizeof(struct in6_addr);
+ default:
+ assert(0);
+ break;
+ }
+
+ return sizeof(struct in_addr);
+}
+
+static bool
+nftnl_expr_xfrm_reg_cmp(const struct nftnl_reg *reg,
+ const struct nftnl_expr *e)
+{
+ const struct nftnl_expr_xfrm *xfrm = nftnl_expr_data(e);
+
+ return reg->xfrm.key == xfrm->key &&
+ reg->xfrm.spnum == xfrm->spnum &&
+ reg->xfrm.dir == xfrm->dir;
+}
+
+static void
+nftnl_expr_xfrm_reg_update(struct nftnl_reg *reg,
+ const struct nftnl_expr *e)
+{
+ const struct nftnl_expr_xfrm *xfrm = nftnl_expr_data(e);
+
+ reg->xfrm.key = xfrm->key;
+ reg->xfrm.spnum = xfrm->spnum;
+ reg->xfrm.dir = xfrm->dir;
+}
+
static const char *xfrmkey2str_array[] = {
[NFT_XFRM_KEY_DADDR_IP4] = "daddr4",
[NFT_XFRM_KEY_SADDR_IP4] = "saddr4",
@@ -197,4 +243,9 @@ struct expr_ops expr_ops_xfrm = {
.parse = nftnl_expr_xfrm_parse,
.build = nftnl_expr_xfrm_build,
.snprintf = nftnl_expr_xfrm_snprintf,
+ .reg = {
+ .len = nftnl_expr_xfrm_reg_len,
+ .cmp = nftnl_expr_xfrm_reg_cmp,
+ .update = nftnl_expr_xfrm_reg_update,
+ },
};
diff --git a/src/regs.c b/src/regs.c
index daedaba..1551aa7 100644
--- a/src/regs.c
+++ b/src/regs.c
@@ -55,10 +55,24 @@ void nftnl_regs_free(const struct nftnl_regs *regs)
static enum nftnl_expr_type nftnl_expr_type(const struct nftnl_expr *expr)
{
- if (!strcmp(expr->ops->name, "meta"))
+ if (!strcmp(expr->ops->name, "ct"))
+ return NFT_EXPR_CT;
+ else if (!strcmp(expr->ops->name, "exthdr"))
+ return NFT_EXPR_EXTHDR;
+ else if (!strcmp(expr->ops->name, "fib"))
+ return NFT_EXPR_FIB;
+ else if (!strcmp(expr->ops->name, "meta"))
return NFT_EXPR_META;
+ else if (!strcmp(expr->ops->name, "osf"))
+ return NFT_EXPR_OSF;
else if (!strcmp(expr->ops->name, "payload"))
return NFT_EXPR_PAYLOAD;
+ else if (!strcmp(expr->ops->name, "rt"))
+ return NFT_EXPR_RT;
+ else if (!strcmp(expr->ops->name, "socket"))
+ return NFT_EXPR_SOCKET;
+ else if (!strcmp(expr->ops->name, "xfrm"))
+ return NFT_EXPR_XFRM;
assert(0);
return NFT_EXPR_UNSPEC;