Annotation of embedaddon/bird/filter/config.Y, revision 1.1.1.1

1.1       misho       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>