summaryrefslogtreecommitdiffstats
path: root/src/parser_bison.y
diff options
context:
space:
mode:
Diffstat (limited to 'src/parser_bison.y')
-rw-r--r--src/parser_bison.y958
1 files changed, 737 insertions, 221 deletions
diff --git a/src/parser_bison.y b/src/parser_bison.y
index ca5c488c..61bed761 100644
--- a/src/parser_bison.y
+++ b/src/parser_bison.y
@@ -9,12 +9,14 @@
*/
%{
+#include <nft.h>
#include <ctype.h>
#include <stddef.h>
#include <stdio.h>
#include <inttypes.h>
#include <syslog.h>
+#include <net/if.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <netinet/if_ether.h>
@@ -65,16 +67,26 @@ static struct scope *current_scope(const struct parser_state *state)
return state->scopes[state->scope];
}
-static void open_scope(struct parser_state *state, struct scope *scope)
+static int open_scope(struct parser_state *state, struct scope *scope)
{
- assert(state->scope < array_size(state->scopes) - 1);
+ if (state->scope >= array_size(state->scopes) - 1) {
+ state->scope_err = true;
+ return -1;
+ }
+
scope_init(scope, current_scope(state));
state->scopes[++state->scope] = scope;
+
+ return 0;
}
static void close_scope(struct parser_state *state)
{
- assert(state->scope > 0);
+ if (state->scope_err || state->scope == 0) {
+ state->scope_err = false;
+ return;
+ }
+
state->scope--;
}
@@ -134,6 +146,51 @@ static bool already_set(const void *attr, const struct location *loc,
return true;
}
+static struct expr *ifname_expr_alloc(const struct location *location,
+ struct list_head *queue,
+ const char *name)
+{
+ size_t length = strlen(name);
+ struct expr *expr;
+
+ if (length == 0) {
+ free_const(name);
+ erec_queue(error(location, "empty interface name"), queue);
+ return NULL;
+ }
+
+ if (length >= IFNAMSIZ) {
+ free_const(name);
+ erec_queue(error(location, "interface name too long"), queue);
+ return NULL;
+ }
+
+ expr = constant_expr_alloc(location, &ifname_type, BYTEORDER_HOST_ENDIAN,
+ length * BITS_PER_BYTE, name);
+
+ free_const(name);
+
+ return expr;
+}
+
+static void timeout_state_free(struct timeout_state *s)
+{
+ free_const(s->timeout_str);
+ free(s);
+}
+
+static void timeout_states_free(struct list_head *list)
+{
+ struct timeout_state *ts, *next;
+
+ list_for_each_entry_safe(ts, next, list, head) {
+ list_del(&ts->head);
+ timeout_state_free(ts);
+ }
+
+ free(list);
+}
+
#define YYLLOC_DEFAULT(Current, Rhs, N) location_update(&Current, Rhs, N)
#define symbol_value(loc, str) \
@@ -191,6 +248,7 @@ int nft_lex(void *, void *, void *);
uint16_t kind; /* must allow > 255 for SACK1, 2.. hack */
uint8_t field;
} tcp_kind_field;
+ struct timeout_state *timeout_state;
}
%token TOKEN_EOF 0 "end of file"
@@ -280,6 +338,8 @@ int nft_lex(void *, void *, void *);
%token DESCRIBE "describe"
%token IMPORT "import"
%token EXPORT "export"
+%token DESTROY "destroy"
+
%token MONITOR "monitor"
%token ALL "all"
@@ -317,7 +377,7 @@ int nft_lex(void *, void *, void *);
%token <string> STRING "string"
%token <string> QUOTED_STRING "quoted string"
%token <string> ASTERISK_STRING "string with a trailing asterisk"
-%destructor { xfree($$); } STRING QUOTED_STRING ASTERISK_STRING
+%destructor { free_const($$); } STRING QUOTED_STRING ASTERISK_STRING
%token LL_HDR "ll"
%token NETWORK_HDR "nh"
@@ -382,6 +442,7 @@ int nft_lex(void *, void *, void *);
%token ICMP6 "icmpv6"
%token PPTR "param-problem"
%token MAXDELAY "max-delay"
+%token TADDR "taddr"
%token AH "ah"
%token RESERVED "reserved"
@@ -428,6 +489,14 @@ int nft_lex(void *, void *, void *);
%token DCCP "dccp"
+%token VXLAN "vxlan"
+%token VNI "vni"
+
+%token GRE "gre"
+%token GRETAP "gretap"
+
+%token GENEVE "geneve"
+
%token SCTP "sctp"
%token CHUNK "chunk"
%token DATA "data"
@@ -533,6 +602,9 @@ int nft_lex(void *, void *, void *);
%token BYTES "bytes"
%token AVGPKT "avgpkt"
+%token LAST "last"
+%token NEVER "never"
+
%token COUNTERS "counters"
%token QUOTAS "quotas"
%token LIMITS "limits"
@@ -615,13 +687,15 @@ int nft_lex(void *, void *, void *);
%token IN "in"
%token OUT "out"
+%token XT "xt"
+
%type <limit_rate> limit_rate_pkts
%type <limit_rate> limit_rate_bytes
%type <string> identifier type_identifier string comment_spec
-%destructor { xfree($$); } identifier type_identifier string comment_spec
+%destructor { free_const($$); } identifier type_identifier string comment_spec
-%type <val> time_spec quota_used
+%type <val> time_spec time_spec_or_num_s quota_used
%type <expr> data_type_expr data_type_atom_expr
%destructor { expr_free($$); } data_type_expr data_type_atom_expr
@@ -629,8 +703,8 @@ int nft_lex(void *, void *, void *);
%type <cmd> line
%destructor { cmd_free($$); } line
-%type <cmd> base_cmd add_cmd replace_cmd create_cmd insert_cmd delete_cmd get_cmd list_cmd reset_cmd flush_cmd rename_cmd export_cmd monitor_cmd describe_cmd import_cmd
-%destructor { cmd_free($$); } base_cmd add_cmd replace_cmd create_cmd insert_cmd delete_cmd get_cmd list_cmd reset_cmd flush_cmd rename_cmd export_cmd monitor_cmd describe_cmd import_cmd
+%type <cmd> base_cmd add_cmd replace_cmd create_cmd insert_cmd delete_cmd get_cmd list_cmd reset_cmd flush_cmd rename_cmd export_cmd monitor_cmd describe_cmd import_cmd destroy_cmd
+%destructor { cmd_free($$); } base_cmd add_cmd replace_cmd create_cmd insert_cmd delete_cmd get_cmd list_cmd reset_cmd flush_cmd rename_cmd export_cmd monitor_cmd describe_cmd import_cmd destroy_cmd
%type <handle> table_spec tableid_spec table_or_id_spec
%destructor { handle_free(&$$); } table_spec tableid_spec table_or_id_spec
@@ -653,11 +727,13 @@ int nft_lex(void *, void *, void *);
%type <val> family_spec family_spec_explicit
%type <val32> int_num chain_policy
%type <prio_spec> extended_prio_spec prio_spec
+%destructor { expr_free($$.expr); } extended_prio_spec prio_spec
+
%type <string> extended_prio_name quota_unit basehook_device_name
-%destructor { xfree($$); } extended_prio_name quota_unit basehook_device_name
+%destructor { free_const($$); } extended_prio_name quota_unit basehook_device_name
%type <expr> dev_spec
-%destructor { xfree($$); } dev_spec
+%destructor { free($$); } dev_spec
%type <table> table_block_alloc table_block
%destructor { close_scope(state); table_free($$); } table_block_alloc
@@ -675,7 +751,7 @@ int nft_lex(void *, void *, void *);
%type <set> map_block_alloc map_block
%destructor { set_free($$); } map_block_alloc
-%type <val> map_block_obj_type
+%type <val> map_block_obj_type map_block_obj_typeof map_block_data_interval
%type <flowtable> flowtable_block_alloc flowtable_block
%destructor { flowtable_free($$); } flowtable_block_alloc
@@ -684,11 +760,14 @@ int nft_lex(void *, void *, void *);
%destructor { obj_free($$); } obj_block_alloc
%type <list> stmt_list stateful_stmt_list set_elem_stmt_list
-%destructor { stmt_list_free($$); xfree($$); } stmt_list stateful_stmt_list set_elem_stmt_list
+%destructor { stmt_list_free($$); free($$); } stmt_list stateful_stmt_list set_elem_stmt_list
%type <stmt> stmt match_stmt verdict_stmt set_elem_stmt
%destructor { stmt_free($$); } stmt match_stmt verdict_stmt set_elem_stmt
-%type <stmt> counter_stmt counter_stmt_alloc stateful_stmt
-%destructor { stmt_free($$); } counter_stmt counter_stmt_alloc stateful_stmt
+%type <stmt> counter_stmt counter_stmt_alloc stateful_stmt last_stmt
+%destructor { stmt_free($$); } counter_stmt counter_stmt_alloc stateful_stmt last_stmt
+%type <stmt> objref_stmt objref_stmt_counter objref_stmt_limit objref_stmt_quota objref_stmt_ct objref_stmt_synproxy
+%destructor { stmt_free($$); } objref_stmt objref_stmt_counter objref_stmt_limit objref_stmt_quota objref_stmt_ct objref_stmt_synproxy
+
%type <stmt> payload_stmt
%destructor { stmt_free($$); } payload_stmt
%type <stmt> ct_stmt
@@ -733,8 +812,8 @@ int nft_lex(void *, void *, void *);
%type <expr> symbol_expr verdict_expr integer_expr variable_expr chain_expr policy_expr
%destructor { expr_free($$); } symbol_expr verdict_expr integer_expr variable_expr chain_expr policy_expr
-%type <expr> primary_expr shift_expr and_expr typeof_expr typeof_data_expr
-%destructor { expr_free($$); } primary_expr shift_expr and_expr typeof_expr typeof_data_expr
+%type <expr> primary_expr shift_expr and_expr typeof_expr typeof_data_expr typeof_key_expr typeof_verdict_expr
+%destructor { expr_free($$); } primary_expr shift_expr and_expr typeof_expr typeof_data_expr typeof_key_expr typeof_verdict_expr
%type <expr> exclusive_or_expr inclusive_or_expr
%destructor { expr_free($$); } exclusive_or_expr inclusive_or_expr
%type <expr> basic_expr
@@ -804,6 +883,8 @@ int nft_lex(void *, void *, void *);
%type <expr> payload_expr payload_raw_expr
%destructor { expr_free($$); } payload_expr payload_raw_expr
%type <val> payload_base_spec
+%type <val> payload_raw_len
+
%type <expr> eth_hdr_expr vlan_hdr_expr
%destructor { expr_free($$); } eth_hdr_expr vlan_hdr_expr
%type <val> eth_hdr_field vlan_hdr_field
@@ -873,7 +954,7 @@ int nft_lex(void *, void *, void *);
%type <val> markup_format
%type <string> monitor_event
-%destructor { xfree($$); } monitor_event
+%destructor { free_const($$); } monitor_event
%type <val> monitor_object monitor_format
%type <val> synproxy_ts synproxy_sack
@@ -886,9 +967,19 @@ int nft_lex(void *, void *, void *);
%type <val> tcpopt_field_maxseg tcpopt_field_mptcp tcpopt_field_sack tcpopt_field_tsopt tcpopt_field_window
%type <tcp_kind_field> tcp_hdr_option_kind_and_field
+%type <expr> inner_eth_expr inner_inet_expr inner_expr
+%destructor { expr_free($$); } inner_eth_expr inner_inet_expr inner_expr
+
+%type <expr> vxlan_hdr_expr geneve_hdr_expr gre_hdr_expr gretap_hdr_expr
+%destructor { expr_free($$); } vxlan_hdr_expr geneve_hdr_expr gre_hdr_expr gretap_hdr_expr
+%type <val> vxlan_hdr_field geneve_hdr_field gre_hdr_field
+
%type <stmt> optstrip_stmt
%destructor { stmt_free($$); } optstrip_stmt
+%type <stmt> xt_stmt
+%destructor { stmt_free($$); } xt_stmt
+
%type <expr> boolean_expr
%destructor { expr_free($$); } boolean_expr
%type <val8> boolean_keys
@@ -897,10 +988,13 @@ int nft_lex(void *, void *, void *);
%destructor { expr_free($$); } exthdr_exists_expr
%type <val> exthdr_key
-%type <val> ct_l4protoname ct_obj_type ct_cmd_type
+%type <val> ct_l4protoname ct_obj_type ct_cmd_type ct_obj_type_map
+
+%type <timeout_state> timeout_state
+%destructor { timeout_state_free($$); } timeout_state
-%type <list> timeout_states timeout_state
-%destructor { xfree($$); } timeout_states timeout_state
+%type <list> timeout_states
+%destructor { timeout_states_free($$); } timeout_states
%type <val> xfrm_state_key xfrm_state_proto_key xfrm_dir xfrm_spnum
%type <expr> xfrm_expr
@@ -935,16 +1029,18 @@ close_scope_at : { scanner_pop_start_cond(nft->scanner, PARSER_SC_AT); };
close_scope_comp : { scanner_pop_start_cond(nft->scanner, PARSER_SC_EXPR_COMP); };
close_scope_ct : { scanner_pop_start_cond(nft->scanner, PARSER_SC_CT); };
close_scope_counter : { scanner_pop_start_cond(nft->scanner, PARSER_SC_COUNTER); };
+close_scope_last : { scanner_pop_start_cond(nft->scanner, PARSER_SC_LAST); };
close_scope_dccp : { scanner_pop_start_cond(nft->scanner, PARSER_SC_EXPR_DCCP); };
+close_scope_destroy : { scanner_pop_start_cond(nft->scanner, PARSER_SC_CMD_DESTROY); };
close_scope_dst : { scanner_pop_start_cond(nft->scanner, PARSER_SC_EXPR_DST); };
close_scope_dup : { scanner_pop_start_cond(nft->scanner, PARSER_SC_STMT_DUP); };
close_scope_esp : { scanner_pop_start_cond(nft->scanner, PARSER_SC_EXPR_ESP); };
close_scope_eth : { scanner_pop_start_cond(nft->scanner, PARSER_SC_ETH); };
close_scope_export : { scanner_pop_start_cond(nft->scanner, PARSER_SC_CMD_EXPORT); };
close_scope_fib : { scanner_pop_start_cond(nft->scanner, PARSER_SC_EXPR_FIB); };
-close_scope_flags : { scanner_pop_start_cond(nft->scanner, PARSER_SC_FLAGS); };
close_scope_frag : { scanner_pop_start_cond(nft->scanner, PARSER_SC_EXPR_FRAG); };
close_scope_fwd : { scanner_pop_start_cond(nft->scanner, PARSER_SC_STMT_FWD); };
+close_scope_gre : { scanner_pop_start_cond(nft->scanner, PARSER_SC_GRE); };
close_scope_hash : { scanner_pop_start_cond(nft->scanner, PARSER_SC_EXPR_HASH); };
close_scope_hbh : { scanner_pop_start_cond(nft->scanner, PARSER_SC_EXPR_HBH); };
close_scope_ip : { scanner_pop_start_cond(nft->scanner, PARSER_SC_IP); };
@@ -981,14 +1077,15 @@ close_scope_udplite : { scanner_pop_start_cond(nft->scanner, PARSER_SC_EXPR_UDPL
close_scope_log : { scanner_pop_start_cond(nft->scanner, PARSER_SC_STMT_LOG); }
close_scope_synproxy : { scanner_pop_start_cond(nft->scanner, PARSER_SC_STMT_SYNPROXY); }
+close_scope_xt : { scanner_pop_start_cond(nft->scanner, PARSER_SC_XT); }
common_block : INCLUDE QUOTED_STRING stmt_separator
{
if (scanner_include_file(nft, scanner, $2, &@$) < 0) {
- xfree($2);
+ free_const($2);
YYERROR;
}
- xfree($2);
+ free_const($2);
}
| DEFINE identifier '=' initializer_expr stmt_separator
{
@@ -998,19 +1095,19 @@ common_block : INCLUDE QUOTED_STRING stmt_separator
erec_queue(error(&@2, "redefinition of symbol '%s'", $2),
state->msgs);
expr_free($4);
- xfree($2);
+ free_const($2);
YYERROR;
}
symbol_bind(scope, $2, $4);
- xfree($2);
+ free_const($2);
}
| REDEFINE identifier '=' initializer_expr stmt_separator
{
struct scope *scope = current_scope(state);
symbol_bind(scope, $2, $4);
- xfree($2);
+ free_const($2);
}
| UNDEFINE identifier stmt_separator
{
@@ -1019,10 +1116,10 @@ common_block : INCLUDE QUOTED_STRING stmt_separator
if (symbol_unbind(scope, $2) < 0) {
erec_queue(error(&@2, "undefined symbol '%s'", $2),
state->msgs);
- xfree($2);
+ free_const($2);
YYERROR;
}
- xfree($2);
+ free_const($2);
}
| error stmt_separator
{
@@ -1070,6 +1167,7 @@ base_cmd : /* empty */ add_cmd { $$ = $1; }
| EXPORT export_cmd close_scope_export { $$ = $2; }
| MONITOR monitor_cmd close_scope_monitor { $$ = $2; }
| DESCRIBE describe_cmd { $$ = $2; }
+ | DESTROY destroy_cmd close_scope_destroy { $$ = $2; }
;
add_cmd : TABLE table_spec
@@ -1318,6 +1416,14 @@ delete_cmd : TABLE table_or_id_spec
{
$$ = cmd_alloc(CMD_DELETE, CMD_OBJ_CHAIN, &$2, &@$, NULL);
}
+ | CHAIN chain_spec chain_block_alloc
+ '{' chain_block '}'
+ {
+ $5->location = @5;
+ handle_merge(&$3->handle, &$2);
+ close_scope(state);
+ $$ = cmd_alloc(CMD_DELETE, CMD_OBJ_CHAIN, &$2, &@$, $5);
+ }
| RULE ruleid_spec
{
$$ = cmd_alloc(CMD_DELETE, CMD_OBJ_RULE, &$2, &@$, NULL);
@@ -1377,6 +1483,74 @@ delete_cmd : TABLE table_or_id_spec
}
;
+destroy_cmd : TABLE table_or_id_spec
+ {
+ $$ = cmd_alloc(CMD_DESTROY, CMD_OBJ_TABLE, &$2, &@$, NULL);
+ }
+ | CHAIN chain_or_id_spec
+ {
+ $$ = cmd_alloc(CMD_DESTROY, CMD_OBJ_CHAIN, &$2, &@$, NULL);
+ }
+ | RULE ruleid_spec
+ {
+ $$ = cmd_alloc(CMD_DESTROY, CMD_OBJ_RULE, &$2, &@$, NULL);
+ }
+ | SET set_or_id_spec
+ {
+ $$ = cmd_alloc(CMD_DESTROY, CMD_OBJ_SET, &$2, &@$, NULL);
+ }
+ | MAP set_spec
+ {
+ $$ = cmd_alloc(CMD_DESTROY, CMD_OBJ_SET, &$2, &@$, NULL);
+ }
+ | ELEMENT set_spec set_block_expr
+ {
+ $$ = cmd_alloc(CMD_DESTROY, CMD_OBJ_ELEMENTS, &$2, &@$, $3);
+ }
+ | FLOWTABLE flowtable_spec
+ {
+ $$ = cmd_alloc(CMD_DESTROY, CMD_OBJ_FLOWTABLE, &$2, &@$, NULL);
+ }
+ | FLOWTABLE flowtableid_spec
+ {
+ $$ = cmd_alloc(CMD_DESTROY, CMD_OBJ_FLOWTABLE, &$2, &@$, NULL);
+ }
+ | FLOWTABLE flowtable_spec flowtable_block_alloc
+ '{' flowtable_block '}'
+ {
+ $5->location = @5;
+ handle_merge(&$3->handle, &$2);
+ $$ = cmd_alloc(CMD_DESTROY, CMD_OBJ_FLOWTABLE, &$2, &@$, $5);
+ }
+ | COUNTER obj_or_id_spec close_scope_counter
+ {
+ $$ = cmd_alloc(CMD_DESTROY, CMD_OBJ_COUNTER, &$2, &@$, NULL);
+ }
+ | QUOTA obj_or_id_spec close_scope_quota
+ {
+ $$ = cmd_alloc(CMD_DESTROY, CMD_OBJ_QUOTA, &$2, &@$, NULL);
+ }
+ | CT ct_obj_type obj_spec ct_obj_alloc close_scope_ct
+ {
+ $$ = cmd_alloc_obj_ct(CMD_DESTROY, $2, &$3, &@$, $4);
+ if ($2 == NFT_OBJECT_CT_TIMEOUT)
+ init_list_head(&$4->ct_timeout.timeout_list);
+ }
+ | LIMIT obj_or_id_spec close_scope_limit
+ {
+ $$ = cmd_alloc(CMD_DESTROY, CMD_OBJ_LIMIT, &$2, &@$, NULL);
+ }
+ | SECMARK obj_or_id_spec close_scope_secmark
+ {
+ $$ = cmd_alloc(CMD_DESTROY, CMD_OBJ_SECMARK, &$2, &@$, NULL);
+ }
+ | SYNPROXY obj_or_id_spec close_scope_synproxy
+ {
+ $$ = cmd_alloc(CMD_DESTROY, CMD_OBJ_SYNPROXY, &$2, &@$, NULL);
+ }
+ ;
+
+
get_cmd : ELEMENT set_spec set_block_expr
{
$$ = cmd_alloc(CMD_GET, CMD_OBJ_ELEMENTS, &$2, &@$, $3);
@@ -1545,8 +1719,13 @@ reset_cmd : COUNTERS ruleset_spec
{
$$ = cmd_alloc(CMD_RESET, CMD_OBJ_COUNTERS, &$2, &@$, NULL);
}
+ | COUNTERS table_spec
+ {
+ $$ = cmd_alloc(CMD_RESET, CMD_OBJ_COUNTERS, &$2, &@$, NULL);
+ }
| COUNTERS TABLE table_spec
{
+ /* alias of previous rule. */
$$ = cmd_alloc(CMD_RESET, CMD_OBJ_COUNTERS, &$3, &@$, NULL);
}
| COUNTER obj_spec close_scope_counter
@@ -1561,10 +1740,53 @@ reset_cmd : COUNTERS ruleset_spec
{
$$ = cmd_alloc(CMD_RESET, CMD_OBJ_QUOTAS, &$3, &@$, NULL);
}
+ | QUOTAS table_spec
+ {
+ /* alias of previous rule. */
+ $$ = cmd_alloc(CMD_RESET, CMD_OBJ_QUOTAS, &$2, &@$, NULL);
+ }
| QUOTA obj_spec close_scope_quota
{
$$ = cmd_alloc(CMD_RESET, CMD_OBJ_QUOTA, &$2, &@$, NULL);
}
+ | RULES ruleset_spec
+ {
+ $$ = cmd_alloc(CMD_RESET, CMD_OBJ_RULES, &$2, &@$, NULL);
+ }
+ | RULES table_spec
+ {
+ $$ = cmd_alloc(CMD_RESET, CMD_OBJ_RULES, &$2, &@$, NULL);
+ }
+ | RULES TABLE table_spec
+ {
+ /* alias of previous rule. */
+ $$ = cmd_alloc(CMD_RESET, CMD_OBJ_RULES, &$3, &@$, NULL);
+ }
+ | RULES chain_spec
+ {
+ $$ = cmd_alloc(CMD_RESET, CMD_OBJ_RULES, &$2, &@$, NULL);
+ }
+ | RULES CHAIN chain_spec
+ {
+ /* alias of previous rule. */
+ $$ = cmd_alloc(CMD_RESET, CMD_OBJ_RULES, &$3, &@$, NULL);
+ }
+ | RULE ruleid_spec
+ {
+ $$ = cmd_alloc(CMD_RESET, CMD_OBJ_RULE, &$2, &@$, NULL);
+ }
+ | ELEMENT set_spec set_block_expr
+ {
+ $$ = cmd_alloc(CMD_RESET, CMD_OBJ_ELEMENTS, &$2, &@$, $3);
+ }
+ | SET set_or_id_spec
+ {
+ $$ = cmd_alloc(CMD_RESET, CMD_OBJ_SET, &$2, &@$, NULL);
+ }
+ | MAP set_or_id_spec
+ {
+ $$ = cmd_alloc(CMD_RESET, CMD_OBJ_MAP, &$2, &@$, NULL);
+ }
;
flush_cmd : TABLE table_spec
@@ -1675,29 +1897,33 @@ describe_cmd : primary_expr
table_block_alloc : /* empty */
{
$$ = table_alloc();
- open_scope(state, &$$->scope);
+ if (open_scope(state, &$$->scope) < 0) {
+ erec_queue(error(&@$, "too many levels of nesting"),
+ state->msgs);
+ state->nerrs++;
+ }
}
;
-table_options : FLAGS STRING close_scope_flags
+table_options : FLAGS STRING
{
if (strcmp($2, "dormant") == 0) {
$<table>0->flags |= TABLE_F_DORMANT;
- xfree($2);
+ free_const($2);
} else if (strcmp($2, "owner") == 0) {
$<table>0->flags |= TABLE_F_OWNER;
- xfree($2);
+ free_const($2);
} else {
erec_queue(error(&@2, "unknown table option %s", $2),
state->msgs);
- xfree($2);
+ free_const($2);
YYERROR;
}
}
| comment_spec
{
if (already_set($<table>0->comment, &@$, state)) {
- xfree($1);
+ free_const($1);
YYERROR;
}
$<table>0->comment = $1;
@@ -1772,7 +1998,7 @@ table_block : /* empty */ { $$ = $<table>-1; }
list_add_tail(&$4->list, &$1->objs);
$$ = $1;
}
- | table_block CT HELPER obj_identifier obj_block_alloc '{' ct_helper_block '}' close_scope_ct stmt_separator
+ | table_block CT HELPER obj_identifier obj_block_alloc '{' ct_helper_block '}' stmt_separator close_scope_ct
{
$5->location = @4;
$5->type = NFT_OBJECT_CT_HELPER;
@@ -1781,7 +2007,7 @@ table_block : /* empty */ { $$ = $<table>-1; }
list_add_tail(&$5->list, &$1->objs);
$$ = $1;
}
- | table_block CT TIMEOUT obj_identifier obj_block_alloc '{' ct_timeout_block '}' close_scope_ct stmt_separator
+ | table_block CT TIMEOUT obj_identifier obj_block_alloc '{' ct_timeout_block '}' stmt_separator close_scope_ct
{
$5->location = @4;
$5->type = NFT_OBJECT_CT_TIMEOUT;
@@ -1790,7 +2016,7 @@ table_block : /* empty */ { $$ = $<table>-1; }
list_add_tail(&$5->list, &$1->objs);
$$ = $1;
}
- | table_block CT EXPECTATION obj_identifier obj_block_alloc '{' ct_expect_block '}' close_scope_ct stmt_separator
+ | table_block CT EXPECTATION obj_identifier obj_block_alloc '{' ct_expect_block '}' stmt_separator close_scope_ct
{
$5->location = @4;
$5->type = NFT_OBJECT_CT_EXPECT;
@@ -1836,8 +2062,12 @@ table_block : /* empty */ { $$ = $<table>-1; }
chain_block_alloc : /* empty */
{
- $$ = chain_alloc(NULL);
- open_scope(state, &$$->scope);
+ $$ = chain_alloc();
+ if (open_scope(state, &$$->scope) < 0) {
+ erec_queue(error(&@$, "too many levels of nesting"),
+ state->msgs);
+ state->nerrs++;
+ }
}
;
@@ -1852,10 +2082,19 @@ chain_block : /* empty */ { $$ = $<chain>-1; }
list_add_tail(&$2->list, &$1->rules);
$$ = $1;
}
+ | chain_block DEVICES '=' flowtable_expr stmt_separator
+ {
+ if ($$->dev_expr) {
+ list_splice_init(&$4->expressions, &$$->dev_expr->expressions);
+ expr_free($4);
+ break;
+ }
+ $$->dev_expr = $4;
+ }
| chain_block comment_spec stmt_separator
{
if (already_set($1->comment, &@2, state)) {
- xfree($2);
+ free_const($2);
YYERROR;
}
$1->comment = $2;
@@ -1871,7 +2110,7 @@ subchain_block : /* empty */ { $$ = $<chain>-1; }
}
;
-typeof_data_expr : primary_expr
+typeof_verdict_expr : primary_expr
{
struct expr *e = $1;
@@ -1903,6 +2142,17 @@ typeof_data_expr : primary_expr
}
;
+typeof_data_expr : INTERVAL typeof_expr
+ {
+ $2->flags |= EXPR_F_INTERVAL;
+ $$ = $2;
+ }
+ | typeof_verdict_expr
+ {
+ $$ = $1;
+ }
+ ;
+
typeof_expr : primary_expr
{
if (expr_ops($1)->build_udata == NULL) {
@@ -1928,25 +2178,28 @@ typeof_expr : primary_expr
set_block_alloc : /* empty */
{
- $$ = set_alloc(NULL);
+ $$ = set_alloc(&internal_location);
}
;
+typeof_key_expr : TYPEOF typeof_expr { $$ = $2; }
+ | TYPE data_type_expr close_scope_type { $$ = $2; }
+ ;
+
set_block : /* empty */ { $$ = $<set>-1; }
| set_block common_block
| set_block stmt_separator
- | set_block TYPE data_type_expr stmt_separator close_scope_type
+ | set_block typeof_key_expr stmt_separator
{
- $1->key = $3;
- $$ = $1;
- }
- | set_block TYPEOF typeof_expr stmt_separator
- {
- $1->key = $3;
- datatype_set($1->key, $3->dtype);
+ if (already_set($1->key, &@2, state)) {
+ expr_free($2);
+ YYERROR;
+ }
+
+ $1->key = $2;
$$ = $1;
}
- | set_block FLAGS set_flag_list stmt_separator close_scope_flags
+ | set_block FLAGS set_flag_list stmt_separator
{
$1->flags = $3;
$$ = $1;
@@ -1969,6 +2222,10 @@ set_block : /* empty */ { $$ = $<set>-1; }
}
| set_block ELEMENTS '=' set_block_expr
{
+ if (already_set($1->init, &@2, state)) {
+ expr_free($4);
+ YYERROR;
+ }
$1->init = $4;
$$ = $1;
}
@@ -1981,7 +2238,7 @@ set_block : /* empty */ { $$ = $<set>-1; }
| set_block comment_spec stmt_separator
{
if (already_set($1->comment, &@2, state)) {
- xfree($2);
+ free_const($2);
YYERROR;
}
$1->comment = $2;
@@ -2008,15 +2265,27 @@ set_flag : CONSTANT { $$ = NFT_SET_CONSTANT; }
map_block_alloc : /* empty */
{
- $$ = set_alloc(NULL);
+ $$ = set_alloc(&internal_location);
}
;
+ct_obj_type_map : TIMEOUT { $$ = NFT_OBJECT_CT_TIMEOUT; }
+ | EXPECTATION { $$ = NFT_OBJECT_CT_EXPECT; }
+ ;
+
map_block_obj_type : COUNTER close_scope_counter { $$ = NFT_OBJECT_COUNTER; }
| QUOTA close_scope_quota { $$ = NFT_OBJECT_QUOTA; }
| LIMIT close_scope_limit { $$ = NFT_OBJECT_LIMIT; }
| SECMARK close_scope_secmark { $$ = NFT_OBJECT_SECMARK; }
- | SYNPROXY { $$ = NFT_OBJECT_SYNPROXY; }
+ | SYNPROXY close_scope_synproxy { $$ = NFT_OBJECT_SYNPROXY; }
+ ;
+
+map_block_obj_typeof : map_block_obj_type
+ | CT ct_obj_type_map close_scope_ct { $$ = $2; }
+ ;
+
+map_block_data_interval : INTERVAL { $$ = EXPR_F_INTERVAL; }
+ | { $$ = 0; }
;
map_block : /* empty */ { $$ = $<set>-1; }
@@ -2027,23 +2296,24 @@ map_block : /* empty */ { $$ = $<set>-1; }
$1->timeout = $3;
$$ = $1;
}
- | map_block TYPE
- data_type_expr COLON data_type_expr
- stmt_separator close_scope_type
+ | map_block GC_INTERVAL time_spec stmt_separator
{
- $1->key = $3;
- $1->data = $5;
-
- $1->flags |= NFT_SET_MAP;
+ $1->gc_int = $3;
$$ = $1;
}
| map_block TYPE
- data_type_expr COLON INTERVAL data_type_expr
+ data_type_expr COLON map_block_data_interval data_type_expr
stmt_separator close_scope_type
{
+ if (already_set($1->key, &@2, state)) {
+ expr_free($3);
+ expr_free($6);
+ YYERROR;
+ }
+
$1->key = $3;
$1->data = $6;
- $1->data->flags |= EXPR_F_INTERVAL;
+ $1->data->flags |= $5;
$1->flags |= NFT_SET_MAP;
$$ = $1;
@@ -2052,35 +2322,49 @@ map_block : /* empty */ { $$ = $<set>-1; }
typeof_expr COLON typeof_data_expr
stmt_separator
{
- $1->key = $3;
- datatype_set($1->key, $3->dtype);
- $1->data = $5;
+ if (already_set($1->key, &@2, state)) {
+ expr_free($3);
+ expr_free($5);
+ YYERROR;
+ }
- $1->flags |= NFT_SET_MAP;
- $$ = $1;
- }
- | map_block TYPEOF
- typeof_expr COLON INTERVAL typeof_expr
- stmt_separator
- {
$1->key = $3;
- datatype_set($1->key, $3->dtype);
- $1->data = $6;
- $1->data->flags |= EXPR_F_INTERVAL;
- $1->flags |= NFT_SET_MAP;
+ if ($5->etype == EXPR_CT && $5->ct.key == NFT_CT_HELPER) {
+ $1->objtype = NFT_OBJECT_CT_HELPER;
+ $1->flags |= NFT_SET_OBJECT;
+ expr_free($5);
+ } else {
+ $1->data = $5;
+ $1->flags |= NFT_SET_MAP;
+ }
+
$$ = $1;
}
| map_block TYPE
data_type_expr COLON map_block_obj_type
stmt_separator close_scope_type
{
+ if (already_set($1->key, &@2, state)) {
+ expr_free($3);
+ YYERROR;
+ }
+
+ $1->key = $3;
+ $1->objtype = $5;
+ $1->flags |= NFT_SET_OBJECT;
+ $$ = $1;
+ }
+ | map_block TYPEOF
+ typeof_expr COLON map_block_obj_typeof
+ stmt_separator
+ {
$1->key = $3;
$1->objtype = $5;
$1->flags |= NFT_SET_OBJECT;
$$ = $1;
}
- | map_block FLAGS set_flag_list stmt_separator close_scope_flags
+ | map_block FLAGS set_flag_list stmt_separator
{
$1->flags |= $3;
$$ = $1;
@@ -2099,7 +2383,7 @@ map_block : /* empty */ { $$ = $<set>-1; }
| map_block comment_spec stmt_separator
{
if (already_set($1->comment, &@2, state)) {
- xfree($2);
+ free_const($2);
YYERROR;
}
$1->comment = $2;
@@ -2124,7 +2408,7 @@ set_policy_spec : PERFORMANCE { $$ = NFT_SET_POL_PERFORMANCE; }
flowtable_block_alloc : /* empty */
{
- $$ = flowtable_alloc(NULL);
+ $$ = flowtable_alloc(&internal_location);
}
;
@@ -2138,10 +2422,10 @@ flowtable_block : /* empty */ { $$ = $<flowtable>-1; }
if ($$->hook.name == NULL) {
erec_queue(error(&@3, "unknown chain hook"),
state->msgs);
- xfree($3);
+ free_const($3);
YYERROR;
}
- xfree($3);
+ free_const($3);
$$->priority = $4;
}
@@ -2153,7 +2437,7 @@ flowtable_block : /* empty */ { $$ = $<flowtable>-1; }
{
$$->flags |= NFT_FLOWTABLE_COUNTER;
}
- | flowtable_block FLAGS OFFLOAD stmt_separator close_scope_flags
+ | flowtable_block FLAGS OFFLOAD stmt_separator
{
$$->flags |= FLOWTABLE_F_HW_OFFLOAD;
}
@@ -2186,17 +2470,21 @@ flowtable_list_expr : flowtable_expr_member
flowtable_expr_member : QUOTED_STRING
{
- $$ = constant_expr_alloc(&@$, &string_type,
- BYTEORDER_HOST_ENDIAN,
- strlen($1) * BITS_PER_BYTE, $1);
- xfree($1);
+ struct expr *expr = ifname_expr_alloc(&@$, state->msgs, $1);
+
+ if (!expr)
+ YYERROR;
+
+ $$ = expr;
}
| STRING
{
- $$ = constant_expr_alloc(&@$, &string_type,
- BYTEORDER_HOST_ENDIAN,
- strlen($1) * BITS_PER_BYTE, $1);
- xfree($1);
+ struct expr *expr = ifname_expr_alloc(&@$, state->msgs, $1);
+
+ if (!expr)
+ YYERROR;
+
+ $$ = expr;
}
| variable_expr
{
@@ -2211,12 +2499,12 @@ data_type_atom_expr : type_identifier
if (dtype == NULL) {
erec_queue(error(&@1, "unknown datatype %s", $1),
state->msgs);
- xfree($1);
+ free_const($1);
YYERROR;
}
$$ = constant_expr_alloc(&@1, dtype, dtype->byteorder,
dtype->size, NULL);
- xfree($1);
+ free_const($1);
}
| TIME
{
@@ -2239,7 +2527,7 @@ data_type_expr : data_type_atom_expr
obj_block_alloc : /* empty */
{
- $$ = obj_alloc(NULL);
+ $$ = obj_alloc(&internal_location);
}
;
@@ -2253,7 +2541,7 @@ counter_block : /* empty */ { $$ = $<obj>-1; }
| counter_block comment_spec
{
if (already_set($<obj>1->comment, &@2, state)) {
- xfree($2);
+ free_const($2);
YYERROR;
}
$<obj>1->comment = $2;
@@ -2270,7 +2558,7 @@ quota_block : /* empty */ { $$ = $<obj>-1; }
| quota_block comment_spec
{
if (already_set($<obj>1->comment, &@2, state)) {
- xfree($2);
+ free_const($2);
YYERROR;
}
$<obj>1->comment = $2;
@@ -2287,7 +2575,7 @@ ct_helper_block : /* empty */ { $$ = $<obj>-1; }
| ct_helper_block comment_spec
{
if (already_set($<obj>1->comment, &@2, state)) {
- xfree($2);
+ free_const($2);
YYERROR;
}
$<obj>1->comment = $2;
@@ -2298,6 +2586,7 @@ ct_timeout_block : /*empty */
{
$$ = $<obj>-1;
init_list_head(&$$->ct_timeout.timeout_list);
+ $$->type = NFT_OBJECT_CT_TIMEOUT;
}
| ct_timeout_block common_block
| ct_timeout_block stmt_separator
@@ -2308,7 +2597,7 @@ ct_timeout_block : /*empty */
| ct_timeout_block comment_spec
{
if (already_set($<obj>1->comment, &@2, state)) {
- xfree($2);
+ free_const($2);
YYERROR;
}
$<obj>1->comment = $2;
@@ -2325,7 +2614,7 @@ ct_expect_block : /*empty */ { $$ = $<obj>-1; }
| ct_expect_block comment_spec
{
if (already_set($<obj>1->comment, &@2, state)) {
- xfree($2);
+ free_const($2);
YYERROR;
}
$<obj>1->comment = $2;
@@ -2342,7 +2631,7 @@ limit_block : /* empty */ { $$ = $<obj>-1; }
| limit_block comment_spec
{
if (already_set($<obj>1->comment, &@2, state)) {
- xfree($2);
+ free_const($2);
YYERROR;
}
$<obj>1->comment = $2;
@@ -2359,7 +2648,7 @@ secmark_block : /* empty */ { $$ = $<obj>-1; }
| secmark_block comment_spec
{
if (already_set($<obj>1->comment, &@2, state)) {
- xfree($2);
+ free_const($2);
YYERROR;
}
$<obj>1->comment = $2;
@@ -2376,7 +2665,7 @@ synproxy_block : /* empty */ { $$ = $<obj>-1; }
| synproxy_block comment_spec
{
if (already_set($<obj>1->comment, &@2, state)) {
- xfree($2);
+ free_const($2);
YYERROR;
}
$<obj>1->comment = $2;
@@ -2397,12 +2686,15 @@ hook_spec : TYPE close_scope_type STRING HOOK STRING dev_spec prio_spec
if (chain_type == NULL) {
erec_queue(error(&@3, "unknown chain type"),
state->msgs);
- xfree($3);
+ free_const($3);
+ free_const($5);
+ expr_free($6);
+ expr_free($7.expr);
YYERROR;
}
$<chain>0->type.loc = @3;
$<chain>0->type.str = xstrdup(chain_type);
- xfree($3);
+ free_const($3);
$<chain>0->loc = @$;
$<chain>0->hook.loc = @5;
@@ -2410,10 +2702,12 @@ hook_spec : TYPE close_scope_type STRING HOOK STRING dev_spec prio_spec
if ($<chain>0->hook.name == NULL) {
erec_queue(error(&@5, "unknown chain hook"),
state->msgs);
- xfree($5);
+ free_const($5);
+ expr_free($6);
+ expr_free($7.expr);
YYERROR;
}
- xfree($5);
+ free_const($5);
$<chain>0->dev_expr = $6;
$<chain>0->priority = $7;
@@ -2460,7 +2754,7 @@ extended_prio_spec : int_num
BYTEORDER_HOST_ENDIAN,
strlen($1) * BITS_PER_BYTE,
$1);
- xfree($1);
+ free_const($1);
$$ = spec;
}
| extended_prio_name PLUS NUM
@@ -2473,7 +2767,7 @@ extended_prio_spec : int_num
BYTEORDER_HOST_ENDIAN,
strlen(str) * BITS_PER_BYTE,
str);
- xfree($1);
+ free_const($1);
$$ = spec;
}
| extended_prio_name DASH NUM
@@ -2486,7 +2780,7 @@ extended_prio_spec : int_num
BYTEORDER_HOST_ENDIAN,
strlen(str) * BITS_PER_BYTE,
str);
- xfree($1);
+ free_const($1);
$$ = spec;
}
;
@@ -2497,12 +2791,11 @@ int_num : NUM { $$ = $1; }
dev_spec : DEVICE string
{
- struct expr *expr;
+ struct expr *expr = ifname_expr_alloc(&@$, state->msgs, $2);
+
+ if (!expr)
+ YYERROR;
- expr = constant_expr_alloc(&@$, &string_type,
- BYTEORDER_HOST_ENDIAN,
- strlen($2) * BITS_PER_BYTE, $2);
- xfree($2);
$$ = compound_expr_alloc(&@$, EXPR_LIST);
compound_expr_add($$, expr);
@@ -2520,7 +2813,7 @@ dev_spec : DEVICE string
| /* empty */ { $$ = NULL; }
;
-flags_spec : FLAGS OFFLOAD close_scope_flags
+flags_spec : FLAGS OFFLOAD
{
$<chain>0->flags |= CHAIN_F_HW_OFFLOAD;
}
@@ -2558,6 +2851,7 @@ chain_policy : ACCEPT { $$ = NF_ACCEPT; }
;
identifier : STRING
+ | LAST { $$ = xstrdup("last"); }
;
string : STRING
@@ -2571,7 +2865,7 @@ time_spec : STRING
uint64_t res;
erec = time_parse(&@1, $1, &res);
- xfree($1);
+ free_const($1);
if (erec != NULL) {
erec_queue(erec, state->msgs);
YYERROR;
@@ -2580,6 +2874,11 @@ time_spec : STRING
}
;
+/* compatibility kludge to allow either 60, 60s, 1m, ... */
+time_spec_or_num_s : NUM
+ | time_spec { $$ = $1 / 1000u; }
+ ;
+
family_spec : /* empty */ { $$ = NFPROTO_IPV4; }
| family_spec_explicit
;
@@ -2767,7 +3066,7 @@ comment_spec : COMMENT string
erec_queue(error(&@2, "comment too long, %d characters maximum allowed",
NFTNL_UDATA_COMMENT_MAXLEN),
state->msgs);
- xfree($2);
+ free_const($2);
YYERROR;
}
$$ = $2;
@@ -2804,7 +3103,7 @@ rule_alloc : stmt_list
list_for_each_entry(i, $1, list)
$$->num_stmts++;
list_splice_tail($1, &$$->stmts);
- xfree($1);
+ free($1);
}
;
@@ -2834,10 +3133,65 @@ stateful_stmt_list : stateful_stmt
}
;
+objref_stmt_counter : COUNTER NAME stmt_expr close_scope_counter
+ {
+ $$ = objref_stmt_alloc(&@$);
+ $$->objref.type = NFT_OBJECT_COUNTER;
+ $$->objref.expr = $3;
+ }
+ ;
+
+objref_stmt_limit : LIMIT NAME stmt_expr close_scope_limit
+ {
+ $$ = objref_stmt_alloc(&@$);
+ $$->objref.type = NFT_OBJECT_LIMIT;
+ $$->objref.expr = $3;
+ }
+ ;
+
+objref_stmt_quota : QUOTA NAME stmt_expr close_scope_quota
+ {
+ $$ = objref_stmt_alloc(&@$);
+ $$->objref.type = NFT_OBJECT_QUOTA;
+ $$->objref.expr = $3;
+ }
+ ;
+
+objref_stmt_synproxy : SYNPROXY NAME stmt_expr close_scope_synproxy
+ {
+ $$ = objref_stmt_alloc(&@$);
+ $$->objref.type = NFT_OBJECT_SYNPROXY;
+ $$->objref.expr = $3;
+ }
+ ;
+
+objref_stmt_ct : CT TIMEOUT SET stmt_expr close_scope_ct
+ {
+ $$ = objref_stmt_alloc(&@$);
+ $$->objref.type = NFT_OBJECT_CT_TIMEOUT;
+ $$->objref.expr = $4;
+
+ }
+ | CT EXPECTATION SET stmt_expr close_scope_ct
+ {
+ $$ = objref_stmt_alloc(&@$);
+ $$->objref.type = NFT_OBJECT_CT_EXPECT;
+ $$->objref.expr = $4;
+ }
+ ;
+
+objref_stmt : objref_stmt_counter
+ | objref_stmt_limit
+ | objref_stmt_quota
+ | objref_stmt_synproxy
+ | objref_stmt_ct
+ ;
+
stateful_stmt : counter_stmt close_scope_counter
| limit_stmt
| quota_stmt
| connlimit_stmt
+ | last_stmt close_scope_last
;
stmt : verdict_stmt
@@ -2861,6 +3215,19 @@ stmt : verdict_stmt
| synproxy_stmt close_scope_synproxy
| chain_stmt
| optstrip_stmt
+ | xt_stmt close_scope_xt
+ | objref_stmt
+ ;
+
+xt_stmt : XT STRING string
+ {
+ $$ = NULL;
+ free_const($2);
+ free_const($3);
+ erec_queue(error(&@$, "unsupported xtables compat expression, use iptables-nft with this ruleset"),
+ state->msgs);
+ YYERROR;
+ }
;
chain_stmt_type : JUMP { $$ = NFT_JUMP; }
@@ -2915,7 +3282,7 @@ verdict_map_list_expr : verdict_map_list_member_expr
verdict_map_list_member_expr: opt_newline set_elem_expr COLON verdict_expr opt_newline
{
- $$ = mapping_expr_alloc(&@$, $2, $4);
+ $$ = mapping_expr_alloc(&@2, $2, $4);
}
;
@@ -2939,12 +3306,6 @@ counter_stmt_alloc : COUNTER
{
$$ = counter_stmt_alloc(&@$);
}
- | COUNTER NAME stmt_expr
- {
- $$ = objref_stmt_alloc(&@$);
- $$->objref.type = NFT_OBJECT_COUNTER;
- $$->objref.expr = $3;
- }
;
counter_args : counter_arg
@@ -2956,14 +3317,32 @@ counter_args : counter_arg
counter_arg : PACKETS NUM
{
+ assert($<stmt>0->ops->type == STMT_COUNTER);
$<stmt>0->counter.packets = $2;
}
| BYTES NUM
{
+ assert($<stmt>0->ops->type == STMT_COUNTER);
$<stmt>0->counter.bytes = $2;
}
;
+last_stmt : LAST
+ {
+ $$ = last_stmt_alloc(&@$);
+ }
+ | LAST USED NEVER
+ {
+ $$ = last_stmt_alloc(&@$);
+ }
+ | LAST USED time_spec
+ {
+ $$ = last_stmt_alloc(&@$);
+ $$->last.used = $3;
+ $$->last.set = true;
+ }
+ ;
+
log_stmt : log_stmt_alloc
| log_stmt_alloc log_args
;
@@ -2998,7 +3377,7 @@ log_arg : PREFIX string
expr = constant_expr_alloc(&@$, &string_type,
BYTEORDER_HOST_ENDIAN,
(strlen($2) + 1) * BITS_PER_BYTE, $2);
- xfree($2);
+ free_const($2);
$<stmt>0->log.prefix = expr;
$<stmt>0->log.flags |= STMT_LOG_PREFIX;
break;
@@ -3072,7 +3451,7 @@ log_arg : PREFIX string
state->msgs);
}
expr_free(expr);
- xfree($2);
+ free_const($2);
YYERROR;
}
item = variable_expr_alloc(&@$, scope, sym);
@@ -3102,7 +3481,7 @@ log_arg : PREFIX string
}
}
- xfree($2);
+ free_const($2);
$<stmt>0->log.prefix = expr;
$<stmt>0->log.flags |= STMT_LOG_PREFIX;
}
@@ -3126,7 +3505,7 @@ log_arg : PREFIX string
$<stmt>0->log.level = $2;
$<stmt>0->log.flags |= STMT_LOG_LEVEL;
}
- | FLAGS log_flags close_scope_flags
+ | FLAGS log_flags
{
$<stmt>0->log.logflags |= $2;
}
@@ -3155,10 +3534,10 @@ level_type : string
else {
erec_queue(error(&@1, "invalid log level"),
state->msgs);
- xfree($1);
+ free_const($1);
YYERROR;
}
- xfree($1);
+ free_const($1);
}
;
@@ -3204,7 +3583,7 @@ log_flag_tcp : SEQUENCE
limit_stmt : LIMIT RATE limit_mode limit_rate_pkts limit_burst_pkts close_scope_limit
{
if ($5 == 0) {
- erec_queue(error(&@5, "limit burst must be > 0"),
+ erec_queue(error(&@5, "packet limit burst must be > 0"),
state->msgs);
YYERROR;
}
@@ -3217,11 +3596,6 @@ limit_stmt : LIMIT RATE limit_mode limit_rate_pkts limit_burst_pkts close_scope
}
| LIMIT RATE limit_mode limit_rate_bytes limit_burst_bytes close_scope_limit
{
- if ($5 == 0) {
- erec_queue(error(&@5, "limit burst must be > 0"),
- state->msgs);
- YYERROR;
- }
$$ = limit_stmt_alloc(&@$);
$$->limit.rate = $4.rate;
$$->limit.unit = $4.unit;
@@ -3229,12 +3603,6 @@ limit_stmt : LIMIT RATE limit_mode limit_rate_pkts limit_burst_pkts close_scope
$$->limit.type = NFT_LIMIT_PKT_BYTES;
$$->limit.flags = $3;
}
- | LIMIT NAME stmt_expr close_scope_limit
- {
- $$ = objref_stmt_alloc(&@$);
- $$->objref.type = NFT_OBJECT_LIMIT;
- $$->objref.expr = $3;
- }
;
quota_mode : OVER { $$ = NFT_QUOTA_F_INV; }
@@ -3253,7 +3621,7 @@ quota_used : /* empty */ { $$ = 0; }
uint64_t rate;
erec = data_unit_parse(&@$, $3, &rate);
- xfree($3);
+ free_const($3);
if (erec != NULL) {
erec_queue(erec, state->msgs);
YYERROR;
@@ -3268,7 +3636,7 @@ quota_stmt : QUOTA quota_mode NUM quota_unit quota_used close_scope_quota
uint64_t rate;
erec = data_unit_parse(&@$, $4, &rate);
- xfree($4);
+ free_const($4);
if (erec != NULL) {
erec_queue(erec, state->msgs);
YYERROR;
@@ -3278,12 +3646,6 @@ quota_stmt : QUOTA quota_mode NUM quota_unit quota_used close_scope_quota
$$->quota.used = $5;
$$->quota.flags = $2;
}
- | QUOTA NAME stmt_expr close_scope_quota
- {
- $$ = objref_stmt_alloc(&@$);
- $$->objref.type = NFT_OBJECT_QUOTA;
- $$->objref.expr = $3;
- }
;
limit_mode : OVER { $$ = NFT_LIMIT_F_INV; }
@@ -3302,7 +3664,7 @@ limit_rate_pkts : NUM SLASH time_unit
}
;
-limit_burst_bytes : /* empty */ { $$ = 5; }
+limit_burst_bytes : /* empty */ { $$ = 0; }
| BURST limit_bytes { $$ = $2; }
;
@@ -3312,7 +3674,7 @@ limit_rate_bytes : NUM STRING
uint64_t rate, unit;
erec = rate_parse(&@$, $2, &rate, &unit);
- xfree($2);
+ free_const($2);
if (erec != NULL) {
erec_queue(erec, state->msgs);
YYERROR;
@@ -3334,7 +3696,7 @@ limit_bytes : NUM BYTES { $$ = $1; }
uint64_t rate;
erec = data_unit_parse(&@$, $2, &rate);
- xfree($2);
+ free_const($2);
if (erec != NULL) {
erec_queue(erec, state->msgs);
YYERROR;
@@ -3363,7 +3725,7 @@ reject_with_expr : STRING
{
$$ = symbol_expr_alloc(&@$, SYMBOL_VALUE,
current_scope(state), $1);
- xfree($1);
+ free_const($1);
}
| integer_expr { $$ = $1; }
;
@@ -3378,40 +3740,40 @@ reject_opts : /* empty */
$<stmt>0->reject.family = NFPROTO_IPV4;
$<stmt>0->reject.type = NFT_REJECT_ICMP_UNREACH;
$<stmt>0->reject.expr = $4;
- datatype_set($<stmt>0->reject.expr, &icmp_code_type);
+ datatype_set($<stmt>0->reject.expr, &reject_icmp_code_type);
}
| WITH ICMP reject_with_expr
{
$<stmt>0->reject.family = NFPROTO_IPV4;
$<stmt>0->reject.type = NFT_REJECT_ICMP_UNREACH;
$<stmt>0->reject.expr = $3;
- datatype_set($<stmt>0->reject.expr, &icmp_code_type);
+ datatype_set($<stmt>0->reject.expr, &reject_icmp_code_type);
}
| WITH ICMP6 TYPE reject_with_expr close_scope_type close_scope_icmp
{
$<stmt>0->reject.family = NFPROTO_IPV6;
$<stmt>0->reject.type = NFT_REJECT_ICMP_UNREACH;
$<stmt>0->reject.expr = $4;
- datatype_set($<stmt>0->reject.expr, &icmpv6_code_type);
+ datatype_set($<stmt>0->reject.expr, &reject_icmpv6_code_type);
}
| WITH ICMP6 reject_with_expr
{
$<stmt>0->reject.family = NFPROTO_IPV6;
$<stmt>0->reject.type = NFT_REJECT_ICMP_UNREACH;
$<stmt>0->reject.expr = $3;
- datatype_set($<stmt>0->reject.expr, &icmpv6_code_type);
+ datatype_set($<stmt>0->reject.expr, &reject_icmpv6_code_type);
}
| WITH ICMPX TYPE reject_with_expr close_scope_type
{
$<stmt>0->reject.type = NFT_REJECT_ICMPX_UNREACH;
$<stmt>0->reject.expr = $4;
- datatype_set($<stmt>0->reject.expr, &icmpx_code_type);
+ datatype_set($<stmt>0->reject.expr, &reject_icmpx_code_type);
}
| WITH ICMPX reject_with_expr
{
$<stmt>0->reject.type = NFT_REJECT_ICMPX_UNREACH;
$<stmt>0->reject.expr = $3;
- datatype_set($<stmt>0->reject.expr, &icmpx_code_type);
+ datatype_set($<stmt>0->reject.expr, &reject_icmpx_code_type);
}
| WITH TCP close_scope_tcp RESET close_scope_reset
{
@@ -3422,8 +3784,8 @@ reject_opts : /* empty */
nat_stmt : nat_stmt_alloc nat_stmt_args
;
-nat_stmt_alloc : SNAT { $$ = nat_stmt_alloc(&@$, NFT_NAT_SNAT); }
- | DNAT { $$ = nat_stmt_alloc(&@$, NFT_NAT_DNAT); }
+nat_stmt_alloc : SNAT { $$ = nat_stmt_alloc(&@$, __NFT_NAT_SNAT); }
+ | DNAT { $$ = nat_stmt_alloc(&@$, __NFT_NAT_DNAT); }
;
tproxy_stmt : TPROXY TO stmt_expr
@@ -3474,12 +3836,6 @@ synproxy_stmt_alloc : SYNPROXY
{
$$ = synproxy_stmt_alloc(&@$);
}
- | SYNPROXY NAME stmt_expr
- {
- $$ = objref_stmt_alloc(&@$);
- $$->objref.type = NFT_OBJECT_SYNPROXY;
- $$->objref.expr = $3;
- }
;
synproxy_args : synproxy_arg
@@ -3828,13 +4184,13 @@ queue_stmt : queue_stmt_compat close_scope_queue
{
$$ = queue_stmt_alloc(&@$, $3, 0);
}
- | QUEUE FLAGS queue_stmt_flags close_scope_flags TO queue_stmt_expr close_scope_queue
+ | QUEUE FLAGS queue_stmt_flags TO queue_stmt_expr close_scope_queue
{
- $$ = queue_stmt_alloc(&@$, $6, $3);
+ $$ = queue_stmt_alloc(&@$, $5, $3);
}
- | QUEUE FLAGS queue_stmt_flags close_scope_flags QUEUENUM queue_stmt_expr_simple close_scope_queue
+ | QUEUE FLAGS queue_stmt_flags QUEUENUM queue_stmt_expr_simple close_scope_queue
{
- $$ = queue_stmt_alloc(&@$, $6, $3);
+ $$ = queue_stmt_alloc(&@$, $5, $3);
}
;
@@ -4027,12 +4383,12 @@ variable_expr : '$' identifier
erec_queue(error(&@2, "unknown identifier '%s'", $2),
state->msgs);
}
- xfree($2);
+ free_const($2);
YYERROR;
}
$$ = variable_expr_alloc(&@$, scope, sym);
- xfree($2);
+ free_const($2);
}
;
@@ -4042,7 +4398,7 @@ symbol_expr : variable_expr
$$ = symbol_expr_alloc(&@$, SYMBOL_VALUE,
current_scope(state),
$1);
- xfree($1);
+ free_const($1);
}
;
@@ -4055,7 +4411,7 @@ set_ref_symbol_expr : AT identifier close_scope_at
$$ = symbol_expr_alloc(&@$, SYMBOL_SET,
current_scope(state),
$2);
- xfree($2);
+ free_const($2);
}
;
@@ -4152,10 +4508,10 @@ osf_ttl : /* empty */
else {
erec_queue(error(&@2, "invalid ttl option"),
state->msgs);
- xfree($2);
+ free_const($2);
YYERROR;
}
- xfree($2);
+ free_const($2);
}
;
@@ -4263,7 +4619,7 @@ set_list_member_expr : opt_newline set_expr opt_newline
}
| opt_newline set_elem_expr COLON set_rhs_expr opt_newline
{
- $$ = mapping_expr_alloc(&@$, $2, $4);
+ $$ = mapping_expr_alloc(&@2, $2, $4);
}
;
@@ -4283,6 +4639,12 @@ meter_key_expr_alloc : concat_expr
set_elem_expr : set_elem_expr_alloc
| set_elem_expr_alloc set_elem_expr_options
+ | set_elem_expr_alloc set_elem_expr_options set_elem_stmt_list
+ {
+ $$ = $1;
+ list_splice_tail($3, &$$->stmt_list);
+ free($3);
+ }
;
set_elem_key_expr : set_lhs_expr { $$ = $1; }
@@ -4293,7 +4655,7 @@ set_elem_expr_alloc : set_elem_key_expr set_elem_stmt_list
{
$$ = set_elem_expr_alloc(&@1, $1);
list_splice_tail($2, &$$->stmt_list);
- xfree($2);
+ free($2);
}
| set_elem_key_expr
{
@@ -4319,7 +4681,7 @@ set_elem_option : TIMEOUT time_spec
| comment_spec
{
if (already_set($<expr>0->comment, &@1, state)) {
- xfree($1);
+ free_const($1);
YYERROR;
}
$<expr>0->comment = $1;
@@ -4395,6 +4757,32 @@ set_elem_stmt : COUNTER close_scope_counter
$$->connlimit.count = $4;
$$->connlimit.flags = NFT_CONNLIMIT_F_INV;
}
+ | QUOTA quota_mode NUM quota_unit quota_used close_scope_quota
+ {
+ struct error_record *erec;
+ uint64_t rate;
+
+ erec = data_unit_parse(&@$, $4, &rate);
+ free_const($4);
+ if (erec != NULL) {
+ erec_queue(erec, state->msgs);
+ YYERROR;
+ }
+ $$ = quota_stmt_alloc(&@$);
+ $$->quota.bytes = $3 * rate;
+ $$->quota.used = $5;
+ $$->quota.flags = $2;
+ }
+ | LAST USED NEVER close_scope_last
+ {
+ $$ = last_stmt_alloc(&@$);
+ }
+ | LAST USED time_spec close_scope_last
+ {
+ $$ = last_stmt_alloc(&@$);
+ $$->last.used = $3;
+ $$->last.set = true;
+ }
;
set_elem_expr_option : TIMEOUT time_spec
@@ -4408,7 +4796,7 @@ set_elem_expr_option : TIMEOUT time_spec
| comment_spec
{
if (already_set($<expr>0->comment, &@1, state)) {
- xfree($1);
+ free_const($1);
YYERROR;
}
$<expr>0->comment = $1;
@@ -4460,7 +4848,7 @@ quota_config : quota_mode NUM quota_unit quota_used
uint64_t rate;
erec = data_unit_parse(&@$, $3, &rate);
- xfree($3);
+ free_const($3);
if (erec != NULL) {
erec_queue(erec, state->msgs);
YYERROR;
@@ -4489,10 +4877,10 @@ secmark_config : string
ret = snprintf(secmark->ctx, sizeof(secmark->ctx), "%s", $1);
if (ret <= 0 || ret >= (int)sizeof(secmark->ctx)) {
erec_queue(error(&@1, "invalid context '%s', max length is %u\n", $1, (int)sizeof(secmark->ctx)), state->msgs);
- xfree($1);
+ free_const($1);
YYERROR;
}
- xfree($1);
+ free_const($1);
}
;
@@ -4509,27 +4897,34 @@ ct_obj_type : HELPER { $$ = NFT_OBJECT_CT_HELPER; }
;
ct_cmd_type : HELPERS { $$ = CMD_OBJ_CT_HELPERS; }
- | TIMEOUT { $$ = CMD_OBJ_CT_TIMEOUT; }
- | EXPECTATION { $$ = CMD_OBJ_CT_EXPECT; }
+ | TIMEOUT { $$ = CMD_OBJ_CT_TIMEOUTS; }
+ | EXPECTATION { $$ = CMD_OBJ_CT_EXPECTATIONS; }
;
ct_l4protoname : TCP close_scope_tcp { $$ = IPPROTO_TCP; }
| UDP close_scope_udp { $$ = IPPROTO_UDP; }
;
-ct_helper_config : TYPE QUOTED_STRING PROTOCOL ct_l4protoname stmt_separator close_scope_type
+ct_helper_config : TYPE QUOTED_STRING PROTOCOL ct_l4protoname stmt_separator close_scope_type
{
struct ct_helper *ct;
int ret;
ct = &$<obj>0->ct_helper;
+ if (ct->l4proto) {
+ erec_queue(error(&@2, "You can only specify this once. This statement is already set for %s.", ct->name), state->msgs);
+ free_const($2);
+ YYERROR;
+ }
+
ret = snprintf(ct->name, sizeof(ct->name), "%s", $2);
if (ret <= 0 || ret >= (int)sizeof(ct->name)) {
erec_queue(error(&@2, "invalid name '%s', max length is %u\n", $2, (int)sizeof(ct->name)), state->msgs);
+ free_const($2);
YYERROR;
}
- xfree($2);
+ free_const($2);
ct->l4proto = $4;
}
@@ -4543,17 +4938,16 @@ timeout_states : timeout_state
{
$$ = xmalloc(sizeof(*$$));
init_list_head($$);
- list_add_tail($1, $$);
+ list_add_tail(&$1->head, $$);
}
| timeout_states COMMA timeout_state
{
- list_add_tail($3, $1);
+ list_add_tail(&$3->head, $1);
$$ = $1;
}
;
-timeout_state : STRING COLON NUM
-
+timeout_state : STRING COLON time_spec_or_num_s
{
struct timeout_state *ts;
@@ -4562,7 +4956,7 @@ timeout_state : STRING COLON NUM
ts->timeout_value = $3;
ts->location = @1;
init_list_head(&ts->head);
- $$ = &ts->head;
+ $$ = ts;
}
;
@@ -4580,7 +4974,7 @@ ct_timeout_config : PROTOCOL ct_l4protoname stmt_separator
ct = &$<obj>0->ct_timeout;
list_splice_tail($4, &ct->timeout_list);
- xfree($4);
+ free($4);
}
| L3PROTOCOL family_spec_explicit stmt_separator
{
@@ -4778,9 +5172,11 @@ keyword_expr : ETHER close_scope_eth { $$ = symbol_value(&@$, "ether"); }
| SNAT close_scope_nat { $$ = symbol_value(&@$, "snat"); }
| ECN { $$ = symbol_value(&@$, "ecn"); }
| RESET close_scope_reset { $$ = symbol_value(&@$, "reset"); }
+ | DESTROY close_scope_destroy { $$ = symbol_value(&@$, "destroy"); }
| ORIGINAL { $$ = symbol_value(&@$, "original"); }
| REPLY { $$ = symbol_value(&@$, "reply"); }
| LABEL { $$ = symbol_value(&@$, "label"); }
+ | LAST close_scope_last { $$ = symbol_value(&@$, "last"); }
;
primary_rhs_expr : symbol_expr { $$ = $1; }
@@ -4843,6 +5239,13 @@ primary_rhs_expr : symbol_expr { $$ = $1; }
BYTEORDER_HOST_ENDIAN,
sizeof(data) * BITS_PER_BYTE, &data);
}
+ | GRE close_scope_gre
+ {
+ uint8_t data = IPPROTO_GRE;
+ $$ = constant_expr_alloc(&@$, &inet_protocol_type,
+ BYTEORDER_HOST_ENDIAN,
+ sizeof(data) * BITS_PER_BYTE, &data);
+ }
| COMP close_scope_comp
{
uint8_t data = IPPROTO_COMP;
@@ -4916,7 +5319,7 @@ chain_expr : variable_expr
BYTEORDER_HOST_ENDIAN,
strlen($1) * BITS_PER_BYTE,
$1);
- xfree($1);
+ free_const($1);
}
;
@@ -4934,7 +5337,7 @@ meta_expr : META meta_key close_scope_meta
unsigned int key;
erec = meta_key_parse(&@$, $2, &key);
- xfree($2);
+ free_const($2);
if (erec != NULL) {
erec_queue(erec, state->msgs);
YYERROR;
@@ -5011,9 +5414,10 @@ meta_stmt : META meta_key SET stmt_expr close_scope_meta
unsigned int key;
erec = meta_key_parse(&@$, $2, &key);
- xfree($2);
+ free_const($2);
if (erec != NULL) {
erec_queue(erec, state->msgs);
+ expr_free($4);
YYERROR;
}
@@ -5252,19 +5656,6 @@ ct_stmt : CT ct_key SET stmt_expr close_scope_ct
break;
}
}
- | CT TIMEOUT SET stmt_expr close_scope_ct
- {
- $$ = objref_stmt_alloc(&@$);
- $$->objref.type = NFT_OBJECT_CT_TIMEOUT;
- $$->objref.expr = $4;
-
- }
- | CT EXPECTATION SET stmt_expr close_scope_ct
- {
- $$ = objref_stmt_alloc(&@$);
- $$->objref.type = NFT_OBJECT_CT_EXPECT;
- $$->objref.expr = $4;
- }
| CT ct_dir ct_key_dir_optional SET stmt_expr close_scope_ct
{
$$ = ct_stmt_alloc(&@$, $3, $2, $5);
@@ -5298,9 +5689,31 @@ payload_expr : payload_raw_expr
| dccp_hdr_expr
| sctp_hdr_expr
| th_hdr_expr
+ | vxlan_hdr_expr
+ | geneve_hdr_expr
+ | gre_hdr_expr
+ | gretap_hdr_expr
;
-payload_raw_expr : AT payload_base_spec COMMA NUM COMMA NUM close_scope_at
+payload_raw_len : NUM
+ {
+ if ($1 > NFT_MAX_EXPR_LEN_BITS) {
+ erec_queue(error(&@1, "raw payload length %u exceeds upper limit of %u",
+ $1, NFT_MAX_EXPR_LEN_BITS),
+ state->msgs);
+ YYERROR;
+ }
+
+ if ($1 == 0) {
+ erec_queue(error(&@1, "raw payload length cannot be 0"), state->msgs);
+ YYERROR;
+ }
+
+ $$ = $1;
+ }
+ ;
+
+payload_raw_expr : AT payload_base_spec COMMA NUM COMMA payload_raw_len close_scope_at
{
$$ = payload_expr_alloc(&@$, NULL, 0);
payload_init_raw($$, $2, $4, $6);
@@ -5318,10 +5731,10 @@ payload_base_spec : LL_HDR { $$ = PROTO_BASE_LL_HDR; }
$$ = PROTO_BASE_INNER_HDR;
} else {
erec_queue(error(&@1, "unknown raw payload base"), state->msgs);
- xfree($1);
+ free_const($1);
YYERROR;
}
- xfree($1);
+ free_const($1);
}
;
@@ -5469,6 +5882,8 @@ icmp6_hdr_field : TYPE close_scope_type { $$ = ICMP6HDR_TYPE; }
| ID { $$ = ICMP6HDR_ID; }
| SEQUENCE { $$ = ICMP6HDR_SEQ; }
| MAXDELAY { $$ = ICMP6HDR_MAXDELAY; }
+ | TADDR { $$ = ICMP6HDR_TADDR; }
+ | DADDR { $$ = ICMP6HDR_DADDR; }
;
auth_hdr_expr : AH auth_hdr_field close_scope_ah
@@ -5501,7 +5916,7 @@ comp_hdr_expr : COMP comp_hdr_field close_scope_comp
;
comp_hdr_field : NEXTHDR { $$ = COMPHDR_NEXTHDR; }
- | FLAGS close_scope_flags { $$ = COMPHDR_FLAGS; }
+ | FLAGS { $$ = COMPHDR_FLAGS; }
| CPI { $$ = COMPHDR_CPI; }
;
@@ -5541,14 +5956,106 @@ tcp_hdr_expr : TCP tcp_hdr_field
| TCP OPTION tcp_hdr_option_kind_and_field
{
$$ = tcpopt_expr_alloc(&@$, $3.kind, $3.field);
+ if ($$ == NULL) {
+ erec_queue(error(&@1, "Could not find a tcp option template"), state->msgs);
+ YYERROR;
+ }
}
- | TCP OPTION AT close_scope_at tcp_hdr_option_type COMMA NUM COMMA NUM
+ | TCP OPTION AT close_scope_at tcp_hdr_option_type COMMA NUM COMMA payload_raw_len
{
$$ = tcpopt_expr_alloc(&@$, $5, 0);
tcpopt_init_raw($$, $5, $7, $9, 0);
}
;
+inner_inet_expr : ip_hdr_expr
+ | icmp_hdr_expr
+ | igmp_hdr_expr
+ | ip6_hdr_expr
+ | icmp6_hdr_expr
+ | auth_hdr_expr
+ | esp_hdr_expr
+ | comp_hdr_expr
+ | udp_hdr_expr
+ | udplite_hdr_expr
+ | tcp_hdr_expr close_scope_tcp
+ | dccp_hdr_expr
+ | sctp_hdr_expr
+ | th_hdr_expr
+ ;
+
+inner_eth_expr : eth_hdr_expr
+ | vlan_hdr_expr
+ | arp_hdr_expr
+ ;
+
+inner_expr : inner_eth_expr
+ | inner_inet_expr
+ ;
+
+vxlan_hdr_expr : VXLAN vxlan_hdr_field
+ {
+ struct expr *expr;
+
+ expr = payload_expr_alloc(&@$, &proto_vxlan, $2);
+ expr->payload.inner_desc = &proto_vxlan;
+ $$ = expr;
+ }
+ | VXLAN inner_expr
+ {
+ $$ = $2;
+ $$->location = @$;
+ $$->payload.inner_desc = &proto_vxlan;
+ }
+ ;
+
+vxlan_hdr_field : VNI { $$ = VXLANHDR_VNI; }
+ | FLAGS { $$ = VXLANHDR_FLAGS; }
+ ;
+
+geneve_hdr_expr : GENEVE geneve_hdr_field
+ {
+ struct expr *expr;
+
+ expr = payload_expr_alloc(&@$, &proto_geneve, $2);
+ expr->payload.inner_desc = &proto_geneve;
+ $$ = expr;
+ }
+ | GENEVE inner_expr
+ {
+ $$ = $2;
+ $$->location = @$;
+ $$->payload.inner_desc = &proto_geneve;
+ }
+ ;
+
+geneve_hdr_field : VNI { $$ = GNVHDR_VNI; }
+ | TYPE { $$ = GNVHDR_TYPE; }
+ ;
+
+gre_hdr_expr : GRE gre_hdr_field close_scope_gre
+ {
+ $$ = payload_expr_alloc(&@$, &proto_gre, $2);
+ }
+ | GRE close_scope_gre inner_inet_expr
+ {
+ $$ = $3;
+ $$->payload.inner_desc = &proto_gre;
+ }
+ ;
+
+gre_hdr_field : HDRVERSION { $$ = GREHDR_VERSION; }
+ | FLAGS { $$ = GREHDR_FLAGS; }
+ | PROTOCOL { $$ = GREHDR_PROTOCOL; }
+ ;
+
+gretap_hdr_expr : GRETAP close_scope_gre inner_expr
+ {
+ $$ = $3;
+ $$->payload.inner_desc = &proto_gretap;
+ }
+ ;
+
optstrip_stmt : RESET TCP OPTION tcp_hdr_option_type close_scope_tcp
{
$$ = optstrip_stmt_alloc(&@$, tcpopt_expr_alloc(&@$,
@@ -5562,7 +6069,7 @@ tcp_hdr_field : SPORT { $$ = TCPHDR_SPORT; }
| ACKSEQ { $$ = TCPHDR_ACKSEQ; }
| DOFF { $$ = TCPHDR_DOFF; }
| RESERVED { $$ = TCPHDR_RESERVED; }
- | FLAGS close_scope_flags { $$ = TCPHDR_FLAGS; }
+ | FLAGS { $$ = TCPHDR_FLAGS; }
| WINDOW { $$ = TCPHDR_WINDOW; }
| CHECKSUM { $$ = TCPHDR_CHECKSUM; }
| URGPTR { $$ = TCPHDR_URGPTR; }
@@ -5648,6 +6155,15 @@ dccp_hdr_expr : DCCP dccp_hdr_field close_scope_dccp
{
$$ = payload_expr_alloc(&@$, &proto_dccp, $2);
}
+ | DCCP OPTION NUM close_scope_dccp
+ {
+ if ($3 > DCCPOPT_TYPE_MAX) {
+ erec_queue(error(&@1, "value too large"),
+ state->msgs);
+ YYERROR;
+ }
+ $$ = dccpopt_expr_alloc(&@$, $3);
+ }
;
dccp_hdr_field : SPORT { $$ = DCCPHDR_SPORT; }
@@ -5676,7 +6192,7 @@ sctp_chunk_type : DATA { $$ = SCTP_CHUNK_TYPE_DATA; }
;
sctp_chunk_common_field : TYPE close_scope_type { $$ = SCTP_CHUNK_COMMON_TYPE; }
- | FLAGS close_scope_flags { $$ = SCTP_CHUNK_COMMON_FLAGS; }
+ | FLAGS { $$ = SCTP_CHUNK_COMMON_FLAGS; }
| LENGTH { $$ = SCTP_CHUNK_COMMON_LENGTH; }
;
@@ -5844,7 +6360,7 @@ rt4_hdr_expr : RT4 rt4_hdr_field close_scope_rt
;
rt4_hdr_field : LAST_ENT { $$ = RT4HDR_LASTENT; }
- | FLAGS close_scope_flags { $$ = RT4HDR_FLAGS; }
+ | FLAGS { $$ = RT4HDR_FLAGS; }
| TAG { $$ = RT4HDR_TAG; }
| SID '[' NUM ']'
{
@@ -5896,7 +6412,7 @@ exthdr_exists_expr : EXTHDR exthdr_key
desc = exthdr_find_proto($2);
/* Assume that NEXTHDR template is always
- * the fist one in list of templates.
+ * the first one in list of templates.
*/
$$ = exthdr_expr_alloc(&@$, desc, 1);
$$->exthdr.flags = NFT_EXTHDR_F_PRESENT;