The kroute_remove() code will fail hard when a connected route is removed.
Most commonly this happens when an interface is deconfigured.
The problem is that there is no logic to match against connected routes.
Connected routes have no real nexthop and just use the ifindex as
identifier, so adjust kroute_matchgw() to select the right route.

This diff solves the problem I have seen while testing.
-- 
:wq Claudio

Index: kroute.c
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/kroute.c,v
retrieving revision 1.298
diff -u -p -r1.298 kroute.c
--- kroute.c    30 Aug 2022 16:00:21 -0000      1.298
+++ kroute.c    14 Sep 2022 17:00:37 -0000
@@ -136,14 +136,14 @@ int       kif_compare(struct kif *, struct kif
 
 struct kroute  *kroute_find(struct ktable *, const struct bgpd_addr *,
                    uint8_t, uint8_t);
-struct kroute  *kroute_matchgw(struct kroute *, struct bgpd_addr *);
+struct kroute  *kroute_matchgw(struct kroute *, struct kroute_full *);
 int             kroute_insert(struct ktable *, struct kroute_full *);
 int             kroute_remove(struct ktable *, struct kroute_full *, int);
 void            kroute_clear(struct ktable *);
 
 struct kroute6 *kroute6_find(struct ktable *, const struct bgpd_addr *,
                    uint8_t, uint8_t);
-struct kroute6 *kroute6_matchgw(struct kroute6 *, struct bgpd_addr *);
+struct kroute6 *kroute6_matchgw(struct kroute6 *, struct kroute_full *);
 void            kroute6_clear(struct ktable *);
 
 struct knexthop        *knexthop_find(struct ktable *, struct bgpd_addr *);
@@ -1583,16 +1583,20 @@ kroute_find(struct ktable *kt, const str
 }
 
 struct kroute *
-kroute_matchgw(struct kroute *kr, struct bgpd_addr *gw)
+kroute_matchgw(struct kroute *kr, struct kroute_full *kf)
 {
        in_addr_t       nexthop;
 
-       if (gw->aid != AID_INET) {
-               log_warnx("%s: no nexthop defined", __func__);
+       if (kf->flags & F_CONNECTED) {
+               do {
+                       if (kr->ifindex == kf->ifindex)
+                               return (kr);
+                       kr = kr->next;
+               } while (kr);
                return (NULL);
        }
-       nexthop = gw->v4.s_addr;
 
+       nexthop = kf->nexthop.v4.s_addr;
        do {
                if (kr->nexthop.s_addr == nexthop)
                        return (kr);
@@ -1735,7 +1739,7 @@ kroute4_remove(struct ktable *kt, struct
        /* get the correct route to remove */
        krm = kr;
        if (!any) {
-               if ((krm = kroute_matchgw(kr, &kf->nexthop)) == NULL) {
+               if ((krm = kroute_matchgw(kr, kf)) == NULL) {
                        log_warnx("delete %s/%u: route not found",
                            log_addr(&kf->prefix), kf->prefixlen);
                        return (-2);
@@ -1805,7 +1809,7 @@ kroute6_remove(struct ktable *kt, struct
        /* get the correct route to remove */
        krm = kr;
        if (!any) {
-               if ((krm = kroute6_matchgw(kr, &kf->nexthop)) == NULL) {
+               if ((krm = kroute6_matchgw(kr, kf)) == NULL) {
                        log_warnx("delete %s/%u: route not found",
                            log_addr(&kf->prefix), kf->prefixlen);
                        return (-2);
@@ -1919,19 +1923,23 @@ kroute6_find(struct ktable *kt, const st
 }
 
 struct kroute6 *
-kroute6_matchgw(struct kroute6 *kr, struct bgpd_addr *gw)
+kroute6_matchgw(struct kroute6 *kr, struct kroute_full *kf)
 {
        struct in6_addr nexthop;
 
-       if (gw->aid != AID_INET6) {
-               log_warnx("%s: no nexthop defined", __func__);
+       if (kf->flags & F_CONNECTED) {
+               do {
+                       if (kr->ifindex == kf->ifindex)
+                               return (kr);
+                       kr = kr->next;
+               } while (kr);
                return (NULL);
        }
-       nexthop = gw->v6;
 
+       nexthop = kf->nexthop.v6;
        do {
                if (memcmp(&kr->nexthop, &nexthop, sizeof(nexthop)) == 0 &&
-                   kr->nexthop_scope_id == gw->scope_id)
+                   kr->nexthop_scope_id == kf->nexthop.scope_id)
                        return (kr);
                kr = kr->next;
        } while (kr);
@@ -3117,8 +3125,7 @@ kr_fib_change(struct ktable *kt, struct 
                        if (!(kf->flags & F_BGPD)) {
                                /* get the correct route */
                                if (mpath && type == RTM_CHANGE &&
-                                   (kr = kroute_matchgw(kr, &kf->nexthop)) ==
-                                   NULL) {
+                                   (kr = kroute_matchgw(kr, kf)) == NULL) {
                                        log_warnx("%s[change]: "
                                            "mpath route not found", __func__);
                                        goto add4;
@@ -3183,8 +3190,7 @@ add4:
                        if (!(kf->flags & F_BGPD)) {
                                /* get the correct route */
                                if (mpath && type == RTM_CHANGE &&
-                                   (kr6 = kroute6_matchgw(kr6, &kf->nexthop))
-                                   == NULL) {
+                                   (kr6 = kroute6_matchgw(kr6, kf)) == NULL) {
                                        log_warnx("%s[change]: IPv6 mpath "
                                            "route not found", __func__);
                                        goto add6;

Reply via email to