Signed-off-by: Fernando Fernandez Mancera <[email protected]>
---
 include/linux/netfilter/nf_SYNPROXY.h | 23 ++++++++++++
 include/linux/netfilter/nf_tables.h   | 16 +++++++++
 include/statement.h                   | 11 ++++++
 src/evaluate.c                        | 16 +++++++++
 src/netlink_delinearize.c             | 17 +++++++++
 src/netlink_linearize.c               | 17 +++++++++
 src/parser_bison.y                    | 48 +++++++++++++++++++++++++
 src/scanner.l                         |  6 ++++
 src/statement.c                       | 50 +++++++++++++++++++++++++++
 9 files changed, 204 insertions(+)
 create mode 100644 include/linux/netfilter/nf_SYNPROXY.h

diff --git a/include/linux/netfilter/nf_SYNPROXY.h 
b/include/linux/netfilter/nf_SYNPROXY.h
new file mode 100644
index 0000000..0e7c391
--- /dev/null
+++ b/include/linux/netfilter/nf_SYNPROXY.h
@@ -0,0 +1,23 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _NF_SYNPROXY_H
+#define _NF_SYNPROXY_H
+
+#include <linux/types.h>
+
+#define NF_SYNPROXY_OPT_MSS            0x01
+#define NF_SYNPROXY_OPT_WSCALE         0x02
+#define NF_SYNPROXY_OPT_SACK_PERM      0x04
+#define NF_SYNPROXY_OPT_TIMESTAMP      0x08
+#define NF_SYNPROXY_OPT_ECN            0x10
+#define NF_SYNPROXY_FLAGMASK           (NF_SYNPROXY_OPT_MSS | \
+                                        NF_SYNPROXY_OPT_WSCALE | \
+                                        NF_SYNPROXY_OPT_SACK_PERM | \
+                                        NF_SYNPROXY_OPT_TIMESTAMP)
+
+struct nf_synproxy_info {
+       __u8    options;
+       __u8    wscale;
+       __u16   mss;
+};
+
+#endif /* _NF_SYNPROXY_H */
diff --git a/include/linux/netfilter/nf_tables.h 
b/include/linux/netfilter/nf_tables.h
index 7bdb234..d9ccf3f 100644
--- a/include/linux/netfilter/nf_tables.h
+++ b/include/linux/netfilter/nf_tables.h
@@ -1529,6 +1529,22 @@ enum nft_osf_attributes {
 };
 #define NFTA_OSF_MAX (__NFTA_OSF_MAX - 1)
 
