File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / bird / filter / config.Y
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Mar 17 19:50:23 2021 UTC (3 years, 4 months ago) by misho
Branches: bird, MAIN
CVS tags: v1_6_8p3, HEAD
bird 1.6.8

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

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