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.

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