cfg.y
3c1a8ef8
 /*
  * $Id$
  *
  *  cfg grammar
2d4b798e
  *
  * Copyright (C) 2001-2003 Fhg Fokus
  *
  * This file is part of ser, a free SIP server.
  *
  * ser is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
  * For a license to use the ser software under conditions
  * other than those described here, or to purchase support for this
  * software, please contact iptel.org by e-mail at the following addresses:
  *    info@iptel.org
  *
  * ser is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License 
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
  * History:
  * ---------
049f64c2
  * 2003-01-29 src_port added (jiri)
2d4b798e
  * 2003-01-23 mhomed added (jiri)
  */
 
3c1a8ef8
 
 %{
 
3e429f5c
 #include <stdlib.h>
63fa628f
 #include <stdio.h>
c75aa645
 #include <sys/types.h>
7268726e
 #include <sys/socket.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
f20a56a2
 #include <string.h>
4e2fdd79
 #include <errno.h>
c07508e2
 #include "route_struct.h"
3e429f5c
 #include "globals.h"
 #include "route.h"
7268726e
 #include "dprint.h"
3bf76e49
 #include "sr_module.h"
31309a3a
 #include "modparam.h"
4e2fdd79
 #include "ip_addr.h"
e278821b
 #include "name_alias.h"
3e429f5c
 
1f377e97
 #include "config.h"
f571aa35
 
03150098
 #ifdef DEBUG_DMALLOC
 #include <dmalloc.h>
 #endif
 
f3f0a4de
 /* hack to avoid alloca usage in the generated C file (needed for compiler
  with no built in alloca, like icc*/
 #undef _ALLOCA_H
1f377e97
 
57e2cd15
 struct id_list{
 	char* s;
 	struct id_list* next;
 };
 
e22bbdb8
 extern int yylex();
3e429f5c
 void yyerror(char* s);
7268726e
 char* tmp;
3bf76e49
 void* f_tmp;
57e2cd15
 struct id_list* lst_tmp;
 
c07508e2
 
3c1a8ef8
 %}
 
 %union {
9a694681
 	long intval;
 	unsigned long uval;
3c1a8ef8
 	char* strval;
c07508e2
 	struct expr* expr;
 	struct action* action;
4e2fdd79
 	struct net* ipnet;
 	struct ip_addr* ipaddr;
57e2cd15
 	struct id_list* idlst;
3c1a8ef8
 }
 
 /* terminals */
 
 
3e429f5c
 /* keywords */
3c1a8ef8
 %token FORWARD
0c5da34b
 %token FORWARD_TCP
f2f969dd
 %token FORWARD_UDP
3c1a8ef8
 %token SEND
0c5da34b
 %token SEND_TCP
3c1a8ef8
 %token DROP
7268726e
 %token LOG_TOK
3c1a8ef8
 %token ERROR
 %token ROUTE
caf80ae6
 %token REPLY_ROUTE
09e52ebb
 %token EXEC
7268726e
 %token SET_HOST
 %token SET_HOSTPORT
1f377e97
 %token PREFIX
 %token STRIP
caf80ae6
 %token APPEND_BRANCH
7268726e
 %token SET_USER
 %token SET_USERPASS
 %token SET_PORT
 %token SET_URI
caf80ae6
 %token REVERT_URI
f20a56a2
 %token IF
 %token ELSE
5ada8f8a
 %token URIHOST
 %token URIPORT
1f377e97
 %token MAX_LEN
3881f12c
 %token SETFLAG
 %token RESETFLAG
 %token ISFLAGSET
1f377e97
 %token LEN_GT
3c1a8ef8
 %token METHOD
 %token URI
 %token SRCIP
049f64c2
 %token SRCPORT
3c1a8ef8
 %token DSTIP
855c2e68
 %token MYSELF
3c1a8ef8
 
 /* config vars. */
 %token DEBUG
 %token FORK
 %token LOGSTDERROR
 %token LISTEN
e278821b
 %token ALIAS
3c1a8ef8
 %token DNS
 %token REV_DNS
7268726e
 %token PORT
f571aa35
 %token STAT
7268726e
 %token CHILDREN
 %token CHECK_VIA
caf80ae6
 %token SYN_BRANCH
843b2927
 %token MEMLOG
caf80ae6
 %token SIP_WARNING
 %token FIFO
 %token FIFO_MODE
 %token SERVER_SIGNATURE
 %token REPLY_TO_VIA
3bf76e49
 %token LOADMODULE
31309a3a
 %token MODPARAM
c3ce2841
 %token MAXBUFFER
054cb6cf
 %token USER
 %token GROUP
2d4b798e
 %token MHOMED
7268726e
 
3c1a8ef8
 
 
 /* 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
4e2fdd79
 %token <strval> IPV6ADDR
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 */
ca6ef89b
 %type <expr> exp exp_elem /*, condition*/
 %type <action> action actions cmd if_cmd stm
 %type <ipaddr> ipv4 ipv6 ip
4e2fdd79
 %type <ipnet> ipnet
