summaryrefslogtreecommitdiff
path: root/nest/config.Y
diff options
context:
space:
mode:
Diffstat (limited to 'nest/config.Y')
-rw-r--r--nest/config.Y347
1 files changed, 190 insertions, 157 deletions
diff --git a/nest/config.Y b/nest/config.Y
index 878224fe..b0f9642f 100644
--- a/nest/config.Y
+++ b/nest/config.Y
@@ -18,9 +18,10 @@ CF_HDR
CF_DEFINES
static struct proto_config *this_proto;
+static struct channel_config *this_channel;
static struct iface_patt *this_ipatt;
static struct iface_patt_node *this_ipn;
-static struct roa_table_config *this_roa_table;
+/* static struct roa_table_config *this_roa_table; */
static list *this_p_list;
static struct password_item *this_p_item;
static int password_id;
@@ -31,7 +32,7 @@ iface_patt_check(void)
struct iface_patt_node *pn;
WALK_LIST(pn, this_ipatt->ipn_list)
- if (!pn->pattern || pn->pxlen)
+ if (!pn->pattern || pn->prefix.type)
cf_error("Interface name/mask expected, not IP prefix");
}
@@ -50,25 +51,37 @@ get_passwords(void)
return rv;
}
+static void
+proto_postconfig(void)
+{
+ CALL(this_proto->protocol->postconfig, this_proto);
+ this_channel = NULL;
+ this_proto = NULL;
+}
+
+
#define DIRECT_CFG ((struct rt_dev_config *) this_proto)
CF_DECLS
CF_KEYWORDS(ROUTER, ID, PROTOCOL, TEMPLATE, PREFERENCE, DISABLED, DEBUG, ALL, OFF, DIRECT)
CF_KEYWORDS(INTERFACE, IMPORT, EXPORT, FILTER, NONE, TABLE, STATES, ROUTES, FILTERS)
+CF_KEYWORDS(IPV4, IPV6, VPN4, VPN6, ROA4, ROA6)
CF_KEYWORDS(RECEIVE, LIMIT, ACTION, WARN, BLOCK, RESTART, DISABLE, KEEP, FILTERED)
CF_KEYWORDS(PASSWORD, FROM, PASSIVE, TO, ID, EVENTS, PACKETS, PROTOCOLS, INTERFACES)
CF_KEYWORDS(ALGORITHM, KEYED, HMAC, MD5, SHA1, SHA256, SHA384, SHA512)
-CF_KEYWORDS(PRIMARY, STATS, COUNT, FOR, COMMANDS, PREEXPORT, NOEXPORT, GENERATE, ROA)
+CF_KEYWORDS(PRIMARY, STATS, COUNT, BY, FOR, COMMANDS, PREEXPORT, NOEXPORT, GENERATE)
CF_KEYWORDS(LISTEN, BGP, V6ONLY, DUAL, ADDRESS, PORT, PASSWORDS, DESCRIPTION, SORTED)
CF_KEYWORDS(RELOAD, IN, OUT, MRTDUMP, MESSAGES, RESTRICT, MEMORY, IGP_METRIC, CLASS, DSCP)
CF_KEYWORDS(GRACEFUL, RESTART, WAIT, MAX, FLUSH, AS)
+/* For r_args_channel */
+CF_KEYWORDS(IPV4, IPV4_MC, IPV4_MPLS, IPV6, IPV6_MC, IPV6_MPLS, VPN4, VPN4_MC, VPN4_MPLS, VPN6, VPN6_MC, VPN6_MPLS, ROA4, ROA6, FLOW4, FLOW6, MPLS, PRI, SEC)
+
CF_ENUM(T_ENUM_RTS, RTS_, DUMMY, STATIC, INHERIT, DEVICE, STATIC_DEVICE, REDIRECT,
RIP, OSPF, OSPF_IA, OSPF_EXT1, OSPF_EXT2, BGP, PIPE, BABEL)
CF_ENUM(T_ENUM_SCOPE, SCOPE_, HOST, LINK, SITE, ORGANIZATION, UNIVERSE, UNDEFINED)
-CF_ENUM(T_ENUM_RTC, RTC_, UNICAST, BROADCAST, MULTICAST, ANYCAST)
-CF_ENUM(T_ENUM_RTD, RTD_, ROUTER, DEVICE, BLACKHOLE, UNREACHABLE, PROHIBIT, MULTIPATH)
+CF_ENUM(T_ENUM_RTD, RTD_, UNICAST, BLACKHOLE, UNREACHABLE, PROHIBIT)
CF_ENUM(T_ENUM_ROA, ROA_, UNKNOWN, VALID, INVALID)
%type <i32> idval
@@ -76,12 +89,14 @@ CF_ENUM(T_ENUM_ROA, ROA_, UNKNOWN, VALID, INVALID)
%type <r> rtable
%type <s> optsym
%type <ra> r_args
-%type <ro> roa_args
-%type <rot> roa_table_arg
%type <sd> sym_args
-%type <i> proto_start echo_mask echo_size debug_mask debug_list debug_flag mrtdump_mask mrtdump_list mrtdump_flag export_mode roa_mode limit_action tab_sorted tos password_algorithm
+%type <i> proto_start echo_mask echo_size debug_mask debug_list debug_flag mrtdump_mask mrtdump_list mrtdump_flag export_mode limit_action net_type table_sorted tos password_algorithm
%type <ps> proto_patt proto_patt2
-%type <g> limit_spec
+%type <cc> channel_start proto_channel
+%type <cl> limit_spec
+%type <net> r_args_for_val
+%type <net_ptr> r_args_for
+%type <t> r_args_channel
CF_GRAMMAR
@@ -97,21 +112,12 @@ rtrid:
idval:
NUM { $$ = $1; }
| '(' term ')' { $$ = f_eval_int($2); }
- | RTRID
- | IPA {
-#ifndef IPV6
- $$ = ipa_to_u32($1);
-#else
- cf_error("Router IDs must be entered as hexadecimal numbers or IPv4 addresses in IPv6 version");
-#endif
- }
+ | IP4 { $$ = ip4_to_u32($1); }
| SYM {
if ($1->class == (SYM_CONSTANT | T_INT) || $1->class == (SYM_CONSTANT | T_QUAD))
$$ = SYM_VAL($1).i;
-#ifndef IPV6
- else if ($1->class == (SYM_CONSTANT | T_IP))
- $$ = ipa_to_u32(SYM_VAL($1).px.ip);
-#endif
+ else if (($1->class == (SYM_CONSTANT | T_IP)) && ipa_is_ip4(SYM_VAL($1).ip))
+ $$ = ipa_to_u32(SYM_VAL($1).ip);
else
cf_error("Number or IPv4 address constant expected");
}
@@ -140,43 +146,42 @@ CF_ADDTO(conf, gr_opts)
gr_opts: GRACEFUL RESTART WAIT expr ';' { new_config->gr_wait = $4; } ;
-/* Creation of routing tables */
+/* Network types (for tables, channels) */
-tab_sorted:
- { $$ = 0; }
- | SORTED { $$ = 1; }
+net_type:
+ IPV4 { $$ = NET_IP4; }
+ | IPV6 { $$ = NET_IP6; }
+ | VPN4 { $$ = NET_VPN4; }
+ | VPN6 { $$ = NET_VPN6; }
+ | ROA4 { $$ = NET_ROA4; }
+ | ROA6 { $$ = NET_ROA6; }
+ | FLOW4{ $$ = NET_FLOW4; }
+ | FLOW6{ $$ = NET_FLOW6; }
;
-CF_ADDTO(conf, newtab)
+CF_ENUM(T_ENUM_NETTYPE, NET_, IP4, IP6, VPN4, VPN6, ROA4, ROA6, FLOW4, FLOW6)
-newtab: TABLE SYM tab_sorted {
- struct rtable_config *cf;
- cf = rt_new_table($2);
- cf->sorted = $3;
- }
- ;
-CF_ADDTO(conf, roa_table)
+/* Creation of routing tables */
-roa_table_start: ROA TABLE SYM {
- this_roa_table = roa_new_table_config($3);
-};
+CF_ADDTO(conf, table)
-roa_table_opts:
- /* empty */
- | roa_table_opts ROA prefix MAX NUM AS NUM ';' {
- roa_add_item_config(this_roa_table, $3.addr, $3.len, $5, $7);
- }
+table_sorted:
+ { $$ = 0; }
+ | SORTED { $$ = 1; }
;
-roa_table:
- roa_table_start
- | roa_table_start '{' roa_table_opts '}'
+table: net_type TABLE SYM table_sorted {
+ struct rtable_config *cf;
+ cf = rt_new_table($3, $1);
+ cf->sorted = $4;
+ }
;
+
/* Definition of protocols */
-CF_ADDTO(conf, proto)
+CF_ADDTO(conf, proto { proto_postconfig(); })
proto_start:
PROTOCOL { $$ = SYM_PROTO; }
@@ -214,24 +219,62 @@ proto_name:
proto_item:
/* EMPTY */
- | PREFERENCE expr {
- if ($2 < 0 || $2 > 0xFFFF) cf_error("Invalid preference");
- this_proto->preference = $2;
- }
| DISABLED bool { this_proto->disabled = $2; }
| DEBUG debug_mask { this_proto->debug = $2; }
| MRTDUMP mrtdump_mask { this_proto->mrtdump = $2; }
- | IMPORT imexport { this_proto->in_filter = $2; }
- | EXPORT imexport { this_proto->out_filter = $2; }
- | RECEIVE LIMIT limit_spec { this_proto->rx_limit = $3; }
- | IMPORT LIMIT limit_spec { this_proto->in_limit = $3; }
- | EXPORT LIMIT limit_spec { this_proto->out_limit = $3; }
- | IMPORT KEEP FILTERED bool { this_proto->in_keep_filtered = $4; }
- | TABLE rtable { this_proto->table = $2; }
| ROUTER ID idval { this_proto->router_id = $3; }
| DESCRIPTION text { this_proto->dsc = $2; }
;
+
+channel_start: net_type
+{
+ $$ = this_channel = channel_config_new(NULL, $1, this_proto);
+};
+
+channel_item:
+ TABLE rtable {
+ if (this_channel->net_type && ($2->addr_type != this_channel->net_type))
+ cf_error("Incompatible table type");
+ this_channel->table = $2;
+ }
+ | IMPORT imexport { this_channel->in_filter = $2; }
+ | EXPORT imexport { this_channel->out_filter = $2; }
+ | RECEIVE LIMIT limit_spec { this_channel->rx_limit = $3; }
+ | IMPORT LIMIT limit_spec { this_channel->in_limit = $3; }
+ | EXPORT LIMIT limit_spec { this_channel->out_limit = $3; }
+ | PREFERENCE expr { this_channel->preference = $2; check_u16($2); }
+ | IMPORT KEEP FILTERED bool { this_channel->in_keep_filtered = $4; }
+ ;
+
+channel_opts:
+ /* empty */
+ | channel_opts channel_item ';'
+ ;
+
+channel_opt_list:
+ /* empty */
+ | '{' channel_opts '}'
+ ;
+
+channel_end:
+{
+ if (!this_channel->table)
+ cf_error("Routing table not specified");
+
+ this_channel = NULL;
+};
+
+proto_channel: channel_start channel_opt_list channel_end;
+
+
+rtable:
+ SYM {
+ if ($1->class != SYM_TABLE) cf_error("Table expected");
+ $$ = $1->def;
+ }
+ ;
+
imexport:
FILTER filter { $$ = $2; }
| where_filter
@@ -248,20 +291,8 @@ limit_action:
;
limit_spec:
- expr limit_action {
- struct proto_limit *l = cfg_allocz(sizeof(struct proto_limit));
- l->limit = $1;
- l->action = $2;
- $$ = l;
- }
- | OFF { $$ = NULL; }
- ;
-
-rtable:
- SYM {
- if ($1->class != SYM_TABLE) cf_error("Table name expected");
- $$ = $1->def;
- }
+ expr limit_action { $$ = (struct channel_limit){ .limit = $1, $$.action = $2 }; }
+ | OFF { $$ = (struct channel_limit){}; }
;
CF_ADDTO(conf, debug_default)
@@ -284,9 +315,8 @@ iface_patt_node_init:
;
iface_patt_node_body:
- TEXT { this_ipn->pattern = $1; this_ipn->prefix = IPA_NONE; this_ipn->pxlen = 0; }
- | prefix_or_ipa { this_ipn->pattern = NULL; this_ipn->prefix = $1.addr; this_ipn->pxlen = $1.len; }
- | TEXT prefix_or_ipa { this_ipn->pattern = $1; this_ipn->prefix = $2.addr; this_ipn->pxlen = $2.len; }
+ TEXT { this_ipn->pattern = $1; /* this_ipn->prefix stays zero */ }
+ | opttext net_or_ipa { this_ipn->pattern = $1; this_ipn->prefix = $2; }
;
iface_negate:
@@ -336,6 +366,7 @@ dev_proto_start: proto_start DIRECT {
dev_proto:
dev_proto_start proto_name '{'
| dev_proto proto_item ';'
+ | dev_proto proto_channel ';'
| dev_proto dev_iface_patt ';'
| dev_proto CHECK LINK bool ';' { DIRECT_CFG->check_link = $4; }
;
@@ -487,26 +518,32 @@ CF_CLI(SHOW ROUTE, r_args, [[[<prefix>|for <prefix>|for <ip>] [table <t>] [filte
r_args:
/* empty */ {
$$ = cfg_allocz(sizeof(struct rt_show_data));
- $$->pxlen = 256;
+ init_list(&($$->tables));
$$->filter = FILTER_ACCEPT;
}
- | r_args prefix {
+ | r_args net_any {
$$ = $1;
- if ($$->pxlen != 256) cf_error("Only one prefix expected");
- $$->prefix = $2.addr;
- $$->pxlen = $2.len;
+ if ($$->addr) cf_error("Only one prefix expected");
+ $$->addr = $2;
}
- | r_args FOR prefix_or_ipa {
+ | r_args FOR r_args_for {
$$ = $1;
- if ($$->pxlen != 256) cf_error("Only one prefix expected");
- $$->prefix = $3.addr;
- $$->pxlen = $3.len;
+ if ($$->addr) cf_error("Only one prefix expected");
$$->show_for = 1;
+ $$->addr = $3;
}
| r_args TABLE SYM {
$$ = $1;
if ($3->class != SYM_TABLE) cf_error("%s is not a table", $3->name);
- $$->table = ((struct rtable_config *)$3->def)->table;
+ rt_show_add_table($$, ((struct rtable_config *)$3->def)->table);
+ $$->tables_defined_by = RSD_TDB_DIRECT;
+ }
+ | r_args TABLE ALL {
+ struct rtable_config *t;
+ $$ = $1;
+ WALK_LIST(t, config->tables)
+ rt_show_add_table($$, t->table);
+ $$->tables_defined_by = RSD_TDB_ALL;
}
| r_args FILTER filter {
$$ = $1;
@@ -533,11 +570,23 @@ r_args:
| r_args export_mode SYM {
struct proto_config *c = (struct proto_config *) $3->def;
$$ = $1;
- if ($$->export_mode) cf_error("Protocol specified twice");
+ if ($$->export_mode) cf_error("Export specified twice");
if ($3->class != SYM_PROTO || !c->proto) cf_error("%s is not a protocol", $3->name);
$$->export_mode = $2;
$$->export_protocol = c->proto;
$$->running_on_config = c->proto->cf->global;
+ $$->tables_defined_by = RSD_TDB_INDIRECT;
+ }
+ | r_args export_mode SYM '.' r_args_channel {
+ struct proto_config *c = (struct proto_config *) $3->def;
+ $$ = $1;
+ if ($$->export_mode) cf_error("Export specified twice");
+ if ($3->class != SYM_PROTO || !c->proto) cf_error("%s is not a protocol", $3->name);
+ $$->export_mode = $2;
+ $$->export_channel = proto_find_channel_by_name(c->proto, $5);
+ if (!$$->export_channel) cf_error("Export channel not found");
+ $$->running_on_config = c->proto->cf->global;
+ $$->tables_defined_by = RSD_TDB_INDIRECT;
}
| r_args PROTOCOL SYM {
struct proto_config *c = (struct proto_config *) $3->def;
@@ -546,6 +595,7 @@ r_args:
if ($3->class != SYM_PROTO || !c->proto) cf_error("%s is not a protocol", $3->name);
$$->show_protocol = c->proto;
$$->running_on_config = c->proto->cf->global;
+ $$->tables_defined_by = RSD_TDB_INDIRECT;
}
| r_args STATS {
$$ = $1;
@@ -557,52 +607,71 @@ r_args:
}
;
+r_args_for:
+ r_args_for_val {
+ $$ = cfg_alloc($1.length);
+ net_copy($$, &$1);
+ }
+ | net_vpn4_
+ | net_vpn6_
+ | VPN_RD IP4 {
+ $$ = cfg_alloc(sizeof(net_addr_vpn4));
+ net_fill_vpn4($$, $2, IP4_MAX_PREFIX_LENGTH, $1);
+ }
+ | VPN_RD IP6 {
+ $$ = cfg_alloc(sizeof(net_addr_vpn6));
+ net_fill_vpn6($$, $2, IP6_MAX_PREFIX_LENGTH, $1);
+ }
+ | SYM {
+ if ($1->class == (SYM_CONSTANT | T_IP))
+ {
+ $$ = cfg_alloc(ipa_is_ip4(SYM_VAL($1).ip) ? sizeof(net_addr_ip4) : sizeof(net_addr_ip6));
+ net_fill_ip_host($$, SYM_VAL($1).ip);
+ }
+ else if (($1->class == (SYM_CONSTANT | T_NET)) && net_type_match(SYM_VAL($1).net, NB_IP | NB_VPN))
+ $$ = SYM_VAL($1).net;
+ else
+ cf_error("IP address or network expected");
+ }
+ ;
+
+r_args_for_val:
+ net_ip4_
+ | net_ip6_
+ | IP4 { net_fill_ip4(&($$), $1, IP4_MAX_PREFIX_LENGTH); }
+ | IP6 { net_fill_ip6(&($$), $1, IP6_MAX_PREFIX_LENGTH); }
+
export_mode:
PREEXPORT { $$ = RSEM_PREEXPORT; }
| EXPORT { $$ = RSEM_EXPORT; }
| NOEXPORT { $$ = RSEM_NOEXPORT; }
;
-
-CF_CLI_HELP(SHOW ROA, ..., [[Show ROA table]])
-CF_CLI(SHOW ROA, roa_args, [<prefix> | in <prefix> | for <prefix>] [as <num>] [table <t>], [[Show ROA table]])
-{ roa_show($3); } ;
-
-roa_args:
- /* empty */ {
- $$ = cfg_allocz(sizeof(struct roa_show_data));
- $$->mode = ROA_SHOW_ALL;
- $$->table = roa_table_default;
- if (roa_table_default == NULL)
- cf_error("No ROA table defined");
- }
- | roa_args roa_mode prefix {
- $$ = $1;
- if ($$->mode != ROA_SHOW_ALL) cf_error("Only one prefix expected");
- $$->prefix = $3.addr;
- $$->pxlen = $3.len;
- $$->mode = $2;
- }
- | roa_args AS NUM {
- $$ = $1;
- $$->asn = $3;
- }
- | roa_args TABLE SYM {
- $$ = $1;
- if ($3->class != SYM_ROA) cf_error("%s is not a ROA table", $3->name);
- $$->table = ((struct roa_table_config *)$3->def)->table;
- }
+/* This is ugly hack */
+r_args_channel:
+ IPV4 { $$ = "ipv4"; }
+ | IPV4_MC { $$ = "ipv4-mc"; }
+ | IPV4_MPLS { $$ = "ipv4-mpls"; }
+ | IPV6 { $$ = "ipv6"; }
+ | IPV6_MC { $$ = "ipv6-mc"; }
+ | IPV6_MPLS { $$ = "ipv6-mpls"; }
+ | VPN4 { $$ = "vpn4"; }
+ | VPN4_MC { $$ = "vpn4-mc"; }
+ | VPN4_MPLS { $$ = "vpn4-mpls"; }
+ | VPN6 { $$ = "vpn6"; }
+ | VPN6_MC { $$ = "vpn6-mc"; }
+ | VPN6_MPLS { $$ = "vpn6-mpls"; }
+ | ROA4 { $$ = "roa4"; }
+ | ROA6 { $$ = "roa6"; }
+ | FLOW4 { $$ = "flow4"; }
+ | FLOW6 { $$ = "flow6"; }
+ | MPLS { $$ = "mpls"; }
+ | PRI { $$ = "pri"; }
+ | SEC { $$ = "sec"; }
;
-roa_mode:
- { $$ = ROA_SHOW_PX; }
- | IN { $$ = ROA_SHOW_IN; }
- | FOR { $$ = ROA_SHOW_FOR; }
- ;
-
-
CF_CLI_HELP(SHOW SYMBOLS, ..., [[Show all known symbolic names]])
-CF_CLI(SHOW SYMBOLS, sym_args, [table|filter|function|protocol|template|roa|<symbol>], [[Show all known symbolic names]])
+CF_CLI(SHOW SYMBOLS, sym_args, [table|filter|function|protocol|template|<symbol>], [[Show all known symbolic names]])
{ cmd_show_symbols($3); } ;
sym_args:
@@ -614,46 +683,10 @@ sym_args:
| sym_args FILTER { $$ = $1; $$->type = SYM_FILTER; }
| sym_args PROTOCOL { $$ = $1; $$->type = SYM_PROTO; }
| sym_args TEMPLATE { $$ = $1; $$->type = SYM_TEMPLATE; }
- | sym_args ROA { $$ = $1; $$->type = SYM_ROA; }
| sym_args SYM { $$ = $1; $$->sym = $2; }
;
-roa_table_arg:
- /* empty */ {
- if (roa_table_default == NULL)
- cf_error("No ROA table defined");
- $$ = roa_table_default;
- }
- | TABLE SYM {
- if ($2->class != SYM_ROA)
- cf_error("%s is not a ROA table", $2->name);
- $$ = ((struct roa_table_config *)$2->def)->table;
- }
- ;
-
-CF_CLI_HELP(ADD, roa ..., [[Add ROA record]])
-CF_CLI(ADD ROA, prefix MAX NUM AS NUM roa_table_arg, <prefix> max <num> as <num> [table <name>], [[Add ROA record]])
-{
- if (! cli_access_restricted())
- { roa_add_item($8, $3.addr, $3.len, $5, $7, ROA_SRC_DYNAMIC); cli_msg(0, ""); }
-};
-
-CF_CLI_HELP(DELETE, roa ..., [[Delete ROA record]])
-CF_CLI(DELETE ROA, prefix MAX NUM AS NUM roa_table_arg, <prefix> max <num> as <num> [table <name>], [[Delete ROA record]])
-{
- if (! cli_access_restricted())
- { roa_delete_item($8, $3.addr, $3.len, $5, $7, ROA_SRC_DYNAMIC); cli_msg(0, ""); }
-};
-
-CF_CLI_HELP(FLUSH, roa [table <name>], [[Removes all dynamic ROA records]])
-CF_CLI(FLUSH ROA, roa_table_arg, [table <name>], [[Removes all dynamic ROA records]])
-{
- if (! cli_access_restricted())
- { roa_flush($3, ROA_SRC_DYNAMIC); cli_msg(0, ""); }
-};
-
-
CF_CLI_HELP(DUMP, ..., [[Dump debugging information]])
CF_CLI(DUMP RESOURCES,,, [[Dump all allocated resource]])
{ rdump(&root_pool); cli_msg(0, ""); } ;