summary refs log tree commit diff
path: root/clients/common/nm-client-utils.c
diff options
context:
space:
mode:
authorMichael Biebl <biebl@debian.org>2020-10-05 22:27:18 +0200
committerMichael Biebl <biebl@debian.org>2020-10-05 22:27:18 +0200
commitaafc1dbe4712c86189bbc1d4d54ad8cb4c69be7e (patch)
treea2a9bb4d007339a0b1304540388230ccedac32bd /clients/common/nm-client-utils.c
parente7b44ef4c80907346ec7492a09c45277459924fc (diff)
New upstream version 1.27.90 upstream/1.27.90
Diffstat (limited to 'clients/common/nm-client-utils.c')
-rw-r--r--clients/common/nm-client-utils.c1382
1 files changed, 729 insertions, 653 deletions
diff --git a/clients/common/nm-client-utils.c b/clients/common/nm-client-utils.c
index d3a02161..e3d3c46a 100644
--- a/clients/common/nm-client-utils.c
+++ b/clients/common/nm-client-utils.c
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0+
+/* SPDX-License-Identifier: GPL-2.0+ */
 /*
  * Copyright (C) 2010 - 2017 Red Hat, Inc.
  */
@@ -17,41 +17,36 @@
 /*****************************************************************************/
 
 static int
-_nmc_objects_sort_by_path_cmp (gconstpointer pa, gconstpointer pb, gpointer user_data)
+_nmc_objects_sort_by_path_cmp(gconstpointer pa, gconstpointer pb, gpointer user_data)
 {
-	NMObject *a = *((NMObject **) pa);
-	NMObject *b = *((NMObject **) pb);
+    NMObject *a = *((NMObject **) pa);
+    NMObject *b = *((NMObject **) pb);
 
-	NM_CMP_SELF (a, b);
-	NM_CMP_RETURN (nm_utils_dbus_path_cmp (nm_object_get_path (a),
-	                                       nm_object_get_path (b)));
-	return 0;
+    NM_CMP_SELF(a, b);
+    NM_CMP_RETURN(nm_utils_dbus_path_cmp(nm_object_get_path(a), nm_object_get_path(b)));
+    return 0;
 }
 
 const NMObject **
-nmc_objects_sort_by_path (const NMObject *const* objs, gssize len)
+nmc_objects_sort_by_path(const NMObject *const *objs, gssize len)
 {
-	const NMObject **arr;
-	gsize i, l;
-
-	if (len < 0)
-		l = NM_PTRARRAY_LEN (objs);
-	else
-		l = len;
-
-	arr = g_new (const NMObject *, l + 1);
-	for (i = 0; i < l; i++)
-		arr[i] = objs[i];
-	arr[l] = NULL;
-
-	if (l > 1) {
-		g_qsort_with_data (arr,
-		                   l,
-		                   sizeof (gpointer),
-		                   _nmc_objects_sort_by_path_cmp,
-		                   NULL);
-	}
-	return arr;
+    const NMObject **arr;
+    gsize            i, l;
+
+    if (len < 0)
+        l = NM_PTRARRAY_LEN(objs);
+    else
+        l = len;
+
+    arr = g_new(const NMObject *, l + 1);
+    for (i = 0; i < l; i++)
+        arr[i] = objs[i];
+    arr[l] = NULL;
+
+    if (l > 1) {
+        g_qsort_with_data(arr, l, sizeof(gpointer), _nmc_objects_sort_by_path_cmp, NULL);
+    }
+    return arr;
 }
 
 /*****************************************************************************/
@@ -60,100 +55,117 @@ nmc_objects_sort_by_path (const NMObject *const* objs, gssize len)
  * If required, the resulting number is checked to be in the <min,max> range.
  */
 static gboolean
-nmc_string_to_uint_base (const char *str,
-                         int base,
-                         gboolean range_check,
-                         unsigned long int min,
-                         unsigned long int max,
-                         unsigned long int *value)
+nmc_string_to_uint_base(const char *       str,
+                        int                base,
+                        gboolean           range_check,
+                        unsigned long int  min,
+                        unsigned long int  max,
+                        unsigned long int *value)
 {
-	char *end;
-	unsigned long int tmp;
-
-	if (!str || !str[0])
-		return FALSE;
-
-	/* FIXME: don't use this function, replace by _nm_utils_ascii_str_to_int64() */
-	errno = 0;
-	tmp = strtoul (str, &end, base);
-	if (errno || *end != '\0' || (range_check && (tmp < min || tmp > max))) {
-		return FALSE;
-	}
-	*value = tmp;
-	return TRUE;
+    char *            end;
+    unsigned long int tmp;
+
+    if (!str || !str[0])
+        return FALSE;
+
+    /* FIXME: don't use this function, replace by _nm_utils_ascii_str_to_int64() */
+    errno = 0;
+    tmp   = strtoul(str, &end, base);
+    if (errno || *end != '\0' || (range_check && (tmp < min || tmp > max))) {
+        return FALSE;
+    }
+    *value = tmp;
+    return TRUE;
 }
 
 gboolean
-nmc_string_to_uint (const char *str,
-                    gboolean range_check,
-                    unsigned long int min,
-                    unsigned long int max,
-                    unsigned long int *value)
+nmc_string_to_uint(const char *       str,
+                   gboolean           range_check,
+                   unsigned long int  min,
+                   unsigned long int  max,
+                   unsigned long int *value)
 {
-	return nmc_string_to_uint_base (str, 10, range_check, min, max, value);
+    return nmc_string_to_uint_base(str, 10, range_check, min, max, value);
 }
 
 gboolean
-nmc_string_to_bool (const char *str, gboolean *val_bool, GError **error)
+nmc_string_to_bool(const char *str, gboolean *val_bool, GError **error)
 {
-	const char *s_true[] = { "true", "yes", "on", "1", NULL };
-	const char *s_false[] = { "false", "no", "off", "0", NULL };
-
-	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
-
-	if (g_strcmp0 (str, "o") == 0) {
-		g_set_error (error, 1, 0,
-		             /* TRANSLATORS: the first %s is the partial value entered by
-		              * the user, the second %s a list of compatible values.
-		              */
-		             _("'%s' is ambiguous (%s)"), str, "on x off");
-		return FALSE;
-	}
-
-	if (nmc_string_is_valid (str, s_true, NULL))
-		*val_bool = TRUE;
-	else if (nmc_string_is_valid (str, s_false, NULL))
-		*val_bool = FALSE;
-	else {
-		g_set_error (error, 1, 0,
-		             _("'%s' is not valid; use [%s] or [%s]"),
-		             str, "true, yes, on", "false, no, off");
-		return FALSE;
-	}
-	return TRUE;
+    const char *s_true[]  = {"true", "yes", "on", "1", NULL};
+    const char *s_false[] = {"false", "no", "off", "0", NULL};
+
+    g_return_val_if_fail(error == NULL || *error == NULL, FALSE);
+
+    if (g_strcmp0(str, "o") == 0) {
+        g_set_error(error,
+                    1,
+                    0,
+                    /* TRANSLATORS: the first %s is the partial value entered by
+                     * the user, the second %s a list of compatible values.
+                     */
+                    _("'%s' is ambiguous (%s)"),
+                    str,
+                    "on x off");
+        return FALSE;
+    }
+
+    if (nmc_string_is_valid(str, s_true, NULL))
+        *val_bool = TRUE;
+    else if (nmc_string_is_valid(str, s_false, NULL))
+        *val_bool = FALSE;
+    else {
+        g_set_error(error,
+                    1,
+                    0,
+                    _("'%s' is not valid; use [%s] or [%s]"),
+                    str,
+                    "true, yes, on",
+                    "false, no, off");
+        return FALSE;
+    }
+    return TRUE;
 }
 
 gboolean
-nmc_string_to_ternary (const char *str, NMTernary *val, GError **error)
+nmc_string_to_ternary(const char *str, NMTernary *val, GError **error)
 {
-	const char *s_true[] = { "true", "yes", "on", NULL };
-	const char *s_false[] = { "false", "no", "off", NULL };
-	const char *s_unknown[] = { "unknown", NULL };
-
-	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
-
-	if (g_strcmp0 (str, "o") == 0) {
-		g_set_error (error, 1, 0,
-		             /* TRANSLATORS: the first %s is the partial value entered by
-		              * the user, the second %s a list of compatible values.
-		              */
-		             _("'%s' is ambiguous (%s)"), str, "on x off");
-		return FALSE;
-	}
-
-	if (nmc_string_is_valid (str, s_true, NULL))
-		*val = NM_TERNARY_TRUE;
-	else if (nmc_string_is_valid (str, s_false, NULL))
-		*val = NM_TERNARY_FALSE;
-	else if (nmc_string_is_valid (str, s_unknown, NULL))
-		*val = NM_TERNARY_DEFAULT;
-	else {
-		g_set_error (error, 1, 0,
-		             _("'%s' is not valid; use [%s], [%s] or [%s]"),
-		             str, "true, yes, on", "false, no, off", "unknown");
-		return FALSE;
-	}
-	return TRUE;
+    const char *s_true[]    = {"true", "yes", "on", NULL};
+    const char *s_false[]   = {"false", "no", "off", NULL};
+    const char *s_unknown[] = {"unknown", NULL};
+
+    g_return_val_if_fail(error == NULL || *error == NULL, FALSE);
+
+    if (g_strcmp0(str, "o") == 0) {
+        g_set_error(error,
+                    1,
+                    0,
+                    /* TRANSLATORS: the first %s is the partial value entered by
+                     * the user, the second %s a list of compatible values.
+                     */
+                    _("'%s' is ambiguous (%s)"),
+                    str,
+                    "on x off");
+        return FALSE;
+    }
+
+    if (nmc_string_is_valid(str, s_true, NULL))
+        *val = NM_TERNARY_TRUE;
+    else if (nmc_string_is_valid(str, s_false, NULL))
+        *val = NM_TERNARY_FALSE;
+    else if (nmc_string_is_valid(str, s_unknown, NULL))
+        *val = NM_TERNARY_DEFAULT;
+    else {
+        g_set_error(error,
+                    1,
+                    0,
+                    _("'%s' is not valid; use [%s], [%s] or [%s]"),
+                    str,
+                    "true, yes, on",
+                    "false, no, off",
+                    "unknown");
+        return FALSE;
+    }
+    return TRUE;
 }
 
 /*
@@ -163,349 +175,411 @@ nmc_string_to_ternary (const char *str, NMTernary *val, GError **error)
  * On failure: error->code : 0 - string not found; 1 - string is ambiguous
  */
 const char *
