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)); 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); } }
gpointer nm_firewall_manager_add_or_change_zone (NMFirewallManager *self, const char *iface, const char *zone, gboolean add, /* TRUE == add, FALSE == change */ FwAddToZoneFunc callback, gpointer user_data) { NMFirewallManagerPrivate *priv = NM_FIREWALL_MANAGER_GET_PRIVATE (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; } info = g_malloc0 (sizeof (*info)); info->iface = g_strdup (iface); info->callback = callback; info->user_data = user_data; nm_log_dbg (LOGD_FIREWALL, "(%s) firewall zone %s -> %s", iface, add ? "add" : "change", zone); 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); }
static CBInfo * _cb_info_create (NMFirewallManager *self, CBInfoOpsType ops_type, const char *iface, NMFirewallManagerAddRemoveCallback callback, gpointer user_data) { NMFirewallManagerPrivate *priv = NM_FIREWALL_MANAGER_GET_PRIVATE (self); CBInfo *info; info = g_slice_new0 (CBInfo); info->self = g_object_ref (self); info->ops_type = ops_type; info->iface = g_strdup (iface); info->callback = callback; info->user_data = user_data; if (priv->running) { info->mode = CB_INFO_MODE_DBUS; info->dbus.cancellable = g_cancellable_new (); } else info->mode = CB_INFO_MODE_IDLE; if (!nm_g_hash_table_add (priv->pending_calls, info)) g_return_val_if_reached (NULL); return info; }
static void nm_firewall_manager_init (NMFirewallManager * self) { NMFirewallManagerPrivate *priv = NM_FIREWALL_MANAGER_GET_PRIVATE (self); priv->pending_calls = g_hash_table_new (g_direct_hash, g_direct_equal); }
gpointer nm_firewall_manager_remove_from_zone (NMFirewallManager *self, const char *iface, const char *zone) { NMFirewallManagerPrivate *priv = NM_FIREWALL_MANAGER_GET_PRIVATE (self); CBInfo *info; if (priv->running == FALSE) { nm_log_dbg (LOGD_FIREWALL, "(%s) firewall zone remove skipped (not running)", iface); return NULL; } info = g_malloc0 (sizeof (*info)); info->iface = g_strdup (iface); nm_log_dbg (LOGD_FIREWALL, "(%s) firewall zone remove -> %s", iface, zone ); 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); }
static void constructed (GObject *object) { NMFirewallManager *self = (NMFirewallManager *) object; NMFirewallManagerPrivate *priv = NM_FIREWALL_MANAGER_GET_PRIVATE (self); gs_free char *owner = NULL; gs_free_error GError *error = NULL; G_OBJECT_CLASS (nm_firewall_manager_parent_class)->constructed (object); priv->proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, NULL, FIREWALL_DBUS_SERVICE, FIREWALL_DBUS_PATH, FIREWALL_DBUS_INTERFACE_ZONE, NULL, &error); if (priv->proxy) { g_signal_connect (priv->proxy, "notify::g-name-owner", G_CALLBACK (name_owner_changed), self); owner = g_dbus_proxy_get_name_owner (priv->proxy); priv->running = (owner != NULL); } else { _LOGW (NULL, "could not connect to system D-Bus (%s)", error->message); } _LOGD (NULL, "firewall constructed (%srunning)", priv->running ? "" : "not"); }
void nm_firewall_manager_cancel_call (NMFirewallManagerCallId call) { NMFirewallManager *self; NMFirewallManagerPrivate *priv; CBInfo *info = call; gs_free_error GError *error = NULL; g_return_if_fail (info); g_return_if_fail (NM_IS_FIREWALL_MANAGER (info->self)); self = info->self; priv = NM_FIREWALL_MANAGER_GET_PRIVATE (self); if (!g_hash_table_remove (priv->pending_calls, info)) g_return_if_reached (); nm_utils_error_set_cancelled (&error, FALSE, "NMFirewallManager"); _LOGD (info, "complete: cancel (%s)", error->message); _cb_info_callback (info, error); if (_cb_info_is_idle (info)) { g_source_remove (info->idle.id); _cb_info_free (info); } else { info->mode = CB_INFO_MODE_DBUS_COMPLETED; g_cancellable_cancel (info->dbus.cancellable); g_clear_object (&info->self); } }
NMFirewallPendingCall nm_firewall_manager_remove_from_zone (NMFirewallManager *self, const char *iface, const char *zone) { NMFirewallManagerPrivate *priv = NM_FIREWALL_MANAGER_GET_PRIVATE (self); CBInfo *info; if (priv->running == FALSE) { nm_log_dbg (LOGD_FIREWALL, "(%s) firewall zone remove skipped (not running)", iface); return PENDING_CALL_DUMMY; } 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); 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); }
static void _cb_info_free (CBInfo *info) { NMFirewallManagerPrivate *priv; g_return_if_fail (info != NULL); 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); 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 void set_running (NMFirewallManager *self, gboolean now_running) { NMFirewallManagerPrivate *priv = NM_FIREWALL_MANAGER_GET_PRIVATE (self); gboolean old_running = priv->running; priv->running = now_running; if (old_running != priv->running) g_object_notify (G_OBJECT (self), NM_FIREWALL_MANAGER_AVAILABLE); }
static void _cb_info_complete_normal (CBInfo *info, GError *error) { NMFirewallManagerPrivate *priv = NM_FIREWALL_MANAGER_GET_PRIVATE (info->self); if (!g_hash_table_remove (priv->pending_calls, info)) g_return_if_reached (); _cb_info_callback (info, error); _cb_info_free (info); }
static void get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { switch (prop_id) { case PROP_AVAILABLE: g_value_set_boolean (value, NM_FIREWALL_MANAGER_GET_PRIVATE (object)->running); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } }
static void dispose (GObject *object) { NMFirewallManagerPrivate *priv = NM_FIREWALL_MANAGER_GET_PRIVATE (object); if (priv->dbus_mgr) { g_signal_handler_disconnect (priv->dbus_mgr, priv->name_owner_id); priv->name_owner_id = 0; g_clear_object (&priv->dbus_mgr); } g_clear_object (&priv->proxy); /* Chain up to the parent class */ G_OBJECT_CLASS (nm_firewall_manager_parent_class)->dispose (object); }
static void dispose (GObject *object) { NMFirewallManager *self = NM_FIREWALL_MANAGER (object); NMFirewallManagerPrivate *priv = NM_FIREWALL_MANAGER_GET_PRIVATE (self); if (priv->pending_calls) { /* as every pending operation takes a reference to the manager, * we don't expect pending operations at this point. */ g_assert (g_hash_table_size (priv->pending_calls) == 0); g_hash_table_unref (priv->pending_calls); priv->pending_calls = NULL; } g_clear_object (&priv->proxy); /* Chain up to the parent class */ G_OBJECT_CLASS (nm_firewall_manager_parent_class)->dispose (object); }
static void nm_firewall_manager_init (NMFirewallManager * self) { NMFirewallManagerPrivate *priv = NM_FIREWALL_MANAGER_GET_PRIVATE (self); DBusGConnection *bus; priv->dbus_mgr = g_object_ref (nm_dbus_manager_get ()); priv->name_owner_id = g_signal_connect (priv->dbus_mgr, NM_DBUS_MANAGER_NAME_OWNER_CHANGED, G_CALLBACK (name_owner_changed), self); priv->running = nm_dbus_manager_name_has_owner (priv->dbus_mgr, FIREWALL_DBUS_SERVICE); nm_log_dbg (LOGD_FIREWALL, "firewall %s running", priv->running ? "is" : "is not" ); bus = nm_dbus_manager_get_connection (priv->dbus_mgr); priv->proxy = dbus_g_proxy_new_for_name (bus, FIREWALL_DBUS_SERVICE, FIREWALL_DBUS_PATH, FIREWALL_DBUS_INTERFACE_ZONE); }
static CBInfo * _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_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 void dispose (GObject *object) { NMFirewallManagerPrivate *priv = NM_FIREWALL_MANAGER_GET_PRIVATE (object); if (priv->disposed) goto out; priv->disposed = TRUE; if (priv->dbus_mgr) { if (priv->name_owner_id) g_signal_handler_disconnect (priv->dbus_mgr, priv->name_owner_id); priv->dbus_mgr = NULL; } if (priv->proxy) g_object_unref (priv->proxy); out: /* Chain up to the parent class */ G_OBJECT_CLASS (nm_firewall_manager_parent_class)->dispose (object); }
NMFirewallPendingCall nm_firewall_manager_add_or_change_zone (NMFirewallManager *self, const char *iface, const char *zone, gboolean add, /* TRUE == add, FALSE == change */ FwAddToZoneFunc callback, gpointer user_data) { NMFirewallManagerPrivate *priv = NM_FIREWALL_MANAGER_GET_PRIVATE (self); CBInfo *info; if (priv->running == FALSE) { 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 (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); 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 NMFirewallManagerCallId _start_request (NMFirewallManager *self, CBInfoOpsType ops_type, const char *iface, const char *zone, NMFirewallManagerAddRemoveCallback callback, gpointer user_data) { NMFirewallManagerPrivate *priv; CBInfo *info; const char *dbus_method; g_return_val_if_fail (NM_IS_FIREWALL_MANAGER (self), NULL); g_return_val_if_fail (iface && *iface, NULL); priv = NM_FIREWALL_MANAGER_GET_PRIVATE (self); info = _cb_info_create (self, ops_type, iface, callback, user_data); _LOGD (info, "firewall zone %s %s:%s%s%s%s", _ops_type_to_string (info->ops_type), iface, NM_PRINT_FMT_QUOTED (zone, "\"", zone, "\"", "default"), _cb_info_is_idle (info) ? " (not running, simulate success)" : ""); if (!_cb_info_is_idle (info)) { switch (ops_type) { case CB_INFO_OPS_ADD: dbus_method = "addInterface"; break; case CB_INFO_OPS_CHANGE: dbus_method = "changeZone"; break; case CB_INFO_OPS_REMOVE: dbus_method = "removeInterface"; break; default: g_assert_not_reached (); } g_dbus_proxy_call (priv->proxy, dbus_method, g_variant_new ("(ss)", zone ? zone : "", iface), G_DBUS_CALL_FLAGS_NONE, 10000, info->dbus.cancellable, _handle_dbus, info); if (!info->callback) { /* if the user did not provide a callback, the call_id is useless. * Especially, the user cannot use the call-id to cancel the request, * because he cannot know whether the request is still pending. * * Hence, returning %NULL doesn't mean that the request could not be started * (the request will always be started). */ return NULL; } } else if (!info->callback) { /* if the user did not provide a callback and firewalld is not running, * there is no point in scheduling an idle-request to fake success. Just * return right away. */ _LOGD (info, "complete: drop request simulating success"); _cb_info_complete_normal (info, NULL); return NULL; } else info->idle.id = g_idle_add (_handle_idle, info); return info; }
void nm_firewall_manager_cancel_call (NMFirewallManager *self, gpointer call) { g_return_if_fail (NM_IS_FIREWALL_MANAGER (self)); dbus_g_proxy_cancel_call (NM_FIREWALL_MANAGER_GET_PRIVATE (self)->proxy, (DBusGProxyCall *) call); }