]> git.ipfire.org Git - thirdparty/nftables.git/commitdiff
src: support limit rate over value
authorPablo Neira Ayuso <pablo@netfilter.org>
Wed, 9 Dec 2015 21:55:30 +0000 (22:55 +0100)
committerPablo Neira Ayuso <pablo@netfilter.org>
Thu, 14 Jan 2016 17:54:39 +0000 (18:54 +0100)
So far it was only possible to match packet under a rate limit, this
patch allows you to explicitly indicate if you want to match packets
that goes over or until the rate limit, eg.

... limit rate over 3/second counter log prefix "OVERLIMIT: " drop
... limit rate over 3 mbytes/second counter log prefix "OVERLIMIT: " drop
... ct state invalid limit rate until 1/second counter log prefix "INVALID: "

When listing rate limit until, this shows:

... ct state invalid limit rate 1/second counter log prefix "INVALID: "

thus, the existing syntax is still valid (i.e. default to rate limit until).

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
include/linux/netfilter/nf_tables.h
include/statement.h
src/netlink_delinearize.c
src/netlink_linearize.c
src/parser_bison.y
src/scanner.l
src/statement.c
tests/py/any/limit.t
tests/py/any/limit.t.payload

index 49de2b8a65abcd407a3cd9685006c8208fd4e553..310c785c5e32bef56616fd037e70e21e72d59f7d 100644 (file)
@@ -771,6 +771,10 @@ enum nft_limit_type {
        NFT_LIMIT_PKT_BYTES
 };
 
