[PATCH 2/5] NMPacRunnerManager implemented to manage DBus talks with PacRunner.



PacRunner is a daemon for handling proxies. It's features includes
parsing PAC Script, downloading script with given PAC Url and answer
proxy queries. NM will use it's both DBus methods : CreateProxyConfiguration
and DestroyProxyConfiguration. NM configures PacRunner with domains
(search domains, routes etc) , Interface and PAC url/Script (for now).
---
 src/Makefile.am            |   5 +
 src/nm-pacrunner-manager.c | 474 +++++++++++++++++++++++++++++++++++++++++++++
 src/nm-pacrunner-manager.h |  41 ++++
 3 files changed, 520 insertions(+)
 create mode 100644 src/nm-pacrunner-manager.c
 create mode 100644 src/nm-pacrunner-manager.h

diff --git a/src/Makefile.am b/src/Makefile.am
index 700cfc4..b771c22 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -433,6 +433,8 @@ libNetworkManager_la_SOURCES = \
        nm-manager.h \
        nm-multi-index.c \
        nm-multi-index.h \
+       nm-pacrunner-manager.c \
+       nm-pacrunner-manager.h \
        nm-policy.c \
        nm-policy.h \
        nm-rfkill-manager.c \
@@ -555,6 +557,9 @@ libnm_iface_helper_la_SOURCES = \
        platform/wifi/wifi-utils.c \
        platform/wifi/wifi-utils.h \
        \
+       nm-pacrunner-manager.c \
+       nm-pacrunner-manager.h \
+       \
        rdisc/nm-fake-rdisc.c \
        rdisc/nm-fake-rdisc.h \
        rdisc/nm-lndp-rdisc.c \
