aboutgitcodebugslistschat
path: root/netlink.c
diff options
context:
space:
mode:
authorStefano Brivio <sbrivio@redhat.com>2024-03-15 13:25:44 +0100
committerStefano Brivio <sbrivio@redhat.com>2024-03-18 08:57:21 +0100
commitf919dc7a4b1ced7e80d790a654900415e1d6250e (patch)
tree191d4aa53845e3f6eb2af8156a10b7496c76b04a /netlink.c
parentf00b153414b1e57e41cfb49cf0ac15c747f6c910 (diff)
downloadpasst-f919dc7a4b1ced7e80d790a654900415e1d6250e.tar
passt-f919dc7a4b1ced7e80d790a654900415e1d6250e.tar.gz
passt-f919dc7a4b1ced7e80d790a654900415e1d6250e.tar.bz2
passt-f919dc7a4b1ced7e80d790a654900415e1d6250e.tar.lz
passt-f919dc7a4b1ced7e80d790a654900415e1d6250e.tar.xz
passt-f919dc7a4b1ced7e80d790a654900415e1d6250e.tar.zst
passt-f919dc7a4b1ced7e80d790a654900415e1d6250e.zip
conf, netlink: Don't require a default route to start
There might be isolated testing environments where default routes and global connectivity are not needed, a single interface has all non-loopback addresses and routes, and still passt and pasta are expected to work. In this case, it's pretty obvious what our upstream interface should be, so go ahead and select the only interface with at least one route, disabling DHCP and implying --no-map-gw as the documentation already states. If there are multiple interfaces with routes, though, refuse to start, because at that point it's really not clear what we should do. Reported-by: Martin Pitt <mpitt@redhat.com> Link: https://github.com/containers/podman/issues/21896 Signed-off-by: Stefano brivio <sbrivio@redhat.com> Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
Diffstat (limited to 'netlink.c')
-rw-r--r--netlink.c31
1 files changed, 28 insertions, 3 deletions
diff --git a/netlink.c b/netlink.c
index 20de9b3..f93f377 100644
--- a/netlink.c
+++ b/netlink.c
@@ -254,6 +254,7 @@ unsigned int nl_get_ext_if(int s, sa_family_t af)
.rtm.rtm_type = RTN_UNICAST,
.rtm.rtm_family = af,
};
+ bool default_only = true;
unsigned int ifi = 0;
struct nlmsghdr *nh;
struct rtattr *rta;
@@ -262,21 +263,40 @@ unsigned int nl_get_ext_if(int s, sa_family_t af)
uint32_t seq;
size_t na;
+again:
+ /* Look for an interface with a default route first, failing that, look
+ * for any interface with a route, and pick it only if it's the only
+ * interface with a route.
+ */
seq = nl_send(s, &req, RTM_GETROUTE, NLM_F_DUMP, sizeof(req));
nl_foreach_oftype(nh, status, s, buf, seq, RTM_NEWROUTE) {
struct rtmsg *rtm = (struct rtmsg *)NLMSG_DATA(nh);
- if (ifi || rtm->rtm_dst_len || rtm->rtm_family != af)
- continue;
+ if (default_only) {
+ if (ifi || rtm->rtm_dst_len || rtm->rtm_family != af)
+ continue;
+ } else {
+ if (rtm->rtm_family != af)
+ continue;
+ }
for (rta = RTM_RTA(rtm), na = RTM_PAYLOAD(nh); RTA_OK(rta, na);
rta = RTA_NEXT(rta, na)) {
if (rta->rta_type == RTA_OIF) {
+ if (!default_only && ifi &&
+ ifi != *(unsigned int *)RTA_DATA(rta))
+ return 0;
+
ifi = *(unsigned int *)RTA_DATA(rta);
} else if (rta->rta_type == RTA_MULTIPATH) {
const struct rtnexthop *rtnh;
rtnh = (struct rtnexthop *)RTA_DATA(rta);
+
+ if (!default_only && ifi &&
+ (int)ifi != rtnh->rtnh_ifindex)
+ return 0;
+
ifi = rtnh->rtnh_ifindex;
}
}
@@ -285,6 +305,11 @@ unsigned int nl_get_ext_if(int s, sa_family_t af)
if (status < 0)
warn("netlink: RTM_GETROUTE failed: %s", strerror(-status));
+ if (!ifi && default_only) {
+ default_only = false;
+ goto again;
+ }
+
return ifi;
}
@@ -332,7 +357,7 @@ bool nl_route_get_def_multipath(struct rtattr *rta, void *gw)
* @af: Address family
* @gw: Default gateway to fill on NL_GET
*
- * Return: 0 on success, negative error code on failure
+ * Return: error on netlink failure, or 0 (gw unset if default route not found)
*/
int nl_route_get_def(int s, unsigned int ifi, sa_family_t af, void *gw)
{