Blame src/scanner.l

Packit c5a612
/*
Packit c5a612
 * Copyright (c) 2007-2008 Patrick McHardy <kaber@trash.net>
Packit c5a612
 *
Packit c5a612
 * This program is free software; you can redistribute it and/or modify
Packit c5a612
 * it under the terms of the GNU General Public License version 2 as
Packit c5a612
 * published by the Free Software Foundation.
Packit c5a612
 *
Packit c5a612
 * Development of this code funded by Astaro AG (http://www.astaro.com/)
Packit c5a612
 */
Packit c5a612
Packit c5a612
%{
Packit c5a612
Packit c5a612
#include <limits.h>
Packit c5a612
#include <glob.h>
Packit c5a612
#include <netinet/in.h>
Packit c5a612
#include <arpa/inet.h>
Packit c5a612
#include <linux/types.h>
Packit c5a612
#include <linux/netfilter.h>
Packit c5a612
Packit c5a612
#include <nftables.h>
Packit c5a612
#include <erec.h>
Packit c5a612
#include <rule.h>
Packit c5a612
#include <parser.h>
Packit c5a612
#include "parser_bison.h"
Packit c5a612
Packit c5a612
#define YY_NO_INPUT
Packit c5a612
Packit c5a612
/*
Packit c5a612
 * Work around flex behaviour when reaching the end of buffer: normally, flex
Packit c5a612
 * regexes are greedy, when reaching the end of buffer however it tries to
Packit c5a612
 * match whatever is left in the buffer and only backs up in case it doesn't
Packit c5a612
 * match *any* pattern. Since we accept unquoted strings, this means any partial
Packit c5a612
 * token will be recognized as string.
Packit c5a612
 *
Packit c5a612
 * Make sure to only pass input to flex linewise to avoid this.
Packit c5a612
 */
Packit c5a612
#define YY_INPUT(buf,result,max_size)						\
Packit c5a612
{										\
Packit c5a612
	result = 0;								\
Packit c5a612
	errno = 0;								\
Packit c5a612
										\
Packit c5a612
	while (result < max_size) {						\
Packit c5a612
		int chr = fgetc(yyin);						\
Packit c5a612
										\
Packit c5a612
		if (chr != EOF) {						\
Packit c5a612
			buf[result++] = chr;					\
Packit c5a612
			if (chr == '\n' || chr == ' ')				\
Packit c5a612
				break;						\
Packit c5a612
			continue;						\
Packit c5a612
		}								\
Packit c5a612
										\
Packit c5a612
		if (ferror(yyin)) {						\
Packit c5a612
			if (errno != EINTR) {					\
Packit c5a612
				YY_FATAL_ERROR("input in flex scanner failed");	\
Packit c5a612
				break;						\
Packit c5a612
			}							\
Packit c5a612
			errno = 0;						\
Packit c5a612
			clearerr(yyin);						\
Packit c5a612
		}								\
Packit c5a612
		break;								\
Packit c5a612
	}									\
Packit c5a612
}
Packit c5a612
Packit c5a612
static void scanner_pop_buffer(yyscan_t scanner);
Packit c5a612
Packit c5a612
Packit c5a612
static void init_pos(struct input_descriptor *indesc)
Packit c5a612
{
Packit c5a612
	indesc->lineno		= 1;
Packit c5a612
	indesc->column		= 1;
Packit c5a612
	indesc->token_offset	= 0;
Packit c5a612
	indesc->line_offset 	= 0;
Packit c5a612
}
Packit c5a612
Packit c5a612
static void update_pos(struct parser_state *state, struct location *loc,
Packit c5a612
		       int len)
Packit c5a612
{
Packit c5a612
	loc->indesc			= state->indesc;
Packit c5a612
	loc->first_line			= state->indesc->lineno;
Packit c5a612
	loc->last_line			= state->indesc->lineno;
Packit c5a612
	loc->first_column		= state->indesc->column;
Packit c5a612
	loc->last_column		= state->indesc->column + len - 1;
Packit c5a612
	state->indesc->column		+= len;
Packit c5a612
}
Packit c5a612
Packit c5a612
static void update_offset(struct parser_state *state, struct location *loc,
Packit c5a612
			  unsigned int len)
Packit c5a612
{
Packit c5a612
	state->indesc->token_offset	+= len;
Packit c5a612
	loc->token_offset		= state->indesc->token_offset;
Packit c5a612
	loc->line_offset		= state->indesc->line_offset;
Packit c5a612
}
Packit c5a612
Packit c5a612
static void reset_pos(struct parser_state *state, struct location *loc)
Packit c5a612
{
Packit c5a612
	state->indesc->line_offset	= state->indesc->token_offset;
Packit c5a612
	state->indesc->lineno		+= 1;
Packit c5a612
	state->indesc->column		= 1;
Packit c5a612
}
Packit c5a612
Packit c5a612
#define YY_USER_ACTION {					\
Packit c5a612
	update_pos(yyget_extra(yyscanner), yylloc, yyleng);	\
Packit c5a612
	update_offset(yyget_extra(yyscanner), yylloc, yyleng);	\
Packit c5a612
}
Packit c5a612
Packit c5a612
/* avoid warnings with -Wmissing-prototypes */
Packit c5a612
extern int	yyget_column(yyscan_t);
Packit c5a612
extern void	yyset_column(int, yyscan_t);
Packit c5a612
Packit c5a612
%}
Packit c5a612
Packit c5a612
space		[ ]
Packit c5a612
tab		\t
Packit c5a612
newline		\n
Packit c5a612
digit		[0-9]
Packit c5a612
hexdigit	[0-9a-fA-F]
Packit c5a612
decstring	{digit}+
Packit c5a612
hexstring	0[xX]{hexdigit}+
Packit c5a612
numberstring	({decstring}|{hexstring})
Packit c5a612
letter		[a-zA-Z]
Packit c5a612
string		({letter}|[_.])({letter}|{digit}|[/\-_\.])*
Packit c5a612
quotedstring	\"[^"]*\"
Packit Service 6f0138
asteriskstring	({string}\*|{string}\\\*)
Packit c5a612
comment		#.*$
Packit c5a612
slash		\/
Packit c5a612
Packit c5a612
timestring	([0-9]+d)?([0-9]+h)?([0-9]+m)?([0-9]+s)?([0-9]+ms)?
Packit c5a612
Packit c5a612
hex4		([[:xdigit:]]{1,4})
Packit c5a612
v680		(({hex4}:){7}{hex4})
Packit c5a612
v670		((:)((:{hex4}){7}))
Packit c5a612
v671		((({hex4}:){1})((:{hex4}){6}))
Packit c5a612
v672		((({hex4}:){2})((:{hex4}){5}))
Packit c5a612
v673		((({hex4}:){3})((:{hex4}){4}))
Packit c5a612
v674		((({hex4}:){4})((:{hex4}){3}))
Packit c5a612
v675		((({hex4}:){5})((:{hex4}){2}))
Packit c5a612
v676		((({hex4}:){6})(:{hex4}{1}))
Packit c5a612
v677		((({hex4}:){7})(:))
Packit c5a612
v67		({v670}|{v671}|{v672}|{v673}|{v674}|{v675}|{v676}|{v677})
Packit c5a612
v660		((:)((:{hex4}){6}))
Packit c5a612
v661		((({hex4}:){1})((:{hex4}){5}))
Packit c5a612
v662		((({hex4}:){2})((:{hex4}){4}))
Packit c5a612
v663		((({hex4}:){3})((:{hex4}){3}))
Packit c5a612
v664		((({hex4}:){4})((:{hex4}){2}))
Packit c5a612
v665		((({hex4}:){5})((:{hex4}){1}))
Packit c5a612
v666		((({hex4}:){6})(:))
Packit c5a612
v66		({v660}|{v661}|{v662}|{v663}|{v664}|{v665}|{v666})
Packit c5a612
v650		((:)((:{hex4}){5}))
Packit c5a612
v651		((({hex4}:){1})((:{hex4}){4}))
Packit c5a612
v652		((({hex4}:){2})((:{hex4}){3}))
Packit c5a612
v653		((({hex4}:){3})((:{hex4}){2}))
Packit c5a612
v654		((({hex4}:){4})(:{hex4}{1}))
Packit c5a612
v655		((({hex4}:){5})(:))
Packit c5a612
v65		({v650}|{v651}|{v652}|{v653}|{v654}|{v655})
Packit c5a612
v640		((:)((:{hex4}){4}))
Packit c5a612
v641		((({hex4}:){1})((:{hex4}){3}))
Packit c5a612
v642		((({hex4}:){2})((:{hex4}){2}))
Packit c5a612
v643		((({hex4}:){3})((:{hex4}){1}))
Packit c5a612
v644		((({hex4}:){4})(:))
Packit c5a612
v64		({v640}|{v641}|{v642}|{v643}|{v644})
Packit c5a612
v630		((:)((:{hex4}){3}))
Packit c5a612
v631		((({hex4}:){1})((:{hex4}){2}))
Packit c5a612
v632		((({hex4}:){2})((:{hex4}){1}))
Packit c5a612
v633		((({hex4}:){3})(:))
Packit c5a612
v63		({v630}|{v631}|{v632}|{v633})
Packit c5a612
v620		((:)((:{hex4}){2}))
Packit c5a612
v620_rfc4291	((:)(:{ip4addr}))
Packit c5a612
v621		((({hex4}:){1})((:{hex4}){1}))
Packit c5a612
v622		((({hex4}:){2})(:))
Packit c5a612
v62_rfc4291	((:)(:[fF]{4})(:{ip4addr}))
Packit c5a612
v62		({v620}|{v621}|{v622}|{v62_rfc4291}|{v620_rfc4291})
Packit c5a612
v610		((:)(:{hex4}{1}))
Packit c5a612
v611		((({hex4}:){1})(:))
Packit c5a612
v61		({v610}|{v611})
Packit c5a612
v60		(::)
Packit c5a612
Packit c5a612
macaddr		(([[:xdigit:]]{1,2}:){5}[[:xdigit:]]{1,2})
Packit c5a612
ip4addr		(([[:digit:]]{1,3}"."){3}([[:digit:]]{1,3}))
Packit c5a612
ip6addr		({v680}|{v67}|{v66}|{v65}|{v64}|{v63}|{v62}|{v61}|{v60})
Packit c5a612
ip6addr_rfc2732	(\[{ip6addr}\])
Packit c5a612
Packit c5a612
classid		({hexdigit}{1,4}:{hexdigit}{1,4})
Packit c5a612
addrstring	({macaddr}|{ip4addr}|{ip6addr})
Packit c5a612
Packit c5a612
%option prefix="nft_"
Packit c5a612
%option outfile="lex.yy.c"
Packit c5a612
%option reentrant
Packit c5a612
%option noyywrap
Packit c5a612
%option nounput
Packit c5a612
%option bison-bridge
Packit c5a612
%option bison-locations
Packit c5a612
%option debug
Packit c5a612
%option yylineno
Packit c5a612
%option nodefault
Packit c5a612
%option warn
Packit c5a612
Packit c5a612
%%
Packit c5a612
Packit c5a612
"=="			{ return EQ; }
Packit c5a612
"eq"			{ return EQ; }
Packit c5a612
"!="			{ return NEQ; }
Packit c5a612
"ne"			{ return NEQ; }
Packit c5a612
"<="			{ return LTE; }
Packit c5a612
"le"			{ return LTE; }
Packit c5a612
"<"			{ return LT; }
Packit c5a612
"lt"			{ return LT; }
Packit c5a612
">="			{ return GTE; }
Packit c5a612
"ge"			{ return GTE; }
Packit c5a612
">"			{ return GT; }
Packit c5a612
"gt"			{ return GT; }
Packit c5a612
","			{ return COMMA; }
Packit c5a612
"."			{ return DOT; }
Packit c5a612
":"			{ return COLON; }
Packit c5a612
";"			{ return SEMICOLON; }
Packit c5a612
"{"			{ return '{'; }
Packit c5a612
"}"			{ return '}'; }
Packit c5a612
"["			{ return '['; }
Packit c5a612
"]"			{ return ']'; }
Packit c5a612
"("			{ return '('; }
Packit c5a612
")"			{ return ')'; }
Packit c5a612
"<<"			{ return LSHIFT; }
Packit c5a612
"lshift"		{ return LSHIFT; }
Packit c5a612
">>"			{ return RSHIFT; }
Packit c5a612
"rshift"		{ return RSHIFT; }
Packit c5a612
"^"			{ return CARET; }
Packit c5a612
"xor"			{ return CARET; }
Packit c5a612
"&"			{ return AMPERSAND; }
Packit c5a612
"and"			{ return AMPERSAND; }
Packit c5a612
"|"			{ return '|'; }
Packit c5a612
"or"			{ return '|'; }
Packit c5a612
"!"			{ return NOT; }
Packit c5a612
"not"			{ return NOT; }
Packit c5a612
"/"			{ return SLASH; }
Packit c5a612
"-"			{ return DASH; }
Packit c5a612
"*"			{ return ASTERISK; }
Packit c5a612
"@"			{ return AT; }
Packit c5a612
"$"			{ return '$'; }
Packit c5a612
"="			{ return '='; }
Packit c5a612
"vmap"			{ return VMAP; }
Packit c5a612
Packit c5a612
"+"			{ return PLUS; }
Packit c5a612
Packit c5a612
"include"		{ return INCLUDE; }
Packit c5a612
"define"		{ return DEFINE; }
Packit c5a612
"redefine"		{ return REDEFINE; }
Packit c5a612
"undefine"		{ return UNDEFINE; }
Packit c5a612
Packit c5a612
"describe"		{ return DESCRIBE; }
Packit c5a612
Packit c5a612
"hook"			{ return HOOK; }
Packit c5a612
"device"		{ return DEVICE; }
Packit c5a612
"devices"		{ return DEVICES; }
Packit c5a612
"table"			{ return TABLE; }
Packit c5a612
"tables"		{ return TABLES; }
Packit c5a612
"chain"			{ return CHAIN; }
Packit c5a612
"chains"		{ return CHAINS; }
Packit c5a612
"rule"			{ return RULE; }
Packit c5a612
"rules"			{ return RULES; }
Packit c5a612
"sets"			{ return SETS; }
Packit c5a612
"set"			{ return SET; }
Packit c5a612
"element"		{ return ELEMENT; }
Packit c5a612
"map"			{ return MAP; }
Packit c5a612
"maps"			{ return MAPS; }
Packit c5a612
"flowtable"		{ return FLOWTABLE; }
Packit c5a612
"handle"		{ return HANDLE; }
Packit c5a612
"ruleset"		{ return RULESET; }
Packit c5a612
"trace"			{ return TRACE; }
Packit c5a612
Packit c5a612
"socket"		{ return SOCKET; }
Packit c5a612
"transparent"		{ return TRANSPARENT;}
Packit c5a612
Packit c5a612
"tproxy"		{ return TPROXY; }
Packit c5a612
Packit c5a612
"accept"		{ return ACCEPT; }
Packit c5a612
"drop"			{ return DROP; }
Packit c5a612
"continue"		{ return CONTINUE; }
Packit c5a612
"jump"			{ return JUMP; }
Packit c5a612
"goto"			{ return GOTO; }
Packit c5a612
"return"		{ return RETURN; }
Packit c5a612
"to"			{ return TO; }
Packit c5a612
Packit c5a612
"inet"			{ return INET; }
Packit c5a612
"netdev"		{ return NETDEV; }
Packit c5a612
Packit c5a612
"add"			{ return ADD; }
Packit c5a612
"replace"		{ return REPLACE; }
Packit c5a612
"update"		{ return UPDATE; }
Packit c5a612
"create"		{ return CREATE; }
Packit c5a612
"insert"		{ return INSERT; }
Packit c5a612
"delete"		{ return DELETE; }
Packit c5a612
"get"			{ return GET; }
Packit c5a612
"list"			{ return LIST; }
Packit c5a612
"reset"			{ return RESET; }
Packit c5a612
"flush"			{ return FLUSH; }
Packit c5a612
"rename"		{ return RENAME; }
Packit c5a612
"import"                { return IMPORT; }
Packit c5a612
"export"		{ return EXPORT; }
Packit c5a612
"monitor"		{ return MONITOR; }
Packit c5a612
Packit c5a612
"position"		{ return POSITION; }
Packit c5a612
"index"			{ return INDEX; }
Packit c5a612
"comment"		{ return COMMENT; }
Packit c5a612
Packit c5a612
"constant"		{ return CONSTANT; }
Packit c5a612
"interval"		{ return INTERVAL; }
Packit c5a612
"dynamic"		{ return DYNAMIC; }
Packit c5a612
"auto-merge"		{ return AUTOMERGE; }
Packit c5a612
"timeout"		{ return TIMEOUT; }
Packit c5a612
"gc-interval"		{ return GC_INTERVAL; }
Packit c5a612
"elements"		{ return ELEMENTS; }
Packit c5a612
"expires"		{ return EXPIRES; }
Packit c5a612
Packit c5a612
"policy"		{ return POLICY; }
Packit c5a612
"size"			{ return SIZE; }
Packit c5a612
"performance"		{ return PERFORMANCE; }
Packit c5a612
"memory"		{ return MEMORY; }
Packit c5a612
Packit c5a612
"flow"			{ return FLOW; }
Packit c5a612
"offload"		{ return OFFLOAD; }
Packit c5a612
"meter"			{ return METER; }
Packit c5a612
"meters"		{ return METERS; }
Packit c5a612
Packit c5a612
"flowtables"		{ return FLOWTABLES; }
Packit c5a612
Packit c5a612
"counter"		{ return COUNTER; }
Packit c5a612
"name"			{ return NAME; }
Packit c5a612
"packets"		{ return PACKETS; }
Packit c5a612
"bytes"			{ return BYTES; }
Packit c5a612
"avgpkt"		{ return AVGPKT; }
Packit c5a612
Packit c5a612
"counters"		{ return COUNTERS; }
Packit c5a612
"quotas"		{ return QUOTAS; }
Packit c5a612
"limits"		{ return LIMITS; }
Packit c5a612
"synproxys"		{ return SYNPROXYS; }
Packit c5a612
Packit c5a612
"log"			{ return LOG; }
Packit c5a612
"prefix"		{ return PREFIX; }
Packit c5a612
"group"			{ return GROUP; }
Packit c5a612
"snaplen"		{ return SNAPLEN; }
Packit c5a612
"queue-threshold"	{ return QUEUE_THRESHOLD; }
Packit c5a612
"level"			{ return LEVEL; }
Packit c5a612
Packit c5a612
"queue"			{ return QUEUE;}
Packit c5a612
"num"			{ return QUEUENUM;}
Packit c5a612
"bypass"		{ return BYPASS;}
Packit c5a612
"fanout"		{ return FANOUT;}
Packit c5a612
Packit c5a612
"limit"			{ return LIMIT; }
Packit c5a612
"rate"			{ return RATE; }
Packit c5a612
"burst"			{ return BURST; }
Packit c5a612
"until"			{ return UNTIL; }
Packit c5a612
"over"			{ return OVER; }
Packit c5a612
Packit c5a612
"quota"			{ return QUOTA; }
Packit c5a612
"used"			{ return USED; }
Packit c5a612
Packit c5a612
"nanosecond"		{ return NANOSECOND; }
Packit c5a612
"microsecond"		{ return MICROSECOND; }
Packit c5a612
"millisecond"		{ return MILLISECOND; }
Packit c5a612
"second"		{ return SECOND; }
Packit c5a612
"minute"		{ return MINUTE; }
Packit c5a612
"hour"			{ return HOUR; }
Packit c5a612
"day"			{ return DAY; }
Packit c5a612
"week"			{ return WEEK; }
Packit c5a612
Packit c5a612
"reject"		{ return _REJECT; }
Packit c5a612
"with"			{ return WITH; }
Packit c5a612
"icmpx"			{ return ICMPX; }
Packit c5a612
Packit c5a612
"snat"			{ return SNAT; }
Packit c5a612
"dnat"			{ return DNAT; }
Packit c5a612
"masquerade"		{ return MASQUERADE; }
Packit c5a612
"redirect"		{ return REDIRECT; }
Packit c5a612
"random"		{ return RANDOM; }
Packit c5a612
"fully-random"		{ return FULLY_RANDOM; }
Packit c5a612
"persistent"		{ return PERSISTENT; }
Packit c5a612
Packit c5a612
"ll"			{ return LL_HDR; }
Packit c5a612
"nh"			{ return NETWORK_HDR; }
Packit c5a612
"th"			{ return TRANSPORT_HDR; }
Packit c5a612
Packit c5a612
"bridge"		{ return BRIDGE; }
Packit c5a612
Packit c5a612
"ether"			{ return ETHER; }
Packit c5a612
"saddr"			{ return SADDR; }
Packit c5a612
"daddr"			{ return DADDR; }
Packit c5a612
"type"			{ return TYPE; }
Packit c5a612
Packit c5a612
"vlan"			{ return VLAN; }
Packit c5a612
"id"			{ return ID; }
Packit c5a612
"cfi"			{ return CFI; }
Packit c5a612
"pcp"			{ return PCP; }
Packit c5a612
Packit c5a612
"arp"			{ return ARP; }
Packit c5a612
"htype"			{ return HTYPE; }
Packit c5a612
"ptype"			{ return PTYPE; }
Packit c5a612
"hlen"			{ return HLEN; }
Packit c5a612
"plen"			{ return PLEN; }
Packit c5a612
"operation"		{ return OPERATION; }
Packit c5a612
Packit c5a612
"ip"			{ return IP; }
Packit c5a612
"version"		{ return HDRVERSION; }
Packit c5a612
"hdrlength"		{ return HDRLENGTH; }
Packit c5a612
"dscp"			{ return DSCP; }
Packit c5a612
"ecn"			{ return ECN; }
Packit c5a612
"length"		{ return LENGTH; }
Packit c5a612
"frag-off"		{ return FRAG_OFF; }
Packit c5a612
"ttl"			{ return TTL; }
Packit c5a612
"protocol"		{ return PROTOCOL; }
Packit c5a612
"checksum"		{ return CHECKSUM; }
Packit c5a612
Packit c5a612
"lsrr"			{ return LSRR; }
Packit c5a612
"rr"			{ return RR; }
Packit c5a612
"ssrr"			{ return SSRR; }
Packit c5a612
"ra"			{ return RA; }
Packit c5a612
Packit c5a612
"value"			{ return VALUE; }
Packit c5a612
"ptr"			{ return PTR; }
Packit c5a612
Packit c5a612
"echo"			{ return ECHO; }
Packit c5a612
"eol"			{ return EOL; }
Packit c5a612
"maxseg"		{ return MAXSEG; }
Packit c5a612
"noop"			{ return NOOP; }
Packit c5a612
"sack"			{ return SACK; }
Packit c5a612
"sack0"			{ return SACK0; }
Packit c5a612
"sack1"			{ return SACK1; }
Packit c5a612
"sack2"			{ return SACK2; }
Packit c5a612
"sack3"			{ return SACK3; }
Packit c5a612
"sack-permitted"	{ return SACK_PERMITTED; }
Packit c5a612
"timestamp"		{ return TIMESTAMP; }
Packit c5a612
"time"			{ return TIME; }
Packit c5a612
Packit c5a612
"kind"			{ return KIND; }
Packit c5a612
"count"			{ return COUNT; }
Packit c5a612
"left"			{ return LEFT; }
Packit c5a612
"right"			{ return RIGHT; }
Packit c5a612
"tsval"			{ return TSVAL; }
Packit c5a612
"tsecr"			{ return TSECR; }
Packit c5a612
Packit c5a612
"icmp"			{ return ICMP; }
Packit c5a612
"code"			{ return CODE; }
Packit c5a612
"sequence"		{ return SEQUENCE; }
Packit c5a612
"gateway"		{ return GATEWAY; }
Packit c5a612
"mtu"			{ return MTU; }
Packit c5a612
Packit c5a612
"igmp"			{ return IGMP; }
Packit c5a612
"mrt"			{ return MRT; }
Packit c5a612
Packit c5a612
"ip6"			{ return IP6; }
Packit c5a612
"priority"		{ return PRIORITY; }
Packit c5a612
"flowlabel"		{ return FLOWLABEL; }
Packit c5a612
"nexthdr"		{ return NEXTHDR; }
Packit c5a612
"hoplimit"		{ return HOPLIMIT; }
Packit c5a612
Packit c5a612
"icmpv6"		{ return ICMP6; }
Packit c5a612
"param-problem"		{ return PPTR; }
Packit c5a612
"max-delay"		{ return MAXDELAY; }
Packit c5a612
Packit c5a612
"ah"			{ return AH; }
Packit c5a612
"reserved"		{ return RESERVED; }
Packit c5a612
"spi"			{ return SPI; }
Packit c5a612
Packit c5a612
"esp"			{ return ESP; }
Packit c5a612
Packit c5a612
"comp"			{ return COMP; }
Packit c5a612
"flags"			{ return FLAGS; }
Packit c5a612
"cpi"			{ return CPI; }
Packit c5a612
Packit c5a612
"udp"			{ return UDP; }
Packit c5a612
"udplite"		{ return UDPLITE; }
Packit c5a612
"sport"			{ return SPORT; }
Packit c5a612
"dport"			{ return DPORT; }
Packit c5a612
Packit c5a612
"tcp"			{ return TCP; }
Packit c5a612
"ackseq"		{ return ACKSEQ; }
Packit c5a612
"doff"			{ return DOFF; }
Packit c5a612
"window"		{ return WINDOW; }
Packit c5a612
"urgptr"		{ return URGPTR; }
Packit c5a612
"option"		{ return OPTION; }
Packit c5a612
Packit c5a612
"dccp"			{ return DCCP; }
Packit c5a612
Packit c5a612
"sctp"			{ return SCTP; }
Packit c5a612
"vtag"			{ return VTAG; }
Packit c5a612
Packit c5a612
"rt"			{ return RT; }
Packit c5a612
"rt0"			{ return RT0; }
Packit c5a612
"rt2"			{ return RT2; }
Packit c5a612
"srh"			{ return RT4; }
Packit c5a612
"seg-left"		{ return SEG_LEFT; }
Packit c5a612
"addr"			{ return ADDR; }
Packit c5a612
"last-entry"		{ return LAST_ENT; }
Packit c5a612
"tag"			{ return TAG; }
Packit c5a612
"sid"			{ return SID; }
Packit c5a612
Packit c5a612
"hbh"			{ return HBH; }
Packit c5a612
Packit c5a612
"frag"			{ return FRAG; }
Packit c5a612
"reserved2"		{ return RESERVED2; }
Packit c5a612
"more-fragments"	{ return MORE_FRAGMENTS; }
Packit c5a612
Packit c5a612
"dst"			{ return DST; }
Packit c5a612
Packit c5a612
"mh"			{ return MH; }
Packit c5a612
Packit c5a612
"meta"			{ return META; }
Packit c5a612
"mark"			{ return MARK; }
Packit c5a612
"iif"			{ return IIF; }
Packit c5a612
"iifname"		{ return IIFNAME; }
Packit c5a612
"iiftype"		{ return IIFTYPE; }
Packit c5a612
"oif"			{ return OIF; }
Packit c5a612
"oifname"		{ return OIFNAME; }
Packit c5a612
"oiftype"		{ return OIFTYPE; }
Packit c5a612
"skuid"			{ return SKUID; }
Packit c5a612
"skgid"			{ return SKGID; }
Packit c5a612
"nftrace"		{ return NFTRACE; }
Packit c5a612
"rtclassid"		{ return RTCLASSID; }
Packit c5a612
"ibriport"		{ return IBRIPORT; }
Packit c5a612
"ibrname"		{ return IBRIDGENAME; }
Packit c5a612
"obriport"		{ return OBRIPORT; }
Packit c5a612
"obrname"		{ return OBRIDGENAME; }
Packit c5a612
"pkttype"		{ return PKTTYPE; }
Packit c5a612
"cpu"			{ return CPU; }
Packit c5a612
"iifgroup"		{ return IIFGROUP; }
Packit c5a612
"oifgroup"		{ return OIFGROUP; }
Packit c5a612
"cgroup"		{ return CGROUP; }
Packit c5a612
Packit c5a612
"classid"		{ return CLASSID; }
Packit c5a612
"nexthop"		{ return NEXTHOP; }
Packit c5a612
Packit c5a612
"ct"			{ return CT; }
Packit c5a612
"l3proto"		{ return L3PROTOCOL; }
Packit c5a612
"proto-src"		{ return PROTO_SRC; }
Packit c5a612
"proto-dst"		{ return PROTO_DST; }
Packit c5a612
"zone"			{ return ZONE; }
Packit c5a612
"original"		{ return ORIGINAL; }
Packit c5a612
"reply"			{ return REPLY; }
Packit c5a612
"direction"		{ return DIRECTION; }
Packit c5a612
"event"			{ return EVENT; }
Packit c5a612
"expectation"		{ return EXPECTATION; }
Packit c5a612
"expiration"		{ return EXPIRATION; }
Packit c5a612
"helper"		{ return HELPER; }
Packit c5a612
"helpers"		{ return HELPERS; }
Packit c5a612
"label"			{ return LABEL; }
Packit c5a612
"state"			{ return STATE; }
Packit c5a612
"status"		{ return STATUS; }
Packit c5a612
Packit c5a612
"numgen"		{ return NUMGEN; }
Packit c5a612
"inc"			{ return INC; }
Packit c5a612
"mod"			{ return MOD; }
Packit c5a612
"offset"		{ return OFFSET; }
Packit c5a612
Packit c5a612
"jhash"			{ return JHASH; }
Packit c5a612
"symhash"		{ return SYMHASH; }
Packit c5a612
"seed"			{ return SEED; }
Packit c5a612
Packit c5a612
"dup"			{ return DUP; }
Packit c5a612
"fwd"			{ return FWD; }
Packit c5a612
Packit c5a612
"fib"			{ return FIB; }
Packit c5a612
Packit c5a612
"osf"			{ return OSF; }
Packit c5a612
Packit c5a612
"synproxy"		{ return SYNPROXY; }
Packit c5a612
"mss"			{ return MSS; }
Packit c5a612
"wscale"		{ return WSCALE; }
Packit c5a612
"sack-perm"		{ return SACKPERM; }
Packit c5a612
Packit c5a612
"notrack"		{ return NOTRACK; }
Packit c5a612
Packit c5a612
"options"		{ return OPTIONS; }
Packit c5a612
"all"			{ return ALL; }
Packit c5a612
Packit c5a612
"xml"			{ return XML; }
Packit c5a612
"json"			{ return JSON; }
Packit c5a612
"vm"                    { return VM; }
Packit c5a612
Packit c5a612
"exists"		{ return EXISTS; }
Packit c5a612
"missing"		{ return MISSING; }
Packit c5a612
Packit c5a612
"exthdr"		{ return EXTHDR; }
Packit c5a612
Packit c5a612
"ipsec"			{ return IPSEC; }
Packit c5a612
"mode"			{ return MODE; }
Packit c5a612
"reqid"			{ return REQID; }
Packit c5a612
"spnum"			{ return SPNUM; }
Packit c5a612
"transport"		{ return TRANSPORT; }
Packit c5a612
"tunnel"		{ return TUNNEL; }
Packit c5a612
Packit c5a612
"in"			{ return IN; }
Packit c5a612
"out"			{ return OUT; }
Packit c5a612
Packit c5a612
"secmark"		{ return SECMARK; }
Packit c5a612
"secmarks"		{ return SECMARKS; }
Packit c5a612
Packit c5a612
{addrstring}		{
Packit c5a612
				yylval->string = xstrdup(yytext);
Packit c5a612
				return STRING;
Packit c5a612
			}
