summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorqingli <qingli@FreeBSD.org>2011-11-11 23:22:38 +0000
committerqingli <qingli@FreeBSD.org>2011-11-11 23:22:38 +0000
commit3b996bbc1149552d433105f70b0d45df8873ed70 (patch)
treed5171052e4e9f042e9a9ad479219c5615fe0be16 /sys
parente4a4d6436f0f0ff5634e11e201ea62c8556c6be0 (diff)
downloadFreeBSD-src-3b996bbc1149552d433105f70b0d45df8873ed70.zip
FreeBSD-src-3b996bbc1149552d433105f70b0d45df8873ed70.tar.gz
A default route learned from the RAs could be deleted manually
after its installation. This removal may be accidental and can prevent the default route from being installed in the future if the associated default router has the best preference. The cause is the lack of status update in the default router on the state of its route installation in the kernel FIB. This patch fixes the described problem. Reviewed by: hrs, discussed with hrs MFC after: 5 days
Diffstat (limited to 'sys')
-rw-r--r--sys/netinet6/in6.c2
-rw-r--r--sys/netinet6/nd6.c40
-rw-r--r--sys/netinet6/nd6.h1
-rw-r--r--sys/netinet6/nd6_rtr.c5
4 files changed, 45 insertions, 3 deletions
diff --git a/sys/netinet6/in6.c b/sys/netinet6/in6.c
index 1e6cb94..8514f73 100644
--- a/sys/netinet6/in6.c
+++ b/sys/netinet6/in6.c
@@ -152,7 +152,7 @@ in6_ifaddloop(struct ifaddr *ifa)
ia = ifa2ia6(ifa);
ifp = ifa->ifa_ifp;
IF_AFDATA_LOCK(ifp);
- ifa->ifa_rtrequest = NULL;
+ ifa->ifa_rtrequest = nd6_rtrequest;
/* XXX QL
* we need to report rt_newaddrmsg
diff --git a/sys/netinet6/nd6.c b/sys/netinet6/nd6.c
index ae7cc4a..875daa0 100644
--- a/sys/netinet6/nd6.c
+++ b/sys/netinet6/nd6.c
@@ -1174,6 +1174,46 @@ done:
}
+/*
+ * Rejuvenate this function for routing operations related
+ * processing.
+ */
+void
+nd6_rtrequest(int req, struct rtentry *rt, struct rt_addrinfo *info)
+{
+ struct sockaddr_in6 *gateway = (struct sockaddr_in6 *)rt->rt_gateway;
+ struct nd_defrouter *dr;
+ struct ifnet *ifp = rt->rt_ifp;
+
+ RT_LOCK_ASSERT(rt);
+
+ switch (req) {
+ case RTM_ADD:
+ break;
+
+ case RTM_DELETE:
+ if (!ifp)
+ return;
+ /*
+ * Only indirect routes are interesting.
+ */
+ if ((rt->rt_flags & RTF_GATEWAY) == 0)
+ return;
+ /*
+ * check for default route
+ */
+ if (IN6_ARE_ADDR_EQUAL(&in6addr_any,
+ &SIN6(rt_key(rt))->sin6_addr)) {
+
+ dr = defrouter_lookup(&gateway->sin6_addr, ifp);
+ if (dr != NULL)
+ dr->installed = 0;
+ }
+ break;
+ }
+}
+
+
int
nd6_ioctl(u_long cmd, caddr_t data, struct ifnet *ifp)
{
diff --git a/sys/netinet6/nd6.h b/sys/netinet6/nd6.h
index 6f63192..ca981d0 100644
--- a/sys/netinet6/nd6.h
+++ b/sys/netinet6/nd6.h
@@ -406,6 +406,7 @@ void nd6_purge __P((struct ifnet *));
void nd6_nud_hint __P((struct rtentry *, struct in6_addr *, int));
int nd6_resolve __P((struct ifnet *, struct rtentry *, struct mbuf *,
struct sockaddr *, u_char *));
+void nd6_rtrequest __P((int, struct rtentry *, struct rt_addrinfo *));
int nd6_ioctl __P((u_long, caddr_t, struct ifnet *));
struct llentry *nd6_cache_lladdr __P((struct ifnet *, struct in6_addr *,
char *, int, int, int));
diff --git a/sys/netinet6/nd6_rtr.c b/sys/netinet6/nd6_rtr.c
index 5352dd5..237f14c 100644
--- a/sys/netinet6/nd6_rtr.c
+++ b/sys/netinet6/nd6_rtr.c
@@ -751,9 +751,10 @@ defrtrlist_update(struct nd_defrouter *new)
/*
* If the preference does not change, there's no need
- * to sort the entries.
+ * to sort the entries. Also make sure the selected
+ * router is still installed in the kernel.
*/
- if (rtpref(new) == oldpref) {
+ if (dr->installed && rtpref(new) == oldpref) {
splx(s);
return (dr);
}
OpenPOWER on IntegriCloud