tech-net archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[PATCH] Deletion of route scrubs ifa flag IFA_ROUTE even if it's not the automatic route



Hi List

sys/net/rtsock.c, r1.119 added code to RTM_DELETE so that IFA_ROUTE was
removed from the ifa flags. Sadly, it did not check to see if it was the
automatic route or not, which lads to this scenario as pointed out by
Matthias Drochner.

ifconfig re0 alias 192.168.0.1/24
route add default 192.168.0.10
ping 192.168.0.10
route delete default
ifconfig re0 -alias 192.168.0.1

This leaves ARP entries around which isn't that great. As author of that
patch, I apologise.
To make ammends, attached is a patch to fix this. It is intended for
pullup to netbsd-5.

The code against RTM_DELETE in rtsock.c has been moved to rtrequest1 in
route.c and checks that is the automatic route before scrubbing the
IFA_ROUTE flag (solves this issue).
It also corrects an existing debug entry (not enabled by default) in
rtsock.c and restores some of the initial logic of calling
ifa->ifa_rtrequest in RTM_CHANGE.
Finally, if an automatic route exists which no ifa claims when we tried
to add it we mark the ifa as IFA_ROUTE.

Comments? 

Thanks

Roy
Index: sys/net/route.c
===================================================================
RCS file: /cvsroot/src/sys/net/route.c,v
retrieving revision 1.115
diff -u -p -r1.115 route.c
--- sys/net/route.c     20 Feb 2009 10:57:19 -0000      1.115
+++ sys/net/route.c     3 Mar 2009 22:16:34 -0000
@@ -628,7 +628,7 @@ int
 rtrequest1(int req, struct rt_addrinfo *info, struct rtentry **ret_nrt)
 {
        int s = splsoftnet();
-       int error = 0;
+       int error = 0, scrub_ifa = 0;
        struct rtentry *rt, *crt;
        struct radix_node *rn;
        struct radix_node_head *rnh;
@@ -658,6 +658,20 @@ rtrequest1(int req, struct rt_addrinfo *
                        /* clean up any cloned children */
                        rtflushclone(dst->sa_family, rt);
                }
+               if ((ifa = rt->rt_ifa) != NULL &&
+                   ifa->ifa_netmask != NULL &&
+                   netmask != NULL &&
+                   ifa->ifa_flags & IFA_ROUTE)
+               {
+                       rt_maskedcopy(dst,
+                           (struct sockaddr *)&maskeddst,
+                           ifa->ifa_netmask);
+                       dst = (struct sockaddr *)&maskeddst;
+                       rn = rnh->rnh_lookup(dst, ifa->ifa_netmask,
+                           rnh);
+                       if ((struct rtentry *)rn == rt)
+                               scrub_ifa = 1;
+               }
                if ((rn = rnh->rnh_deladdr(dst, netmask, rnh)) == NULL)
                        senderr(ESRCH);
                if (rn->rn_flags & (RNF_ACTIVE | RNF_ROOT))
@@ -672,8 +686,12 @@ rtrequest1(int req, struct rt_addrinfo *
                        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 != NULL) {
+                       if (ifa->ifa_rtrequest)
+                               ifa->ifa_rtrequest(RTM_DELETE, rt, info);
+                       if (scrub_ifa)
+                               ifa->ifa_flags &= ~IFA_ROUTE;
+               }
                rttrash++;
                if (ret_nrt)
                        *ret_nrt = rt;
@@ -690,9 +708,8 @@ rtrequest1(int req, struct rt_addrinfo *
                        senderr(EINVAL);
                ifa = rt->rt_ifa;
                flags = rt->rt_flags & ~(RTF_CLONING | RTF_STATIC);
-               flags |= RTF_CLONED;
+               flags |= RTF_CLONED | RTF_HOST;
                gateway = rt->rt_gateway;
-               flags |= RTF_HOST;
                goto makeroute;
 
        case RTM_ADD:
Index: sys/net/rtsock.c
===================================================================
RCS file: /cvsroot/src/sys/net/rtsock.c,v
retrieving revision 1.123
diff -u -p -r1.123 rtsock.c
--- sys/net/rtsock.c    20 Feb 2009 10:54:57 -0000      1.123
+++ sys/net/rtsock.c    3 Mar 2009 22:16:35 -0000
@@ -28,7 +28,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
-
+    
 /*
  * Copyright (c) 1988, 1991, 1993
  *     The Regents of the University of California.  All rights reserved.
@@ -301,12 +301,6 @@ route_output(struct mbuf *m, ...)
                error = rtrequest1(rtm->rtm_type, &info, &saved_nrt);
                if (error == 0) {
                        (rt = saved_nrt)->rt_refcnt++;
-                       ifa = rt_get_ifa(rt);
-                       /*
-                        * If deleting an automatic route, scrub the flag.
-                        */
-                       if (ifa->ifa_flags & IFA_ROUTE)
-                               ifa->ifa_flags &= ~IFA_ROUTE;
                        goto report;
                }
                break;
@@ -360,12 +354,12 @@ route_output(struct mbuf *m, ...)
                                if (info.rti_info[RTAX_IFA]->sa_family ==
                                    AF_INET) {
                                        printf("%s: copying out RTAX_IFA %s ",
-                                           __func__, inet_ntoa(
+                                           __func__, inet_ntoa((
                                            (const struct sockaddr_in *)
-                                           info.rti_info[RTAX_IFA])->sin_addr);
+                                           
info.rti_info[RTAX_IFA])->sin_addr));
                                        printf("for info.rti_info[RTAX_DST] %s "
                                            "ifa_getifa %p ifa_seqno %p\n",
-                                           inet_ntoa(
+                                           inet_ntoa((
                                            (const struct sockaddr_in *)
                                            info.rti_info[RTAX_DST])->sin_addr),
                                            (void *)rtifa->ifa_getifa,
@@ -425,30 +419,20 @@ route_output(struct mbuf *m, ...)
                                ifp = ifa->ifa_ifp;
                        }
                        oifa = rt->rt_ifa;
-                       if (oifa && oifa->ifa_flags & IFA_ROUTE) {
-                               /*
-                                * If changing an automatically added route,
-                                * remove the flag and store the fact.
-                                */
-                               oifa->ifa_flags &= ~IFA_ROUTE;
-                               ifa_route = 1;
-                       }
-                       if (ifa) {
-                               if (oifa != ifa) {
-                                       if (oifa && oifa->ifa_rtrequest) {
+                       if (ifa && oifa != ifa) {
+                               if (oifa) {
+                                       if (oifa->ifa_flags & IFA_ROUTE) {
+                                               oifa->ifa_flags &= ~IFA_ROUTE;
+                                               ifa_route = 1;
+                                       }
+                                       if (oifa->ifa_rtrequest)
                                                oifa->ifa_rtrequest(RTM_DELETE,
                                                    rt, &info);
-                                       }
-                                       /*
-                                        * If changing an automatically added
-                                        * route, store this if not static.
-                                        */
-                                       if (ifa_route &&
-                                           !(rt->rt_flags & RTF_STATIC))
-                                               ifa->ifa_flags |= IFA_ROUTE;
-                                       rt_replace_ifa(rt, ifa);
-                                       rt->rt_ifp = ifp;
                                }
+                               if (ifa_route)
+                                       ifa->ifa_flags |= IFA_ROUTE;
+                               rt_replace_ifa(rt, ifa);
+                               rt->rt_ifp = ifp;
                        }
                        rt_setmetrics(rtm->rtm_inits, &rtm->rtm_rmx,
                            &rt->rt_rmx);
Index: sys/netinet/in.c
===================================================================
RCS file: /cvsroot/src/sys/netinet/in.c,v
retrieving revision 1.131
diff -u -p -r1.131 in.c
--- sys/netinet/in.c    12 Feb 2009 19:05:36 -0000      1.131
+++ sys/netinet/in.c    3 Mar 2009 22:16:35 -0000
@@ -993,16 +993,13 @@ in_addprefix(struct in_ifaddr *target, i
 
        /*
         * noone seem to have prefix route.  insert it.
+        * if it already exists, mark ourselves as having it.
         */
        error = rtinit(&target->ia_ifa, RTM_ADD, flags);
+       if (error == EEXIST)
+               error = 0;
        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;
 }
 

Attachment: signature.asc
Description: This is a digitally signed message part



Home | Main Index | Thread Index | Old Index