+/**
+ * enum nft_synproxy_attributes - nftables synproxy expression
+ * netlink attributes
+ *
+ * @NFTA_SYNPROXY_MSS: mss value sent to the backend (NLA_U16)
+ * @NFTA_SYNPROXY_WSCALE: wscale value sent to the backend (NLA_U8)
+ * @NFTA_SYNPROXY_FLAGS: flags (NLA_U32)
+ */
+enum nft_synproxy_attributes {
+       NFTA_SYNPROXY_MSS,
+       NFTA_SYNPROXY_WSCALE,
+       NFTA_SYNPROXY_FLAGS,
+       __NFTA_SYNPROXY_MAX,
+};
+#define NFTA_SYNPROXY_MAX (__NFTA_SYNPROXY_MAX - 1)
+
 /**
  * enum nft_device_attributes - nf_tables device netlink attributes
  *
diff --git a/include/statement.h b/include/statement.h
index 91d6e0e..f789ced 100644
--- a/include/statement.h
+++ b/include/statement.h
@@ -203,6 +203,14 @@ struct map_stmt {
 
 extern struct stmt *map_stmt_alloc(const struct location *loc);
 
+struct synproxy_stmt {
+       uint16_t        mss;
+       uint8_t         wscale;
+       uint32_t        flags;
+};
+
+extern struct stmt *synproxy_stmt_alloc(const struct location *loc);
+
 struct meter_stmt {
        struct expr             *set;
        struct expr             *key;
@@ -270,6 +278,7 @@ extern struct stmt *xt_stmt_alloc(const struct location 
*loc);
  * @STMT_FLOW_OFFLOAD: flow offload statement
  * @STMT_CONNLIMIT:    connection limit statement
  * @STMT_MAP:          map statement
+ * @STMT_SYNPROXY:     synproxy statement
  */
 enum stmt_types {
        STMT_INVALID,
@@ -297,6 +306,7 @@ enum stmt_types {
        STMT_FLOW_OFFLOAD,
        STMT_CONNLIMIT,
        STMT_MAP,
+       STMT_SYNPROXY,
 };
 
 /**
@@ -361,6 +371,7 @@ struct stmt {
                struct objref_stmt      objref;
                struct flow_stmt        flow;
                struct map_stmt         map;
+               struct synproxy_stmt    synproxy;
        };
 };
 
diff --git a/src/evaluate.c b/src/evaluate.c
index 39101b4..04692b8 100644
--- a/src/evaluate.c
+++ b/src/evaluate.c
@@ -17,6 +17,7 @@
 #include <linux/netfilter.h>
 #include <linux/netfilter_arp.h>
 #include <linux/netfilter/nf_tables.h>
+#include <linux/netfilter/nf_SYNPROXY.h>
 #include <linux/netfilter_ipv4.h>
 #include <netinet/ip_icmp.h>
 #include <netinet/icmp6.h>
@@ -2704,6 +2705,19 @@ static int stmt_evaluate_tproxy(struct eval_ctx *ctx, 
struct stmt *stmt)
        return 0;
 }
 
+static int stmt_evaluate_synproxy(struct eval_ctx *ctx, struct stmt *stmt)
+{
+       printf("Values of the synproxy expr: %u %u\n", stmt->synproxy.mss, 
stmt->synproxy.wscale);
+       if (stmt->synproxy.flags != 0 &&
+           !(stmt->synproxy.flags & (NF_SYNPROXY_OPT_MSS |
+                                     NF_SYNPROXY_OPT_WSCALE |
+                                     NF_SYNPROXY_OPT_TIMESTAMP |
+                                     NF_SYNPROXY_OPT_SACK_PERM)))
+               return stmt_error(ctx, stmt, "This flags are not supported for 
SYNPROXY");
+
+       return 0;
+}
+
 static int stmt_evaluate_dup(struct eval_ctx *ctx, struct stmt *stmt)
 {
        int err;
@@ -3048,6 +3062,8 @@ int stmt_evaluate(struct eval_ctx *ctx, struct stmt *stmt)
                return stmt_evaluate_objref(ctx, stmt);
        case STMT_MAP:
                return stmt_evaluate_map(ctx, stmt);
+       case STMT_SYNPROXY:
+               return stmt_evaluate_synproxy(ctx, stmt);
        default:
                BUG("unknown statement type %s\n", stmt->ops->name);
        }
diff --git a/src/netlink_delinearize.c b/src/netlink_delinearize.c
index 0270e1f..2785325 100644
--- a/src/netlink_delinearize.c
+++ b/src/netlink_delinearize.c
@@ -1010,6 +1010,22 @@ out_err:
        xfree(stmt);
 }
 
+static void netlink_parse_synproxy(struct netlink_parse_ctx *ctx,
+                                  const struct location *loc,
+                                  const struct nftnl_expr *nle)
+{
+       struct stmt *stmt;
+
+       stmt = synproxy_stmt_alloc(loc);
+       stmt->synproxy.mss = nftnl_expr_get_u16(nle, NFTNL_EXPR_SYNPROXY_MSS);
+       stmt->synproxy.wscale = nftnl_expr_get_u8(nle,
+                                                 NFTNL_EXPR_SYNPROXY_WSCALE);
+       stmt->synproxy.flags = nftnl_expr_get_u32(nle,
+                                                 NFTNL_EXPR_SYNPROXY_FLAGS);
+
+       ctx->stmt = stmt;
+}
+
 static void netlink_parse_tproxy(struct netlink_parse_ctx *ctx,
                              const struct location *loc,
                              const struct nftnl_expr *nle)
@@ -1476,6 +1492,7 @@ static const struct {
        { .name = "tcpopt",     .parse = netlink_parse_exthdr },
        { .name = "flow_offload", .parse = netlink_parse_flow_offload },
        { .name = "xfrm",       .parse = netlink_parse_xfrm },
+       { .name = "synproxy",   .parse = netlink_parse_synproxy },
 };
 
 static int netlink_parse_expr(const struct nftnl_expr *nle,
diff --git a/src/netlink_linearize.c b/src/netlink_linearize.c
index 2c6aa64..498326d 100644
--- a/src/netlink_linearize.c
+++ b/src/netlink_linearize.c
@@ -1141,6 +1141,21 @@ static void netlink_gen_tproxy_stmt(struct 
netlink_linearize_ctx *ctx,
        nftnl_rule_add_expr(ctx->nlr, nle);
 }
 
+static void netlink_gen_synproxy_stmt(struct netlink_linearize_ctx *ctx,
+                                     const struct stmt *stmt)
+{
+       struct nftnl_expr *nle;
+
+       nle = alloc_nft_expr("synproxy");
+       nftnl_expr_set_u16(nle, NFTNL_EXPR_SYNPROXY_MSS, stmt->synproxy.mss);
+       nftnl_expr_set_u8(nle, NFTNL_EXPR_SYNPROXY_WSCALE,
+                         stmt->synproxy.wscale);
+       nftnl_expr_set_u32(nle, NFTNL_EXPR_SYNPROXY_FLAGS,
+                          stmt->synproxy.flags);
+
+       nftnl_rule_add_expr(ctx->nlr, nle);
+}
+
 static void netlink_gen_dup_stmt(struct netlink_linearize_ctx *ctx,
                                 const struct stmt *stmt)
 {
@@ -1382,6 +1397,8 @@ static void netlink_gen_stmt(struct netlink_linearize_ctx 
*ctx,
                return netlink_gen_nat_stmt(ctx, stmt);
        case STMT_TPROXY:
                return netlink_gen_tproxy_stmt(ctx, stmt);
+       case STMT_SYNPROXY:
+               return netlink_gen_synproxy_stmt(ctx, stmt);
        case STMT_DUP:
                return netlink_gen_dup_stmt(ctx, stmt);
        case STMT_QUEUE:
diff --git a/src/parser_bison.y b/src/parser_bison.y
index 97a48f3..61e0888 100644
--- a/src/parser_bison.y
+++ b/src/parser_bison.y
@@ -23,6 +23,7 @@
 #include <linux/netfilter/nf_nat.h>
 #include <linux/netfilter/nf_log.h>
 #include <linux/netfilter/nfnetlink_osf.h>
+#include <linux/netfilter/nf_SYNPROXY.h>
 #include <linux/xfrm.h>
 #include <netinet/ip_icmp.h>
 #include <netinet/icmp6.h>
@@ -200,6 +201,12 @@ int nft_lex(void *, void *, void *);
 
 %token OSF                     "osf"
 
+%token SYNPROXY                        "synproxy"
+%token MSS                     "mss"
+%token WSCALE                  "wscale"
+%token TIMESTAMP               "timestamp"
+%token SACKPERM                        "sack-perm"
+
 %token HOOK                    "hook"
 %token DEVICE                  "device"
 %token DEVICES                 "devices"
@@ -601,6 +608,9 @@ int nft_lex(void *, void *, void *);
 %type <val>                    nf_nat_flags nf_nat_flag offset_opt
 %type <stmt>                   tproxy_stmt
 %destructor { stmt_free($$); } tproxy_stmt
+%type <stmt>                   synproxy_stmt synproxy_stmt_alloc
+%destructor { stmt_free($$); } synproxy_stmt synproxy_stmt_alloc
+
 
 %type <stmt>                   queue_stmt queue_stmt_alloc
 %destructor { stmt_free($$); } queue_stmt queue_stmt_alloc
@@ -2245,6 +2255,7 @@ stmt                      :       verdict_stmt
                        |       fwd_stmt
                        |       set_stmt
                        |       map_stmt
+                       |       synproxy_stmt
                        ;
 
 verdict_stmt           :       verdict_expr
@@ -2675,6 +2686,43 @@ tproxy_stmt              :       TPROXY TO stmt_expr
                        }
                        ;
 
+synproxy_stmt          :       synproxy_stmt_alloc
+                       |       synproxy_stmt_alloc     synproxy_args
+                       ;
+
+synproxy_stmt_alloc    :       SYNPROXY
+                       {
+                               $$ = synproxy_stmt_alloc(&@$);
+                       }
+                       ;
+
+synproxy_args          :       synproxy_arg
+                       {
+                               $<stmt>$        = $<stmt>0;
+                       }
+                       |       synproxy_args   synproxy_arg
+                       ;
+
+synproxy_arg           :       MSS     NUM
+                       {
+                               $<stmt>0->synproxy.mss = $2;
+                               $<stmt>0->synproxy.flags |= NF_SYNPROXY_OPT_MSS;
+                       }
+                       |       WSCALE  NUM
+                       {
+                               $<stmt>0->synproxy.wscale = $2;
+                               $<stmt>0->synproxy.flags |= 
NF_SYNPROXY_OPT_WSCALE;
+                       }
+                       |       TIMESTAMP
+                       {
+                               $<stmt>0->synproxy.flags |= 
NF_SYNPROXY_OPT_TIMESTAMP;
+                       }
+                       |       SACKPERM
+                       {
+                               $<stmt>0->synproxy.flags |= 
NF_SYNPROXY_OPT_SACK_PERM;
+                       }
+                       ;
+
 primary_stmt_expr      :       symbol_expr             { $$ = $1; }
                        |       integer_expr            { $$ = $1; }
                        |       boolean_expr            { $$ = $1; }
diff --git a/src/scanner.l b/src/scanner.l
index d1f6e87..e990cc6 100644
--- a/src/scanner.l
+++ b/src/scanner.l
@@ -543,6 +543,12 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr})
 
 "osf"                  { return OSF; }
 
+"synproxy"             { return SYNPROXY; }
+"mss"                  { return MSS; }
+"wscale"               { return WSCALE; }
+"timestamp"            { return TIMESTAMP; }
+"sack-perm"            { return SACKPERM; }
+
 "notrack"              { return NOTRACK; }
 
 "options"              { return OPTIONS; }
diff --git a/src/statement.c b/src/statement.c
index a9e8b3a..3489e3e 100644
--- a/src/statement.c
+++ b/src/statement.c
@@ -29,6 +29,7 @@
 #include <netinet/in.h>
 #include <linux/netfilter/nf_nat.h>
 #include <linux/netfilter/nf_log.h>
+#include <linux/netfilter/nf_SYNPROXY.h>
 
 struct stmt *stmt_alloc(const struct location *loc,
                        const struct stmt_ops *ops)
@@ -877,3 +878,52 @@ struct stmt *xt_stmt_alloc(const struct location *loc)
 {
        return stmt_alloc(loc, &xt_stmt_ops);
 }
+
+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 synproxy_stmt_print(const struct stmt *stmt,
+                               struct output_ctx *octx)
+{
+       uint32_t flags = stmt->synproxy.flags;
+       const char *ts_str = synproxy_timestamp_to_str(flags);
+       const char *sack_str = synproxy_sack_to_str(flags);
+
+       if (flags & (NF_SYNPROXY_OPT_MSS | NF_SYNPROXY_OPT_WSCALE))
+               nft_print(octx, "synproxy mss %u wscale %u%s%s",
+                         stmt->synproxy.mss, stmt->synproxy.wscale,
+                         ts_str, sack_str);
+       else if (flags & NF_SYNPROXY_OPT_MSS)
+               nft_print(octx, "synproxy mss %u%s%s", stmt->synproxy.mss,
+                         ts_str, sack_str);
+       else if (flags & NF_SYNPROXY_OPT_WSCALE)
+               nft_print(octx, "synproxy wscale %u%s%s", stmt->synproxy.wscale,
+                         ts_str, sack_str);
+       else
+               nft_print(octx, "synproxy%s%s", ts_str, sack_str);
+
+}
+
+static const struct stmt_ops synproxy_stmt_ops = {
+       .type           = STMT_SYNPROXY,
+       .name           = "synproxy",
+       .print          = synproxy_stmt_print,
+};
+
+struct stmt *synproxy_stmt_alloc(const struct location *loc)
+{
+       return stmt_alloc(loc, &synproxy_stmt_ops);
+}
-- 
2.20.1

Reply via email to