Packit c5a612
Packit c5a612
{ip6addr_rfc2732}	{
Packit c5a612
				yytext[yyleng - 1] = '\0';
Packit c5a612
				yylval->string = xstrdup(yytext + 1);
Packit c5a612
				return STRING;
Packit c5a612
			}
Packit c5a612
Packit c5a612
{timestring}		{
Packit c5a612
				yylval->string = xstrdup(yytext);
Packit c5a612
				return STRING;
Packit c5a612
			}
Packit c5a612
Packit c5a612
{numberstring}		{
Packit c5a612
				errno = 0;
Packit c5a612
				yylval->val = strtoull(yytext, NULL, 0);
Packit c5a612
				if (errno != 0) {
Packit c5a612
					yylval->string = xstrdup(yytext);
Packit c5a612
					return STRING;
Packit c5a612
				}
Packit c5a612
				return NUM;
Packit c5a612
			}
Packit c5a612
Packit c5a612
{classid}/[ \t\n:\-},]	{
Packit c5a612
				yylval->string = xstrdup(yytext);
Packit c5a612
				return STRING;
Packit c5a612
			}
Packit c5a612
Packit c5a612
{quotedstring}		{
Packit c5a612
				yytext[yyleng - 1] = '\0';
Packit c5a612
				yylval->string = xstrdup(yytext + 1);
Packit c5a612
				return QUOTED_STRING;
Packit c5a612
			}