09e52ebb
 %type <strval> host
57e2cd15
 %type <strval> listen_id
 %type <idlst>  id_lst
f20a56a2
 /*%type <route_el> rules;
   %type <route_el> rule;
 */
3c1a8ef8
 
 
 
 %%
 
 
 cfg:	statements
 	;
 
3e429f5c
 statements:	statements statement {}
 		| statement {}
 		| statements error { yyerror(""); YYABORT;}
3c1a8ef8
 	;
 
7268726e
 statement:	assign_stm 
3bf76e49
 		| module_stm
7268726e
 		| route_stm 
caf80ae6
 		| reply_route_stm
c07508e2
 		| CR	/* null statement*/
3c1a8ef8
 	;
 
57e2cd15
 listen_id:	ip			{	tmp=ip_addr2a($1);
 		 					if(tmp==0){
 								LOG(L_CRIT, "ERROR: cfg. parser: bad ip "
 										"addresss.\n");
 								$$=0;
 							}else{
 								$$=malloc(strlen(tmp)+1);
 								if ($$==0){
 									LOG(L_CRIT, "ERROR: cfg. parser: out of "
 											"memory.\n");
 								}else{
 									strncpy($$, tmp, strlen(tmp)+1);
 								}
 							}
 						}
 		 |	ID			{	$$=malloc(strlen($1)+1);
 		 					if ($$==0){
 									LOG(L_CRIT, "ERROR: cfg. parser: out of "
 											"memory.\n");
 							}else{
 									strncpy($$, $1, strlen($1)+1);
 							}
 						}
 		 |	STRING			{	$$=malloc(strlen($1)+1);
 		 					if ($$==0){
 									LOG(L_CRIT, "ERROR: cfg. parser: out of "
 											"memory.\n");
 							}else{
 									strncpy($$, $1, strlen($1)+1);
 							}
 						}
 		 |	host		{	$$=malloc(strlen($1)+1);
 		 					if ($$==0){
 									LOG(L_CRIT, "ERROR: cfg. parser: out of "
 											"memory.\n");
 							}else{
 									strncpy($$, $1, strlen($1)+1);
 							}
 						}
 	;
 
 id_lst:	  listen_id	{	$$=malloc(sizeof(struct id_list));
 						if ($$==0){
 							LOG(L_CRIT,"ERROR: cfg. parser: out of memory.\n");
 						}else{
 							$$->s=$1;
 							$$->next=0;
 						}
 					}
 		| listen_id id_lst	{
 						$$=malloc(sizeof(struct id_list));
 						if ($$==0){
 							LOG(L_CRIT,"ERROR: cfg. parser: out of memory.\n");
 						}else{
 							$$->s=$1;
 							$$->next=$2;
 						}
 							}
 		;
 
 
7268726e
 assign_stm:	DEBUG EQUAL NUMBER { debug=$3; }
c07508e2
 		| DEBUG EQUAL error  { yyerror("number  expected"); }
7268726e
 		| FORK  EQUAL NUMBER { dont_fork= ! $3; }
c07508e2
 		| FORK  EQUAL error  { yyerror("boolean value expected"); }
7268726e
 		| LOGSTDERROR EQUAL NUMBER { log_stderr=$3; }
c07508e2
 		| LOGSTDERROR EQUAL error { yyerror("boolean value expected"); }
7268726e
 		| DNS EQUAL NUMBER   { received_dns|= ($3)?DO_DNS:0; }
c07508e2
 		| DNS EQUAL error { yyerror("boolean value expected"); }
7268726e
 		| REV_DNS EQUAL NUMBER { received_dns|= ($3)?DO_REV_DNS:0; }
c07508e2
 		| REV_DNS EQUAL error { yyerror("boolean value expected"); }
36ef0329
 		| PORT EQUAL NUMBER   { port_no=$3; 
 								if (sock_no>0) 
 									sock_info[sock_no-1].port_no=port_no;
 							  }
e4067ffb
 		| STAT EQUAL STRING {
 					#ifdef STATS
 							stat_file=$3;
 					#endif
 							}
c3ce2841
 		| MAXBUFFER EQUAL NUMBER { maxbuffer=$3; }
 		| MAXBUFFER EQUAL error { yyerror("number expected"); }
7268726e
 		| PORT EQUAL error    { yyerror("number expected"); } 
 		| CHILDREN EQUAL NUMBER { children_no=$3; }
 		| CHILDREN EQUAL error { yyerror("number expected"); } 
 		| CHECK_VIA EQUAL NUMBER { check_via=$3; }
 		| CHECK_VIA EQUAL error { yyerror("boolean value expected"); }
caf80ae6
 		| SYN_BRANCH EQUAL NUMBER { syn_branch=$3; }
 		| SYN_BRANCH EQUAL error { yyerror("boolean value expected"); }
843b2927
 		| MEMLOG EQUAL NUMBER { memlog=$3; }
 		| MEMLOG EQUAL error { yyerror("int value expected"); }
