On Wed, Dec 11, 2019 at 04:38:38PM +0100, Denis Fondras wrote:
> On Tue, Dec 10, 2019 at 09:51:12PM +0100, Remi Locherer wrote:
> > Unfortunately redistribute does not work anymore.
> > 
> 
> Indeed, simple tests are too simple...
> 
> Here is an updated diff.

ok remi@

> 
> Index: kroute.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/ospf6d/kroute.c,v
> retrieving revision 1.60
> diff -u -p -r1.60 kroute.c
> --- kroute.c  2 Jan 2019 21:32:55 -0000       1.60
> +++ kroute.c  11 Dec 2019 14:51:25 -0000
> @@ -80,7 +80,7 @@ struct kroute_node  *kroute_match(struct 
>  
>  int          protect_lo(void);
>  void         get_rtaddrs(int, struct sockaddr *, struct sockaddr **);
> -void         if_change(u_short, int, struct if_data *);
> +void         if_change(u_short, int, struct if_data *, struct sockaddr_dl *);
>  void         if_newaddr(u_short, struct sockaddr_in6 *,
>                   struct sockaddr_in6 *, struct sockaddr_in6 *);
>  void         if_deladdr(u_short, struct sockaddr_in6 *,
> @@ -90,6 +90,7 @@ void                if_announce(void *);
>  int          send_rtmsg(int, int, struct kroute *);
>  int          dispatch_rtmsg(void);
>  int          fetchtable(void);
> +int          rtmsg_process(char *, size_t); 
>  
>  RB_HEAD(kroute_tree, kroute_node)    krt;
>  RB_PROTOTYPE(kroute_tree, kroute_node, entry, kroute_compare)
> @@ -801,7 +802,8 @@ get_rtaddrs(int addrs, struct sockaddr *
>  }
>  
>  void
> -if_change(u_short ifindex, int flags, struct if_data *ifd)
> +if_change(u_short ifindex, int flags, struct if_data *ifd,
> +    struct sockaddr_dl *sdl)
>  {
>       struct kroute_node      *kr, *tkr;
>       struct iface            *iface;
> @@ -809,7 +811,7 @@ if_change(u_short ifindex, int flags, st
>  
>       wasvalid = kif_validate(ifindex);
>  
> -     if ((iface = kif_update(ifindex, flags, ifd, NULL)) == NULL) {
> +     if ((iface = kif_update(ifindex, flags, ifd, sdl)) == NULL) {
>               log_warn("if_change: kif_update(%u)", ifindex);
>               return;
>       }
> @@ -1135,12 +1137,8 @@ fetchtable(void)
>  {
>       size_t                   len;
>       int                      mib[7];
> -     char                    *buf, *next, *lim;
> -     struct rt_msghdr        *rtm;
> -     struct sockaddr         *sa, *rti_info[RTAX_MAX];
> -     struct sockaddr_in6     *sa_in6;
> -     struct sockaddr_rtlabel *label;
> -     struct kroute_node      *kr;
> +     char                    *buf;
> +     int                      rv;
>  
>       mib[0] = CTL_NET;
>       mib[1] = PF_ROUTE;
> @@ -1164,102 +1162,10 @@ fetchtable(void)
>               return (-1);
>       }
>  
> -     lim = buf + len;
> -     for (next = buf; next < lim; next += rtm->rtm_msglen) {
> -             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))
> -                     continue;
> -
> -             if ((kr = calloc(1, sizeof(struct kroute_node))) == NULL) {
> -                     log_warn("fetchtable");
> -                     free(buf);
> -                     return (-1);
> -             }
> -
> -             kr->r.flags = F_KERNEL;
> -             kr->r.priority = rtm->rtm_priority;
> -
> -             switch (sa->sa_family) {
> -             case AF_INET6:
> -                     kr->r.prefix =
> -                         ((struct sockaddr_in6 *)sa)->sin6_addr;
> -                     sa_in6 = (struct sockaddr_in6 *)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_in6 != NULL) {
> -                             if (sa_in6->sin6_len == 0)
> -                                     break;
> -                             kr->r.prefixlen =
> -                                 mask2prefixlen(sa_in6);
> -                     } else if (rtm->rtm_flags & RTF_HOST)
> -                             kr->r.prefixlen = 128;
> -                     else
> -                             fatalx("classful IPv6 route?!!");
> -                     break;
> -             default:
> -                     free(kr);
> -                     continue;
> -             }
> -
> -             kr->r.ifindex = rtm->rtm_index;
> -             if ((sa = rti_info[RTAX_GATEWAY]) != NULL)
> -                     switch (sa->sa_family) {
> -                     case AF_INET6:
> -                             if (rtm->rtm_flags & RTF_CONNECTED) {
> -                                     kr->r.flags |= F_CONNECTED;
> -                                     break;
> -                             }
> -
> -                             sa_in6 = (struct sockaddr_in6 *)sa;
> -                             /*
> -                              * XXX The kernel provides the scope via the
> -                              * XXX kame hack instead of the scope_id field.
> -                              */
> -                             recoverscope(sa_in6);
> -                             kr->r.nexthop = sa_in6->sin6_addr;
> -                             kr->r.scope = sa_in6->sin6_scope_id;
> -                             break;
> -                     case AF_LINK:
> -                             /*
> -                              * Traditional BSD connected routes have
> -                              * a gateway of type AF_LINK.
> -                              */
> -                             kr->r.flags |= F_CONNECTED;
> -                             break;
> -                     }
> -
> -             if (rtm->rtm_priority == kr_state.fib_prio)  {
> -                     send_rtmsg(kr_state.fd, RTM_DELETE, &kr->r);
> -                     free(kr);
> -             } else {
> -                     if ((label = (struct sockaddr_rtlabel *)
> -                         rti_info[RTAX_LABEL]) != NULL) {
> -                             kr->r.rtlabel =
> -                                 rtlabel_name2id(label->sr_label);
> -                             kr->r.ext_tag =
> -                                 rtlabel_id2tag(kr->r.rtlabel);
> -                     }
> -                     kroute_insert(kr);
> -             }
> -
> -     }
> +     rv = rtmsg_process(buf, len);
>       free(buf);
> -     return (0);
> +
> +     return (rv);
>  }
>  
>  int
> @@ -1267,12 +1173,8 @@ fetchifs(u_short ifindex)
>  {
>       size_t                   len;
>       int                      mib[6];
> -     char                    *buf, *next, *lim;
> -     struct rt_msghdr        *rtm;
> -     struct if_msghdr         ifm;
> -     struct ifa_msghdr       *ifam;
> -     struct iface            *iface;
> -     struct sockaddr         *sa, *rti_info[RTAX_MAX];
> +     char                    *buf;
> +     int                      rv;
>  
>       mib[0] = CTL_NET;
>       mib[1] = PF_ROUTE;
> @@ -1295,38 +1197,10 @@ fetchifs(u_short ifindex)
>               return (-1);
>       }
>  
> -     lim = buf + len;
> -     for (next = buf; next < lim; next += rtm->rtm_msglen) {
> -             rtm = (struct rt_msghdr *)next;
> -             if (rtm->rtm_version != RTM_VERSION)
> -                     continue;
> -             switch (rtm->rtm_type) {
> -             case RTM_IFINFO:
> -                     bcopy(rtm, &ifm, sizeof ifm);
> -                     sa = (struct sockaddr *)(next + sizeof(ifm));
> -                     get_rtaddrs(ifm.ifm_addrs, sa, rti_info);
> -
> -                     if ((iface = kif_update(ifm.ifm_index,
> -                         ifm.ifm_flags, &ifm.ifm_data,
> -                         (struct sockaddr_dl *)rti_info[RTAX_IFP])) == NULL)
> -                     break;
> -             case RTM_NEWADDR:
> -                     ifam = (struct ifa_msghdr *)rtm;
> -                     if ((ifam->ifam_addrs & (RTA_NETMASK | RTA_IFA |
> -                         RTA_BRD)) == 0)
> -                             break;
> -                     sa = (struct sockaddr *)(ifam + 1);
> -                     get_rtaddrs(ifam->ifam_addrs, sa, rti_info);
> -
> -                     if_newaddr(ifam->ifam_index,
> -                         (struct sockaddr_in6 *)rti_info[RTAX_IFA],
> -                         (struct sockaddr_in6 *)rti_info[RTAX_NETMASK],
> -                         (struct sockaddr_in6 *)rti_info[RTAX_BRD]);
> -                     break;
> -             }
> -     }
> +     rv = rtmsg_process(buf, len);
>       free(buf);
> -     return (0);
> +
> +     return (rv);
>  }
>  
>  int
> @@ -1334,7 +1208,25 @@ dispatch_rtmsg(void)
>  {
>       char                     buf[RT_BUF_SIZE];
>       ssize_t                  n;
> -     char                    *next, *lim;
> +
> +     if ((n = read(kr_state.fd, &buf, sizeof(buf))) == -1) {
> +             if (errno == EAGAIN || errno == EINTR)
> +                     return (0);
> +             log_warn("dispatch_rtmsg: read error");
> +             return (-1);
> +     }
> +
> +     if (n == 0) {
> +             log_warnx("routing socket closed");
> +             return (-1);
> +     }
> +
> +     return (rtmsg_process(buf, n));
> +}
> +
> +int
> +rtmsg_process(char *buf, size_t len)
> +{
>       struct rt_msghdr        *rtm;
>       struct if_msghdr         ifm;
>       struct ifa_msghdr       *ifam;
> @@ -1348,25 +1240,15 @@ dispatch_rtmsg(void)
>       unsigned int             scope;
>       u_short                  ifindex = 0;
>       int                      rv;
> +     size_t                   offset;
> +     char                    *next;
>  
> -     if ((n = read(kr_state.fd, &buf, sizeof(buf))) == -1) {
> -             if (errno == EAGAIN || errno == EINTR)
> -                     return (0);
> -             log_warn("dispatch_rtmsg: read error");
> -             return (-1);
> -     }
> -
> -     if (n == 0) {
> -             log_warnx("routing socket closed");
> -             return (-1);
> -     }
> -
> -     lim = buf + n;
> -     for (next = buf; next < lim; next += rtm->rtm_msglen) {
> +     for (offset = 0; offset < len; offset += rtm->rtm_msglen) {
> +             next = buf + offset;
>               rtm = (struct rt_msghdr *)next;
> -             if (lim < next + sizeof(u_short) ||
> -                 lim < next + rtm->rtm_msglen)
> -                     fatalx("dispatch_rtmsg: partial rtm in buffer");
> +             if (len < offset + sizeof(u_short) ||
> +                 len < offset + rtm->rtm_msglen)
> +                     fatalx("rtmsg_process: partial rtm in buffer");
>               if (rtm->rtm_version != RTM_VERSION)
>                       continue;
>  
> @@ -1378,18 +1260,25 @@ dispatch_rtmsg(void)
>               mpath = 0;
>               prio = 0;
>  
> -             if (rtm->rtm_type == RTM_ADD || rtm->rtm_type == RTM_CHANGE ||
> -                 rtm->rtm_type == RTM_DELETE) {
> -                     sa = (struct sockaddr *)(next + rtm->rtm_hdrlen);
> -                     get_rtaddrs(rtm->rtm_addrs, sa, rti_info);
> +             sa = (struct sockaddr *)(next + rtm->rtm_hdrlen);
> +             get_rtaddrs(rtm->rtm_addrs, sa, rti_info);
> +
> +             switch (rtm->rtm_type) {
> +             case RTM_ADD:
> +             case RTM_GET:
> +             case RTM_CHANGE:
> +             case RTM_DELETE:
> +                     if (rtm->rtm_errno)             /* failed attempts... */
> +                             continue;
>  
>                       if (rtm->rtm_tableid != kr_state.rdomain)
>                               continue;
>  
> -                     if (rtm->rtm_pid == kr_state.pid) /* caused by us */
> +                     if (rtm->rtm_type == RTM_GET &&
> +                         rtm->rtm_pid != kr_state.pid) /* caused by us */
>                               continue;
>  
> -                     if (rtm->rtm_errno)             /* failed attempts... */
> +                     if ((sa = rti_info[RTAX_DST]) == NULL)
>                               continue;
>  
>                       /* Skip ARP/ND cache and broadcast routes. */
> @@ -1399,6 +1288,8 @@ dispatch_rtmsg(void)
>                       if (rtm->rtm_flags & RTF_MPATH)
>                               mpath = 1;
>                       prio = rtm->rtm_priority;
> +                     flags = (prio == kr_state.fib_prio) ?
> +                         F_OSPFD_INSERTED : F_KERNEL;
>  
>                       switch (sa->sa_family) {
>                       case AF_INET6:
> @@ -1431,6 +1322,9 @@ dispatch_rtmsg(void)
>                       if ((sa = rti_info[RTAX_GATEWAY]) != NULL) {
>                               switch (sa->sa_family) {
>                               case AF_INET6:
> +                                     if (rtm->rtm_flags & RTF_CONNECTED)
> +                                             flags |= F_CONNECTED;
> +
>                                       sa_in6 = (struct sockaddr_in6 *)sa;
>                                       /*
>                                        * XXX The kernel provides the scope
> @@ -1450,10 +1344,11 @@ dispatch_rtmsg(void)
>  
>               switch (rtm->rtm_type) {
>               case RTM_ADD:
> +             case RTM_GET:
>               case RTM_CHANGE:
>                       if (IN6_IS_ADDR_UNSPECIFIED(&nexthop) &&
>                           !(flags & F_CONNECTED)) {
> -                             log_warnx("dispatch_rtmsg no nexthop for %s/%u",
> +                             log_warnx("rtmsg_process no nexthop for %s/%u",
>                                   log_in6addr(&prefix), prefixlen);
>                               continue;
>                       }
> @@ -1467,7 +1362,7 @@ dispatch_rtmsg(void)
>                               kr = okr;
>                               if (mpath && (kr = kroute_matchgw(okr,
>                                   &nexthop, scope)) == NULL) {
> -                                     log_warnx("dispatch_rtmsg mpath route"
> +                                     log_warnx("rtmsg_process: mpath route"
>                                           " not found");
>                                       /* add routes we missed out earlier */
>                                       goto add;
> @@ -1502,7 +1397,7 @@ dispatch_rtmsg(void)
>  add:
>                               if ((kr = calloc(1,
>                                   sizeof(struct kroute_node))) == NULL) {
> -                                     log_warn("dispatch_rtmsg");
> +                                     log_warn("rtmsg_process calloc");
>                                       return (-1);
>                               }
>                               kr->r.prefix = prefix;
> @@ -1540,31 +1435,29 @@ add:
>                       if ((kr = kroute_find(&prefix, prefixlen, prio)) ==
>                           NULL)
>                               continue;
> +                     if (!(kr->r.flags & F_KERNEL))
> +                             continue;
>                       /* get the correct route */
>                       okr = kr;
>                       if (mpath && (kr = kroute_matchgw(kr, &nexthop,
>                           scope)) == NULL) {
> -                             log_warnx("dispatch_rtmsg mpath route"
> +                             log_warnx("rtmsg_process mpath route"
>                                   " not found");
>                               return (-1);
>                       }
> -                     if (!(kr->r.flags & F_KERNEL))
> -                             continue;
>                       if (kroute_remove(kr) == -1)
>                               return (-1);
>                       break;
>               case RTM_IFINFO:
>                       memcpy(&ifm, next, sizeof(ifm));
> -                     if_change(ifm.ifm_index, ifm.ifm_flags,
> -                         &ifm.ifm_data);
> +                     if_change(ifm.ifm_index, ifm.ifm_flags, &ifm.ifm_data,
> +                         (struct sockaddr_dl *)rti_info[RTAX_IFP]);
>                       break;
>               case RTM_NEWADDR:
>                       ifam = (struct ifa_msghdr *)rtm;
>                       if ((ifam->ifam_addrs & (RTA_NETMASK | RTA_IFA |
>                           RTA_BRD)) == 0)
>                               break;
> -                     sa = (struct sockaddr *)(ifam + 1);
> -                     get_rtaddrs(ifam->ifam_addrs, sa, rti_info);
>  
>                       if_newaddr(ifam->ifam_index,
>                           (struct sockaddr_in6 *)rti_info[RTAX_IFA],
> @@ -1576,8 +1469,6 @@ add:
>                       if ((ifam->ifam_addrs & (RTA_NETMASK | RTA_IFA |
>                           RTA_BRD)) == 0)
>                               break;
> -                     sa = (struct sockaddr *)(ifam + 1);
> -                     get_rtaddrs(ifam->ifam_addrs, sa, rti_info);
>  
>                       if_deladdr(ifam->ifam_index,
>                           (struct sockaddr_in6 *)rti_info[RTAX_IFA],
> @@ -1592,5 +1483,5 @@ add:
>                       break;
>               }
>       }
> -     return (0);
> +     return (offset);
>  }

Reply via email to