summary refs log tree commit diff
path: root/src/nm-logging.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nm-logging.c')
-rw-r--r--src/nm-logging.c1536
1 files changed, 774 insertions, 762 deletions
diff --git a/src/nm-logging.c b/src/nm-logging.c
index 3368c5db..11affbfb 100644
--- a/src/nm-logging.c
+++ b/src/nm-logging.c
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0+
+/* SPDX-License-Identifier: GPL-2.0+ */
 /*
  * Copyright (C) 2006 - 2012 Red Hat, Inc.
  * Copyright (C) 2006 - 2008 Novell, Inc.
@@ -18,8 +18,8 @@
 #include <strings.h>
 
 #if SYSTEMD_JOURNAL
-#define SD_JOURNAL_SUPPRESS_LOCATION
-#include <systemd/sd-journal.h>
+    #define SD_JOURNAL_SUPPRESS_LOCATION
+    #include <systemd/sd-journal.h>
 #endif
 
 #include "nm-glib-aux/nm-logging-base.h"
@@ -54,17 +54,17 @@
 
 /*****************************************************************************/
 
-G_STATIC_ASSERT (LOG_EMERG   == 0);
-G_STATIC_ASSERT (LOG_ALERT   == 1);
-G_STATIC_ASSERT (LOG_CRIT    == 2);
-G_STATIC_ASSERT (LOG_ERR     == 3);
-G_STATIC_ASSERT (LOG_WARNING == 4);
-G_STATIC_ASSERT (LOG_NOTICE  == 5);
-G_STATIC_ASSERT (LOG_INFO    == 6);
-G_STATIC_ASSERT (LOG_DEBUG   == 7);
+G_STATIC_ASSERT(LOG_EMERG == 0);
+G_STATIC_ASSERT(LOG_ALERT == 1);
+G_STATIC_ASSERT(LOG_CRIT == 2);
+G_STATIC_ASSERT(LOG_ERR == 3);
+G_STATIC_ASSERT(LOG_WARNING == 4);
+G_STATIC_ASSERT(LOG_NOTICE == 5);
+G_STATIC_ASSERT(LOG_INFO == 6);
+G_STATIC_ASSERT(LOG_DEBUG == 7);
 
 /* We have more then 32 logging domains. Assert that it compiles to a 64 bit sized enum */
-G_STATIC_ASSERT (sizeof (NMLogDomain) >= sizeof (guint64));
+G_STATIC_ASSERT(sizeof(NMLogDomain) >= sizeof(guint64));
 
 /* Combined domains */
 #define LOGD_ALL_STRING     "ALL"
@@ -75,478 +75,473 @@ G_STATIC_ASSERT (sizeof (NMLogDomain) >= sizeof (guint64));
 /*****************************************************************************/
 
 typedef enum {
-	LOG_BACKEND_GLIB,
-	LOG_BACKEND_SYSLOG,
-	LOG_BACKEND_JOURNAL,
+    LOG_BACKEND_GLIB,
+    LOG_BACKEND_SYSLOG,
+    LOG_BACKEND_JOURNAL,
 } LogBackend;
 
 typedef struct {
-	NMLogDomain num;
-	const char *name;
+    NMLogDomain num;
+    const char *name;
 } LogDesc;
 
 typedef struct {
-	char *logging_domains_to_string;
+    char *logging_domains_to_string;
 } GlobalMain;
 
 typedef struct {
-	NMLogLevel log_level;
-	bool uses_syslog:1;
-	bool init_pre_done:1;
-	bool init_done:1;
-	bool debug_stderr:1;
-	const char *prefix;
-	const char *syslog_identifier;
-
-	/* before we setup syslog (during start), the backend defaults to GLIB, meaning:
-	 * we use g_log() for all logging. At that point, the application is not yet supposed
-	 * to do any logging and doing so indicates a bug.
-	 *
-	 * Afterwards, the backend is either SYSLOG or JOURNAL. From that point, also
-	 * g_log() is redirected to this backend via a logging handler. */
-	LogBackend log_backend;
+    NMLogLevel  log_level;
+    bool        uses_syslog : 1;
+    bool        init_pre_done : 1;
+    bool        init_done : 1;
+    bool        debug_stderr : 1;
+    const char *prefix;
+    const char *syslog_identifier;
+
+    /* before we setup syslog (during start), the backend defaults to GLIB, meaning:
+     * we use g_log() for all logging. At that point, the application is not yet supposed
+     * to do any logging and doing so indicates a bug.
+     *
+     * Afterwards, the backend is either SYSLOG or JOURNAL. From that point, also
+     * g_log() is redirected to this backend via a logging handler. */
+    LogBackend log_backend;
 } Global;
 
 /*****************************************************************************/
 
-G_LOCK_DEFINE_STATIC (log);
+G_LOCK_DEFINE_STATIC(log);
 
 /* This data must only be accessed from the main-thread (and as
  * such does not need any lock). */
-static GlobalMain gl_main = { };
+static GlobalMain gl_main = {};
 
 static union {
-	/* a union with an immutable and a mutable alias for the Global.
-	 * Since nm-logging must be thread-safe, we must take care at which
-	 * places we only read value ("imm") and where we modify them ("mut"). */
-	Global       mut;
-	const Global imm;
+    /* a union with an immutable and a mutable alias for the Global.
+     * Since nm-logging must be thread-safe, we must take care at which
+     * places we only read value ("imm") and where we modify them ("mut"). */
+    Global       mut;
+    const Global imm;
 } gl = {
-	.imm = {
-		/* nm_logging_setup ("INFO", LOGD_DEFAULT_STRING, NULL, NULL); */
-		.log_level = LOGL_INFO,
-		.log_backend = LOG_BACKEND_GLIB,
-		.syslog_identifier = "SYSLOG_IDENTIFIER="G_LOG_DOMAIN,
-		.prefix = "",
-	},
+    .imm =
+        {
+            /* nm_logging_setup ("INFO", LOGD_DEFAULT_STRING, NULL, NULL); */
+            .log_level         = LOGL_INFO,
+            .log_backend       = LOG_BACKEND_GLIB,
+            .syslog_identifier = "SYSLOG_IDENTIFIER=" G_LOG_DOMAIN,
+            .prefix            = "",
+        },
 };
 
 NMLogDomain _nm_logging_enabled_state[_LOGL_N_REAL] = {
-	/* nm_logging_setup ("INFO", LOGD_DEFAULT_STRING, NULL, NULL);
-	 *
-	 * Note: LOGD_VPN_PLUGIN is special and must be disabled for
-	 * DEBUG and TRACE levels. */
-	[LOGL_INFO] = LOGD_DEFAULT,
-	[LOGL_WARN] = LOGD_DEFAULT,
-	[LOGL_ERR]  = LOGD_DEFAULT,
+    /* nm_logging_setup ("INFO", LOGD_DEFAULT_STRING, NULL, NULL);
+     *
+     * Note: LOGD_VPN_PLUGIN is special and must be disabled for
+     * DEBUG and TRACE levels. */
+    [LOGL_INFO] = LOGD_DEFAULT,
+    [LOGL_WARN] = LOGD_DEFAULT,
+    [LOGL_ERR]  = LOGD_DEFAULT,
 };
 
 /*****************************************************************************/
 
 static const LogDesc domain_desc[] = {
-	{ LOGD_PLATFORM,  "PLATFORM" },
-	{ LOGD_RFKILL,    "RFKILL" },
-	{ LOGD_ETHER,     "ETHER" },
-	{ LOGD_WIFI,      "WIFI" },
-	{ LOGD_BT,        "BT" },
-	{ LOGD_MB,        "MB" },
-	{ LOGD_DHCP4,     "DHCP4" },
-	{ LOGD_DHCP6,     "DHCP6" },
-	{ LOGD_PPP,       "PPP" },
-	{ LOGD_WIFI_SCAN, "WIFI_SCAN" },
-	{ LOGD_IP4,       "IP4" },
-	{ LOGD_IP6,       "IP6" },
-	{ LOGD_AUTOIP4,   "AUTOIP4" },
-	{ LOGD_DNS,       "DNS" },
-	{ LOGD_VPN,       "VPN" },
-	{ LOGD_SHARING,   "SHARING" },
-	{ LOGD_SUPPLICANT,"SUPPLICANT" },
-	{ LOGD_AGENTS,    "AGENTS" },
-	{ LOGD_SETTINGS,  "SETTINGS" },
-	{ LOGD_SUSPEND,   "SUSPEND" },
-	{ LOGD_CORE,      "CORE" },
-	{ LOGD_DEVICE,    "DEVICE" },
-	{ LOGD_OLPC,      "OLPC" },
-	{ LOGD_INFINIBAND,"INFINIBAND" },
-	{ LOGD_FIREWALL,  "FIREWALL" },
-	{ LOGD_ADSL,      "ADSL" },
-	{ LOGD_BOND,      "BOND" },
-	{ LOGD_VLAN,      "VLAN" },
-	{ LOGD_BRIDGE,    "BRIDGE" },
-	{ LOGD_DBUS_PROPS,"DBUS_PROPS" },
-	{ LOGD_TEAM,      "TEAM" },
-	{ LOGD_CONCHECK,  "CONCHECK" },
-	{ LOGD_DCB,       "DCB" },
-	{ LOGD_DISPATCH,  "DISPATCH" },
-	{ LOGD_AUDIT,     "AUDIT" },
-	{ LOGD_SYSTEMD,   "SYSTEMD" },
-	{ LOGD_VPN_PLUGIN,"VPN_PLUGIN" },
-	{ LOGD_PROXY,     "PROXY" },
-	{ 0 },
+    {LOGD_PLATFORM, "PLATFORM"},
+    {LOGD_RFKILL, "RFKILL"},
+    {LOGD_ETHER, "ETHER"},
+    {LOGD_WIFI, "WIFI"},
+    {LOGD_BT, "BT"},
+    {LOGD_MB, "MB"},
+    {LOGD_DHCP4, "DHCP4"},
+    {LOGD_DHCP6, "DHCP6"},
+    {LOGD_PPP, "PPP"},
+    {LOGD_WIFI_SCAN, "WIFI_SCAN"},
+    {LOGD_IP4, "IP4"},
+    {LOGD_IP6, "IP6"},
+    {LOGD_AUTOIP4, "AUTOIP4"},
+    {LOGD_DNS, "DNS"},
+    {LOGD_VPN, "VPN"},
+    {LOGD_SHARING, "SHARING"},
+    {LOGD_SUPPLICANT, "SUPPLICANT"},
+    {LOGD_AGENTS, "AGENTS"},
+    {LOGD_SETTINGS, "SETTINGS"},
+    {LOGD_SUSPEND, "SUSPEND"},
+    {LOGD_CORE, "CORE"},
+    {LOGD_DEVICE, "DEVICE"},
+    {LOGD_OLPC, "OLPC"},
+    {LOGD_INFINIBAND, "INFINIBAND"},
+    {LOGD_FIREWALL, "FIREWALL"},
+    {LOGD_ADSL, "ADSL"},
+    {LOGD_BOND, "BOND"},
+    {LOGD_VLAN, "VLAN"},
+    {LOGD_BRIDGE, "BRIDGE"},
+    {LOGD_DBUS_PROPS, "DBUS_PROPS"},
+    {LOGD_TEAM, "TEAM"},
+    {LOGD_CONCHECK, "CONCHECK"},
+    {LOGD_DCB, "DCB"},
+    {LOGD_DISPATCH, "DISPATCH"},
+    {LOGD_AUDIT, "AUDIT"},
+    {LOGD_SYSTEMD, "SYSTEMD"},
+    {LOGD_VPN_PLUGIN, "VPN_PLUGIN"},
+    {LOGD_PROXY, "PROXY"},
+    {0},
 };
 
 /*****************************************************************************/
 
