@@ -972,6 +972,7 @@ enum nft_osf_attributes {
* @NFT_CT_DST_IP: conntrack layer 3 protocol destination (IPv4 address)
* @NFT_CT_SRC_IP6: conntrack layer 3 protocol source (IPv6 address)
* @NFT_CT_DST_IP6: conntrack layer 3 protocol destination (IPv6 address)
+ * @NFT_CT_TIMEOUT: connection tracking timeout policy assigned to conntrack
*/
enum nft_ct_keys {
NFT_CT_STATE,
@@ -997,6 +998,7 @@ enum nft_ct_keys {
NFT_CT_DST_IP,
NFT_CT_SRC_IP6,
NFT_CT_DST_IP6,
+ NFT_CT_TIMEOUT,
__NFT_CT_MAX
};
#define NFT_CT_MAX (__NFT_CT_MAX - 1)
@@ -1403,13 +1405,23 @@ enum nft_ct_helper_attributes {
};
#define NFTA_CT_HELPER_MAX (__NFTA_CT_HELPER_MAX - 1)
+enum nft_ct_timeout_attributes {
+ NFTA_CT_TIMEOUT_L3PROTO,
+ NFTA_CT_TIMEOUT_L4PROTO,
+ NFTA_CT_TIMEOUT_DATA,
+ __NFTA_CT_TIMEOUT_MAX,
+};
+#define NFTA_CT_TIMEOUT_MAX (__NFTA_CT_TIMEOUT_MAX - 1)
+
#define NFT_OBJECT_UNSPEC 0
#define NFT_OBJECT_COUNTER 1
#define NFT_OBJECT_QUOTA 2
#define NFT_OBJECT_CT_HELPER 3
#define NFT_OBJECT_LIMIT 4
#define NFT_OBJECT_CONNLIMIT 5
-#define __NFT_OBJECT_MAX 6
+#define NFT_OBJECT_TUNNEL 6
+#define NFT_OBJECT_CT_TIMEOUT 7
+#define __NFT_OBJECT_MAX 8
#define NFT_OBJECT_MAX (__NFT_OBJECT_MAX - 1)
/**
@@ -4,6 +4,7 @@
#include <stdint.h>
#include <nftables.h>
#include <list.h>
+#include <netinet/in.h>
/**
* struct handle_spec - handle ID
@@ -308,6 +309,18 @@ struct ct_helper {
uint8_t l4proto;
};
+struct ct_timeout {
+ uint16_t l3proto;
+ uint8_t l4proto;
+ uint32_t *timeout;
+ struct timeout_state {
+ uint8_t timeout_index;
+ uint32_t timeout_value;
+ uint8_t l4;
+ struct list_head timeout_list;
+ } timeout_state;
+};
+
struct limit {
uint64_t rate;
uint64_t unit;
@@ -336,6 +349,7 @@ struct obj {
struct quota quota;
struct ct_helper ct_helper;
struct limit limit;
+ struct ct_timeout ct_timeout;
};
};
@@ -462,6 +476,7 @@ enum cmd_obj {
CMD_OBJ_LIMITS,
CMD_OBJ_FLOWTABLE,
CMD_OBJ_FLOWTABLES,
+ CMD_OBJ_CT_TIMEOUT,
};
struct markup {
@@ -617,4 +632,13 @@ enum udata_set_elem_flags {
SET_ELEM_F_INTERVAL_OPEN = 0x1,
};
+struct timeout_protocol {
+ uint32_t attr_max;
+ const char *const *state_to_name;
+ uint32_t *dflt_timeout;
+};
+
+extern struct timeout_protocol timeout_protocol[IPPROTO_MAX];
+extern void timeout_str2num(const char *timeout_state, struct timeout_state *ts);
+
#endif /* NFTABLES_RULE_H */
@@ -3224,6 +3224,7 @@ static int cmd_evaluate_add(struct eval_ctx *ctx, struct cmd *cmd)
case CMD_OBJ_COUNTER:
case CMD_OBJ_QUOTA:
case CMD_OBJ_CT_HELPER:
+ case CMD_OBJ_CT_TIMEOUT:
case CMD_OBJ_LIMIT:
return 0;
default:
@@ -3251,6 +3252,7 @@ static int cmd_evaluate_delete(struct eval_ctx *ctx, struct cmd *cmd)
case CMD_OBJ_COUNTER:
case CMD_OBJ_QUOTA:
case CMD_OBJ_CT_HELPER:
+ case CMD_OBJ_CT_TIMEOUT:
case CMD_OBJ_LIMIT:
return 0;
default:
@@ -3383,6 +3385,8 @@ static int cmd_evaluate_list(struct eval_ctx *ctx, struct cmd *cmd)
return cmd_evaluate_list_obj(ctx, cmd, NFT_OBJECT_COUNTER);
case CMD_OBJ_CT_HELPER:
return cmd_evaluate_list_obj(ctx, cmd, NFT_OBJECT_CT_HELPER);
+ case CMD_OBJ_CT_TIMEOUT:
+ return cmd_evaluate_list_obj(ctx, cmd, NFT_OBJECT_CT_TIMEOUT);
case CMD_OBJ_LIMIT:
return cmd_evaluate_list_obj(ctx, cmd, NFT_OBJECT_LIMIT);
case CMD_OBJ_COUNTERS:
@@ -41,6 +41,7 @@
#include <utils.h>
#include <erec.h>
#include <iface.h>
+//#include <rule.h>
#define nft_mon_print(monh, ...) nft_print(monh->ctx->octx, __VA_ARGS__)
@@ -334,6 +335,14 @@ alloc_nftnl_obj(const struct handle *h, struct obj *obj)
nftnl_obj_set_u16(nlo, NFTNL_OBJ_CT_HELPER_L3PROTO,
obj->ct_helper.l3proto);
break;
+ case NFT_OBJECT_CT_TIMEOUT:
+ nftnl_obj_set_u8(nlo, NFTNL_OBJ_CT_TIMEOUT_L4PROTO,
+ obj->ct_timeout.l4proto);
+ if (obj->ct_timeout.l3proto)
+ nftnl_obj_set_u16(nlo, NFTNL_OBJ_CT_TIMEOUT_L3PROTO,
+ obj->ct_timeout.l3proto);
+ nftnl_obj_set(nlo, NFTNL_OBJ_CT_TIMEOUT_ARRAY, obj->ct_timeout.timeout);
+ break;
case NFT_OBJECT_LIMIT:
nftnl_obj_set_u64(nlo, NFTNL_OBJ_LIMIT_RATE, obj->limit.rate);
nftnl_obj_set_u64(nlo, NFTNL_OBJ_LIMIT_UNIT, obj->limit.unit);
@@ -1437,6 +1446,11 @@ struct obj *netlink_delinearize_obj(struct netlink_ctx *ctx,
obj->ct_helper.l3proto = nftnl_obj_get_u16(nlo, NFTNL_OBJ_CT_HELPER_L3PROTO);
obj->ct_helper.l4proto = nftnl_obj_get_u8(nlo, NFTNL_OBJ_CT_HELPER_L4PROTO);
break;
+ case NFT_OBJECT_CT_TIMEOUT:
+ obj->ct_timeout.l3proto = nftnl_obj_get_u16(nlo, NFTNL_OBJ_CT_TIMEOUT_L3PROTO);
+ obj->ct_timeout.l4proto = nftnl_obj_get_u8(nlo, NFTNL_OBJ_CT_TIMEOUT_L4PROTO);
+ obj->ct_timeout.timeout = (uint32_t *)nftnl_obj_get(nlo, NFTNL_OBJ_CT_TIMEOUT_ARRAY);
+ break;
case NFT_OBJECT_LIMIT:
obj->limit.rate =
nftnl_obj_get_u64(nlo, NFTNL_OBJ_LIMIT_RATE);
@@ -550,7 +550,7 @@ int nft_lex(void *, void *, void *);
%type <flowtable> flowtable_block_alloc flowtable_block
%destructor { flowtable_free($$); } flowtable_block_alloc
-%type <obj> obj_block_alloc counter_block quota_block ct_helper_block limit_block
+%type <obj> obj_block_alloc counter_block quota_block ct_helper_block ct_timeout_block limit_block
%destructor { obj_free($$); } obj_block_alloc
%type <list> stmt_list
@@ -753,6 +753,9 @@ int nft_lex(void *, void *, void *);
%type <val> ct_l4protoname ct_obj_type
+%type <list> timeout_states timeout_state
+%destructor { xfree($$); } timeout_states timeout_state
+
%%
input : /* empty */
@@ -960,6 +963,10 @@ add_cmd : TABLE table_spec
$$ = cmd_alloc_obj_ct(CMD_ADD, NFT_OBJECT_CT_HELPER, &$3, &@$, $4);
}
+ | CT TIMEOUT obj_spec ct_obj_alloc '{' ct_timeout_block '}' stmt_separator
+ {
+ $$ = cmd_alloc_obj_ct(CMD_ADD, NFT_OBJECT_CT_TIMEOUT, &$3, &@$, $4);
+ }
| LIMIT obj_spec limit_obj
{
$$ = cmd_alloc(CMD_ADD, CMD_OBJ_LIMIT, &$2, &@$, $3);
@@ -1041,6 +1048,10 @@ create_cmd : TABLE table_spec
{
$$ = cmd_alloc_obj_ct(CMD_CREATE, NFT_OBJECT_CT_HELPER, &$3, &@$, $4);
}
+ | CT TIMEOUT obj_spec ct_obj_alloc '{' ct_timeout_block '}' stmt_separator
+ {
+ $$ = cmd_alloc_obj_ct(CMD_CREATE, NFT_OBJECT_CT_TIMEOUT, &$3, &@$, $4);
+ }
| LIMIT obj_spec limit_obj
{
$$ = cmd_alloc(CMD_CREATE, CMD_OBJ_LIMIT, &$2, &@$, $3);
@@ -1233,6 +1244,10 @@ list_cmd : TABLE table_spec
{
$$ = cmd_alloc(CMD_LIST, CMD_OBJ_CT_HELPERS, &$4, &@$, NULL);
}
+ | CT TIMEOUT TABLE table_spec
+ {
+ $$ = cmd_alloc(CMD_LIST, CMD_OBJ_CT_TIMEOUT, &$4, &@$, NULL);
+ }
;
reset_cmd : COUNTERS ruleset_spec
@@ -1464,6 +1479,15 @@ table_block : /* empty */ { $$ = $<table>-1; }
list_add_tail(&$5->list, &$1->objs);
$$ = $1;
}
+ | table_block CT TIMEOUT obj_identifier obj_block_alloc '{' ct_timeout_block '}' stmt_separator
+ {
+ $5->location = @4;
+ $5->type = NFT_OBJECT_CT_TIMEOUT;
+ handle_merge(&$5->handle, &$4);
+ handle_free(&$4);
+ list_add_tail(&$5->list, &$1->objs);
+ $$ = $1;
+ }
| table_block LIMIT obj_identifier
obj_block_alloc '{' limit_block '}'
stmt_separator
@@ -1759,6 +1783,15 @@ ct_helper_block : /* empty */ { $$ = $<obj>-1; }
}
;
+ct_timeout_block : /*empty */ { $$ = $<obj>-1; }
+ | ct_timeout_block common_block
+ | ct_timeout_block stmt_separator
+ | ct_timeout_block ct_timeout_config
+ {
+ $$ = $1;
+ }
+ ;
+
limit_block : /* empty */ { $$ = $<obj>-1; }
| limit_block common_block
| limit_block stmt_separator
@@ -3229,12 +3262,43 @@ quota_obj : quota_config
;
ct_obj_type : HELPER { $$ = NFT_OBJECT_CT_HELPER; }
+ | TIMEOUT { $$ = NFT_OBJECT_CT_TIMEOUT; }
;
ct_l4protoname : TCP { $$ = IPPROTO_TCP; }
| UDP { $$ = IPPROTO_UDP; }
;
+timeout_states : timeout_state
+ {
+ $$ = xmalloc(sizeof(*$$));
+ init_list_head($$);
+ list_add_tail($1, $$);
+ }
+ | timeout_states COMMA timeout_state
+ {
+ list_add_tail($3, $1);
+ $$ = $1;
+ }
+ ;
+
+timeout_state : STRING COLON NUM
+
+ {
+ struct timeout_state *ts;
+
+ ts = xzalloc(sizeof(*ts));
+ timeout_str2num($1, ts);
+ if (!ts) {
+ erec_queue(error(&@2, "invalid timeout state name '%s'\n", $1), state->msgs);
+ YYERROR;
+ }
+ ts->timeout_value = $3;
+ init_list_head(&ts->timeout_list);
+ $$ = &ts->timeout_list;
+ }
+ ;
+
ct_helper_config : TYPE QUOTED_STRING PROTOCOL ct_l4protoname stmt_separator
{
struct ct_helper *ct;
@@ -3256,6 +3320,42 @@ ct_helper_config : TYPE QUOTED_STRING PROTOCOL ct_l4protoname stmt_separator
}
;
+ct_timeout_config : PROTOCOL ct_l4protoname SEMICOLON
+ {
+ struct ct_timeout *ct;
+ int l4proto = $2;
+
+ ct = &$<obj>0->ct_timeout;
+ ct->l4proto = l4proto;
+ }
+ | POLICY '=' '{' timeout_states '}' stmt_separator
+ {
+ int l4proto = IPPROTO_TCP;
+ size_t timeout_array_size;
+ struct timeout_state *ts;
+ struct ct_timeout *ct;
+ uint32_t *timeout;
+
+ ct = &$<obj>0->ct_timeout;
+ init_list_head(&ct->timeout_state.timeout_list);
+ timeout_array_size = sizeof(uint32_t) * (timeout_protocol[l4proto].attr_max);
+ timeout = xzalloc(timeout_array_size);
+ list_for_each_entry(ts, $4, timeout_list) {
+ if (ct->l4proto == ts->l4) {
+ timeout[ts->timeout_index] = ts->timeout_value;
+ } else {
+ erec_queue(error(&@2, "invalid timeout state name for given l4proto\n"), state->msgs);
+ YYERROR;
+ }
+ }
+ ct->timeout = timeout;
+ }
+ | L3PROTOCOL family_spec_explicit stmt_separator
+ {
+ $<obj>0->ct_timeout.l3proto = $2;
+ }
+ ;
+
ct_obj_alloc :
{
$$ = obj_alloc(&@$);
@@ -3731,6 +3831,7 @@ ct_key : L3PROTOCOL { $$ = NFT_CT_L3PROTOCOL; }
| PROTO_DST { $$ = NFT_CT_PROTO_DST; }
| LABEL { $$ = NFT_CT_LABELS; }
| EVENT { $$ = NFT_CT_EVENTMASK; }
+ | TIMEOUT { $$ = NFT_CT_TIMEOUT; }
| ct_key_dir_optional
;
@@ -3779,6 +3880,11 @@ ct_stmt : CT ct_key SET stmt_expr
$$->objref.type = NFT_OBJECT_CT_HELPER;
$$->objref.expr = $4;
break;
+ case NFT_CT_TIMEOUT:
+ $$ = objref_stmt_alloc(&@$);
+ $$->objref.type = NFT_OBJECT_CT_TIMEOUT;
+ $$->objref.expr = $4;
+ break;
default:
$$ = ct_stmt_alloc(&@$, $2, -1, $4);
break;
@@ -29,6 +29,72 @@
#include <linux/netfilter.h>
#include <linux/netfilter_arp.h>
+const char *const tcp_state_to_name[] = {
+ [NFTNL_CTTIMEOUT_TCP_SYN_SENT] = "syn_sent",
+ [NFTNL_CTTIMEOUT_TCP_SYN_RECV] = "syn_recv",
+ [NFTNL_CTTIMEOUT_TCP_ESTABLISHED] = "established",
+ [NFTNL_CTTIMEOUT_TCP_FIN_WAIT] = "fin_wait",
+ [NFTNL_CTTIMEOUT_TCP_CLOSE_WAIT] = "close_wait",
+ [NFTNL_CTTIMEOUT_TCP_LAST_ACK] = "last_ack",
+ [NFTNL_CTTIMEOUT_TCP_TIME_WAIT] = "time_wait",
+ [NFTNL_CTTIMEOUT_TCP_CLOSE] = "close",
+ [NFTNL_CTTIMEOUT_TCP_SYN_SENT2] = "syn_sent2",
+ [NFTNL_CTTIMEOUT_TCP_RETRANS] = "retrans",
+ [NFTNL_CTTIMEOUT_TCP_UNACK] = "unack",
+};
+
+const char *const udp_state_to_name[] = {
+ [NFTNL_CTTIMEOUT_UDP_UNREPLIED] = "unreplied",
+ [NFTNL_CTTIMEOUT_UDP_REPLIED] = "replied",
+};
+
+uint32_t tcp_dflt_timeout[] = {
+ [NFTNL_CTTIMEOUT_TCP_SYN_SENT] = 120,
+ [NFTNL_CTTIMEOUT_TCP_SYN_RECV] = 60,
+ [NFTNL_CTTIMEOUT_TCP_ESTABLISHED] = 432000,
+ [NFTNL_CTTIMEOUT_TCP_FIN_WAIT] = 120,
+ [NFTNL_CTTIMEOUT_TCP_CLOSE_WAIT] = 60,
+ [NFTNL_CTTIMEOUT_TCP_LAST_ACK] = 30,
+ [NFTNL_CTTIMEOUT_TCP_TIME_WAIT] = 120,
+ [NFTNL_CTTIMEOUT_TCP_CLOSE] = 10,
+ [NFTNL_CTTIMEOUT_TCP_SYN_SENT2] = 120,
+ [NFTNL_CTTIMEOUT_TCP_RETRANS] = 300,
+ [NFTNL_CTTIMEOUT_TCP_UNACK] = 300,
+
+};
+
+uint32_t udp_dflt_timeout[] = {
+ [NFTNL_CTTIMEOUT_UDP_UNREPLIED] = 30,
+ [NFTNL_CTTIMEOUT_UDP_REPLIED] = 180,
+};
+
+struct timeout_protocol timeout_protocol[IPPROTO_MAX] = {
+ [IPPROTO_TCP] = {
+ .attr_max = NFTNL_CTTIMEOUT_TCP_MAX,
+ .state_to_name = tcp_state_to_name,
+ .dflt_timeout = tcp_dflt_timeout,
+ },
+ [IPPROTO_UDP] = {
+ .attr_max = NFTNL_CTTIMEOUT_UDP_MAX,
+ .state_to_name = udp_state_to_name,
+ .dflt_timeout = udp_dflt_timeout,
+ },
+};
+
+void timeout_str2num(const char *timeout_state, struct timeout_state *ts)
+{
+ unsigned int i, l4;
+
+ for (l4 = 0; l4 < IPPROTO_MAX; l4++) {
+ for (i = 0; i < timeout_protocol[l4].attr_max; i++) {
+ if (!strcmp(timeout_protocol[l4].state_to_name[i], timeout_state)) {
+ ts->timeout_index = i;
+ ts->l4 = l4;
+ }
+ }
+ }
+}
+
void handle_free(struct handle *h)
{
xfree(h->table.name);
@@ -1093,6 +1159,7 @@ void cmd_free(struct cmd *cmd)
case CMD_OBJ_COUNTER:
case CMD_OBJ_QUOTA:
case CMD_OBJ_CT_HELPER:
+ case CMD_OBJ_CT_TIMEOUT:
case CMD_OBJ_LIMIT:
obj_free(cmd->object);
break;
@@ -1187,6 +1254,7 @@ static int do_command_add(struct netlink_ctx *ctx, struct cmd *cmd, bool excl)
case CMD_OBJ_COUNTER:
case CMD_OBJ_QUOTA:
case CMD_OBJ_CT_HELPER:
+ case CMD_OBJ_CT_TIMEOUT:
case CMD_OBJ_LIMIT:
return netlink_add_obj(ctx, cmd, flags);
case CMD_OBJ_FLOWTABLE:
@@ -1272,6 +1340,9 @@ static int do_command_delete(struct netlink_ctx *ctx, struct cmd *cmd)
return netlink_delete_obj(ctx, cmd, NFT_OBJECT_QUOTA);
case CMD_OBJ_CT_HELPER:
return netlink_delete_obj(ctx, cmd, NFT_OBJECT_CT_HELPER);
+ case CMD_OBJ_CT_TIMEOUT:
+ return netlink_delete_obj(ctx, cmd,
+ NFT_OBJECT_CT_TIMEOUT);
case CMD_OBJ_LIMIT:
return netlink_delete_obj(ctx, cmd, NFT_OBJECT_LIMIT);
case CMD_OBJ_FLOWTABLE:
@@ -1417,9 +1488,28 @@ static void print_proto_name_proto(uint8_t l4, struct output_ctx *octx)
const struct protoent *p = getprotobynumber(l4);
if (p)
- nft_print(octx, "%s\n", p->p_name);
+ nft_print(octx, "%s", p->p_name);
else
- nft_print(octx, "%d\n", l4);
+ nft_print(octx, "%d", l4);
+}
+
+static void print_proto_timeout_policy(uint8_t l4, uint32_t *timeout,
+ struct output_ctx *octx)
+{
+ unsigned int i, b = 0;
+
+ nft_print(octx, "\t\tpolicy = {");
+ for (i = 0; i < timeout_protocol[l4].attr_max; i++) {
+ if (timeout[i] != timeout_protocol[l4].dflt_timeout[i]) {
+ if (b)
+ nft_print(octx, ", ");
+ nft_print(octx, "%s: %u",
+ timeout_protocol[l4].state_to_name[i],
+ timeout[i]);
+ b = 1;
+ }
+ }
+ nft_print(octx, "}");
}
static void obj_print_data(const struct obj *obj,
@@ -1466,9 +1556,24 @@ static void obj_print_data(const struct obj *obj,
nft_print(octx, "\t\ttype \"%s\" protocol ",
obj->ct_helper.name);
print_proto_name_proto(obj->ct_helper.l4proto, octx);
+ nft_print(octx, "\n");
nft_print(octx, "\t\tl3proto %s",
family2str(obj->ct_helper.l3proto));
break;
+ case NFT_OBJECT_CT_TIMEOUT:
+ nft_print(octx, "ct timeout %s {", obj->handle.obj.name);
+ if (octx->handle > 0)
+ nft_print(octx, " # handle %" PRIu64, obj->handle.handle.id);
+ nft_print(octx, "%s", opts->nl);
+ nft_print(octx, "\t\tprotocol ");
+ print_proto_name_proto(obj->ct_timeout.l4proto, octx);
+ nft_print(octx, ";%s", opts->nl);
+ nft_print(octx, "\t\tl3proto %s",
+ family2str(obj->ct_timeout.l3proto));
+ nft_print(octx, "%s", opts->nl);
+ print_proto_timeout_policy(obj->ct_timeout.l4proto,
+ obj->ct_timeout.timeout, octx);
+ break;
case NFT_OBJECT_LIMIT: {
bool inv = obj->limit.flags & NFT_LIMIT_F_INV;
const char *data_unit;
@@ -1515,6 +1620,7 @@ static const char * const obj_type_name_array[] = {
[NFT_OBJECT_QUOTA] = "quota",
[NFT_OBJECT_CT_HELPER] = "",
[NFT_OBJECT_LIMIT] = "limit",
+ [NFT_OBJECT_CT_TIMEOUT] = "",
};
const char *obj_type_name(enum stmt_types type)
@@ -1529,6 +1635,7 @@ static uint32_t obj_type_cmd_array[NFT_OBJECT_MAX + 1] = {
[NFT_OBJECT_QUOTA] = CMD_OBJ_QUOTA,
[NFT_OBJECT_CT_HELPER] = CMD_OBJ_CT_HELPER,
[NFT_OBJECT_LIMIT] = CMD_OBJ_LIMIT,
+ [NFT_OBJECT_CT_TIMEOUT] = CMD_OBJ_CT_TIMEOUT,
};
uint32_t obj_type_to_cmd(uint32_t type)
@@ -1877,6 +1984,8 @@ static int do_command_list(struct netlink_ctx *ctx, struct cmd *cmd)
case CMD_OBJ_CT_HELPER:
case CMD_OBJ_CT_HELPERS:
return do_list_obj(ctx, cmd, NFT_OBJECT_CT_HELPER);
+ case CMD_OBJ_CT_TIMEOUT:
+ return do_list_obj(ctx, cmd, NFT_OBJECT_CT_TIMEOUT);
case CMD_OBJ_LIMIT:
case CMD_OBJ_LIMITS:
return do_list_obj(ctx, cmd, NFT_OBJECT_LIMIT);
@@ -2094,6 +2203,9 @@ struct cmd *cmd_alloc_obj_ct(enum cmd_ops op, int type, const struct handle *h,
case NFT_OBJECT_CT_HELPER:
cmd_obj = CMD_OBJ_CT_HELPER;
break;
+ case NFT_OBJECT_CT_TIMEOUT:
+ cmd_obj = CMD_OBJ_CT_TIMEOUT;
+ break;
default:
BUG("missing type mapping");
}
@@ -203,6 +203,7 @@ static const char *objref_type[NFT_OBJECT_MAX + 1] = {
[NFT_OBJECT_QUOTA] = "quota",
[NFT_OBJECT_CT_HELPER] = "ct helper",
[NFT_OBJECT_LIMIT] = "limit",
+ [NFT_OBJECT_CT_TIMEOUT] = "ct timeout",
};
const char *objref_type_name(uint32_t type)
@@ -219,6 +220,9 @@ static void objref_stmt_print(const struct stmt *stmt, struct output_ctx *octx)
case NFT_OBJECT_CT_HELPER:
nft_print(octx, "ct helper set ");
break;
+ case NFT_OBJECT_CT_TIMEOUT:
+ nft_print(octx, "ct timeout set ");
+ break;
default:
nft_print(octx, "%s name ",
objref_type_name(stmt->objref.type));
This patch adds support for adding, listing and deleting ct timeout objects which can be assigned via rule to assign connection tracking timeout policies via objref infrastructure. %nft add table filter %nft add chain filter output %nft add ct timeout filter test-tcp { protocol tcp \; policy = { established: 132, close: 13, close_wait: 17 } \; } %nft add rule filter output ct timeout set test-tcp %nft list ruleset table ip filter { ct timeout test-tcp { protocol tcp; l3proto ip policy = {established: 132, close_wait: 17, close: 13} } chain output { ct timeout set "test-tcp" } } %nft delete rule filter output handle <handle> %nft delete ct timeout filter test-tcp Signed-off-by: Harsha Sharma <harshasharmaiitr@gmail.com> --- Changes in v5: - Remove nftnl_timeout_policy_attr_set_u32 - remove nftnl_obj_get_void - other changes with libnftnl patches Changes in v4: - updated syntax and log message - fix parser_bison to parse input from files for ct timeout obj - output similar to output Changes in v3: - parse multiple timeout policies - return error for invalid timeout state name - change in log message Changes in v2: - Change in syntax for addition of ct timeout objects - remove tokens from scanner and parser_bison for timeout states - list only updated timeout values - change in log message accordingly - other minor changes include/linux/netfilter/nf_tables.h | 14 ++++- include/rule.h | 24 ++++++++ src/evaluate.c | 4 ++ src/netlink.c | 14 +++++ src/parser_bison.y | 108 ++++++++++++++++++++++++++++++++- src/rule.c | 116 +++++++++++++++++++++++++++++++++++- src/statement.c | 4 ++ 7 files changed, 280 insertions(+), 4 deletions(-)