Introduce the routing flag RTF_LOCAL to track local address routes.
Add functions rt_ifa_addlocal() and rt_ifa_remlocal() to add and remove local routes for the address and announce the new address and route to the routing socket. Add in_ifaddlocal() and in_ifremlocal() to use these functions. Rename in6_if{add,rem}loop() to in6_if{add,rem}local() and use these functions. rtinit() no longer announces the address, just the network route for the address. As such, calls to rt_newaddrmsg() have been removed from in_addprefix() and in_scrubprefix(). This solves the problem of potentially more than one announcement, or no announcement at all for the address in certain situations.
This commit is contained in:
parent
9ce3434ff9
commit
42900924fd
131
sys/net/route.c
131
sys/net/route.c
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: route.c,v 1.135 2015/02/25 12:45:34 roy Exp $ */
|
||||
/* $NetBSD: route.c,v 1.136 2015/02/26 09:54:46 roy Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1998, 2008 The NetBSD Foundation, Inc.
|
||||
@ -90,10 +90,11 @@
|
||||
* @(#)route.c 8.3 (Berkeley) 1/9/95
|
||||
*/
|
||||
|
||||
#include "opt_inet.h"
|
||||
#include "opt_route.h"
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: route.c,v 1.135 2015/02/25 12:45:34 roy Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: route.c,v 1.136 2015/02/26 09:54:46 roy Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/kmem.h>
|
||||
@ -960,7 +961,7 @@ rtinit(struct ifaddr *ifa, int cmd, int flags)
|
||||
;
|
||||
else switch (cmd) {
|
||||
case RTM_DELETE:
|
||||
rt_newaddrmsg(cmd, ifa, error, nrt);
|
||||
rt_newmsg(cmd, nrt);
|
||||
if (rt->rt_refcnt <= 0) {
|
||||
rt->rt_refcnt++;
|
||||
rtfree(rt);
|
||||
@ -984,7 +985,7 @@ rtinit(struct ifaddr *ifa, int cmd, int flags)
|
||||
|
||||
if (cmd == RTM_LLINFO_UPD && ifa->ifa_rtrequest != NULL)
|
||||
ifa->ifa_rtrequest(RTM_LLINFO_UPD, rt, &info);
|
||||
rt_newaddrmsg(RTM_CHANGE, ifa, error, nrt);
|
||||
rt_newmsg(RTM_CHANGE, nrt);
|
||||
break;
|
||||
case RTM_ADD:
|
||||
rt->rt_refcnt--;
|
||||
@ -1000,12 +1001,132 @@ rtinit(struct ifaddr *ifa, int cmd, int flags)
|
||||
if (ifa->ifa_rtrequest != NULL)
|
||||
ifa->ifa_rtrequest(RTM_ADD, rt, &info);
|
||||
}
|
||||
rt_newaddrmsg(cmd, ifa, error, nrt);
|
||||
rt_newmsg(cmd, nrt);
|
||||
break;
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
static const struct in_addr inmask32 = {.s_addr = INADDR_BROADCAST};
|
||||
|
||||
/* Subroutine for rt_ifa_addlocal() and rt_ifa_remlocal() */
|
||||
static int
|
||||
rt_ifa_localrequest(int cmd, struct ifaddr *ifa)
|
||||
{
|
||||
struct sockaddr *all1_sa;
|
||||
struct sockaddr_in all1_sin;
|
||||
#ifdef INET6
|
||||
struct sockaddr_in6 all1_sin6;
|
||||
#endif
|
||||
struct rtentry *nrt = NULL;
|
||||
int flags, e;
|
||||
|
||||
switch(ifa->ifa_addr->sa_family) {
|
||||
case AF_INET:
|
||||
sockaddr_in_init(&all1_sin, &inmask32, 0);
|
||||
all1_sa = (struct sockaddr *)&all1_sin;
|
||||
break;
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
sockaddr_in6_init(&all1_sin6, &in6mask128, 0, 0, 0);
|
||||
all1_sa = (struct sockaddr *)&all1_sin6;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
flags = RTF_UP | RTF_HOST | RTF_LOCAL;
|
||||
if (!(ifa->ifa_ifp->if_flags & (IFF_LOOPBACK | IFF_POINTOPOINT)))
|
||||
flags |= RTF_LLINFO;
|
||||
e = rtrequest(cmd, ifa->ifa_addr, ifa->ifa_addr, all1_sa, flags, &nrt);
|
||||
|
||||
/* Make sure rt_ifa be equal to IFA, the second argument of the
|
||||
* function. */
|
||||
if (cmd == RTM_ADD && nrt && ifa != nrt->rt_ifa)
|
||||
rt_replace_ifa(nrt, ifa);
|
||||
|
||||
rt_newaddrmsg(cmd, ifa, e, nrt);
|
||||
if (nrt) {
|
||||
if (cmd == RTM_DELETE) {
|
||||
if (nrt->rt_refcnt <= 0) {
|
||||
/* XXX: we should free the entry ourselves. */
|
||||
nrt->rt_refcnt++;
|
||||
rtfree(nrt);
|
||||
}
|
||||
} else {
|
||||
/* the cmd must be RTM_ADD here */
|
||||
nrt->rt_refcnt--;
|
||||
}
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a local route entry for the address.
|
||||
* Announce the addition of the address and the route to the routing socket.
|
||||
*/
|
||||
int
|
||||
rt_ifa_addlocal(struct ifaddr *ifa)
|
||||
{
|
||||
struct rtentry *rt;
|
||||
int e;
|
||||
|
||||
/* If there is no loopback entry, allocate one. */
|
||||
rt = rtalloc1(ifa->ifa_addr, 0);
|
||||
if (rt == NULL || (rt->rt_flags & RTF_HOST) == 0 ||
|
||||
(rt->rt_ifp->if_flags & IFF_LOOPBACK) == 0)
|
||||
e = rt_ifa_localrequest(RTM_ADD, ifa);
|
||||
else {
|
||||
e = 0;
|
||||
rt_newaddrmsg(RTM_NEWADDR, ifa, 0, NULL);
|
||||
}
|
||||
if (rt != NULL)
|
||||
rt->rt_refcnt--;
|
||||
return e;
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove the local route entry for the address.
|
||||
* Announce the removal of the address and the route to the routing socket.
|
||||
*/
|
||||
int
|
||||
rt_ifa_remlocal(struct ifaddr *ifa, struct ifaddr *alt_ifa)
|
||||
{
|
||||
struct rtentry *rt;
|
||||
int e = 0;
|
||||
|
||||
rt = rtalloc1(ifa->ifa_addr, 0);
|
||||
|
||||
/*
|
||||
* Before deleting, check if a corresponding loopbacked
|
||||
* host route surely exists. With this check, we can avoid
|
||||
* deleting an interface direct route whose destination is
|
||||
* the same as the address being removed. This can happen
|
||||
* when removing a subnet-router anycast address on an
|
||||
* interface attached to a shared medium.
|
||||
*/
|
||||
if (rt != NULL &&
|
||||
(rt->rt_flags & RTF_HOST) &&
|
||||
(rt->rt_ifp->if_flags & IFF_LOOPBACK))
|
||||
{
|
||||
/* If we cannot replace the route's ifaddr with the equivalent
|
||||
* ifaddr of another interface, I believe it is safest to
|
||||
* delete the route.
|
||||
*/
|
||||
if (alt_ifa == NULL)
|
||||
e = rt_ifa_localrequest(RTM_DELETE, ifa);
|
||||
else {
|
||||
rt_replace_ifa(rt, alt_ifa);
|
||||
rt_newmsg(RTM_CHANGE, rt);
|
||||
}
|
||||
} else
|
||||
rt_newaddrmsg(RTM_DELADDR, ifa, 0, NULL);
|
||||
if (rt != NULL)
|
||||
rt->rt_refcnt--;
|
||||
return e;
|
||||
}
|
||||
|
||||
/*
|
||||
* Route timer routines. These routes allow functions to be called
|
||||
* for various routes at any time. This is useful in supporting
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: route.h,v 1.86 2015/02/25 12:45:34 roy Exp $ */
|
||||
/* $NetBSD: route.h,v 1.87 2015/02/26 09:54:46 roy Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1980, 1986, 1993
|
||||
@ -155,6 +155,7 @@ struct ortentry {
|
||||
#define RTF_PROTO1 0x8000 /* protocol specific routing flag */
|
||||
#define RTF_SRC 0x10000 /* route has fixed source address */
|
||||
#define RTF_ANNOUNCE 0x20000 /* announce new ARP or NDP entry */
|
||||
#define RTF_LOCAL 0x40000 /* route represents a local address */
|
||||
|
||||
/*
|
||||
* Routing statistics.
|
||||
@ -504,6 +505,8 @@ struct rtentry *rt_lookup(rtbl_t *, const struct sockaddr *,
|
||||
struct rtentry *rt_deladdr(rtbl_t *, const struct sockaddr *,
|
||||
const struct sockaddr *);
|
||||
void rtbl_init(void);
|
||||
int rt_ifa_addlocal(struct ifaddr *);
|
||||
int rt_ifa_remlocal(struct ifaddr *, struct ifaddr *);
|
||||
rtbl_t *rt_gettable(sa_family_t);
|
||||
void rt_assert_inactive(const struct rtentry *);
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: if_arp.c,v 1.160 2014/11/13 16:11:18 christos Exp $ */
|
||||
/* $NetBSD: if_arp.c,v 1.161 2015/02/26 09:54:46 roy Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1998, 2000, 2008 The NetBSD Foundation, Inc.
|
||||
@ -68,7 +68,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: if_arp.c,v 1.160 2014/11/13 16:11:18 christos Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: if_arp.c,v 1.161 2015/02/26 09:54:46 roy Exp $");
|
||||
|
||||
#include "opt_ddb.h"
|
||||
#include "opt_inet.h"
|
||||
@ -453,7 +453,9 @@ arp_setgate(struct rtentry *rt, struct sockaddr *gate,
|
||||
if ((rt->rt_flags & RTF_HOST) == 0 && netmask != NULL &&
|
||||
satocsin(netmask)->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 | RTF_LOCAL)) && !rt->rt_llinfo))
|
||||
{
|
||||
union {
|
||||
struct sockaddr sa;
|
||||
struct sockaddr_storage ss;
|
||||
@ -554,7 +556,9 @@ arp_rtrequest(int req, struct rtentry *rt, const struct rt_addrinfo *info)
|
||||
break;
|
||||
case RTM_ADD:
|
||||
gate = arp_setgate(rt, gate, info->rti_info[RTAX_NETMASK]);
|
||||
if (rt->rt_flags & RTF_CLONING) {
|
||||
if (rt->rt_flags & RTF_CLONING ||
|
||||
((rt->rt_flags & (RTF_LLINFO | RTF_LOCAL)) && !la))
|
||||
{
|
||||
/*
|
||||
* Give this route an expiration time, even though
|
||||
* it's a "permanent" route, so that routes cloned
|
||||
@ -592,6 +596,7 @@ arp_rtrequest(int req, struct rtentry *rt, const struct rt_addrinfo *info)
|
||||
}
|
||||
#endif
|
||||
}
|
||||
if (rt->rt_flags & RTF_CLONING)
|
||||
break;
|
||||
}
|
||||
/* Announce a new entry if requested. */
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: in.c,v 1.149 2014/12/01 17:07:43 christos Exp $ */
|
||||
/* $NetBSD: in.c,v 1.150 2015/02/26 09:54:46 roy Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
|
||||
@ -91,7 +91,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: in.c,v 1.149 2014/12/01 17:07:43 christos Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: in.c,v 1.150 2015/02/26 09:54:46 roy Exp $");
|
||||
|
||||
#include "opt_inet.h"
|
||||
#include "opt_inet_conf.h"
|
||||
@ -602,6 +602,40 @@ in_control(struct socket *so, u_long cmd, void *data, struct ifnet *ifp)
|
||||
return error;
|
||||
}
|
||||
|
||||
/* Add ownaddr as loopback rtentry. */
|
||||
static void
|
||||
in_ifaddlocal(struct ifaddr *ifa)
|
||||
{
|
||||
|
||||
rt_ifa_addlocal(ifa);
|
||||
}
|
||||
|
||||
/* Rempve loopback entry of ownaddr */
|
||||
static void
|
||||
in_ifremlocal(struct ifaddr *ifa)
|
||||
{
|
||||
struct in_ifaddr *ia, *p;
|
||||
struct ifaddr *alt_ifa = NULL;
|
||||
int ia_count = 0;
|
||||
|
||||
ia = (struct in_ifaddr *)ifa;
|
||||
/* Delete the entry if exactly one ifaddr matches the
|
||||
* address, ifa->ifa_addr. */
|
||||
TAILQ_FOREACH(p, &in_ifaddrhead, ia_list) {
|
||||
if (!in_hosteq(p->ia_addr.sin_addr, ia->ia_addr.sin_addr))
|
||||
continue;
|
||||
if (p->ia_ifp != ia->ia_ifp)
|
||||
alt_ifa = &p->ia_ifa;
|
||||
if (++ia_count > 1 && alt_ifa != NULL)
|
||||
break;
|
||||
}
|
||||
|
||||
if (ia_count == 0)
|
||||
return;
|
||||
|
||||
rt_ifa_remlocal(ifa, ia_count == 1 ? NULL : alt_ifa);
|
||||
}
|
||||
|
||||
void
|
||||
in_purgeaddr(struct ifaddr *ifa)
|
||||
{
|
||||
@ -609,6 +643,7 @@ in_purgeaddr(struct ifaddr *ifa)
|
||||
struct in_ifaddr *ia = (void *) ifa;
|
||||
|
||||
in_ifscrub(ifp, ia);
|
||||
in_ifremlocal(ifa);
|
||||
LIST_REMOVE(ia, ia_hash);
|
||||
ifa_remove(ifp, &ia->ia_ifa);
|
||||
TAILQ_REMOVE(&in_ifaddrhead, ia, ia_list);
|
||||
@ -857,6 +892,9 @@ in_ifinit(struct ifnet *ifp, struct in_ifaddr *ia,
|
||||
ia->ia_ifa.ifa_addr = sintosa(&ia->ia_addr);
|
||||
}
|
||||
|
||||
/* Add the local route to the address */
|
||||
in_ifaddlocal(&ia->ia_ifa);
|
||||
|
||||
i = ia->ia_addr.sin_addr.s_addr;
|
||||
if (IN_CLASSA(i))
|
||||
ia->ia_netmask = IN_CLASSA_NET;
|
||||
@ -958,14 +996,10 @@ in_addprefix(struct in_ifaddr *target, int flags)
|
||||
* interface address, we don't need to bother
|
||||
*
|
||||
* XXX RADIX_MPATH implications here? -dyoung
|
||||
*
|
||||
* But we should still notify userland of the new address
|
||||
*/
|
||||
if (ia->ia_flags & IFA_ROUTE) {
|
||||
rt_newaddrmsg(RTM_NEWADDR, &target->ia_ifa, 0, NULL);
|
||||
if (ia->ia_flags & IFA_ROUTE)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* noone seem to have prefix route. insert it.
|
||||
@ -995,10 +1029,8 @@ in_scrubprefix(struct in_ifaddr *target)
|
||||
int error;
|
||||
|
||||
/* If we don't have IFA_ROUTE we should still inform userland */
|
||||
if ((target->ia_flags & IFA_ROUTE) == 0) {
|
||||
rt_newaddrmsg(RTM_DELADDR, &target->ia_ifa, 0, NULL);
|
||||
if ((target->ia_flags & IFA_ROUTE) == 0)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (rtinitflags(target))
|
||||
prefix = target->ia_dstaddr.sin_addr;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: ip_carp.c,v 1.59 2014/07/31 02:37:25 ozaki-r Exp $ */
|
||||
/* $NetBSD: ip_carp.c,v 1.60 2015/02/26 09:54:46 roy Exp $ */
|
||||
/* $OpenBSD: ip_carp.c,v 1.113 2005/11/04 08:11:54 mcbride Exp $ */
|
||||
|
||||
/*
|
||||
@ -31,7 +31,7 @@
|
||||
#include "opt_mbuftrace.h"
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: ip_carp.c,v 1.59 2014/07/31 02:37:25 ozaki-r Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: ip_carp.c,v 1.60 2015/02/26 09:54:46 roy Exp $");
|
||||
|
||||
/*
|
||||
* TODO:
|
||||
@ -446,9 +446,9 @@ carp_setroute(struct carp_softc *sc, int cmd)
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
if (cmd == RTM_ADD)
|
||||
in6_ifaddloop(ifa);
|
||||
in6_ifaddlocal(ifa);
|
||||
else
|
||||
in6_ifremloop(ifa);
|
||||
in6_ifremlocal(ifa);
|
||||
break;
|
||||
#endif /* INET6 */
|
||||
default:
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: in6.c,v 1.183 2015/02/25 00:26:58 roy Exp $ */
|
||||
/* $NetBSD: in6.c,v 1.184 2015/02/26 09:54:46 roy Exp $ */
|
||||
/* $KAME: in6.c,v 1.198 2001/07/18 09:12:38 itojun Exp $ */
|
||||
|
||||
/*
|
||||
@ -62,7 +62,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: in6.c,v 1.183 2015/02/25 00:26:58 roy Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: in6.c,v 1.184 2015/02/26 09:54:46 roy Exp $");
|
||||
|
||||
#include "opt_inet.h"
|
||||
#include "opt_compat_netbsd.h"
|
||||
@ -144,70 +144,6 @@ static int in6_ifinit(struct ifnet *, struct in6_ifaddr *,
|
||||
const struct sockaddr_in6 *, int);
|
||||
static void in6_unlink_ifa(struct in6_ifaddr *, struct ifnet *);
|
||||
|
||||
/*
|
||||
* Subroutine for in6_ifaddloop() and in6_ifremloop().
|
||||
* This routine does actual work.
|
||||
*/
|
||||
static void
|
||||
in6_ifloop_request(int cmd, struct ifaddr *ifa)
|
||||
{
|
||||
struct sockaddr_in6 all1_sa;
|
||||
struct rtentry *nrt = NULL;
|
||||
int e;
|
||||
|
||||
sockaddr_in6_init(&all1_sa, &in6mask128, 0, 0, 0);
|
||||
|
||||
/*
|
||||
* We specify the address itself as the gateway, and set the
|
||||
* RTF_LLINFO flag, so that the corresponding host route would have
|
||||
* the flag, and thus applications that assume traditional behavior
|
||||
* would be happy. Note that we assume the caller of the function
|
||||
* (probably implicitly) set nd6_rtrequest() to ifa->ifa_rtrequest,
|
||||
* which changes the outgoing interface to the loopback interface.
|
||||
*/
|
||||
e = rtrequest(cmd, ifa->ifa_addr, ifa->ifa_addr,
|
||||
(struct sockaddr *)&all1_sa, RTF_UP|RTF_HOST|RTF_LLINFO, &nrt);
|
||||
if (e != 0) {
|
||||
log(LOG_ERR, "in6_ifloop_request: "
|
||||
"%s operation failed for %s (errno=%d)\n",
|
||||
cmd == RTM_ADD ? "ADD" : "DELETE",
|
||||
ip6_sprintf(&((struct in6_ifaddr *)ifa)->ia_addr.sin6_addr),
|
||||
e);
|
||||
}
|
||||
|
||||
/*
|
||||
* Make sure rt_ifa be equal to IFA, the second argument of the
|
||||
* function.
|
||||
* We need this because when we refer to rt_ifa->ia6_flags in
|
||||
* ip6_input, we assume that the rt_ifa points to the address instead
|
||||
* of the loopback address.
|
||||
*/
|
||||
if (cmd == RTM_ADD && nrt && ifa != nrt->rt_ifa)
|
||||
rt_replace_ifa(nrt, ifa);
|
||||
|
||||
/*
|
||||
* Report the addition/removal of the address to the routing socket
|
||||
* unless the address is marked tentative, where it will be reported
|
||||
* once DAD completes.
|
||||
* XXX: since we called rtinit for a p2p interface with a destination,
|
||||
* we end up reporting twice in such a case. Should we rather
|
||||
* omit the second report?
|
||||
*/
|
||||
if (nrt) {
|
||||
rt_newaddrmsg(cmd, ifa, e, nrt);
|
||||
if (cmd == RTM_DELETE) {
|
||||
if (nrt->rt_refcnt <= 0) {
|
||||
/* XXX: we should free the entry ourselves. */
|
||||
nrt->rt_refcnt++;
|
||||
rtfree(nrt);
|
||||
}
|
||||
} else {
|
||||
/* the cmd must be RTM_ADD here */
|
||||
nrt->rt_refcnt--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Add ownaddr as loopback rtentry. We previously add the route only if
|
||||
* necessary (ex. on a p2p link). However, since we now manage addresses
|
||||
@ -216,28 +152,21 @@ in6_ifloop_request(int cmd, struct ifaddr *ifa)
|
||||
* any more.
|
||||
*/
|
||||
void
|
||||
in6_ifaddloop(struct ifaddr *ifa)
|
||||
in6_ifaddlocal(struct ifaddr *ifa)
|
||||
{
|
||||
struct rtentry *rt;
|
||||
|
||||
/* If there is no loopback entry, allocate one. */
|
||||
rt = rtalloc1(ifa->ifa_addr, 0);
|
||||
if (rt == NULL || (rt->rt_flags & RTF_HOST) == 0 ||
|
||||
(rt->rt_ifp->if_flags & IFF_LOOPBACK) == 0)
|
||||
in6_ifloop_request(RTM_ADD, ifa);
|
||||
if (rt != NULL)
|
||||
rt->rt_refcnt--;
|
||||
rt_ifa_addlocal(ifa);
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove loopback rtentry of ownaddr generated by in6_ifaddloop(),
|
||||
* Remove loopback rtentry of ownaddr generated by in6_ifaddlocal(),
|
||||
* if it exists.
|
||||
*/
|
||||
void
|
||||
in6_ifremloop(struct ifaddr *ifa)
|
||||
in6_ifremlocal(struct ifaddr *ifa)
|
||||
{
|
||||
struct in6_ifaddr *alt_ia = NULL, *ia;
|
||||
struct rtentry *rt;
|
||||
struct in6_ifaddr *ia;
|
||||
struct ifaddr *alt_ifa = NULL;
|
||||
int ia_count = 0;
|
||||
|
||||
/*
|
||||
@ -272,38 +201,15 @@ in6_ifremloop(struct ifaddr *ifa)
|
||||
if (!IN6_ARE_ADDR_EQUAL(IFA_IN6(ifa), &ia->ia_addr.sin6_addr))
|
||||
continue;
|
||||
if (ia->ia_ifp != ifa->ifa_ifp)
|
||||
alt_ia = ia;
|
||||
if (++ia_count > 1 && alt_ia != NULL)
|
||||
alt_ifa = &ia->ia_ifa;
|
||||
if (++ia_count > 1 && alt_ifa != NULL)
|
||||
break;
|
||||
}
|
||||
|
||||
if (ia_count == 0)
|
||||
return;
|
||||
|
||||
if ((rt = rtalloc1(ifa->ifa_addr, 0)) == NULL)
|
||||
return;
|
||||
rt->rt_refcnt--;
|
||||
|
||||
/*
|
||||
* Before deleting, check if a corresponding loopbacked
|
||||
* host route surely exists. With this check, we can avoid
|
||||
* deleting an interface direct route whose destination is
|
||||
* the same as the address being removed. This can happen
|
||||
* when removing a subnet-router anycast address on an
|
||||
* interface attached to a shared medium.
|
||||
*/
|
||||
if ((rt->rt_flags & RTF_HOST) == 0 ||
|
||||
(rt->rt_ifp->if_flags & IFF_LOOPBACK) == 0)
|
||||
return;
|
||||
|
||||
/* If we cannot replace the route's ifaddr with the equivalent
|
||||
* ifaddr of another interface, I believe it is safest to
|
||||
* delete the route.
|
||||
*/
|
||||
if (ia_count == 1 || alt_ia == NULL)
|
||||
in6_ifloop_request(RTM_DELETE, ifa);
|
||||
else
|
||||
rt_replace_ifa(rt, &alt_ia->ia_ifa);
|
||||
rt_ifa_remlocal(ifa, ia_count == 1 ? NULL : alt_ifa);
|
||||
}
|
||||
|
||||
int
|
||||
@ -1383,7 +1289,7 @@ in6_purgeaddr(struct ifaddr *ifa)
|
||||
}
|
||||
|
||||
/* Remove ownaddr's loopback rtentry, if it exists. */
|
||||
in6_ifremloop(&(ia->ia_ifa));
|
||||
in6_ifremlocal(&(ia->ia_ifa));
|
||||
|
||||
/*
|
||||
* leave from multicast groups we have joined for the interface
|
||||
@ -1781,8 +1687,9 @@ in6_ifinit(struct ifnet *ifp, struct in6_ifaddr *ia,
|
||||
/* Add ownaddr as loopback rtentry, if necessary (ex. on p2p link). */
|
||||
if (newhost) {
|
||||
/* set the rtrequest function to create llinfo */
|
||||
if ((ifp->if_flags & (IFF_LOOPBACK | IFF_POINTOPOINT)) == 0)
|
||||
ia->ia_ifa.ifa_rtrequest = nd6_rtrequest;
|
||||
in6_ifaddloop(&ia->ia_ifa);
|
||||
in6_ifaddlocal(&ia->ia_ifa);
|
||||
} else {
|
||||
/* Inform the routing socket of new flags/timings */
|
||||
rt_newaddrmsg(RTM_NEWADDR, &ia->ia_ifa, 0, NULL);
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: in6_var.h,v 1.71 2014/09/05 06:06:31 matt Exp $ */
|
||||
/* $NetBSD: in6_var.h,v 1.72 2015/02/26 09:54:46 roy Exp $ */
|
||||
/* $KAME: in6_var.h,v 1.81 2002/06/08 11:16:51 itojun Exp $ */
|
||||
|
||||
/*
|
||||
@ -693,8 +693,8 @@ int in6_if2idlen (struct ifnet *);
|
||||
void *in6_domifattach(struct ifnet *);
|
||||
void in6_domifdetach(struct ifnet *, void *);
|
||||
void in6_restoremkludge(struct in6_ifaddr *, struct ifnet *);
|
||||
void in6_ifremloop(struct ifaddr *);
|
||||
void in6_ifaddloop(struct ifaddr *);
|
||||
void in6_ifremlocal(struct ifaddr *);
|
||||
void in6_ifaddlocal(struct ifaddr *);
|
||||
void in6_createmkludge(struct ifnet *);
|
||||
void in6_purgemkludge(struct ifnet *);
|
||||
struct in6_ifaddr *in6ifa_ifpforlinklocal(const struct ifnet *, int);
|
||||
|
Loading…
x
Reference in New Issue
Block a user