Module Name:    src
Committed By:   roy
Date:           Tue Mar 24 16:36:52 UTC 2009

Modified Files:
        src/sys/net: route.c

Log Message:
When a route is deleted or it's ifa changed and it's the connected route
for the ifa we should ensure the IFA_ROUTE flag is removed from the ifa
and if applicable, added to the new ifa.


To generate a diff of this commit:
cvs rdiff -u -r1.115 -r1.116 src/sys/net/route.c

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.115 src/sys/net/route.c:1.116
--- src/sys/net/route.c:1.115	Fri Feb 20 10:57:19 2009
+++ src/sys/net/route.c	Tue Mar 24 16:36:52 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: route.c,v 1.115 2009/02/20 10:57:19 yamt Exp $	*/
+/*	$NetBSD: route.c,v 1.116 2009/03/24 16:36:52 roy Exp $	*/
 
 /*-
  * Copyright (c) 1998, 2008 The NetBSD Foundation, Inc.
@@ -93,7 +93,7 @@
 #include "opt_route.h"
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: route.c,v 1.115 2009/02/20 10:57:19 yamt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: route.c,v 1.116 2009/03/24 16:36:52 roy Exp $");
 
 #include <sys/param.h>
 #include <sys/sysctl.h>
@@ -192,9 +192,50 @@
 		rt->rt_ifa_seqno = *ifa->ifa_seqno;
 }
 
+/*
+ * Is this route the connected route for the ifa?
+ */
+static int
+rt_ifa_connected(const struct rtentry *rt, const struct ifaddr *ifa)
+{
+	const struct sockaddr *key, *dst, *odst;
+	struct sockaddr_storage maskeddst;
+
+	key = rt_getkey(rt);
+	dst = rt->rt_flags & RTF_HOST ? ifa->ifa_dstaddr : ifa->ifa_addr;
+	if (dst == NULL ||
+	    dst->sa_family != key->sa_family ||
+	    dst->sa_len != key->sa_len)
+		return 0;
+	if ((rt->rt_flags & RTF_HOST) == 0 && ifa->ifa_netmask) {
+		odst = dst;
+		dst = (struct sockaddr *)&maskeddst;
+		rt_maskedcopy(odst, (struct sockaddr *)&maskeddst,
+		    ifa->ifa_netmask);
+	}
+	return (memcmp(dst, key, dst->sa_len) == 0);
+}
+
 void
 rt_replace_ifa(struct rtentry *rt, struct ifaddr *ifa)
 {
+	if (rt->rt_ifa &&
+	    rt->rt_ifa != ifa &&
+	    rt->rt_ifa->ifa_flags & IFA_ROUTE &&
+	    rt_ifa_connected(rt, rt->rt_ifa))
+	{
+		RT_DPRINTF("rt->_rt_key = %p, ifa = %p, "
+		    "replace deleted IFA_ROUTE\n",
+		    (void *)rt->_rt_key, (void *)rt->rt_ifa);
+		rt->rt_ifa->ifa_flags &= ~IFA_ROUTE;
+		if (rt_ifa_connected(rt, ifa)) {
+			RT_DPRINTF("rt->_rt_key = %p, ifa = %p, "
+			    "replace added IFA_ROUTE\n",
+			    (void *)rt->_rt_key, (void *)ifa);
+			ifa->ifa_flags |= IFA_ROUTE;
+		}
+	}
+
 	IFAREF(ifa);
 	IFAFREE(rt->rt_ifa);
 	rt_set_ifa1(rt, ifa);
@@ -672,8 +713,17 @@
 			rt->rt_parent = NULL;
 		}
 		rt->rt_flags &= ~RTF_UP;
-		if ((ifa = rt->rt_ifa) && ifa->ifa_rtrequest)
-			ifa->ifa_rtrequest(RTM_DELETE, rt, info);
+		if ((ifa = rt->rt_ifa)) {
+			if (ifa->ifa_flags & IFA_ROUTE &&
+			    rt_ifa_connected(rt, ifa)) {
+				RT_DPRINTF("rt->_rt_key = %p, ifa = %p, "
+				    "deleted IFA_ROUTE\n",
+				    (void *)rt->_rt_key, (void *)ifa);
+				ifa->ifa_flags &= ~IFA_ROUTE;
+			}
+			if (ifa->ifa_rtrequest)
+				ifa->ifa_rtrequest(RTM_DELETE, rt, info);
+		}
 		rttrash++;
 		if (ret_nrt)
 			*ret_nrt = rt;

Reply via email to