summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPablo Neira Ayuso <pablo@netfilter.org>2018-06-06 18:44:55 +0200
committerPablo Neira Ayuso <pablo@netfilter.org>2018-06-06 18:44:55 +0200
commit20defe9a14dda8ca33092d8e0f92b14f6b451029 (patch)
treeb1f66c15a683c8e41122be081cfc1461562427c0
parent8a2a96237249db7816218b9cbed1457a5d51a3ad (diff)
expr: extend fwd to support address and protocol
To support forwarding through neighbour layer from ingress. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
-rw-r--r--include/libnftnl/expr.h2
-rw-r--r--include/linux/netfilter/nf_tables.h4
-rw-r--r--src/expr/fwd.c60
3 files changed, 62 insertions, 4 deletions
diff --git a/include/libnftnl/expr.h b/include/libnftnl/expr.h
index 7d222af..219104e 100644
--- a/include/libnftnl/expr.h
+++ b/include/libnftnl/expr.h
@@ -238,6 +238,8 @@ enum {
enum {
NFTNL_EXPR_FWD_SREG_DEV = NFTNL_EXPR_BASE,
+ NFTNL_EXPR_FWD_SREG_ADDR,
+ NFTNL_EXPR_FWD_NFPROTO,
};
enum {
diff --git a/include/linux/netfilter/nf_tables.h b/include/linux/netfilter/nf_tables.h
index e8f4b58..91449ef 100644
--- a/include/linux/netfilter/nf_tables.h
+++ b/include/linux/netfilter/nf_tables.h
@@ -1273,10 +1273,14 @@ enum nft_dup_attributes {
* enum nft_fwd_attributes - nf_tables fwd expression netlink attributes
*
* @NFTA_FWD_SREG_DEV: source register of output interface (NLA_U32: nft_register)
+ * @NFTA_FWD_SREG_ADDR: source register of destination address (NLA_U32: nft_register)
+ * @NFTA_FWD_NFPROTO: layer 3 family of source register address (NLA_U32: enum nfproto)
*/
enum nft_fwd_attributes {
NFTA_FWD_UNSPEC,
NFTA_FWD_SREG_DEV,
+ NFTA_FWD_SREG_ADDR,
+ NFTA_FWD_NFPROTO,
__NFTA_FWD_MAX
};
#define NFTA_FWD_MAX (__NFTA_FWD_MAX - 1)
diff --git a/src/expr/fwd.c b/src/expr/fwd.c
index 1312ea1..9021606 100644
--- a/src/expr/fwd.c
+++ b/src/expr/fwd.c
@@ -23,6 +23,8 @@
struct nftnl_expr_fwd {
enum nft_registers sreg_dev;
+ enum nft_registers sreg_addr;
+ uint32_t nfproto;
};
static int nftnl_expr_fwd_set(struct nftnl_expr *e, uint16_t type,
@@ -32,7 +34,13 @@ static int nftnl_expr_fwd_set(struct nftnl_expr *e, uint16_t type,
switch (type) {
case NFTNL_EXPR_FWD_SREG_DEV:
- fwd->sreg_dev= *((uint32_t *)data);
+ fwd->sreg_dev = *((uint32_t *)data);
+ break;
+ case NFTNL_EXPR_FWD_SREG_ADDR:
+ fwd->sreg_addr = *((uint32_t *)data);
+ break;
+ case NFTNL_EXPR_FWD_NFPROTO:
+ fwd->nfproto = *((uint32_t *)data);
break;
default:
return -1;
@@ -49,6 +57,12 @@ static const void *nftnl_expr_fwd_get(const struct nftnl_expr *e,
case NFTNL_EXPR_FWD_SREG_DEV:
*data_len = sizeof(fwd->sreg_dev);
return &fwd->sreg_dev;
+ case NFTNL_EXPR_FWD_SREG_ADDR:
+ *data_len = sizeof(fwd->sreg_addr);
+ return &fwd->sreg_addr;
+ case NFTNL_EXPR_FWD_NFPROTO:
+ *data_len = sizeof(fwd->nfproto);
+ return &fwd->nfproto;
}
return NULL;
}
@@ -63,6 +77,8 @@ static int nftnl_expr_fwd_cb(const struct nlattr *attr, void *data)
switch (type) {
case NFTA_FWD_SREG_DEV:
+ case NFTA_FWD_SREG_ADDR:
+ case NFTA_FWD_NFPROTO:
if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
abi_breakage();
break;
@@ -79,6 +95,10 @@ static void nftnl_expr_fwd_build(struct nlmsghdr *nlh,
if (e->flags & (1 << NFTNL_EXPR_FWD_SREG_DEV))
mnl_attr_put_u32(nlh, NFTA_FWD_SREG_DEV, htonl(fwd->sreg_dev));
+ if (e->flags & (1 << NFTNL_EXPR_FWD_SREG_ADDR))
+ mnl_attr_put_u32(nlh, NFTA_FWD_SREG_ADDR, htonl(fwd->sreg_addr));
+ if (e->flags & (1 << NFTNL_EXPR_FWD_NFPROTO))
+ mnl_attr_put_u32(nlh, NFTA_FWD_NFPROTO, htonl(fwd->nfproto));
}
static int nftnl_expr_fwd_parse(struct nftnl_expr *e, struct nlattr *attr)
@@ -94,6 +114,14 @@ static int nftnl_expr_fwd_parse(struct nftnl_expr *e, struct nlattr *attr)
fwd->sreg_dev = ntohl(mnl_attr_get_u32(tb[NFTA_FWD_SREG_DEV]));
e->flags |= (1 << NFTNL_EXPR_FWD_SREG_DEV);
}
+ if (tb[NFTA_FWD_SREG_ADDR]) {
+ fwd->sreg_addr = ntohl(mnl_attr_get_u32(tb[NFTA_FWD_SREG_ADDR]));
+ e->flags |= (1 << NFTNL_EXPR_FWD_SREG_ADDR);
+ }
+ if (tb[NFTA_FWD_NFPROTO]) {
+ fwd->nfproto = ntohl(mnl_attr_get_u32(tb[NFTA_FWD_NFPROTO]));
+ e->flags |= (1 << NFTNL_EXPR_FWD_NFPROTO);
+ }
return ret;
}
@@ -102,12 +130,18 @@ static int nftnl_expr_fwd_json_parse(struct nftnl_expr *e, json_t *root,
struct nftnl_parse_err *err)
{
#ifdef JSON_PARSING
- uint32_t sreg_dev;
+ uint32_t u32val;
int ret;
- ret = nftnl_jansson_parse_val(root, "sreg_dev", NFTNL_TYPE_U32, &sreg_dev, err);
+ ret = nftnl_jansson_parse_val(root, "sreg_dev", NFTNL_TYPE_U32, &u32val, err);
+ if (ret >= 0)
+ nftnl_expr_set_u32(e, NFTNL_EXPR_FWD_SREG_DEV, u32val);
+ ret = nftnl_jansson_parse_val(root, "sreg_addr", NFTNL_TYPE_U32, &u32val, err);
if (ret >= 0)
- nftnl_expr_set_u32(e, NFTNL_EXPR_FWD_SREG_DEV, sreg_dev);
+ nftnl_expr_set_u32(e, NFTNL_EXPR_FWD_SREG_ADDR, u32val);
+ ret = nftnl_jansson_parse_val(root, "nfproto", NFTNL_TYPE_U32, &u32val, err);
+ if (ret >= 0)
+ nftnl_expr_set_u32(e, NFTNL_EXPR_FWD_NFPROTO, u32val);
return 0;
#else
@@ -124,6 +158,10 @@ static int nftnl_expr_fwd_export(char *buf, size_t size,
if (e->flags & (1 << NFTNL_EXPR_FWD_SREG_DEV))
nftnl_buf_u32(&b, type, fwd->sreg_dev, "sreg_dev");
+ if (e->flags & (1 << NFTNL_EXPR_FWD_SREG_ADDR))
+ nftnl_buf_u32(&b, type, fwd->sreg_dev, "sreg_addr");
+ if (e->flags & (1 << NFTNL_EXPR_FWD_NFPROTO))
+ nftnl_buf_u32(&b, type, fwd->nfproto, "nfproto");
return nftnl_buf_done(&b);
}
@@ -140,6 +178,16 @@ static int nftnl_expr_fwd_snprintf_default(char *buf, size_t len,
fwd->sreg_dev);
SNPRINTF_BUFFER_SIZE(ret, remain, offset);
}
+ if (e->flags & (1 << NFTNL_EXPR_FWD_SREG_ADDR)) {
+ ret = snprintf(buf + offset, remain, "sreg_addr %u ",
+ fwd->sreg_addr);
+ SNPRINTF_BUFFER_SIZE(ret, remain, offset);
+ }
+ if (e->flags & (1 << NFTNL_EXPR_FWD_NFPROTO)) {
+ ret = snprintf(buf + offset, remain, "nfproto %u ",
+ fwd->nfproto);
+ SNPRINTF_BUFFER_SIZE(ret, remain, offset);
+ }
return offset;
}
@@ -168,6 +216,10 @@ static bool nftnl_expr_fwd_cmp(const struct nftnl_expr *e1,
if (e1->flags & (1 << NFTNL_EXPR_FWD_SREG_DEV))
eq &= (f1->sreg_dev == f2->sreg_dev);
+ if (e1->flags & (1 << NFTNL_EXPR_FWD_SREG_ADDR))
+ eq &= (f1->sreg_addr == f2->sreg_addr);
+ if (e1->flags & (1 << NFTNL_EXPR_FWD_NFPROTO))
+ eq &= (f1->nfproto == f2->nfproto);
return eq;
}