-/* $OpenBSD: route.c,v 1.209 2015/04/20 09:12:57 mpi Exp $ */
+/* $OpenBSD: route.c,v 1.210 2015/05/15 12:00:57 claudio Exp $ */
/* $NetBSD: route.c,v 1.14 1996/02/13 22:00:46 christos Exp $ */
/*
return (error);
}
+static inline int
+rtequal(struct rtentry *a, struct rtentry *b)
+{
+ if (memcmp(rt_key(a), rt_key(b), rt_key(a)->sa_len) == 0 &&
+ memcmp(rt_mask(a), rt_mask(b), rt_mask(a)->sa_len) == 0)
+ return 1;
+ else
+ return 0;
+}
+
int
rtflushclone1(struct radix_node *rn, void *arg, u_int id)
{
rt = (struct rtentry *)rn;
parent = (struct rtentry *)arg;
- if ((rt->rt_flags & RTF_CLONED) != 0 && rt->rt_parent == parent)
+ if ((rt->rt_flags & RTF_CLONED) != 0 && (rt->rt_parent == parent ||
+ rtequal(rt->rt_parent, parent)))
rtdeletemsg(rt, id);
return 0;
}
{
struct rtentry *rt, *nrt = NULL;
struct sockaddr_rtlabel sa_rl;
+ struct sockaddr_dl sa_dl = { sizeof(sa_dl), AF_LINK };
struct rt_addrinfo info;
u_short rtableid = ifa->ifa_ifp->if_rdomain;
- u_int8_t prio = RTP_CONNECTED;
+ u_int8_t prio = ifa->ifa_ifp->if_priority + RTP_STATIC;
int error;
+ sa_dl.sdl_type = ifa->ifa_ifp->if_type;
+ sa_dl.sdl_index = ifa->ifa_ifp->if_index;
+
memset(&info, 0, sizeof(info));
info.rti_ifa = ifa;
- info.rti_flags = flags;
+ info.rti_flags = flags | RTF_MPATH;
info.rti_info[RTAX_DST] = dst;
- info.rti_info[RTAX_GATEWAY] = ifa->ifa_addr;
+ info.rti_info[RTAX_GATEWAY] = (struct sockaddr *)&sa_dl;
info.rti_info[RTAX_LABEL] =
rtlabel_id2sa(ifa->ifa_ifp->if_rtlabelid, &sa_rl);
struct sockaddr *deldst;
struct rt_addrinfo info;
struct sockaddr_rtlabel sa_rl;
+ struct sockaddr_dl sa_dl = { sizeof(sa_dl), AF_LINK };
u_short rtableid = ifa->ifa_ifp->if_rdomain;
- u_int8_t prio = RTP_CONNECTED;
+ u_int8_t prio = ifa->ifa_ifp->if_priority + RTP_STATIC;
int error;
#ifdef MPLS
}
}
+ sa_dl.sdl_type = ifa->ifa_ifp->if_type;
+ sa_dl.sdl_index = ifa->ifa_ifp->if_index;
+
memset(&info, 0, sizeof(info));
info.rti_ifa = ifa;
info.rti_flags = flags;
info.rti_info[RTAX_DST] = dst;
+ info.rti_info[RTAX_GATEWAY] = (struct sockaddr *)&sa_dl;
info.rti_info[RTAX_LABEL] =
rtlabel_id2sa(ifa->ifa_ifp->if_rtlabelid, &sa_rl);
}
} else {
if (rt->rt_flags & RTF_UP) {
+ /*
+ * Remove cloned routes (mainly arp) to
+ * down interfaces so we have a chance to
+ * clone a new route from a better source.
+ */
+ if (rt->rt_flags & RTF_CLONED) {
+ rtdeletemsg(rt, id);
+ return (0);
+ }
/* take route down */
rt->rt_flags &= ~RTF_UP;
rn_mpath_reprio(rn, rt->rt_priority | RTP_DOWN);
-/* $OpenBSD: if_ether.c,v 1.151 2015/04/22 04:12:22 jsg Exp $ */
+/* $OpenBSD: if_ether.c,v 1.152 2015/05/15 12:00:57 claudio Exp $ */
/* $NetBSD: if_ether.c,v 1.31 1996/05/11 12:59:58 mycroft Exp $ */
/*
int db_show_radix_node(struct radix_node *, void *, u_int);
#endif
-static const struct sockaddr_dl null_sdl = { sizeof(null_sdl), AF_LINK };
-
/*
* Timeout routine. Age arp_tab entries periodically.
*/
rt->rt_flags |= RTF_CLONING;
if (rt->rt_flags & RTF_CLONING ||
((rt->rt_flags & (RTF_LLINFO | RTF_LOCAL)) && !la)) {
- /*
- * Case 1: This route should come from a route to iface.
- */
- rt_setgate(rt, (struct sockaddr *)&null_sdl,
- ifp->if_rdomain);
- gate = rt->rt_gateway;
- SDL(gate)->sdl_type = ifp->if_type;
- SDL(gate)->sdl_index = ifp->if_index;
/*
* Give this route an expiration time, even though
* it's a "permanent" route, so that routes cloned
}
if (ifa) {
rt->rt_expire = 0;
- SDL(gate)->sdl_alen = ETHER_ADDR_LEN;
- memcpy(LLADDR(SDL(gate)),
- ((struct arpcom *)ifp)->ac_enaddr, ETHER_ADDR_LEN);
-
/*
* XXX Since lo0 is in the default rdomain we
* should not (ab)use it for any route related
-/* $OpenBSD: in.c,v 1.115 2015/01/12 13:51:45 mpi Exp $ */
+/* $OpenBSD: in.c,v 1.116 2015/05/15 12:00:57 claudio Exp $ */
/* $NetBSD: in.c,v 1.26 1996/02/13 23:41:39 christos Exp $ */
/*
struct ifnet *);
void in_purgeaddr(struct ifaddr *);
-int in_addprefix(struct in_ifaddr *);
-int in_scrubprefix(struct in_ifaddr *);
int in_addhost(struct in_ifaddr *, struct sockaddr_in *);
int in_scrubhost(struct in_ifaddr *, struct sockaddr_in *);
int in_insert_prefix(struct in_ifaddr *);
if (ISSET(ifp->if_flags, IFF_POINTOPOINT))
in_scrubhost(ia, &ia->ia_dstaddr);
else if (!ISSET(ifp->if_flags, IFF_LOOPBACK))
- in_scrubprefix(ia);
+ if (ia->ia_flags & IFA_ROUTE)
+ in_remove_prefix(ia);
}
/*
goto out;
error = in_addhost(ia, &ia->ia_dstaddr);
} else if (!ISSET(ifp->if_flags, IFF_LOOPBACK)) {
- error = in_addprefix(ia);
+ error = in_insert_prefix(ia);
}
/*
ia->ia_flags &= ~IFA_ROUTE;
}
-/*
- * add a route to prefix ("connected route" in cisco terminology).
- * does nothing if there's some interface address with the same prefix already.
- */
-int
-in_addprefix(struct in_ifaddr *ia0)
-{
- struct ifnet *ifp;
- struct ifaddr *ifa;
- struct in_ifaddr *ia;
- struct in_addr prefix, mask, p, m;
-
- prefix = ia0->ia_addr.sin_addr;
- mask = ia0->ia_sockmask.sin_addr;
- prefix.s_addr &= mask.s_addr;
-
- TAILQ_FOREACH(ifp, &ifnet, if_list) {
- if (ifp->if_flags & (IFF_LOOPBACK|IFF_POINTOPOINT))
- continue;
-
- if (ifp->if_rdomain != ia0->ia_ifp->if_rdomain)
- continue;
-
- TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
- if (ifa->ifa_addr->sa_family != AF_INET)
- continue;
-
- ia = ifatoia(ifa);
-
- if ((ia->ia_flags & IFA_ROUTE) == 0)
- continue;
-
- p = ia->ia_addr.sin_addr;
- m = ia->ia_sockmask.sin_addr;
- p.s_addr &= m.s_addr;
-
- if (prefix.s_addr != p.s_addr ||
- mask.s_addr != m.s_addr)
- continue;
-
-#if NCARP > 0
- /* move to a real interface instead of carp interface */
- if (ia->ia_ifp->if_type == IFT_CARP &&
- ia0->ia_ifp->if_type != IFT_CARP) {
- in_remove_prefix(ia);
- break;
- }
-#endif
- /*
- * If we got a matching prefix route inserted by other
- * interface address, we don't need to bother
- */
- return (0);
- }
- }
-
- /*
- * noone seem to have prefix route. insert it.
- */
- return in_insert_prefix(ia0);
-}
-
-/*
- * remove a route to prefix ("connected route" in cisco terminology).
- * re-installs the route by using another interface address, if there's one
- * with the same prefix (otherwise we lose the route mistakenly).
- */
-int
-in_scrubprefix(struct in_ifaddr *ia0)
-{
- struct ifnet *ifp;
- struct ifaddr *ifa;
- struct in_ifaddr *ia;
- struct in_addr prefix, mask, p, m;
-
- if ((ia0->ia_flags & IFA_ROUTE) == 0)
- return 0;
-
- prefix = ia0->ia_addr.sin_addr;
- mask = ia0->ia_sockmask.sin_addr;
- prefix.s_addr &= mask.s_addr;
-
- TAILQ_FOREACH(ifp, &ifnet, if_list) {
- if (ifp->if_flags & (IFF_LOOPBACK|IFF_POINTOPOINT))
- continue;
-
- if (ifp->if_rdomain != ia0->ia_ifp->if_rdomain)
- continue;
-
- TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
- if (ifa->ifa_addr->sa_family != AF_INET)
- continue;
-
- ia = ifatoia(ifa);
-
- if ((ia->ia_flags & IFA_ROUTE) != 0)
- continue;
-
- p = ia->ia_addr.sin_addr;
- m = ia->ia_sockmask.sin_addr;
- p.s_addr &= m.s_addr;
-
- if (prefix.s_addr != p.s_addr ||
- mask.s_addr != m.s_addr)
- continue;
-
- /* Move IFA_ROUTE to the matching prefix route. */
- in_remove_prefix(ia0);
- return (in_insert_prefix(ia));
- }
- }
-
- /*
- * noone seem to have prefix route. remove it.
- */
- in_remove_prefix(ia0);
- return 0;
-}
-
/*
* Return 1 if the address is a local broadcast address.
*/
-/* $OpenBSD: in6.c,v 1.156 2015/04/20 09:07:42 mpi Exp $ */
+/* $OpenBSD: in6.c,v 1.157 2015/05/15 12:00:57 claudio Exp $ */
/* $KAME: in6.c,v 1.372 2004/06/14 08:14:21 itojun Exp $ */
/*
#include <sys/syslog.h>
#include <net/if.h>
+#include <net/if_dl.h>
#include <net/if_types.h>
#include <net/route.h>
/* 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;
bzero(&info, sizeof(info));
info.rti_info[RTAX_DST] = sin6tosa(&mltaddr);
- info.rti_info[RTAX_GATEWAY] = sin6tosa(&ia6->ia_addr);
+ info.rti_info[RTAX_GATEWAY] = (struct sockaddr *)&sa_dl;
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 */
bzero(&info, sizeof(info));
info.rti_info[RTAX_DST] = sin6tosa(&mltaddr);
- info.rti_info[RTAX_GATEWAY] = sin6tosa(&ia6->ia_addr);
+ info.rti_info[RTAX_GATEWAY] = (struct sockaddr *)&sa_dl;
info.rti_info[RTAX_NETMASK] = sin6tosa(&mltmask);
info.rti_info[RTAX_IFA] = sin6tosa(&ia6->ia_addr);
info.rti_flags = RTF_UP | RTF_CLONING;
-/* $OpenBSD: nd6.c,v 1.135 2015/04/27 14:51:44 mpi Exp $ */
+/* $OpenBSD: nd6.c,v 1.136 2015/05/15 12:00:57 claudio Exp $ */
/* $KAME: nd6.c,v 1.280 2002/06/08 19:52:07 itojun Exp $ */
/*
}
if (!rt) {
if (create && ifp) {
+ struct sockaddr_dl sa_dl = { sizeof(sa_dl), AF_LINK };
struct rt_addrinfo info;
int e;
if (ifa == NULL)
return (NULL);
+ sa_dl.sdl_type = ifp->if_type;
+ sa_dl.sdl_index = ifp->if_index;
+
/*
* Create a new route. RTF_LLINFO is necessary
* to create a Neighbor Cache entry for the
bzero(&info, sizeof(info));
info.rti_flags = RTF_UP | RTF_HOST | RTF_LLINFO;
info.rti_info[RTAX_DST] = sin6tosa(&sin6);
- info.rti_info[RTAX_GATEWAY] = ifa->ifa_addr;
+ info.rti_info[RTAX_GATEWAY] = (struct sockaddr *)&sa_dl;
if ((e = rtrequest1(RTM_ADD, &info, RTP_CONNECTED,
&rt, rtableid)) != 0) {
#if 0
{
struct sockaddr *gate = rt->rt_gateway;
struct llinfo_nd6 *ln = (struct llinfo_nd6 *)rt->rt_llinfo;
- static struct sockaddr_dl null_sdl = {sizeof(null_sdl), AF_LINK};
struct ifnet *ifp = rt->rt_ifp;
struct ifaddr *ifa;
struct nd_defrouter *dr;
*/
if ((rt->rt_flags & RTF_CLONING) ||
((rt->rt_flags & (RTF_LLINFO | RTF_LOCAL)) && !ln)) {
- /*
- * Case 1: This route should come from a route to
- * interface (RTF_CLONING case) or the route should be
- * treated as on-link but is currently not
- * (RTF_LLINFO && !ln case).
- */
- rt_setgate(rt, (struct sockaddr *)&null_sdl,
- ifp->if_rdomain);
- gate = rt->rt_gateway;
- SDL(gate)->sdl_type = ifp->if_type;
- SDL(gate)->sdl_index = ifp->if_index;
if (ln)
nd6_llinfo_settimer(ln, 0);
if ((rt->rt_flags & RTF_CLONING) != 0)
/* FALLTHROUGH */
case RTM_RESOLVE:
if (gate->sa_family != AF_LINK ||
- gate->sa_len < sizeof(null_sdl)) {
+ gate->sa_len < sizeof(struct sockaddr_dl)) {
log(LOG_DEBUG, "%s: bad gateway value: %s\n",
__func__, ifp->if_xname);
break;
ifa = &in6ifa_ifpwithaddr(ifp,
&satosin6(rt_key(rt))->sin6_addr)->ia_ifa;
if (ifa) {
- caddr_t macp = nd6_ifptomac(ifp);
nd6_llinfo_settimer(ln, -1);
ln->ln_state = ND6_LLINFO_REACHABLE;
ln->ln_byhint = 0;
- if (macp) {
- memcpy(LLADDR(SDL(gate)), macp, ifp->if_addrlen);
- SDL(gate)->sdl_alen = ifp->if_addrlen;
- }
/*
* XXX Since lo0 is in the default rdomain we
-/* $OpenBSD: nd6_rtr.c,v 1.102 2015/04/27 14:51:44 mpi Exp $ */
+/* $OpenBSD: nd6_rtr.c,v 1.103 2015/05/15 12:00:57 claudio Exp $ */
/* $KAME: nd6_rtr.c,v 1.97 2001/02/07 11:09:13 itojun Exp $ */
/*
#include <sys/queue.h>
#include <net/if.h>
+#include <net/if_dl.h>
#include <net/if_var.h>
#include <net/if_types.h>
#include <net/route.h>
struct ifaddr *ifa;
struct ifnet *ifp = pr->ndpr_ifp;
struct sockaddr_in6 mask6;
+ struct sockaddr_dl sa_dl = { sizeof(sa_dl), AF_LINK };
struct nd_prefix *opr;
u_long rtflags;
int error = 0;
bzero(&mask6, sizeof(mask6));
mask6.sin6_len = sizeof(mask6);
mask6.sin6_addr = pr->ndpr_mask;
+
+ sa_dl.sdl_type = ifp->if_type;
+ sa_dl.sdl_index = ifp->if_index;
+
/* rtrequest1() will probably set RTF_UP, but we're not sure. */
rtflags = RTF_UP;
if (nd6_need_cache(ifp))
bzero(&info, sizeof(info));
info.rti_flags = rtflags;
info.rti_info[RTAX_DST] = sin6tosa(&pr->ndpr_prefix);
- info.rti_info[RTAX_GATEWAY] = ifa->ifa_addr;
+ info.rti_info[RTAX_GATEWAY] = (struct sockaddr *)&sa_dl;
info.rti_info[RTAX_NETMASK] = sin6tosa(&mask6);
error = rtrequest1(RTM_ADD, &info, RTP_CONNECTED, &rt, ifp->if_rdomain);