+enum nft_limit_flags {
+       NFT_LIMIT_F_INV = (1 << 0),
+};
+
 /**
  * enum nft_limit_attributes - nf_tables limit expression netlink attributes
  *
@@ -778,6 +782,7 @@ enum nft_limit_type {
  * @NFTA_LIMIT_UNIT: refill unit (NLA_U64)
  * @NFTA_LIMIT_BURST: burst (NLA_U32)
  * @NFTA_LIMIT_TYPE: type of limit (NLA_U32: enum nft_limit_type)
+ * @NFTA_LIMIT_FLAGS: flags (NLA_U32: enum nft_limit_flags)
  */
 enum nft_limit_attributes {
        NFTA_LIMIT_UNSPEC,
@@ -785,6 +790,7 @@ enum nft_limit_attributes {
        NFTA_LIMIT_UNIT,
        NFTA_LIMIT_BURST,
        NFTA_LIMIT_TYPE,
+       NFTA_LIMIT_FLAGS,
        __NFTA_LIMIT_MAX
 };
 #define NFTA_LIMIT_MAX         (__NFTA_LIMIT_MAX - 1)
index 53620aece62f3eae3b2a8ab5f21cdaf79d477507..6be3a240ec79d32d78f433b890dad3d033feda59 100644 (file)
@@ -61,6 +61,7 @@ struct limit_stmt {
        uint64_t                unit;
        enum nft_limit_type     type;
        uint32_t                burst;
+       uint32_t                flags;
 };
 
 extern struct stmt *limit_stmt_alloc(const struct location *loc);
index 841be6090a67aaa41034c2d2803b055ca00d455c..3f01781658c476becb2b2b4e20c23576532fa163 100644 (file)
@@ -621,6 +621,7 @@ static void netlink_parse_limit(struct netlink_parse_ctx *ctx,
        stmt->limit.unit = nftnl_expr_get_u64(nle, NFTNL_EXPR_LIMIT_UNIT);
        stmt->limit.type = nftnl_expr_get_u32(nle, NFTNL_EXPR_LIMIT_TYPE);
        stmt->limit.burst = nftnl_expr_get_u32(nle, NFTNL_EXPR_LIMIT_BURST);
+       stmt->limit.flags = nftnl_expr_get_u32(nle, NFTNL_EXPR_LIMIT_FLAGS);
        list_add_tail(&stmt->list, &ctx->rule->stmts);
 }
 
index c77c462bb6fa5a6fced0c575d0b80607e71f36aa..0dc7f97e704e12b1bb66a354aa3e3c103a0a0dde 100644 (file)
@@ -793,6 +793,7 @@ static void netlink_gen_limit_stmt(struct netlink_linearize_ctx *ctx,
        if (stmt->limit.burst > 0)
                nftnl_expr_set_u32(nle, NFTNL_EXPR_LIMIT_BURST,
                                   stmt->limit.burst);
+       nftnl_expr_set_u32(nle, NFTNL_EXPR_LIMIT_FLAGS, stmt->limit.flags);
 
        nftnl_rule_add_expr(ctx->nlr, nle);
 }
index 833e7f5d60dafea3dbb1d7d07811577e5b8f31ef..514dd7eb2fe81667690ae5a42f6fbd6696fae881 100644 (file)
@@ -367,6 +367,8 @@ static void location_update(struct location *loc, struct location *rhs, int n)
 %token LIMIT                   "limit"
 %token RATE                    "rate"
 %token BURST                   "burst"
+%token OVER                    "over"
+%token UNTIL                   "until"
 
 %token NANOSECOND              "nanosecond"
 %token MICROSECOND             "microsecond"
@@ -458,7 +460,7 @@ static void location_update(struct location *loc, struct location *rhs, int n)
 %type <val>                    level_type
 %type <stmt>                   limit_stmt
 %destructor { stmt_free($$); } limit_stmt
-%type <val>                    limit_burst time_unit
+%type <val>                    limit_burst limit_mode time_unit
 %type <stmt>                   reject_stmt reject_stmt_alloc
 %destructor { stmt_free($$); } reject_stmt reject_stmt_alloc
 %type <stmt>                   nat_stmt nat_stmt_alloc masq_stmt masq_stmt_alloc redir_stmt redir_stmt_alloc
@@ -1467,33 +1469,40 @@ level_type              :       LEVEL_EMERG     { $$ = LOG_EMERG; }
                        |       LEVEL_DEBUG     { $$ = LOG_DEBUG; }
                        ;
 
-limit_stmt             :       LIMIT   RATE    NUM     SLASH   time_unit       limit_burst
+limit_stmt             :       LIMIT   RATE    limit_mode      NUM     SLASH   time_unit       limit_burst
                        {
                                $$ = limit_stmt_alloc(&@$);
-                               $$->limit.rate  = $3;
-                               $$->limit.unit  = $5;
-                               $$->limit.burst = $6;
+                               $$->limit.rate  = $4;
+                               $$->limit.unit  = $6;
+                               $$->limit.burst = $7;
                                $$->limit.type  = NFT_LIMIT_PKTS;
+                               $$->limit.flags = $3;
                        }
-                       |       LIMIT RATE      NUM     STRING  limit_burst
+                       |       LIMIT   RATE    limit_mode      NUM     STRING  limit_burst
                        {
                                struct error_record *erec;
                                uint64_t rate, unit;
 
-                               erec = rate_parse(&@$, $4, &rate, &unit);
+                               erec = rate_parse(&@$, $5, &rate, &unit);
                                if (erec != NULL) {
                                        erec_queue(erec, state->msgs);
                                        YYERROR;
                                }
 
                                $$ = limit_stmt_alloc(&@$);
-                               $$->limit.rate  = rate * $3;
+                               $$->limit.rate  = rate * $4;
                                $$->limit.unit  = unit;
-                               $$->limit.burst = $5;
+                               $$->limit.burst = $6;
                                $$->limit.type  = NFT_LIMIT_PKT_BYTES;
+                               $$->limit.flags = $3;
                        }
                        ;
 
+limit_mode             :       OVER                            { $$ = NFT_LIMIT_F_INV; }
+                       |       UNTIL                           { $$ = 0; }
+                       |       /* empty */                     { $$ = 0; }
+                       ;
+
 limit_burst            :       /* empty */                     { $$ = 0; }
                        |       BURST   NUM     PACKETS         { $$ = $2; }
                        |       BURST   NUM     BYTES           { $$ = $2; }
index a98e7b6a4a296052d480416dc531c2abcc37d506..e5ac8aa7b58dd8f082cd68db49cd75d6827d0594 100644 (file)
@@ -312,6 +312,8 @@ addrstring  ({macaddr}|{ip4addr}|{ip6addr})
 "limit"                        { return LIMIT; }
 "rate"                 { return RATE; }
 "burst"                        { return BURST; }
+"until"                        { return UNTIL; }
+"over"                 { return OVER; }
 
 "nanosecond"           { return NANOSECOND; }
 "microsecond"          { return MICROSECOND; }
index 2d1a3e6bd1340298dcad87cb1fe175f3136adff9..153e93be785f320cd978ff7579e84e7c64fa980f 100644 (file)
@@ -213,21 +213,24 @@ static const char *get_rate(uint64_t byte_rate, uint64_t *rate)
 
 static void limit_stmt_print(const struct stmt *stmt)
 {
+       bool inv = stmt->limit.flags & NFT_LIMIT_F_INV;
        const char *data_unit;
        uint64_t rate;
 
        switch (stmt->limit.type) {
        case NFT_LIMIT_PKTS:
-               printf("limit rate %" PRIu64 "/%s",
-                      stmt->limit.rate, get_unit(stmt->limit.unit));
+               printf("limit rate %s%" PRIu64 "/%s",
+                      inv ? "over " : "", stmt->limit.rate,
+                      get_unit(stmt->limit.unit));
                if (stmt->limit.burst > 0)
                        printf(" burst %u packets", stmt->limit.burst);
                break;
        case NFT_LIMIT_PKT_BYTES:
                data_unit = get_rate(stmt->limit.rate, &rate);
 
-               printf("limit rate %" PRIu64 " %s/%s",
-                      rate, data_unit, get_unit(stmt->limit.unit));
+               printf("limit rate %s%" PRIu64 " %s/%s",
+                      inv ? "over " : "", rate, data_unit,
+                      get_unit(stmt->limit.unit));
                if (stmt->limit.burst > 0) {
                        uint64_t burst;
 
index 358b5abb8d3a7f907e4b029a0c2f624303089853..8180bea3ddae62195e6c951a1f88d7c21c31ffd2 100644 (file)
@@ -26,3 +26,22 @@ limit rate 1025 bytes/second burst 512 bytes;ok
 limit rate 1025 kbytes/second burst 1023 kbytes;ok
 limit rate 1025 mbytes/second burst 1025 kbytes;ok
 limit rate 1025000 mbytes/second burst 1023 mbytes;ok
+
+limit rate over 400/minute;ok
+limit rate over 20/second;ok
+limit rate over 400/hour;ok
+limit rate over 40/day;ok
+limit rate over 400/week;ok
+limit rate over 1023/second burst 10 packets;ok
+
+limit rate over 1 kbytes/second;ok
+limit rate over 2 kbytes/second;ok
+limit rate over 1025 kbytes/second;ok
+limit rate over 1023 mbytes/second;ok
+limit rate over 10230 mbytes/second;ok
+limit rate over 1023000 mbytes/second;ok
+
+limit rate over 1025 bytes/second burst 512 bytes;ok
+limit rate over 1025 kbytes/second burst 1023 kbytes;ok
+limit rate over 1025 mbytes/second burst 1025 kbytes;ok
+limit rate over 1025000 mbytes/second burst 1023 mbytes;ok
index a3c87d842e0c61277a1250c0dfbd66b988f3551b..b0cc84b42ff392317d5d8e75ac3c2a02672cacc7 100644 (file)
 # limit rate 400/minute
 ip test-ip4 output
-  [ limit rate 400/minute burst 0 type packets ]
+  [ limit rate 400/minute burst 0 type packets flags 0x0 ]
 
 # limit rate 20/second
 ip test-ip4 output
-  [ limit rate 20/second burst 0 type packets ]
+  [ limit rate 20/second burst 0 type packets flags 0x0 ]
 
 # limit rate 400/hour
 ip test-ip4 output
-  [ limit rate 400/hour burst 0 type packets ]
+  [ limit rate 400/hour burst 0 type packets flags 0x0 ]
 
 # limit rate 400/week
 ip test-ip4 output
-  [ limit rate 400/week burst 0 type packets ]
+  [ limit rate 400/week burst 0 type packets flags 0x0 ]
 
 # limit rate 40/day
 ip test-ip4 output
-  [ limit rate 40/day burst 0 type packets ]
+  [ limit rate 40/day burst 0 type packets flags 0x0 ]
 
 # limit rate 1023/second burst 10 packets
 ip test-ip4 output
-  [ limit rate 1023/second burst 10 type packets ]
+  [ limit rate 1023/second burst 10 type packets flags 0x0 ]
 
 # limit rate 1 kbytes/second
 ip test-ip4 output
-  [ limit rate 1024/second burst 0 type bytes ]
+  [ limit rate 1024/second burst 0 type bytes flags 0x0 ]
 
 # limit rate 2 kbytes/second
 ip test-ip4 output
-  [ limit rate 2048/second burst 0 type bytes ]
+  [ limit rate 2048/second burst 0 type bytes flags 0x0 ]
 
 # limit rate 1025 kbytes/second
 ip test-ip4 output
-  [ limit rate 1049600/second burst 0 type bytes ]
+  [ limit rate 1049600/second burst 0 type bytes flags 0x0 ]
 
 # limit rate 1023 mbytes/second
 ip test-ip4 output
-  [ limit rate 1072693248/second burst 0 type bytes ]
+  [ limit rate 1072693248/second burst 0 type bytes flags 0x0 ]
 
 # limit rate 10230 mbytes/second
 ip test-ip4 output
-  [ limit rate 10726932480/second burst 0 type bytes ]
+  [ limit rate 10726932480/second burst 0 type bytes flags 0x0 ]
 
 # limit rate 1023000 mbytes/second
 ip test-ip4 output
-  [ limit rate 1072693248000/second burst 0 type bytes ]
+  [ limit rate 1072693248000/second burst 0 type bytes flags 0x0 ]
 
 # limit rate 1025 bytes/second burst 512 bytes
 ip test-ip4 output
-  [ limit rate 1025/second burst 512 type bytes ]
+  [ limit rate 1025/second burst 512 type bytes flags 0x0 ]
 
 # limit rate 1025 kbytes/second burst 1023 kbytes
 ip test-ip4 output
-  [ limit rate 1049600/second burst 1047552 type bytes ]
+  [ limit rate 1049600/second burst 1047552 type bytes flags 0x0 ]
 
 # limit rate 1025 mbytes/second burst 1025 kbytes
 ip test-ip4 output
-  [ limit rate 1074790400/second burst 1049600 type bytes ]
+  [ limit rate 1074790400/second burst 1049600 type bytes flags 0x0 ]
 
 # limit rate 1025000 mbytes/second burst 1023 mbytes
 ip test-ip4 output
-  [ limit rate 1074790400000/second burst 1072693248 type bytes ]
+  [ limit rate 1074790400000/second burst 1072693248 type bytes flags 0x0 ]
+
+# limit rate over 400/minute
+ip test-ip4 output
+  [ limit rate 400/minute burst 0 type packets flags 0x1 ]
+
+# limit rate over 20/second
+ip test-ip4 output
+  [ limit rate 20/second burst 0 type packets flags 0x1 ]
+
+# limit rate over 400/hour
+ip test-ip4 output
+  [ limit rate 400/hour burst 0 type packets flags 0x1 ]
+
+# limit rate over 400/week
+ip test-ip4 output
+  [ limit rate 400/week burst 0 type packets flags 0x1 ]
+
+# limit rate over 40/day
+ip test-ip4 output
+  [ limit rate 40/day burst 0 type packets flags 0x1 ]
+
+# limit rate over 1023/second burst 10 packets
+ip test-ip4 output
+  [ limit rate 1023/second burst 10 type packets flags 0x1 ]
+
+# limit rate over 1 kbytes/second
+ip test-ip4 output
+  [ limit rate 1024/second burst 0 type bytes flags 0x1 ]
+
+# limit rate over 2 kbytes/second
+ip test-ip4 output
+  [ limit rate 2048/second burst 0 type bytes flags 0x1 ]
+
+# limit rate over 1025 kbytes/second
+ip test-ip4 output
+  [ limit rate 1049600/second burst 0 type bytes flags 0x1 ]
+
+# limit rate over 1023 mbytes/second
+ip test-ip4 output
+  [ limit rate 1072693248/second burst 0 type bytes flags 0x1 ]
+
+# limit rate over 10230 mbytes/second
+ip test-ip4 output
+  [ limit rate 10726932480/second burst 0 type bytes flags 0x1 ]
+
+# limit rate over 1023000 mbytes/second
+ip test-ip4 output
+  [ limit rate 1072693248000/second burst 0 type bytes flags 0x1 ]
+
+# limit rate over 1025 bytes/second burst 512 bytes
+ip test-ip4 output
+  [ limit rate 1025/second burst 512 type bytes flags 0x1 ]
+
+# limit rate over 1025 kbytes/second burst 1023 kbytes
+ip test-ip4 output
+  [ limit rate 1049600/second burst 1047552 type bytes flags 0x1 ]
+
+# limit rate over 1025 mbytes/second burst 1025 kbytes
+ip test-ip4 output
+  [ limit rate 1074790400/second burst 1049600 type bytes flags 0x1 ]
+
+# limit rate over 1025000 mbytes/second burst 1023 mbytes
+ip test-ip4 output
+  [ limit rate 1074790400000/second burst 1072693248 type bytes flags 0x1 ]