From aa5b89a2ec8db5735925f78f3c91885a513ce51e Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Thu, 22 Oct 2015 15:15:47 +0200 Subject: ip4-config: let the IPv4 device route depend on the peer-address Usually, the peer-address is the same as the local address. In case where it is not, it is the peer-address that determines the IPv4 device-route. So we must use the peer-address. Also, don't consider device-routes with the first octet of zero, just like kernel does. Also, nm_ip4_config_get_subnet_for_host() is effectively the same as nm_ip4_config_destination_is_direct(). So drop it. --- src/devices/nm-device.c | 2 +- src/nm-ip4-config.c | 57 +++++++++++++++++++++++-------------------------- src/nm-ip4-config.h | 1 - 3 files changed, 28 insertions(+), 32 deletions(-) diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index 7338ff5ffb..9fe3d2ac71 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -3711,7 +3711,7 @@ ip4_config_merge_and_apply (NMDevice *self, goto END_ADD_DEFAULT_ROUTE; has_direct_route = ( gateway == 0 - || nm_ip4_config_get_subnet_for_host (composite, gateway) + || nm_ip4_config_destination_is_direct (composite, gateway, 32) || nm_ip4_config_get_direct_route_for_host (composite, gateway)); priv->default_route.v4_has = TRUE; diff --git a/src/nm-ip4-config.c b/src/nm-ip4-config.c index 413dec520e..5c35605d4b 100644 --- a/src/nm-ip4-config.c +++ b/src/nm-ip4-config.c @@ -100,13 +100,13 @@ nm_ip4_config_get_ifindex (const NMIP4Config *config) return NM_IP4_CONFIG_GET_PRIVATE (config)->ifindex; } +/******************************************************************/ + static gboolean -same_prefix (guint32 address1, guint32 address2, int plen) +_ipv4_is_zeronet (in_addr_t network) { - guint32 masked1 = ntohl (address1) >> (32 - plen); - guint32 masked2 = ntohl (address2) >> (32 - plen); - - return masked1 == masked2; + /* Same as ipv4_is_zeronet() from kernel's include/linux/in.h. */ + return (network & htonl(0xff000000)) == htonl(0x00000000); } /******************************************************************/ @@ -307,7 +307,16 @@ nm_ip4_config_commit (const NMIP4Config *config, int ifindex, gboolean routes_fu route.ifindex = ifindex; route.source = NM_IP_CONFIG_SOURCE_KERNEL; - route.network = nm_utils_ip4_address_clear_host_address (addr->address, addr->plen); + + /* The destination network depends on the peer-address. */ + route.network = nm_utils_ip4_address_clear_host_address (nm_platform_ip4_address_get_peer (addr), addr->plen); + + if (_ipv4_is_zeronet (route.network)) { + /* Kernel doesn't add device-routes for destinations that + * start with 0.x.y.z. Skip them. */ + continue; + } + route.plen = addr->plen; route.pref_src = addr->address; route.metric = default_route_metric; @@ -1256,12 +1265,22 @@ nm_ip4_config_destination_is_direct (const NMIP4Config *config, guint32 network, { guint naddresses = nm_ip4_config_get_num_addresses (config); int i; + in_addr_t peer_network; for (i = 0; i < naddresses; i++) { const NMPlatformIP4Address *item = nm_ip4_config_get_address (config, i); - if (item->plen <= plen && same_prefix (item->address, network, item->plen)) - return TRUE; + if (item->plen > plen) + continue; + + peer_network = nm_utils_ip4_address_clear_host_address (nm_platform_ip4_address_get_peer (item), item->plen); + if (_ipv4_is_zeronet (peer_network)) + continue; + + if (peer_network != nm_utils_ip4_address_clear_host_address (network, item->plen)) + continue; + + return TRUE; } return FALSE; @@ -1554,28 +1573,6 @@ nm_ip4_config_get_direct_route_for_host (const NMIP4Config *config, guint32 host return best_route; } -const NMPlatformIP4Address * -nm_ip4_config_get_subnet_for_host (const NMIP4Config *config, guint32 host) -{ - NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); - guint i; - NMPlatformIP4Address *subnet = NULL; - - g_return_val_if_fail (host, NULL); - - for (i = 0; i < priv->addresses->len; i++) { - NMPlatformIP4Address *item = &g_array_index (priv->addresses, NMPlatformIP4Address, i); - - if (subnet && subnet->plen >= item->plen) - continue; - if (nm_utils_ip4_address_clear_host_address (host, item->plen) != nm_utils_ip4_address_clear_host_address (item->address, item->plen)) - continue; - subnet = item; - } - - return subnet; -} - /******************************************************************/ void diff --git a/src/nm-ip4-config.h b/src/nm-ip4-config.h index 1c76b97e99..160f2246bf 100644 --- a/src/nm-ip4-config.h +++ b/src/nm-ip4-config.h @@ -102,7 +102,6 @@ guint32 nm_ip4_config_get_num_routes (const NMIP4Config *config); const NMPlatformIP4Route *nm_ip4_config_get_route (const NMIP4Config *config, guint32 i); const NMPlatformIP4Route *nm_ip4_config_get_direct_route_for_host (const NMIP4Config *config, guint32 host); -const NMPlatformIP4Address *nm_ip4_config_get_subnet_for_host (const NMIP4Config *config, guint32 host); /* Nameservers */ void nm_ip4_config_reset_nameservers (NMIP4Config *config); -- cgit v1.2.1