The idea behind this diff is to use struct kroute_full in more places.
Mainly when parsing route messages. This allows to factor out the pure
route message parsing into dispatch_rtmsg_addr() and use it in both the
gerneral routing socket code but also in fetchtables(). Which removes some
duplicated code.

As a second step then this kroute_full is applied to the kroute tree. Here
I limited my changes to be minimal for now. A follow up will look more
into kr_fib_change() and tries to streamline that code and the bits in
fetchtable().

Also struct kroute_full could be used in more places with the goal to have
less mostly similar function for IPv4, IPv6 and the L3VPNs. Again this is
for later.

This should behave the same as before but dispatch_rtmsg_addr() decides
now in a different way if a route is connected or not (using the
RTF_GATEWAY flag for this). With this loopback routes show now up as
connected. It should have no noticable impact on routing.

Please give this a good test.
-- 
:wq Claudio

Index: kroute.c
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/kroute.c,v
retrieving revision 1.251
diff -u -p -r1.251 kroute.c
--- kroute.c    7 Jun 2022 16:42:07 -0000       1.251
+++ kroute.c    7 Jun 2022 17:05:37 -0000
@@ -130,7 +130,7 @@ void        kr_fib_update_prio(u_int, uint8_t);
 struct kroute_node     *kroute_find(struct ktable *, in_addr_t, uint8_t,
                            uint8_t);
 struct kroute_node     *kroute_matchgw(struct kroute_node *,
-                           struct sockaddr_in *);
+                           struct bgpd_addr *);
 int                     kroute_insert(struct ktable *, struct kroute_node *);
 int                     kroute_remove(struct ktable *, struct kroute_node *);
 void                    kroute_clear(struct ktable *);
@@ -138,7 +138,7 @@ void                         kroute_clear(struct ktable *);
 struct kroute6_node    *kroute6_find(struct ktable *, const struct in6_addr *,
                            uint8_t, uint8_t);
 struct kroute6_node    *kroute6_matchgw(struct kroute6_node *,
-                           struct sockaddr_in6 *);
+                           struct bgpd_addr *);
 int                     kroute6_insert(struct ktable *, struct kroute6_node *);
 int                     kroute6_remove(struct ktable *, struct kroute6_node *);
 void                    kroute6_clear(struct ktable *);
