Annotation of embedaddon/bird2/conf/confbase.Y, revision 1.1.1.1

1.1       misho       1: /*
                      2:  *     BIRD -- Configuration Parser Top
                      3:  *
                      4:  *     (c) 1998--2000 Martin Mares <mj@ucw.cz>
                      5:  *
                      6:  *     Can be freely distributed and used under the terms of the GNU GPL.
                      7:  */
                      8: 
                      9: CF_HDR
                     10: 
                     11: #define PARSER 1
                     12: 
                     13: #include "nest/bird.h"
                     14: #include "conf/conf.h"
                     15: #include "lib/resource.h"
                     16: #include "lib/socket.h"
                     17: #include "lib/timer.h"
                     18: #include "lib/string.h"
                     19: #include "nest/protocol.h"
                     20: #include "nest/iface.h"
                     21: #include "nest/route.h"
                     22: #include "nest/cli.h"
                     23: #include "filter/filter.h"
                     24: 
                     25: /* FIXME: Turn on YYERROR_VERBOSE and work around lots of bison bugs? */
                     26: 
                     27: CF_DEFINES
                     28: 
                     29: static void
                     30: check_u16(uint val)
                     31: {
                     32:   if (val > 0xFFFF)
                     33:     cf_error("Value %u out of range (0-65535)", val);
                     34: }
                     35: 
                     36: #define cf_assert(cond, ...) do { if (!(cond)) cf_error(__VA_ARGS__); } while (0)
                     37: static inline void cf_assert_symbol(const struct symbol *sym, uint class) {
                     38:   switch (class) {
                     39:     case SYM_PROTO: cf_assert(sym->class == SYM_PROTO, "Protocol name required"); break;
                     40:     case SYM_TEMPLATE: cf_assert(sym->class == SYM_TEMPLATE, "Protocol template name required"); break;
                     41:     case SYM_FUNCTION: cf_assert(sym->class == SYM_FUNCTION, "Function name required"); break;
                     42:     case SYM_FILTER: cf_assert(sym->class == SYM_FILTER, "Filter name required"); break;
                     43:     case SYM_TABLE: cf_assert(sym->class == SYM_TABLE, "Table name required"); break;
                     44:     case SYM_ATTRIBUTE: cf_assert(sym->class == SYM_ATTRIBUTE, "Custom attribute name required"); break;
                     45:     case SYM_VARIABLE: cf_assert((sym->class & ~0xff) == SYM_VARIABLE, "Variable name required"); break;
                     46:     case SYM_CONSTANT: cf_assert((sym->class & ~0xff) == SYM_CONSTANT, "Constant name required"); break;
                     47:     default: bug("This shall not happen");
                     48:   }
                     49: }
                     50: 
                     51: CF_DECLS
                     52: 
                     53: %union {
                     54:   uint i;
                     55:   u32 i32;
                     56:   u64 i64;
                     57:   ip_addr a;
                     58:   ip4_addr ip4;
                     59:   ip6_addr ip6;
                     60:   net_addr net;
                     61:   net_addr *net_ptr;
                     62:   struct symbol *s;
                     63:   char *t;
                     64:   struct rtable_config *r;
                     65:   struct channel_config *cc;
                     66:   struct f_inst *x;
                     67:   struct {
                     68:     struct f_inst *begin, *end;
                     69:   } xp;
                     70:   enum filter_return fret;
                     71:   enum ec_subtype ecs;
                     72:   struct f_dynamic_attr fda;
                     73:   struct f_static_attr fsa;
                     74:   struct f_lval flv;
                     75:   struct f_line *fl;
                     76:   const struct filter *f;
                     77:   struct f_tree *e;
                     78:   struct f_trie *trie;
                     79:   struct f_val v;
                     80:   struct password_item *p;
                     81:   struct rt_show_data *ra;
                     82:   struct sym_show_data *sd;
                     83:   struct lsadb_show_data *ld;
                     84:   struct mrt_dump_data *md;
                     85:   struct iface *iface;
                     86:   void *g;
                     87:   btime time;
                     88:   struct f_prefix px;
                     89:   struct proto_spec ps;
                     90:   struct channel_limit cl;
                     91:   struct timeformat *tf;
                     92:   mpls_label_stack *mls;
                     93: }
                     94: 
                     95: %token END CLI_MARKER INVALID_TOKEN ELSECOL DDOT
                     96: %token GEQ LEQ NEQ AND OR
                     97: %token PO PC
                     98: %token <i> NUM ENUM
                     99: %token <ip4> IP4
                    100: %token <ip6> IP6
                    101: %token <i64> VPN_RD
                    102: %token <s> CF_SYM_KNOWN CF_SYM_UNDEFINED
                    103: %token <t> TEXT
                    104: %type <iface> ipa_scope
                    105: 
                    106: %type <i> expr bool pxlen4
                    107: %type <time> expr_us time
                    108: %type <a> ipa
                    109: %type <net> net_ip4_ net_ip6_ net_ip6 net_ip_ net_ip net_or_ipa
                    110: %type <net_ptr> net_ net_any net_vpn4_ net_vpn6_ net_vpn_ net_roa4_ net_roa6_ net_roa_ net_ip6_sadr_ net_mpls_
                    111: %type <mls> label_stack_start label_stack
                    112: 
                    113: %type <t> text opttext
                    114: %type <s> symbol
                    115: 
                    116: %nonassoc PREFIX_DUMMY
                    117: %left AND OR
                    118: %nonassoc '=' '<' '>' '~' GEQ LEQ NEQ NMA PO PC
                    119: %left '+' '-'
                    120: %left '*' '/' '%'
                    121: %left '!'
                    122: %nonassoc '.'
                    123: 
                    124: %start config
                    125: 
                    126: CF_KEYWORDS(DEFINE, ON, OFF, YES, NO, S, MS, US, PORT, VPN, MPLS, FROM)
                    127: 
                    128: CF_GRAMMAR
                    129: 
                    130: /* Basic config file structure */
                    131: 
                    132: config: conf_entries END { return 0; }
                    133:  | CLI_MARKER cli_cmd { return 0; }
                    134:  ;
                    135: 
                    136: conf_entries:
                    137:    /* EMPTY */
                    138:  | conf_entries conf
                    139:  ;
                    140: 
                    141: conf: ';' ;
                    142: 
                    143: 
                    144: /* Constant expressions */
                    145: 
                    146: conf: definition ;
                    147: 
                    148: definition:
                    149:    DEFINE symbol '=' term ';' {
                    150:      struct f_val *val = cfg_alloc(sizeof(struct f_val));
                    151:      if (f_eval(f_linearize($4), cfg_mem, val) > F_RETURN) cf_error("Runtime error");
                    152:      cf_define_symbol($2, SYM_CONSTANT | val->type, val, val);
                    153:    }
                    154:  ;
                    155: 
                    156: expr:
                    157:    NUM
                    158:  | '(' term ')' { $$ = f_eval_int(f_linearize($2)); }
                    159:  | CF_SYM_KNOWN {
                    160:      if ($1->class != (SYM_CONSTANT | T_INT)) cf_error("Number constant expected");
                    161:      $$ = SYM_VAL($1).i; }
                    162:  ;
                    163: 
                    164: expr_us:
                    165:    expr S  { $$ = $1 S_; }
                    166:  | expr MS { $$ = $1 MS_; }
                    167:  | expr US { $$ = $1 US_; }
                    168:  ;
                    169: 
                    170: symbol: CF_SYM_UNDEFINED | CF_SYM_KNOWN ;
                    171: 
                    172: /* Switches */
                    173: 
                    174: bool:
                    175:    expr { $$ = !!$1; }
                    176:  | ON { $$ = 1; }
                    177:  | YES { $$ = 1; }
                    178:  | OFF { $$ = 0; }
                    179:  | NO { $$ = 0; }
                    180:  | /* Silence means agreement */ { $$ = 1; }
                    181:  ;
                    182: 
                    183: 
                    184: /* Addresses */
                    185: 
                    186: ipa:
                    187:    IP4 { $$ = ipa_from_ip4($1); }
                    188:  | IP6 { $$ = ipa_from_ip6($1); }
                    189:  | CF_SYM_KNOWN {
                    190:      if ($1->class != (SYM_CONSTANT | T_IP)) cf_error("IP address constant expected");
                    191:      $$ = SYM_VAL($1).ip;
                    192:    }
                    193:  ;
                    194: 
                    195: ipa_scope:
                    196:    /* empty */ { $$ = NULL; }
                    197:  | '%' symbol { $$ = if_get_by_name($2->name); }
                    198:  ;
                    199: 
                    200: 
                    201: /* Networks - internal */
                    202: 
                    203: pxlen4:
                    204:    '/' NUM {
                    205:      if ($2 > IP4_MAX_PREFIX_LENGTH) cf_error("Invalid prefix length %u", $2);
                    206:      $$ = $2;
                    207:    }
                    208:  ;
                    209: 
                    210: net_ip4_: IP4 pxlen4
                    211: {
                    212:   net_fill_ip4(&($$), $1, $2);
                    213: 
                    214:   net_addr_ip4 *n = (void *) &($$);
                    215:   if (!net_validate_ip4(n))
                    216:     cf_error("Invalid IPv4 prefix %I4/%d, maybe you wanted %I4/%d",
                    217:             n->prefix, n->pxlen, ip4_and(n->prefix, ip4_mkmask(n->pxlen)), n->pxlen);
                    218: };
                    219: 
                    220: net_ip6_: IP6 '/' NUM
                    221: {
                    222:   if ($3 > IP6_MAX_PREFIX_LENGTH)
                    223:     cf_error("Invalid prefix length %u", $3);
                    224: 
                    225:   net_fill_ip6(&($$), $1, $3);
                    226: 
                    227:   net_addr_ip6 *n = (void *) &($$);
                    228:   if (!net_validate_ip6(n))
                    229:     cf_error("Invalid IPv6 prefix %I6/%d, maybe you wanted %I6/%d",
                    230:             n->prefix, n->pxlen, ip6_and(n->prefix, ip6_mkmask(n->pxlen)), n->pxlen);
                    231: };
                    232: 
                    233: net_ip6_sadr_: IP6 '/' NUM FROM IP6 '/' NUM
                    234: {
                    235:   if ($3 > IP6_MAX_PREFIX_LENGTH)
                    236:     cf_error("Invalid prefix length %u", $3);
                    237: 
                    238:   if ($7 > IP6_MAX_PREFIX_LENGTH)
                    239:     cf_error("Invalid prefix length %u", $7);
                    240: 
                    241:   $$ = cfg_alloc(sizeof(net_addr_ip6_sadr));
                    242:   net_fill_ip6_sadr($$, $1, $3, $5, $7);
                    243: 
                    244:   net_addr_ip6_sadr *n = (void *) $$;
                    245:   if (!net_validate_ip6_sadr(n))
                    246:     cf_error("Invalid SADR IPv6 prefix %I6/%d from %I6/%d, maybe you wanted %I6/%d from %I6/%d",
                    247:             n->dst_prefix, n->dst_pxlen, n->src_prefix, n->src_pxlen,
                    248:             ip6_and(n->dst_prefix, ip6_mkmask(n->dst_pxlen)), n->dst_pxlen,
                    249:             ip6_and(n->src_prefix, ip6_mkmask(n->src_pxlen)), n->src_pxlen);
                    250: };
                    251: 
                    252: net_vpn4_: VPN_RD net_ip4_
                    253: {
                    254:   $$ = cfg_alloc(sizeof(net_addr_vpn4));
                    255:   net_fill_vpn4($$, net4_prefix(&$2), net4_pxlen(&$2), $1);
                    256: }
                    257: 
                    258: net_vpn6_: VPN_RD net_ip6_
                    259: {
                    260:   $$ = cfg_alloc(sizeof(net_addr_vpn6));
                    261:   net_fill_vpn6($$, net6_prefix(&$2), net6_pxlen(&$2), $1);
                    262: }
                    263: 
                    264: net_roa4_: net_ip4_ MAX NUM AS NUM
                    265: {
                    266:   $$ = cfg_alloc(sizeof(net_addr_roa4));
                    267:   net_fill_roa4($$, net4_prefix(&$1), net4_pxlen(&$1), $3, $5);
                    268:   if ($3 < net4_pxlen(&$1) || $3 > IP4_MAX_PREFIX_LENGTH)
                    269:     cf_error("Invalid max prefix length %u", $3);
                    270: };
                    271: 
                    272: net_roa6_: net_ip6_ MAX NUM AS NUM
                    273: {
                    274:   $$ = cfg_alloc(sizeof(net_addr_roa6));
                    275:   net_fill_roa6($$, net6_prefix(&$1), net6_pxlen(&$1), $3, $5);
                    276:   if ($3 < net6_pxlen(&$1) || $3 > IP6_MAX_PREFIX_LENGTH)
                    277:     cf_error("Invalid max prefix length %u", $3);
                    278: };
                    279: 
                    280: net_mpls_: MPLS NUM
                    281: {
                    282:   $$ = cfg_alloc(sizeof(net_addr_roa6));
                    283:   net_fill_mpls($$, $2);
                    284: }
                    285: 
                    286: net_ip_: net_ip4_ | net_ip6_ ;
                    287: net_vpn_: net_vpn4_ | net_vpn6_ ;
                    288: net_roa_: net_roa4_ | net_roa6_ ;
                    289: 
                    290: net_:
                    291:    net_ip_ { $$ = cfg_alloc($1.length); net_copy($$, &($1)); }
                    292:  | net_vpn_
                    293:  | net_roa_
                    294:  | net_flow_
                    295:  | net_ip6_sadr_
                    296:  | net_mpls_
                    297:  ;
                    298: 
                    299: 
                    300: /* Networks - regular */
                    301: 
                    302: net_ip6:
                    303:    net_ip6_
                    304:  | CF_SYM_KNOWN {
                    305:      if (($1->class != (SYM_CONSTANT | T_NET)) || (SYM_VAL($1).net->type != NET_IP6))
                    306:        cf_error("IPv6 network constant expected");
                    307:      $$ = * SYM_VAL($1).net;
                    308:    }
                    309:  ;
                    310: 
                    311: net_ip:
                    312:    net_ip_
                    313:  | CF_SYM_KNOWN {
                    314:      if (($1->class != (SYM_CONSTANT | T_NET)) || !net_is_ip(SYM_VAL($1).net))
                    315:        cf_error("IP network constant expected");
                    316:      $$ = * SYM_VAL($1).net;
                    317:    }
                    318:  ;
                    319: 
                    320: net_any:
                    321:    net_
                    322:  | CF_SYM_KNOWN {
                    323:      if ($1->class != (SYM_CONSTANT | T_NET))
                    324:        cf_error("Network constant expected");
                    325:      $$ = (net_addr *) SYM_VAL($1).net; /* Avoid const warning */
                    326:    }
                    327:  ;
                    328: 
                    329: net_or_ipa:
                    330:    net_ip4_
                    331:  | net_ip6_
                    332:  | IP4 { net_fill_ip4(&($$), $1, IP4_MAX_PREFIX_LENGTH); }
                    333:  | IP6 { net_fill_ip6(&($$), $1, IP6_MAX_PREFIX_LENGTH); }
                    334:  | CF_SYM_KNOWN {
                    335:      if ($1->class == (SYM_CONSTANT | T_IP))
                    336:        net_fill_ip_host(&($$), SYM_VAL($1).ip);
                    337:      else if (($1->class == (SYM_CONSTANT | T_NET)) && net_is_ip(SYM_VAL($1).net))
                    338:        $$ = * SYM_VAL($1).net;
                    339:      else
                    340:        cf_error("IP address or network constant expected");
                    341:    }
                    342:  ;
                    343: 
                    344: label_stack_start: NUM
                    345: {
                    346:   $$ = cfg_allocz(sizeof(mpls_label_stack));
                    347:   $$->len = 1;
                    348:   $$->stack[0] = $1;
                    349: };
                    350: 
                    351: label_stack:
                    352:     label_stack_start
                    353:   | label_stack '/' NUM {
                    354:     if ($1->len >= MPLS_MAX_LABEL_STACK)
                    355:       cf_error("Too many labels in stack");
                    356:     $1->stack[$1->len++] = $3;
                    357:     $$ = $1;
                    358:   }
                    359: ;
                    360: 
                    361: time:
                    362:    TEXT {
                    363:      $$ = tm_parse_time($1);
                    364:      if (!$$)
                    365:        cf_error("Invalid date/time");
                    366:    }
                    367:  ;
                    368: 
                    369: text:
                    370:    TEXT
                    371:  | CF_SYM_KNOWN {
                    372:      if ($1->class != (SYM_CONSTANT | T_STRING)) cf_error("String constant expected");
                    373:      $$ = SYM_VAL($1).s;
                    374:    }
                    375:  ;
                    376: 
                    377: opttext:
                    378:     TEXT
                    379:  | /* empty */ { $$ = NULL; }
                    380:  ;
                    381: 
                    382: 
                    383: CF_CODE
                    384: 
                    385: CF_END

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