summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPablo Neira Ayuso <pablo@netfilter.org>2013-12-27 12:48:40 +0100
committerPablo Neira Ayuso <pablo@netfilter.org>2013-12-28 23:05:36 +0100
commita54d7b05fb241dae62039d2c200e9a18941cf250 (patch)
tree468effca3721361266d79ab9960131cb2b0c7589
parent173de1e0bcc2e9d25134f52015d16b47f02e9a8a (diff)
netlink: fix dictionary feature with data mappings
This patch fixes dictionary feature, that allows you to conditionally set packet fields based on a given selector, eg. add rule ip filter input meta dnat set tcp dport map { 22 => 1.1.1.1, 23 => 2.2.2.2 } This means that traffic flowing to tcp port 22 is dnatted to address 1.1.1.1 and tcp port 23 is dnatted to address 2.2.2.2. This feature was partially broken by aae836a ("src: use libnftables") although it also needs the kernel fix ("netfilter: nf_tables: fix wrong datatype in nft_validate_data_load()"). This patch also fixes endianness issues when displaying the mark via `list table' related to list_setelem_cb() since the byteorder was left unset for the data part of a set element. meta mark set tcp dport map { telnet => 0x02000000, ssh => 0x01000000} ^ ^ Note the wrong endianness in the example above. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
-rw-r--r--src/netlink.c14
1 files changed, 13 insertions, 1 deletions
diff --git a/src/netlink.c b/src/netlink.c
index cab8cf4b..59bd8e49 100644
--- a/src/netlink.c
+++ b/src/netlink.c
@@ -157,13 +157,22 @@ static struct nft_set_elem *alloc_nft_setelem(const struct expr *expr)
nft_set_elem_attr_set(nlse, NFT_SET_ELEM_ATTR_KEY,
&nld.value, nld.len);
netlink_gen_data(expr->right, &nld);
- if (expr->right->ops->type == EXPR_VERDICT) {
+ switch (expr->right->ops->type) {
+ case EXPR_VERDICT:
nft_set_elem_attr_set_u32(nlse, NFT_SET_ELEM_ATTR_VERDICT,
expr->right->verdict);
if (expr->chain != NULL) {
nft_set_elem_attr_set(nlse, NFT_SET_ELEM_ATTR_CHAIN,
nld.chain, strlen(nld.chain));
}
+ break;
+ case EXPR_VALUE:
+ nft_set_elem_attr_set(nlse, NFT_SET_ELEM_ATTR_DATA,
+ nld.value, nld.len);
+ break;
+ default:
+ BUG("unexpected set element expression\n");
+ break;
}
}
@@ -994,6 +1003,9 @@ static int list_setelem_cb(struct nft_set_elem *nlse, void *arg)
set->datatype->type == TYPE_VERDICT ?
NFT_REG_VERDICT : NFT_REG_1);
data->dtype = set->datatype;
+ data->byteorder = set->datatype->byteorder;
+ if (data->byteorder == BYTEORDER_HOST_ENDIAN)
+ mpz_switch_byteorder(data->value, data->len / BITS_PER_BYTE);
expr = mapping_expr_alloc(&internal_location, expr, data);
}