summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/datatype.h4
-rw-r--r--include/expression.h11
-rw-r--r--include/linux/netfilter/nf_tables.h39
-rw-r--r--include/rule.h5
-rw-r--r--include/statement.h11
-rw-r--r--src/datatype.c82
-rw-r--r--src/evaluate.c47
-rw-r--r--src/expression.c42
-rw-r--r--src/netlink.c83
-rw-r--r--src/netlink_delinearize.c255
-rw-r--r--src/netlink_linearize.c26
-rw-r--r--src/parser_bison.y105
-rw-r--r--src/rule.c23
-rw-r--r--src/scanner.l10
-rw-r--r--src/segtree.c8
-rw-r--r--src/statement.c31
-rw-r--r--tests/regression/any/ct.t26
-rw-r--r--tests/regression/any/frag.t10
-rw-r--r--tests/regression/any/meta.t43
-rw-r--r--tests/regression/arp/arp.t14
-rw-r--r--tests/regression/inet/ah.t16
-rw-r--r--tests/regression/inet/comp.t8
-rw-r--r--tests/regression/inet/dccp.t11
-rw-r--r--tests/regression/inet/esp.t8
-rw-r--r--tests/regression/inet/sctp.t16
-rw-r--r--tests/regression/inet/tcp.t30
-rw-r--r--tests/regression/inet/udp.t20
-rw-r--r--tests/regression/inet/udplite.t18
-rw-r--r--tests/regression/ip/dnat.t12
-rw-r--r--tests/regression/ip/icmp.t20
-rw-r--r--tests/regression/ip/ip.t38
-rw-r--r--tests/regression/ip/masquerade.t2
-rw-r--r--tests/regression/ip/nat.t18
-rw-r--r--tests/regression/ip/redirect.t2
-rw-r--r--tests/regression/ip/snat.t12
-rw-r--r--tests/regression/ip6/dnat.t (renamed from tests/regression/ip6/nat.t)3
-rw-r--r--tests/regression/ip6/dst.t8
-rw-r--r--tests/regression/ip6/hbh.t8
-rw-r--r--tests/regression/ip6/ip6.t12
-rw-r--r--tests/regression/ip6/masquerade.t2
-rw-r--r--tests/regression/ip6/mh.t18
-rw-r--r--tests/regression/ip6/redirect.t2
-rw-r--r--tests/regression/ip6/rt.t16
-rw-r--r--tests/regression/ip6/snat.t6
-rwxr-xr-xtests/regression/nft-test.py19
45 files changed, 845 insertions, 355 deletions
diff --git a/include/datatype.h b/include/datatype.h
index 3c3f42f3..2a6a4fca 100644
--- a/include/datatype.h
+++ b/include/datatype.h
@@ -231,4 +231,8 @@ concat_subtype_lookup(uint32_t type, unsigned int n)
return datatype_lookup(concat_subtype_id(type, n));
}
+extern void time_print(uint64_t seconds);
+extern struct error_record *time_parse(const struct location *loc,
+ const char *c, uint64_t *res);
+
#endif /* NFTABLES_DATATYPE_H */
diff --git a/include/expression.h b/include/expression.h
index 7477c3e6..010cb954 100644
--- a/include/expression.h
+++ b/include/expression.h
@@ -27,6 +27,7 @@
* @EXPR_LIST: list of expressions
* @EXPR_SET: literal set
* @EXPR_SET_REF: set reference
+ * @EXPR_SET_ELEM: set element
* @EXPR_MAPPING: a single mapping (key : value)
* @EXPR_MAP: map operation (expr map { EXPR_MAPPING, ... })
* @EXPR_UNARY: byteorder conversion, generated during evaluation
@@ -48,6 +49,7 @@ enum expr_types {
EXPR_LIST,
EXPR_SET,
EXPR_SET_REF,
+ EXPR_SET_ELEM,
EXPR_MAPPING,
EXPR_MAP,
EXPR_UNARY,
@@ -230,6 +232,13 @@ struct expr {
struct set *set;
};
struct {
+ /* EXPR_SET_ELEM */
+ struct expr *key;
+ uint64_t timeout;
+ uint64_t expiration;
+ const char *comment;
+ };
+ struct {
/* EXPR_UNARY */
struct expr *arg;
};
@@ -363,6 +372,8 @@ extern struct expr *map_expr_alloc(const struct location *loc,
extern struct expr *set_ref_expr_alloc(const struct location *loc,
struct set *set);
+extern struct expr *set_elem_expr_alloc(const struct location *loc,
+ struct expr *key);
extern void range_expr_value_low(mpz_t rop, const struct expr *expr);
extern void range_expr_value_high(mpz_t rop, const struct expr *expr);
diff --git a/include/linux/netfilter/nf_tables.h b/include/linux/netfilter/nf_tables.h
index 832bc46d..0e964439 100644
--- a/include/linux/netfilter/nf_tables.h
+++ b/include/linux/netfilter/nf_tables.h
@@ -207,12 +207,14 @@ enum nft_rule_compat_attributes {
* @NFT_SET_CONSTANT: set contents may not change while bound
* @NFT_SET_INTERVAL: set contains intervals
* @NFT_SET_MAP: set is used as a dictionary
+ * @NFT_SET_TIMEOUT: set uses timeouts
*/
enum nft_set_flags {
NFT_SET_ANONYMOUS = 0x1,
NFT_SET_CONSTANT = 0x2,
NFT_SET_INTERVAL = 0x4,
NFT_SET_MAP = 0x8,
+ NFT_SET_TIMEOUT = 0x10,
};
/**
@@ -251,6 +253,8 @@ enum nft_set_desc_attributes {
* @NFTA_SET_POLICY: selection policy (NLA_U32)
* @NFTA_SET_DESC: set description (NLA_NESTED)
* @NFTA_SET_ID: uniquely identifies a set in a transaction (NLA_U32)
+ * @NFTA_SET_TIMEOUT: default timeout value (NLA_U64)
+ * @NFTA_SET_GC_INTERVAL: garbage collection interval (NLA_U32)
*/
enum nft_set_attributes {
NFTA_SET_UNSPEC,
@@ -264,6 +268,8 @@ enum nft_set_attributes {
NFTA_SET_POLICY,
NFTA_SET_DESC,
NFTA_SET_ID,
+ NFTA_SET_TIMEOUT,
+ NFTA_SET_GC_INTERVAL,
__NFTA_SET_MAX
};
#define NFTA_SET_MAX (__NFTA_SET_MAX - 1)
@@ -283,12 +289,18 @@ enum nft_set_elem_flags {
* @NFTA_SET_ELEM_KEY: key value (NLA_NESTED: nft_data)
* @NFTA_SET_ELEM_DATA: data value of mapping (NLA_NESTED: nft_data_attributes)
* @NFTA_SET_ELEM_FLAGS: bitmask of nft_set_elem_flags (NLA_U32)
+ * @NFTA_SET_ELEM_TIMEOUT: timeout value (NLA_U64)
+ * @NFTA_SET_ELEM_EXPIRATION: expiration time (NLA_U64)
+ * @NFTA_SET_ELEM_USERDATA: user data (NLA_BINARY)
*/
enum nft_set_elem_attributes {
NFTA_SET_ELEM_UNSPEC,
NFTA_SET_ELEM_KEY,
NFTA_SET_ELEM_DATA,
NFTA_SET_ELEM_FLAGS,
+ NFTA_SET_ELEM_TIMEOUT,
+ NFTA_SET_ELEM_EXPIRATION,
+ NFTA_SET_ELEM_USERDATA,
__NFTA_SET_ELEM_MAX
};
#define NFTA_SET_ELEM_MAX (__NFTA_SET_ELEM_MAX - 1)
@@ -504,6 +516,33 @@ enum nft_lookup_attributes {
};
#define NFTA_LOOKUP_MAX (__NFTA_LOOKUP_MAX - 1)
+enum nft_dynset_ops {
+ NFT_DYNSET_OP_ADD,
+ NFT_DYNSET_OP_UPDATE,
+};
+
+/**
+ * enum nft_dynset_attributes - dynset expression attributes
+ *
+ * @NFTA_DYNSET_SET_NAME: name of set the to add data to (NLA_STRING)
+ * @NFTA_DYNSET_SET_ID: uniquely identifier of the set in the transaction (NLA_U32)
+ * @NFTA_DYNSET_OP: operation (NLA_U32)
+ * @NFTA_DYNSET_SREG_KEY: source register of the key (NLA_U32)
+ * @NFTA_DYNSET_SREG_DATA: source register of the data (NLA_U32)
+ * @NFTA_DYNSET_TIMEOUT: timeout value for the new element (NLA_U64)
+ */
+enum nft_dynset_attributes {
+ NFTA_DYNSET_UNSPEC,
+ NFTA_DYNSET_SET_NAME,
+ NFTA_DYNSET_SET_ID,
+ NFTA_DYNSET_OP,
+ NFTA_DYNSET_SREG_KEY,
+ NFTA_DYNSET_SREG_DATA,
+ NFTA_DYNSET_TIMEOUT,
+ __NFTA_DYNSET_MAX,
+};
+#define NFTA_DYNSET_MAX (__NFTA_DYNSET_MAX - 1)
+
/**
* enum nft_payload_bases - nf_tables payload expression offset bases
*
diff --git a/include/rule.h b/include/rule.h
index 97959f7b..5d445993 100644
--- a/include/rule.h
+++ b/include/rule.h
@@ -173,6 +173,7 @@ enum set_flags {
SET_F_CONSTANT = 0x2,
SET_F_INTERVAL = 0x4,
SET_F_MAP = 0x8,
+ SET_F_TIMEOUT = 0x10,
};
/**
@@ -183,6 +184,8 @@ enum set_flags {
* @location: location the set was defined/declared at
* @refcnt: reference count
* @flags: bitmask of set flags
+ * @gc_int: garbage collection interval
+ * @timeout: default timeout value
* @keytype: key data type
* @keylen: key length
* @datatype: mapping data type
@@ -197,6 +200,8 @@ struct set {
struct location location;
unsigned int refcnt;
uint32_t flags;
+ uint32_t gc_int;
+ uint64_t timeout;
const struct datatype *keytype;
unsigned int keylen;
const struct datatype *datatype;
diff --git a/include/statement.h b/include/statement.h
index d1431215..48e61307 100644
--- a/include/statement.h
+++ b/include/statement.h
@@ -104,6 +104,14 @@ extern struct stmt *ct_stmt_alloc(const struct location *loc,
enum nft_ct_keys key,
struct expr *expr);
+struct set_stmt {
+ struct expr *set;
+ struct expr *key;
+ enum nft_dynset_ops op;
+};
+
+extern struct stmt *set_stmt_alloc(const struct location *loc);
+
/**
* enum stmt_types - statement types
*
@@ -120,6 +128,7 @@ extern struct stmt *ct_stmt_alloc(const struct location *loc,
* @STMT_REDIR: redirect statement
* @STMT_QUEUE: QUEUE statement
* @STMT_CT: conntrack statement
+ * @STMT_SET: set statement
*/
enum stmt_types {
STMT_INVALID,
@@ -135,6 +144,7 @@ enum stmt_types {
STMT_REDIR,
STMT_QUEUE,
STMT_CT,
+ STMT_SET,
};
/**
@@ -184,6 +194,7 @@ struct stmt {
struct redir_stmt redir;
struct queue_stmt queue;
struct ct_stmt ct;
+ struct set_stmt set;
};
};
diff --git a/src/datatype.c b/src/datatype.c
index c93f76a3..f93337b1 100644
--- a/src/datatype.c
+++ b/src/datatype.c
@@ -760,11 +760,9 @@ const struct datatype icmpx_code_type = {
.sym_tbl = &icmpx_code_tbl,
};
-static void time_type_print(const struct expr *expr)
+void time_print(uint64_t seconds)
{
- uint64_t days, hours, minutes, seconds;
-
- seconds = mpz_get_uint64(expr->value);
+ uint64_t days, hours, minutes;
days = seconds / 86400;
seconds %= 86400;
@@ -775,8 +773,6 @@ static void time_type_print(const struct expr *expr)
minutes = seconds / 60;
seconds %= 60;
- printf("\"");
-
if (days > 0)
printf("%"PRIu64"d", days);
if (hours > 0)
@@ -785,8 +781,6 @@ static void time_type_print(const struct expr *expr)
printf("%"PRIu64"m", minutes);
if (seconds > 0)
printf("%"PRIu64"s", seconds);
-
- printf("\"");
}
enum {
@@ -805,8 +799,8 @@ static uint32_t str2int(char *tmp, const char *c, int k)
return atoi(tmp);
}
-static struct error_record *time_type_parse(const struct expr *sym,
- struct expr **res)
+struct error_record *time_parse(const struct location *loc, const char *str,
+ uint64_t *res)
{
int i, len;
unsigned int k = 0;
@@ -815,76 +809,82 @@ static struct error_record *time_type_parse(const struct expr *sym,
uint64_t d = 0, h = 0, m = 0, s = 0;
uint32_t mask = 0;
- c = sym->identifier;
+ c = str;
len = strlen(c);
for (i = 0; i < len; i++, c++) {
switch (*c) {
case 'd':
- if (mask & DAY) {
- return error(&sym->location,
+ if (mask & DAY)
+ return error(loc,
"Day has been specified twice");
- }
+
d = str2int(tmp, c, k);
k = 0;
mask |= DAY;
break;
case 'h':
- if (mask & HOUR) {
- return error(&sym->location,
+ if (mask & HOUR)
+ return error(loc,
"Hour has been specified twice");
- }
+
h = str2int(tmp, c, k);
k = 0;
- if (h > 23) {
- return error(&sym->location,
- "Hour needs to be 0-23");
- }
mask |= HOUR;
break;
case 'm':
- if (mask & MIN) {
- return error(&sym->location,
+ if (mask & MIN)
+ return error(loc,
"Minute has been specified twice");
- }
+
m = str2int(tmp, c, k);
k = 0;
- if (m > 59) {
- return error(&sym->location,
- "Minute needs to be 0-59");
- }
mask |= MIN;
break;
case 's':
- if (mask & SECS) {
- return error(&sym->location,
+ if (mask & SECS)
+ return error(loc,
"Second has been specified twice");
- }
+
s = str2int(tmp, c, k);
k = 0;
- if (s > 59) {
- return error(&sym->location,
- "second needs to be 0-59");
- }
mask |= SECS;
break;
default:
if (!isdigit(*c))
- return error(&sym->location, "wrong format");
+ return error(loc, "wrong time format");
- if (k++ >= array_size(tmp)) {
- return error(&sym->location,
- "value too large");
- }
+ if (k++ >= array_size(tmp))
+ return error(loc, "value too large");
break;
}
}
/* default to seconds if no unit was specified */
if (!mask)
- s = atoi(sym->identifier);
+ s = atoi(str);
else
s = 24*60*60*d+60*60*h+60*m+s;
+ *res = s;
+ return NULL;
+}
+
+
+static void time_type_print(const struct expr *expr)
+{
+ time_print(mpz_get_uint64(expr->value));
+}
+
+static struct error_record *time_type_parse(const struct expr *sym,
+ struct expr **res)
+{
+ struct error_record *erec;
+ uint64_t s;
+
+ erec = time_parse(&sym->location, sym->identifier, &s);
+ if (erec != NULL)
+ return erec;
+
if (s > UINT32_MAX)
return error(&sym->location, "value too large");
diff --git a/src/evaluate.c b/src/evaluate.c
index 7ecb7939..e260a803 100644
--- a/src/evaluate.c
+++ b/src/evaluate.c
@@ -614,7 +614,7 @@ static int expr_evaluate_concat(struct eval_ctx *ctx, struct expr **expr)
struct expr *i, *next;
list_for_each_entry_safe(i, next, &(*expr)->expressions, list) {
- if (dtype && off == 0)
+ if (expr_is_constant(*expr) && dtype && off == 0)
return expr_binary_error(ctx->msgs, i, *expr,
"unexpected concat component, "
"expecting %s",
@@ -675,6 +675,19 @@ static int expr_evaluate_list(struct eval_ctx *ctx, struct expr **expr)
return 0;
}
+static int expr_evaluate_set_elem(struct eval_ctx *ctx, struct expr **expr)
+{
+ struct expr *elem = *expr;
+
+ if (expr_evaluate(ctx, &elem->key) < 0)
+ return -1;
+
+ elem->dtype = elem->key->dtype;
+ elem->len = elem->key->len;
+ elem->flags = elem->key->flags;
+ return 0;
+}
+
static int expr_evaluate_set(struct eval_ctx *ctx, struct expr **expr)
{
struct expr *set = *expr, *i, *next;
@@ -1100,6 +1113,8 @@ static int expr_evaluate(struct eval_ctx *ctx, struct expr **expr)
return expr_evaluate_list(ctx, expr);
case EXPR_SET:
return expr_evaluate_set(ctx, expr);
+ case EXPR_SET_ELEM:
+ return expr_evaluate_set_elem(ctx, expr);
case EXPR_MAP:
return expr_evaluate_map(ctx, expr);
case EXPR_MAPPING:
@@ -1646,6 +1661,30 @@ static int stmt_evaluate_log(struct eval_ctx *ctx, struct stmt *stmt)
return 0;
}
+static int stmt_evaluate_set(struct eval_ctx *ctx, struct stmt *stmt)
+{
+ expr_set_context(&ctx->ectx, NULL, 0);
+ if (expr_evaluate(ctx, &stmt->set.set) < 0)
+ return -1;
+ if (stmt->set.set->ops->type != EXPR_SET_REF)
+ return expr_error(ctx->msgs, stmt->set.set,
+ "Expression does not refer to a set");
+
+ if (stmt_evaluate_arg(ctx, stmt,
+ stmt->set.set->set->keytype,
+ stmt->set.set->set->keylen,
+ &stmt->set.key) < 0)
+ return -1;
+ if (expr_is_constant(stmt->set.key))
+ return expr_error(ctx->msgs, stmt->set.key,
+ "Key expression can not be constant");
+ if (stmt->set.key->comment != NULL)
+ return expr_error(ctx->msgs, stmt->set.key,
+ "Key expression comments are not supported");
+
+ return 0;
+}
+
int stmt_evaluate(struct eval_ctx *ctx, struct stmt *stmt)
{
#ifdef DEBUG
@@ -1680,6 +1719,8 @@ int stmt_evaluate(struct eval_ctx *ctx, struct stmt *stmt)
return stmt_evaluate_redir(ctx, stmt);
case STMT_QUEUE:
return stmt_evaluate_queue(ctx, stmt);
+ case STMT_SET:
+ return stmt_evaluate_set(ctx, stmt);
default:
BUG("unknown statement type %s\n", stmt->ops->name);
}
@@ -1722,6 +1763,10 @@ static int set_evaluate(struct eval_ctx *ctx, struct set *set)
return -1;
}
+ /* Default timeout value implies timeout support */
+ if (set->timeout)
+ set->flags |= SET_F_TIMEOUT;
+
if (!(set->flags & SET_F_MAP))
return 0;
diff --git a/src/expression.c b/src/expression.c
index 5b848da7..3edc5501 100644
--- a/src/expression.c
+++ b/src/expression.c
@@ -886,6 +886,44 @@ struct expr *set_ref_expr_alloc(const struct location *loc, struct set *set)
return expr;
}
+static void set_elem_expr_print(const struct expr *expr)
+{
+ expr_print(expr->key);
+ if (expr->timeout) {
+ printf(" timeout ");
+ time_print(expr->timeout / 1000);
+ }
+ if (expr->expiration) {
+ printf(" expires ");
+ time_print(expr->expiration / 1000);
+ }
+ if (expr->comment)
+ printf(" comment \"%s\"", expr->comment);
+}
+
+static void set_elem_expr_destroy(struct expr *expr)
+{
+ xfree(expr->comment);
+ expr_free(expr->key);
+}
+
+static const struct expr_ops set_elem_expr_ops = {
+ .type = EXPR_SET_ELEM,
+ .name = "set element",
+ .print = set_elem_expr_print,
+ .destroy = set_elem_expr_destroy,
+};
+
+struct expr *set_elem_expr_alloc(const struct location *loc, struct expr *key)
+{
+ struct expr *expr;
+
+ expr = expr_alloc(loc, &set_elem_expr_ops, key->dtype,
+ key->byteorder, key->len);
+ expr->key = key;
+ return expr;
+}
+
void range_expr_value_low(mpz_t rop, const struct expr *expr)
{
switch (expr->ops->type) {
@@ -897,6 +935,8 @@ void range_expr_value_low(mpz_t rop, const struct expr *expr)
return range_expr_value_low(rop, expr->left);
case EXPR_MAPPING:
return range_expr_value_low(rop, expr->left);
+ case EXPR_SET_ELEM:
+ return range_expr_value_low(rop, expr->key);
default:
BUG("invalid range expression type %s\n", expr->ops->name);
}
@@ -919,6 +959,8 @@ void range_expr_value_high(mpz_t rop, const struct expr *expr)
return range_expr_value_high(rop, expr->right);
case EXPR_MAPPING:
return range_expr_value_high(rop, expr->left);
+ case EXPR_SET_ELEM:
+ return range_expr_value_high(rop, expr->key);
default:
BUG("invalid range expression type %s\n", expr->ops->name);
}
diff --git a/src/netlink.c b/src/netlink.c
index 343d8bea..d31387f8 100644
--- a/src/netlink.c
+++ b/src/netlink.c
@@ -205,6 +205,7 @@ struct nft_set *alloc_nft_set(const struct handle *h)
static struct nft_set_elem *alloc_nft_setelem(const struct expr *expr)
{
+ const struct expr *elem, *key, *data;
struct nft_set_elem *nlse;
struct nft_data_linearize nld;
@@ -212,24 +213,34 @@ static struct nft_set_elem *alloc_nft_setelem(const struct expr *expr)
if (nlse == NULL)
memory_allocation_error();
- if (expr->ops->type == EXPR_VALUE ||
- expr->flags & EXPR_F_INTERVAL_END) {
- netlink_gen_data(expr, &nld);
- nft_set_elem_attr_set(nlse, NFT_SET_ELEM_ATTR_KEY,
- &nld.value, nld.len);
+ data = NULL;
+ if (expr->ops->type == EXPR_MAPPING) {
+ elem = expr->left;
+ if (!(expr->flags & EXPR_F_INTERVAL_END))
+ data = expr->right;
} else {
- assert(expr->ops->type == EXPR_MAPPING);
- netlink_gen_data(expr->left, &nld);
- nft_set_elem_attr_set(nlse, NFT_SET_ELEM_ATTR_KEY,
- &nld.value, nld.len);
- netlink_gen_data(expr->right, &nld);
- switch (expr->right->ops->type) {
+ elem = expr;
+ }
+ key = elem->key;
+
+ netlink_gen_data(key, &nld);
+ nft_set_elem_attr_set(nlse, NFT_SET_ELEM_ATTR_KEY, &nld.value, nld.len);
+ if (elem->timeout)
+ nft_set_elem_attr_set_u64(nlse, NFT_SET_ELEM_ATTR_TIMEOUT,
+ elem->timeout);
+ if (elem->comment)
+ nft_set_elem_attr_set(nlse, NFT_SET_ELEM_ATTR_USERDATA,
+ elem->comment, strlen(elem->comment) + 1);
+
+ if (data != NULL) {
+ netlink_gen_data(data, &nld);
+ switch (data->ops->type) {
case EXPR_VERDICT:
nft_set_elem_attr_set_u32(nlse, NFT_SET_ELEM_ATTR_VERDICT,
- expr->right->verdict);
- if (expr->chain != NULL)
+ data->verdict);
+ if (data->chain != NULL)
nft_set_elem_attr_set(nlse, NFT_SET_ELEM_ATTR_CHAIN,
- nld.chain, strlen(nld.chain));
+ nld.chain, strlen(nld.chain));
break;
case EXPR_VALUE:
nft_set_elem_attr_set(nlse, NFT_SET_ELEM_ATTR_DATA,
@@ -1063,6 +1074,11 @@ static struct set *netlink_delinearize_set(struct netlink_ctx *ctx,
set->datalen = data_len * BITS_PER_BYTE;
}
+ if (nft_set_attr_is_set(nls, NFT_SET_ATTR_TIMEOUT))
+ set->timeout = nft_set_attr_get_u64(nls, NFT_SET_ATTR_TIMEOUT);
+ if (nft_set_attr_is_set(nls, NFT_SET_ATTR_GC_INTERVAL))
+ set->gc_int = nft_set_attr_get_u32(nls, NFT_SET_ATTR_GC_INTERVAL);
+
if (nft_set_attr_is_set(nls, NFT_SET_ATTR_POLICY))
set->policy = nft_set_attr_get_u32(nls, NFT_SET_ATTR_POLICY);
@@ -1126,6 +1142,11 @@ static int netlink_add_set_batch(struct netlink_ctx *ctx,
nft_set_attr_set_u32(nls, NFT_SET_ATTR_DATA_LEN,
set->datalen / BITS_PER_BYTE);
}
+ if (set->timeout)
+ nft_set_attr_set_u64(nls, NFT_SET_ATTR_TIMEOUT, set->timeout);
+ if (set->gc_int)
+ nft_set_attr_set_u32(nls, NFT_SET_ATTR_GC_INTERVAL, set->gc_int);
+
set->handle.set_id = ++set_id;
nft_set_attr_set_u32(nls, NFT_SET_ATTR_ID, set->handle.set_id);
@@ -1368,7 +1389,7 @@ static int netlink_delinearize_setelem(struct nft_set_elem *nlse,
struct set *set)
{
struct nft_data_delinearize nld;
- struct expr *expr, *data;
+ struct expr *expr, *key, *data;
uint32_t flags = 0;
nld.value =
@@ -1376,17 +1397,31 @@ static int netlink_delinearize_setelem(struct nft_set_elem *nlse,
if (nft_set_elem_attr_is_set(nlse, NFT_SET_ELEM_ATTR_FLAGS))
flags = nft_set_elem_attr_get_u32(nlse, NFT_SET_ELEM_ATTR_FLAGS);
- expr = netlink_alloc_value(&netlink_location, &nld);
- expr->dtype = set->keytype;
- expr->byteorder = set->keytype->byteorder;
+ key = netlink_alloc_value(&netlink_location, &nld);
+ key->dtype = set->keytype;
+ key->byteorder = set->keytype->byteorder;
if (!(set->flags & SET_F_INTERVAL) &&
- expr->byteorder == BYTEORDER_HOST_ENDIAN)
- mpz_switch_byteorder(expr->value, expr->len / BITS_PER_BYTE);
-
- if (expr->dtype->basetype != NULL &&
- expr->dtype->basetype->type == TYPE_BITMASK)
- expr = bitmask_expr_to_binops(expr);
+ key->byteorder == BYTEORDER_HOST_ENDIAN)
+ mpz_switch_byteorder(key->value, key->len / BITS_PER_BYTE);
+
+ if (key->dtype->basetype != NULL &&
+ key->dtype->basetype->type == TYPE_BITMASK)
+ key = bitmask_expr_to_binops(key);
+
+ expr = set_elem_expr_alloc(&netlink_location, key);
+ if (nft_set_elem_attr_is_set(nlse, NFT_SET_ELEM_ATTR_TIMEOUT))
+ expr->timeout = nft_set_elem_attr_get_u64(nlse, NFT_SET_ELEM_ATTR_TIMEOUT);
+ if (nft_set_elem_attr_is_set(nlse, NFT_SET_ELEM_ATTR_EXPIRATION))
+ expr->expiration = nft_set_elem_attr_get_u64(nlse, NFT_SET_ELEM_ATTR_EXPIRATION);
+ if (nft_set_elem_attr_is_set(nlse, NFT_SET_ELEM_ATTR_USERDATA)) {
+ const void *data;
+ uint32_t len;
+
+ data = nft_set_elem_attr_get(nlse, NFT_SET_ELEM_ATTR_USERDATA, &len);
+ expr->comment = xmalloc(len);
+ memcpy((char *)expr->comment, data, len);
+ }
if (flags & NFT_SET_ELEM_INTERVAL_END) {
expr->flags |= EXPR_F_INTERVAL_END;
diff --git a/src/netlink_delinearize.c b/src/netlink_delinearize.c
index b23d5875..0645ea8b 100644
--- a/src/netlink_delinearize.c
+++ b/src/netlink_delinearize.c
@@ -692,6 +692,40 @@ static void netlink_parse_queue(struct netlink_parse_ctx *ctx,
list_add_tail(&stmt->list, &ctx->rule->stmts);
}
+static void netlink_parse_dynset(struct netlink_parse_ctx *ctx,
+ const struct location *loc,
+ const struct nft_rule_expr *nle)
+{
+ struct expr *expr;
+ struct stmt *stmt;
+ struct set *set;
+ enum nft_registers sreg;
+ const char *name;
+
+ name = nft_rule_expr_get_str(nle, NFT_EXPR_DYNSET_SET_NAME);
+ set = set_lookup(ctx->table, name);
+ if (set == NULL)
+ return netlink_error(ctx, loc,
+ "Unknown set '%s' in dynset statement",
+ name);
+
+ sreg = netlink_parse_register(nle, NFT_EXPR_DYNSET_SREG_KEY);
+ expr = netlink_get_register(ctx, loc, sreg);
+ if (expr == NULL)
+ return netlink_error(ctx, loc,
+ "Dynset statement has no key expression");
+
+ expr = set_elem_expr_alloc(&expr->location, expr);
+ expr->timeout = nft_rule_expr_get_u64(nle, NFT_EXPR_DYNSET_TIMEOUT);
+
+ stmt = set_stmt_alloc(loc);
+ stmt->set.set = set_ref_expr_alloc(loc, set);
+ stmt->set.op = nft_rule_expr_get_u32(nle, NFT_EXPR_DYNSET_OP);
+ stmt->set.key = expr;
+
+ list_add_tail(&stmt->list, &ctx->rule->stmts);
+}
+
static const struct {
const char *name;
void (*parse)(struct netlink_parse_ctx *ctx,
@@ -715,6 +749,7 @@ static const struct {
{ .name = "masq", .parse = netlink_parse_masq },
{ .name = "redir", .parse = netlink_parse_redir },
{ .name = "queue", .parse = netlink_parse_queue },
+ { .name = "dynset", .parse = netlink_parse_dynset },
};
static int netlink_parse_expr(struct nft_rule_expr *nle, void *arg)
@@ -743,6 +778,7 @@ struct rule_pp_ctx {
struct proto_ctx pctx;
enum proto_bases pbase;
struct stmt *pdep;
+ struct stmt *stmt;
};
/*
@@ -791,48 +827,57 @@ static void integer_type_postprocess(struct expr *expr)
}
}
-static void payload_match_postprocess(struct rule_pp_ctx *ctx,
- struct stmt *stmt, struct expr *expr)
+static void payload_match_expand(struct rule_pp_ctx *ctx, struct expr *expr)
{
struct expr *left = expr->left, *right = expr->right, *tmp;
struct list_head list = LIST_HEAD_INIT(list);
struct stmt *nstmt;
struct expr *nexpr;
+ payload_expr_expand(&list, left, &ctx->pctx);
+ list_for_each_entry(left, &list, list) {
+ tmp = constant_expr_splice(right, left->len);
+ expr_set_type(tmp, left->dtype, left->byteorder);
+ if (tmp->byteorder == BYTEORDER_HOST_ENDIAN)
+ mpz_switch_byteorder(tmp->value, tmp->len / BITS_PER_BYTE);
+
+ nexpr = relational_expr_alloc(&expr->location, expr->op,
+ left, tmp);
+ if (expr->op == OP_EQ)
+ left->ops->pctx_update(&ctx->pctx, nexpr);
+
+ nstmt = expr_stmt_alloc(&ctx->stmt->location, nexpr);
+ list_add_tail(&nstmt->list, &ctx->stmt->list);
+
+ /* Remember the first payload protocol expression to
+ * kill it later on if made redundant by a higher layer
+ * payload expression.
+ */
+ if (ctx->pbase == PROTO_BASE_INVALID &&
+ left->flags & EXPR_F_PROTOCOL)
+ payload_dependency_store(ctx, nstmt,
+ left->payload.base);
+ else
+ payload_dependency_kill(ctx, nexpr->left);
+ }
+ list_del(&ctx->stmt->list);
+ stmt_free(ctx->stmt);
+ ctx->stmt = NULL;
+}
+
+static void payload_match_postprocess(struct rule_pp_ctx *ctx,
+ struct expr *expr)
+{
switch (expr->op) {
case OP_EQ:
case OP_NEQ:
- payload_expr_expand(&list, left, &ctx->pctx);
- list_for_each_entry(left, &list, list) {
- tmp = constant_expr_splice(right, left->len);
- expr_set_type(tmp, left->dtype, left->byteorder);
- if (tmp->byteorder == BYTEORDER_HOST_ENDIAN)
- mpz_switch_byteorder(tmp->value, tmp->len / BITS_PER_BYTE);
-
- nexpr = relational_expr_alloc(&expr->location, expr->op,
- left, tmp);
- if (expr->op == OP_EQ)
- left->ops->pctx_update(&ctx->pctx, nexpr);
-
- nstmt = expr_stmt_alloc(&stmt->location, nexpr);
- list_add_tail(&nstmt->list, &stmt->list);
-
- /* Remember the first payload protocol expression to
- * kill it later on if made redundant by a higher layer
- * payload expression.
- */
- if (ctx->pbase == PROTO_BASE_INVALID &&
- left->flags & EXPR_F_PROTOCOL)
- payload_dependency_store(ctx, nstmt,
- left->payload.base);
- else
- payload_dependency_kill(ctx, nexpr->left);
+ if (expr->right->ops->type == EXPR_VALUE) {
+ payload_match_expand(ctx, expr);
+ break;
}
- list_del(&stmt->list);
- stmt_free(stmt);
- break;
+ /* Fall through */
default:
- payload_expr_complete(left, &ctx->pctx);
+ payload_expr_complete(expr->left, &ctx->pctx);
expr_set_type(expr->right, expr->left->dtype,
expr->left->byteorder);
payload_dependency_kill(ctx, expr->left);
@@ -841,7 +886,6 @@ static void payload_match_postprocess(struct rule_pp_ctx *ctx,
}
static void meta_match_postprocess(struct rule_pp_ctx *ctx,
- struct stmt *stmt,
const struct expr *expr)
{
struct expr *left = expr->left;
@@ -852,7 +896,8 @@ static void meta_match_postprocess(struct rule_pp_ctx *ctx,
if (ctx->pbase == PROTO_BASE_INVALID &&
left->flags & EXPR_F_PROTOCOL)
- payload_dependency_store(ctx, stmt, left->meta.base);
+ payload_dependency_store(ctx, ctx->stmt,
+ left->meta.base);
break;
case OP_LOOKUP:
expr_set_type(expr->right, expr->left->dtype,
@@ -936,8 +981,7 @@ static void relational_binop_postprocess(struct expr *expr)
}
}
-static void expr_postprocess(struct rule_pp_ctx *ctx,
- struct stmt *stmt, struct expr **exprp)
+static void expr_postprocess(struct rule_pp_ctx *ctx, struct expr **exprp)
{
struct expr *expr = *exprp, *i;
@@ -945,29 +989,29 @@ static void expr_postprocess(struct rule_pp_ctx *ctx,
switch (expr->ops->type) {
case EXPR_MAP:
- expr_postprocess(ctx, stmt, &expr->map);
- expr_postprocess(ctx, stmt, &expr->mappings);
+ expr_postprocess(ctx, &expr->map);
+ expr_postprocess(ctx, &expr->mappings);
break;
case EXPR_MAPPING:
- expr_postprocess(ctx, stmt, &expr->left);
- expr_postprocess(ctx, stmt, &expr->right);
+ expr_postprocess(ctx, &expr->left);
+ expr_postprocess(ctx, &expr->right);
break;
case EXPR_SET:
list_for_each_entry(i, &expr->expressions, list)
- expr_postprocess(ctx, stmt, &i);
+ expr_postprocess(ctx, &i);
break;
case EXPR_UNARY:
- expr_postprocess(ctx, stmt, &expr->arg);
+ expr_postprocess(ctx, &expr->arg);
expr_set_type(expr->arg, expr->arg->dtype, !expr->arg->byteorder);
*exprp = expr_get(expr->arg);
expr_free(expr);
break;
case EXPR_BINOP:
- expr_postprocess(ctx, stmt, &expr->left);
+ expr_postprocess(ctx, &expr->left);
expr_set_type(expr->right, expr->left->dtype,
expr->left->byteorder);
- expr_postprocess(ctx, stmt, &expr->right);
+ expr_postprocess(ctx, &expr->right);
expr_set_type(expr, expr->left->dtype,
expr->left->byteorder);
@@ -975,19 +1019,19 @@ static void expr_postprocess(struct rule_pp_ctx *ctx,
case EXPR_RELATIONAL:
switch (expr->left->ops->type) {
case EXPR_PAYLOAD:
- payload_match_postprocess(ctx, stmt, expr);
+ payload_match_postprocess(ctx, expr);
return;
default:
- expr_postprocess(ctx, stmt, &expr->left);
+ expr_postprocess(ctx, &expr->left);
break;
}
expr_set_type(expr->right, expr->left->dtype, expr->left->byteorder);
- expr_postprocess(ctx, stmt, &expr->right);
+ expr_postprocess(ctx, &expr->right);
switch (expr->left->ops->type) {
case EXPR_META:
- meta_match_postprocess(ctx, stmt, expr);
+ meta_match_postprocess(ctx, expr);
break;
case EXPR_BINOP:
relational_binop_postprocess(expr);
@@ -1028,8 +1072,11 @@ static void expr_postprocess(struct rule_pp_ctx *ctx,
break;
case EXPR_RANGE:
- expr_postprocess(ctx, stmt, &expr->left);
- expr_postprocess(ctx, stmt, &expr->right);
+ expr_postprocess(ctx, &expr->left);
+ expr_postprocess(ctx, &expr->right);
+ break;
+ case EXPR_SET_ELEM:
+ expr_postprocess(ctx, &expr->key);
break;
case EXPR_SET_REF:
case EXPR_EXTHDR:
@@ -1042,18 +1089,19 @@ static void expr_postprocess(struct rule_pp_ctx *ctx,
}
}
-static void stmt_reject_postprocess(struct rule_pp_ctx rctx, struct stmt *stmt)
+static void stmt_reject_postprocess(struct rule_pp_ctx *rctx)
{
const struct proto_desc *desc, *base;
+ struct stmt *stmt = rctx->stmt;
int protocol;
- switch (rctx.pctx.family) {
+ switch (rctx->pctx.family) {
case NFPROTO_IPV4:
- stmt->reject.family = rctx.pctx.family;
+ stmt->reject.family = rctx->pctx.family;
stmt->reject.expr->dtype = &icmp_code_type;
break;
case NFPROTO_IPV6:
- stmt->reject.family = rctx.pctx.family;
+ stmt->reject.family = rctx->pctx.family;
stmt->reject.expr->dtype = &icmpv6_code_type;
break;
case NFPROTO_INET:
@@ -1061,8 +1109,8 @@ static void stmt_reject_postprocess(struct rule_pp_ctx rctx, struct stmt *stmt)
stmt->reject.expr->dtype = &icmpx_code_type;
break;
}
- base = rctx.pctx.protocol[PROTO_BASE_LL_HDR].desc;
- desc = rctx.pctx.protocol[PROTO_BASE_NETWORK_HDR].desc;
+ base = rctx->pctx.protocol[PROTO_BASE_LL_HDR].desc;
+ desc = rctx->pctx.protocol[PROTO_BASE_NETWORK_HDR].desc;
protocol = proto_find_num(base, desc);
switch (protocol) {
case NFPROTO_IPV4:
@@ -1079,8 +1127,8 @@ static void stmt_reject_postprocess(struct rule_pp_ctx rctx, struct stmt *stmt)
stmt->reject.expr->dtype = &icmpx_code_type;
break;
}
- base = rctx.pctx.protocol[PROTO_BASE_LL_HDR].desc;
- desc = rctx.pctx.protocol[PROTO_BASE_NETWORK_HDR].desc;
+ base = rctx->pctx.protocol[PROTO_BASE_LL_HDR].desc;
+ desc = rctx->pctx.protocol[PROTO_BASE_NETWORK_HDR].desc;
protocol = proto_find_num(base, desc);
switch (protocol) {
case __constant_htons(ETH_P_IP):
@@ -1100,44 +1148,119 @@ static void stmt_reject_postprocess(struct rule_pp_ctx rctx, struct stmt *stmt)
}
}
+static bool expr_may_merge_range(struct expr *expr, struct expr *prev,
+ enum ops *op)
+{
+ struct expr *left, *prev_left;
+
+ if (prev->ops->type == EXPR_RELATIONAL &&
+ expr->ops->type == EXPR_RELATIONAL) {
+ /* ct and meta needs an unary to swap byteorder, in this case
+ * we have to explore the inner branch in this tree.
+ */
+ if (expr->left->ops->type == EXPR_UNARY)
+ left = expr->left->arg;
+ else
+ left = expr->left;
+
+ if (prev->left->ops->type == EXPR_UNARY)
+ prev_left = prev->left->arg;
+ else
+ prev_left = prev->left;
+
+ if (left->ops->type == prev_left->ops->type) {
+ if (expr->op == OP_LTE && prev->op == OP_GTE) {
+ *op = OP_EQ;
+ return true;
+ } else if (expr->op == OP_GT && prev->op == OP_LT) {
+ *op = OP_NEQ;
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+static void expr_postprocess_range(struct rule_pp_ctx *ctx, struct stmt *prev,
+ enum ops op)
+{
+ struct stmt *nstmt, *stmt = ctx->stmt;
+ struct expr *nexpr, *rel;
+
+ nexpr = range_expr_alloc(&prev->location, expr_clone(prev->expr->right),
+ expr_clone(stmt->expr->right));
+ expr_set_type(nexpr, stmt->expr->right->dtype,
+ stmt->expr->right->byteorder);
+
+ rel = relational_expr_alloc(&prev->location, op,
+ expr_clone(stmt->expr->left), nexpr);
+
+ nstmt = expr_stmt_alloc(&stmt->location, rel);
+ list_add_tail(&nstmt->list, &stmt->list);
+
+ list_del(&prev->list);
+ stmt_free(prev);
+
+ list_del(&stmt->list);
+ stmt_free(stmt);
+ ctx->stmt = nstmt;
+}
+
+static void stmt_expr_postprocess(struct rule_pp_ctx *ctx, struct stmt *prev)
+{
+ enum ops op;
+
+ if (prev && ctx->stmt->ops->type == prev->ops->type &&
+ expr_may_merge_range(ctx->stmt->expr, prev->expr, &op))
+ expr_postprocess_range(ctx, prev, op);
+
+ expr_postprocess(ctx, &ctx->stmt->expr);
+}
+
static void rule_parse_postprocess(struct netlink_parse_ctx *ctx, struct rule *rule)
{
struct rule_pp_ctx rctx;
- struct stmt *stmt, *next;
+ struct stmt *stmt, *next, *prev = NULL;
memset(&rctx, 0, sizeof(rctx));
proto_ctx_init(&rctx.pctx, rule->handle.family);
list_for_each_entry_safe(stmt, next, &rule->stmts, list) {
+ rctx.stmt = stmt;
+
switch (stmt->ops->type) {
case STMT_EXPRESSION:
- expr_postprocess(&rctx, stmt, &stmt->expr);
+ stmt_expr_postprocess(&rctx, prev);
break;
case STMT_META:
if (stmt->meta.expr != NULL)
- expr_postprocess(&rctx, stmt, &stmt->meta.expr);
+ expr_postprocess(&rctx, &stmt->meta.expr);
break;
case STMT_CT:
if (stmt->ct.expr != NULL)
- expr_postprocess(&rctx, stmt, &stmt->ct.expr);
+ expr_postprocess(&rctx, &stmt->ct.expr);
break;
case STMT_NAT:
if (stmt->nat.addr != NULL)
- expr_postprocess(&rctx, stmt, &stmt->nat.addr);
+ expr_postprocess(&rctx, &stmt->nat.addr);
if (stmt->nat.proto != NULL)
- expr_postprocess(&rctx, stmt, &stmt->nat.proto);
+ expr_postprocess(&rctx, &stmt->nat.proto);
break;
case STMT_REDIR:
if (stmt->redir.proto != NULL)
- expr_postprocess(&rctx, stmt,
- &stmt->redir.proto);
+ expr_postprocess(&rctx, &stmt->redir.proto);
break;
case STMT_REJECT:
- stmt_reject_postprocess(rctx, stmt);
+ stmt_reject_postprocess(&rctx);
+ break;
+ case STMT_SET:
+ expr_postprocess(&rctx, &stmt->set.key);
break;
default:
break;
}
+ prev = rctx.stmt;
}
}
diff --git a/src/netlink_linearize.c b/src/netlink_linearize.c
index 0a0b6864..fbc6ae12 100644
--- a/src/netlink_linearize.c
+++ b/src/netlink_linearize.c
@@ -529,6 +529,8 @@ static void netlink_gen_expr(struct netlink_linearize_ctx *ctx,
return netlink_gen_meta(ctx, expr, dreg);
case EXPR_CT:
return netlink_gen_ct(ctx, expr, dreg);
+ case EXPR_SET_ELEM:
+ return netlink_gen_expr(ctx, expr->key, dreg);
default:
BUG("unknown expression type %s\n", expr->ops->name);
}
@@ -799,6 +801,28 @@ static void netlink_gen_ct_stmt(struct netlink_linearize_ctx *ctx,
nft_rule_add_expr(ctx->nlr, nle);
}
+static void netlink_gen_set_stmt(struct netlink_linearize_ctx *ctx,
+ const struct stmt *stmt)
+{
+ struct nft_rule_expr *nle;
+ enum nft_registers sreg_key;
+
+ sreg_key = get_register(ctx);
+ netlink_gen_expr(ctx, stmt->set.key, sreg_key);
+ release_register(ctx);
+
+ nle = alloc_nft_expr("dynset");
+ netlink_put_register(nle, NFT_EXPR_DYNSET_SREG_KEY, sreg_key);
+ nft_rule_expr_set_u64(nle, NFT_EXPR_DYNSET_TIMEOUT,
+ stmt->set.key->timeout);
+ nft_rule_expr_set_u32(nle, NFT_EXPR_DYNSET_OP, stmt->set.op);
+ nft_rule_expr_set_str(nle, NFT_EXPR_DYNSET_SET_NAME,
+ stmt->set.set->set->handle.set);
+ nft_rule_expr_set_u32(nle, NFT_EXPR_DYNSET_SET_ID,
+ stmt->set.set->set->handle.set_id);
+ nft_rule_add_expr(ctx->nlr, nle);
+}
+
static void netlink_gen_stmt(struct netlink_linearize_ctx *ctx,
const struct stmt *stmt)
{
@@ -827,6 +851,8 @@ static void netlink_gen_stmt(struct netlink_linearize_ctx *ctx,
return netlink_gen_queue_stmt(ctx, stmt);
case STMT_CT:
return netlink_gen_ct_stmt(ctx, stmt);
+ case STMT_SET:
+ return netlink_gen_set_stmt(ctx, stmt);
default:
BUG("unknown statement type %s\n", stmt->ops->name);
}
diff --git a/src/parser_bison.y b/src/parser_bison.y
index b86381d9..eac3fcbe 100644
--- a/src/parser_bison.y
+++ b/src/parser_bison.y
@@ -181,6 +181,7 @@ static void location_update(struct location *loc, struct location *rhs, int n)
%token INET "inet"
%token ADD "add"
+%token UPDATE "update"
%token CREATE "create"
%token INSERT "insert"
%token DELETE "delete"
@@ -201,6 +202,8 @@ static void location_update(struct location *loc, struct location *rhs, int n)
%token CONSTANT "constant"
%token INTERVAL "interval"
+%token TIMEOUT "timeout"
+%token GC_INTERVAL "gc-interval"
%token ELEMENTS "elements"
%token POLICY "policy"
@@ -396,6 +399,8 @@ static void location_update(struct location *loc, struct location *rhs, int n)
%type <string> identifier string comment_spec
%destructor { xfree($$); } identifier string comment_spec
+%type <val> time_spec
+
%type <val> type_identifier
%type <datatype> data_type
@@ -452,6 +457,9 @@ static void location_update(struct location *loc, struct location *rhs, int n)
%type <stmt> queue_stmt queue_stmt_alloc
%destructor { stmt_free($$); } queue_stmt queue_stmt_alloc
%type <val> queue_stmt_flags queue_stmt_flag
+%type <stmt> set_stmt
+%destructor { stmt_free($$); } set_stmt
+%type <val> set_stmt_op
%type <expr> symbol_expr verdict_expr integer_expr
%destructor { expr_free($$); } symbol_expr verdict_expr integer_expr
@@ -468,8 +476,8 @@ static void location_update(struct location *loc, struct location *rhs, int n)
%destructor { expr_free($$); } prefix_expr range_expr wildcard_expr
%type <expr> list_expr
%destructor { expr_free($$); } list_expr
-%type <expr> concat_expr map_lhs_expr
-%destructor { expr_free($$); } concat_expr map_lhs_expr
+%type <expr> concat_expr
+%destructor { expr_free($$); } concat_expr
%type <expr> map_expr
%destructor { expr_free($$); } map_expr
@@ -482,6 +490,8 @@ static void location_update(struct location *loc, struct location *rhs, int n)
%type <expr> set_expr set_list_expr set_list_member_expr
%destructor { expr_free($$); } set_expr set_list_expr set_list_member_expr
+%type <expr> set_elem_expr set_elem_expr_alloc set_lhs_expr set_rhs_expr
+%destructor { expr_free($$); } set_elem_expr set_elem_expr_alloc set_lhs_expr set_rhs_expr
%type <expr> expr initializer_expr
%destructor { expr_free($$); } expr initializer_expr
@@ -940,6 +950,16 @@ set_block : /* empty */ { $$ = $<set>-1; }
$1->flags = $3;
$$ = $1;
}
+ | set_block TIMEOUT time_spec stmt_seperator
+ {
+ $1->timeout = $3 * 1000;
+ $$ = $1;
+ }
+ | set_block GC_INTERVAL time_spec stmt_seperator
+ {
+ $1->gc_int = $3 * 1000;
+ $$ = $1;
+ }
| set_block ELEMENTS '=' set_expr
{
$1->init = $4;
@@ -957,6 +977,7 @@ set_flag_list : set_flag_list COMMA set_flag
set_flag : CONSTANT { $$ = SET_F_CONSTANT; }
| INTERVAL { $$ = SET_F_INTERVAL; }
+ | TIMEOUT { $$ = SET_F_TIMEOUT; }
;
map_block_alloc : /* empty */
@@ -1093,6 +1114,20 @@ string : STRING
| QUOTED_STRING
;
+time_spec : STRING
+ {
+ struct error_record *erec;
+ uint64_t res;
+
+ erec = time_parse(&@1, $1, &res);
+ if (erec != NULL) {
+ erec_queue(erec, state->msgs);
+ YYERROR;
+ }
+ $$ = res;
+ }
+ ;
+
family_spec : /* empty */ { $$ = NFPROTO_IPV4; }
| family_spec_explicit
;
@@ -1236,6 +1271,7 @@ stmt : verdict_stmt
| ct_stmt
| masq_stmt
| redir_stmt
+ | set_stmt
;
verdict_stmt : verdict_expr
@@ -1281,13 +1317,12 @@ verdict_map_list_expr : verdict_map_list_member_expr
| verdict_map_list_expr COMMA opt_newline
;
-verdict_map_list_member_expr: opt_newline map_lhs_expr COLON verdict_expr opt_newline
+verdict_map_list_member_expr: opt_newline set_elem_expr COLON verdict_expr opt_newline
{
$$ = mapping_expr_alloc(&@$, $2, $4);
}
;
-
counter_stmt : counter_stmt_alloc
| counter_stmt_alloc counter_args
@@ -1549,6 +1584,19 @@ queue_stmt_flag : BYPASS { $$ = NFT_QUEUE_FLAG_BYPASS; }
| FANOUT { $$ = NFT_QUEUE_FLAG_CPU_FANOUT; }
;
+set_stmt : SET set_stmt_op set_elem_expr symbol_expr
+ {
+ $$ = set_stmt_alloc(&@$);
+ $$->set.op = $2;
+ $$->set.key = $3;
+ $$->set.set = $4;
+ }
+ ;
+
+set_stmt_op : ADD { $$ = NFT_DYNSET_OP_ADD; }
+ | UPDATE { $$ = NFT_DYNSET_OP_UPDATE; }
+ ;
+
match_stmt : relational_expr
{
$$ = expr_stmt_alloc(&@$, $1);
@@ -1702,10 +1750,6 @@ multiton_expr : prefix_expr
| wildcard_expr
;
-map_lhs_expr : multiton_expr
- | concat_expr
- ;
-
map_expr : concat_expr MAP expr
{
$$ = map_expr_alloc(&@$, $1, $3);
@@ -1713,9 +1757,9 @@ map_expr : concat_expr MAP expr
;
expr : concat_expr
+ | multiton_expr
| set_expr
| map_expr
- | multiton_expr
;
set_expr : '{' set_list_expr '}'
@@ -1738,20 +1782,55 @@ set_list_expr : set_list_member_expr
| set_list_expr COMMA opt_newline
;
-set_list_member_expr : opt_newline expr opt_newline
+set_list_member_expr : opt_newline set_expr opt_newline
{
$$ = $2;
}
- | opt_newline map_lhs_expr COLON concat_expr opt_newline
+ | opt_newline set_elem_expr opt_newline
{
- $$ = mapping_expr_alloc(&@$, $2, $4);
+ $$ = $2;
}
- | opt_newline map_lhs_expr COLON verdict_expr opt_newline
+ | opt_newline set_elem_expr COLON set_rhs_expr opt_newline
{
$$ = mapping_expr_alloc(&@$, $2, $4);
}
;
+set_elem_expr : set_elem_expr_alloc
+ | set_elem_expr_alloc set_elem_options
+ ;
+
+set_elem_expr_alloc : set_lhs_expr
+ {
+ $$ = set_elem_expr_alloc(&@1, $1);
+ }
+ ;
+
+set_elem_options : set_elem_option
+ {
+ $<expr>$ = $<expr>0;
+ }
+ | set_elem_options set_elem_option
+ ;
+
+set_elem_option : TIMEOUT time_spec
+ {
+ $<expr>0->timeout = $2 * 1000;
+ }
+ | COMMENT string
+ {
+ $<expr>0->comment = $2;
+ }
+ ;
+
+set_lhs_expr : concat_expr
+ | multiton_expr
+ ;
+
+set_rhs_expr : concat_expr
+ | verdict_expr
+ ;
+
initializer_expr : expr
| list_expr
;
diff --git a/src/rule.c b/src/rule.c
index 71143807..b2090ddd 100644
--- a/src/rule.c
+++ b/src/rule.c
@@ -136,6 +136,7 @@ static void do_set_print(const struct set *set, struct print_fmt_options *opts)
{
const char *delim = "";
const char *type;
+ uint32_t flags;
type = set->flags & SET_F_MAP ? "map" : "set";
printf("%s%s", opts->tab, type);
@@ -167,7 +168,12 @@ static void do_set_print(const struct set *set, struct print_fmt_options *opts)
}
}
- if (set->flags & (SET_F_CONSTANT | SET_F_INTERVAL)) {
+ flags = set->flags;
+ /* "timeout" flag is redundant if a default timeout exists */
+ if (set->timeout)
+ flags &= ~SET_F_TIMEOUT;
+
+ if (flags & (SET_F_CONSTANT | SET_F_INTERVAL | SET_F_TIMEOUT)) {
printf("%s%sflags ", opts->tab, opts->tab);
if (set->flags & SET_F_CONSTANT) {
printf("%sconstant", delim);
@@ -177,6 +183,21 @@ static void do_set_print(const struct set *set, struct print_fmt_options *opts)
printf("%sinterval", delim);
delim = ",";
}
+ if (set->flags & SET_F_TIMEOUT) {
+ printf("%stimeout", delim);
+ delim = ",";
+ }
+ printf("%s", opts->nl);
+ }
+
+ if (set->timeout) {
+ printf("%s%stimeout ", opts->tab, opts->tab);
+ time_print(set->timeout / 1000);
+ printf("%s", opts->nl);
+ }
+ if (set->gc_int) {
+ printf("%s%sgc-interval ", opts->tab, opts->tab);
+ time_print(set->gc_int / 1000);
printf("%s", opts->nl);
}
diff --git a/src/scanner.l b/src/scanner.l
index 73c4f8b1..985ea2a3 100644
--- a/src/scanner.l
+++ b/src/scanner.l
@@ -117,6 +117,8 @@ quotedstring \"[^"]*\"
comment #.*$
slash \/
+timestring ([0-9]+d)?([0-9]+h)?([0-9]+m)?([0-9]+s)?
+
hex4 ([[:xdigit:]]{1,4})
v680 (({hex4}:){7}{hex4})
v670 ((:)((:{hex4}){7}))
@@ -255,6 +257,7 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr})
"inet" { return INET; }
"add" { return ADD; }
+"update" { return UPDATE; }
"create" { return CREATE; }
"insert" { return INSERT; }
"delete" { return DELETE; }
@@ -269,6 +272,8 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr})
"constant" { return CONSTANT; }
"interval" { return INTERVAL; }
+"timeout" { return TIMEOUT; }
+"gc-interval" { return GC_INTERVAL; }
"elements" { return ELEMENTS; }
"policy" { return POLICY; }
@@ -457,6 +462,11 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr})
return STRING;
}
+{timestring} {
+ yylval->string = xstrdup(yytext);
+ return STRING;
+ }
+
{decstring} {
errno = 0;
yylval->val = strtoull(yytext, NULL, 0);
diff --git a/src/segtree.c b/src/segtree.c
index 65221e9d..060951c0 100644
--- a/src/segtree.c
+++ b/src/segtree.c
@@ -419,6 +419,7 @@ static void set_insert_interval(struct expr *set, struct seg_tree *tree,
expr = constant_expr_alloc(&internal_location, tree->keytype,
tree->byteorder, tree->keylen, NULL);
mpz_set(expr->value, ei->left);
+ expr = set_elem_expr_alloc(&internal_location, expr);
if (ei->expr != NULL && ei->expr->ops->type == EXPR_MAPPING)
expr = mapping_expr_alloc(&ei->expr->location, expr,
@@ -473,9 +474,9 @@ extern void interval_map_decompose(struct expr *set);
static struct expr *expr_value(struct expr *expr)
{
if (expr->ops->type == EXPR_MAPPING)
- return expr->left;
+ return expr->left->key;
else
- return expr;
+ return expr->key;
}
static int expr_value_cmp(const void *p1, const void *p2)
@@ -565,6 +566,7 @@ void interval_map_decompose(struct expr *set)
mpz_set(tmp->value, range);
tmp = range_expr_alloc(&low->location, expr_value(low), tmp);
+ tmp = set_elem_expr_alloc(&low->location, tmp);
if (low->ops->type == EXPR_MAPPING)
tmp = mapping_expr_alloc(&tmp->location, tmp, low->right);
@@ -576,6 +578,7 @@ void interval_map_decompose(struct expr *set)
prefix_len = expr_value(i)->len - mpz_scan0(range, 0);
prefix = prefix_expr_alloc(&low->location, expr_value(low),
prefix_len);
+ prefix = set_elem_expr_alloc(&low->location, prefix);
if (low->ops->type == EXPR_MAPPING)
prefix = mapping_expr_alloc(&low->location, prefix,
low->right);
@@ -598,6 +601,7 @@ void interval_map_decompose(struct expr *set)
mpz_init_bitmask(i->value, i->len);
i = range_expr_alloc(&low->location, expr_value(low), i);
+ i = set_elem_expr_alloc(&low->location, i);
if (low->ops->type == EXPR_MAPPING)
i = mapping_expr_alloc(&i->location, i, low->right);
diff --git a/src/statement.c b/src/statement.c
index d72c6e9b..9ebc5938 100644
--- a/src/statement.c
+++ b/src/statement.c
@@ -377,3 +377,34 @@ struct stmt *redir_stmt_alloc(const struct location *loc)
{
return stmt_alloc(loc, &redir_stmt_ops);
}
+
+static const char * const set_stmt_op_names[] = {
+ [NFT_DYNSET_OP_ADD] = "add",
+ [NFT_DYNSET_OP_UPDATE] = "update",
+};
+
+static void set_stmt_print(const struct stmt *stmt)
+{
+ printf("set %s ", set_stmt_op_names[stmt->set.op]);
+ expr_print(stmt->set.key);
+ printf(" ");
+ expr_print(stmt->set.set);
+}
+
+static void set_stmt_destroy(struct stmt *stmt)
+{
+ expr_free(stmt->set.key);
+ expr_free(stmt->set.set);
+}
+
+static const struct stmt_ops set_stmt_ops = {
+ .type = STMT_SET,
+ .name = "set",
+ .print = set_stmt_print,
+ .destroy = set_stmt_destroy,
+};
+
+struct stmt *set_stmt_alloc(const struct location *loc)
+{
+ return stmt_alloc(loc, &set_stmt_ops);
+}
diff --git a/tests/regression/any/ct.t b/tests/regression/any/ct.t
index bb26cb85..6ec05261 100644
--- a/tests/regression/any/ct.t
+++ b/tests/regression/any/ct.t
@@ -44,10 +44,10 @@ ct mark and 0x3 != 0x1;ok;ct mark & 0x00000003 != 0x00000001
ct mark xor 0x23 == 0x11;ok;ct mark 0x00000032
ct mark xor 0x3 != 0x1;ok;ct mark != 0x00000002
-ct mark 0x32;ok;ct mark 0x00000032
-ct mark != 0x32;ok;ct mark != 0x00000032
-ct mark 0x32-0x45;ok
-ct mark != 0x32-0x43;ok
+ct mark 0x00000032;ok
+ct mark != 0x00000032;ok
+ct mark 0x00000032-0x00000045;ok
+ct mark != 0x00000032-0x00000045;ok
ct mark {0x32, 0x2222, 0x42de3};ok;ct mark { 0x00042de3, 0x00002222, 0x00000032}
- ct mark != {0x32, 0x2222, 0x42de3};ok
@@ -60,16 +60,14 @@ ct mark set 0x11333 and 0x11;ok;ct mark set 0x00000011
ct mark set 0x12 or 0x11;ok;ct mark set 0x00000013
ct mark set 0x11;ok;ct mark set 0x00000011
-ct expiration 30;ok
-ct expiration 22;ok
-ct expiration != 233;ok
-ct expiration 33-45;ok
-# BUG: ct expiration 33-45 and ct expiration != 33-45
-# Broken output: ct expiration >= "33s" ct expiration <= "9709d53m20s"
-ct expiration != 33-45;ok
-ct expiration {33, 55, 67, 88};ok
-- ct expiration != {33, 55, 67, 88};ok
-ct expiration {33-55};ok
+ct expiration 30;ok;ct expiration 30s
+ct expiration 22;ok;ct expiration 22s
+ct expiration != 233;ok;ct expiration != 3m53s
+ct expiration 33-45;ok;ct expiration 33s-45s
+ct expiration != 33-45;ok;ct expiration != 33s-45s
+ct expiration {33, 55, 67, 88};ok;ct expiration { 1m7s, 33s, 55s, 1m28s}
+- ct expiration != {33, 55, 67, 88};ok;ct expiration { 1m7s, 33s, 55s, 1m28s}
+ct expiration {33-55};ok;ct expiration { 33s-55s}
# BUG: ct expiration {33-55}
# Broken output: ct expiration { "4271d23h25m52s"-"8738d3h11m59s" }
- ct expiration != {33-55};ok
diff --git a/tests/regression/any/frag.t b/tests/regression/any/frag.t
index 92caf1e5..d61a3d4f 100644
--- a/tests/regression/any/frag.t
+++ b/tests/regression/any/frag.t
@@ -14,9 +14,9 @@ frag nexthdr ah;ok;frag nexthdr 51
frag reserved 22;ok
frag reserved != 233;ok
-frag reserved 33-45;ok;frag reserved >= 33 frag reserved <= 45
-frag reserved != 33-45;ok;frag reserved < 33 frag reserved > 45
-frag reserved { 33, 55, 67, 88};ok;frag reserved { 88, 33, 67, 55}
+frag reserved 33-45;ok
+frag reserved != 33-45;ok
+frag reserved { 33, 55, 67, 88};ok
- frag reserved != { 33, 55, 67, 88};ok
frag reserved { 33-55};ok
- frag reserved != { 33-55};ok
@@ -56,8 +56,8 @@ frag reserved { 33-55};ok
frag id 1;ok
frag id 22;ok
frag id != 33;ok
-frag id 33-45;ok;frag id >= 33 frag id <= 45
-frag id != 33-45;ok;frag id < 33 frag id > 45
+frag id 33-45;ok
+frag id != 33-45;ok
frag id { 33, 55, 67, 88};ok
- frag id != { 33, 55, 67, 88};ok
frag id { 33-55};ok
diff --git a/tests/regression/any/meta.t b/tests/regression/any/meta.t
index 7108d177..ca0b4d4a 100644
--- a/tests/regression/any/meta.t
+++ b/tests/regression/any/meta.t
@@ -27,8 +27,8 @@ meta nfproto {ipv4, ipv6};ok
meta l4proto 22;ok
meta l4proto != 233;ok
-meta l4proto 33-45;ok;meta l4proto >= 33 meta l4proto <= 45
-meta l4proto != 33-45;ok;meta l4proto < 33 meta l4proto > 45
+meta l4proto 33-45;ok
+meta l4proto != 33-45;ok
meta l4proto { 33, 55, 67, 88};ok;meta l4proto { 33, 55, 67, 88}
- meta l4proto != { 33, 55, 67, 88};ok
meta l4proto { 33-55};ok
@@ -96,9 +96,9 @@ meta skuid != man;ok;skuid != 6
meta skuid lt 3000 accept;ok;skuid < 3000 accept
meta skuid gt 3000 accept;ok;skuid > 3000 accept
meta skuid eq 3000 accept;ok;skuid 3000 accept
-meta skuid 3001-3005 accept;ok
-meta skuid != 2001-2005 accept;ok
-meta skuid { 2001-2005} accept;ok
+meta skuid 3001-3005 accept;ok;skuid 3001-3005 accept
+meta skuid != 2001-2005 accept;ok;skuid != 2001-2005 accept
+meta skuid { 2001-2005} accept;ok;skuid { 2001-2005} accept
- meta skuid != { 2001-2005} accept;ok
meta skgid {man, root, backup} accept;ok;skgid { 34, 12, 0} accept
@@ -108,10 +108,10 @@ meta skgid != man;ok;skgid != 12
meta skgid lt 3000 accept;ok;skgid < 3000 accept
meta skgid gt 3000 accept;ok;skgid > 3000 accept
meta skgid eq 3000 accept;ok;skgid 3000 accept
-meta skgid 2001-2005 accept;ok
-meta skgid != 2001-2005 accept;ok
-meta skgid { 2001-2005} accept;ok
-- meta skgid != { 2001-2005} accept;ok
+meta skgid 2001-2005 accept;ok;skgid 2001-2005 accept
+meta skgid != 2001-2005 accept;ok;skgid != 2001-2005 accept
+meta skgid { 2001-2005} accept;ok;skgid { 2001-2005} accept
+- meta skgid != { 2001-2005} accept;ok;skgid != { 2001-2005} accept
# BUG: meta nftrace 2 and meta nftrace 1
# $ sudo nft add rule ip test input meta nftrace 2
@@ -153,11 +153,10 @@ meta pkttype { broadcast, multicast} accept;ok
meta cpu 1;ok;cpu 1
meta cpu != 1;ok;cpu != 1
-meta cpu 1-3;ok;cpu >= 1 cpu <= 3
-# BUG: there is not matching of packets with this rule.
-meta cpu != 1-2;ok;cpu < 1 cpu > 2
-meta cpu { 2,3};ok;cpu { 2, 3}
--meta cpu != { 2,3};ok
+meta cpu 1-3;ok;cpu 1-3
+meta cpu != 1-2;ok;cpu != 1-2
+meta cpu { 2,3};ok;cpu { 2,3}
+-meta cpu != { 2,3};ok; cpu != { 2,3}
meta iifgroup 0;ok;iifgroup default
meta iifgroup != 0;ok;iifgroup != default
@@ -180,11 +179,11 @@ meta oifgroup {11-33};ok
- meta oifgroup != {11,33};ok
- meta oifgroup != {11-33};ok
-meta cgroup 0x100001;ok;cgroup 1048577
-meta cgroup != 0x100001;ok;cgroup != 1048577
-meta cgroup { 0x100001, 0x100002};ok
-# meta cgroup != { 0x100001, 0x100002};ok
-meta cgroup 0x100001 - 0x100003;ok
-# meta cgroup != 0x100001 - 0x100003;ok
-meta cgroup {0x100001 - 0x100003};ok
-# meta cgroup != { 0x100001 - 0x100003};ok
+meta cgroup 1048577;ok;cgroup 1048577
+meta cgroup != 1048577;ok;cgroup != 1048577
+meta cgroup { 1048577, 1048578 };ok;cgroup { 1048577, 1048578}
+# meta cgroup != { 1048577, 1048578};ok;cgroup != { 1048577, 1048578}
+meta cgroup 1048577-1048578;ok;cgroup 1048577-1048578
+meta cgroup != 1048577-1048578;ok;cgroup != 1048577-1048578
+meta cgroup {1048577-1048578};ok;cgroup { 1048577-1048578}
+# meta cgroup != { 1048577-1048578};ok;cgroup != { 1048577-1048578}
diff --git a/tests/regression/arp/arp.t b/tests/regression/arp/arp.t
index 797e394b..c4e07d57 100644
--- a/tests/regression/arp/arp.t
+++ b/tests/regression/arp/arp.t
@@ -6,19 +6,19 @@ arp htype 1;ok
arp htype != 1;ok
arp htype 22;ok
arp htype != 233;ok
-arp htype 33-45;ok;arp htype >= 33 arp htype <= 45
-arp htype != 33-45;ok;arp htype < 33 arp htype > 45
+arp htype 33-45;ok
+arp htype != 33-45;ok
arp htype { 33, 55, 67, 88};ok
- arp htype != { 33, 55, 67, 88};ok
arp htype { 33-55};ok
- arp htype != { 33-55};ok
-arp ptype 0x0800;ok
+arp ptype 0x0800;ok;arp ptype ip
arp hlen 22;ok
arp hlen != 233;ok
-arp hlen 33-45;ok;arp hlen >= 33 arp hlen <= 45
-arp hlen != 33-45;ok;arp hlen < 33 arp hlen > 45
+arp hlen 33-45;ok
+arp hlen != 33-45;ok
arp hlen { 33, 55, 67, 88};ok
- arp hlen != { 33, 55, 67, 88};ok
arp hlen { 33-55};ok
@@ -26,8 +26,8 @@ arp hlen { 33-55};ok
arp plen 22;ok
arp plen != 233;ok
-arp plen 33-45;ok;arp plen >= 33 arp plen <= 45
-arp plen != 33-45;ok;arp plen < 33 arp plen > 45
+arp plen 33-45;ok
+arp plen != 33-45;ok
arp plen { 33, 55, 67, 88};ok
- arp plen != { 33, 55, 67, 88};ok
arp plen { 33-55};ok
diff --git a/tests/regression/inet/ah.t b/tests/regression/inet/ah.t
index 6defc35c..666659d3 100644
--- a/tests/regression/inet/ah.t
+++ b/tests/regression/inet/ah.t
@@ -17,8 +17,8 @@
- ah nexthdr { esp, ah, comp, udp, udplite, tcp, dccp, sctp};ok;ah nexthdr { 6, 132, 50, 17, 136, 33, 51, 108}
- ah nexthdr != { esp, ah, comp, udp, udplite, tcp, dccp, sctp};ok
-ah hdrlength 11-23;ok;ah hdrlength >= 11 ah hdrlength <= 23
-ah hdrlength != 11-23;ok;ah hdrlength < 11 ah hdrlength > 23
+ah hdrlength 11-23;ok
+ah hdrlength != 11-23;ok
ah hdrlength { 11-23};ok
- ah hdrlength != { 11-23};ok
ah hdrlength {11, 23, 44 };ok
@@ -26,8 +26,8 @@ ah hdrlength {11, 23, 44 };ok
ah reserved 22;ok
ah reserved != 233;ok
-ah reserved 33-45;ok;ah reserved >= 33 ah reserved <= 45
-ah reserved != 33-45;ok;ah reserved < 33 ah reserved > 45
+ah reserved 33-45;ok
+ah reserved != 33-45;ok
ah reserved {23, 100};ok
- ah reserved != {33, 55, 67, 88};ok
ah reserved { 33-55};ok
@@ -35,8 +35,8 @@ ah reserved { 33-55};ok
ah spi 111;ok
ah spi != 111;ok
-ah spi 111-222;ok;ah spi >= 111 ah spi <= 222
-ah spi != 111-222;ok;ah spi < 111 ah spi > 222
+ah spi 111-222;ok
+ah spi != 111-222;ok
ah spi {111, 122};ok
- ah spi != {111, 122};ok
# BUG: invalid expression type set
@@ -54,5 +54,5 @@ ah sequence {23, 25, 33};ok
- ah sequence != {23, 25, 33};ok
ah sequence { 23-33};ok
- ah sequence != { 33-44};ok
-ah sequence 23-33;ok;ah sequence >= 23 ah sequence <= 33
-ah sequence != 23-33;ok;ah sequence < 23 ah sequence > 33
+ah sequence 23-33;ok
+ah sequence != 23-33;ok
diff --git a/tests/regression/inet/comp.t b/tests/regression/inet/comp.t
index 32db32b2..afdc63f3 100644
--- a/tests/regression/inet/comp.t
+++ b/tests/regression/inet/comp.t
@@ -4,9 +4,9 @@
:input;type filter hook input priority 0
-# BUG: Do no list table.
+# BUG: nft: payload.c:88: payload_expr_pctx_update: Assertion `left->payload.base + 1 <= (__PROTO_BASE_MAX - 1)' failed.
- comp nexthdr esp;ok;comp nexthdr 50
-comp nexthdr != esp;ok
+comp nexthdr != esp;ok;comp nexthdr != 50
- comp nexthdr {esp, ah, comp, udp, udplite, tcp, tcp, dccp, sctp};ok
# comp flags ## 8-bit field. Reserved for future use. MUST be set to zero.
@@ -23,8 +23,8 @@ comp flags { 0x33-0x55};ok
comp cpi 22;ok
comp cpi != 233;ok
-comp cpi 33-45;ok;comp cpi >= 33 comp cpi <= 45
-comp cpi != 33-45;ok;comp cpi < 33 comp cpi > 45
+comp cpi 33-45;ok
+comp cpi != 33-45;ok
comp cpi {33, 55, 67, 88};ok
- comp cpi != {33, 55, 67, 88};ok
comp cpi { 33-55};ok
diff --git a/tests/regression/inet/dccp.t b/tests/regression/inet/dccp.t
index 272c0e2a..e323992e 100644
--- a/tests/regression/inet/dccp.t
+++ b/tests/regression/inet/dccp.t
@@ -3,15 +3,16 @@
*inet;test-inet
:input;type filter hook input priority 0
-dccp sport 21-35;ok;dccp sport >= 21 dccp sport <= 35
-dccp sport != 21-35;ok;dccp sport < 21 dccp sport > 35
-dccp sport {23, 24, 25};ok;dccp sport { 23, 24, 25}
+dccp sport 21-35;ok
+dccp sport != 21-35;ok
+dccp sport {23, 24, 25};ok
- dccp sport != { 27, 34};ok
# BUG: invalid expression type set
# nft: src/evaluate.c:975: expr_evaluate_relational: Assertion '0' failed.
-dccp sport { ftp-data - re-mail-ck};ok;dccp sport { 20-50}
-dccp sport ftp-data - re-mail-ck;ok;dccp sport >= 20 dccp sport <= 50
+dccp sport { 20-50 };ok
+dccp sport ftp-data - re-mail-ck;ok;dccp sport 20-50
+dccp sport 20-50;ok
dccp sport { 20-50};ok
- dccp sport != {27-34};ok
# dccp sport != {27-34};ok
diff --git a/tests/regression/inet/esp.t b/tests/regression/inet/esp.t
index 1f23aa4e..3a8502d9 100644
--- a/tests/regression/inet/esp.t
+++ b/tests/regression/inet/esp.t
@@ -5,16 +5,16 @@
esp spi 100;ok
esp spi != 100;ok
-esp spi 111-222;ok;esp spi >= 111 esp spi <= 222
-esp spi != 111-222;ok;esp spi < 111 esp spi > 222
+esp spi 111-222;ok
+esp spi != 111-222;ok
esp spi { 100, 102};ok
- esp spi != { 100, 102};ok
esp spi { 100-102};ok
- esp spi {100-102};ok
esp sequence 22;ok
-esp sequence 22-24;ok;esp sequence >= 22 esp sequence <= 24
-esp sequence != 22-24;ok;esp sequence < 22 esp sequence > 24
+esp sequence 22-24;ok
+esp sequence != 22-24;ok
esp sequence { 22, 24};ok
- esp sequence != { 22, 24};ok
# BUG: invalid expression type set
diff --git a/tests/regression/inet/sctp.t b/tests/regression/inet/sctp.t
index b98b0af4..537a9b17 100644
--- a/tests/regression/inet/sctp.t
+++ b/tests/regression/inet/sctp.t
@@ -5,8 +5,8 @@
sctp sport 23;ok
sctp sport != 23;ok
-sctp sport 23-44;ok;sctp sport >= 23 sctp sport <= 44
-sctp sport != 23-44;ok;sctp sport < 23 sctp sport > 44
+sctp sport 23-44;ok
+sctp sport != 23-44;ok
sctp sport { 23, 24, 25};ok
- sctp sport != { 23, 24, 25};ok
sctp sport { 23-44};ok
@@ -16,8 +16,8 @@ sctp sport { 23-44};ok
sctp dport 23;ok
sctp dport != 23;ok
-sctp dport 23-44;ok;sctp dport >= 23 sctp dport <= 44
-sctp dport != 23-44;ok;sctp dport < 23 sctp dport > 44
+sctp dport 23-44;ok
+sctp dport != 23-44;ok
sctp dport { 23, 24, 25};ok
- sctp dport != { 23, 24, 25};ok
sctp dport { 23-44};ok
@@ -25,8 +25,8 @@ sctp dport { 23-44};ok
sctp checksum 1111;ok
sctp checksum != 11;ok
-sctp checksum 21-333;ok;sctp checksum >= 21 sctp checksum <= 333
-sctp checksum != 32-111;ok;sctp checksum < 32 sctp checksum > 111
+sctp checksum 21-333;ok
+sctp checksum != 32-111;ok
sctp checksum { 22, 33, 44};ok
- sctp checksum != { 22, 33, 44};ok
sctp checksum { 22-44};ok
@@ -34,8 +34,8 @@ sctp checksum { 22-44};ok
sctp vtag 22;ok
sctp vtag != 233;ok
-sctp vtag 33-45;ok;sctp vtag >= 33 sctp vtag <= 45
-sctp vtag != 33-45;ok;sctp vtag < 33 sctp vtag > 45
+sctp vtag 33-45;ok
+sctp vtag != 33-45;ok
sctp vtag {33, 55, 67, 88};ok
- sctp vtag != {33, 55, 67, 88};ok
sctp vtag { 33-55};ok
diff --git a/tests/regression/inet/tcp.t b/tests/regression/inet/tcp.t
index f72ec52b..5eb3882c 100644
--- a/tests/regression/inet/tcp.t
+++ b/tests/regression/inet/tcp.t
@@ -5,8 +5,8 @@
tcp dport 22;ok
tcp dport != 233;ok
-tcp dport 33-45;ok;tcp dport >= 33 tcp dport <= 45
-tcp dport != 33-45;ok;tcp dport < 33 tcp dport > 45
+tcp dport 33-45;ok
+tcp dport != 33-45;ok
tcp dport { 33, 55, 67, 88};ok
- tcp dport != { 33, 55, 67, 88};ok
tcp dport { 33-55};ok
@@ -21,8 +21,8 @@ tcp dport { 22, 53, 80, 110 };ok
tcp sport 22;ok
tcp sport != 233;ok
-tcp sport 33-45;ok;tcp sport >= 33 tcp sport <= 45
-tcp sport != 33-45;ok;tcp sport < 33 tcp sport > 45
+tcp sport 33-45;ok
+tcp sport != 33-45;ok
tcp sport { 33, 55, 67, 88};ok
- tcp sport != { 33, 55, 67, 88};ok
tcp sport { 33-55};ok
@@ -33,13 +33,13 @@ tcp sport 8080 drop;ok
tcp sport 1024 tcp dport 22;ok
tcp sport 1024 tcp dport 22 tcp sequence 0;ok
-tcp sequence 0 tcp sport 1024 tcp dport 22;ok;tcp sport 1024 tcp dport 22 tcp sequence 0
+tcp sequence 0 tcp sport 1024 tcp dport 22;ok
tcp sequence 0 tcp sport { 1024, 1022} tcp dport 22;ok
tcp sequence 22;ok
tcp sequence != 233;ok
-tcp sequence 33-45;ok;tcp sequence >= 33 tcp sequence <= 45
-tcp sequence != 33-45;ok;tcp sequence < 33 tcp sequence > 45
+tcp sequence 33-45;ok
+tcp sequence != 33-45;ok
tcp sequence { 33, 55, 67, 88};ok
- tcp sequence != { 33, 55, 67, 88};ok
tcp sequence { 33-55};ok
@@ -48,8 +48,8 @@ tcp sequence { 33-55};ok
tcp ackseq 42949672 drop;ok
tcp ackseq 22;ok
tcp ackseq != 233;ok
-tcp ackseq 33-45;ok;tcp ackseq >= 33 tcp ackseq <= 45
-tcp ackseq != 33-45;ok;tcp ackseq < 33 tcp ackseq > 45
+tcp ackseq 33-45;ok
+tcp ackseq != 33-45;ok
tcp ackseq { 33, 55, 67, 88};ok
- tcp ackseq != { 33, 55, 67, 88};ok
tcp ackseq { 33-55};ok
@@ -75,8 +75,8 @@ tcp flags != cwr;ok
tcp window 22222;ok
tcp window 22;ok
tcp window != 233;ok
-tcp window 33-45;ok;tcp window >= 33 tcp window <= 45
-tcp window != 33-45;ok;tcp window < 33 tcp window > 45
+tcp window 33-45;ok
+tcp window != 33-45;ok
tcp window { 33, 55, 67, 88};ok
- tcp window != { 33, 55, 67, 88};ok
tcp window { 33-55};ok
@@ -85,8 +85,8 @@ tcp window { 33-55};ok
tcp checksum 23456 log drop;ok
tcp checksum 22;ok
tcp checksum != 233;ok
-tcp checksum 33-45;ok;tcp checksum >= 33 tcp checksum <= 45
-tcp checksum != 33-45;ok;tcp checksum < 33 tcp checksum > 45
+tcp checksum 33-45;ok
+tcp checksum != 33-45;ok
tcp checksum { 33, 55, 67, 88};ok
- tcp checksum != { 33, 55, 67, 88};ok
tcp checksum { 33-55};ok
@@ -95,8 +95,8 @@ tcp checksum { 33-55};ok
tcp urgptr 1234 accept;ok
tcp urgptr 22;ok
tcp urgptr != 233;ok
-tcp urgptr 33-45;ok;tcp urgptr >= 33 tcp urgptr <= 45
-tcp urgptr != 33-45;ok;tcp urgptr < 33 tcp urgptr > 45
+tcp urgptr 33-45;ok
+tcp urgptr != 33-45;ok
tcp urgptr { 33, 55, 67, 88};ok
- tcp urgptr != { 33, 55, 67, 88};ok
tcp urgptr { 33-55};ok
diff --git a/tests/regression/inet/udp.t b/tests/regression/inet/udp.t
index 0e8a01f0..58f4002d 100644
--- a/tests/regression/inet/udp.t
+++ b/tests/regression/inet/udp.t
@@ -5,9 +5,9 @@
udp sport 80 accept;ok
udp sport != 60 accept;ok
-udp sport 50-70 accept;ok;udp sport >= 50 udp sport <= 70 accept
-udp sport != 50-60 accept;ok;udp sport < 50 udp sport > 60 accept
-udp sport { 49, 50} drop;ok;udp sport { 49, 50} drop
+udp sport 50-70 accept;ok
+udp sport != 50-60 accept;ok
+udp sport { 49, 50} drop;ok
- udp sport != { 50, 60} accept;ok
# BUG: invalid expression type set
# nft: src/evaluate.c:975: expr_evaluate_relational: Assertion '0' failed.
@@ -16,19 +16,19 @@ udp sport { 12-40};ok
udp dport 80 accept;ok
udp dport != 60 accept;ok
-udp dport 70-75 accept;ok;udp dport >= 70 udp dport <= 75 accept
-udp dport != 50-60 accept;ok;udp dport < 50 udp dport > 60 accept
+udp dport 70-75 accept;ok
+udp dport != 50-60 accept;ok
udp dport { 49, 50} drop;ok
- udp dport != { 50, 60} accept;ok
# BUG: invalid expression type set
# nft: src/evaluate.c:975: expr_evaluate_relational: Assertion '0' failed.
-udp dport { 70-75} accept;ok;udp dport { 70-75} accept
+udp dport { 70-75} accept;ok
- udp dport != { 50-60} accept;ok
udp length 6666;ok
udp length != 6666;ok
-udp length 50-65 accept;ok;udp length >= 50 udp length <= 65 accept
-udp length != 50-65 accept;ok;udp length < 50 udp length > 65 accept
+udp length 50-65 accept;ok
+udp length != 50-65 accept;ok
udp length { 50, 65} accept;ok
- udp length != { 50, 65} accept;ok
udp length { 35-50};ok
@@ -41,8 +41,8 @@ udp checksum 6666 drop;ok
udp checksum 22;ok
udp checksum != 233;ok
-udp checksum 33-45;ok;udp checksum >= 33 udp checksum <= 45
-udp checksum != 33-45;ok;udp checksum < 33 udp checksum > 45
+udp checksum 33-45;ok
+udp checksum != 33-45;ok
udp checksum { 33, 55, 67, 88};ok
- udp checksum != { 33, 55, 67, 88};ok
udp checksum { 33-55};ok
diff --git a/tests/regression/inet/udplite.t b/tests/regression/inet/udplite.t
index 1d5fbb35..9420ab45 100644
--- a/tests/regression/inet/udplite.t
+++ b/tests/regression/inet/udplite.t
@@ -5,20 +5,20 @@
udplite sport 80 accept;ok
udplite sport != 60 accept;ok
-udplite sport 50-70 accept;ok;udplite sport >= 50 udplite sport <= 70 accept
-udplite sport != 50-60 accept;ok;udplite sport < 50 udplite sport > 60 accept
-udplite sport { 49, 50} drop;ok;udplite sport { 49, 50} drop
+udplite sport 50-70 accept;ok
+udplite sport != 50-60 accept;ok
+udplite sport { 49, 50} drop;ok
- udplite sport != { 50, 60} accept;ok
udplite sport { 12-40};ok
- udplite sport != { 13-24};ok
udplite dport 80 accept;ok
udplite dport != 60 accept;ok
-udplite dport 70-75 accept;ok;udplite dport >= 70 udplite dport <= 75 accept
-udplite dport != 50-60 accept;ok;udplite dport < 50 udplite dport > 60 accept
-udplite dport { 49, 50} drop;ok;udplite dport { 49, 50} drop
+udplite dport 70-75 accept;ok
+udplite dport != 50-60 accept;ok
+udplite dport { 49, 50} drop;ok
- udplite dport != { 50, 60} accept;ok
-udplite dport { 70-75} accept;ok;udplite dport { 70-75} accept
+udplite dport { 70-75} accept;ok
- udplite dport != { 50-60} accept;ok
- udplite csumcov 6666;ok
@@ -34,8 +34,8 @@ udplite checksum 6666 drop;ok
- udplite checksum != { 444, 555} accept;ok
udplite checksum 22;ok
udplite checksum != 233;ok
-udplite checksum 33-45;ok;udplite checksum >= 33 udplite checksum <= 45
-udplite checksum != 33-45;ok;udplite checksum < 33 udplite checksum > 45
+udplite checksum 33-45;ok
+udplite checksum != 33-45;ok
udplite checksum { 33, 55, 67, 88};ok
- udplite checksum != { 33, 55, 67, 88};ok
udplite checksum { 33-55};ok
diff --git a/tests/regression/ip/dnat.t b/tests/regression/ip/dnat.t
new file mode 100644
index 00000000..78fc454d
--- /dev/null
+++ b/tests/regression/ip/dnat.t
@@ -0,0 +1,12 @@
+*ip;test-ip4
+:prerouting;type nat hook prerouting priority 0
+
+iifname "eth0" tcp dport 80-90 dnat 192.168.3.2;ok
+iifname "eth0" tcp dport != 80-90 dnat 192.168.3.2;ok
+iifname "eth0" tcp dport {80, 90, 23} dnat 192.168.3.2;ok
+- iifname "eth0" tcp dport != {80, 90, 23} dnat 192.168.3.2;ok
+- iifname "eth0" tcp dport != {80, 90, 23} dnat 192.168.3.2;ok
+# BUG: invalid expression type set
+# nft: src/evaluate.c:975: expr_evaluate_relational: Assertion '0' failed.
+
+iifname "eth0" tcp dport != 23-34 dnat 192.168.3.2;ok
diff --git a/tests/regression/ip/icmp.t b/tests/regression/ip/icmp.t
index cd43a668..9c2aba78 100644
--- a/tests/regression/ip/icmp.t
+++ b/tests/regression/ip/icmp.t
@@ -24,8 +24,8 @@ icmp type {echo-reply, destination-unreachable, source-quench, redirect, echo-re
icmp code 111 accept;ok
icmp code != 111 accept;ok
-icmp code 33-55;ok;icmp code >= 33 icmp code <= 55
-icmp code != 33-55;ok;icmp code < 33 icmp code > 55
+icmp code 33-55;ok
+icmp code != 33-55;ok
icmp code { 33-55};ok
- icmp code != { 33-55};ok
icmp code { 2, 4, 54, 33, 56};ok
@@ -36,8 +36,8 @@ icmp code { 2, 4, 54, 33, 56};ok
icmp checksum 12343 accept;ok
icmp checksum != 12343 accept;ok
-icmp checksum 11-343 accept;ok;icmp checksum >= 11 icmp checksum <= 343 accept
-icmp checksum != 11-343 accept;ok;icmp checksum < 11 icmp checksum > 343 accept
+icmp checksum 11-343 accept;ok
+icmp checksum != 11-343 accept;ok
icmp checksum { 11-343} accept;ok
- icmp checksum != { 11-343} accept;ok
icmp checksum { 1111, 222, 343} accept;ok
@@ -49,8 +49,8 @@ icmp checksum { 1111, 222, 343} accept;ok
icmp id 1245 log;ok
icmp id 22;ok
icmp id != 233;ok
-icmp id 33-45;ok;icmp id >= 33 icmp id <= 45
-icmp id != 33-45;ok;icmp id < 33 icmp id > 45
+icmp id 33-45;ok
+icmp id != 33-45;ok
icmp id { 33-55};ok
- icmp id != { 33-55};ok
icmp id { 22, 34, 333};ok
@@ -61,8 +61,8 @@ icmp id { 22, 34, 333};ok
icmp sequence 22;ok
icmp sequence != 233;ok
-icmp sequence 33-45;ok;icmp sequence >= 33 icmp sequence <= 45
-icmp sequence != 33-45;ok;icmp sequence < 33 icmp sequence > 45
+icmp sequence 33-45;ok
+icmp sequence != 33-45;ok
icmp sequence { 33, 55, 67, 88};ok
- icmp sequence != { 33, 55, 67, 88};ok
icmp sequence { 33-55};ok
@@ -83,8 +83,8 @@ icmp mtu { 33-55};ok
icmp gateway 22;ok
icmp gateway != 233;ok
-icmp gateway 33-45;ok;icmp gateway >= 33 icmp gateway <= 45
-icmp gateway != 33-45;ok;icmp gateway < 33 icmp gateway > 45
+icmp gateway 33-45;ok
+icmp gateway != 33-45;ok
icmp gateway { 33, 55, 67, 88};ok
- icmp gateway != { 33, 55, 67, 88};ok
icmp gateway { 33-55};ok
diff --git a/tests/regression/ip/ip.t b/tests/regression/ip/ip.t
index a781de5b..fa864dfd 100644
--- a/tests/regression/ip/ip.t
+++ b/tests/regression/ip/ip.t
@@ -30,8 +30,8 @@
ip length 232;ok
ip length != 233;ok
-ip length 333-435;ok;ip length >= 333 ip length <= 435
-ip length != 333-453;ok;ip length < 333 ip length > 453
+ip length 333-435;ok
+ip length != 333-453;ok
ip length { 333, 553, 673, 838};ok
- ip length != { 333, 535, 637, 883};ok
ip length { 333-535};ok
@@ -39,8 +39,8 @@ ip length { 333-535};ok
ip id 22;ok
ip id != 233;ok
-ip id 33-45;ok;ip id >= 33 ip id <= 45
-ip id != 33-45;ok;ip id < 33 ip id > 45
+ip id 33-45;ok
+ip id != 33-45;ok
ip id { 33, 55, 67, 88};ok
- ip id != { 33, 55, 67, 88};ok
ip id { 33-55};ok
@@ -48,8 +48,8 @@ ip id { 33-55};ok
ip frag-off 222 accept;ok
ip frag-off != 233;ok
-ip frag-off 33-45;ok;ip frag-off >= 33 ip frag-off <= 45
-ip frag-off != 33-45;ok;ip frag-off < 33 ip frag-off > 45
+ip frag-off 33-45;ok
+ip frag-off != 33-45;ok
ip frag-off { 33, 55, 67, 88};ok
- ip frag-off != { 33, 55, 67, 88};ok
ip frag-off { 33-55};ok
@@ -57,8 +57,8 @@ ip frag-off { 33-55};ok
ip ttl 0 drop;ok
ip ttl 233 log;ok
-ip ttl 33-55;ok;ip ttl >= 33 ip ttl <= 55
-ip ttl != 45-50;ok;ip ttl < 45 ip ttl > 50
+ip ttl 33-55;ok
+ip ttl != 45-50;ok
ip ttl {43, 53, 45 };ok
- ip ttl != {46, 56, 93 };ok
# BUG: ip ttl != {46, 56, 93 };ok
@@ -75,8 +75,8 @@ ip protocol { icmp, esp, ah, comp, udp, udplite, tcp, dccp, sctp} accept;ok;ip p
ip checksum 13172 drop;ok
ip checksum 22;ok
ip checksum != 233;ok
-ip checksum 33-45;ok;ip checksum >= 33 ip checksum <= 45
-ip checksum != 33-45;ok;ip checksum < 33 ip checksum > 45
+ip checksum 33-45;ok
+ip checksum != 33-45;ok
ip checksum { 33, 55, 67, 88};ok
- ip checksum != { 33, 55, 67, 88};ok
ip checksum { 33-55};ok
@@ -87,20 +87,20 @@ ip saddr != 192.168.2.0/24;ok
ip saddr 192.168.3.1 ip daddr 192.168.3.100;ok
ip saddr != 1.1.1.1 log prefix giuseppe;ok;ip saddr != 1.1.1.1 log prefix "giuseppe"
ip saddr 1.1.1.1 log prefix example group 1;ok;ip saddr 1.1.1.1 log prefix "example" group 1
-ip daddr 192.168.0.1-192.168.0.250;ok;ip daddr >= 192.168.0.1 ip daddr <= 192.168.0.250
-ip daddr 10.0.0.0-10.255.255.255;ok;ip daddr >= 10.0.0.0 ip daddr <= 10.255.255.255
-ip daddr 172.16.0.0-172.31.255.255;ok;ip daddr >= 172.16.0.0 ip daddr <= 172.31.255.255
-ip daddr 192.168.3.1-192.168.4.250;ok;ip daddr >= 192.168.3.1 ip daddr <= 192.168.4.250
-ip daddr != 192.168.0.1-192.168.0.250;ok;ip daddr < 192.168.0.1 ip daddr > 192.168.0.250
+ip daddr 192.168.0.1-192.168.0.250;ok
+ip daddr 10.0.0.0-10.255.255.255;ok
+ip daddr 172.16.0.0-172.31.255.255;ok
+ip daddr 192.168.3.1-192.168.4.250;ok
+ip daddr != 192.168.0.1-192.168.0.250;ok
ip daddr { 192.168.0.1-192.168.0.250};ok
- ip daddr != { 192.168.0.1-192.168.0.250};ok
ip daddr { 192.168.5.1, 192.168.5.2, 192.168.5.3 } accept;ok
- ip daddr != { 192.168.5.1, 192.168.5.2, 192.168.5.3 } accept;ok
-ip daddr 192.168.1.2-192.168.1.55;ok;ip daddr >= 192.168.1.2 ip daddr <= 192.168.1.55
-ip daddr != 192.168.1.2-192.168.1.55;ok;ip daddr < 192.168.1.2 ip daddr > 192.168.1.55
-ip saddr 192.168.1.3-192.168.33.55;ok;ip saddr >= 192.168.1.3 ip saddr <= 192.168.33.55
-ip saddr != 192.168.1.3-192.168.33.55;ok;ip saddr < 192.168.1.3 ip saddr > 192.168.33.55
+ip daddr 192.168.1.2-192.168.1.55;ok
+ip daddr != 192.168.1.2-192.168.1.55;ok
+ip saddr 192.168.1.3-192.168.33.55;ok
+ip saddr != 192.168.1.3-192.168.33.55;ok
ip daddr 192.168.0.1;ok
ip daddr 192.168.0.1 drop;ok
diff --git a/tests/regression/ip/masquerade.t b/tests/regression/ip/masquerade.t
index d0fe02d1..35001f37 100644
--- a/tests/regression/ip/masquerade.t
+++ b/tests/regression/ip/masquerade.t
@@ -21,5 +21,5 @@ ip saddr 10.1.1.1 masquerade drop;fail
# masquerade with sets
tcp dport { 1,2,3,4,5,6,7,8,101,202,303,1001,2002,3003} masquerade;ok
-ip daddr 10.0.0.0-10.2.3.4 udp dport 53 counter packets 0 bytes 0 masquerade;ok;ip daddr >= 10.0.0.0 ip daddr <= 10.2.3.4 udp dport 53 counter packets 0 bytes 0 masquerade
+ip daddr 10.0.0.0-10.2.3.4 udp dport 53 counter packets 0 bytes 0 masquerade;ok
iifname eth0 ct state new,established tcp dport vmap {22 : drop, 222 : drop } masquerade;ok
diff --git a/tests/regression/ip/nat.t b/tests/regression/ip/nat.t
deleted file mode 100644
index 5afe823a..00000000
--- a/tests/regression/ip/nat.t
+++ /dev/null
@@ -1,18 +0,0 @@
-*ip;test-ip4
-# bug: Nat tables is not supported yet in inet table.
--*inet;test-inet
-
-:output;type nat hook output priority 0
-
-iifname eth0 tcp dport 80-90 dnat 192.168.3.2;ok;iifname "eth0" tcp dport >= 80 tcp dport <= 90 dnat 192.168.3.2
-iifname eth0 tcp dport != 80-90 dnat 192.168.3.2;ok;iifname "eth0" tcp dport < 80 tcp dport > 90 dnat 192.168.3.2
-iifname eth0 tcp dport {80, 90, 23} dnat 192.168.3.2;ok
-- iifname eth0 tcp dport != {80, 90, 23} dnat 192.168.3.2;ok
-
-iifname eth0 tcp sport 23-34 snat 192.168.3.2;ok;iifname "eth0" tcp sport >= 23 tcp sport <= 34 snat 192.168.3.2
-
-- iifname eth0 tcp dport != {80, 90, 23} dnat 192.168.3.2;ok
-# BUG: invalid expression type set
-# nft: src/evaluate.c:975: expr_evaluate_relational: Assertion '0' failed.
-
-iifname eth0 tcp dport != 23-34 dnat 192.168.3.2;ok;iifname "eth0" tcp dport < 23 tcp dport > 34 dnat 192.168.3.2
diff --git a/tests/regression/ip/redirect.t b/tests/regression/ip/redirect.t
index bbf440d1..b7eecb74 100644
--- a/tests/regression/ip/redirect.t
+++ b/tests/regression/ip/redirect.t
@@ -41,5 +41,5 @@ ip saddr 10.1.1.1 redirect drop;fail
# redirect with sets
tcp dport { 1, 2, 3, 4, 5, 6, 7, 8, 101, 202, 303, 1001, 2002, 3003} redirect;ok
-ip daddr 10.0.0.0-10.2.3.4 udp dport 53 counter packets 0 bytes 0 redirect;ok;ip daddr >= 10.0.0.0 ip daddr <= 10.2.3.4 udp dport 53 counter packets 0 bytes 0 redirect
+ip daddr 10.0.0.0-10.2.3.4 udp dport 53 counter packets 0 bytes 0 redirect;ok
iifname eth0 ct state new,established tcp dport vmap {22 : drop, 222 : drop } redirect;ok
diff --git a/tests/regression/ip/snat.t b/tests/regression/ip/snat.t
new file mode 100644
index 00000000..1caf7c76
--- /dev/null
+++ b/tests/regression/ip/snat.t
@@ -0,0 +1,12 @@
+*ip;test-ip4
+:postrouting;type nat hook postrouting priority 0
+
+iifname "eth0" tcp dport 80-90 snat 192.168.3.2;ok
+iifname "eth0" tcp dport != 80-90 snat 192.168.3.2;ok
+iifname "eth0" tcp dport {80, 90, 23} snat 192.168.3.2;ok
+- iifname "eth0" tcp dport != {80, 90, 23} snat 192.168.3.2;ok
+- iifname "eth0" tcp dport != {80, 90, 23} snat 192.168.3.2;ok
+# BUG: invalid expression type set
+# nft: src/evaluate.c:975: expr_evaluate_relational: Assertion '0' failed.
+
+iifname "eth0" tcp dport != 23-34 snat 192.168.3.2;ok
diff --git a/tests/regression/ip6/nat.t b/tests/regression/ip6/dnat.t
index 2fb4ac81..a2555c72 100644
--- a/tests/regression/ip6/nat.t
+++ b/tests/regression/ip6/dnat.t
@@ -1,6 +1,5 @@
*ip6;test-ip6
-- *inet;test-inet
-:input;type nat hook input priority 0
+:prerouting;type nat hook prerouting priority 0
tcp dport 80-90 dnat 2001:838:35f:1::-2001:838:35f:2:: :80-100;ok
tcp dport 80-90 dnat 2001:838:35f:1::-2001:838:35f:2:: :100;ok
diff --git a/tests/regression/ip6/dst.t b/tests/regression/ip6/dst.t
index 1b1bc52a..3207af76 100644
--- a/tests/regression/ip6/dst.t
+++ b/tests/regression/ip6/dst.t
@@ -4,8 +4,8 @@
dst nexthdr 22;ok
dst nexthdr != 233;ok
-dst nexthdr 33-45;ok;dst nexthdr >= 33 dst nexthdr <= 45
-dst nexthdr != 33-45;ok;dst nexthdr < 33 dst nexthdr > 45
+dst nexthdr 33-45;ok
+dst nexthdr != 33-45;ok
dst nexthdr { 33, 55, 67, 88};ok
- dst nexthdr != { 33, 55, 67, 88};ok
dst nexthdr { 33-55};ok
@@ -17,8 +17,8 @@ dst nexthdr != icmp;ok;dst nexthdr != 1
dst hdrlength 22;ok
dst hdrlength != 233;ok
-dst hdrlength 33-45;ok;dst hdrlength >= 33 dst hdrlength <= 45
-dst hdrlength != 33-45;ok;dst hdrlength < 33 dst hdrlength > 45
+dst hdrlength 33-45;ok
+dst hdrlength != 33-45;ok
dst hdrlength { 33, 55, 67, 88};ok
- dst hdrlength != { 33, 55, 67, 88};ok
dst hdrlength { 33-55};ok
diff --git a/tests/regression/ip6/hbh.t b/tests/regression/ip6/hbh.t
index b274b8b7..4e67c42a 100644
--- a/tests/regression/ip6/hbh.t
+++ b/tests/regression/ip6/hbh.t
@@ -4,8 +4,8 @@
hbh hdrlength 22;ok
hbh hdrlength != 233;ok
-hbh hdrlength 33-45;ok;hbh hdrlength >= 33 hbh hdrlength <= 45
-hbh hdrlength != 33-45;ok;hbh hdrlength < 33 hbh hdrlength > 45
+hbh hdrlength 33-45;ok
+hbh hdrlength != 33-45;ok
hbh hdrlength {33, 55, 67, 88};ok
- hbh hdrlength != {33, 55, 67, 88};ok
hbh hdrlength { 33-55};ok
@@ -15,8 +15,8 @@ hbh nexthdr {esp, ah, comp, udp, udplite, tcp, dccp, sctp, icmpv6};ok;hbh nexthd
- hbh nexthdr != {esp, ah, comp, udp, udplite, tcp, dccp, sctp, icmpv6};ok
hbh nexthdr 22;ok
hbh nexthdr != 233;ok
-hbh nexthdr 33-45;ok;hbh nexthdr >= 33 hbh nexthdr <= 45
-hbh nexthdr != 33-45;ok;hbh nexthdr < 33 hbh nexthdr > 45
+hbh nexthdr 33-45;ok
+hbh nexthdr != 33-45;ok
hbh nexthdr {33, 55, 67, 88};ok
- hbh nexthdr != {33, 55, 67, 88};ok
hbh nexthdr { 33-55};ok
diff --git a/tests/regression/ip6/ip6.t b/tests/regression/ip6/ip6.t
index 243c7894..529a0687 100644
--- a/tests/regression/ip6/ip6.t
+++ b/tests/regression/ip6/ip6.t
@@ -29,8 +29,8 @@ ip6 flowlabel { 33-55};ok
ip6 length 22;ok
ip6 length != 233;ok
-ip6 length 33-45;ok;ip6 length >= 33 ip6 length <= 45
-ip6 length != 33-45;ok;ip6 length < 33 ip6 length > 45
+ip6 length 33-45;ok
+ip6 length != 33-45;ok
- ip6 length { 33, 55, 67, 88};ok
- ip6 length != {33, 55, 67, 88};ok
ip6 length { 33-55};ok
@@ -43,13 +43,13 @@ ip6 nexthdr esp;ok;ip6 nexthdr 50
ip6 nexthdr != esp;ok;ip6 nexthdr != 50
ip6 nexthdr { 33-44};ok
- p6 nexthdr != { 33-44};ok
-ip6 nexthdr 33-44;ok;ip6 nexthdr >= 33 ip6 nexthdr <= 44
-ip6 nexthdr != 33-44;ok;ip6 nexthdr < 33 ip6 nexthdr > 44
+ip6 nexthdr 33-44;ok
+ip6 nexthdr != 33-44;ok
ip6 hoplimit 1 log;ok
ip6 hoplimit != 233;ok
-ip6 hoplimit 33-45;ok;ip6 hoplimit >= 33 ip6 hoplimit <= 45
-ip6 hoplimit != 33-45;ok;ip6 hoplimit < 33 ip6 hoplimit > 45
+ip6 hoplimit 33-45;ok
+ip6 hoplimit != 33-45;ok
ip6 hoplimit {33, 55, 67, 88};ok
- ip6 hoplimit != {33, 55, 67, 88};ok
ip6 hoplimit {33-55};ok
diff --git a/tests/regression/ip6/masquerade.t b/tests/regression/ip6/masquerade.t
index 817acd4f..4e6c086c 100644
--- a/tests/regression/ip6/masquerade.t
+++ b/tests/regression/ip6/masquerade.t
@@ -21,5 +21,5 @@ ip6 saddr ::1 masquerade drop;fail
# masquerade with sets
tcp dport { 1,2,3,4,5,6,7,8,101,202,303,1001,2002,3003} masquerade;ok
-ip6 daddr fe00::1-fe00::200 udp dport 53 counter packets 0 bytes 0 masquerade;ok;ip6 daddr >= fe00::1 ip6 daddr <= fe00::200 udp dport 53 counter packets 0 bytes 0 masquerade
+ip6 daddr fe00::1-fe00::200 udp dport 53 counter packets 0 bytes 0 masquerade;ok
iifname eth0 ct state new,established tcp dport vmap {22 : drop, 222 : drop } masquerade;ok
diff --git a/tests/regression/ip6/mh.t b/tests/regression/ip6/mh.t
index 4ff58a17..cd652b39 100644
--- a/tests/regression/ip6/mh.t
+++ b/tests/regression/ip6/mh.t
@@ -10,8 +10,8 @@ mh nexthdr icmp;ok;mh nexthdr 1
mh nexthdr != icmp;ok;mh nexthdr != 1
mh nexthdr 22;ok
mh nexthdr != 233;ok
-mh nexthdr 33-45;ok;mh nexthdr >= 33 mh nexthdr <= 45
-mh nexthdr != 33-45;ok;mh nexthdr < 33 mh nexthdr > 45
+mh nexthdr 33-45;ok
+mh nexthdr != 33-45;ok
mh nexthdr { 33, 55, 67, 88 };ok
- mh nexthdr != { 33, 55, 67, 88 };ok
mh nexthdr { 33-55 };ok
@@ -19,9 +19,9 @@ mh nexthdr { 33-55 };ok
mh hdrlength 22;ok
mh hdrlength != 233;ok
-mh hdrlength 33-45;ok;mh hdrlength >= 33 mh hdrlength <= 45
-mh hdrlength != 33-45;ok;mh hdrlength < 33 mh hdrlength > 45
-mh hdrlength { 33, 55, 67, 88 };ok;mh hdrlength { 67, 33, 88, 55}
+mh hdrlength 33-45;ok
+mh hdrlength != 33-45;ok
+mh hdrlength { 33, 55, 67, 88 };ok
- mh hdrlength != { 33, 55, 67, 88 };ok
mh hdrlength { 33-55 };ok
- mh hdrlength != { 33-55 };ok
@@ -32,8 +32,8 @@ mh type != home-agent-switch-message;ok
mh reserved 22;ok
mh reserved != 233;ok
-mh reserved 33-45;ok;mh reserved >= 33 mh reserved <= 45
-mh reserved != 33-45;ok;mh reserved < 33 mh reserved > 45
+mh reserved 33-45;ok
+mh reserved != 33-45;ok
mh reserved { 33, 55, 67, 88};ok
- mh reserved != {33, 55, 67, 88};ok
mh reserved { 33-55};ok
@@ -41,8 +41,8 @@ mh reserved { 33-55};ok
mh checksum 22;ok
mh checksum != 233;ok
-mh checksum 33-45;ok;mh checksum >= 33 mh checksum <= 45
-mh checksum != 33-45;ok;mh checksum < 33 mh checksum > 45
+mh checksum 33-45;ok
+mh checksum != 33-45;ok
mh checksum { 33, 55, 67, 88};ok
- mh checksum != { 33, 55, 67, 88};ok
mh checksum { 33-55};ok
diff --git a/tests/regression/ip6/redirect.t b/tests/regression/ip6/redirect.t
index 730d7339..31ffe8c9 100644
--- a/tests/regression/ip6/redirect.t
+++ b/tests/regression/ip6/redirect.t
@@ -40,5 +40,5 @@ ip6 saddr ::1 redirect drop;fail
# redirect with sets
tcp dport { 1, 2, 3, 4, 5, 6, 7, 8, 101, 202, 303, 1001, 2002, 3003} redirect;ok
-ip6 daddr fe00::1-fe00::200 udp dport 53 counter packets 0 bytes 0 redirect;ok;ip6 daddr >= fe00::1 ip6 daddr <= fe00::200 udp dport 53 counter packets 0 bytes 0 redirect
+ip6 daddr fe00::1-fe00::200 udp dport 53 counter packets 0 bytes 0 redirect;ok
iifname eth0 ct state new,established tcp dport vmap {22 : drop, 222 : drop } redirect;ok
diff --git a/tests/regression/ip6/rt.t b/tests/regression/ip6/rt.t
index 76579ba5..eca47ca8 100644
--- a/tests/regression/ip6/rt.t
+++ b/tests/regression/ip6/rt.t
@@ -10,8 +10,8 @@ rt nexthdr icmp;ok;rt nexthdr 1
rt nexthdr != icmp;ok;rt nexthdr != 1
rt nexthdr 22;ok
rt nexthdr != 233;ok
-rt nexthdr 33-45;ok;rt nexthdr >= 33 rt nexthdr <= 45
-rt nexthdr != 33-45;ok;rt nexthdr < 33 rt nexthdr > 45
+rt nexthdr 33-45;ok
+rt nexthdr != 33-45;ok
rt nexthdr { 33, 55, 67, 88};ok
- rt nexthdr != { 33, 55, 67, 88};ok
rt nexthdr { 33-55};ok;rt nexthdr { 33-55}
@@ -19,8 +19,8 @@ rt nexthdr { 33-55};ok;rt nexthdr { 33-55}
rt hdrlength 22;ok
rt hdrlength != 233;ok
-rt hdrlength 33-45;ok;rt hdrlength >= 33 rt hdrlength <= 45
-rt hdrlength != 33-45;ok;rt hdrlength < 33 rt hdrlength > 45
+rt hdrlength 33-45;ok
+rt hdrlength != 33-45;ok
rt hdrlength { 33, 55, 67, 88};ok
- rt hdrlength != { 33, 55, 67, 88};ok
rt hdrlength { 33-55};ok
@@ -28,8 +28,8 @@ rt hdrlength { 33-55};ok
rt type 22;ok
rt type != 233;ok
-rt type 33-45;ok;rt type >= 33 rt type <= 45
-rt type != 33-45;ok;rt type < 33 rt type > 45
+rt type 33-45;ok
+rt type != 33-45;ok
rt type { 33, 55, 67, 88};ok
- rt type != { 33, 55, 67, 88};ok
rt type { 33-55};ok
@@ -37,8 +37,8 @@ rt type { 33-55};ok
rt seg-left 22;ok
rt seg-left != 233;ok
-rt seg-left 33-45;ok;rt seg-left >= 33 rt seg-left <= 45
-rt seg-left != 33-45;ok;rt seg-left < 33 rt seg-left > 45
+rt seg-left 33-45;ok
+rt seg-left != 33-45;ok
rt seg-left { 33, 55, 67, 88};ok
- rt seg-left != { 33, 55, 67, 88};ok
rt seg-left { 33-55};ok
diff --git a/tests/regression/ip6/snat.t b/tests/regression/ip6/snat.t
new file mode 100644
index 00000000..73452752
--- /dev/null
+++ b/tests/regression/ip6/snat.t
@@ -0,0 +1,6 @@
+*ip6;test-ip6
+- *inet;test-inet
+:postrouting;type nat hook postrouting priority 0
+
+tcp dport 80-90 snat 2001:838:35f:1::-2001:838:35f:2:: :80-100;ok
+tcp dport 80-90 snat 2001:838:35f:1::-2001:838:35f:2:: :100;ok
diff --git a/tests/regression/nft-test.py b/tests/regression/nft-test.py
index 559ad41f..7823f44c 100755
--- a/tests/regression/nft-test.py
+++ b/tests/regression/nft-test.py
@@ -44,26 +44,21 @@ class Colors:
RED = ''
ENDC = ''
-def print_error(reason, filename=None, lineno=None):
+def print_msg(reason, filename=None, lineno=None, color=None, errstr=None):
'''
- Prints an error with nice colors, indicating file and line number.
+ Prints a message with nice colors, indicating file and line number.
'''
if filename and lineno:
- print (filename + ": " + Colors.RED + "ERROR:" +
+ print (filename + ": " + color + "ERROR:" +
Colors.ENDC + " line %d: %s" % (lineno + 1, reason))
else:
- print (Colors.RED + "ERROR:" + Colors.ENDC + " %s" % (reason))
+ print (color + "ERROR:" + Colors.ENDC + " %s" % (reason))
+def print_error(reason, filename=None, lineno=None):
+ print_msg(reason, filename, lineno, Colors.RED, "ERROR:")
def print_warning(reason, filename=None, lineno=None):
- '''
- Prints a warning with nice colors, indicating file and line number.
- '''
- if filename and lineno:
- print (filename + ": " + Colors.YELLOW + "WARNING:" + \
- Colors.ENDC + " line %d: %s" % (lineno + 1, reason))
- else:
- print (Colors.YELLOW + "WARNING:" + " %s" % (reason))
+ print_msg(reason, filename, lineno, Colors.YELLOW, "WARNING:")
def print_differences_warning(filename, lineno, rule1, rule2, cmd):