summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/net/route.c46
-rw-r--r--sys/netinet/if_ether.c8
-rw-r--r--sys/netinet/in.c9
3 files changed, 55 insertions, 8 deletions
diff --git a/sys/net/route.c b/sys/net/route.c
index 7601cb56900..65e716236a2 100644
--- a/sys/net/route.c
+++ b/sys/net/route.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: route.c,v 1.171 2014/06/16 19:47:21 mpi Exp $ */
+/* $OpenBSD: route.c,v 1.172 2014/07/12 14:26:00 mpi Exp $ */
/* $NetBSD: route.c,v 1.14 1996/02/13 22:00:46 christos Exp $ */
/*
@@ -1129,7 +1129,8 @@ rt_ifa_add(struct ifaddr *ifa, int flags, struct sockaddr *dst)
if (ifa->ifa_rtrequest)
ifa->ifa_rtrequest(RTM_ADD, rt);
}
- rt_newaddrmsg(RTM_ADD, ifa, error, nrt);
+ if (flags & RTF_LOCAL)
+ rt_newaddrmsg(RTM_ADD, ifa, error, nrt);
}
return (error);
}
@@ -1183,7 +1184,8 @@ rt_ifa_del(struct ifaddr *ifa, int flags, struct sockaddr *dst)
error = rtrequest1(RTM_DELETE, &info, prio, &nrt, rtableid);
if (error == 0 && (rt = nrt) != NULL) {
- rt_newaddrmsg(RTM_DELETE, ifa, error, nrt);
+ if (flags & RTF_LOCAL)
+ rt_newaddrmsg(RTM_DELETE, ifa, error, nrt);
if (rt->rt_refcnt <= 0) {
rt->rt_refcnt++;
rtfree(rt);
@@ -1203,6 +1205,26 @@ rt_ifa_addloop(struct ifaddr *ifa)
{
struct rtentry *rt;
+ /*
+ * If the configured address correspond to the magical "any"
+ * address do not add a local route entry because that might
+ * corrupt the routing tree which uses this value for the
+ * default routes.
+ */
+ switch (ifa->ifa_addr->sa_family) {
+ case AF_INET:
+ if (satosin(ifa->ifa_addr)->sin_addr.s_addr == INADDR_ANY)
+ return;
+ break;
+ case AF_INET6:
+ if (IN6_ARE_ADDR_EQUAL(&satosin6(ifa->ifa_addr)->sin6_addr,
+ &in6addr_any))
+ return;
+ break;
+ default:
+ break;
+ }
+
/* If there is no loopback entry, allocate one. */
rt = rtalloc1(ifa->ifa_addr, 0, ifa->ifa_ifp->if_rdomain);
if (rt == NULL || (rt->rt_flags & RTF_HOST) == 0 ||
@@ -1222,6 +1244,24 @@ rt_ifa_delloop(struct ifaddr *ifa)
struct rtentry *rt;
/*
+ * We do not add local routes for such address, so do not bother
+ * removing them.
+ */
+ switch (ifa->ifa_addr->sa_family) {
+ case AF_INET:
+ if (satosin(ifa->ifa_addr)->sin_addr.s_addr == INADDR_ANY)
+ return;
+ break;
+ case AF_INET6:
+ if (IN6_ARE_ADDR_EQUAL(&satosin6(ifa->ifa_addr)->sin6_addr,
+ &in6addr_any))
+ return;
+ break;
+ default:
+ break;
+ }
+
+ /*
* Before deleting, check if a corresponding loopbacked host
* route surely exists. With this check, we can avoid to
* delete an interface direct route whose destination is same
diff --git a/sys/netinet/if_ether.c b/sys/netinet/if_ether.c
index 0edf1a9c6de..b3c7b813469 100644
--- a/sys/netinet/if_ether.c
+++ b/sys/netinet/if_ether.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_ether.c,v 1.129 2014/06/16 19:47:21 mpi Exp $ */
+/* $OpenBSD: if_ether.c,v 1.130 2014/07/12 14:26:00 mpi Exp $ */
/* $NetBSD: if_ether.c,v 1.31 1996/05/11 12:59:58 mycroft Exp $ */
/*
@@ -174,7 +174,8 @@ arp_rtrequest(int req, struct rtentry *rt)
if ((rt->rt_flags & RTF_HOST) == 0 && rt_mask(rt) &&
satosin(rt_mask(rt))->sin_addr.s_addr != 0xffffffff)
rt->rt_flags |= RTF_CLONING;
- if (rt->rt_flags & RTF_CLONING) {
+ if (rt->rt_flags & RTF_CLONING ||
+ ((rt->rt_flags & RTF_LLINFO) && !la)) {
/*
* Case 1: This route should come from a route to iface.
*/
@@ -189,7 +190,8 @@ arp_rtrequest(int req, struct rtentry *rt)
* from it do not need their expiration time set.
*/
rt->rt_expire = time_second;
- break;
+ if ((rt->rt_flags & RTF_CLONING) != 0)
+ break;
}
/* Announce a new entry if requested. */
if (rt->rt_flags & RTF_ANNOUNCE)
diff --git a/sys/netinet/in.c b/sys/netinet/in.c
index 425b408c376..70e1a8d4e67 100644
--- a/sys/netinet/in.c
+++ b/sys/netinet/in.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: in.c,v 1.99 2014/06/26 13:08:25 mpi Exp $ */
+/* $OpenBSD: in.c,v 1.100 2014/07/12 14:26:00 mpi Exp $ */
/* $NetBSD: in.c,v 1.26 1996/02/13 23:41:39 christos Exp $ */
/*
@@ -619,8 +619,10 @@ in_ifinit(struct ifnet *ifp, struct in_ifaddr *ia, struct sockaddr_in *sin,
* Always remove the address from the tree to make sure its
* position gets updated in case the key changes.
*/
- if (!newaddr)
+ if (!newaddr) {
+ rt_ifa_delloop(&ia->ia_ifa);
ifa_del(ifp, &ia->ia_ifa);
+ }
oldaddr = ia->ia_addr;
ia->ia_addr = *sin;
@@ -702,6 +704,7 @@ out:
* carp(4).
*/
ifa_add(ifp, &ia->ia_ifa);
+ rt_ifa_addloop(&ia->ia_ifa);
if (error && newaddr)
in_purgeaddr(&ia->ia_ifa);
@@ -719,7 +722,9 @@ in_purgeaddr(struct ifaddr *ifa)
in_ifscrub(ifp, ia);
+ rt_ifa_delloop(&ia->ia_ifa);
ifa_del(ifp, &ia->ia_ifa);
+
TAILQ_REMOVE(&in_ifaddr, ia, ia_list);
if (ia->ia_allhosts != NULL) {
in_delmulti(ia->ia_allhosts);