- ipv6 support (-DUSE_IPV6)
[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
25 #include "config.h"
26
27 #ifdef DEBUG_DMALLOC
28 #include <dmalloc.h>
29 #endif
30
31
32 extern int yylex();
33 void yyerror(char* s);
34 char* tmp;
35 void* f_tmp;
36
37 %}
38
39 %union {
40         int intval;
41         unsigned uval;
42         char* strval;
43         struct expr* expr;
44         struct action* action;
45         struct net* ipnet;
46         struct ip_addr* ipaddr;
47 }
48
49 /* terminals */
50
51
52 /* keywords */
53 %token FORWARD
54 %token SEND
55 %token DROP
56 %token LOG_TOK
57 %token ERROR
58 %token ROUTE
59 %token EXEC
60 %token SET_HOST
61 %token SET_HOSTPORT
62 %token PREFIX
63 %token STRIP
64 %token SET_USER
65 %token SET_USERPASS
66 %token SET_PORT
67 %token SET_URI
68 %token IF
69 %token ELSE
70 %token URIHOST
71 %token URIPORT
72 %token MAX_LEN
73 %token SETFLAG
74 %token RESETFLAG
75 %token ISFLAGSET
76 %token LEN_GT
77 %token METHOD
78 %token URI
79 %token SRCIP
80 %token DSTIP
81
82 /* config vars. */
83 %token DEBUG
84 %token FORK
85 %token LOGSTDERROR
86 %token LISTEN
87 %token DNS
88 %token REV_DNS
89 %token PORT
90 %token STAT
91 %token CHILDREN
92 %token CHECK_VIA
93 %token LOOP_CHECKS
94 %token LOADMODULE
95 %token MODPARAM
96 %token MAXBUFFER
97
98
99
100 /* operators */
101 %nonassoc EQUAL
102 %nonassoc EQUAL_T
103 %nonassoc MATCH
104 %left OR
105 %left AND
106 %left NOT
107
108 /* values */
109 %token <intval> NUMBER
110 %token <strval> ID
111 %token <strval> STRING
112 %token <strval> IPV6ADDR
113
114 /* other */
115 %token COMMA
116 %token SEMICOLON
117 %token RPAREN
118 %token LPAREN
119 %token LBRACE
120 %token RBRACE
121 %token LBRACK
122 %token RBRACK
123 %token SLASH
124 %token DOT
125 %token CR
126
127
128 /*non-terminals */
129 %type <expr> exp, exp_elem /*, condition*/
130 %type <action> action, actions, cmd, if_cmd, stm
131 %type <ipaddr> ipv4, ipv6, ip
132 %type <ipnet> ipnet
133 %type <strval> host
134 /*%type <route_el> rules;
135   %type <route_el> rule;
136 */
137
138
139
140 %%
141
142
143 cfg:    statements
144         ;
145
146 statements:     statements statement {}
147                 | statement {}
148                 | statements error { yyerror(""); YYABORT;}
149         ;
150
151 statement:      assign_stm 
152                 | module_stm
153                 | route_stm 
154                 | CR    /* null statement*/
155         ;
156
157 assign_stm:     DEBUG EQUAL NUMBER { debug=$3; }
158                 | DEBUG EQUAL error  { yyerror("number  expected"); }
159                 | FORK  EQUAL NUMBER { dont_fork= ! $3; }
160                 | FORK  EQUAL error  { yyerror("boolean value expected"); }
161                 | LOGSTDERROR EQUAL NUMBER { log_stderr=$3; }
162                 | LOGSTDERROR EQUAL error { yyerror("boolean value expected"); }
163                 | DNS EQUAL NUMBER   { received_dns|= ($3)?DO_DNS:0; }
164                 | DNS EQUAL error { yyerror("boolean value expected"); }
165                 | REV_DNS EQUAL NUMBER { received_dns|= ($3)?DO_REV_DNS:0; }
166                 | REV_DNS EQUAL error { yyerror("boolean value expected"); }
167                 | PORT EQUAL NUMBER   { port_no=$3; }
168                 | STAT EQUAL STRING {
169                                         #ifdef STATS
170                                                         stat_file=$3;
171                                         #endif
172                                                         }
173                 | MAXBUFFER EQUAL NUMBER { maxbuffer=$3; }
174                 | MAXBUFFER EQUAL error { yyerror("number expected"); }
175                 | PORT EQUAL error    { yyerror("number expected"); } 
176                 | CHILDREN EQUAL NUMBER { children_no=$3; }
177                 | CHILDREN EQUAL error { yyerror("number expected"); } 
178                 | CHECK_VIA EQUAL NUMBER { check_via=$3; }
179                 | CHECK_VIA EQUAL error { yyerror("boolean value expected"); }
180                 | LOOP_CHECKS EQUAL NUMBER { loop_checks=$3; }
181                 | LOOP_CHECKS EQUAL error { yyerror("boolean value expected"); }
182                 | LISTEN EQUAL ip  {
183                                                                 if (addresses_no < MAX_LISTEN){
184                                                                         tmp=ip_addr2a($3);
185                                                                 /*      tmp=inet_ntoa(*(struct in_addr*)&$3);*/
186                                                                         if (tmp==0){
187                                                                                 LOG(L_CRIT, "ERROR: cfg. parser: "
188                                                                                         " bad ip address: %s\n",
189                                                                                         strerror(errno));
190                                                                         }else{
191                                                                                 names[addresses_no]=
192                                                                                                 (char*)malloc(strlen(tmp)+1);
193                                                                                 if (names[addresses_no]==0){
194                                                                                         LOG(L_CRIT, "ERROR: cfg. parser: "
195                                                                                                                 "out of memory.\n");
196                                                                                 }else{
197                                                                                         strncpy(names[addresses_no], tmp,
198                                                                                                         strlen(tmp)+1);
199                                                                                         addresses_no++;
200                                                                                 }
201                                                                         }
202                                                                 }else{
203                                                                         LOG(L_CRIT, "ERROR: cfg. parser:"
204                                                                                                 " too many listen addresses"
205                                                                                                 "(max. %d).\n", MAX_LISTEN);
206                                                                 }
207                                                           }
208                 | LISTEN EQUAL ID        {
209                                                                 if (addresses_no < MAX_LISTEN){
210                                                                         names[addresses_no]=
211                                                                                                 (char*)malloc(strlen($3)+1);
212                                                                         if (names[addresses_no]==0){
213                                                                                 LOG(L_CRIT, "ERROR: cfg. parser:"
214                                                                                                                 " out of memory.\n");
215                                                                         }else{
216                                                                                 strncpy(names[addresses_no], $3,
217                                                                                                         strlen($3)+1);
218                                                                                 addresses_no++;
219                                                                         }
220                                                                 }else{
221                                                                         LOG(L_CRIT, "ERROR: cfg. parser: "
222                                                                                                 "too many listen addresses"
223                                                                                                 "(max. %d).\n", MAX_LISTEN);
224                                                                 }
225                                                           }
226                 | LISTEN EQUAL STRING {
227                                                                 if (addresses_no < MAX_LISTEN){
228                                                                         names[addresses_no]=
229                                                                                 (char*)malloc(strlen($3)+1);
230                                                                         if (names[addresses_no]==0){
231                                                                                 LOG(L_CRIT, "ERROR: cfg. parser:"
232                                                                                                         " out of memory.\n");
233                                                                         }else{
234                                                                                 strncpy(names[addresses_no], $3,
235                                                                                                 strlen($3)+1);
236                                                                                 addresses_no++;
237                                                                         }
238                                                                 }else{
239                                                                         LOG(L_CRIT, "ERROR: cfg. parser: "
240                                                                                                 "too many listen addresses"
241                                                                                                 "(max. %d).\n", MAX_LISTEN);
242                                                                 }
243                                                           }
244                 | LISTEN EQUAL  error { yyerror("ip address or hostname"
245                                                 "expected"); }
246                 | error EQUAL { yyerror("unknown config variable"); }
247         ;
248
249 module_stm:     LOADMODULE STRING       { DBG("loading module %s\n", $2);
250                                                                   if (load_module($2)!=0){
251                                                                                 yyerror("failed to load module");
252                                                                   }
253                                                                 }
254                  | LOADMODULE error     { yyerror("string expected");  }
255                  | MODPARAM LPAREN STRING COMMA STRING COMMA STRING RPAREN {
256                          if (set_mod_param($3, $5, STR_PARAM, $7) != 0) {
257                                  yyerror("Can't set module parameter");
258                          }
259                    }
260                  | MODPARAM LPAREN STRING COMMA STRING COMMA NUMBER RPAREN {
261                          if (set_mod_param($3, $5, INT_PARAM, (void*)$7) != 0) {
262                                  yyerror("Can't set module parameter");
263                          }
264                    }
265                  | MODPARAM error { yyerror("Invalid arguments"); }
266                  ;
267
268
269 ip:              ipv4  { $$=$1; }
270                 |ipv6  { $$=$1; }
271                 ;
272
273 ipv4:   NUMBER DOT NUMBER DOT NUMBER DOT NUMBER { 
274                                                                                         $$=malloc(sizeof(struct ip_addr));
275                                                                                         if ($$==0){
276                                                                                                 LOG(L_CRIT, "ERROR: cfg. "
277                                                                                                         "parser: out of memory.\n"
278                                                                                                         );
279                                                                                         }else{
280                                                                                                 memset($$, 0, 
281                                                                                                         sizeof(struct ip_addr));
282                                                                                                 $$->af=AF_INET;
283                                                                                                 $$->len=4;
284                                                                                                 if (($1>255) || ($1<0) ||
285                                                                                                         ($3>255) || ($3<0) ||
286                                                                                                         ($5>255) || ($5<0) ||
287                                                                                                         ($7>255) || ($7<0)){
288                                                                                                         yyerror("invalid ipv4"
289                                                                                                                         "address");
290                                                                                                         $$->u.addr32[0]=0;
291                                                                                                         /* $$=0; */
292                                                                                                 }else{
293                                                                                                         $$->u.addr[0]=$1;
294                                                                                                         $$->u.addr[1]=$3;
295                                                                                                         $$->u.addr[2]=$5;
296                                                                                                         $$->u.addr[3]=$7;
297                                                                                                         /*
298                                                                                                         $$=htonl( ($1<<24)|
299                                                                                                         ($3<<16)| ($5<<8)|$7 );
300                                                                                                         */
301                                                                                                 }
302                                                                                         }
303                                                                                                 }
304         ;
305
306 ipv6:   IPV6ADDR {
307                                         $$=malloc(sizeof(struct ip_addr));
308                                         if ($$==0){
309                                                 LOG(L_CRIT, "ERROR: cfg. parser: out of memory.\n");
310                                         }else{
311                                                 memset($$, 0, sizeof(struct ip_addr));
312                                                 $$->af=AF_INET6;
313                                                 $$->len=16;
314                                         #ifndef USE_IPV6
315                                                 yyerror("ipv6 address & no ipv6 support compiled in");
316                                                 YYABORT;
317                                         #endif
318                                                 if (inet_pton(AF_INET6, $1, $$->u.addr)<=0){
319                                                         yyerror("bad ipv6 address");
320                                                 }
321                                         }
322                                 }
323         ;
324
325
326 route_stm:      ROUTE LBRACE actions RBRACE { push($3, &rlist[DEFAULT_RT]); }
327
328                 | ROUTE LBRACK NUMBER RBRACK LBRACE actions RBRACE { 
329                                                                                 if (($3<RT_NO) && ($3>=0)){
330                                                                                         push($6, &rlist[$3]);
331                                                                                 }else{
332                                                                                         yyerror("invalid routing"
333                                                                                                         "table number");
334                                                                                         YYABORT; }
335                                                                                 }
336                 | ROUTE error { yyerror("invalid  route  statement"); }
337         ;
338 /*
339 rules:  rules rule { push($2, &$1); $$=$1; }
340         | rule {$$=$1; }
341         | rules error { $$=0; yyerror("invalid rule"); }
342          ;
343
344 rule:   condition       actions CR {
345                                                                 $$=0;
346                                                                 if (add_rule($1, $2, &$$)<0) {
347                                                                         yyerror("error calling add_rule");
348                                                                         YYABORT;
349                                                                 }
350                                                           }
351         | CR            { $$=0;}
352         | condition error { $$=0; yyerror("bad actions in rule"); }
353         ;
354
355 condition:      exp {$$=$1;}
356 */
357
358 exp:    exp AND exp     { $$=mk_exp(AND_OP, $1, $3); }
359         | exp OR  exp           { $$=mk_exp(OR_OP, $1, $3);  }
360         | NOT exp                       { $$=mk_exp(NOT_OP, $2, 0);  }
361         | LPAREN exp RPAREN     { $$=$2; }
362         | exp_elem                      { $$=$1; }
363         ;
364
365 exp_elem:       METHOD EQUAL_T STRING   {$$= mk_elem(   EQUAL_OP, STRING_ST, 
366                                                                                                         METHOD_O, $3);
367                                                                         }
368                 | METHOD EQUAL_T ID     {$$ = mk_elem(  EQUAL_OP, STRING_ST,
369                                                                                         METHOD_O, $3); 
370                                                         }
371                 | METHOD EQUAL_T error { $$=0; yyerror("string expected"); }
372                 | METHOD MATCH STRING   {$$ = mk_elem(  MATCH_OP, STRING_ST,
373                                                                                                 METHOD_O, $3); 
374                                                                 }
375                 | METHOD MATCH ID       {$$ = mk_elem(  MATCH_OP, STRING_ST,
376                                                                                         METHOD_O, $3); 
377                                                         }
378                 | METHOD MATCH error { $$=0; yyerror("string expected"); }
379                 | METHOD error  { $$=0; yyerror("invalid operator,"
380                                                                                 "== or =~ expected");
381                                                 }
382                 | URI EQUAL_T STRING    {$$ = mk_elem(  EQUAL_OP, STRING_ST,
383                                                                                                 URI_O, $3); 
384                                                                 }
385                 | URI EQUAL_T ID        {$$ = mk_elem(  EQUAL_OP, STRING_ST,
386                                                                                         URI_O, $3); 
387                                                         }
388                 | URI EQUAL_T error { $$=0; yyerror("string expected"); }
389                 | URI MATCH STRING      { $$=mk_elem(   MATCH_OP, STRING_ST,
390                                                                                         URI_O, $3);
391                                                         }
392                 | URI MATCH ID          { $$=mk_elem(   MATCH_OP, STRING_ST,
393                                                                                         URI_O, $3);
394                                                         }
395                 | URI MATCH error {  $$=0; yyerror("string expected"); }
396                 | URI error     { $$=0; yyerror("invalid operator,"
397                                                                         " == or =~ expected");
398                                         }
399                 | SRCIP EQUAL_T ipnet   { $$=mk_elem(   EQUAL_OP, NET_ST,
400                                                                                                 SRCIP_O, $3);
401                                                                 }
402                 | SRCIP EQUAL_T STRING  { $$=mk_elem(   EQUAL_OP, STRING_ST,
403                                                                                                 SRCIP_O, $3);
404                                                                 }
405                 | SRCIP EQUAL_T host    { $$=mk_elem(   EQUAL_OP, STRING_ST,
406                                                                                                 SRCIP_O, $3);
407                                                                 }
408                 | SRCIP EQUAL_T error { $$=0; yyerror( "ip address or hostname"
409                                                  "expected" ); }
410                 | SRCIP MATCH STRING    { $$=mk_elem(   MATCH_OP, STRING_ST,
411                                                                                                 SRCIP_O, $3);
412                                                                 }
413                 | SRCIP MATCH ID                { $$=mk_elem(   MATCH_OP, STRING_ST,
414                                                                                                 SRCIP_O, $3);
415                                                                 }
416                 | SRCIP MATCH error  { $$=0; yyerror( "hostname expected"); }
417                 | SRCIP error  { $$=0; 
418                                                  yyerror("invalid operator, == or =~ expected");}
419                 | DSTIP EQUAL_T ipnet   { $$=mk_elem(   EQUAL_OP, NET_ST,
420                                                                                                 DSTIP_O, $3);
421                                                                 }
422                 | DSTIP EQUAL_T STRING  { $$=mk_elem(   EQUAL_OP, STRING_ST,
423                                                                                                 DSTIP_O, $3);
424                                                                 }
425                 | DSTIP EQUAL_T host    { $$=mk_elem(   EQUAL_OP, STRING_ST,
426                                                                                                 DSTIP_O, $3);
427                                                                 }
428                 | DSTIP EQUAL_T error { $$=0; yyerror( "ip address or hostname"
429                                                                         "expected" ); }
430                 | DSTIP MATCH STRING    { $$=mk_elem(   MATCH_OP, STRING_ST,
431                                                                                                 DSTIP_O, $3);
432                                                                 }
433                 | DSTIP MATCH ID        { $$=mk_elem(   MATCH_OP, STRING_ST,
434                                                                                         DSTIP_O, $3);
435                                                         }
436                 | DSTIP MATCH error  { $$=0; yyerror ( "hostname  expected" ); }
437                 | DSTIP error { $$=0; 
438                                                 yyerror("invalid operator, == or =~ expected");}
439                 | stm                           { $$=mk_elem( NO_OP, ACTIONS_ST, ACTION_O, $1 ); }
440                 | NUMBER                {$$=mk_elem( NO_OP, NUMBER_ST, NUMBER_O, (void*)$1 ); }
441         ;
442
443 ipnet:  ip SLASH ip     { $$=mk_net($1, $3); } 
444         | ip SLASH NUMBER       {       if (($3<0) || ($3>$1->len*8)){
445                                                                 yyerror("invalid bit number in netmask");
446                                                                 $$=0;
447                                                         }else{
448                                                                 $$=mk_net_bitlen($1, $3);
449                                                         /*
450                                                                 $$=mk_net($1, 
451                                                                                 htonl( ($3)?~( (1<<(32-$3))-1 ):0 ) );
452                                                         */
453                                                         }
454                                                 }
455         | ip                            { $$=mk_net_bitlen($1, $1->len*8); }
456         | ip SLASH error        { $$=0;
457                                                  yyerror("netmask (eg:255.0.0.0 or 8) expected");
458                                                 }
459         ;
460
461 host:   ID                              { $$=$1; }
462         | host DOT ID           { $$=(char*)malloc(strlen($1)+1+strlen($3)+1);
463                                                   if ($$==0){
464                                                         LOG(L_CRIT, "ERROR: cfg. parser: memory allocation"
465                                                                                 " failure while parsing host\n");
466                                                   }else{
467                                                         memcpy($$, $1, strlen($1));
468                                                         $$[strlen($1)]='.';
469                                                         memcpy($$+strlen($1)+1, $3, strlen($3));
470                                                         $$[strlen($1)+1+strlen($3)]=0;
471                                                   }
472                                                   free($1); free($3);
473                                                 };
474         | host DOT error { $$=0; free($1); yyerror("invalid hostname"); }
475         ;
476
477
478 stm:            cmd                                             { $$=$1; }
479                 |       LBRACE actions RBRACE   { $$=$2; }
480         ;
481
482 actions:        actions action  {$$=append_action($1, $2); }
483                 | action                        {$$=$1;}
484                 | actions error { $$=0; yyerror("bad command"); }
485         ;
486
487 action:         cmd SEMICOLON {$$=$1;}
488                 | SEMICOLON /* null action */ {$$=0;}
489                 | cmd error { $$=0; yyerror("bad command: missing ';'?"); }
490         ;
491
492 if_cmd:         IF exp stm                              { $$=mk_action3( IF_T,
493                                                                                                          EXPR_ST,
494                                                                                                          ACTIONS_ST,
495                                                                                                          NOSUBTYPE,
496                                                                                                          $2,
497                                                                                                          $3,
498                                                                                                          0);
499                                                                         }
500                 |       IF exp stm ELSE stm             { $$=mk_action3( IF_T,
501                                                                                                          EXPR_ST,
502                                                                                                          ACTIONS_ST,
503                                                                                                          ACTIONS_ST,
504                                                                                                          $2,
505                                                                                                          $3,
506                                                                                                          $5);
507                                                                         }
508         ;
509
510 cmd:            FORWARD LPAREN host RPAREN      { $$=mk_action( FORWARD_T,
511                                                                                                                 STRING_ST,
512                                                                                                                 NUMBER_ST,
513                                                                                                                 $3,
514                                                                                                                 0);
515                                                                                 }
516                 | FORWARD LPAREN STRING RPAREN  { $$=mk_action( FORWARD_T,
517                                                                                                                 STRING_ST,
518                                                                                                                 NUMBER_ST,
519                                                                                                                 $3,
520                                                                                                                 0);
521                                                                                 }
522                 | FORWARD LPAREN ip RPAREN      { $$=mk_action( FORWARD_T,
523                                                                                                                 IP_ST,
524                                                                                                                 NUMBER_ST,
525                                                                                                                 (void*)$3,
526                                                                                                                 0);
527                                                                                 }
528                 | FORWARD LPAREN host COMMA NUMBER RPAREN { $$=mk_action(FORWARD_T,
529                                                                                                                                  STRING_ST,
530                                                                                                                                  NUMBER_ST,
531                                                                                                                                 $3,
532                                                                                                                                 (void*)$5);
533                                                                                                  }
534                 | FORWARD LPAREN STRING COMMA NUMBER RPAREN {$$=mk_action(FORWARD_T,
535                                                                                                                                  STRING_ST,
536                                                                                                                                  NUMBER_ST,
537                                                                                                                                 $3,
538                                                                                                                                 (void*)$5);
539                                                                                                         }
540                 | FORWARD LPAREN ip COMMA NUMBER RPAREN { $$=mk_action(FORWARD_T,
541                                                                                                                                  IP_ST,
542                                                                                                                                  NUMBER_ST,
543                                                                                                                                  (void*)$3,
544                                                                                                                                 (void*)$5);
545                                                                                                   }
546                 | FORWARD LPAREN URIHOST COMMA URIPORT RPAREN {
547                                                                                                         $$=mk_action(FORWARD_T,
548                                                                                                                                  URIHOST_ST,
549                                                                                                                                  URIPORT_ST,
550                                                                                                                                 0,
551                                                                                                                                 0);
552                                                                                                         }
553                                                                                                         
554                                                                         
555                 | FORWARD LPAREN URIHOST COMMA NUMBER RPAREN {
556                                                                                                         $$=mk_action(FORWARD_T,
557                                                                                                                                  URIHOST_ST,
558                                                                                                                                  NUMBER_ST,
559                                                                                                                                 0,
560                                                                                                                                 (void*)$5);
561                                                                                                         }
562                 | FORWARD LPAREN URIHOST RPAREN {
563                                                                                                         $$=mk_action(FORWARD_T,
564                                                                                                                                  URIHOST_ST,
565                                                                                                                                  NUMBER_ST,
566                                                                                                                                 0,
567                                                                                                                                 0);
568                                                                                 }
569                 | FORWARD error { $$=0; yyerror("missing '(' or ')' ?"); }
570                 | FORWARD LPAREN error RPAREN { $$=0; yyerror("bad forward"
571                                                                                 "argument"); }
572                 | SEND LPAREN host RPAREN       { $$=mk_action( SEND_T,
573                                                                                                         STRING_ST,
574                                                                                                         NUMBER_ST,
575                                                                                                         $3,
576                                                                                                         0);
577                                                                         }
578                 | SEND LPAREN STRING RPAREN { $$=mk_action(     SEND_T,
579                                                                                                         STRING_ST,
580                                                                                                         NUMBER_ST,
581                                                                                                         $3,
582                                                                                                         0);
583                                                                         }
584                 | SEND LPAREN ip RPAREN         { $$=mk_action( SEND_T,
585                                                                                                         IP_ST,
586                                                                                                         NUMBER_ST,
587                                                                                                         (void*)$3,
588                                                                                                         0);
589                                                                         }
590                 | SEND LPAREN host COMMA NUMBER RPAREN  { $$=mk_action( SEND_T,
591                                                                                                                                 STRING_ST,
592                                                                                                                                 NUMBER_ST,
593                                                                                                                                 $3,
594                                                                                                                                 (void*)$5);
595                                                                                                 }
596                 | SEND LPAREN STRING COMMA NUMBER RPAREN {$$=mk_action( SEND_T,
597                                                                                                                                 STRING_ST,
598                                                                                                                                 NUMBER_ST,
599                                                                                                                                 $3,
600                                                                                                                                 (void*)$5);
601                                                                                                 }
602                 | SEND LPAREN ip COMMA NUMBER RPAREN { $$=mk_action(    SEND_T,
603                                                                                                                                 IP_ST,
604                                                                                                                                 NUMBER_ST,
605                                                                                                                                 (void*)$3,
606                                                                                                                                 (void*)$5);
607                                                                                            }
608                 | SEND error { $$=0; yyerror("missing '(' or ')' ?"); }
609                 | SEND LPAREN error RPAREN { $$=0; yyerror("bad send"
610                                                                                                         "argument"); }
611                 | DROP LPAREN RPAREN    {$$=mk_action(DROP_T,0, 0, 0, 0); }
612                 | DROP                                  {$$=mk_action(DROP_T,0, 0, 0, 0); }
613                 | LOG_TOK LPAREN STRING RPAREN  {$$=mk_action(  LOG_T, NUMBER_ST, 
614                                                                                                         STRING_ST,(void*)4,$3);
615                                                                         }
616                 | LOG_TOK LPAREN NUMBER COMMA STRING RPAREN     {$$=mk_action(  LOG_T,
617                                                                                                                                 NUMBER_ST, 
618                                                                                                                                 STRING_ST,
619                                                                                                                                 (void*)$3,
620                                                                                                                                 $5);
621                                                                                                 }
622                 | LOG_TOK error { $$=0; yyerror("missing '(' or ')' ?"); }
623                 | LOG_TOK LPAREN error RPAREN { $$=0; yyerror("bad log"
624                                                                         "argument"); }
625                 | SETFLAG LPAREN NUMBER RPAREN {$$=mk_action( SETFLAG_T, NUMBER_ST, 0,
626                                                                                                         (void *)$3, 0 ); }
627                 | SETFLAG error { $$=0; yyerror("missing '(' or ')'?"); }
628
629                 | LEN_GT LPAREN NUMBER RPAREN {$$=mk_action( LEN_GT_T, NUMBER_ST, 0,
630                                                                                                         (void *)$3, 0 ); }
631                 | LEN_GT LPAREN MAX_LEN RPAREN {$$=mk_action( LEN_GT_T, NUMBER_ST, 0,
632                                                                                                         (void *) BUF_SIZE, 0 ); }
633                 | LEN_GT error { $$=0; yyerror("missing '(' or ')'?"); }
634
635                 | RESETFLAG LPAREN NUMBER RPAREN {$$=mk_action( RESETFLAG_T, NUMBER_ST, 0,
636                                                                                                         (void *)$3, 0 ); }
637                 | RESETFLAG error { $$=0; yyerror("missing '(' or ')'?"); }
638                 | ISFLAGSET LPAREN NUMBER RPAREN {$$=mk_action( ISFLAGSET_T, NUMBER_ST, 0,
639                                                                                                         (void *)$3, 0 ); }
640                 | ISFLAGSET error { $$=0; yyerror("missing '(' or ')'?"); }
641                 | ERROR LPAREN STRING COMMA STRING RPAREN {$$=mk_action(ERROR_T,
642                                                                                                                                 STRING_ST, 
643                                                                                                                                 STRING_ST,
644                                                                                                                                 $3,
645                                                                                                                                 $5);
646                                                                                                   }
647                 | ERROR error { $$=0; yyerror("missing '(' or ')' ?"); }
648                 | ERROR LPAREN error RPAREN { $$=0; yyerror("bad error"
649                                                                                                                 "argument"); }
650                 | ROUTE LPAREN NUMBER RPAREN    { $$=mk_action(ROUTE_T, NUMBER_ST,
651                                                                                                                 0, (void*)$3, 0);
652                                                                                 }
653                 | ROUTE error { $$=0; yyerror("missing '(' or ')' ?"); }
654                 | ROUTE LPAREN error RPAREN { $$=0; yyerror("bad route"
655                                                 "argument"); }
656                 | EXEC LPAREN STRING RPAREN     { $$=mk_action( EXEC_T, STRING_ST, 0,
657                                                                                                         $3, 0);
658                                                                         }
659                 | SET_HOST LPAREN STRING RPAREN { $$=mk_action(SET_HOST_T, STRING_ST,
660                                                                                                                 0, $3, 0); }
661                 | SET_HOST error { $$=0; yyerror("missing '(' or ')' ?"); }
662                 | SET_HOST LPAREN error RPAREN { $$=0; yyerror("bad argument, "
663                                                                                                                 "string expected"); }
664
665                 | PREFIX LPAREN STRING RPAREN { $$=mk_action(PREFIX_T, STRING_ST,
666                                                                                                                 0, $3, 0); }
667                 | PREFIX error { $$=0; yyerror("missing '(' or ')' ?"); }
668                 | PREFIX LPAREN error RPAREN { $$=0; yyerror("bad argument, "
669                                                                                                                 "string expected"); }
670                 | STRIP LPAREN NUMBER RPAREN { $$=mk_action(STRIP_T, NUMBER_ST,
671                                                                                                                 0, (void *) $3, 0); }
672                 | STRIP error { $$=0; yyerror("missing '(' or ')' ?"); }
673                 | STRIP LPAREN error RPAREN { $$=0; yyerror("bad argument, "
674                                                                                                                 "number expected"); }
675
676                 | SET_HOSTPORT LPAREN STRING RPAREN { $$=mk_action( SET_HOSTPORT_T, 
677                                                                                                                 STRING_ST, 0, $3, 0); }
678                 | SET_HOSTPORT error { $$=0; yyerror("missing '(' or ')' ?"); }
679                 | SET_HOSTPORT LPAREN error RPAREN { $$=0; yyerror("bad argument,"
680                                                                                                 " string expected"); }
681                 | SET_PORT LPAREN STRING RPAREN { $$=mk_action( SET_PORT_T, STRING_ST,
682                                                                                                                 0, $3, 0); }
683                 | SET_PORT error { $$=0; yyerror("missing '(' or ')' ?"); }
684                 | SET_PORT LPAREN error RPAREN { $$=0; yyerror("bad argument, "
685                                                                                                                 "string expected"); }
686                 | SET_USER LPAREN STRING RPAREN { $$=mk_action( SET_USER_T, STRING_ST,
687                                                                                                                 0, $3, 0); }
688                 | SET_USER error { $$=0; yyerror("missing '(' or ')' ?"); }
689                 | SET_USER LPAREN error RPAREN { $$=0; yyerror("bad argument, "
690                                                                                                                 "string expected"); }
691                 | SET_USERPASS LPAREN STRING RPAREN { $$=mk_action( SET_USERPASS_T, 
692                                                                                                                 STRING_ST, 0, $3, 0); }
693                 | SET_USERPASS error { $$=0; yyerror("missing '(' or ')' ?"); }
694                 | SET_USERPASS LPAREN error RPAREN { $$=0; yyerror("bad argument, "
695                                                                                                                 "string expected"); }
696                 | SET_URI LPAREN STRING RPAREN { $$=mk_action( SET_URI_T, STRING_ST, 
697                                                                                                                 0, $3, 0); }
698                 | SET_URI error { $$=0; yyerror("missing '(' or ')' ?"); }
699                 | SET_URI LPAREN error RPAREN { $$=0; yyerror("bad argument, "
700                                                                                 "string expected"); }
701                 | ID LPAREN RPAREN                      { f_tmp=(void*)find_export($1, 0);
702                                                                            if (f_tmp==0){
703                                                                                 yyerror("unknown command, missing"
704                                                                                 " loadmodule?\n");
705                                                                                 $$=0;
706                                                                            }else{
707                                                                                 $$=mk_action(   MODULE_T,
708                                                                                                                 CMDF_ST,
709                                                                                                                 0,
710                                                                                                                 f_tmp,
711                                                                                                                 0
712                                                                                                         );
713                                                                            }
714                                                                         }
715                 | ID LPAREN STRING RPAREN { f_tmp=(void*)find_export($1, 1);
716                                                                         if (f_tmp==0){
717                                                                                 yyerror("unknown command, missing"
718                                                                                 " loadmodule?\n");
719                                                                                 $$=0;
720                                                                         }else{
721                                                                                 $$=mk_action(   MODULE_T,
722                                                                                                                 CMDF_ST,
723                                                                                                                 STRING_ST,
724                                                                                                                 f_tmp,
725                                                                                                                 $3
726                                                                                                         );
727                                                                         }
728                                                                   }
729                 | ID LPAREN STRING  COMMA STRING RPAREN 
730                                                                   { f_tmp=(void*)find_export($1, 2);
731                                                                         if (f_tmp==0){
732                                                                                 yyerror("unknown command, missing"
733                                                                                 " loadmodule?\n");
734                                                                                 $$=0;
735                                                                         }else{
736                                                                                 $$=mk_action3(  MODULE_T,
737                                                                                                                 CMDF_ST,
738                                                                                                                 STRING_ST,
739                                                                                                                 STRING_ST,
740                                                                                                                 f_tmp,
741                                                                                                                 $3,
742                                                                                                                 $5
743                                                                                                         );
744                                                                         }
745                                                                   }
746                 | ID LPAREN error RPAREN { $$=0; yyerror("bad arguments"); }
747                 | if_cmd                { $$=$1; }
748         ;
749
750
751 %%
752
753 extern int line;
754 extern int column;
755 extern int startcolumn;
756 void yyerror(char* s)
757 {
758         LOG(L_CRIT, "parse error (%d,%d-%d): %s\n", line, startcolumn, 
759                         column, s);
760         cfg_errors++;
761 }
762
763 /*
764 int main(int argc, char ** argv)
765 {
766         if (yyparse()!=0)
767                 fprintf(stderr, "parsing error\n");
768 }
769 */