[network-manager-openconnect/th/logging-bgo767733: 4/6] src: make logging level configurable via NM_VPN_LOG_LEVEL
- From: Thomas Haller <thaller src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [network-manager-openconnect/th/logging-bgo767733: 4/6] src: make logging level configurable via NM_VPN_LOG_LEVEL
- Date: Thu, 23 Jun 2016 14:47:21 +0000 (UTC)
commit eb32126b88fea4b1b4960c7538464a553eb9f547
Author: Thomas Haller <thaller redhat com>
Date: Thu Jun 16 18:22:17 2016 +0200
src: make logging level configurable via NM_VPN_LOG_LEVEL
NetworkManager supports enabling logging for VPN plugins via
$ nmcli general logging level KEEP domains VPN_PLUGIN:TRACE
In that case, it will spawn the VPN plugin with NM_VPN_LOG_LEVEL
set to a syslog level. Use that, to enable verbose logging of the
nm-openconnect and openconnect service.
po/POTFILES.in | 1 +
shared/Makefile.am | 2 +
shared/nm-utils/nm-shared-utils.c | 239 +++++++++++++++++++++++++++++++++++++
shared/nm-utils/nm-shared-utils.h | 66 ++++++++++
src/Makefile.am | 2 +
src/nm-openconnect-service.c | 15 ++-
6 files changed, 322 insertions(+), 3 deletions(-)
---
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 948e971..f645d26 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -7,5 +7,6 @@ properties/auth-helpers.c
properties/nm-openconnect-editor-plugin.c
properties/nm-openconnect-editor.c
src/nm-openconnect-service.c
+shared/nm-utils/nm-shared-utils.c
shared/nm-utils/nm-vpn-plugin-utils.c
[type: gettext/glade]properties/nm-openconnect-dialog.ui
diff --git a/shared/Makefile.am b/shared/Makefile.am
index 3f7ee53..44777a7 100644
--- a/shared/Makefile.am
+++ b/shared/Makefile.am
@@ -3,6 +3,8 @@ EXTRA_DIST = \
nm-utils/gsystem-local-alloc.h \
nm-utils/nm-glib.h \
nm-utils/nm-macros-internal.h \
+ nm-utils/nm-shared-utils.c \
+ nm-utils/nm-shared-utils.h \
nm-utils/nm-vpn-editor-plugin-call.h \
nm-utils/nm-vpn-plugin-macros.h \
nm-utils/nm-vpn-plugin-utils.c \
diff --git a/shared/nm-utils/nm-shared-utils.c b/shared/nm-utils/nm-shared-utils.c
new file mode 100644
index 0000000..38f6529
--- /dev/null
+++ b/shared/nm-utils/nm-shared-utils.c
@@ -0,0 +1,239 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager -- Network link manager
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that 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 library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA.
+ *
+ * (C) Copyright 2016 Red Hat, Inc.
+ */
+
+#include "nm-default.h"
+
+#include "nm-shared-utils.h"
+
+#include <errno.h>
+
+/*****************************************************************************/
+
+/* _nm_utils_ascii_str_to_int64:
+ *
+ * A wrapper for g_ascii_strtoll, that checks whether the whole string
+ * can be successfully converted to a number and is within a given
+ * range. On any error, @fallback will be returned and %errno will be set
+ * to a non-zero value. On success, %errno will be set to zero, check %errno
+ * for errors. Any trailing or leading (ascii) white space is ignored and the
+ * functions is locale independent.
+ *
+ * The function is guaranteed to return a value between @min and @max
+ * (inclusive) or @fallback. Also, the parsing is rather strict, it does
+ * not allow for any unrecognized characters, except leading and trailing
+ * white space.
+ **/
+gint64
+_nm_utils_ascii_str_to_int64 (const char *str, guint base, gint64 min, gint64 max, gint64 fallback)
+{
+ gint64 v;
+ char *s = NULL;
+
+ if (str) {
+ while (g_ascii_isspace (str[0]))
+ str++;
+ }
+ if (!str || !str[0]) {
+ errno = EINVAL;
+ return fallback;
+ }
+
+ errno = 0;
+ v = g_ascii_strtoll (str, &s, base);
+
+ if (errno != 0)
+ return fallback;
+ if (s[0] != '\0') {
+ while (g_ascii_isspace (s[0]))
+ s++;
+ if (s[0] != '\0') {
+ errno = EINVAL;
+ return fallback;
+ }
+ }
+ if (v > max || v < min) {
+ errno = ERANGE;
+ return fallback;
+ }
+
+ return v;
+}
+
+/*****************************************************************************/
+
+gint
+_nm_utils_ascii_str_to_bool (const char *str,
+ gint default_value)
+{
+ gsize len;
+ char *s = NULL;
+
+ if (!str)
+ return default_value;
+
+ while (str[0] && g_ascii_isspace (str[0]))
+ str++;
+
+ if (!str[0])
+ return default_value;
+
+ len = strlen (str);
+ if (g_ascii_isspace (str[len - 1])) {
+ s = g_strdup (str);
+ g_strchomp (s);
+ str = s;
+ }
+
+ if (!g_ascii_strcasecmp (str, "true") || !g_ascii_strcasecmp (str, "yes") || !g_ascii_strcasecmp
(str, "on") || !g_ascii_strcasecmp (str, "1"))
+ default_value = TRUE;
+ else if (!g_ascii_strcasecmp (str, "false") || !g_ascii_strcasecmp (str, "no") || !g_ascii_strcasecmp
(str, "off") || !g_ascii_strcasecmp (str, "0"))
+ default_value = FALSE;
+ if (s)
+ g_free (s);
+ return default_value;
+}
+
+/*****************************************************************************/
+
+G_DEFINE_QUARK (nm-utils-error-quark, nm_utils_error)
+
+void
+nm_utils_error_set_cancelled (GError **error,
+ gboolean is_disposing,
+ const char *instance_name)
+{
+ if (is_disposing) {
+ g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_CANCELLED_DISPOSING,
+ "Disposing %s instance",
+ instance_name && *instance_name ? instance_name : "source");
+ } else {
+ g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_CANCELLED,
+ "Request cancelled");
+ }
+}
+
+gboolean
+nm_utils_error_is_cancelled (GError *error,
+ gboolean consider_is_disposing)
+{
+ if (error) {
+ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ return TRUE;
+ if ( consider_is_disposing
+ && g_error_matches (error, NM_UTILS_ERROR, NM_UTILS_ERROR_CANCELLED_DISPOSING))
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/*****************************************************************************/
+
+/**
+ * nm_g_object_set_property:
+ * @object: the target object
+ * @property_name: the property name
+ * @value: the #GValue to set
+ * @error: (allow-none): optional error argument
+ *
+ * A reimplementation of g_object_set_property(), but instead
+ * returning an error instead of logging a warning. All g_object_set*()
+ * versions in glib require you to not pass invalid types or they will
+ * log a g_warning() -- without reporting an error. We don't want that,
+ * so we need to hack error checking around it.
+ *
+ * Returns: whether the value was successfully set.
+ */
+gboolean
+nm_g_object_set_property (GObject *object,
+ const gchar *property_name,
+ const GValue *value,
+ GError **error)
+{
+ GParamSpec *pspec;
+ nm_auto_unset_gvalue GValue tmp_value = G_VALUE_INIT;
+ GObjectClass *klass;
+
+ g_return_val_if_fail (G_IS_OBJECT (object), FALSE);
+ g_return_val_if_fail (property_name != NULL, FALSE);
+ g_return_val_if_fail (G_IS_VALUE (value), FALSE);
+ g_return_val_if_fail (!error || !*error, FALSE);
+
+ /* g_object_class_find_property() does g_param_spec_get_redirect_target(),
+ * where we differ from a plain g_object_set_property(). */
+ pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (object), property_name);
+
+ if (!pspec) {
+ g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN,
+ _("object class '%s' has no property named '%s'"),
+ G_OBJECT_TYPE_NAME (object),
+ property_name);
+ return FALSE;
+ }
+ if (!(pspec->flags & G_PARAM_WRITABLE)) {
+ g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN,
+ _("property '%s' of object class '%s' is not writable"),
+ pspec->name,
+ G_OBJECT_TYPE_NAME (object));
+ return FALSE;
+ }
+ if ((pspec->flags & G_PARAM_CONSTRUCT_ONLY)) {
+ g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN,
+ _("construct property \"%s\" for object '%s' can't be set after construction"),
+ pspec->name, G_OBJECT_TYPE_NAME (object));
+ return FALSE;
+ }
+
+ klass = g_type_class_peek (pspec->owner_type);
+ if (klass == NULL) {
+ g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN,
+ _("'%s::%s' is not a valid property name; '%s' is not a GObject subtype"),
+ g_type_name (pspec->owner_type), pspec->name, g_type_name (pspec->owner_type));
+ return FALSE;
+ }
+
+ /* provide a copy to work from, convert (if necessary) and validate */
+ g_value_init (&tmp_value, pspec->value_type);
+ if (!g_value_transform (value, &tmp_value)) {
+ g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN,
+ _("unable to set property '%s' of type '%s' from value of type '%s'"),
+ pspec->name,
+ g_type_name (pspec->value_type),
+ G_VALUE_TYPE_NAME (value));
+ return FALSE;
+ }
+ if ( g_param_value_validate (pspec, &tmp_value)
+ && !(pspec->flags & G_PARAM_LAX_VALIDATION)) {
+ gs_free char *contents = g_strdup_value_contents (value);
+
+ g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN,
+ _("value \"%s\" of type '%s' is invalid or out of range for property '%s' of
type '%s'"),
+ contents,
+ G_VALUE_TYPE_NAME (value),
+ pspec->name,
+ g_type_name (pspec->value_type));
+ return FALSE;
+ }
+
+ g_object_set_property (object, property_name, &tmp_value);
+ return TRUE;
+}
+
+/*****************************************************************************/
diff --git a/shared/nm-utils/nm-shared-utils.h b/shared/nm-utils/nm-shared-utils.h
new file mode 100644
index 0000000..cfa8f99
--- /dev/null
+++ b/shared/nm-utils/nm-shared-utils.h
@@ -0,0 +1,66 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager -- Network link manager
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that 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 library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA.
+ *
+ * (C) Copyright 2016 Red Hat, Inc.
+ */
+
+#ifndef __NM_SHARED_UTILS_H__
+#define __NM_SHARED_UTILS_H__
+
+/******************************************************************************/
+
+gint64 _nm_utils_ascii_str_to_int64 (const char *str, guint base, gint64 min, gint64 max, gint64 fallback);
+
+gint _nm_utils_ascii_str_to_bool (const char *str,
+ gint default_value);
+
+/******************************************************************************/
+
+/**
+ * NMUtilsError:
+ * @NM_UTILS_ERROR_UNKNOWN: unknown or unclassified error
+ * @NM_UTILS_ERROR_CANCELLED_DISPOSING: when disposing an object that has
+ * pending aynchronous operations, the operation is cancelled with this
+ * error reason. Depending on the usage, this might indicate a bug because
+ * usually the target object should stay alive as long as there are pending
+ * operations.
+ */
+typedef enum {
+ NM_UTILS_ERROR_UNKNOWN = 0, /*< nick=Unknown >*/
+ NM_UTILS_ERROR_CANCELLED_DISPOSING, /*< nick=CancelledDisposing >*/
+} NMUtilsError;
+
+#define NM_UTILS_ERROR (nm_utils_error_quark ())
+GQuark nm_utils_error_quark (void);
+
+void nm_utils_error_set_cancelled (GError **error,
+ gboolean is_disposing,
+ const char *instance_name);
+gboolean nm_utils_error_is_cancelled (GError *error,
+ gboolean consider_is_disposing);
+
+/******************************************************************************/
+
+gboolean nm_g_object_set_property (GObject *object,
+ const gchar *property_name,
+ const GValue *value,
+ GError **error);
+
+/******************************************************************************/
+
+#endif /* __NM_SHARED_UTILS_H__ */
diff --git a/src/Makefile.am b/src/Makefile.am
index 02fd140..5fc94fa 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -19,6 +19,8 @@ AM_CPPFLAGS = \
###############################################################################
nm_openconnect_service_SOURCES = \
+ $(top_srcdir)/shared/nm-utils/nm-shared-utils.c \
+ $(top_srcdir)/shared/nm-utils/nm-shared-utils.h \
nm-openconnect-service.c \
nm-openconnect-service.h \
$(NULL)
diff --git a/src/nm-openconnect-service.c b/src/nm-openconnect-service.c
index 93bcb69..2acdf23 100644
--- a/src/nm-openconnect-service.c
+++ b/src/nm-openconnect-service.c
@@ -42,6 +42,7 @@
#include <grp.h>
#include <locale.h>
+#include "nm-utils/nm-shared-utils.h"
#include "nm-utils/nm-vpn-plugin-macros.h"
#if !defined(DIST_VERSION)
@@ -110,6 +111,7 @@ static struct {
uid_t tun_owner;
gid_t tun_group;
gboolean debug;
+ int log_level;
GMainLoop *loop;
} gl/*obal*/;
@@ -117,7 +119,7 @@ static struct {
#define _NMLOG(level, ...) \
G_STMT_START { \
- if ((level) > LOG_INFO || gl.debug) { \
+ if (gl.log_level >= (level)) { \
g_print ("nm-openconnect[%ld] %-7s " _NM_UTILS_MACRO_FIRST (__VA_ARGS__) "\n", \
(long) getpid (), \
nm_utils_syslog_to_str (level) \
@@ -128,7 +130,7 @@ static struct {
static gboolean
_LOGD_enabled (void)
{
- return gl.debug;
+ return gl.log_level >= LOG_INFO;
}
#define _LOGD(...) _NMLOG(LOG_INFO, __VA_ARGS__)
@@ -481,8 +483,11 @@ nm_openconnect_start_openconnect_binary (NMOpenconnectPlugin *plugin,
g_ptr_array_add (openconnect_argv, (gpointer) props_vpn_gw);
- if (gl.debug)
+ if (gl.log_level >= LOG_INFO) {
g_ptr_array_add (openconnect_argv, (gpointer) "--verbose");
+ if (gl.log_level >= LOG_DEBUG)
+ g_ptr_array_add (openconnect_argv, (gpointer) "--verbose");
+ }
g_ptr_array_add (openconnect_argv, NULL);
@@ -715,6 +720,10 @@ int main (int argc, char *argv[])
if (getenv ("OPENCONNECT_DEBUG"))
gl.debug = TRUE;
+ gl.log_level = _nm_utils_ascii_str_to_int64 (getenv ("NM_VPN_LOG_LEVEL"),
+ 10, 0, LOG_DEBUG,
+ gl.debug ? LOG_INFO : LOG_NOTICE);
+
_LOGD ("nm-openconnect-service (version " DIST_VERSION ") starting...");
if (system ("/sbin/modprobe tun") == -1)
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]