-nmc_string_is_valid (const char *input, const char **allowed, GError **error)
+nmc_string_is_valid(const char *input, const char **allowed, GError **error)
 {
-	const char **p;
-	size_t input_ln, p_len;
-	const char *partial_match = NULL;
-	gboolean ambiguous = FALSE;
-
-	g_return_val_if_fail (!error || !*error, NULL);
-
-	if (!input || !*input)
-		goto finish;
-
-	input_ln = strlen (input);
-	for (p = allowed; p && *p; p++) {
-		p_len = strlen (*p);
-		if (g_ascii_strncasecmp (input, *p, input_ln) == 0) {
-			if (input_ln == p_len)
-				return *p;
-			if (!partial_match)
-				partial_match = *p;
-			else
-				ambiguous = TRUE;
-		}
-	}
-
-	if (ambiguous) {
-		GString *candidates = g_string_new ("");
-
-		for (p = allowed; *p; p++) {
-			if (g_ascii_strncasecmp (input, *p, input_ln) == 0) {
-				if (candidates->len > 0)
-					g_string_append (candidates, ", ");
-				g_string_append (candidates, *p);
-			}
-		}
-		g_set_error (error, 1, 1, _("'%s' is ambiguous: %s"),
-		             input, candidates->str);
-		g_string_free (candidates, TRUE);
-		return NULL;
-	}
+    const char **p;
+    size_t       input_ln, p_len;
+    const char * partial_match = NULL;
+    gboolean     ambiguous     = FALSE;
+
+    g_return_val_if_fail(!error || !*error, NULL);
+
+    if (!input || !*input)
+        goto finish;
+
+    input_ln = strlen(input);
+    for (p = allowed; p && *p; p++) {
+        p_len = strlen(*p);
+        if (g_ascii_strncasecmp(input, *p, input_ln) == 0) {
+            if (input_ln == p_len)
+                return *p;
+            if (!partial_match)
+                partial_match = *p;
+            else
+                ambiguous = TRUE;
+        }
+    }
+
+    if (ambiguous) {
+        GString *candidates = g_string_new("");
+
+        for (p = allowed; *p; p++) {
+            if (g_ascii_strncasecmp(input, *p, input_ln) == 0) {
+                if (candidates->len > 0)
+                    g_string_append(candidates, ", ");
+                g_string_append(candidates, *p);
+            }
+        }
+        g_set_error(error, 1, 1, _("'%s' is ambiguous: %s"), input, candidates->str);
+        g_string_free(candidates, TRUE);
+        return NULL;
+    }
 finish:
-	if (!partial_match) {
-		char *valid_vals = g_strjoinv (", ", (char **) allowed);
+    if (!partial_match) {
+        char *valid_vals = g_strjoinv(", ", (char **) allowed);
 
-		if (!input || !*input)
-			g_set_error (error, 1, 0, _("missing name, try one of [%s]"), valid_vals);
-		else
-			g_set_error (error, 1, 0, _("'%s' not among [%s]"), input, valid_vals);
+        if (!input || !*input)
+            g_set_error(error, 1, 0, _("missing name, try one of [%s]"), valid_vals);
+        else
+            g_set_error(error, 1, 0, _("'%s' not among [%s]"), input, valid_vals);
 
-		g_free (valid_vals);
-	}
+        g_free(valid_vals);
+    }
 
-	return partial_match;
+    return partial_match;
 }
 
 gboolean
-matches (const char *cmd, const char *pattern)
+matches(const char *cmd, const char *pattern)
 {
-	size_t len = strlen (cmd);
-	if (!len || len > strlen (pattern))
-		return FALSE;
-	return memcmp (pattern, cmd, len) == 0;
+    size_t len = strlen(cmd);
+    if (!len || len > strlen(pattern))
+        return FALSE;
+    return memcmp(pattern, cmd, len) == 0;
 }
 
 const char *
-nmc_bond_validate_mode (const char *mode, GError **error)
+nmc_bond_validate_mode(const char *mode, GError **error)
 {
-	unsigned long mode_int;
-	static const char *valid_modes[] = { "balance-rr",
-	                                     "active-backup",
-	                                     "balance-xor",
-	                                     "broadcast",
-	                                     "802.3ad",
-	                                     "balance-tlb",
-	                                     "balance-alb",
-	                                     NULL };
-	if (nmc_string_to_uint (mode, TRUE, 0, 6, &mode_int)) {
-		/* Translate bonding mode numbers to mode names:
-		 * https://www.kernel.org/doc/Documentation/networking/bonding.txt
-		 */
-		return valid_modes[mode_int];
-	} else
-		return nmc_string_is_valid (mode, valid_modes, error);
+    unsigned long      mode_int;
+    static const char *valid_modes[] = {"balance-rr",
+                                        "active-backup",
+                                        "balance-xor",
+                                        "broadcast",
+                                        "802.3ad",
+                                        "balance-tlb",
+                                        "balance-alb",
+                                        NULL};
+    if (nmc_string_to_uint(mode, TRUE, 0, 6, &mode_int)) {
+        /* Translate bonding mode numbers to mode names:
+         * https://www.kernel.org/doc/Documentation/networking/bonding.txt
+         */
+        return valid_modes[mode_int];
+    } else
+        return nmc_string_is_valid(mode, valid_modes, error);
 }
 
-NM_UTILS_LOOKUP_STR_DEFINE (nmc_device_state_to_string, NMDeviceState,
-	NM_UTILS_LOOKUP_DEFAULT (N_("unknown")),
-	NM_UTILS_LOOKUP_ITEM (NM_DEVICE_STATE_UNMANAGED,    N_("unmanaged")),
-	NM_UTILS_LOOKUP_ITEM (NM_DEVICE_STATE_UNAVAILABLE,  N_("unavailable")),
-	NM_UTILS_LOOKUP_ITEM (NM_DEVICE_STATE_DISCONNECTED, N_("disconnected")),
-	NM_UTILS_LOOKUP_ITEM (NM_DEVICE_STATE_PREPARE,      N_("connecting (prepare)")),
-	NM_UTILS_LOOKUP_ITEM (NM_DEVICE_STATE_CONFIG,       N_("connecting (configuring)")),
-	NM_UTILS_LOOKUP_ITEM (NM_DEVICE_STATE_NEED_AUTH,    N_("connecting (need authentication)")),
-	NM_UTILS_LOOKUP_ITEM (NM_DEVICE_STATE_IP_CONFIG,    N_("connecting (getting IP configuration)")),
-	NM_UTILS_LOOKUP_ITEM (NM_DEVICE_STATE_IP_CHECK,     N_("connecting (checking IP connectivity)")),
-	NM_UTILS_LOOKUP_ITEM (NM_DEVICE_STATE_SECONDARIES,  N_("connecting (starting secondary connections)")),
-	NM_UTILS_LOOKUP_ITEM (NM_DEVICE_STATE_ACTIVATED,    N_("connected")),
-	NM_UTILS_LOOKUP_ITEM (NM_DEVICE_STATE_DEACTIVATING, N_("deactivating")),
-	NM_UTILS_LOOKUP_ITEM (NM_DEVICE_STATE_FAILED,       N_("connection failed")),
-	NM_UTILS_LOOKUP_ITEM (NM_DEVICE_STATE_UNKNOWN,      N_("unknown")),
-)
-
-static
-NM_UTILS_LOOKUP_STR_DEFINE (_device_state_to_string, NMDeviceState,
-	NM_UTILS_LOOKUP_DEFAULT (NULL),
-	NM_UTILS_LOOKUP_ITEM (NM_DEVICE_STATE_PREPARE,      N_("connecting (externally)")),
-	NM_UTILS_LOOKUP_ITEM (NM_DEVICE_STATE_CONFIG,       N_("connecting (externally)")),
-	NM_UTILS_LOOKUP_ITEM (NM_DEVICE_STATE_NEED_AUTH,    N_("connecting (externally)")),
-	NM_UTILS_LOOKUP_ITEM (NM_DEVICE_STATE_IP_CONFIG,    N_("connecting (externally)")),
-	NM_UTILS_LOOKUP_ITEM (NM_DEVICE_STATE_IP_CHECK,     N_("connecting (externally)")),
-	NM_UTILS_LOOKUP_ITEM (NM_DEVICE_STATE_SECONDARIES,  N_("connecting (externally)")),
-	NM_UTILS_LOOKUP_ITEM (NM_DEVICE_STATE_ACTIVATED,    N_("connected (externally)")),
-	NM_UTILS_LOOKUP_ITEM (NM_DEVICE_STATE_DEACTIVATING, N_("deactivating (externally)")),
-	NM_UTILS_LOOKUP_ITEM (NM_DEVICE_STATE_FAILED,       N_("deactivating (externally)")),
-	NM_UTILS_LOOKUP_ITEM_IGNORE_OTHER (),
-)
+NM_UTILS_LOOKUP_STR_DEFINE(
+    nmc_device_state_to_string,
+    NMDeviceState,
+    NM_UTILS_LOOKUP_DEFAULT(N_("unknown")),
+    NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_UNMANAGED, N_("unmanaged")),
+    NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_UNAVAILABLE, N_("unavailable")),
+    NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_DISCONNECTED, N_("disconnected")),
+    NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_PREPARE, N_("connecting (prepare)")),
+    NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_CONFIG, N_("connecting (configuring)")),
+    NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_NEED_AUTH, N_("connecting (need authentication)")),
+    NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_IP_CONFIG, N_("connecting (getting IP configuration)")),
+    NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_IP_CHECK, N_("connecting (checking IP connectivity)")),
+    NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_SECONDARIES,
+                         N_("connecting (starting secondary connections)")),
+    NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_ACTIVATED, N_("connected")),
+    NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_DEACTIVATING, N_("deactivating")),
+    NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_FAILED, N_("connection failed")),
+    NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_UNKNOWN, N_("unknown")), );
+
+static NM_UTILS_LOOKUP_STR_DEFINE(
+    _device_state_to_string,
+    NMDeviceState,
+    NM_UTILS_LOOKUP_DEFAULT(NULL),
+    NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_PREPARE, N_("connecting (externally)")),
+    NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_CONFIG, N_("connecting (externally)")),
+    NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_NEED_AUTH, N_("connecting (externally)")),
+    NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_IP_CONFIG, N_("connecting (externally)")),
+    NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_IP_CHECK, N_("connecting (externally)")),
+    NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_SECONDARIES, N_("connecting (externally)")),
+    NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_ACTIVATED, N_("connected (externally)")),
+    NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_DEACTIVATING, N_("deactivating (externally)")),
+    NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_FAILED, N_("deactivating (externally)")),
+    NM_UTILS_LOOKUP_ITEM_IGNORE_OTHER(), );
 
 const char *
