diff --git a/nest/config.Y b/nest/config.Y index 7ead8589..310fce25 100644 --- a/nest/config.Y +++ b/nest/config.Y @@ -117,7 +117,7 @@ CF_KEYWORDS(IPV4, IPV6, VPN4, VPN6, ROA4, ROA6, FLOW4, FLOW6, SADR, MPLS) CF_KEYWORDS(RECEIVE, LIMIT, ACTION, WARN, BLOCK, RESTART, DISABLE, KEEP, FILTERED, RPKI) CF_KEYWORDS(PASSWORD, KEY, FROM, PASSIVE, TO, ID, EVENTS, PACKETS, PROTOCOLS, CHANNELS, INTERFACES) CF_KEYWORDS(ALGORITHM, KEYED, HMAC, MD5, SHA1, SHA256, SHA384, SHA512, BLAKE2S128, BLAKE2S256, BLAKE2B256, BLAKE2B512) -CF_KEYWORDS(PRIMARY, STATS, COUNT, BY, FOR, COMMANDS, PREEXPORT, NOEXPORT, EXPORTED, GENERATE) +CF_KEYWORDS(PRIMARY, STATS, COUNT, BY, FOR, IN, COMMANDS, PREEXPORT, NOEXPORT, EXPORTED, GENERATE) CF_KEYWORDS(BGP, PASSWORDS, DESCRIPTION, SORTED) CF_KEYWORDS(RELOAD, IN, OUT, MRTDUMP, MESSAGES, RESTRICT, MEMORY, IGP_METRIC, CLASS, DSCP) CF_KEYWORDS(TIMEFORMAT, ISO, SHORT, LONG, ROUTE, PROTOCOL, BASE, LOG, S, MS, US) @@ -621,14 +621,22 @@ r_args: $$ = $1; if ($$->addr) cf_error("Only one prefix expected"); $$->addr = $2; + $$->addr_mode = RSD_ADDR_EQUAL; } | r_args FOR r_args_for { $$ = $1; if ($$->addr) cf_error("Only one prefix expected"); - $$->show_for = 1; $$->addr = $3; + $$->addr_mode = RSD_ADDR_FOR; } - | r_args TABLE CF_SYM_KNOWN { + | r_args IN net_any { + $$ = $1; + if ($$->addr) cf_error("Only one prefix expected"); + if (!net_type_match($3, NB_IP)) cf_error("Only IP networks accepted for 'in' argument"); + $$->addr = $3; + $$->addr_mode = RSD_ADDR_IN; + } +| r_args TABLE CF_SYM_KNOWN { cf_assert_symbol($3, SYM_TABLE); $$ = $1; rt_show_add_table($$, $3->table->table); diff --git a/nest/route.h b/nest/route.h index fa87e22c..ace4c7f7 100644 --- a/nest/route.h +++ b/nest/route.h @@ -384,7 +384,7 @@ struct rt_show_data { struct channel *export_channel; struct config *running_on_config; struct krt_proto *kernel; - int export_mode, primary_only, filtered, stats, show_for; + int export_mode, addr_mode, primary_only, filtered, stats; int table_open; /* Iteration (fit) is open */ int net_counter, rt_counter, show_counter, table_counter; @@ -403,6 +403,11 @@ struct rt_show_data_rtable * rt_show_add_table(struct rt_show_data *d, rtable *t #define RSD_TDB_SET 0x1 /* internal: show empty tables */ #define RSD_TDB_NMN 0x2 /* internal: need matching net */ +/* Value of addr_mode */ +#define RSD_ADDR_EQUAL 1 /* Exact query - show route */ +#define RSD_ADDR_FOR 2 /* Longest prefix match - show route for */ +#define RSD_ADDR_IN 3 /* Interval query - show route in */ + /* Value of export_mode in struct rt_show_data */ #define RSEM_NONE 0 /* Export mode not used */ #define RSEM_PREEXPORT 1 /* Routes ready for export, before filtering */ diff --git a/nest/rt-show.c b/nest/rt-show.c index 7691878d..b8c818f8 100644 --- a/nest/rt-show.c +++ b/nest/rt-show.c @@ -255,12 +255,17 @@ rt_show_cont(struct cli *c) FIB_ITERATE_START(fib, it, net, n) { + if ((d->addr_mode == RSD_ADDR_IN) && (!net_in_netX(n->n.addr, d->addr))) + goto next; + if (!max--) { FIB_ITERATE_PUT(it); return; } rt_show_net(c, n, d); + + next:; } FIB_ITERATE_END; @@ -402,7 +407,7 @@ rt_show(struct rt_show_data *d) rt_show_prepare_tables(d); - if (!d->addr) + if (!d->addr || (d->addr_mode == RSD_ADDR_IN)) { WALK_LIST(tab, d->tables) rt_lock_table(tab->table); @@ -420,7 +425,7 @@ rt_show(struct rt_show_data *d) d->tab = tab; d->kernel = rt_show_get_kernel(d); - if (d->show_for) + if (d->addr_mode == RSD_ADDR_FOR) n = net_route(tab->table, d->addr); else n = net_find(tab->table, d->addr);