diff options
author | Florian Westphal <fw@strlen.de> | 2013-10-22 15:03:52 +0200 |
---|---|---|
committer | Florian Westphal <fw@strlen.de> | 2014-02-18 22:31:07 +0100 |
commit | 2fcce8b0677b31a5566d4b0e2d7432e8f678aabc (patch) | |
tree | c1924e84d72d566526f22b4c663dd05141695dee /src | |
parent | 71dc2810574a373dd1969088b7484933e40f6b46 (diff) |
ct: connlabel matching support
Takes advantage of the fact that the current maximum label storage area
is 128 bits, i.e. the dynamically allocated extension area in the
kernel will always fit into a nft register.
Currently this re-uses rt_symbol_table_init() to read connlabel.conf.
This works since the format is pretty much the same.
Signed-off-by: Florian Westphal <fw@strlen.de>
Diffstat (limited to 'src')
-rw-r--r-- | src/ct.c | 72 | ||||
-rw-r--r-- | src/parser.y | 2 | ||||
-rw-r--r-- | src/scanner.l | 1 |
3 files changed, 75 insertions, 0 deletions
@@ -20,8 +20,10 @@ #include <linux/netfilter/nf_conntrack_common.h> #include <linux/netfilter/nf_conntrack_tuple_common.h> +#include <erec.h> #include <expression.h> #include <datatype.h> +#include <gmputil.h> #include <ct.h> #include <gmputil.h> #include <utils.h> @@ -91,6 +93,73 @@ static const struct datatype ct_status_type = { .sym_tbl = &ct_status_tbl, }; +static struct symbol_table *ct_label_tbl; + +#define CT_LABEL_BIT_SIZE 128 + +static void ct_label_type_print(const struct expr *expr) +{ + unsigned long bit = mpz_scan1(expr->value, 0); + const struct symbolic_constant *s; + + for (s = ct_label_tbl->symbols; s->identifier != NULL; s++) { + if (bit != s->value) + continue; + printf("%s", s->identifier); + return; + } + /* can happen when connlabel.conf is altered after rules were added */ + gmp_printf("0x%Zx", expr->value); +} + +static struct error_record *ct_label_type_parse(const struct expr *sym, + struct expr **res) +{ + const struct symbolic_constant *s; + const struct datatype *dtype; + uint8_t data[CT_LABEL_BIT_SIZE]; + mpz_t value; + + for (s = ct_label_tbl->symbols; s->identifier != NULL; s++) { + if (!strcmp(sym->identifier, s->identifier)) + break; + } + + dtype = sym->dtype; + if (s->identifier == NULL) + return error(&sym->location, "Could not parse %s", dtype->desc); + + if (s->value >= CT_LABEL_BIT_SIZE) + return error(&sym->location, "%s: out of range (%u max)", + s->identifier, s->value, CT_LABEL_BIT_SIZE); + + mpz_init2(value, dtype->size); + mpz_setbit(value, s->value); + mpz_export_data(data, value, BYTEORDER_HOST_ENDIAN, sizeof(data)); + + *res = constant_expr_alloc(&sym->location, dtype, + dtype->byteorder, sizeof(data), + data); + mpz_clear(value); + return NULL; +} + +static const struct datatype ct_label_type = { + .type = TYPE_CT_LABEL, + .name = "ct_label", + .desc = "conntrack label", + .byteorder = BYTEORDER_HOST_ENDIAN, + .size = CT_LABEL_BIT_SIZE, + .basetype = &bitmask_type, + .print = ct_label_type_print, + .parse = ct_label_type_parse, +}; + +static void __init ct_label_table_init(void) +{ + ct_label_tbl = rt_symbol_table_init("/etc/xtables/connlabel.conf"); +} + static const struct ct_template ct_templates[] = { [NFT_CT_STATE] = CT_TEMPLATE("state", &ct_state_type, BYTEORDER_HOST_ENDIAN, @@ -125,6 +194,9 @@ static const struct ct_template ct_templates[] = { [NFT_CT_PROTO_DST] = CT_TEMPLATE("proto-dst", &invalid_type, BYTEORDER_BIG_ENDIAN, 2 * BITS_PER_BYTE), + [NFT_CT_LABEL] = CT_TEMPLATE("label", &ct_label_type, + BYTEORDER_HOST_ENDIAN, + CT_LABEL_BIT_SIZE), }; static void ct_expr_print(const struct expr *expr) diff --git a/src/parser.y b/src/parser.y index 07613e21..b3acc748 100644 --- a/src/parser.y +++ b/src/parser.y @@ -314,6 +314,7 @@ static void location_update(struct location *loc, struct location *rhs, int n) %token L3PROTOCOL "l3proto" %token PROTO_SRC "proto-src" %token PROTO_DST "proto-dst" +%token LABEL "label" %token COUNTER "counter" %token PACKETS "packets" @@ -1551,6 +1552,7 @@ ct_key : STATE { $$ = NFT_CT_STATE; } | PROTOCOL { $$ = NFT_CT_PROTOCOL; } | PROTO_SRC { $$ = NFT_CT_PROTO_SRC; } | PROTO_DST { $$ = NFT_CT_PROTO_DST; } + | LABEL { $$ = NFT_CT_LABEL; } ; payload_expr : payload_raw_expr diff --git a/src/scanner.l b/src/scanner.l index e4cb3983..45c64763 100644 --- a/src/scanner.l +++ b/src/scanner.l @@ -411,6 +411,7 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr}) "l3proto" { return L3PROTOCOL; } "proto-src" { return PROTO_SRC; } "proto-dst" { return PROTO_DST; } +"label" { return LABEL; } "xml" { return XML; } "json" { return JSON; } |