caf80ae6
 		| SIP_WARNING EQUAL NUMBER { sip_warning=$3; }
 		| SIP_WARNING EQUAL error { yyerror("boolean value expected"); }
 		| FIFO EQUAL STRING { fifo=$3; }
 		| FIFO EQUAL error { yyerror("string value expected"); }
 		| FIFO_MODE EQUAL NUMBER { fifo_mode=$3; }
054cb6cf
 		| FIFO_MODE EQUAL error { yyerror("int value expected"); }
 		| USER EQUAL STRING     { user=$3; }
 		| USER EQUAL ID         { user=$3; }
 		| USER EQUAL error      { yyerror("string value expected"); }
 		| GROUP EQUAL STRING     { group=$3; }
 		| GROUP EQUAL ID         { group=$3; }
 		| GROUP EQUAL error      { yyerror("string value expected"); }
2d4b798e
 		| MHOMED EQUAL NUMBER { mhomed=$3; }
 		| MHOMED EQUAL error { yyerror("boolean value expected"); }
caf80ae6
 		| SERVER_SIGNATURE EQUAL NUMBER { server_signature=$3; }
 		| SERVER_SIGNATURE EQUAL error { yyerror("boolean value expected"); }
 		| REPLY_TO_VIA EQUAL NUMBER { reply_to_via=$3; }
 		| REPLY_TO_VIA EQUAL error { yyerror("boolean value expected"); }
57e2cd15
 		| LISTEN EQUAL id_lst {
 							for(lst_tmp=$3; lst_tmp; lst_tmp=lst_tmp->next){
36ef0329
 								if (sock_no < MAX_LISTEN){
 									sock_info[sock_no].name.s=
57e2cd15
 										(char*)malloc(strlen(lst_tmp->s)+1);
36ef0329
 									if (sock_info[sock_no].name.s==0){
f20a56a2
 										LOG(L_CRIT, "ERROR: cfg. parser:"
 													" out of memory.\n");
57e2cd15
 										break;
7268726e
 									}else{
57e2cd15
 										strncpy(sock_info[sock_no].name.s,
 												lst_tmp->s,
 												strlen(lst_tmp->s)+1);
 										sock_info[sock_no].name.len=
 													strlen(lst_tmp->s);
36ef0329
 										sock_info[sock_no].port_no=port_no;
 										sock_no++;
7268726e
 									}
 								}else{
f20a56a2
 									LOG(L_CRIT, "ERROR: cfg. parser: "
 												"too many listen addresses"
7268726e
 												"(max. %d).\n", MAX_LISTEN);
57e2cd15
 									break;
7268726e
 								}
57e2cd15
 							}
 							 }
c07508e2
 		| LISTEN EQUAL  error { yyerror("ip address or hostname"
 						"expected"); }
57e2cd15
 		| ALIAS EQUAL  id_lst { 
1baa06b5
 							for(lst_tmp=$3; lst_tmp; lst_tmp=lst_tmp->next)
 								add_alias(lst_tmp->s, strlen(lst_tmp->s), 0);
57e2cd15
 							  }
e278821b
 		| ALIAS  EQUAL error  { yyerror(" hostname expected"); }
c07508e2
 		| error EQUAL { yyerror("unknown config variable"); }
3c1a8ef8
 	;
 
96001c50
 module_stm:	LOADMODULE STRING	{ DBG("loading module %s\n", $2);
3bf76e49
 		  						  if (load_module($2)!=0){
 								  		yyerror("failed to load module");
 								  }
 								}
31309a3a
 		 | LOADMODULE error	{ yyerror("string expected");  }
                  | MODPARAM LPAREN STRING COMMA STRING COMMA STRING RPAREN {
 			 if (set_mod_param($3, $5, STR_PARAM, $7) != 0) {
 				 yyerror("Can't set module parameter");
 			 }
 		   }
                  | MODPARAM LPAREN STRING COMMA STRING COMMA NUMBER RPAREN {
 			 if (set_mod_param($3, $5, INT_PARAM, (void*)$7) != 0) {
 				 yyerror("Can't set module parameter");
 			 }
 		   }
                  | MODPARAM error { yyerror("Invalid arguments"); }
3bf76e49
 		 ;
 
3c1a8ef8
 
4e2fdd79
 ip:		 ipv4  { $$=$1; }
 		|ipv6  { $$=$1; }
 		;
 
09e52ebb
 ipv4:	NUMBER DOT NUMBER DOT NUMBER DOT NUMBER { 
4e2fdd79
 											$$=malloc(sizeof(struct ip_addr));
 											if ($$==0){
 												LOG(L_CRIT, "ERROR: cfg. "
 													"parser: out of memory.\n"
 													);
09e52ebb
 											}else{
4e2fdd79
 												memset($$, 0, 
 													sizeof(struct ip_addr));
 												$$->af=AF_INET;
 												$$->len=4;
 												if (($1>255) || ($1<0) ||
 													($3>255) || ($3<0) ||
 													($5>255) || ($5<0) ||
 													($7>255) || ($7<0)){
 													yyerror("invalid ipv4"
 															"address");
 													$$->u.addr32[0]=0;
 													/* $$=0; */
 												}else{
 													$$->u.addr[0]=$1;
 													$$->u.addr[1]=$3;
 													$$->u.addr[2]=$5;
 													$$->u.addr[3]=$7;
 													/*
 													$$=htonl( ($1<<24)|
3e429f5c
 													($3<<16)| ($5<<8)|$7 );
4e2fdd79
 													*/
 												}
09e52ebb
 											}
 												}
