summary refs log tree commit diff
path: root/src/core/settings
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/settings')
-rw-r--r--src/core/settings/nm-secret-agent.c2
-rw-r--r--src/core/settings/nm-settings-connection.c2
-rw-r--r--src/core/settings/nm-settings-plugin.c2
-rw-r--r--src/core/settings/nm-settings-utils.c4
-rw-r--r--src/core/settings/nm-settings-utils.h2
-rw-r--r--src/core/settings/nm-settings.c2
-rw-r--r--src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c21
-rw-r--r--src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c34
-rw-r--r--src/core/settings/plugins/ifcfg-rh/shvar.c6
-rw-r--r--src/core/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c29
-rw-r--r--src/core/settings/plugins/ifupdown/nms-ifupdown-plugin.c2
-rw-r--r--src/core/settings/plugins/keyfile/tests/keyfiles/Test_Duplicate_Gateways17
-rw-r--r--src/core/settings/plugins/keyfile/tests/keyfiles/Test_Write_Bluetooth_DUN24
-rw-r--r--src/core/settings/plugins/keyfile/tests/keyfiles/Test_Write_Bridge_Component14
-rw-r--r--src/core/settings/plugins/keyfile/tests/keyfiles/Test_Write_Bridge_Main20
-rw-r--r--src/core/settings/plugins/keyfile/tests/keyfiles/Test_Write_Enum16
-rw-r--r--src/core/settings/plugins/keyfile/tests/keyfiles/Test_Write_Flags18
-rw-r--r--src/core/settings/plugins/keyfile/tests/keyfiles/Test_Write_GSM26
-rw-r--r--src/core/settings/plugins/keyfile/tests/keyfiles/Test_Write_Infiniband19
-rw-r--r--src/core/settings/plugins/keyfile/tests/keyfiles/Test_Write_TC21
-rw-r--r--src/core/settings/plugins/keyfile/tests/keyfiles/Test_Write_Wired36
-rw-r--r--src/core/settings/plugins/keyfile/tests/keyfiles/Test_Write_Wired_IP620
-rw-r--r--src/core/settings/plugins/keyfile/tests/keyfiles/Test_Write_Wireless20
-rw-r--r--src/core/settings/plugins/keyfile/tests/test-keyfile-settings.c125
24 files changed, 417 insertions, 65 deletions
diff --git a/src/core/settings/nm-secret-agent.c b/src/core/settings/nm-secret-agent.c
index bb300345..6448ec57 100644
--- a/src/core/settings/nm-secret-agent.c
+++ b/src/core/settings/nm-secret-agent.c
@@ -142,7 +142,7 @@ _call_id_new(NMSecretAgent        *self,
     NMSecretAgentCallId  *call_id;
 
     call_id  = g_slice_new(NMSecretAgentCallId);
-    *call_id = (NMSecretAgentCallId){
+    *call_id = (NMSecretAgentCallId) {
         .self          = g_object_ref(self),
         .path          = g_strdup(path),
         .setting_name  = g_strdup(setting_name),
diff --git a/src/core/settings/nm-settings-connection.c b/src/core/settings/nm-settings-connection.c
index 459c60ad..d5611e76 100644
--- a/src/core/settings/nm-settings-connection.c
+++ b/src/core/settings/nm-settings-connection.c
@@ -1721,7 +1721,7 @@ settings_connection_update(NMSettingsConnection  *self,
         goto error;
 
     info  = g_slice_new(UpdateInfo);
-    *info = (UpdateInfo){
+    *info = (UpdateInfo) {
         .is_update2   = is_update2,
         .context      = context,
         .agent_mgr    = g_object_ref(priv->agent_mgr),
diff --git a/src/core/settings/nm-settings-plugin.c b/src/core/settings/nm-settings-plugin.c
index 60181759..5dae482f 100644
--- a/src/core/settings/nm-settings-plugin.c
+++ b/src/core/settings/nm-settings-plugin.c
@@ -110,7 +110,7 @@ nm_settings_plugin_create_connection_load_entries(const char *const *filenames,
 
     entries = g_new(NMSettingsPluginConnectionLoadEntry, len);
     for (i = 0; i < len; i++) {
-        entries[i] = (NMSettingsPluginConnectionLoadEntry){
+        entries[i] = (NMSettingsPluginConnectionLoadEntry) {
             .filename = filenames[i],
             .error    = NULL,
             .handled  = FALSE,
diff --git a/src/core/settings/nm-settings-utils.c b/src/core/settings/nm-settings-utils.c
index 4343a376..820d4fbd 100644
--- a/src/core/settings/nm-settings-utils.c
+++ b/src/core/settings/nm-settings-utils.c
@@ -37,14 +37,14 @@ nm_sett_util_stat_mtime(const char *filename, gboolean do_lstat, struct timespec
     }
 
     if (gettimeofday(&now_tv, NULL) == 0) {
-        *out_val = (struct timespec){
+        *out_val = (struct timespec) {
             .tv_sec  = now_tv.tv_sec,
             .tv_nsec = now_tv.tv_usec * 1000u,
         };
         return out_val;
     }
 
-    *out_val = (struct timespec){};
+    *out_val = (struct timespec) {};
     return out_val;
 }
 
diff --git a/src/core/settings/nm-settings-utils.h b/src/core/settings/nm-settings-utils.h
index d3f50ddf..949963e2 100644
--- a/src/core/settings/nm-settings-utils.h
+++ b/src/core/settings/nm-settings-utils.h
@@ -81,7 +81,7 @@ typedef struct {
 } NMSettUtilAllowFilenameData;
 
 #define NM_SETT_UTIL_ALLOW_FILENAME_DATA(_storages, _allowed_filename) \
-    (&((NMSettUtilAllowFilenameData){                                  \
+    (&((NMSettUtilAllowFilenameData) {                                 \
         .idx_by_filename  = (_storages)->idx_by_filename,              \
         .allowed_filename = (_allowed_filename),                       \
     }))
diff --git a/src/core/settings/nm-settings.c b/src/core/settings/nm-settings.c
index 80b1f4b2..50d98ece 100644
--- a/src/core/settings/nm-settings.c
+++ b/src/core/settings/nm-settings.c
@@ -703,7 +703,7 @@ _startup_complete_notify_connection(NMSettings           *self,
         if (timeout_msec == 0)
             return;
         scd  = g_slice_new(StartupCompleteData);
-        *scd = (StartupCompleteData){
+        *scd = (StartupCompleteData) {
             .sett_conn    = g_object_ref(sett_conn),
             .timeout_msec = timeout_msec,
         };
diff --git a/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c b/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c
index 81964de6..d64052cb 100644
--- a/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c
+++ b/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c
@@ -2056,9 +2056,8 @@ make_ip4_setting(shvarFile *ifcfg,
          * Pick up just IPv4 addresses (IPv6 addresses are taken by make_ip6_setting())
          */
         for (i = 1; i < 10000; i++) {
-            int      af;
-            NMIPAddr ip;
-            char     tag[256];
+            NMDnsServer dns;
+            char        tag[256];
 
             numbered_tag(tag, "DNS", i);
             nm_clear_g_free(&value);
@@ -2066,14 +2065,16 @@ make_ip4_setting(shvarFile *ifcfg,
             if (!v)
                 break;
 
-            if (!nm_utils_dnsname_parse(AF_UNSPEC, v, &af, &ip, NULL)) {
+            if (!nm_dns_uri_parse(AF_UNSPEC, v, &dns)) {
                 g_set_error(error,
                             NM_SETTINGS_ERROR,
                             NM_SETTINGS_ERROR_INVALID_CONNECTION,
                             "Invalid DNS server address '%s'",
                             v);
                 return NULL;
-            } else if (af == AF_INET) {
+            }
+
+            if (dns.addr_family == AF_INET) {
                 if (!nm_setting_ip_config_add_dns(s_ip4, v))
                     PARSE_WARNING("duplicate DNS server %s", tag);
             } else {
@@ -2606,9 +2607,8 @@ make_ip6_setting(shvarFile *ifcfg, shvarFile *network_ifcfg, gboolean routes_rea
      * Pick up just IPv6 addresses (IPv4 addresses are taken by make_ip4_setting())
      */
     for (i = 1; i < 10000; i++) {
-        int      af;
-        NMIPAddr ip;
-        char     tag[256];
+        NMDnsServer dns;
+        char        tag[256];
 
         numbered_tag(tag, "DNS", i);
         nm_clear_g_free(&value);
@@ -2616,7 +2616,7 @@ make_ip6_setting(shvarFile *ifcfg, shvarFile *network_ifcfg, gboolean routes_rea
         if (!v)
             break;
 
-        if (!nm_utils_dnsname_parse(AF_UNSPEC, v, &af, &ip, NULL)) {
+        if (!nm_dns_uri_parse(AF_UNSPEC, v, &dns)) {
             if (is_disabled)
                 continue;
             g_set_error(error,
@@ -2625,7 +2625,8 @@ make_ip6_setting(shvarFile *ifcfg, shvarFile *network_ifcfg, gboolean routes_rea
                         "Invalid DNS server address '%s'",
                         v);
             return NULL;
-        } else if (af == AF_INET6) {
+        }
+        if (dns.addr_family == AF_INET6) {
             if (is_disabled) {
                 PARSE_WARNING("ignore DNS server addresses with method disabled/ignore");
                 break;
diff --git a/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c b/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c
index 21f31d8b..6e0411c6 100644
--- a/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c
+++ b/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c
@@ -1454,6 +1454,15 @@ write_ethtool_setting(NMConnection *connection, shvarFile *ifcfg, GError **error
                 return FALSE;
             }
         }
+        if (ethtool_id == NM_ETHTOOL_ID_FEC_MODE) {
+            if (nm_setting_option_get_uint32(NM_SETTING(s_ethtool),
+                                             nm_ethtool_data[ethtool_id]->optname,
+                                             &u32)) {
+                nm_sprintf_buf(prop_name, "ethtool.%s", nm_ethtool_data[ethtool_id]->optname);
+                set_error_unsupported(error, connection, prop_name, FALSE);
+                return FALSE;
+            }
+        }
 
         if (!any_option) {
             /* Write an empty dummy "-A" option without arguments. This is to
@@ -3588,13 +3597,24 @@ do_write_construct(NMConnection                   *connection,
     } else
         route_ignore = FALSE;
 
-    if ((s_ip4 = nm_connection_get_setting_ip4_config(connection))
-        && nm_setting_ip_config_get_dhcp_dscp(s_ip4)) {
-        set_error_unsupported(error,
-                              connection,
-                              NM_SETTING_IP4_CONFIG_SETTING_NAME "." NM_SETTING_IP_CONFIG_DHCP_DSCP,
-                              FALSE);
-        return FALSE;
+    if ((s_ip4 = nm_connection_get_setting_ip4_config(connection))) {
+        if (nm_setting_ip_config_get_dhcp_dscp(s_ip4)) {
+            set_error_unsupported(error,
+                                  connection,
+                                  NM_SETTING_IP4_CONFIG_SETTING_NAME
+                                  "." NM_SETTING_IP_CONFIG_DHCP_DSCP,
+                                  FALSE);
+            return FALSE;
+        }
+        if (nm_setting_ip4_config_get_dhcp_ipv6_only_preferred(NM_SETTING_IP4_CONFIG(s_ip4))
+            != NM_SETTING_IP4_DHCP_IPV6_ONLY_PREFERRED_DEFAULT) {
+            set_error_unsupported(error,
+                                  connection,
+                                  NM_SETTING_IP4_CONFIG_SETTING_NAME
+                                  "." NM_SETTING_IP4_CONFIG_DHCP_IPV6_ONLY_PREFERRED,
+                                  FALSE);
+            return FALSE;
+        }
     }
 
     write_ip4_setting(connection,
diff --git a/src/core/settings/plugins/ifcfg-rh/shvar.c b/src/core/settings/plugins/ifcfg-rh/shvar.c
index 1ca2ea60..565e20f7 100644
--- a/src/core/settings/plugins/ifcfg-rh/shvar.c
+++ b/src/core/settings/plugins/ifcfg-rh/shvar.c
@@ -722,7 +722,7 @@ svFile_new(const char *name, int fd, const char *content)
     nm_assert(fd >= -1);
 
     s  = g_slice_new(shvarFile);
-    *s = (shvarFile){
+    *s = (shvarFile) {
         .fileName = g_strdup(name),
         .fd       = fd,
         .lst_head = C_LIST_INIT(s->lst_head),
@@ -796,7 +796,7 @@ line_new_parse(const char *value, gsize len)
     nm_assert(value);
 
     line  = g_slice_new(shvarLine);
-    *line = (shvarLine){
+    *line = (shvarLine) {
         .lst   = C_LIST_INIT(line->lst),
         .dirty = TRUE,
     };
@@ -836,7 +836,7 @@ line_new_build(const char *key, const char *value)
     value = svEscape(value, &value_escaped);
 
     line    = g_slice_new(shvarLine);
-    new_key = g_strdup(key), *line = (shvarLine){
+    new_key = g_strdup(key), *line = (shvarLine) {
                                  .lst             = C_LIST_INIT(line->lst),
                                  .line            = value_escaped ?: g_strdup(value),
                                  .key_with_prefix = new_key,
diff --git a/src/core/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c b/src/core/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c
index 334662c3..ea978a98 100644
--- a/src/core/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c
+++ b/src/core/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c
@@ -3623,7 +3623,8 @@ test_roundtrip_ethtool(void)
             optname = nm_ethtool_data[ethtool_id]->optname;
             vtype   = nm_ethtool_id_get_variant_type(ethtool_id);
 
-            if (nm_ethtool_optname_is_channels(optname) || nm_ethtool_optname_is_eee(optname)) {
+            if (nm_ethtool_optname_is_channels(optname) || nm_ethtool_optname_is_eee(optname)
+                || nm_ethtool_optname_is_fec(optname)) {
                 /* Not supported */
                 continue;
             }
@@ -9520,18 +9521,24 @@ do_svUnescape_combine_ansi(GString                *str_val,
 static void
 test_svUnescape(void)
 {
-#define V0(v_value, v_expected)                                       \
-    {                                                                 \
-        .val = "" v_value "", .exp = v_expected, .can_concat = FALSE, \
+#define V0(v_value, v_expected)      \
+    {                                \
+        .val        = "" v_value "", \
+        .exp        = v_expected,    \
+        .can_concat = FALSE,         \
     }
-#define V1(v_value, v_expected)                                              \
-    {                                                                        \
-        .val = "" v_value "", .exp = v_expected, .can_concat = !!v_expected, \
+#define V1(v_value, v_expected)      \
+    {                                \
+        .val        = "" v_value "", \
+        .exp        = v_expected,    \
+        .can_concat = !!v_expected,  \
     }
-#define V2(v_value, v_expected)                                      \
-    {                                                                \
-        .val = "" v_value "", .exp = v_expected, .can_concat = TRUE, \
-        .needs_ascii_separator = TRUE,                               \
+#define V2(v_value, v_expected)                 \
+    {                                           \
+        .val                   = "" v_value "", \
+        .exp                   = v_expected,    \
+        .can_concat            = TRUE,          \
+        .needs_ascii_separator = TRUE,          \
     }
     const UnescapeTestData data_full[] = {
         V1("", ""),
diff --git a/src/core/settings/plugins/ifupdown/nms-ifupdown-plugin.c b/src/core/settings/plugins/ifupdown/nms-ifupdown-plugin.c
index 14c82c55..1b03ce2a 100644
--- a/src/core/settings/plugins/ifupdown/nms-ifupdown-plugin.c
+++ b/src/core/settings/plugins/ifupdown/nms-ifupdown-plugin.c
@@ -330,7 +330,7 @@ load_eni_ifaces(NMSIfupdownPlugin *self)
                     storage = nm_settings_storage_new(NM_SETTINGS_PLUGIN(self), uuid, NULL);
 
                 sd  = g_slice_new(StorageData);
-                *sd = (StorageData){
+                *sd = (StorageData) {
                     .connection = g_steal_pointer(&connection),
                     .storage    = g_steal_pointer(&storage),
                 };
diff --git a/src/core/settings/plugins/keyfile/tests/keyfiles/Test_Duplicate_Gateways b/src/core/settings/plugins/keyfile/tests/keyfiles/Test_Duplicate_Gateways
new file mode 100644
index 00000000..0b081761
--- /dev/null
+++ b/src/core/settings/plugins/keyfile/tests/keyfiles/Test_Duplicate_Gateways
@@ -0,0 +1,17 @@
+[connection]
+id=Test Duplicate Gateways
+uuid=5e2a7b1e-e4c8-4964-88c4-ca7255471aa1
+type=802-3-ethernet
+autoconnect=true
+timestamp=6654332
+
+[ipv4]
+method=manual
+address1=192.168.0.5/24;192.168.0.254
+address2=192.0.2.1/16
+gateway=192.168.0.253
+
+[ipv6]
+method=manual
+gateway=fd01::bbbb
+address1=fd01::1/64;fd01::aaaa
diff --git a/src/core/settings/plugins/keyfile/tests/keyfiles/Test_Write_Bluetooth_DUN b/src/core/settings/plugins/keyfile/tests/keyfiles/Test_Write_Bluetooth_DUN
new file mode 100644
index 00000000..80de393e
--- /dev/null
+++ b/src/core/settings/plugins/keyfile/tests/keyfiles/Test_Write_Bluetooth_DUN
@@ -0,0 +1,24 @@
+[connection]
+id=T-Mobile Funkadelic
+uuid=76c59c25-c27c-57a4-8357-1409491cea45
+type=bluetooth
+autoconnect=false
+timestamp=305415219
+
+[gsm]
+apn=internet2.voicestream.com
+password=parliament
+username=george.clinton
+
+[bluetooth]
+bdaddr=AA:B9:A1:74:55:44
+type=dun
+
+[ipv4]
+method=auto
+
+[ipv6]
+addr-gen-mode=default
+method=auto
+
+[proxy]
diff --git a/src/core/settings/plugins/keyfile/tests/keyfiles/Test_Write_Bridge_Component b/src/core/settings/plugins/keyfile/tests/keyfiles/Test_Write_Bridge_Component
new file mode 100644
index 00000000..81e1ba80
--- /dev/null
+++ b/src/core/settings/plugins/keyfile/tests/keyfiles/Test_Write_Bridge_Component
@@ -0,0 +1,14 @@
+[connection]
+id=Test Write Bridge Component
+uuid=7c4e34eb-419f-531c-b6ca-486f51a08d1d
+type=ethernet
+controller=br0
+port-type=bridge
+
+[ethernet]
+mac-address=99:88:77:66:55:44
+mtu=1300
+
+[bridge-port]
+path-cost=99
+priority=3
diff --git a/src/core/settings/plugins/keyfile/tests/keyfiles/Test_Write_Bridge_Main b/src/core/settings/plugins/keyfile/tests/keyfiles/Test_Write_Bridge_Main
new file mode 100644
index 00000000..03182b43
--- /dev/null
+++ b/src/core/settings/plugins/keyfile/tests/keyfiles/Test_Write_Bridge_Main
@@ -0,0 +1,20 @@
+[connection]
+id=Test Write Bridge Main
+uuid=b23c15e0-815b-5e6e-a5f9-aea49237aa35
+type=bridge
+interface-name=br0
+
+[ethernet]
+
+[bridge]
+
+[ipv4]
+address1=1.2.3.4/24
+gateway=1.1.1.1
+method=manual
+
+[ipv6]
+addr-gen-mode=default
+method=auto
+
+[proxy]
diff --git a/src/core/settings/plugins/keyfile/tests/keyfiles/Test_Write_Enum b/src/core/settings/plugins/keyfile/tests/keyfiles/Test_Write_Enum
new file mode 100644
index 00000000..3ebd6657
--- /dev/null
+++ b/src/core/settings/plugins/keyfile/tests/keyfiles/Test_Write_Enum
@@ -0,0 +1,16 @@
+[connection]
+id=Test Write Enum Property
+uuid=7e4cb57c-33ff-51fc-ae49-4ee414ef0b63
+type=ethernet
+
+[ethernet]
+
+[ipv4]
+method=auto
+
+[ipv6]
+addr-gen-mode=default
+ip6-privacy=2
+method=auto
+
+[proxy]
diff --git a/src/core/settings/plugins/keyfile/tests/keyfiles/Test_Write_Flags b/src/core/settings/plugins/keyfile/tests/keyfiles/Test_Write_Flags
new file mode 100644
index 00000000..403a3fd2
--- /dev/null
+++ b/src/core/settings/plugins/keyfile/tests/keyfiles/Test_Write_Flags
@@ -0,0 +1,18 @@
+[connection]
+id=Test Write Flags Property
+uuid=19febe12-db48-5661-94cc-16529548d772
+type=gsm
+
+[gsm]
+apn=myapn
+password-flags=6
+username=adfasdfasdf
+
+[ipv4]
+method=auto
+
+[ipv6]
+addr-gen-mode=default
+method=auto
+
+[proxy]
diff --git a/src/core/settings/plugins/keyfile/tests/keyfiles/Test_Write_GSM b/src/core/settings/plugins/keyfile/tests/keyfiles/Test_Write_GSM
new file mode 100644
index 00000000..2f6dc26c
--- /dev/null
+++ b/src/core/settings/plugins/keyfile/tests/keyfiles/Test_Write_GSM
@@ -0,0 +1,26 @@
+[connection]
+id=T-Mobile Funkadelic 2
+uuid=952d369e-52c7-5686-ad8c-37ca7e47f8b2
+type=gsm
+autoconnect=false
+timestamp=305415219
+
+[gsm]
+apn=internet2.voicestream.com
+device-id=da812de91eec16620b06cd0ca5cbc7ea25245222
+home-only=true
+network-id=254098
+password=parliament2
+pin=123456
+sim-id=89148000000060671234
+sim-operator-id=310260
+username=george.clinton.again
+
+[ipv4]
+method=auto
+
+[ipv6]
+addr-gen-mode=default
+method=auto
+
+[proxy]
diff --git a/src/core/settings/plugins/keyfile/tests/keyfiles/Test_Write_Infiniband b/src/core/settings/plugins/keyfile/tests/keyfiles/Test_Write_Infiniband
new file mode 100644
index 00000000..f72b669e
--- /dev/null
+++ b/src/core/settings/plugins/keyfile/tests/keyfiles/Test_Write_Infiniband
@@ -0,0 +1,19 @@
+[connection]
+id=Work InfiniBand
+uuid=c27325f5-9eff-517a-9d96-d7897785fa5b
+type=infiniband
+autoconnect=false
+
+[infiniband]
+mac-address=99:88:77:66:55:44:AB:BC:CD:DE:EF:F0:0A:1B:2C:3D:4E:5F:6F:BA
+mtu=900
+transport-mode=datagram
+
+[ipv4]
+method=auto
+
+[ipv6]
+addr-gen-mode=default
+method=auto
+
+[proxy]
diff --git a/src/core/settings/plugins/keyfile/tests/keyfiles/Test_Write_TC b/src/core/settings/plugins/keyfile/tests/keyfiles/Test_Write_TC
new file mode 100644
index 00000000..496e7bd9
--- /dev/null
+++ b/src/core/settings/plugins/keyfile/tests/keyfiles/Test_Write_TC
@@ -0,0 +1,21 @@
+[connection]
+id=Test TC
+uuid=ed1cb963-ff64-5129-99ca-e05ab3195ce4
+type=ethernet
+
+[ethernet]
+
+[ipv4]
+method=auto
+
+[ipv6]
+addr-gen-mode=default
+method=auto
+
+[proxy]
+
+[tc]
+qdisc.root=handle 1234: fq_codel
+qdisc.ffff:fff1=ingress
+tfilter.1234:=matchall action drop
+tfilter.ffff:=matchall action simple sdata Hello
diff --git a/src/core/settings/plugins/keyfile/tests/keyfiles/Test_Write_Wired b/src/core/settings/plugins/keyfile/tests/keyfiles/Test_Write_Wired
new file mode 100644
index 00000000..69ca9a6d
--- /dev/null
+++ b/src/core/settings/plugins/keyfile/tests/keyfiles/Test_Write_Wired
@@ -0,0 +1,36 @@
+[connection]
+id=Work Wired
+uuid=9342d47a-1bab-5709-9869-c840b2eac501
+type=ethernet
+autoconnect=false
+timestamp=305419896
+
+[ethernet]
+mac-address=99:88:77:66:55:44
+mtu=900
+
+[ipv4]
+address1=192.168.0.5/24
+address2=1.2.3.4/8
+dns=4.2.2.1;4.2.2.2;
+gateway=192.168.0.1
+method=manual
+route1=10.10.10.2/24,10.10.10.1,3
+route2=1.1.1.1/8,1.2.1.1,1
+route3=2.2.2.2/7
+route4=3.3.3.3/6,0.0.0.0,4
+route4_options=cwnd=10,mtu=1492,src=1.2.3.4,weight=5
+
+[ipv6]
+addr-gen-mode=default
+address1=abcd::beef/64
+address2=dcba::beef/56
+dns=1::cafe;2::cafe;
+dns-search=wallaceandgromit.com;
+method=manual
+route1=1:2:3:4:5:6:7:8/64,8:7:6:5:4:3:2:1,3
+route2=2001::1000/56,2001::1111,1
+route3=4:5:6:7:8:9:0:1/63,::,5
+route4=5:6:7:8:9:0:1:2/62
+
+[proxy]
diff --git a/src/core/settings/plugins/keyfile/tests/keyfiles/Test_Write_Wired_IP6 b/src/core/settings/plugins/keyfile/tests/keyfiles/Test_Write_Wired_IP6
new file mode 100644
index 00000000..cc379ec6
--- /dev/null
+++ b/src/core/settings/plugins/keyfile/tests/keyfiles/Test_Write_Wired_IP6
@@ -0,0 +1,20 @@
+[connection]
+id=Work Wired IP6
+uuid=0bef2d09-50a3-56b9-912a-5dc941284e3e
+type=ethernet
+autoconnect=false
+
+[ethernet]
+
+[ipv4]
+method=disabled
+
+[ipv6]
+addr-gen-mode=default
+address1=abcd::beef/64
+dns=1::cafe;
+dns-search=wallaceandgromit.com;
+gateway=dcba::beef
+method=manual
+
+[proxy]
diff --git a/src/core/settings/plugins/keyfile/tests/keyfiles/Test_Write_Wireless b/src/core/settings/plugins/keyfile/tests/keyfiles/Test_Write_Wireless
new file mode 100644
index 00000000..2fc15098
--- /dev/null
+++ b/src/core/settings/plugins/keyfile/tests/keyfiles/Test_Write_Wireless
@@ -0,0 +1,20 @@
+[connection]
+id=Work Wireless
+uuid=e9b337d3-6aa0-552a-822c-4b71c8ddec2e
+type=wifi
+autoconnect=false
+timestamp=305415219
+
+[wifi]
+bssid=AA:B9:A1:74:55:44
+mtu=1000
+ssid=1337
+
+[ipv4]
+method=auto
+
+[ipv6]
+addr-gen-mode=default
+method=auto
+
+[proxy]
diff --git a/src/core/settings/plugins/keyfile/tests/test-keyfile-settings.c b/src/core/settings/plugins/keyfile/tests/test-keyfile-settings.c
index f999105a..6b6913c5 100644
--- a/src/core/settings/plugins/keyfile/tests/test-keyfile-settings.c
+++ b/src/core/settings/plugins/keyfile/tests/test-keyfile-settings.c
@@ -163,13 +163,48 @@ write_test_connection(NMConnection *connection, char **testfile)
 }
 
 static void
-write_test_connection_and_reread(NMConnection *connection, gboolean normalize_connection)
+write_test_connection_and_reread(NMConnection *connection,
+                                 gboolean      normalize_connection,
+                                 const char   *reference)
 {
     gs_free char *testfile = NULL;
 
     g_assert(NM_IS_CONNECTION(connection));
 
     write_test_connection(connection, &testfile);
+
+    if (reference) {
+        gs_free char         *data1 = NULL;
+        gs_free char         *data2 = NULL;
+        gsize                 len1;
+        gsize                 len2;
+        gs_free_error GError *error = NULL;
+        gboolean              success;
+
+        success = g_file_get_contents(testfile, &data1, &len1, &error);
+        nmtst_assert_success(success, error);
+
+        if (nm_streq0(g_getenv("NM_TEST_REGENERATE"), "1")) {
+            success = g_file_set_contents(reference, data1, len1, &error);
+            nmtst_assert_success(success, error);
+        } else {
+            success = g_file_get_contents(reference, &data2, &len2, &error);
+            nmtst_assert_success(success, error);
+
+            if (len1 != len2 || !nm_streq0(data1, data2)) {
+                g_error("The content of \"%s\" (%zu) differs from \"%s\" (%zu). Set "
+                        "NM_TEST_REGENERATE=1 to update the files "
+                        "in place\n\n>>>%s<<<\n\n>>>%s<<<\n",
+                        testfile,
+                        len1,
+                        reference,
+                        len2,
+                        data1,
+                        data2);
+            }
+        }
+    }
+
     assert_reread_and_unlink(connection, normalize_connection, testfile);
 }
 
@@ -369,6 +404,34 @@ test_read_valid_wired_connection(void)
 }
 
 static void
+test_read_duplicate_gateways(void)
+{
+    gs_unref_object NMConnection *connection = NULL;
+    NMSettingIPConfig            *s_ip4;
+    NMSettingIPConfig            *s_ip6;
+
+    NMTST_EXPECT_NM_WARN(
+        "*ipv4* ignoring gateway * from \"address*\" keys because the \"gateway\" key is set*");
+    NMTST_EXPECT_NM_WARN(
+        "*ipv6* ignoring gateway * from \"address*\" keys because the \"gateway\" key is set*");
+    connection = keyfile_read_connection_from_file(TEST_KEYFILES_DIR "/Test_Duplicate_Gateways");
+    g_test_assert_expected_messages();
+
+    s_ip4 = nm_connection_get_setting_ip4_config(connection);
+    g_assert(s_ip4);
+    g_assert_cmpint(nm_setting_ip_config_get_num_addresses(s_ip4), ==, 2);
+    check_ip_address(s_ip4, 0, "192.168.0.5", 24);
+    check_ip_address(s_ip4, 1, "192.0.2.1", 16);
+    g_assert_cmpstr(nm_setting_ip_config_get_gateway(s_ip4), ==, "192.168.0.253");
+
+    s_ip6 = nm_connection_get_setting_ip6_config(connection);
+    g_assert(s_ip6);
+    g_assert_cmpint(nm_setting_ip_config_get_num_addresses(s_ip6), ==, 1);
+    check_ip_address(s_ip6, 0, "fd01::1", 64);
+    g_assert_cmpstr(nm_setting_ip_config_get_gateway(s_ip6), ==, "fd01::bbbb");
+}
+
+static void
 add_one_ip_address(NMSettingIPConfig *s_ip, const char *addr, guint32 prefix)
 {
     NMIPAddress          *ip_addr;
@@ -408,13 +471,13 @@ add_one_ip_route(NMSettingIPConfig *s_ip,
 static void
 test_write_wired_connection(void)
 {
-    NMTST_UUID_INIT(uuid);
     gs_unref_object NMConnection *connection = NULL;
     NMSettingConnection          *s_con;
     NMSettingWired               *s_wired;
     NMSettingIPConfig            *s_ip4;
     NMSettingIPConfig            *s_ip6;
     NMIPRoute                    *rt;
+    const char                   *uuid        = "9342d47a-1bab-5709-9869-c840b2eac501";
     const char                   *mac         = "99:88:77:66:55:44";
     const char                   *dns1        = "4.2.2.1";
     const char                   *dns2        = "4.2.2.2";
@@ -529,7 +592,7 @@ test_write_wired_connection(void)
     /* DNS searches */
     nm_setting_ip_config_add_dns_search(s_ip6, "wallaceandgromit.com");
 
-    write_test_connection_and_reread(connection, FALSE);
+    write_test_connection_and_reread(connection, FALSE, TEST_KEYFILES_DIR "/Test_Write_Wired");
 }
 
 static void
@@ -573,12 +636,12 @@ test_read_ip6_wired_connection(void)
 static void
 test_write_ip6_wired_connection(void)
 {
-    NMTST_UUID_INIT(uuid);
     gs_unref_object NMConnection *connection = NULL;
     NMSettingConnection          *s_con;
     NMSettingWired               *s_wired;
     NMSettingIPConfig            *s_ip4;
     NMSettingIPConfig            *s_ip6;
+    const char                   *uuid    = "0bef2d09-50a3-56b9-912a-5dc941284e3e";
     const char                   *dns     = "1::cafe";
     const char                   *address = "abcd::beef";
     const char                   *gw      = "dcba::beef";
@@ -634,7 +697,7 @@ test_write_ip6_wired_connection(void)
     /* DNS searches */
     nm_setting_ip_config_add_dns_search(s_ip6, "wallaceandgromit.com");
 
-    write_test_connection_and_reread(connection, FALSE);
+    write_test_connection_and_reread(connection, FALSE, TEST_KEYFILES_DIR "/Test_Write_Wired_IP6");
 }
 
 static void
@@ -746,12 +809,12 @@ test_read_valid_wireless_connection(void)
 static void
 test_write_wireless_connection(void)
 {
-    NMTST_UUID_INIT(uuid);
     gs_unref_object NMConnection *connection = NULL;
     NMSettingConnection          *s_con;
     NMSettingWireless            *s_wireless;
     NMSettingIPConfig            *s_ip4;
     NMSettingIPConfig            *s_ip6;
+    const char                   *uuid  = "e9b337d3-6aa0-552a-822c-4b71c8ddec2e";
     const char                   *bssid = "aa:b9:a1:74:55:44";
     GBytes                       *ssid;
     unsigned char                 tmpssid[] = {0x31, 0x33, 0x33, 0x37};
@@ -809,7 +872,7 @@ test_write_wireless_connection(void)
 
     g_object_set(s_ip6, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_AUTO, NULL);
 
-    write_test_connection_and_reread(connection, FALSE);
+    write_test_connection_and_reread(connection, FALSE, TEST_KEYFILES_DIR "/Test_Write_Wireless");
 }
 
 static void
@@ -1181,12 +1244,12 @@ test_read_bt_dun_connection(void)
 static void
 test_write_bt_dun_connection(void)
 {
-    NMTST_UUID_INIT(uuid);
     gs_unref_object NMConnection *connection = NULL;
     NMSettingConnection          *s_con;
     NMSettingBluetooth           *s_bt;
     NMSettingIPConfig            *s_ip4;
     NMSettingGsm                 *s_gsm;
+    const char                   *uuid      = "76c59c25-c27c-57a4-8357-1409491cea45";
     const char                   *bdaddr    = "aa:b9:a1:74:55:44";
     guint64                       timestamp = 0x12344433L;
 
@@ -1242,7 +1305,9 @@ test_write_bt_dun_connection(void)
                  "parliament",
                  NULL);
 
-    write_test_connection_and_reread(connection, TRUE);
+    write_test_connection_and_reread(connection,
+                                     TRUE,
+                                     TEST_KEYFILES_DIR "/Test_Write_Bluetooth_DUN");
 }
 
 static void
@@ -1286,12 +1351,12 @@ test_read_gsm_connection(void)
 static void
 test_write_gsm_connection(void)
 {
-    NMTST_UUID_INIT(uuid);
     gs_unref_object NMConnection *connection = NULL;
     NMSettingConnection          *s_con;
     NMSettingIPConfig            *s_ip4;
     NMSettingGsm                 *s_gsm;
     guint64                       timestamp = 0x12344433L;
+    const char                   *uuid      = "952d369e-52c7-5686-ad8c-37ca7e47f8b2";
 
     connection = nm_simple_connection_new();
 
@@ -1345,7 +1410,7 @@ test_write_gsm_connection(void)
                  "310260",
                  NULL);
 
-    write_test_connection_and_reread(connection, TRUE);
+    write_test_connection_and_reread(connection, TRUE, TEST_KEYFILES_DIR "/Test_Write_GSM");
 }
 
 static void
@@ -1830,12 +1895,12 @@ test_read_infiniband_connection(void)
 static void
 test_write_infiniband_connection(void)
 {
-    NMTST_UUID_INIT(uuid);
     gs_unref_object NMConnection *connection = NULL;
     NMSettingConnection          *s_con;
     NMSettingInfiniband          *s_ib;
     NMSettingIPConfig            *s_ip4;
     NMSettingIPConfig            *s_ip6;
+    const char                   *uuid = "c27325f5-9eff-517a-9d96-d7897785fa5b";
     const char *mac = "99:88:77:66:55:44:ab:bc:cd:de:ef:f0:0a:1b:2c:3d:4e:5f:6f:ba";
 
     connection = nm_simple_connection_new();
@@ -1883,7 +1948,7 @@ test_write_infiniband_connection(void)
     nm_connection_add_setting(connection, NM_SETTING(s_ip6));
     g_object_set(s_ip6, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_AUTO, NULL);
 
-    write_test_connection_and_reread(connection, FALSE);
+    write_test_connection_and_reread(connection, FALSE, TEST_KEYFILES_DIR "/Test_Write_Infiniband");
 }
 
 static void
@@ -1922,13 +1987,13 @@ test_read_bridge_main(void)
 static void
 test_write_bridge_main(void)
 {
-    NMTST_UUID_INIT(uuid);
     gs_unref_object NMConnection *connection = NULL;
     NMSettingConnection          *s_con;
     NMSettingBridge              *s_bridge;
     NMSettingWired               *s_wired;
     NMSettingIPConfig            *s_ip4;
     NMSettingIPConfig            *s_ip6;
+    const char                   *uuid = "b23c15e0-815b-5e6e-a5f9-aea49237aa35";
 
     connection = nm_simple_connection_new();
     g_assert(connection);
@@ -1982,7 +2047,9 @@ test_write_bridge_main(void)
     nm_connection_add_setting(connection, NM_SETTING(s_ip6));
     g_object_set(s_ip6, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_AUTO, NULL);
 
-    write_test_connection_and_reread(connection, FALSE);
+    write_test_connection_and_reread(connection,
+                                     FALSE,
+                                     TEST_KEYFILES_DIR "/Test_Write_Bridge_Main");
 }
 
 static void
@@ -2022,12 +2089,12 @@ test_read_bridge_component(void)
 static void
 test_write_bridge_component(void)
 {
-    NMTST_UUID_INIT(uuid);
     gs_unref_object NMConnection *connection = NULL;
     NMSettingConnection          *s_con;
     NMSettingBridgePort          *s_port;
     NMSettingWired               *s_wired;
-    const char                   *mac = "99:88:77:66:55:44";
+    const char                   *mac  = "99:88:77:66:55:44";
+    const char                   *uuid = "7c4e34eb-419f-531c-b6ca-486f51a08d1d";
 
     connection = nm_simple_connection_new();
     g_assert(connection);
@@ -2071,7 +2138,9 @@ test_write_bridge_component(void)
                  99,
                  NULL);
 
-    write_test_connection_and_reread(connection, FALSE);
+    write_test_connection_and_reread(connection,
+                                     FALSE,
+                                     TEST_KEYFILES_DIR "/Test_Write_Bridge_Component");
 }
 
 static void
@@ -2423,11 +2492,11 @@ test_read_enum_property(void)
 static void
 test_write_enum_property(void)
 {
-    NMTST_UUID_INIT(uuid);
     gs_unref_object NMConnection *connection = NULL;
     NMSettingConnection          *s_con;
     NMSettingWired               *s_wired;
     NMSettingIPConfig            *s_ip6;
+    const char                   *uuid = "7e4cb57c-33ff-51fc-ae49-4ee414ef0b63";
 
     connection = nm_simple_connection_new();
 
@@ -2461,7 +2530,7 @@ test_write_enum_property(void)
 
     nmtst_connection_normalize(connection);
 
-    write_test_connection_and_reread(connection, FALSE);
+    write_test_connection_and_reread(connection, FALSE, TEST_KEYFILES_DIR "/Test_Write_Enum");
 }
 
 static void
@@ -2482,10 +2551,10 @@ test_read_flags_property(void)
 static void
 test_write_flags_property(void)
 {
-    NMTST_UUID_INIT(uuid);
     gs_unref_object NMConnection *connection = NULL;
     NMSettingConnection          *s_con;
     NMSetting                    *s_gsm;
+    const char                   *uuid = "19febe12-db48-5661-94cc-16529548d772";
 
     connection = nm_simple_connection_new();
 
@@ -2517,7 +2586,7 @@ test_write_flags_property(void)
 
     nmtst_connection_normalize(connection);
 
-    write_test_connection_and_reread(connection, FALSE);
+    write_test_connection_and_reread(connection, FALSE, TEST_KEYFILES_DIR "/Test_Write_Flags");
 }
 
 /*****************************************************************************/
@@ -2586,9 +2655,11 @@ test_write_tc_config(void)
     NMTCAction                   *action;
     GError                       *error = NULL;
 
-    connection =
-        nmtst_create_minimal_connection("Test TC", NULL, NM_SETTING_WIRED_SETTING_NAME, NULL);
-    s_tc = nm_setting_tc_config_new();
+    connection = nmtst_create_minimal_connection("Test TC",
+                                                 "ed1cb963-ff64-5129-99ca-e05ab3195ce4",
+                                                 NM_SETTING_WIRED_SETTING_NAME,
+                                                 NULL);
+    s_tc       = nm_setting_tc_config_new();
 
     qdisc1 = nm_tc_qdisc_new("fq_codel", TC_H_ROOT, &error);
     nmtst_assert_success(qdisc1, error);
@@ -2622,7 +2693,7 @@ test_write_tc_config(void)
     nm_connection_add_setting(connection, s_tc);
 
     nmtst_connection_normalize(connection);
-    write_test_connection_and_reread(connection, FALSE);
+    write_test_connection_and_reread(connection, FALSE, TEST_KEYFILES_DIR "/Test_Write_TC");
 
     nm_tc_qdisc_unref(qdisc1);
     nm_tc_qdisc_unref(qdisc2);
@@ -2856,6 +2927,8 @@ main(int argc, char **argv)
     g_test_add_func("/keyfile/test_read_valid_wired_connection", test_read_valid_wired_connection);
     g_test_add_func("/keyfile/test_write_wired_connection", test_write_wired_connection);
 
+    g_test_add_func("/keyfile/test_read_duplicate_gateways", test_read_duplicate_gateways);
+
     g_test_add_func("/keyfile/test_read_ip6_wired_connection", test_read_ip6_wired_connection);
     g_test_add_func("/keyfile/test_write_ip6_wired_connection", test_write_ip6_wired_connection);