-static char *_domains_to_string (gboolean include_level_override,
-                                 NMLogLevel log_level,
-                                 const NMLogDomain log_state[static _LOGL_N_REAL]);
+static char *_domains_to_string(gboolean          include_level_override,
+                                NMLogLevel        log_level,
+                                const NMLogDomain log_state[static _LOGL_N_REAL]);
 
 /*****************************************************************************/
 
 static gboolean
-_syslog_identifier_valid_domain (const char *domain)
+_syslog_identifier_valid_domain(const char *domain)
 {
-	char c;
-
-	if (!domain || !domain[0])
-		return FALSE;
-
-	/* we pass the syslog identifier as format string. No funny stuff. */
-
-	for (; (c = domain[0]); domain++) {
-		if (   (c >= 'a' && c <= 'z')
-		    || (c >= 'A' && c <= 'Z')
-		    || (c >= '0' && c <= '9')
-		    || NM_IN_SET (c, '-', '_'))
-			continue;
-		return FALSE;
-	}
-	return TRUE;
+    char c;
+
+    if (!domain || !domain[0])
+        return FALSE;
+
+    /* we pass the syslog identifier as format string. No funny stuff. */
+
+    for (; (c = domain[0]); domain++) {
+        if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9')
+            || NM_IN_SET(c, '-', '_'))
+            continue;
+        return FALSE;
+    }
+    return TRUE;
 }
 
 static gboolean
-_syslog_identifier_assert (const char *syslog_identifier)
+_syslog_identifier_assert(const char *syslog_identifier)
 {
-	g_assert (syslog_identifier);
-	g_assert (g_str_has_prefix (syslog_identifier, "SYSLOG_IDENTIFIER="));
-	g_assert (_syslog_identifier_valid_domain (&syslog_identifier[NM_STRLEN ("SYSLOG_IDENTIFIER=")]));
-	return TRUE;
+    g_assert(syslog_identifier);
+    g_assert(g_str_has_prefix(syslog_identifier, "SYSLOG_IDENTIFIER="));
+    g_assert(_syslog_identifier_valid_domain(&syslog_identifier[NM_STRLEN("SYSLOG_IDENTIFIER=")]));
+    return TRUE;
 }
 
 static const char *
-syslog_identifier_domain (const char *syslog_identifier)
+syslog_identifier_domain(const char *syslog_identifier)
 {
-	nm_assert (_syslog_identifier_assert (syslog_identifier));
-	return &syslog_identifier[NM_STRLEN ("SYSLOG_IDENTIFIER=")];
+    nm_assert(_syslog_identifier_assert(syslog_identifier));
+    return &syslog_identifier[NM_STRLEN("SYSLOG_IDENTIFIER=")];
 }
 
 #if SYSTEMD_JOURNAL
 static const char *
-syslog_identifier_full (const char *syslog_identifier)
+syslog_identifier_full(const char *syslog_identifier)
 {
-	nm_assert (_syslog_identifier_assert (syslog_identifier));
-	return &syslog_identifier[0];
+    nm_assert(_syslog_identifier_assert(syslog_identifier));
+    return &syslog_identifier[0];
 }
 #endif
 
 /*****************************************************************************/
 
 static gboolean
-match_log_level (const char  *level,
-                 NMLogLevel  *out_level,
-                 GError     **error)
+match_log_level(const char *level, NMLogLevel *out_level, GError **error)
 {
-	if (_nm_log_parse_level (level, out_level))
-		return TRUE;
-
-	g_set_error (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_UNKNOWN_LOG_LEVEL,
-	             _("Unknown log level '%s'"), level);
-	return FALSE;
+    if (_nm_log_parse_level(level, out_level))
+        return TRUE;
+
+    g_set_error(error,
+                NM_MANAGER_ERROR,
+                NM_MANAGER_ERROR_UNKNOWN_LOG_LEVEL,
+                _("Unknown log level '%s'"),
+                level);
+    return FALSE;
 }
 
 gboolean
