kernel-pfroute: Route via interface if we don't have a next hop

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.
This commit is contained in:
Tobias Brunner
2024-09-25 16:12:34 +02:00
parent fccc76449d
commit bf165afb78
@@ -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;