diff options
-rw-r--r-- | doc/payload-expression.txt | 4 | ||||
-rw-r--r-- | include/tcpopt.h | 35 | ||||
-rw-r--r-- | src/parser_bison.y | 26 | ||||
-rw-r--r-- | src/parser_json.c | 10 | ||||
-rw-r--r-- | src/scanner.l | 3 | ||||
-rw-r--r-- | src/tcpopt.c | 92 |
6 files changed, 75 insertions, 95 deletions
diff --git a/doc/payload-expression.txt b/doc/payload-expression.txt index 9df20a18..2fa394ea 100644 --- a/doc/payload-expression.txt +++ b/doc/payload-expression.txt @@ -525,13 +525,13 @@ nftables currently supports matching (finding) a given ipv6 extension header, TC *dst* {*nexthdr* | *hdrlength*} *mh* {*nexthdr* | *hdrlength* | *checksum* | *type*} *srh* {*flags* | *tag* | *sid* | *seg-left*} -*tcp option* {*eol* | *noop* | *maxseg* | *window* | *sack-perm* | *sack* | *sack0* | *sack1* | *sack2* | *sack3* | *timestamp*} 'tcp_option_field' +*tcp option* {*eol* | *nop* | *maxseg* | *window* | *sack-perm* | *sack* | *sack0* | *sack1* | *sack2* | *sack3* | *timestamp*} 'tcp_option_field' *ip option* { lsrr | ra | rr | ssrr } 'ip_option_field' The following syntaxes are valid only in a relational expression with boolean type on right-hand side for checking header existence only: [verse] *exthdr* {*hbh* | *frag* | *rt* | *dst* | *mh*} -*tcp option* {*eol* | *noop* | *maxseg* | *window* | *sack-perm* | *sack* | *sack0* | *sack1* | *sack2* | *sack3* | *timestamp*} +*tcp option* {*eol* | *nop* | *maxseg* | *window* | *sack-perm* | *sack* | *sack0* | *sack1* | *sack2* | *sack3* | *timestamp*} *ip option* { lsrr | ra | rr | ssrr } .IPv6 extension headers diff --git a/include/tcpopt.h b/include/tcpopt.h index ffdbcb02..7f3fbb8b 100644 --- a/include/tcpopt.h +++ b/include/tcpopt.h @@ -6,7 +6,7 @@ #include <statement.h> extern struct expr *tcpopt_expr_alloc(const struct location *loc, - uint8_t type, uint8_t field); + unsigned int kind, unsigned int field); extern void tcpopt_init_raw(struct expr *expr, uint8_t type, unsigned int offset, unsigned int len, @@ -15,21 +15,22 @@ extern void tcpopt_init_raw(struct expr *expr, uint8_t type, extern bool tcpopt_find_template(struct expr *expr, const struct expr *mask, unsigned int *shift); -enum tcpopt_hdr_types { - TCPOPTHDR_INVALID, - TCPOPTHDR_EOL, - TCPOPTHDR_NOOP, - TCPOPTHDR_MAXSEG, - TCPOPTHDR_WINDOW, - TCPOPTHDR_SACK_PERMITTED, - TCPOPTHDR_SACK0, - TCPOPTHDR_SACK1, - TCPOPTHDR_SACK2, - TCPOPTHDR_SACK3, - TCPOPTHDR_TIMESTAMP, - TCPOPTHDR_ECHO, - TCPOPTHDR_ECHO_REPLY, - __TCPOPTHDR_MAX +/* TCP option numbers used on wire */ +enum tcpopt_kind { + TCPOPT_KIND_EOL = 0, + TCPOPT_KIND_NOP = 1, + TCPOPT_KIND_MAXSEG = 2, + TCPOPT_KIND_WINDOW = 3, + TCPOPT_KIND_SACK_PERMITTED = 4, + TCPOPT_KIND_SACK = 5, + TCPOPT_KIND_TIMESTAMP = 8, + TCPOPT_KIND_ECHO = 8, + __TCPOPT_KIND_MAX, + + /* extra oob info, internal to nft */ + TCPOPT_KIND_SACK1 = 256, + TCPOPT_KIND_SACK2 = 257, + TCPOPT_KIND_SACK3 = 258, }; enum tcpopt_hdr_fields { @@ -44,6 +45,6 @@ enum tcpopt_hdr_fields { TCPOPTHDR_FIELD_TSECR, }; -extern const struct exthdr_desc *tcpopthdr_protocols[__TCPOPTHDR_MAX]; +extern const struct exthdr_desc *tcpopt_protocols[__TCPOPT_KIND_MAX]; #endif /* NFTABLES_TCPOPT_H */ 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]; |