3c1a8ef8
 	;
 
4e2fdd79
 ipv6:	IPV6ADDR {
 					$$=malloc(sizeof(struct ip_addr));
 					if ($$==0){
 						LOG(L_CRIT, "ERROR: cfg. parser: out of memory.\n");
 					}else{
 						memset($$, 0, sizeof(struct ip_addr));
 						$$->af=AF_INET6;
 						$$->len=16;
381659ac
 					#ifdef USE_IPV6
4e2fdd79
 						if (inet_pton(AF_INET6, $1, $$->u.addr)<=0){
 							yyerror("bad ipv6 address");
 						}
381659ac
 					#else
 						yyerror("ipv6 address & no ipv6 support compiled in");
 						YYABORT;
 					#endif
4e2fdd79
 					}
 				}
 	;
 
 
f20a56a2
 route_stm:	ROUTE LBRACE actions RBRACE { push($3, &rlist[DEFAULT_RT]); }
3e429f5c
 
f20a56a2
 		| ROUTE LBRACK NUMBER RBRACK LBRACE actions RBRACE { 
3e429f5c
 										if (($3<RT_NO) && ($3>=0)){
 											push($6, &rlist[$3]);
 										}else{
 											yyerror("invalid routing"
 													"table number");
 											YYABORT; }
 										}
c07508e2
 		| ROUTE error { yyerror("invalid  route  statement"); }
3c1a8ef8
 	;
caf80ae6
 
 reply_route_stm: REPLY_ROUTE LBRACK NUMBER RBRACK LBRACE actions RBRACE {
 										if (($3<REPLY_RT_NO)&&($3>=1)){
 											push($6, &reply_rlist[$3]);
 										} else {
 											yyerror("invalid reply routing"
 												"table number");
 											YYABORT; }
 										}
 		| REPLY_ROUTE error { yyerror("invalid reply_route statement"); }
 	;
f20a56a2
 /*
7268726e
 rules:	rules rule { push($2, &$1); $$=$1; }
 	| rule {$$=$1; }
3e429f5c
 	| rules error { $$=0; yyerror("invalid rule"); }
3c1a8ef8
 	 ;
 
09e52ebb
 rule:	condition	actions CR {
3e429f5c
 								$$=0;
 								if (add_rule($1, $2, &$$)<0) {
 									yyerror("error calling add_rule");
 									YYABORT;
 								}
 							  }
f20a56a2
 	| CR		{ $$=0;}
3e429f5c
 	| condition error { $$=0; yyerror("bad actions in rule"); }
3c1a8ef8
 	;
 
09e52ebb
 condition:	exp {$$=$1;}
f20a56a2
 */
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,"
7268726e
 										"== or =~ expected");
09e52ebb
 						}
 		| 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); 
 				 			}
855c2e68
 		| URI EQUAL_T MYSELF    { $$=mk_elem(	EQUAL_OP, MYSELF_ST,
 												URI_O, 0);
 								}
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,"
7268726e
 				  					" == or =~ expected");
09e52ebb
 					}
049f64c2
 		| SRCPORT EQUAL_T NUMBER	{ $$=mk_elem(	EQUAL_OP, NUMBER_ST,
 												SRCPORT_O, (void *) $3 ); }
 		| SRCPORT EQUAL_T error { $$=0; yyerror("number expected"); }
 		| SRCPORT error { $$=0; yyerror("equation operator expected"); }
4e2fdd79
 		| SRCIP EQUAL_T ipnet	{ $$=mk_elem(	EQUAL_OP, NET_ST,
09e52ebb
 												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);
 								}
855c2e68
 		| SRCIP EQUAL_T MYSELF  { $$=mk_elem(	EQUAL_OP, MYSELF_ST,
 												SRCIP_O, 0);
 								}
09e52ebb
 		| 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; 
7268726e
 						 yyerror("invalid operator, == or =~ expected");}
4e2fdd79
 		| DSTIP EQUAL_T ipnet	{ $$=mk_elem(	EQUAL_OP, NET_ST,
09e52ebb
 												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);
 								}
855c2e68
 		| DSTIP EQUAL_T MYSELF  { $$=mk_elem(	EQUAL_OP, MYSELF_ST,
 												DSTIP_O, 0);
 								}
09e52ebb
 		| 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; 
7268726e
 						yyerror("invalid operator, == or =~ expected");}
