]> git.ipfire.org Git - thirdparty/strongswan.git/commitdiff
kernel-pfroute: Route via interface if we don't have a next hop
authorTobias Brunner <tobias@strongswan.org>
Tue, 28 Sep 2021 08:10:04 +0000 (10:10 +0200)
committerTobias Brunner <tobias@strongswan.org>
Wed, 25 Sep 2024 14:12:34 +0000 (16:12 +0200)
Compared to RTA_IFP, the format is different when passing an interface
as RTA_GATEWAY, it requires the interface's address and not its name.

src/libcharon/plugins/kernel_pfroute/kernel_pfroute_net.c

index 815ba255874d9806b45f32efe64435f3536e730d..5caf5f2c014b3cf337f7dcd49516f45325745d8a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009-2016 Tobias Brunner
+ * Copyright (C) 2009-2024 Tobias Brunner
  *
  * Copyright (C) secunet Security Networks AG
  *
@@ -1443,6 +1443,35 @@ static void add_rt_ifname(struct rt_msghdr *hdr, int type, char *name)
        }
 }
 
+/**
+ * Append an interface address sockaddr_dl to routing message
+ */
+static void add_rt_ifaddr(struct rt_msghdr *hdr, int type, char *name)
+{
+       struct ifaddrs *ifap, *ifa;
+       struct sockaddr_dl *sdl;
+
+       if (getifaddrs(&ifap) < 0)
+       {
+               return;
+       }
+
+       for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next)
+       {
+               if (!ifa->ifa_addr || ifa->ifa_addr->sa_family != AF_LINK ||
+                       !streq(name, ifa->ifa_name))
+               {
+                       continue;
+               }
+               sdl = (struct sockaddr_dl*)ifa->ifa_addr;
+               memcpy((char*)hdr + hdr->rtm_msglen, sdl, sdl->sdl_len);
+               hdr->rtm_msglen += SA_LEN(sdl->sdl_len);
+               hdr->rtm_addrs |= type;
+               break;
+       }
+       freeifaddrs(ifap);
+}
+
 /**
  * Add or remove a route
  */
@@ -1519,6 +1548,10 @@ static status_t manage_route(private_kernel_pfroute_net_t *this, int op,
                                {
                                        add_rt_addr(&msg.hdr, RTA_GATEWAY, gateway);
                                }
+                               else if (if_name)
+                               {
+                                       add_rt_ifaddr(&msg.hdr, RTA_GATEWAY, if_name);
+                               }
                                break;
                        default:
                                break;