diff --git a/src/NetworkManagerUtils.c b/src/NetworkManagerUtils.c index 71513a4f7..20cd2aa2f 100644 --- a/src/NetworkManagerUtils.c +++ b/src/NetworkManagerUtils.c @@ -153,229 +153,6 @@ nm_utils_ip4_prefix_to_netmask (guint32 prefix) return (guint32) htonl (netmask); } -void -nm_utils_merge_ip4_config (NMIP4Config *ip4_config, NMSettingIP4Config *setting) -{ - int i, j; - gboolean setting_never_default; - - if (!setting) - return; /* Defaults are just fine */ - - if (nm_setting_ip4_config_get_ignore_auto_dns (setting)) { - nm_ip4_config_reset_nameservers (ip4_config); - nm_ip4_config_reset_domains (ip4_config); - nm_ip4_config_reset_searches (ip4_config); - } - - if (nm_setting_ip4_config_get_ignore_auto_routes (setting)) - nm_ip4_config_reset_routes (ip4_config); - - for (i = 0; i < nm_setting_ip4_config_get_num_dns (setting); i++) { - guint32 ns; - gboolean found = FALSE; - - /* Avoid dupes */ - ns = nm_setting_ip4_config_get_dns (setting, i); - for (j = 0; j < nm_ip4_config_get_num_nameservers (ip4_config); j++) { - if (nm_ip4_config_get_nameserver (ip4_config, j) == ns) { - found = TRUE; - break; - } - } - - if (!found) - nm_ip4_config_add_nameserver (ip4_config, ns); - } - - /* DNS search domains */ - for (i = 0; i < nm_setting_ip4_config_get_num_dns_searches (setting); i++) { - const char *search = nm_setting_ip4_config_get_dns_search (setting, i); - gboolean found = FALSE; - - /* Avoid dupes */ - for (j = 0; j < nm_ip4_config_get_num_searches (ip4_config); j++) { - if (!strcmp (search, nm_ip4_config_get_search (ip4_config, j))) { - found = TRUE; - break; - } - } - - if (!found) - nm_ip4_config_add_search (ip4_config, search); - } - - /* IPv4 addresses */ - for (i = 0; i < nm_setting_ip4_config_get_num_addresses (setting); i++) { - NMIP4Address *setting_addr = nm_setting_ip4_config_get_address (setting, i); - guint32 num; - - num = nm_ip4_config_get_num_addresses (ip4_config); - for (j = 0; j < num; j++) { - NMIP4Address *cfg_addr = nm_ip4_config_get_address (ip4_config, j); - - /* Dupe, override with user-specified address */ - if (nm_ip4_address_get_address (cfg_addr) == nm_ip4_address_get_address (setting_addr)) { - nm_ip4_config_replace_address (ip4_config, j, setting_addr); - break; - } - } - - if (j == num) - nm_ip4_config_add_address (ip4_config, setting_addr); - } - - /* IPv4 routes */ - for (i = 0; i < nm_setting_ip4_config_get_num_routes (setting); i++) { - NMIP4Route *setting_route = nm_setting_ip4_config_get_route (setting, i); - guint32 num; - - num = nm_ip4_config_get_num_routes (ip4_config); - for (j = 0; j < num; j++) { - NMIP4Route *cfg_route = nm_ip4_config_get_route (ip4_config, j); - - /* Dupe, override with user-specified route */ - if ( (nm_ip4_route_get_dest (cfg_route) == nm_ip4_route_get_dest (setting_route)) - && (nm_ip4_route_get_prefix (cfg_route) == nm_ip4_route_get_prefix (setting_route)) - && (nm_ip4_route_get_next_hop (cfg_route) == nm_ip4_route_get_next_hop (setting_route))) { - nm_ip4_config_replace_route (ip4_config, j, setting_route); - break; - } - } - - if (j == num) - nm_ip4_config_add_route (ip4_config, setting_route); - } - - setting_never_default = nm_setting_ip4_config_get_never_default (setting); - - if (nm_setting_ip4_config_get_ignore_auto_routes (setting)) - nm_ip4_config_set_never_default (ip4_config, setting_never_default); - else { - if (setting_never_default) - nm_ip4_config_set_never_default (ip4_config, TRUE); - } -} - -static inline gboolean -ip6_addresses_equal (const struct in6_addr *a, const struct in6_addr *b) -{ - return memcmp (a, b, sizeof (struct in6_addr)) == 0; -} - -/* This is exactly identical to nm_utils_merge_ip4_config, with s/4/6/, - * except that we can't compare addresses with ==. - */ -void -nm_utils_merge_ip6_config (NMIP6Config *ip6_config, NMSettingIP6Config *setting) -{ - int i, j; - - if (!setting) - return; /* Defaults are just fine */ - - if (nm_setting_ip6_config_get_ignore_auto_dns (setting)) { - nm_ip6_config_reset_nameservers (ip6_config); - nm_ip6_config_reset_domains (ip6_config); - nm_ip6_config_reset_searches (ip6_config); - } - - if (nm_setting_ip6_config_get_ignore_auto_routes (setting)) - nm_ip6_config_reset_routes (ip6_config); - - for (i = 0; i < nm_setting_ip6_config_get_num_dns (setting); i++) { - const struct in6_addr *ns; - gboolean found = FALSE; - - /* Avoid dupes */ - ns = nm_setting_ip6_config_get_dns (setting, i); - for (j = 0; j < nm_ip6_config_get_num_nameservers (ip6_config); j++) { - if (ip6_addresses_equal (nm_ip6_config_get_nameserver (ip6_config, j), ns)) { - found = TRUE; - break; - } - } - - if (!found) - nm_ip6_config_add_nameserver (ip6_config, ns); - } - - /* DNS search domains */ - for (i = 0; i < nm_setting_ip6_config_get_num_dns_searches (setting); i++) { - const char *search = nm_setting_ip6_config_get_dns_search (setting, i); - gboolean found = FALSE; - - /* Avoid dupes */ - for (j = 0; j < nm_ip6_config_get_num_searches (ip6_config); j++) { - if (!strcmp (search, nm_ip6_config_get_search (ip6_config, j))) { - found = TRUE; - break; - } - } - - if (!found) - nm_ip6_config_add_search (ip6_config, search); - } - - /* IPv6 addresses */ - for (i = 0; i < nm_setting_ip6_config_get_num_addresses (setting); i++) { - NMIP6Address *setting_addr = nm_setting_ip6_config_get_address (setting, i); - guint32 num; - - num = nm_ip6_config_get_num_addresses (ip6_config); - for (j = 0; j < num; j++) { - NMIP6Address *cfg_addr = nm_ip6_config_get_address (ip6_config, j); - - /* Dupe, override with user-specified address */ - if (ip6_addresses_equal (nm_ip6_address_get_address (cfg_addr), nm_ip6_address_get_address (setting_addr))) { - nm_ip6_config_replace_address (ip6_config, j, setting_addr); - break; - } - } - - if (j == num) - nm_ip6_config_add_address (ip6_config, setting_addr); - } - - /* IPv6 routes */ - for (i = 0; i < nm_setting_ip6_config_get_num_routes (setting); i++) { - NMIP6Route *setting_route = nm_setting_ip6_config_get_route (setting, i); - guint32 num; - - num = nm_ip6_config_get_num_routes (ip6_config); - for (j = 0; j < num; j++) { - NMIP6Route *cfg_route = nm_ip6_config_get_route (ip6_config, j); - - /* Dupe, override with user-specified route */ - if ( ip6_addresses_equal (nm_ip6_route_get_dest (cfg_route), nm_ip6_route_get_dest (setting_route)) - && (nm_ip6_route_get_prefix (cfg_route) == nm_ip6_route_get_prefix (setting_route)) - && ip6_addresses_equal (nm_ip6_route_get_next_hop (cfg_route), nm_ip6_route_get_next_hop (setting_route))) { - nm_ip6_config_replace_route (ip6_config, j, setting_route); - break; - } - } - - if (j == num) - nm_ip6_config_add_route (ip6_config, setting_route); - } - - if (nm_setting_ip6_config_get_never_default (setting)) - nm_ip6_config_set_never_default (ip6_config, TRUE); -} - -gboolean -nm_match_spec_string (const GSList *specs, const char *match) -{ - const GSList *iter; - - for (iter = specs; iter; iter = g_slist_next (iter)) { - if (!g_ascii_strcasecmp ((const char *) iter->data, match)) - return TRUE; - } - - return FALSE; -} - gboolean nm_match_spec_hwaddr (const GSList *specs, const char *hwaddr) { diff --git a/src/NetworkManagerUtils.h b/src/NetworkManagerUtils.h index 2ed86afd3..819cb075c 100644 --- a/src/NetworkManagerUtils.h +++ b/src/NetworkManagerUtils.h @@ -36,9 +36,6 @@ gboolean nm_ethernet_address_is_valid (const struct ether_addr *test_addr); int nm_spawn_process (const char *args); -void nm_utils_merge_ip4_config (NMIP4Config *ip4_config, NMSettingIP4Config *setting); -void nm_utils_merge_ip6_config (NMIP6Config *ip6_config, NMSettingIP6Config *setting); - gboolean nm_match_spec_string (const GSList *specs, const char *string); gboolean nm_match_spec_hwaddr (const GSList *specs, const char *hwaddr); gboolean nm_match_spec_s390_subchannels (const GSList *specs, const char *subchannels); diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index 439279eb3..ef57b8129 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -1929,7 +1929,7 @@ autoip_changed (NMDevice *self, { NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE; - nm_utils_merge_ip4_config (config, s_ip4); + nm_ip4_config_merge_setting (config, s_ip4); if (!nm_device_set_ip4_config (self, config, TRUE, &reason)) { nm_log_err (LOGD_AUTOIP4, "(%s): failed to update IP4 config in response to autoip event.", nm_device_get_iface (self)); @@ -2179,7 +2179,7 @@ dhcp4_lease_change (NMDevice *device, NMIP4Config *config) g_assert (connection); /* Merge with user overrides */ - nm_utils_merge_ip4_config (config, nm_connection_get_setting_ip4_config (connection)); + nm_ip4_config_merge_setting (config, nm_connection_get_setting_ip4_config (connection)); if (!nm_device_set_ip4_config (device, config, TRUE, &reason)) { nm_log_warn (LOGD_DHCP4, "(%s): failed to update IPv4 config in response to DHCP event.", @@ -2603,7 +2603,7 @@ ip6_config_merge_and_apply (NMDevice *self, merge_ip6_configs (composite, priv->dhcp6_ip6_config); /* Merge user overrides into the composite config */ - nm_utils_merge_ip6_config (composite, nm_connection_get_setting_ip6_config (connection)); + nm_ip6_config_merge_setting (composite, nm_connection_get_setting_ip6_config (connection)); success = nm_device_set_ip6_config (self, composite, TRUE, out_reason); g_object_unref (composite); @@ -3697,7 +3697,7 @@ nm_device_activate_ip4_config_commit (gpointer user_data) NM_DEVICE_GET_CLASS (self)->ip4_config_pre_commit (self, config); /* Merge with user overrides */ - nm_utils_merge_ip4_config (config, nm_connection_get_setting_ip4_config (connection)); + nm_ip4_config_merge_setting (config, nm_connection_get_setting_ip4_config (connection)); if (!nm_device_set_ip4_config (self, config, TRUE, &reason)) { nm_log_info (LOGD_DEVICE | LOGD_IP4, @@ -4344,7 +4344,7 @@ nm_device_set_ip4_config (NMDevice *self, priv->ip4_config = g_object_ref (new_config); if (commit) - success = nm_system_apply_ip4_config (ip_ifindex, new_config, nm_device_get_priority (self)); + success = nm_ip4_config_commit (new_config, ip_ifindex, nm_device_get_priority (self)); if (success || !commit) { /* Export over D-Bus */ @@ -4401,7 +4401,7 @@ nm_device_set_ip6_config (NMDevice *self, priv->ip6_config = g_object_ref (new_config); if (commit) - success = nm_system_apply_ip6_config (ip_ifindex, new_config, nm_device_get_priority (self)); + success = nm_ip6_config_commit (new_config, ip_ifindex, nm_device_get_priority (self)); if (success || !commit) { /* Export over D-Bus */ @@ -5857,8 +5857,8 @@ update_ip_config (NMDevice *self) if (!ifindex) return; - ip4_config = nm_ip4_config_new_for_interface (ifindex); - ip6_config = nm_ip6_config_new_for_interface (ifindex); + ip4_config = nm_ip4_config_capture (ifindex); + ip6_config = nm_ip6_config_capture (ifindex); nm_device_set_ip4_config (self, ip4_config, FALSE, &ignored); nm_device_set_ip6_config (self, ip6_config, FALSE, &ignored); diff --git a/src/nm-ip4-config.c b/src/nm-ip4-config.c index 332d07ee9..3208a1644 100644 --- a/src/nm-ip4-config.c +++ b/src/nm-ip4-config.c @@ -79,8 +79,33 @@ nm_ip4_config_new (void) return (NMIP4Config *) g_object_new (NM_TYPE_IP4_CONFIG, NULL); } +void +nm_ip4_config_export (NMIP4Config *config) +{ + NMIP4ConfigPrivate *priv; + static guint32 counter = 0; + + g_return_if_fail (NM_IS_IP4_CONFIG (config)); + + priv = NM_IP4_CONFIG_GET_PRIVATE (config); + g_return_if_fail (priv->path == NULL); + + priv->path = g_strdup_printf (NM_DBUS_PATH "/IP4Config/%d", counter++); + nm_dbus_manager_register_object (nm_dbus_manager_get (), priv->path, config); +} + +const char * +nm_ip4_config_get_dbus_path (NMIP4Config *config) +{ + g_return_val_if_fail (NM_IS_IP4_CONFIG (config), NULL); + + return NM_IP4_CONFIG_GET_PRIVATE (config)->path; +} + +/******************************************************************/ + NMIP4Config * -nm_ip4_config_new_for_interface (int ifindex) +nm_ip4_config_capture (int ifindex) { NMIP4Config *ip4; GArray *addrs_array, *routes_array; @@ -128,29 +153,207 @@ nm_ip4_config_new_for_interface (int ifindex) return ip4; } +gboolean +nm_ip4_config_commit (NMIP4Config *config, int ifindex, int priority) +{ + int mtu = nm_ip4_config_get_mtu (config); + int i; + + g_return_val_if_fail (ifindex > 0, FALSE); + g_return_val_if_fail (config != NULL, FALSE); + + /* Addresses */ + { + int count = nm_ip4_config_get_num_addresses (config); + NMIP4Address *config_address; + GArray *addresses = g_array_sized_new (FALSE, FALSE, sizeof (NMPlatformIP4Address), count); + NMPlatformIP4Address address; + + for (i = 0; i < count; i++) { + config_address = nm_ip4_config_get_address (config, i); + memset (&address, 0, sizeof (address)); + address.address = nm_ip4_address_get_address (config_address); + address.plen = nm_ip4_address_get_prefix (config_address); + g_array_append_val (addresses, address); + } + + nm_platform_ip4_address_sync (ifindex, addresses); + g_array_unref (addresses); + } + + /* Routes */ + { + int count = nm_ip4_config_get_num_routes (config); + NMIP4Route *config_route; + GArray *routes = g_array_sized_new (FALSE, FALSE, sizeof (NMPlatformIP4Route), count); + NMPlatformIP4Route route; + + for (i = 0; i < count; i++) { + config_route = nm_ip4_config_get_route (config, i); + memset (&route, 0, sizeof (route)); + route.network = nm_ip4_route_get_dest (config_route); + route.plen = nm_ip4_route_get_prefix (config_route); + route.gateway = nm_ip4_route_get_next_hop (config_route); + route.metric = priority; + + /* Don't add the route if it's more specific than one of the subnets + * the device already has an IP address on. + */ + if (nm_ip4_config_destination_is_direct (config, route.network, route.plen)) + continue; + + /* Don't add the default route when and the connection + * is never supposed to be the default connection. + */ + if (nm_ip4_config_get_never_default (config) && route.network == 0) + continue; + + g_array_append_val (routes, route); + } + + nm_platform_ip4_route_sync (ifindex, routes); + g_array_unref (routes); + } + + /* MTU */ + if (mtu && mtu != nm_platform_link_get_mtu (ifindex)) + nm_platform_link_set_mtu (ifindex, mtu); + + return TRUE; +} + void -nm_ip4_config_export (NMIP4Config *config) +nm_ip4_config_merge_setting (NMIP4Config *ip4_config, NMSettingIP4Config *setting) { - NMIP4ConfigPrivate *priv; - static guint32 counter = 0; + int i, j; + gboolean setting_never_default; - g_return_if_fail (NM_IS_IP4_CONFIG (config)); + if (!setting) + return; /* Defaults are just fine */ - priv = NM_IP4_CONFIG_GET_PRIVATE (config); - g_return_if_fail (priv->path == NULL); + if (nm_setting_ip4_config_get_ignore_auto_dns (setting)) { + nm_ip4_config_reset_nameservers (ip4_config); + nm_ip4_config_reset_domains (ip4_config); + nm_ip4_config_reset_searches (ip4_config); + } - priv->path = g_strdup_printf (NM_DBUS_PATH "/IP4Config/%d", counter++); - nm_dbus_manager_register_object (nm_dbus_manager_get (), priv->path, config); + if (nm_setting_ip4_config_get_ignore_auto_routes (setting)) + nm_ip4_config_reset_routes (ip4_config); + + for (i = 0; i < nm_setting_ip4_config_get_num_dns (setting); i++) { + guint32 ns; + gboolean found = FALSE; + + /* Avoid dupes */ + ns = nm_setting_ip4_config_get_dns (setting, i); + for (j = 0; j < nm_ip4_config_get_num_nameservers (ip4_config); j++) { + if (nm_ip4_config_get_nameserver (ip4_config, j) == ns) { + found = TRUE; + break; + } + } + + if (!found) + nm_ip4_config_add_nameserver (ip4_config, ns); + } + + /* DNS search domains */ + for (i = 0; i < nm_setting_ip4_config_get_num_dns_searches (setting); i++) { + const char *search = nm_setting_ip4_config_get_dns_search (setting, i); + gboolean found = FALSE; + + /* Avoid dupes */ + for (j = 0; j < nm_ip4_config_get_num_searches (ip4_config); j++) { + if (!strcmp (search, nm_ip4_config_get_search (ip4_config, j))) { + found = TRUE; + break; + } + } + + if (!found) + nm_ip4_config_add_search (ip4_config, search); + } + + /* IPv4 addresses */ + for (i = 0; i < nm_setting_ip4_config_get_num_addresses (setting); i++) { + NMIP4Address *setting_addr = nm_setting_ip4_config_get_address (setting, i); + guint32 num; + + num = nm_ip4_config_get_num_addresses (ip4_config); + for (j = 0; j < num; j++) { + NMIP4Address *cfg_addr = nm_ip4_config_get_address (ip4_config, j); + + /* Dupe, override with user-specified address */ + if (nm_ip4_address_get_address (cfg_addr) == nm_ip4_address_get_address (setting_addr)) { + nm_ip4_config_replace_address (ip4_config, j, setting_addr); + break; + } + } + + if (j == num) + nm_ip4_config_add_address (ip4_config, setting_addr); + } + + /* IPv4 routes */ + for (i = 0; i < nm_setting_ip4_config_get_num_routes (setting); i++) { + NMIP4Route *setting_route = nm_setting_ip4_config_get_route (setting, i); + guint32 num; + + num = nm_ip4_config_get_num_routes (ip4_config); + for (j = 0; j < num; j++) { + NMIP4Route *cfg_route = nm_ip4_config_get_route (ip4_config, j); + + /* Dupe, override with user-specified route */ + if ( (nm_ip4_route_get_dest (cfg_route) == nm_ip4_route_get_dest (setting_route)) + && (nm_ip4_route_get_prefix (cfg_route) == nm_ip4_route_get_prefix (setting_route)) + && (nm_ip4_route_get_next_hop (cfg_route) == nm_ip4_route_get_next_hop (setting_route))) { + nm_ip4_config_replace_route (ip4_config, j, setting_route); + break; + } + } + + if (j == num) + nm_ip4_config_add_route (ip4_config, setting_route); + } + + setting_never_default = nm_setting_ip4_config_get_never_default (setting); + + if (nm_setting_ip4_config_get_ignore_auto_routes (setting)) + nm_ip4_config_set_never_default (ip4_config, setting_never_default); + else { + if (setting_never_default) + nm_ip4_config_set_never_default (ip4_config, TRUE); + } } -const char * -nm_ip4_config_get_dbus_path (NMIP4Config *config) -{ - g_return_val_if_fail (NM_IS_IP4_CONFIG (config), NULL); +/******************************************************************/ - return NM_IP4_CONFIG_GET_PRIVATE (config)->path; +gboolean +nm_ip4_config_destination_is_direct (NMIP4Config *config, guint32 dest, guint32 dest_prefix) +{ + int num; + int i; + + num = nm_ip4_config_get_num_addresses (config); + for (i = 0; i < num; i++) { + NMIP4Address *addr = nm_ip4_config_get_address (config, i); + guint32 prefix = nm_ip4_address_get_prefix (addr); + guint32 address = nm_ip4_address_get_address (addr); + + if (prefix <= dest_prefix) { + guint32 masked_addr = ntohl(address) >> (32 - prefix); + guint32 masked_dest = ntohl(dest) >> (32 - prefix); + + if (masked_addr == masked_dest) + return TRUE; + } + } + + return FALSE; } +/******************************************************************/ + void nm_ip4_config_take_address (NMIP4Config *config, NMIP4Address *address) { diff --git a/src/nm-ip4-config.h b/src/nm-ip4-config.h index e65753137..ce171aaf4 100644 --- a/src/nm-ip4-config.h +++ b/src/nm-ip4-config.h @@ -51,11 +51,18 @@ GType nm_ip4_config_get_type (void); NMIP4Config * nm_ip4_config_new (void); -NMIP4Config * nm_ip4_config_new_for_interface (int ifindex); void nm_ip4_config_export (NMIP4Config *config); const char * nm_ip4_config_get_dbus_path (NMIP4Config *config); +/* Integration with nm-platform and nm-setting */ +NMIP4Config *nm_ip4_config_capture (int ifindex); +gboolean nm_ip4_config_commit (NMIP4Config *config, int ifindex, int priority); +void nm_ip4_config_merge_setting (NMIP4Config *config, NMSettingIP4Config *setting); + +/* Utility functions */ +gboolean nm_ip4_config_destination_is_direct (NMIP4Config *config, guint32 dest, guint32 plen); + void nm_ip4_config_take_address (NMIP4Config *config, NMIP4Address *address); void nm_ip4_config_add_address (NMIP4Config *config, NMIP4Address *address); void nm_ip4_config_replace_address (NMIP4Config *config, guint32 i, NMIP4Address *new_address); diff --git a/src/nm-ip6-config.c b/src/nm-ip6-config.c index 3df4d9aa2..d9a3387e1 100644 --- a/src/nm-ip6-config.c +++ b/src/nm-ip6-config.c @@ -74,8 +74,45 @@ nm_ip6_config_new (void) return (NMIP6Config *) g_object_new (NM_TYPE_IP6_CONFIG, NULL); } +void +nm_ip6_config_export (NMIP6Config *config) +{ + NMIP6ConfigPrivate *priv; + static guint32 counter = 0; + + g_return_if_fail (NM_IS_IP6_CONFIG (config)); + + priv = NM_IP6_CONFIG_GET_PRIVATE (config); + g_return_if_fail (priv->path == NULL); + + priv->path = g_strdup_printf (NM_DBUS_PATH "/IP6Config/%d", counter++); + nm_dbus_manager_register_object (nm_dbus_manager_get (), priv->path, config); +} + +const char * +nm_ip6_config_get_dbus_path (NMIP6Config *config) +{ + g_return_val_if_fail (NM_IS_IP6_CONFIG (config), NULL); + + return NM_IP6_CONFIG_GET_PRIVATE (config)->path; +} + +void +nm_ip6_config_take_address (NMIP6Config *config, NMIP6Address *address) +{ + NMIP6ConfigPrivate *priv; + + g_return_if_fail (NM_IS_IP6_CONFIG (config)); + g_return_if_fail (address != NULL); + + priv = NM_IP6_CONFIG_GET_PRIVATE (config); + priv->addresses = g_slist_append (priv->addresses, address); +} + +/******************************************************************/ + NMIP6Config * -nm_ip6_config_new_for_interface (int ifindex) +nm_ip6_config_capture (int ifindex) { NMIP6Config *ip6; GArray *addrs_array, *routes_array; @@ -123,41 +160,224 @@ nm_ip6_config_new_for_interface (int ifindex) return ip6; } -void -nm_ip6_config_export (NMIP6Config *config) +gboolean +nm_ip6_config_commit (NMIP6Config *config, int ifindex, int priority) { - NMIP6ConfigPrivate *priv; - static guint32 counter = 0; + int i; - g_return_if_fail (NM_IS_IP6_CONFIG (config)); + g_return_val_if_fail (ifindex > 0, FALSE); + g_return_val_if_fail (config != NULL, FALSE); - priv = NM_IP6_CONFIG_GET_PRIVATE (config); - g_return_if_fail (priv->path == NULL); + /* Addresses */ + { + int count = nm_ip6_config_get_num_addresses (config); + NMIP6Address *config_address; + GArray *addresses = g_array_sized_new (FALSE, FALSE, sizeof (NMPlatformIP6Address), count); + NMPlatformIP6Address address; - priv->path = g_strdup_printf (NM_DBUS_PATH "/IP6Config/%d", counter++); - nm_dbus_manager_register_object (nm_dbus_manager_get (), priv->path, config); + for (i = 0; i < count; i++) { + config_address = nm_ip6_config_get_address (config, i); + memset (&address, 0, sizeof (address)); + address.address = *nm_ip6_address_get_address (config_address); + address.plen = nm_ip6_address_get_prefix (config_address); + g_array_append_val (addresses, address); + } + + nm_platform_ip6_address_sync (ifindex, addresses); + g_array_unref (addresses); + } + + /* Routes */ + { + int count = nm_ip6_config_get_num_routes (config); + NMIP6Route *config_route; + GArray *routes = g_array_sized_new (FALSE, FALSE, sizeof (NMPlatformIP6Route), count); + NMPlatformIP6Route route; + + for (i = 0; i < count; i++) { + config_route = nm_ip6_config_get_route (config, i); + memset (&route, 0, sizeof (route)); + route.network = *nm_ip6_route_get_dest (config_route); + route.plen = nm_ip6_route_get_prefix (config_route); + route.gateway = *nm_ip6_route_get_next_hop (config_route); + route.metric = priority; + + /* Don't add the route if it's more specific than one of the subnets + * the device already has an IP address on. + */ + if (nm_ip6_config_destination_is_direct (config, &route.network, route.plen)) + continue; + + /* Don't add the default route when and the connection + * is never supposed to be the default connection. + */ + if (nm_ip6_config_get_never_default (config) && IN6_IS_ADDR_UNSPECIFIED (&route.network)) + continue; + + g_array_append_val (routes, route); + } + + nm_platform_ip6_route_sync (ifindex, routes); + g_array_unref (routes); + } + + return TRUE; } -const char * -nm_ip6_config_get_dbus_path (NMIP6Config *config) +static inline gboolean +ip6_addresses_equal (const struct in6_addr *a, const struct in6_addr *b) { - g_return_val_if_fail (NM_IS_IP6_CONFIG (config), NULL); - - return NM_IP6_CONFIG_GET_PRIVATE (config)->path; + return memcmp (a, b, sizeof (struct in6_addr)) == 0; } void -nm_ip6_config_take_address (NMIP6Config *config, NMIP6Address *address) +nm_ip6_config_merge_setting (NMIP6Config *ip6_config, NMSettingIP6Config *setting) { - NMIP6ConfigPrivate *priv; + int i, j; - g_return_if_fail (NM_IS_IP6_CONFIG (config)); - g_return_if_fail (address != NULL); + if (!setting) + return; /* Defaults are just fine */ - priv = NM_IP6_CONFIG_GET_PRIVATE (config); - priv->addresses = g_slist_append (priv->addresses, address); + if (nm_setting_ip6_config_get_ignore_auto_dns (setting)) { + nm_ip6_config_reset_nameservers (ip6_config); + nm_ip6_config_reset_domains (ip6_config); + nm_ip6_config_reset_searches (ip6_config); + } + + if (nm_setting_ip6_config_get_ignore_auto_routes (setting)) + nm_ip6_config_reset_routes (ip6_config); + + for (i = 0; i < nm_setting_ip6_config_get_num_dns (setting); i++) { + const struct in6_addr *ns; + gboolean found = FALSE; + + /* Avoid dupes */ + ns = nm_setting_ip6_config_get_dns (setting, i); + for (j = 0; j < nm_ip6_config_get_num_nameservers (ip6_config); j++) { + if (ip6_addresses_equal (nm_ip6_config_get_nameserver (ip6_config, j), ns)) { + found = TRUE; + break; + } + } + + if (!found) + nm_ip6_config_add_nameserver (ip6_config, ns); + } + + /* DNS search domains */ + for (i = 0; i < nm_setting_ip6_config_get_num_dns_searches (setting); i++) { + const char *search = nm_setting_ip6_config_get_dns_search (setting, i); + gboolean found = FALSE; + + /* Avoid dupes */ + for (j = 0; j < nm_ip6_config_get_num_searches (ip6_config); j++) { + if (!strcmp (search, nm_ip6_config_get_search (ip6_config, j))) { + found = TRUE; + break; + } + } + + if (!found) + nm_ip6_config_add_search (ip6_config, search); + } + + /* IPv6 addresses */ + for (i = 0; i < nm_setting_ip6_config_get_num_addresses (setting); i++) { + NMIP6Address *setting_addr = nm_setting_ip6_config_get_address (setting, i); + guint32 num; + + num = nm_ip6_config_get_num_addresses (ip6_config); + for (j = 0; j < num; j++) { + NMIP6Address *cfg_addr = nm_ip6_config_get_address (ip6_config, j); + + /* Dupe, override with user-specified address */ + if (ip6_addresses_equal (nm_ip6_address_get_address (cfg_addr), nm_ip6_address_get_address (setting_addr))) { + nm_ip6_config_replace_address (ip6_config, j, setting_addr); + break; + } + } + + if (j == num) + nm_ip6_config_add_address (ip6_config, setting_addr); + } + + /* IPv6 routes */ + for (i = 0; i < nm_setting_ip6_config_get_num_routes (setting); i++) { + NMIP6Route *setting_route = nm_setting_ip6_config_get_route (setting, i); + guint32 num; + + num = nm_ip6_config_get_num_routes (ip6_config); + for (j = 0; j < num; j++) { + NMIP6Route *cfg_route = nm_ip6_config_get_route (ip6_config, j); + + /* Dupe, override with user-specified route */ + if ( ip6_addresses_equal (nm_ip6_route_get_dest (cfg_route), nm_ip6_route_get_dest (setting_route)) + && (nm_ip6_route_get_prefix (cfg_route) == nm_ip6_route_get_prefix (setting_route)) + && ip6_addresses_equal (nm_ip6_route_get_next_hop (cfg_route), nm_ip6_route_get_next_hop (setting_route))) { + nm_ip6_config_replace_route (ip6_config, j, setting_route); + break; + } + } + + if (j == num) + nm_ip6_config_add_route (ip6_config, setting_route); + } + + if (nm_setting_ip6_config_get_never_default (setting)) + nm_ip6_config_set_never_default (ip6_config, TRUE); } +gboolean +nm_match_spec_string (const GSList *specs, const char *match) +{ + const GSList *iter; + + for (iter = specs; iter; iter = g_slist_next (iter)) { + if (!g_ascii_strcasecmp ((const char *) iter->data, match)) + return TRUE; + } + + return FALSE; +} + +/******************************************************************/ + +gboolean +nm_ip6_config_destination_is_direct (NMIP6Config *config, const struct in6_addr *dest, guint32 dest_prefix) +{ + int num; + int i; + + num = nm_ip6_config_get_num_addresses (config); + for (i = 0; i < num; i++) { + NMIP6Address *addr = nm_ip6_config_get_address (config, i); + guint32 prefix = nm_ip6_address_get_prefix (addr); + const struct in6_addr *address = nm_ip6_address_get_address (addr); + + if (prefix <= dest_prefix) { + const guint8 *maskbytes = (const guint8 *)address; + const guint8 *addrbytes = (const guint8 *)dest; + int nbytes, nbits; + + /* Copied from g_inet_address_mask_matches() */ + nbytes = prefix / 8; + if (nbytes != 0 && memcmp (maskbytes, addrbytes, nbytes) != 0) + continue; + + nbits = prefix % 8; + if (nbits == 0) + return TRUE; + + if (maskbytes[nbytes] == (addrbytes[nbytes] & (0xFF << (8 - nbits)))) + return TRUE; + } + } + + return FALSE; +} + +/******************************************************************/ + void nm_ip6_config_add_address (NMIP6Config *config, NMIP6Address *address) diff --git a/src/nm-ip6-config.h b/src/nm-ip6-config.h index d25c859b7..b051f3067 100644 --- a/src/nm-ip6-config.h +++ b/src/nm-ip6-config.h @@ -50,11 +50,18 @@ GType nm_ip6_config_get_type (void); NMIP6Config * nm_ip6_config_new (void); -NMIP6Config * nm_ip6_config_new_for_interface (int ifindex); void nm_ip6_config_export (NMIP6Config *config); const char * nm_ip6_config_get_dbus_path (NMIP6Config *config); +/* Integration with nm-platform and nm-setting */ +NMIP6Config *nm_ip6_config_capture (int ifindex); +gboolean nm_ip6_config_commit (NMIP6Config *config, int ifindex, int priority); +void nm_ip6_config_merge_setting (NMIP6Config *config, NMSettingIP6Config *setting); + +/* Utility functions */ +gboolean nm_ip6_config_destination_is_direct (NMIP6Config *config, const struct in6_addr *dest, guint32 plen); + void nm_ip6_config_take_address (NMIP6Config *config, NMIP6Address *address); void nm_ip6_config_add_address (NMIP6Config *config, NMIP6Address *address); void nm_ip6_config_replace_address (NMIP6Config *config, guint32 i, NMIP6Address *new_address); @@ -69,8 +76,8 @@ const struct in6_addr *nm_ip6_config_get_nameserver (NMIP6Config *config, g guint32 nm_ip6_config_get_num_nameservers (NMIP6Config *config); void nm_ip6_config_reset_nameservers (NMIP6Config *config); -void nm_ip6_config_set_gateway (NMIP6Config *config, const struct in6_addr *gateway); -const struct in6_addr *nm_ip6_config_get_gateway (NMIP6Config *config); +void nm_ip6_config_set_gateway (NMIP6Config *config, const struct in6_addr *gateway); +const struct in6_addr *nm_ip6_config_get_gateway (NMIP6Config *config); void nm_ip6_config_take_route (NMIP6Config *config, NMIP6Route *route); void nm_ip6_config_add_route (NMIP6Config *config, NMIP6Route *route); diff --git a/src/nm-policy.c b/src/nm-policy.c index 9025be36d..b6efbc7a6 100644 --- a/src/nm-policy.c +++ b/src/nm-policy.c @@ -1623,9 +1623,9 @@ vpn_connection_deactivated (NMPolicy *policy, NMVPNConnection *vpn) if (parent) { parent_ip4 = nm_device_get_ip4_config (parent); if (parent_ip4) { - if (!nm_system_apply_ip4_config (nm_device_get_ip_ifindex (parent), - parent_ip4, - nm_device_get_priority (parent))) { + if (!nm_ip4_config_commit (parent_ip4, + nm_device_get_ip_ifindex (parent), + nm_device_get_priority (parent))) { nm_log_err (LOGD_VPN, "failed to re-apply VPN parent device IPv4 addresses and routes."); } } @@ -1643,9 +1643,9 @@ vpn_connection_deactivated (NMPolicy *policy, NMVPNConnection *vpn) if (parent) { parent_ip6 = nm_device_get_ip6_config (parent); if (parent_ip6) { - if (!nm_system_apply_ip6_config (nm_device_get_ip_ifindex (parent), - parent_ip6, - nm_device_get_priority (parent))) { + if (!nm_ip6_config_commit (parent_ip6, + nm_device_get_ip_ifindex (parent), + nm_device_get_priority (parent))) { nm_log_err (LOGD_VPN, "failed to re-apply VPN parent device IPv6 addresses and routes."); } } diff --git a/src/nm-system.c b/src/nm-system.c index 80d57ba0f..dc2ba9d3c 100644 --- a/src/nm-system.c +++ b/src/nm-system.c @@ -50,30 +50,6 @@ #include "nm-utils.h" #include "nm-logging.h" -static gboolean -ip4_dest_in_same_subnet (NMIP4Config *config, guint32 dest, guint32 dest_prefix) -{ - int num; - int i; - - num = nm_ip4_config_get_num_addresses (config); - for (i = 0; i < num; i++) { - NMIP4Address *addr = nm_ip4_config_get_address (config, i); - guint32 prefix = nm_ip4_address_get_prefix (addr); - guint32 address = nm_ip4_address_get_address (addr); - - if (prefix <= dest_prefix) { - guint32 masked_addr = ntohl(address) >> (32 - prefix); - guint32 masked_dest = ntohl(dest) >> (32 - prefix); - - if (masked_addr == masked_dest) - return TRUE; - } - } - - return FALSE; -} - NMPlatformIP4Route * nm_system_add_ip4_vpn_gateway_route (NMDevice *parent_device, guint32 vpn_gw) { @@ -117,7 +93,7 @@ nm_system_add_ip4_vpn_gateway_route (NMDevice *parent_device, guint32 vpn_gw) * IP addresses, don't add the host route to it, but a route through the * parent device. */ - if (ip4_dest_in_same_subnet (parent_config, vpn_gw, 32)) + if (nm_ip4_config_destination_is_direct (parent_config, vpn_gw, 32)) route->gateway = 0; if (!nm_platform_ip4_route_add (route->ifindex, @@ -137,115 +113,6 @@ nm_system_add_ip4_vpn_gateway_route (NMDevice *parent_device, guint32 vpn_gw) return route; } -/* - * nm_system_apply_ip4_config - * - * Set IPv4 configuration of the device from an NMIP4Config object. - * - */ -gboolean -nm_system_apply_ip4_config (int ifindex, NMIP4Config *config, int priority) -{ - int mtu = nm_ip4_config_get_mtu (config); - int i; - - g_return_val_if_fail (ifindex > 0, FALSE); - g_return_val_if_fail (config != NULL, FALSE); - - /* Addresses */ - { - int count = nm_ip4_config_get_num_addresses (config); - NMIP4Address *config_address; - GArray *addresses = g_array_sized_new (FALSE, FALSE, sizeof (NMPlatformIP4Address), count); - NMPlatformIP4Address address; - - for (i = 0; i < count; i++) { - config_address = nm_ip4_config_get_address (config, i); - memset (&address, 0, sizeof (address)); - address.address = nm_ip4_address_get_address (config_address); - address.plen = nm_ip4_address_get_prefix (config_address); - g_array_append_val (addresses, address); - } - - nm_platform_ip4_address_sync (ifindex, addresses); - g_array_unref (addresses); - } - - /* Routes */ - { - int count = nm_ip4_config_get_num_routes (config); - NMIP4Route *config_route; - GArray *routes = g_array_sized_new (FALSE, FALSE, sizeof (NMPlatformIP4Route), count); - NMPlatformIP4Route route; - - for (i = 0; i < count; i++) { - config_route = nm_ip4_config_get_route (config, i); - memset (&route, 0, sizeof (route)); - route.network = nm_ip4_route_get_dest (config_route); - route.plen = nm_ip4_route_get_prefix (config_route); - route.gateway = nm_ip4_route_get_next_hop (config_route); - route.metric = priority; - - /* Don't add the route if it's more specific than one of the subnets - * the device already has an IP address on. - */ - if (ip4_dest_in_same_subnet (config, route.network, route.plen)) - continue; - - /* Don't add the default route when and the connection - * is never supposed to be the default connection. - */ - if (nm_ip4_config_get_never_default (config) && route.network == 0) - continue; - - g_array_append_val (routes, route); - } - - nm_platform_ip4_route_sync (ifindex, routes); - g_array_unref (routes); - } - - /* MTU */ - if (mtu && mtu != nm_platform_link_get_mtu (ifindex)) - nm_platform_link_set_mtu (ifindex, mtu); - - return TRUE; -} - -static gboolean -ip6_dest_in_same_subnet (NMIP6Config *config, const struct in6_addr *dest, guint32 dest_prefix) -{ - int num; - int i; - - num = nm_ip6_config_get_num_addresses (config); - for (i = 0; i < num; i++) { - NMIP6Address *addr = nm_ip6_config_get_address (config, i); - guint32 prefix = nm_ip6_address_get_prefix (addr); - const struct in6_addr *address = nm_ip6_address_get_address (addr); - - if (prefix <= dest_prefix) { - const guint8 *maskbytes = (const guint8 *)address; - const guint8 *addrbytes = (const guint8 *)dest; - int nbytes, nbits; - - /* Copied from g_inet_address_mask_matches() */ - nbytes = prefix / 8; - if (nbytes != 0 && memcmp (maskbytes, addrbytes, nbytes) != 0) - continue; - - nbits = prefix % 8; - if (nbits == 0) - return TRUE; - - if (maskbytes[nbytes] == (addrbytes[nbytes] & (0xFF << (8 - nbits)))) - return TRUE; - } - } - - return FALSE; -} - NMPlatformIP6Route * nm_system_add_ip6_vpn_gateway_route (NMDevice *parent_device, const struct in6_addr *vpn_gw) @@ -293,7 +160,7 @@ nm_system_add_ip6_vpn_gateway_route (NMDevice *parent_device, * IP addresses, don't add the host route to it, but a route through the * parent device. */ - if (ip6_dest_in_same_subnet (parent_config, vpn_gw, 128)) + if (nm_ip6_config_destination_is_direct (parent_config, vpn_gw, 128)) route->gateway = in6addr_any; if (!nm_platform_ip6_route_add (route->ifindex, @@ -313,78 +180,6 @@ nm_system_add_ip6_vpn_gateway_route (NMDevice *parent_device, return route; } -/* - * nm_system_apply_ip6_config - * - * Set IPv6 configuration of the device from an NMIP6Config object. - * - */ -gboolean -nm_system_apply_ip6_config (int ifindex, - NMIP6Config *config, - int priority) -{ - int i; - - g_return_val_if_fail (ifindex > 0, FALSE); - g_return_val_if_fail (config != NULL, FALSE); - - /* Addresses */ - { - int count = nm_ip6_config_get_num_addresses (config); - NMIP6Address *config_address; - GArray *addresses = g_array_sized_new (FALSE, FALSE, sizeof (NMPlatformIP6Address), count); - NMPlatformIP6Address address; - - for (i = 0; i < count; i++) { - config_address = nm_ip6_config_get_address (config, i); - memset (&address, 0, sizeof (address)); - address.address = *nm_ip6_address_get_address (config_address); - address.plen = nm_ip6_address_get_prefix (config_address); - g_array_append_val (addresses, address); - } - - nm_platform_ip6_address_sync (ifindex, addresses); - g_array_unref (addresses); - } - - /* Routes */ - { - int count = nm_ip6_config_get_num_routes (config); - NMIP6Route *config_route; - GArray *routes = g_array_sized_new (FALSE, FALSE, sizeof (NMPlatformIP6Route), count); - NMPlatformIP6Route route; - - for (i = 0; i < count; i++) { - config_route = nm_ip6_config_get_route (config, i); - memset (&route, 0, sizeof (route)); - route.network = *nm_ip6_route_get_dest (config_route); - route.plen = nm_ip6_route_get_prefix (config_route); - route.gateway = *nm_ip6_route_get_next_hop (config_route); - route.metric = priority; - - /* Don't add the route if it's more specific than one of the subnets - * the device already has an IP address on. - */ - if (ip6_dest_in_same_subnet (config, &route.network, route.plen)) - continue; - - /* Don't add the default route when and the connection - * is never supposed to be the default connection. - */ - if (nm_ip6_config_get_never_default (config) && IN6_IS_ADDR_UNSPECIFIED (&route.network)) - continue; - - g_array_append_val (routes, route); - } - - nm_platform_ip6_route_sync (ifindex, routes); - g_array_unref (routes); - } - - return TRUE; -} - static const struct { const char *option; const char *default_value; diff --git a/src/nm-system.h b/src/nm-system.h index e45ed4399..450407ee8 100644 --- a/src/nm-system.h +++ b/src/nm-system.h @@ -24,7 +24,6 @@ #include "nm-platform.h" #include "nm-device.h" -#include "nm-ip4-config.h" #include "nm-setting-bond.h" NMPlatformIP4Route *nm_system_add_ip4_vpn_gateway_route (NMDevice *parent_device, @@ -32,14 +31,6 @@ NMPlatformIP4Route *nm_system_add_ip4_vpn_gateway_route (NMDevice *parent_device NMPlatformIP6Route *nm_system_add_ip6_vpn_gateway_route (NMDevice *parent_device, const struct in6_addr *vpn_gw); -gboolean nm_system_apply_ip4_config (int ifindex, - NMIP4Config *config, - int priority); - -gboolean nm_system_apply_ip6_config (int ifindex, - NMIP6Config *config, - int priority); - gboolean nm_system_apply_bonding_config (const char *iface, NMSettingBond *s_bond); #endif diff --git a/src/vpn-manager/nm-vpn-connection.c b/src/vpn-manager/nm-vpn-connection.c index b63b91dea..2bd1ffc44 100644 --- a/src/vpn-manager/nm-vpn-connection.c +++ b/src/vpn-manager/nm-vpn-connection.c @@ -609,12 +609,12 @@ nm_vpn_connection_apply_config (NMVPNConnection *connection) nm_platform_link_set_up (priv->ip_ifindex); if (priv->ip4_config) { - if (!nm_system_apply_ip4_config (priv->ip_ifindex, priv->ip4_config, 0)) + if (!nm_ip4_config_commit (priv->ip4_config, priv->ip_ifindex, 0)) return FALSE; } if (priv->ip6_config) { - if (!nm_system_apply_ip6_config (priv->ip_ifindex, priv->ip6_config, 0)) + if (!nm_ip6_config_commit (priv->ip6_config, priv->ip_ifindex, 0)) /* FIXME: remove ip4 config */ return FALSE; } @@ -906,7 +906,7 @@ nm_vpn_connection_ip4_config_get (DBusGProxy *proxy, /* Merge in user overrides from the NMConnection's IPv4 setting */ s_ip4 = nm_connection_get_setting_ip4_config (priv->connection); - nm_utils_merge_ip4_config (config, s_ip4); + nm_ip4_config_merge_setting (config, s_ip4); priv->ip4_config = config; nm_vpn_connection_config_maybe_complete (connection, TRUE); @@ -1043,7 +1043,7 @@ nm_vpn_connection_ip6_config_get (DBusGProxy *proxy, /* Merge in user overrides from the NMConnection's IPv6 setting */ s_ip6 = nm_connection_get_setting_ip6_config (priv->connection); - nm_utils_merge_ip6_config (config, s_ip6); + nm_ip6_config_merge_setting (config, s_ip6); priv->ip6_config = config; nm_vpn_connection_config_maybe_complete (connection, TRUE);