855c2e68
 		| MYSELF EQUAL_T URI    { $$=mk_elem(	EQUAL_OP, MYSELF_ST,
 												URI_O, 0);
 								}
 		| MYSELF EQUAL_T SRCIP  { $$=mk_elem(	EQUAL_OP, MYSELF_ST,
 												SRCIP_O, 0);
 								}
 		| MYSELF EQUAL_T DSTIP  { $$=mk_elem(	EQUAL_OP, MYSELF_ST,
 												DSTIP_O, 0);
 								}
 		| MYSELF EQUAL_T error {	$$=0; 
 									yyerror(" URI, SRCIP or DSTIP expected"); }
 		| MYSELF error	{ $$=0; yyerror ("invalid operator, == expected"); }
f20a56a2
 		| stm				{ $$=mk_elem( NO_OP, ACTIONS_ST, ACTION_O, $1 ); }
 		| NUMBER		{$$=mk_elem( NO_OP, NUMBER_ST, NUMBER_O, (void*)$1 ); }
3c1a8ef8
 	;
 
4e2fdd79
 ipnet:	ip SLASH ip	{ $$=mk_net($1, $3); } 
 	| ip SLASH NUMBER 	{	if (($3<0) || ($3>$1->len*8)){
09e52ebb
 								yyerror("invalid bit number in netmask");
 								$$=0;
 							}else{
4e2fdd79
 								$$=mk_net_bitlen($1, $3);
 							/*
f20a56a2
 								$$=mk_net($1, 
 										htonl( ($3)?~( (1<<(32-$3))-1 ):0 ) );
4e2fdd79
 							*/
09e52ebb
 							}
 						}
4e2fdd79
 	| ip				{ $$=mk_net_bitlen($1, $1->len*8); }
 	| ip 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){
f20a56a2
 						  	LOG(L_CRIT, "ERROR: cfg. parser: memory allocation"
 										" failure while parsing host\n");
09e52ebb
 						  }else{
 						  	memcpy($$, $1, strlen($1));
 						  	$$[strlen($1)]='.';
 						  	memcpy($$+strlen($1)+1, $3, strlen($3));
 						  	$$[strlen($1)+1+strlen($3)]=0;
 						  }
 						  free($1); free($3);
ca6ef89b
 						}
09e52ebb
 	| host DOT error { $$=0; free($1); yyerror("invalid hostname"); }
3c1a8ef8
 	;
 
 
f20a56a2
 stm:		cmd						{ $$=$1; }
 		|	LBRACE actions RBRACE	{ $$=$2; }
 	;
 
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
 	;
 
f20a56a2
 if_cmd:		IF exp stm				{ $$=mk_action3( IF_T,
 													 EXPR_ST,
 													 ACTIONS_ST,
 													 NOSUBTYPE,
 													 $2,
 													 $3,
 													 0);
 									}
 		|	IF exp stm ELSE stm		{ $$=mk_action3( IF_T,
 													 EXPR_ST,
 													 ACTIONS_ST,
 													 ACTIONS_ST,
 													 $2,
 													 $3,
 													 $5);
 									}
 	;
 
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);
 										}
4e2fdd79
 		| FORWARD LPAREN ip RPAREN	{ $$=mk_action(	FORWARD_T,
09e52ebb
 														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);
 													}
4e2fdd79
 		| FORWARD LPAREN ip COMMA NUMBER RPAREN { $$=mk_action(FORWARD_T,
09e52ebb
 																 IP_ST,
 																 NUMBER_ST,
 																 (void*)$3,
 																(void*)$5);
 												  }
5ada8f8a
 		| FORWARD LPAREN URIHOST COMMA URIPORT RPAREN {
 													$$=mk_action(FORWARD_T,
 																 URIHOST_ST,
 																 URIPORT_ST,
 																0,
 																0);
 													}
 													
 									
 		| FORWARD LPAREN URIHOST COMMA NUMBER RPAREN {
 													$$=mk_action(FORWARD_T,
 																 URIHOST_ST,
 																 NUMBER_ST,
 																0,
 																(void*)$5);
 													}
 		| FORWARD LPAREN URIHOST RPAREN {
 													$$=mk_action(FORWARD_T,
 																 URIHOST_ST,
 																 NUMBER_ST,
 																0,
 																0);
 										}
09e52ebb
 		| FORWARD error { $$=0; yyerror("missing '(' or ')' ?"); }
 		| FORWARD LPAREN error RPAREN { $$=0; yyerror("bad forward"
 										"argument"); }
