summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLubomir Rintel <lkundrak@v3.sk>2015-08-26 14:55:39 +0200
committerLubomir Rintel <lkundrak@v3.sk>2015-08-26 16:55:59 +0200
commit894b74ce5e55d26aa9a809c45283de88c514290b (patch)
tree35dbc16459bac8a64761bc98fa5cc45cd020789a
parenta386319c3803fb957745e19cc428be62dd8f3ab0 (diff)
downloadNetworkManager-894b74ce5e55d26aa9a809c45283de88c514290b.tar.gz
fixup! device: allow multiple vpn IP configurations
-rw-r--r--src/devices/nm-device.c94
-rw-r--r--src/devices/nm-device.h8
-rw-r--r--src/vpn-manager/nm-vpn-connection.c54
3 files changed, 100 insertions, 56 deletions
diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c
index 1e7866f732..872bfcc0d0 100644
--- a/src/devices/nm-device.c
+++ b/src/devices/nm-device.c
@@ -263,6 +263,7 @@ typedef struct {
NMIP4Config * dev_ip4_config; /* Config from DHCP, PPP, LLv4, etc */
NMIP4Config * ext_ip4_config; /* Stuff added outside NM */
NMIP4Config * wwan_ip4_config; /* WWAN configuration */
+ GSList * vpn4_configs; /* VPNs which use this device */
struct {
gboolean v4_has;
gboolean v4_is_assumed;
@@ -280,7 +281,6 @@ typedef struct {
gulong dhcp4_state_sigid;
NMDhcp4Config * dhcp4_config;
guint dhcp4_restart_id;
- GHashTable * vpn4_config; /* connection => config map for VPNs which use this device */
guint arp_round2_id;
PingInfo gw_ping;
@@ -300,9 +300,9 @@ typedef struct {
NMIP6Config * ip6_config;
IpState ip6_state;
NMIP6Config * con_ip6_config; /* config from the setting */
- GHashTable * vpn6_config; /* connection => config map for VPNs which use this device */
NMIP6Config * wwan_ip6_config;
NMIP6Config * ext_ip6_config; /* Stuff added outside NM */
+ GSList * vpn6_configs; /* VPNs which use this device */
gboolean nm_ipv6ll; /* TRUE if NM handles the device's IPv6LL address */
guint32 ip6_mtu;
@@ -3418,7 +3418,7 @@ dhcp4_cleanup (NMDevice *self, CleanupType cleanup_type, gboolean release)
}
static void
-_ip4_config_merge_default (gpointer key, gpointer value, gpointer user_data)
+_ip4_config_merge_default (gpointer value, gpointer user_data)
{
NMIP4Config *src = (NMIP4Config *) value;
NMIP4Config *dst = (NMIP4Config *) user_data;
@@ -3472,7 +3472,7 @@ ip4_config_merge_and_apply (NMDevice *self,
| (ignore_auto_dns ? NM_IP_CONFIG_MERGE_NO_DNS : 0));
}
- g_hash_table_foreach (priv->vpn4_config, _ip4_config_merge_default, composite);
+ g_slist_foreach (priv->vpn4_configs, _ip4_config_merge_default, composite);
if (priv->ext_ip4_config)
nm_ip4_config_merge (composite, priv->ext_ip4_config, NM_IP_CONFIG_MERGE_DEFAULT);
@@ -4080,7 +4080,7 @@ dhcp6_cleanup (NMDevice *self, CleanupType cleanup_type, gboolean release)
}
static void
-_ip6_config_merge_default (gpointer key, gpointer value, gpointer user_data)
+_ip6_config_merge_default (gpointer value, gpointer user_data)
{
NMIP6Config *src = (NMIP6Config *) value;
NMIP6Config *dst = (NMIP6Config *) user_data;
@@ -4134,7 +4134,7 @@ ip6_config_merge_and_apply (NMDevice *self,
| (ignore_auto_dns ? NM_IP_CONFIG_MERGE_NO_DNS : 0));
}
- g_hash_table_foreach (priv->vpn6_config, _ip6_config_merge_default, composite);
+ g_slist_foreach (priv->vpn6_configs, _ip6_config_merge_default, composite);
if (priv->ext_ip6_config)
nm_ip6_config_merge (composite, priv->ext_ip6_config, NM_IP_CONFIG_MERGE_DEFAULT);
@@ -6697,14 +6697,31 @@ nm_device_set_ip4_config (NMDevice *self,
}
void
-nm_device_set_vpn4_config (gpointer conn, NMDevice *self, NMIP4Config *config)
+nm_device_replace_vpn4_config (NMDevice *self, NMIP4Config *old, NMIP4Config *config)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
- if (config)
- g_hash_table_replace (priv->vpn4_config, conn, g_object_ref (config));
- else
- g_hash_table_remove (priv->vpn4_config, conn);
+ if (old) {
+ /* Removing a configuration */
+ if (config) {
+ /* Replace it with a new one in the same place in the list,
+ * an already active connection sent a config update */
+ GSList *link = g_slist_find (priv->vpn4_configs, old);
+ link->data = g_object_ref (config);
+ } else {
+ /* Just remove it without replacement, on a connection teardown */
+ priv->vpn4_configs = g_slist_remove (priv->vpn4_configs, old);
+ }
+ g_object_unref (old);
+ } else {
+ if (config) {
+ /* Appending a new configuration, e.g. when actiating a new connection */
+ priv->vpn4_configs = g_slist_append (priv->vpn4_configs, g_object_ref (config));
+ } else {
+ /* No new config, nor we did have any previously. */
+ return;
+ }
+ }
/* NULL to use existing configs */
if (!ip4_config_merge_and_apply (self, NULL, TRUE, NULL))
@@ -6824,14 +6841,31 @@ nm_device_set_ip6_config (NMDevice *self,
}
void
-nm_device_set_vpn6_config (gpointer conn, NMDevice *self, NMIP6Config *config)
+nm_device_replace_vpn6_config (NMDevice *self, NMIP6Config *old, NMIP6Config *config)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
- if (config)
- g_hash_table_replace (priv->vpn6_config, conn, g_object_ref (config));
- else
- g_hash_table_remove (priv->vpn6_config, conn);
+ if (old) {
+ /* Removing a configuration */
+ if (config) {
+ /* Replace it with a new one in the same place in the list,
+ * an already active connection sent a config update */
+ GSList *link = g_slist_find (priv->vpn6_configs, old);
+ link->data = g_object_ref (config);
+ } else {
+ /* Just remove it without replacement, on a connection teardown */
+ priv->vpn6_configs = g_slist_remove (priv->vpn6_configs, old);
+ }
+ g_object_unref (old);
+ } else {
+ if (config) {
+ /* Appending a new configuration, e.g. when actiating a new connection */
+ priv->vpn6_configs = g_slist_append (priv->vpn6_configs, g_object_ref (config));
+ } else {
+ /* No new config, nor we did have any previously. */
+ return;
+ }
+ }
/* NULL to use existing configs */
if (!ip6_config_merge_and_apply (self, TRUE, NULL))
@@ -7429,7 +7463,7 @@ capture_lease_config (NMDevice *self,
}
static void
-_ip4_config_intersect (gpointer key, gpointer value, gpointer user_data)
+_ip4_config_intersect (gpointer value, gpointer user_data)
{
NMIP4Config *dst = (NMIP4Config *) value;
NMIP4Config *src = (NMIP4Config *) user_data;
@@ -7438,7 +7472,7 @@ _ip4_config_intersect (gpointer key, gpointer value, gpointer user_data)
}
static void
-_ip4_config_subtract (gpointer key, gpointer value, gpointer user_data)
+_ip4_config_subtract (gpointer value, gpointer user_data)
{
NMIP4Config *dst = (NMIP4Config *) value;
NMIP4Config *src = (NMIP4Config *) user_data;
@@ -7484,7 +7518,7 @@ update_ip4_config (NMDevice *self, gboolean initial)
if (priv->dev_ip4_config)
nm_ip4_config_intersect (priv->dev_ip4_config, priv->ext_ip4_config);
- g_hash_table_foreach (priv->vpn4_config, _ip4_config_intersect, priv->ext_ip4_config);
+ g_slist_foreach (priv->vpn4_configs, _ip4_config_intersect, priv->ext_ip4_config);
if (priv->wwan_ip4_config)
nm_ip4_config_intersect (priv->wwan_ip4_config, priv->ext_ip4_config);
@@ -7497,7 +7531,7 @@ update_ip4_config (NMDevice *self, gboolean initial)
if (priv->dev_ip4_config)
nm_ip4_config_subtract (priv->ext_ip4_config, priv->dev_ip4_config);
- g_hash_table_foreach (priv->vpn4_config, _ip4_config_subtract, priv->ext_ip4_config);
+ g_slist_foreach (priv->vpn4_configs, _ip4_config_subtract, priv->ext_ip4_config);
if (priv->wwan_ip4_config)
nm_ip4_config_subtract (priv->ext_ip4_config, priv->wwan_ip4_config);
@@ -7507,7 +7541,7 @@ update_ip4_config (NMDevice *self, gboolean initial)
}
static void
-_ip6_config_intersect (gpointer key, gpointer value, gpointer user_data)
+_ip6_config_intersect (gpointer value, gpointer user_data)
{
NMIP6Config *dst = (NMIP6Config *) value;
NMIP6Config *src = (NMIP6Config *) user_data;
@@ -7516,7 +7550,7 @@ _ip6_config_intersect (gpointer key, gpointer value, gpointer user_data)
}
static void
-_ip6_config_subtract (gpointer key, gpointer value, gpointer user_data)
+_ip6_config_subtract (gpointer value, gpointer user_data)
{
NMIP6Config *dst = (NMIP6Config *) value;
NMIP6Config *src = (NMIP6Config *) user_data;
@@ -7561,7 +7595,7 @@ update_ip6_config (NMDevice *self, gboolean initial)
nm_ip6_config_intersect (priv->dhcp6_ip6_config, priv->ext_ip6_config);
if (priv->wwan_ip6_config)
nm_ip6_config_intersect (priv->wwan_ip6_config, priv->ext_ip6_config);
- g_hash_table_foreach (priv->vpn6_config, _ip6_config_intersect, priv->ext_ip4_config);
+ g_slist_foreach (priv->vpn6_configs, _ip6_config_intersect, priv->ext_ip4_config);
/* Remove parts from ext_ip6_config to only contain the information that
* was configured externally -- we already have the same configuration from
@@ -7574,7 +7608,7 @@ update_ip6_config (NMDevice *self, gboolean initial)
nm_ip6_config_subtract (priv->ext_ip6_config, priv->dhcp6_ip6_config);
if (priv->wwan_ip6_config)
nm_ip6_config_subtract (priv->ext_ip6_config, priv->wwan_ip6_config);
- g_hash_table_foreach (priv->vpn6_config, _ip6_config_subtract, priv->ext_ip4_config);
+ g_slist_foreach (priv->vpn6_configs, _ip6_config_subtract, priv->ext_ip4_config);
ip6_config_merge_and_apply (self, FALSE, NULL);
}
@@ -8262,8 +8296,10 @@ _cleanup_generic_post (NMDevice *self, CleanupType cleanup_type)
g_clear_object (&priv->wwan_ip6_config);
g_clear_object (&priv->ip6_config);
- g_hash_table_remove_all (priv->vpn4_config);
- g_hash_table_remove_all (priv->vpn6_config);
+ g_slist_free_full (priv->vpn4_configs, g_object_unref);
+ priv->vpn4_configs = NULL;
+ g_slist_free_full (priv->vpn6_configs, g_object_unref);
+ priv->vpn6_configs = NULL;
clear_act_request (self);
@@ -9202,9 +9238,6 @@ nm_device_init (NMDevice *self)
priv->v4_commit_first_time = TRUE;
priv->v6_commit_first_time = TRUE;
-
- priv->vpn4_config = g_hash_table_new_full (NULL, NULL, NULL, g_object_unref);
- priv->vpn6_config = g_hash_table_new_full (NULL, NULL, NULL, g_object_unref);
}
static void
@@ -9279,9 +9312,6 @@ dispose (GObject *object)
_cleanup_generic_post (self, CLEANUP_TYPE_KEEP);
- g_clear_pointer (&priv->vpn4_config, g_hash_table_unref);
- g_clear_pointer (&priv->vpn6_config, g_hash_table_unref);
-
g_hash_table_remove_all (priv->ip6_saved_properties);
if (priv->recheck_assume_id) {
diff --git a/src/devices/nm-device.h b/src/devices/nm-device.h
index d6b02cb9a3..7742ef359d 100644
--- a/src/devices/nm-device.h
+++ b/src/devices/nm-device.h
@@ -343,10 +343,14 @@ NMDhcp4Config * nm_device_get_dhcp4_config (NMDevice *dev);
NMDhcp6Config * nm_device_get_dhcp6_config (NMDevice *dev);
NMIP4Config * nm_device_get_ip4_config (NMDevice *dev);
-void nm_device_set_vpn4_config (gpointer conn, NMDevice *dev, NMIP4Config *config);
+void nm_device_replace_vpn4_config (NMDevice *dev,
+ NMIP4Config *old,
+ NMIP4Config *config);
NMIP6Config * nm_device_get_ip6_config (NMDevice *dev);
-void nm_device_set_vpn6_config (gpointer conn, NMDevice *dev, NMIP6Config *config);
+void nm_device_replace_vpn6_config (NMDevice *dev,
+ NMIP6Config *old,
+ NMIP6Config *config);
void nm_device_capture_initial_config (NMDevice *dev);
diff --git a/src/vpn-manager/nm-vpn-connection.c b/src/vpn-manager/nm-vpn-connection.c
index e0e771686f..4016a493d3 100644
--- a/src/vpn-manager/nm-vpn-connection.c
+++ b/src/vpn-manager/nm-vpn-connection.c
@@ -100,11 +100,11 @@ typedef struct {
GVariant *connect_hash;
guint connect_timeout;
gboolean has_ip4;
- NMIP4Config *ip4_config;
+ NMIP4Config *ip4_config, *parent_ip4_config;
guint32 ip4_internal_gw;
guint32 ip4_external_gw;
gboolean has_ip6;
- NMIP6Config *ip6_config;
+ NMIP6Config *ip6_config, *parent_ip6_config;
struct in6_addr *ip6_internal_gw;
struct in6_addr *ip6_external_gw;
char *ip_iface;
@@ -233,6 +233,22 @@ fw_call_cleanup (NMVpnConnection *connection)
}
static void
+remove_parent_device_config (NMVpnConnection *connection, NMDevice *device)
+{
+ NMVpnConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE (connection);
+
+ if (priv->parent_ip4_config) {
+ nm_device_replace_vpn4_config (device, priv->parent_ip4_config, NULL);
+ g_clear_object (&priv->parent_ip4_config);
+ }
+
+ if (priv->parent_ip6_config) {
+ nm_device_replace_vpn6_config (device, priv->parent_ip6_config, NULL);
+ g_clear_object (&priv->parent_ip6_config);
+ }
+}
+
+static void
vpn_cleanup (NMVpnConnection *connection, NMDevice *parent_dev)
{
NMVpnConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE (connection);
@@ -243,8 +259,7 @@ vpn_cleanup (NMVpnConnection *connection, NMDevice *parent_dev)
nm_platform_address_flush (NM_PLATFORM_GET, priv->ip_ifindex);
}
- nm_device_set_vpn4_config (connection, parent_dev, NULL);
- nm_device_set_vpn6_config (connection, parent_dev, NULL);
+ remove_parent_device_config (connection, parent_dev);
/* Remove zone from firewall */
if (priv->ip_iface)
@@ -930,22 +945,19 @@ apply_parent_device_config (NMVpnConnection *connection)
}
}
- if (vpn4_parent_config) {
- /* Add any explicit route to the VPN gateway through the parent device */
- if (priv->ip4_external_gw)
- add_ip4_vpn_gateway_route (vpn4_parent_config, parent_dev, priv->ip4_external_gw);
+ /* Add any explicit route to the VPN gateway through the parent device */
+ if (vpn4_parent_config && priv->ip4_external_gw)
+ add_ip4_vpn_gateway_route (vpn4_parent_config, parent_dev, priv->ip4_external_gw);
+ if (vpn6_parent_config && priv->ip6_external_gw)
+ add_ip6_vpn_gateway_route (vpn6_parent_config, parent_dev, priv->ip6_external_gw);
- nm_device_set_vpn4_config (connection, parent_dev, vpn4_parent_config);
- g_object_unref (vpn4_parent_config);
- }
- if (vpn6_parent_config) {
- /* Add any explicit route to the VPN gateway through the parent device */
- if (priv->ip6_external_gw)
- add_ip6_vpn_gateway_route (vpn6_parent_config, parent_dev, priv->ip6_external_gw);
+ nm_device_replace_vpn4_config (parent_dev, priv->parent_ip4_config, vpn4_parent_config);
+ g_clear_object (&priv->parent_ip4_config);
+ priv->parent_ip4_config = vpn4_parent_config;
- nm_device_set_vpn6_config (connection, parent_dev, vpn6_parent_config);
- g_object_unref (vpn6_parent_config);
- }
+ nm_device_replace_vpn6_config (parent_dev, priv->parent_ip6_config, vpn6_parent_config);
+ g_clear_object (&priv->parent_ip6_config);
+ priv->parent_ip4_config = vpn4_parent_config;
}
static gboolean
@@ -2177,10 +2189,8 @@ device_changed (NMActiveConnection *active,
* out that connectivity is down and start its reconnect attempt if it
* needs to.
*/
- if (old_device) {
- nm_device_set_vpn4_config (active, old_device, NULL);
- nm_device_set_vpn6_config (active, old_device, NULL);
- }
+ if (old_device)
+ remove_parent_device_config (NM_VPN_CONNECTION (active), old_device);
if (new_device)
apply_parent_device_config (NM_VPN_CONNECTION (active));