summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPablo Neira Ayuso <pablo@netfilter.org>2016-08-16 23:30:18 +0200
committerPablo Neira Ayuso <pablo@netfilter.org>2016-08-18 03:14:58 +0200
commit6f2eb8548e0d18078989adec069b438b2f154767 (patch)
tree6e2e838e8a6c20f24a8ce2d8fea65e0fa3966f26
parent860979abdbe3081c310a5acd9250abdfcb741ce4 (diff)
src: meta priority support using tc classid
This patch adds the missing bits to scan and parse the meta priority handle as expressed by tc classid major:minor syntax. The :minor syntax is not support for two reason: major is always >= 1 and this clashes with port syntax in nat. Here below, several example on how to match the packet priority field: nft add rule filter forward meta priority abcd:0 nft add rule filter forward meta priority abcd:1234 and to set it, you have to: nft add rule filter forward meta priority set abcd:1234 The priority expression in flex looks ahead to restrict the pattern to avoid problems with mappings: {classid}/[ \t\n:\-},] So the following doesn't break: ... vmap { 25:accept } ^^^^^ The lookahead expression requires a slight change to extend the input string in one byte. This patch is conservative as you always have to explicity indicate major and minor numbers even if zero. We could consider supporting this shortcut in the future: abcd: However, with regards to this: :abcd We don't need to support it since major number is assumed to be >= 1. However, if we ever decide to support this, we'll have problems since this clashes with our port representation in redirect and mangle. So let's keep this simple and start with this approach. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
-rw-r--r--src/cli.c8
-rw-r--r--src/erec.c1
-rw-r--r--src/main.c3
-rw-r--r--src/meta.c39
-rw-r--r--src/scanner.l6
-rw-r--r--src/statement.c2
-rw-r--r--tests/py/any/meta.t22
-rw-r--r--tests/py/any/meta.t.payload73
8 files changed, 132 insertions, 22 deletions
diff --git a/src/cli.c b/src/cli.c
index adffd6b9..a74411a0 100644
--- a/src/cli.c
+++ b/src/cli.c
@@ -92,6 +92,8 @@ static void cli_complete(char *line)
const HIST_ENTRY *hist;
const char *c;
LIST_HEAD(msgs);
+ int len;
+ char *s;
if (line == NULL) {
printf("\n");
@@ -119,6 +121,12 @@ static void cli_complete(char *line)
if (hist == NULL || strcmp(hist->line, line))
add_history(line);
+ len = strlen(line);
+ s = xmalloc(len + 2);
+ snprintf(s, len + 2, "%s\n", line);
+ xfree(line);
+ line = s;
+
parser_init(state, &msgs);
scanner_push_buffer(scanner, &indesc_cli, line);
nft_run(scanner, state, &msgs);
diff --git a/src/erec.c b/src/erec.c
index 0a1e6c74..36032165 100644
--- a/src/erec.c
+++ b/src/erec.c
@@ -92,6 +92,7 @@ void erec_print(FILE *f, const struct error_record *erec)
case INDESC_BUFFER:
case INDESC_CLI:
line = indesc->data;
+ *strchrnul(line, '\n') = '\0';
break;
case INDESC_FILE:
memset(buf, 0, sizeof(buf));
diff --git a/src/main.c b/src/main.c
index ad73d800..39a47bbc 100644
--- a/src/main.c
+++ b/src/main.c
@@ -328,12 +328,13 @@ int main(int argc, char * const *argv)
for (len = 0, i = optind; i < argc; i++)
len += strlen(argv[i]) + strlen(" ");
- buf = xzalloc(len + 1);
+ buf = xzalloc(len + 2);
for (i = optind; i < argc; i++) {
strcat(buf, argv[i]);
if (i + 1 < argc)
strcat(buf, " ");
}
+ strcat(buf, "\n");
parser_init(&state, &msgs);
scanner = scanner_init(&state);
scanner_push_buffer(scanner, &indesc_cmdline, buf);
diff --git a/src/meta.c b/src/meta.c
index 1b178197..5a6fee5c 100644
--- a/src/meta.c
+++ b/src/meta.c
@@ -10,6 +10,7 @@
* Development of this code funded by Astaro AG (http://www.astaro.com/)
*/
+#include <errno.h>
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
@@ -89,34 +90,50 @@ static struct error_record *tchandle_type_parse(const struct expr *sym,
struct expr **res)
{
uint32_t handle;
+ char *str;
if (strcmp(sym->identifier, "root") == 0)
handle = TC_H_ROOT;
else if (strcmp(sym->identifier, "none") == 0)
handle = TC_H_UNSPEC;
- else if (sym->identifier[0] == ':') {
- if (sscanf(sym->identifier, ":%04x", &handle) != 1)
+ else if (strchr(sym->identifier, ':')) {
+ uint16_t tmp;
+ char *colon;
+
+ str = xstrdup(sym->identifier);
+
+ colon = strchr(str, ':');
+ if (!colon)
goto err;
- } else if (sym->identifier[strlen(sym->identifier)-1] == ':') {
- if (sscanf(sym->identifier, "%04x:", &handle) != 1)
+
+ *colon = '\0';
+
+ errno = 0;
+ tmp = strtoull(str, NULL, 16);
+ if (errno != 0)
goto err;
- handle <<= 16;
- } else {
- uint32_t min, max;
+ handle = (tmp << 16);
+ if (str[strlen(str) - 1] == ':')
+ goto out;
- if (sscanf(sym->identifier, "%04x:%04x", &max, &min) != 2)
+ errno = 0;
+ tmp = strtoull(colon + 1, NULL, 16);
+ if (errno != 0)
goto err;
- handle = max << 16 | min;
+ handle |= tmp;
+ } else {
+ handle = strtoull(sym->identifier, NULL, 0);
}
+out:
*res = constant_expr_alloc(&sym->location, sym->dtype,
BYTEORDER_HOST_ENDIAN,
sizeof(handle) * BITS_PER_BYTE, &handle);
return NULL;
err:
- return error(&sym->location, "Could not parse %s",
- sym->dtype->desc);
+ xfree(str);
+ return error(&sym->location, "Could not parse %s", sym->dtype->desc);
}
static const struct datatype tchandle_type = {
diff --git a/src/scanner.l b/src/scanner.l
index b1420f35..e9384fd6 100644
--- a/src/scanner.l
+++ b/src/scanner.l
@@ -170,6 +170,7 @@ ip4addr (([[:digit:]]{1,3}"."){3}([[:digit:]]{1,3}))
ip6addr ({v680}|{v67}|{v66}|{v65}|{v64}|{v63}|{v62}|{v61}|{v60})
ip6addr_rfc2732 (\[{ip6addr}\])
+classid ({hexdigit}{1,4}:{hexdigit}{1,4})
addrstring ({macaddr}|{ip4addr}|{ip6addr})
%option prefix="nft_"
@@ -506,6 +507,11 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr})
return NUM;
}
+{classid}/[ \t\n:\-},] {
+ yylval->string = xstrdup(yytext);
+ return STRING;
+ }
+
{quotedstring} {
yytext[yyleng - 1] = '\0';
yylval->string = xstrdup(yytext + 1);
diff --git a/src/statement.c b/src/statement.c
index fbe74a64..59b133c2 100644
--- a/src/statement.c
+++ b/src/statement.c
@@ -477,7 +477,7 @@ static void redir_stmt_print(const struct stmt *stmt)
printf("redirect");
if (stmt->redir.proto) {
- printf(" to ");
+ printf(" to :");
expr_print(stmt->redir.proto);
}
diff --git a/tests/py/any/meta.t b/tests/py/any/meta.t
index 9015a219..ceeac485 100644
--- a/tests/py/any/meta.t
+++ b/tests/py/any/meta.t
@@ -38,15 +38,19 @@ meta l4proto { 33, 55, 67, 88};ok;meta l4proto { 33, 55, 67, 88}
meta l4proto { 33-55};ok
- meta l4proto != { 33-55};ok
-- meta priority :aabb;ok
-- meta priority bcad:dadc;ok
-- meta priority aabb:;ok
-- meta priority != :aabb;ok
-- meta priority != bcad:dadc;ok
-- meta priority != aabb:;ok
-- meta priority bcad:dada-bcad:dadc;ok
-- meta priority != bcad:dada-bcad:dadc;ok
-- meta priority {bcad:dada, bcad:dadc, aaaa:bbbb};ok
+meta priority root;ok
+meta priority none;ok
+meta priority 0x87654321;ok;meta priority 8765:4321
+meta priority 2271560481;ok;meta priority 8765:4321
+meta priority 1:1234;ok
+meta priority bcad:dadc;ok
+meta priority aabb:0;ok
+meta priority != bcad:dadc;ok
+meta priority != aabb:0;ok
+meta priority bcad:dada-bcad:dadc;ok
+meta priority != bcad:dada-bcad:dadc;ok
+meta priority {bcad:dada, bcad:dadc, aaaa:bbbb};ok
+meta priority set cafe:beef;ok
- meta priority != {bcad:dada, bcad:dadc, aaaa:bbbb};ok
meta mark 0x4;ok;mark 0x00000004
diff --git a/tests/py/any/meta.t.payload b/tests/py/any/meta.t.payload
index 0affd925..19bb17c0 100644
--- a/tests/py/any/meta.t.payload
+++ b/tests/py/any/meta.t.payload
@@ -790,3 +790,76 @@ ip test-ip4 input
ip test-ip4 input
[ meta load prandom => reg 1 ]
[ cmp gt reg 1 0x40420f00 ]
+
+# meta priority root
+ip test-ip4 input
+ [ meta load priority => reg 1 ]
+ [ cmp eq reg 1 0xffffffff ]
+
+# meta priority none
+netdev test-netdev ingress
+ [ meta load priority => reg 1 ]
+ [ cmp eq reg 1 0x00000000 ]
+
+# meta priority 1:1234
+ip test-ip4 input
+ [ meta load priority => reg 1 ]
+ [ cmp eq reg 1 0x00011234 ]
+
+# meta priority bcad:dadc
+ip test-ip4 input
+ [ meta load priority => reg 1 ]
+ [ cmp eq reg 1 0xbcaddadc ]
+
+# meta priority aabb:0
+ip test-ip4 input
+ [ meta load priority => reg 1 ]
+ [ cmp eq reg 1 0xaabb0000 ]
+
+# meta priority != bcad:dadc
+ip test-ip4 input
+ [ meta load priority => reg 1 ]
+ [ cmp neq reg 1 0xbcaddadc ]
+
+# meta priority != aabb:0
+ip test-ip4 input
+ [ meta load priority => reg 1 ]
+ [ cmp neq reg 1 0xaabb0000 ]
+
+# meta priority bcad:dada-bcad:dadc
+ip test-ip4 input
+ [ meta load priority => reg 1 ]
+ [ byteorder reg 1 = hton(reg 1, 4, 4) ]
+ [ cmp gte reg 1 0xdadaadbc ]
+ [ cmp lte reg 1 0xdcdaadbc ]
+
+# meta priority != bcad:dada-bcad:dadc
+ip test-ip4 input
+ [ meta load priority => reg 1 ]
+ [ byteorder reg 1 = hton(reg 1, 4, 4) ]
+ [ cmp lt reg 1 0xdadaadbc ]
+ [ cmp gt reg 1 0xdcdaadbc ]
+
+# meta priority {bcad:dada, bcad:dadc, aaaa:bbbb}
+__set%d test-ip4 3
+__set%d test-ip4 0
+ element bcaddada : 0 [end] element bcaddadc : 0 [end] element aaaabbbb : 0 [end]
+ip test-ip4 input
+ [ meta load priority => reg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# meta priority set cafe:beef
+ip test-ip4 input
+ [ immediate reg 1 0xcafebeef ]
+ [ meta set priority with reg 1 ]
+
+# meta priority 0x87654321
+ip test-ip4 input
+ [ meta load priority => reg 1 ]
+ [ cmp eq reg 1 0x87654321 ]
+
+# meta priority 2271560481
+ip test-ip4 input
+ [ meta load priority => reg 1 ]
+ [ cmp eq reg 1 0x87654321 ]
+