gnetworkmonitornetlink: handle default route via device

If the default route is via a device rather than a particular IP
address, then neither RTA_DST nor RTA_GATEWAY will be present in the
RTM_NEWROUTE message, and so GNetworkMonitorNetlink would ignore it,
and then think there was no default route. (This could happen with
certain kinds of VPNs, if they were set to route all traffic through
the VPN.)

Fix this by recognizing routes that specify RTA_OIF ("output
interface") instead of RTA_GATEWAY.

https://bugzilla.gnome.org/show_bug.cgi?id=701609
This commit is contained in:
Dan Winship 2013-06-04 17:29:55 -03:00
parent 973464781c
commit c08ef6c165

View File

@ -218,8 +218,7 @@ static void
add_network (GNetworkMonitorNetlink *nl, add_network (GNetworkMonitorNetlink *nl,
GSocketFamily family, GSocketFamily family,
gint dest_len, gint dest_len,
guint8 *dest, guint8 *dest)
guint8 *gateway)
{ {
GInetAddress *dest_addr; GInetAddress *dest_addr;
GInetAddressMask *network; GInetAddressMask *network;
@ -245,8 +244,7 @@ static void
remove_network (GNetworkMonitorNetlink *nl, remove_network (GNetworkMonitorNetlink *nl,
GSocketFamily family, GSocketFamily family,
gint dest_len, gint dest_len,
guint8 *dest, guint8 *dest)
guint8 *gateway)
{ {
GInetAddress *dest_addr; GInetAddress *dest_addr;
GInetAddressMask *network; GInetAddressMask *network;
@ -305,7 +303,7 @@ read_netlink_messages (GSocket *socket,
struct rtmsg *rtmsg; struct rtmsg *rtmsg;
struct rtattr *attr; struct rtattr *attr;
gsize attrlen; gsize attrlen;
guint8 *dest, *gateway; guint8 *dest, *gateway, *oif;
gboolean retval = TRUE; gboolean retval = TRUE;
iv.buffer = NULL; iv.buffer = NULL;
@ -367,22 +365,24 @@ read_netlink_messages (GSocket *socket,
attrlen = NLMSG_PAYLOAD (msg, sizeof (struct rtmsg)); attrlen = NLMSG_PAYLOAD (msg, sizeof (struct rtmsg));
attr = RTM_RTA (rtmsg); attr = RTM_RTA (rtmsg);
dest = gateway = NULL; dest = gateway = oif = NULL;
while (RTA_OK (attr, attrlen)) while (RTA_OK (attr, attrlen))
{ {
if (attr->rta_type == RTA_DST) if (attr->rta_type == RTA_DST)
dest = RTA_DATA (attr); dest = RTA_DATA (attr);
else if (attr->rta_type == RTA_GATEWAY) else if (attr->rta_type == RTA_GATEWAY)
gateway = RTA_DATA (attr); gateway = RTA_DATA (attr);
else if (attr->rta_type == RTA_OIF)
oif = RTA_DATA (attr);
attr = RTA_NEXT (attr, attrlen); attr = RTA_NEXT (attr, attrlen);
} }
if (dest || gateway) if (dest || gateway || oif)
{ {
if (msg->nlmsg_type == RTM_NEWROUTE) if (msg->nlmsg_type == RTM_NEWROUTE)
add_network (nl, rtmsg->rtm_family, rtmsg->rtm_dst_len, dest, gateway); add_network (nl, rtmsg->rtm_family, rtmsg->rtm_dst_len, dest);
else else
remove_network (nl, rtmsg->rtm_family, rtmsg->rtm_dst_len, dest, gateway); remove_network (nl, rtmsg->rtm_family, rtmsg->rtm_dst_len, dest);
queue_request_dump (nl); queue_request_dump (nl);
} }
break; break;