%{
/* cfg.y - configuration language */

/* Written 1995-1997 by Werner Almesberger, EPFL-LRC */


#include <string.h>
#include <ctype.h>
#include <linux/atm.h>

#include "atm.h"
#include "atmd.h"

#include "proto.h"
#include "io.h"
#include "trace.h"
#include "policy.h"


extern int net;

static RULE *rule;


static int hex2num(char digit)
{
    if (isdigit(digit)) return digit-'0';
    if (islower(digit)) return toupper(digit)-'A'+10;
    return digit-'A'+10;
}


static void put_address(char *address)
{
    char *mask;

    mask = strchr(address,'/');
    if (mask) *mask++ = 0;
    if (text2atm(address,(struct sockaddr *) &rule->addr,sizeof(rule->addr),
      T2A_SVC | T2A_WILDCARD | T2A_NAME | T2A_LOCAL) < 0) {
	yyerror("invalid address");
	return;
    }
    if (!mask) rule->mask = -1;
    else rule->mask = strtol(mask,NULL,10);
    add_rule(rule);
}

%}

%union {
    int num;
    char *str;
    struct sockaddr_atmpvc pvc;
};


%token		TOK_LEVEL TOK_DEBUG TOK_INFO TOK_WARN TOK_ERROR TOK_FATAL
%token		TOK_SIG TOK_UNI30 TOK_UNI31 TOK_UNI40 TOK_Q2963_1 TOK_SAAL
%token		TOK_VC TOK_IO TOK_NET TOK_VPCI TOK_ITF TOK_PCR TOK_TRACE
%token		TOK_POLICY TOK_ALLOW TOK_REJECT
%token <num>	TOK_NUMBER
%token <str>	TOK_DUMP_DIR TOK_LOGFILE TOK_QOS TOK_FROM TOK_TO
%token <pvc>	TOK_PVC

%type <num>	level opt_trace_size action

%%

all:
    | item all
    ;

item:
    TOK_LEVEL level
	{
	    set_verbosity(NULL,$2);
	}
    | TOK_SIG sig
    | TOK_SAAL saal
    | TOK_IO io
    | TOK_DEBUG debug
    | TOK_POLICY policy
    ;

sig:
    sig_item
    | '{' sig_items '}'
    ;

sig_items:
    | sig_item sig_items
    ;

saal:
    saal_item
    | '{' saal_items '}'
    ;

saal_items:
    | saal_item saal_items
    ;

io:
    io_item
    | '{' io_items '}'
    ;

io_items:
    | io_item io_items
    ;

debug:
    debug_item
    | '{' debug_items '}'
    ;

debug_items:
    | debug_item debug_items
    ;

policy:
    policy_item
    | '{' policy_items '}'
    ;

policy_items:
    | policy_item policy_items
    ;

sig_item:
    TOK_LEVEL level
	{
	    set_verbosity("Q2931",$2);
	    set_verbosity("KERNEL",$2);
	    set_verbosity("SAP",$2);
	}
    | TOK_VPCI TOK_NUMBER TOK_ITF TOK_NUMBER
	{
	    enter_vpci($2,$4);
	}
    | TOK_UNI30
	{
#ifndef UNI30
	    yyerror("Sorry, not supported yet");
#endif
	}
    | TOK_UNI31
	{
#ifndef UNI31
	    yyerror("Sorry, not supported yet");
#endif
	}
    | TOK_UNI40
	{
#ifndef UNI40
	    yyerror("Sorry, not supported yet");
#endif
	}
    | TOK_Q2963_1
	{
#ifndef Q2963_1
	    yyerror("Sorry, not supported yet");
#endif
	}
    | TOK_NET
	{
	    net = 1;
	}
    ;

saal_item:
    TOK_LEVEL level
	{
	    set_verbosity("SSCF",$2);
	    set_verbosity("SSCOP",$2);
	}
    ;

io_item:
    TOK_LEVEL level
	{
	    set_verbosity("IO",$2);
	}
    | TOK_VC TOK_PVC
	{
	    signaling_pvc = $2;
	}
    | TOK_PCR TOK_NUMBER
	{
	    sig_pcr = $2;
	}
    | TOK_QOS
	{
	    sig_qos = $1;
	}
    ;

debug_item:
    TOK_LEVEL level
	{
	    set_verbosity(NULL,$2);
	}
    | TOK_DUMP_DIR
	{
	    dump_dir = $1;
	    if (!trace_size) trace_size = DEFAULT_TRACE_SIZE;
	}
    | TOK_LOGFILE
	{
	    set_logfile($1);
	}
    | TOK_TRACE opt_trace_size
	{
	    trace_size = $2;
	}
    ;

opt_trace_size:
 	{
	    $$ = DEFAULT_TRACE_SIZE;
	}
    | TOK_NUMBER
	{
	    $$ = $1;
	}
    ;

level:
    TOK_DEBUG
	{
	    $$ = DIAG_DEBUG;
	}
    | TOK_INFO
	{
	    $$ = DIAG_INFO;
	}
    | TOK_WARN
	{
	    $$ = DIAG_WARN;
	}
    | TOK_ERROR
	{
	    $$ = DIAG_ERROR;
	}
    | TOK_FATAL
	{
	    $$ = DIAG_FATAL;
	}
    ;

policy_item:
    TOK_LEVEL level
	{
	    set_verbosity("POLICY",$2);
	}
    | action
	{
	    rule = alloc_t(RULE);
	    rule->type = $1;
	}
      direction
    ;

action:
    TOK_ALLOW
	{
	    $$ = ACL_ALLOW;
	}
    | TOK_REJECT
	{
	    $$ = ACL_REJECT;
	}
    ;

direction:
    TOK_FROM
	{
	    rule->type |= ACL_IN;
	    put_address($1);
	}
    | TOK_TO
	{
	    rule->type |= ACL_OUT;
	    put_address($1);
	}
    ;
