cfg.y
3c1a8ef8
 /*
  * $Id$
  *
  *  cfg grammar
  */
 
 %{
 
c07508e2
 #include "route_struct.h"
 
3c1a8ef8
 %}
 
 %union {
 	int intval;
09e52ebb
 	unsigned uval;
3c1a8ef8
 	char* strval;
c07508e2
 	struct expr* expr;
 	struct action* action;
09e52ebb
 	struct net* net;
3c1a8ef8
 }
 
 /* terminals */
 
 
 /* keywors */
 %token FORWARD
 %token SEND
 %token DROP
 %token LOG
 %token ERROR
 %token ROUTE
09e52ebb
 %token EXEC
 
3c1a8ef8
 %token METHOD
 %token URI
 %token SRCIP
 %token DSTIP
 
 /* config vars. */
 %token DEBUG
 %token FORK
 %token LOGSTDERROR
 %token LISTEN
 %token DNS
 %token REV_DNS
 
 
 /* operators */
 %nonassoc EQUAL
 %nonassoc EQUAL_T
 %nonassoc MATCH
 %left OR
09e52ebb
 %left AND
 %left NOT
3c1a8ef8
 
 /* values */
c07508e2
 %token <intval> NUMBER
 %token <strval> ID
 %token <strval> STRING
3c1a8ef8
 
 /* other */
 %token COMMA
 %token SEMICOLON
 %token RPAREN
 %token LPAREN
 %token LBRACE
 %token RBRACE
 %token LBRACK
 %token RBRACK
 %token SLASH
 %token DOT
 %token CR
 
 
 /*non-terminals */
c07508e2
 %type <expr> exp, condition,  exp_elem
 %type <action> action, actions, cmd
09e52ebb
 %type <uval> ipv4
 %type <net> net4
 %type <strval> host
3c1a8ef8
 
 
 
 %%
 
 
 cfg:	statements
 	;
 
 statements:	statements statement {printf("got <> <>\n");}
c07508e2
 		| statement {printf("got a statement<>\n"); }
 		| statements error { yyerror(""); }
3c1a8ef8
 	;
 
 statement:	assign_stm CR
c07508e2
 		| route_stm CR
 		| CR	/* null statement*/
3c1a8ef8
 	;
 
c07508e2
 assign_stm:	DEBUG EQUAL NUMBER 
 		| DEBUG EQUAL error  { yyerror("number  expected"); }
 		| FORK  EQUAL NUMBER
 		| FORK  EQUAL error  { yyerror("boolean value expected"); }
 		| LOGSTDERROR EQUAL NUMBER 
 		| LOGSTDERROR EQUAL error { yyerror("boolean value expected"); }
 		| DNS EQUAL NUMBER
 		| DNS EQUAL error { yyerror("boolean value expected"); }
 		| REV_DNS EQUAL NUMBER 
 		| REV_DNS EQUAL error { yyerror("boolean value expected"); }
 		| LISTEN EQUAL ipv4 
 		| LISTEN EQUAL ID 
 		| LISTEN EQUAL STRING
 		| LISTEN EQUAL  error { yyerror("ip address or hostname"
 						"expected"); }
 		| error EQUAL { yyerror("unknown config variable"); }
3c1a8ef8
 	;
 
 
09e52ebb
 ipv4:	NUMBER DOT NUMBER DOT NUMBER DOT NUMBER { 
 											if (($1>255) || ($1<0) ||
 												($3>255) || ($3<0) ||
 												($5>255) || ($5<0) ||
 												($7>255) || ($7<0)){
 												yyerror("invalid ipv4"
 														"address");
 												$$=0;
 											}else{
 												$$=($1<<24)|($3<<16)|
 													($5<<8)|$7;
 											}
 												}
3c1a8ef8
 	;
 
c07508e2
 route_stm:	ROUTE LBRACE rules RBRACE 
 		| ROUTE LBRACK NUMBER RBRACK LBRACE rules RBRACE
 		| ROUTE error { yyerror("invalid  route  statement"); }
3c1a8ef8
 	;
 
c07508e2
 rules:	rules rule
 	| rule
 	| rules error { yyerror("invalid rule"); }