-nm_logging_setup (const char  *level,
-                  const char  *domains,
-                  char       **bad_domains,
-                  GError     **error)
+nm_logging_setup(const char *level, const char *domains, char **bad_domains, GError **error)
 {
-	GString *unrecognized = NULL;
-	NMLogDomain cur_log_state[_LOGL_N_REAL];
-	NMLogDomain new_log_state[_LOGL_N_REAL];
-	NMLogLevel cur_log_level;
-	NMLogLevel new_log_level;
-	gs_free const char **domains_v = NULL;
-	gsize i_d;
-	int i;
-	gboolean had_platform_debug;
-	gs_free char *domains_free = NULL;
-
-	NM_ASSERT_ON_MAIN_THREAD ();
-
-	g_return_val_if_fail (!bad_domains || !*bad_domains, FALSE);
-	g_return_val_if_fail (!error || !*error, FALSE);
-
-	cur_log_level = gl.imm.log_level;
-	memcpy (cur_log_state, _nm_logging_enabled_state, sizeof (cur_log_state));
-
-	new_log_level = cur_log_level;
-
-	if (!domains || !*domains) {
-		domains_free = _domains_to_string (FALSE,
-		                                   cur_log_level,
-		                                   cur_log_state);
-		domains = domains_free;
-	}
-
-	for (i = 0; i < G_N_ELEMENTS (new_log_state); i++)
-		new_log_state[i] = 0;
-
-	if (level && *level) {
-		if (!match_log_level (level, &new_log_level, error))
-			return FALSE;
-		if (new_log_level == _LOGL_KEEP) {
-			new_log_level = cur_log_level;
-			for (i = 0; i < G_N_ELEMENTS (new_log_state); i++)
-				new_log_state[i] = cur_log_state[i];
-		}
-	}
-
-	domains_v = nm_utils_strsplit_set (domains, ", ");
-	for (i_d = 0; domains_v && domains_v[i_d]; i_d++) {
-		const char *s = domains_v[i_d];
-		const char *p;
-		const LogDesc *diter;
-		NMLogLevel domain_log_level;
-		NMLogDomain bits;
-
-		/* LOGD_VPN_PLUGIN is protected, that is, when setting ALL or DEFAULT,
-		 * it does not enable the verbose levels DEBUG and TRACE, because that
-		 * may expose sensitive data. */
-		NMLogDomain protect = LOGD_NONE;
-
-		p = strchr (s, ':');
-		if (p) {
-			*((char *) p) = '\0';
-			if (!match_log_level (p + 1, &domain_log_level, error))
-				return FALSE;
-		} else
-			domain_log_level = new_log_level;
-
-		bits = 0;
-
-		if (domains_free) {
-			/* The caller didn't provide any domains to set (`nmcli general logging level DEBUG`).
-			 * We reset all domains that were previously set, but we still want to protect
-			 * VPN_PLUGIN domain. */
-			protect = LOGD_VPN_PLUGIN;
-		}
-
-		/* Check for combined domains */
-		if (!g_ascii_strcasecmp (s, LOGD_ALL_STRING)) {
-			bits = LOGD_ALL;
-			protect = LOGD_VPN_PLUGIN;
-		} else if (!g_ascii_strcasecmp (s, LOGD_DEFAULT_STRING)) {
-			bits = LOGD_DEFAULT;
-			protect = LOGD_VPN_PLUGIN;
-		} else if (!g_ascii_strcasecmp (s, LOGD_DHCP_STRING))
-			bits = LOGD_DHCP;
-		else if (!g_ascii_strcasecmp (s, LOGD_IP_STRING))
-			bits = LOGD_IP;
-
-		/* Check for compatibility domains */
-		else if (!g_ascii_strcasecmp (s, "HW"))
-			bits = LOGD_PLATFORM;
-		else if (!g_ascii_strcasecmp (s, "WIMAX"))
-			continue;
-
-		else {
-			for (diter = &domain_desc[0]; diter->name; diter++) {
-				if (!g_ascii_strcasecmp (diter->name, s)) {
-					bits = diter->num;
-					break;
-				}
-			}
-
-			if (!bits) {
-				if (!bad_domains) {
-					g_set_error (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_UNKNOWN_LOG_DOMAIN,
-					             _("Unknown log domain '%s'"), s);
-					return FALSE;
-				}
-
-				if (unrecognized)
-					g_string_append (unrecognized, ", ");
-				else
-					unrecognized = g_string_new (NULL);
-				g_string_append (unrecognized, s);
-				continue;
-			}
-		}
-
-		if (domain_log_level == _LOGL_KEEP) {
-			for (i = 0; i < G_N_ELEMENTS (new_log_state); i++)
-				new_log_state[i] = (new_log_state[i] & ~bits) | (cur_log_state[i] & bits);
-		} else {
-			for (i = 0; i < G_N_ELEMENTS (new_log_state); i++) {
-				if (i < domain_log_level)
-					new_log_state[i] &= ~bits;
-				else {
-					new_log_state[i] |= bits;
-					if (   (protect & bits)
-					    && i < LOGL_INFO)
-						new_log_state[i] &= ~protect;
-				}
-			}
-		}
-	}
-
-	nm_clear_g_free (&gl_main.logging_domains_to_string);
-
-	had_platform_debug = _nm_logging_enabled_lockfree (LOGL_DEBUG, LOGD_PLATFORM);
-
-	G_LOCK (log);
-
-	gl.mut.log_level = new_log_level;
-	for (i = 0; i < G_N_ELEMENTS (new_log_state); i++)
-		_nm_logging_enabled_state[i] = new_log_state[i];
-
-	G_UNLOCK (log);
-
-	if (   had_platform_debug
-	    && !_nm_logging_enabled_lockfree (LOGL_DEBUG, LOGD_PLATFORM)) {
-		/* when debug logging is enabled, platform will cache all access to
-		 * sysctl. When the user disables debug-logging, we want to clear that
-		 * cache right away. */
-		_nm_logging_clear_platform_logging_cache ();
-	}
-
-	if (unrecognized)
-		*bad_domains = g_string_free (unrecognized, FALSE);
-
-	return TRUE;
+    GString *            unrecognized = NULL;
+    NMLogDomain          cur_log_state[_LOGL_N_REAL];
+    NMLogDomain          new_log_state[_LOGL_N_REAL];
+    NMLogLevel           cur_log_level;
+    NMLogLevel           new_log_level;
+    gs_free const char **domains_v = NULL;
+    gsize                i_d;
+    int                  i;
+    gboolean             had_platform_debug;
+    gs_free char *       domains_free = NULL;
+
+    NM_ASSERT_ON_MAIN_THREAD();
+
+    g_return_val_if_fail(!bad_domains || !*bad_domains, FALSE);
+    g_return_val_if_fail(!error || !*error, FALSE);
+
+    cur_log_level = gl.imm.log_level;
+    memcpy(cur_log_state, _nm_logging_enabled_state, sizeof(cur_log_state));
+
+    new_log_level = cur_log_level;
+
+    if (!domains || !*domains) {
+        domains_free = _domains_to_string(FALSE, cur_log_level, cur_log_state);
+        domains      = domains_free;
+    }
+
+    for (i = 0; i < G_N_ELEMENTS(new_log_state); i++)
+        new_log_state[i] = 0;
+
+    if (level && *level) {
+        if (!match_log_level(level, &new_log_level, error))
+            return FALSE;
+        if (new_log_level == _LOGL_KEEP) {
+            new_log_level = cur_log_level;
+            for (i = 0; i < G_N_ELEMENTS(new_log_state); i++)
+                new_log_state[i] = cur_log_state[i];
+        }
+    }
+
+    domains_v = nm_utils_strsplit_set(domains, ", ");
+    for (i_d = 0; domains_v && domains_v[i_d]; i_d++) {
+        const char *   s = domains_v[i_d];
+        const char *   p;
+        const LogDesc *diter;
+        NMLogLevel     domain_log_level;
+        NMLogDomain    bits;
+
+        /* LOGD_VPN_PLUGIN is protected, that is, when setting ALL or DEFAULT,
+         * it does not enable the verbose levels DEBUG and TRACE, because that
+         * may expose sensitive data. */
+        NMLogDomain protect = LOGD_NONE;
+
+        p = strchr(s, ':');
+        if (p) {
+            *((char *) p) = '\0';
+            if (!match_log_level(p + 1, &domain_log_level, error))
+                return FALSE;
+        } else
+            domain_log_level = new_log_level;
+
+        bits = 0;
+
+        if (domains_free) {
+            /* The caller didn't provide any domains to set (`nmcli general logging level DEBUG`).
+             * We reset all domains that were previously set, but we still want to protect
+             * VPN_PLUGIN domain. */
+            protect = LOGD_VPN_PLUGIN;
+        }
+
+        /* Check for combined domains */
+        if (!g_ascii_strcasecmp(s, LOGD_ALL_STRING)) {
+            bits    = LOGD_ALL;
+            protect = LOGD_VPN_PLUGIN;
+        } else if (!g_ascii_strcasecmp(s, LOGD_DEFAULT_STRING)) {
+            bits    = LOGD_DEFAULT;
+            protect = LOGD_VPN_PLUGIN;
+        } else if (!g_ascii_strcasecmp(s, LOGD_DHCP_STRING))
+            bits = LOGD_DHCP;
+        else if (!g_ascii_strcasecmp(s, LOGD_IP_STRING))
+            bits = LOGD_IP;
+
+        /* Check for compatibility domains */
+        else if (!g_ascii_strcasecmp(s, "HW"))
+            bits = LOGD_PLATFORM;
+        else if (!g_ascii_strcasecmp(s, "WIMAX"))
+            continue;
+
+        else {
+            for (diter = &domain_desc[0]; diter->name; diter++) {
+                if (!g_ascii_strcasecmp(diter->name, s)) {
+                    bits = diter->num;
+                    break;
+                }
+            }
+
+            if (!bits) {
+                if (!bad_domains) {
+                    g_set_error(error,
+                                NM_MANAGER_ERROR,
+                                NM_MANAGER_ERROR_UNKNOWN_LOG_DOMAIN,
+                                _("Unknown log domain '%s'"),
+                                s);
+                    return FALSE;
+                }
+
+                if (unrecognized)
+                    g_string_append(unrecognized, ", ");
+                else
+                    unrecognized = g_string_new(NULL);
+                g_string_append(unrecognized, s);
+                continue;
+            }
+        }
+
+        if (domain_log_level == _LOGL_KEEP) {
+            for (i = 0; i < G_N_ELEMENTS(new_log_state); i++)
+                new_log_state[i] = (new_log_state[i] & ~bits) | (cur_log_state[i] & bits);
+        } else {
+            for (i = 0; i < G_N_ELEMENTS(new_log_state); i++) {
+                if (i < domain_log_level)
+                    new_log_state[i] &= ~bits;
+                else {
+                    new_log_state[i] |= bits;
+                    if ((protect & bits) && i < LOGL_INFO)
+                        new_log_state[i] &= ~protect;
+                }
+            }
+        }
+    }
+
+    nm_clear_g_free(&gl_main.logging_domains_to_string);
+
+    had_platform_debug = _nm_logging_enabled_lockfree(LOGL_DEBUG, LOGD_PLATFORM);
+
+    G_LOCK(log);
+
+    gl.mut.log_level = new_log_level;
+    for (i = 0; i < G_N_ELEMENTS(new_log_state); i++)
+        _nm_logging_enabled_state[i] = new_log_state[i];
+
+    G_UNLOCK(log);
+
+    if (had_platform_debug && !_nm_logging_enabled_lockfree(LOGL_DEBUG, LOGD_PLATFORM)) {
+        /* when debug logging is enabled, platform will cache all access to
+         * sysctl. When the user disables debug-logging, we want to clear that
+         * cache right away. */
+        _nm_logging_clear_platform_logging_cache();
+    }
+
+    if (unrecognized)
+        *bad_domains = g_string_free(unrecognized, FALSE);
+
+    return TRUE;
 }
 
 const char *