Packit c5a612
Packit c5a612
{asteriskstring}	{
Packit c5a612
				yylval->string = xstrdup(yytext);
Packit c5a612
				return ASTERISK_STRING;
Packit c5a612
			}
Packit c5a612
Packit c5a612
{string}		{
Packit c5a612
				yylval->string = xstrdup(yytext);
Packit c5a612
				return STRING;
Packit c5a612
			}
Packit c5a612
Packit c5a612
\\{newline}		{
Packit c5a612
				reset_pos(yyget_extra(yyscanner), yylloc);
Packit c5a612
			}
Packit c5a612
Packit c5a612
{newline}		{
Packit c5a612
				reset_pos(yyget_extra(yyscanner), yylloc);
Packit c5a612
				return NEWLINE;
Packit c5a612
			}
Packit c5a612
Packit c5a612
{tab}+
Packit c5a612
{space}+
Packit c5a612
{comment}
Packit c5a612
Packit c5a612
<<EOF>> 		{
Packit c5a612
				update_pos(yyget_extra(yyscanner), yylloc, 1);
Packit c5a612
				scanner_pop_buffer(yyscanner);
Packit c5a612
				if (YY_CURRENT_BUFFER == NULL)
Packit c5a612
					return TOKEN_EOF;
Packit c5a612
			}