@@ -188,8 +188,9 @@ int         send_rt6msg(int, int, struct ktable
 int            dispatch_rtmsg(u_int);
 int            fetchtable(struct ktable *);
 int            fetchifs(int);
-int            dispatch_rtmsg_addr(struct rt_msghdr *,
-                   struct sockaddr *[RTAX_MAX], struct ktable *);
+int            dispatch_rtmsg_addr(struct rt_msghdr *, struct kroute_full *);
+int            kr_fib_delete(struct ktable *, struct kroute_full *, int);
+int            kr_fib_change(struct ktable *, struct kroute_full *, int, int);
 
 RB_PROTOTYPE(kroute_tree, kroute_node, entry, kroute_compare)
 RB_GENERATE(kroute_tree, kroute_node, entry, kroute_compare)
@@ -1780,21 +1781,21 @@ kroute_find(struct ktable *kt, in_addr_t
 }
 
 struct kroute_node *
-kroute_matchgw(struct kroute_node *kr, struct sockaddr_in *sa_in)
+kroute_matchgw(struct kroute_node *kr, struct bgpd_addr *gw)
 {
        in_addr_t       nexthop;
 
-       if (sa_in == NULL) {
+       if (gw->aid != AID_INET) {
                log_warnx("%s: no nexthop defined", __func__);
                return (NULL);
        }
-       nexthop = sa_in->sin_addr.s_addr;
+       nexthop = gw->v4.s_addr;
 
-       while (kr) {
+       do {
                if (kr->r.nexthop.s_addr == nexthop)
                        return (kr);
                kr = kr->next;
-       }
+       } while (kr);
 
        return (NULL);
 }
@@ -1933,21 +1934,21 @@ kroute6_find(struct ktable *kt, const st
 }
 
 struct kroute6_node *
-kroute6_matchgw(struct kroute6_node *kr, struct sockaddr_in6 *sa_in6)
+kroute6_matchgw(struct kroute6_node *kr, struct bgpd_addr *gw)
 {
        struct in6_addr nexthop;
 
-       if (sa_in6 == NULL) {
+       if (gw->aid != AID_INET6) {
                log_warnx("%s: no nexthop defined", __func__);
                return (NULL);
        }
-       memcpy(&nexthop, &sa_in6->sin6_addr, sizeof(nexthop));
+       nexthop = gw->v6;
 
-       while (kr) {
+       do {
                if (memcmp(&kr->r.nexthop, &nexthop, sizeof(nexthop)) == 0)
                        return (kr);
                kr = kr->next;
-       }
+       } while (kr);
 
        return (NULL);
 }
@@ -3180,12 +3181,9 @@ fetchtable(struct ktable *kt)
        int                      mib[7];
        char                    *buf = NULL, *next, *lim;
        struct rt_msghdr        *rtm;
-       struct sockaddr         *sa, *gw, *rti_info[RTAX_MAX];
-       struct sockaddr_in      *sa_in;
-       struct sockaddr_in6     *sa_in6;
-       struct sockaddr_rtlabel *label;
-       struct kroute_node      *kr = NULL;
-       struct kroute6_node     *kr6 = NULL;
+       struct kroute_full       kl;
+       struct kroute_node      *kr;
+       struct kroute6_node     *kr6;
 
        mib[0] = CTL_NET;
        mib[1] = PF_ROUTE;
@@ -3219,144 +3217,48 @@ fetchtable(struct ktable *kt)
                rtm = (struct rt_msghdr *)next;
                if (rtm->rtm_version != RTM_VERSION)
                        continue;
-               sa = (struct sockaddr *)(next + rtm->rtm_hdrlen);
-               get_rtaddrs(rtm->rtm_addrs, sa, rti_info);
-
-               if ((sa = rti_info[RTAX_DST]) == NULL)
-                       continue;
 
-               /* Skip ARP/ND cache and broadcast routes. */
-               if (rtm->rtm_flags & (RTF_LLINFO|RTF_BROADCAST))
+               if (dispatch_rtmsg_addr(rtm, &kl) == -1)
                        continue;
 
-               switch (sa->sa_family) {
-               case AF_INET:
-                       if ((kr = calloc(1, sizeof(struct kroute_node))) ==
-                           NULL) {
-                               log_warn("%s", __func__);
-                               free(buf);
-                               return (-1);
-                       }
-
-                       kr->r.flags = F_KERNEL;
-                       kr->r.priority = rtm->rtm_priority;
-                       kr->r.ifindex = rtm->rtm_index;
-                       kr->r.prefix.s_addr =
-                           ((struct sockaddr_in *)sa)->sin_addr.s_addr;
-                       sa_in = (struct sockaddr_in *)rti_info[RTAX_NETMASK];
-                       if (rtm->rtm_flags & RTF_STATIC)
-                               kr->r.flags |= F_STATIC;
-                       if (rtm->rtm_flags & RTF_BLACKHOLE)
-                               kr->r.flags |= F_BLACKHOLE;
-                       if (rtm->rtm_flags & RTF_REJECT)
-                               kr->r.flags |= F_REJECT;
-                       if (rtm->rtm_flags & RTF_DYNAMIC)
-                               kr->r.flags |= F_DYNAMIC;
-                       if (sa_in != NULL) {
-                               if (sa_in->sin_len == 0)
-                                       break;
-                               kr->r.prefixlen =
-                                   mask2prefixlen(sa_in->sin_addr.s_addr);
-                       } else if (rtm->rtm_flags & RTF_HOST)
-                               kr->r.prefixlen = 32;
-                       else
-                               kr->r.prefixlen =
-                                   prefixlen_classful(kr->r.prefix.s_addr);
-                       if ((label = (struct sockaddr_rtlabel *)
-                           rti_info[RTAX_LABEL]) != NULL) {
-                               kr->r.labelid =
-                                   rtlabel_name2id(label->sr_label);
-                       }
-                       break;
-               case AF_INET6:
-                       if ((kr6 = calloc(1, sizeof(struct kroute6_node))) ==
-                           NULL) {
+               if (kl.prefix.aid == AID_INET) {
+                       if ((kr = calloc(1,
+                           sizeof(struct kroute_node))) == NULL) {
                                log_warn("%s", __func__);
-                               free(buf);
                                return (-1);
                        }
+                       kr->r.prefix.s_addr = kl.prefix.v4.s_addr;
+                       kr->r.prefixlen = kl.prefixlen;
+                       if (kl.nexthop.aid == AID_INET)
+                               kr->r.nexthop.s_addr = kl.nexthop.v4.s_addr;
+                       kr->r.flags = kl.flags;
+                       kr->r.ifindex = kl.ifindex;
+                       kr->r.priority = kl.priority;
+                       kr->r.labelid = rtlabel_name2id(kl.label);
 
-                       kr6->r.flags = F_KERNEL;
-                       kr6->r.priority = rtm->rtm_priority;
-                       kr6->r.ifindex = rtm->rtm_index;
-                       memcpy(&kr6->r.prefix,
-                           &((struct sockaddr_in6 *)sa)->sin6_addr,
-                           sizeof(kr6->r.prefix));
-
-                       sa_in6 = (struct sockaddr_in6 *)rti_info[RTAX_NETMASK];
-                       if (rtm->rtm_flags & RTF_STATIC)
-                               kr6->r.flags |= F_STATIC;
-                       if (rtm->rtm_flags & RTF_BLACKHOLE)
-                               kr6->r.flags |= F_BLACKHOLE;
-                       if (rtm->rtm_flags & RTF_REJECT)
-                               kr6->r.flags |= F_REJECT;
-                       if (rtm->rtm_flags & RTF_DYNAMIC)
-                               kr6->r.flags |= F_DYNAMIC;
-                       if (sa_in6 != NULL) {
-                               if (sa_in6->sin6_len == 0)
-                                       break;
-                               kr6->r.prefixlen = mask2prefixlen6(sa_in6);
-                       } else if (rtm->rtm_flags & RTF_HOST)
-                               kr6->r.prefixlen = 128;
-                       else
-                               fatalx("INET6 route without netmask");
-                       if ((label = (struct sockaddr_rtlabel *)
-                           rti_info[RTAX_LABEL]) != NULL) {
-                               kr6->r.labelid =
-                                   rtlabel_name2id(label->sr_label);
-                       }
-                       break;
-               default:
-                       continue;
-               }
-
-               if ((gw = rti_info[RTAX_GATEWAY]) != NULL)
-                       switch (gw->sa_family) {
-                       case AF_INET:
-                               if (kr == NULL)
-                                       fatalx("v4 gateway for !v4 dst?!");
-
-                               if (rtm->rtm_flags & RTF_CONNECTED) {
-                                       kr->r.flags |= F_CONNECTED;
-                                       break;
-                               }
-
-                               kr->r.nexthop.s_addr =
-                                   ((struct sockaddr_in *)gw)->sin_addr.s_addr;
-                               break;
-                       case AF_INET6:
-                               if (kr6 == NULL)
-                                       fatalx("v6 gateway for !v6 dst?!");
-
-                               if (rtm->rtm_flags & RTF_CONNECTED) {
-                                       kr6->r.flags |= F_CONNECTED;
-                                       break;
-                               }
-
-                               memcpy(&kr6->r.nexthop,
-                                   &((struct sockaddr_in6 *)gw)->sin6_addr,
-                                   sizeof(kr6->r.nexthop));
-                               break;
-                       case AF_LINK:
-                               /*
-                                * Traditional BSD connected routes have
-                                * a gateway of type AF_LINK.
-                                */
-                               if (sa->sa_family == AF_INET)
-                                       kr->r.flags |= F_CONNECTED;
-                               else if (sa->sa_family == AF_INET6)
-                                       kr6->r.flags |= F_CONNECTED;
-                               break;
-                       }
-
-               if (sa->sa_family == AF_INET) {
                        if (rtm->rtm_priority == kr_state.fib_prio) {
                                send_rtmsg(kr_state.fd, RTM_DELETE, kt, &kr->r);
                                rtlabel_unref(kr->r.labelid);
                                free(kr);
                        } else
                                kroute_insert(kt, kr);
-               } else if (sa->sa_family == AF_INET6) {
+               } else if (kl.prefix.aid == AID_INET6) {
+                       if ((kr6 = calloc(1,
+                           sizeof(struct kroute6_node))) == NULL) {
+                               log_warn("%s", __func__);
+                               return (-1);
+                       }
+                       kr6->r.prefix = kl.prefix.v6;
+                       kr6->r.prefixlen = kl.prefixlen;
+                       if (kl.nexthop.aid == AID_INET6)
+                               kr6->r.nexthop = kl.nexthop.v6;
+                       else
+                               kr6->r.nexthop = in6addr_any;
+                       kr6->r.flags = kl.flags;
+                       kr6->r.ifindex = kl.ifindex;
+                       kr6->r.priority = kl.priority;
+                       kr6->r.labelid = rtlabel_name2id(kl.label);
+
                        if (rtm->rtm_priority == kr_state.fib_prio) {
                                send_rt6msg(kr_state.fd, RTM_DELETE, kt,
                                    &kr6->r);
@@ -3454,8 +3356,9 @@ dispatch_rtmsg(u_int rdomain)
        char                    *next, *lim;
        struct rt_msghdr        *rtm;
        struct if_msghdr         ifm;
-       struct sockaddr         *sa, *rti_info[RTAX_MAX];
+       struct kroute_full       kl;
        struct ktable           *kt;
+       int                      mpath = 0;
 
        if ((n = read(kr_state.fd, &buf, sizeof(buf))) == -1) {
                if (errno == EAGAIN || errno == EINTR)
@@ -3482,23 +3385,34 @@ dispatch_rtmsg(u_int rdomain)
                case RTM_ADD:
                case RTM_CHANGE:
                case RTM_DELETE:
-                       sa = (struct sockaddr *)(next + rtm->rtm_hdrlen);
-                       get_rtaddrs(rtm->rtm_addrs, sa, rti_info);
-
                        if (rtm->rtm_pid == kr_state.pid) /* cause by us */
                                continue;
 
-                       if (rtm->rtm_errno)              /* failed attempts */
-                               continue;
+                       /* failed attempts */
+                       if (rtm->rtm_errno || !(rtm->rtm_flags & RTF_DONE))
+                               return (-1);
 
-                       if (rtm->rtm_flags & RTF_LLINFO) /* arp cache */
+                       if ((kt = ktable_get(rtm->rtm_tableid)) == NULL)
                                continue;
 
-                       if ((kt = ktable_get(rtm->rtm_tableid)) == NULL)
+                       if (dispatch_rtmsg_addr(rtm, &kl) == -1)
                                continue;
 
-                       if (dispatch_rtmsg_addr(rtm, rti_info, kt) == -1)
-                               return (-1);
+                       if (rtm->rtm_flags & RTF_MPATH)
+                               mpath = 1;
+
+                       switch (rtm->rtm_type) {
+                       case RTM_ADD:
+                       case RTM_CHANGE:
+                               if (kr_fib_change(kt, &kl, rtm->rtm_type,
+                                   mpath) == -1)
+                                       return -1;
+                               break;
+                       case RTM_DELETE:
+                               if (kr_fib_delete(kt, &kl, mpath) == -1)
+                                       return -1;
+                               break;
+                       }
                        break;
                case RTM_IFINFO:
                        memcpy(&ifm, next, sizeof(ifm));
@@ -3517,191 +3431,190 @@ dispatch_rtmsg(u_int rdomain)
 }
 
 int
-dispatch_rtmsg_addr(struct rt_msghdr *rtm, struct sockaddr *rti_info[RTAX_MAX],
-    struct ktable *kt)
+dispatch_rtmsg_addr(struct rt_msghdr *rtm, struct kroute_full *kr)
 {
-       struct sockaddr         *sa;
+       struct sockaddr         *sa, *rti_info[RTAX_MAX];
        struct sockaddr_in      *sa_in;
        struct sockaddr_in6     *sa_in6;
        struct sockaddr_rtlabel *label;
-       struct kroute_node      *kr;
-       struct kroute6_node     *kr6;
-       struct bgpd_addr         prefix;
-       int                      flags, oflags, mpath = 0, changed = 0;
-       int                      rtlabel_changed = 0;
-       uint16_t                 ifindex, new_labelid;
-       uint8_t                  prefixlen;
-       uint8_t                  prio;
-
-       flags = F_KERNEL;
-       ifindex = 0;
-       prefixlen = 0;
-       bzero(&prefix, sizeof(prefix));
+
+       sa = (struct sockaddr *)((char *)rtm + rtm->rtm_hdrlen);
+       get_rtaddrs(rtm->rtm_addrs, sa, rti_info);
+
+       /* Skip ARP/ND cache and broadcast routes. */
+       if (rtm->rtm_flags & (RTF_LLINFO|RTF_BROADCAST))
+               return (-1);
 
        if ((sa = rti_info[RTAX_DST]) == NULL) {
-               log_warnx("empty route message");
-               return (0);
+               log_warnx("route message without destination");
+               return (-1);
        }
 
+       memset(kr, 0, sizeof(*kr));
+       kr->flags = F_KERNEL;
+
        if (rtm->rtm_flags & RTF_STATIC)
-               flags |= F_STATIC;
+               kr->flags |= F_STATIC;
        if (rtm->rtm_flags & RTF_BLACKHOLE)
-               flags |= F_BLACKHOLE;
+               kr->flags |= F_BLACKHOLE;
        if (rtm->rtm_flags & RTF_REJECT)
-               flags |= F_REJECT;
+               kr->flags |= F_REJECT;
        if (rtm->rtm_flags & RTF_DYNAMIC)
-               flags |= F_DYNAMIC;
-#ifdef RTF_MPATH
-       if (rtm->rtm_flags & RTF_MPATH)
-               mpath = 1;
-#endif
+               kr->flags |= F_DYNAMIC;
 
-       prio = rtm->rtm_priority;
+       kr->priority = rtm->rtm_priority;
        label = (struct sockaddr_rtlabel *)rti_info[RTAX_LABEL];
+       if (label != NULL)
+               if (strlcpy(kr->label, label->sr_label, sizeof(kr->label)) >=
+                   sizeof(kr->label))
+                       fatalx("rtm label overflow");
 
+       sa2addr(sa, &kr->prefix, NULL);
        switch (sa->sa_family) {
        case AF_INET:
-               prefix.aid = AID_INET;
-               prefix.v4.s_addr = ((struct sockaddr_in *)sa)->sin_addr.s_addr;
                sa_in = (struct sockaddr_in *)rti_info[RTAX_NETMASK];
                if (sa_in != NULL) {
                        if (sa_in->sin_len != 0)
-                               prefixlen = mask2prefixlen(
+                               kr->prefixlen = mask2prefixlen(
                                    sa_in->sin_addr.s_addr);
                } else if (rtm->rtm_flags & RTF_HOST)
-                       prefixlen = 32;
+                       kr->prefixlen = 32;
                else
-                       prefixlen =
-                           prefixlen_classful(prefix.v4.s_addr);
+                       kr->prefixlen =
+                           prefixlen_classful(kr->prefix.v4.s_addr);
                break;
        case AF_INET6:
-               prefix.aid = AID_INET6;
-               memcpy(&prefix.v6, &((struct sockaddr_in6 *)sa)->sin6_addr,
-                   sizeof(struct in6_addr));
                sa_in6 = (struct sockaddr_in6 *)rti_info[RTAX_NETMASK];
                if (sa_in6 != NULL) {
                        if (sa_in6->sin6_len != 0)
-                               prefixlen = mask2prefixlen6(sa_in6);
+                               kr->prefixlen = mask2prefixlen6(sa_in6);
                } else if (rtm->rtm_flags & RTF_HOST)
-                       prefixlen = 128;
+                       kr->prefixlen = 128;
                else
                        fatalx("in6 net addr without netmask");
                break;
        default:
-               return (0);
+               return (-1);
        }
 
-       if ((sa = rti_info[RTAX_GATEWAY]) != NULL)
+       if ((sa = rti_info[RTAX_GATEWAY]) == NULL) {
+               log_warnx("route %s/%u without gateway",
+                   log_addr(&kr->prefix), kr->prefixlen);
+               return (-1);
+       }
+
+       if (rtm->rtm_flags & RTF_GATEWAY) {
                switch (sa->sa_family) {
                case AF_LINK:
-                       flags |= F_CONNECTED;
-                       ifindex = rtm->rtm_index;
-                       sa = NULL;
-                       mpath = 0;      /* link local stuff can't be mpath */
+                       kr->flags |= F_CONNECTED;
+                       kr->ifindex = rtm->rtm_index;
                        break;
                case AF_INET:
                case AF_INET6:
-                       if (rtm->rtm_flags & RTF_CONNECTED) {
-                               flags |= F_CONNECTED;
-                               ifindex = rtm->rtm_index;
-                               sa = NULL;
-                               mpath = 0; /* link local stuff can't be mpath */
-                       }
+                       sa2addr(rti_info[RTAX_GATEWAY], &kr->nexthop, NULL);
                        break;
                }
+       } else {
+               kr->flags |= F_CONNECTED;
+               kr->ifindex = rtm->rtm_index;
+       }
 
-       if (rtm->rtm_type == RTM_DELETE) {
-               switch (prefix.aid) {
-               case AID_INET:
-                       sa_in = (struct sockaddr_in *)sa;
-                       if ((kr = kroute_find(kt, prefix.v4.s_addr,
-                           prefixlen, prio)) == NULL)
-                               return (0);
-                       if (!(kr->r.flags & F_KERNEL))
-                               return (0);
+       return (0);
+}
 
-                       if (mpath)
-                               /* get the correct route */
-                               if ((kr = kroute_matchgw(kr, sa_in)) == NULL) {
-                                       log_warnx("%s[delete]: "
-                                           "mpath route not found", __func__);
-                                       return (0);
-                               }
+int
+kr_fib_delete(struct ktable *kt, struct kroute_full *kl, int mpath)
+{
+       struct kroute_node      *kr;
+       struct kroute6_node     *kr6;
 
-                       if (kroute_remove(kt, kr) == -1)
-                               return (-1);
-                       break;
-               case AID_INET6:
-                       sa_in6 = (struct sockaddr_in6 *)sa;
-                       if ((kr6 = kroute6_find(kt, &prefix.v6, prefixlen,
-                           prio)) == NULL)
-                               return (0);
-                       if (!(kr6->r.flags & F_KERNEL))
-                               return (0);
+       switch (kl->prefix.aid) {
+       case AID_INET:
+               if ((kr = kroute_find(kt, kl->prefix.v4.s_addr,
+                   kl->prefixlen, kl->priority)) == NULL)
+                       return (0);
+               if (!(kr->r.flags & F_KERNEL))
+                       return (0);
 
-                       if (mpath)
-                               /* get the correct route */
-                               if ((kr6 = kroute6_matchgw(kr6, sa_in6)) ==
-                                   NULL) {
-                                       log_warnx("%s[delete]: IPv6 mpath "
-                                           "route not found", __func__);
-                                       return (0);
-                               }
+               if (mpath) {
+                       /* get the correct route */
+                       if ((kr = kroute_matchgw(kr, &kl->nexthop)) == NULL) {
+                               log_warnx("delete %s/%u: route not found",
+                                   log_addr(&kl->prefix), kl->prefixlen);
+                               return (0);
+                       }
+               }
+               if (kroute_remove(kt, kr) == -1)
+                       return (-1);
+               break;
+       case AID_INET6:
+               if ((kr6 = kroute6_find(kt, &kl->prefix.v6, kl->prefixlen,
+                   kl->priority)) == NULL)
+                       return (0);
+               if (!(kr6->r.flags & F_KERNEL))
+                       return (0);
 
-                       if (kroute6_remove(kt, kr6) == -1)
-                               return (-1);
-                       break;
+               if (mpath) {
+                       /* get the correct route */
+                       if ((kr6 = kroute6_matchgw(kr6, &kl->nexthop)) ==
+                           NULL) {
+                               log_warnx("delete %s/%u: route not found",
+                                   log_addr(&kl->prefix), kl->prefixlen);
+                               return (0);
+                       }
                }
-               return (0);
+               if (kroute6_remove(kt, kr6) == -1)
+                       return (-1);
+               break;
        }
+       return (0);
+}
 
-       if (sa == NULL && !(flags & F_CONNECTED)) {
-               log_warnx("%s: no nexthop for %s/%u",
-                   __func__, log_addr(&prefix), prefixlen);
-               return (0);
-       }
+int
+kr_fib_change(struct ktable *kt, struct kroute_full *kl, int type, int mpath)
+{
+       struct kroute_node      *kr;
+       struct kroute6_node     *kr6;
+       int                      flags, oflags;
+       int                      changed = 0, rtlabel_changed = 0;
+       uint16_t                 new_labelid;
 
-       switch (prefix.aid) {
+       flags = kl->flags;
+       switch (kl->prefix.aid) {
        case AID_INET:
-               sa_in = (struct sockaddr_in *)sa;
-               if ((kr = kroute_find(kt, prefix.v4.s_addr, prefixlen,
-                   prio)) != NULL) {
+               if ((kr = kroute_find(kt, kl->prefix.v4.s_addr, kl->prefixlen,
+                   kl->priority)) != NULL) {
                        if (kr->r.flags & F_KERNEL) {
                                /* get the correct route */
-                               if (mpath && rtm->rtm_type == RTM_CHANGE &&
-                                   (kr = kroute_matchgw(kr, sa_in)) == NULL) {
+                               if (mpath && type == RTM_CHANGE &&
+                                   (kr = kroute_matchgw(kr, &kl->nexthop)) ==
+                                   NULL) {
                                        log_warnx("%s[change]: "
                                            "mpath route not found", __func__);
                                        goto add4;
-                               } else if (mpath && rtm->rtm_type == RTM_ADD)
+                               } else if (mpath && type == RTM_ADD)
                                        goto add4;
 
-                               if (sa_in != NULL) {
+                               if (kl->nexthop.aid == AID_INET) {
                                        if (kr->r.nexthop.s_addr !=
-                                           sa_in->sin_addr.s_addr)
+                                           kl->nexthop.v4.s_addr)
                                                changed = 1;
                                        kr->r.nexthop.s_addr =
-                                           sa_in->sin_addr.s_addr;
+                                           kl->nexthop.v4.s_addr;
                                } else {
                                        if (kr->r.nexthop.s_addr != 0)
                                                changed = 1;
                                        kr->r.nexthop.s_addr = 0;
+                                       kr->r.ifindex = kl->ifindex;
                                }
 
                                if (kr->r.flags & F_NEXTHOP)
                                        flags |= F_NEXTHOP;
 
-                               if (label != NULL) {
-                                       new_labelid =
-                                           rtlabel_name2id(label->sr_label);
-                                       if (kr->r.labelid != new_labelid) {
-                                               rtlabel_unref(kr->r.labelid);
-                                               kr->r.labelid = new_labelid;
-                                               rtlabel_changed = 1;
-                                       }
-                               } else if (kr->r.labelid) {
+                               new_labelid = rtlabel_name2id(kl->label);
+                               if (kr->r.labelid != new_labelid) {
                                        rtlabel_unref(kr->r.labelid);
-                                       kr->r.labelid = 0;
+                                       kr->r.labelid = new_labelid;
                                        rtlabel_changed = 1;
                                }
 
@@ -3729,10 +3642,6 @@ dispatch_rtmsg_addr(struct rt_msghdr *rt
                                if (kr->r.flags & F_NEXTHOP && changed)
                                        knexthop_track(kt, kr);
                        }
-               } else if (rtm->rtm_type == RTM_CHANGE) {
-                       log_warnx("%s: change req for %s/%u: not in table",
-                           __func__, log_addr(&prefix), prefixlen);
-                       return (0);
                } else {
 add4:
                        if ((kr = calloc(1,
@@ -3740,70 +3649,54 @@ add4:
                                log_warn("%s", __func__);
                                return (-1);
                        }
-                       kr->r.prefix.s_addr = prefix.v4.s_addr;
-                       kr->r.prefixlen = prefixlen;
-                       if (sa_in != NULL)
-                               kr->r.nexthop.s_addr = sa_in->sin_addr.s_addr;
-                       else
-                               kr->r.nexthop.s_addr = 0;
+                       kr->r.prefix.s_addr = kl->prefix.v4.s_addr;
+                       kr->r.prefixlen = kl->prefixlen;
+                       if (kl->nexthop.aid == AID_INET)
+                               kr->r.nexthop.s_addr = kl->nexthop.v4.s_addr;
                        kr->r.flags = flags;
-                       kr->r.ifindex = ifindex;
-                       kr->r.priority = prio;
+                       kr->r.ifindex = kl->ifindex;
+                       kr->r.priority = kl->priority;
+                       kr->r.labelid = rtlabel_name2id(kl->label);
 
-                       if (label) {
-                               kr->r.labelid =
-                                   rtlabel_name2id(label->sr_label);
-                       }
                        kroute_insert(kt, kr);
                }
                break;
        case AID_INET6:
-               sa_in6 = (struct sockaddr_in6 *)sa;
-               if ((kr6 = kroute6_find(kt, &prefix.v6, prefixlen, prio)) !=
-                   NULL) {
+               if ((kr6 = kroute6_find(kt, &kl->prefix.v6, kl->prefixlen,
+                   kl->priority)) != NULL) {
                        if (kr6->r.flags & F_KERNEL) {
                                /* get the correct route */
-                               if (mpath && rtm->rtm_type == RTM_CHANGE &&
-                                   (kr6 = kroute6_matchgw(kr6, sa_in6)) ==
-                                   NULL) {
+                               if (mpath && type == RTM_CHANGE &&
+                                   (kr6 = kroute6_matchgw(kr6, &kl->nexthop))
+                                   == NULL) {
                                        log_warnx("%s[change]: IPv6 mpath "
                                            "route not found", __func__);
                                        goto add6;
-                               } else if (mpath && rtm->rtm_type == RTM_ADD)
+                               } else if (mpath && type == RTM_ADD)
                                        goto add6;
 
-                               if (sa_in6 != NULL) {
+                               if (kl->nexthop.aid == AID_INET6) {
                                        if (memcmp(&kr6->r.nexthop,
-                                           &sa_in6->sin6_addr,
+                                           &kl->nexthop.v6,
                                            sizeof(struct in6_addr)))
                                                changed = 1;
-                                       memcpy(&kr6->r.nexthop,
-                                           &sa_in6->sin6_addr,
-                                           sizeof(struct in6_addr));
+                                       kr6->r.nexthop = kl->nexthop.v6;
                                } else {
                                        if (memcmp(&kr6->r.nexthop,
                                            &in6addr_any,
                                            sizeof(struct in6_addr)))
                                                changed = 1;
-                                       memcpy(&kr6->r.nexthop,
-                                           &in6addr_any,
-                                           sizeof(struct in6_addr));
+                                       kr6->r.nexthop = in6addr_any;
+                                       kr6->r.ifindex = kl->ifindex;
                                }
 
                                if (kr6->r.flags & F_NEXTHOP)
                                        flags |= F_NEXTHOP;
 
-                               if (label != NULL) {
-                                       new_labelid =
-                                           rtlabel_name2id(label->sr_label);
-                                       if (kr6->r.labelid != new_labelid) {
-                                               rtlabel_unref(kr6->r.labelid);
-                                               kr6->r.labelid = new_labelid;
-                                               rtlabel_changed = 1;
-                                       }
-                               } else if (kr6->r.labelid) {
+                               new_labelid = rtlabel_name2id(kl->label);
+                               if (kr6->r.labelid != new_labelid) {
                                        rtlabel_unref(kr6->r.labelid);
-                                       kr6->r.labelid = 0;
+                                       kr6->r.labelid = new_labelid;
                                        rtlabel_changed = 1;
                                }
 
@@ -3832,10 +3725,6 @@ add4:
                                if (kr6->r.flags & F_NEXTHOP && changed)
                                        knexthop_track(kt, kr6);
                        }
-               } else if (rtm->rtm_type == RTM_CHANGE) {
-                       log_warnx("%s: change req for %s/%u: not in table",
-                           __func__, log_addr(&prefix), prefixlen);
-                       return (0);
                } else {
 add6:
                        if ((kr6 = calloc(1,
@@ -3843,23 +3732,17 @@ add6:
                                log_warn("%s", __func__);
                                return (-1);
                        }
-                       memcpy(&kr6->r.prefix, &prefix.v6,
-                           sizeof(struct in6_addr));
-                       kr6->r.prefixlen = prefixlen;
-                       if (sa_in6 != NULL)
-                               memcpy(&kr6->r.nexthop, &sa_in6->sin6_addr,
-                                   sizeof(struct in6_addr));
+                       kr6->r.prefix = kl->prefix.v6;
+                       kr6->r.prefixlen = kl->prefixlen;
+                       if (kl->nexthop.aid == AID_INET6)
+                               kr6->r.nexthop = kl->nexthop.v6;
                        else
-                               memcpy(&kr6->r.nexthop, &in6addr_any,
-                                   sizeof(struct in6_addr));
+                               kr6->r.nexthop = in6addr_any;
                        kr6->r.flags = flags;
-                       kr6->r.ifindex = ifindex;
-                       kr6->r.priority = prio;
+                       kr6->r.ifindex = kl->ifindex;
+                       kr6->r.priority = kl->priority;
+                       kr6->r.labelid = rtlabel_name2id(kl->label);
 
-                       if (label) {
-                               kr6->r.labelid =
-                                   rtlabel_name2id(label->sr_label);
-                       }
                        kroute6_insert(kt, kr6);
                }
                break;

Reply via email to