Module Name: src
Committed By: roy
Date: Thu Feb 26 09:54:46 UTC 2015
Modified Files:
src/sys/net: route.c route.h
src/sys/netinet: if_arp.c in.c ip_carp.c
src/sys/netinet6: in6.c in6_var.h
Log Message:
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.
To generate a diff of this commit:
cvs rdiff -u -r1.135 -r1.136 src/sys/net/route.c
cvs rdiff -u -r1.86 -r1.87 src/sys/net/route.h
cvs rdiff -u -r1.160 -r1.161 src/sys/netinet/if_arp.c
cvs rdiff -u -r1.149 -r1.150 src/sys/netinet/in.c
cvs rdiff -u -r1.59 -r1.60 src/sys/netinet/ip_carp.c
cvs rdiff -u -r1.183 -r1.184 src/sys/netinet6/in6.c
cvs rdiff -u -r1.71 -r1.72 src/sys/netinet6/in6_var.h
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/net/route.c
diff -u src/sys/net/route.c:1.135 src/sys/net/route.c:1.136
--- src/sys/net/route.c:1.135 Wed Feb 25 12:45:34 2015
+++ src/sys/net/route.c Thu Feb 26 09:54:46 2015
@@ -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
;
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
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
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
Index: src/sys/net/route.h
diff -u src/sys/net/route.h:1.86 src/sys/net/route.h:1.87
--- src/sys/net/route.h:1.86 Wed Feb 25 12:45:34 2015
+++ src/sys/net/route.h Thu Feb 26 09:54:46 2015
@@ -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 *, cons
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 *);
Index: src/sys/netinet/if_arp.c
diff -u src/sys/netinet/if_arp.c:1.160 src/sys/netinet/if_arp.c:1.161
--- src/sys/netinet/if_arp.c:1.160 Thu Nov 13 16:11:18 2014
+++ src/sys/netinet/if_arp.c Thu Feb 26 09:54:46 2015
@@ -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 s
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 *r
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,7 +596,8 @@ arp_rtrequest(int req, struct rtentry *r
}
#endif
}
- break;
+ if (rt->rt_flags & RTF_CLONING)
+ break;
}
/* Announce a new entry if requested. */
if (rt->rt_flags & RTF_ANNOUNCE) {
Index: src/sys/netinet/in.c
diff -u src/sys/netinet/in.c:1.149 src/sys/netinet/in.c:1.150
--- src/sys/netinet/in.c:1.149 Mon Dec 1 17:07:43 2014
+++ src/sys/netinet/in.c Thu Feb 26 09:54:46 2015
@@ -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
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_i
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,13 +996,9 @@ in_addprefix(struct in_ifaddr *target, i
* 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;
- }
}
/*
@@ -974,9 +1008,9 @@ in_addprefix(struct in_ifaddr *target, i
if (error == 0)
target->ia_flags |= IFA_ROUTE;
else if (error == EEXIST) {
- /*
+ /*
* the fact the route already exists is not an error.
- */
+ */
error = 0;
}
return error;
@@ -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;
Index: src/sys/netinet/ip_carp.c
diff -u src/sys/netinet/ip_carp.c:1.59 src/sys/netinet/ip_carp.c:1.60
--- src/sys/netinet/ip_carp.c:1.59 Thu Jul 31 02:37:25 2014
+++ src/sys/netinet/ip_carp.c Thu Feb 26 09:54:46 2015
@@ -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
#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:
Index: src/sys/netinet6/in6.c
diff -u src/sys/netinet6/in6.c:1.183 src/sys/netinet6/in6.c:1.184
--- src/sys/netinet6/in6.c:1.183 Wed Feb 25 00:26:58 2015
+++ src/sys/netinet6/in6.c Thu Feb 26 09:54:46 2015
@@ -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"
@@ -145,70 +145,6 @@ static int in6_ifinit(struct ifnet *, st
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
* separately from prefixes, we should always add the route. We can't
@@ -216,28 +152,21 @@ in6_ifloop_request(int cmd, struct ifadd
* 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
/* Add ownaddr as loopback rtentry, if necessary (ex. on p2p link). */
if (newhost) {
/* set the rtrequest function to create llinfo */
- ia->ia_ifa.ifa_rtrequest = nd6_rtrequest;
- in6_ifaddloop(&ia->ia_ifa);
+ if ((ifp->if_flags & (IFF_LOOPBACK | IFF_POINTOPOINT)) == 0)
+ ia->ia_ifa.ifa_rtrequest = nd6_rtrequest;
+ in6_ifaddlocal(&ia->ia_ifa);
} else {
/* Inform the routing socket of new flags/timings */
rt_newaddrmsg(RTM_NEWADDR, &ia->ia_ifa, 0, NULL);
Index: src/sys/netinet6/in6_var.h
diff -u src/sys/netinet6/in6_var.h:1.71 src/sys/netinet6/in6_var.h:1.72
--- src/sys/netinet6/in6_var.h:1.71 Fri Sep 5 06:06:31 2014
+++ src/sys/netinet6/in6_var.h Thu Feb 26 09:54:46 2015
@@ -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);