aae6738d2a1b95c4ae93b5ecc520e1dbe1c880af
[sip-router] / cfg.y
1 /*
2  * $Id$
3  *
4  *  cfg grammar
5  */
6
7 %{
8
9 #include <stdlib.h>
10 #include <stdio.h>
11 #include <sys/types.h>
12 #include <sys/socket.h>
13 #include <netinet/in.h>
14 #include <arpa/inet.h>
15 #include <string.h>
16 #include <errno.h>
17 #include "route_struct.h"
18 #include "globals.h"
19 #include "route.h"
20 #include "dprint.h"
21 #include "sr_module.h"
22 #include "modparam.h"
23 #include "ip_addr.h"
24 #include "name_alias.h"
25
26 #include "config.h"
27
28 #ifdef DEBUG_DMALLOC
29 #include <dmalloc.h>
30 #endif
31
32 /* hack to avoid alloca usage in the generated C file (needed for compiler
33  with no built in alloca, like icc*/
34 #undef _ALLOCA_H
35
36 struct id_list{
37         char* s;
38         struct id_list* next;
39 };
40
41 extern int yylex();
42 void yyerror(char* s);
43 char* tmp;
44 void* f_tmp;
45 struct id_list* lst_tmp;
46
47
48 %}
49
50 %union {
51         long intval;
52         unsigned long uval;
53         char* strval;
54         struct expr* expr;
55         struct action* action;
56         struct net* ipnet;
57         struct ip_addr* ipaddr;
58         struct id_list* idlst;
59 }
60
61 /* terminals */
62
63
64 /* keywords */
65 %token FORWARD
66 %token FORWARD_TCP
67 %token SEND
68 %token SEND_TCP
69 %token DROP
70 %token LOG_TOK
71 %token ERROR
72 %token ROUTE
73 %token REPLY_ROUTE
74 %token EXEC
75 %token SET_HOST
76 %token SET_HOSTPORT
77 %token PREFIX
78 %token STRIP
79 %token APPEND_BRANCH
80 %token SET_USER
81 %token SET_USERPASS
82 %token SET_PORT
83 %token SET_URI
84 %token REVERT_URI
85 %token IF
86 %token ELSE
87 %token URIHOST
88 %token URIPORT
89 %token MAX_LEN
90 %token SETFLAG
91 %token RESETFLAG
92 %token ISFLAGSET
93 %token LEN_GT
94 %token METHOD
95 %token URI
96 %token SRCIP
97 %token DSTIP
98 %token MYSELF
99
100 /* config vars. */
101 %token DEBUG
102 %token FORK
103 %token LOGSTDERROR
104 %token LISTEN
105 %token ALIAS
106 %token DNS
107 %token REV_DNS
108 %token PORT
109 %token STAT
110 %token CHILDREN
111 %token CHECK_VIA
112 %token SYN_BRANCH
113 %token MEMLOG
114 %token SIP_WARNING
115 %token FIFO
116 %token FIFO_MODE
117 %token SERVER_SIGNATURE
118 %token REPLY_TO_VIA
119 %token LOADMODULE
120 %token MODPARAM
121 %token MAXBUFFER
122 %token USER
123 %token GROUP
124
125
126
127 /* operators */
128 %nonassoc EQUAL
129 %nonassoc EQUAL_T
130 %nonassoc MATCH
131 %left OR
132 %left AND
133 %left NOT
134
135 /* values */
136 %token <intval> NUMBER
137 %token <strval> ID
138 %token <strval> STRING
139 %token <strval> IPV6ADDR
140
141 /* other */
142 %token COMMA
143 %token SEMICOLON
144 %token RPAREN
145 %token LPAREN
146 %token LBRACE
147 %token RBRACE
148 %token LBRACK
149 %token RBRACK
150 %token SLASH
151 %token DOT
152 %token CR
153
154
155 /*non-terminals */
156 %type <expr> exp exp_elem /*, condition*/
157 %type <action> action actions cmd if_cmd stm
158 %type <ipaddr> ipv4 ipv6 ip
159 %type <ipnet> ipnet
160 %type <strval> host
161 %type <strval> listen_id
162 %type <idlst>  id_lst
163 /*%type <route_el> rules;
164   %type <route_el> rule;
165 */
166
167
168
169 %%
170
171
172 cfg:    statements
173         ;
174
175 statements:     statements statement {}
176                 | statement {}
177                 | statements error { yyerror(""); YYABORT;}
178         ;
179
180 statement:      assign_stm 
181                 | module_stm
182                 | route_stm 
183                 | reply_route_stm
184                 | CR    /* null statement*/
185         ;
186
187 listen_id:      ip                      {       tmp=ip_addr2a($1);
188                                                         if(tmp==0){
189                                                                 LOG(L_CRIT, "ERROR: cfg. parser: bad ip "
190                                                                                 "addresss.\n");
191                                                                 $$=0;
192                                                         }else{
193                                                                 $$=malloc(strlen(tmp)+1);
194                                                                 if ($$==0){
195                                                                         LOG(L_CRIT, "ERROR: cfg. parser: out of "
196                                                                                         "memory.\n");
197                                                                 }else{
198                                                                         strncpy($$, tmp, strlen(tmp)+1);
199                                                                 }
200                                                         }
201                                                 }
202                  |      ID                      {       $$=malloc(strlen($1)+1);
203                                                         if ($$==0){
204                                                                         LOG(L_CRIT, "ERROR: cfg. parser: out of "
205                                                                                         "memory.\n");
206                                                         }else{
207                                                                         strncpy($$, $1, strlen($1)+1);
208                                                         }
209                                                 }
210                  |      STRING                  {       $$=malloc(strlen($1)+1);
211                                                         if ($$==0){
212                                                                         LOG(L_CRIT, "ERROR: cfg. parser: out of "
213                                                                                         "memory.\n");
214                                                         }else{
215                                                                         strncpy($$, $1, strlen($1)+1);
216                                                         }
217                                                 }
218                  |      host            {       $$=malloc(strlen($1)+1);
219                                                         if ($$==0){
220                                                                         LOG(L_CRIT, "ERROR: cfg. parser: out of "
221                                                                                         "memory.\n");
222                                                         }else{
223                                                                         strncpy($$, $1, strlen($1)+1);
224                                                         }
225                                                 }
226         ;
227
228 id_lst:   listen_id     {       $$=malloc(sizeof(struct id_list));
229                                                 if ($$==0){
230                                                         LOG(L_CRIT,"ERROR: cfg. parser: out of memory.\n");
231                                                 }else{
232                                                         $$->s=$1;
233                                                         $$->next=0;
234                                                 }
235                                         }
236                 | listen_id id_lst      {
237                                                 $$=malloc(sizeof(struct id_list));
238                                                 if ($$==0){
239                                                         LOG(L_CRIT,"ERROR: cfg. parser: out of memory.\n");
240                                                 }else{
241                                                         $$->s=$1;
242                                                         $$->next=$2;
243                                                 }
244                                                         }
245                 ;
246
247
248 assign_stm:     DEBUG EQUAL NUMBER { debug=$3; }
249                 | DEBUG EQUAL error  { yyerror("number  expected"); }
250                 | FORK  EQUAL NUMBER { dont_fork= ! $3; }
251                 | FORK  EQUAL error  { yyerror("boolean value expected"); }
252                 | LOGSTDERROR EQUAL NUMBER { log_stderr=$3; }
253                 | LOGSTDERROR EQUAL error { yyerror("boolean value expected"); }
254                 | DNS EQUAL NUMBER   { received_dns|= ($3)?DO_DNS:0; }
255                 | DNS EQUAL error { yyerror("boolean value expected"); }
256                 | REV_DNS EQUAL NUMBER { received_dns|= ($3)?DO_REV_DNS:0; }
257                 | REV_DNS EQUAL error { yyerror("boolean value expected"); }
258                 | PORT EQUAL NUMBER   { port_no=$3; 
259                                                                 if (sock_no>0) 
260                                                                         sock_info[sock_no-1].port_no=port_no;
261                                                           }
262                 | STAT EQUAL STRING {
263                                         #ifdef STATS
264                                                         stat_file=$3;
265                                         #endif
266                                                         }
267                 | MAXBUFFER EQUAL NUMBER { maxbuffer=$3; }
268                 | MAXBUFFER EQUAL error { yyerror("number expected"); }
269                 | PORT EQUAL error    { yyerror("number expected"); } 
270                 | CHILDREN EQUAL NUMBER { children_no=$3; }
271                 | CHILDREN EQUAL error { yyerror("number expected"); } 
272                 | CHECK_VIA EQUAL NUMBER { check_via=$3; }
273                 | CHECK_VIA EQUAL error { yyerror("boolean value expected"); }
274                 | SYN_BRANCH EQUAL NUMBER { syn_branch=$3; }
275                 | SYN_BRANCH EQUAL error { yyerror("boolean value expected"); }
276                 | MEMLOG EQUAL NUMBER { memlog=$3; }
277                 | MEMLOG EQUAL error { yyerror("int value expected"); }
278                 | SIP_WARNING EQUAL NUMBER { sip_warning=$3; }
279                 | SIP_WARNING EQUAL error { yyerror("boolean value expected"); }
280                 | FIFO EQUAL STRING { fifo=$3; }
281                 | FIFO EQUAL error { yyerror("string value expected"); }
282                 | FIFO_MODE EQUAL NUMBER { fifo_mode=$3; }
283                 | FIFO_MODE EQUAL error { yyerror("int value expected"); }
284                 | USER EQUAL STRING     { user=$3; }
285                 | USER EQUAL ID         { user=$3; }
286                 | USER EQUAL error      { yyerror("string value expected"); }
287                 | GROUP EQUAL STRING     { group=$3; }
288                 | GROUP EQUAL ID         { group=$3; }
289                 | GROUP EQUAL error      { yyerror("string value expected"); }
290                 | SERVER_SIGNATURE EQUAL NUMBER { server_signature=$3; }
291                 | SERVER_SIGNATURE EQUAL error { yyerror("boolean value expected"); }
292                 | REPLY_TO_VIA EQUAL NUMBER { reply_to_via=$3; }
293                 | REPLY_TO_VIA EQUAL error { yyerror("boolean value expected"); }
294                 | LISTEN EQUAL id_lst {
295                                                         for(lst_tmp=$3; lst_tmp; lst_tmp=lst_tmp->next){
296                                                                 if (sock_no < MAX_LISTEN){
297                                                                         sock_info[sock_no].name.s=
298                                                                                 (char*)malloc(strlen(lst_tmp->s)+1);
299                                                                         if (sock_info[sock_no].name.s==0){
300                                                                                 LOG(L_CRIT, "ERROR: cfg. parser:"
301                                                                                                         " out of memory.\n");
302                                                                                 break;
303                                                                         }else{
304                                                                                 strncpy(sock_info[sock_no].name.s,
305                                                                                                 lst_tmp->s,
306                                                                                                 strlen(lst_tmp->s)+1);
307                                                                                 sock_info[sock_no].name.len=
308                                                                                                         strlen(lst_tmp->s);
309                                                                                 sock_info[sock_no].port_no=port_no;
310                                                                                 sock_no++;
311                                                                         }
312                                                                 }else{
313                                                                         LOG(L_CRIT, "ERROR: cfg. parser: "
314                                                                                                 "too many listen addresses"
315                                                                                                 "(max. %d).\n", MAX_LISTEN);
316                                                                         break;
317                                                                 }
318                                                         }
319                                                          }
320                 | LISTEN EQUAL  error { yyerror("ip address or hostname"
321                                                 "expected"); }
322                 | ALIAS EQUAL  id_lst { 
323                                                         for(lst_tmp=$3; lst_tmp; lst_tmp=lst_tmp->next)
324                                                                 add_alias(lst_tmp->s, strlen(lst_tmp->s), 0);
325                                                           }
326                 | ALIAS  EQUAL error  { yyerror(" hostname expected"); }
327                 | error EQUAL { yyerror("unknown config variable"); }
328         ;
329
330 module_stm:     LOADMODULE STRING       { DBG("loading module %s\n", $2);
331                                                                   if (load_module($2)!=0){
332                                                                                 yyerror("failed to load module");
333                                                                   }
334                                                                 }
335                  | LOADMODULE error     { yyerror("string expected");  }
336                  | MODPARAM LPAREN STRING COMMA STRING COMMA STRING RPAREN {
337                          if (set_mod_param($3, $5, STR_PARAM, $7) != 0) {
338                                  yyerror("Can't set module parameter");
339                          }
340                    }
341                  | MODPARAM LPAREN STRING COMMA STRING COMMA NUMBER RPAREN {
342                          if (set_mod_param($3, $5, INT_PARAM, (void*)$7) != 0) {
343                                  yyerror("Can't set module parameter");
344                          }
345                    }
346                  | MODPARAM error { yyerror("Invalid arguments"); }
347                  ;
348
349
350 ip:              ipv4  { $$=$1; }
351                 |ipv6  { $$=$1; }
352                 ;
353
354 ipv4:   NUMBER DOT NUMBER DOT NUMBER DOT NUMBER { 
355                                                                                         $$=malloc(sizeof(struct ip_addr));
356                                                                                         if ($$==0){
357                                                                                                 LOG(L_CRIT, "ERROR: cfg. "
358                                                                                                         "parser: out of memory.\n"
359                                                                                                         );
360                                                                                         }else{
361                                                                                                 memset($$, 0, 
362                                                                                                         sizeof(struct ip_addr));
363                                                                                                 $$->af=AF_INET;
364                                                                                                 $$->len=4;
365                                                                                                 if (($1>255) || ($1<0) ||
366                                                                                                         ($3>255) || ($3<0) ||
367                                                                                                         ($5>255) || ($5<0) ||
368                                                                                                         ($7>255) || ($7<0)){
369                                                                                                         yyerror("invalid ipv4"
370                                                                                                                         "address");
371                                                                                                         $$->u.addr32[0]=0;
372                                                                                                         /* $$=0; */
373                                                                                                 }else{
374                                                                                                         $$->u.addr[0]=$1;
375                                                                                                         $$->u.addr[1]=$3;
376                                                                                                         $$->u.addr[2]=$5;
377                                                                                                         $$->u.addr[3]=$7;
378                                                                                                         /*
379                                                                                                         $$=htonl( ($1<<24)|
380                                                                                                         ($3<<16)| ($5<<8)|$7 );
381                                                                                                         */
382                                                                                                 }
383                                                                                         }
384                                                                                                 }
385         ;
386
387 ipv6:   IPV6ADDR {
388                                         $$=malloc(sizeof(struct ip_addr));
389                                         if ($$==0){
390                                                 LOG(L_CRIT, "ERROR: cfg. parser: out of memory.\n");
391                                         }else{
392                                                 memset($$, 0, sizeof(struct ip_addr));
393                                                 $$->af=AF_INET6;
394                                                 $$->len=16;
395                                         #ifdef USE_IPV6
396                                                 if (inet_pton(AF_INET6, $1, $$->u.addr)<=0){
397                                                         yyerror("bad ipv6 address");
398                                                 }
399                                         #else
400                                                 yyerror("ipv6 address & no ipv6 support compiled in");
401                                                 YYABORT;
402                                         #endif
403                                         }
404                                 }
405         ;
406
407
408 route_stm:      ROUTE LBRACE actions RBRACE { push($3, &rlist[DEFAULT_RT]); }
409
410                 | ROUTE LBRACK NUMBER RBRACK LBRACE actions RBRACE { 
411                                                                                 if (($3<RT_NO) && ($3>=0)){
412                                                                                         push($6, &rlist[$3]);
413                                                                                 }else{
414                                                                                         yyerror("invalid routing"
415                                                                                                         "table number");
416                                                                                         YYABORT; }
417                                                                                 }
418                 | ROUTE error { yyerror("invalid  route  statement"); }
419         ;
420
421 reply_route_stm: REPLY_ROUTE LBRACK NUMBER RBRACK LBRACE actions RBRACE {
422                                                                                 if (($3<REPLY_RT_NO)&&($3>=1)){
423                                                                                         push($6, &reply_rlist[$3]);
424                                                                                 } else {
425                                                                                         yyerror("invalid reply routing"
426                                                                                                 "table number");
427                                                                                         YYABORT; }
428                                                                                 }
429                 | REPLY_ROUTE error { yyerror("invalid reply_route statement"); }
430         ;
431 /*
432 rules:  rules rule { push($2, &$1); $$=$1; }
433         | rule {$$=$1; }
434         | rules error { $$=0; yyerror("invalid rule"); }
435          ;
436
437 rule:   condition       actions CR {
438                                                                 $$=0;
439                                                                 if (add_rule($1, $2, &$$)<0) {
440                                                                         yyerror("error calling add_rule");
441                                                                         YYABORT;
442                                                                 }
443                                                           }
444         | CR            { $$=0;}
445         | condition error { $$=0; yyerror("bad actions in rule"); }
446         ;
447
448 condition:      exp {$$=$1;}
449 */
450
451 exp:    exp AND exp     { $$=mk_exp(AND_OP, $1, $3); }
452         | exp OR  exp           { $$=mk_exp(OR_OP, $1, $3);  }
453         | NOT exp                       { $$=mk_exp(NOT_OP, $2, 0);  }
454         | LPAREN exp RPAREN     { $$=$2; }
455         | exp_elem                      { $$=$1; }
456         ;
457
458 exp_elem:       METHOD EQUAL_T STRING   {$$= mk_elem(   EQUAL_OP, STRING_ST, 
459                                                                                                         METHOD_O, $3);
460                                                                         }
461                 | METHOD EQUAL_T ID     {$$ = mk_elem(  EQUAL_OP, STRING_ST,
462                                                                                         METHOD_O, $3); 
463                                                         }
464                 | METHOD EQUAL_T error { $$=0; yyerror("string expected"); }
465                 | METHOD MATCH STRING   {$$ = mk_elem(  MATCH_OP, STRING_ST,
466                                                                                                 METHOD_O, $3); 
467                                                                 }
468                 | METHOD MATCH ID       {$$ = mk_elem(  MATCH_OP, STRING_ST,
469                                                                                         METHOD_O, $3); 
470                                                         }
471                 | METHOD MATCH error { $$=0; yyerror("string expected"); }
472                 | METHOD error  { $$=0; yyerror("invalid operator,"
473                                                                                 "== or =~ expected");
474                                                 }
475                 | URI EQUAL_T STRING    {$$ = mk_elem(  EQUAL_OP, STRING_ST,
476                                                                                                 URI_O, $3); 
477                                                                 }
478                 | URI EQUAL_T ID        {$$ = mk_elem(  EQUAL_OP, STRING_ST,
479                                                                                         URI_O, $3); 
480                                                         }
481                 | URI EQUAL_T MYSELF    { $$=mk_elem(   EQUAL_OP, MYSELF_ST,
482                                                                                                 URI_O, 0);
483                                                                 }
484                 | URI EQUAL_T error { $$=0; yyerror("string expected"); }
485                 | URI MATCH STRING      { $$=mk_elem(   MATCH_OP, STRING_ST,
486                                                                                         URI_O, $3);
487                                                         }
488                 | URI MATCH ID          { $$=mk_elem(   MATCH_OP, STRING_ST,
489                                                                                         URI_O, $3);
490                                                         }
491                 | URI MATCH error {  $$=0; yyerror("string expected"); }
492                 | URI error     { $$=0; yyerror("invalid operator,"
493                                                                         " == or =~ expected");
494                                         }
495                 | SRCIP EQUAL_T ipnet   { $$=mk_elem(   EQUAL_OP, NET_ST,
496                                                                                                 SRCIP_O, $3);
497                                                                 }
498                 | SRCIP EQUAL_T STRING  { $$=mk_elem(   EQUAL_OP, STRING_ST,
499                                                                                                 SRCIP_O, $3);
500                                                                 }
501                 | SRCIP EQUAL_T host    { $$=mk_elem(   EQUAL_OP, STRING_ST,
502                                                                                                 SRCIP_O, $3);
503                                                                 }
504                 | SRCIP EQUAL_T MYSELF  { $$=mk_elem(   EQUAL_OP, MYSELF_ST,
505                                                                                                 SRCIP_O, 0);
506                                                                 }
507                 | SRCIP EQUAL_T error { $$=0; yyerror( "ip address or hostname"
508                                                  "expected" ); }
509                 | SRCIP MATCH STRING    { $$=mk_elem(   MATCH_OP, STRING_ST,
510                                                                                                 SRCIP_O, $3);
511                                                                 }
512                 | SRCIP MATCH ID                { $$=mk_elem(   MATCH_OP, STRING_ST,
513                                                                                                 SRCIP_O, $3);
514                                                                 }
515                 | SRCIP MATCH error  { $$=0; yyerror( "hostname expected"); }
516                 | SRCIP error  { $$=0; 
517                                                  yyerror("invalid operator, == or =~ expected");}
518                 | DSTIP EQUAL_T ipnet   { $$=mk_elem(   EQUAL_OP, NET_ST,
519                                                                                                 DSTIP_O, $3);
520                                                                 }
521                 | DSTIP EQUAL_T STRING  { $$=mk_elem(   EQUAL_OP, STRING_ST,
522                                                                                                 DSTIP_O, $3);
523                                                                 }
524                 | DSTIP EQUAL_T host    { $$=mk_elem(   EQUAL_OP, STRING_ST,
525                                                                                                 DSTIP_O, $3);
526                                                                 }
527                 | DSTIP EQUAL_T MYSELF  { $$=mk_elem(   EQUAL_OP, MYSELF_ST,
528                                                                                                 DSTIP_O, 0);
529                                                                 }
530                 | DSTIP EQUAL_T error { $$=0; yyerror( "ip address or hostname"
531                                                                         "expected" ); }
532                 | DSTIP MATCH STRING    { $$=mk_elem(   MATCH_OP, STRING_ST,
533                                                                                                 DSTIP_O, $3);
534                                                                 }
535                 | DSTIP MATCH ID        { $$=mk_elem(   MATCH_OP, STRING_ST,
536                                                                                         DSTIP_O, $3);
537                                                         }
538                 | DSTIP MATCH error  { $$=0; yyerror ( "hostname  expected" ); }
539                 | DSTIP error { $$=0; 
540                                                 yyerror("invalid operator, == or =~ expected");}
541                 | MYSELF EQUAL_T URI    { $$=mk_elem(   EQUAL_OP, MYSELF_ST,
542                                                                                                 URI_O, 0);
543                                                                 }
544                 | MYSELF EQUAL_T SRCIP  { $$=mk_elem(   EQUAL_OP, MYSELF_ST,
545                                                                                                 SRCIP_O, 0);
546                                                                 }
547                 | MYSELF EQUAL_T DSTIP  { $$=mk_elem(   EQUAL_OP, MYSELF_ST,
548                                                                                                 DSTIP_O, 0);
549                                                                 }
550                 | MYSELF EQUAL_T error {        $$=0; 
551                                                                         yyerror(" URI, SRCIP or DSTIP expected"); }
552                 | MYSELF error  { $$=0; yyerror ("invalid operator, == expected"); }
553                 | stm                           { $$=mk_elem( NO_OP, ACTIONS_ST, ACTION_O, $1 ); }
554                 | NUMBER                {$$=mk_elem( NO_OP, NUMBER_ST, NUMBER_O, (void*)$1 ); }
555         ;
556
557 ipnet:  ip SLASH ip     { $$=mk_net($1, $3); } 
558         | ip SLASH NUMBER       {       if (($3<0) || ($3>$1->len*8)){
559                                                                 yyerror("invalid bit number in netmask");
560                                                                 $$=0;
561                                                         }else{
562                                                                 $$=mk_net_bitlen($1, $3);
563                                                         /*
564                                                                 $$=mk_net($1, 
565                                                                                 htonl( ($3)?~( (1<<(32-$3))-1 ):0 ) );
566                                                         */
567                                                         }
568                                                 }
569         | ip                            { $$=mk_net_bitlen($1, $1->len*8); }
570         | ip SLASH error        { $$=0;
571                                                  yyerror("netmask (eg:255.0.0.0 or 8) expected");
572                                                 }
573         ;
574
575 host:   ID                              { $$=$1; }
576         | host DOT ID           { $$=(char*)malloc(strlen($1)+1+strlen($3)+1);
577                                                   if ($$==0){
578                                                         LOG(L_CRIT, "ERROR: cfg. parser: memory allocation"
579                                                                                 " failure while parsing host\n");
580                                                   }else{
581                                                         memcpy($$, $1, strlen($1));
582                                                         $$[strlen($1)]='.';
583                                                         memcpy($$+strlen($1)+1, $3, strlen($3));
584                                                         $$[strlen($1)+1+strlen($3)]=0;
585                                                   }
586                                                   free($1); free($3);
587                                                 }
588         | host DOT error { $$=0; free($1); yyerror("invalid hostname"); }
589         ;
590
591
592 stm:            cmd                                             { $$=$1; }
593                 |       LBRACE actions RBRACE   { $$=$2; }
594         ;
595
596 actions:        actions action  {$$=append_action($1, $2); }
597                 | action                        {$$=$1;}
598                 | actions error { $$=0; yyerror("bad command"); }
599         ;
600
601 action:         cmd SEMICOLON {$$=$1;}
602                 | SEMICOLON /* null action */ {$$=0;}
603                 | cmd error { $$=0; yyerror("bad command: missing ';'?"); }
604         ;
605
606 if_cmd:         IF exp stm                              { $$=mk_action3( IF_T,
607                                                                                                          EXPR_ST,
608                                                                                                          ACTIONS_ST,
609                                                                                                          NOSUBTYPE,
610                                                                                                          $2,
611                                                                                                          $3,
612                                                                                                          0);
613                                                                         }
614                 |       IF exp stm ELSE stm             { $$=mk_action3( IF_T,
615                                                                                                          EXPR_ST,
616                                                                                                          ACTIONS_ST,
617                                                                                                          ACTIONS_ST,
618                                                                                                          $2,
619                                                                                                          $3,
620                                                                                                          $5);
621                                                                         }
622         ;
623
624 cmd:            FORWARD LPAREN host RPAREN      { $$=mk_action( FORWARD_T,
625                                                                                                                 STRING_ST,
626                                                                                                                 NUMBER_ST,
627                                                                                                                 $3,
628                                                                                                                 0);
629                                                                                 }
630                 | FORWARD LPAREN STRING RPAREN  { $$=mk_action( FORWARD_T,
631                                                                                                                 STRING_ST,
632                                                                                                                 NUMBER_ST,
633                                                                                                                 $3,
634                                                                                                                 0);
635                                                                                 }
636                 | FORWARD LPAREN ip RPAREN      { $$=mk_action( FORWARD_T,
637                                                                                                                 IP_ST,
638                                                                                                                 NUMBER_ST,
639                                                                                                                 (void*)$3,
640                                                                                                                 0);
641                                                                                 }
642                 | FORWARD LPAREN host COMMA NUMBER RPAREN { $$=mk_action(FORWARD_T,
643                                                                                                                                  STRING_ST,
644                                                                                                                                  NUMBER_ST,
645                                                                                                                                 $3,
646                                                                                                                                 (void*)$5);
647                                                                                                  }
648                 | FORWARD LPAREN STRING COMMA NUMBER RPAREN {$$=mk_action(FORWARD_T,
649                                                                                                                                  STRING_ST,
650                                                                                                                                  NUMBER_ST,
651                                                                                                                                 $3,
652                                                                                                                                 (void*)$5);
653                                                                                                         }
654                 | FORWARD LPAREN ip COMMA NUMBER RPAREN { $$=mk_action(FORWARD_T,
655                                                                                                                                  IP_ST,
656                                                                                                                                  NUMBER_ST,
657                                                                                                                                  (void*)$3,
658                                                                                                                                 (void*)$5);
659                                                                                                   }
660                 | FORWARD LPAREN URIHOST COMMA URIPORT RPAREN {
661                                                                                                         $$=mk_action(FORWARD_T,
662                                                                                                                                  URIHOST_ST,
663                                                                                                                                  URIPORT_ST,
664                                                                                                                                 0,
665                                                                                                                                 0);
666                                                                                                         }
667                                                                                                         
668                                                                         
669                 | FORWARD LPAREN URIHOST COMMA NUMBER RPAREN {
670                                                                                                         $$=mk_action(FORWARD_T,
671                                                                                                                                  URIHOST_ST,
672                                                                                                                                  NUMBER_ST,
673                                                                                                                                 0,
674                                                                                                                                 (void*)$5);
675                                                                                                         }
676                 | FORWARD LPAREN URIHOST RPAREN {
677                                                                                                         $$=mk_action(FORWARD_T,
678                                                                                                                                  URIHOST_ST,
679                                                                                                                                  NUMBER_ST,
680                                                                                                                                 0,
681                                                                                                                                 0);
682                                                                                 }
683                 | FORWARD error { $$=0; yyerror("missing '(' or ')' ?"); }
684                 | FORWARD LPAREN error RPAREN { $$=0; yyerror("bad forward"
685                                                                                 "argument"); }
686                 | SEND LPAREN host RPAREN       { $$=mk_action( SEND_T,
687                                                                                                         STRING_ST,
688                                                                                                         NUMBER_ST,
689                                                                                                         $3,
690                                                                                                         0);
691                                                                         }
692                 | SEND LPAREN STRING RPAREN { $$=mk_action(     SEND_T,
693                                                                                                         STRING_ST,
694                                                                                                         NUMBER_ST,
695                                                                                                         $3,
696                                                                                                         0);
697                                                                         }
698                 | SEND LPAREN ip RPAREN         { $$=mk_action( SEND_T,
699                                                                                                         IP_ST,
700                                                                                                         NUMBER_ST,
701                                                                                                         (void*)$3,
702                                                                                                         0);
703                                                                         }
704                 | SEND LPAREN host COMMA NUMBER RPAREN  { $$=mk_action( SEND_T,
705                                                                                                                                 STRING_ST,
706                                                                                                                                 NUMBER_ST,
707                                                                                                                                 $3,
708                                                                                                                                 (void*)$5);
709                                                                                                 }
710                 | SEND LPAREN STRING COMMA NUMBER RPAREN {$$=mk_action( SEND_T,
711                                                                                                                                 STRING_ST,
712                                                                                                                                 NUMBER_ST,
713                                                                                                                                 $3,
714                                                                                                                                 (void*)$5);
715                                                                                                 }
716                 | SEND LPAREN ip COMMA NUMBER RPAREN { $$=mk_action(    SEND_T,
717                                                                                                                                 IP_ST,
718                                                                                                                                 NUMBER_ST,
719                                                                                                                                 (void*)$3,
720                                                                                                                                 (void*)$5);
721                                                                                            }
722                 | SEND error { $$=0; yyerror("missing '(' or ')' ?"); }
723                 | SEND LPAREN error RPAREN { $$=0; yyerror("bad send"
724                                                                                                         "argument"); }
725                 | SEND_TCP LPAREN host RPAREN   { $$=mk_action( SEND_TCP_T,
726                                                                                                         STRING_ST,
727                                                                                                         NUMBER_ST,
728                                                                                                         $3,
729                                                                                                         0);
730                                                                         }
731                 | SEND_TCP LPAREN STRING RPAREN { $$=mk_action( SEND_TCP_T,
732                                                                                                         STRING_ST,
733                                                                                                         NUMBER_ST,
734                                                                                                         $3,
735                                                                                                         0);
736                                                                         }
737                 | SEND_TCP LPAREN ip RPAREN             { $$=mk_action( SEND_TCP_T,
738                                                                                                         IP_ST,
739                                                                                                         NUMBER_ST,
740                                                                                                         (void*)$3,
741                                                                                                         0);
742                                                                         }
743                 | SEND_TCP LPAREN host COMMA NUMBER RPAREN      { $$=mk_action( SEND_TCP_T,
744                                                                                                                                 STRING_ST,
745                                                                                                                                 NUMBER_ST,
746                                                                                                                                 $3,
747                                                                                                                                 (void*)$5);
748                                                                                                 }
749                 | SEND_TCP LPAREN STRING COMMA NUMBER RPAREN {$$=mk_action(     SEND_TCP_T,
750                                                                                                                                 STRING_ST,
751                                                                                                                                 NUMBER_ST,
752                                                                                                                                 $3,
753                                                                                                                                 (void*)$5);
754                                                                                                 }
755                 | SEND_TCP LPAREN ip COMMA NUMBER RPAREN { $$=mk_action(        SEND_TCP_T,
756                                                                                                                                 IP_ST,
757                                                                                                                                 NUMBER_ST,
758                                                                                                                                 (void*)$3,
759                                                                                                                                 (void*)$5);
760                                                                                            }
761                 | SEND_TCP error { $$=0; yyerror("missing '(' or ')' ?"); }
762                 | SEND_TCP LPAREN error RPAREN { $$=0; yyerror("bad send_tcp"
763                                                                                                         "argument"); }
764                 | DROP LPAREN RPAREN    {$$=mk_action(DROP_T,0, 0, 0, 0); }
765                 | DROP                                  {$$=mk_action(DROP_T,0, 0, 0, 0); }
766                 | LOG_TOK LPAREN STRING RPAREN  {$$=mk_action(  LOG_T, NUMBER_ST, 
767                                                                                                         STRING_ST,(void*)4,$3);
768                                                                         }
769                 | LOG_TOK LPAREN NUMBER COMMA STRING RPAREN     {$$=mk_action(  LOG_T,
770                                                                                                                                 NUMBER_ST, 
771                                                                                                                                 STRING_ST,
772                                                                                                                                 (void*)$3,
773                                                                                                                                 $5);
774                                                                                                 }
775                 | LOG_TOK error { $$=0; yyerror("missing '(' or ')' ?"); }
776                 | LOG_TOK LPAREN error RPAREN { $$=0; yyerror("bad log"
777                                                                         "argument"); }
778                 | SETFLAG LPAREN NUMBER RPAREN {$$=mk_action( SETFLAG_T, NUMBER_ST, 0,
779                                                                                                         (void *)$3, 0 ); }
780                 | SETFLAG error { $$=0; yyerror("missing '(' or ')'?"); }
781
782                 | LEN_GT LPAREN NUMBER RPAREN {$$=mk_action( LEN_GT_T, NUMBER_ST, 0,
783                                                                                                         (void *)$3, 0 ); }
784                 | LEN_GT LPAREN MAX_LEN RPAREN {$$=mk_action( LEN_GT_T, NUMBER_ST, 0,
785                                                                                                         (void *) BUF_SIZE, 0 ); }
786                 | LEN_GT error { $$=0; yyerror("missing '(' or ')'?"); }
787
788                 | RESETFLAG LPAREN NUMBER RPAREN {$$=mk_action( RESETFLAG_T, NUMBER_ST, 0,
789                                                                                                         (void *)$3, 0 ); }
790                 | RESETFLAG error { $$=0; yyerror("missing '(' or ')'?"); }
791                 | ISFLAGSET LPAREN NUMBER RPAREN {$$=mk_action( ISFLAGSET_T, NUMBER_ST, 0,
792                                                                                                         (void *)$3, 0 ); }
793                 | ISFLAGSET error { $$=0; yyerror("missing '(' or ')'?"); }
794                 | ERROR LPAREN STRING COMMA STRING RPAREN {$$=mk_action(ERROR_T,
795                                                                                                                                 STRING_ST, 
796                                                                                                                                 STRING_ST,
797                                                                                                                                 $3,
798                                                                                                                                 $5);
799                                                                                                   }
800                 | ERROR error { $$=0; yyerror("missing '(' or ')' ?"); }
801                 | ERROR LPAREN error RPAREN { $$=0; yyerror("bad error"
802                                                                                                                 "argument"); }
803                 | ROUTE LPAREN NUMBER RPAREN    { $$=mk_action(ROUTE_T, NUMBER_ST,
804                                                                                                                 0, (void*)$3, 0);
805                                                                                 }
806                 | ROUTE error { $$=0; yyerror("missing '(' or ')' ?"); }
807                 | ROUTE LPAREN error RPAREN { $$=0; yyerror("bad route"
808                                                 "argument"); }
809                 | EXEC LPAREN STRING RPAREN     { $$=mk_action( EXEC_T, STRING_ST, 0,
810                                                                                                         $3, 0);
811                                                                         }
812                 | SET_HOST LPAREN STRING RPAREN { $$=mk_action(SET_HOST_T, STRING_ST,
813                                                                                                                 0, $3, 0); }
814                 | SET_HOST error { $$=0; yyerror("missing '(' or ')' ?"); }
815                 | SET_HOST LPAREN error RPAREN { $$=0; yyerror("bad argument, "
816                                                                                                                 "string expected"); }
817
818                 | PREFIX LPAREN STRING RPAREN { $$=mk_action(PREFIX_T, STRING_ST,
819                                                                                                                 0, $3, 0); }
820                 | PREFIX error { $$=0; yyerror("missing '(' or ')' ?"); }
821                 | PREFIX LPAREN error RPAREN { $$=0; yyerror("bad argument, "
822                                                                                                                 "string expected"); }
823                 | STRIP LPAREN NUMBER RPAREN { $$=mk_action(STRIP_T, NUMBER_ST,
824                                                                                                                 0, (void *) $3, 0); }
825                 | STRIP error { $$=0; yyerror("missing '(' or ')' ?"); }
826                 | STRIP LPAREN error RPAREN { $$=0; yyerror("bad argument, "
827                                                                                                                 "number expected"); }
828
829                 | APPEND_BRANCH LPAREN STRING RPAREN { $$=mk_action( APPEND_BRANCH_T,
830                                                                                                         STRING_ST, 0, $3, 0) ; }
831                 | APPEND_BRANCH LPAREN RPAREN { $$=mk_action( APPEND_BRANCH_T,
832                                                                                                         STRING_ST, 0, 0, 0 ) ; }
833                 | APPEND_BRANCH {  $$=mk_action( APPEND_BRANCH_T, STRING_ST, 0, 0, 0 ) ; }
834
835                 | SET_HOSTPORT LPAREN STRING RPAREN { $$=mk_action( SET_HOSTPORT_T, 
836                                                                                                                 STRING_ST, 0, $3, 0); }
837                 | SET_HOSTPORT error { $$=0; yyerror("missing '(' or ')' ?"); }
838                 | SET_HOSTPORT LPAREN error RPAREN { $$=0; yyerror("bad argument,"
839                                                                                                 " string expected"); }
840                 | SET_PORT LPAREN STRING RPAREN { $$=mk_action( SET_PORT_T, STRING_ST,
841                                                                                                                 0, $3, 0); }
842                 | SET_PORT error { $$=0; yyerror("missing '(' or ')' ?"); }
843                 | SET_PORT LPAREN error RPAREN { $$=0; yyerror("bad argument, "
844                                                                                                                 "string expected"); }
845                 | SET_USER LPAREN STRING RPAREN { $$=mk_action( SET_USER_T, STRING_ST,
846                                                                                                                 0, $3, 0); }
847                 | SET_USER error { $$=0; yyerror("missing '(' or ')' ?"); }
848                 | SET_USER LPAREN error RPAREN { $$=0; yyerror("bad argument, "
849                                                                                                                 "string expected"); }
850                 | SET_USERPASS LPAREN STRING RPAREN { $$=mk_action( SET_USERPASS_T, 
851                                                                                                                 STRING_ST, 0, $3, 0); }
852                 | SET_USERPASS error { $$=0; yyerror("missing '(' or ')' ?"); }
853                 | SET_USERPASS LPAREN error RPAREN { $$=0; yyerror("bad argument, "
854                                                                                                                 "string expected"); }
855                 | SET_URI LPAREN STRING RPAREN { $$=mk_action( SET_URI_T, STRING_ST, 
856                                                                                                                 0, $3, 0); }
857                 | SET_URI error { $$=0; yyerror("missing '(' or ')' ?"); }
858                 | SET_URI LPAREN error RPAREN { $$=0; yyerror("bad argument, "
859                                                                                 "string expected"); }
860                 | REVERT_URI LPAREN RPAREN { $$=mk_action( REVERT_URI_T, 0,0,0,0); }
861                 | REVERT_URI { $$=mk_action( REVERT_URI_T, 0,0,0,0); }
862                 | ID LPAREN RPAREN                      { f_tmp=(void*)find_export($1, 0);
863                                                                            if (f_tmp==0){
864                                                                                 yyerror("unknown command, missing"
865                                                                                 " loadmodule?\n");
866                                                                                 $$=0;
867                                                                            }else{
868                                                                                 $$=mk_action(   MODULE_T,
869                                                                                                                 CMDF_ST,
870                                                                                                                 0,
871                                                                                                                 f_tmp,
872                                                                                                                 0
873                                                                                                         );
874                                                                            }
875                                                                         }
876                 | ID LPAREN STRING RPAREN { f_tmp=(void*)find_export($1, 1);
877                                                                         if (f_tmp==0){
878                                                                                 yyerror("unknown command, missing"
879                                                                                 " loadmodule?\n");
880                                                                                 $$=0;
881                                                                         }else{
882                                                                                 $$=mk_action(   MODULE_T,
883                                                                                                                 CMDF_ST,
884                                                                                                                 STRING_ST,
885                                                                                                                 f_tmp,
886                                                                                                                 $3
887                                                                                                         );
888                                                                         }
889                                                                   }
890                 | ID LPAREN STRING  COMMA STRING RPAREN 
891                                                                   { f_tmp=(void*)find_export($1, 2);
892                                                                         if (f_tmp==0){
893                                                                                 yyerror("unknown command, missing"
894                                                                                 " loadmodule?\n");
895                                                                                 $$=0;
896                                                                         }else{
897                                                                                 $$=mk_action3(  MODULE_T,
898                                                                                                                 CMDF_ST,
899                                                                                                                 STRING_ST,
900                                                                                                                 STRING_ST,
901                                                                                                                 f_tmp,
902                                                                                                                 $3,
903                                                                                                                 $5
904                                                                                                         );
905                                                                         }
906                                                                   }
907                 | ID LPAREN error RPAREN { $$=0; yyerror("bad arguments"); }
908                 | if_cmd                { $$=$1; }
909         ;
910
911
912 %%
913
914 extern int line;
915 extern int column;
916 extern int startcolumn;
917 void yyerror(char* s)
918 {
919         LOG(L_CRIT, "parse error (%d,%d-%d): %s\n", line, startcolumn, 
920                         column, s);
921         cfg_errors++;
922 }
923
924 /*
925 int main(int argc, char ** argv)
926 {
927         if (yyparse()!=0)
928                 fprintf(stderr, "parsing error\n");
929 }
930 */