f2f969dd
 		| FORWARD_UDP LPAREN host RPAREN	{ $$=mk_action(	FORWARD_UDP_T,
 														STRING_ST,
 														NUMBER_ST,
 														$3,
 														0);
 										}
 		| FORWARD_UDP LPAREN STRING RPAREN	{ $$=mk_action(	FORWARD_UDP_T,
 														STRING_ST,
 														NUMBER_ST,
 														$3,
 														0);
 										}
 		| FORWARD_UDP LPAREN ip RPAREN	{ $$=mk_action(	FORWARD_UDP_T,
 														IP_ST,
 														NUMBER_ST,
 														(void*)$3,
 														0);
 										}
 		| FORWARD_UDP LPAREN host COMMA NUMBER RPAREN { $$=mk_action(
 																FORWARD_UDP_T,
 																 STRING_ST,
 																 NUMBER_ST,
 																$3,
 																(void*)$5);
 												 }
 		| FORWARD_UDP LPAREN STRING COMMA NUMBER RPAREN {$$=mk_action(
 																FORWARD_UDP_T,
 																 STRING_ST,
 																 NUMBER_ST,
 																$3,
 																(void*)$5);
 													}
 		| FORWARD_UDP LPAREN ip COMMA NUMBER RPAREN { $$=mk_action(
 																FORWARD_UDP_T,
 																 IP_ST,
 																 NUMBER_ST,
 																 (void*)$3,
 																(void*)$5);
 												  }
 		| FORWARD_UDP LPAREN URIHOST COMMA URIPORT RPAREN {
 													$$=mk_action(FORWARD_UDP_T,
 																 URIHOST_ST,
 																 URIPORT_ST,
 																0,
 																0);
 													}
 													
 									
 		| FORWARD_UDP LPAREN URIHOST COMMA NUMBER RPAREN {
 													$$=mk_action(FORWARD_UDP_T,
 																 URIHOST_ST,
 																 NUMBER_ST,
 																0,
 																(void*)$5);
 													}
 		| FORWARD_UDP LPAREN URIHOST RPAREN {
 													$$=mk_action(FORWARD_UDP_T,
 																 URIHOST_ST,
 																 NUMBER_ST,
 																0,
 																0);
 										}
 		| FORWARD_UDP error { $$=0; yyerror("missing '(' or ')' ?"); }
 		| FORWARD_UDP LPAREN error RPAREN { $$=0; yyerror("bad forward_udp"
 										"argument"); }
 		| FORWARD_TCP LPAREN host RPAREN	{ $$=mk_action(	FORWARD_TCP_T,
 														STRING_ST,
 														NUMBER_ST,
 														$3,
 														0);
 										}
 		| FORWARD_TCP LPAREN STRING RPAREN	{ $$=mk_action(	FORWARD_TCP_T,
 														STRING_ST,
 														NUMBER_ST,
 														$3,
 														0);
 										}
 		| FORWARD_TCP LPAREN ip RPAREN	{ $$=mk_action(	FORWARD_TCP_T,
 														IP_ST,
 														NUMBER_ST,
 														(void*)$3,
 														0);
 										}
 		| FORWARD_TCP LPAREN host COMMA NUMBER RPAREN { $$=mk_action(
 																FORWARD_TCP_T,
 																 STRING_ST,
 																 NUMBER_ST,
 																$3,
 																(void*)$5);
 												 }
 		| FORWARD_TCP LPAREN STRING COMMA NUMBER RPAREN {$$=mk_action(
 																FORWARD_TCP_T,
 																 STRING_ST,
 																 NUMBER_ST,
 																$3,
 																(void*)$5);
 													}
 		| FORWARD_TCP LPAREN ip COMMA NUMBER RPAREN { $$=mk_action(FORWARD_TCP_T,
 																 IP_ST,
 																 NUMBER_ST,
 																 (void*)$3,
 																(void*)$5);
 												  }
 		| FORWARD_TCP LPAREN URIHOST COMMA URIPORT RPAREN {
 													$$=mk_action(FORWARD_TCP_T,
 																 URIHOST_ST,
 																 URIPORT_ST,
 																0,
 																0);
 													}
 													
 									
 		| FORWARD_TCP LPAREN URIHOST COMMA NUMBER RPAREN {
 													$$=mk_action(FORWARD_TCP_T,
 																 URIHOST_ST,
 																 NUMBER_ST,
 																0,
 																(void*)$5);
 													}
 		| FORWARD_TCP LPAREN URIHOST RPAREN {
 													$$=mk_action(FORWARD_TCP_T,
 																 URIHOST_ST,
 																 NUMBER_ST,
 																0,
 																0);
 										}
 		| FORWARD_TCP error { $$=0; yyerror("missing '(' or ')' ?"); }
 		| FORWARD_TCP LPAREN error RPAREN { $$=0; yyerror("bad forward_tcp"
 										"argument"); }
09e52ebb
 		| 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);
 									}
4e2fdd79
 		| SEND LPAREN ip RPAREN		{ $$=mk_action(	SEND_T,
09e52ebb
 													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);
 												}
4e2fdd79
 		| SEND LPAREN ip COMMA NUMBER RPAREN { $$=mk_action(	SEND_T,
09e52ebb
 																IP_ST,
 																NUMBER_ST,
 																(void*)$3,
 																(void*)$5);
 											   }
 		| SEND error { $$=0; yyerror("missing '(' or ')' ?"); }
 		| SEND LPAREN error RPAREN { $$=0; yyerror("bad send"
 													"argument"); }