-nmc_device_state_to_string_with_external (NMDevice *device)
+nmc_device_state_to_string_with_external(NMDevice *device)
 {
-	NMActiveConnection *ac;
-	NMDeviceState state;
-	const char *s;
+    NMActiveConnection *ac;
+    NMDeviceState       state;
+    const char *        s;
 
-	state = nm_device_get_state (device);
+    state = nm_device_get_state(device);
 
-	if (   (ac = nm_device_get_active_connection (device))
-	    && NM_FLAGS_HAS (nm_active_connection_get_state_flags (ac), NM_ACTIVATION_STATE_FLAG_EXTERNAL)
-	    && (s = _device_state_to_string (state)))
-		return s;
+    if ((ac = nm_device_get_active_connection(device))
+        && NM_FLAGS_HAS(nm_active_connection_get_state_flags(ac), NM_ACTIVATION_STATE_FLAG_EXTERNAL)
+        && (s = _device_state_to_string(state)))
+        return s;
 
-	return nmc_device_state_to_string (state);
+    return nmc_device_state_to_string(state);
 }
 
-NM_UTILS_LOOKUP_STR_DEFINE (nmc_device_metered_to_string, NMMetered,
-	NM_UTILS_LOOKUP_DEFAULT (N_("unknown")),
-	NM_UTILS_LOOKUP_ITEM (NM_METERED_YES,       N_("yes")),
-	NM_UTILS_LOOKUP_ITEM (NM_METERED_NO,        N_("no")),
-	NM_UTILS_LOOKUP_ITEM (NM_METERED_GUESS_YES, N_("yes (guessed)")),
-	NM_UTILS_LOOKUP_ITEM (NM_METERED_GUESS_NO,  N_("no (guessed)")),
-	NM_UTILS_LOOKUP_ITEM (NM_METERED_UNKNOWN,   N_("unknown")),
-)
-
-NM_UTILS_LOOKUP_STR_DEFINE (nmc_device_reason_to_string, NMDeviceStateReason,
-	/* TRANSLATORS: Unknown reason for a device state change (NMDeviceStateReason) */
-	NM_UTILS_LOOKUP_DEFAULT (N_("Unknown")),
-	NM_UTILS_LOOKUP_ITEM (NM_DEVICE_STATE_REASON_NONE,                           N_("No reason given")),
-	NM_UTILS_LOOKUP_ITEM (NM_DEVICE_STATE_REASON_UNKNOWN,                        N_("Unknown error")),
-	NM_UTILS_LOOKUP_ITEM (NM_DEVICE_STATE_REASON_NOW_MANAGED,                    N_("Device is now managed")),
-	NM_UTILS_LOOKUP_ITEM (NM_DEVICE_STATE_REASON_NOW_UNMANAGED,                  N_("Device is now unmanaged")),
-	NM_UTILS_LOOKUP_ITEM (NM_DEVICE_STATE_REASON_CONFIG_FAILED,                  N_("The device could not be readied for configuration")),
-	NM_UTILS_LOOKUP_ITEM (NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE,          N_("IP configuration could not be reserved (no available address, timeout, etc.)")),
-	NM_UTILS_LOOKUP_ITEM (NM_DEVICE_STATE_REASON_IP_CONFIG_EXPIRED,              N_("The IP configuration is no longer valid")),
-	NM_UTILS_LOOKUP_ITEM (NM_DEVICE_STATE_REASON_NO_SECRETS,                     N_("Secrets were required, but not provided")),
-	NM_UTILS_LOOKUP_ITEM (NM_DEVICE_STATE_REASON_SUPPLICANT_DISCONNECT,          N_("802.1X supplicant disconnected")),
-	NM_UTILS_LOOKUP_ITEM (NM_DEVICE_STATE_REASON_SUPPLICANT_CONFIG_FAILED,       N_("802.1X supplicant configuration failed")),
-	NM_UTILS_LOOKUP_ITEM (NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED,              N_("802.1X supplicant failed")),
-	NM_UTILS_LOOKUP_ITEM (NM_DEVICE_STATE_REASON_SUPPLICANT_TIMEOUT,             N_("802.1X supplicant took too long to authenticate")),
-	NM_UTILS_LOOKUP_ITEM (NM_DEVICE_STATE_REASON_PPP_START_FAILED,               N_("PPP service failed to start")),
-	NM_UTILS_LOOKUP_ITEM (NM_DEVICE_STATE_REASON_PPP_DISCONNECT,                 N_("PPP service disconnected")),
-	NM_UTILS_LOOKUP_ITEM (NM_DEVICE_STATE_REASON_PPP_FAILED,                     N_("PPP failed")),
-	NM_UTILS_LOOKUP_ITEM (NM_DEVICE_STATE_REASON_DHCP_START_FAILED,              N_("DHCP client failed to start")),
-	NM_UTILS_LOOKUP_ITEM (NM_DEVICE_STATE_REASON_DHCP_ERROR,                     N_("DHCP client error")),
-	NM_UTILS_LOOKUP_ITEM (NM_DEVICE_STATE_REASON_DHCP_FAILED,                    N_("DHCP client failed")),
-	NM_UTILS_LOOKUP_ITEM (NM_DEVICE_STATE_REASON_SHARED_START_FAILED,            N_("Shared connection service failed to start")),
-	NM_UTILS_LOOKUP_ITEM (NM_DEVICE_STATE_REASON_SHARED_FAILED,                  N_("Shared connection service failed")),
-	NM_UTILS_LOOKUP_ITEM (NM_DEVICE_STATE_REASON_AUTOIP_START_FAILED,            N_("AutoIP service failed to start")),
-	NM_UTILS_LOOKUP_ITEM (NM_DEVICE_STATE_REASON_AUTOIP_ERROR,                   N_("AutoIP service error")),
-	NM_UTILS_LOOKUP_ITEM (NM_DEVICE_STATE_REASON_AUTOIP_FAILED,                  N_("AutoIP service failed")),
-	NM_UTILS_LOOKUP_ITEM (NM_DEVICE_STATE_REASON_MODEM_BUSY,                     N_("The line is busy")),
-	NM_UTILS_LOOKUP_ITEM (NM_DEVICE_STATE_REASON_MODEM_NO_DIAL_TONE,             N_("No dial tone")),
-	NM_UTILS_LOOKUP_ITEM (NM_DEVICE_STATE_REASON_MODEM_NO_CARRIER,               N_("No carrier could be established")),
-	NM_UTILS_LOOKUP_ITEM (NM_DEVICE_STATE_REASON_MODEM_DIAL_TIMEOUT,             N_("The dialing request timed out")),
-	NM_UTILS_LOOKUP_ITEM (NM_DEVICE_STATE_REASON_MODEM_DIAL_FAILED,              N_("The dialing attempt failed")),
-	NM_UTILS_LOOKUP_ITEM (NM_DEVICE_STATE_REASON_MODEM_INIT_FAILED,              N_("Modem initialization failed")),
-	NM_UTILS_LOOKUP_ITEM (NM_DEVICE_STATE_REASON_GSM_APN_FAILED,                 N_("Failed to select the specified APN")),
-	NM_UTILS_LOOKUP_ITEM (NM_DEVICE_STATE_REASON_GSM_REGISTRATION_NOT_SEARCHING, N_("Not searching for networks")),
-	NM_UTILS_LOOKUP_ITEM (NM_DEVICE_STATE_REASON_GSM_REGISTRATION_DENIED,        N_("Network registration denied")),
-	NM_UTILS_LOOKUP_ITEM (NM_DEVICE_STATE_REASON_GSM_REGISTRATION_TIMEOUT,       N_("Network registration timed out")),
-	NM_UTILS_LOOKUP_ITEM (NM_DEVICE_STATE_REASON_GSM_REGISTRATION_FAILED,        N_("Failed to register with the requested network")),
-	NM_UTILS_LOOKUP_ITEM (NM_DEVICE_STATE_REASON_GSM_PIN_CHECK_FAILED,           N_("PIN check failed")),
-	NM_UTILS_LOOKUP_ITEM (NM_DEVICE_STATE_REASON_FIRMWARE_MISSING,               N_("Necessary firmware for the device may be missing")),
-	NM_UTILS_LOOKUP_ITEM (NM_DEVICE_STATE_REASON_REMOVED,                        N_("The device was removed")),
-	NM_UTILS_LOOKUP_ITEM (NM_DEVICE_STATE_REASON_SLEEPING,                       N_("NetworkManager went to sleep")),
-	NM_UTILS_LOOKUP_ITEM (NM_DEVICE_STATE_REASON_CONNECTION_REMOVED,             N_("The device's active connection disappeared")),
-	NM_UTILS_LOOKUP_ITEM (NM_DEVICE_STATE_REASON_USER_REQUESTED,                 N_("Device disconnected by user or client")),
-	NM_UTILS_LOOKUP_ITEM (NM_DEVICE_STATE_REASON_CARRIER,                        N_("Carrier/link changed")),
-	NM_UTILS_LOOKUP_ITEM (NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED,             N_("The device's existing connection was assumed")),
-	NM_UTILS_LOOKUP_ITEM (NM_DEVICE_STATE_REASON_SUPPLICANT_AVAILABLE,           N_("The supplicant is now available")),
-	NM_UTILS_LOOKUP_ITEM (NM_DEVICE_STATE_REASON_MODEM_NOT_FOUND,                N_("The modem could not be found")),
-	NM_UTILS_LOOKUP_ITEM (NM_DEVICE_STATE_REASON_BT_FAILED,                      N_("The Bluetooth connection failed or timed out")),
-	NM_UTILS_LOOKUP_ITEM (NM_DEVICE_STATE_REASON_GSM_SIM_NOT_INSERTED,           N_("GSM Modem's SIM card not inserted")),
-	NM_UTILS_LOOKUP_ITEM (NM_DEVICE_STATE_REASON_GSM_SIM_PIN_REQUIRED,           N_("GSM Modem's SIM PIN required")),
-	NM_UTILS_LOOKUP_ITEM (NM_DEVICE_STATE_REASON_GSM_SIM_PUK_REQUIRED,           N_("GSM Modem's SIM PUK required")),
-	NM_UTILS_LOOKUP_ITEM (NM_DEVICE_STATE_REASON_GSM_SIM_WRONG,                  N_("GSM Modem's SIM wrong")),
-	NM_UTILS_LOOKUP_ITEM (NM_DEVICE_STATE_REASON_INFINIBAND_MODE,                N_("InfiniBand device does not support connected mode")),
-	NM_UTILS_LOOKUP_ITEM (NM_DEVICE_STATE_REASON_DEPENDENCY_FAILED,              N_("A dependency of the connection failed")),
-	NM_UTILS_LOOKUP_ITEM (NM_DEVICE_STATE_REASON_BR2684_FAILED,                  N_("A problem with the RFC 2684 Ethernet over ADSL bridge")),
-	NM_UTILS_LOOKUP_ITEM (NM_DEVICE_STATE_REASON_MODEM_MANAGER_UNAVAILABLE,      N_("ModemManager is unavailable")),
-	NM_UTILS_LOOKUP_ITEM (NM_DEVICE_STATE_REASON_SSID_NOT_FOUND,                 N_("The Wi-Fi network could not be found")),
-	NM_UTILS_LOOKUP_ITEM (NM_DEVICE_STATE_REASON_SECONDARY_CONNECTION_FAILED,    N_("A secondary connection of the base connection failed")),
-	NM_UTILS_LOOKUP_ITEM (NM_DEVICE_STATE_REASON_DCB_FCOE_FAILED,                N_("DCB or FCoE setup failed")),
-	NM_UTILS_LOOKUP_ITEM (NM_DEVICE_STATE_REASON_TEAMD_CONTROL_FAILED,           N_("teamd control failed")),
-	NM_UTILS_LOOKUP_ITEM (NM_DEVICE_STATE_REASON_MODEM_FAILED,                   N_("Modem failed or no longer available")),
-	NM_UTILS_LOOKUP_ITEM (NM_DEVICE_STATE_REASON_MODEM_AVAILABLE,                N_("Modem now ready and available")),
-	NM_UTILS_LOOKUP_ITEM (NM_DEVICE_STATE_REASON_SIM_PIN_INCORRECT,              N_("SIM PIN was incorrect")),
-	NM_UTILS_LOOKUP_ITEM (NM_DEVICE_STATE_REASON_NEW_ACTIVATION,                 N_("New connection activation was enqueued")),
-	NM_UTILS_LOOKUP_ITEM (NM_DEVICE_STATE_REASON_PARENT_CHANGED,                 N_("The device's parent changed")),
-	NM_UTILS_LOOKUP_ITEM (NM_DEVICE_STATE_REASON_PARENT_MANAGED_CHANGED,         N_("The device parent's management changed")),
-	NM_UTILS_LOOKUP_ITEM (NM_DEVICE_STATE_REASON_OVSDB_FAILED,                   N_("Open vSwitch database connection failed")),
-	NM_UTILS_LOOKUP_ITEM (NM_DEVICE_STATE_REASON_IP_ADDRESS_DUPLICATE,           N_("A duplicate IP address was detected")),
-	NM_UTILS_LOOKUP_ITEM (NM_DEVICE_STATE_REASON_IP_METHOD_UNSUPPORTED,          N_("The selected IP method is not supported")),
-	NM_UTILS_LOOKUP_ITEM (NM_DEVICE_STATE_REASON_SRIOV_CONFIGURATION_FAILED,     N_("Failed to configure SR-IOV parameters")),
-	NM_UTILS_LOOKUP_ITEM (NM_DEVICE_STATE_REASON_PEER_NOT_FOUND,                 N_("The Wi-Fi P2P peer could not be found")),
-)
-
-NM_UTILS_LOOKUP_STR_DEFINE (nm_active_connection_state_reason_to_string, NMActiveConnectionStateReason,
-	/* TRANSLATORS: Unknown reason for a connection state change (NMActiveConnectionStateReason) */
-	NM_UTILS_LOOKUP_DEFAULT (N_("Unknown")),
-	NM_UTILS_LOOKUP_ITEM (NM_ACTIVE_CONNECTION_STATE_REASON_UNKNOWN,               N_("Unknown reason")),
-	NM_UTILS_LOOKUP_ITEM (NM_ACTIVE_CONNECTION_STATE_REASON_NONE,                  N_("The connection was disconnected")),
-	NM_UTILS_LOOKUP_ITEM (NM_ACTIVE_CONNECTION_STATE_REASON_USER_DISCONNECTED,     N_("Disconnected by user")),
-	NM_UTILS_LOOKUP_ITEM (NM_ACTIVE_CONNECTION_STATE_REASON_DEVICE_DISCONNECTED,   N_("The base network connection was interrupted")),
-	NM_UTILS_LOOKUP_ITEM (NM_ACTIVE_CONNECTION_STATE_REASON_SERVICE_STOPPED,       N_("The VPN service stopped unexpectedly")),
-	NM_UTILS_LOOKUP_ITEM (NM_ACTIVE_CONNECTION_STATE_REASON_IP_CONFIG_INVALID,     N_("The VPN service returned invalid configuration")),
-	NM_UTILS_LOOKUP_ITEM (NM_ACTIVE_CONNECTION_STATE_REASON_CONNECT_TIMEOUT,       N_("The connection attempt timed out")),
-	NM_UTILS_LOOKUP_ITEM (NM_ACTIVE_CONNECTION_STATE_REASON_SERVICE_START_TIMEOUT, N_("The VPN service did not start in time")),
-	NM_UTILS_LOOKUP_ITEM (NM_ACTIVE_CONNECTION_STATE_REASON_SERVICE_START_FAILED,  N_("The VPN service failed to start")),
-	NM_UTILS_LOOKUP_ITEM (NM_ACTIVE_CONNECTION_STATE_REASON_NO_SECRETS,            N_("No valid secrets")),
-	NM_UTILS_LOOKUP_ITEM (NM_ACTIVE_CONNECTION_STATE_REASON_LOGIN_FAILED,          N_("Invalid secrets")),
-	NM_UTILS_LOOKUP_ITEM (NM_ACTIVE_CONNECTION_STATE_REASON_CONNECTION_REMOVED,    N_("The connection was removed")),
-	NM_UTILS_LOOKUP_ITEM (NM_ACTIVE_CONNECTION_STATE_REASON_DEPENDENCY_FAILED,     N_("Master connection failed")),
-	NM_UTILS_LOOKUP_ITEM (NM_ACTIVE_CONNECTION_STATE_REASON_DEVICE_REALIZE_FAILED, N_("Could not create a software link")),
-	NM_UTILS_LOOKUP_ITEM (NM_ACTIVE_CONNECTION_STATE_REASON_DEVICE_REMOVED,        N_("The device disappeared")),
-)
+NM_UTILS_LOOKUP_STR_DEFINE(nmc_device_metered_to_string,
+                           NMMetered,
+                           NM_UTILS_LOOKUP_DEFAULT(N_("unknown")),
+                           NM_UTILS_LOOKUP_ITEM(NM_METERED_YES, N_("yes")),
+                           NM_UTILS_LOOKUP_ITEM(NM_METERED_NO, N_("no")),
+                           NM_UTILS_LOOKUP_ITEM(NM_METERED_GUESS_YES, N_("yes (guessed)")),
+                           NM_UTILS_LOOKUP_ITEM(NM_METERED_GUESS_NO, N_("no (guessed)")),
+                           NM_UTILS_LOOKUP_ITEM(NM_METERED_UNKNOWN, N_("unknown")), );
+
+NM_UTILS_LOOKUP_STR_DEFINE(
+    nmc_device_reason_to_string,
+    NMDeviceStateReason,
+    /* TRANSLATORS: Unknown reason for a device state change (NMDeviceStateReason) */
+    NM_UTILS_LOOKUP_DEFAULT(N_("Unknown")),
+    NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_NONE, N_("No reason given")),
+    NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_UNKNOWN, N_("Unknown error")),
+    NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_NOW_MANAGED, N_("Device is now managed")),
+    NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_NOW_UNMANAGED, N_("Device is now unmanaged")),
+    NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_CONFIG_FAILED,
+                         N_("The device could not be readied for configuration")),
+    NM_UTILS_LOOKUP_ITEM(
+        NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE,
+        N_("IP configuration could not be reserved (no available address, timeout, etc.)")),
+    NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_IP_CONFIG_EXPIRED,
+                         N_("The IP configuration is no longer valid")),
+    NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_NO_SECRETS,
+                         N_("Secrets were required, but not provided")),
+    NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_SUPPLICANT_DISCONNECT,
+                         N_("802.1X supplicant disconnected")),
+    NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_SUPPLICANT_CONFIG_FAILED,
+                         N_("802.1X supplicant configuration failed")),
+    NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED, N_("802.1X supplicant failed")),
+    NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_SUPPLICANT_TIMEOUT,
+                         N_("802.1X supplicant took too long to authenticate")),
+    NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_PPP_START_FAILED,
+                         N_("PPP service failed to start")),
+    NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_PPP_DISCONNECT, N_("PPP service disconnected")),
+    NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_PPP_FAILED, N_("PPP failed")),
+    NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_DHCP_START_FAILED,
+                         N_("DHCP client failed to start")),
+    NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_DHCP_ERROR, N_("DHCP client error")),
+    NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_DHCP_FAILED, N_("DHCP client failed")),
+    NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_SHARED_START_FAILED,
+                         N_("Shared connection service failed to start")),
+    NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_SHARED_FAILED,
+                         N_("Shared connection service failed")),
+    NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_AUTOIP_START_FAILED,
+                         N_("AutoIP service failed to start")),
+    NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_AUTOIP_ERROR, N_("AutoIP service error")),
+    NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_AUTOIP_FAILED, N_("AutoIP service failed")),
+    NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_MODEM_BUSY, N_("The line is busy")),
+    NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_MODEM_NO_DIAL_TONE, N_("No dial tone")),
+    NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_MODEM_NO_CARRIER,
+                         N_("No carrier could be established")),
+    NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_MODEM_DIAL_TIMEOUT,
+                         N_("The dialing request timed out")),
+    NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_MODEM_DIAL_FAILED,
+                         N_("The dialing attempt failed")),
+    NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_MODEM_INIT_FAILED,
+                         N_("Modem initialization failed")),
+    NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_GSM_APN_FAILED,
+                         N_("Failed to select the specified APN")),
+    NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_GSM_REGISTRATION_NOT_SEARCHING,
+                         N_("Not searching for networks")),
+    NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_GSM_REGISTRATION_DENIED,
+                         N_("Network registration denied")),
+    NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_GSM_REGISTRATION_TIMEOUT,
+                         N_("Network registration timed out")),
+    NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_GSM_REGISTRATION_FAILED,
+                         N_("Failed to register with the requested network")),
+    NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_GSM_PIN_CHECK_FAILED, N_("PIN check failed")),
+    NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_FIRMWARE_MISSING,
+                         N_("Necessary firmware for the device may be missing")),
+    NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_REMOVED, N_("The device was removed")),
+    NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_SLEEPING, N_("NetworkManager went to sleep")),
+    NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_CONNECTION_REMOVED,
+                         N_("The device's active connection disappeared")),
+    NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_USER_REQUESTED,
+                         N_("Device disconnected by user or client")),
+    NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_CARRIER, N_("Carrier/link changed")),
+    NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED,
+                         N_("The device's existing connection was assumed")),
+    NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_SUPPLICANT_AVAILABLE,
+                         N_("The supplicant is now available")),
+    NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_MODEM_NOT_FOUND,
+                         N_("The modem could not be found")),
+    NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_BT_FAILED,
+                         N_("The Bluetooth connection failed or timed out")),
+    NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_GSM_SIM_NOT_INSERTED,
+                         N_("GSM Modem's SIM card not inserted")),
+    NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_GSM_SIM_PIN_REQUIRED,
+                         N_("GSM Modem's SIM PIN required")),
+    NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_GSM_SIM_PUK_REQUIRED,
+                         N_("GSM Modem's SIM PUK required")),
+    NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_GSM_SIM_WRONG, N_("GSM Modem's SIM wrong")),
+    NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_INFINIBAND_MODE,
+                         N_("InfiniBand device does not support connected mode")),
+    NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_DEPENDENCY_FAILED,
+                         N_("A dependency of the connection failed")),
+    NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_BR2684_FAILED,
+                         N_("A problem with the RFC 2684 Ethernet over ADSL bridge")),
+    NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_MODEM_MANAGER_UNAVAILABLE,
+                         N_("ModemManager is unavailable")),
+    NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_SSID_NOT_FOUND,
+                         N_("The Wi-Fi network could not be found")),
+    NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_SECONDARY_CONNECTION_FAILED,
+                         N_("A secondary connection of the base connection failed")),
+    NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_DCB_FCOE_FAILED, N_("DCB or FCoE setup failed")),
+    NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_TEAMD_CONTROL_FAILED, N_("teamd control failed")),
+    NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_MODEM_FAILED,
+                         N_("Modem failed or no longer available")),
+    NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_MODEM_AVAILABLE,
+                         N_("Modem now ready and available")),
+    NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_SIM_PIN_INCORRECT, N_("SIM PIN was incorrect")),
+    NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_NEW_ACTIVATION,
+                         N_("New connection activation was enqueued")),
+    NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_PARENT_CHANGED, N_("The device's parent changed")),
+    NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_PARENT_MANAGED_CHANGED,
+                         N_("The device parent's management changed")),
+    NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_OVSDB_FAILED,
+                         N_("Open vSwitch database connection failed")),
+    NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_IP_ADDRESS_DUPLICATE,
+                         N_("A duplicate IP address was detected")),
+    NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_IP_METHOD_UNSUPPORTED,
+                         N_("The selected IP method is not supported")),
+    NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_SRIOV_CONFIGURATION_FAILED,
+                         N_("Failed to configure SR-IOV parameters")),
+    NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_PEER_NOT_FOUND,
+                         N_("The Wi-Fi P2P peer could not be found")), );
+
+NM_UTILS_LOOKUP_STR_DEFINE(
+    nm_active_connection_state_reason_to_string,
+    NMActiveConnectionStateReason,
+    /* TRANSLATORS: Unknown reason for a connection state change (NMActiveConnectionStateReason) */
+    NM_UTILS_LOOKUP_DEFAULT(N_("Unknown")),
+    NM_UTILS_LOOKUP_ITEM(NM_ACTIVE_CONNECTION_STATE_REASON_UNKNOWN, N_("Unknown reason")),
+    NM_UTILS_LOOKUP_ITEM(NM_ACTIVE_CONNECTION_STATE_REASON_NONE,
+                         N_("The connection was disconnected")),
+    NM_UTILS_LOOKUP_ITEM(NM_ACTIVE_CONNECTION_STATE_REASON_USER_DISCONNECTED,
+                         N_("Disconnected by user")),
+    NM_UTILS_LOOKUP_ITEM(NM_ACTIVE_CONNECTION_STATE_REASON_DEVICE_DISCONNECTED,
+                         N_("The base network connection was interrupted")),
+    NM_UTILS_LOOKUP_ITEM(NM_ACTIVE_CONNECTION_STATE_REASON_SERVICE_STOPPED,
+                         N_("The VPN service stopped unexpectedly")),
+    NM_UTILS_LOOKUP_ITEM(NM_ACTIVE_CONNECTION_STATE_REASON_IP_CONFIG_INVALID,
+                         N_("The VPN service returned invalid configuration")),
+    NM_UTILS_LOOKUP_ITEM(NM_ACTIVE_CONNECTION_STATE_REASON_CONNECT_TIMEOUT,
+                         N_("The connection attempt timed out")),
+    NM_UTILS_LOOKUP_ITEM(NM_ACTIVE_CONNECTION_STATE_REASON_SERVICE_START_TIMEOUT,
+                         N_("The VPN service did not start in time")),
+    NM_UTILS_LOOKUP_ITEM(NM_ACTIVE_CONNECTION_STATE_REASON_SERVICE_START_FAILED,
+                         N_("The VPN service failed to start")),
+    NM_UTILS_LOOKUP_ITEM(NM_ACTIVE_CONNECTION_STATE_REASON_NO_SECRETS, N_("No valid secrets")),
+    NM_UTILS_LOOKUP_ITEM(NM_ACTIVE_CONNECTION_STATE_REASON_LOGIN_FAILED, N_("Invalid secrets")),
+    NM_UTILS_LOOKUP_ITEM(NM_ACTIVE_CONNECTION_STATE_REASON_CONNECTION_REMOVED,
+                         N_("The connection was removed")),
+    NM_UTILS_LOOKUP_ITEM(NM_ACTIVE_CONNECTION_STATE_REASON_DEPENDENCY_FAILED,
+                         N_("Master connection failed")),
+    NM_UTILS_LOOKUP_ITEM(NM_ACTIVE_CONNECTION_STATE_REASON_DEVICE_REALIZE_FAILED,
+                         N_("Could not create a software link")),
+    NM_UTILS_LOOKUP_ITEM(NM_ACTIVE_CONNECTION_STATE_REASON_DEVICE_REMOVED,
+                         N_("The device disappeared")), );
 
 NMActiveConnectionState
