diff options
-rw-r--r-- | sys/net/route.c | 46 | ||||
-rw-r--r-- | sys/netinet/if_ether.c | 8 | ||||
-rw-r--r-- | sys/netinet/in.c | 9 |
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); |