Ver Fonte

- config parser + expression builder seem to be working

Andrei Pelinescu-Onciul há 24 anos atrás
pai
commit
09e52ebb78
4 ficheiros alterados com 317 adições e 123 exclusões
  1. 12 6
      cfg.lex
  2. 247 113
      cfg.y
  3. 46 3
      route_struct.c
  4. 12 1
      route_struct.h

+ 12 - 6
cfg.lex

@@ -19,8 +19,9 @@
 	static int comment_nest=0;
 	static int state=0;
 	static char* str=0;
-	int line=0;
-	int column=0;
+	int line=1;
+	int column=1;
+	int startcolumn=1;
 
 	static char* addstr(char*, char**);
 	static void count();
@@ -38,6 +39,7 @@ SEND	send
 LOG		log
 ERROR	error
 ROUTE	route
+EXEC	exec
 /* condition keywords */
 METHOD	method
 URI		uri
@@ -47,7 +49,7 @@ DSTIP	dst_ip
 EQUAL	=
 EQUAL_T	==
 MATCH	~=
-NOT		!
+NOT		!|"not"
 AND		"and"|"&&"|"&"
 OR		"or"|"||"|"|"
 
@@ -101,6 +103,7 @@ EAT_ABLE	[\ \t\b\r]
 <INITIAL>{LOG}	{ count(); yylval.strval=yytext; return LOG; }
 <INITIAL>{ERROR}	{ count(); yylval.strval=yytext; return ERROR; }
 <INITIAL>{ROUTE}	{ count(); yylval.strval=yytext; return ROUTE; }
+<INITIAL>{EXEC}	{ count(); yylval.strval=yytext; return EXEC; }
 
 <INITIAL>{METHOD}	{ count(); yylval.strval=yytext; return METHOD; }
 <INITIAL>{URI}	{ count(); yylval.strval=yytext; return URI; }
@@ -186,7 +189,8 @@ EAT_ABLE	[\ \t\b\r]
 
 <INITIAL>{COM_LINE}.*{CR}	{ count(); } 
 
-<INITIAL>{ID}			{ count(); yylval.strval=yytext; return ID; }
+<INITIAL>{ID}			{ count(); addstr(yytext, &str);
+						  yylval.strval=str; str=0; return ID; }
 
 
 <<EOF>>							{
@@ -237,12 +241,14 @@ static void count()
 {
 	int i;
 	
+	startcolumn=column;
 	for (i=0; i<yyleng;i++){
 		if (yytext[i]=='\n'){
 			line++;
-			column=0;
+			column=startcolumn=1;
 		}else if (yytext[i]=='\t'){
-			column+=8 -(column%8);
+			column++;
+			/*column+=8 -(column%8);*/
 		}else{
 			column++;
 		}

+ 247 - 113
cfg.y

@@ -12,9 +12,11 @@
 
 %union {
 	int intval;
+	unsigned uval;
 	char* strval;
 	struct expr* expr;
 	struct action* action;
+	struct net* net;
 }
 
 /* terminals */
@@ -27,6 +29,8 @@
 %token LOG
 %token ERROR
 %token ROUTE
+%token EXEC
+
 %token METHOD
 %token URI
 %token SRCIP
@@ -45,9 +49,9 @@
 %nonassoc EQUAL
 %nonassoc EQUAL_T
 %nonassoc MATCH
-%left NOT
-%left AND
 %left OR
+%left AND
+%left NOT
 
 /* values */
 %token <intval> NUMBER
@@ -71,6 +75,9 @@
 /*non-terminals */
 %type <expr> exp, condition,  exp_elem
 %type <action> action, actions, cmd
+%type <uval> ipv4
+%type <net> net4
+%type <strval> host
 
 
 
@@ -109,7 +116,19 @@ assign_stm:	DEBUG EQUAL NUMBER
 	;
 
 
-ipv4:	NUMBER DOT NUMBER DOT NUMBER DOT NUMBER
+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;
+											}
+												}
 	;
 
 route_stm:	ROUTE LBRACE rules RBRACE 
@@ -122,140 +141,253 @@ rules:	rules rule
 	| rules error { yyerror("invalid rule"); }
 	 ;
 
-rule:	condition	actions CR
+rule:	condition	actions CR {
+								printf("Got a new rule!\n");
+								printf("expr: "); print_expr($1);
+								printf("\n  -> actions: ");
+								print_action($2); printf("\n");
+							   }
 	| CR  /* null rule */
 	| condition error { yyerror("bad actions in rule"); }
 	;
 
-condition:	exp
+condition:	exp {$$=$1;}
 	;
 
-exp:	exp AND exp 
-	| exp OR  exp 
-	| NOT exp 
-	| LPAREN exp RPAREN
-	| exp_elem
+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; }
 	;
 
-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); 
-				 	}
+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); 
+				 			}
 		| METHOD EQUAL_T error { $$=0; yyerror("string expected"); }