-nmc_activation_get_effective_state (NMActiveConnection *active,
-                                    NMDevice *device,
-                                    const char **reason)
+nmc_activation_get_effective_state(NMActiveConnection *active,
+                                   NMDevice *          device,
+                                   const char **       reason)
 {
-	NMActiveConnectionState ac_state;
-	NMActiveConnectionStateReason ac_reason;
-	NMDeviceState dev_state = NM_DEVICE_STATE_UNKNOWN;
-	NMDeviceStateReason dev_reason = NM_DEVICE_STATE_REASON_UNKNOWN;
-
-	g_return_val_if_fail (active, NM_ACTIVE_CONNECTION_STATE_UNKNOWN);
-	g_return_val_if_fail (reason, NM_ACTIVE_CONNECTION_STATE_UNKNOWN);
-
-	*reason = NULL;
-	ac_reason = nm_active_connection_get_state_reason (active);
-
-	if (device) {
-		dev_state = nm_device_get_state (device);
-		dev_reason = nm_device_get_state_reason (device);
-	}
-
-	ac_state = nm_active_connection_get_state (active);
-	switch (ac_state) {
-	case NM_ACTIVE_CONNECTION_STATE_DEACTIVATED:
-		if (   !device
-		    || ac_reason != NM_ACTIVE_CONNECTION_STATE_REASON_DEVICE_DISCONNECTED
-		    || nm_device_get_active_connection (device) != active) {
-			/* (1)
-			 * - we have no device,
-			 * - or, @ac_reason is specific
-			 * - or, @device no longer references the current @active
-			 * >> we complete with @ac_reason. */
-			*reason = gettext (nm_active_connection_state_reason_to_string (ac_reason));
-		} else if (   dev_state <= NM_DEVICE_STATE_DISCONNECTED
-		           || dev_state >= NM_DEVICE_STATE_FAILED) {
-			/* (2)
-			 * - not (1)
-			 * - and, the device is no longer in an activated state,
-			 * >> we complete with @dev_reason. */
-			*reason = gettext (nmc_device_reason_to_string (dev_reason));
-		} else {
-			/* (3)
-			 * we wait for the device go disconnect. We will get a better
-			 * failure reason from the device (2). */
-			return NM_ACTIVE_CONNECTION_STATE_UNKNOWN;
-		}
-		break;
-	case NM_ACTIVE_CONNECTION_STATE_ACTIVATING:
-		/* activating master connection does not automatically activate any slaves, so their
-		 * active connection state will not progress beyond ACTIVATING state.
-		 * Monitor the device instead. */
-		if (   device
-		    && (   NM_IS_DEVICE_BOND (device)
-		        || NM_IS_DEVICE_TEAM (device)
-		        || NM_IS_DEVICE_BRIDGE (device))
-		    && dev_state >= NM_DEVICE_STATE_IP_CONFIG
-		    && dev_state <= NM_DEVICE_STATE_ACTIVATED) {
-			*reason = "master waiting for slaves";
-			return NM_ACTIVE_CONNECTION_STATE_ACTIVATED;
-		}
-		break;
-	default:
-		break;
-	}
-
-	return ac_state;
+    NMActiveConnectionState       ac_state;
+    NMActiveConnectionStateReason ac_reason;
+    NMDeviceState                 dev_state  = NM_DEVICE_STATE_UNKNOWN;
+    NMDeviceStateReason           dev_reason = NM_DEVICE_STATE_REASON_UNKNOWN;
+
+    g_return_val_if_fail(active, NM_ACTIVE_CONNECTION_STATE_UNKNOWN);
+    g_return_val_if_fail(reason, NM_ACTIVE_CONNECTION_STATE_UNKNOWN);
+
+    *reason   = NULL;
+    ac_reason = nm_active_connection_get_state_reason(active);
+
+    if (device) {
+        dev_state  = nm_device_get_state(device);
+        dev_reason = nm_device_get_state_reason(device);
+    }
+
+    ac_state = nm_active_connection_get_state(active);
+    switch (ac_state) {
+    case NM_ACTIVE_CONNECTION_STATE_DEACTIVATED:
+        if (!device || ac_reason != NM_ACTIVE_CONNECTION_STATE_REASON_DEVICE_DISCONNECTED
+            || nm_device_get_active_connection(device) != active) {
+            /* (1)
+             * - we have no device,
+             * - or, @ac_reason is specific
+             * - or, @device no longer references the current @active
+             * >> we complete with @ac_reason. */
+            *reason = gettext(nm_active_connection_state_reason_to_string(ac_reason));
+        } else if (dev_state <= NM_DEVICE_STATE_DISCONNECTED
+                   || dev_state >= NM_DEVICE_STATE_FAILED) {
+            /* (2)
+             * - not (1)
+             * - and, the device is no longer in an activated state,
+             * >> we complete with @dev_reason. */
+            *reason = gettext(nmc_device_reason_to_string(dev_reason));
+        } else {
+            /* (3)
+             * we wait for the device go disconnect. We will get a better
+             * failure reason from the device (2). */
+            return NM_ACTIVE_CONNECTION_STATE_UNKNOWN;
+        }
+        break;
+    case NM_ACTIVE_CONNECTION_STATE_ACTIVATING:
+        /* activating master connection does not automatically activate any slaves, so their
+         * active connection state will not progress beyond ACTIVATING state.
+         * Monitor the device instead. */
+        if (device
+            && (NM_IS_DEVICE_BOND(device) || NM_IS_DEVICE_TEAM(device)
+                || NM_IS_DEVICE_BRIDGE(device))
+            && dev_state >= NM_DEVICE_STATE_IP_CONFIG && dev_state <= NM_DEVICE_STATE_ACTIVATED) {
+            *reason = "master waiting for slaves";
+            return NM_ACTIVE_CONNECTION_STATE_ACTIVATED;
+        }
+        break;
+    default:
+        break;
+    }
+
+    return ac_state;
 }
 
 static gboolean
