summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Mares <mj@ucw.cz>1999-12-01 15:10:21 +0000
committerMartin Mares <mj@ucw.cz>1999-12-01 15:10:21 +0000
commit730f2e2c8c29b3461caa096fa514cbf71f84e51b (patch)
tree0a01f3aeb128be3746f67ee9c9adc1c8c62013d7
parent04a60c689aeb10fafa9919bcff5f8391e0f3a158 (diff)
Added dumping of routing tables (`show route'). This includes filtering.
-rw-r--r--TODO4
-rw-r--r--conf/confbase.Y1
-rw-r--r--doc/reply_codes3
-rw-r--r--nest/config.Y43
-rw-r--r--nest/route.h14
-rw-r--r--nest/rt-attr.c16
-rw-r--r--nest/rt-table.c124
7 files changed, 194 insertions, 11 deletions
diff --git a/TODO b/TODO
index d82bf811..a1c7dc3c 100644
--- a/TODO
+++ b/TODO
@@ -48,12 +48,10 @@ shutdown # order system shutdown
configure [<file>]
debug <what> # dump debugging information to log
show <name> # show everything you know about symbol <name>
- route [<route>] [table <name>] [filter (<name> | { <inline> })] [where <condition>] [all]
- status # router id, version etc.
+ route [<route>] [table <name>] [filter (<name> | { <inline> })] [where <condition>] [all] <-- WHERE
rip ??? [<name>]
ospf ??? [<name>]
static ??? [<name>]
- neighbors # ???
filters [<name>]
(disable|enable|restart) <protocol> # or ALL?
diff --git a/conf/confbase.Y b/conf/confbase.Y
index 02a86e94..2a76decc 100644
--- a/conf/confbase.Y
+++ b/conf/confbase.Y
@@ -33,6 +33,7 @@ CF_DECLS
struct f_tree *e;
struct f_val v;
struct password_item *p;
+ struct rt_show_data *ra;
}
%token END CLI_MARKER
diff --git a/doc/reply_codes b/doc/reply_codes
index 3bafd745..abc2e6f6 100644
--- a/doc/reply_codes
+++ b/doc/reply_codes
@@ -18,8 +18,11 @@ Reply codes of BIRD command-line interface
1004 Interface flags
1005 Interface summary
1006 Protocol details
+1007 Route list
+1008 Route details
8000 Reply too long
+8001 Route not found
9000 Command too long
9001 Parse error
diff --git a/nest/config.Y b/nest/config.Y
index b807085a..89177a7a 100644
--- a/nest/config.Y
+++ b/nest/config.Y
@@ -28,6 +28,7 @@ CF_ENUM(T_ENUM_RTS, RTS_, DUMMY, STATIC, INHERIT, DEVICE, STATIC_DEVICE, REDIREC
%type <r> rtable
%type <p> password_list password_begin
%type <s> optsym
+%type <ra> r_args
CF_GRAMMAR
@@ -201,12 +202,49 @@ CF_CLI(SHOW PROTOCOLS, optsym, [<name>], [[Show routing protocols]])
CF_CLI(SHOW PROTOCOLS VERBOSE, optsym, [<name>], [[Show routing protocol details]])
{ proto_show($4, 1); } ;
+optsym:
+ SYM
+ | /* empty */ { $$ = NULL; }
+ ;
+
CF_CLI(SHOW INTERFACES,,, [[Show network interfaces]])
{ if_show(); } ;
CF_CLI(SHOW INTERFACES SUMMARY,,, [[Show summary of network interfaces]])
{ if_show_summary(); } ;
+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;
+ }
+ ;
+
/* FIXME: These are examples. Remove them soon. */
CF_CLI_HELP(TEST, <subsystem>, [[Tests different subsystems]])
CF_CLI(TEST LEDS, NUM, <N>, [[Flash each LED <N> times]]) { cli_msg(0, "%d", $3); } ;
@@ -218,11 +256,6 @@ CF_CLI(TEST LONG,,, [[Test long replies]]) {
cli_msg(-2, "Start");
} ;
-optsym:
- SYM
- | /* empty */ { $$ = NULL; }
- ;
-
CF_CODE
/* FIXME: Test only, remove */
diff --git a/nest/route.h b/nest/route.h
index c2b21d13..41d188da 100644
--- a/nest/route.h
+++ b/nest/route.h
@@ -15,6 +15,9 @@
struct protocol;
struct proto;
+struct symbol;
+struct filter;
+struct cli;
/*
* Generic data structure for storing network prefixes. Also used
@@ -186,6 +189,16 @@ void rt_feed_baby(struct proto *p);
void rt_prune(rtable *tab);
void rt_prune_all(void);
+struct rt_show_data {
+ ip_addr prefix;
+ unsigned pxlen;
+ rtable *table;
+ struct filter *filter;
+ int verbose;
+ struct fib_iterator fit;
+};
+void rt_show(struct rt_show_data *);
+
/*
* Route Attributes
*
@@ -311,6 +324,7 @@ static inline void rta_free(rta *r) { if (r && !--r->uc) rta__free(r); }
void rta_dump(rta *);
void rta_dump_all(void);
static inline eattr * rta_find(rta *a, unsigned ea) { return ea_find(a->eattrs, ea); }
+void rta_show(struct cli *, rta *);
/*
* Default protocol preferences
diff --git a/nest/rt-attr.c b/nest/rt-attr.c
index 2c50f4d2..04dcf516 100644
--- a/nest/rt-attr.c
+++ b/nest/rt-attr.c
@@ -13,6 +13,7 @@
#include "nest/route.h"
#include "nest/protocol.h"
#include "nest/iface.h"
+#include "nest/cli.h"
#include "lib/resource.h"
/*
@@ -347,12 +348,11 @@ rta_dump(rta *a)
"RTS_STAT_DEV", "RTS_REDIR", "RTS_RIP", "RTS_RIP_EXT",
"RTS_OSPF", "RTS_OSPF_EXT", "RTS_OSPF_IA",
"RTS_OSPF_BOUNDARY", "RTS_BGP" };
- static char *sco[] = { "HOST", "LINK", "SITE", "UNIV" };
static char *rtc[] = { "", " BC", " MC", " AC" };
static char *rtd[] = { "", " DEV", " HOLE", " UNREACH", " PROHIBIT" };
debug("p=%s uc=%d %s %s%s%s",
- a->proto->name, a->uc, rts[a->source], sco[a->scope], rtc[a->cast],
+ a->proto->name, a->uc, rts[a->source], ip_scope_text(a->scope), rtc[a->cast],
rtd[a->dest]);
if (a->flags & RTF_EXTERIOR)
debug(" EXT");
@@ -388,6 +388,18 @@ rta_dump_all(void)
}
void
+rta_show(struct cli *c, rta *a)
+{
+ static char *src_names[] = { "dummy", "static", "inherit", "device", "static-device", "redirect",
+ "RIP", "RIP-ext", "OSPF", "OSPF-ext", "OSPF-IA", "OSPF-boundary",
+ "BGP" };
+ static char *cast_names[] = { "unicast", "broadcast", "multicast", "anycast" };
+
+ cli_printf(c, -1008, "\tType: %s %s %s", src_names[a->source], cast_names[a->cast], ip_scope_text(a->scope));
+ /* FIXME: Here we probably should print the dynamic attributes... */
+}
+
+void
rta_init(void)
{
rta_pool = rp_new(&root_pool, "Attributes");
diff --git a/nest/rt-table.c b/nest/rt-table.c
index 353473d1..edbf154d 100644
--- a/nest/rt-table.c
+++ b/nest/rt-table.c
@@ -1,7 +1,7 @@
/*
* BIRD -- Routing Table
*
- * (c) 1998 Martin Mares <mj@ucw.cz>
+ * (c) 1998--1999 Martin Mares <mj@ucw.cz>
*
* Can be freely distributed and used under the terms of the GNU GPL.
*/
@@ -13,8 +13,11 @@
#include "nest/bird.h"
#include "nest/route.h"
#include "nest/protocol.h"
+#include "nest/cli.h"
+#include "nest/iface.h"
#include "lib/resource.h"
#include "lib/event.h"
+#include "lib/string.h"
#include "conf/conf.h"
#include "filter/filter.h"
@@ -489,3 +492,122 @@ rt_commit(struct config *c)
r->table = t;
}
}
+
+/*
+ * CLI commands
+ */
+
+static void
+rt_show_rte(struct cli *c, byte *ia, rte *e, struct rt_show_data *d)
+{
+ byte via[STD_ADDRESS_P_LENGTH+32], from[STD_ADDRESS_P_LENGTH];
+ byte tm[TM_RELTIME_BUFFER_SIZE], info[256];
+ rta *a = e->attrs;
+
+ switch (a->dest)
+ {
+ case RTD_ROUTER: bsprintf(via, "via %I on %s", a->gw, a->iface->name); break;
+ case RTD_DEVICE: bsprintf(via, "dev %s", a->iface->name); break;
+ case RTD_BLACKHOLE: bsprintf(via, "blackhole"); break;
+ case RTD_UNREACHABLE: bsprintf(via, "unreachable"); break;
+ case RTD_PROHIBIT: bsprintf(via, "prohibited"); break;
+ default: bsprintf(via, "???");
+ }
+ tm_format_reltime(tm, e->lastmod);
+ if (ipa_nonzero(a->from) && !ipa_equal(a->from, a->gw))
+ bsprintf(from, " from %I", a->from);
+ else
+ from[0] = 0;
+ if (a->proto->proto->get_route_info)
+ a->proto->proto->get_route_info(e, info);
+ else
+ bsprintf(info, " (%d)", e->pref);
+ cli_printf(c, -1007, "%-18s %s [%s %s%s]%s", ia, via, a->proto->name, tm, from, info);
+ if (d->verbose)
+ {
+ rta_show(c, a);
+ if (a->proto->proto->show_route_data)
+ a->proto->proto->show_route_data(e);
+ }
+}
+
+static void
+rt_show_net(struct cli *c, net *n, struct rt_show_data *d)
+{
+ rte *e, *ee;
+ byte ia[STD_ADDRESS_P_LENGTH+8];
+
+ bsprintf(ia, "%I/%d", n->n.prefix, n->n.pxlen);
+ for(e=n->routes; e; e=e->next)
+ {
+ struct ea_list *tmpa = NULL;
+ ee = e;
+ rte_update_lock(); /* We use the update buffer for filtering */
+ if (d->filter == FILTER_ACCEPT || f_run(d->filter, &ee, &tmpa, rte_update_pool) <= F_MODIFY)
+ {
+ rt_show_rte(c, ia, e, d);
+ ia[0] = 0;
+ }
+ if (e != ee)
+ rte_free(ee);
+ rte_update_unlock();
+ }
+}
+
+static void
+rt_show_cont(struct cli *c)
+{
+ struct rt_show_data *d = c->rover;
+ unsigned max = 1; /* FIXME: After some debugging, increase to reasonable amount */
+ struct fib *fib = &d->table->fib;
+ struct fib_iterator *it = &d->fit;
+
+ FIB_ITERATE_START(fib, it, f)
+ {
+ net *n = (net *) f;
+ if (!max--)
+ {
+ FIB_ITERATE_PUT(it, f);
+ return;
+ }
+ rt_show_net(c, n, d);
+ }
+ FIB_ITERATE_END(f);
+ cli_printf(c, 0, "");
+ c->cont = c->cleanup = NULL;
+}
+
+static void
+rt_show_cleanup(struct cli *c)
+{
+ struct rt_show_data *d = c->rover;
+
+ /* Unlink the iterator */
+ fit_get(&d->table->fib, &d->fit);
+}
+
+void
+rt_show(struct rt_show_data *d)
+{
+ struct rtable_config *tc;
+ net *n;
+
+ if (d->pxlen == 256)
+ {
+ FIB_ITERATE_INIT(&d->fit, &d->table->fib);
+ this_cli->cont = rt_show_cont;
+ this_cli->cleanup = rt_show_cleanup;
+ this_cli->rover = d;
+ }
+ else
+ {
+ n = fib_find(&d->table->fib, &d->prefix, d->pxlen);
+ if (n)
+ {
+ rt_show_net(this_cli, n, d);
+ cli_msg(0, "");
+ }
+ else
+ cli_msg(8001, "Network not in table");
+ }
+}