3c1a8ef8
 	 ;
 
09e52ebb
 rule:	condition	actions CR {
 								printf("Got a new rule!\n");
 								printf("expr: "); print_expr($1);
 								printf("\n  -> actions: ");
 								print_action($2); printf("\n");
 							   }
c07508e2
 	| CR  /* null rule */
 	| condition error { yyerror("bad actions in rule"); }
3c1a8ef8
 	;
 
09e52ebb
 condition:	exp {$$=$1;}
3c1a8ef8
 	;
 
09e52ebb
 exp:	exp AND exp 	{ $$=mk_exp(AND_OP, $1, $3); }
 	| exp OR  exp		{ $$=mk_exp(OR_OP, $1, $3);  }
 	| NOT exp 			{ $$=mk_exp(NOT_OP, $2, 0);  }
 	| LPAREN exp RPAREN	{ $$=$2; }
 	| exp_elem			{ $$=$1; }
3c1a8ef8
 	;
 
09e52ebb
 exp_elem:	METHOD EQUAL_T STRING	{$$= mk_elem(	EQUAL_OP, STRING_ST, 
 													METHOD_O, $3);
 									}
 		| METHOD EQUAL_T ID	{$$ = mk_elem(	EQUAL_OP, STRING_ST,
 											METHOD_O, $3); 
 				 			}
c07508e2
 		| METHOD EQUAL_T error { $$=0; yyerror("string expected"); }
09e52ebb
 		| METHOD MATCH STRING	{$$ = mk_elem(	MATCH_OP, STRING_ST,
 												METHOD_O, $3); 
 				 				}
 		| METHOD MATCH ID	{$$ = mk_elem(	MATCH_OP, STRING_ST,
 											METHOD_O, $3); 
 				 			}
c07508e2
 		| METHOD MATCH error { $$=0; yyerror("string expected"); }
09e52ebb
 		| METHOD error	{ $$=0; yyerror("invalid operator,"
 										"== or ~= expected");
 						}
 		| URI EQUAL_T STRING 	{$$ = mk_elem(	EQUAL_OP, STRING_ST,
 												URI_O, $3); 
 				 				}
 		| URI EQUAL_T ID 	{$$ = mk_elem(	EQUAL_OP, STRING_ST,
 											URI_O, $3); 
 				 			}
c07508e2
 		| URI EQUAL_T error { $$=0; yyerror("string expected"); }
09e52ebb
 		| URI MATCH STRING	{ $$=mk_elem(	MATCH_OP, STRING_ST,
 											URI_O, $3);
 							}
 		| URI MATCH ID		{ $$=mk_elem(	MATCH_OP, STRING_ST,
 											URI_O, $3);
 							}
c07508e2
 		| URI MATCH error {  $$=0; yyerror("string expected"); }
09e52ebb
 		| URI error	{ $$=0; yyerror("invalid operator,"
 				  					" == or ~= expected");
 					}
 		| SRCIP EQUAL_T net4	{ $$=mk_elem(	EQUAL_OP, NET_ST,
 												SRCIP_O, $3);
 								}
 		| SRCIP EQUAL_T STRING	{ $$=mk_elem(	EQUAL_OP, STRING_ST,
 												SRCIP_O, $3);
 								}
 		| SRCIP EQUAL_T host	{ $$=mk_elem(	EQUAL_OP, STRING_ST,
 												SRCIP_O, $3);
 								}
 		| SRCIP EQUAL_T error { $$=0; yyerror( "ip address or hostname"
c07508e2
 						 "expected" ); }