-nm_logging_level_to_string (void)
+nm_logging_level_to_string(void)
 {
-	NM_ASSERT_ON_MAIN_THREAD ();
+    NM_ASSERT_ON_MAIN_THREAD();
 
-	return level_desc[gl.imm.log_level].name;
+    return level_desc[gl.imm.log_level].name;
 }
 
 const char *
-nm_logging_all_levels_to_string (void)
+nm_logging_all_levels_to_string(void)
 {
-	static GString *str;
+    static GString *str;
 
-	if (G_UNLIKELY (!str)) {
-		int i;
+    if (G_UNLIKELY(!str)) {
+        int i;
 
-		str = g_string_new (NULL);
-		for (i = 0; i < G_N_ELEMENTS (level_desc); i++) {
-			if (str->len)
-				g_string_append_c (str, ',');
-			g_string_append (str, level_desc[i].name);
-		}
-	}
+        str = g_string_new(NULL);
+        for (i = 0; i < G_N_ELEMENTS(level_desc); i++) {
+            if (str->len)
+                g_string_append_c(str, ',');
+            g_string_append(str, level_desc[i].name);
+        }
+    }
 
-	return str->str;
+    return str->str;
 }
 
 const char *
-nm_logging_domains_to_string (void)
+nm_logging_domains_to_string(void)
 {
-	NM_ASSERT_ON_MAIN_THREAD ();
+    NM_ASSERT_ON_MAIN_THREAD();
 
-	if (G_UNLIKELY (!gl_main.logging_domains_to_string)) {
-		gl_main.logging_domains_to_string = _domains_to_string (TRUE,
-		                                                        gl.imm.log_level,
-		                                                        _nm_logging_enabled_state);
-	}
+    if (G_UNLIKELY(!gl_main.logging_domains_to_string)) {
+        gl_main.logging_domains_to_string =
+            _domains_to_string(TRUE, gl.imm.log_level, _nm_logging_enabled_state);
+    }
 
-	return gl_main.logging_domains_to_string;
+    return gl_main.logging_domains_to_string;
 }
 
 static char *
-_domains_to_string (gboolean include_level_override,
-                    NMLogLevel log_level,
-                    const NMLogDomain log_state[static _LOGL_N_REAL])
+_domains_to_string(gboolean          include_level_override,
+                   NMLogLevel        log_level,
+                   const NMLogDomain log_state[static _LOGL_N_REAL])
 {
-	const LogDesc *diter;
-	GString *str;
-	int i;
-
-	/* We don't just return g_strdup() the logging domains that were set during
-	 * nm_logging_setup(), because we want to expand "DEFAULT" and "ALL".
-	 */
-
-	str = g_string_sized_new (75);
-	for (diter = &domain_desc[0]; diter->name; diter++) {
-		/* If it's set for any lower level, it will also be set for LOGL_ERR */
-		if (!(diter->num & log_state[LOGL_ERR]))
-			continue;
-
-		if (str->len)
-			g_string_append_c (str, ',');
-		g_string_append (str, diter->name);
-
-		if (!include_level_override)
-			continue;
-
-		/* Check if it's logging at a lower level than the default. */
-		for (i = 0; i < log_level; i++) {
-			if (diter->num & log_state[i]) {
-				g_string_append_printf (str, ":%s", level_desc[i].name);
-				break;
-			}
-		}
-		/* Check if it's logging at a higher level than the default. */
-		if (!(diter->num & log_state[log_level])) {
-			for (i = log_level + 1; i < _LOGL_N_REAL; i++) {
-				if (diter->num & log_state[i]) {
-					g_string_append_printf (str, ":%s", level_desc[i].name);
-					break;
-				}
-			}
-		}
-	}
-	return g_string_free (str, FALSE);
+    const LogDesc *diter;
+    GString *      str;
+    int            i;
+
+    /* We don't just return g_strdup() the logging domains that were set during
+     * nm_logging_setup(), because we want to expand "DEFAULT" and "ALL".
+     */
+
+    str = g_string_sized_new(75);
+    for (diter = &domain_desc[0]; diter->name; diter++) {
+        /* If it's set for any lower level, it will also be set for LOGL_ERR */
+        if (!(diter->num & log_state[LOGL_ERR]))
+            continue;
+
+        if (str->len)
+            g_string_append_c(str, ',');
+        g_string_append(str, diter->name);
+
+        if (!include_level_override)
+            continue;
+
+        /* Check if it's logging at a lower level than the default. */
+        for (i = 0; i < log_level; i++) {
+            if (diter->num & log_state[i]) {
+                g_string_append_printf(str, ":%s", level_desc[i].name);
+                break;
+            }
+        }
+        /* Check if it's logging at a higher level than the default. */
+        if (!(diter->num & log_state[log_level])) {
+            for (i = log_level + 1; i < _LOGL_N_REAL; i++) {
+                if (diter->num & log_state[i]) {
+                    g_string_append_printf(str, ":%s", level_desc[i].name);
+                    break;
+                }
+            }
+        }
+    }
+    return g_string_free(str, FALSE);
 }
 
 static char _all_logging_domains_to_str[273];
 
 const char *
-nm_logging_all_domains_to_string (void)
+nm_logging_all_domains_to_string(void)
 {
-	static const char *volatile str = NULL;
-	const char *s;
+    static const char *volatile str = NULL;
+    const char *s;
 
 again:
-	s = g_atomic_pointer_get (&str);
-	if (G_UNLIKELY (!s)) {
-		static gsize once = 0;
-		const LogDesc *diter;
-		gsize buf_l;
-		char *buf_p;
-
-		if (!g_once_init_enter (&once))
-			goto again;
-
-		buf_p = _all_logging_domains_to_str;
-		buf_l = sizeof (_all_logging_domains_to_str);
-
-		nm_utils_strbuf_append_str (&buf_p, &buf_l, LOGD_DEFAULT_STRING);
-		for (diter = &domain_desc[0]; diter->name; diter++) {
-			nm_utils_strbuf_append_c (&buf_p, &buf_l, ',');
-			nm_utils_strbuf_append_str (&buf_p, &buf_l, diter->name);
-			if (diter->num == LOGD_DHCP6)
-				nm_utils_strbuf_append_str (&buf_p, &buf_l, ","LOGD_DHCP_STRING);
-			else if (diter->num == LOGD_IP6)
-				nm_utils_strbuf_append_str (&buf_p, &buf_l, ","LOGD_IP_STRING);
-		}
-		nm_utils_strbuf_append_str (&buf_p, &buf_l, LOGD_ALL_STRING);
-
-		/* Did you modify the logging domains (or their names)? Adjust the size of
-		 * _all_logging_domains_to_str buffer above to have the exact size. */
-		nm_assert (strlen (_all_logging_domains_to_str) == sizeof (_all_logging_domains_to_str) - 1);
-		nm_assert (buf_l == 1);
-
-		s = _all_logging_domains_to_str;
-		g_atomic_pointer_set (&str, s);
-		g_once_init_leave (&once, 1);
-	}
-
-	return s;
+    s = g_atomic_pointer_get(&str);
+    if (G_UNLIKELY(!s)) {
+        static gsize   once = 0;
+        const LogDesc *diter;
+        gsize          buf_l;
+        char *         buf_p;
+
+        if (!g_once_init_enter(&once))
+            goto again;
+
+        buf_p = _all_logging_domains_to_str;
+        buf_l = sizeof(_all_logging_domains_to_str);
+
+        nm_utils_strbuf_append_str(&buf_p, &buf_l, LOGD_DEFAULT_STRING);
+        for (diter = &domain_desc[0]; diter->name; diter++) {
+            nm_utils_strbuf_append_c(&buf_p, &buf_l, ',');
+            nm_utils_strbuf_append_str(&buf_p, &buf_l, diter->name);
+            if (diter->num == LOGD_DHCP6)
+                nm_utils_strbuf_append_str(&buf_p, &buf_l, "," LOGD_DHCP_STRING);
+            else if (diter->num == LOGD_IP6)
+                nm_utils_strbuf_append_str(&buf_p, &buf_l, "," LOGD_IP_STRING);
+        }
+        nm_utils_strbuf_append_str(&buf_p, &buf_l, LOGD_ALL_STRING);
+
+        /* Did you modify the logging domains (or their names)? Adjust the size of
+         * _all_logging_domains_to_str buffer above to have the exact size. */
+        nm_assert(strlen(_all_logging_domains_to_str) == sizeof(_all_logging_domains_to_str) - 1);
+        nm_assert(buf_l == 1);
+
+        s = _all_logging_domains_to_str;
+        g_atomic_pointer_set(&str, s);
+        g_once_init_leave(&once, 1);
+    }
+
+    return s;
 }
 
 /**
@@ -559,466 +554,483 @@ again:
  *   give @domain, or %_LOGL_OFF if it is disabled.
  **/
 NMLogLevel
