Author: melifaro
Date: Fri Mar 29 16:24:20 2013
New Revision: 248895
URL: http://svnweb.freebsd.org/changeset/base/248895

Log:
  Merge 248070.
  
  Fix long-standing issue with interface routes being unprotected:
  Use RTM_PINNED flag to mark route as immutable.
  Forbid deleting immutable routes without special rtrequest1_fib() flag.
  Adding interface address with prefix already in route table is handled
  by atomically deleting old prefix and adding interface one.

Modified:
  stable/9/sys/net/if.c
  stable/9/sys/net/route.c
  stable/9/sys/net/route.h
Directory Properties:
  stable/9/sys/   (props changed)
  stable/9/sys/net/   (props changed)

Modified: stable/9/sys/net/if.c
==============================================================================
--- stable/9/sys/net/if.c       Fri Mar 29 16:16:50 2013        (r248894)
+++ stable/9/sys/net/if.c       Fri Mar 29 16:24:20 2013        (r248895)
@@ -1379,7 +1379,8 @@ if_rtdel(struct radix_node *rn, void *ar
                        return (0);
 
                err = rtrequest_fib(RTM_DELETE, rt_key(rt), rt->rt_gateway,
-                               rt_mask(rt), rt->rt_flags|RTF_RNH_LOCKED,
+                               rt_mask(rt),
+                               rt->rt_flags|RTF_RNH_LOCKED|RTF_PINNED,
                                (struct rtentry **) NULL, rt->rt_fibnum);
                if (err) {
                        log(LOG_WARNING, "if_rtdel: error %d\n", err);

Modified: stable/9/sys/net/route.c
==============================================================================
--- stable/9/sys/net/route.c    Fri Mar 29 16:16:50 2013        (r248894)
+++ stable/9/sys/net/route.c    Fri Mar 29 16:24:20 2013        (r248895)
@@ -1112,6 +1112,14 @@ rtrequest1_fib(int req, struct rt_addrin
                        error = 0;
                }
 #endif
+               if ((flags & RTF_PINNED) == 0) {
+                       /* Check if target route can be deleted */
+                       rt = (struct rtentry *)rnh->rnh_lookup(dst,
+                           netmask, rnh);
+                       if ((rt != NULL) && (rt->rt_flags & RTF_PINNED))
+                               senderr(EADDRINUSE);
+               }
+
                /*
                 * Remove the item from the tree and return it.
                 * Complain if it is not there and do no more processing.
@@ -1435,6 +1443,7 @@ rtinit1(struct ifaddr *ifa, int cmd, int
        int didwork = 0;
        int a_failure = 0;
        static struct sockaddr_dl null_sdl = {sizeof(null_sdl), AF_LINK};
+       struct radix_node_head *rnh;
 
        if (flags & RTF_HOST) {
                dst = ifa->ifa_dstaddr;
@@ -1493,7 +1502,6 @@ rtinit1(struct ifaddr *ifa, int cmd, int
         */
        for ( fibnum = startfib; fibnum <= endfib; fibnum++) {
                if (cmd == RTM_DELETE) {
-                       struct radix_node_head *rnh;
                        struct radix_node *rn;
                        /*
                         * Look up an rtentry that is in the routing tree and
@@ -1543,7 +1551,8 @@ rtinit1(struct ifaddr *ifa, int cmd, int
                 */
                bzero((caddr_t)&info, sizeof(info));
                info.rti_ifa = ifa;
-               info.rti_flags = flags | (ifa->ifa_flags & ~IFA_RTSELF);
+               info.rti_flags = flags |
+                   (ifa->ifa_flags & ~IFA_RTSELF) | RTF_PINNED;
                info.rti_info[RTAX_DST] = dst;
                /* 
                 * doing this for compatibility reasons
@@ -1555,6 +1564,33 @@ rtinit1(struct ifaddr *ifa, int cmd, int
                        info.rti_info[RTAX_GATEWAY] = ifa->ifa_addr;
                info.rti_info[RTAX_NETMASK] = netmask;
                error = rtrequest1_fib(cmd, &info, &rt, fibnum);
+
+               if ((error == EEXIST) && (cmd == RTM_ADD)) {
+                       /*
+                        * Interface route addition failed.
+                        * Atomically delete current prefix generating
+                        * RTM_DELETE message, and retry adding
+                        * interface prefix.
+                        */
+                       rnh = rt_tables_get_rnh(fibnum, dst->sa_family);
+                       RADIX_NODE_HEAD_LOCK(rnh);
+
+                       /* Delete old prefix */
+                       info.rti_ifa = NULL;
+                       info.rti_flags = RTF_RNH_LOCKED;
+
+                       error = rtrequest1_fib(RTM_DELETE, &info, &rt, fibnum);
+                       if (error == 0) {
+                               info.rti_ifa = ifa;
+                               info.rti_flags = flags | RTF_RNH_LOCKED |
+                                   (ifa->ifa_flags & ~IFA_RTSELF) | RTF_PINNED;
+                               error = rtrequest1_fib(cmd, &info, &rt, fibnum);
+                       }
+
+                       RADIX_NODE_HEAD_UNLOCK(rnh);
+               }
+
+
                if (error == 0 && rt != NULL) {
                        /*
                         * notify any listening routing agents of the change

Modified: stable/9/sys/net/route.h
==============================================================================
--- stable/9/sys/net/route.h    Fri Mar 29 16:16:50 2013        (r248894)
+++ stable/9/sys/net/route.h    Fri Mar 29 16:24:20 2013        (r248895)
@@ -176,7 +176,7 @@ struct ortentry {
 /*                     0x20000            unused, was RTF_WASCLONED */
 #define RTF_PROTO3     0x40000         /* protocol specific routing flag */
 /*                     0x80000            unused */
-#define RTF_PINNED     0x100000        /* future use */
+#define RTF_PINNED     0x100000        /* route is immutable */
 #define        RTF_LOCAL       0x200000        /* route represents a local 
address */
 #define        RTF_BROADCAST   0x400000        /* route represents a bcast 
address */
 #define        RTF_MULTICAST   0x800000        /* route represents a mcast 
address */
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to