pasta: Strip RTA_PREFSRC when copying routes to the namespace

Host routes can include a preferred source address (RTA_PREFSRC), which
must be one of the host's addresses.  However when using pasta with -a the
namespace might be given a different address, not on the host.  This seems
to occur pretty routinely depending on the network configuration systems
in place on the host.

With --config-net we will try to copy host routes to the namespace.  If
one of those includes an RTA_PREFSRC, but the namespace doesn't have the
host address, this will fail with -EINVAL, causing pasta to fail.

Fix this by stripping off RTA_PREFSRC attributes from routes as we copy
them to the namespace.  This is by no means infallible, bit it should at
least handle common cases for the time being.

Link: https://bugs.passt.top/show_bug.cgi?id=71
Link: https://github.com/containers/podman/pull/19699#issuecomment-1688769287
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
This commit is contained in:
David Gibson 2023-08-23 17:03:38 +10:00 committed by Stefano Brivio
parent 5e4f7b92b0
commit a7e4bfb857

View file

@ -462,8 +462,21 @@ int nl_route_dup(int s_src, unsigned int ifi_src,
for (rta = RTM_RTA(rtm), na = RTM_PAYLOAD(nh); RTA_OK(rta, na); for (rta = RTM_RTA(rtm), na = RTM_PAYLOAD(nh); RTA_OK(rta, na);
rta = RTA_NEXT(rta, na)) { rta = RTA_NEXT(rta, na)) {
if (rta->rta_type == RTA_OIF) if (rta->rta_type == RTA_OIF) {
/* The host obviously list's the host interface
* id here, we need to change it to the
* namespace's interface id
*/
*(unsigned int *)RTA_DATA(rta) = ifi_dst; *(unsigned int *)RTA_DATA(rta) = ifi_dst;
} else if (rta->rta_type == RTA_PREFSRC) {
/* Host routes might include a preferred source
* address, which must be one of the host's
* addresses. However, with -a pasta will use a
* different namespace address, making such a
* route invalid in the namespace. Strip off
* RTA_PREFSRC attributes to avoid that. */
rta->rta_type = RTA_UNSPEC;
}
} }
} }