From 3ccf3a0f61993a61ae5d28856dfc5b5486a69a81 Mon Sep 17 00:00:00 2001 From: mpi Date: Tue, 26 May 2015 12:19:51 +0000 Subject: [PATCH] Store the IP address of the corresponding ifa in the rt_gateway field of RTF_CLONING and RTF_BROASCAST routes to not create MPATH conflicts when IP address aliases are used. This change makes it possible to have multiple RTF_CLONING routes with the same priority. Note that any of the existing RTF_CLONING route might be used by the kernel to create a RTF_CLONED route which should not be a problem with aliases since they are attached to the same ifp. This unbreak address aliases since the kernel supports multiple connected routes for a subnet. Found the hardway by djm@, ok claudio@ --- sys/net/route.c | 16 ++++++++++++---- sys/netinet/in.c | 9 ++++----- sys/netinet6/in6.c | 10 +++------- sys/netinet6/nd6_rtr.c | 4 ++-- 4 files changed, 21 insertions(+), 18 deletions(-) diff --git a/sys/net/route.c b/sys/net/route.c index d364fa93296..dc510860670 100644 --- a/sys/net/route.c +++ b/sys/net/route.c @@ -1,4 +1,4 @@ -/* $OpenBSD: route.c,v 1.211 2015/05/26 12:02:11 mpi Exp $ */ +/* $OpenBSD: route.c,v 1.212 2015/05/26 12:19:51 mpi Exp $ */ /* $NetBSD: route.c,v 1.14 1996/02/13 22:00:46 christos Exp $ */ /* @@ -729,6 +729,7 @@ rtrequest1(int req, struct rt_addrinfo *info, u_int8_t prio, struct ifaddr *ifa; struct sockaddr *ndst; struct sockaddr_rtlabel *sa_rl, sa_rl2; + struct sockaddr_dl sa_dl = { sizeof(sa_dl), AF_LINK }; int dlen, error; #ifdef MPLS struct sockaddr_mpls *sa_mpls; @@ -827,9 +828,10 @@ rtrequest1(int req, struct rt_addrinfo *info, u_int8_t prio, info->rti_ifa = NULL; info->rti_info[RTAX_IFA] = rt->rt_ifa->ifa_addr; } + info->rti_flags = rt->rt_flags & ~(RTF_CLONING | RTF_STATIC); info->rti_flags |= RTF_CLONED; - info->rti_info[RTAX_GATEWAY] = rt->rt_gateway; + info->rti_info[RTAX_GATEWAY] = (struct sockaddr *)&sa_dl; info->rti_flags |= RTF_HOST; info->rti_info[RTAX_LABEL] = rtlabel_id2sa(rt->rt_labelid, &sa_rl2); @@ -1134,7 +1136,10 @@ rt_ifa_add(struct ifaddr *ifa, int flags, struct sockaddr *dst) info.rti_ifa = ifa; info.rti_flags = flags | RTF_MPATH; info.rti_info[RTAX_DST] = dst; - info.rti_info[RTAX_GATEWAY] = (struct sockaddr *)&sa_dl; + if (flags & RTF_LLINFO) + info.rti_info[RTAX_GATEWAY] = (struct sockaddr *)&sa_dl; + else + info.rti_info[RTAX_GATEWAY] = ifa->ifa_addr; info.rti_info[RTAX_LABEL] = rtlabel_id2sa(ifa->ifa_ifp->if_rtlabelid, &sa_rl); @@ -1229,7 +1234,10 @@ rt_ifa_del(struct ifaddr *ifa, int flags, struct sockaddr *dst) info.rti_ifa = ifa; info.rti_flags = flags; info.rti_info[RTAX_DST] = dst; - info.rti_info[RTAX_GATEWAY] = (struct sockaddr *)&sa_dl; + if (flags & RTF_LLINFO) + info.rti_info[RTAX_GATEWAY] = (struct sockaddr *)&sa_dl; + else + info.rti_info[RTAX_GATEWAY] = ifa->ifa_addr; info.rti_info[RTAX_LABEL] = rtlabel_id2sa(ifa->ifa_ifp->if_rtlabelid, &sa_rl); diff --git a/sys/netinet/in.c b/sys/netinet/in.c index 91636b9390b..c741c80b8a2 100644 --- a/sys/netinet/in.c +++ b/sys/netinet/in.c @@ -1,4 +1,4 @@ -/* $OpenBSD: in.c,v 1.116 2015/05/15 12:00:57 claudio Exp $ */ +/* $OpenBSD: in.c,v 1.117 2015/05/26 12:19:51 mpi Exp $ */ /* $NetBSD: in.c,v 1.26 1996/02/13 23:41:39 christos Exp $ */ /* @@ -737,8 +737,8 @@ in_insert_prefix(struct in_ifaddr *ia) return (error); if (ia->ia_broadaddr.sin_addr.s_addr != 0) - error = rt_ifa_add(ifa, RTF_UP | RTF_HOST | - RTF_LLINFO | RTF_BROADCAST, ifa->ifa_broadaddr); + error = rt_ifa_add(ifa, RTF_UP | RTF_HOST | RTF_BROADCAST, + ifa->ifa_broadaddr); if (!error) ia->ia_flags |= IFA_ROUTE; @@ -754,8 +754,7 @@ in_remove_prefix(struct in_ifaddr *ia) rt_ifa_del(ifa, 0, ifa->ifa_addr); if (ia->ia_broadaddr.sin_addr.s_addr != 0) - rt_ifa_del(ifa, RTF_HOST | RTF_LLINFO | RTF_BROADCAST, - ifa->ifa_broadaddr); + rt_ifa_del(ifa, RTF_HOST | RTF_BROADCAST, ifa->ifa_broadaddr); ia->ia_flags &= ~IFA_ROUTE; } diff --git a/sys/netinet6/in6.c b/sys/netinet6/in6.c index 951476450be..d2c97378295 100644 --- a/sys/netinet6/in6.c +++ b/sys/netinet6/in6.c @@ -1,4 +1,4 @@ -/* $OpenBSD: in6.c,v 1.157 2015/05/15 12:00:57 claudio Exp $ */ +/* $OpenBSD: in6.c,v 1.158 2015/05/26 12:19:52 mpi Exp $ */ /* $KAME: in6.c,v 1.372 2004/06/14 08:14:21 itojun Exp $ */ /* @@ -828,10 +828,6 @@ in6_update_ifa(struct ifnet *ifp, struct in6_aliasreq *ifra, /* join solicited multicast addr for new host id */ struct sockaddr_in6 llsol; - struct sockaddr_dl sa_dl = { sizeof(sa_dl), AF_LINK }; - - sa_dl.sdl_type = ifp->if_type; - sa_dl.sdl_index = ifp->if_index; bzero(&llsol, sizeof(llsol)); llsol.sin6_family = AF_INET6; @@ -892,7 +888,7 @@ in6_update_ifa(struct ifnet *ifp, struct in6_aliasreq *ifra, bzero(&info, sizeof(info)); info.rti_info[RTAX_DST] = sin6tosa(&mltaddr); - info.rti_info[RTAX_GATEWAY] = (struct sockaddr *)&sa_dl; + info.rti_info[RTAX_GATEWAY] = sin6tosa(&ia6->ia_addr); info.rti_info[RTAX_NETMASK] = sin6tosa(&mltmask); info.rti_info[RTAX_IFA] = sin6tosa(&ia6->ia_addr); /* XXX: we need RTF_CLONING to fake nd6_rtrequest */ @@ -961,7 +957,7 @@ in6_update_ifa(struct ifnet *ifp, struct in6_aliasreq *ifra, bzero(&info, sizeof(info)); info.rti_info[RTAX_DST] = sin6tosa(&mltaddr); - info.rti_info[RTAX_GATEWAY] = (struct sockaddr *)&sa_dl; + info.rti_info[RTAX_GATEWAY] = sin6tosa(&ia6->ia_addr); info.rti_info[RTAX_NETMASK] = sin6tosa(&mltmask); info.rti_info[RTAX_IFA] = sin6tosa(&ia6->ia_addr); info.rti_flags = RTF_UP | RTF_CLONING; diff --git a/sys/netinet6/nd6_rtr.c b/sys/netinet6/nd6_rtr.c index 50797c5004a..deb7ff826d0 100644 --- a/sys/netinet6/nd6_rtr.c +++ b/sys/netinet6/nd6_rtr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: nd6_rtr.c,v 1.103 2015/05/15 12:00:57 claudio Exp $ */ +/* $OpenBSD: nd6_rtr.c,v 1.104 2015/05/26 12:19:52 mpi Exp $ */ /* $KAME: nd6_rtr.c,v 1.97 2001/02/07 11:09:13 itojun Exp $ */ /* @@ -1739,7 +1739,7 @@ nd6_prefix_onlink(struct nd_prefix *pr) bzero(&info, sizeof(info)); info.rti_flags = rtflags; info.rti_info[RTAX_DST] = sin6tosa(&pr->ndpr_prefix); - info.rti_info[RTAX_GATEWAY] = (struct sockaddr *)&sa_dl; + info.rti_info[RTAX_GATEWAY] = ifa->ifa_addr; info.rti_info[RTAX_NETMASK] = sin6tosa(&mask6); error = rtrequest1(RTM_ADD, &info, RTP_CONNECTED, &rt, ifp->if_rdomain); -- 2.20.1