Re: Create a default local route for every IPv4 address

2014-06-10 Thread Martin Pieuchot
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 -  1.168
 +++ net/route.c   28 May 2014 11:59:14 -
 @@ -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 +,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 

Re: Create a default local route for every IPv4 address

2014-05-28 Thread Martin Pieuchot
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 -  1.168
+++ net/route.c 28 May 2014 11:59:14 -
@@ -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 +,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  

Re: Create a default local route for every IPv4 address

2014-05-28 Thread Kenneth Westerback
On 28 May 2014 10:15, Martin Pieuchot mpieuc...@nolizard.org 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.


In my tree and snap a-building.

 Ken

 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 -  1.168
 +++ net/route.c 28 May 2014 11:59:14 -
 @@ -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 +,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)

Re: Create a default local route for every IPv4 address

2014-05-28 Thread Kenneth Westerback
On 28 May 2014 10:18, Kenneth Westerback kwesterb...@gmail.com wrote:
 On 28 May 2014 10:15, Martin Pieuchot mpieuc...@nolizard.org 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.


 In my tree and snap a-building.

  Ken

And dhclient does seem to like this much better. I withdraw my
objection, even if I don't understand enough to ok it. :-)

 Ken


 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 -  1.168
 +++ net/route.c 28 May 2014 11:59:14 -
 @@ -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 +,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)
 -   

Create a default local route for every IPv4 address

2014-05-26 Thread Martin Pieuchot
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   02 - 4
lo0  
+10.3.3.2   00:00:24:cc:21:eb  UHL00 - 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  00 - 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 -   1.127
+++ netinet/if_ether.c  26 May 2014 09:46:42 -
@@ -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 != 0x)
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.c25 Apr 2014 09:44:38 -  1.96
+++ netinet/in.c26 May 2014 09:46:42 -
@@ -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);



Re: Create a default local route for every IPv4 address

2014-05-26 Thread Kenneth Westerback
On 26 May 2014 06:10, Martin Pieuchot mpieuc...@nolizard.org wrote:
 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   02 - 4  
   lo0
 +10.3.3.2   00:00:24:cc:21:eb  UHL00 - 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  00 - 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?

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.

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.

I'm in the middle of some other stuff but I certainly want to test
this to make sure there are no bad side effects on dhclient.

 Ken



 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 -   1.127
 +++ netinet/if_ether.c  26 May 2014 09:46:42 -
 @@ -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 != 0x)
 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.c25 Apr 2014 09:44:38 -  1.96
 +++ netinet/in.c26 May 2014 09:46:42 -
 @@ -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);



Re: Create a default local route for every IPv4 address

2014-05-26 Thread Henning Brauer
* Kenneth Westerback kwesterb...@gmail.com [2014-05-26 14:05]:
 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.

there is a broad difference between the kernel does it always and
in some cases, some userland app does it. in the former case, the
existance of the local route can be used e. g. for the local/remote
decision, in the latter case that is utterly unreliable.

-- 
Henning Brauer, h...@bsws.de, henn...@openbsd.org
BS Web Services GmbH, http://bsws.de, Full-Service ISP
Secure Hosting, Mail and DNS. Virtual  Dedicated Servers, Root to Fully Managed
Henning Brauer Consulting, http://henningbrauer.com/



Re: Create a default local route for every IPv4 address

2014-05-26 Thread Martin Pieuchot
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.

 I'm in the middle of some other stuff but I certainly want to test
 this to make sure there are no bad side effects on dhclient.

No rush, let me know when you're done :)

Martin