Index | Thread | Search

From:
Theo Buehler <tb@theobuehler.org>
Subject:
Re: bgpd: fix for bgpctl show rib out <IP>
To:
tech@openbsd.org
Date:
Wed, 20 May 2026 11:50:05 +0200

Download raw body.

Thread
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)));
>  
>