diff options
Diffstat (limited to 'src/scanner.l')
-rw-r--r-- | src/scanner.l | 835 |
1 files changed, 594 insertions, 241 deletions
diff --git a/src/scanner.l b/src/scanner.l index 45699c85..e4d20e69 100644 --- a/src/scanner.l +++ b/src/scanner.l @@ -10,12 +10,15 @@ %{ +#include <nft.h> + #include <limits.h> #include <glob.h> #include <netinet/in.h> #include <arpa/inet.h> #include <linux/types.h> #include <linux/netfilter.h> +#include <sys/stat.h> #include <nftables.h> #include <erec.h> @@ -98,6 +101,8 @@ static void reset_pos(struct parser_state *state, struct location *loc) state->indesc->column = 1; } +static void scanner_push_start_cond(void *scanner, enum startcond_type type); + #define YY_USER_ACTION { \ update_pos(yyget_extra(yyscanner), yylloc, yyleng); \ update_offset(yyget_extra(yyscanner), yylloc, yyleng); \ @@ -116,12 +121,12 @@ digit [0-9] hexdigit [0-9a-fA-F] decstring {digit}+ hexstring 0[xX]{hexdigit}+ -numberstring ({decstring}|{hexstring}) letter [a-zA-Z] string ({letter}|[_.])({letter}|{digit}|[/\-_\.])* quotedstring \"[^"]*\" asteriskstring ({string}\*|{string}\\\*|\\\*|{string}\\\*{string}) comment #.*$ +comment_line ^[ \t]*#.*\n slash \/ timestring ([0-9]+d)?([0-9]+h)?([0-9]+m)?([0-9]+s)?([0-9]+ms)? @@ -193,6 +198,62 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr}) %option yylineno %option nodefault %option warn +%option stack +%s SCANSTATE_ARP +%s SCANSTATE_AT +%s SCANSTATE_CT +%s SCANSTATE_COUNTER +%s SCANSTATE_ETH +%s SCANSTATE_GRE +%s SCANSTATE_ICMP +%s SCANSTATE_IGMP +%s SCANSTATE_IP +%s SCANSTATE_IP6 +%s SCANSTATE_LAST +%s SCANSTATE_LIMIT +%s SCANSTATE_META +%s SCANSTATE_POLICY +%s SCANSTATE_QUOTA +%s SCANSTATE_SCTP +%s SCANSTATE_SECMARK +%s SCANSTATE_TCP +%s SCANSTATE_TYPE +%s SCANSTATE_VLAN +%s SCANSTATE_XT +%s SCANSTATE_CMD_DESTROY +%s SCANSTATE_CMD_EXPORT +%s SCANSTATE_CMD_IMPORT +%s SCANSTATE_CMD_LIST +%s SCANSTATE_CMD_MONITOR +%s SCANSTATE_CMD_RESET +%s SCANSTATE_EXPR_AH +%s SCANSTATE_EXPR_COMP +%s SCANSTATE_EXPR_DCCP +%s SCANSTATE_EXPR_DST +%s SCANSTATE_EXPR_ESP +%s SCANSTATE_EXPR_FIB +%s SCANSTATE_EXPR_FRAG +%s SCANSTATE_EXPR_HASH +%s SCANSTATE_EXPR_HBH +%s SCANSTATE_EXPR_IPSEC +%s SCANSTATE_EXPR_MH +%s SCANSTATE_EXPR_NUMGEN +%s SCANSTATE_EXPR_OSF +%s SCANSTATE_EXPR_QUEUE +%s SCANSTATE_EXPR_RT +%s SCANSTATE_EXPR_SCTP_CHUNK +%s SCANSTATE_EXPR_SOCKET +%s SCANSTATE_EXPR_TH +%s SCANSTATE_EXPR_UDP +%s SCANSTATE_EXPR_UDPLITE + +%s SCANSTATE_STMT_DUP +%s SCANSTATE_STMT_FWD +%s SCANSTATE_STMT_LOG +%s SCANSTATE_STMT_NAT +%s SCANSTATE_STMT_REJECT +%s SCANSTATE_STMT_SYNPROXY +%s SCANSTATE_STMT_TPROXY %% @@ -233,7 +294,7 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr}) "/" { return SLASH; } "-" { return DASH; } "*" { return ASTERISK; } -"@" { return AT; } +"@" { scanner_push_start_cond(yyscanner, SCANSTATE_AT); return AT; } "$" { return '$'; } "=" { return '='; } "vmap" { return VMAP; } @@ -247,29 +308,36 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr}) "describe" { return DESCRIBE; } +<SCANSTATE_CMD_LIST,SCANSTATE_CMD_MONITOR>{ + "chains" { return CHAINS; } + "sets" { return SETS; } + "tables" { return TABLES; } +} +<SCANSTATE_CMD_MONITOR>{ + "rules" { return RULES; } + "trace" { return TRACE; } +} "hook" { return HOOK; } "device" { return DEVICE; } "devices" { return DEVICES; } "table" { return TABLE; } -"tables" { return TABLES; } "chain" { return CHAIN; } -"chains" { return CHAINS; } "rule" { return RULE; } -"rules" { return RULES; } -"sets" { return SETS; } "set" { return SET; } "element" { return ELEMENT; } "map" { return MAP; } -"maps" { return MAPS; } "flowtable" { return FLOWTABLE; } "handle" { return HANDLE; } "ruleset" { return RULESET; } -"trace" { return TRACE; } - -"socket" { return SOCKET; } -"transparent" { return TRANSPARENT;} -"tproxy" { return TPROXY; } +"socket" { scanner_push_start_cond(yyscanner, SCANSTATE_EXPR_SOCKET); return SOCKET; } +<SCANSTATE_EXPR_SOCKET>{ + "transparent" { return TRANSPARENT; } + "wildcard" { return WILDCARD; } + "cgroupv2" { return CGROUPV2; } + "level" { return LEVEL; } +} +"tproxy" { scanner_push_start_cond(yyscanner, SCANSTATE_STMT_TPROXY); return TPROXY; } "accept" { return ACCEPT; } "drop" { return DROP; } @@ -277,7 +345,7 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr}) "jump" { return JUMP; } "goto" { return GOTO; } "return" { return RETURN; } -"to" { return TO; } +<SCANSTATE_EXPR_QUEUE,SCANSTATE_STMT_DUP,SCANSTATE_STMT_FWD,SCANSTATE_STMT_NAT,SCANSTATE_STMT_TPROXY,SCANSTATE_IP,SCANSTATE_IP6>"to" { return TO; } /* XXX: SCANSTATE_IP is a workaround */ "inet" { return INET; } "netdev" { return NETDEV; } @@ -289,13 +357,15 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr}) "insert" { return INSERT; } "delete" { return DELETE; } "get" { return GET; } -"list" { return LIST; } -"reset" { return RESET; } +"list" { scanner_push_start_cond(yyscanner, SCANSTATE_CMD_LIST); return LIST; } +"reset" { scanner_push_start_cond(yyscanner, SCANSTATE_CMD_RESET); return RESET; } "flush" { return FLUSH; } "rename" { return RENAME; } -"import" { return IMPORT; } -"export" { return EXPORT; } -"monitor" { return MONITOR; } +"import" { scanner_push_start_cond(yyscanner, SCANSTATE_CMD_IMPORT); return IMPORT; } +"export" { scanner_push_start_cond(yyscanner, SCANSTATE_CMD_EXPORT); return EXPORT; } +"monitor" { scanner_push_start_cond(yyscanner, SCANSTATE_CMD_MONITOR); return MONITOR; } +"destroy" { scanner_push_start_cond(yyscanner, SCANSTATE_CMD_DESTROY); return DESTROY; } + "position" { return POSITION; } "index" { return INDEX; } @@ -310,202 +380,342 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr}) "elements" { return ELEMENTS; } "expires" { return EXPIRES; } -"policy" { return POLICY; } +"policy" { scanner_push_start_cond(yyscanner, SCANSTATE_POLICY); return POLICY; } "size" { return SIZE; } -"performance" { return PERFORMANCE; } -"memory" { return MEMORY; } +<SCANSTATE_POLICY>{ + "performance" { return PERFORMANCE; } + "memory" { return MEMORY; } +} "flow" { return FLOW; } "offload" { return OFFLOAD; } "meter" { return METER; } -"meters" { return METERS; } - -"flowtables" { return FLOWTABLES; } - -"counter" { return COUNTER; } -"name" { return NAME; } -"packets" { return PACKETS; } -"bytes" { return BYTES; } -"avgpkt" { return AVGPKT; } - -"counters" { return COUNTERS; } -"quotas" { return QUOTAS; } -"limits" { return LIMITS; } -"synproxys" { return SYNPROXYS; } - -"log" { return LOG; } -"prefix" { return PREFIX; } -"group" { return GROUP; } -"snaplen" { return SNAPLEN; } -"queue-threshold" { return QUEUE_THRESHOLD; } -"level" { return LEVEL; } - -"queue" { return QUEUE;} -"num" { return QUEUENUM;} -"bypass" { return BYPASS;} -"fanout" { return FANOUT;} - -"limit" { return LIMIT; } -"rate" { return RATE; } -"burst" { return BURST; } -"until" { return UNTIL; } -"over" { return OVER; } - -"quota" { return QUOTA; } -"used" { return USED; } - -"nanosecond" { return NANOSECOND; } -"microsecond" { return MICROSECOND; } -"millisecond" { return MILLISECOND; } -"second" { return SECOND; } -"minute" { return MINUTE; } + +<SCANSTATE_CMD_LIST>{ + "meters" { return METERS; } + "flowtables" { return FLOWTABLES; } + "limits" { return LIMITS; } + "maps" { return MAPS; } + "secmarks" { return SECMARKS; } + "synproxys" { return SYNPROXYS; } + "hooks" { return HOOKS; } +} + +"counter" { scanner_push_start_cond(yyscanner, SCANSTATE_COUNTER); return COUNTER; } +<SCANSTATE_COUNTER,SCANSTATE_LIMIT,SCANSTATE_QUOTA,SCANSTATE_STMT_SYNPROXY,SCANSTATE_EXPR_OSF>"name" { return NAME; } +<SCANSTATE_COUNTER,SCANSTATE_CT,SCANSTATE_LIMIT>"packets" { return PACKETS; } +<SCANSTATE_COUNTER,SCANSTATE_CT,SCANSTATE_LIMIT,SCANSTATE_QUOTA>"bytes" { return BYTES; } + +"last" { scanner_push_start_cond(yyscanner, SCANSTATE_LAST); return LAST; } +<SCANSTATE_LAST>{ + "never" { return NEVER; } +} + +<SCANSTATE_CMD_LIST,SCANSTATE_CMD_RESET>{ + "counters" { return COUNTERS; } + "quotas" { return QUOTAS; } + "rules" { return RULES; } +} + +"log" { scanner_push_start_cond(yyscanner, SCANSTATE_STMT_LOG); return LOG; } +<SCANSTATE_STMT_LOG,SCANSTATE_STMT_NAT,SCANSTATE_IP,SCANSTATE_IP6>"prefix" { return PREFIX; } +<SCANSTATE_STMT_LOG>{ + "snaplen" { return SNAPLEN; } + "queue-threshold" { return QUEUE_THRESHOLD; } + "level" { return LEVEL; } + "group" { return GROUP; } +} + +"queue" { scanner_push_start_cond(yyscanner, SCANSTATE_EXPR_QUEUE); return QUEUE;} +<SCANSTATE_EXPR_QUEUE>{ + "num" { return QUEUENUM;} + "bypass" { return BYPASS;} + "fanout" { return FANOUT;} +} +"limit" { scanner_push_start_cond(yyscanner, SCANSTATE_LIMIT); return LIMIT; } +<SCANSTATE_LIMIT>{ + "rate" { return RATE; } + "burst" { return BURST; } + + /* time_unit */ + "second" { return SECOND; } + "minute" { return MINUTE; } + "week" { return WEEK; } +} +<SCANSTATE_CT,SCANSTATE_LIMIT,SCANSTATE_QUOTA>"over" { return OVER; } + +"quota" { scanner_push_start_cond(yyscanner, SCANSTATE_QUOTA); return QUOTA; } +<SCANSTATE_QUOTA>{ + "until" { return UNTIL; } +} + +<SCANSTATE_QUOTA,SCANSTATE_LAST>"used" { return USED; } + "hour" { return HOUR; } "day" { return DAY; } -"week" { return WEEK; } -"reject" { return _REJECT; } -"with" { return WITH; } -"icmpx" { return ICMPX; } +"reject" { scanner_push_start_cond(yyscanner, SCANSTATE_STMT_REJECT); return _REJECT; } +<SCANSTATE_STMT_REJECT>{ + "with" { return WITH; } + "icmpx" { return ICMPX; } +} -"snat" { return SNAT; } -"dnat" { return DNAT; } -"masquerade" { return MASQUERADE; } -"redirect" { return REDIRECT; } +"snat" { scanner_push_start_cond(yyscanner, SCANSTATE_STMT_NAT); return SNAT; } +"dnat" { scanner_push_start_cond(yyscanner, SCANSTATE_STMT_NAT); return DNAT; } +"masquerade" { scanner_push_start_cond(yyscanner, SCANSTATE_STMT_NAT); return MASQUERADE; } +"redirect" { scanner_push_start_cond(yyscanner, SCANSTATE_STMT_NAT); return REDIRECT; } "random" { return RANDOM; } -"fully-random" { return FULLY_RANDOM; } -"persistent" { return PERSISTENT; } +<SCANSTATE_STMT_NAT>{ + "fully-random" { return FULLY_RANDOM; } + "persistent" { return PERSISTENT; } + "port" { return PORT; } +} -"ll" { return LL_HDR; } -"nh" { return NETWORK_HDR; } -"th" { return TRANSPORT_HDR; } +<SCANSTATE_AT>{ + "ll" { return LL_HDR; } + "nh" { return NETWORK_HDR; } +} +"th" { scanner_push_start_cond(yyscanner, SCANSTATE_EXPR_TH); return TRANSPORT_HDR; } "bridge" { return BRIDGE; } -"ether" { return ETHER; } -"saddr" { return SADDR; } -"daddr" { return DADDR; } -"type" { return TYPE; } +"ether" { scanner_push_start_cond(yyscanner, SCANSTATE_ETH); return ETHER; } +<SCANSTATE_ARP,SCANSTATE_CT,SCANSTATE_ETH,SCANSTATE_IP,SCANSTATE_IP6,SCANSTATE_EXPR_FIB,SCANSTATE_EXPR_IPSEC>{ + "saddr" { return SADDR; } + "daddr" { return DADDR; } +} +"type" { scanner_push_start_cond(yyscanner, SCANSTATE_TYPE); return TYPE; } "typeof" { return TYPEOF; } -"vlan" { return VLAN; } -"id" { return ID; } -"cfi" { return CFI; } -"pcp" { return PCP; } - -"arp" { return ARP; } -"htype" { return HTYPE; } -"ptype" { return PTYPE; } -"hlen" { return HLEN; } -"plen" { return PLEN; } -"operation" { return OPERATION; } - -"ip" { return IP; } -"version" { return HDRVERSION; } -"hdrlength" { return HDRLENGTH; } -"dscp" { return DSCP; } +"vlan" { scanner_push_start_cond(yyscanner, SCANSTATE_VLAN); return VLAN; } +<SCANSTATE_CT,SCANSTATE_EXPR_FRAG,SCANSTATE_VLAN,SCANSTATE_IP,SCANSTATE_ICMP>"id" { return ID; } +<SCANSTATE_VLAN>{ + "cfi" { return CFI; } + "dei" { return DEI; } + "pcp" { return PCP; } +} +"8021ad" { yylval->string = xstrdup(yytext); return STRING; } +"8021q" { yylval->string = xstrdup(yytext); return STRING; } + +"arp" { scanner_push_start_cond(yyscanner, SCANSTATE_ARP); return ARP; } +<SCANSTATE_ARP>{ + "htype" { return HTYPE; } + "ptype" { return PTYPE; } + "hlen" { return HLEN; } + "plen" { return PLEN; } + "operation" { return OPERATION; } +} + +"ip" { scanner_push_start_cond(yyscanner, SCANSTATE_IP); return IP; } +<SCANSTATE_IP,SCANSTATE_IP6,SCANSTATE_EXPR_OSF,SCANSTATE_GRE>{ + "version" { return HDRVERSION; } +} +<SCANSTATE_EXPR_AH,SCANSTATE_EXPR_DST,SCANSTATE_EXPR_HBH,SCANSTATE_EXPR_MH,SCANSTATE_EXPR_RT,SCANSTATE_IP>{ + "hdrlength" { return HDRLENGTH; } +} +<SCANSTATE_IP,SCANSTATE_IP6,SCANSTATE_TYPE>{ + "dscp" { return DSCP; } +} "ecn" { return ECN; } -"length" { return LENGTH; } -"frag-off" { return FRAG_OFF; } -"ttl" { return TTL; } -"protocol" { return PROTOCOL; } -"checksum" { return CHECKSUM; } - -"lsrr" { return LSRR; } -"rr" { return RR; } -"ssrr" { return SSRR; } -"ra" { return RA; } - -"value" { return VALUE; } -"ptr" { return PTR; } - -"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; } -"time" { return TIME; } +<SCANSTATE_EXPR_UDP,SCANSTATE_IP,SCANSTATE_IP6,SCANSTATE_META,SCANSTATE_TCP,SCANSTATE_SCTP,SCANSTATE_EXPR_SCTP_CHUNK>"length" { return LENGTH; } +<SCANSTATE_EXPR_FRAG,SCANSTATE_IP>{ + "frag-off" { return FRAG_OFF; } +} +<SCANSTATE_EXPR_OSF,SCANSTATE_IP>{ + "ttl" { return TTL; } +} +<SCANSTATE_CT,SCANSTATE_IP,SCANSTATE_META,SCANSTATE_TYPE,SCANSTATE_GRE>"protocol" { return PROTOCOL; } +<SCANSTATE_EXPR_MH,SCANSTATE_EXPR_UDP,SCANSTATE_EXPR_UDPLITE,SCANSTATE_ICMP,SCANSTATE_IGMP,SCANSTATE_IP,SCANSTATE_SCTP,SCANSTATE_TCP>{ + "checksum" { return CHECKSUM; } +} -"kind" { return KIND; } -"count" { return COUNT; } -"left" { return LEFT; } -"right" { return RIGHT; } -"tsval" { return TSVAL; } -"tsecr" { return TSECR; } +<SCANSTATE_IP>{ + "lsrr" { return LSRR; } + "rr" { return RR; } + "ssrr" { return SSRR; } + "ra" { return RA; } -"icmp" { return ICMP; } -"code" { return CODE; } -"sequence" { return SEQUENCE; } -"gateway" { return GATEWAY; } -"mtu" { return MTU; } + "ptr" { return PTR; } + "value" { return VALUE; } -"igmp" { return IGMP; } -"mrt" { return MRT; } + "option" { return OPTION; } + "options" { return OPTIONS; } +} -"ip6" { return IP6; } -"priority" { return PRIORITY; } -"flowlabel" { return FLOWLABEL; } -"nexthdr" { return NEXTHDR; } -"hoplimit" { return HOPLIMIT; } +<SCANSTATE_TCP>{ + /* tcp header fields */ + "ackseq" { return ACKSEQ; } + "doff" { return DOFF; } + "window" { return WINDOW; } + "urgptr" { return URGPTR; } + + /* tcp option types */ + "echo" { return ECHO; } + "eol" { return EOL; } + "maxseg" { return MSS; } + "mss" { return MSS; } + "nop" { return NOP; } + "noop" { return NOP; } + "sack" { return SACK; } + "sack0" { return SACK0; } + "sack1" { return SACK1; } + "sack2" { return SACK2; } + "sack3" { return SACK3; } + "sack-permitted" { return SACK_PERM; } + "sack-perm" { return SACK_PERM; } + "timestamp" { return TIMESTAMP; } + "fastopen" { return FASTOPEN; } + "mptcp" { return MPTCP; } + "md5sig" { return MD5SIG; } + + /* tcp option fields */ + "left" { return LEFT; } + "right" { return RIGHT; } + "count" { return COUNT; } + "tsval" { return TSVAL; } + "tsecr" { return TSECR; } + "subtype" { return SUBTYPE; } + + "options" { return OPTIONS; } + "option" { return OPTION; } +} +"time" { return TIME; } -"icmpv6" { return ICMP6; } -"param-problem" { return PPTR; } -"max-delay" { return MAXDELAY; } +"icmp" { scanner_push_start_cond(yyscanner, SCANSTATE_ICMP); return ICMP; } +"icmpv6" { scanner_push_start_cond(yyscanner, SCANSTATE_ICMP); return ICMP6; } +<SCANSTATE_ICMP>{ + "gateway" { return GATEWAY; } + "code" { return CODE; } + "param-problem" { return PPTR; } + "max-delay" { return MAXDELAY; } + "mtu" { return MTU; } + "taddr" { return TADDR; } + "daddr" { return DADDR; } +} +<SCANSTATE_EXPR_AH,SCANSTATE_EXPR_ESP,SCANSTATE_ICMP,SCANSTATE_TCP>{ + "sequence" { return SEQUENCE; } +} + +"igmp" { scanner_push_start_cond(yyscanner, SCANSTATE_IGMP); return IGMP; } +<SCANSTATE_IGMP>{ + "mrt" { return MRT; } + "group" { return GROUP; } +} + +"ip6" { scanner_push_start_cond(yyscanner, SCANSTATE_IP6); return IP6; } +"priority" { return PRIORITY; } +<SCANSTATE_IP6>{ + "flowlabel" { return FLOWLABEL; } + "hoplimit" { return HOPLIMIT; } +} +<SCANSTATE_EXPR_AH,SCANSTATE_EXPR_COMP,SCANSTATE_EXPR_DST,SCANSTATE_EXPR_FRAG,SCANSTATE_EXPR_HBH,SCANSTATE_EXPR_MH,SCANSTATE_EXPR_RT,SCANSTATE_IP6>{ + "nexthdr" { return NEXTHDR; } +} -"ah" { return AH; } -"reserved" { return RESERVED; } -"spi" { return SPI; } +"ah" { scanner_push_start_cond(yyscanner, SCANSTATE_EXPR_AH); return AH; } +<SCANSTATE_EXPR_AH,SCANSTATE_EXPR_FRAG,SCANSTATE_EXPR_MH,SCANSTATE_TCP>{ + "reserved" { return RESERVED; } +} +<SCANSTATE_EXPR_AH,SCANSTATE_EXPR_ESP,SCANSTATE_EXPR_IPSEC>"spi" { return SPI; } -"esp" { return ESP; } +"esp" { scanner_push_start_cond(yyscanner, SCANSTATE_EXPR_ESP); return ESP; } -"comp" { return COMP; } +"comp" { scanner_push_start_cond(yyscanner, SCANSTATE_EXPR_COMP); return COMP; } +<SCANSTATE_EXPR_COMP>{ + "cpi" { return CPI; } +} "flags" { return FLAGS; } -"cpi" { return CPI; } -"udp" { return UDP; } -"udplite" { return UDPLITE; } -"sport" { return SPORT; } -"dport" { return DPORT; } -"port" { return PORT; } +"udp" { scanner_push_start_cond(yyscanner, SCANSTATE_EXPR_UDP); return UDP; } +"udplite" { scanner_push_start_cond(yyscanner, SCANSTATE_EXPR_UDPLITE); return UDPLITE; } +<SCANSTATE_EXPR_UDPLITE>{ + "csumcov" { return CSUMCOV; } +} +<SCANSTATE_EXPR_DCCP,SCANSTATE_SCTP,SCANSTATE_TCP,SCANSTATE_EXPR_TH,SCANSTATE_EXPR_UDP,SCANSTATE_EXPR_UDPLITE>{ + "sport" { return SPORT; } +} +<SCANSTATE_CT,SCANSTATE_EXPR_DCCP,SCANSTATE_SCTP,SCANSTATE_TCP,SCANSTATE_EXPR_TH,SCANSTATE_EXPR_UDP,SCANSTATE_EXPR_UDPLITE>{ + "dport" { return DPORT; } +} +<SCANSTATE_EXPR_DCCP>{ + "option" { return OPTION; } +} -"tcp" { return TCP; } -"ackseq" { return ACKSEQ; } -"doff" { return DOFF; } -"window" { return WINDOW; } -"urgptr" { return URGPTR; } -"option" { return OPTION; } +"vxlan" { return VXLAN; } +"vni" { return VNI; } -"dccp" { return DCCP; } +"geneve" { return GENEVE; } -"sctp" { return SCTP; } -"vtag" { return VTAG; } +"gre" { scanner_push_start_cond(yyscanner, SCANSTATE_GRE); return GRE; } +"gretap" { scanner_push_start_cond(yyscanner, SCANSTATE_GRE); return GRETAP; } -"rt" { return RT; } -"rt0" { return RT0; } -"rt2" { return RT2; } -"srh" { return RT4; } -"seg-left" { return SEG_LEFT; } -"addr" { return ADDR; } -"last-entry" { return LAST_ENT; } -"tag" { return TAG; } -"sid" { return SID; } +"tcp" { scanner_push_start_cond(yyscanner, SCANSTATE_TCP); return TCP; } -"hbh" { return HBH; } +"dccp" { scanner_push_start_cond(yyscanner, SCANSTATE_EXPR_DCCP); return DCCP; } -"frag" { return FRAG; } -"reserved2" { return RESERVED2; } -"more-fragments" { return MORE_FRAGMENTS; } +"sctp" { scanner_push_start_cond(yyscanner, SCANSTATE_SCTP); return SCTP; } + +<SCANSTATE_SCTP>{ + "chunk" { scanner_push_start_cond(yyscanner, SCANSTATE_EXPR_SCTP_CHUNK); return CHUNK; } + "vtag" { return VTAG; } +} + +<SCANSTATE_EXPR_SCTP_CHUNK>{ + "data" { return DATA; } + "init" { return INIT; } + "init-ack" { return INIT_ACK; } + "heartbeat" { return HEARTBEAT; } + "heartbeat-ack" { return HEARTBEAT_ACK; } + "abort" { return ABORT; } + "shutdown" { return SHUTDOWN; } + "shutdown-ack" { return SHUTDOWN_ACK; } + "error" { return ERROR; } + "cookie-echo" { return COOKIE_ECHO; } + "cookie-ack" { return COOKIE_ACK; } + "ecne" { return ECNE; } + "cwr" { return CWR; } + "shutdown-complete" { return SHUTDOWN_COMPLETE; } + "asconf-ack" { return ASCONF_ACK; } + "forward-tsn" { return FORWARD_TSN; } + "asconf" { return ASCONF; } + + "tsn" { return TSN; } + "sack" { return SACK; } + "stream" { return STREAM; } + "ssn" { return SSN; } + "ppid" { return PPID; } + "init-tag" { return INIT_TAG; } + "a-rwnd" { return A_RWND; } + "num-outbound-streams" { return NUM_OSTREAMS; } + "num-inbound-streams" { return NUM_ISTREAMS; } + "initial-tsn" { return INIT_TSN; } + "cum-tsn-ack" { return CUM_TSN_ACK; } + "num-gap-ack-blocks" { return NUM_GACK_BLOCKS; } + "num-dup-tsns" { return NUM_DUP_TSNS; } + "lowest-tsn" { return LOWEST_TSN; } + "seqno" { return SEQNO; } + "new-cum-tsn" { return NEW_CUM_TSN; } +} -"dst" { return DST; } +"rt" { scanner_push_start_cond(yyscanner, SCANSTATE_EXPR_RT); return RT; } +"rt0" { scanner_push_start_cond(yyscanner, SCANSTATE_EXPR_RT); return RT0; } +"rt2" { scanner_push_start_cond(yyscanner, SCANSTATE_EXPR_RT); return RT2; } +"srh" { scanner_push_start_cond(yyscanner, SCANSTATE_EXPR_RT); return RT4; } +<SCANSTATE_EXPR_RT,SCANSTATE_STMT_NAT,SCANSTATE_IP,SCANSTATE_IP6>"addr" { return ADDR; } -"mh" { return MH; } +"hbh" { scanner_push_start_cond(yyscanner, SCANSTATE_EXPR_HBH); return HBH; } -"meta" { return META; } +"frag" { scanner_push_start_cond(yyscanner, SCANSTATE_EXPR_FRAG); return FRAG; } +<SCANSTATE_EXPR_FRAG>{ + "reserved2" { return RESERVED2; } + "more-fragments" { return MORE_FRAGMENTS; } +} + +"dst" { scanner_push_start_cond(yyscanner, SCANSTATE_EXPR_DST); return DST; } + +"mh" { scanner_push_start_cond(yyscanner, SCANSTATE_EXPR_MH); return MH; } + +"meta" { scanner_push_start_cond(yyscanner, SCANSTATE_META); return META; } "mark" { return MARK; } "iif" { return IIF; } "iifname" { return IIFNAME; } @@ -527,73 +737,98 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr}) "oifgroup" { return OIFGROUP; } "cgroup" { return CGROUP; } -"classid" { return CLASSID; } -"nexthop" { return NEXTHOP; } - -"ct" { return CT; } -"l3proto" { return L3PROTOCOL; } -"proto-src" { return PROTO_SRC; } -"proto-dst" { return PROTO_DST; } -"zone" { return ZONE; } -"original" { return ORIGINAL; } -"reply" { return REPLY; } -"direction" { return DIRECTION; } -"event" { return EVENT; } -"expectation" { return EXPECTATION; } -"expiration" { return EXPIRATION; } -"helper" { return HELPER; } -"helpers" { return HELPERS; } -"label" { return LABEL; } -"state" { return STATE; } -"status" { return STATUS; } - -"numgen" { return NUMGEN; } -"inc" { return INC; } -"mod" { return MOD; } -"offset" { return OFFSET; } - -"jhash" { return JHASH; } -"symhash" { return SYMHASH; } -"seed" { return SEED; } - -"dup" { return DUP; } -"fwd" { return FWD; } - -"fib" { return FIB; } - -"osf" { return OSF; } - -"synproxy" { return SYNPROXY; } -"mss" { return MSS; } -"wscale" { return WSCALE; } -"sack-perm" { return SACKPERM; } +<SCANSTATE_EXPR_RT>{ + "nexthop" { return NEXTHOP; } + "seg-left" { return SEG_LEFT; } + "mtu" { return MTU; } + "last-entry" { return LAST_ENT; } + "tag" { return TAG; } + "sid" { return SID; } +} +<SCANSTATE_EXPR_RT,SCANSTATE_TYPE>{ + "classid" { return CLASSID; } +} + +"ct" { scanner_push_start_cond(yyscanner, SCANSTATE_CT); return CT; } +<SCANSTATE_CT>{ + "avgpkt" { return AVGPKT; } + "l3proto" { return L3PROTOCOL; } + "proto-src" { return PROTO_SRC; } + "proto-dst" { return PROTO_DST; } + "zone" { return ZONE; } + "original" { return ORIGINAL; } + "reply" { return REPLY; } + "direction" { return DIRECTION; } + "event" { return EVENT; } + "expectation" { return EXPECTATION; } + "expiration" { return EXPIRATION; } + "helper" { return HELPER; } + "helpers" { return HELPERS; } + "label" { return LABEL; } + "state" { return STATE; } + "status" { return STATUS; } + "count" { return COUNT; } +} + +"numgen" { scanner_push_start_cond(yyscanner, SCANSTATE_EXPR_NUMGEN); return NUMGEN; } +<SCANSTATE_EXPR_NUMGEN>{ + "inc" { return INC; } +} + +"jhash" { scanner_push_start_cond(yyscanner, SCANSTATE_EXPR_HASH); return JHASH; } +"symhash" { scanner_push_start_cond(yyscanner, SCANSTATE_EXPR_HASH); return SYMHASH; } + +<SCANSTATE_EXPR_HASH>{ + "seed" { return SEED; } +} +<SCANSTATE_EXPR_HASH,SCANSTATE_EXPR_NUMGEN>{ + "mod" { return MOD; } + "offset" { return OFFSET; } +} +"dup" { scanner_push_start_cond(yyscanner, SCANSTATE_STMT_DUP); return DUP; } +"fwd" { scanner_push_start_cond(yyscanner, SCANSTATE_STMT_FWD); return FWD; } + +"fib" { scanner_push_start_cond(yyscanner, SCANSTATE_EXPR_FIB); return FIB; } + +"osf" { scanner_push_start_cond(yyscanner, SCANSTATE_EXPR_OSF); return OSF; } + +"synproxy" { scanner_push_start_cond(yyscanner, SCANSTATE_STMT_SYNPROXY); return SYNPROXY; } +<SCANSTATE_STMT_SYNPROXY>{ + "wscale" { return WSCALE; } + "maxseg" { return MSS; } + "mss" { return MSS; } + "timestamp" { return TIMESTAMP; } + "sack-permitted" { return SACK_PERM; } + "sack-perm" { return SACK_PERM; } +} "notrack" { return NOTRACK; } -"options" { return OPTIONS; } "all" { return ALL; } -"xml" { return XML; } -"json" { return JSON; } -"vm" { return VM; } +<SCANSTATE_CMD_EXPORT,SCANSTATE_CMD_IMPORT,SCANSTATE_CMD_MONITOR>{ + "xml" { return XML; } + "json" { return JSON; } + "vm" { return VM; } +} "exists" { return EXISTS; } "missing" { return MISSING; } "exthdr" { return EXTHDR; } -"ipsec" { return IPSEC; } -"mode" { return MODE; } -"reqid" { return REQID; } -"spnum" { return SPNUM; } -"transport" { return TRANSPORT; } -"tunnel" { return TUNNEL; } +"ipsec" { scanner_push_start_cond(yyscanner, SCANSTATE_EXPR_IPSEC); return IPSEC; } +<SCANSTATE_EXPR_IPSEC>{ + "reqid" { return REQID; } + "spnum" { return SPNUM; } + + "in" { return IN; } + "out" { return OUT; } +} -"in" { return IN; } -"out" { return OUT; } +"secmark" { scanner_push_start_cond(yyscanner, SCANSTATE_SECMARK); return SECMARK; } -"secmark" { return SECMARK; } -"secmarks" { return SECMARKS; } +"xt" { scanner_push_start_cond(yyscanner, SCANSTATE_XT); return XT; } {addrstring} { yylval->string = xstrdup(yytext); @@ -611,9 +846,9 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr}) return STRING; } -{numberstring} { +{hexstring} { errno = 0; - yylval->val = strtoull(yytext, NULL, 0); + yylval->val = strtoull(yytext, NULL, 16); if (errno != 0) { yylval->string = xstrdup(yytext); return STRING; @@ -621,6 +856,19 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr}) return NUM; } +{decstring} { + int base = yytext[0] == '0' ? 8 : 10; + char *end; + + errno = 0; + yylval->val = strtoull(yytext, &end, base); + if (errno != 0 || *end) { + yylval->string = xstrdup(yytext); + return STRING; + } + return NUM; + } + {classid}/[ \t\n:\-},] { yylval->string = xstrdup(yytext); return STRING; @@ -653,6 +901,9 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr}) {tab}+ {space}+ +{comment_line} { + reset_pos(yyget_extra(yyscanner), yylloc); + } {comment} <<EOF>> { @@ -724,9 +975,59 @@ static void scanner_push_file(struct nft_ctx *nft, void *scanner, scanner_push_indesc(state, indesc); } +enum nft_include_type { + NFT_INCLUDE, + NFT_CMDLINE, +}; + +static bool __is_useable(unsigned int type, enum nft_include_type t) +{ + type &= S_IFMT; + switch (type) { + case S_IFREG: return true; + case S_IFIFO: + return t == NFT_CMDLINE; /* disallow include /path/to/fifo */ + default: + break; + } + + return false; +} + +/* need to use stat() to, fopen() will block for named fifos */ +static bool filename_is_useable(const char *name) +{ + struct stat sb; + int err; + + err = stat(name, &sb); + if (err) + return false; + + return __is_useable(sb.st_mode, NFT_INCLUDE); +} + +static bool fp_is_useable(FILE *fp, enum nft_include_type t) +{ + int fd = fileno(fp); + struct stat sb; + int err; + + if (fd < 0) + return false; + + err = fstat(fd, &sb); + if (err < 0) + return false; + + return __is_useable(sb.st_mode, t); +} + static int include_file(struct nft_ctx *nft, void *scanner, const char *filename, const struct location *loc, - const struct input_descriptor *parent_indesc) + const struct input_descriptor *parent_indesc, + enum nft_include_type includetype) + { struct parser_state *state = yyget_extra(scanner); struct error_record *erec; @@ -738,12 +1039,24 @@ static int include_file(struct nft_ctx *nft, void *scanner, goto err; } + if (includetype == NFT_INCLUDE && !filename_is_useable(filename)) { + erec = error(loc, "Not a regular file: \"%s\"\n", filename); + goto err; + } + f = fopen(filename, "r"); if (f == NULL) { erec = error(loc, "Could not open file \"%s\": %s\n", filename, strerror(errno)); goto err; } + + if (!fp_is_useable(f, includetype)) { + fclose(f); + erec = error(loc, "Not a regular file: \"%s\"\n", filename); + goto err; + } + scanner_push_file(nft, scanner, f, filename, loc, parent_indesc); return 0; err: @@ -804,7 +1117,7 @@ static int include_glob(struct nft_ctx *nft, void *scanner, const char *pattern, ret = glob(pattern, flags, NULL, &glob_data); if (ret == 0) { char *path; - int len; + size_t len; /* reverse alphabetical order due to stack */ for (i = glob_data.gl_pathc; i > 0; i--) { @@ -816,7 +1129,7 @@ static int include_glob(struct nft_ctx *nft, void *scanner, const char *pattern, if (len == 0 || path[len - 1] == '/') continue; - ret = include_file(nft, scanner, path, loc, indesc); + ret = include_file(nft, scanner, path, loc, indesc, NFT_INCLUDE); if (ret != 0) goto err; } @@ -853,7 +1166,7 @@ err: int scanner_read_file(struct nft_ctx *nft, const char *filename, const struct location *loc) { - return include_file(nft, nft->scanner, filename, loc, NULL); + return include_file(nft, nft->scanner, filename, loc, NULL, NFT_CMDLINE); } static bool search_in_include_path(const char *filename) @@ -925,7 +1238,7 @@ void scanner_push_buffer(void *scanner, const struct input_descriptor *indesc, new_indesc = xzalloc(sizeof(struct input_descriptor)); memcpy(new_indesc, indesc, sizeof(*new_indesc)); new_indesc->data = buffer; - new_indesc->name = NULL; + new_indesc->name = xstrdup(indesc->name); scanner_push_indesc(state, new_indesc); b = yy_scan_string(buffer, scanner); @@ -940,14 +1253,16 @@ void *scanner_init(struct parser_state *state) yylex_init_extra(state, &scanner); yyset_out(NULL, scanner); + state->startcond_active = xzalloc_array(__SC_MAX, + sizeof(*state->startcond_active)); return scanner; } static void input_descriptor_destroy(const struct input_descriptor *indesc) { if (indesc->name) - xfree(indesc->name); - xfree(indesc); + free_const(indesc->name); + free_const(indesc); } static void input_descriptor_list_destroy(struct parser_state *state) @@ -969,5 +1284,43 @@ void scanner_destroy(struct nft_ctx *nft) struct parser_state *state = yyget_extra(nft->scanner); input_descriptor_list_destroy(state); + free(state->startcond_active); + yylex_destroy(nft->scanner); } + +static void scanner_push_start_cond(void *scanner, enum startcond_type type) +{ + struct parser_state *state = yyget_extra(scanner); + + state->startcond_type = type; + state->startcond_active[type]++; + + yy_push_state((int)type, scanner); +} + +void scanner_pop_start_cond(void *scanner, enum startcond_type t) +{ + struct parser_state *state = yyget_extra(scanner); + + state->startcond_active[t]--; + + if (state->startcond_type != t) { + state->flex_state_pop++; + return; /* Can't pop just yet! */ + } + + while (state->flex_state_pop) { + state->flex_state_pop--; + state->startcond_type = yy_top_state(scanner); + yy_pop_state(scanner); + + t = state->startcond_type; + if (state->startcond_active[t]) + return; + } + + state->startcond_type = yy_top_state(scanner); + + yy_pop_state(scanner); +} |