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