09e52ebb
 		| SRCIP MATCH STRING	{ $$=mk_elem(	MATCH_OP, STRING_ST,
 												SRCIP_O, $3);
 								}
 		| SRCIP MATCH ID		{ $$=mk_elem(	MATCH_OP, STRING_ST,
 												SRCIP_O, $3);
 								}
 		| SRCIP MATCH error  { $$=0; yyerror( "hostname expected"); }
 		| SRCIP error  { $$=0; 
 						 yyerror("invalid operator, == or ~= expected");}
 		| DSTIP EQUAL_T net4	{ $$=mk_elem(	EQUAL_OP, NET_ST,
 												DSTIP_O, $3);
 								}
 		| DSTIP EQUAL_T STRING	{ $$=mk_elem(	EQUAL_OP, STRING_ST,
 												DSTIP_O, $3);
 								}
 		| DSTIP EQUAL_T host	{ $$=mk_elem(	EQUAL_OP, STRING_ST,
 												DSTIP_O, $3);
 								}
 		| DSTIP EQUAL_T error { $$=0; yyerror( "ip address or hostname"
 						 			"expected" ); }
 		| DSTIP MATCH STRING	{ $$=mk_elem(	MATCH_OP, STRING_ST,
 												DSTIP_O, $3);
 								}
 		| DSTIP MATCH ID	{ $$=mk_elem(	MATCH_OP, STRING_ST,
 											DSTIP_O, $3);
 							}
 		| DSTIP MATCH error  { $$=0; yyerror ( "hostname  expected" ); }
 		| DSTIP error { $$=0; 
 						yyerror("invalid operator, == or ~= expected");}
3c1a8ef8
 	;
 
09e52ebb
 net4:	ipv4 SLASH ipv4	{ $$=mk_net($1, $3); } 
a15c363f
 	| ipv4 SLASH NUMBER {	if (($3>32)|($3<0)){
09e52ebb
 								yyerror("invalid bit number in netmask");
 								$$=0;
 							}else{
 								$$=mk_net($1, (1<<$3)-1);
 							}
 						}
 	| ipv4				{ $$=mk_net($1, 0xffffffff); }
 	| ipv4 SLASH error { $$=0;
 						 yyerror("netmask (eg:255.0.0.0 or 8) expected");}
3c1a8ef8
 	;
 
09e52ebb
 host:	ID				{ $$=$1; }
 	| host DOT ID		{ $$=(char*)malloc(strlen($1)+1+strlen($3)+1);
 						  if ($$==0){
 						  	fprintf(stderr, "memory allocation failure"
 						 				" while parsing host\n");
 						  }else{
 						  	memcpy($$, $1, strlen($1));
 						  	$$[strlen($1)]='.';
 						  	memcpy($$+strlen($1)+1, $3, strlen($3));
 						  	$$[strlen($1)+1+strlen($3)]=0;
 						  }
 						  free($1); free($3);
 						};
 	| host DOT error { $$=0; free($1); yyerror("invalid hostname"); }
3c1a8ef8
 	;
 
 
09e52ebb
 actions:	actions action	{$$=append_action($1, $2); }
 		| action			{$$=$1;}
 		| actions error { $$=0; yyerror("bad command"); }
c07508e2
 	;
 
09e52ebb
 action:		cmd SEMICOLON {$$=$1;}
 		| SEMICOLON /* null action */ {$$=0;}
 		| cmd error { $$=0; yyerror("bad command: missing ';'?"); }
3c1a8ef8
 	;
 
