On 26/02/16(Fri) 17:38, Matthieu Herrb wrote:
> My hosting ISP is using a routing model where every machine has
> a IP address with a /32 mask and uses a default route specificed at
> the link level.
[...]
> For OpenBSD this setup maps to
> 
> hostname.em0:
> 
>     inet 92.224.149.DDD/32
>     ! route add 91.224.148.0/32 -link -iface em0
> 
> /etc/mygate:
> 
>     91.224.148.0
> 
> While this works when configured manually (an ARP request is generated
> by the route add -link command and both the ARP and route entries show
> up), it tends to not beeing stable (ie the default route disapears):
> 
> 1. on boot while I explicitely see the '! route' command output in
>   dmesg -s, the default route doesn't work after the boot, the /32
>   route has disapeared once the machine reaches the login: prompt to
>   let me connect on console and check it. If I run the command manualy
>   again, the route becomes active again and is useable.
>   So it seems that something flushes the ARP table after executing the
>   route command in /etc/hostname.if
> 
> 2. but if I quiese the network for 20mn to let the ARP entry for the
>   router time out, then again the associated route disapears.
> 
> I can work around these problems by putting a permanent ARP entry for
> the router in rc.local, but I'd like to know if there isn't some kind
> of bug that needs to be fixed there.
> 
> This kind of routing setup seems popular among cloud style VM hosting
> providers, and with the growing support for running OpenBSD as a
> guest, I guess this is going to become a more frequent issue.

The problem here is that you're generating the route entry manually so
when the ARP timer will expire the entry will be removed.

Instead of adding a "link" entry I would add a cloning route that will
generate it.  The first diff below changes route(8) to not add a
RTF_GATEWAY flag when creating a RTF_CLONING entry.  With it you should
be able to add a working cloning route with:

# route add 91.224.148.0 -netmask 255.255.255.255 -cloning 92.224.149.DDD

Note that the CIDR notation wont work due to another route(8) limitation.

If this approach is acceptable, the second diff makes sure RTF_CLONING
is never set with RTF_GATEWAY or RTF_HOST.  Claudio do you think this
could have any drawback?

Index: route.c
===================================================================
RCS file: /cvs/src/sbin/route/route.c,v
retrieving revision 1.182
diff -u -p -r1.182 route.c
--- route.c     3 Dec 2015 08:00:49 -0000       1.182
+++ route.c     27 Feb 2016 14:02:56 -0000
@@ -629,7 +629,7 @@ newroute(int argc, char **argv)
        flags |= RTF_UP;
        if (ishost)
                flags |= RTF_HOST;
-       if (iflag == 0)
+       if (iflag == 0 && !(flags & RTF_CLONING))
                flags |= RTF_GATEWAY;
        for (attempts = 1; ; attempts++) {
                errno = 0;




Index: net/rtsock.c
===================================================================
RCS file: /cvs/src/sys/net/rtsock.c,v
retrieving revision 1.186
diff -u -p -r1.186 rtsock.c
--- net/rtsock.c        12 Jan 2016 09:27:46 -0000      1.186
+++ net/rtsock.c        27 Feb 2016 14:09:56 -0000
@@ -558,6 +558,12 @@ route_output(struct mbuf *m, ...)
        rtm->rtm_flags &= ~(RTF_DONE|RTF_CLONED);
        rtm->rtm_fmask &= RTF_FMASK;
 
+       if ((rtm->rtm_flags & (RTF_CLONING|RTF_GATEWAY|RTF_HOST)) ==
+           (RTF_CLONING|RTF_GATEWAY|RTF_HOST)) {
+               error = EINVAL;
+               goto fail;
+       }
+
        if (rtm->rtm_priority != 0) {
                if (rtm->rtm_priority > RTP_MAX ||
                    rtm->rtm_priority == RTP_LOCAL) {

Reply via email to