Diff below changes the behavior of the kernel to add a route for every
new  IPv4 address, when it is configured on an interface.  Actually
such route is created the first time a program tries to resolve it.
That's why with this diff you don't see the "cloned" flag:

-10.3.3.2           00:00:24:cc:21:eb  UHLc       0        2     -     4        
lo0  
+10.3.3.2           00:00:24:cc:21:eb  UHL        0        0     -     4        
lo0 

This now automagically created route can still be deleted from userland.
In such case it will be re-created as soon as a program tries to resolve
it, just like it is now.

Addresses configured on a point-to-point will have a slightly different
route added, which matches the IPv6 behavior:

 97.78.45.33       127.0.0.1          H          0        0     -     4         
lo0  

Such addresses are also not automatically re-created if they are
previously deleted, and you'll need to re-configure the address on your
interface or add it manually if you want it back.

With this diff, a new route will always be created when an address is
configured, which mean that a RTM_NEWADDR message will be generated at
least once per-address.  If the address is the first in a particular
subnet, two messages will be generated, one for the route to prefix and
one for the local route.

Do you see any problem with all of this?  Can it goes in?

Index: netinet/if_ether.c
===================================================================
RCS file: /home/ncvs/src/sys/netinet/if_ether.c,v
retrieving revision 1.127
diff -u -p -r1.127 if_ether.c
--- netinet/if_ether.c  7 May 2014 08:14:59 -0000       1.127
+++ netinet/if_ether.c  26 May 2014 09:46:42 -0000
@@ -174,7 +174,8 @@ arp_rtrequest(int req, struct rtentry *r
                if ((rt->rt_flags & RTF_HOST) == 0 && rt_mask(rt) &&
                    satosin(rt_mask(rt))->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) && !la)) {
                        /*
                         * Case 1: This route should come from a route to iface.
                         */
@@ -189,7 +190,8 @@ arp_rtrequest(int req, struct rtentry *r
                         * from it do not need their expiration time set.
                         */
                        rt->rt_expire = time_second;
-                       break;
+                       if ((rt->rt_flags & RTF_CLONING) != 0)
+                               break;
                }
                /* Announce a new entry if requested. */
                if (rt->rt_flags & RTF_ANNOUNCE)
Index: netinet/in.c
===================================================================
RCS file: /home/ncvs/src/sys/netinet/in.c,v
retrieving revision 1.96
diff -u -p -r1.96 in.c
--- netinet/in.c        25 Apr 2014 09:44:38 -0000      1.96
+++ netinet/in.c        26 May 2014 09:46:42 -0000
@@ -702,6 +702,7 @@ out:
         * carp(4).
         */
        ifa_add(ifp, &ia->ia_ifa);
+       rt_ifa_addloop(&ia->ia_ifa);
 
        if (error && newaddr)
                in_purgeaddr(&ia->ia_ifa);
@@ -718,6 +719,8 @@ in_purgeaddr(struct ifaddr *ifa)
        splsoftassert(IPL_SOFTNET);
 
        in_ifscrub(ifp, ia);
+
+       rt_ifa_delloop(&ia->ia_ifa);
 
        ifa_del(ifp, &ia->ia_ifa);
        TAILQ_REMOVE(&in_ifaddr, ia, ia_list);

Reply via email to