Hello, I have one comment on this patch. As you can see there is no json output test because right now it is not possible to create the json output of the synproxy object reference. I have been trying it but as we are supporting "synproxy" without arguments in the statement expression, then I don't know how to deal with the synproxy object reference json parsing. Have you any hint on how should we deal with that? Thanks! :-) On 9/11/19 11:45 PM, Fernando Fernandez Mancera wrote: > Add support for "synproxy" stateful object. For example (for TCP port 80 and > using maps with saddr): > > table ip foo { > synproxy https-synproxy { > mss 1460 > wscale 7 > timestamp sack-perm > } > > synproxy other-synproxy { > mss 1460 > wscale 5 > } > > chain bar { > tcp dport 80 synproxy name "https-synproxy" > synproxy name ip saddr map { 192.168.1.0/24 : "https-synproxy", 192.168.2.0/24 : "other-synproxy" } > } > } > > Signed-off-by: Fernando Fernandez Mancera <ffmancera@xxxxxxxxxx> > --- > v1: initial patch > v2: fix a typo > v3: one argument per line > v4: add python tests > --- > include/linux/netfilter/nf_tables.h | 3 +- > include/rule.h | 11 +++ > src/evaluate.c | 5 ++ > src/json.c | 20 ++++- > src/mnl.c | 8 ++ > src/netlink.c | 8 ++ > src/parser_bison.y | 124 +++++++++++++++++++++++++++- > src/parser_json.c | 22 ++++- > src/rule.c | 50 +++++++++++ > src/scanner.l | 1 + > src/statement.c | 1 + > tests/py/ip/objects.t | 4 + > 12 files changed, 251 insertions(+), 6 deletions(-) > > diff --git a/include/linux/netfilter/nf_tables.h b/include/linux/netfilter/nf_tables.h > index 0ff932d..ed8881a 100644 > --- a/include/linux/netfilter/nf_tables.h > +++ b/include/linux/netfilter/nf_tables.h > @@ -1481,7 +1481,8 @@ enum nft_ct_expectation_attributes { > #define NFT_OBJECT_CT_TIMEOUT 7 > #define NFT_OBJECT_SECMARK 8 > #define NFT_OBJECT_CT_EXPECT 9 > -#define __NFT_OBJECT_MAX 10 > +#define NFT_OBJECT_SYNPROXY 10 > +#define __NFT_OBJECT_MAX 11 > #define NFT_OBJECT_MAX (__NFT_OBJECT_MAX - 1) > > /** > diff --git a/include/rule.h b/include/rule.h > index 0ef6aac..2708cbe 100644 > --- a/include/rule.h > +++ b/include/rule.h > @@ -399,6 +399,12 @@ struct limit { > uint32_t flags; > }; > > +struct synproxy { > + uint16_t mss; > + uint8_t wscale; > + uint32_t flags; > +}; > + > struct secmark { > char ctx[NFT_SECMARK_CTX_MAXLEN]; > }; > @@ -426,6 +432,7 @@ struct obj { > struct ct_timeout ct_timeout; > struct secmark secmark; > struct ct_expect ct_expect; > + struct synproxy synproxy; > }; > }; > > @@ -529,6 +536,8 @@ enum cmd_ops { > * @CMD_OBJ_FLOWTABLES: flow tables > * @CMD_OBJ_SECMARK: secmark > * @CMD_OBJ_SECMARKS: multiple secmarks > + * @CMD_OBJ_SYNPROXY: synproxy > + * @CMD_OBJ_SYNPROXYS: multiple synproxys > */ > enum cmd_obj { > CMD_OBJ_INVALID, > @@ -561,6 +570,8 @@ enum cmd_obj { > CMD_OBJ_SECMARK, > CMD_OBJ_SECMARKS, > CMD_OBJ_CT_EXPECT, > + CMD_OBJ_SYNPROXY, > + CMD_OBJ_SYNPROXYS, > }; > > struct markup { > diff --git a/src/evaluate.c b/src/evaluate.c > index 29fe966..a56cd2a 100644 > --- a/src/evaluate.c > +++ b/src/evaluate.c > @@ -3743,6 +3743,7 @@ static int cmd_evaluate_add(struct eval_ctx *ctx, struct cmd *cmd) > case CMD_OBJ_CT_TIMEOUT: > case CMD_OBJ_SECMARK: > case CMD_OBJ_CT_EXPECT: > + case CMD_OBJ_SYNPROXY: > return obj_evaluate(ctx, cmd->object); > default: > BUG("invalid command object type %u\n", cmd->obj); > @@ -3766,6 +3767,7 @@ static int cmd_evaluate_delete(struct eval_ctx *ctx, struct cmd *cmd) > case CMD_OBJ_LIMIT: > case CMD_OBJ_SECMARK: > case CMD_OBJ_CT_EXPECT: > + case CMD_OBJ_SYNPROXY: > return 0; > default: > BUG("invalid command object type %u\n", cmd->obj); > @@ -3911,6 +3913,8 @@ static int cmd_evaluate_list(struct eval_ctx *ctx, struct cmd *cmd) > return cmd_evaluate_list_obj(ctx, cmd, NFT_OBJECT_SECMARK); > case CMD_OBJ_CT_EXPECT: > return cmd_evaluate_list_obj(ctx, cmd, NFT_OBJECT_CT_EXPECT); > + case CMD_OBJ_SYNPROXY: > + return cmd_evaluate_list_obj(ctx, cmd, NFT_OBJECT_SYNPROXY); > case CMD_OBJ_COUNTERS: > case CMD_OBJ_QUOTAS: > case CMD_OBJ_CT_HELPERS: > @@ -3918,6 +3922,7 @@ static int cmd_evaluate_list(struct eval_ctx *ctx, struct cmd *cmd) > case CMD_OBJ_SETS: > case CMD_OBJ_FLOWTABLES: > case CMD_OBJ_SECMARKS: > + case CMD_OBJ_SYNPROXYS: > if (cmd->handle.table.name == NULL) > return 0; > if (table_lookup(&cmd->handle, &ctx->nft->cache) == NULL) > diff --git a/src/json.c b/src/json.c > index 55ce053..6adc801 100644 > --- a/src/json.c > +++ b/src/json.c > @@ -282,8 +282,8 @@ static json_t *obj_print_json(const struct obj *obj) > { > const char *rate_unit = NULL, *burst_unit = NULL; > const char *type = obj_type_name(obj->type); > + json_t *root, *tmp, *flags; > uint64_t rate, burst; > - json_t *root, *tmp; > > root = json_pack("{s:s, s:s, s:s, s:I}", > "family", family2str(obj->handle.family), > @@ -368,6 +368,24 @@ static json_t *obj_print_json(const struct obj *obj) > json_string(burst_unit)); > } > > + json_object_update(root, tmp); > + json_decref(tmp); > + break; > + case NFT_OBJECT_SYNPROXY: > + flags = json_array(); > + tmp = json_pack("{s:i, s:i}", > + "mss", obj->synproxy.mss, > + "wscale", obj->synproxy.wscale); > + if (obj->synproxy.flags & NF_SYNPROXY_OPT_TIMESTAMP) > + json_array_append_new(flags, json_string("timestamp")); > + if (obj->synproxy.flags & NF_SYNPROXY_OPT_SACK_PERM) > + json_array_append_new(flags, json_string("sack-perm")); > + > + if (json_array_size(flags) > 0) > + json_object_set_new(tmp, "flags", flags); > + else > + json_decref(flags); > + > json_object_update(root, tmp); > json_decref(tmp); > break; > diff --git a/src/mnl.c b/src/mnl.c > index 8031bd6..57ff89f 100644 > --- a/src/mnl.c > +++ b/src/mnl.c > @@ -1036,6 +1036,14 @@ int mnl_nft_obj_add(struct netlink_ctx *ctx, const struct cmd *cmd, > nftnl_obj_set_str(nlo, NFTNL_OBJ_SECMARK_CTX, > obj->secmark.ctx); > break; > + case NFT_OBJECT_SYNPROXY: > + nftnl_obj_set_u16(nlo, NFTNL_OBJ_SYNPROXY_MSS, > + obj->synproxy.mss); > + nftnl_obj_set_u8(nlo, NFTNL_OBJ_SYNPROXY_WSCALE, > + obj->synproxy.wscale); > + nftnl_obj_set_u32(nlo, NFTNL_OBJ_SYNPROXY_FLAGS, > + obj->synproxy.flags); > + break; > default: > BUG("Unknown type %d\n", obj->type); > break; > diff --git a/src/netlink.c b/src/netlink.c > index f8e1120..1e669e5 100644 > --- a/src/netlink.c > +++ b/src/netlink.c > @@ -1030,6 +1030,14 @@ struct obj *netlink_delinearize_obj(struct netlink_ctx *ctx, > obj->ct_expect.size = > nftnl_obj_get_u8(nlo, NFTNL_OBJ_CT_EXPECT_SIZE); > break; > + case NFT_OBJECT_SYNPROXY: > + obj->synproxy.mss = > + nftnl_obj_get_u16(nlo, NFTNL_OBJ_SYNPROXY_MSS); > + obj->synproxy.wscale = > + nftnl_obj_get_u8(nlo, NFTNL_OBJ_SYNPROXY_WSCALE); > + obj->synproxy.flags = > + nftnl_obj_get_u32(nlo, NFTNL_OBJ_SYNPROXY_FLAGS); > + break; > } > obj->type = type; > > diff --git a/src/parser_bison.y b/src/parser_bison.y > index b7db1a2..3fccea6 100644 > --- a/src/parser_bison.y > +++ b/src/parser_bison.y > @@ -151,6 +151,7 @@ int nft_lex(void *, void *, void *); > struct counter *counter; > struct quota *quota; > struct secmark *secmark; > + struct synproxy *synproxy; > struct ct *ct; > struct limit *limit; > const struct datatype *datatype; > @@ -461,6 +462,7 @@ int nft_lex(void *, void *, void *); > %token COUNTERS "counters" > %token QUOTAS "quotas" > %token LIMITS "limits" > +%token SYNPROXYS "synproxys" > %token HELPERS "helpers" > > %token LOG "log" > @@ -592,7 +594,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 ct_timeout_block ct_expect_block limit_block secmark_block > +%type <obj> obj_block_alloc counter_block quota_block ct_helper_block ct_timeout_block ct_expect_block limit_block secmark_block synproxy_block > %destructor { obj_free($$); } obj_block_alloc > > %type <list> stmt_list > @@ -700,8 +702,8 @@ int nft_lex(void *, void *, void *); > %type <expr> and_rhs_expr exclusive_or_rhs_expr inclusive_or_rhs_expr > %destructor { expr_free($$); } and_rhs_expr exclusive_or_rhs_expr inclusive_or_rhs_expr > > -%type <obj> counter_obj quota_obj ct_obj_alloc limit_obj secmark_obj > -%destructor { obj_free($$); } counter_obj quota_obj ct_obj_alloc limit_obj secmark_obj > +%type <obj> counter_obj quota_obj ct_obj_alloc limit_obj secmark_obj synproxy_obj > +%destructor { obj_free($$); } counter_obj quota_obj ct_obj_alloc limit_obj secmark_obj synproxy_obj > > %type <expr> relational_expr > %destructor { expr_free($$); } relational_expr > @@ -787,6 +789,9 @@ int nft_lex(void *, void *, void *); > %destructor { xfree($$); } limit_config > %type <secmark> secmark_config > %destructor { xfree($$); } secmark_config > +%type <synproxy> synproxy_config > +%destructor { xfree($$); } synproxy_config > +%type <val> synproxy_ts synproxy_sack > > %type <expr> tcp_hdr_expr > %destructor { expr_free($$); } tcp_hdr_expr > @@ -1012,6 +1017,10 @@ add_cmd : TABLE table_spec > { > $$ = cmd_alloc(CMD_ADD, CMD_OBJ_SECMARK, &$2, &@$, $3); > } > + | SYNPROXY obj_spec synproxy_obj > + { > + $$ = cmd_alloc(CMD_ADD, CMD_OBJ_SYNPROXY, &$2, &@$, $3); > + } > ; > > replace_cmd : RULE ruleid_spec rule > @@ -1105,6 +1114,10 @@ create_cmd : TABLE table_spec > { > $$ = cmd_alloc(CMD_CREATE, CMD_OBJ_SECMARK, &$2, &@$, $3); > } > + | SYNPROXY obj_spec synproxy_obj > + { > + $$ = cmd_alloc(CMD_CREATE, CMD_OBJ_SYNPROXY, &$2, &@$, $3); > + } > ; > > insert_cmd : RULE rule_position rule > @@ -1189,6 +1202,14 @@ delete_cmd : TABLE table_spec > { > $$ = cmd_alloc(CMD_DELETE, CMD_OBJ_SECMARK, &$2, &@$, NULL); > } > + | SYNPROXY obj_spec > + { > + $$ = cmd_alloc(CMD_DELETE, CMD_OBJ_SYNPROXY, &$2, &@$, NULL); > + } > + | SYNPROXY objid_spec > + { > + $$ = cmd_alloc(CMD_DELETE, CMD_OBJ_SYNPROXY, &$2, &@$, NULL); > + } > ; > > get_cmd : ELEMENT set_spec set_block_expr > @@ -1273,6 +1294,18 @@ list_cmd : TABLE table_spec > { > $$ = cmd_alloc(CMD_LIST, CMD_OBJ_SECMARK, &$2, &@$, NULL); > } > + | SYNPROXYS ruleset_spec > + { > + $$ = cmd_alloc(CMD_LIST, CMD_OBJ_SYNPROXYS, &$2, &@$, NULL); > + } > + | SYNPROXYS TABLE table_spec > + { > + $$ = cmd_alloc(CMD_LIST, CMD_OBJ_SYNPROXYS, &$3, &@$, NULL); > + } > + | SYNPROXY obj_spec > + { > + $$ = cmd_alloc(CMD_LIST, CMD_OBJ_SYNPROXY, &$2, &@$, NULL); > + } > | RULESET ruleset_spec > { > $$ = cmd_alloc(CMD_LIST, CMD_OBJ_RULESET, &$2, &@$, NULL); > @@ -1592,6 +1625,17 @@ table_block : /* empty */ { $$ = $<table>-1; } > list_add_tail(&$4->list, &$1->objs); > $$ = $1; > } > + | table_block SYNPROXY obj_identifier > + obj_block_alloc '{' synproxy_block '}' > + stmt_separator > + { > + $4->location = @3; > + $4->type = NFT_OBJECT_SYNPROXY; > + handle_merge(&$4->handle, &$3); > + handle_free(&$3); > + list_add_tail(&$4->list, &$1->objs); > + $$ = $1; > + } > ; > > chain_block_alloc : /* empty */ > @@ -1928,6 +1972,16 @@ secmark_block : /* empty */ { $$ = $<obj>-1; } > } > ; > > +synproxy_block : /* empty */ { $$ = $<obj>-1; } > + | synproxy_block common_block > + | synproxy_block stmt_separator > + | synproxy_block synproxy_config > + { > + $1->synproxy = *$2; > + $$ = $1; > + } > + ; > + > type_identifier : STRING { $$ = $1; } > | MARK { $$ = xstrdup("mark"); } > | DSCP { $$ = xstrdup("dscp"); } > @@ -2788,6 +2842,12 @@ synproxy_stmt_alloc : SYNPROXY > { > $$ = synproxy_stmt_alloc(&@$); > } > + | SYNPROXY NAME stmt_expr > + { > + $$ = objref_stmt_alloc(&@$); > + $$->objref.type = NFT_OBJECT_SYNPROXY; > + $$->objref.expr = $3; > + } > ; > > synproxy_args : synproxy_arg > @@ -2817,6 +2877,64 @@ synproxy_arg : MSS NUM > } > ; > > +synproxy_config : MSS NUM WSCALE NUM synproxy_ts synproxy_sack > + { > + struct synproxy *synproxy; > + uint32_t flags = 0; > + > + synproxy = xzalloc(sizeof(*synproxy)); > + synproxy->mss = $2; > + flags |= NF_SYNPROXY_OPT_MSS; > + synproxy->wscale = $4; > + flags |= NF_SYNPROXY_OPT_WSCALE; > + if ($5) > + flags |= $5; > + if ($6) > + flags |= $6; > + synproxy->flags = flags; > + $$ = synproxy; > + } > + | MSS NUM stmt_separator WSCALE NUM stmt_separator synproxy_ts synproxy_sack > + { > + struct synproxy *synproxy; > + uint32_t flags = 0; > + > + synproxy = xzalloc(sizeof(*synproxy)); > + synproxy->mss = $2; > + flags |= NF_SYNPROXY_OPT_MSS; > + synproxy->wscale = $5; > + flags |= NF_SYNPROXY_OPT_WSCALE; > + if ($7) > + flags |= $7; > + if ($8) > + flags |= $8; > + synproxy->flags = flags; > + $$ = synproxy; > + } > + ; > + > +synproxy_obj : synproxy_config > + { > + $$ = obj_alloc(&@$); > + $$->type = NFT_OBJECT_SYNPROXY; > + $$->synproxy = *$1; > + } > + ; > + > +synproxy_ts : /* empty */ { $$ = 0; } > + | TIMESTAMP > + { > + $$ = NF_SYNPROXY_OPT_TIMESTAMP; > + } > + ; > + > +synproxy_sack : /* empty */ { $$ = 0; } > + | SACKPERM > + { > + $$ = NF_SYNPROXY_OPT_SACK_PERM; > + } > + ; > + > primary_stmt_expr : symbol_expr { $$ = $1; } > | integer_expr { $$ = $1; } > | boolean_expr { $$ = $1; } > diff --git a/src/parser_json.c b/src/parser_json.c > index 183d9c9..bcac5e1 100644 > --- a/src/parser_json.c > +++ b/src/parser_json.c > @@ -3019,8 +3019,9 @@ static struct cmd *json_parse_cmd_add_object(struct json_ctx *ctx, > const char *family, *tmp, *rate_unit = "packets", *burst_unit = "bytes"; > uint32_t l3proto = NFPROTO_UNSPEC; > struct handle h = { 0 }; > + int inv = 0, flags = 0; > struct obj *obj; > - int inv = 0; > + json_t *jflags; > > if (json_unpack_err(ctx, root, "{s:s, s:s}", > "family", &family, > @@ -3196,6 +3197,25 @@ static struct cmd *json_parse_cmd_add_object(struct json_ctx *ctx, > obj->limit.unit = seconds_from_unit(tmp); > obj->limit.flags = inv ? NFT_LIMIT_F_INV : 0; > break; > + case CMD_OBJ_SYNPROXY: > + obj->type = NFT_OBJECT_SYNPROXY; > + if (json_unpack_err(ctx, root, "{s:i, s:i}", > + "mss", &obj->synproxy.mss, > + "wscale", &obj->synproxy.wscale)) { > + obj_free(obj); > + return NULL; > + } > + obj->synproxy.flags |= NF_SYNPROXY_OPT_MSS; > + obj->synproxy.flags |= NF_SYNPROXY_OPT_WSCALE; > + if (!json_unpack(root, "{s:o}", "flags", &jflags)) { > + flags = json_parse_synproxy_flags(ctx, jflags); > + if (flags < 0) { > + obj_free(obj); > + return NULL; > + } > + obj->synproxy.flags |= flags; > + } > + break; > default: > BUG("Invalid CMD '%d'", cmd_obj); > } > diff --git a/src/rule.c b/src/rule.c > index 1912513..5bb1c1d 100644 > --- a/src/rule.c > +++ b/src/rule.c > @@ -32,6 +32,7 @@ > #include <linux/netfilter.h> > #include <linux/netfilter_arp.h> > #include <linux/netfilter_ipv4.h> > +#include <linux/netfilter/nf_synproxy.h> > #include <net/if.h> > #include <linux/netfilter_bridge.h> > > @@ -1451,6 +1452,7 @@ void cmd_free(struct cmd *cmd) > case CMD_OBJ_CT_EXPECT: > case CMD_OBJ_LIMIT: > case CMD_OBJ_SECMARK: > + case CMD_OBJ_SYNPROXY: > obj_free(cmd->object); > break; > case CMD_OBJ_FLOWTABLE: > @@ -1542,6 +1544,7 @@ static int do_command_add(struct netlink_ctx *ctx, struct cmd *cmd, bool excl) > case CMD_OBJ_CT_EXPECT: > case CMD_OBJ_LIMIT: > case CMD_OBJ_SECMARK: > + case CMD_OBJ_SYNPROXY: > return mnl_nft_obj_add(ctx, cmd, flags); > case CMD_OBJ_FLOWTABLE: > return mnl_nft_flowtable_add(ctx, cmd, flags); > @@ -1627,6 +1630,8 @@ static int do_command_delete(struct netlink_ctx *ctx, struct cmd *cmd) > return mnl_nft_obj_del(ctx, cmd, NFT_OBJECT_LIMIT); > case CMD_OBJ_SECMARK: > return mnl_nft_obj_del(ctx, cmd, NFT_OBJECT_SECMARK); > + case CMD_OBJ_SYNPROXY: > + return mnl_nft_obj_del(ctx, cmd, NFT_OBJECT_SYNPROXY); > case CMD_OBJ_FLOWTABLE: > return mnl_nft_flowtable_del(ctx, cmd); > default: > @@ -1778,6 +1783,22 @@ static void print_proto_timeout_policy(uint8_t l4, const uint32_t *timeout, > nft_print(octx, " }%s", opts->stmt_separator); > } > > +static const char *synproxy_sack_to_str(const uint32_t flags) > +{ > + if (flags & NF_SYNPROXY_OPT_SACK_PERM) > + return "sack-perm"; > + > + return ""; > +} > + > +static const char *synproxy_timestamp_to_str(const uint32_t flags) > +{ > + if (flags & NF_SYNPROXY_OPT_TIMESTAMP) > + return "timestamp"; > + > + return ""; > +} > + > static void obj_print_data(const struct obj *obj, > struct print_fmt_options *opts, > struct output_ctx *octx) > @@ -1911,6 +1932,30 @@ static void obj_print_data(const struct obj *obj, > nft_print(octx, "%s", opts->nl); > } > break; > + case NFT_OBJECT_SYNPROXY: { > + uint32_t flags = obj->synproxy.flags; > + const char *sack_str = synproxy_sack_to_str(flags); > + const char *ts_str = synproxy_timestamp_to_str(flags); > + > + nft_print(octx, " %s {", obj->handle.obj.name); > + if (nft_output_handle(octx)) > + nft_print(octx, " # handle %" PRIu64, obj->handle.handle.id); > + > + if (flags & NF_SYNPROXY_OPT_MSS) { > + nft_print(octx, "%s%s%s", opts->nl, opts->tab, opts->tab); > + nft_print(octx, "mss %u", obj->synproxy.mss); > + } > + if (flags & NF_SYNPROXY_OPT_WSCALE) { > + nft_print(octx, "%s%s%s", opts->nl, opts->tab, opts->tab); > + nft_print(octx, "wscale %u", obj->synproxy.wscale); > + } > + if (flags & (NF_SYNPROXY_OPT_TIMESTAMP | NF_SYNPROXY_OPT_SACK_PERM)) { > + nft_print(octx, "%s%s%s", opts->nl, opts->tab, opts->tab); > + nft_print(octx, "%s %s", ts_str, sack_str); > + } > + nft_print(octx, "%s", opts->stmt_separator); > + } > + break; > default: > nft_print(octx, " unknown {%s", opts->nl); > break; > @@ -1924,6 +1969,7 @@ static const char * const obj_type_name_array[] = { > [NFT_OBJECT_LIMIT] = "limit", > [NFT_OBJECT_CT_TIMEOUT] = "ct timeout", > [NFT_OBJECT_SECMARK] = "secmark", > + [NFT_OBJECT_SYNPROXY] = "synproxy", > [NFT_OBJECT_CT_EXPECT] = "ct expectation", > }; > > @@ -1941,6 +1987,7 @@ static uint32_t obj_type_cmd_array[NFT_OBJECT_MAX + 1] = { > [NFT_OBJECT_LIMIT] = CMD_OBJ_LIMIT, > [NFT_OBJECT_CT_TIMEOUT] = CMD_OBJ_CT_TIMEOUT, > [NFT_OBJECT_SECMARK] = CMD_OBJ_SECMARK, > + [NFT_OBJECT_SYNPROXY] = CMD_OBJ_SYNPROXY, > [NFT_OBJECT_CT_EXPECT] = CMD_OBJ_CT_EXPECT, > }; > > @@ -2308,6 +2355,9 @@ static int do_command_list(struct netlink_ctx *ctx, struct cmd *cmd) > case CMD_OBJ_SECMARK: > case CMD_OBJ_SECMARKS: > return do_list_obj(ctx, cmd, NFT_OBJECT_SECMARK); > + case CMD_OBJ_SYNPROXY: > + case CMD_OBJ_SYNPROXYS: > + return do_list_obj(ctx, cmd, NFT_OBJECT_SYNPROXY); > case CMD_OBJ_FLOWTABLES: > return do_list_flowtables(ctx, cmd); > default: > diff --git a/src/scanner.l b/src/scanner.l > index fdf84ba..3de5a9e 100644 > --- a/src/scanner.l > +++ b/src/scanner.l > @@ -330,6 +330,7 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr}) > "counters" { return COUNTERS; } > "quotas" { return QUOTAS; } > "limits" { return LIMITS; } > +"synproxys" { return SYNPROXYS; } > > "log" { return LOG; } > "prefix" { return PREFIX; } > diff --git a/src/statement.c b/src/statement.c > index 12689ee..5aa5b1e 100644 > --- a/src/statement.c > +++ b/src/statement.c > @@ -209,6 +209,7 @@ static const char *objref_type[NFT_OBJECT_MAX + 1] = { > [NFT_OBJECT_LIMIT] = "limit", > [NFT_OBJECT_CT_TIMEOUT] = "ct timeout", > [NFT_OBJECT_SECMARK] = "secmark", > + [NFT_OBJECT_SYNPROXY] = "synproxy", > [NFT_OBJECT_CT_EXPECT] = "ct expectation", > }; > > diff --git a/tests/py/ip/objects.t b/tests/py/ip/objects.t > index 35d0110..4f4f909 100644 > --- a/tests/py/ip/objects.t > +++ b/tests/py/ip/objects.t > @@ -50,3 +50,7 @@ ct timeout set "cttime1";ok > %ctexpect5 type ct expectation { protocol udp; dport 9876; timeout 2m; size 12; l3proto ip; };ok > > ct expectation set "ctexpect1";ok > + > +# synproxy > +%synproxy1 type synproxy mss 1460 wscale 7;ok > +%synproxy2 type synproxy mss 1460 wscale 7 timestamp sack-perm;ok >