File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / bird / filter / config.Y
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Aug 22 12:33:54 2017 UTC (6 years, 10 months ago) by misho
Branches: bird, MAIN
CVS tags: v1_6_3p0, v1_6_3, HEAD
bird 1.6.3

    1: /*
    2:  *	BIRD - filters
    3:  *
    4:  *	Copyright 1998--2000 Pavel Machek
    5:  *
    6:  *	Can be freely distributed and used under the terms of the GNU GPL.
    7:  *
    8: 	FIXME: priority of ! should be lower
    9:  */
   10: 
   11: CF_HDR
   12: 
   13: CF_DEFINES
   14: 
   15: #define P(a,b) ((a << 8) | b)
   16: 
   17: static inline u32 pair(u32 a, u32 b) { return (a << 16) | b; }
   18: static inline u32 pair_a(u32 p) { return p >> 16; }
   19: static inline u32 pair_b(u32 p) { return p & 0xFFFF; }
   20: 
   21: 
   22: /*
   23:  * Sets and their items are during parsing handled as lists, linked
   24:  * through left ptr. The first item in a list also contains a pointer
   25:  * to the last item in a list (right ptr). For convenience, even items
   26:  * are handled as one-item lists. Lists are merged by f_merge_items().
   27:  */
   28: static int
   29: f_valid_set_type(int type)
   30: {
   31:   switch (type)
   32:   {
   33:   case T_INT:
   34:   case T_PAIR:
   35:   case T_QUAD:
   36:   case T_ENUM:
   37:   case T_IP:
   38:   case T_EC:
   39:   case T_LC:
   40:     return 1;
   41: 
   42:   default:
   43:     return 0;
   44:   }
   45: }
   46: 
   47: static inline struct f_tree *
   48: f_new_item(struct f_val from, struct f_val to)
   49: {
   50:   struct f_tree *t = f_new_tree();
   51:   t->right = t;
   52:   t->from = from;
   53:   t->to = to;
   54:   return t;
   55: }
   56: 
   57: static inline struct f_tree *
   58: f_merge_items(struct f_tree *a, struct f_tree *b)
   59: {
   60:   if (!a) return b;
   61:   a->right->left = b;
   62:   a->right = b->right;
   63:   b->right = NULL;
   64:   return a;
   65: }
   66: 
   67: static inline struct f_tree *
   68: f_new_pair_item(int fa, int ta, int fb, int tb)
   69: {
   70:   check_u16(fa);
   71:   check_u16(ta);
   72:   check_u16(fb);
   73:   check_u16(tb);
   74: 
   75:   if ((ta < fa) || (tb < fb))
   76:     cf_error( "From value cannot be higher that To value in pair sets");
   77: 
   78:   struct f_tree *t = f_new_tree();
   79:   t->right = t;
   80:   t->from.type = t->to.type = T_PAIR;
   81:   t->from.val.i = pair(fa, fb);
   82:   t->to.val.i = pair(ta, tb);
   83:   return t;
   84: }
   85: 
   86: static inline struct f_tree *
   87: f_new_pair_set(int fa, int ta, int fb, int tb)
   88: {
   89:   check_u16(fa);
   90:   check_u16(ta);
   91:   check_u16(fb);
   92:   check_u16(tb);
   93: 
   94:   if ((ta < fa) || (tb < fb))
   95:     cf_error( "From value cannot be higher that To value in pair sets");
   96: 
   97:   struct f_tree *lst = NULL;
   98:   int i;
   99: 
  100:   for (i = fa; i <= ta; i++)
  101:     lst = f_merge_items(lst, f_new_pair_item(i, i, fb, tb));
  102: 
  103:   return lst;
  104: }
  105: 
  106: #define CC_ALL 0xFFFF
  107: #define EC_ALL 0xFFFFFFFF
  108: #define LC_ALL 0xFFFFFFFF
  109: 
  110: static struct f_tree *
  111: f_new_ec_item(u32 kind, u32 ipv4_used, u32 key, u32 vf, u32 vt)
  112: {
  113:   u64 fm, to;
  114: 
  115:   if (ipv4_used || (key >= 0x10000)) {
  116:     check_u16(vf);
  117:     if (vt == EC_ALL)
  118:       vt = 0xFFFF;
  119:     else
  120:       check_u16(vt);
  121:   }
  122: 
  123:   if (kind == EC_GENERIC) {
  124:     fm = ec_generic(key, vf);
  125:     to = ec_generic(key, vt);
  126:   }
  127:   else if (ipv4_used) {
  128:     fm = ec_ip4(kind, key, vf);
  129:     to = ec_ip4(kind, key, vt);
  130:   }
  131:   else if (key < 0x10000) {
  132:     fm = ec_as2(kind, key, vf);
  133:     to = ec_as2(kind, key, vt);
  134:   }
  135:   else {
  136:     fm = ec_as4(kind, key, vf);
  137:     to = ec_as4(kind, key, vt);
  138:   }
  139: 
  140:   struct f_tree *t = f_new_tree();
  141:   t->right = t;
  142:   t->from.type = t->to.type = T_EC;
  143:   t->from.val.ec = fm;
  144:   t->to.val.ec = to;
  145:   return t;
  146: }
  147: 
  148: static struct f_tree *
  149: f_new_lc_item(u32 f1, u32 t1, u32 f2, u32 t2, u32 f3, u32 t3)
  150: {
  151:   struct f_tree *t = f_new_tree();
  152:   t->right = t;
  153:   t->from.type = t->to.type = T_LC;
  154:   t->from.val.lc = (lcomm) {f1, f2, f3};
  155:   t->to.val.lc = (lcomm) {t1, t2, t3};
  156:   return t;
  157: }
  158: 
  159: static inline struct f_inst *
  160: f_generate_empty(struct f_inst *dyn)
  161: {
  162:   struct f_inst *e = f_new_inst();
  163:   e->code = 'E';
  164: 
  165:   switch (dyn->aux & EAF_TYPE_MASK) {
  166:     case EAF_TYPE_AS_PATH:
  167:       e->aux = T_PATH;
  168:       break;
  169:     case EAF_TYPE_INT_SET:
  170:       e->aux = T_CLIST;
  171:       break;
  172:     case EAF_TYPE_EC_SET:
  173:       e->aux = T_ECLIST;
  174:       break;
  175:     case EAF_TYPE_LC_SET:
  176:       e->aux = T_LCLIST;
  177:       break;
  178:     default:
  179:       cf_error("Can't empty that attribute");
  180:   }
  181: 
  182:   dyn->code = P('e','S');
  183:   dyn->a1.p = e;
  184:   return dyn;
  185: }
  186: 
  187: 
  188: static inline struct f_inst *
  189: f_generate_dpair(struct f_inst *t1, struct f_inst *t2)
  190: {
  191:   struct f_inst *rv;
  192: 
  193:   if ((t1->code == 'c') && (t2->code == 'c')) {
  194:     if ((t1->aux != T_INT) || (t2->aux != T_INT))
  195:       cf_error( "Can't operate with value of non-integer type in pair constructor");
  196: 
  197:     check_u16(t1->a2.i);
  198:     check_u16(t2->a2.i);
  199: 
  200:     rv = f_new_inst();
  201:     rv->code = 'c';
  202:     rv->aux = T_PAIR;
  203:     rv->a2.i = pair(t1->a2.i, t2->a2.i);
  204:   }
  205:   else {
  206:     rv = f_new_inst();
  207:     rv->code = P('m', 'p');
  208:     rv->a1.p = t1;
  209:     rv->a2.p = t2;
  210:   }
  211: 
  212:   return rv;
  213: }
  214: 
  215: static inline struct f_inst *
  216: f_generate_ec(u16 kind, struct f_inst *tk, struct f_inst *tv)
  217: {
  218:   struct f_inst *rv;
  219:   int c1 = 0, c2 = 0, ipv4_used = 0;
  220:   u32 key = 0, val2 = 0;
  221: 
  222:   if (tk->code == 'c') {
  223:     c1 = 1;
  224: 
  225:     if (tk->aux == T_INT) {
  226:       ipv4_used = 0; key = tk->a2.i;
  227:     }
  228:     else if (tk->aux == T_QUAD) {
  229:       ipv4_used = 1; key = tk->a2.i;
  230:     }
  231:     else
  232:       cf_error("Can't operate with key of non-integer/IPv4 type in EC constructor");
  233:   }
  234: 
  235: #ifndef IPV6
  236:   /* IP->Quad implicit conversion */
  237:   else if (tk->code == 'C') {
  238:     c1 = 1;
  239:     struct f_val *val = tk->a1.p;
  240: 
  241:     if (val->type == T_INT) {
  242:       ipv4_used = 0; key = val->val.i;
  243:     }
  244:     else if (val->type == T_QUAD) {
  245:       ipv4_used = 1; key = val->val.i;
  246:     }
  247:     else if (val->type == T_IP) {
  248:       ipv4_used = 1; key = ipa_to_u32(val->val.px.ip);
  249:     }
  250:     else
  251:       cf_error("Can't operate with key of non-integer/IPv4 type in EC constructor");
  252:   }
  253: #endif
  254: 
  255:   if (tv->code == 'c') {
  256:     if (tv->aux != T_INT)
  257:       cf_error("Can't operate with value of non-integer type in EC constructor");
  258:     c2 = 1;
  259:     val2 = tv->a2.i;
  260:   }
  261: 
  262:   if (c1 && c2) {
  263:     u64 ec;
  264: 
  265:     if (kind == EC_GENERIC) {
  266:       ec = ec_generic(key, val2);
  267:     }
  268:     else if (ipv4_used) {
  269:       check_u16(val2);
  270:       ec = ec_ip4(kind, key, val2);
  271:     }
  272:     else if (key < 0x10000) {
  273:       ec = ec_as2(kind, key, val2);
  274:     }
  275:     else {
  276:       check_u16(val2);
  277:       ec = ec_as4(kind, key, val2);
  278:     }
  279: 
  280:     NEW_F_VAL;
  281:     rv = f_new_inst();
  282:     rv->code = 'C';
  283:     rv->a1.p = val;
  284:     val->type = T_EC;
  285:     val->val.ec = ec;
  286:   }
  287:   else {
  288:     rv = f_new_inst();
  289:     rv->code = P('m','c');
  290:     rv->aux = kind;
  291:     rv->a1.p = tk;
  292:     rv->a2.p = tv;
  293:   }
  294: 
  295:   return rv;
  296: }
  297: 
  298: static inline struct f_inst *
  299: f_generate_lc(struct f_inst *t1, struct f_inst *t2, struct f_inst *t3)
  300: {
  301:   struct f_inst *rv;
  302: 
  303:   if ((t1->code == 'c') && (t2->code == 'c') && (t3->code == 'c')) {
  304:     if ((t1->aux != T_INT) || (t2->aux != T_INT) || (t3->aux != T_INT))
  305:       cf_error( "LC - Can't operate with value of non-integer type in tuple constructor");
  306: 
  307:     rv = f_new_inst();
  308:     rv->code = 'C';
  309: 
  310:     NEW_F_VAL;
  311:     rv->a1.p = val;
  312:     val->type = T_LC;
  313:     val->val.lc = (lcomm) { t1->a2.i, t2->a2.i, t3->a2.i };
  314:   }
  315:   else
  316:   {
  317:     rv = cfg_allocz(sizeof(struct f_inst3));
  318:     rv->lineno = ifs->lino;
  319:     rv->code = P('m','l');
  320:     rv->a1.p = t1;
  321:     rv->a2.p = t2;
  322:     INST3(rv).p = t3;
  323:   }
  324: 
  325:   return rv;
  326: }
  327: 
  328: 
  329: 
  330: CF_DECLS
  331: 
  332: CF_KEYWORDS(FUNCTION, PRINT, PRINTN, UNSET, RETURN,
  333: 	ACCEPT, REJECT, ERROR, QUITBIRD,
  334: 	INT, BOOL, IP, PREFIX, PAIR, QUAD, EC, LC,
  335: 	SET, STRING, BGPMASK, BGPPATH, CLIST, ECLIST, LCLIST,
  336: 	IF, THEN, ELSE, CASE,
  337: 	TRUE, FALSE, RT, RO, UNKNOWN, GENERIC,
  338: 	FROM, GW, NET, MASK, PROTO, SOURCE, SCOPE, CAST, DEST, IFNAME, IFINDEX,
  339: 	PREFERENCE,
  340: 	LEN,
  341: 	DEFINED,
  342: 	ADD, DELETE, CONTAINS, RESET,
  343: 	PREPEND, FIRST, LAST, LAST_NONAGGREGATED, MATCH,
  344: 	ROA_CHECK,
  345: 	EMPTY,
  346: 	FILTER, WHERE, EVAL)
  347: 
  348: %nonassoc THEN
  349: %nonassoc ELSE
  350: 
  351: %type <x> term block cmds cmds_int cmd function_body constant constructor print_one print_list var_list var_listn dynamic_attr static_attr function_call symbol bgp_path_expr
  352: %type <f> filter filter_body where_filter
  353: %type <i> type break_command ec_kind
  354: %type <i32> cnum
  355: %type <e> pair_item ec_item lc_item set_item switch_item set_items switch_items switch_body
  356: %type <trie> fprefix_set
  357: %type <v> set_atom switch_atom fprefix fprefix_s fipa
  358: %type <s> decls declsn one_decl function_params
  359: %type <h> bgp_path bgp_path_tail1 bgp_path_tail2
  360: 
  361: CF_GRAMMAR
  362: 
  363: CF_ADDTO(conf, filter_def)
  364: filter_def:
  365:    FILTER SYM { $2 = cf_define_symbol($2, SYM_FILTER, NULL); cf_push_scope( $2 ); }
  366:      filter_body {
  367:      $2->def = $4;
  368:      $4->name = $2->name;
  369:      DBG( "We have new filter defined (%s)\n", $2->name );
  370:      cf_pop_scope();
  371:    }
  372:  ;
  373: 
  374: CF_ADDTO(conf, filter_eval)
  375: filter_eval:
  376:    EVAL term { f_eval_int($2); }
  377:  ;
  378: 
  379: type:
  380:    INT { $$ = T_INT; }
  381:  | BOOL { $$ = T_BOOL; }
  382:  | IP { $$ = T_IP; }
  383:  | PREFIX { $$ = T_PREFIX; }
  384:  | PAIR { $$ = T_PAIR; }
  385:  | QUAD { $$ = T_QUAD; }
  386:  | EC { $$ = T_EC; }
  387:  | LC { $$ = T_LC; }
  388:  | STRING { $$ = T_STRING; }
  389:  | BGPMASK { $$ = T_PATH_MASK; }
  390:  | BGPPATH { $$ = T_PATH; }
  391:  | CLIST { $$ = T_CLIST; }
  392:  | ECLIST { $$ = T_ECLIST; }
  393:  | LCLIST { $$ = T_LCLIST; }
  394:  | type SET {
  395: 	switch ($1) {
  396: 	  case T_INT:
  397: 	  case T_PAIR:
  398: 	  case T_QUAD:
  399: 	  case T_EC:
  400: 	  case T_LC:
  401: 	  case T_IP:
  402: 	       $$ = T_SET;
  403: 	       break;
  404: 
  405: 	  case T_PREFIX:
  406: 	       $$ = T_PREFIX_SET;
  407: 	    break;
  408: 
  409: 	  default:
  410: 		cf_error( "You can't create sets of this type." );
  411: 	}
  412:    }
  413:  ;
  414: 
  415: one_decl:
  416:    type SYM {
  417:      struct f_val * val = cfg_alloc(sizeof(struct f_val));
  418:      val->type = T_VOID;
  419:      $2 = cf_define_symbol($2, SYM_VARIABLE | $1, val);
  420:      DBG( "New variable %s type %x\n", $2->name, $1 );
  421:      $2->aux2 = NULL;
  422:      $$=$2;
  423:    }
  424:  ;
  425: 
  426: /* Decls with ';' at the end */
  427: decls: /* EMPTY */ { $$ = NULL; }
  428:  | one_decl ';' decls {
  429:      $$ = $1;
  430:      $$->aux2 = $3;
  431:    }
  432:  ;
  433: 
  434: /* Declarations that have no ';' at the end. */
  435: declsn: one_decl { $$ = $1; }
  436:  | one_decl ';' declsn {
  437:      $$ = $1;
  438:      $$->aux2 = $3;
  439:    }
  440:  ;
  441: 
  442: filter_body:
  443:    function_body {
  444:      struct filter *f = cfg_alloc(sizeof(struct filter));
  445:      f->name = NULL;
  446:      f->root = $1;
  447:      $$ = f;
  448:    }
  449:  ;
  450: 
  451: filter:
  452:    SYM {
  453:      if ($1->class != SYM_FILTER) cf_error("No such filter.");
  454:      $$ = $1->def;
  455:    }
  456:  | filter_body
  457:  ;
  458: 
  459: where_filter:
  460:    WHERE term {
  461:      /* Construct 'IF term THEN ACCEPT; REJECT;' */
  462:      struct filter *f = cfg_alloc(sizeof(struct filter));
  463:      struct f_inst *i, *acc, *rej;
  464:      acc = f_new_inst();		/* ACCEPT */
  465:      acc->code = P('p',',');
  466:      acc->a1.p = NULL;
  467:      acc->a2.i = F_ACCEPT;
  468:      rej = f_new_inst();		/* REJECT */
  469:      rej->code = P('p',',');
  470:      rej->a1.p = NULL;
  471:      rej->a2.i = F_REJECT;
  472:      i = f_new_inst();			/* IF */
  473:      i->code = '?';
  474:      i->a1.p = $2;
  475:      i->a2.p = acc;
  476:      i->next = rej;
  477:      f->name = NULL;
  478:      f->root = i;
  479:      $$ = f;
  480:   }
  481:  ;
  482: 
  483: function_params:
  484:    '(' declsn ')' { DBG( "Have function parameters\n" ); $$=$2; }
  485:  | '(' ')' { $$=NULL; }
  486:  ;
  487: 
  488: function_body:
  489:    decls '{' cmds '}' {
  490:      if ($1) {
  491:        /* Prepend instruction to clear local variables */
  492:        $$ = f_new_inst();
  493:        $$->code = P('c','v');
  494:        $$->a1.p = $1;
  495:        $$->next = $3;
  496:      } else
  497:        $$ = $3;
  498:    }
  499:  ;
  500: 
  501: CF_ADDTO(conf, function_def)
  502: function_def:
  503:    FUNCTION SYM { DBG( "Beginning of function %s\n", $2->name );
  504:      $2 = cf_define_symbol($2, SYM_FUNCTION, NULL);
  505:      cf_push_scope($2);
  506:    } function_params function_body {
  507:      $2->def = $5;
  508:      $2->aux2 = $4;
  509:      DBG("Hmm, we've got one function here - %s\n", $2->name);
  510:      cf_pop_scope();
  511:    }
  512:  ;
  513: 
  514: /* Programs */
  515: 
  516: /* Hack: $$ of cmds_int is the last node.
  517:    $$->next of cmds_int is temporary used for the first node */
  518: 
  519: cmds: /* EMPTY */ { $$ = NULL; }
  520:  | cmds_int { $$ = $1->next; $1->next = NULL; }
  521:  ;
  522: 
  523: cmds_int: cmd { $$ = $1; $1->next = $1; }
  524:  | cmds_int cmd { $$ = $2; $2->next = $1->next ; $1->next = $2; }
  525:  ;
  526: 
  527: block:
  528:    cmd {
  529:      $$=$1;
  530:    }
  531:  | '{' cmds '}' {
  532:      $$=$2;
  533:    }
  534:  ;
  535: 
  536: /*
  537:  * Complex types, their bison value is struct f_val
  538:  */
  539: fipa:
  540:    IPA %prec PREFIX_DUMMY { $$.type = T_IP; $$.val.px.ip = $1; }
  541:  ;
  542: 
  543: 
  544: 
  545: /*
  546:  * Set constants. They are also used in switch cases. We use separate
  547:  * nonterminals for switch (set_atom/switch_atom, set_item/switch_item ...)
  548:  * to elude a collision between symbol (in expr) in set_atom and symbol
  549:  * as a function call in switch case cmds.
  550:  */
  551: 
  552: set_atom:
  553:    NUM   { $$.type = T_INT; $$.val.i = $1; }
  554:  | RTRID { $$.type = T_QUAD; $$.val.i = $1; }
  555:  | fipa  { $$ = $1; }
  556:  | ENUM  { $$.type = pair_a($1); $$.val.i = pair_b($1); }
  557:  | '(' term ')' {
  558:      $$ = f_eval($2, cfg_mem);
  559:      if (!f_valid_set_type($$.type)) cf_error("Set-incompatible type");
  560:    }
  561:  | SYM {
  562:      if (!cf_symbol_is_constant($1)) cf_error("%s: constant expected", $1->name);
  563:      if (!f_valid_set_type(SYM_TYPE($1))) cf_error("%s: set-incompatible type", $1->name);
  564:      $$ = *(struct f_val *)($1->def);
  565:    }
  566:  ;
  567: 
  568: switch_atom:
  569:    NUM   { $$.type = T_INT; $$.val.i = $1; }
  570:  | '(' term ')' { $$.type = T_INT; $$.val.i = f_eval_int($2); }
  571:  | RTRID { $$.type = T_QUAD; $$.val.i = $1; }
  572:  | fipa  { $$ = $1; }
  573:  | ENUM  { $$.type = pair_a($1); $$.val.i = pair_b($1); }
  574:  ;
  575: 
  576: cnum:
  577:    term { $$ = f_eval_int($1); }
  578: 
  579: pair_item:
  580:    '(' cnum ',' cnum ')'		{ $$ = f_new_pair_item($2, $2, $4, $4); }
  581:  | '(' cnum ',' cnum DDOT cnum ')'	{ $$ = f_new_pair_item($2, $2, $4, $6); }
  582:  | '(' cnum ',' '*' ')'			{ $$ = f_new_pair_item($2, $2, 0, CC_ALL); }
  583:  | '(' cnum DDOT cnum ',' cnum ')'	{ $$ = f_new_pair_set($2, $4, $6, $6); }
  584:  | '(' cnum DDOT cnum ',' cnum DDOT cnum ')' { $$ = f_new_pair_set($2, $4, $6, $8); }
  585:  | '(' cnum DDOT cnum ',' '*' ')'	{ $$ = f_new_pair_item($2, $4, 0, CC_ALL); }
  586:  | '(' '*' ',' cnum ')'			{ $$ = f_new_pair_set(0, CC_ALL, $4, $4); }
  587:  | '(' '*' ',' cnum DDOT cnum ')'	{ $$ = f_new_pair_set(0, CC_ALL, $4, $6); }
  588:  | '(' '*' ',' '*' ')'			{ $$ = f_new_pair_item(0, CC_ALL, 0, CC_ALL); }
  589:  | '(' cnum ',' cnum ')' DDOT '(' cnum ',' cnum ')'
  590:    { $$ = f_new_pair_item($2, $8, $4, $10); }
  591:  ;
  592: 
  593: ec_kind:
  594:    RT { $$ = EC_RT; }
  595:  | RO { $$ = EC_RO; }
  596:  | UNKNOWN NUM { $$ = $2; }
  597:  | GENERIC { $$ = EC_GENERIC; }
  598:  ;
  599: 
  600: ec_item:
  601:    '(' ec_kind ',' cnum ',' cnum ')'		{ $$ = f_new_ec_item($2, 0, $4, $6, $6); }
  602:  | '(' ec_kind ',' cnum ',' cnum DDOT cnum ')'	{ $$ = f_new_ec_item($2, 0, $4, $6, $8); }
  603:  | '(' ec_kind ',' cnum ',' '*' ')'		{ $$ = f_new_ec_item($2, 0, $4, 0, EC_ALL); }
  604:  ;
  605: 
  606: lc_item:
  607:    '(' cnum ',' cnum ',' cnum ')'	    { $$ = f_new_lc_item($2, $2, $4, $4, $6, $6); }
  608:  | '(' cnum ',' cnum ',' cnum DDOT cnum ')' { $$ = f_new_lc_item($2, $2, $4, $4, $6, $8); }
  609:  | '(' cnum ',' cnum ',' '*' ')'	    { $$ = f_new_lc_item($2, $2, $4, $4, 0, LC_ALL); }
  610:  | '(' cnum ',' cnum DDOT cnum ',' '*' ')'  { $$ = f_new_lc_item($2, $2, $4, $6, 0, LC_ALL); }
  611:  | '(' cnum ',' '*' ',' '*' ')'		    { $$ = f_new_lc_item($2, $2, 0, LC_ALL, 0, LC_ALL); }
  612:  | '(' cnum DDOT cnum ',' '*' ',' '*' ')'   { $$ = f_new_lc_item($2, $4, 0, LC_ALL, 0, LC_ALL); }
  613:  | '(' '*' ',' '*' ',' '*' ')'		    { $$ = f_new_lc_item(0, LC_ALL, 0, LC_ALL, 0, LC_ALL); }
  614:  | '(' cnum ',' cnum ',' cnum ')' DDOT '(' cnum ',' cnum ',' cnum ')'
  615:    { $$ = f_new_lc_item($2, $10, $4, $12, $6, $14); }
  616: ;
  617: 
  618: set_item:
  619:    pair_item
  620:  | ec_item
  621:  | lc_item
  622:  | set_atom { $$ = f_new_item($1, $1); }
  623:  | set_atom DDOT set_atom { $$ = f_new_item($1, $3); }
  624:  ;
  625: 
  626: switch_item:
  627:    pair_item
  628:  | ec_item
  629:  | lc_item
  630:  | switch_atom { $$ = f_new_item($1, $1); }
  631:  | switch_atom DDOT switch_atom { $$ = f_new_item($1, $3); }
  632:  ;
  633: 
  634: set_items:
  635:    set_item
  636:  | set_items ',' set_item { $$ = f_merge_items($1, $3); }
  637:  ;
  638: 
  639: switch_items:
  640:    switch_item
  641:  | switch_items ',' switch_item { $$ = f_merge_items($1, $3); }
  642:  ;
  643: 
  644: fprefix_s:
  645:    IPA '/' NUM %prec '/' {
  646:      if (($3 < 0) || ($3 > MAX_PREFIX_LENGTH) || !ip_is_prefix($1, $3)) cf_error("Invalid network prefix: %I/%d.", $1, $3);
  647:      $$.type = T_PREFIX; $$.val.px.ip = $1; $$.val.px.len = $3;
  648:    }
  649:  ;
  650: 
  651: fprefix:
  652:    fprefix_s { $$ = $1; }
  653:  | fprefix_s '+' { $$ = $1; $$.val.px.len |= LEN_PLUS; }
  654:  | fprefix_s '-' { $$ = $1; $$.val.px.len |= LEN_MINUS; }
  655:  | fprefix_s '{' NUM ',' NUM '}' {
  656:      if (! ((0 <= $3) && ($3 <= $5) && ($5 <= MAX_PREFIX_LENGTH))) cf_error("Invalid prefix pattern range: {%d, %d}.", $3, $5);
  657:      $$ = $1; $$.val.px.len |= LEN_RANGE | ($3 << 16) | ($5 << 8);
  658:    }
  659:  ;
  660: 
  661: fprefix_set:
  662:    fprefix { $$ = f_new_trie(cfg_mem, sizeof(struct f_trie_node)); trie_add_fprefix($$, &($1.val.px)); }
  663:  | fprefix_set ',' fprefix { $$ = $1; trie_add_fprefix($$, &($3.val.px)); }
  664:  ;
  665: 
  666: switch_body: /* EMPTY */ { $$ = NULL; }
  667:  | switch_body switch_items ':' cmds  {
  668:      /* Fill data fields */
  669:      struct f_tree *t;
  670:      for (t = $2; t; t = t->left)
  671:        t->data = $4;
  672:      $$ = f_merge_items($1, $2);
  673:    }
  674:  | switch_body ELSECOL cmds {
  675:      struct f_tree *t = f_new_tree();
  676:      t->from.type = t->to.type = T_VOID;
  677:      t->right = t;
  678:      t->data = $3;
  679:      $$ = f_merge_items($1, t);
  680:  }
  681:  ;
  682: 
  683: /* CONST '(' expr ')' { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_INT; $$->a2.i = $3; } */
  684: 
  685: bgp_path_expr:
  686:    symbol       { $$ = $1; }
  687:  | '(' term ')' { $$ = $2; }
  688:  ;
  689: 
  690: bgp_path:
  691:    PO  bgp_path_tail1 PC  { $$ = $2; }
  692:  | '/' bgp_path_tail2 '/' { $$ = $2; }
  693:  ;
  694: 
  695: bgp_path_tail1:
  696:    NUM bgp_path_tail1		{ $$ = cfg_allocz(sizeof(struct f_path_mask)); $$->next = $2; $$->kind = PM_ASN; $$->val = $1; }
  697:  | NUM DDOT NUM bgp_path_tail1	{ $$ = cfg_allocz(sizeof(struct f_path_mask)); $$->next = $4; $$->kind = PM_ASN_RANGE; $$->val = $1; $$->val2 = $3; }
  698:  | '*' bgp_path_tail1		{ $$ = cfg_allocz(sizeof(struct f_path_mask)); $$->next = $2; $$->kind = PM_ASTERISK; }
  699:  | '?' bgp_path_tail1		{ $$ = cfg_allocz(sizeof(struct f_path_mask)); $$->next = $2; $$->kind = PM_QUESTION; }
  700:  | bgp_path_expr bgp_path_tail1	{ $$ = cfg_allocz(sizeof(struct f_path_mask)); $$->next = $2; $$->kind = PM_ASN_EXPR; $$->val = (uintptr_t) $1; }
  701:  | 				{ $$ = NULL; }
  702:  ;
  703: 
  704: bgp_path_tail2:
  705:    NUM bgp_path_tail2 { $$ = cfg_allocz(sizeof(struct f_path_mask)); $$->next = $2; $$->kind = PM_ASN; $$->val = $1; }
  706:  | '?' bgp_path_tail2 { $$ = cfg_allocz(sizeof(struct f_path_mask)); $$->next = $2; $$->kind = PM_ASTERISK; }
  707:  | 		      { $$ = NULL; }
  708:  ;
  709: 
  710: constant:
  711:    NUM    { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_INT;  $$->a2.i = $1; }
  712:  | TRUE   { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_BOOL; $$->a2.i = 1;  }
  713:  | FALSE  { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_BOOL; $$->a2.i = 0;  }
  714:  | TEXT   { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_STRING; $$->a2.p = $1; }
  715:  | fipa	   { NEW_F_VAL; $$ = f_new_inst(); $$->code = 'C'; $$->a1.p = val; *val = $1; }
  716:  | fprefix_s {NEW_F_VAL; $$ = f_new_inst(); $$->code = 'C'; $$->a1.p = val; *val = $1; }
  717:  | RTRID  { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_QUAD;  $$->a2.i = $1; }
  718:  | '[' set_items ']' { DBG( "We've got a set here..." ); $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_SET; $$->a2.p = build_tree($2); DBG( "ook\n" ); }
  719:  | '[' fprefix_set ']' { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_PREFIX_SET;  $$->a2.p = $2; }
  720:  | ENUM	  { $$ = f_new_inst(); $$->code = 'c'; $$->aux = $1 >> 16; $$->a2.i = $1 & 0xffff; }
  721:  | bgp_path { NEW_F_VAL; $$ = f_new_inst(); $$->code = 'C'; val->type = T_PATH_MASK; val->val.path_mask = $1; $$->a1.p = val; }
  722:  ;
  723: 
  724: constructor:
  725:    '(' term ',' term ')' { $$ = f_generate_dpair($2, $4); }
  726:  | '(' ec_kind ',' term ',' term ')' { $$ = f_generate_ec($2, $4, $6); }
  727:  | '(' term ',' term ',' term ')' { $$ = f_generate_lc($2, $4, $6); }
  728:  ;
  729: 
  730: 
  731: /*
  732:  *  Maybe there are no dynamic attributes defined by protocols.
  733:  *  For such cases, we force the dynamic_attr list to contain
  734:  *  at least an invalid token, so it is syntantically correct.
  735:  */
  736: CF_ADDTO(dynamic_attr, INVALID_TOKEN { $$ = NULL; })
  737: 
  738: rtadot: /* EMPTY, we are not permitted RTA. prefix */
  739:  ;
  740: 
  741: function_call:
  742:    SYM '(' var_list ')' {
  743:      struct symbol *sym;
  744:      struct f_inst *inst = $3;
  745:      if ($1->class != SYM_FUNCTION)
  746:        cf_error("You can't call something which is not a function. Really.");
  747:      DBG("You are calling function %s\n", $1->name);
  748:      $$ = f_new_inst();
  749:      $$->code = P('c','a');
  750:      $$->a1.p = inst;
  751:      $$->a2.p = $1->def;
  752:      sym = $1->aux2;
  753:      while (sym || inst) {
  754:        if (!sym || !inst)
  755: 	 cf_error("Wrong number of arguments for function %s.", $1->name);
  756:        DBG( "You should pass parameter called %s\n", sym->name);
  757:        inst->a1.p = sym;
  758:        sym = sym->aux2;
  759:        inst = inst->next;
  760:      }
  761:    }
  762:  ;
  763: 
  764: symbol:
  765:    SYM {
  766:      $$ = f_new_inst();
  767: 
  768:      switch ($1->class & 0xff00) {
  769:        case SYM_CONSTANT: $$->code = 'C'; break;
  770:        case SYM_VARIABLE: $$->code = 'V'; break;
  771:        default: cf_error("%s: variable expected.", $1->name);
  772:      }
  773: 
  774:      $$->a1.p = $1->def;
  775:      $$->a2.p = $1->name;
  776:    }
  777: 
  778: static_attr:
  779:    FROM    { $$ = f_new_inst(); $$->aux = T_IP;         $$->a2.i = SA_FROM;	$$->a1.i = 1; }
  780:  | GW      { $$ = f_new_inst(); $$->aux = T_IP;         $$->a2.i = SA_GW;	$$->a1.i = 1; }
  781:  | NET     { $$ = f_new_inst(); $$->aux = T_PREFIX;     $$->a2.i = SA_NET; }
  782:  | PROTO   { $$ = f_new_inst(); $$->aux = T_STRING;     $$->a2.i = SA_PROTO; }
  783:  | SOURCE  { $$ = f_new_inst(); $$->aux = T_ENUM_RTS;   $$->a2.i = SA_SOURCE; }
  784:  | SCOPE   { $$ = f_new_inst(); $$->aux = T_ENUM_SCOPE; $$->a2.i = SA_SCOPE;	$$->a1.i = 1; }
  785:  | CAST    { $$ = f_new_inst(); $$->aux = T_ENUM_RTC;   $$->a2.i = SA_CAST; }
  786:  | DEST    { $$ = f_new_inst(); $$->aux = T_ENUM_RTD;   $$->a2.i = SA_DEST;	$$->a1.i = 1; }
  787:  | IFNAME  { $$ = f_new_inst(); $$->aux = T_STRING;     $$->a2.i = SA_IFNAME; }
  788:  | IFINDEX { $$ = f_new_inst(); $$->aux = T_INT;        $$->a2.i = SA_IFINDEX; }
  789:  ;
  790: 
  791: term:
  792:    '(' term ')'      { $$ = $2; }
  793:  | term '+' term     { $$ = f_new_inst(); $$->code = '+';        $$->a1.p = $1; $$->a2.p = $3; }
  794:  | term '-' term     { $$ = f_new_inst(); $$->code = '-';        $$->a1.p = $1; $$->a2.p = $3; }
  795:  | term '*' term     { $$ = f_new_inst(); $$->code = '*';        $$->a1.p = $1; $$->a2.p = $3; }
  796:  | term '/' term     { $$ = f_new_inst(); $$->code = '/';        $$->a1.p = $1; $$->a2.p = $3; }
  797:  | term AND term     { $$ = f_new_inst(); $$->code = '&';        $$->a1.p = $1; $$->a2.p = $3; }
  798:  | term OR  term     { $$ = f_new_inst(); $$->code = '|';        $$->a1.p = $1; $$->a2.p = $3; }
  799:  | term '=' term     { $$ = f_new_inst(); $$->code = P('=','='); $$->a1.p = $1; $$->a2.p = $3; }
  800:  | term NEQ term { $$ = f_new_inst(); $$->code = P('!','=');     $$->a1.p = $1; $$->a2.p = $3; }
  801:  | term '<' term     { $$ = f_new_inst(); $$->code = '<';        $$->a1.p = $1; $$->a2.p = $3; }
  802:  | term LEQ term { $$ = f_new_inst(); $$->code = P('<','=');     $$->a1.p = $1; $$->a2.p = $3; }
  803:  | term '>' term     { $$ = f_new_inst(); $$->code = '<';        $$->a1.p = $3; $$->a2.p = $1; }
  804:  | term GEQ term { $$ = f_new_inst(); $$->code = P('<','=');     $$->a1.p = $3; $$->a2.p = $1; }
  805:  | term '~' term     { $$ = f_new_inst(); $$->code = '~';        $$->a1.p = $1; $$->a2.p = $3; }
  806:  | term NMA term { $$ = f_new_inst(); $$->code = P('!','~');     $$->a1.p = $1; $$->a2.p = $3; }
  807:  | '!' term { $$ = f_new_inst(); $$->code = '!'; $$->a1.p = $2; }
  808:  | DEFINED '(' term ')' { $$ = f_new_inst(); $$->code = P('d','e');  $$->a1.p = $3; }
  809: 
  810:  | symbol   { $$ = $1; }
  811:  | constant { $$ = $1; }
  812:  | constructor { $$ = $1; }
  813: 
  814:  | PREFERENCE { $$ = f_new_inst(); $$->code = 'P'; }
  815: 
  816:  | rtadot static_attr { $$ = $2; $$->code = 'a'; }
  817: 
  818:  | rtadot dynamic_attr { $$ = $2; $$->code = P('e','a'); }
  819: 
  820:  | term '.' IP { $$ = f_new_inst(); $$->code = P('c','p'); $$->a1.p = $1; $$->aux = T_IP; }
  821:  | term '.' LEN { $$ = f_new_inst(); $$->code = 'L'; $$->a1.p = $1; }
  822:  | term '.' MASK '(' term ')' { $$ = f_new_inst(); $$->code = P('i','M'); $$->a1.p = $1; $$->a2.p = $5; }
  823:  | term '.' FIRST { $$ = f_new_inst(); $$->code = P('a','f'); $$->a1.p = $1; }
  824:  | term '.' LAST  { $$ = f_new_inst(); $$->code = P('a','l'); $$->a1.p = $1; }
  825:  | term '.' LAST_NONAGGREGATED  { $$ = f_new_inst(); $$->code = P('a','L'); $$->a1.p = $1; }
  826: 
  827: /* Communities */
  828: /* This causes one shift/reduce conflict
  829:  | rtadot dynamic_attr '.' ADD '(' term ')' { }
  830:  | rtadot dynamic_attr '.' DELETE '(' term ')' { }
  831:  | rtadot dynamic_attr '.' CONTAINS '(' term ')' { }
  832:  | rtadot dynamic_attr '.' RESET{ }
  833: */
  834: 
  835:  | '+' EMPTY '+' { $$ = f_new_inst(); $$->code = 'E'; $$->aux = T_PATH; }
  836:  | '-' EMPTY '-' { $$ = f_new_inst(); $$->code = 'E'; $$->aux = T_CLIST; }
  837:  | '-' '-' EMPTY '-' '-' { $$ = f_new_inst(); $$->code = 'E'; $$->aux = T_ECLIST; }
  838:  | '-' '-' '-' EMPTY '-' '-' '-' { $$ = f_new_inst(); $$->code = 'E'; $$->aux = T_LCLIST; }
  839:  | PREPEND '(' term ',' term ')' { $$ = f_new_inst(); $$->code = P('A','p'); $$->a1.p = $3; $$->a2.p = $5; }
  840:  | ADD '(' term ',' term ')' { $$ = f_new_inst(); $$->code = P('C','a'); $$->a1.p = $3; $$->a2.p = $5; $$->aux = 'a'; }
  841:  | DELETE '(' term ',' term ')' { $$ = f_new_inst(); $$->code = P('C','a'); $$->a1.p = $3; $$->a2.p = $5; $$->aux = 'd'; }
  842:  | FILTER '(' term ',' term ')' { $$ = f_new_inst(); $$->code = P('C','a'); $$->a1.p = $3; $$->a2.p = $5; $$->aux = 'f'; }
  843: 
  844:  | ROA_CHECK '(' SYM ')' { $$ = f_generate_roa_check($3, NULL, NULL); }
  845:  | ROA_CHECK '(' SYM ',' term ',' term ')' { $$ = f_generate_roa_check($3, $5, $7); }
  846: 
  847: /* | term '.' LEN { $$->code = P('P','l'); } */
  848: 
  849: /* function_call is inlined here */
  850:  | SYM '(' var_list ')' {
  851:      struct symbol *sym;
  852:      struct f_inst *inst = $3;
  853:      if ($1->class != SYM_FUNCTION)
  854:        cf_error("You can't call something which is not a function. Really.");
  855:      DBG("You are calling function %s\n", $1->name);
  856:      $$ = f_new_inst();
  857:      $$->code = P('c','a');
  858:      $$->a1.p = inst;
  859:      $$->a2.p = $1->def;
  860:      sym = $1->aux2;
  861:      while (sym || inst) {
  862:        if (!sym || !inst)
  863: 	 cf_error("Wrong number of arguments for function %s.", $1->name);
  864:        DBG( "You should pass parameter called %s\n", sym->name);
  865:        inst->a1.p = sym;
  866:        sym = sym->aux2;
  867:        inst = inst->next;
  868:      }
  869:    }
  870:  ;
  871: 
  872: break_command:
  873:    QUITBIRD { $$ = F_QUITBIRD; }
  874:  | ACCEPT { $$ = F_ACCEPT; }
  875:  | REJECT { $$ = F_REJECT; }
  876:  | ERROR { $$ = F_ERROR; }
  877:  | PRINT { $$ = F_NOP; }
  878:  | PRINTN { $$ = F_NONL; }
  879:  ;
  880: 
  881: print_one:
  882:    term { $$ = f_new_inst(); $$->code = 'p'; $$->a1.p = $1; $$->a2.p = NULL; }
  883:  ;
  884: 
  885: print_list: /* EMPTY */ { $$ = NULL; }
  886:  | print_one { $$ = $1; }
  887:  | print_one ',' print_list {
  888:      if ($1) {
  889:        $1->next = $3;
  890:        $$ = $1;
  891:      } else $$ = $3;
  892:    }
  893:  ;
  894: 
  895: var_listn: term {
  896:      $$ = f_new_inst();
  897:      $$->code = 's';
  898:      $$->a1.p = NULL;
  899:      $$->a2.p = $1;
  900:      $$->next = NULL;
  901:    }
  902:  | term ',' var_listn {
  903:      $$ = f_new_inst();
  904:      $$->code = 's';
  905:      $$->a1.p = NULL;
  906:      $$->a2.p = $1;
  907:      $$->next = $3;
  908:    }
  909:  ;
  910: 
  911: var_list: /* EMPTY */ { $$ = NULL; }
  912:  | var_listn { $$ = $1; }
  913:  ;
  914: 
  915: cmd:
  916:    IF term THEN block {
  917:      $$ = f_new_inst();
  918:      $$->code = '?';
  919:      $$->a1.p = $2;
  920:      $$->a2.p = $4;
  921:    }
  922:  | IF term THEN block ELSE block {
  923:      struct f_inst *i = f_new_inst();
  924:      i->code = '?';
  925:      i->a1.p = $2;
  926:      i->a2.p = $4;
  927:      $$ = f_new_inst();
  928:      $$->code = '?';
  929:      $$->a1.p = i;
  930:      $$->a2.p = $6;
  931:    }
  932:  | SYM '=' term ';' {
  933:      $$ = f_new_inst();
  934:      DBG( "Ook, we'll set value\n" );
  935:      if (($1->class & ~T_MASK) != SYM_VARIABLE)
  936:        cf_error( "You may set only variables." );
  937:      $$->code = 's';
  938:      $$->a1.p = $1;
  939:      $$->a2.p = $3;
  940:    }
  941:  | RETURN term ';' {
  942:      $$ = f_new_inst();
  943:      DBG( "Ook, we'll return the value\n" );
  944:      $$->code = 'r';
  945:      $$->a1.p = $2;
  946:    }
  947:  | rtadot dynamic_attr '=' term ';' {
  948:      $$ = $2;
  949:      $$->code = P('e','S');
  950:      $$->a1.p = $4;
  951:    }
  952:  | rtadot static_attr '=' term ';' {
  953:      $$ = $2;
  954:      if (!$$->a1.i)
  955:        cf_error( "This static attribute is read-only.");
  956:      $$->code = P('a','S');
  957:      $$->a1.p = $4;
  958:    }
  959:  | PREFERENCE '=' term ';' {
  960:      $$ = f_new_inst();
  961:      $$->code = P('P','S');
  962:      $$->a1.p = $3;
  963:    }
  964:  | UNSET '(' rtadot dynamic_attr ')' ';' {
  965:      $$ = $4;
  966:      $$->aux = EAF_TYPE_UNDEF | EAF_TEMP;
  967:      $$->code = P('e','S');
  968:      $$->a1.p = NULL;
  969:    }
  970:  | break_command print_list ';' { $$ = f_new_inst(); $$->code = P('p',','); $$->a1.p = $2; $$->a2.i = $1; }
  971:  | function_call ';' { $$ = $1; }
  972:  | CASE term '{' switch_body '}' {
  973:       $$ = f_new_inst();
  974:       $$->code = P('S','W');
  975:       $$->a1.p = $2;
  976:       $$->a2.p = build_tree( $4 );
  977:    }
  978: 
  979: 
  980:  | rtadot dynamic_attr '.' EMPTY ';' { $$ = f_generate_empty($2); }
  981:  | rtadot dynamic_attr '.' PREPEND '(' term ')' ';'   { $$ = f_generate_complex( P('A','p'), 'x', $2, $6 ); }
  982:  | rtadot dynamic_attr '.' ADD '(' term ')' ';'       { $$ = f_generate_complex( P('C','a'), 'a', $2, $6 ); }
  983:  | rtadot dynamic_attr '.' DELETE '(' term ')' ';'    { $$ = f_generate_complex( P('C','a'), 'd', $2, $6 ); }
  984:  | rtadot dynamic_attr '.' FILTER '(' term ')' ';'    { $$ = f_generate_complex( P('C','a'), 'f', $2, $6 ); }
  985:  ;
  986: 
  987: CF_END

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>