-		| METHOD MATCH STRING 	{$$ = mk_elem(	MATCH_OP,
-							STRING_ST,
-							METHOD_O,
-							$3); 
-				 	}
-		| METHOD MATCH ID	{$$ = mk_elem(	MATCH_OP,
-							STRING_ST,
-							METHOD_O,
-							$3); 
-				 	}
+		| METHOD MATCH STRING	{$$ = mk_elem(	MATCH_OP, STRING_ST,
+												METHOD_O, $3); 
+				 				}
+		| METHOD MATCH ID	{$$ = mk_elem(	MATCH_OP, STRING_ST,
+											METHOD_O, $3); 
+				 			}
 		| METHOD MATCH error { $$=0; yyerror("string expected"); }
-		| 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); 
-				 	}
+		| 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); 
+				 			}
 		| URI EQUAL_T error { $$=0; yyerror("string expected"); }
-		| URI MATCH STRING 
-		| URI MATCH ID
+		| URI MATCH STRING	{ $$=mk_elem(	MATCH_OP, STRING_ST,
+											URI_O, $3);
+							}
+		| URI MATCH ID		{ $$=mk_elem(	MATCH_OP, STRING_ST,
+											URI_O, $3);
+							}
 		| URI MATCH error {  $$=0; yyerror("string expected"); }
-		| URI error	{ $$=0; 
-				  yyerror("invalid operator,"
-				  		" == or ~= expected");
-				}
-		| SRCIP EQUAL_T net4 
-		| SRCIP EQUAL_T STRING 
-		| SRCIP EQUAL_T host
-		| SRCIP EQUAL_T error { yyerror( "ip address or hostname"
-						 "expected" ); }
-		| SRCIP MATCH STRING
-		| SRCIP MATCH ID
-		| SRCIP MATCH error  { yyerror( "hostname expected"); }
-		| SRCIP error  {yyerror("invalid operator, == or ~= expected");}
-		| DSTIP EQUAL_T net4 
-		| DSTIP EQUAL_T STRING
-		| DSTIP EQUAL_T host
-		| DSTIP EQUAL_T error { yyerror( "ip address or hostname"
+		| 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"
 						 "expected" ); }
-		| DSTIP MATCH STRING
-		| DSTIP MATCH ID
-		| DSTIP MATCH error  { yyerror ( "hostname  expected" ); }
-		| DSTIP error {yyerror("invalid operator, == or ~= expected");}
+		| 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");}
 	;
 
