diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/exthdr.c | 2 | ||||
-rw-r--r-- | src/parser_bison.y | 81 | ||||
-rw-r--r-- | src/scanner.l | 19 | ||||
-rw-r--r-- | src/tcpopt.c | 147 |
4 files changed, 126 insertions, 123 deletions
diff --git a/src/exthdr.c b/src/exthdr.c index cfc6bb60..ddda1b87 100644 --- a/src/exthdr.c +++ b/src/exthdr.c @@ -33,7 +33,7 @@ static void exthdr_expr_print(const struct expr *expr) char buf[3] = {0}; if (offset) - snprintf(buf, sizeof buf, " %d", offset); + snprintf(buf, sizeof buf, "%d", offset); printf("tcp option %s%s %s", expr->exthdr.desc->name, buf, expr->exthdr.tmpl->token); } diff --git a/src/parser_bison.y b/src/parser_bison.y index 36d46050..15931e96 100644 --- a/src/parser_bison.y +++ b/src/parser_bison.y @@ -309,6 +309,23 @@ static void location_update(struct location *loc, struct location *rhs, int n) %token WINDOW "window" %token URGPTR "urgptr" %token OPTION "option" +%token ECHO "echo" +%token EOL "eol" +%token MAXSEG "maxseg" +%token NOOP "noop" +%token SACK "sack" +%token SACK0 "sack0" +%token SACK1 "sack1" +%token SACK2 "sack2" +%token SACK3 "sack3" +%token SACK_PERMITTED "sack-permitted" +%token TIMESTAMP "timestamp" +%token KIND "kind" +%token COUNT "count" +%token LEFT "left" +%token RIGHT "right" +%token TSVAL "tsval" +%token TSECR "tsecr" %token DCCP "dccp" @@ -430,8 +447,8 @@ static void location_update(struct location *loc, struct location *rhs, int n) %token NOTRACK "notrack" -%type <string> identifier type_identifier string comment_spec tcp_option_name tcp_option_field -%destructor { xfree($$); } identifier type_identifier string comment_spec tcp_option_name tcp_option_field +%type <string> identifier type_identifier string comment_spec +%destructor { xfree($$); } identifier type_identifier string comment_spec %type <val> time_spec quota_used @@ -602,9 +619,6 @@ static void location_update(struct location *loc, struct location *rhs, int n) %destructor { expr_free($$); } mh_hdr_expr %type <val> mh_hdr_field -%type <expr> tcp_hdr_optexpr -%destructor { expr_free($$); } tcp_hdr_optexpr - %type <expr> meta_expr %destructor { expr_free($$); } meta_expr %type <val> meta_key meta_key_qualified meta_key_unqualified numgen_type @@ -634,6 +648,7 @@ static void location_update(struct location *loc, struct location *rhs, int n) %type <expr> tcp_hdr_expr %destructor { expr_free($$); } tcp_hdr_expr %type <val> tcp_hdr_field +%type <val> tcp_hdr_option_type tcp_hdr_option_field %% @@ -3211,6 +3226,10 @@ tcp_hdr_expr : TCP tcp_hdr_field { $$ = payload_expr_alloc(&@$, &proto_tcp, $2); } + | TCP OPTION tcp_hdr_option_type tcp_hdr_option_field + { + $$ = tcpopt_expr_alloc(&@$, $3, $4); + } ; tcp_hdr_field : SPORT { $$ = TCPHDR_SPORT; } @@ -3225,6 +3244,30 @@ tcp_hdr_field : SPORT { $$ = TCPHDR_SPORT; } | URGPTR { $$ = TCPHDR_URGPTR; } ; +tcp_hdr_option_type : EOL { $$ = TCPOPTHDR_EOL; } + | NOOP { $$ = TCPOPTHDR_NOOP; } + | MAXSEG { $$ = TCPOPTHDR_MAXSEG; } + | WINDOW { $$ = TCPOPTHDR_WINDOW; } + | SACK_PERMITTED { $$ = 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_field : KIND { $$ = TCPOPTHDR_FIELD_KIND; } + | LENGTH { $$ = TCPOPTHDR_FIELD_LENGTH; } + | SIZE { $$ = TCPOPTHDR_FIELD_SIZE; } + | COUNT { $$ = TCPOPTHDR_FIELD_COUNT; } + | LEFT { $$ = TCPOPTHDR_FIELD_LEFT; } + | RIGHT { $$ = TCPOPTHDR_FIELD_RIGHT; } + | TSVAL { $$ = TCPOPTHDR_FIELD_TSVAL; } + | TSECR { $$ = TCPOPTHDR_FIELD_TSECR; } + ; + dccp_hdr_expr : DCCP dccp_hdr_field { $$ = payload_expr_alloc(&@$, &proto_dccp, $2); @@ -3255,7 +3298,6 @@ exthdr_expr : hbh_hdr_expr | frag_hdr_expr | dst_hdr_expr | mh_hdr_expr - | tcp_hdr_optexpr ; hbh_hdr_expr : HBH hbh_hdr_field @@ -3338,31 +3380,4 @@ mh_hdr_field : NEXTHDR { $$ = MHHDR_NEXTHDR; } | CHECKSUM { $$ = MHHDR_CHECKSUM; } ; -tcp_option_name : STRING { $$ = $1; } - | WINDOW { $$ = xstrdup("window"); } - ; - -tcp_option_field : STRING { $$ = $1; } - | LENGTH { $$ = xstrdup("length"); } - | SIZE { $$ = xstrdup("size"); } - ; - -tcp_hdr_optexpr : TCP OPTION tcp_option_name tcp_option_field - { - $$ = tcpopt_expr_alloc(&@$, $3, 0, $4); - } - | TCP OPTION STRING NUM tcp_option_field - { - if (strcmp($3, "sack")) { - erec_queue(error(&@2, "tcp: number (%d) can only be used with sack option", $4), state->msgs); - YYERROR; - } - - if ($4 > 3) { - erec_queue(error(&@2, "tcp: option block (%d) too large (0-3)", $4), state->msgs); - YYERROR; - } - $$ = tcpopt_expr_alloc(&@$, $3, $4, $5); - } - ; %% diff --git a/src/scanner.l b/src/scanner.l index e0ddcac1..b70e1a80 100644 --- a/src/scanner.l +++ b/src/scanner.l @@ -375,6 +375,25 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr}) "protocol" { return PROTOCOL; } "checksum" { return CHECKSUM; } +"echo" { return ECHO; } +"eol" { return EOL; } +"maxseg" { return MAXSEG; } +"noop" { return NOOP; } +"sack" { return SACK; } +"sack0" { return SACK0; } +"sack1" { return SACK1; } +"sack2" { return SACK2; } +"sack3" { return SACK3; } +"sack-permitted" { return SACK_PERMITTED; } +"timestamp" { return TIMESTAMP; } + +"kind" { return KIND; } +"count" { return COUNT; } +"left" { return LEFT; } +"right" { return RIGHT; } +"tsval" { return TSVAL; } +"tsecr" { return TSECR; } + "icmp" { return ICMP; } "code" { return CODE; } "sequence" { return SEQUENCE; } diff --git a/src/tcpopt.c b/src/tcpopt.c index e6f92bc6..f8612141 100644 --- a/src/tcpopt.c +++ b/src/tcpopt.c @@ -12,48 +12,6 @@ #include <expression.h> #include <tcpopt.h> -/* We do not need to export these enums, because the tcpopts are parsed at - * runtime and not by bison. - */ -enum tcpopt_eol_hdr_fields { - TCPOPT_EOLHDR_KIND, -}; - -enum tcpopt_nop_hdr_fields { - TCPOPT_NOPHDR_KIND, -}; - -enum tcpopt_maxseg_hdr_fields { - TCPOPT_MAXSEGHDR_KIND, - TCPOPT_MAXSEGHDR_LENGTH, - TCPOPT_MAXSEGHDR_SIZE, -}; - -enum tcpopt_window_hdr_fields { - TCPOPT_WINDOWHDR_KIND, - TCPOPT_WINDOWHDR_LENGTH, - TCPOPT_WINDOWHDR_COUNT, -}; - -enum tcpopt_sack_permitted_hdr_fields { - TCPOPT_SACKPERMHDR_KIND, - TCPOPT_SACKPERMHDR_LENGTH, -}; - -enum tcpopt_sack_hdr_fields { - TCPOPT_SACKHDR_KIND, - TCPOPT_SACKHDR_LENGTH, - TCPOPT_SACKHDR_LEFT, - TCPOPT_SACKHDR_RIGHT, -}; - -enum tcpopt_timestamp_hdr_fields { - TCPOPT_TIMESTAMPSHDR_KIND, - TCPOPT_TIMESTAMPSHDR_LENGTH, - TCPOPT_TIMESTAMPSHDR_TSVAL, - TCPOPT_TIMESTAMPSHDR_TSECR, -}; - static const struct proto_hdr_template tcpopt_unknown_template = PROTO_HDR_TEMPLATE("unknown", &invalid_type, BYTEORDER_INVALID, 0, 0); @@ -64,7 +22,7 @@ const struct exthdr_desc tcpopt_eol = { .name = "eol", .type = TCPOPT_EOL, .templates = { - [TCPOPT_EOLHDR_KIND] = PHT("kind", 0, 8), + [TCPOPTHDR_FIELD_KIND] = PHT("kind", 0, 8), }, }; @@ -72,7 +30,7 @@ const struct exthdr_desc tcpopt_nop = { .name = "noop", .type = TCPOPT_NOP, .templates = { - [TCPOPT_NOPHDR_KIND] = PHT("kind", 0, 8), + [TCPOPTHDR_FIELD_KIND] = PHT("kind", 0, 8), }, }; @@ -80,9 +38,9 @@ const struct exthdr_desc tcptopt_maxseg = { .name = "maxseg", .type = TCPOPT_MAXSEG, .templates = { - [TCPOPT_MAXSEGHDR_KIND] = PHT("kind", 0, 8), - [TCPOPT_MAXSEGHDR_LENGTH] = PHT("length", 8, 8), - [TCPOPT_MAXSEGHDR_SIZE] = PHT("size", 16, 16), + [TCPOPTHDR_FIELD_KIND] = PHT("kind", 0, 8), + [TCPOPTHDR_FIELD_LENGTH] = PHT("length", 8, 8), + [TCPOPTHDR_FIELD_SIZE] = PHT("size", 16, 16), }, }; @@ -90,18 +48,18 @@ const struct exthdr_desc tcpopt_window = { .name = "window", .type = TCPOPT_WINDOW, .templates = { - [TCPOPT_WINDOWHDR_KIND] = PHT("kind", 0, 8), - [TCPOPT_WINDOWHDR_LENGTH] = PHT("length", 8, 8), - [TCPOPT_WINDOWHDR_COUNT] = PHT("count", 16, 8), + [TCPOPTHDR_FIELD_KIND] = PHT("kind", 0, 8), + [TCPOPTHDR_FIELD_LENGTH] = PHT("length", 8, 8), + [TCPOPTHDR_FIELD_COUNT] = PHT("count", 16, 8), }, }; const struct exthdr_desc tcpopt_sack_permitted = { - .name = "sack_permitted", + .name = "sack-permitted", .type = TCPOPT_SACK_PERMITTED, .templates = { - [TCPOPT_SACKPERMHDR_KIND] = PHT("kind", 0, 8), - [TCPOPT_SACKPERMHDR_LENGTH] = PHT("length", 8, 8), + [TCPOPTHDR_FIELD_KIND] = PHT("kind", 0, 8), + [TCPOPTHDR_FIELD_LENGTH] = PHT("length", 8, 8), }, }; @@ -109,10 +67,10 @@ const struct exthdr_desc tcpopt_sack = { .name = "sack", .type = TCPOPT_SACK, .templates = { - [TCPOPT_SACKHDR_KIND] = PHT("kind", 0, 8), - [TCPOPT_SACKHDR_LENGTH] = PHT("length", 8, 8), - [TCPOPT_SACKHDR_LEFT] = PHT("left", 16, 32), - [TCPOPT_SACKHDR_RIGHT] = PHT("right", 48, 32), + [TCPOPTHDR_FIELD_KIND] = PHT("kind", 0, 8), + [TCPOPTHDR_FIELD_LENGTH] = PHT("length", 8, 8), + [TCPOPTHDR_FIELD_LEFT] = PHT("left", 16, 32), + [TCPOPTHDR_FIELD_RIGHT] = PHT("right", 48, 32), }, }; @@ -120,10 +78,10 @@ const struct exthdr_desc tcpopt_timestamp = { .name = "timestamp", .type = TCPOPT_TIMESTAMP, .templates = { - [TCPOPT_TIMESTAMPSHDR_KIND] = PHT("kind", 0, 8), - [TCPOPT_TIMESTAMPSHDR_LENGTH] = PHT("length", 8, 8), - [TCPOPT_TIMESTAMPSHDR_TSVAL] = PHT("tsval", 16, 32), - [TCPOPT_TIMESTAMPSHDR_TSECR] = PHT("tsecr", 48, 32), + [TCPOPTHDR_FIELD_KIND] = PHT("kind", 0, 8), + [TCPOPTHDR_FIELD_LENGTH] = PHT("length", 8, 8), + [TCPOPTHDR_FIELD_TSVAL] = PHT("tsval", 16, 32), + [TCPOPTHDR_FIELD_TSECR] = PHT("tsecr", 48, 32), }, }; #undef PHT @@ -178,46 +136,57 @@ static unsigned int calc_offset_reverse(const struct exthdr_desc *desc, } } +static const struct exthdr_desc *tcpopthdr_protocols[] = { + [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, +}; -struct expr *tcpopt_expr_alloc(const struct location *loc, - const char *option_str, - const unsigned int option_num, - const char *option_field) +static uint8_t tcpopt_find_optnum(uint8_t optnum) { - const struct proto_hdr_template *tmp, *tmpl = &tcpopt_unknown_template; - const struct exthdr_desc *desc = NULL; - struct expr *expr; - unsigned int i, j; + if (optnum > TCPOPTHDR_SACK3) + return 0; - for (i = 0; i < array_size(tcpopt_protocols); ++i) { - if (tcpopt_protocols[i] == TCPOPT_OBSOLETE) - continue; + return tcpopt_optnum[optnum]; +} - if (!tcpopt_protocols[i]->name || - strcmp(option_str, tcpopt_protocols[i]->name)) - continue; +struct expr *tcpopt_expr_alloc(const struct location *loc, uint8_t type, + uint8_t field) +{ + const struct proto_hdr_template *tmpl; + const struct exthdr_desc *desc; + struct expr *expr; + uint8_t optnum; - for (j = 0; j < array_size(tcpopt_protocols[i]->templates); ++j) { - tmp = &tcpopt_protocols[i]->templates[j]; - if (!tmp->token || strcmp(option_field, tmp->token)) - continue; + desc = tcpopthdr_protocols[type]; + tmpl = &desc->templates[field]; + if (!tmpl) + return NULL; - desc = tcpopt_protocols[i]; - tmpl = tmp; - goto found; - } - } + optnum = tcpopt_find_optnum(type); -found: - /* tmpl still points to tcpopt_unknown_template if nothing was found and - * desc is null - */ expr = expr_alloc(loc, &exthdr_expr_ops, tmpl->dtype, BYTEORDER_BIG_ENDIAN, tmpl->len); expr->exthdr.desc = desc; expr->exthdr.tmpl = tmpl; expr->exthdr.op = NFT_EXTHDR_OP_TCPOPT; - expr->exthdr.offset = calc_offset(desc, tmpl, option_num); + expr->exthdr.offset = calc_offset(desc, tmpl, optnum); return expr; } |