From patchwork Wed Jun 13 23:11:04 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Harsha Sharma X-Patchwork-Id: 929122 X-Patchwork-Delegate: pablo@netfilter.org Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netfilter-devel-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="i3P8gnNo"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 415jDQ5zLkz9s0W for ; Thu, 14 Jun 2018 09:11:18 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S935557AbeFMXLR (ORCPT ); Wed, 13 Jun 2018 19:11:17 -0400 Received: from mail-wr0-f179.google.com ([209.85.128.179]:35340 "EHLO mail-wr0-f179.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S935503AbeFMXLQ (ORCPT ); Wed, 13 Jun 2018 19:11:16 -0400 Received: by mail-wr0-f179.google.com with SMTP id l10-v6so4425628wrn.2 for ; Wed, 13 Jun 2018 16:11:15 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id; bh=ttD0PT/g7FQ03KI+Jrx8XeNTO+Uot9H4QBlfw8J1cf4=; b=i3P8gnNoZWwAl3OZX2WZLcCSaiid5CqqVHyHjuTId0sj+OhWnGXe1FjZK7oq+ZYrGV mU4Ut6z5aRK2Usmb7W6sBuh4LmwyjTjOGbQ+hqGZQcNOOPaUoKGZkGxg8BR0Zrt2cMDZ OpZ7reDb7rP/6LpcI0nKZyq747Xma/vDIMtiV+7TvYlKtShbMts473tooU6ObPBG+eTC BG5R3X5kRVFtRQvMp1u3hNgKRQJeTMCMcjII9fj84aLFlPGxZ/fEZLjQNDQLGMeWO8n8 OyDXksYjTYRQmxBgrlR5G3GsbmFRO346os8Ln7eiC+EH8R0bxW5uUp/T9uWAE/JmiUuK tmKg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=ttD0PT/g7FQ03KI+Jrx8XeNTO+Uot9H4QBlfw8J1cf4=; b=oDkJV0USM+SvdXY7B58PfMGGWQ2518QiRDomBRAR2iCpchVxObdCFzm1SnQlVzTn/K 8Ygj8TS1RmqgDFzjyQ90w2bvWytPLxqo5g0PWWanSC7qskNFPZKN3KmEIwYYBBjQ9j7G J+3PoOLydnyzyX1uCPLQ2FmlWw6XAMDRA/7TZ1qCwuHPPA20nsrgUaFh6J/Ri7tHUfI7 CVEgDREVbusmQqaiiiU/ka0Xw2BzjfF+tIvC1tYVrnvaPOZG5vUuOIssi4f8ulxJBjpJ 5Yy0CNUyzqT0iBXYVmhFB7qP6yPFn+x2YPy3BoPIIA0fK4U/R0Gu/d2QERuPS6g0LCnt ZK3w== X-Gm-Message-State: APt69E0cSE5AQcSGktOs5M3dGNJaQLQMTSMEOUwvSlB1pn2AL8GG4x8t PLzcNNLjSxG+7uLfEWBlUJg= X-Google-Smtp-Source: ADUXVKLxVaeRCoIqOartv8Gr1YbNEDPtug964JV7p1wyf09oUx0fY33admm9G04jdlaB+O+W1hTWpg== X-Received: by 2002:adf:a54a:: with SMTP id j10-v6mr107238wrb.155.1528931474697; Wed, 13 Jun 2018 16:11:14 -0700 (PDT) Received: from XDDDDD.fritz.box ([2001:16b8:2d18:f600:1885:d2ca:1315:e180]) by smtp.gmail.com with ESMTPSA id l41-v6sm6778243wre.87.2018.06.13.16.11.12 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 13 Jun 2018 16:11:13 -0700 (PDT) From: Harsha Sharma To: harshasharmaiitr@gmail.com, pablo@netfilter.org Cc: netfilter-devel@vger.kernel.org Subject: [PATCH WIP nftables] src: add ct timeout support Date: Thu, 14 Jun 2018 01:11:04 +0200 Message-Id: <20180613231104.14712-1-harshasharmaiitr@gmail.com> X-Mailer: git-send-email 2.14.1 Sender: netfilter-devel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netfilter-devel@vger.kernel.org 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\ established 132\; } %nft add rule filter output ct timeout set test-tcp %nft list ruleset table ip filter { ct timeout test-tcp { protocol tcp l3proto ip syn_sent 120 syn_recv 60 established 132 fin_wait 120 close_wait 60 last_ack 30 time_wait 120 close 10 syn_sent2 120 retrans 300 } chain output { ct timeout set "test-tcp" } } %nft delete rule filter output handle %nft delete ct timeout filter test-tcp Signed-off-by: Harsha Sharma --- include/linux/netfilter/nf_tables.h | 13 +++- include/rule.h | 17 +++++ src/evaluate.c | 4 ++ src/netlink.c | 19 ++++++ src/parser_bison.y | 130 +++++++++++++++++++++++++++++++++++- src/rule.c | 67 ++++++++++++++++++- src/scanner.l | 13 ++++ src/statement.c | 4 ++ 8 files changed, 264 insertions(+), 3 deletions(-) diff --git a/include/linux/netfilter/nf_tables.h b/include/linux/netfilter/nf_tables.h index 88e0ca1..8e7c757 100644 --- a/include/linux/netfilter/nf_tables.h +++ b/include/linux/netfilter/nf_tables.h @@ -958,6 +958,7 @@ enum nft_socket_keys { * @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, @@ -983,6 +984,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) @@ -1373,13 +1375,22 @@ 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_CT_TIMEOUT 6 +#define __NFT_OBJECT_MAX 7 #define NFT_OBJECT_MAX (__NFT_OBJECT_MAX - 1) /** diff --git a/include/rule.h b/include/rule.h index 909ff36..e52e9b3 100644 --- a/include/rule.h +++ b/include/rule.h @@ -4,6 +4,8 @@ #include #include #include +#include +#include /** * struct handle_spec - handle ID @@ -308,6 +310,12 @@ struct ct_helper { uint8_t l4proto; }; +struct ct_timeout { + uint16_t l3proto; + uint8_t l4proto; + uint32_t *timeout; +}; + struct limit { uint64_t rate; uint64_t unit; @@ -336,6 +344,7 @@ struct obj { struct quota quota; struct ct_helper ct_helper; struct limit limit; + struct ct_timeout ct_timeout; }; }; @@ -462,6 +471,7 @@ enum cmd_obj { CMD_OBJ_LIMITS, CMD_OBJ_FLOWTABLE, CMD_OBJ_FLOWTABLES, + CMD_OBJ_CT_TIMEOUT, }; struct markup { @@ -617,4 +627,11 @@ enum udata_set_elem_flags { SET_ELEM_F_INTERVAL_OPEN = 0x1, }; +struct timeout_protocol { + uint32_t attr_max; + const char *const *state_to_name; +}; + +extern struct timeout_protocol timeout_protocol[IPPROTO_MAX]; + #endif /* NFTABLES_RULE_H */ diff --git a/src/evaluate.c b/src/evaluate.c index c4ee3cc..69f3230 100644 --- a/src/evaluate.c +++ b/src/evaluate.c @@ -3130,6 +3130,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: @@ -3157,6 +3158,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: @@ -3289,6 +3291,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 864947b..9eaf253 100644 --- a/src/netlink.c +++ b/src/netlink.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -41,6 +42,7 @@ #include #include #include +#include #define nft_mon_print(monh, ...) nft_print(monh->ctx->octx, __VA_ARGS__) @@ -334,6 +336,18 @@ 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); + for (unsigned int i = 0; i < timeout_protocol[obj->ct_timeout.l4proto].attr_max; ++i) { + if (obj->ct_timeout.timeout[i]) { + nftnl_timeout_policy_attr_set_u32(nlo, i, obj->ct_timeout.timeout[i]); + } + } + 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 +1451,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 = nftnl_obj_get(nlo, NFTNL_OBJ_CT_TIMEOUT_DATA); + 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 33915ed..7961981 100644 --- a/src/parser_bison.y +++ b/src/parser_bison.y @@ -12,6 +12,7 @@ #include #include +#include #include #include #include @@ -154,6 +155,7 @@ int nft_lex(void *, void *, void *); struct handle_spec handle_spec; struct position_spec position_spec; const struct exthdr_desc *exthdr_desc; + struct ct_timeout *ct_timeout; } %token TOKEN_EOF 0 "end of file" @@ -502,6 +504,18 @@ int nft_lex(void *, void *, void *); %token EXTHDR "exthdr" +%token T_ESTABLISHED "established" +%token T_SYN_SENT "syn_sent" +%token T_SYN_RECV "syn_recv" +%token T_FIN_WAIT "fin_wait" +%token T_CLOSE_WAIT "close_wait" +%token T_LAST_ACK "last_ack" +%token T_TIME_WAIT "time_wait" +%token T_CLOSE "close" +%token T_LISTEN "listen" + +%token T_REPLIED "replied" +%token T_UNREPLIED "unreplied" %type identifier type_identifier string comment_spec %destructor { xfree($$); } identifier type_identifier string comment_spec @@ -545,7 +559,7 @@ int nft_lex(void *, void *, void *); %type flowtable_block_alloc flowtable_block %destructor { flowtable_free($$); } flowtable_block_alloc -%type obj_block_alloc counter_block quota_block ct_helper_block limit_block +%type obj_block_alloc counter_block quota_block ct_helper_block ct_timeout_block limit_block %destructor { obj_free($$); } obj_block_alloc %type stmt_list @@ -741,6 +755,9 @@ int nft_lex(void *, void *, void *); %type exthdr_key %type ct_l4protoname ct_obj_type +%type tcp_states tcp_state +%type udp_states udp_state +%type timeout_states %% @@ -949,6 +966,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); @@ -1030,6 +1051,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); @@ -1222,6 +1247,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 @@ -1453,6 +1482,15 @@ table_block : /* empty */ { $$ = $-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 @@ -1747,6 +1785,15 @@ ct_helper_block : /* empty */ { $$ = $-1; } } ; +ct_timeout_block : /*empty */ { $$ = $-1; } + | ct_timeout_block common_block + | ct_timeout_block stmt_separator + | ct_timeout_block ct_timeout_config + { + $$ = $1; + } + ; + limit_block : /* empty */ { $$ = $-1; } | limit_block common_block | limit_block stmt_separator @@ -3169,12 +3216,69 @@ 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 : tcp_states + | udp_states + ; + +tcp_states : tcp_states tcp_state + | tcp_state + ; + +tcp_state : T_SYN_SENT + { + $$ = NFTA_CT_TIMEOUT_ATTR_TCP_SYN_SENT; + } + | T_SYN_RECV + { + $$ = NFTA_CT_TIMEOUT_ATTR_TCP_SYN_RECV; + } + | T_ESTABLISHED + { + $$ = NFTA_CT_TIMEOUT_ATTR_TCP_ESTABLISHED; + } + | T_FIN_WAIT + { + $$ = NFTA_CT_TIMEOUT_ATTR_TCP_FIN_WAIT; + } + | T_CLOSE_WAIT + { + $$ = NFTA_CT_TIMEOUT_ATTR_TCP_CLOSE_WAIT; + } + | T_LAST_ACK + { + $$ = NFTA_CT_TIMEOUT_ATTR_TCP_LAST_ACK; + } + | T_TIME_WAIT + { + $$ = NFTA_CT_TIMEOUT_ATTR_TCP_TIME_WAIT; + } + | T_CLOSE + { + $$ = NFTA_CT_TIMEOUT_ATTR_TCP_CLOSE; + } + ; + +udp_states : udp_states udp_state + | udp_state + ; + +udp_state : T_REPLIED + { + $$ = NFTA_CT_TIMEOUT_ATTR_UDP_REPLIED; + } + | T_UNREPLIED + { + $$ = NFTA_CT_TIMEOUT_ATTR_UDP_UNREPLIED; + } + ; + ct_helper_config : TYPE QUOTED_STRING PROTOCOL ct_l4protoname stmt_separator { struct ct_helper *ct; @@ -3196,6 +3300,24 @@ ct_helper_config : TYPE QUOTED_STRING PROTOCOL ct_l4protoname stmt_separator } ; +ct_timeout_config : PROTOCOL ct_l4protoname timeout_states NUM stmt_separator + { + struct ct_timeout *ct; + int l4proto = $2; + int type = $3; + size_t timeout_array_size = sizeof(uint32_t) * (timeout_protocol[l4proto].attr_max); + + ct = &$0->ct_timeout; + ct->l4proto = l4proto; + ct->timeout = calloc(1, timeout_array_size); + ct->timeout[type] = $4; + } + | L3PROTOCOL family_spec_explicit stmt_separator + { + $0->ct_timeout.l3proto = $2; + } + ; + ct_obj_alloc : { $$ = obj_alloc(&@$); @@ -3670,6 +3792,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 ; @@ -3718,6 +3841,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; diff --git a/src/rule.c b/src/rule.c index 56b956a..295fc0a 100644 --- a/src/rule.c +++ b/src/rule.c @@ -29,6 +29,36 @@ #include #include +const char *const tcp_state_to_name[] = { + [NFTA_CT_TIMEOUT_ATTR_TCP_SYN_SENT] = "syn_sent", + [NFTA_CT_TIMEOUT_ATTR_TCP_SYN_RECV] = "syn_recv", + [NFTA_CT_TIMEOUT_ATTR_TCP_ESTABLISHED] = "established", + [NFTA_CT_TIMEOUT_ATTR_TCP_FIN_WAIT] = "fin_wait", + [NFTA_CT_TIMEOUT_ATTR_TCP_CLOSE_WAIT] = "close_wait", + [NFTA_CT_TIMEOUT_ATTR_TCP_LAST_ACK] = "last_ack", + [NFTA_CT_TIMEOUT_ATTR_TCP_TIME_WAIT] = "time_wait", + [NFTA_CT_TIMEOUT_ATTR_TCP_CLOSE] = "close", + [NFTA_CT_TIMEOUT_ATTR_TCP_SYN_SENT2] = "syn_sent2", + [NFTA_CT_TIMEOUT_ATTR_TCP_RETRANS] = "retrans", + [NFTA_CT_TIMEOUT_ATTR_TCP_UNACK] = "unack", +}; + +const char *const udp_state_to_name[] = { + [NFTA_CT_TIMEOUT_ATTR_UDP_UNREPLIED] = "unreplied", + [NFTA_CT_TIMEOUT_ATTR_UDP_REPLIED] = "replied", +}; + +struct timeout_protocol timeout_protocol[IPPROTO_MAX] = { + [IPPROTO_TCP] = { + .attr_max = NFTA_CT_TIMEOUT_ATTR_TCP_MAX, + .state_to_name = tcp_state_to_name, + }, + [IPPROTO_UDP] = { + .attr_max = NFTA_CT_TIMEOUT_ATTR_UDP_MAX, + .state_to_name = udp_state_to_name, + }, +}; + void handle_free(struct handle *h) { xfree(h->table.name); @@ -1089,6 +1119,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; @@ -1183,6 +1214,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: @@ -1267,7 +1299,11 @@ static int do_command_delete(struct netlink_ctx *ctx, struct cmd *cmd) case CMD_OBJ_QUOTA: return netlink_delete_obj(ctx, cmd, NFT_OBJECT_QUOTA); case CMD_OBJ_CT_HELPER: - return netlink_delete_obj(ctx, cmd, NFT_OBJECT_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: @@ -1418,6 +1454,17 @@ static void print_proto_name_proto(uint8_t l4, struct output_ctx *octx) nft_print(octx, "%d\n", l4); } +static void print_proto_timeout_policy(uint8_t l4, uint32_t *timeout, struct output_ctx *octx) +{ + unsigned int i; + + for (i = 0; i < timeout_protocol[l4].attr_max; ++i) { + if (timeout[i]) { + nft_print(octx, "\t\t%s %u\n", timeout_protocol[l4].state_to_name[i], timeout[i]); + } + } +} + static void obj_print_data(const struct obj *obj, struct print_fmt_options *opts, struct output_ctx *octx) @@ -1465,6 +1512,18 @@ static void obj_print_data(const struct obj *obj, 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, "\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; @@ -1511,6 +1570,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) @@ -1525,6 +1585,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) @@ -1875,6 +1936,7 @@ 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: case CMD_OBJ_LIMIT: case CMD_OBJ_LIMITS: return do_list_obj(ctx, cmd, NFT_OBJECT_LIMIT); @@ -2092,6 +2154,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/scanner.l b/src/scanner.l index 416bd27..330d966 100644 --- a/src/scanner.l +++ b/src/scanner.l @@ -547,6 +547,19 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr}) "exthdr" { return EXTHDR; } +"established" { return T_ESTABLISHED; } +"syn_sent" { return T_SYN_SENT; } +"syn_recv" { return T_SYN_RECV; } +"fin_wait" { return T_FIN_WAIT; } +"close_wait" { return T_CLOSE_WAIT; } +"last_ack" { return T_LAST_ACK; } +"time_wait" { return T_TIME_WAIT; } +"close" { return T_CLOSE; } +"listen" { return T_LISTEN; } + +"replied" { return T_REPLIED; } +"unreplied" { return T_UNREPLIED; } + {addrstring} { yylval->string = xstrdup(yytext); return STRING; diff --git a/src/statement.c b/src/statement.c index 6f5e666..3f88729 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));