Packit c5a612
Packit c5a612
.			{ return JUNK; }
Packit c5a612
Packit c5a612
%%
Packit c5a612
Packit c5a612
static void scanner_pop_buffer(yyscan_t scanner)
Packit c5a612
{
Packit c5a612
	struct parser_state *state = yyget_extra(scanner);
Packit c5a612
Packit c5a612
	yypop_buffer_state(scanner);
Packit c5a612
	state->indesc = state->indescs[--state->indesc_idx];
Packit c5a612
}
Packit c5a612
Packit c5a612
static void scanner_push_file(struct nft_ctx *nft, void *scanner,
Packit c5a612
			      const char *filename, const struct location *loc)
Packit c5a612
{
Packit c5a612
	struct parser_state *state = yyget_extra(scanner);
Packit c5a612
	struct input_descriptor *indesc;
Packit c5a612
	YY_BUFFER_STATE b;
Packit c5a612
Packit c5a612
	b = yy_create_buffer(nft->f[state->indesc_idx], YY_BUF_SIZE, scanner);
Packit c5a612
	yypush_buffer_state(b, scanner);
Packit c5a612
Packit c5a612
	indesc = xzalloc(sizeof(struct input_descriptor));
Packit c5a612
Packit c5a612
	if (loc != NULL)
Packit c5a612
		indesc->location = *loc;
Packit c5a612
	indesc->type	= INDESC_FILE;
Packit c5a612
	indesc->name	= xstrdup(filename);
Packit c5a612
	init_pos(indesc);
Packit c5a612
Packit c5a612
	state->indescs[state->indesc_idx] = indesc;
Packit c5a612
	state->indesc = state->indescs[state->indesc_idx++];
Packit c5a612
	list_add_tail(&indesc->list, &state->indesc_list);
Packit c5a612
}
Packit c5a612
Packit c5a612
static int include_file(struct nft_ctx *nft, void *scanner,
Packit c5a612
			const char *filename, const struct location *loc)