09e52ebb
 cmd:		FORWARD LPAREN host RPAREN	{ $$=mk_action(	FORWARD_T,
 														STRING_ST,
 														NUMBER_ST,
 														$3,
 														0);
 										}
 		| FORWARD LPAREN STRING RPAREN	{ $$=mk_action(	FORWARD_T,
 														STRING_ST,
 														NUMBER_ST,
 														$3,
 														0);
 										}
 		| FORWARD LPAREN ipv4 RPAREN	{ $$=mk_action(	FORWARD_T,
 														IP_ST,
 														NUMBER_ST,
 														(void*)$3,
 														0);
 										}
 		| FORWARD LPAREN host COMMA NUMBER RPAREN { $$=mk_action(FORWARD_T,
 																 STRING_ST,
 																 NUMBER_ST,
 																$3,
 																(void*)$5);
 												 }
 		| FORWARD LPAREN STRING COMMA NUMBER RPAREN {$$=mk_action(FORWARD_T,
 																 STRING_ST,
 																 NUMBER_ST,
 																$3,
 																(void*)$5);
 													}
 		| FORWARD LPAREN ipv4 COMMA NUMBER RPAREN { $$=mk_action(FORWARD_T,
 																 IP_ST,
 																 NUMBER_ST,
 																 (void*)$3,
 																(void*)$5);
 												  }
 		| FORWARD error { $$=0; yyerror("missing '(' or ')' ?"); }
 		| FORWARD LPAREN error RPAREN { $$=0; yyerror("bad forward"
 										"argument"); }
 		| SEND LPAREN host RPAREN	{ $$=mk_action(	SEND_T,
 													STRING_ST,
 													NUMBER_ST,
 													$3,
 													0);
 									}
 		| SEND LPAREN STRING RPAREN { $$=mk_action(	SEND_T,
 													STRING_ST,
 													NUMBER_ST,
 													$3,
 													0);
 									}
 		| SEND LPAREN ipv4 RPAREN	{ $$=mk_action(	SEND_T,
 													IP_ST,
 													NUMBER_ST,
 													(void*)$3,
 													0);
 									}
 		| SEND LPAREN host COMMA NUMBER RPAREN	{ $$=mk_action(	SEND_T,
 																STRING_ST,
 																NUMBER_ST,
 																$3,
 																(void*)$5);
 												}
 		| SEND LPAREN STRING COMMA NUMBER RPAREN {$$=mk_action(	SEND_T,
 																STRING_ST,
 																NUMBER_ST,
 																$3,
 																(void*)$5);
 												}
 		| SEND LPAREN ipv4 COMMA NUMBER RPAREN { $$=mk_action(	SEND_T,
 																IP_ST,
 																NUMBER_ST,
 																(void*)$3,
 																(void*)$5);
 											   }
 		| SEND error { $$=0; yyerror("missing '(' or ')' ?"); }
 		| SEND LPAREN error RPAREN { $$=0; yyerror("bad send"
 													"argument"); }
 		| DROP LPAREN RPAREN	{$$=mk_action(DROP_T,0, 0, 0, 0); }
 		| DROP					{$$=mk_action(DROP_T,0, 0, 0, 0); }
 		| LOG LPAREN STRING RPAREN	{$$=mk_action(	LOG_T, NUMBER_ST, 
 													STRING_ST,(void*)4,$3);
 									}
 		| LOG LPAREN NUMBER COMMA STRING RPAREN	{$$=mk_action(	LOG_T,
 																NUMBER_ST, 
 																STRING_ST,
 																(void*)$3,
 																$5);
 												}
 		| LOG error { $$=0; yyerror("missing '(' or ')' ?"); }
 		| LOG LPAREN error RPAREN { $$=0; yyerror("bad log"
 									"argument"); }
 		| ERROR LPAREN STRING COMMA STRING RPAREN {$$=mk_action(ERROR_T,
 																STRING_ST, 
 																STRING_ST,
 																$3,
 																$5);
 												  }
 												
 		| ERROR error { $$=0; yyerror("missing '(' or ')' ?"); }
 		| ERROR LPAREN error RPAREN { $$=0; yyerror("bad error"
 														"argument"); }
 		| ROUTE LPAREN NUMBER RPAREN	{ $$=mk_action(ROUTE_T, NUMBER_ST,
 														0, (void*)$3, 0);
 										}
 		| ROUTE error { $$=0; yyerror("missing '(' or ')' ?"); }
 		| ROUTE LPAREN error RPAREN { $$=0; yyerror("bad route"
c07508e2
 						"argument"); }
09e52ebb
 		| EXEC LPAREN STRING RPAREN	{ $$=mk_action(	EXEC_T, STRING_ST, 0,
 													$3, 0);
 									}
3c1a8ef8
 	;
 
 
 %%
 
 extern int line;
 extern int column;
09e52ebb
 extern int startcolumn;
3c1a8ef8
 yyerror(char* s)
 {
09e52ebb
 	fprintf(stderr, "parse error (%d,%d-%d): %s\n", line, startcolumn, 
 			column, s);
3c1a8ef8
 }
 
a15c363f
 /*
3c1a8ef8
 int main(int argc, char ** argv)
 {
 	if (yyparse()!=0)
 		fprintf(stderr, "parsing error\n");
 }
a15c363f
 */