diff --git a/src/nm-pacrunner-manager.c b/src/nm-pacrunner-manager.c
new file mode 100644
index 0000000..95236d4
--- /dev/null
+++ b/src/nm-pacrunner-manager.c
@@ -0,0 +1,474 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+
+#include "nm-default.h"
+
+#include <stdlib.h>
+
+#include "nm-utils.h"
+#include "nm-platform.h"
+#include "nm-pacrunner-manager.h"
+#include "nm-proxy-config.h"
+#include "nm-ip4-config.h"
+#include "nm-ip6-config.h"
+#include "NetworkManagerUtils.h"
+
+G_DEFINE_TYPE (NMPacRunnerManager, nm_pacrunner_manager, G_TYPE_OBJECT)
+
+#define NM_PACRUNNER_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_PACRUNNER_MANAGER, 
NMPacRunnerManagerPrivate))
+
+#define PACRUNNER_DBUS_SERVICE "org.pacrunner"
+#define PACRUNNER_DBUS_INTERFACE "org.pacrunner.Manager"
+#define PACRUNNER_DBUS_PATH "/org/pacrunner/manager"
+
+struct remove_data {
+       char *iface;
+       char *path;
+};
+
+typedef struct {
+       gboolean started;
+       char *iface;
+       GDBusProxy *pacrunner;
+       GCancellable *pacrunner_cancellable;
+       GVariant *pacrunner_manager_args;
+       GPtrArray *domains;
+} NMPacRunnerManagerPrivate;
+
+/*****************************************************************************/
+
+#define _NMLOG_DOMAIN         LOGD_PROXY
+#define _NMLOG_PREFIX_NAME    "pacrunner"
+#define _NMLOG(level, ...) \
+    G_STMT_START { \
+        nm_log ((level), _NMLOG_DOMAIN, \
+                "%s[%p]: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \
+                _NMLOG_PREFIX_NAME, \
+                (self) \
+                _NM_UTILS_MACRO_REST(__VA_ARGS__)); \
+    } G_STMT_END
+
+/*****************************************************************************/
+
+static GList *rmv = NULL;
+
+static void
+remove_data_destroy (struct remove_data *data)
+{
+       g_return_if_fail (data != NULL);
+
+       g_free (data->iface);
+       g_free (data->path);
+       memset (data, 0, sizeof (struct remove_data));
+       g_free (data);
+}
+
+static void
+add_pacrunner_proxy_data (NMPacRunnerManager *self,
+                          GVariantBuilder *proxy_data,
+                          const char *prefix,
+                          GVariant *variant)
+{
+       g_variant_builder_open (proxy_data, G_VARIANT_TYPE ("{sv}"));
+
+       g_variant_builder_add (proxy_data, "{sv}",
+                              prefix,
+                              variant);
+
+       g_variant_builder_close (proxy_data);
+}
+
+static void
+add_proxy_config (NMPacRunnerManager *self, GVariantBuilder *proxy_data, const NMProxyConfig *proxy_config)
+{
+       const char *pac = NULL;
+       NMProxyConfigMethod method;
+
+       method = nm_proxy_config_get_method (proxy_config);
+       if (method == NM_PROXY_CONFIG_METHOD_NONE)
+               return;
+
+       pac = nm_proxy_config_get_pac_url (proxy_config);
+       if (pac != NULL) {
+               add_pacrunner_proxy_data (self,
+                                         proxy_data,
+                                         "URL",
+                                         g_variant_new_string (pac));
+       } else {
+               pac = nm_proxy_config_get_pac_script (proxy_config);
+               if (pac) {
+                       add_pacrunner_proxy_data (self,
+                                                 proxy_data,
+                                                 "Script",
+                                                 g_variant_new_string (pac));
+               }
+       }
+}
+
+static void
+add_ip4_config (NMPacRunnerManager *self, GVariantBuilder *proxy_data, NMIP4Config *ip4, NMProxyIPConfigType 
type)
+{
+       NMPacRunnerManagerPrivate *priv = NM_PACRUNNER_MANAGER_GET_PRIVATE (self);
+       int n, i;
+
+       if (type == NM_PROXY_IP_CONFIG_TYPE_VPN) {
+               n = nm_ip4_config_get_num_searches (ip4);
+               for (i = 0; i < n; i++) {
+                       g_ptr_array_add (priv->domains, g_strdup (nm_ip4_config_get_search (ip4, i)));
+               }
+
+               if (n == 0) {
+                       /* If not searches, use any domains */
+                       n = nm_ip4_config_get_num_domains (ip4);
+                       for (i = 0; i < n; i++) {
+                               g_ptr_array_add (priv->domains, g_strdup (nm_ip4_config_get_domain (ip4, i)));
+                       }
+               }
+
+               for (i = 0; i < nm_ip4_config_get_num_addresses (ip4); i++) {
+                       const NMPlatformIP4Address *address = nm_ip4_config_get_address (ip4, i);
+
+                       GString *addr = g_string_new (NULL);
+                       g_string_append_printf (addr, "%s/%u",
+                                               nm_utils_inet4_ntop (address->address, NULL),
+                                               address->plen);
+                       g_ptr_array_add (priv->domains, g_strdup (addr->str));
+
+                       g_string_free (addr, TRUE);
+               }
+
+               for (i = 0; i < nm_ip4_config_get_num_routes (ip4); i++) {
+                       const NMPlatformIP4Route *routes = nm_ip4_config_get_route (ip4, i);
+
+                       GString *route = g_string_new (NULL);
+                       g_string_append_printf (route, "%s/%u",
+                                               nm_utils_inet4_ntop (routes->network, NULL),
+                                               routes->plen);
+                       g_ptr_array_add (priv->domains, g_strdup (route->str));
+
+                       g_string_free (route, TRUE);
+               }
+       }
+}
+
+static void
+add_ip6_config (NMPacRunnerManager *self, GVariantBuilder *proxy_data, NMIP6Config *ip6, NMProxyIPConfigType 
type)
+{
+       NMPacRunnerManagerPrivate *priv = NM_PACRUNNER_MANAGER_GET_PRIVATE (self);
+       int n, i;
+
+       if (type == NM_PROXY_IP_CONFIG_TYPE_VPN) {
+               n = nm_ip6_config_get_num_searches (ip6);
+               for (i = 0; i < n; i++) {
+                       g_ptr_array_add (priv->domains, g_strdup (nm_ip6_config_get_search (ip6, i)));
+               }
+
+               if (n == 0) {
+                       /* If not searches, use any domains */
+                       n = nm_ip6_config_get_num_domains (ip6);
+                       for (i = 0; i < n; i++) {
+                               g_ptr_array_add (priv->domains, g_strdup (nm_ip6_config_get_domain (ip6, i)));
+                       }
+               }
+
+               for (i = 0; i < nm_ip6_config_get_num_addresses (ip6); i++) {
+                       const NMPlatformIP6Address *address = nm_ip6_config_get_address (ip6, i);
+
+                       GString *addr = g_string_new (NULL);
+                       g_string_append_printf (addr, "%s/%u",
+                                               nm_utils_inet6_ntop (&address->address, NULL),
+                                               address->plen);
+                       g_ptr_array_add (priv->domains, g_strdup (addr->str));
+
+                       g_string_free (addr, TRUE);
+               }
+
+               for (i = 0; i < nm_ip6_config_get_num_routes (ip6); i++) {
+                       const NMPlatformIP6Route *routes = nm_ip6_config_get_route (ip6, i);
+
+                       GString *route = g_string_new (NULL);
+                       g_string_append_printf (route, "%s/%u",
+                                               nm_utils_inet6_ntop (&routes->network, NULL),
+                                               routes->plen);
+                       g_ptr_array_add (priv->domains, g_strdup (route->str));
+
+                       g_string_free (route, TRUE);
+               }
+       }
+}
+
+static void
+pacrunner_send_done (GObject *source, GAsyncResult *res, gpointer user_data)
+{
+       NMPacRunnerManager *self = NM_PACRUNNER_MANAGER (user_data);
+       NMPacRunnerManagerPrivate *priv = NM_PACRUNNER_MANAGER_GET_PRIVATE (self);
+       gs_free_error GError *error = NULL;
+       gs_unref_variant GVariant *variant = NULL;
+       const char *path = NULL;
+       GList *iter = NULL;
+       gboolean found = FALSE;
+
+       variant = g_dbus_proxy_call_finish (priv->pacrunner, res, &error);
+       if (!variant) {
+               _LOGW ("sending proxy config to pacrunner failed: %s", error->message);
+       } else {
+               struct remove_data *data;
+               g_variant_get (variant, "(&o)", &path);
+
+               for (iter = g_list_first (rmv); iter; iter = g_list_next (iter)) {
+                       struct remove_data *r = iter->data;
+                       if (g_strcmp0 (priv->iface, r->iface) == 0) {
+                               g_free (r->path);
+                               r->path = g_strdup (path);
+                               found = TRUE;
+                               break;
+                       }
+               }
+
+               if (!found) {
+                       data = g_malloc0 (sizeof (struct remove_data));
+                       data->iface = g_strdup (priv->iface);
+                       data->path = g_strdup (path);
+                       rmv = g_list_append (rmv, data);
+                       _LOGD ("proxy config sent to pacrunner");
+               }
+       }
+}
+
+static void
+send_pacrunner_proxy_data (NMPacRunnerManager *self)
+{
+       NMPacRunnerManagerPrivate *priv = NM_PACRUNNER_MANAGER_GET_PRIVATE (self);
+
+       if (!priv->pacrunner_manager_args)
+               return;
+
+       if (priv->pacrunner)
+               g_dbus_proxy_call (priv->pacrunner,
+                                  "CreateProxyConfiguration",
+                                  priv->pacrunner_manager_args,
+                                  G_DBUS_CALL_FLAGS_NONE,
+                                  -1,
+                                  NULL,
+                                 (GAsyncReadyCallback) pacrunner_send_done,
+                                  self);
+}
+
+static void
+name_owner_changed (GObject *object,
+                    GParamSpec *pspec,
+                    gpointer user_data)
+{
+       NMPacRunnerManager *self = NM_PACRUNNER_MANAGER (user_data);
+       gs_free char *owner = NULL;
+
+       owner = g_dbus_proxy_get_name_owner (G_DBUS_PROXY (object));
+       if (owner) {
+               _LOGI ("PacRunner appeared as %s", owner);
+               send_pacrunner_proxy_data (self);
+       } else {
+               _LOGI ("PacRunner disappeared");
+       }
+}
+
+static void
+pacrunner_proxy_cb (GObject *source, GAsyncResult *res, gpointer user_data)
+{
+       NMPacRunnerManager *self = NULL;
+       NMPacRunnerManagerPrivate *priv;
+       gs_free_error GError *error = NULL;
+       gs_free char *owner = NULL;
+       GDBusProxy *proxy;
+
+       proxy = g_dbus_proxy_new_for_bus_finish (res, &error);
+       if (!proxy
+           && g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+               return;
+
+       self = NM_PACRUNNER_MANAGER (user_data);
+       priv = NM_PACRUNNER_MANAGER_GET_PRIVATE (self);
+
+       if (!proxy) {
+               priv->started = FALSE;
+               _LOGI ("failed to connect to pacrunner via DBus: %s", error->message);
+               return;
+       }
+
+       priv->pacrunner = proxy;
+       nm_clear_g_cancellable (&priv->pacrunner_cancellable);
+
+       _LOGD ("pacrunner proxy creation successful");
+
+       g_signal_connect (priv->pacrunner, "notify::g-name-owner",
+                         G_CALLBACK (name_owner_changed), self);
+       owner = g_dbus_proxy_get_name_owner (priv->pacrunner);
+}
+
+static void
+start_pacrunner (NMPacRunnerManager *self)
+{
+       NMPacRunnerManagerPrivate *priv = NM_PACRUNNER_MANAGER_GET_PRIVATE (self);
+
+       if (priv->started)
+               return;
+
+       priv->pacrunner_cancellable = g_cancellable_new ();
+
+       g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM,
+                                 G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
+                                 NULL,
+                                 PACRUNNER_DBUS_SERVICE,
+                                 PACRUNNER_DBUS_PATH,
+                                 PACRUNNER_DBUS_INTERFACE,
+                                 priv->pacrunner_cancellable,
+                                (GAsyncReadyCallback) pacrunner_proxy_cb,
+                                 self);
+       priv->started = TRUE;
+}
+
+gboolean
+nm_pacrunner_manager_send (NMPacRunnerManager *self,
+                           const char *iface,
+                           NMProxyConfig *proxy_config,
+                           NMIP4Config *ip4_config,
+                           NMIP6Config *ip6_config,
+                           NMProxyIPConfigType type)
+{
+       char **strv = NULL;
+       NMProxyConfigMethod method;
+       NMPacRunnerManagerPrivate *priv;
+       GVariantBuilder proxy_data;
+
+       g_return_val_if_fail (NM_IS_PACRUNNER_MANAGER (self), FALSE);
+       priv = NM_PACRUNNER_MANAGER_GET_PRIVATE (self);
+
+       if (!priv->started) {
+               _LOGI ("Can't send config to pacrunner (not available on bus)");
+               return FALSE;
+       }
+
+       g_free (priv->iface);
+       priv->iface = g_strdup (iface);
+
+       g_variant_builder_init (&proxy_data, G_VARIANT_TYPE_VARDICT);
+
+       method = nm_proxy_config_get_method (proxy_config);
+       g_variant_builder_add (&proxy_data, "{sv}",
+                              "Method",
+                              g_variant_new_string (method == NM_PROXY_CONFIG_METHOD_AUTO ? "auto" : 
"direct"));
+
+       g_variant_builder_add (&proxy_data, "{sv}",
+                              "Interface",
+                              g_variant_new_string (iface));
+
+       priv->domains = g_ptr_array_new_with_free_func (g_free);
+
+       if (proxy_config)
+               add_proxy_config (self, &proxy_data, proxy_config);
+       if (ip4_config)
+               add_ip4_config (self, &proxy_data, ip4_config, type);
+       if (ip6_config)
+               add_ip6_config (self, &proxy_data, ip6_config, type);
+
+       /* Terminating NULL so we can use g_strfreev() to free it */
+       g_ptr_array_add (priv->domains, NULL);
+
+       /* Free the array and return NULL if the only element was the ending NULL */
+       strv = (char **) g_ptr_array_free (priv->domains, (priv->domains->len == 1));
+
+       if (strv) {
+               add_pacrunner_proxy_data (self,
+                                         &proxy_data,
+                                         "Domains",
+                                         g_variant_new_strv ((const char *const *) strv, -1));
+               g_strfreev (strv);
+       }
+
+       g_clear_pointer (&priv->pacrunner_manager_args, g_variant_unref);
+       priv->pacrunner_manager_args = g_variant_ref_sink (g_variant_new ("(a{sv})", &proxy_data));
+
+       send_pacrunner_proxy_data (self);
+
+       return TRUE;
+}
+
+static void
+pacrunner_remove_done (GObject *source, GAsyncResult *res, gpointer user_data)
+{
+       NMPacRunnerManager *self = NM_PACRUNNER_MANAGER (user_data);
+       NMPacRunnerManagerPrivate *priv = NM_PACRUNNER_MANAGER_GET_PRIVATE (self);
+       gs_free_error GError *error = NULL;
+       gs_unref_variant GVariant *ret = NULL;
+
+       ret = g_dbus_proxy_call_finish (priv->pacrunner, res, &error);
+       if (!ret || g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+               _LOGI ("Couldn't remove proxy config from pacrunner");
+       else
+               _LOGD ("Sucessfully removed proxy config from pacrunner");
+}
+
+void
+nm_pacrunner_manager_remove (NMPacRunnerManager *self, const char *iface)
+{
+       NMPacRunnerManagerPrivate *priv = NM_PACRUNNER_MANAGER_GET_PRIVATE (self);
+       GList *list;
+
+       for (list = g_list_first(rmv); list; list = g_list_next(list)) {
+               struct remove_data *data = list->data;
+               if (g_strcmp0 (data->iface, iface) == 0) {
+                       if ((priv->pacrunner) && (data->path))
+                               g_dbus_proxy_call (priv->pacrunner,
+                                                  "DestroyProxyConfiguration",
+                                                  g_variant_new ("(o)", data->path),
+                                                  G_DBUS_CALL_FLAGS_NONE,
+                                                  -1,
+                                                  NULL,
+                                                 (GAsyncReadyCallback) pacrunner_remove_done,
+                                                  self);
+                       break;
+               }
+       }
+}
+
+NMPacRunnerManager *
+nm_pacrunner_manager_get (void)
+{
+       return NM_PACRUNNER_MANAGER (g_object_new (NM_TYPE_PACRUNNER_MANAGER, NULL));
+}
+
+static void
+nm_pacrunner_manager_init (NMPacRunnerManager *self)
+{
+       NMPacRunnerManagerPrivate *priv = NM_PACRUNNER_MANAGER_GET_PRIVATE (self);
+
+       priv->started = FALSE;
+
+       start_pacrunner (self);
+}
+
+static void
+dispose (GObject *object)
+{
+       NMPacRunnerManagerPrivate *priv = NM_PACRUNNER_MANAGER_GET_PRIVATE (object);
+
+       g_free (priv->iface);
+
+       nm_clear_g_cancellable (&priv->pacrunner_cancellable);
+
+       g_clear_object (&priv->pacrunner);
+
+       g_clear_pointer (&priv->pacrunner_manager_args, g_variant_unref);
+
+       g_list_free_full (rmv, (GDestroyNotify) remove_data_destroy);
+
+       G_OBJECT_CLASS (nm_pacrunner_manager_parent_class)->dispose (object);
+}
+
+static void
+nm_pacrunner_manager_class_init (NMPacRunnerManagerClass *klass)
+{
+       GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+       g_type_class_add_private (object_class, sizeof (NMPacRunnerManagerPrivate));
+
+       object_class->dispose = dispose;
+}
diff --git a/src/nm-pacrunner-manager.h b/src/nm-pacrunner-manager.h
new file mode 100644
index 0000000..55a4a4f
--- /dev/null
+++ b/src/nm-pacrunner-manager.h
@@ -0,0 +1,41 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+
+#ifndef __NETWORKMANAGER_PACRUNNER_MANAGER_H__
+#define __NETWORKMANAGER_PACRUNNER_MANAGER_H__
+
+#include "nm-default.h"
+
+typedef enum {
+       NM_PROXY_IP_CONFIG_TYPE_DEFAULT = 0,
+       NM_PROXY_IP_CONFIG_TYPE_VPN
+} NMProxyIPConfigType;
+
+#define NM_TYPE_PACRUNNER_MANAGER            (nm_pacrunner_manager_get_type ())
+#define NM_PACRUNNER_MANAGER(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_PACRUNNER_MANAGER, 
NMPacRunnerManager))
+#define NM_PACRUNNER_MANAGER_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_PACRUNNER_MANAGER, 
NMPacRunnerManagerClass))
+#define NM_IS_PACRUNNER_MANAGER(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_PACRUNNER_MANAGER))
+#define NM_IS_PACRUNNER_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_PACRUNNER_MANAGER))
+#define NM_PACRUNNER_MANAGER_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_PACRUNNER_MANAGER, 
NMPacRunnerManagerClass))
+
+struct _NMPacRunnerManager {
+       GObject parent;
+};
+
+typedef struct {
+       GObjectClass parent;
+} NMPacRunnerManagerClass;
+
+GType nm_pacrunner_manager_get_type (void);
+
+NMPacRunnerManager *nm_pacrunner_manager_get (void);
+
+gboolean nm_pacrunner_manager_send (NMPacRunnerManager *self,
+                                    const char *iface,
+                                    NMProxyConfig *proxy_config,
+                                    NMIP4Config *ip4_config,
+                                    NMIP6Config *ip6_config,
+                                    NMProxyIPConfigType type);
+
+void nm_pacrunner_manager_remove (NMPacRunnerManager *self, const char *iface);
+
+#endif /* __NETWORKMANAGER_PACRUNNER_MANAGER_H__ */
-- 
2.5.5



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]