summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Williams <dcbw@redhat.com>2013-08-01 15:44:53 -0500
committerDan Williams <dcbw@redhat.com>2013-08-02 17:19:36 -0500
commit455df69f0275726a4681e2e04c7b09545153e028 (patch)
treeaf54d485671de3451847342373910bffb7ee479b
parent7e21b528a974737a4508d3a21289537e54c46cfe (diff)
downloadNetworkManager-455df69f0275726a4681e2e04c7b09545153e028.tar.gz
core: fix handling of externally added IPv4 adresses and routes on IP change
The switch to combine IPv4 configs to arrive at the final config would cause externally added addresses and routes to be removed from the interface when a DHCP or LLv4 event came in, becasue the externally added details weren't cached anywhere and thus would be dropped on the IP changes.
-rw-r--r--src/devices/nm-device.c56
1 files changed, 32 insertions, 24 deletions
diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c
index 44bfe8c93e..9ca3661b8f 100644
--- a/src/devices/nm-device.c
+++ b/src/devices/nm-device.c
@@ -228,6 +228,7 @@ typedef struct {
NMIP4Config * ip4_config; /* Combined config from VPN, settings, and device */
IpState ip4_state;
NMIP4Config * dev_ip4_config; /* Config from DHCP, PPP, LLv4, etc */
+ NMIP4Config * ext_ip4_config; /* Stuff added outside NM */
/* DHCPv4 tracking */
NMDHCPClient * dhcp4_client;
@@ -303,6 +304,7 @@ static gboolean nm_device_set_ip4_config (NMDevice *dev,
NMDeviceStateReason *reason);
static gboolean ip4_config_merge_and_apply (NMDevice *self,
NMIP4Config *config,
+ gboolean commit,
NMDeviceStateReason *out_reason);
static gboolean nm_device_set_ip6_config (NMDevice *dev,
@@ -2102,7 +2104,7 @@ nm_device_handle_autoip4_event (NMDevice *self,
aipd_timeout_remove (self);
nm_device_activate_schedule_ip4_config_result (self, config);
} else if (priv->ip4_state == IP_DONE) {
- if (!ip4_config_merge_and_apply (self, config, &reason)) {
+ if (!ip4_config_merge_and_apply (self, config, TRUE, &reason)) {
nm_log_err (LOGD_AUTOIP4, "(%s): failed to update IP4 config for autoip change.",
nm_device_get_iface (self));
nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, reason);
@@ -2274,6 +2276,7 @@ dhcp4_add_option_cb (gpointer key, gpointer value, gpointer user_data)
static gboolean
ip4_config_merge_and_apply (NMDevice *self,
NMIP4Config *config,
+ gboolean commit,
NMDeviceStateReason *out_reason)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
@@ -2281,30 +2284,32 @@ ip4_config_merge_and_apply (NMDevice *self,
gboolean success;
NMIP4Config *composite;
- connection = nm_device_get_connection (self);
- g_assert (connection);
-
/* Merge all the configs into the composite config */
if (config) {
g_clear_object (&priv->dev_ip4_config);
priv->dev_ip4_config = g_object_ref (config);
}
- g_assert (priv->dev_ip4_config);
-
composite = nm_ip4_config_new ();
- nm_ip4_config_merge (composite, priv->dev_ip4_config);
+ if (priv->dev_ip4_config)
+ nm_ip4_config_merge (composite, priv->dev_ip4_config);
if (priv->vpn4_config)
nm_ip4_config_merge (composite, priv->vpn4_config);
+ if (priv->ext_ip4_config)
+ nm_ip4_config_merge (composite, priv->ext_ip4_config);
/* Merge user overrides into the composite config */
- nm_ip4_config_merge_setting (composite, nm_connection_get_setting_ip4_config (connection));
+ connection = nm_device_get_connection (self);
+ if (connection)
+ nm_ip4_config_merge_setting (composite, nm_connection_get_setting_ip4_config (connection));
/* Allow setting MTU etc */
- if (NM_DEVICE_GET_CLASS (self)->ip4_config_pre_commit)
- NM_DEVICE_GET_CLASS (self)->ip4_config_pre_commit (self, composite);
+ if (commit) {
+ if (NM_DEVICE_GET_CLASS (self)->ip4_config_pre_commit)
+ NM_DEVICE_GET_CLASS (self)->ip4_config_pre_commit (self, composite);
+ }
- success = nm_device_set_ip4_config (self, composite, TRUE, out_reason);
+ success = nm_device_set_ip4_config (self, composite, commit, out_reason);
g_object_unref (composite);
return success;
}
@@ -2316,7 +2321,7 @@ dhcp4_lease_change (NMDevice *self, NMIP4Config *config)
g_return_if_fail (config != NULL);
- if (!ip4_config_merge_and_apply (self, config, &reason)) {
+ if (!ip4_config_merge_and_apply (self, config, TRUE, &reason)) {
nm_log_warn (LOGD_DHCP4, "(%s): failed to update IPv4 config for DHCP change.",
nm_device_get_ip_iface (self));
nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, reason);
@@ -3780,7 +3785,7 @@ nm_device_activate_ip4_config_commit (gpointer user_data)
nm_platform_link_set_up (ifindex);
/* NULL to use the existing priv->dev_ip4_config */
- if (!ip4_config_merge_and_apply (self, NULL, &reason)) {
+ if (!ip4_config_merge_and_apply (self, NULL, TRUE, &reason)) {
nm_log_info (LOGD_DEVICE | LOGD_IP4,
"Activation (%s) Stage 5 of 5 (IPv4 Commit) failed",
iface);
@@ -4152,6 +4157,7 @@ nm_device_deactivate (NMDevice *self, NMDeviceStateReason reason)
/* Clean up nameservers and addresses */
nm_device_set_ip4_config (self, NULL, TRUE, &ignored);
nm_device_set_ip6_config (self, NULL, TRUE, &ignored);
+ g_clear_object (&priv->ext_ip4_config);
g_clear_object (&priv->vpn4_config);
g_clear_object (&priv->vpn6_config);
@@ -4423,7 +4429,7 @@ nm_device_set_vpn4_config (NMDevice *device, NMIP4Config *config)
priv->vpn4_config = g_object_ref (config);
/* NULL to use existing configs */
- if (!ip4_config_merge_and_apply (device, NULL, NULL)) {
+ if (!ip4_config_merge_and_apply (device, NULL, TRUE, NULL)) {
nm_log_warn (LOGD_IP4, "(%s): failed to set VPN routes for device",
nm_device_get_ip_iface (device));
}
@@ -4846,6 +4852,7 @@ dispose (GObject *object)
nm_device_take_down (self, FALSE);
}
g_clear_object (&priv->dev_ip4_config);
+ g_clear_object (&priv->ext_ip4_config);
g_clear_object (&priv->vpn4_config);
g_clear_object (&priv->ip4_config);
@@ -5933,8 +5940,7 @@ update_ip_config (NMDevice *self)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
NMDeviceStateReason ignored = NM_DEVICE_STATE_REASON_NONE;
- NMIP4Config *ip4_config;
- NMIP6Config *ip6_config;
+ NMIP6Config *ip6_config = NULL;
int ifindex;
if (priv->state != NM_DEVICE_STATE_UNMANAGED)
@@ -5944,16 +5950,18 @@ update_ip_config (NMDevice *self)
if (!ifindex)
return;
- ip4_config = nm_ip4_config_capture (ifindex);
- ip6_config = nm_ip6_config_capture (ifindex);
+ g_clear_object (&priv->ext_ip4_config);
+ priv->ext_ip4_config = nm_ip4_config_capture (ifindex);
+ if (priv->dev_ip4_config)
+ nm_ip4_config_subtract (priv->ext_ip4_config, priv->dev_ip4_config);
+ if (priv->vpn4_config)
+ nm_ip4_config_subtract (priv->ext_ip4_config, priv->vpn4_config);
- nm_device_set_ip4_config (self, ip4_config, FALSE, &ignored);
- nm_device_set_ip6_config (self, ip6_config, FALSE, &ignored);
+ ip4_config_merge_and_apply (self, NULL, FALSE, NULL);
- if (ip4_config)
- g_object_unref (ip4_config);
- if (ip6_config)
- g_object_unref (ip6_config);
+ ip6_config = nm_ip6_config_capture (ifindex);
+ nm_device_set_ip6_config (self, ip6_config, FALSE, &ignored);
+ g_clear_object (&ip6_config);
}
static gboolean