aboutgitcodebugslistschat
path: root/netlink.c
diff options
context:
space:
mode:
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)
{