-can_show_utf8 (void)
+can_show_utf8(void)
 {
-	static gboolean can_show_utf8_set = FALSE;
-	static gboolean can_show_utf8 = TRUE;
-	char *locale_str;
-
-	if (G_LIKELY (can_show_utf8_set))
-		return can_show_utf8;
-
-	if (!g_get_charset (NULL)) {
-		/* Non-UTF-8 locale */
-		locale_str = g_locale_from_utf8 ("\342\226\202\342\226\204\342\226\206\342\226\210", -1, NULL, NULL, NULL);
-		if (locale_str)
-			g_free (locale_str);
-		else
-			can_show_utf8 = FALSE;
-	}
-
-	return can_show_utf8;
+    static gboolean can_show_utf8_set = FALSE;
+    static gboolean can_show_utf8     = TRUE;
+    char *          locale_str;
+
+    if (G_LIKELY(can_show_utf8_set))
+        return can_show_utf8;
+
+    if (!g_get_charset(NULL)) {
+        /* Non-UTF-8 locale */
+        locale_str = g_locale_from_utf8("\342\226\202\342\226\204\342\226\206\342\226\210",
+                                        -1,
+                                        NULL,
+                                        NULL,
+                                        NULL);
+        if (locale_str)
+            g_free(locale_str);
+        else
+            can_show_utf8 = FALSE;
+    }
+
+    return can_show_utf8;
 }
 
