1998-11-27 19:37:57 +00:00
|
|
|
/*
|
|
|
|
* BIRD -- Core Configuration
|
|
|
|
*
|
1999-02-05 21:37:34 +00:00
|
|
|
* (c) 1998--1999 Martin Mares <mj@ucw.cz>
|
1998-11-27 19:37:57 +00:00
|
|
|
*
|
|
|
|
* Can be freely distributed and used under the terms of the GNU GPL.
|
|
|
|
*/
|
|
|
|
|
|
|
|
CF_HDR
|
|
|
|
|
1999-02-05 21:37:34 +00:00
|
|
|
static struct proto_config *this_proto;
|
1999-08-03 19:30:49 +00:00
|
|
|
static struct iface_patt *this_ipatt;
|
1998-11-27 21:09:57 +00:00
|
|
|
|
1998-11-29 22:03:58 +00:00
|
|
|
#include "nest/rt-dev.h"
|
1999-05-26 14:24:57 +00:00
|
|
|
#include "nest/password.h"
|
1998-11-29 22:03:58 +00:00
|
|
|
|
1998-11-27 19:37:57 +00:00
|
|
|
CF_DECLS
|
|
|
|
|
1999-03-26 21:44:38 +00:00
|
|
|
CF_KEYWORDS(ROUTER, ID, PROTOCOL, PREFERENCE, DISABLED, DEBUG, ALL, OFF, DIRECT)
|
1999-05-17 20:14:52 +00:00
|
|
|
CF_KEYWORDS(INTERFACE, IMPORT, EXPORT, FILTER, NONE, TABLE)
|
1999-05-31 17:12:00 +00:00
|
|
|
CF_KEYWORDS(PASSWORD, FROM, PASSIVE, TO, ID)
|
1998-11-27 19:37:57 +00:00
|
|
|
|
1999-11-15 11:36:22 +00:00
|
|
|
CF_ENUM(T_ENUM_RTS, RTS_, DUMMY, STATIC, INHERIT, DEVICE, STATIC_DEVICE, REDIRECT,
|
|
|
|
RIP, RIP_EXT, OSPF, OSPF_EXT, OSPF_IA, OSPF_BOUNDARY, BGP, PIPE)
|
|
|
|
|
1999-08-03 19:36:06 +00:00
|
|
|
%type <i32> idval
|
1999-04-05 20:15:31 +00:00
|
|
|
%type <f> imexport
|
1999-05-17 20:14:52 +00:00
|
|
|
%type <r> rtable
|
1999-05-26 14:24:57 +00:00
|
|
|
%type <p> password_list password_begin
|
1999-11-25 15:35:30 +00:00
|
|
|
%type <s> optsym
|
1999-12-01 15:10:21 +00:00
|
|
|
%type <ra> r_args
|
1998-11-27 19:37:57 +00:00
|
|
|
|
|
|
|
CF_GRAMMAR
|
|
|
|
|
1998-11-27 21:09:57 +00:00
|
|
|
/* Setting of router ID */
|
|
|
|
|
1998-11-27 19:37:57 +00:00
|
|
|
CF_ADDTO(conf, rtrid)
|
1999-05-17 20:14:52 +00:00
|
|
|
|
1999-03-29 19:04:14 +00:00
|
|
|
rtrid: ROUTER ID idval ';' {
|
1999-02-05 21:37:34 +00:00
|
|
|
new_config->router_id = $3;
|
1998-11-27 21:09:57 +00:00
|
|
|
}
|
1998-11-27 19:37:57 +00:00
|
|
|
;
|
|
|
|
|
|
|
|
idval:
|
1999-08-03 19:36:06 +00:00
|
|
|
NUM { $$ = $1; }
|
|
|
|
| RTRID
|
|
|
|
| IPA {
|
|
|
|
#ifndef IPV6
|
|
|
|
$$ = ipa_to_u32($1);
|
|
|
|
#else
|
|
|
|
cf_error("Router IDs must be entered as hexadecimal numbers in IPv6 version");
|
|
|
|
#endif
|
|
|
|
}
|
1998-11-27 19:37:57 +00:00
|
|
|
;
|
|
|
|
|
1999-05-17 20:14:52 +00:00
|
|
|
/* Creation of routing tables */
|
|
|
|
|
|
|
|
CF_ADDTO(conf, newtab)
|
|
|
|
|
|
|
|
newtab: TABLE SYM {
|
|
|
|
struct rtable_config *c = cfg_allocz(sizeof(struct rtable_config));
|
|
|
|
struct symbol *s = $2;
|
|
|
|
cf_define_symbol(s, SYM_TABLE, c);
|
|
|
|
c->name = s->name;
|
|
|
|
add_tail(&new_config->tables, &c->n);
|
|
|
|
}
|
|
|
|
;
|
|
|
|
|
1998-11-27 21:09:57 +00:00
|
|
|
/* Definition of protocols */
|
|
|
|
|
|
|
|
CF_ADDTO(conf, proto)
|
|
|
|
|
|
|
|
proto_start: PROTOCOL
|
|
|
|
|
|
|
|
proto_name:
|
|
|
|
/* EMPTY */ {
|
1999-11-30 14:02:27 +00:00
|
|
|
struct symbol *s = cf_default_name(this_proto->protocol->name, &this_proto->protocol->name_counter);
|
1998-11-27 21:09:57 +00:00
|
|
|
s->class = SYM_PROTO;
|
|
|
|
s->def = this_proto;
|
|
|
|
this_proto->name = s->name;
|
|
|
|
}
|
|
|
|
| SYM {
|
1999-05-17 20:14:52 +00:00
|
|
|
cf_define_symbol($1, SYM_PROTO, this_proto);
|
1998-11-27 21:09:57 +00:00
|
|
|
this_proto->name = $1->name;
|
|
|
|
}
|
|
|
|
;
|
|
|
|
|
|
|
|
proto_item:
|
|
|
|
/* EMPTY */
|
1998-11-27 21:32:45 +00:00
|
|
|
| PREFERENCE expr {
|
1998-11-27 21:09:57 +00:00
|
|
|
if ($2 < 0 || $2 > 255) cf_error("Invalid preference");
|
|
|
|
this_proto->preference = $2;
|
|
|
|
}
|
1998-11-29 14:40:39 +00:00
|
|
|
| DISABLED { this_proto->disabled = 1; }
|
|
|
|
| DEBUG expr { this_proto->debug = $2; }
|
|
|
|
| DEBUG ALL { this_proto->debug = ~0; }
|
|
|
|
| DEBUG OFF { this_proto->debug = 0; }
|
1999-04-05 20:15:31 +00:00
|
|
|
| IMPORT imexport { this_proto->in_filter = $2; }
|
|
|
|
| EXPORT imexport { this_proto->out_filter = $2; }
|
1999-05-17 20:14:52 +00:00
|
|
|
| TABLE rtable { this_proto->table = $2; }
|
1999-04-05 20:15:31 +00:00
|
|
|
;
|
|
|
|
|
|
|
|
imexport:
|
|
|
|
FILTER filter { $$ = $2; }
|
|
|
|
| ALL { $$ = FILTER_ACCEPT; }
|
|
|
|
| NONE { $$ = FILTER_REJECT; }
|
1998-11-27 21:09:57 +00:00
|
|
|
;
|
|
|
|
|
1999-05-17 20:14:52 +00:00
|
|
|
rtable:
|
|
|
|
SYM {
|
|
|
|
if ($1->class != SYM_TABLE) cf_error("Table name expected");
|
|
|
|
$$ = $1->def;
|
|
|
|
}
|
|
|
|
;
|
|
|
|
|
1999-08-03 19:30:49 +00:00
|
|
|
/* Interface patterns */
|
|
|
|
|
|
|
|
iface_patt:
|
|
|
|
TEXT { this_ipatt->pattern = $1; this_ipatt->prefix = IPA_NONE; this_ipatt->pxlen = 0; }
|
|
|
|
| IPA pxlen { this_ipatt->pattern = NULL; this_ipatt->prefix = $1; this_ipatt->pxlen = $2; }
|
|
|
|
| TEXT IPA pxlen { this_ipatt->pattern = $1; this_ipatt->prefix = $2; this_ipatt->pxlen = $3; }
|
|
|
|
;
|
|
|
|
|
1999-03-26 21:44:38 +00:00
|
|
|
/* Direct device route protocol */
|
1998-11-29 22:03:58 +00:00
|
|
|
|
|
|
|
CF_ADDTO(proto, dev_proto '}')
|
|
|
|
|
1999-03-26 21:44:38 +00:00
|
|
|
dev_proto_start: proto_start DIRECT {
|
|
|
|
struct rt_dev_config *p = proto_config_new(&proto_device, sizeof(struct rt_dev_config));
|
|
|
|
this_proto = &p->c;
|
|
|
|
p->c.preference = DEF_PREF_DIRECT;
|
|
|
|
init_list(&p->iface_list);
|
1998-11-29 22:03:58 +00:00
|
|
|
}
|
|
|
|
;
|
|
|
|
|
|
|
|
dev_proto:
|
1999-03-26 21:44:38 +00:00
|
|
|
dev_proto_start proto_name '{'
|
1998-11-29 22:03:58 +00:00
|
|
|
| dev_proto proto_item ';'
|
|
|
|
| dev_proto dev_iface_list ';'
|
|
|
|
;
|
|
|
|
|
1999-08-03 19:30:49 +00:00
|
|
|
dev_iface_entry_init:
|
|
|
|
/* EMPTY */ {
|
|
|
|
struct rt_dev_config *p = (void *) this_proto;
|
|
|
|
struct iface_patt *k = cfg_allocz(sizeof(struct iface_patt));
|
|
|
|
add_tail(&p->iface_list, &k->n);
|
|
|
|
this_ipatt = k;
|
1998-11-29 22:03:58 +00:00
|
|
|
}
|
|
|
|
;
|
|
|
|
|
1999-08-03 19:30:49 +00:00
|
|
|
dev_iface_entry:
|
|
|
|
dev_iface_entry_init iface_patt
|
|
|
|
;
|
|
|
|
|
|
|
|
dev_iface_list:
|
|
|
|
INTERFACE dev_iface_entry
|
|
|
|
| dev_iface_list ',' dev_iface_entry
|
|
|
|
;
|
|
|
|
|
|
|
|
/* Password lists */
|
|
|
|
|
1999-05-26 14:24:57 +00:00
|
|
|
password_begin:
|
|
|
|
PASSWORD TEXT {
|
|
|
|
last_password_item = cfg_alloc(sizeof (struct password_item));
|
|
|
|
last_password_item->password = $2;
|
|
|
|
last_password_item->from = 0;
|
1999-11-30 14:02:27 +00:00
|
|
|
last_password_item->to = TIME_INFINITY;
|
1999-05-26 14:24:57 +00:00
|
|
|
last_password_item->id = 0;
|
|
|
|
last_password_item->next = NULL;
|
|
|
|
$$=last_password_item;
|
|
|
|
}
|
|
|
|
;
|
|
|
|
|
|
|
|
password_items:
|
|
|
|
/* empty */ { }
|
1999-05-26 14:37:07 +00:00
|
|
|
| FROM datetime password_items { last_password_item->from = $2; }
|
|
|
|
| TO datetime password_items { last_password_item->to = $2; }
|
1999-05-31 17:12:00 +00:00
|
|
|
| PASSIVE datetime password_items { last_password_item->passive = $2; }
|
1999-05-26 14:37:07 +00:00
|
|
|
| ID NUM password_items { last_password_item->id = $2; }
|
1999-05-26 14:24:57 +00:00
|
|
|
;
|
|
|
|
|
|
|
|
password_list:
|
|
|
|
/* empty */ { $$ = NULL; }
|
1999-05-26 14:37:07 +00:00
|
|
|
| password_begin password_items ';' password_list {
|
1999-10-02 10:44:48 +00:00
|
|
|
$1->next = $4;
|
|
|
|
$$ = $1;
|
1999-05-26 14:24:57 +00:00
|
|
|
}
|
|
|
|
;
|
|
|
|
|
Parse CLI commands. We use the same parser as for configuration files (because
we want to allow filter and similar complex constructs to be used in commands
and we should avoid code duplication), only with CLI_MARKER token prepended
before the whole input.
Defined macro CF_CLI(cmd, args, help) for defining CLI commands in .Y files.
The first argument specifies the command itself, the remaining two arguments
are copied to the help file (er, will be copied after the help file starts
to exist). This macro automatically creates a skeleton rule for the command,
you only need to append arguments as in:
CF_CLI(STEAL MONEY, <$>, [[Steal <$> US dollars or equivalent in any other currency]]): NUM {
cli_msg(0, "%d$ stolen", $3);
} ;
Also don't forget to reset lexer state between inputs.
1999-10-31 17:47:47 +00:00
|
|
|
/* Core commands */
|
|
|
|
|
1999-11-25 15:35:30 +00:00
|
|
|
CF_CLI_HELP(SHOW,,[[Show status information]])
|
|
|
|
|
|
|
|
CF_CLI(SHOW STATUS,,, [[Show router status]]) {
|
1999-11-30 12:57:14 +00:00
|
|
|
cli_msg(1000, "BIRD " BIRD_VERSION);
|
1999-11-25 15:35:30 +00:00
|
|
|
/* FIXME: Should include uptime, shutdown flag et cetera */
|
|
|
|
} ;
|
|
|
|
|
|
|
|
CF_CLI(SHOW PROTOCOLS, optsym, [<name>], [[Show routing protocols]])
|
1999-11-30 12:57:14 +00:00
|
|
|
{ proto_show($3, 0); } ;
|
|
|
|
|
|
|
|
CF_CLI(SHOW PROTOCOLS VERBOSE, optsym, [<name>], [[Show routing protocol details]])
|
|
|
|
{ proto_show($4, 1); } ;
|
1999-11-25 15:35:30 +00:00
|
|
|
|
1999-12-01 15:10:21 +00:00
|
|
|
optsym:
|
|
|
|
SYM
|
|
|
|
| /* empty */ { $$ = NULL; }
|
|
|
|
;
|
|
|
|
|
1999-11-25 15:35:30 +00:00
|
|
|
CF_CLI(SHOW INTERFACES,,, [[Show network interfaces]])
|
|
|
|
{ if_show(); } ;
|
|
|
|
|
|
|
|
CF_CLI(SHOW INTERFACES SUMMARY,,, [[Show summary of network interfaces]])
|
|
|
|
{ if_show_summary(); } ;
|
|
|
|
|
1999-12-01 15:10:21 +00:00
|
|
|
CF_CLI(SHOW ROUTE, r_args, [<prefix>] [table <t>] [filter <f>] [all], [[Show routing table]])
|
|
|
|
{ rt_show($3); } ;
|
|
|
|
|
|
|
|
r_args:
|
|
|
|
/* empty */ {
|
|
|
|
$$ = cfg_allocz(sizeof(struct rt_show_data));
|
|
|
|
$$->pxlen = 256;
|
|
|
|
$$->filter = FILTER_ACCEPT;
|
|
|
|
$$->table = config->master_rtc->table;
|
|
|
|
}
|
|
|
|
| r_args IPA pxlen {
|
|
|
|
$$ = $1;
|
|
|
|
if ($$->pxlen != 256) cf_error("Only one prefix expected");
|
|
|
|
if (!ip_is_prefix($2, $3)) cf_error("Invalid prefix");
|
|
|
|
$$->prefix = $2;
|
|
|
|
$$->pxlen = $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;
|
|
|
|
}
|
|
|
|
| r_args FILTER filter {
|
|
|
|
$$ = $1;
|
|
|
|
$$->filter = $3;
|
|
|
|
}
|
|
|
|
| r_args ALL {
|
|
|
|
$$ = $1;
|
|
|
|
$$->verbose = 1;
|
|
|
|
}
|
|
|
|
;
|
|
|
|
|
Added some temporary examples of how to define CLI commands (search for CF_CLI).
To define a new command, just add a new rule to the gramar:
CF_CLI(COMMAND NAME, arguments, help-args, help-text) {
what-should-the-command-do
} ;
where <arguments> are appended to the RHS of the rule, <help-args> is the
argument list as shown in the help and <help-text> is description of the
command for the help.
<what-should-the-command-do> is a C code snippet to be executed. It should
not take too much time to execute. If you want to print out a lot of
information, you can schedule a routine to be called after the current
buffer is flushed by making cli->cont point to the routine (see the
TEST LONG command definition for an example); if the connection is closed
in the meantime, cli->cleanup gets called.
You can access `struct cli' belonging to the connection you're currently
servicing as this_cli, but only during parse time, not from routines scheduled
for deferred execution.
Functions to call inside command handlers:
cli_printf(cli, code, printf-args) -- print text to CLI connection,
<code> is message code as assigned in doc/reply_codes or a negative
one if it's a continuation line.
cli_msg(code, printf-args) -- the same for this_cli.
Use 'sock -x bird.ctl' for connecting to the CLI until a client is written.
1999-11-17 12:14:44 +00:00
|
|
|
/* FIXME: These are examples. Remove them soon. */
|
|
|
|
CF_CLI_HELP(TEST, <subsystem>, [[Tests different subsystems]])
|
1999-11-25 15:35:30 +00:00
|
|
|
CF_CLI(TEST LEDS, NUM, <N>, [[Flash each LED <N> times]]) { cli_msg(0, "%d", $3); } ;
|
Added some temporary examples of how to define CLI commands (search for CF_CLI).
To define a new command, just add a new rule to the gramar:
CF_CLI(COMMAND NAME, arguments, help-args, help-text) {
what-should-the-command-do
} ;
where <arguments> are appended to the RHS of the rule, <help-args> is the
argument list as shown in the help and <help-text> is description of the
command for the help.
<what-should-the-command-do> is a C code snippet to be executed. It should
not take too much time to execute. If you want to print out a lot of
information, you can schedule a routine to be called after the current
buffer is flushed by making cli->cont point to the routine (see the
TEST LONG command definition for an example); if the connection is closed
in the meantime, cli->cleanup gets called.
You can access `struct cli' belonging to the connection you're currently
servicing as this_cli, but only during parse time, not from routines scheduled
for deferred execution.
Functions to call inside command handlers:
cli_printf(cli, code, printf-args) -- print text to CLI connection,
<code> is message code as assigned in doc/reply_codes or a negative
one if it's a continuation line.
cli_msg(code, printf-args) -- the same for this_cli.
Use 'sock -x bird.ctl' for connecting to the CLI until a client is written.
1999-11-17 12:14:44 +00:00
|
|
|
CF_CLI(TEST MEMORY,,, [[Replace all useful information by testing patterns]]) { cli_msg(0, "DONE"); } ;
|
|
|
|
CF_CLI(TEST LONG,,, [[Test long replies]]) {
|
|
|
|
static void test_command(struct cli *);
|
|
|
|
this_cli->cont = test_command;
|
|
|
|
this_cli->rover = (void *) 1;
|
|
|
|
cli_msg(-2, "Start");
|
|
|
|
} ;
|
Parse CLI commands. We use the same parser as for configuration files (because
we want to allow filter and similar complex constructs to be used in commands
and we should avoid code duplication), only with CLI_MARKER token prepended
before the whole input.
Defined macro CF_CLI(cmd, args, help) for defining CLI commands in .Y files.
The first argument specifies the command itself, the remaining two arguments
are copied to the help file (er, will be copied after the help file starts
to exist). This macro automatically creates a skeleton rule for the command,
you only need to append arguments as in:
CF_CLI(STEAL MONEY, <$>, [[Steal <$> US dollars or equivalent in any other currency]]): NUM {
cli_msg(0, "%d$ stolen", $3);
} ;
Also don't forget to reset lexer state between inputs.
1999-10-31 17:47:47 +00:00
|
|
|
|
1998-11-27 19:37:57 +00:00
|
|
|
CF_CODE
|
|
|
|
|
1999-11-25 15:35:30 +00:00
|
|
|
/* FIXME: Test only, remove */
|
Added some temporary examples of how to define CLI commands (search for CF_CLI).
To define a new command, just add a new rule to the gramar:
CF_CLI(COMMAND NAME, arguments, help-args, help-text) {
what-should-the-command-do
} ;
where <arguments> are appended to the RHS of the rule, <help-args> is the
argument list as shown in the help and <help-text> is description of the
command for the help.
<what-should-the-command-do> is a C code snippet to be executed. It should
not take too much time to execute. If you want to print out a lot of
information, you can schedule a routine to be called after the current
buffer is flushed by making cli->cont point to the routine (see the
TEST LONG command definition for an example); if the connection is closed
in the meantime, cli->cleanup gets called.
You can access `struct cli' belonging to the connection you're currently
servicing as this_cli, but only during parse time, not from routines scheduled
for deferred execution.
Functions to call inside command handlers:
cli_printf(cli, code, printf-args) -- print text to CLI connection,
<code> is message code as assigned in doc/reply_codes or a negative
one if it's a continuation line.
cli_msg(code, printf-args) -- the same for this_cli.
Use 'sock -x bird.ctl' for connecting to the CLI until a client is written.
1999-11-17 12:14:44 +00:00
|
|
|
static void test_command(struct cli *c)
|
|
|
|
{
|
|
|
|
int i = (int) c->rover;
|
|
|
|
if (i < 10) {
|
|
|
|
cli_printf(c, -3, "%d", i);
|
|
|
|
c->rover = (void *) ++i;
|
|
|
|
} else {
|
|
|
|
c->cont = NULL;
|
|
|
|
cli_printf(c, 4, "DONE");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1998-11-27 19:37:57 +00:00
|
|
|
CF_END
|