Send an IFP to distinguish (default) routes over different interfaces
authorflorian <florian@openbsd.org>
Sat, 23 Jul 2022 09:29:20 +0000 (09:29 +0000)
committerflorian <florian@openbsd.org>
Sat, 23 Jul 2022 09:29:20 +0000 (09:29 +0000)
to the same gateway.

Unfortunately this doesn't help with deleting the correct route when
issuing ifconfig inet -autoconf, the kernel always deletes the first
route. This is the one with the lowest priority if the routes have
different priorities.

What does work is identifying routes by priority but dhcpleased(8)
doesn't set the priority so that the kernel choses the right one
when adding a route and it doesn't yet track the priority the
kernel set.

Another issue is that we might end up with routes having the same
gateway and same priority pointing out of different interfaces. For
example when two ethernet interfaces are set to autoconf and they are
connected to the layer 2 network. This seems like a bad idea but it is
something that could be configured.

Problem reported by mbuhl, claudio suggested to try to send an IFP.

Even though it doesn't work, it seems worthwhile to send the IFP for
when the kernel gains the ability to distinguish routes by IFP.

sbin/dhcpleased/dhcpleased.c

index f57dda5..bfd7c84 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: dhcpleased.c,v 1.24 2022/03/21 04:35:41 dlg Exp $     */
+/*     $OpenBSD: dhcpleased.c,v 1.25 2022/07/23 09:29:20 florian Exp $ */
 
 /*
  * Copyright (c) 2017, 2021 Florian Obser <florian@openbsd.org>
@@ -30,6 +30,7 @@
 
 #include <net/if.h>
 #include <net/route.h>
+#include <net/if_dl.h>
 #include <netinet/in.h>
 #include <netinet/if_ether.h>
 #include <netinet/in_var.h>
@@ -1014,8 +1015,9 @@ configure_route(uint8_t rtm_type, uint32_t if_index, int rdomain, struct
     struct sockaddr_in *ifa, int rtm_flags)
 {
        struct rt_msghdr                 rtm;
+       struct sockaddr_dl               ifp;
        struct sockaddr_rtlabel          rl;
-       struct iovec                     iov[12];
+       struct iovec                     iov[14];
        long                             pad = 0;
        int                              iovcnt = 0, padlen;
 
@@ -1028,7 +1030,8 @@ configure_route(uint8_t rtm_type, uint32_t if_index, int rdomain, struct
        rtm.rtm_tableid = rdomain;
        rtm.rtm_seq = ++rtm_seq;
        rtm.rtm_priority = RTP_NONE;
-       rtm.rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK | RTA_LABEL;
+       rtm.rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK | RTA_IFP |
+           RTA_LABEL;
        rtm.rtm_flags = RTF_UP | RTF_STATIC | RTF_MPATH | rtm_flags;
 
        if (ifa)
@@ -1067,6 +1070,20 @@ configure_route(uint8_t rtm_type, uint32_t if_index, int rdomain, struct
                rtm.rtm_msglen += padlen;
        }
 
+       memset(&ifp, 0, sizeof(ifp));
+       ifp.sdl_len = sizeof(struct sockaddr_dl);
+       ifp.sdl_family = AF_LINK;
+       ifp.sdl_index = if_index;
+       iov[iovcnt].iov_base = &ifp;
+       iov[iovcnt++].iov_len = sizeof(ifp);
+       rtm.rtm_msglen += sizeof(ifp);
+       padlen = ROUNDUP(sizeof(ifp)) - sizeof(ifp);
+       if (padlen > 0) {
+               iov[iovcnt].iov_base = &pad;
+               iov[iovcnt++].iov_len = padlen;
+               rtm.rtm_msglen += padlen;
+       }
+
        if (ifa) {
                iov[iovcnt].iov_base = ifa;
                iov[iovcnt++].iov_len = ifa->sin_len;