0c5da34b
 		| SEND_TCP LPAREN host RPAREN	{ $$=mk_action(	SEND_TCP_T,
 													STRING_ST,
 													NUMBER_ST,
 													$3,
 													0);
 									}
 		| SEND_TCP LPAREN STRING RPAREN { $$=mk_action(	SEND_TCP_T,
 													STRING_ST,
 													NUMBER_ST,
 													$3,
 													0);
 									}
 		| SEND_TCP LPAREN ip RPAREN		{ $$=mk_action(	SEND_TCP_T,
 													IP_ST,
 													NUMBER_ST,
 													(void*)$3,
 													0);
 									}
 		| SEND_TCP LPAREN host COMMA NUMBER RPAREN	{ $$=mk_action(	SEND_TCP_T,
 																STRING_ST,
 																NUMBER_ST,
 																$3,
 																(void*)$5);
 												}
 		| SEND_TCP LPAREN STRING COMMA NUMBER RPAREN {$$=mk_action(	SEND_TCP_T,
 																STRING_ST,
 																NUMBER_ST,
 																$3,
 																(void*)$5);
 												}
 		| SEND_TCP LPAREN ip COMMA NUMBER RPAREN { $$=mk_action(	SEND_TCP_T,
 																IP_ST,
 																NUMBER_ST,
 																(void*)$3,
 																(void*)$5);
 											   }
 		| SEND_TCP error { $$=0; yyerror("missing '(' or ')' ?"); }
 		| SEND_TCP LPAREN error RPAREN { $$=0; yyerror("bad send_tcp"
 													"argument"); }
09e52ebb
 		| DROP LPAREN RPAREN	{$$=mk_action(DROP_T,0, 0, 0, 0); }
 		| DROP					{$$=mk_action(DROP_T,0, 0, 0, 0); }
7268726e
 		| LOG_TOK LPAREN STRING RPAREN	{$$=mk_action(	LOG_T, NUMBER_ST, 
09e52ebb
 													STRING_ST,(void*)4,$3);
 									}
7268726e
 		| LOG_TOK LPAREN NUMBER COMMA STRING RPAREN	{$$=mk_action(	LOG_T,
09e52ebb
 																NUMBER_ST, 
 																STRING_ST,
 																(void*)$3,
 																$5);
 												}
7268726e
 		| LOG_TOK error { $$=0; yyerror("missing '(' or ')' ?"); }
 		| LOG_TOK LPAREN error RPAREN { $$=0; yyerror("bad log"
09e52ebb
 									"argument"); }
3881f12c
 		| SETFLAG LPAREN NUMBER RPAREN {$$=mk_action( SETFLAG_T, NUMBER_ST, 0,
 													(void *)$3, 0 ); }
 		| SETFLAG error { $$=0; yyerror("missing '(' or ')'?"); }
1f377e97
 
 		| LEN_GT LPAREN NUMBER RPAREN {$$=mk_action( LEN_GT_T, NUMBER_ST, 0,
 													(void *)$3, 0 ); }
 		| LEN_GT LPAREN MAX_LEN RPAREN {$$=mk_action( LEN_GT_T, NUMBER_ST, 0,
 													(void *) BUF_SIZE, 0 ); }
 		| LEN_GT error { $$=0; yyerror("missing '(' or ')'?"); }
 
3881f12c
 		| RESETFLAG LPAREN NUMBER RPAREN {$$=mk_action(	RESETFLAG_T, NUMBER_ST, 0,
 													(void *)$3, 0 ); }
 		| RESETFLAG error { $$=0; yyerror("missing '(' or ')'?"); }
 		| ISFLAGSET LPAREN NUMBER RPAREN {$$=mk_action(	ISFLAGSET_T, NUMBER_ST, 0,
 													(void *)$3, 0 ); }
 		| ISFLAGSET error { $$=0; yyerror("missing '(' or ')'?"); }
09e52ebb
 		| 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);
 									}
f20a56a2
 		| SET_HOST LPAREN STRING RPAREN { $$=mk_action(SET_HOST_T, STRING_ST,
 														0, $3, 0); }
7268726e
 		| SET_HOST error { $$=0; yyerror("missing '(' or ')' ?"); }
f20a56a2
 		| SET_HOST LPAREN error RPAREN { $$=0; yyerror("bad argument, "
 														"string expected"); }
1f377e97
 
 		| PREFIX LPAREN STRING RPAREN { $$=mk_action(PREFIX_T, STRING_ST,
 														0, $3, 0); }
 		| PREFIX error { $$=0; yyerror("missing '(' or ')' ?"); }
 		| PREFIX LPAREN error RPAREN { $$=0; yyerror("bad argument, "
 														"string expected"); }
 		| STRIP LPAREN NUMBER RPAREN { $$=mk_action(STRIP_T, NUMBER_ST,
 														0, (void *) $3, 0); }
 		| STRIP error { $$=0; yyerror("missing '(' or ')' ?"); }
 		| STRIP LPAREN error RPAREN { $$=0; yyerror("bad argument, "
 														"number expected"); }
 
