summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorFlorian Westphal <fw@strlen.de>2020-11-02 14:53:26 +0100
committerFlorian Westphal <fw@strlen.de>2020-11-09 12:19:24 +0100
commit41158e0388ac56380fc0ee301f0d43f95ec43fab (patch)
treeaa970b7dcf43bc7c1c150cc166701944602beb95 /src
parent2a9aea6f2dfb6ee61528809af98860e06b38762b (diff)
tcpopts: clean up parser -> tcpopt.c plumbing
tcpopt template mapping is asymmetric: one mapping is to match dumped netlink exthdr expression to the original tcp option template. This struct is indexed by the raw, on-write kind/type number. The other mapping maps parsed options to the tcp option template. Remove the latter. The parser is changed to translate the textual option name, e.g. "maxseg" to the on-wire number. This avoids the second mapping, it will also allow to more easily support raw option matching in a followup patch. Signed-off-by: Florian Westphal <fw@strlen.de>
Diffstat (limited to 'src')
-rw-r--r--src/parser_bison.y26
-rw-r--r--src/parser_json.c10
-rw-r--r--src/scanner.l3
-rw-r--r--src/tcpopt.c92
4 files changed, 55 insertions, 76 deletions
diff --git a/src/parser_bison.y b/src/parser_bison.y
index 8d6e28c9..fcbfb40d 100644
--- a/src/parser_bison.y
+++ b/src/parser_bison.y
@@ -399,7 +399,7 @@ int nft_lex(void *, void *, void *);
%token OPTION "option"
%token ECHO "echo"
%token EOL "eol"
-%token NOOP "noop"
+%token NOP "nop"
%token SACK "sack"
%token SACK0 "sack0"
%token SACK1 "sack1"
@@ -5212,18 +5212,18 @@ tcp_hdr_field : SPORT { $$ = TCPHDR_SPORT; }
| URGPTR { $$ = TCPHDR_URGPTR; }
;
-tcp_hdr_option_type : EOL { $$ = TCPOPTHDR_EOL; }
- | NOOP { $$ = TCPOPTHDR_NOOP; }
- | MSS { $$ = TCPOPTHDR_MAXSEG; }
- | WINDOW { $$ = TCPOPTHDR_WINDOW; }
- | SACK_PERM { $$ = TCPOPTHDR_SACK_PERMITTED; }
- | SACK { $$ = TCPOPTHDR_SACK0; }
- | SACK0 { $$ = TCPOPTHDR_SACK0; }
- | SACK1 { $$ = TCPOPTHDR_SACK1; }
- | SACK2 { $$ = TCPOPTHDR_SACK2; }
- | SACK3 { $$ = TCPOPTHDR_SACK3; }
- | ECHO { $$ = TCPOPTHDR_ECHO; }
- | TIMESTAMP { $$ = TCPOPTHDR_TIMESTAMP; }
+tcp_hdr_option_type : EOL { $$ = TCPOPT_KIND_EOL; }
+ | NOP { $$ = TCPOPT_KIND_NOP; }
+ | MSS { $$ = TCPOPT_KIND_MAXSEG; }
+ | WINDOW { $$ = TCPOPT_KIND_WINDOW; }
+ | SACK_PERM { $$ = TCPOPT_KIND_SACK_PERMITTED; }
+ | SACK { $$ = TCPOPT_KIND_SACK; }
+ | SACK0 { $$ = TCPOPT_KIND_SACK; }
+ | SACK1 { $$ = TCPOPT_KIND_SACK1; }
+ | SACK2 { $$ = TCPOPT_KIND_SACK2; }
+ | SACK3 { $$ = TCPOPT_KIND_SACK3; }
+ | ECHO { $$ = TCPOPT_KIND_ECHO; }
+ | TIMESTAMP { $$ = TCPOPT_KIND_TIMESTAMP; }
;
tcp_hdr_option_field : KIND { $$ = TCPOPTHDR_FIELD_KIND; }
diff --git a/src/parser_json.c b/src/parser_json.c
index 13623912..c68b64d9 100644
--- a/src/parser_json.c
+++ b/src/parser_json.c
@@ -458,9 +458,9 @@ static int json_parse_tcp_option_type(const char *name, int *val)
{
unsigned int i;
- for (i = 0; i < array_size(tcpopthdr_protocols); i++) {
- if (tcpopthdr_protocols[i] &&
- !strcmp(tcpopthdr_protocols[i]->name, name)) {
+ for (i = 0; i < array_size(tcpopt_protocols); i++) {
+ if (tcpopt_protocols[i] &&
+ !strcmp(tcpopt_protocols[i]->name, name)) {
if (val)
*val = i;
return 0;
@@ -469,7 +469,7 @@ static int json_parse_tcp_option_type(const char *name, int *val)
/* special case for sack0 - sack3 */
if (sscanf(name, "sack%u", &i) == 1 && i < 4) {
if (val)
- *val = TCPOPTHDR_SACK0 + i;
+ *val = TCPOPT_KIND_SACK + i;
return 0;
}
return 1;
@@ -478,7 +478,7 @@ static int json_parse_tcp_option_type(const char *name, int *val)
static int json_parse_tcp_option_field(int type, const char *name, int *val)
{
unsigned int i;
- const struct exthdr_desc *desc = tcpopthdr_protocols[type];
+ const struct exthdr_desc *desc = tcpopt_protocols[type];
for (i = 0; i < array_size(desc->templates); i++) {
if (desc->templates[i].token &&
diff --git a/src/scanner.l b/src/scanner.l
index 516c648f..8bde1fbe 100644
--- a/src/scanner.l
+++ b/src/scanner.l
@@ -423,7 +423,8 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr})
"eol" { return EOL; }
"maxseg" { return MSS; }
"mss" { return MSS; }
-"noop" { return NOOP; }
+"nop" { return NOP; }
+"noop" { return NOP; }
"sack" { return SACK; }
"sack0" { return SACK0; }
"sack1" { return SACK1; }
diff --git a/src/tcpopt.c b/src/tcpopt.c
index 6dbaa9e6..8d5bdec5 100644
--- a/src/tcpopt.c
+++ b/src/tcpopt.c
@@ -20,7 +20,7 @@ static const struct proto_hdr_template tcpopt_unknown_template =
__offset, __len)
static const struct exthdr_desc tcpopt_eol = {
.name = "eol",
- .type = TCPOPT_EOL,
+ .type = TCPOPT_KIND_EOL,
.templates = {
[TCPOPTHDR_FIELD_KIND] = PHT("kind", 0, 8),
},
@@ -28,7 +28,7 @@ static const struct exthdr_desc tcpopt_eol = {
static const struct exthdr_desc tcpopt_nop = {
.name = "noop",
- .type = TCPOPT_NOP,
+ .type = TCPOPT_KIND_NOP,
.templates = {
[TCPOPTHDR_FIELD_KIND] = PHT("kind", 0, 8),
},
@@ -36,7 +36,7 @@ static const struct exthdr_desc tcpopt_nop = {
static const struct exthdr_desc tcptopt_maxseg = {
.name = "maxseg",
- .type = TCPOPT_MAXSEG,
+ .type = TCPOPT_KIND_MAXSEG,
.templates = {
[TCPOPTHDR_FIELD_KIND] = PHT("kind", 0, 8),
[TCPOPTHDR_FIELD_LENGTH] = PHT("length", 8, 8),
@@ -46,7 +46,7 @@ static const struct exthdr_desc tcptopt_maxseg = {
static const struct exthdr_desc tcpopt_window = {
.name = "window",
- .type = TCPOPT_WINDOW,
+ .type = TCPOPT_KIND_WINDOW,
.templates = {
[TCPOPTHDR_FIELD_KIND] = PHT("kind", 0, 8),
[TCPOPTHDR_FIELD_LENGTH] = PHT("length", 8, 8),
@@ -56,7 +56,7 @@ static const struct exthdr_desc tcpopt_window = {
static const struct exthdr_desc tcpopt_sack_permitted = {
.name = "sack-perm",
- .type = TCPOPT_SACK_PERMITTED,
+ .type = TCPOPT_KIND_SACK_PERMITTED,
.templates = {
[TCPOPTHDR_FIELD_KIND] = PHT("kind", 0, 8),
[TCPOPTHDR_FIELD_LENGTH] = PHT("length", 8, 8),
@@ -65,7 +65,7 @@ static const struct exthdr_desc tcpopt_sack_permitted = {
static const struct exthdr_desc tcpopt_sack = {
.name = "sack",
- .type = TCPOPT_SACK,
+ .type = TCPOPT_KIND_SACK,
.templates = {
[TCPOPTHDR_FIELD_KIND] = PHT("kind", 0, 8),
[TCPOPTHDR_FIELD_LENGTH] = PHT("length", 8, 8),
@@ -76,7 +76,7 @@ static const struct exthdr_desc tcpopt_sack = {
static const struct exthdr_desc tcpopt_timestamp = {
.name = "timestamp",
- .type = TCPOPT_TIMESTAMP,
+ .type = TCPOPT_KIND_TIMESTAMP,
.templates = {
[TCPOPTHDR_FIELD_KIND] = PHT("kind", 0, 8),
[TCPOPTHDR_FIELD_LENGTH] = PHT("length", 8, 8),
@@ -86,19 +86,14 @@ static const struct exthdr_desc tcpopt_timestamp = {
};
#undef PHT
-#define TCPOPT_OBSOLETE ((struct exthdr_desc *)NULL)
-#define TCPOPT_ECHO 6
-#define TCPOPT_ECHO_REPLY 7
-static const struct exthdr_desc *tcpopt_protocols[] = {
- [TCPOPT_EOL] = &tcpopt_eol,
- [TCPOPT_NOP] = &tcpopt_nop,
- [TCPOPT_MAXSEG] = &tcptopt_maxseg,
- [TCPOPT_WINDOW] = &tcpopt_window,
- [TCPOPT_SACK_PERMITTED] = &tcpopt_sack_permitted,
- [TCPOPT_SACK] = &tcpopt_sack,
- [TCPOPT_ECHO] = TCPOPT_OBSOLETE,
- [TCPOPT_ECHO_REPLY] = TCPOPT_OBSOLETE,
- [TCPOPT_TIMESTAMP] = &tcpopt_timestamp,
+const struct exthdr_desc *tcpopt_protocols[] = {
+ [TCPOPT_KIND_EOL] = &tcpopt_eol,
+ [TCPOPT_KIND_NOP] = &tcpopt_nop,
+ [TCPOPT_KIND_MAXSEG] = &tcptopt_maxseg,
+ [TCPOPT_KIND_WINDOW] = &tcpopt_window,
+ [TCPOPT_KIND_SACK_PERMITTED] = &tcpopt_sack_permitted,
+ [TCPOPT_KIND_SACK] = &tcpopt_sack,
+ [TCPOPT_KIND_TIMESTAMP] = &tcpopt_timestamp,
};
static unsigned int calc_offset(const struct exthdr_desc *desc,
@@ -136,51 +131,34 @@ static unsigned int calc_offset_reverse(const struct exthdr_desc *desc,
}
}
-const struct exthdr_desc *tcpopthdr_protocols[__TCPOPTHDR_MAX] = {
- [TCPOPTHDR_EOL] = &tcpopt_eol,
- [TCPOPTHDR_NOOP] = &tcpopt_nop,
- [TCPOPTHDR_MAXSEG] = &tcptopt_maxseg,
- [TCPOPTHDR_WINDOW] = &tcpopt_window,
- [TCPOPTHDR_SACK_PERMITTED] = &tcpopt_sack_permitted,
- [TCPOPTHDR_SACK0] = &tcpopt_sack,
- [TCPOPTHDR_SACK1] = &tcpopt_sack,
- [TCPOPTHDR_SACK2] = &tcpopt_sack,
- [TCPOPTHDR_SACK3] = &tcpopt_sack,
- [TCPOPTHDR_ECHO] = TCPOPT_OBSOLETE,
- [TCPOPTHDR_ECHO_REPLY] = TCPOPT_OBSOLETE,
- [TCPOPTHDR_TIMESTAMP] = &tcpopt_timestamp,
-};
-
-static uint8_t tcpopt_optnum[] = {
- [TCPOPTHDR_SACK0] = 0,
- [TCPOPTHDR_SACK1] = 1,
- [TCPOPTHDR_SACK2] = 2,
- [TCPOPTHDR_SACK3] = 3,
-};
-
-static uint8_t tcpopt_find_optnum(uint8_t optnum)
-{
- if (optnum > TCPOPTHDR_SACK3)
- return 0;
-
- return tcpopt_optnum[optnum];
-}
-
-struct expr *tcpopt_expr_alloc(const struct location *loc, uint8_t type,
- uint8_t field)
+struct expr *tcpopt_expr_alloc(const struct location *loc,
+ unsigned int kind,
+ unsigned int field)
{
const struct proto_hdr_template *tmpl;
const struct exthdr_desc *desc;
+ uint8_t optnum = 0;
struct expr *expr;
- uint8_t optnum;
- desc = tcpopthdr_protocols[type];
+ switch (kind) {
+ case TCPOPT_KIND_SACK1:
+ kind = TCPOPT_KIND_SACK;
+ optnum = 1;
+ break;
+ case TCPOPT_KIND_SACK2:
+ kind = TCPOPT_KIND_SACK;
+ optnum = 2;
+ break;
+ case TCPOPT_KIND_SACK3:
+ kind = TCPOPT_KIND_SACK;
+ optnum = 3;
+ }
+
+ desc = tcpopt_protocols[kind];
tmpl = &desc->templates[field];
if (!tmpl)
return NULL;
- optnum = tcpopt_find_optnum(type);
-
expr = expr_alloc(loc, EXPR_EXTHDR, tmpl->dtype,
BYTEORDER_BIG_ENDIAN, tmpl->len);
expr->exthdr.desc = desc;
@@ -206,7 +184,7 @@ void tcpopt_init_raw(struct expr *expr, uint8_t type, unsigned int offset,
assert(type < array_size(tcpopt_protocols));
expr->exthdr.desc = tcpopt_protocols[type];
expr->exthdr.flags = flags;
- assert(expr->exthdr.desc != TCPOPT_OBSOLETE);
+ assert(expr->exthdr.desc != NULL);
for (i = 0; i < array_size(expr->exthdr.desc->templates); ++i) {
tmpl = &expr->exthdr.desc->templates[i];