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.
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);