Packit c5a612
{
Packit c5a612
	struct parser_state *state = yyget_extra(scanner);
Packit c5a612
	struct error_record *erec;
Packit c5a612
	FILE *f;
Packit c5a612
Packit c5a612
	if (state->indesc_idx == MAX_INCLUDE_DEPTH) {
Packit c5a612
		erec = error(loc, "Include nested too deeply, max %u levels",
Packit c5a612
			     MAX_INCLUDE_DEPTH);
Packit c5a612
		goto err;
Packit c5a612
	}
Packit c5a612
Packit c5a612
	f = fopen(filename, "r");
Packit c5a612
	if (f == NULL) {
Packit c5a612
		erec = error(loc, "Could not open file \"%s\": %s\n",
Packit c5a612
			     filename, strerror(errno));
Packit c5a612
		goto err;
Packit c5a612
	}
Packit c5a612
	nft->f[state->indesc_idx] = f;
Packit c5a612
	scanner_push_file(nft, scanner, filename, loc);
Packit c5a612
	return 0;
Packit c5a612
err:
Packit c5a612
	erec_queue(erec, state->msgs);
Packit c5a612
	return -1;
Packit c5a612
}
Packit c5a612
Packit c5a612
static int include_glob(struct nft_ctx *nft, void *scanner, const char *pattern,
Packit c5a612
			const struct location *loc)