-
 static gboolean
-can_show_graphics (void)
+can_show_graphics(void)
 {
-	static gboolean can_show_graphics_set = FALSE;
-	static gboolean can_show_graphics = TRUE;
+    static gboolean can_show_graphics_set = FALSE;
+    static gboolean can_show_graphics     = TRUE;
 
-	if (G_LIKELY (can_show_graphics_set))
-		return can_show_graphics;
+    if (G_LIKELY(can_show_graphics_set))
+        return can_show_graphics;
 
-	can_show_graphics = can_show_utf8 ();
+    can_show_graphics = can_show_utf8();
 
-	/* The linux console font typically doesn't have characters we need */
-	if (g_strcmp0 (g_getenv ("TERM"), "linux") == 0)
-		can_show_graphics = FALSE;
+    /* The linux console font typically doesn't have characters we need */
+    if (g_strcmp0(g_getenv("TERM"), "linux") == 0)
+        can_show_graphics = FALSE;
 
-	return can_show_graphics;
+    return can_show_graphics;
 }
 
 /**
@@ -515,26 +589,26 @@ can_show_graphics (void)
  * Converts @strength into a 4-character-wide graphical representation of
  * strength suitable for printing to stdout. If the current locale and terminal
  * support it, this will use unicode graphics characters to represent
- * "bars". Otherwise it will use 0 to 4 asterisks.
+ * "bars". Otherwise, it will use 0 to 4 asterisks.
  *
  * Returns: the graphical representation of the access point strength
  */
 const char *
-nmc_wifi_strength_bars (guint8 strength)
+nmc_wifi_strength_bars(guint8 strength)
 {
-	if (!can_show_graphics ())
-		return nm_utils_wifi_strength_bars (strength);
-
-	if (strength > 80)
-		return /* ▂▄▆█ */ "\342\226\202\342\226\204\342\226\206\342\226\210";
-	else if (strength > 55)
-		return /* ▂▄▆_ */ "\342\226\202\342\226\204\342\226\206_";
-	else if (strength > 30)
-		return /* ▂▄__ */ "\342\226\202\342\226\204__";
-	else if (strength > 5)
-		return /* ▂___ */ "\342\226\202___";
-	else
-		return /* ____ */ "____";
+    if (!can_show_graphics())
+        return nm_utils_wifi_strength_bars(strength);
+
+    if (strength > 80)
+        return /* ▂▄▆█ */ "\342\226\202\342\226\204\342\226\206\342\226\210";
+    else if (strength > 55)
+        return /* ▂▄▆_ */ "\342\226\202\342\226\204\342\226\206_";
+    else if (strength > 30)
+        return /* ▂▄__ */ "\342\226\202\342\226\204__";
+    else if (strength > 5)
+        return /* ▂___ */ "\342\226\202___";
+    else
+        return /* ____ */ "____";
 }
 
 /**
@@ -543,12 +617,12 @@ nmc_wifi_strength_bars (guint8 strength)
  * Returns: the string substituted when hiding actual password glyphs
  */
 const char *
