crossroads

Git mirror of https://crossroads.e-tunity.com/
git clone git://git.finwo.net/app/crossroads
Log | Files | Refs

parser.y (24788B)


      1 /* Parser of crossroads configuration files */
      2 
      3 %{
      4 /* Prologue */
      5 #include "crossroads.h"
      6 
      7 #define YYSTYPE Confsets
      8 
      9 /* Static parser vars */
     10 static int i;				/* Loop counter */
     11 static Backend cur_backend;		/* Storage for a handled backend */
     12 static Service cur_service;		/* Storage for a handled service */
     13 
     14 /* Parser debugging related */
     15 // #define PARSER_DEBUG
     16 #ifdef PARSER_DEBUG
     17     static void pmsg (char const *x) {
     18 	printf ("P: %s\n", x);
     19     }
     20     static void psmsg (char const *x, char const *y) {
     21 	printf ("P: %s %s\n", x, y);
     22     }
     23     static void pimsg(char const *x, int y) {
     24 	printf ("P: %s %d\n", x, y);
     25     }
     26 #else
     27 #   define pmsg(x)
     28 #   define psmsg(x,y)
     29 #   define pimsg(x,y)
     30 #endif
     31 
     32 /* Error handler for yyparse() */
     33 static int yyerror (char *msg) {
     34     error ("Parse error at line %d, '%s': %s",
     35 	   yylineno + 1, yytext, yyerrmsg);
     36 }
     37 
     38 /* Store an encountered string */
     39 static char *laststr;
     40 static void setlaststr (char const *what) {
     41     free (laststr);
     42     laststr = xstrdup (what);
     43 }
     44 
     45 /* Store an encountered number */
     46 static int lastnr;
     47 static void setlastnr (char const *what) {
     48     lastnr = atoi (what);
     49 }
     50 
     51 /* Store an encountered 'over' number */
     52 static int lastovernr;
     53 static void setlastovernr (char const *what) {
     54     lastovernr = atoi(what);
     55 }
     56 
     57 /* Store an encountered 'externalhandler' */
     58 static char *lastext;
     59 static void setlastext (char const *what) {
     60     free (lastext);
     61     lastext = xstrdup (what);
     62 }
     63 
     64 /* Get the server part from HOSTNAME:PORT in allocated memory */
     65 static char *serverpart (char const *what) {
     66     char *ret = xstrdup (what);
     67     char *cp;
     68 
     69     if ( (cp = strchr (ret, ':')) )
     70 	*cp = 0;
     71     return (ret);
     72 }
     73 
     74 /* Get the port part from HOSTNAME:PORT */
     75 static int portpart (char const *what) {
     76     char *cp;
     77 
     78     if ( (cp = strchr (what, ':')) )
     79 	return (atoi (cp + 1));
     80     return (0);
     81 }
     82 
     83 /* Add a list of IP filters to the allowlist or the denylist */
     84 static void add_any (char *what, int chain) {
     85     char *item;
     86     int result;
     87     for (item = strtok (what, " "); item; item = strtok (0, " ")) {
     88 	if (chain)
     89 	    result = ipf_add_allow (&cur_service, item);
     90 	else
     91 	    result = ipf_add_deny  (&cur_service, item);
     92 	if (result)
     93 	    error ("Bad IP filter specifier '%s' at line %d",
     94 		   item, yylineno + 1);
     95     }
     96 }
     97 static void add_allowfrom (char *what) {
     98     add_any (what, 1);
     99 }
    100 static void add_denyfrom (char *what) {
    101     add_any (what, 0);
    102 }
    103 
    104 /* Set uid/gid for external commands. */
    105 static void setuseraccount (char *username) {
    106     struct passwd *pw;
    107 
    108     if (! (pw = getpwnam (username)) )
    109 	error ("Invalid username '%s' at line %d", username, yylineno + 1);
    110     cur_service.uid = pw->pw_uid;
    111     cur_service.gid = pw->pw_gid;
    112 }
    113 
    114 %}
    115 
    116 /* Declarations */
    117 %token SERVICE IDENTIFIER PORT NUMBER BACKEND VERBOSITY SERVER
    118        ON OFF DISPATCHMODE ROUNDROBIN REVIVINGINTERVAL SHMKEY WEIGHT
    119        ONSTART ONFAIL STRING BACKLOG RANDOM BYDURATION BYSIZE
    120        BYCONNECTIONS CONNECTIONTIMEOUT MAXCONNECTIONS BYORDER TRAFFICLOG
    121        OVER DECAY BINDTO THROUGHPUTLOG TYPE ANY HTTP
    122        STICKYCOOKIE ADDCLIENTHEADER SETCLIENTHEADER APPENDCLIENTHEADER
    123        ADDSERVERHEADER SETSERVERHEADER APPENDSERVERHEADER
    124        ALLOWFROM DENYFROM ALLOWFILE DENYFILE EXTERNALHANDLER ONEND
    125        USERACCOUNT
    126 
    127 %%
    128 /* Config file grammar rules */
    129 
    130 input:
    131         element
    132 	input
    133 |
    134 	element
    135 ;
    136 
    137 element:
    138 	service
    139 	servicename
    140 	'{'
    141 	servicestatements
    142 	'}' {
    143 	    /* Verify the service description, supply defaults
    144 	     * and so on.
    145 	     */
    146 	    if (!cur_service.port)
    147 		error ("Service %s lacks a port",
    148 		       cur_service.name);
    149 	    if (!cur_service.nbackend)
    150 		error ("Service %s lacks back ends",
    151 		       cur_service.name);
    152 
    153 	    if (!cur_service.shmkey)
    154 		cur_service.shmkey = cur_service.port | SHM_MASK;
    155 
    156 	    if (!cur_service.bind)
    157 		cur_service.bind = "any";
    158 
    159 	    /* Add to the list. */
    160 	    service = xrealloc (service, ++nservice * sizeof(Service));
    161 	    service[nservice - 1] = cur_service;
    162 	    memset (&cur_service, 0, sizeof(Service));
    163 	}
    164 ;
    165 
    166 service:
    167 	service_expected
    168 	SERVICE
    169 ;
    170 
    171 servicename:
    172 	servicename_expected
    173 	IDENTIFIER {
    174 	    psmsg ("service:", yytext);
    175 	    cur_service.name = xstrdup(yytext);
    176 	}
    177 ;
    178 
    179 servicestatements:
    180 	servicestatements
    181 	servicestatement
    182 |
    183 	servicestatement
    184 ;
    185 
    186 servicestatement:
    187 	servicebody_expected
    188 	servicebody
    189 ;
    190 
    191 servicebody:
    192 	portstatement {
    193 	    pimsg ("sevice port:", $1.set[0].v.ival);
    194 	    cur_service.port = $1.set[0].v.ival;
    195 	    free ($1.set);
    196 	}
    197 |
    198 	bindstatement {
    199 	    psmsg ("service binding:", $1.set[0].v.sval);
    200 	    cur_service.bind = $1.set[0].v.sval;
    201 	    free ($1.set);
    202 	}
    203 |
    204 	verbositystatement {
    205 	    pimsg ("service verbosity:", $1.set[0].v.ival);
    206 	    cur_service.verbosity = $1.set[0].v.ival;
    207 	    free ($1.set);
    208 	}
    209 |
    210 	dispatchmodestatement {
    211 	    pimsg ("service dispatch mode:", $1.set[0].v.ival);
    212 	    pimsg ("service dispatch over:", lastovernr);
    213 	    psmsg ("service dispatch exth:", lastext);
    214 	    cur_service.dispatchtype = $1.set[0].v.ival;
    215 	    cur_service.dispatchover = lastovernr;
    216 	    cur_service.dispatchext  = lastext;
    217 	    free ($1.set);
    218 	}
    219 |
    220 	revivingintervalstatement {
    221 	    pimsg ("service revival interval:", $1.set[0].v.ival);
    222 	    cur_service.rev_interval = $1.set[0].v.ival;
    223 	    free ($1.set);
    224 	}
    225 |
    226 	backlogstatement {
    227 	    pimsg ("service backlog:", $1.set[0].v.ival);
    228 	    cur_service.backlog = $1.set[0].v.ival;
    229 	    free ($1.set);
    230 	}
    231 |
    232 	shmkeystatement {
    233 	    pimsg ("service shmkey:", $1.set[0].v.ival);
    234 	    cur_service.shmkey = $1.set[0].v.ival;
    235 	    free ($1.set);
    236 	}
    237 |
    238 	connectiontimeoutstatement {
    239 	    pimsg ("connection timout:", $1.set[0].v.ival);
    240 	    cur_service.connectiontimeout = $1.set[0].v.ival;
    241 	    free ($1.set);
    242 	}
    243 |
    244 	maxconnectionsstatement {
    245 	    pimsg ("max clients in service:", $1.set[0].v.ival);
    246 	    cur_service.maxconnections = $1.set[0].v.ival;
    247 	    free ($1.set);
    248 	}
    249 |
    250 	typestatement {
    251 	    pimsg ("service type: ", $1.set[0].v.ival);
    252 	    cur_service.type = $1.set[0].v.ival;
    253 	    free ($1.set);
    254 	}
    255 |
    256 	allowfromstatement {
    257 	    psmsg ("allow from: ", $1.set[0].v.sval);
    258 	    add_allowfrom ($1.set[0].v.sval);
    259 	    free ($1.set);
    260 	}
    261 |
    262 	allowfilestatement {
    263 	    psmsg ("allow file: ", $1.set[0].v.sval);
    264 	    cur_service.allowfile = $1.set[0].v.sval;
    265 	    free ($1.set);
    266 	}
    267 |
    268 	denyfromstatement {
    269 	    psmsg ("deny from: ", $1.set[0].v.sval);
    270 	    add_denyfrom ($1.set[0].v.sval);
    271 	    free ($1.set);
    272 	}
    273 |
    274 	denyfilestatement {
    275 	    psmsg ("deny file: ", $1.set[0].v.sval);
    276 	    cur_service.denyfile = $1.set[0].v.sval;
    277 	    free ($1.set);
    278 	}
    279 |
    280 	useraccountstatement {
    281 	    psmsg ("user account: ", $1.set[0].v.sval);
    282 	    setuseraccount ($1.set[0].v.sval);
    283 	    free ($1.set[0].v.sval);
    284 	    free ($1.set);
    285 	}
    286 |
    287 	backendblock {
    288 	    pimsg ("converting backend statements, count is", $1.n);
    289 	    for (i = 0; i < $1.n; i++)
    290 		switch ($1.set[i].cf) {
    291 		case cf_portspec:
    292 		    pimsg ("backend block port:", $1.set[i].v.ival);
    293 		    cur_backend.port = $1.set[i].v.ival;
    294 		    break;
    295 		case cf_serverspec:
    296 		    psmsg ("backend block server:", $1.set[i].v.sval);
    297 		    cur_backend.server = serverpart ($1.set[i].v.sval);
    298 		    cur_backend.port   = portpart ($1.set[i].v.sval);
    299 		    free ($1.set[i].v.sval);
    300 		    break;
    301 		case cf_verbosityspec:
    302 		    pimsg ("backend block verbosity:", $1.set[i].v.ival);
    303 		    cur_backend.verbosity = $1.set[i].v.ival;
    304 		    break;
    305 		case cf_onstartspec:
    306 		    psmsg ("backend block onstart:", $1.set[i].v.sval);
    307 		    cur_backend.onstart = $1.set[i].v.sval;
    308 		    break;
    309 		case cf_onfailspec:
    310 		    psmsg ("backend block onfail:", $1.set[i].v.sval);
    311 		    cur_backend.onfail = $1.set[i].v.sval;
    312 		    break;
    313 		case cf_onendspec:
    314 		    psmsg ("backend block onend:", $1.set[i].v.sval);
    315 		    cur_backend.onend = $1.set[i].v.sval;
    316 		    break;
    317 		case cf_dumpspec:
    318 		    psmsg ("backend trafficlog:", $1.set[i].v.sval);
    319 		    cur_backend.dumpfile = $1.set[i].v.sval;
    320 		    break;
    321 		case cf_thruspec:
    322 		    psmsg ("backend throughputlog:", $1.set[i].v.sval);
    323 		    cur_backend.thruputfile = $1.set[i].v.sval;
    324 		    break;
    325 		case cf_weightspec:
    326 		    pimsg ("backend weight:", $1.set[i].v.ival);
    327 		    cur_backend.weight = $1.set[i].v.ival;
    328 		    break;
    329 		case cf_decayspec:
    330 		    pimsg ("backend decay:", $1.set[i].v.ival);
    331 		    if ($1.set[i].v.ival >= 100)
    332 			error ("Decay specifier %d must be a percentage, "
    333 			       "never more than 99",
    334 			       $1.set[i].v.ival);
    335 		    cur_backend.decay = $1.set[i].v.ival;
    336 		    break;
    337 		case cf_maxconnectionsspec:
    338 		    pimsg ("backend max clients: ", $1.set[i].v.ival);
    339 		    cur_backend.maxconnections = $1.set[i].v.ival;
    340 		    break;
    341 		case cf_stickycookiespec:
    342 		    psmsg ("backend sticky cookie:",
    343 			   $1.set[i].v.sval);
    344 		    cur_backend.stickycookie = $1.set[i].v.sval;
    345 		    break;
    346 		case cf_addclientheaderspec:
    347 		    psmsg ("client header to add:",
    348 			   $1.set[i].v.sval);
    349 		    cur_backend.addclientheader =
    350 			xrealloc (cur_backend.addclientheader,
    351 				  (cur_backend.naddclientheader + 1) *
    352 				  sizeof(char*));
    353 		    cur_backend.addclientheader
    354 			[cur_backend.naddclientheader++] =
    355 			    $1.set[i].v.sval;
    356 		    break;
    357 		case cf_setclientheaderspec:
    358 		    psmsg ("client header to set:",
    359 			   $1.set[i].v.sval);
    360 		    cur_backend.setclientheader =
    361 			xrealloc (cur_backend.setclientheader,
    362 				  (cur_backend.nsetclientheader + 1) *
    363 				  sizeof(char*));
    364 		    cur_backend.setclientheader
    365 			[cur_backend.nsetclientheader++] =
    366 			    $1.set[i].v.sval;
    367 		    break;
    368 		case cf_appendclientheaderspec:
    369 		    psmsg ("client header to append:",
    370 			   $1.set[i].v.sval);
    371 		    cur_backend.appendclientheader =
    372 			xrealloc (cur_backend.appendclientheader,
    373 				  (cur_backend.nappendclientheader + 1) *
    374 				  sizeof(char*));
    375 		    cur_backend.appendclientheader
    376 			[cur_backend.nappendclientheader++] =
    377 			    $1.set[i].v.sval;
    378 		    break;
    379 		case cf_addserverheaderspec:
    380 		    psmsg ("server header to add:",
    381 			   $1.set[i].v.sval);
    382 		    cur_backend.addserverheader =
    383 			xrealloc (cur_backend.addserverheader,
    384 				  (cur_backend.naddserverheader + 1) *
    385 				  sizeof(char*));
    386 		    cur_backend.addserverheader
    387 			[cur_backend.naddserverheader++] =
    388 			    $1.set[i].v.sval;
    389 		    break;
    390 		case cf_setserverheaderspec:
    391 		    psmsg ("server header to set:",
    392 			   $1.set[i].v.sval);
    393 		    cur_backend.setserverheader =
    394 			xrealloc (cur_backend.setserverheader,
    395 				  (cur_backend.nsetserverheader + 1) *
    396 				  sizeof(char*));
    397 		    cur_backend.setserverheader
    398 			[cur_backend.nsetserverheader++] =
    399 			    $1.set[i].v.sval;
    400 		    break;
    401 		case cf_appendserverheaderspec:
    402 		    psmsg ("server header to append:",
    403 			   $1.set[i].v.sval);
    404 		    cur_backend.appendserverheader =
    405 			xrealloc (cur_backend.appendserverheader,
    406 				  (cur_backend.nappendserverheader + 1) *
    407 				  sizeof(char*));
    408 		    cur_backend.appendserverheader
    409 			[cur_backend.nappendserverheader++] =
    410 			    $1.set[i].v.sval;
    411 		    break;
    412 		default:
    413 		    error ("Internal jam, unhandled type %d "
    414 			   "in backend specification",
    415 			   $1.set[i].cf);
    416 		}
    417 	    free ($1.set);
    418 
    419 	    /* Verify the backend block, supply defaults,
    420 	     * And so on.
    421 	     */
    422 	    if (!cur_service.port)
    423 		error ("Back end %s lacks port",
    424 		       cur_service.port);
    425 	    if (!cur_backend.weight)
    426 		cur_backend.weight = 1;
    427 
    428 	    /* Add to the list. */
    429 	    cur_service.backend = xrealloc (cur_service.backend,
    430 					    ++cur_service.nbackend *
    431 					    sizeof(Backend));
    432 	    cur_service.backend[cur_service.nbackend - 1] =
    433 		cur_backend;
    434 	    pimsg ("this was backend defintion", cur_service.nbackend);
    435 	    memset (&cur_backend, 0, sizeof(cur_backend));
    436 	}
    437 ;
    438 
    439 portstatement:
    440 	PORT
    441 	number
    442 	semicol {
    443 	    pimsg ("port statement:", lastnr);
    444 	    $$.n = 1;
    445 	    $$.set = xmalloc (sizeof(Confset));
    446 	    $$.set[0].cf = cf_portspec;
    447 	    $$.set[0].v.ival = lastnr;
    448 	}
    449 ;
    450 
    451 bindstatement:
    452 	BINDTO
    453 	ipaddress
    454 	semicol {
    455 	    psmsg ("bindto statement:", laststr);
    456 	    $$.n = 1;
    457 	    $$.set = xmalloc (sizeof(Confset));
    458 	    $$.set[0].cf = cf_bindspec;
    459 	    $$.set[0].v.sval = xstrdup(laststr);
    460 	}
    461 ;
    462 
    463 ipaddress:
    464 	ipaddress_expected
    465 	STRING {
    466 	    setlaststr (laststring);
    467 	    free (laststring);
    468 	    laststring = 0;
    469 	}
    470 ;
    471 
    472 number:
    473 	number_expected
    474 	NUMBER {
    475 	    setlastnr (yytext);
    476 	}
    477 ;
    478 
    479 semicol:
    480 	semicol_expected
    481 	';'
    482 ;
    483 
    484 verbositystatement:
    485 	VERBOSITY
    486 	onoff_expected
    487 	onoff
    488 	semicol {
    489 	    pimsg ("verbosity statement:", lastnr);
    490 	    $$.n = 1;
    491 	    $$.set = xmalloc (sizeof(Confset));
    492 	    $$.set[0].cf = cf_verbosityspec;
    493 	    $$.set[0].v.ival = lastnr;
    494 	}
    495 ;
    496 
    497 onoff:
    498 	ON {
    499 	    lastnr = 1;
    500 	}
    501 |
    502 	OFF {
    503 	    lastnr = 0;
    504 	}
    505 ;
    506 
    507 dispatchmodestatement:
    508 	DISPATCHMODE
    509 	dispatchmethod
    510 	dispatchtail
    511 	semicol {
    512 	    $$ = $2;
    513 	}
    514 ;
    515 
    516 dispatchtail:
    517 	dispatchover
    518 	|
    519 	dispatchext
    520 	|
    521 	/* empty */
    522 ;
    523 
    524 dispatchover:
    525 	OVER
    526 	overnumber {
    527 	    pimsg ("dispatch mode statement:", lastnr);
    528 	    $$.n = 1;
    529 	    $$.set = xmalloc (sizeof(Confset));
    530 	    $$.set[0].cf = cf_dispatchspec;
    531 	    $$.set[0].v.ival = lastnr;
    532 
    533 	    if (lastovernr &&
    534 		(lastnr != ds_bysize && lastnr != ds_byduration))
    535 		error ("Service '%s': this dispatch mode "
    536 		       "doesn't support 'over <connections>'",
    537 		       cur_service.name);
    538 	}
    539 ;
    540 
    541 overnumber:
    542 	number_expected
    543 	NUMBER {
    544 	    setlastovernr (yytext);
    545 	}
    546 ;
    547 
    548 dispatchext:
    549 	commandline {
    550 	    psmsg ("external handler:", laststr);
    551 	    if (lastnr != ds_externalhandler)
    552 		error ("Service %s: this dispatch mode doesn't support "
    553 		       "an external handler", cur_service.name);
    554 	    setlastext (laststr);
    555 	}
    556 ;
    557 
    558 dispatchmethod:
    559 	dispatchmethod_expected
    560 	dispatchmethodspec {
    561 	    $$.n = 1;
    562 	    $$.set = xmalloc (sizeof(Confset));
    563 	    $$.set[0].v.ival = lastnr;
    564 	}
    565 ;
    566 
    567 dispatchmethodspec:
    568 	ROUNDROBIN {
    569 	    lastnr = ds_roundrobin;
    570 	}
    571 |
    572 	RANDOM {
    573 	    lastnr = ds_random;
    574 	}
    575 |
    576 	BYDURATION {
    577 	    lastnr = ds_byduration;
    578 	}
    579 |
    580 	BYSIZE {
    581 	    lastnr = ds_bysize;
    582 	}
    583 |
    584 	BYORDER {
    585 	    lastnr = ds_byorder;
    586 	}
    587 |
    588 	BYCONNECTIONS {
    589 	    lastnr = ds_byconnections;
    590 	}
    591 |
    592 	EXTERNALHANDLER {
    593 	    lastnr = ds_externalhandler;
    594 	}
    595 ;
    596 
    597 useraccountstatement:
    598 	USERACCOUNT
    599 	useraccount
    600 	semicol {
    601 	    pimsg ("user account statement:", laststr);
    602 	    $$.n = 1;
    603 	    $$.set = xmalloc (sizeof(Confset));
    604 	    $$.set[0].cf = cf_useraccountspec;
    605 	    $$.set[0].v.sval = xstrdup (laststr);
    606 	}
    607 ;
    608 
    609 useraccount:
    610 	useraccount_expected
    611 	STRING {
    612 	    setlaststr (laststring);
    613 	    free (laststring);
    614 	    laststring = 0;
    615 	}
    616 ;
    617 
    618 revivingintervalstatement:
    619 	REVIVINGINTERVAL
    620 	number
    621 	semicol {
    622 	    pimsg ("reviving interval statement:", lastnr);
    623 	    $$.n = 1;
    624 	    $$.set = xmalloc (sizeof(Confset));
    625 	    $$.set[0].cf = cf_revivespec;
    626 	    $$.set[0].v.ival = lastnr;
    627 	}
    628 ;
    629 
    630 backlogstatement:
    631 	BACKLOG
    632 	number
    633 	semicol {
    634 	    pimsg ("backlog statement:", lastnr);
    635 	    $$.n = 1;
    636 	    $$.set = xmalloc (sizeof(Confset));
    637 	    $$.set[0].cf = cf_revivespec;
    638 	    $$.set[0].v.ival = lastnr;
    639 	}
    640 ;
    641 
    642 shmkeystatement:
    643 	SHMKEY
    644 	number
    645 	semicol {
    646 	    pimsg ("shmkey statement:", lastnr);
    647 	    $$.n = 1;
    648 	    $$.set = xmalloc (sizeof(Confset));
    649 	    $$.set[0].cf = cf_shmkeyspec;
    650 	    $$.set[0].v.ival = lastnr;
    651 	}
    652 ;
    653 
    654 connectiontimeoutstatement:
    655 	CONNECTIONTIMEOUT
    656 	number
    657 	semicol {
    658 	    pimsg ("connection timeout statement:", lastnr);
    659 	    $$.n = 1;
    660 	    $$.set = xmalloc (sizeof(Confset));
    661 	    $$.set[0].cf = cf_connectiontimeoutspec;
    662 	    $$.set[0].v.ival = lastnr;
    663 	}
    664 ;
    665 
    666 maxconnectionsstatement:
    667 	MAXCONNECTIONS
    668 	number
    669 	semicol {
    670 	    pimsg ("max clients statement (service):", lastnr);
    671 	    $$.n = 1;
    672 	    $$.set = xmalloc (sizeof(Confset));
    673 	    $$.set[0].cf = cf_maxconnectionsspec;
    674 	    $$.set[0].v.ival = lastnr;
    675 	}
    676 ;
    677 
    678 typestatement:
    679 	TYPE
    680 	typespec
    681 	semicol {
    682 	    pimsg ("service type:", lastnr);
    683 	    $$.n = 1;
    684 	    $$.set = xmalloc (sizeof(Confset));
    685 	    $$.set[0].cf = cf_typespec;
    686 	    $$.set[0].v.ival = lastnr;
    687 	}
    688 ;
    689 
    690 typespec:
    691 	type_expected
    692 	typespecifier
    693 	;
    694 
    695 typespecifier:
    696 	ANY {
    697 	    lastnr = type_any;
    698 	}
    699 |
    700 	HTTP {
    701 	    lastnr = type_http;
    702 	}
    703 ;
    704 
    705 allowfromstatement:
    706 	ALLOWFROM
    707 	ipfilters
    708 	semicol {
    709 	    psmsg ("allow from: ", laststr);
    710 	    $$.n = 1;
    711 	    $$.set = xmalloc (sizeof(Confset));
    712 	    $$.set[0].cf = cf_allowfromspec;
    713 	    $$.set[0].v.sval = xstrdup(laststr);
    714 	}
    715 ;
    716 
    717 denyfromstatement:
    718 	DENYFROM
    719 	ipfilters
    720 	semicol {
    721 	    psmsg ("allow from: ", laststr);
    722 	    $$.n = 1;
    723 	    $$.set = xmalloc (sizeof(Confset));
    724 	    $$.set[0].cf = cf_denyfromspec;
    725 	    $$.set[0].v.sval = xstrdup(laststr);
    726 	}
    727 ;
    728 
    729 allowfilestatement:
    730 	ALLOWFILE
    731 	filename
    732 	semicol {
    733 	    psmsg ("allow file: ", laststr);
    734 	    $$.n = 1;
    735 	    $$.set = xmalloc (sizeof(Confset));
    736 	    $$.set[0].cf = cf_allowfilespec;
    737 	    $$.set[0].v.sval = xstrdup(laststr);
    738 	}
    739 ;
    740 
    741 denyfilestatement:
    742 	DENYFILE
    743 	filename
    744 	semicol {
    745 	    psmsg ("allow file: ", laststr);
    746 	    $$.n = 1;
    747 	    $$.set = xmalloc (sizeof(Confset));
    748 	    $$.set[0].cf = cf_allowfilespec;
    749 	    $$.set[0].v.sval = xstrdup(laststr);
    750 	}
    751 ;
    752 
    753 ipfilters:
    754 	ipfilters_expected
    755 	STRING {
    756 	    setlaststr (laststring);
    757 	    free (laststring);
    758 	    laststring = 0;
    759 	}
    760 ;
    761 
    762 backendblock:
    763 	BACKEND
    764 	backendname
    765 	'{'
    766 	backenddefinitions
    767 	'}' {
    768 	    $$ = $4;
    769 	}
    770 ;
    771 
    772 backendname:
    773 	backendname_expected
    774 	IDENTIFIER {
    775 	    psmsg ("backend name:", yytext);
    776 	    cur_backend.name = xstrdup (yytext);
    777 	}
    778 ;
    779 
    780 backenddefinitions:
    781 	backenddefinitions
    782 	backenddefinition {
    783 	    $1.n++;
    784 	    $1.set = xrealloc ($1.set, $1.n * sizeof(Confset));
    785 	    $1.set[$1.n - 1] = $2.set[0];
    786 	    $$ = $1;
    787 	}
    788 |
    789 	backenddefinition {
    790 	    $$ = $1;
    791 	}
    792 ;
    793 
    794 backenddefinition:
    795 	backendstatement_expected
    796 	backendstatement {
    797 	    $$ = $2;
    798 	}
    799 ;
    800 
    801 backendstatement:
    802 	serverstatement {
    803 	    psmsg ("backend server:", $1.set[0].v.sval);
    804 	    $$ = $1;
    805 	}
    806 |
    807 	portstatement {
    808 	    pimsg ("backend port:", $1.set[0].v.ival);
    809 	    $$ = $1;
    810 	}
    811 |
    812 	verbositystatement {
    813 	    pimsg ("backend verbosity:", $1.set[0].v.ival);
    814 	    $$ = $1;
    815 	}
    816 |
    817 	onstartstatement {
    818 	    psmsg ("backend onstart:", $1.set[0].v.sval);
    819 	    $$ = $1;
    820 	}
    821 |
    822 	onendstatement {
    823 	    psmsg ("backend onend:", $1.set[0].v.sval);
    824 	    $$ = $1;
    825 	}
    826 |
    827 	onfailstatement {
    828 	    psmsg ("backend onfail:", $1.set[0].v.sval);
    829 	    $$ = $1;
    830 	}
    831 |
    832 	dumptrafficstatement {
    833 	    psmsg ("backend trafficlog:", $1.set[0].v.sval);
    834 	    $$ = $1;
    835 	}
    836 |
    837 	throughputstatement {
    838 	    psmsg ("backend trafficlog:", $1.set[0].v.sval);
    839 	    $$ = $1;
    840 	}
    841 |
    842 	weightstatement {
    843 	    pimsg ("backend weight:", $1.set[0].v.ival);
    844 	    $$ = $1;
    845 	}
    846 |
    847 	decaystatement {
    848 	    pimsg ("backend decay:", $1.set[0].v.ival);
    849 	    $$ = $1;
    850 	}
    851 |
    852 	maxconnectionsstatement {
    853 	    pimsg ("backend maxconnections:", $1.set[0].v.ival);
    854 	    $$ = $1;
    855 	}
    856 |
    857 	stickycookiestatement {
    858 	    psmsg ("backend sticky cookie:", $1.set[0].v.sval);
    859 	    $$ = $1;
    860 	}
    861 |
    862 	addclientheaderstatement {
    863 	    psmsg ("addclientheader:", $1.set[0].v.sval);
    864 	    $$ = $1;
    865 	}
    866 |
    867 	setclientheaderstatement {
    868 	    psmsg ("setclientheader:", $1.set[0].v.sval);
    869 	    $$ = $1;
    870 	}
    871 |
    872 	appendclientheaderstatement {
    873 	    psmsg ("appendclientheader:", $1.set[0].v.sval);
    874 	    $$ = $1;
    875 	}
    876 |
    877 	addserverheaderstatement {
    878 	    psmsg ("addserverheader:", $1.set[0].v.sval);
    879 	    $$ = $1;
    880 	}
    881 |
    882 	setserverheaderstatement {
    883 	    psmsg ("setserverheader:", $1.set[0].v.sval);
    884 	    $$ = $1;
    885 	}
    886 |
    887 	appendserverheaderstatement {
    888 	    psmsg ("appendserverheader:", $1.set[0].v.sval);
    889 	    $$ = $1;
    890 	}
    891 ;
    892 
    893 serverstatement:
    894 	SERVER
    895 	serveraddress_expected
    896 	serveraddress
    897 	semicol {
    898 	    psmsg ("server statement:", laststr);
    899 	    $$.n = 1;
    900 	    $$.set = xmalloc (sizeof (Confset));
    901 	    $$.set[0].cf = cf_serverspec;
    902 	    $$.set[0].v.sval = xstrdup (laststr);
    903 	}
    904 ;
    905 
    906 weightstatement:
    907 	WEIGHT
    908 	number
    909 	semicol {
    910 	    pimsg ("weight statement", lastnr);
    911 	    $$.n = 1;
    912 	    $$.set = xmalloc (sizeof (Confset));
    913 	    $$.set[0].cf = cf_weightspec;
    914 	    $$.set[0].v.ival = lastnr;
    915 	}
    916 ;
    917 
    918 decaystatement:
    919 	DECAY
    920 	number
    921 	semicol {
    922 	    pimsg ("decay statement", lastnr);
    923 	    $$.n = 1;
    924 	    $$.set = xmalloc (sizeof (Confset));
    925 	    $$.set[0].cf = cf_decayspec;
    926 	    $$.set[0].v.ival = lastnr;
    927 	}
    928 ;
    929 
    930 serveraddress:
    931 	STRING {
    932 	    setlaststr (laststring);
    933 	}
    934 ;
    935 
    936 onstartstatement:
    937 	ONSTART
    938 	commandline
    939 	semicol {
    940 	    psmsg ("onstart statement:", laststr);
    941 	    $$.n = 1;
    942 	    $$.set = xmalloc (sizeof (Confset));
    943 	    $$.set[0].cf = cf_onstartspec;
    944 	    $$.set[0].v.sval = xstrdup (laststr);
    945 	}
    946 ;
    947 
    948 onfailstatement:
    949 	ONFAIL
    950 	commandline
    951 	semicol {
    952 	    psmsg ("onfail statement:", laststr);
    953 	    $$.n = 1;
    954 	    $$.set = xmalloc (sizeof (Confset));
    955 	    $$.set[0].cf = cf_onfailspec;
    956 	    $$.set[0].v.sval = xstrdup (laststr);
    957 	}
    958 ;
    959 
    960 onendstatement:
    961 	ONEND
    962 	commandline
    963 	semicol {
    964 	    psmsg ("onend statement:", laststr);
    965 	    $$.n = 1;
    966 	    $$.set = xmalloc (sizeof (Confset));
    967 	    $$.set[0].cf = cf_onendspec;
    968 	    $$.set[0].v.sval = xstrdup (laststr);
    969 	}
    970 ;
    971 
    972 dumptrafficstatement:
    973 	TRAFFICLOG
    974 	filename
    975 	semicol {
    976 	    psmsg ("trafficlog statement:", laststr);
    977 	    $$.n = 1;
    978 	    $$.set = xmalloc (sizeof (Confset));
    979 	    $$.set[0].cf = cf_dumpspec;
    980 	    $$.set[0].v.sval = xstrdup (laststr);
    981 	}
    982 ;
    983 
    984 throughputstatement:
    985 	THROUGHPUTLOG
    986 	filename
    987 	semicol {
    988 	    psmsg ("throughputlog statement:", laststr);
    989 	    $$.n = 1;
    990 	    $$.set = xmalloc (sizeof (Confset));
    991 	    $$.set[0].cf = cf_thruspec;
    992 	    $$.set[0].v.sval = xstrdup (laststr);
    993 	}
    994 ;
    995 
    996 commandline:
    997 	commandline_expected
    998 	STRING {
    999 	    setlaststr (laststring);
   1000 	    free (laststring);
   1001 	    laststring = 0;
   1002 	}
   1003 ;
   1004 
   1005 filename:
   1006 	filename_expected
   1007 	STRING {
   1008 	    setlaststr (laststring);
   1009 	    free (laststring);
   1010 	    laststring = 0;
   1011 	}
   1012 ;
   1013 
   1014 stickycookiestatement:
   1015 	STICKYCOOKIE
   1016 	cookiespecifier
   1017 	semicol {
   1018 	    psmsg ("insertcookie statement:", laststr);
   1019 	    $$.n = 1;
   1020 	    $$.set = xmalloc (sizeof (Confset));
   1021 	    $$.set[0].cf = cf_stickycookiespec;
   1022 	    $$.set[0].v.sval = xstrdup (laststr);
   1023 	}
   1024 ;
   1025 
   1026 cookiespecifier:
   1027 	cookie_expected
   1028 	STRING {
   1029 		setlaststr (laststring);
   1030 		free (laststring);
   1031 		laststring = 0;
   1032 	}
   1033 ;
   1034 
   1035 addclientheaderstatement:
   1036 	ADDCLIENTHEADER
   1037 	headerstring
   1038 	semicol {
   1039 	    psmsg ("addclientheader statement:", laststr);
   1040 	    $$.n = 1;
   1041 	    $$.set = xmalloc (sizeof(Confset));
   1042 	    $$.set[0].cf = cf_addclientheaderspec;
   1043 	    $$.set[0].v.sval = xstrdup (laststr);
   1044 	}
   1045 ;
   1046 
   1047 setclientheaderstatement:
   1048 	SETCLIENTHEADER
   1049 	headerstring
   1050 	semicol {
   1051 	    psmsg ("setclientheader statement:", laststr);
   1052 	    $$.n = 1;
   1053 	    $$.set = xmalloc (sizeof(Confset));
   1054 	    $$.set[0].cf = cf_setclientheaderspec;
   1055 	    $$.set[0].v.sval = xstrdup (laststr);
   1056 	}
   1057 ;
   1058 
   1059 appendclientheaderstatement:
   1060 	APPENDCLIENTHEADER
   1061 	headerstring
   1062 	semicol {
   1063 	    psmsg ("appendclientheader statement:", laststr);
   1064 	    $$.n = 1;
   1065 	    $$.set = xmalloc (sizeof(Confset));
   1066 	    $$.set[0].cf = cf_appendclientheaderspec;
   1067 	    $$.set[0].v.sval = xstrdup (laststr);
   1068 	}
   1069 ;
   1070 
   1071 addserverheaderstatement:
   1072 	ADDSERVERHEADER
   1073 	headerstring
   1074 	semicol {
   1075 	    psmsg ("addserverheader statement:", laststr);
   1076 	    $$.n = 1;
   1077 	    $$.set = xmalloc (sizeof(Confset));
   1078 	    $$.set[0].cf = cf_addserverheaderspec;
   1079 	    $$.set[0].v.sval = xstrdup (laststr);
   1080 	}
   1081 ;
   1082 
   1083 setserverheaderstatement:
   1084 	SETSERVERHEADER
   1085 	headerstring
   1086 	semicol {
   1087 	    psmsg ("setserverheader statement:", laststr);
   1088 	    $$.n = 1;
   1089 	    $$.set = xmalloc (sizeof(Confset));
   1090 	    $$.set[0].cf = cf_setserverheaderspec;
   1091 	    $$.set[0].v.sval = xstrdup (laststr);
   1092 	}
   1093 ;
   1094 
   1095 appendserverheaderstatement:
   1096 	APPENDSERVERHEADER
   1097 	headerstring
   1098 	semicol {
   1099 	    psmsg ("appendserverheader statement:", laststr);
   1100 	    $$.n = 1;
   1101 	    $$.set = xmalloc (sizeof(Confset));
   1102 	    $$.set[0].cf = cf_appendserverheaderspec;
   1103 	    $$.set[0].v.sval = xstrdup (laststr);
   1104 	}
   1105 ;
   1106 
   1107 headerstring:
   1108 	headerstring_expected
   1109 	STRING {
   1110 	    setlaststr (laststring);
   1111 	    free (laststring);
   1112 	    laststring = 0;
   1113 	}
   1114 ;
   1115 
   1116 headerstring_expected: {
   1117     yyerrmsg = "HTTP header specifier expected";
   1118 }
   1119 ;
   1120 
   1121 cookie_expected: {
   1122     yyerrmsg = "cookie specifier expected";
   1123 }
   1124 ;
   1125 
   1126 number_expected: {
   1127     yyerrmsg = "number expected";
   1128 }
   1129 ;
   1130 
   1131 serveraddress_expected: {
   1132     yyerrmsg = "hostname or IP address expected";
   1133 }
   1134 ;
   1135 
   1136 service_expected: {
   1137     yyerrmsg = "'service' expected";
   1138 }
   1139 ;
   1140 
   1141 backendstatement_expected: {
   1142     yyerrmsg = "backend definition statement expected";
   1143 }
   1144 ;
   1145 
   1146 servicebody_expected: {
   1147     yyerrmsg = "service body statement expected";
   1148 }
   1149 ;
   1150 
   1151 semicol_expected: {
   1152     yyerrmsg = "semicolon (;) expected";
   1153 }
   1154 ;
   1155 
   1156 onoff_expected: {
   1157     yyerrmsg = "'on' or 'off' expetcted";
   1158 }
   1159 ;
   1160 
   1161 dispatchmethod_expected: {
   1162     yyerrmsg = "dispatch method expected";
   1163 }
   1164 ;
   1165 
   1166 commandline_expected: {
   1167     yyerrmsg = "command line expected";
   1168 }
   1169 ;
   1170 
   1171 filename_expected: {
   1172     yyerrmsg = "file name expected";
   1173 }
   1174 ;
   1175 
   1176 servicename_expected: {
   1177     yyerrmsg = "service name (identifier) expected";
   1178 }
   1179 ;
   1180 
   1181 backendname_expected: {
   1182     yyerrmsg = "backend name (identifier) expected";
   1183 }
   1184 ;
   1185 
   1186 ipaddress_expected: {
   1187     yyerrmsg = "IP address or 'any' expected";
   1188 }
   1189 ;
   1190 
   1191 type_expected: {
   1192     yyerrmsg = "Service type expected ('any', 'stickyhttp', ...)";
   1193 }
   1194 ;
   1195 
   1196 ipfilters_expected: {
   1197     yyerrmsg = "IP filter(s) expected";
   1198 }
   1199 ;
   1200 
   1201 useraccount_expected: {
   1202     yyerrmsg = "username expected";
   1203 }
   1204 ;