Packit c5a612
{
Packit c5a612
	struct parser_state *state = yyget_extra(scanner);
Packit c5a612
	struct error_record *erec = NULL;
Packit c5a612
	bool wildcard = false;
Packit c5a612
	glob_t glob_data;
Packit c5a612
	unsigned int i;
Packit c5a612
	int flags = 0;
Packit c5a612
	int ret;
Packit c5a612
	char *p;
Packit c5a612
Packit c5a612
	/* This function can return four meaningful values:
Packit c5a612
	 *
Packit c5a612
	 *  -1 means that there was an error.
Packit c5a612
	 *   0 means that a single non-wildcard match was done.
Packit c5a612
	 *   1 means that there are no wildcards in the pattern and the
Packit c5a612
	 *     search can continue.
Packit c5a612
	 *   2 means that there are wildcards in the pattern and the search
Packit c5a612
	 *     can continue.
Packit c5a612
	 *
Packit c5a612
	 * The diffrence is needed, because there is a semantic difference
Packit c5a612
	 * between patterns with wildcards and no wildcards. Not finding a
Packit c5a612
	 * non-wildcard file is an error but not finding any matches for a
Packit c5a612
	 * wildcard pattern is not.
Packit c5a612
	 */
Packit c5a612
Packit c5a612
	/* There shouldn't be a need to use escape characters in include paths.
Packit c5a612
	 */
Packit c5a612
	flags |= GLOB_NOESCAPE;
Packit c5a612
Packit c5a612
	/* Mark directories so we can filter them out (also links). */
Packit c5a612
	flags |= GLOB_MARK;
Packit c5a612
Packit c5a612
	/* If there is no match, glob() doesn't set GLOB_MAGCHAR even if there
Packit c5a612
	 * are wildcard characters in the pattern. We need to look for (luckily
Packit c5a612
	 * well-known and not likely to change) magic characters ourselves. In a
Packit c5a612
	 * perfect world, we could use glob() itself to figure out if there are
Packit c5a612
	 * wildcards in the pattern.
Packit c5a612
	 */
Packit c5a612
	p = (char *)pattern;
Packit c5a612
	while (*p) {
Packit c5a612
		if (*p == '*' || *p == '?' || *p == '[') {
Packit c5a612
			wildcard = true;
Packit c5a612
			break;
Packit c5a612
		}
Packit c5a612
		p++;
Packit c5a612
	}
Packit c5a612
Packit c5a612
	ret = glob(pattern, flags, NULL, &glob_data);
Packit c5a612
	if (ret == 0) {
Packit c5a612
		char *path;
Packit c5a612
		int len;
Packit c5a612
Packit c5a612
		/* reverse alphabetical order due to stack */
Packit c5a612
		for (i = glob_data.gl_pathc; i > 0; i--) {
Packit c5a612
Packit c5a612
			path = glob_data.gl_pathv[i-1];
Packit c5a612
Packit c5a612
			/* ignore directories */
Packit c5a612
			len = strlen(path);
Packit c5a612
			if (len == 0 || path[len - 1] == '/')
Packit c5a612
				continue;
Packit c5a612
Packit c5a612
			ret = include_file(nft, scanner, path, loc);
Packit c5a612
			if (ret != 0)
Packit c5a612
				goto err;
Packit c5a612
		}
Packit c5a612
Packit c5a612
		globfree(&glob_data);
Packit c5a612
Packit c5a612
		/* If no wildcards and we found the file, stop the search (with
Packit c5a612
		 * 0). In case of wildcards we need to still continue the
Packit c5a612
		 * search, because other matches might be in other include
Packit c5a612
		 * directories. We handled the case with a non-wildcard pattern
Packit c5a612
		 * and no matches already before.
Packit c5a612
		 */
Packit c5a612
		 return wildcard ? 2 : 0;
Packit c5a612
	} else if (ret == GLOB_NOMATCH) {
Packit c5a612
		globfree(&glob_data);
Packit c5a612
Packit c5a612
		/* We need to tell the caller whether wildcards were used in
Packit c5a612
		 * case of no match, because the semantics for handling the
Packit c5a612
		 * cases are different.
Packit c5a612
		 */
Packit c5a612
		return wildcard ? 2 : 1;
Packit c5a612
	}
Packit c5a612
Packit c5a612
	erec = error(loc, "Failed to glob the pattern %s", pattern);
Packit c5a612
Packit c5a612
	/* intentional fall through */
Packit c5a612
err:
Packit c5a612
	if (erec)
Packit c5a612
		erec_queue(erec, state->msgs);
Packit c5a612
	globfree(&glob_data);
Packit c5a612
	return -1;
Packit c5a612
}
Packit c5a612
Packit c5a612
int scanner_read_file(struct nft_ctx *nft, const char *filename,
Packit c5a612
		      const struct location *loc)
