From: Theo Buehler Subject: Re: bgpd: fix for bgpctl show rib out To: tech@openbsd.org Date: Wed, 20 May 2026 16:38:46 +0200 On Wed, May 20, 2026 at 04:22:43PM +0200, Claudio Jeker wrote: > On Wed, May 20, 2026 at 11:50:05AM +0200, Theo Buehler wrote: > > 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 > > > 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 > > I realized that I sent out and committed an older version of what I > wanted. Here is a fixup for that. > > The loop needs to be done a bit differently to properly terminate in all > cases. In the not-found case where req->prefixlen != hostplen we currently > end up spinning forever. There is a similar issue if pte->prefixlen = 0 > and not-found. > > In both cases the do { } while (!found && pte != NULL); keeps spinning. > The fix for this is below. Force pte to NULL before doing the extra > lookup. Because of that set plen early and use a while loop. Can't say I'm surprised. It's very difficult to read this kind of code. It does look a bit better in this second version. ok tb > > -- > :wq Claudio > > Index: rde.c > =================================================================== > RCS file: /cvs/src/usr.sbin/bgpd/rde.c,v > diff -u -p -r1.701 rde.c > --- rde.c 20 May 2026 09:56:56 -0000 1.701 > +++ rde.c 20 May 2026 14:05:58 -0000 > @@ -3382,14 +3382,16 @@ rde_dump_ctx_new(struct ctl_show_rib_req > pte, p, ctx); > found = 1; > } > + plen = pte->prefixlen - 1; > + pte = NULL; > if (!found && > req->prefixlen == hostplen) { > - for (plen = pte->prefixlen - 1; > - plen >= 0; plen--) { > + while (plen >= 0) { > pte = pt_get( > &req->prefix, plen); > if (pte != NULL) > break; > + plen--; > } > } > } while (!found && pte != NULL);