caf80ae6
 		| APPEND_BRANCH LPAREN STRING RPAREN { $$=mk_action( APPEND_BRANCH_T,
 													STRING_ST, 0, $3, 0) ; }
 		| APPEND_BRANCH LPAREN RPAREN { $$=mk_action( APPEND_BRANCH_T,
 													STRING_ST, 0, 0, 0 ) ; }
 		| APPEND_BRANCH {  $$=mk_action( APPEND_BRANCH_T, STRING_ST, 0, 0, 0 ) ; }
 
f20a56a2
 		| SET_HOSTPORT LPAREN STRING RPAREN { $$=mk_action( SET_HOSTPORT_T, 
 														STRING_ST, 0, $3, 0); }
7268726e
 		| SET_HOSTPORT error { $$=0; yyerror("missing '(' or ')' ?"); }
f20a56a2
 		| SET_HOSTPORT LPAREN error RPAREN { $$=0; yyerror("bad argument,"
 												" string expected"); }
 		| SET_PORT LPAREN STRING RPAREN { $$=mk_action( SET_PORT_T, STRING_ST,
 														0, $3, 0); }
7268726e
 		| SET_PORT error { $$=0; yyerror("missing '(' or ')' ?"); }
f20a56a2
 		| SET_PORT LPAREN error RPAREN { $$=0; yyerror("bad argument, "
 														"string expected"); }
 		| SET_USER LPAREN STRING RPAREN { $$=mk_action( SET_USER_T, STRING_ST,
 														0, $3, 0); }
7268726e
 		| SET_USER error { $$=0; yyerror("missing '(' or ')' ?"); }
f20a56a2
 		| SET_USER LPAREN error RPAREN { $$=0; yyerror("bad argument, "
 														"string expected"); }
 		| SET_USERPASS LPAREN STRING RPAREN { $$=mk_action( SET_USERPASS_T, 
 														STRING_ST, 0, $3, 0); }
7268726e
 		| SET_USERPASS error { $$=0; yyerror("missing '(' or ')' ?"); }
f20a56a2
 		| SET_USERPASS LPAREN error RPAREN { $$=0; yyerror("bad argument, "
 														"string expected"); }
 		| SET_URI LPAREN STRING RPAREN { $$=mk_action( SET_URI_T, STRING_ST, 
 														0, $3, 0); }
7268726e
 		| SET_URI error { $$=0; yyerror("missing '(' or ')' ?"); }
f20a56a2
 		| SET_URI LPAREN error RPAREN { $$=0; yyerror("bad argument, "
 										"string expected"); }
caf80ae6
 		| REVERT_URI LPAREN RPAREN { $$=mk_action( REVERT_URI_T, 0,0,0,0); }
 		| REVERT_URI { $$=mk_action( REVERT_URI_T, 0,0,0,0); }
51eadd0c
 		| ID LPAREN RPAREN			{ f_tmp=(void*)find_export($1, 0);
34fd2612
 									   if (f_tmp==0){
2bd748c6
 										yyerror("unknown command, missing"
34fd2612
 										" loadmodule?\n");
 										$$=0;
 									   }else{
 										$$=mk_action(	MODULE_T,
 														CMDF_ST,
 														0,
 														f_tmp,
 														0
 													);
 									   }
 									}
51eadd0c
 		| ID LPAREN STRING RPAREN { f_tmp=(void*)find_export($1, 1);
3bf76e49
 									if (f_tmp==0){
2bd748c6
 										yyerror("unknown command, missing"
3bf76e49
 										" loadmodule?\n");
 										$$=0;
 									}else{
 										$$=mk_action(	MODULE_T,
 														CMDF_ST,
 														STRING_ST,
 														f_tmp,
 														$3
 													);
 									}
 								  }
34fd2612
 		| ID LPAREN STRING  COMMA STRING RPAREN 
51eadd0c
 								  { f_tmp=(void*)find_export($1, 2);
34fd2612
 									if (f_tmp==0){
2bd748c6
 										yyerror("unknown command, missing"
34fd2612
 										" loadmodule?\n");
 										$$=0;
 									}else{
 										$$=mk_action3(	MODULE_T,
 														CMDF_ST,
 														STRING_ST,
 														STRING_ST,
 														f_tmp,
 														$3,
 														$5
 													);
 									}
 								  }
3bf76e49
 		| ID LPAREN error RPAREN { $$=0; yyerror("bad arguments"); }
f20a56a2
 		| if_cmd		{ $$=$1; }
3c1a8ef8
 	;
 
 
 %%
 
 extern int line;
 extern int column;
09e52ebb
 extern int startcolumn;
3e429f5c
 void yyerror(char* s)
3c1a8ef8
 {
7268726e
 	LOG(L_CRIT, "parse error (%d,%d-%d): %s\n", line, startcolumn, 
09e52ebb
 			column, s);
63fa628f
 	cfg_errors++;
3c1a8ef8
 }
 
a15c363f
 /*
3c1a8ef8
 int main(int argc, char ** argv)
 {
 	if (yyparse()!=0)
 		fprintf(stderr, "parsing error\n");
 }
a15c363f
 */