Annotation of embedaddon/bird2/conf/confbase.Y, revision 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>