Commit d638ccde authored by Thomas Haller's avatar Thomas Haller

firewall: merge branch 'th/rh1098281_firewall_assumed_device'

https://bugzilla.redhat.com/show_bug.cgi?id=1098281Signed-off-by: Thomas Haller's avatarThomas Haller <thaller@redhat.com>
parents 6fd8afd3 06a45fdc
......@@ -210,9 +210,6 @@ nm_sources = \
dnsmasq-manager/nm-dnsmasq-utils.c \
dnsmasq-manager/nm-dnsmasq-utils.h \
\
firewall-manager/nm-firewall-manager.c \
firewall-manager/nm-firewall-manager.h \
\
platform/nm-fake-platform.c \
platform/nm-fake-platform.h \
platform/nm-linux-platform.c \
......@@ -304,6 +301,8 @@ nm_sources = \
nm-dispatcher.h \
nm-enum-types.c \
nm-enum-types.h \
nm-firewall-manager.c \
nm-firewall-manager.h \
nm-ip4-config.c \
nm-ip4-config.h \
nm-ip6-config.c \
......
......@@ -260,7 +260,7 @@ typedef struct {
gulong dnsmasq_state_id;
/* Firewall */
DBusGProxyCall *fw_call;
NMFirewallPendingCall fw_call;
/* avahi-autoipd stuff */
GPid aipd_pid;
......@@ -4545,8 +4545,14 @@ out:
static void
fw_change_zone_cb (GError *error, gpointer user_data)
{
NMDevice *self = NM_DEVICE (user_data);
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
NMDevice *self;
NMDevicePrivate *priv;
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
return;
self = NM_DEVICE (user_data);
priv = NM_DEVICE_GET_PRIVATE (self);
priv->fw_call = NULL;
......@@ -4555,7 +4561,6 @@ fw_change_zone_cb (GError *error, gpointer user_data)
}
activation_source_schedule (self, nm_device_activate_stage3_ip_config_start, 0);
_LOGI (LOGD_DEVICE, "Activation: Stage 3 of 5 (IP Configure Start) scheduled.");
}
......@@ -4577,12 +4582,22 @@ nm_device_activate_schedule_stage3_ip_config_start (NMDevice *self)
priv = NM_DEVICE_GET_PRIVATE (self);
g_return_if_fail (priv->act_request);
g_return_if_fail (!priv->fw_call);
/* Add the interface to the specified firewall zone */
connection = nm_device_get_connection (self);
g_assert (connection);
s_con = nm_connection_get_setting_connection (connection);
zone = nm_setting_connection_get_zone (s_con);
if (nm_device_uses_assumed_connection (self)) {
_LOGD (LOGD_DEVICE, "Activation: skip setting firewall zone '%s' for assumed device", zone ? zone : "default");
activation_source_schedule (self, nm_device_activate_stage3_ip_config_start, 0);
_LOGI (LOGD_DEVICE, "Activation: Stage 3 of 5 (IP Configure Start) scheduled.");
return;
}
_LOGD (LOGD_DEVICE, "Activation: setting firewall zone '%s'", zone ? zone : "default");
priv->fw_call = nm_firewall_manager_add_or_change_zone (nm_firewall_manager_get (),
nm_device_get_ip_iface (self),
......@@ -6880,7 +6895,9 @@ _cleanup_generic_pre (NMDevice *self, gboolean deconfigure)
}
connection = nm_device_get_connection (self);
if (deconfigure && connection) {
if ( deconfigure
&& connection
&& !nm_device_uses_assumed_connection (self)) {
nm_firewall_manager_remove_from_zone (nm_firewall_manager_get (),
nm_device_get_ip_iface (self),
NULL);
......
......@@ -22,6 +22,7 @@
#include <string.h>
#include <glib.h>
#include <gio/gio.h>
#include <dbus/dbus.h>
#include "nm-firewall-manager.h"
......@@ -46,6 +47,8 @@ typedef struct {
guint name_owner_id;
DBusGProxy * proxy;
gboolean running;
GSList *pending_calls;
} NMFirewallManagerPrivate;
enum {
......@@ -58,44 +61,89 @@ static guint signals[LAST_SIGNAL] = { 0 };
/********************************************************************/
#define PENDING_CALL_DUMMY ((NMFirewallPendingCall) GUINT_TO_POINTER(1))
#define PENDING_CALL_FROM_INFO(info) ((NMFirewallPendingCall) info)
typedef struct {
NMFirewallManager *self;
char *iface;
FwAddToZoneFunc callback;
gpointer user_data;
guint id;
gboolean completed;
guint idle_id;
DBusGProxyCall *dbus_call;
} CBInfo;
static void
cb_info_free (CBInfo *info)
_cb_info_free (CBInfo *info)
{
NMFirewallManagerPrivate *priv;
g_return_if_fail (info != NULL);
if (!info->completed)
if (!info->completed) {
nm_log_dbg (LOGD_FIREWALL, "(%s) firewall zone call cancelled [%u]", info->iface, info->id);
if (info->callback) {
GError *error;
error = g_error_new_literal (G_IO_ERROR, G_IO_ERROR_CANCELLED,
"Operation was cancelled");
info->callback (error, info->user_data);
g_error_free (error);
}
}
g_free (info->iface);
g_free (info);
priv = NM_FIREWALL_MANAGER_GET_PRIVATE (info->self);
priv->pending_calls = g_slist_remove (priv->pending_calls, info);
g_object_unref (info->self);
g_slice_free (CBInfo, info);
}
static CBInfo *
_cb_info_create (const char *iface, FwAddToZoneFunc callback, gpointer user_data)
_cb_info_create (NMFirewallManager *self, const char *iface, FwAddToZoneFunc callback, gpointer user_data)
{
NMFirewallManagerPrivate *priv = NM_FIREWALL_MANAGER_GET_PRIVATE (self);
static guint id;
CBInfo *info;
info = g_malloc (sizeof (CBInfo));
info = g_slice_new0 (CBInfo);
if (++id == 0)
++id;
info->self = g_object_ref (self);
info->id = id;
info->iface = g_strdup (iface);
info->completed = FALSE;
info->callback = callback;
info->user_data = user_data;
priv->pending_calls = g_slist_prepend (priv->pending_calls, info);
return info;
}
static gboolean
add_or_change_idle_cb (gpointer user_data)
{
CBInfo *info = user_data;
if (info->idle_id == 0) {
/* operation was cancelled. _cb_info_free will invoke callback. */
} else {
nm_log_dbg (LOGD_FIREWALL, "(%s) firewall zone call pretends success [%u]",
info->iface, info->id);
if (info->callback)
info->callback (NULL, info->user_data);
info->completed = TRUE;
info->idle_id = 0;
}
_cb_info_free (info);
return G_SOURCE_REMOVE;
}
static void
add_or_change_cb (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data)
{
......@@ -119,14 +167,15 @@ add_or_change_cb (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data
info->iface, info->id);
}
info->callback (error, info->user_data);
if (info->callback)
info->callback (error, info->user_data);
info->completed = TRUE;
g_free (zone);
g_clear_error (&error);
}
gpointer
NMFirewallPendingCall
nm_firewall_manager_add_or_change_zone (NMFirewallManager *self,
const char *iface,
const char *zone,
......@@ -138,24 +187,32 @@ nm_firewall_manager_add_or_change_zone (NMFirewallManager *self,
CBInfo *info;
if (priv->running == FALSE) {
nm_log_dbg (LOGD_FIREWALL, "(%s) firewall zone add/change skipped (not running)", iface);
callback (NULL, user_data);
return NULL;
if (callback) {
info = _cb_info_create (self, iface, callback, user_data);
info->idle_id = g_idle_add (add_or_change_idle_cb, info);
nm_log_dbg (LOGD_FIREWALL, "(%s) firewall zone %s -> %s%s%s [%u] (not running, simulate success)", iface, add ? "add" : "change",
zone?"\"":"", zone ? zone : "default", zone?"\"":"", info->id);
return PENDING_CALL_FROM_INFO (info);
} else {
nm_log_dbg (LOGD_FIREWALL, "(%s) firewall zone add/change skipped (not running)", iface);
return PENDING_CALL_DUMMY;
}
}
info = _cb_info_create (iface, callback, user_data);
info = _cb_info_create (self, iface, callback, user_data);
nm_log_dbg (LOGD_FIREWALL, "(%s) firewall zone %s -> %s%s%s [%u]", iface, add ? "add" : "change",
zone?"\"":"", zone ? zone : "default", zone?"\"":"", info->id);
return dbus_g_proxy_begin_call_with_timeout (priv->proxy,
add ? "addInterface" : "changeZone",
add_or_change_cb,
info,
(GDestroyNotify) cb_info_free,
10000, /* timeout */
G_TYPE_STRING, zone ? zone : "",
G_TYPE_STRING, iface,
G_TYPE_INVALID);
info->dbus_call = dbus_g_proxy_begin_call_with_timeout (priv->proxy,
add ? "addInterface" : "changeZone",
add_or_change_cb,
info,
(GDestroyNotify) _cb_info_free,
10000, /* timeout */
G_TYPE_STRING, zone ? zone : "",
G_TYPE_STRING, iface,
G_TYPE_INVALID);
return PENDING_CALL_FROM_INFO (info);
}
static void
......@@ -187,7 +244,7 @@ remove_cb (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data)
g_clear_error (&error);
}
gpointer
NMFirewallPendingCall
nm_firewall_manager_remove_from_zone (NMFirewallManager *self,
const char *iface,
const char *zone)
......@@ -197,29 +254,49 @@ nm_firewall_manager_remove_from_zone (NMFirewallManager *self,
if (priv->running == FALSE) {
nm_log_dbg (LOGD_FIREWALL, "(%s) firewall zone remove skipped (not running)", iface);
return NULL;
return PENDING_CALL_DUMMY;
}
info = _cb_info_create (iface, NULL, NULL);
info = _cb_info_create (self, iface, NULL, NULL);
nm_log_dbg (LOGD_FIREWALL, "(%s) firewall zone remove -> %s%s%s [%u]", iface,
zone?"\"":"", zone ? zone : "*", zone?"\"":"", info->id);
return dbus_g_proxy_begin_call_with_timeout (priv->proxy,
"removeInterface",
remove_cb,
info,
(GDestroyNotify) cb_info_free,
10000, /* timeout */
G_TYPE_STRING, zone ? zone : "",
G_TYPE_STRING, iface,
G_TYPE_INVALID);
info->dbus_call = dbus_g_proxy_begin_call_with_timeout (priv->proxy,
"removeInterface",
remove_cb,
info,
(GDestroyNotify) _cb_info_free,
10000, /* timeout */
G_TYPE_STRING, zone ? zone : "",
G_TYPE_STRING, iface,
G_TYPE_INVALID);
return PENDING_CALL_FROM_INFO (info);
}
void nm_firewall_manager_cancel_call (NMFirewallManager *self, gpointer call)
void nm_firewall_manager_cancel_call (NMFirewallManager *self, NMFirewallPendingCall call)
{
NMFirewallManagerPrivate *priv = NM_FIREWALL_MANAGER_GET_PRIVATE (self);
GSList *pending;
CBInfo *info;
g_return_if_fail (NM_IS_FIREWALL_MANAGER (self));
dbus_g_proxy_cancel_call (NM_FIREWALL_MANAGER_GET_PRIVATE (self)->proxy,
(DBusGProxyCall *) call);
if (call == PENDING_CALL_DUMMY)
return;
pending = g_slist_find (priv->pending_calls, call);
if (!pending)
return;
priv->pending_calls = g_slist_remove_link (priv->pending_calls, pending);
info = (CBInfo *) call;
if (info->idle_id)
info->idle_id = 0;
else {
dbus_g_proxy_cancel_call (NM_FIREWALL_MANAGER_GET_PRIVATE (self)->proxy,
info->dbus_call);
}
}
static void
......@@ -318,6 +395,8 @@ dispose (GObject *object)
{
NMFirewallManagerPrivate *priv = NM_FIREWALL_MANAGER_GET_PRIVATE (object);
g_assert (priv->pending_calls == NULL);
if (priv->dbus_mgr) {
g_signal_handler_disconnect (priv->dbus_mgr, priv->name_owner_id);
priv->name_owner_id = 0;
......
......@@ -40,6 +40,9 @@ G_BEGIN_DECLS
#define NM_FIREWALL_MANAGER_AVAILABLE "available"
struct _NMFirewallPendingCall;
typedef struct _NMFirewallPendingCall *NMFirewallPendingCall;
typedef struct {
GObject parent;
} NMFirewallManager;
......@@ -57,16 +60,16 @@ NMFirewallManager *nm_firewall_manager_get (void);
typedef void (*FwAddToZoneFunc) (GError *error, gpointer user_data);
gpointer nm_firewall_manager_add_or_change_zone (NMFirewallManager *mgr,
const char *iface,
const char *zone,
gboolean add,
FwAddToZoneFunc callback,
gpointer user_data);
gpointer nm_firewall_manager_remove_from_zone (NMFirewallManager *mgr,
const char *iface,
const char *zone);
void nm_firewall_manager_cancel_call (NMFirewallManager *mgr, gpointer fw_call);
NMFirewallPendingCall nm_firewall_manager_add_or_change_zone (NMFirewallManager *mgr,
const char *iface,
const char *zone,
gboolean add,
FwAddToZoneFunc callback,
gpointer user_data);
NMFirewallPendingCall nm_firewall_manager_remove_from_zone (NMFirewallManager *mgr,
const char *iface,
const char *zone);
void nm_firewall_manager_cancel_call (NMFirewallManager *mgr, NMFirewallPendingCall fw_call);
#endif /* __NETWORKMANAGER_FIREWALL_MANAGER_H__ */
......@@ -1576,7 +1576,8 @@ firewall_update_zone (NMPolicy *policy, NMConnection *connection)
NMDevice *dev = NM_DEVICE (iter->data);
if ( (nm_device_get_connection (dev) == connection)
&& (nm_device_get_state (dev) == NM_DEVICE_STATE_ACTIVATED)) {
&& (nm_device_get_state (dev) == NM_DEVICE_STATE_ACTIVATED)
&& !nm_device_uses_assumed_connection (dev)) {
nm_firewall_manager_add_or_change_zone (nm_firewall_manager_get (),
nm_device_get_ip_iface (dev),
nm_setting_connection_get_zone (s_con),
......@@ -1606,7 +1607,8 @@ firewall_started (NMFirewallManager *manager,
continue;
s_con = nm_connection_get_setting_connection (connection);
if (nm_device_get_state (dev) == NM_DEVICE_STATE_ACTIVATED) {
if ( nm_device_get_state (dev) == NM_DEVICE_STATE_ACTIVATED
&& !nm_device_uses_assumed_connection (dev)) {
nm_firewall_manager_add_or_change_zone (nm_firewall_manager_get (),
nm_device_get_ip_iface (dev),
nm_setting_connection_get_zone (s_con),
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment