Hi,

I have been working on the synproxy expression. In my opinion, there is
no way to use sets or maps with synproxy so I think it should be a
statement.

This patch is almost finished, but I have been dealing with the
following error.

# nft add table ip foo
# nft add chain ip foo bar
# nft add rule ip foo bar synproxy mss 1460 wscale 7

> Error: Could not process rule: Numerical result out of range
> add rule ip foo bar synproxy mss 10 wscale 2
> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

I have tried to debug it using libnftables directly. And I still getting
the same error. The problem should be in the libnftnl or nf-next patch.
I am probably missing something. Any suggestion? Thanks :-)

On 6/17/19 12:32 PM, Fernando Fernandez Mancera wrote:
> 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);
> +}
> 

Reply via email to