On 28/05/14(Wed) 16:15, Martin Pieuchot wrote:
> On 26/05/14(Mon) 15:17, Martin Pieuchot wrote:
> > On 26/05/14(Mon) 08:03, Kenneth Westerback wrote:
> > > [...]
> > > 
> > > dhclient used to create such routes but that was removed as useless so
> > > I'm not sure why we want/need to add them back. I'm not a routing
> > > table guru so perhaps this is different in some way.
> > 
> > We want it back to be able to tell if an address is configured locally
> > by using the routing table.  But to be able to trust the routing table
> > we must ensure that every local address is associated to a route entry.
> > This diff is a step in this direction.
> > 
> > > Extra RTM_NEWADDR messages may cause problems for dhclient, since it
> > > will exit on what it thinks are attempts to add addresses to an
> > > interface. Not sure if RTM_NEWADDR makes sense if all you are doing is
> > > adding a route.
> > 
> > That's a really good question, and I don't have the answer.
> > 
> > Originally RTM_NEWADDR was generated when a route to prefix was added
> > for a new address.  It was simple: 1 address -> 1 route + message.
> > 
> > Later on the logic in netinet/in.c has been modified to be able to setup
> > an address without adding a route to prefix, if this route was already
> > present for example.  That's what happens if you have two addresses on
> > the same subnet configured on your machine.  With this, we now have:
> > 1 address -> maybe 1 route + message.
> > 
> > With this diff we always create a route, but maybe a second one if it is
> > the first address of a subnet.  So we have: 1 address -> 1 or 2 route +
> > messages.
> 
> Here's a more complete diff that seems to not freak out dhclient(8). It
> makes use of the RTF_LOCAL flag to restore the original behavior of the 
> RTM_NEWADDR message.
> 
> I appreciate if people can test it and report back.  It should be pretty
> safe from the IPv4 side, but I'd like to know if it causes any
> regression in IPv6 land.

Unless I hear an objection I'll commit this diff tomorrow.

> Index: net/route.c
> ===================================================================
> RCS file: /home/ncvs/src/sys/net/route.c,v
> retrieving revision 1.168
> diff -u -p -r1.168 route.c
> --- net/route.c       27 May 2014 19:38:15 -0000      1.168
> +++ net/route.c       28 May 2014 11:59:14 -0000
> @@ -1097,6 +1097,7 @@ rt_ifa_add(struct ifaddr *ifa, int flags
>       struct sockaddr_rtlabel  sa_rl;
>       struct rt_addrinfo       info;
>       u_short                  rtableid = ifa->ifa_ifp->if_rdomain;
> +     u_int8_t                 prio = RTP_CONNECTED;
>       int                      error;
>  
>       memset(&info, 0, sizeof(info));
> @@ -1110,7 +1111,10 @@ rt_ifa_add(struct ifaddr *ifa, int flags
>       if ((flags & RTF_HOST) == 0)
>               info.rti_info[RTAX_NETMASK] = ifa->ifa_netmask;
>  
> -     error = rtrequest1(RTM_ADD, &info, RTP_CONNECTED, &nrt, rtableid);
> +     if (flags & RTF_LOCAL)
> +             prio = RTP_LOCAL;
> +
> +     error = rtrequest1(RTM_ADD, &info, prio, &nrt, rtableid);
>       if (error == 0 && (rt = nrt) != NULL) {
>               rt->rt_refcnt--;
>               if (rt->rt_ifa != ifa) {
> @@ -1125,7 +1129,8 @@ rt_ifa_add(struct ifaddr *ifa, int flags
>                       if (ifa->ifa_rtrequest)
>                               ifa->ifa_rtrequest(RTM_ADD, rt);
>               }
> -             rt_newaddrmsg(RTM_ADD, ifa, error, nrt);
> +             if (flags & RTF_LOCAL)
> +                     rt_newaddrmsg(RTM_ADD, ifa, error, nrt);
>       }
>       return (error);
>  }
> @@ -1139,6 +1144,7 @@ rt_ifa_del(struct ifaddr *ifa, int flags
>       struct rt_addrinfo       info;
>       struct sockaddr_rtlabel  sa_rl;
>       u_short                  rtableid = ifa->ifa_ifp->if_rdomain;
> +     u_int8_t                 prio = RTP_CONNECTED;
>       int                      error;
>  
>       if ((flags & RTF_HOST) == 0 && ifa->ifa_netmask) {
> @@ -1173,9 +1179,13 @@ rt_ifa_del(struct ifaddr *ifa, int flags
>       if ((flags & RTF_HOST) == 0)
>               info.rti_info[RTAX_NETMASK] = ifa->ifa_netmask;
>  
> -     error = rtrequest1(RTM_DELETE, &info, RTP_CONNECTED, &nrt, rtableid);
> +     if (flags & RTF_LOCAL)
> +             prio = RTP_LOCAL;
> +
> +     error = rtrequest1(RTM_DELETE, &info, prio, &nrt, rtableid);
>       if (error == 0 && (rt = nrt) != NULL) {
> -             rt_newaddrmsg(RTM_DELETE, ifa, error, nrt);
> +             if (flags & RTF_LOCAL)
> +                     rt_newaddrmsg(RTM_DELETE, ifa, error, nrt);
>               if (rt->rt_refcnt <= 0) {
>                       rt->rt_refcnt++;
>                       rtfree(rt);
> @@ -1199,7 +1209,8 @@ rt_ifa_addloop(struct ifaddr *ifa)
>       rt = rtalloc1(ifa->ifa_addr, 0, ifa->ifa_ifp->if_rdomain);
>       if (rt == NULL || (rt->rt_flags & RTF_HOST) == 0 ||
>           (rt->rt_ifp->if_flags & IFF_LOOPBACK) == 0)
> -             rt_ifa_add(ifa, RTF_UP| RTF_HOST | RTF_LLINFO, ifa->ifa_addr);
> +             rt_ifa_add(ifa, RTF_UP| RTF_HOST | RTF_LLINFO | RTF_LOCAL,
> +                 ifa->ifa_addr);
>       if (rt)
>               rt->rt_refcnt--;
>  }
> @@ -1223,7 +1234,8 @@ rt_ifa_delloop(struct ifaddr *ifa)
>       rt = rtalloc1(ifa->ifa_addr, 0, ifa->ifa_ifp->if_rdomain);
>       if (rt != NULL && (rt->rt_flags & RTF_HOST) != 0 &&
>           (rt->rt_ifp->if_flags & IFF_LOOPBACK) != 0)
> -             rt_ifa_del(ifa,  RTF_HOST | RTF_LLINFO,  ifa->ifa_addr);
> +             rt_ifa_del(ifa,  RTF_HOST | RTF_LLINFO | RTF_LOCAL,
> +                 ifa->ifa_addr);
>       if (rt)
>               rt->rt_refcnt--;
>  }
> 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        28 May 2014 11:59:14 -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      28 May 2014 11:59:14 -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