-net4:	ipv4 SLASH ipv4 
-	| ipv4 SLASH NUMBER 
-	| ipv4
-	| ipv4 SLASH error {yyerror("netmask (eg:255.0.0.0 or 8) expected");}
+net4:	ipv4 SLASH ipv4	{ $$=mk_net($1, $3); } 
+	| ipv4 SLASH NUMBER {	if (($3>32)|($3<1)){
+								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");}
 	;
 
-host:	ID
-	| host DOT ID
-	| host DOT error { yyerror("invalid hostname"); }
+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"); }
 	;
 
 
-actions:	actions action 
-		| action
-		| actions error { yyerror("bad command"); }
+actions:	actions action	{$$=append_action($1, $2); }
+		| action			{$$=$1;}
+		| actions error { $$=0; yyerror("bad command"); }
 	;
 
-action:		cmd SEMICOLON
-		| SEMICOLON /* null action */
-		| cmd error { yyerror("bad command: missing ';'?"); }
+action:		cmd SEMICOLON {$$=$1;}
+		| SEMICOLON /* null action */ {$$=0;}
+		| cmd error { $$=0; yyerror("bad command: missing ';'?"); }
 	;
 
-cmd:		FORWARD LPAREN host RPAREN 
-		| FORWARD LPAREN STRING RPAREN 
-		| FORWARD LPAREN ipv4 RPAREN 
-		| FORWARD LPAREN host COMMA NUMBER RPAREN
-		| FORWARD LPAREN STRING COMMA NUMBER RPAREN
-		| FORWARD LPAREN ipv4 COMMA NUMBER RPAREN
-		| FORWARD error { yyerror("missing '(' or ')' ?"); }
-		| FORWARD LPAREN error RPAREN { yyerror("bad forward"
-						"argument"); }
-		| SEND LPAREN host RPAREN 
-		| SEND LPAREN STRING RPAREN 
-		| SEND LPAREN ipv4 RPAREN
-		| SEND LPAREN host COMMA NUMBER RPAREN
-		| SEND LPAREN STRING COMMA NUMBER RPAREN
-		| SEND LPAREN ipv4 COMMA NUMBER RPAREN
-		| SEND error { yyerror("missing '(' or ')' ?"); }
-		| SEND LPAREN error RPAREN { yyerror("bad send"
-						"argument"); }
-		| DROP LPAREN RPAREN 
-		| DROP 
-		| LOG LPAREN STRING RPAREN
-		| LOG LPAREN NUMBER COMMA STRING RPAREN
-		| LOG error { yyerror("missing '(' or ')' ?"); }
-		| LOG LPAREN error RPAREN { yyerror("bad log"
-						"argument"); }
-		| ERROR LPAREN STRING COMMA STRING RPAREN 
-		| ERROR error { yyerror("missing '(' or ')' ?"); }
-		| ERROR LPAREN error RPAREN { yyerror("bad error"
-						"argument"); }
-		| ROUTE LPAREN NUMBER RPAREN
-		| ROUTE error { yyerror("missing '(' or ')' ?"); }
-		| ROUTE LPAREN error RPAREN { yyerror("bad route"
+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"
 						"argument"); }
+		| EXEC LPAREN STRING RPAREN	{ $$=mk_action(	EXEC_T, STRING_ST, 0,
+													$3, 0);
+									}
 	;
 
 
@@ -263,9 +395,11 @@ cmd:		FORWARD LPAREN host RPAREN
 
 extern int line;
 extern int column;
+extern int startcolumn;
 yyerror(char* s)
 {
-	fprintf(stderr, "parse error (%d,%d): %s\n", line, column, s);
+	fprintf(stderr, "parse error (%d,%d-%d): %s\n", line, startcolumn, 
+			column, s);
 }
 
 int main(int argc, char ** argv)

+ 46 - 3
route_struct.c

@@ -8,6 +8,7 @@
 #include  "route_struct.h"
 
 #include <stdio.h>
+#include <netinet/in.h>
 
 struct expr* mk_exp(int op, struct expr* left, struct expr* right)
 {
@@ -74,8 +75,46 @@ struct action* append_action(struct action* a, struct action* b)
 	return a;
 }
 
+
+
+struct net* mk_net(unsigned long ip, unsigned long mask)
+{
+	struct net* n;
+
+	n=(struct net*)malloc(sizeof(struct net));
+	if (n==0) goto error;
+	n->ip=ip;
+	n->mask=mask;
+	return n;
+error:
+	fprintf(stderr, "ERROR: mk_net_mask: memory allocation failure\n");
+	return 0;
+}
+
 	
 	
+
+void print_ip(unsigned ip)
+{
+	ip=htonl(ip);
+	printf("%d.%d.%d.%d", ((unsigned char*)&ip)[0],
+						  ((unsigned char*)&ip)[1],
+						  ((unsigned char*)&ip)[2],
+						  ((unsigned char*)&ip)[3]);
+}
+
+
+void print_net(struct net* net)
+{
+	if (net==0){
+		fprintf(stderr, "ERROR: print net: null pointer\n");
+		return;
+	}
+	print_ip(net->ip); printf("/"); print_ip(net->mask);
+}
+
+
+
 void print_expr(struct expr* exp)
 {
 	if (exp==0){
@@ -105,8 +144,9 @@ void print_expr(struct expr* exp)
 				break;
 			case MATCH_OP:
 				printf("~=");
+				break;
 			default:
-				priint("<UNKNOWN>");
+				printf("<UNKNOWN>");
 		}
 		switch(exp->subtype){
 			case NOSUBTYPE: 
@@ -116,10 +156,13 @@ void print_expr(struct expr* exp)
 					printf("\"%s\"", (char*)exp->r.param);
 					break;
 			case NET_ST:
-					printf("");
+					print_net((struct net*)exp->r.param);
+					break;
+			case IP_ST:
+					print_ip(exp->r.intval);
 					break;
 			default:
-					prinf("UNKNOWN");
+					printf("UNKNOWN");
 		}
 	}else if (exp->type==EXP_T){
 		switch(exp->op){

+ 12 - 1
route_struct.h

@@ -11,7 +11,7 @@ enum { AND_OP=1, OR_OP, NOT_OP };
 enum { EQUAL_OP=10, MATCH_OP };
 enum { METHOD_O=1, URI_O, SRCIP_O, DSTIP_O };
 
-enum { FORWARD_T=1, SEND_T, DROP_T, LOG_T, ERROR_T};
+enum { FORWARD_T=1, SEND_T, DROP_T, LOG_T, ERROR_T, ROUTE_T, EXEC_T};
 enum { NOSUBTYPE=0, STRING_ST, NET_ST, NUMBER_ST, IP_ST };
 
 	
@@ -26,6 +26,7 @@ struct expr{
 	union {
 		struct expr* expr;
 		void* param;
+		int   intval;
 	}r;
 };
 
@@ -42,9 +43,19 @@ struct action{
 	struct action* next;
 };
 
+
+struct net{
+	unsigned long ip;
+	unsigned long mask;
+};
+
 struct expr* mk_exp(int op, struct expr* left, struct expr* right);
 struct expr* mk_elem(int op, int subtype, int operand, void* param);
 struct action* mk_action(int type, int p1_type, int p2_type, void* p1, void* p2);
+struct action* append_action(struct action* a, struct action* b);
+
+
+struct net* mk_net(unsigned long ip, unsigned long mask);
 
 void print_action(struct action* a);
 void print_expr(struct expr* exp);