-nmc_password_subst_char (void)
+nmc_password_subst_char(void)
 {
-	if (can_show_graphics ())
-		return "\u2022"; /* Bullet */
-	else
-		return "*";
+    if (can_show_graphics())
+        return "\u2022"; /* Bullet */
+    else
+        return "*";
 }
 
 /*
@@ -566,60 +640,59 @@ NM_PRAGMA_WARNING_REENABLE
 #pragma GCC visibility pop
 
 void
-nmc_print_qrcode (const char *str)
+nmc_print_qrcode(const char *str)
 {
-	uint8_t tempBuffer[qrcodegen_BUFFER_LEN_FOR_VERSION (qrcodegen_VERSION_MAX)];
-	uint8_t qrcode[qrcodegen_BUFFER_LEN_FOR_VERSION (qrcodegen_VERSION_MAX)];
-	gboolean term_linux;
-	int size;
-	int x;
-	int y;
-
-	term_linux = g_strcmp0 (g_getenv ("TERM"), "linux") == 0;
-	if (!term_linux && !can_show_graphics ())
-		return;
-
-	if (!qrcodegen_encodeText (str,
-	                           tempBuffer,
-	                           qrcode,
-	                           qrcodegen_Ecc_LOW,
-	                           qrcodegen_VERSION_MIN,
-	                           qrcodegen_VERSION_MAX,
-	                           qrcodegen_Mask_AUTO,
-	                           FALSE)) {
-		return;
-	}
-
-	size = qrcodegen_getSize (qrcode);
-
-	g_print ("\n");
-
-	if (term_linux) {
-		/* G1 alternate character set on Linux console. */
-		for (y = -1; y < size + 1; y += 1) {
-			g_print ("  \033[37;40;1m\016");
-			for (x = -1; x < size + 1; x++) {
-				g_print (  qrcodegen_getModule (qrcode, x, y)
-				         ? "  " : "\060\060");
-			}
-			g_print ("\017\033[0m\n");
-		}
-	} else {
-		/* UTF-8 */
-		for (y = -2; y < size + 2; y += 2) {
-			g_print ("  \033[37;40m");
-			for (x = -2; x < size + 2; x++) {
-				bool top = qrcodegen_getModule (qrcode, x, y);
-				bool bottom = qrcodegen_getModule (qrcode, x, y + 1);
-				if (top) {
-					g_print (bottom ? " " : "\u2584");
-				} else {
-					g_print (bottom ? "\u2580" : "\u2588");
-				}
-			}
-			g_print ("\033[0m\n");
-		}
-	}
+    uint8_t  tempBuffer[qrcodegen_BUFFER_LEN_FOR_VERSION(qrcodegen_VERSION_MAX)];
+    uint8_t  qrcode[qrcodegen_BUFFER_LEN_FOR_VERSION(qrcodegen_VERSION_MAX)];
+    gboolean term_linux;
+    int      size;
+    int      x;
+    int      y;
+
+    term_linux = g_strcmp0(g_getenv("TERM"), "linux") == 0;
+    if (!term_linux && !can_show_graphics())
+        return;
+
+    if (!qrcodegen_encodeText(str,
+                              tempBuffer,
+                              qrcode,
+                              qrcodegen_Ecc_LOW,
+                              qrcodegen_VERSION_MIN,
+                              qrcodegen_VERSION_MAX,
+                              qrcodegen_Mask_AUTO,
+                              FALSE)) {
+        return;
+    }
+
+    size = qrcodegen_getSize(qrcode);
+
+    g_print("\n");
+
+    if (term_linux) {
+        /* G1 alternate character set on Linux console. */
+        for (y = -1; y < size + 1; y += 1) {
+            g_print("  \033[37;40;1m\016");
+            for (x = -1; x < size + 1; x++) {
+                g_print(qrcodegen_getModule(qrcode, x, y) ? "  " : "\060\060");
+            }
+            g_print("\017\033[0m\n");
+        }
+    } else {
+        /* UTF-8 */
+        for (y = -2; y < size + 2; y += 2) {
+            g_print("  \033[37;40m");
+            for (x = -2; x < size + 2; x++) {
+                bool top    = qrcodegen_getModule(qrcode, x, y);
+                bool bottom = qrcodegen_getModule(qrcode, x, y + 1);
+                if (top) {
+                    g_print(bottom ? " " : "\u2584");
+                } else {
+                    g_print(bottom ? "\u2580" : "\u2588");
+                }
+            }
+            g_print("\033[0m\n");
+        }
+    }
 }
 
 /**
@@ -638,173 +711,176 @@ nmc_print_qrcode (const char *str)
  * Returns: (transfer full): hash table with parsed passwords, or %NULL on an error
  */
 GHashTable *
-nmc_utils_read_passwd_file (const char *passwd_file,
-                            gssize *out_error_line,
-                            GError **error)
+nmc_utils_read_passwd_file(const char *passwd_file, gssize *out_error_line, GError **error)
 {
-	nm_auto_clear_secret_ptr NMSecretPtr contents = { 0 };
-
-	NM_SET_OUT (out_error_line, -1);
-
-	if (!passwd_file)
-		return g_hash_table_new_full (nm_str_hash, g_str_equal, g_free, (GDestroyNotify) nm_free_secret);
-
-	if (!nm_utils_file_get_contents (-1,
-	                                 passwd_file,
-	                                 1024*1024,
-	                                 NM_UTILS_FILE_GET_CONTENTS_FLAG_SECRET,
-	                                 &contents.str,
-	                                 &contents.len,
-	                                 NULL,
-	                                 error))
-		return NULL;
-
-	return nmc_utils_parse_passwd_file (contents.str, out_error_line, error);
+    nm_auto_clear_secret_ptr NMSecretPtr contents = {0};
+
+    NM_SET_OUT(out_error_line, -1);
+
+    if (!passwd_file)
+        return g_hash_table_new_full(nm_str_hash,
+                                     g_str_equal,
+                                     g_free,
+                                     (GDestroyNotify) nm_free_secret);
+
+    if (!nm_utils_file_get_contents(-1,
+                                    passwd_file,
+                                    1024 * 1024,
+                                    NM_UTILS_FILE_GET_CONTENTS_FLAG_SECRET,
+                                    &contents.str,
+                                    &contents.len,
+                                    NULL,
+                                    error))
+        return NULL;
+
+    return nmc_utils_parse_passwd_file(contents.str, out_error_line, error);
 }
 
 GHashTable *
