summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLudovic Ferrandis <ludovic.ferrandis@intel.com>2013-08-21 14:18:17 +0200
committerRegis Merlino <regis.merlino@intel.com>2013-08-22 16:57:45 +0200
commita2a19b273105c71da1d10d54bfa93cb1e56df56a (patch)
tree5a3a84f8be5c7441f3a79d484091cfad716941a3
parenta56c850798271ffb645744c066220401106a972a (diff)
downloaddleyna-core-a2a19b273105c71da1d10d54bfa93cb1e56df56a.tar.gz
[Network Filtering] Add Network Filtering support
Add Network Filtering support in dLeyna. Add API to the core library to manage the GUPnPWhiteList object Manage 2 new settings: 1 - netf_enabled (boolean): To activate or deactivate the network filtering 2 - netf_entries (str list): List of supported network Signed-off-by: Ludovic Ferrandis <ludovic.ferrandis@intel.com>
-rw-r--r--Makefile.am8
-rw-r--r--configure.ac4
-rw-r--r--libdleyna/core/settings.c157
-rw-r--r--libdleyna/core/settings.h4
-rw-r--r--libdleyna/core/white-list.c125
-rw-r--r--libdleyna/core/white-list.h50
6 files changed, 338 insertions, 10 deletions
diff --git a/Makefile.am b/Makefile.am
index c166e83..9fc4360 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -2,7 +2,7 @@ libdleyna_coreincdir = $(includedir)/dleyna-1.0/libdleyna/core
connectordir = $(libdir)/dleyna-1.0/connectors
sysconfigdir = $(sysconfdir)
-DLEYNA_CORE_VERSION = 1:2:0
+DLEYNA_CORE_VERSION = 2:0:1
AM_CFLAGS = $(GLIB_CFLAGS) \
$(GIO_CFLAGS) \
@@ -25,7 +25,8 @@ libdleyna_coreinc_HEADERS = libdleyna/core/connector.h \
libdleyna/core/service-task.h \
libdleyna/core/settings.h \
libdleyna/core/task-atom.h \
- libdleyna/core/task-processor.h
+ libdleyna/core/task-processor.h \
+ libdleyna/core/white-list.h
libdleyna_core_1_0_la_LDFLAGS = -version-info $(DLEYNA_CORE_VERSION) \
@@ -38,7 +39,8 @@ libdleyna_core_1_0_la_SOURCES = $(libdleyna_coreinc_HEADERS) \
libdleyna/core/main-loop.c \
libdleyna/core/service-task.c \
libdleyna/core/settings.c \
- libdleyna/core/task-processor.c
+ libdleyna/core/task-processor.c \
+ libdleyna/core/white-list.c
libdleyna_core_1_0_la_LIBADD = $(GLIB_LIBS) \
$(GIO_LIBS) \
diff --git a/configure.ac b/configure.ac
index 67dbcd2..d6a5af5 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,7 +1,7 @@
AC_PREREQ([2.66])
AC_INIT([dleyna-core],
- [0.2.1],
+ [0.2.2],
[https://github.com/01org/dleyna-core/issues/new],
,
[https://01.org/dleyna/])
@@ -39,7 +39,7 @@ PKG_PROG_PKG_CONFIG(0.16)
PKG_CHECK_MODULES([GLIB], [glib-2.0 >= 2.28])
PKG_CHECK_MODULES([GIO], [gio-2.0 >= 2.28])
PKG_CHECK_MODULES([GMODULE], [gmodule-2.0 >= 2.28])
-PKG_CHECK_MODULES([GUPNP], [gupnp-1.0 >= 0.19.1])
+PKG_CHECK_MODULES([GUPNP], [gupnp-1.0 >= 0.20.5])
# Checks for header files.
AC_CHECK_HEADERS([stdlib.h string.h syslog.h])
diff --git a/libdleyna/core/settings.c b/libdleyna/core/settings.c
index 701f527..c86ace9 100644
--- a/libdleyna/core/settings.c
+++ b/libdleyna/core/settings.c
@@ -25,6 +25,7 @@
#include "log.h"
#include "settings.h"
+#include "white-list.h"
struct dleyna_settings_t_ {
GKeyFile *keyfile;
@@ -40,15 +41,23 @@ struct dleyna_settings_t_ {
/* Log section */
dleyna_log_type_t log_type;
int log_level;
+
+ /* netf section */
+ gboolean netf_enabled;
+ GVariant *netf_entries;
};
#define DLEYNA_SETTINGS_GROUP_GENERAL "general"
#define DLEYNA_SETTINGS_KEY_NEVER_QUIT "never-quit"
#define DLEYNA_SETTINGS_KEY_CONNECTOR_NAME "connector-name"
-#define DLEYNA_SETTINGS_GROUP_LOG "log"
-#define DLEYNA_SETTINGS_KEY_LOG_TYPE "log-type"
-#define DLEYNA_SETTINGS_KEY_LOG_LEVEL "log-level"
+#define DLEYNA_SETTINGS_GROUP_LOG "log"
+#define DLEYNA_SETTINGS_KEY_LOG_TYPE "log-type"
+#define DLEYNA_SETTINGS_KEY_LOG_LEVEL "log-level"
+
+#define DLEYNA_SETTINGS_GROUP_NETF "netf"
+#define DLEYNA_SETTINGS_KEY_NETF_ENABLED "netf-enabled"
+#define DLEYNA_SETTINGS_KEY_NETF_LIST "netf-list"
#define DLEYNA_SETTINGS_DEFAULT_NEVER_QUIT DLEYNA_NEVER_QUIT
#define DLEYNA_SETTINGS_DEFAULT_CONNECTOR_NAME DLEYNA_CONNECTOR_NAME
@@ -57,18 +66,30 @@ struct dleyna_settings_t_ {
#define DLEYNA_SETTINGS_LOG_KEYS(sys, loc, settings) \
do { \
+ gchar *str = NULL; \
+ \
DLEYNA_LOG_DEBUG_NL(); \
DLEYNA_LOG_INFO("Load file [%s]", loc ? loc : sys); \
DLEYNA_LOG_DEBUG_NL(); \
+ \
DLEYNA_LOG_DEBUG("[General settings]"); \
DLEYNA_LOG_DEBUG("Never Quit: %s", (settings)->never_quit ? "T" : "F");\
DLEYNA_LOG_DEBUG_NL(); \
DLEYNA_LOG_DEBUG("Connector Name: %s", (settings)->connector_name);\
DLEYNA_LOG_DEBUG_NL(); \
+ \
DLEYNA_LOG_DEBUG("[Logging settings]"); \
DLEYNA_LOG_DEBUG("Log Type : %d", (settings)->log_type); \
DLEYNA_LOG_DEBUG("Log Level: 0x%02X", (settings)->log_level); \
DLEYNA_LOG_DEBUG_NL(); \
+ \
+ if ((settings)->netf_entries != NULL) \
+ str = g_variant_print((settings)->netf_entries, FALSE); \
+ DLEYNA_LOG_DEBUG("[Network filtering settings]"); \
+ DLEYNA_LOG_DEBUG("Enabled : %s", (settings)->netf_enabled ? "T" : "F");\
+ DLEYNA_LOG_DEBUG("Entries: %s", str); \
+ g_free(str); \
+ DLEYNA_LOG_DEBUG_NL(); \
} while (0)
@@ -148,6 +169,25 @@ exit:
return keyfile;
}
+static GVariant *prv_to_netf_entries(char **list)
+{
+ GVariantBuilder vb;
+ GVariant *result = NULL;
+
+ if ((list != NULL) && (*list != NULL)) {
+ g_variant_builder_init(&vb, G_VARIANT_TYPE("as"));
+
+ while (*list != NULL) {
+ g_variant_builder_add(&vb, "s", *list);
+ list++;
+ }
+
+ result = g_variant_ref_sink(g_variant_builder_end(&vb));
+ }
+
+ return result;
+}
+
static int prv_to_log_level(gint *int_list, gsize length)
{
gsize i;
@@ -205,6 +245,7 @@ static void prv_read_keys(dleyna_settings_t *settings)
gchar *s_val;
gint *int_star;
gsize length;
+ gchar **list;
b_val = g_key_file_get_boolean(keyfile,
DLEYNA_SETTINGS_GROUP_GENERAL,
@@ -252,13 +293,38 @@ static void prv_read_keys(dleyna_settings_t *settings)
&error);
if (error == NULL) {
- settings->log_level = prv_to_log_level(int_star,
- length);
+ settings->log_level = prv_to_log_level(int_star, length);
g_free(int_star);
} else {
g_error_free(error);
error = NULL;
}
+
+ b_val = g_key_file_get_boolean(keyfile,
+ DLEYNA_SETTINGS_GROUP_NETF,
+ DLEYNA_SETTINGS_KEY_NETF_ENABLED,
+ &error);
+
+ if (error == NULL) {
+ settings->netf_enabled = b_val;
+ } else {
+ g_error_free(error);
+ error = NULL;
+ }
+
+ list = g_key_file_get_string_list(keyfile,
+ DLEYNA_SETTINGS_GROUP_NETF,
+ DLEYNA_SETTINGS_KEY_NETF_LIST,
+ NULL,
+ &error);
+
+ if (error == NULL) {
+ settings->netf_entries = prv_to_netf_entries(list);
+ g_strfreev(list);
+ } else {
+ g_error_free(error);
+ error = NULL;
+ }
}
static void prv_init_default(dleyna_settings_t *settings)
@@ -269,6 +335,9 @@ static void prv_init_default(dleyna_settings_t *settings)
settings->log_type = DLEYNA_SETTINGS_DEFAULT_LOG_TYPE;
settings->log_level = DLEYNA_SETTINGS_DEFAULT_LOG_LEVEL;
+
+ settings->netf_enabled = FALSE;
+ settings->netf_entries = NULL;
}
static void prv_keyfile_init(dleyna_settings_t *settings,
@@ -289,19 +358,64 @@ static void prv_keyfile_init(dleyna_settings_t *settings,
static void prv_keyfile_finalize(dleyna_settings_t *settings)
{
+ if (settings->netf_entries != NULL) {
+ g_variant_unref(settings->netf_entries);
+ settings->netf_entries = NULL;
+ }
+
if (settings->keyfile != NULL) {
g_key_file_free(settings->keyfile);
settings->keyfile = NULL;
}
}
+static gboolean prv_netf_entries_are_equal(GVariant *old, GVariant *new)
+{
+ gboolean match;
+ GVariantIter iter1;
+ GVariantIter iter2;
+ gchar *entry1;
+ gchar *entry2;
+
+ match = (old == new);
+
+ if (match ||
+ ((old == NULL) && (new != NULL)) ||
+ ((old != NULL) && (new == NULL)))
+ goto exit;
+
+ (void) g_variant_iter_init(&iter1, old);
+
+ while (g_variant_iter_next(&iter1, "&s", &entry1)) {
+ (void) g_variant_iter_init(&iter2, new);
+
+ while (g_variant_iter_next(&iter2, "&s", &entry2) && !match)
+ match = !strcmp(entry1, entry2);
+
+ if (!match)
+ break;
+ }
+
+exit:
+ return match;
+}
+
static void prv_reload(dleyna_settings_t *settings)
{
gchar *sys_path = NULL;
gchar *loc_path = NULL;
+ gboolean saved_netf_enabled;
+ GVariant *saved_netf_entries;
+ GVariant *netf_entries;
DLEYNA_LOG_INFO("Reload local configuration file");
+ /* Save all White List information */
+ saved_netf_enabled = settings->netf_enabled;
+ saved_netf_entries = settings->netf_entries;
+ /* Prevent prv_keyfile_finalize()) to free it */
+ settings->netf_entries = NULL;
+
prv_keyfile_finalize(settings);
prv_init_default(settings);
prv_get_keyfile_path(settings->file_name, &sys_path, &loc_path);
@@ -309,6 +423,32 @@ static void prv_reload(dleyna_settings_t *settings)
if (sys_path || loc_path)
prv_keyfile_init(settings, sys_path, loc_path);
+ netf_entries = settings->netf_entries;
+
+ /* FIXME: Block white list signals instead */
+ /* A little optimization hack:
+ * 1 - Updating the wl list has no effect if the wl is disabled.
+ * 2 - If the enabled settings has changed to disabled, apply first.
+ * 3 - If it has changed to enabled, update the list first, then
+ * apply the change last.
+ */
+ if (!settings->netf_enabled && saved_netf_enabled)
+ dleyna_white_list_enable(settings->netf_enabled, TRUE);
+
+ /* Remove old entries if new ones are different.
+ * Don't clear() to avoid to loose entries added by a client
+ */
+ if (!prv_netf_entries_are_equal(saved_netf_entries, netf_entries)) {
+ dleyna_white_list_remove_entries(saved_netf_entries, FALSE);
+ dleyna_white_list_add_entries(netf_entries, TRUE);
+ }
+
+ if (settings->netf_enabled && !saved_netf_enabled)
+ dleyna_white_list_enable(settings->netf_enabled, TRUE);
+
+ if (saved_netf_entries != NULL)
+ g_variant_unref(saved_netf_entries);
+
DLEYNA_SETTINGS_LOG_KEYS(sys_path, loc_path, settings);
g_free(sys_path);
@@ -430,6 +570,7 @@ void dleyna_settings_delete(dleyna_settings_t *settings)
g_file_monitor_cancel(settings->monitor);
g_object_unref(settings->monitor);
}
+
g_free(settings->connector_name);
g_free(settings->file_name);
@@ -437,3 +578,9 @@ void dleyna_settings_delete(dleyna_settings_t *settings)
g_free(settings);
}
+
+void dleyna_settings_init_white_list(dleyna_settings_t *settings)
+{
+ dleyna_white_list_add_entries(settings->netf_entries, TRUE);
+ dleyna_white_list_enable(settings->netf_enabled, TRUE);
+}
diff --git a/libdleyna/core/settings.h b/libdleyna/core/settings.h
index 4274879..b09456f 100644
--- a/libdleyna/core/settings.h
+++ b/libdleyna/core/settings.h
@@ -28,9 +28,13 @@
typedef struct dleyna_settings_t_ dleyna_settings_t;
void dleyna_settings_new(const gchar *server, dleyna_settings_t **settings);
+
void dleyna_settings_delete(dleyna_settings_t *settings);
+void dleyna_settings_init_white_list(dleyna_settings_t *settings);
+
gboolean dleyna_settings_is_never_quit(dleyna_settings_t *settings);
+
const gchar *dleyna_settings_connector_name(dleyna_settings_t *settings);
#endif /* DLEYNA_SETTINGS_H__ */
diff --git a/libdleyna/core/white-list.c b/libdleyna/core/white-list.c
new file mode 100644
index 0000000..fa5d2d0
--- /dev/null
+++ b/libdleyna/core/white-list.c
@@ -0,0 +1,125 @@
+/*
+ * dLeyna
+ *
+ * Copyright (C) 2013 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU Lesser General Public License,
+ * version 2.1, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Ludovic Ferrandis <ludovic.ferrandis@intel.com>
+ *
+ */
+
+#include <string.h>
+
+#include "white-list.h"
+#include "log.h"
+
+static dleyna_white_list_t g_wl_cb;
+
+#if DLEYNA_LOG_LEVEL & DLEYNA_LOG_LEVEL_DEBUG
+static void prv_dump_wl_entries(GUPnPWhiteList *wl)
+{
+ GList *l;
+
+ l = gupnp_white_list_get_entries(wl);
+
+ DLEYNA_LOG_DEBUG_NL();
+ DLEYNA_LOG_DEBUG("White List entries:");
+
+ if (l != NULL) {
+ while (l != NULL) {
+ DLEYNA_LOG_DEBUG(" Entry: [%s].", (char *)l->data);
+ l = l->next;
+ }
+ } else {
+ DLEYNA_LOG_DEBUG(" White List Empty.");
+ }
+
+ DLEYNA_LOG_DEBUG_NL();
+}
+#endif
+
+void dleyna_white_list_enable(gboolean enabled, gboolean notify)
+{
+ if (g_wl_cb.wl != NULL) {
+ gupnp_white_list_set_enabled(g_wl_cb.wl, enabled);
+
+ DLEYNA_LOG_DEBUG("White List enabled: %d", enabled);
+
+ if (notify && (g_wl_cb.cb_enabled != NULL))
+ g_wl_cb.cb_enabled(g_wl_cb.user_data);
+ }
+}
+
+void dleyna_white_list_add_entries(GVariant *entries, gboolean notify)
+{
+ GVariantIter viter;
+ gchar *entry;
+
+ if ((entries != NULL) && (g_wl_cb.wl != NULL)) {
+ (void) g_variant_iter_init(&viter, entries);
+
+ while (g_variant_iter_next(&viter, "&s", &entry))
+ (void) gupnp_white_list_add_entry(g_wl_cb.wl, entry);
+
+#if DLEYNA_LOG_LEVEL & DLEYNA_LOG_LEVEL_DEBUG
+ prv_dump_wl_entries(g_wl_cb.wl);
+#endif
+
+ if (notify && (g_wl_cb.cb_entries != NULL))
+ g_wl_cb.cb_entries(g_wl_cb.user_data);
+ }
+}
+
+void dleyna_white_list_remove_entries(GVariant *entries, gboolean notify)
+{
+ GVariantIter viter;
+ gchar *entry;
+
+ if ((entries != NULL) && (g_wl_cb.wl != NULL)) {
+ (void) g_variant_iter_init(&viter, entries);
+
+ while (g_variant_iter_next(&viter, "&s", &entry))
+ (void) gupnp_white_list_remove_entry(g_wl_cb.wl, entry);
+
+#if DLEYNA_LOG_LEVEL & DLEYNA_LOG_LEVEL_DEBUG
+ prv_dump_wl_entries(g_wl_cb.wl);
+#endif
+
+ if (notify && (g_wl_cb.cb_entries != NULL))
+ g_wl_cb.cb_entries(g_wl_cb.user_data);
+ }
+}
+
+void dleyna_white_list_clear(gboolean notify)
+{
+ if (g_wl_cb.wl != NULL) {
+ gupnp_white_list_clear(g_wl_cb.wl);
+
+#if DLEYNA_LOG_LEVEL & DLEYNA_LOG_LEVEL_DEBUG
+ prv_dump_wl_entries(g_wl_cb.wl);
+#endif
+
+ if (notify && (g_wl_cb.cb_entries != NULL))
+ g_wl_cb.cb_entries(g_wl_cb.user_data);
+ }
+}
+
+void dleyna_white_list_set_info(dleyna_white_list_t *data)
+{
+ if (data != NULL)
+ memcpy(&g_wl_cb, data, sizeof(dleyna_white_list_t));
+ else
+ memset(&g_wl_cb, 0, sizeof(dleyna_white_list_t));
+}
diff --git a/libdleyna/core/white-list.h b/libdleyna/core/white-list.h
new file mode 100644
index 0000000..a0e760e
--- /dev/null
+++ b/libdleyna/core/white-list.h
@@ -0,0 +1,50 @@
+/*
+ * dLeyna
+ *
+ * Copyright (C) 2013 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU Lesser General Public License,
+ * version 2.1, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Ludovic Ferrandis <ludovic.ferrandis@intel.com>
+ *
+ */
+
+#ifndef DLEYNA_WHITE_LIST_H__
+#define DLEYNA_WHITE_LIST_H__
+
+#include <glib.h>
+#include <libgupnp/gupnp-white-list.h>
+
+typedef void (*dleyna_white_list_notify_t)(gpointer user_data);
+
+typedef struct dleyna_white_list_t_ dleyna_white_list_t;
+
+struct dleyna_white_list_t_ {
+ GUPnPWhiteList *wl;
+ dleyna_white_list_notify_t cb_enabled;
+ dleyna_white_list_notify_t cb_entries;
+ gpointer user_data;
+};
+
+void dleyna_white_list_enable(gboolean enabled, gboolean notify);
+
+void dleyna_white_list_add_entries(GVariant *entries, gboolean notify);
+
+void dleyna_white_list_remove_entries(GVariant *entries, gboolean notify);
+
+void dleyna_white_list_clear(gboolean notify);
+
+void dleyna_white_list_set_info(dleyna_white_list_t *data);
+
+#endif /* DLEYNA_WHITE_LIST_H__ */