diff options
-rw-r--r-- | include/linux/netfilter/nf_tables.h | 14 | ||||
-rw-r--r-- | include/rule.h | 28 | ||||
-rw-r--r-- | src/evaluate.c | 36 | ||||
-rw-r--r-- | src/netlink.c | 15 | ||||
-rw-r--r-- | src/parser_bison.y | 91 | ||||
-rw-r--r-- | src/rule.c | 115 | ||||
-rw-r--r-- | src/statement.c | 4 |
7 files changed, 298 insertions, 5 deletions
diff --git a/include/linux/netfilter/nf_tables.h b/include/linux/netfilter/nf_tables.h index fe656525..143ebe28 100644 --- a/include/linux/netfilter/nf_tables.h +++ b/include/linux/netfilter/nf_tables.h @@ -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) /** diff --git a/include/rule.h b/include/rule.h index cfbbcf1f..88478aa6 100644 --- a/include/rule.h +++ b/include/rule.h @@ -4,6 +4,8 @@ #include <stdint.h> #include <nftables.h> #include <list.h> +#include <netinet/in.h> +#include <libnftnl/object.h> /* For NFTNL_CTTIMEOUT_ARRAY_MAX. */ /** * struct handle_spec - handle ID @@ -324,6 +326,21 @@ struct ct_helper { uint8_t l4proto; }; +struct timeout_state { + struct list_head head; + struct location location; + uint8_t timeout_index; + const char *timeout_str; + unsigned int timeout_value; +}; + +struct ct_timeout { + uint16_t l3proto; + uint8_t l4proto; + uint32_t timeout[NFTNL_CTTIMEOUT_ARRAY_MAX]; + struct list_head timeout_list; +}; + struct limit { uint64_t rate; uint64_t unit; @@ -352,6 +369,7 @@ struct obj { struct quota quota; struct ct_helper ct_helper; struct limit limit; + struct ct_timeout ct_timeout; }; }; @@ -478,6 +496,7 @@ enum cmd_obj { CMD_OBJ_LIMITS, CMD_OBJ_FLOWTABLE, CMD_OBJ_FLOWTABLES, + CMD_OBJ_CT_TIMEOUT, }; struct markup { @@ -633,4 +652,13 @@ enum udata_set_elem_flags { SET_ELEM_F_INTERVAL_OPEN = 0x1, }; +struct timeout_protocol { + uint32_t array_size; + const char *const *state_to_name; + uint32_t *dflt_timeout; +}; + +extern struct timeout_protocol timeout_protocol[IPPROTO_MAX]; +extern int timeout_str2num(uint16_t l4proto, struct timeout_state *ts); + #endif /* NFTABLES_RULE_H */ diff --git a/src/evaluate.c b/src/evaluate.c index a3a78744..9a7118ec 100644 --- a/src/evaluate.c +++ b/src/evaluate.c @@ -3196,11 +3196,36 @@ static int chain_evaluate(struct eval_ctx *ctx, struct chain *chain) return 0; } +static int obj_evaluate(struct eval_ctx *ctx, struct obj *obj) +{ + struct ct_timeout *ct = &obj->ct_timeout; + struct timeout_state *ts, *next; + unsigned int i; + + if (obj->type != NFT_OBJECT_CT_TIMEOUT) + return 0; + + for (i = 0; i < timeout_protocol[ct->l4proto].array_size; i++) + ct->timeout[i] = timeout_protocol[ct->l4proto].dflt_timeout[i]; + + list_for_each_entry_safe(ts, next, &ct->timeout_list, head) { + if (timeout_str2num(ct->l4proto, ts) < 0) + return __stmt_binary_error(ctx, &ts->location, NULL, + "invalid state for this protocol"); + + ct->timeout[ts->timeout_index] = ts->timeout_value; + list_del(&ts->head); + xfree(ts); + } + return 0; +} + static int table_evaluate(struct eval_ctx *ctx, struct table *table) { struct flowtable *ft; struct chain *chain; struct set *set; + struct obj *obj; if (table_lookup(&ctx->cmd->handle, ctx->cache) == NULL) { if (table == NULL) { @@ -3232,6 +3257,11 @@ static int table_evaluate(struct eval_ctx *ctx, struct table *table) if (flowtable_evaluate(ctx, ft) < 0) return -1; } + list_for_each_entry(obj, &table->objs, list) { + handle_merge(&obj->handle, &table->handle); + if (obj_evaluate(ctx, obj) < 0) + return -1; + } ctx->table = NULL; return 0; @@ -3281,7 +3311,8 @@ static int cmd_evaluate_add(struct eval_ctx *ctx, struct cmd *cmd) case CMD_OBJ_QUOTA: case CMD_OBJ_CT_HELPER: case CMD_OBJ_LIMIT: - return 0; + case CMD_OBJ_CT_TIMEOUT: + return obj_evaluate(ctx, cmd->object); default: BUG("invalid command object type %u\n", cmd->obj); } @@ -3307,6 +3338,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: @@ -3439,6 +3471,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: diff --git a/src/netlink.c b/src/netlink.c index bd472799..f795d984 100644 --- a/src/netlink.c +++ b/src/netlink.c @@ -334,6 +334,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 +1445,13 @@ 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); + memcpy(obj->ct_timeout.timeout, + nftnl_obj_get(nlo, NFTNL_OBJ_CT_TIMEOUT_ARRAY), + NFTNL_CTTIMEOUT_ARRAY_MAX * sizeof(uint32_t)); + break; case NFT_OBJECT_LIMIT: obj->limit.rate = nftnl_obj_get_u64(nlo, NFTNL_OBJ_LIMIT_RATE); diff --git a/src/parser_bison.y b/src/parser_bison.y index 86036124..85830d88 100644 --- a/src/parser_bison.y +++ b/src/parser_bison.y @@ -554,7 +554,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 @@ -755,6 +755,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 */ @@ -962,6 +965,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); @@ -1043,6 +1050,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); @@ -1235,6 +1246,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 @@ -1466,6 +1481,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 @@ -1761,6 +1785,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 @@ -3279,6 +3312,7 @@ quota_obj : quota_config ; ct_obj_type : HELPER { $$ = NFT_OBJECT_CT_HELPER; } + | TIMEOUT { $$ = NFT_OBJECT_CT_TIMEOUT; } ; ct_l4protoname : TCP { $$ = IPPROTO_TCP; } @@ -3306,6 +3340,55 @@ ct_helper_config : TYPE QUOTED_STRING PROTOCOL ct_l4protoname stmt_separator } ; +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)); + ts->timeout_str = $1; + ts->timeout_value = $3; + ts->location = @1; + init_list_head(&ts->head); + $$ = &ts->head; + } + ; + +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 + { + struct ct_timeout *ct; + + ct = &$<obj>0->ct_timeout; + init_list_head(&ct->timeout_list); + list_splice_tail($4, &ct->timeout_list); + } + | L3PROTOCOL family_spec_explicit stmt_separator + { + $<obj>0->ct_timeout.l3proto = $2; + } + ; + ct_obj_alloc : { $$ = obj_alloc(&@$); @@ -3781,6 +3864,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 ; @@ -3829,6 +3913,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; @@ -32,6 +32,70 @@ #include <net/if.h> #include <linux/netfilter_bridge.h> +static 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", +}; + +static const char *const udp_state_to_name[] = { + [NFTNL_CTTIMEOUT_UDP_UNREPLIED] = "unreplied", + [NFTNL_CTTIMEOUT_UDP_REPLIED] = "replied", +}; + +static 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, +}; + +static uint32_t udp_dflt_timeout[] = { + [NFTNL_CTTIMEOUT_UDP_UNREPLIED] = 30, + [NFTNL_CTTIMEOUT_UDP_REPLIED] = 180, +}; + +struct timeout_protocol timeout_protocol[IPPROTO_MAX] = { + [IPPROTO_TCP] = { + .array_size = NFTNL_CTTIMEOUT_TCP_MAX, + .state_to_name = tcp_state_to_name, + .dflt_timeout = tcp_dflt_timeout, + }, + [IPPROTO_UDP] = { + .array_size = NFTNL_CTTIMEOUT_UDP_MAX, + .state_to_name = udp_state_to_name, + .dflt_timeout = udp_dflt_timeout, + }, +}; + +int timeout_str2num(uint16_t l4proto, struct timeout_state *ts) +{ + unsigned int i; + + for (i = 0; i < timeout_protocol[l4proto].array_size; i++) { + if (!strcmp(timeout_protocol[l4proto].state_to_name[i], ts->timeout_str)) { + ts->timeout_index = i; + return 0; + } + } + return -1; +} + void handle_free(struct handle *h) { xfree(h->table.name); @@ -1261,6 +1325,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; @@ -1359,6 +1424,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: @@ -1444,6 +1510,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: @@ -1589,9 +1658,29 @@ 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, const uint32_t *timeout, + struct output_ctx *octx) +{ + bool comma = false; + unsigned int i; + + nft_print(octx, "\t\tpolicy = {"); + for (i = 0; i < timeout_protocol[l4].array_size; i++) { + if (timeout[i] != timeout_protocol[l4].dflt_timeout[i]) { + if (comma) + nft_print(octx, ", "); + nft_print(octx, "%s: %u", + timeout_protocol[l4].state_to_name[i], + timeout[i]); + comma = true; + } + } + nft_print(octx, "}"); } static void obj_print_data(const struct obj *obj, @@ -1638,9 +1727,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; @@ -1687,6 +1791,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) @@ -1701,6 +1806,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) @@ -2054,6 +2160,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); @@ -2271,6 +2379,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"); } diff --git a/src/statement.c b/src/statement.c index 45d2067c..a02ebc84 100644 --- a/src/statement.c +++ b/src/statement.c @@ -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)); |