-nm_logging_get_level (NMLogDomain domain)
+nm_logging_get_level(NMLogDomain domain)
 {
-	NMLogLevel sl = _LOGL_OFF;
+    NMLogLevel sl = _LOGL_OFF;
 
-	G_STATIC_ASSERT (LOGL_TRACE == 0);
-	while (   sl > LOGL_TRACE
-	       && _nm_logging_enabled_lockfree (sl - 1, domain))
-		sl--;
-	return sl;
+    G_STATIC_ASSERT(LOGL_TRACE == 0);
+    while (sl > LOGL_TRACE && _nm_logging_enabled_lockfree(sl - 1, domain))
+        sl--;
+    return sl;
 }
 
 gboolean
-_nm_logging_enabled_locking (NMLogLevel level,
-                             NMLogDomain domain)
+_nm_logging_enabled_locking(NMLogLevel level, NMLogDomain domain)
 {
-	gboolean v;
+    gboolean v;
 
-	G_LOCK (log);
-	v = _nm_logging_enabled_lockfree (level, domain);
-	G_UNLOCK (log);
-	return v;
+    G_LOCK(log);
+    v = _nm_logging_enabled_lockfree(level, domain);
+    G_UNLOCK(log);
+    return v;
 }
 
 gboolean
-_nm_log_enabled_impl (gboolean mt_require_locking,
-                      NMLogLevel level,
-                      NMLogDomain domain)
+_nm_log_enabled_impl(gboolean mt_require_locking, NMLogLevel level, NMLogDomain domain)
 {
-	return nm_logging_enabled_mt (mt_require_locking, level, domain);
+    return nm_logging_enabled_mt(mt_require_locking, level, domain);
 }
 
 #if SYSTEMD_JOURNAL
 static void
-_iovec_set (struct iovec *iov, const void *str, gsize len)
+_iovec_set(struct iovec *iov, const void *str, gsize len)
 {
-	iov->iov_base = (void *) str;
-	iov->iov_len = len;
+    iov->iov_base = (void *) str;
+    iov->iov_len  = len;
 }
 
 static void
-_iovec_set_string (struct iovec *iov, const char *str)
+_iovec_set_string(struct iovec *iov, const char *str)
 {
-	_iovec_set (iov, str, strlen (str));
+    _iovec_set(iov, str, strlen(str));
 }
 
-#define _iovec_set_string_literal(iov, str) _iovec_set ((iov), ""str"", NM_STRLEN (str))
+    #define _iovec_set_string_literal(iov, str) _iovec_set((iov), "" str "", NM_STRLEN(str))
 
-_nm_printf (3, 4)
-static void
-_iovec_set_format (struct iovec *iov, char **iov_free, const char *format, ...)
+_nm_printf(3, 4) static void _iovec_set_format(struct iovec *iov,
+                                               char **       iov_free,
+                                               const char *  format,
+                                               ...)
 {
-	va_list ap;
-	char *str;
+    va_list ap;
+    char *  str;
 
-	va_start (ap, format);
-	str = g_strdup_vprintf (format, ap);
-	va_end (ap);
+    va_start(ap, format);
+    str = g_strdup_vprintf(format, ap);
+    va_end(ap);
 
-	_iovec_set_string (iov, str);
-	*iov_free = str;
+    _iovec_set_string(iov, str);
+    *iov_free = str;
 }
 