-nmc_utils_parse_passwd_file (char *contents /* will be modified */,
-                             gssize *out_error_line,
-                             GError **error)
+nmc_utils_parse_passwd_file(char *   contents /* will be modified */,
+                            gssize * out_error_line,
+                            GError **error)
 {
-	gs_unref_hashtable GHashTable *pwds_hash = NULL;
-	const char *contents_str;
-	gsize contents_line;
-
-	pwds_hash = g_hash_table_new_full (nm_str_hash, g_str_equal, g_free, (GDestroyNotify) nm_free_secret);
-
-	NM_SET_OUT (out_error_line, -1);
-
-	contents_str = contents;
-	contents_line = 0;
-	while (contents_str[0]) {
-		nm_auto_free_secret char *l_hash_key = NULL;
-		nm_auto_free_secret char *l_hash_val = NULL;
-		const char *l_content_line;
-		const char *l_setting;
-		const char *l_prop;
-		const char *l_val;
-		const char *s;
-		gsize l_hash_val_len;
-
-		/* consume first line. As line delimiters we accept "\r\n", "\n", and "\r". */
-		l_content_line = contents_str;
-		s = l_content_line;
-		while (!NM_IN_SET (s[0], '\0', '\r', '\n'))
-			s++;
-		if (s[0] != '\0') {
-			if (   s[0] == '\r'
-			    && s[1] == '\n') {
-				((char *) s)[0] = '\0';
-				s += 2;
-			} else {
-				((char *) s)[0] = '\0';
-				s += 1;
-			}
-		}
-		contents_str = s;
-		contents_line++;
-
-		l_content_line = nm_str_skip_leading_spaces (l_content_line);
-		if (NM_IN_SET (l_content_line[0], '\0', '#')) {
-			/* a comment or empty line. Ignore. */
-			continue;
-		}
-
-		l_setting = l_content_line;
-
-		s = l_setting;
-		while (!NM_IN_SET (s[0], '\0', ':', '='))
-			s++;
-		if (s[0] == '\0') {
-			NM_SET_OUT (out_error_line, contents_line);
-			nm_utils_error_set (error, NM_UTILS_ERROR_UNKNOWN,
-			                    _("missing colon for \"<setting>.<property>:<secret>\" format"));
-			return NULL;
-		}
-		((char *) s)[0] = '\0';
-		s++;
-
-		l_val = s;
-
-		g_strchomp ((char *) l_setting);
-
-		nm_assert (nm_str_is_stripped (l_setting));
-
-		s = strchr (l_setting, '.');
-		if (!s) {
-			NM_SET_OUT (out_error_line, contents_line);
-			nm_utils_error_set (error, NM_UTILS_ERROR_UNKNOWN,
-			                    _("missing dot for \"<setting>.<property>:<secret>\" format"));
-			return NULL;
-		} else if (s == l_setting) {
-			NM_SET_OUT (out_error_line, contents_line);
-			nm_utils_error_set (error, NM_UTILS_ERROR_UNKNOWN,
-			                    _("missing setting for \"<setting>.<property>:<secret>\" format"));
-			return NULL;
-		}
-		((char *) s)[0] = '\0';
-		s++;
-
-		l_prop = s;
-		if (l_prop[0] == '\0') {
-			NM_SET_OUT (out_error_line, contents_line);
-			nm_utils_error_set (error, NM_UTILS_ERROR_UNKNOWN,
-			                    _("missing property for \"<setting>.<property>:<secret>\" format"));
-			return NULL;
-		}
-
-		/* Accept wifi-sec or wifi instead of cumbersome '802-11-wireless-security' */
-		if (NM_IN_STRSET (l_setting, "wifi-sec", "wifi"))
-			l_setting = NM_SETTING_WIRELESS_SECURITY_SETTING_NAME;
-
-		if (nm_setting_lookup_type (l_setting) == G_TYPE_INVALID) {
-			NM_SET_OUT (out_error_line, contents_line);
-			nm_utils_error_set (error, NM_UTILS_ERROR_UNKNOWN,
-			                    _("invalid setting name"));
-			return NULL;
-		}
-
-		if (   nm_streq (l_setting, "vpn")
-		    && NM_STR_HAS_PREFIX (l_prop, "secret.")) {
-			/* in 1.12.0, we wrongly required the VPN secrets to be named
-			 * "vpn.secret". It should be "vpn.secrets". Work around it
-			 * (rh#1628833). */
-			l_hash_key = g_strdup_printf ("vpn.secrets.%s", &l_prop[NM_STRLEN ("secret.")]);
-		} else
-			l_hash_key = g_strdup_printf ("%s.%s", l_setting, l_prop);
-
-		if (!g_utf8_validate (l_hash_key, -1, NULL)) {
-			NM_SET_OUT (out_error_line, contents_line);
-			nm_utils_error_set (error, NM_UTILS_ERROR_UNKNOWN,
-			                    _("property name is not UTF-8"));
-			return NULL;
-		}
-
-		/* Support backslash escaping in the secret value. We strip non-escaped leading/trailing whitespaces. */
-		s = nm_utils_buf_utf8safe_unescape (l_val, NM_UTILS_STR_UTF8_SAFE_UNESCAPE_STRIP_SPACES, &l_hash_val_len, (gpointer *) &l_hash_val);
-		if (!l_hash_val)
-			l_hash_val = g_strdup (s);
-
-		if (!g_utf8_validate (l_hash_val, -1, NULL)) {
-			/* In some cases it might make sense to support binary secrets (like the WPA-PSK which has no
-			 * defined encoding. However, all API that follows can only handle UTF-8, and no mechanism
-			 * to escape the secrets. Reject non-UTF-8 early. */
-			NM_SET_OUT (out_error_line, contents_line);
-			nm_utils_error_set (error, NM_UTILS_ERROR_UNKNOWN,
-			                    _("secret is not UTF-8"));
-			return NULL;
-		}
-
-		if (strlen (l_hash_val) != l_hash_val_len) {
-			NM_SET_OUT (out_error_line, contents_line);
-			nm_utils_error_set (error, NM_UTILS_ERROR_UNKNOWN,
-			                    _("secret is not UTF-8"));
-			return NULL;
-		}
-
-		g_hash_table_insert (pwds_hash, g_steal_pointer (&l_hash_key), g_steal_pointer (&l_hash_val));
-	}
-
-	return g_steal_pointer (&pwds_hash);
+    gs_unref_hashtable GHashTable *pwds_hash = NULL;
+    const char *                   contents_str;
+    gsize                          contents_line;
+
+    pwds_hash =
+        g_hash_table_new_full(nm_str_hash, g_str_equal, g_free, (GDestroyNotify) nm_free_secret);
+
+    NM_SET_OUT(out_error_line, -1);
+
+    contents_str  = contents;
+    contents_line = 0;
+    while (contents_str[0]) {
+        nm_auto_free_secret char *l_hash_key = NULL;
+        nm_auto_free_secret char *l_hash_val = NULL;
+        const char *              l_content_line;
+        const char *              l_setting;
+        const char *              l_prop;
+        const char *              l_val;
+        const char *              s;
+        gsize                     l_hash_val_len;
+
+        /* consume first line. As line delimiters we accept "\r\n", "\n", and "\r". */
+        l_content_line = contents_str;
+        s              = l_content_line;
+        while (!NM_IN_SET(s[0], '\0', '\r', '\n'))
+            s++;
+        if (s[0] != '\0') {
+            if (s[0] == '\r' && s[1] == '\n') {
+                ((char *) s)[0] = '\0';
+                s += 2;
+            } else {
+                ((char *) s)[0] = '\0';
+                s += 1;
+            }
+        }
+        contents_str = s;
+        contents_line++;
+
+        l_content_line = nm_str_skip_leading_spaces(l_content_line);
+        if (NM_IN_SET(l_content_line[0], '\0', '#')) {
+            /* a comment or empty line. Ignore. */
+            continue;
+        }
+
+        l_setting = l_content_line;
+
+        s = l_setting;
+        while (!NM_IN_SET(s[0], '\0', ':', '='))
+            s++;
+        if (s[0] == '\0') {
+            NM_SET_OUT(out_error_line, contents_line);
+            nm_utils_error_set(error,
+                               NM_UTILS_ERROR_UNKNOWN,
+                               _("missing colon for \"<setting>.<property>:<secret>\" format"));
+            return NULL;
+        }
+        ((char *) s)[0] = '\0';
+        s++;
+
+        l_val = s;
+
+        g_strchomp((char *) l_setting);
+
+        nm_assert(nm_str_is_stripped(l_setting));
+
+        s = strchr(l_setting, '.');
+        if (!s) {
+            NM_SET_OUT(out_error_line, contents_line);
+            nm_utils_error_set(error,
+                               NM_UTILS_ERROR_UNKNOWN,
+                               _("missing dot for \"<setting>.<property>:<secret>\" format"));
+            return NULL;
+        } else if (s == l_setting) {
+            NM_SET_OUT(out_error_line, contents_line);
+            nm_utils_error_set(error,
+                               NM_UTILS_ERROR_UNKNOWN,
+                               _("missing setting for \"<setting>.<property>:<secret>\" format"));
+            return NULL;
+        }
+        ((char *) s)[0] = '\0';
+        s++;
+
+        l_prop = s;
+        if (l_prop[0] == '\0') {
+            NM_SET_OUT(out_error_line, contents_line);
+            nm_utils_error_set(error,
+                               NM_UTILS_ERROR_UNKNOWN,
+                               _("missing property for \"<setting>.<property>:<secret>\" format"));
+            return NULL;
+        }
+
+        /* Accept wifi-sec or wifi instead of cumbersome '802-11-wireless-security' */
+        if (NM_IN_STRSET(l_setting, "wifi-sec", "wifi"))
+            l_setting = NM_SETTING_WIRELESS_SECURITY_SETTING_NAME;
+
+        if (nm_setting_lookup_type(l_setting) == G_TYPE_INVALID) {
+            NM_SET_OUT(out_error_line, contents_line);
+            nm_utils_error_set(error, NM_UTILS_ERROR_UNKNOWN, _("invalid setting name"));
+            return NULL;
+        }
+
+        if (nm_streq(l_setting, "vpn") && NM_STR_HAS_PREFIX(l_prop, "secret.")) {
+            /* in 1.12.0, we wrongly required the VPN secrets to be named
+             * "vpn.secret". It should be "vpn.secrets". Work around it
+             * (rh#1628833). */
+            l_hash_key = g_strdup_printf("vpn.secrets.%s", &l_prop[NM_STRLEN("secret.")]);
+        } else
+            l_hash_key = g_strdup_printf("%s.%s", l_setting, l_prop);
+
+        if (!g_utf8_validate(l_hash_key, -1, NULL)) {
+            NM_SET_OUT(out_error_line, contents_line);
+            nm_utils_error_set(error, NM_UTILS_ERROR_UNKNOWN, _("property name is not UTF-8"));
+            return NULL;
+        }
+
+        /* Support backslash escaping in the secret value. We strip non-escaped leading/trailing whitespaces. */
+        s = nm_utils_buf_utf8safe_unescape(l_val,
+                                           NM_UTILS_STR_UTF8_SAFE_UNESCAPE_STRIP_SPACES,
+                                           &l_hash_val_len,
+                                           (gpointer *) &l_hash_val);
+        if (!l_hash_val)
+            l_hash_val = g_strdup(s);
+
+        if (!g_utf8_validate(l_hash_val, -1, NULL)) {
+            /* In some cases it might make sense to support binary secrets (like the WPA-PSK which has no
+             * defined encoding. However, all API that follows can only handle UTF-8, and no mechanism
+             * to escape the secrets. Reject non-UTF-8 early. */
+            NM_SET_OUT(out_error_line, contents_line);
+            nm_utils_error_set(error, NM_UTILS_ERROR_UNKNOWN, _("secret is not UTF-8"));
+            return NULL;
+        }
+
+        if (strlen(l_hash_val) != l_hash_val_len) {
+            NM_SET_OUT(out_error_line, contents_line);
+            nm_utils_error_set(error, NM_UTILS_ERROR_UNKNOWN, _("secret is not UTF-8"));
+            return NULL;
+        }
+
+        g_hash_table_insert(pwds_hash, g_steal_pointer(&l_hash_key), g_steal_pointer(&l_hash_val));
+    }
+
+    return g_steal_pointer(&pwds_hash);
 }