On Wed, Jun 08, 2022 at 01:28:14PM +0200, Claudio Jeker wrote:
> 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.

I spent some time with this diff. This is outside my comfort zone.  I'll
need to read this once more with a fresh head.

I like the direction and less spaghetti is good.

Some small remarks and questions inline.

> -- 
> :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;

I guess the #ifdef RTF_MPATH was dropped since kroute.c is no longer
built outside of OpenBSD with recent -portable changes?

> +
> +                     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)

This is the only kroute_full called kr in the entire file. I would
prefer calling it kl (or kf as in the older code you don't touch).

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

I would wrap this the same way as the assignment a few lines down:

                                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;

why is there no kr->r.ifindex assignment here?

>                               } 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