diff options
Diffstat (limited to 'src/scanner.l')
-rw-r--r-- | src/scanner.l | 182 |
1 files changed, 145 insertions, 37 deletions
diff --git a/src/scanner.l b/src/scanner.l index 1371cd04..96c505bc 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> @@ -118,59 +121,58 @@ 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)? hex4 ([[:xdigit:]]{1,4}) +rfc4291_broader (((:{hex4}){2})|(:{ip4addr})) v680 (({hex4}:){7}{hex4}) -v670 ((:)((:{hex4}){7})) -v671 ((({hex4}:){1})((:{hex4}){6})) -v672 ((({hex4}:){2})((:{hex4}){5})) -v673 ((({hex4}:){3})((:{hex4}){4})) -v674 ((({hex4}:){4})((:{hex4}){3})) -v675 ((({hex4}:){5})((:{hex4}){2})) +v670 ((:)((:{hex4}){5}){rfc4291_broader}) +v671 ((({hex4}:){1})((:{hex4}){4}){rfc4291_broader}) +v672 ((({hex4}:){2})((:{hex4}){3}){rfc4291_broader}) +v673 ((({hex4}:){3})((:{hex4}){2}){rfc4291_broader}) +v674 ((({hex4}:){4})((:{hex4}){1}){rfc4291_broader}) +v675 ((({hex4}:){5}){rfc4291_broader}) v676 ((({hex4}:){6})(:{hex4}{1})) v677 ((({hex4}:){7})(:)) v67 ({v670}|{v671}|{v672}|{v673}|{v674}|{v675}|{v676}|{v677}) -v660 ((:)((:{hex4}){6})) -v661 ((({hex4}:){1})((:{hex4}){5})) -v662 ((({hex4}:){2})((:{hex4}){4})) -v663 ((({hex4}:){3})((:{hex4}){3})) -v664 ((({hex4}:){4})((:{hex4}){2})) +v660 ((:)((:{hex4}){4}){rfc4291_broader}) +v661 ((({hex4}:){1})((:{hex4}){3}){rfc4291_broader}) +v662 ((({hex4}:){2})((:{hex4}){2}){rfc4291_broader}) +v663 ((({hex4}:){3})((:{hex4}){1}){rfc4291_broader}) +v664 ((({hex4}:){4}){rfc4291_broader}) v665 ((({hex4}:){5})((:{hex4}){1})) v666 ((({hex4}:){6})(:)) v66 ({v660}|{v661}|{v662}|{v663}|{v664}|{v665}|{v666}) -v650 ((:)((:{hex4}){5})) -v651 ((({hex4}:){1})((:{hex4}){4})) -v652 ((({hex4}:){2})((:{hex4}){3})) -v653 ((({hex4}:){3})((:{hex4}){2})) +v650 ((:)((:{hex4}){3}){rfc4291_broader}) +v651 ((({hex4}:){1})((:{hex4}){2}){rfc4291_broader}) +v652 ((({hex4}:){2})((:{hex4}){1}){rfc4291_broader}) +v653 ((({hex4}:){3}){rfc4291_broader}) v654 ((({hex4}:){4})(:{hex4}{1})) v655 ((({hex4}:){5})(:)) v65 ({v650}|{v651}|{v652}|{v653}|{v654}|{v655}) -v640 ((:)((:{hex4}){4})) -v641 ((({hex4}:){1})((:{hex4}){3})) -v642 ((({hex4}:){2})((:{hex4}){2})) +v640 ((:)((:{hex4}){2}){rfc4291_broader}) +v641 ((({hex4}:){1})((:{hex4}){1}){rfc4291_broader}) +v642 ((({hex4}:){2}){rfc4291_broader}) v643 ((({hex4}:){3})((:{hex4}){1})) v644 ((({hex4}:){4})(:)) v64 ({v640}|{v641}|{v642}|{v643}|{v644}) -v630 ((:)((:{hex4}){3})) -v631 ((({hex4}:){1})((:{hex4}){2})) +v630 ((:)((:{hex4}){1}){rfc4291_broader}) +v631 ((({hex4}:){1}){rfc4291_broader}) v632 ((({hex4}:){2})((:{hex4}){1})) v633 ((({hex4}:){3})(:)) v63 ({v630}|{v631}|{v632}|{v633}) -v620 ((:)((:{hex4}){2})) -v620_rfc4291 ((:)(:{ip4addr})) +v620 ((:){rfc4291_broader}) v621 ((({hex4}:){1})((:{hex4}){1})) v622 ((({hex4}:){2})(:)) -v62_rfc4291 ((:)(:[fF]{4})(:{ip4addr})) -v62 ({v620}|{v621}|{v622}|{v62_rfc4291}|{v620_rfc4291}) +v62 ({v620}|{v621}|{v622}) v610 ((:)(:{hex4}{1})) v611 ((({hex4}:){1})(:)) v61 ({v610}|{v611}) @@ -201,10 +203,12 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr}) %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 @@ -214,6 +218,8 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr}) %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 @@ -357,6 +363,8 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr}) "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; } @@ -397,9 +405,15 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr}) <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; } @@ -431,10 +445,11 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr}) "quota" { scanner_push_start_cond(yyscanner, SCANSTATE_QUOTA); return QUOTA; } <SCANSTATE_QUOTA>{ - "used" { return USED; } "until" { return UNTIL; } } +<SCANSTATE_QUOTA,SCANSTATE_LAST>"used" { return USED; } + "hour" { return HOUR; } "day" { return DAY; } @@ -491,7 +506,7 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr}) } "ip" { scanner_push_start_cond(yyscanner, SCANSTATE_IP); return IP; } -<SCANSTATE_IP,SCANSTATE_IP6,SCANSTATE_EXPR_OSF>{ +<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>{ @@ -508,7 +523,7 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr}) <SCANSTATE_EXPR_OSF,SCANSTATE_IP>{ "ttl" { return TTL; } } -<SCANSTATE_CT,SCANSTATE_IP,SCANSTATE_META,SCANSTATE_TYPE>"protocol" { return PROTOCOL; } +<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; } } @@ -573,6 +588,8 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr}) "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; } @@ -619,6 +636,17 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr}) <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; } +} + +"vxlan" { return VXLAN; } +"vni" { return VNI; } + +"geneve" { return GENEVE; } + +"gre" { scanner_push_start_cond(yyscanner, SCANSTATE_GRE); return GRE; } +"gretap" { scanner_push_start_cond(yyscanner, SCANSTATE_GRE); return GRETAP; } "tcp" { scanner_push_start_cond(yyscanner, SCANSTATE_TCP); return TCP; } @@ -799,6 +827,8 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr}) "secmark" { scanner_push_start_cond(yyscanner, SCANSTATE_SECMARK); return SECMARK; } +"xt" { scanner_push_start_cond(yyscanner, SCANSTATE_XT); return XT; } + {addrstring} { yylval->string = xstrdup(yytext); return STRING; @@ -815,9 +845,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; @@ -825,6 +855,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; @@ -857,6 +900,9 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr}) {tab}+ {space}+ +{comment_line} { + reset_pos(yyget_extra(yyscanner), yylloc); + } {comment} <<EOF>> { @@ -928,9 +974,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; @@ -942,12 +1038,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: @@ -1008,7 +1116,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--) { @@ -1020,7 +1128,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; } @@ -1057,7 +1165,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) @@ -1152,8 +1260,8 @@ void *scanner_init(struct parser_state *state) 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) @@ -1175,7 +1283,7 @@ void scanner_destroy(struct nft_ctx *nft) struct parser_state *state = yyget_extra(nft->scanner); input_descriptor_list_destroy(state); - xfree(state->startcond_active); + free(state->startcond_active); yylex_destroy(nft->scanner); } |