-#define _iovec_set_format_a(iov, reserve_extra, format, ...) \
-	G_STMT_START { \
-		const gsize _size = (reserve_extra) + (NM_STRLEN (format) + 3); \
-		char *const _buf = g_alloca (_size); \
-		int _len; \
-		\
-		G_STATIC_ASSERT_EXPR ((reserve_extra) + (NM_STRLEN (format) + 3) <= 96); \
-		\
-		_len = g_snprintf (_buf, _size, ""format"", ##__VA_ARGS__);\
-		\
-		nm_assert (_len >= 0); \
-		nm_assert (_len < _size); \
-		nm_assert (_len == strlen (_buf)); \
-		\
-		_iovec_set ((iov), _buf, _len); \
-	} G_STMT_END
-
-#define _iovec_set_format_str_a(iov, max_str_len, format, str_arg) \
-	G_STMT_START { \
-		const char *_str_arg = (str_arg); \
-		\
-		nm_assert (_str_arg && strlen (_str_arg) < (max_str_len)); \
-		_iovec_set_format_a ((iov), (max_str_len), format, str_arg); \
-	} G_STMT_END
+    #define _iovec_set_format_a(iov, reserve_extra, format, ...)                   \
+        G_STMT_START                                                               \
+        {                                                                          \
+            const gsize _size = (reserve_extra) + (NM_STRLEN(format) + 3);         \
+            char *const _buf  = g_alloca(_size);                                   \
+            int         _len;                                                      \
+                                                                                   \
+            G_STATIC_ASSERT_EXPR((reserve_extra) + (NM_STRLEN(format) + 3) <= 96); \
+                                                                                   \
+            _len = g_snprintf(_buf, _size, "" format "", ##__VA_ARGS__);           \
+                                                                                   \
+            nm_assert(_len >= 0);                                                  \
+            nm_assert(_len < _size);                                               \
+            nm_assert(_len == strlen(_buf));                                       \
+                                                                                   \
+            _iovec_set((iov), _buf, _len);                                         \
+        }                                                                          \
+        G_STMT_END
+
+    #define _iovec_set_format_str_a(iov, max_str_len, format, str_arg)  \
+        G_STMT_START                                                    \
+        {                                                               \
+            const char *_str_arg = (str_arg);                           \
+                                                                        \
+            nm_assert(_str_arg &&strlen(_str_arg) < (max_str_len));     \
+            _iovec_set_format_a((iov), (max_str_len), format, str_arg); \
+        }                                                               \
+        G_STMT_END
 
 #endif
 
 void
-_nm_log_impl (const char *file,
-              guint line,
-              const char *func,
-              gboolean mt_require_locking,
-              NMLogLevel level,
-              NMLogDomain domain,
-              int error,
-              const char *ifname,
-              const char *conn_uuid,
-              const char *fmt,
-              ...)
+_nm_log_impl(const char *file,
+             guint       line,
+             const char *func,
+             gboolean    mt_require_locking,
+             NMLogLevel  level,
+             NMLogDomain domain,
+             int         error,
+             const char *ifname,
+             const char *conn_uuid,
+             const char *fmt,
+             ...)
 {
-	va_list args;
-	char *msg;
-	GTimeVal tv;
-	int errsv;
-	const NMLogDomain *cur_log_state;
-	NMLogDomain cur_log_state_copy[_LOGL_N_REAL];
-	Global g_copy;
-	const Global *g;
-
-	if (G_UNLIKELY (mt_require_locking)) {
-		G_LOCK (log);
-		/* we evaluate logging-enabled under lock. There is still a race that
-		 * we might log the message below *after* logging was disabled. That means,
-		 * when disabling logging, we might still log messages. */
-		if (!_nm_logging_enabled_lockfree (level, domain)) {
-			G_UNLOCK (log);
-			return;
-		}
-		g_copy = gl.imm;
-		memcpy (cur_log_state_copy, _nm_logging_enabled_state, sizeof (cur_log_state_copy));
-		G_UNLOCK (log);
-		g = &g_copy;
-		cur_log_state = cur_log_state_copy;
-	} else {
-		NM_ASSERT_ON_MAIN_THREAD ();
-		if (!_nm_logging_enabled_lockfree (level, domain))
-			return;
-		g = &gl.imm;
-		cur_log_state = _nm_logging_enabled_state;
-	}
-
-	(void) cur_log_state;
-
-	errsv = errno;
-
-	/* Make sure that %m maps to the specified error */
-	if (error != 0) {
-		if (error < 0)
-			error = -error;
-		errno = error;
-	}
-
-	va_start (args, fmt);
-	msg = g_strdup_vprintf (fmt, args);
-	va_end (args);
+    va_list            args;
+    char *             msg;
+    GTimeVal           tv;
+    int                errsv;
+    const NMLogDomain *cur_log_state;
+    NMLogDomain        cur_log_state_copy[_LOGL_N_REAL];
+    Global             g_copy;
+    const Global *     g;
+
+    if (G_UNLIKELY(mt_require_locking)) {
+        G_LOCK(log);
+        /* we evaluate logging-enabled under lock. There is still a race that
+         * we might log the message below *after* logging was disabled. That means,
+         * when disabling logging, we might still log messages. */
+        if (!_nm_logging_enabled_lockfree(level, domain)) {
+            G_UNLOCK(log);
+            return;
+        }
+        g_copy = gl.imm;
+        memcpy(cur_log_state_copy, _nm_logging_enabled_state, sizeof(cur_log_state_copy));
+        G_UNLOCK(log);
+        g             = &g_copy;
+        cur_log_state = cur_log_state_copy;
+    } else {
+        NM_ASSERT_ON_MAIN_THREAD();
+        if (!_nm_logging_enabled_lockfree(level, domain))
+            return;
+        g             = &gl.imm;
+        cur_log_state = _nm_logging_enabled_state;
+    }
+
+    (void) cur_log_state;
+
+    errsv = errno;
+
+    /* Make sure that %m maps to the specified error */
+    if (error != 0) {
+        if (error < 0)
+            error = -error;
+        errno = error;
+    }
+
+    va_start(args, fmt);
+    msg = g_strdup_vprintf(fmt, args);
+    va_end(args);
 
 #define MESSAGE_FMT "%s%-7s [%ld.%04ld] %s"
 #define MESSAGE_ARG(prefix, tv, msg) \
-    prefix, \
-    level_desc[level].level_str, \
-    (tv).tv_sec, \
-    ((tv).tv_usec / 100), \
-    (msg)
+    prefix, level_desc[level].level_str, (tv).tv_sec, ((tv).tv_usec / 100), (msg)
 
-	g_get_current_time (&tv);
+    g_get_current_time(&tv);
 
-	if (g->debug_stderr)
-		g_printerr (MESSAGE_FMT"\n", MESSAGE_ARG (g->prefix, tv, msg));
+    if (g->debug_stderr)
+        g_printerr(MESSAGE_FMT "\n", MESSAGE_ARG(g->prefix, tv, msg));
 
-	switch (g->log_backend) {
+    switch (g->log_backend) {
 #if SYSTEMD_JOURNAL
-	case LOG_BACKEND_JOURNAL:
-		{
-			gint64 now, boottime;
-			struct iovec iov_data[15];
-			struct iovec *iov = iov_data;
-			char *iov_free_data[5];
-			char **iov_free = iov_free_data;
-			const LogDesc *diter;
-			NMLogDomain dom_all;
-			char s_log_domains_buf[NM_STRLEN ("NM_LOG_DOMAINS=") + sizeof (_all_logging_domains_to_str)];
-			char *s_log_domains;
-			gsize l_log_domains;
-
-			now = nm_utils_get_monotonic_timestamp_nsec ();
-			boottime = nm_utils_monotonic_timestamp_as_boottime (now, 1);
-
-			_iovec_set_format_a (iov++, 30, "PRIORITY=%d", level_desc[level].syslog_level);
-			_iovec_set_format (iov++, iov_free++, "MESSAGE="MESSAGE_FMT, MESSAGE_ARG (g->prefix, tv, msg));
-			_iovec_set_string (iov++, syslog_identifier_full (g->syslog_identifier));
-			_iovec_set_format_a (iov++, 30, "SYSLOG_PID=%ld", (long) getpid ());
-
-			dom_all = domain;
-			s_log_domains = s_log_domains_buf;
-			l_log_domains = sizeof (s_log_domains_buf);
-
-			nm_utils_strbuf_append_str (&s_log_domains, &l_log_domains, "NM_LOG_DOMAINS=");
-			for (diter = &domain_desc[0]; dom_all != 0 && diter->name; diter++) {
-				if (!NM_FLAGS_ANY (dom_all, diter->num))
-					continue;
-				if (dom_all != domain)
-					nm_utils_strbuf_append_c (&s_log_domains, &l_log_domains, ',');
-				nm_utils_strbuf_append_str (&s_log_domains, &l_log_domains, diter->name);
-				dom_all &= ~diter->num;
-			}
-			nm_assert (l_log_domains > 0);
-			_iovec_set (iov++, s_log_domains_buf, s_log_domains - s_log_domains_buf);
-
-			G_STATIC_ASSERT_EXPR (LOG_FAC (LOG_DAEMON) == 3);
-			_iovec_set_string_literal (iov++, "SYSLOG_FACILITY=3");
-			_iovec_set_format_str_a (iov++, 15, "NM_LOG_LEVEL=%s", level_desc[level].name);
-			if (func)
-				_iovec_set_format (iov++, iov_free++, "CODE_FUNC=%s", func);
-			_iovec_set_format (iov++, iov_free++, "CODE_FILE=%s", file ?: "");
-			_iovec_set_format_a (iov++, 20, "CODE_LINE=%u", line);
-			_iovec_set_format_a (iov++, 60, "TIMESTAMP_MONOTONIC=%lld.%06lld", (long long) (now / NM_UTILS_NSEC_PER_SEC), (long long) ((now % NM_UTILS_NSEC_PER_SEC) / 1000));
-			_iovec_set_format_a (iov++, 60, "TIMESTAMP_BOOTTIME=%lld.%06lld", (long long) (boottime / NM_UTILS_NSEC_PER_SEC), (long long) ((boottime % NM_UTILS_NSEC_PER_SEC) / 1000));
-			if (error != 0)
-				_iovec_set_format_a (iov++, 30, "ERRNO=%d", error);
-			if (ifname)
-				_iovec_set_format (iov++, iov_free++, "NM_DEVICE=%s", ifname);
-			if (conn_uuid)
-				_iovec_set_format (iov++, iov_free++, "NM_CONNECTION=%s", conn_uuid);
-
-			nm_assert (iov <= &iov_data[G_N_ELEMENTS (iov_data)]);
-			nm_assert (iov_free <= &iov_free_data[G_N_ELEMENTS (iov_free_data)]);
-
-			sd_journal_sendv (iov_data, iov - iov_data);
-
-			for (; --iov_free >= iov_free_data; )
-				g_free (*iov_free);
-		}
-		break;
+    case LOG_BACKEND_JOURNAL:
+    {
+        gint64         now, boottime;
+        struct iovec   iov_data[15];
+        struct iovec * iov = iov_data;
+        char *         iov_free_data[5];
+        char **        iov_free = iov_free_data;
+        const LogDesc *diter;
+        NMLogDomain    dom_all;
+        char  s_log_domains_buf[NM_STRLEN("NM_LOG_DOMAINS=") + sizeof(_all_logging_domains_to_str)];
+        char *s_log_domains;
+        gsize l_log_domains;
+
+        now      = nm_utils_get_monotonic_timestamp_nsec();
+        boottime = nm_utils_monotonic_timestamp_as_boottime(now, 1);
+
+        _iovec_set_format_a(iov++, 30, "PRIORITY=%d", level_desc[level].syslog_level);
+        _iovec_set_format(iov++,
+                          iov_free++,
+                          "MESSAGE=" MESSAGE_FMT,
+                          MESSAGE_ARG(g->prefix, tv, msg));
+        _iovec_set_string(iov++, syslog_identifier_full(g->syslog_identifier));
+        _iovec_set_format_a(iov++, 30, "SYSLOG_PID=%ld", (long) getpid());
+
+        dom_all       = domain;
+        s_log_domains = s_log_domains_buf;
+        l_log_domains = sizeof(s_log_domains_buf);
+
+        nm_utils_strbuf_append_str(&s_log_domains, &l_log_domains, "NM_LOG_DOMAINS=");
+        for (diter = &domain_desc[0]; dom_all != 0 && diter->name; diter++) {
+            if (!NM_FLAGS_ANY(dom_all, diter->num))
+                continue;
+            if (dom_all != domain)
+                nm_utils_strbuf_append_c(&s_log_domains, &l_log_domains, ',');
+            nm_utils_strbuf_append_str(&s_log_domains, &l_log_domains, diter->name);
+            dom_all &= ~diter->num;
+        }
+        nm_assert(l_log_domains > 0);
+        _iovec_set(iov++, s_log_domains_buf, s_log_domains - s_log_domains_buf);
+
+        G_STATIC_ASSERT_EXPR(LOG_FAC(LOG_DAEMON) == 3);
+        _iovec_set_string_literal(iov++, "SYSLOG_FACILITY=3");
+        _iovec_set_format_str_a(iov++, 15, "NM_LOG_LEVEL=%s", level_desc[level].name);
+        if (func)
+            _iovec_set_format(iov++, iov_free++, "CODE_FUNC=%s", func);
+        _iovec_set_format(iov++, iov_free++, "CODE_FILE=%s", file ?: "");
+        _iovec_set_format_a(iov++, 20, "CODE_LINE=%u", line);
+        _iovec_set_format_a(iov++,
+                            60,
+                            "TIMESTAMP_MONOTONIC=%lld.%06lld",
+                            (long long) (now / NM_UTILS_NSEC_PER_SEC),
+                            (long long) ((now % NM_UTILS_NSEC_PER_SEC) / 1000));
+        _iovec_set_format_a(iov++,
+                            60,
+                            "TIMESTAMP_BOOTTIME=%lld.%06lld",
+                            (long long) (boottime / NM_UTILS_NSEC_PER_SEC),
+                            (long long) ((boottime % NM_UTILS_NSEC_PER_SEC) / 1000));
+        if (error != 0)
+            _iovec_set_format_a(iov++, 30, "ERRNO=%d", error);
+        if (ifname)
+            _iovec_set_format(iov++, iov_free++, "NM_DEVICE=%s", ifname);
+        if (conn_uuid)
+            _iovec_set_format(iov++, iov_free++, "NM_CONNECTION=%s", conn_uuid);
+
+        nm_assert(iov <= &iov_data[G_N_ELEMENTS(iov_data)]);
+        nm_assert(iov_free <= &iov_free_data[G_N_ELEMENTS(iov_free_data)]);
+
+        sd_journal_sendv(iov_data, iov - iov_data);
+
+        for (; --iov_free >= iov_free_data;)
+            g_free(*iov_free);
+    } break;
 #endif
-	case LOG_BACKEND_SYSLOG:
-		syslog (level_desc[level].syslog_level,
-		        MESSAGE_FMT, MESSAGE_ARG (g->prefix, tv, msg));
-		break;
-	default:
-		g_log (syslog_identifier_domain (g->syslog_identifier), level_desc[level].g_log_level,
-		       MESSAGE_FMT, MESSAGE_ARG (g->prefix, tv, msg));
-		break;
-	}
-
-	g_free (msg);
-
-	errno = errsv;
+    case LOG_BACKEND_SYSLOG:
+        syslog(level_desc[level].syslog_level, MESSAGE_FMT, MESSAGE_ARG(g->prefix, tv, msg));
+        break;
+    default:
+        g_log(syslog_identifier_domain(g->syslog_identifier),
+              level_desc[level].g_log_level,
+              MESSAGE_FMT,
+              MESSAGE_ARG(g->prefix, tv, msg));
+        break;
+    }
+
+    g_free(msg);
+
+    errno = errsv;
 }
 
 /*****************************************************************************/
 
 void
-_nm_utils_monotonic_timestamp_initialized (const struct timespec *tp,
-                                           gint64 offset_sec,
-                                           gboolean is_boottime)
+_nm_utils_monotonic_timestamp_initialized(const struct timespec *tp,
+                                          gint64                 offset_sec,
+                                          gboolean               is_boottime)
 {
-	NM_ASSERT_ON_MAIN_THREAD ();
-
-	if (_nm_logging_enabled_lockfree (LOGL_DEBUG, LOGD_CORE)) {
-		time_t now = time (NULL);
-		struct tm tm;
-		char s[255];
-
-		strftime (s, sizeof (s), "%Y-%m-%d %H:%M:%S", localtime_r (&now, &tm));
-		nm_log_dbg (LOGD_CORE, "monotonic timestamp started counting 1.%09ld seconds ago with "
-		                       "an offset of %lld.0 seconds to %s (local time is %s)",
-		                       tp->tv_nsec,
-		                       (long long) -offset_sec,
-		                       is_boottime ? "CLOCK_BOOTTIME" : "CLOCK_MONOTONIC", s);
-	}
+    NM_ASSERT_ON_MAIN_THREAD();
+
+    if (_nm_logging_enabled_lockfree(LOGL_DEBUG, LOGD_CORE)) {
+        time_t    now = time(NULL);
+        struct tm tm;
+        char      s[255];
+
+        strftime(s, sizeof(s), "%Y-%m-%d %H:%M:%S", localtime_r(&now, &tm));
+        nm_log_dbg(LOGD_CORE,
+                   "monotonic timestamp started counting 1.%09ld seconds ago with "
+                   "an offset of %lld.0 seconds to %s (local time is %s)",
+                   tp->tv_nsec,
+                   (long long) -offset_sec,
+                   is_boottime ? "CLOCK_BOOTTIME" : "CLOCK_MONOTONIC",
+                   s);
+    }
 }
 
 /*****************************************************************************/
 
 static void
-nm_log_handler (const char *log_domain,
-                GLogLevelFlags level,
-                const char *message,
-                gpointer ignored)
+nm_log_handler(const char *log_domain, GLogLevelFlags level, const char *message, gpointer ignored)
 {
-	int syslog_priority;
-
-	switch (level & G_LOG_LEVEL_MASK) {
-	case G_LOG_LEVEL_ERROR:
-		syslog_priority = LOG_CRIT;
-		break;
-	case G_LOG_LEVEL_CRITICAL:
-		syslog_priority = LOG_ERR;
-		break;
-	case G_LOG_LEVEL_WARNING:
-		syslog_priority = LOG_WARNING;
-		break;
-	case G_LOG_LEVEL_MESSAGE:
-		syslog_priority = LOG_NOTICE;
-		break;
-	case G_LOG_LEVEL_DEBUG:
-		syslog_priority = LOG_DEBUG;
-		break;
-	case G_LOG_LEVEL_INFO:
-	default:
-		syslog_priority = LOG_INFO;
-		break;
-	}
-
-	/* we don't need any locking here. The glib log handler gets only registered
-	 * once during nm_logging_init() and the global data is not modified afterwards. */
-	nm_assert (gl.imm.init_done);
-
-	if (gl.imm.debug_stderr)
-		g_printerr ("%s%s\n", gl.imm.prefix, message ?: "");
-
-	switch (gl.imm.log_backend) {
+    int syslog_priority;
+
+    switch (level & G_LOG_LEVEL_MASK) {
+    case G_LOG_LEVEL_ERROR:
+        syslog_priority = LOG_CRIT;
+        break;
+    case G_LOG_LEVEL_CRITICAL:
+        syslog_priority = LOG_ERR;
+        break;
+    case G_LOG_LEVEL_WARNING:
+        syslog_priority = LOG_WARNING;
+        break;
+    case G_LOG_LEVEL_MESSAGE:
+        syslog_priority = LOG_NOTICE;
+        break;
+    case G_LOG_LEVEL_DEBUG:
+        syslog_priority = LOG_DEBUG;
+        break;
+    case G_LOG_LEVEL_INFO:
+    default:
+        syslog_priority = LOG_INFO;
+        break;
+    }
+
+    /* we don't need any locking here. The glib log handler gets only registered
+     * once during nm_logging_init() and the global data is not modified afterwards. */
+    nm_assert(gl.imm.init_done);
+
+    if (gl.imm.debug_stderr)
+        g_printerr("%s%s\n", gl.imm.prefix, message ?: "");
+
+    switch (gl.imm.log_backend) {
 #if SYSTEMD_JOURNAL
-	case LOG_BACKEND_JOURNAL:
-		{
-			gint64 now, boottime;
-
-			now = nm_utils_get_monotonic_timestamp_nsec ();
-			boottime = nm_utils_monotonic_timestamp_as_boottime (now, 1);
-
-			sd_journal_send ("PRIORITY=%d", syslog_priority,
-			                 "MESSAGE=%s%s", gl.imm.prefix, message ?: "",
-			                 syslog_identifier_full (gl.imm.syslog_identifier),
-			                 "SYSLOG_PID=%ld", (long) getpid (),
-			                 "SYSLOG_FACILITY=3",
-			                 "GLIB_DOMAIN=%s", log_domain ?: "",
-			                 "GLIB_LEVEL=%d", (int) (level & G_LOG_LEVEL_MASK),
-			                 "TIMESTAMP_MONOTONIC=%lld.%06lld", (long long) (now / NM_UTILS_NSEC_PER_SEC), (long long) ((now % NM_UTILS_NSEC_PER_SEC) / 1000),
-			                 "TIMESTAMP_BOOTTIME=%lld.%06lld", (long long) (boottime / NM_UTILS_NSEC_PER_SEC), (long long) ((boottime % NM_UTILS_NSEC_PER_SEC) / 1000),
-			                 NULL);
-		}
-		break;
+    case LOG_BACKEND_JOURNAL:
+    {
+        gint64 now, boottime;
+
+        now      = nm_utils_get_monotonic_timestamp_nsec();
+        boottime = nm_utils_monotonic_timestamp_as_boottime(now, 1);
+
+        sd_journal_send("PRIORITY=%d",
+                        syslog_priority,
+                        "MESSAGE=%s%s",
+                        gl.imm.prefix,
+                        message ?: "",
+                        syslog_identifier_full(gl.imm.syslog_identifier),
+                        "SYSLOG_PID=%ld",
+                        (long) getpid(),
+                        "SYSLOG_FACILITY=3",
+                        "GLIB_DOMAIN=%s",
+                        log_domain ?: "",
+                        "GLIB_LEVEL=%d",
+                        (int) (level & G_LOG_LEVEL_MASK),
+                        "TIMESTAMP_MONOTONIC=%lld.%06lld",
+                        (long long) (now / NM_UTILS_NSEC_PER_SEC),
+                        (long long) ((now % NM_UTILS_NSEC_PER_SEC) / 1000),
+                        "TIMESTAMP_BOOTTIME=%lld.%06lld",
+                        (long long) (boottime / NM_UTILS_NSEC_PER_SEC),
+                        (long long) ((boottime % NM_UTILS_NSEC_PER_SEC) / 1000),
+                        NULL);
+    } break;
 #endif
-	default:
-		syslog (syslog_priority, "%s%s", gl.imm.prefix, message ?: "");
-		break;
-	}
+    default:
+        syslog(syslog_priority, "%s%s", gl.imm.prefix, message ?: "");
+        break;
+    }
 }
 
 gboolean
-nm_logging_syslog_enabled (void)
+nm_logging_syslog_enabled(void)
 {
-	NM_ASSERT_ON_MAIN_THREAD ();
+    NM_ASSERT_ON_MAIN_THREAD();
 
-	return gl.imm.uses_syslog;
+    return gl.imm.uses_syslog;
 }
 
 void
-nm_logging_init_pre (const char *syslog_identifier,
-                     char *prefix_take)
+nm_logging_init_pre(const char *syslog_identifier, char *prefix_take)
 {
-	/* this function may be called zero or one times, and only
-	 * - on the main thread
-	 * - not after nm_logging_init(). */
+    /* this function may be called zero or one times, and only
+     * - on the main thread
+     * - not after nm_logging_init(). */
 
-	NM_ASSERT_ON_MAIN_THREAD ();
+    NM_ASSERT_ON_MAIN_THREAD();
 
-	if (gl.imm.init_pre_done)
-		g_return_if_reached ();
+    if (gl.imm.init_pre_done)
+        g_return_if_reached();
 
-	if (gl.imm.init_done)
-		g_return_if_reached ();
+    if (gl.imm.init_done)
+        g_return_if_reached();
 
-	if (!_syslog_identifier_valid_domain (syslog_identifier))
-		g_return_if_reached ();
+    if (!_syslog_identifier_valid_domain(syslog_identifier))
+        g_return_if_reached();
 
-	if (!prefix_take || !prefix_take[0])
-		g_return_if_reached ();
+    if (!prefix_take || !prefix_take[0])
+        g_return_if_reached();
 
-	G_LOCK (log);
+    G_LOCK(log);
 
-	gl.mut.init_pre_done = TRUE;
+    gl.mut.init_pre_done = TRUE;
 
-	gl.mut.syslog_identifier = g_strdup_printf ("SYSLOG_IDENTIFIER=%s", syslog_identifier);
-	nm_assert (_syslog_identifier_assert (gl.imm.syslog_identifier));
+    gl.mut.syslog_identifier = g_strdup_printf("SYSLOG_IDENTIFIER=%s", syslog_identifier);
+    nm_assert(_syslog_identifier_assert(gl.imm.syslog_identifier));
 
-	/* we pass the allocated string on and never free it. */
-	gl.mut.prefix = prefix_take;
+    /* we pass the allocated string on and never free it. */
+    gl.mut.prefix = prefix_take;
 
-	G_UNLOCK (log);
+    G_UNLOCK(log);
 }
 
 void
-nm_logging_init (const char *logging_backend, gboolean debug)
+nm_logging_init(const char *logging_backend, gboolean debug)
 {
-	gboolean fetch_monotonic_timestamp = FALSE;
-	gboolean obsolete_debug_backend = FALSE;
-	LogBackend x_log_backend;
-
-	/* this function may be called zero or one times, and only on the
-	 * main thread. */
+    gboolean   fetch_monotonic_timestamp = FALSE;
+    gboolean   obsolete_debug_backend    = FALSE;
+    LogBackend x_log_backend;
 
-	NM_ASSERT_ON_MAIN_THREAD ();
+    /* this function may be called zero or one times, and only on the
+     * main thread. */
 
-	nm_assert (NM_IN_STRSET (""NM_CONFIG_DEFAULT_LOGGING_BACKEND,
-	                         NM_LOG_CONFIG_BACKEND_JOURNAL,
-	                         NM_LOG_CONFIG_BACKEND_SYSLOG));
+    NM_ASSERT_ON_MAIN_THREAD();
 
-	if (gl.imm.init_done)
-		g_return_if_reached ();
+    nm_assert(NM_IN_STRSET("" NM_CONFIG_DEFAULT_LOGGING_BACKEND,
+                           NM_LOG_CONFIG_BACKEND_JOURNAL,
+                           NM_LOG_CONFIG_BACKEND_SYSLOG));
 
-	if (!logging_backend)
-		logging_backend = ""NM_CONFIG_DEFAULT_LOGGING_BACKEND;
+    if (gl.imm.init_done)
+        g_return_if_reached();
 
-	if (nm_streq (logging_backend, NM_LOG_CONFIG_BACKEND_DEBUG)) {
-		/* "debug" was wrongly documented as a valid logging backend. It makes no sense however,
-		 * because printing to stderr only makes sense when not demonizing. Whether to daemonize
-		 * is only controlled via command line arguments (--no-daemon, --debug) and not via the
-		 * logging backend from configuration.
-		 *
-		 * Fall back to the default. */
-		logging_backend = ""NM_CONFIG_DEFAULT_LOGGING_BACKEND;
-		obsolete_debug_backend = TRUE;
-	}
+    if (!logging_backend)
+        logging_backend = "" NM_CONFIG_DEFAULT_LOGGING_BACKEND;
 
+    if (nm_streq(logging_backend, NM_LOG_CONFIG_BACKEND_DEBUG)) {
+        /* "debug" was wrongly documented as a valid logging backend. It makes no sense however,
+         * because printing to stderr only makes sense when not demonizing. Whether to daemonize
+         * is only controlled via command line arguments (--no-daemon, --debug) and not via the
+         * logging backend from configuration.
+         *
+         * Fall back to the default. */
+        logging_backend        = "" NM_CONFIG_DEFAULT_LOGGING_BACKEND;
+        obsolete_debug_backend = TRUE;
+    }
 
-	G_LOCK (log);
+    G_LOCK(log);
 
 #if SYSTEMD_JOURNAL
-	if (!nm_streq (logging_backend, NM_LOG_CONFIG_BACKEND_SYSLOG)) {
-		x_log_backend = LOG_BACKEND_JOURNAL;
+    if (!nm_streq(logging_backend, NM_LOG_CONFIG_BACKEND_SYSLOG)) {
+        x_log_backend = LOG_BACKEND_JOURNAL;
 
-		/* We only log the monotonic-timestamp with structured logging (journal).
-		 * Only in this case, fetch the timestamp. */
-		fetch_monotonic_timestamp = TRUE;
-	} else
+        /* We only log the monotonic-timestamp with structured logging (journal).
+         * Only in this case, fetch the timestamp. */
+        fetch_monotonic_timestamp = TRUE;
+    } else
 #endif
-	{
-		x_log_backend = LOG_BACKEND_SYSLOG;
-		openlog (syslog_identifier_domain (gl.imm.syslog_identifier), LOG_PID, LOG_DAEMON);
-	}
-
-	gl.mut.init_done = TRUE;
-	gl.mut.log_backend = x_log_backend;
-	gl.mut.uses_syslog = TRUE;
-	gl.mut.debug_stderr = debug;
-
-	g_log_set_handler (syslog_identifier_domain (gl.imm.syslog_identifier),
-	                   G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL | G_LOG_FLAG_RECURSION,
-	                   nm_log_handler,
-	                   NULL);
-
-	G_UNLOCK (log);
-
-
-	if (fetch_monotonic_timestamp) {
-		/* ensure we read a monotonic timestamp. Reading the timestamp the first
-		 * time causes a logging message. We don't want to do that during _nm_log_impl. */
-		nm_utils_get_monotonic_timestamp_nsec ();
-	}
-
-	if (obsolete_debug_backend)
-		nm_log_dbg (LOGD_CORE, "config: ignore deprecated logging backend 'debug', fallback to '%s'", logging_backend);
-
-	if (nm_streq (logging_backend, NM_LOG_CONFIG_BACKEND_SYSLOG)) {
-		/* good */
-	} else if (nm_streq (logging_backend, NM_LOG_CONFIG_BACKEND_JOURNAL)) {
+    {
+        x_log_backend = LOG_BACKEND_SYSLOG;
+        openlog(syslog_identifier_domain(gl.imm.syslog_identifier), LOG_PID, LOG_DAEMON);
+    }
+
+    gl.mut.init_done    = TRUE;
+    gl.mut.log_backend  = x_log_backend;
+    gl.mut.uses_syslog  = TRUE;
+    gl.mut.debug_stderr = debug;
+
+    g_log_set_handler(syslog_identifier_domain(gl.imm.syslog_identifier),
+                      G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL | G_LOG_FLAG_RECURSION,
+                      nm_log_handler,
+                      NULL);
+
+    G_UNLOCK(log);
+
+    if (fetch_monotonic_timestamp) {
+        /* ensure we read a monotonic timestamp. Reading the timestamp the first
+         * time causes a logging message. We don't want to do that during _nm_log_impl. */
+        nm_utils_get_monotonic_timestamp_nsec();
+    }
+
+    if (obsolete_debug_backend)
+        nm_log_dbg(LOGD_CORE,
+                   "config: ignore deprecated logging backend 'debug', fallback to '%s'",
+                   logging_backend);
+
+    if (nm_streq(logging_backend, NM_LOG_CONFIG_BACKEND_SYSLOG)) {
+        /* good */
+    } else if (nm_streq(logging_backend, NM_LOG_CONFIG_BACKEND_JOURNAL)) {
 #if !SYSTEMD_JOURNAL
-		nm_log_warn (LOGD_CORE, "config: logging backend 'journal' is not available, fallback to 'syslog'");
+        nm_log_warn(LOGD_CORE,
+                    "config: logging backend 'journal' is not available, fallback to 'syslog'");
 #endif
-	} else {
-		nm_log_warn (LOGD_CORE, "config: invalid logging backend '%s', fallback to '%s'",
-		             logging_backend,
+    } else {
+        nm_log_warn(LOGD_CORE,
+                    "config: invalid logging backend '%s', fallback to '%s'",
+                    logging_backend,
 #if SYSTEMD_JOURNAL
-		             NM_LOG_CONFIG_BACKEND_JOURNAL
+                    NM_LOG_CONFIG_BACKEND_JOURNAL
 #else
-		             NM_LOG_CONFIG_BACKEND_SYSLOG
+                    NM_LOG_CONFIG_BACKEND_SYSLOG
 #endif
-		             );
-	}
+        );
+    }
 }