Packit c5a612
{
Packit c5a612
	return include_file(nft, nft->scanner, filename, loc);
Packit c5a612
}
Packit c5a612
Packit c5a612
static bool search_in_include_path(const char *filename)
Packit c5a612
{
Packit c5a612
	return (strncmp(filename, "./", strlen("./")) != 0 &&
Packit c5a612
		strncmp(filename, "../", strlen("../")) != 0 &&
Packit c5a612
		filename[0] != '/');
Packit c5a612
}
Packit c5a612
Packit c5a612
int scanner_include_file(struct nft_ctx *nft, void *scanner,
Packit c5a612
			 const char *filename, const struct location *loc)
Packit c5a612
{
Packit c5a612
	struct parser_state *state = yyget_extra(scanner);
Packit c5a612
	struct error_record *erec;
Packit c5a612
	char buf[PATH_MAX];
Packit c5a612
	unsigned int i;
Packit c5a612
	int ret = -1;
Packit c5a612
Packit c5a612
	if (search_in_include_path(filename)) {
Packit c5a612
		for (i = 0; i < nft->num_include_paths; i++) {
Packit c5a612
			ret = snprintf(buf, sizeof(buf), "%s/%s",
Packit c5a612
				       nft->include_paths[i], filename);
Packit c5a612
			if (ret < 0 || ret >= PATH_MAX) {
Packit c5a612
				erec = error(loc, "Too long file path \"%s/%s\"\n",
Packit c5a612
					     nft->include_paths[i], filename);
Packit c5a612
				erec_queue(erec, state->msgs);
Packit c5a612
				return -1;
Packit c5a612
			}
Packit c5a612
Packit c5a612
			ret = include_glob(nft, scanner, buf, loc);
Packit c5a612
Packit c5a612
			/* error was already handled */
Packit c5a612
			if (ret == -1)
Packit c5a612
				return -1;
Packit c5a612
			/* no wildcards and file was processed: break early. */
Packit c5a612
			if (ret == 0)
Packit c5a612
				return 0;
Packit c5a612
Packit c5a612
			/* else 1 (no wildcards) or 2 (wildcards): keep
Packit c5a612
			 * searching.
Packit c5a612
			 */
Packit c5a612
		}
Packit c5a612
	} else {
Packit c5a612
		/* an absolute path (starts with '/') */
Packit c5a612
		ret = include_glob(nft, scanner, filename, loc);
Packit c5a612
	}
Packit c5a612
Packit c5a612
	/* handle the case where no file was found */
Packit c5a612
	if (ret == -1)
Packit c5a612
		return -1;
Packit c5a612
	else if (ret == 0 || ret == 2)
Packit c5a612
		return 0;
Packit c5a612
Packit c5a612
	/* 1 means an error, because there are no more include directories to
Packit c5a612
	 * search, and the pattern does not have wildcard characters.
Packit c5a612
	 */
Packit c5a612
	erec = error(loc, "File not found: %s", filename);
Packit c5a612
	erec_queue(erec, state->msgs);
Packit c5a612
	return -1;
Packit c5a612
}
Packit c5a612
Packit c5a612
void scanner_push_buffer(void *scanner, const struct input_descriptor *indesc,
Packit c5a612
			 const char *buffer)
