summary refs log tree commit diff
path: root/src/libnm-core-impl/nm-utils.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libnm-core-impl/nm-utils.c')
-rw-r--r--src/libnm-core-impl/nm-utils.c554
1 files changed, 283 insertions, 271 deletions
diff --git a/src/libnm-core-impl/nm-utils.c b/src/libnm-core-impl/nm-utils.c
index ccdd4b92..55b01c15 100644
--- a/src/libnm-core-impl/nm-utils.c
+++ b/src/libnm-core-impl/nm-utils.c
@@ -79,7 +79,7 @@ NM_IS_SOCK_ADDR_ENDPOINT(const NMSockAddrEndpoint *self)
 static const char *
 _parse_endpoint(char *str, guint16 *out_port)
 {
-    char *      s;
+    char       *s;
     const char *s_port;
     gint16      port;
 
@@ -147,8 +147,8 @@ nm_sock_addr_endpoint_new(const char *endpoint)
     gsize               l_endpoint;
     gsize               l_host = 0;
     gsize               i;
-    gs_free char *      host_clone = NULL;
-    const char *        host;
+    gs_free char       *host_clone = NULL;
+    const char         *host;
     guint16             port;
 
     g_return_val_if_fail(endpoint, NULL);
@@ -294,7 +294,7 @@ nm_sock_addr_endpoint_get_fixed_sockaddr(NMSockAddrEndpoint *self, gpointer sock
 
     {
         gs_free char *tmp_str = NULL;
-        const char *  host_part;
+        const char   *host_part;
 
         host_part = nm_strndup_a(200, self->host, s - self->host, &tmp_str);
         if (nm_utils_parse_inaddr_bin(AF_INET6, host_part, &addr_family, &addrbin))
@@ -328,169 +328,181 @@ good:
 
 /*****************************************************************************/
 
-struct IsoLangToEncodings {
-    const char *       lang;
-    const char *const *encodings;
-};
+typedef const char *const StrvArray4Type[4];
 
-#define LANG_ENCODINGS(l, ...)                             \
-    {                                                      \
-        .lang = l, .encodings = NM_MAKE_STRV(__VA_ARGS__), \
+#define LL(l, ...)                               \
+    {                                            \
+        .name = l, .value = {__VA_ARGS__, NULL}, \
     }
 
 /* 5-letter language codes */
-static const struct IsoLangToEncodings isoLangEntries5[] = {
-    /* Simplified Chinese */
-    LANG_ENCODINGS("zh_cn", "euc-cn", "gb2312", "gb18030"), /* PRC */
-    LANG_ENCODINGS("zh_sg", "euc-cn", "gb2312", "gb18030"), /* Singapore */
-
-    /* Traditional Chinese */
-    LANG_ENCODINGS("zh_tw", "big5", "euc-tw"),              /* Taiwan */
-    LANG_ENCODINGS("zh_hk", "big5", "euc-tw", "big5-hkcs"), /* Hong Kong */
-    LANG_ENCODINGS("zh_mo", "big5", "euc-tw"),              /* Macau */
-
-    LANG_ENCODINGS(NULL, NULL)};
+static _NM_UTILS_STRING_TABLE_LOOKUP_DEFINE(
+    _iso_lang_entries_5_lookup,
+    StrvArray4Type,
+    const char *const *,
+    { nm_assert(name); },
+    { return NULL; },
+    ,
+    LL("zh_cn", "euc-cn", "gb2312", "gb18030"), /* Simplified Chinese, PRC */
+    LL("zh_hk", "big5", "euc-tw", "big5-hkcs"), /* Traditional Chinese, Hong Kong */
+    LL("zh_mo", "big5", "euc-tw"),              /* Traditional Chinese, Macau */
+    LL("zh_sg", "euc-cn", "gb2312", "gb18030"), /* Simplified Chinese, Singapore */
+    LL("zh_tw", "big5", "euc-tw"),              /* Traditional Chinese, Taiwan */
+);
 
 /* 2-letter language codes; we don't care about the other 3 in this table */
-static const struct IsoLangToEncodings isoLangEntries2[] = {
-    /* Japanese */
-    LANG_ENCODINGS("ja", "euc-jp", "shift_jis", "iso-2022-jp"),
-
-    /* Korean */
-    LANG_ENCODINGS("ko", "euc-kr", "iso-2022-kr", "johab"),
-
-    /* Thai */
-    LANG_ENCODINGS("th", "iso-8859-11", "windows-874"),
-
-    /* Central European */
-    LANG_ENCODINGS("hu", "iso-8859-2", "windows-1250"), /* Hungarian */
-    LANG_ENCODINGS("cs", "iso-8859-2", "windows-1250"), /* Czech */
-    LANG_ENCODINGS("hr", "iso-8859-2", "windows-1250"), /* Croatian */
-    LANG_ENCODINGS("pl", "iso-8859-2", "windows-1250"), /* Polish */
-    LANG_ENCODINGS("ro", "iso-8859-2", "windows-1250"), /* Romanian */
-    LANG_ENCODINGS("sk", "iso-8859-2", "windows-1250"), /* Slovakian */
-    LANG_ENCODINGS("sl", "iso-8859-2", "windows-1250"), /* Slovenian */
-    LANG_ENCODINGS("sh", "iso-8859-2", "windows-1250"), /* Serbo-Croatian */
-
-    /* Cyrillic */
-    LANG_ENCODINGS("ru", "koi8-r", "windows-1251", "iso-8859-5"), /* Russian */
-    LANG_ENCODINGS("be", "koi8-r", "windows-1251", "iso-8859-5"), /* Belorussian */
-    LANG_ENCODINGS("bg", "windows-1251", "koi8-r", "iso-8859-5"), /* Bulgarian */
-    LANG_ENCODINGS("mk", "koi8-r", "windows-1251", "iso-8859-5"), /* Macedonian */
-    LANG_ENCODINGS("sr", "koi8-r", "windows-1251", "iso-8859-5"), /* Serbian */
-    LANG_ENCODINGS("uk", "koi8-u", "koi8-r", "windows-1251"),     /* Ukrainian */
-
-    /* Arabic */
-    LANG_ENCODINGS("ar", "iso-8859-6", "windows-1256"),
-
-    /* Baltic */
-    LANG_ENCODINGS("et", "iso-8859-4", "windows-1257"), /* Estonian */
-    LANG_ENCODINGS("lt", "iso-8859-4", "windows-1257"), /* Lithuanian */
-    LANG_ENCODINGS("lv", "iso-8859-4", "windows-1257"), /* Latvian */
-
-    /* Greek */
-    LANG_ENCODINGS("el", "iso-8859-7", "windows-1253"),
-
-    /* Hebrew */
-    LANG_ENCODINGS("he", "iso-8859-8", "windows-1255"),
-    LANG_ENCODINGS("iw", "iso-8859-8", "windows-1255"),
-
-    /* Turkish */
-    LANG_ENCODINGS("tr", "iso-8859-9", "windows-1254"),
-
-    /* Table end */
-    LANG_ENCODINGS(NULL, NULL)};
-
-static GHashTable *langToEncodings5 = NULL;
-static GHashTable *langToEncodings2 = NULL;
+static _NM_UTILS_STRING_TABLE_LOOKUP_DEFINE(
+    _iso_lang_entries_2_lookup,
+    StrvArray4Type,
+    const char *const *,
+    { nm_assert(name); },
+    { return NULL; },
+    ,
+    LL("ar", "iso-8859-6", "windows-1256"),           /* Arabic */
+    LL("be", "koi8-r", "windows-1251", "iso-8859-5"), /* Cyrillic, Belorussian */
+    LL("bg", "windows-1251", "koi8-r", "iso-8859-5"), /* Cyrillic, Bulgarian */
+    LL("cs", "iso-8859-2", "windows-1250"),           /* Central European, Czech */
+    LL("el", "iso-8859-7", "windows-1253"),           /* Greek */
+    LL("et", "iso-8859-4", "windows-1257"),           /* Baltic, Estonian */
+    LL("he", "iso-8859-8", "windows-1255"),           /* Hebrew */
+    LL("hr", "iso-8859-2", "windows-1250"),           /* Central European, Croatian */
+    LL("hu", "iso-8859-2", "windows-1250"),           /* Central European, Hungarian */
+    LL("iw", "iso-8859-8", "windows-1255"),           /* Hebrew */
+    LL("ja", "euc-jp", "shift_jis", "iso-2022-jp"),   /* Japanese */
+    LL("ko", "euc-kr", "iso-2022-kr", "johab"),       /* Korean */
+    LL("lt", "iso-8859-4", "windows-1257"),           /* Baltic, Lithuanian */
+    LL("lv", "iso-8859-4", "windows-1257"),           /* Baltic, Latvian */
+    LL("mk", "koi8-r", "windows-1251", "iso-8859-5"), /* Cyrillic, Macedonian */
+    LL("pl", "iso-8859-2", "windows-1250"),           /* Central European, Polish */
+    LL("ro", "iso-8859-2", "windows-1250"),           /* Central European, Romanian */
+    LL("ru", "koi8-r", "windows-1251", "iso-8859-5"), /* Cyrillic, Russian */
+    LL("sh", "iso-8859-2", "windows-1250"),           /* Central European, Serbo-Croatian */
+    LL("sk", "iso-8859-2", "windows-1250"),           /* Central European, Slovakian */
+    LL("sl", "iso-8859-2", "windows-1250"),           /* Central European, Slovenian */
+    LL("sr", "koi8-r", "windows-1251", "iso-8859-5"), /* Cyrillic, Serbian */
+    LL("th", "iso-8859-11", "windows-874"),           /* Thai */
+    LL("tr", "iso-8859-9", "windows-1254"),           /* Turkish */
+    LL("uk", "koi8-u", "koi8-r", "windows-1251"),     /* Cyrillic, Ukrainian */
+);
 
-static void
-init_lang_to_encodings_hash(void)
+static const char *const *
+_system_encodings_for_lang(const char *lang)
 {
-    struct IsoLangToEncodings *enc;
+    char               tmp_lang[3];
+    const char *const *e;
 
-    if (G_UNLIKELY(langToEncodings5 == NULL)) {
-        /* Five-letter codes */
-        enc              = (struct IsoLangToEncodings *) &isoLangEntries5[0];
-        langToEncodings5 = g_hash_table_new(nm_str_hash, g_str_equal);
-        while (enc->lang) {
-            g_hash_table_insert(langToEncodings5, (gpointer) enc->lang, (gpointer) enc->encodings);
-            enc++;
-        }
+    nm_assert(lang);
+
+    if (lang[0] == '\0' || lang[1] == '\0') {
+        /* need at least two characters. */
+        nm_assert(!_iso_lang_entries_5_lookup(lang));
+        nm_assert(!_iso_lang_entries_2_lookup(lang));
+        return NULL;
     }
 
-    if (G_UNLIKELY(langToEncodings2 == NULL)) {
-        /* Two-letter codes */
-        enc              = (struct IsoLangToEncodings *) &isoLangEntries2[0];
-        langToEncodings2 = g_hash_table_new(nm_str_hash, g_str_equal);
-        while (enc->lang) {
-            g_hash_table_insert(langToEncodings2, (gpointer) enc->lang, (gpointer) enc->encodings);
-            enc++;
-        }
+    if (lang[2] != '\0') {
+        nm_assert(!_iso_lang_entries_2_lookup(lang));
+
+        if (lang[3] != '\0' && lang[4] != '\0' && lang[5] == '\0') {
+            /* lang is 5 characters long. Try it. */
+            if ((e = _iso_lang_entries_5_lookup(lang)))
+                return e;
+        } else
+            nm_assert(!_iso_lang_entries_5_lookup(lang));
+
+        /* extract the first 2 characters and ignore the rest. */
+        tmp_lang[0] = lang[0];
+        tmp_lang[1] = lang[1];
+        tmp_lang[2] = '\0';
+        lang        = tmp_lang;
     }
+
+    if ((e = _iso_lang_entries_2_lookup(lang)))
+        return e;
+
+    return NULL;
 }
 
-static gboolean
-get_encodings_for_lang(const char *lang, const char *const **encodings)
+const char *const *
+nmtst_system_encodings_for_lang(const char *lang)
+{
+    return _system_encodings_for_lang(lang);
+}
+
+static const char *const *
+_system_encodings_get_default(void)
 {
-    gs_free char *tmp_lang = NULL;
+    static gsize       init_once = 0;
+    static const char *default_encodings[4];
 
-    g_return_val_if_fail(lang, FALSE);
-    g_return_val_if_fail(encodings, FALSE);
+    if (g_once_init_enter(&init_once)) {
+        const char *e_default = NULL;
+        int         i;
 
-    init_lang_to_encodings_hash();
+        g_get_charset(&e_default);
 
-    if ((*encodings = g_hash_table_lookup(langToEncodings5, lang)))
-        return TRUE;
+        i = 0;
+        if (e_default)
+            default_encodings[i++] = e_default;
+        if (!nm_streq0(e_default, "iso-8859-1"))
+            default_encodings[i++] = "iso-8859-1";
+        if (!nm_streq0(e_default, "windows-1251"))
+            default_encodings[i++] = "windows-1251";
+        default_encodings[i++] = NULL;
+        nm_assert(i <= G_N_ELEMENTS(default_encodings));
 
-    /* Truncate tmp_lang to length of 2 */
-    if (strlen(lang) > 2) {
-        tmp_lang    = g_strdup(lang);
-        tmp_lang[2] = '\0';
-        if ((*encodings = g_hash_table_lookup(langToEncodings2, tmp_lang)))
-            return TRUE;
+        g_once_init_leave(&init_once, 1);
     }
 
-    return FALSE;
+    return default_encodings;
+}
+
+const char *const *
+nmtst_system_encodings_get_default(void)
+{
+    return _system_encodings_get_default();
 }
 
 static const char *const *
-get_system_encodings(void)
+_system_encodings_get(void)
 {
-    static const char *const *cached_encodings;
-    static char *             default_encodings[4];
-    const char *const *       encodings = NULL;
-    char *                    lang;
+    static const char *const *cached = NULL;
+    const char *const        *e;
 
-    if (cached_encodings)
-        return cached_encodings;
+again:
+    if (!(e = g_atomic_pointer_get(&cached))) {
+        const char *lang;
 
-    /* Use environment variables as encoding hint */
-    lang = getenv("LC_ALL");
-    if (!lang)
-        lang = getenv("LC_CTYPE");
-    if (!lang)
-        lang = getenv("LANG");
-    if (lang) {
-        char *dot;
+        /* Use environment variables as encoding hint */
+        lang = getenv("LC_ALL") ?: getenv("LC_CTYPE") ?: getenv("LANG");
 
-        lang = g_ascii_strdown(lang, -1);
-        if ((dot = strchr(lang, '.')))
-            *dot = '\0';
+        if (lang) {
+            gs_free char *lang_down = NULL;
+            char         *dot;
 
-        get_encodings_for_lang(lang, &encodings);
-        g_free(lang);
-    }
-    if (!encodings) {
-        g_get_charset((const char **) &default_encodings[0]);
-        default_encodings[1] = "iso-8859-1";
-        default_encodings[2] = "windows-1251";
-        default_encodings[3] = NULL;
-        encodings            = (const char *const *) default_encodings;
+            lang_down = g_ascii_strdown(lang, -1);
+            if ((dot = strchr(lang_down, '.')))
+                *dot = '\0';
+            e = _system_encodings_for_lang(lang_down);
+        }
+
+        if (!e)
+            e = _system_encodings_get_default();
+
+        /* in any case, @e is now a static buffer, that we may cache. */
+        nm_assert(e);
+
+        if (!g_atomic_pointer_compare_and_exchange(&cached, NULL, e))
+            goto again;
     }
 
-    cached_encodings = encodings;
-    return cached_encodings;
+    return e;
+}
+
+const char *const *
+nmtst_system_encodings_get(void)
+{
+    return _system_encodings_get();
 }
 
 /*****************************************************************************/
@@ -560,14 +572,14 @@ nm_utils_ssid_to_utf8(const guint8 *ssid, gsize len)
 {
     const char *const *encodings;
     const char *const *e;
-    char *             converted = NULL;
+    char              *converted = NULL;
 
     g_return_val_if_fail(ssid != NULL, NULL);
 
     if (g_utf8_validate((const char *) ssid, len, NULL))
         return g_strndup((const char *) ssid, len);
 
-    encodings = get_system_encodings();
+    encodings = _system_encodings_get();
 
     for (e = encodings; *e; e++) {
         converted = g_convert((const char *) ssid, len, "UTF-8", *e, NULL, NULL, NULL);
@@ -652,7 +664,7 @@ nm_utils_escape_ssid(const guint8 *ssid, gsize len)
 {
     static char   escaped[NM_IW_ESSID_MAX_SIZE * 2 + 1];
     const guint8 *s = ssid;
-    char *        d = escaped;
+    char         *d = escaped;
 
     if (nm_utils_is_empty_ssid(ssid, len)) {
         memcpy(escaped, "<hidden>", sizeof("<hidden>"));
@@ -746,9 +758,9 @@ _nm_utils_string_slist_validate(GSList *list, const char **valid_values)
 GSList *
 _nm_utils_hash_values_to_slist(GHashTable *hash)
 {
-    GSList *       list = NULL;
+    GSList        *list = NULL;
     GHashTableIter iter;
-    void *         value;
+    void          *value;
 
     g_return_val_if_fail(hash, NULL);
 
@@ -763,8 +775,8 @@ void
 _nm_utils_strdict_from_dbus(_NM_SETT_INFO_PROP_FROM_DBUS_GPROP_FCN_ARGS _nm_nil)
 {
     GVariantIter iter;
-    const char * key, *value;
-    GHashTable * hash;
+    const char  *key, *value;
+    GHashTable  *hash;
 
     hash = g_hash_table_new_full(nm_str_hash, g_str_equal, g_free, g_free);
     g_variant_iter_init(&iter, from);
@@ -786,7 +798,7 @@ const NMSettInfoPropertType nm_sett_info_propert_type_strdict =
 GHashTable *
 _nm_utils_copy_strdict(GHashTable *strdict)
 {
-    GHashTable *   copy;
+    GHashTable    *copy;
     GHashTableIter iter;
     gpointer       key, value;
 
@@ -861,7 +873,7 @@ char **
 _nm_utils_slist_to_strv(const GSList *slist, gboolean deep_copy)
 {
     const GSList *iter;
-    char **       strv;
+    char        **strv;
     guint         len, i;
 
     if (!slist)
@@ -1328,7 +1340,7 @@ nm_utils_ip4_dns_from_variant(GVariant *value)
 {
     const guint32 *array;
     gsize          length;
-    char **        dns;
+    char         **dns;
     gsize          i;
 
     g_return_val_if_fail(g_variant_is_of_type(value, G_VARIANT_TYPE("au")), NULL);
@@ -1409,9 +1421,9 @@ nm_utils_ip4_addresses_to_variant(GPtrArray *addresses, const char *gateway)
 GPtrArray *
 nm_utils_ip4_addresses_from_variant(GVariant *value, char **out_gateway)
 {
-    GPtrArray *  addresses;
+    GPtrArray   *addresses;
     GVariantIter iter;
-    GVariant *   addr_var;
+    GVariant    *addr_var;
 
     g_return_val_if_fail(g_variant_is_of_type(value, G_VARIANT_TYPE("aau")), NULL);
 
@@ -1424,8 +1436,8 @@ nm_utils_ip4_addresses_from_variant(GVariant *value, char **out_gateway)
     while (g_variant_iter_next(&iter, "@au", &addr_var)) {
         const guint32 *addr_array;
         gsize          length;
-        NMIPAddress *  addr;
-        GError *       error = NULL;
+        NMIPAddress   *addr;
+        GError        *error = NULL;
 
         addr_array = g_variant_get_fixed_array(addr_var, &length, sizeof(guint32));
         if (length < 3) {
@@ -1506,8 +1518,8 @@ GPtrArray *
 nm_utils_ip4_routes_from_variant(GVariant *value)
 {
     GVariantIter iter;
-    GVariant *   route_var;
-    GPtrArray *  routes;
+    GVariant    *route_var;
+    GPtrArray   *routes;
 
     g_return_val_if_fail(g_variant_is_of_type(value, G_VARIANT_TYPE("aau")), NULL);
 
@@ -1517,8 +1529,8 @@ nm_utils_ip4_routes_from_variant(GVariant *value)
     while (g_variant_iter_next(&iter, "@au", &route_var)) {
         const guint32 *route_array;
         gsize          length;
-        NMIPRoute *    route;
-        GError *       error = NULL;
+        NMIPRoute     *route;
+        GError        *error = NULL;
 
         route_array = g_variant_get_fixed_array(route_var, &length, sizeof(guint32));
         if (length < 4) {
@@ -1647,8 +1659,8 @@ char **
 nm_utils_ip6_dns_from_variant(GVariant *value)
 {
     GVariantIter iter;
-    GVariant *   ip_var;
-    char **      dns;
+    GVariant    *ip_var;
+    char       **dns;
     gsize        i;
 
     g_return_val_if_fail(g_variant_is_of_type(value, G_VARIANT_TYPE("aay")), NULL);
@@ -1695,7 +1707,7 @@ nm_utils_ip6_addresses_to_variant(GPtrArray *addresses, const char *gateway)
 
     if (addresses) {
         for (i = 0; i < addresses->len; i++) {
-            NMIPAddress *          addr = addresses->pdata[i];
+            NMIPAddress           *addr = addresses->pdata[i];
             struct in6_addr        address_bin;
             struct in6_addr        gateway_bin_data;
             const struct in6_addr *gateway_bin;
@@ -1741,9 +1753,9 @@ GPtrArray *
 nm_utils_ip6_addresses_from_variant(GVariant *value, char **out_gateway)
 {
     GVariantIter iter;
-    GVariant *   addr_var, *gateway_var;
+    GVariant    *addr_var, *gateway_var;
     guint32      prefix;
-    GPtrArray *  addresses;
+    GPtrArray   *addresses;
 
     g_return_val_if_fail(g_variant_is_of_type(value, G_VARIANT_TYPE("a(ayuay)")), NULL);
 
@@ -1754,10 +1766,10 @@ nm_utils_ip6_addresses_from_variant(GVariant *value, char **out_gateway)
     addresses = g_ptr_array_new_with_free_func((GDestroyNotify) nm_ip_address_unref);
 
     while (g_variant_iter_next(&iter, "(@ayu@ay)", &addr_var, &prefix, &gateway_var)) {
-        NMIPAddress *          addr;
+        NMIPAddress           *addr;
         const struct in6_addr *addr_bytes, *gateway_bytes;
         gsize                  addr_len, gateway_len;
-        GError *               error = NULL;
+        GError                *error = NULL;
 
         if (!g_variant_is_of_type(addr_var, G_VARIANT_TYPE_BYTESTRING)
             || !g_variant_is_of_type(gateway_var, G_VARIANT_TYPE_BYTESTRING)) {
@@ -1820,7 +1832,7 @@ nm_utils_ip6_routes_to_variant(GPtrArray *routes)
 
     if (routes) {
         for (i = 0; i < routes->len; i++) {
-            NMIPRoute *     route = routes->pdata[i];
+            NMIPRoute      *route = routes->pdata[i];
             struct in6_addr dest_bytes;
             struct in6_addr next_hop_bytes;
             guint32         metric;
@@ -1860,9 +1872,9 @@ nm_utils_ip6_routes_to_variant(GPtrArray *routes)
 GPtrArray *
 nm_utils_ip6_routes_from_variant(GVariant *value)
 {
-    GPtrArray *            routes;
+    GPtrArray             *routes;
     GVariantIter           iter;
-    GVariant *             dest_var, *next_hop_var;
+    GVariant              *dest_var, *next_hop_var;
     const struct in6_addr *dest, *next_hop;
     gsize                  dest_len, next_hop_len;
     guint32                prefix, metric;
@@ -1874,7 +1886,7 @@ nm_utils_ip6_routes_from_variant(GVariant *value)
     g_variant_iter_init(&iter, value);
     while (g_variant_iter_next(&iter, "(@ayu@ayu)", &dest_var, &prefix, &next_hop_var, &metric)) {
         NMIPRoute *route;
-        GError *   error = NULL;
+        GError    *error = NULL;
 
         if (!g_variant_is_of_type(dest_var, G_VARIANT_TYPE_BYTESTRING)
             || !g_variant_is_of_type(next_hop_var, G_VARIANT_TYPE_BYTESTRING)) {
@@ -1939,7 +1951,7 @@ nm_utils_ip_addresses_to_variant(GPtrArray *addresses)
 
     if (addresses) {
         for (i = 0; i < addresses->len; i++) {
-            NMIPAddress *        addr = addresses->pdata[i];
+            NMIPAddress         *addr = addresses->pdata[i];
             GVariantBuilder      addr_builder;
             gs_free const char **names = NULL;
             guint                j, len;
@@ -1985,15 +1997,15 @@ nm_utils_ip_addresses_to_variant(GPtrArray *addresses)
 GPtrArray *
 nm_utils_ip_addresses_from_variant(GVariant *value, int family)
 {
-    GPtrArray *  addresses;
+    GPtrArray   *addresses;
     GVariantIter iter, attrs_iter;
-    GVariant *   addr_var;
-    const char * ip;
+    GVariant    *addr_var;
+    const char  *ip;
     guint32      prefix;
-    const char * attr_name;
-    GVariant *   attr_val;
+    const char  *attr_name;
+    GVariant    *attr_val;
     NMIPAddress *addr;
-    GError *     error = NULL;
+    GError      *error = NULL;
 
     g_return_val_if_fail(g_variant_is_of_type(value, G_VARIANT_TYPE("aa{sv}")), NULL);
 
@@ -2051,7 +2063,7 @@ nm_utils_ip_routes_to_variant(GPtrArray *routes)
 
     if (routes) {
         for (i = 0; i < routes->len; i++) {
-            NMIPRoute *          route = routes->pdata[i];
+            NMIPRoute           *route = routes->pdata[i];
             GVariantBuilder      route_builder;
             gs_free const char **names = NULL;
             guint                j, len;
@@ -2110,16 +2122,16 @@ nm_utils_ip_routes_to_variant(GPtrArray *routes)
 GPtrArray *
 nm_utils_ip_routes_from_variant(GVariant *value, int family)
 {
-    GPtrArray *  routes;
+    GPtrArray   *routes;
     GVariantIter iter, attrs_iter;
-    GVariant *   route_var;
-    const char * dest, *next_hop;
+    GVariant    *route_var;
+    const char  *dest, *next_hop;
     guint32      prefix, metric32;
     gint64       metric;
-    const char * attr_name;
-    GVariant *   attr_val;
-    NMIPRoute *  route;
-    GError *     error = NULL;
+    const char  *attr_name;
+    GVariant    *attr_val;
+    NMIPRoute   *route;
+    GError      *error = NULL;
 
     g_return_val_if_fail(g_variant_is_of_type(value, G_VARIANT_TYPE("aa{sv}")), NULL);
 
@@ -2297,7 +2309,7 @@ static const NMVariantAttributeSpec *const tc_qdisc_fq_codel_spec[] = {
 };
 
 typedef struct {
-    const char *                         kind;
+    const char                          *kind;
     const NMVariantAttributeSpec *const *attrs;
 } NMQdiscAttributeSpec;
 
@@ -2323,7 +2335,7 @@ void
 _nm_utils_string_append_tc_qdisc_rest(GString *string, NMTCQdisc *qdisc)
 {
     guint32       handle = nm_tc_qdisc_get_handle(qdisc);
-    const char *  kind   = nm_tc_qdisc_get_kind(qdisc);
+    const char   *kind   = nm_tc_qdisc_get_kind(qdisc);
     gs_free char *str    = NULL;
 
     if (handle != TC_H_UNSPEC && !NM_IN_STRSET(kind, "ingress", "clsact")) {
@@ -2368,14 +2380,14 @@ nm_utils_tc_qdisc_to_str(NMTCQdisc *qdisc, GError **error)
 
 static gboolean
 _tc_read_common_opts(const char *str,
-                     guint32 *   handle,
-                     guint32 *   parent,
-                     char **     kind,
-                     char **     rest,
-                     GError **   error)
+                     guint32    *handle,
+                     guint32    *parent,
+                     char      **kind,
+                     char      **rest,
+                     GError    **error)
 {
     gs_unref_hashtable GHashTable *ht = NULL;
-    GVariant *                     variant;
+    GVariant                      *variant;
 
     ht = nm_utils_parse_variant_attributes(str, ' ', ' ', FALSE, tc_object_attribute_spec, error);
     if (!ht)
@@ -2456,11 +2468,11 @@ _tc_read_common_opts(const char *str,
 NMTCQdisc *
 nm_utils_tc_qdisc_from_str(const char *str, GError **error)
 {
-    guint32            handle              = TC_H_UNSPEC;
-    guint32            parent              = TC_H_UNSPEC;
-    gs_free char *     kind                = NULL;
-    gs_free char *     rest                = NULL;
-    NMTCQdisc *        qdisc               = NULL;
+    guint32                        handle  = TC_H_UNSPEC;
+    guint32                        parent  = TC_H_UNSPEC;
+    gs_free char                  *kind    = NULL;
+    gs_free char                  *rest    = NULL;
+    NMTCQdisc                     *qdisc   = NULL;
     gs_unref_hashtable GHashTable *options = NULL;
     GHashTableIter                 iter;
     gpointer                       key, value;
@@ -2541,8 +2553,8 @@ static const NMVariantAttributeSpec *const tc_action_attribute_spec[] = {
 static gboolean
 _string_append_tc_action(GString *string, NMTCAction *action, GError **error)
 {
-    const char *                         kind = nm_tc_action_get_kind(action);
-    gs_free char *                       str  = NULL;
+    const char                          *kind = nm_tc_action_get_kind(action);
+    gs_free char                        *str  = NULL;
     const NMVariantAttributeSpec *const *attrs;
 
     if (nm_streq(kind, "simple"))
@@ -2605,12 +2617,12 @@ nm_utils_tc_action_to_str(NMTCAction *action, GError **error)
 NMTCAction *
 nm_utils_tc_action_from_str(const char *str, GError **error)
 {
-    const char *            kind                 = NULL;
-    const char *            rest                 = NULL;
-    nm_auto_unref_tc_action NMTCAction *action   = NULL;
-    gs_unref_hashtable GHashTable *ht            = NULL;
-    gs_unref_hashtable GHashTable *      options = NULL;
-    GVariant *                           variant;
+    const char                          *kind    = NULL;
+    const char                          *rest    = NULL;
+    nm_auto_unref_tc_action NMTCAction  *action  = NULL;
+    gs_unref_hashtable GHashTable       *ht      = NULL;
+    gs_unref_hashtable GHashTable       *options = NULL;
+    GVariant                            *variant;
     const NMVariantAttributeSpec *const *attrs;
 
     nm_assert(str);
@@ -2753,15 +2765,15 @@ static const NMVariantAttributeSpec *const tc_tfilter_attribute_spec[] = {
 NMTCTfilter *
 nm_utils_tc_tfilter_from_str(const char *str, GError **error)
 {
-    guint32                 handle                 = TC_H_UNSPEC;
-    guint32                 parent                 = TC_H_UNSPEC;
-    gs_free char *          kind                   = NULL;
-    gs_free char *          rest                   = NULL;
+    guint32                             handle     = TC_H_UNSPEC;
+    guint32                             parent     = TC_H_UNSPEC;
+    gs_free char                       *kind       = NULL;
+    gs_free char                       *rest       = NULL;
     nm_auto_unref_tc_action NMTCAction *action     = NULL;
-    const char *                        extra_opts = NULL;
-    NMTCTfilter *                       tfilter    = NULL;
-    gs_unref_hashtable GHashTable *ht              = NULL;
-    GVariant *                     variant;
+    const char                         *extra_opts = NULL;
+    NMTCTfilter                        *tfilter    = NULL;
+    gs_unref_hashtable GHashTable      *ht         = NULL;
+    GVariant                           *variant;
 
     nm_assert(str);
     nm_assert(!error || !*error);
@@ -2826,11 +2838,11 @@ char *
 nm_utils_sriov_vf_to_str(const NMSriovVF *vf, gboolean omit_index, GError **error)
 {
     gs_free NMUtilsNamedValue *values = NULL;
-    gs_free const char **      names  = NULL;
-    const guint *              vlan_ids;
+    gs_free const char       **names  = NULL;
+    const guint               *vlan_ids;
     guint                      num_vlans, num_attrs;
     guint                      i;
-    GString *                  str;
+    GString                   *str;
 
     str = g_string_new("");
     if (!omit_index)
@@ -2987,7 +2999,7 @@ NMSriovVF *
 nm_utils_sriov_vf_from_str(const char *str, GError **error)
 {
     gs_free char *index_free = NULL;
-    const char *  detail;
+    const char   *detail;
 
     g_return_val_if_fail(str, NULL);
     g_return_val_if_fail(!error || !*error, NULL);
@@ -3008,13 +3020,13 @@ NMSriovVF *
 _nm_utils_sriov_vf_from_strparts(const char *index,
                                  const char *detail,
                                  gboolean    ignore_unknown,
-                                 GError **   error)
+                                 GError    **error)
 {
-    NMSriovVF *        vf;
-    guint32            n_index;
-    GHashTableIter     iter;
-    char *             key;
-    GVariant *         variant;
+    NMSriovVF                     *vf;
+    guint32                        n_index;
+    GHashTableIter                 iter;
+    char                          *key;
+    GVariant                      *variant;
     gs_unref_hashtable GHashTable *ht = NULL;
 
     n_index = _nm_utils_ascii_str_to_int64(index, 10, 0, G_MAXUINT32, 0);
@@ -3102,7 +3114,7 @@ file_has_extension(const char *filename, const char *extensions[])
 gboolean
 nm_utils_file_is_certificate(const char *filename)
 {
-    const char *       extensions[] = {".der", ".pem", ".crt", ".cer", NULL};
+    const char        *extensions[] = {".der", ".pem", ".crt", ".cer", NULL};
     NMCryptoFileFormat file_format;
 
     g_return_val_if_fail(filename != NULL, FALSE);
@@ -3160,12 +3172,12 @@ nm_utils_file_is_pkcs12(const char *filename)
 /*****************************************************************************/
 
 gboolean
-_nm_utils_check_file(const char *              filename,
+_nm_utils_check_file(const char               *filename,
                      gint64                    check_owner,
                      NMUtilsCheckFilePredicate check_file,
                      gpointer                  user_data,
-                     struct stat *             out_st,
-                     GError **                 error)
+                     struct stat              *out_st,
+                     GError                  **error)
 {
     struct stat st_backup;
 
@@ -3232,11 +3244,11 @@ _nm_utils_check_file(const char *              filename,
 }
 
 gboolean
-_nm_utils_check_module_file(const char *              name,
+_nm_utils_check_module_file(const char               *name,
                             int                       check_owner,
                             NMUtilsCheckFilePredicate check_file,
                             gpointer                  user_data,
-                            GError **                 error)
+                            GError                  **error)
 {
     if (!g_path_is_absolute(name)) {
         g_set_error(error,
@@ -3310,13 +3322,13 @@ _nm_utils_check_module_file(const char *              name,
  *   invocations of the function might overwrite it.
  */
 const char *
-nm_utils_file_search_in_paths(const char *                      progname,
-                              const char *                      try_first,
-                              const char *const *               paths,
+nm_utils_file_search_in_paths(const char                       *progname,
+                              const char                       *try_first,
+                              const char *const                *paths,
                               GFileTest                         file_test_flags,
                               NMUtilsFileSearchInPathsPredicate predicate,
                               gpointer                          user_data,
-                              GError **                         error)
+                              GError                          **error)
 {
     g_return_val_if_fail(!error || !*error, NULL);
     g_return_val_if_fail(progname && progname[0] && !strchr(progname, '/'), NULL);
@@ -3899,19 +3911,19 @@ _nm_utils_hwaddr_canonical_or_invalid(const char *mac, gssize length)
 }
 
 char *
-_nm_utils_ipaddr_canonical_or_invalid(int addr_family, const char *ip)
+_nm_utils_ipaddr_canonical_or_invalid(int addr_family, const char *ip, gboolean map_zero_to_null)
 {
     NMIPAddr addr_bin;
 
-    nm_assert_addr_family(addr_family);
+    nm_assert_addr_family_or_unspec(addr_family);
 
     if (!ip)
         return NULL;
 
-    if (!nm_utils_parse_inaddr_bin(addr_family, ip, NULL, &addr_bin))
+    if (!nm_utils_parse_inaddr_bin(addr_family, ip, &addr_family, &addr_bin))
         return g_strdup(ip);
 
-    if (nm_ip_addr_is_null(addr_family, &addr_bin))
+    if (map_zero_to_null && nm_ip_addr_is_null(addr_family, &addr_bin))
         return NULL;
 
     return nm_utils_inet_ntop_dup(addr_family, &addr_bin);
@@ -4078,7 +4090,7 @@ _nm_utils_hwaddr_cloned_set(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS _nm_nil)
 {
     gsize         length;
     const guint8 *array;
-    char *        str;
+    char         *str;
 
     nm_assert(nm_streq0(property_info->name, "cloned-mac-address"));
 
@@ -4174,10 +4186,10 @@ const NMSettInfoPropertType nm_sett_info_propert_type_assigned_mac_address =
  * For new settings, they shall validate the secret-flags strictly. */
 gboolean
 _nm_utils_secret_flags_validate(NMSettingSecretFlags secret_flags,
-                                const char *         setting_name,
-                                const char *         property_name,
+                                const char          *setting_name,
+                                const char          *property_name,
                                 NMSettingSecretFlags disallowed_flags,
-                                GError **            error)
+                                GError             **error)
 {
     if (secret_flags == NM_SETTING_SECRET_FLAG_NONE)
         return TRUE;
@@ -4226,10 +4238,10 @@ _nm_utils_secret_flags_validate(NMSettingSecretFlags secret_flags,
 
 gboolean
 _nm_utils_wps_method_validate(NMSettingWirelessSecurityWpsMethod wps_method,
-                              const char *                       setting_name,
-                              const char *                       property_name,
+                              const char                        *setting_name,
+                              const char                        *property_name,
                               gboolean                           wps_required,
-                              GError **                          error)
+                              GError                           **error)
 {
     if (wps_method > NM_SETTING_WIRELESS_SECURITY_WPS_METHOD_PIN) {
         g_set_error_literal(error,
@@ -4283,15 +4295,15 @@ _split_word(char *s)
 }
 
 gboolean
-_nm_utils_generate_mac_address_mask_parse(const char *        value,
-                                          struct ether_addr * out_mask,
+_nm_utils_generate_mac_address_mask_parse(const char         *value,
+                                          struct ether_addr  *out_mask,
                                           struct ether_addr **out_ouis,
-                                          gsize *             out_ouis_len,
-                                          GError **           error)
+                                          gsize              *out_ouis_len,
+                                          GError            **error)
 {
-    gs_free char *    s_free = NULL;
-    char *            s, *s_next;
-    struct ether_addr mask;
+    gs_free char          *s_free = NULL;
+    char                  *s, *s_next;
+    struct ether_addr      mask;
     gs_unref_array GArray *ouis = NULL;
 
     g_return_val_if_fail(!error || !*error, FALSE);
@@ -4694,7 +4706,7 @@ guint
 _nm_utils_strstrdictkey_hash(gconstpointer a)
 {
     const NMUtilsStrStrDictKey *k = a;
-    const char *                p;
+    const char                 *p;
     NMHashState                 h;
 
     nm_hash_init(&h, 76642997u);
@@ -4777,7 +4789,7 @@ _nm_utils_strstrdictkey_create(const char *v1, const char *v2)
 }
 
 static gboolean
-validate_dns_option(const char *                name,
+validate_dns_option(const char                 *name,
                     gboolean                    numeric,
                     gboolean                    ipv6,
                     const NMUtilsDNSOptionDesc *option_descs)
@@ -4813,16 +4825,16 @@ validate_dns_option(const char *                name,
  * %FALSE otherwise
  */
 gboolean
-_nm_utils_dns_option_validate(const char *                option,
-                              char **                     out_name,
-                              long *                      out_value,
+_nm_utils_dns_option_validate(const char                 *option,
+                              char                      **out_name,
+                              long                       *out_value,
                               gboolean                    ipv6,
                               const NMUtilsDNSOptionDesc *option_descs)
 {
     gs_free char *option0_free = NULL;
-    const char *  option0;
-    const char *  option1;
-    const char *  delim;
+    const char   *option0;
+    const char   *option1;
+    const char   *delim;
     long          option1_num;
 
     g_return_val_if_fail(option != NULL, FALSE);
@@ -5013,7 +5025,7 @@ gboolean
 nm_utils_is_json_object(const char *str, GError **error)
 {
     nm_auto_decref_json nm_json_t *json = NULL;
-    const NMJsonVt *               vt;
+    const NMJsonVt                *vt;
     nm_json_error_t                jerror;
 
     g_return_val_if_fail(!error || !*error, FALSE);
@@ -5097,7 +5109,7 @@ _nmtst_variant_attribute_spec_assert_sorted(const NMVariantAttributeSpec *const
 const NMVariantAttributeSpec *
 _nm_variant_attribute_spec_find_binary_search(const NMVariantAttributeSpec *const *array,
                                               gsize                                len,
-                                              const char *                         name)
+                                              const char                          *name)
 {
     gssize idx;
 
@@ -5132,16 +5144,16 @@ _nm_variant_attribute_spec_find_binary_search(const NMVariantAttributeSpec *cons
  * Since: 1.8
  */
 GHashTable *
-nm_utils_parse_variant_attributes(const char *                         string,
+nm_utils_parse_variant_attributes(const char                          *string,
                                   char                                 attr_separator,
                                   char                                 key_value_separator,
                                   gboolean                             ignore_unknown,
                                   const NMVariantAttributeSpec *const *spec,
-                                  GError **                            error)
+                                  GError                             **error)
 {
-    gs_unref_hashtable GHashTable *      ht  = NULL;
-    const char *                         ptr = string, *start = NULL, *sep;
-    GVariant *                           variant;
+    gs_unref_hashtable GHashTable       *ht  = NULL;
+    const char                          *ptr = string, *start = NULL, *sep;
+    GVariant                            *variant;
     const NMVariantAttributeSpec *const *s;
 
     g_return_val_if_fail(string, NULL);
@@ -5460,11 +5472,11 @@ nm_utils_base64secret_decode(const char *base64_key, gsize required_key_len, gui
 gboolean
 nm_utils_base64secret_normalize(const char *base64_key,
                                 gsize       required_key_len,
-                                char **     out_base64_key_norm)
+                                char      **out_base64_key_norm)
 {
     gs_free guint8 *buf_free = NULL;
     guint8          buf_static[200];
-    guint8 *        buf;
+    guint8         *buf;
 
     if (required_key_len > sizeof(buf_static)) {
         buf_free = g_new(guint8, required_key_len);
@@ -5488,7 +5500,7 @@ _nm_utils_bridge_vlans_to_dbus(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil)
     gs_unref_ptrarray GPtrArray *vlans = NULL;
     GVariantBuilder              builder;
     guint                        i;
-    const char *                 property_name = property_info->name;
+    const char                  *property_name = property_info->name;
 
     nm_assert(property_name);
 
@@ -5497,7 +5509,7 @@ _nm_utils_bridge_vlans_to_dbus(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_nil)
 
     if (vlans) {
         for (i = 0; i < vlans->len; i++) {
-            NMBridgeVlan *  vlan = vlans->pdata[i];
+            NMBridgeVlan   *vlan = vlans->pdata[i];
             GVariantBuilder vlan_builder;
             guint16         vid_start, vid_end;
 
@@ -5529,7 +5541,7 @@ _nm_utils_bridge_vlans_from_dbus(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS _nm_nil)
 {
     gs_unref_ptrarray GPtrArray *vlans = NULL;
     GVariantIter                 vlan_iter;
-    GVariant *                   vlan_var;
+    GVariant                    *vlan_var;
 
     g_return_val_if_fail(g_variant_is_of_type(value, G_VARIANT_TYPE("aa{sv}")), FALSE);
 
@@ -5537,7 +5549,7 @@ _nm_utils_bridge_vlans_from_dbus(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS _nm_nil)
     g_variant_iter_init(&vlan_iter, value);
     while (g_variant_iter_next(&vlan_iter, "@a{sv}", &vlan_var)) {
         _nm_unused gs_unref_variant GVariant *var_unref = vlan_var;
-        NMBridgeVlan *                        vlan;
+        NMBridgeVlan                         *vlan;
         guint16                               vid_start, vid_end;
         gboolean                              pvid = FALSE, untagged = FALSE;
 
@@ -5587,13 +5599,13 @@ _nm_utils_bridge_compare_vlans(GPtrArray *vlans_a, GPtrArray *vlans_b)
 }
 
 gboolean
-_nm_utils_bridge_vlan_verify_list(GPtrArray * vlans,
+_nm_utils_bridge_vlan_verify_list(GPtrArray  *vlans,
                                   gboolean    check_normalizable,
-                                  GError **   error,
+                                  GError    **error,
                                   const char *setting,
                                   const char *property)
 {
-    guint              i;
+    guint                          i;
     gs_unref_hashtable GHashTable *h          = NULL;
     gboolean                       pvid_found = FALSE;