summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJiří Klimeš <jklimes@redhat.com>2015-07-03 13:07:08 +0100
committerJiří Klimeš <jklimes@redhat.com>2015-07-03 21:50:50 +0200
commitecf38f775e11f5d32aa4cf7e34043bf017c4a1ee (patch)
tree05d082812b8af30d34ce2b906122efdac5299223
parent31c8bd6b698cd868357699f3a31f46e780718259 (diff)
downloadNetworkManager-jk/vpn-firewall-zone-rh1065948.tar.gz
vpn: send firewall zone to firewalld also for VPN connections (rh #1065948)jk/vpn-firewall-zone-rh1065948
https://bugzilla.redhat.com/show_bug.cgi?id=1065948
-rw-r--r--src/vpn-manager/nm-vpn-connection.c89
1 files changed, 82 insertions, 7 deletions
diff --git a/src/vpn-manager/nm-vpn-connection.c b/src/vpn-manager/nm-vpn-connection.c
index 33fde937b6..37bc0f0800 100644
--- a/src/vpn-manager/nm-vpn-connection.c
+++ b/src/vpn-manager/nm-vpn-connection.c
@@ -45,6 +45,7 @@
#include "nm-core-internal.h"
#include "nm-default-route-manager.h"
#include "nm-route-manager.h"
+#include "nm-firewall-manager.h"
#include "gsystem-local-alloc.h"
#include "nm-vpn-connection-glue.h"
@@ -94,6 +95,9 @@ typedef struct {
NMVpnServiceState service_state;
+ /* Firewall */
+ NMFirewallPendingCall fw_call;
+
GDBusProxy *proxy;
GCancellable *cancellable;
GVariant *connect_hash;
@@ -221,6 +225,17 @@ call_plugin_disconnect (NMVpnConnection *self)
}
static void
+fw_call_cleanup (NMVpnConnection *connection)
+{
+ NMVpnConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE (connection);
+
+ if (priv->fw_call) {
+ nm_firewall_manager_cancel_call (nm_firewall_manager_get (), priv->fw_call);
+ priv->fw_call = NULL;
+ }
+}
+
+static void
vpn_cleanup (NMVpnConnection *connection, NMDevice *parent_dev)
{
NMVpnConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE (connection);
@@ -234,6 +249,14 @@ vpn_cleanup (NMVpnConnection *connection, NMDevice *parent_dev)
nm_device_set_vpn4_config (parent_dev, NULL);
nm_device_set_vpn6_config (parent_dev, NULL);
+ /* Remove zone from firewall */
+ if (priv->ip_iface)
+ nm_firewall_manager_remove_from_zone (nm_firewall_manager_get (),
+ priv->ip_iface,
+ NULL);
+ /* Cancel pending firewall call */
+ fw_call_cleanup (connection);
+
g_free (priv->banner);
priv->banner = NULL;
@@ -246,6 +269,7 @@ vpn_cleanup (NMVpnConnection *connection, NMDevice *parent_dev)
*/
if (priv->connection)
nm_connection_clear_secrets (priv->connection);
+
}
static void
@@ -947,10 +971,47 @@ nm_vpn_connection_apply_config (NMVpnConnection *connection)
}
static void
+_cleanup_failed_config (NMVpnConnection *connection)
+{
+ NMVpnConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE (connection);
+
+ g_clear_object (&priv->ip4_config);
+ g_clear_object (&priv->ip6_config);
+
+ nm_log_warn (LOGD_VPN, "VPN connection '%s' did not receive valid IP config information.",
+ nm_connection_get_id (priv->connection));
+ _set_vpn_state (connection, STATE_FAILED, NM_VPN_CONNECTION_STATE_REASON_IP_CONFIG_INVALID, FALSE);
+}
+
+static void
+fw_change_zone_cb (GError *error, gpointer user_data)
+{
+ NMVpnConnection *connection = NM_VPN_CONNECTION (user_data);
+ NMVpnConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE (connection);
+
+ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ return;
+
+ priv->fw_call = NULL;
+
+ if (error) {
+ nm_log_warn (LOGD_VPN, "VPN connection '%s': setting firewall zone failed: '%s'",
+ nm_connection_get_id (priv->connection), error->message);
+ // FIXME: fail the activation?
+ }
+
+ if (!nm_vpn_connection_apply_config (connection))
+ _cleanup_failed_config (connection);
+}
+
+static void
nm_vpn_connection_config_maybe_complete (NMVpnConnection *connection,
gboolean success)
{
NMVpnConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE (connection);
+ NMConnection *base_con;
+ NMSettingConnection *s_con;
+ const char *zone;
if (priv->vpn_state < STATE_IP_CONFIG_GET || priv->vpn_state > STATE_ACTIVATED)
return;
@@ -971,16 +1032,28 @@ nm_vpn_connection_config_maybe_complete (NMVpnConnection *connection,
if (success) {
print_vpn_config (connection);
- if (nm_vpn_connection_apply_config (connection))
+ /* Add the tunnel interface to the specified firewall zone */
+ if (priv->ip_iface) {
+ base_con = nm_vpn_connection_get_connection (connection);
+ g_assert (base_con);
+ s_con = nm_connection_get_setting_connection (base_con);
+ zone = nm_setting_connection_get_zone (s_con);
+
+ nm_log_dbg (LOGD_VPN, "VPN connection '%s': setting firewall zone '%s' for '%s'",
+ nm_connection_get_id (base_con), zone ? zone : "default", priv->ip_iface);
+ priv->fw_call = nm_firewall_manager_add_or_change_zone (nm_firewall_manager_get (),
+ priv->ip_iface,
+ zone,
+ FALSE,
+ fw_change_zone_cb,
+ connection);
return;
+ } else
+ if (nm_vpn_connection_apply_config (connection))
+ return;
}
- g_clear_object (&priv->ip4_config);
- g_clear_object (&priv->ip6_config);
-
- nm_log_warn (LOGD_VPN, "VPN connection '%s' did not receive valid IP config information.",
- nm_connection_get_id (priv->connection));
- _set_vpn_state (connection, STATE_FAILED, NM_VPN_CONNECTION_STATE_REASON_IP_CONFIG_INVALID, FALSE);
+ _cleanup_failed_config (connection);
}
static gboolean
@@ -2150,6 +2223,8 @@ dispose (GObject *object)
g_clear_object (&priv->proxy);
g_clear_object (&priv->connection);
+ fw_call_cleanup (NM_VPN_CONNECTION (object));
+
G_OBJECT_CLASS (nm_vpn_connection_parent_class)->dispose (object);
}