Download raw body.
bgpd: fix for bgpctl show rib out <IP>
On Wed, May 20, 2026 at 11:44:18AM +0200, Claudio Jeker wrote:
> There is an error when it comes to handling
> bgpctl show rib out <IP>
> queries. If the IP to lookup up is covered by a not exported route but
> instead by a less specific one the lookup fails.
>
> For example in this setup where the /26 route is filtered:
> bgpctl show rib
> flags vs destination gateway lpref med aspath origin
> AI*> N-? 192.0.2.0/24 0.0.0.0 100 0 i
> AI*> N-? 192.0.2.0/26 0.0.0.0 100 0 i
> bgpctl show rib out
> flags vs destination gateway lpref med aspath origin
> AI* N-? 192.0.2.0/24 10.83.0.138 100 0 i
> bgpctl show rib out 192.0.2.0/24
> flags vs destination gateway lpref med aspath origin
> AI* N-? 192.0.2.0/24 10.83.0.138 100 0 i
>
> but
> bgpctl show rib out 192.0.2.1
> flags vs destination gateway lpref med aspath origin
>
> The last command fails even though there is a route for 192.0.2.1 it just
> hides behind 192.0.2.0/26.
>
> The diff below fixes this. In the pt_lookup() case one needs to walk up
> all possible prefixes to see if a covering route is actually exported.
>
> Not super fond of this diff since it adds yet another loop into a nested
> mess. This should all be refactored but I'm not doing that right now.
Yeah, well... Diff makes sense and if it works that's better than leaving
it broken.
ok tb
> --
> :wq Claudio
>
> Index: rde.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/bgpd/rde.c,v
> diff -u -p -r1.700 rde.c
> --- rde.c 13 May 2026 14:01:29 -0000 1.700
> +++ rde.c 18 May 2026 11:36:40 -0000
> @@ -3276,7 +3276,7 @@ rde_dump_ctx_new(struct ctl_show_rib_req
> struct rib_entry *re;
> struct adjout_prefix *p;
> u_int error;
> - uint8_t hostplen, plen;
> + int hostplen, plen;
> uint16_t rid;
>
> if ((ctx = calloc(1, sizeof(*ctx))) == NULL) {
> @@ -3342,6 +3342,7 @@ rde_dump_ctx_new(struct ctl_show_rib_req
>
> do {
> struct pt_entry *pte;
> + int found;
>
> if (req->flags & F_SHORTER) {
> for (plen = 0; plen <= req->prefixlen;
> @@ -3370,13 +3371,28 @@ rde_dump_ctx_new(struct ctl_show_rib_req
> if (pte == NULL)
> continue;
>
> - /* dump all matching paths */
> - for (p = adjout_prefix_first(peer, pte);
> - p != NULL;
> - p = adjout_prefix_next(peer, pte, p)) {
> - rde_dump_adjout_upcall(peer, pte, p,
> - ctx);
> - }
> + do {
> + /* dump all matching paths */
> + found = 0;
> + for (p = adjout_prefix_first(peer, pte);
> + p != NULL;
> + p = adjout_prefix_next(peer, pte,
> + p)) {
> + rde_dump_adjout_upcall(peer,
> + pte, p, ctx);
> + found = 1;
> + }
> + if (!found &&
> + req->prefixlen == hostplen) {
> + for (plen = pte->prefixlen - 1;
> + plen >= 0; plen--) {
> + pte = pt_get(
> + &req->prefix, plen);
> + if (pte != NULL)
> + break;
> + }
> + }
> + } while (!found && pte != NULL);
> } while ((peer = peer_match(&req->neighbor,
> peer->conf.id)));
>
>
bgpd: fix for bgpctl show rib out <IP>