Packit c5a612
{
Packit c5a612
	struct parser_state *state = yyget_extra(scanner);
Packit c5a612
	YY_BUFFER_STATE b;
Packit c5a612
Packit c5a612
	state->indesc = xzalloc(sizeof(struct input_descriptor));
Packit c5a612
	state->indescs[state->indesc_idx] = state->indesc;
Packit c5a612
	state->indesc_idx++;
Packit c5a612
Packit c5a612
	memcpy(state->indesc, indesc, sizeof(*state->indesc));
Packit c5a612
	state->indesc->data = buffer;
Packit c5a612
	state->indesc->name = NULL;
Packit c5a612
	list_add_tail(&state->indesc->list, &state->indesc_list);
Packit c5a612
Packit c5a612
	b = yy_scan_string(buffer, scanner);
Packit c5a612
	assert(b != NULL);
Packit c5a612
	init_pos(state->indesc);
Packit c5a612
}
Packit c5a612
Packit c5a612
void *scanner_init(struct parser_state *state)
Packit c5a612
{
Packit c5a612
	yyscan_t scanner;
Packit c5a612
Packit c5a612
	yylex_init_extra(state, &scanner);
Packit c5a612
	yyset_out(NULL, scanner);
Packit c5a612
Packit c5a612
	return scanner;
Packit c5a612
}
Packit c5a612
Packit c5a612
static void input_descriptor_destroy(const struct input_descriptor *indesc)
Packit c5a612
{
Packit c5a612
	if (indesc->name)
Packit c5a612
		xfree(indesc->name);
Packit c5a612
	xfree(indesc);
Packit c5a612
}
Packit c5a612
Packit c5a612
static void input_descriptor_list_destroy(struct parser_state *state)
Packit c5a612
{
Packit c5a612
	struct input_descriptor *indesc, *next;
Packit c5a612
Packit c5a612
	list_for_each_entry_safe(indesc, next, &state->indesc_list, list) {
Packit c5a612
		list_del(&indesc->list);
Packit c5a612
		input_descriptor_destroy(indesc);
Packit c5a612
	}
Packit c5a612
}
Packit c5a612
Packit c5a612
void scanner_destroy(struct nft_ctx *nft)
Packit c5a612
{
Packit c5a612
	struct parser_state *state = yyget_extra(nft->scanner);
Packit c5a612
Packit c5a612
	do {
Packit c5a612
		yypop_buffer_state(nft->scanner);
Packit c5a612
Packit c5a612
		if (nft->f[state->indesc_idx]) {
Packit c5a612
			fclose(nft->f[state->indesc_idx]);
Packit c5a612
			nft->f[state->indesc_idx] = NULL;
Packit c5a612
		}
Packit c5a612
	} while (state->indesc_idx--);
Packit c5a612
Packit c5a612
	input_descriptor_list_destroy(state);
Packit c5a612
	yylex_destroy(nft->scanner);
Packit c5a612
}