]> git.ipfire.org Git - thirdparty/nftables.git/commitdiff
src: add synproxy stateful object support
authorFernando Fernandez Mancera <ffmancera@riseup.net>
Thu, 12 Sep 2019 23:07:05 +0000 (01:07 +0200)
committerPablo Neira Ayuso <pablo@netfilter.org>
Fri, 13 Sep 2019 11:34:53 +0000 (13:34 +0200)
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@riseup.net>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
14 files changed:
include/linux/netfilter/nf_tables.h
include/rule.h
src/evaluate.c
src/json.c
src/mnl.c
src/netlink.c
src/parser_bison.y
src/parser_json.c
src/rule.c
src/scanner.l
src/statement.c
tests/py/ip/objects.t
tests/py/ip/objects.t.json
tests/py/ip/objects.t.payload

index 0ff932dadc8e3d943d78acd6124d7953dd4f7a0f..ed8881ad18edd07ad799c387e0c76b754fd54c0f 100644 (file)
@@ -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)
 
 /**
index 0ef6aacdd71b5e606ae17155cd61d9e65739789f..2708cbebc9f8e5b738726bfb168c615dbb59a3e2 100644 (file)
@@ -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 {
index 29fe966008b1bc90913751181ed456cb06b57e38..a56cd2a56e9906c3d802c2aaf59db4119edc03da 100644 (file)
@@ -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)
index 55ce05315d371a7852abeca9d418aef045b92bcc..6adc8012dc8e651e3a22c71b2b3e8296e54910ee 100644 (file)
@@ -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;
index 8031bd6add800faf5a0c7efaebea88596d8aa906..57ff89f50e2321229bbd63cfa7599f9cdec756e8 100644 (file)
--- 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;
index f8e1120447d95eed116b2cda79ca8a851812c4d3..1e669e5dcaa18a12113ec4bf6ebfead868f2e6f4 100644 (file)
@@ -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;
 
index b7db1a21845b82da7f77bd1861b54a315e24e59b..3fccea6734c0b18b182e6c14d258efc6a69e4386 100644 (file)
@@ -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; }
index 183d9c972181e1c8c15221154f2e9a7258bd7093..398ae19275c3bca55ed5471174cf4cb92c901e74 100644 (file)
@@ -2244,13 +2244,18 @@ static int json_parse_synproxy_flags(struct json_ctx *ctx, json_t *root)
 static struct stmt *json_parse_synproxy_stmt(struct json_ctx *ctx,
                                             const char *key, json_t *value)
 {
-       struct stmt *stmt;
+       struct stmt *stmt = NULL;
        json_t *jflags;
        int tmp, flags;
 
-       stmt = synproxy_stmt_alloc(int_loc);
+       if (json_typeof(value) == JSON_NULL) {
+               stmt = synproxy_stmt_alloc(int_loc);
+               return stmt;
+       }
 
        if (!json_unpack(value, "{s:i}", "mss", &tmp)) {
+               if (!stmt)
+                       stmt = synproxy_stmt_alloc(int_loc);
                if (tmp < 0) {
                        json_error(ctx, "Invalid synproxy mss value '%d'", tmp);
                        stmt_free(stmt);
@@ -2260,6 +2265,8 @@ static struct stmt *json_parse_synproxy_stmt(struct json_ctx *ctx,
                stmt->synproxy.flags |= NF_SYNPROXY_OPT_MSS;
        }
        if (!json_unpack(value, "{s:i}", "wscale", &tmp)) {
+               if (!stmt)
+                       stmt = synproxy_stmt_alloc(int_loc);
                if (tmp < 0) {
                        json_error(ctx, "Invalid synproxy wscale value '%d'", tmp);
                        stmt_free(stmt);
@@ -2269,6 +2276,8 @@ static struct stmt *json_parse_synproxy_stmt(struct json_ctx *ctx,
                stmt->synproxy.flags |= NF_SYNPROXY_OPT_WSCALE;
        }
        if (!json_unpack(value, "{s:o}", "flags", &jflags)) {
+               if (!stmt)
+                       stmt = synproxy_stmt_alloc(int_loc);
                flags = json_parse_synproxy_flags(ctx, jflags);
 
                if (flags < 0) {
@@ -2277,6 +2286,17 @@ static struct stmt *json_parse_synproxy_stmt(struct json_ctx *ctx,
                }
                stmt->synproxy.flags |= flags;
        }
+
+       if (!stmt) {
+               stmt = objref_stmt_alloc(int_loc);
+               stmt->objref.type = NFT_OBJECT_SYNPROXY;
+               stmt->objref.expr = json_parse_stmt_expr(ctx, value);
+               if (!stmt->objref.expr) {
+                       json_error(ctx, "Invalid synproxy reference");
+                       stmt_free(stmt);
+                       return NULL;
+               }
+       }
        return stmt;
 }
 
@@ -3019,8 +3039,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 +3217,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);
        }
index 19125131c8ed27440a6568c08ac3fe33757eae53..5bb1c1d307895af3a73f23f9880d4bb719f71af2 100644 (file)
@@ -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:
index fdf84ba7820e02598de852842879601218d5c984..3de5a9e0426e6853a98d114300e48b76155a38fc 100644 (file)
@@ -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; }
index 12689ee51043652619e4a8511e34ba4da2106212..5aa5b1e0bda4fbabbdc0ea0f561aed6b93fe6772 100644 (file)
@@ -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",
 };
 
index 35d01101bd53bbfe08bebd333900965011d58dee..4fcde7cc12ea1383cfb321723d5eab6ccc3d26bc 100644 (file)
@@ -50,3 +50,9 @@ 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
+
+synproxy name tcp dport map {443 : "synproxy1", 80 : "synproxy2"};ok
index 596ad188b5f4a0e551ae648b1b20bd5b92403dd5..634f19217072693b0b6b644c3adeac104d52f69f 100644 (file)
     }
 ]
 
+# synproxy name tcp dport map {443 : "synproxy1", 80 : "synproxy2"}
+[
+    {
+        "synproxy": {
+            "map": {
+                "key": {
+                    "payload": {
+                        "field": "dport",
+                        "protocol": "tcp"
+                    }
+                },
+                "data": {
+                    "set": [
+                        [
+                            80,
+                            "synproxy2"
+                        ],
+                        [
+                            443,
+                            "synproxy1"
+                        ]
+                    ]
+                }
+            }
+        }
+    }
+]
index ef3e86aa8ba726d7a8983a3d7ac4f6c52c503252..5252724ceead153412b0605949325fcf7af88880 100644 (file)
@@ -67,3 +67,13 @@ ip test-ip4 output
 # ct expectation set "ctexpect1"
 ip test-ip4 output
   [ objref type 9 name ctexpect1 ]
+
+# synproxy name tcp dport map {443 : "synproxy1", 80 : "synproxy2"}
+__objmap%d test-ip4 43 size 2
+__objmap%d test-ip4 0
+       element 0000bb01  : 0 [end]     element 00005000  : 0 [end]
+ip test-ip4 output
+  [ meta load l4proto => reg 1 ]
+  [ cmp eq reg 1 0x00000006 ]
+  [ payload load 2b @ transport header + 2 => reg 1 ]
+  [ objref sreg 1 set __objmap%d ]