diff options
| author | Michael Biebl <biebl@debian.org> | 2018-10-20 01:30:31 +0200 |
|---|---|---|
| committer | Michael Biebl <biebl@debian.org> | 2018-10-20 01:30:31 +0200 |
| commit | 6518e361171f64bcaaa4bf868139362ed95cc2e0 (patch) | |
| tree | d2d5b53faf80646a40ec2c0c7f2a42b3959612f5 /src/settings/plugins | |
| parent | e126f3e804c35480c4f075777430419d6ece23da (diff) | |
New upstream version 1.14.2 upstream/1.14.2
Diffstat (limited to 'src/settings/plugins')
50 files changed, 2658 insertions, 2378 deletions
diff --git a/src/settings/plugins/ibft/meson.build b/src/settings/plugins/ibft/meson.build index 1b6ff28a..c7dbe459 100644 --- a/src/settings/plugins/ibft/meson.build +++ b/src/settings/plugins/ibft/meson.build @@ -1,15 +1,9 @@ name = 'nm-settings-plugin-ibft' -cflags = [ - '-DSBINDIR="@0@"'.format(nm_sbindir), - '-DSYSCONFDIR="@0@"'.format(nm_sysconfdir) -] - libnms_ibft_core = static_library( 'nms-ibft-core', 'nms-ibft-reader.c', dependencies: nm_dep, - c_args: cflags ) sources = files( @@ -21,7 +15,6 @@ libnm_settings_plugin_ibft = shared_module( name, sources: sources, dependencies: nm_dep, - c_args: cflags, link_with: libnms_ibft_core, link_args: ldflags_linker_script_settings, link_depends: linker_script_settings, diff --git a/src/settings/plugins/ibft/nms-ibft-plugin.c b/src/settings/plugins/ibft/nms-ibft-plugin.c index 77ce208f..69dd3733 100644 --- a/src/settings/plugins/ibft/nms-ibft-plugin.c +++ b/src/settings/plugins/ibft/nms-ibft-plugin.c @@ -42,19 +42,15 @@ typedef struct { } NMSIbftPluginPrivate; struct _NMSIbftPlugin { - GObject parent; + NMSettingsPlugin parent; NMSIbftPluginPrivate _priv; }; struct _NMSIbftPluginClass { - GObjectClass parent; + NMSettingsPluginClass parent; }; -static void settings_plugin_interface_init (NMSettingsPluginInterface *plugin_iface); - -G_DEFINE_TYPE_EXTENDED (NMSIbftPlugin, nms_ibft_plugin, G_TYPE_OBJECT, 0, - G_IMPLEMENT_INTERFACE (NM_TYPE_SETTINGS_PLUGIN, - settings_plugin_interface_init)) +G_DEFINE_TYPE (NMSIbftPlugin, nms_ibft_plugin, NM_TYPE_SETTINGS_PLUGIN); #define NMS_IBFT_PLUGIN_GET_PRIVATE(self) _NM_GET_PRIVATE (self, NMSIbftPlugin, NMS_IS_IBFT_PLUGIN) @@ -84,9 +80,9 @@ read_connections (NMSIbftPlugin *self) connection = nms_ibft_connection_new (iter->data, &error); if (connection) { nm_log_info (LOGD_SETTINGS, "ibft: read connection '%s'", - nm_connection_get_id (NM_CONNECTION (connection))); + nm_settings_connection_get_id (NM_SETTINGS_CONNECTION (connection))); g_hash_table_insert (priv->connections, - g_strdup (nm_connection_get_uuid (NM_CONNECTION (connection))), + g_strdup (nm_settings_connection_get_uuid (NM_SETTINGS_CONNECTION (connection))), connection); } else { nm_log_warn (LOGD_SETTINGS, "ibft: failed to read iscsiadm record: %s", error->message); @@ -121,11 +117,6 @@ get_connections (NMSettingsPlugin *config) /*****************************************************************************/ static void -init (NMSettingsPlugin *config) -{ -} - -static void nms_ibft_plugin_init (NMSIbftPlugin *self) { NMSIbftPluginPrivate *priv = NMS_IBFT_PLUGIN_GET_PRIVATE (self); @@ -148,24 +139,20 @@ dispose (GObject *object) } static void -nms_ibft_plugin_class_init (NMSIbftPluginClass *req_class) +nms_ibft_plugin_class_init (NMSIbftPluginClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (req_class); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMSettingsPluginClass *plugin_class = NM_SETTINGS_PLUGIN_CLASS (klass); object_class->dispose = dispose; -} -static void -settings_plugin_interface_init (NMSettingsPluginInterface *plugin_iface) -{ - plugin_iface->get_connections = get_connections; - plugin_iface->init = init; + plugin_class->get_connections = get_connections; } /*****************************************************************************/ -G_MODULE_EXPORT GObject * +G_MODULE_EXPORT NMSettingsPlugin * nm_settings_plugin_factory (void) { - return G_OBJECT (g_object_ref (nms_ibft_plugin_get ())); + return NM_SETTINGS_PLUGIN (g_object_ref (nms_ibft_plugin_get ())); } diff --git a/src/settings/plugins/ibft/nms-ibft-reader.c b/src/settings/plugins/ibft/nms-ibft-reader.c index cf849e28..ac5824a1 100644 --- a/src/settings/plugins/ibft/nms-ibft-reader.c +++ b/src/settings/plugins/ibft/nms-ibft-reader.c @@ -98,7 +98,7 @@ nms_ibft_reader_load_blocks (const char *iscsiadm_path, const char *envp[1] = { NULL }; GSList *blocks = NULL; char *out = NULL, *err = NULL; - gint status = 0; + int status = 0; char **lines = NULL, **iter; GPtrArray *block_lines = NULL; gboolean success = FALSE; diff --git a/src/settings/plugins/ibft/tests/iscsiadm-test-bad-dns1 b/src/settings/plugins/ibft/tests/iscsiadm-test-bad-dns1 deleted file mode 100755 index 54f02da6..00000000 --- a/src/settings/plugins/ibft/tests/iscsiadm-test-bad-dns1 +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/bash - -cat << EOF -# BEGIN RECORD -iface.initiatorname = iqn.pjones6 -iface.hwaddress = 00:33:21:98:b9:f0 -iface.bootproto = STATIC -iface.ipaddress = 192.168.32.72 -iface.subnet_mask = 255.255.252.0 -iface.gateway = 192.168.35.254 -iface.primary_dns = 10000.500.250.1 -iface.secondary_dns = 10.16.255.3 -iface.vlan_id = 0 -iface.net_ifacename = eth0 -node.name = iqn.0.2008-11.com.blahblah:iscsi0 -node.conn[0].address = 10.16.52.16 -node.conn[0].port = 3260 -node.boot_lun = 00000000 -# END RECORD -EOF - diff --git a/src/settings/plugins/ibft/tests/iscsiadm-test-bad-dns2 b/src/settings/plugins/ibft/tests/iscsiadm-test-bad-dns2 deleted file mode 100755 index ebd7a9ca..00000000 --- a/src/settings/plugins/ibft/tests/iscsiadm-test-bad-dns2 +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/bash - -cat << EOF -# BEGIN RECORD -iface.initiatorname = iqn.pjones6 -iface.hwaddress = 00:33:21:98:b9:f0 -iface.bootproto = STATIC -iface.ipaddress = 192.168.32.72 -iface.subnet_mask = 255.255.252.0 -iface.gateway = 192.168.35.254 -iface.primary_dns = 10.16.255.2 -iface.secondary_dns = blah.foo.bar.baz -iface.vlan_id = 0 -iface.net_ifacename = eth0 -node.name = iqn.0.2008-11.com.blahblah:iscsi0 -node.conn[0].address = 10.16.52.16 -node.conn[0].port = 3260 -node.boot_lun = 00000000 -# END RECORD -EOF - diff --git a/src/settings/plugins/ibft/tests/iscsiadm-test-bad-entry b/src/settings/plugins/ibft/tests/iscsiadm-test-bad-entry deleted file mode 100755 index 4e326048..00000000 --- a/src/settings/plugins/ibft/tests/iscsiadm-test-bad-entry +++ /dev/null @@ -1,20 +0,0 @@ -#!/bin/bash - -cat << EOF -# BEGIN RECORD -iface.initiatorname = iqn.pjones6 -iface.hwaddress = 00:33:21:98:b9:f0 -iface.bootproto = STATIC -iface.ipaddress 192.168.32.72 -iface.subnet_mask = 255.255.252.0 -iface.gateway = 192.168.35.254 -iface.primary_dns = 10.16.255.2 -iface.secondary_dns = 10.16.255.3 -iface.vlan_id = 0 -iface.net_ifacename = eth0 -node.name = iqn.0.2008-11.com.blahblah:iscsi0 -node.conn[0].address = 10.16.52.16 -node.conn[0].port = 3260 -node.boot_lun = 00000000 -# END RECORD - diff --git a/src/settings/plugins/ibft/tests/iscsiadm-test-bad-gateway b/src/settings/plugins/ibft/tests/iscsiadm-test-bad-gateway deleted file mode 100755 index 5390a6c3..00000000 --- a/src/settings/plugins/ibft/tests/iscsiadm-test-bad-gateway +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/bash - -cat << EOF -# BEGIN RECORD -iface.initiatorname = iqn.pjones6 -iface.hwaddress = 00:33:21:98:b9:f0 -iface.bootproto = STATIC -iface.ipaddress = 192.168.32.72 -iface.subnet_mask = 255.255.252.0 -iface.gateway = bb.cc.dd.ee -iface.primary_dns = 10.16.255.2 -iface.secondary_dns = 10.16.255.3 -iface.vlan_id = 0 -iface.net_ifacename = eth0 -node.name = iqn.0.2008-11.com.blahblah:iscsi0 -node.conn[0].address = 10.16.52.16 -node.conn[0].port = 3260 -node.boot_lun = 00000000 -# END RECORD -EOF - diff --git a/src/settings/plugins/ibft/tests/iscsiadm-test-bad-ipaddr b/src/settings/plugins/ibft/tests/iscsiadm-test-bad-ipaddr deleted file mode 100755 index b41cd1f1..00000000 --- a/src/settings/plugins/ibft/tests/iscsiadm-test-bad-ipaddr +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/bash - -cat << EOF -# BEGIN RECORD -iface.initiatorname = iqn.pjones6 -iface.hwaddress = 00:33:21:98:b9:f0 -iface.bootproto = STATIC -iface.ipaddress = aa.bb.cc.dd -iface.subnet_mask = 255.255.252.0 -iface.gateway = 192.168.35.254 -iface.primary_dns = 10.16.255.2 -iface.secondary_dns = 10.16.255.3 -iface.vlan_id = 0 -iface.net_ifacename = eth0 -node.name = iqn.0.2008-11.com.blahblah:iscsi0 -node.conn[0].address = 10.16.52.16 -node.conn[0].port = 3260 -node.boot_lun = 00000000 -# END RECORD -EOF - diff --git a/src/settings/plugins/ibft/tests/iscsiadm-test-bad-record b/src/settings/plugins/ibft/tests/iscsiadm-test-bad-record deleted file mode 100755 index 22b34e6f..00000000 --- a/src/settings/plugins/ibft/tests/iscsiadm-test-bad-record +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/bash - -cat << EOF -# BEGIN RECORD -iface.initiatorname = iqn.pjones6 -iface.hwaddress = 00:33:21:98:b9:f0 -iface.bootproto = DHCP -iface.gateway = 10.16.52.254 -iface.primary_dns = 10.16.255.2 -iface.secondary_dns = 10.16.255.3 -iface.vlan_id = 0 -iface.net_ifacename = eth0 -node.name = iqn.0.2008-11.com.blahblah:iscsi0 -node.conn[0].address = 10.16.52.16 -node.conn[0].port = 3260 -node.boot_lun = 00000000 -EOF - diff --git a/src/settings/plugins/ibft/tests/iscsiadm-test-dhcp b/src/settings/plugins/ibft/tests/iscsiadm-test-dhcp deleted file mode 100755 index 556b0586..00000000 --- a/src/settings/plugins/ibft/tests/iscsiadm-test-dhcp +++ /dev/null @@ -1,33 +0,0 @@ -#!/bin/bash - -cat << EOF -# BEGIN RECORD -iface.initiatorname = iqn.pjones6 -iface.hwaddress = 00:33:21:98:b9:f0 -iface.bootproto = DHCP -iface.gateway = 10.16.52.254 -iface.primary_dns = 10.16.255.2 -iface.secondary_dns = 10.16.255.3 -iface.vlan_id = 0 -iface.net_ifacename = eth0 -node.name = iqn.0.2008-11.com.blahblah:iscsi0 -node.conn[0].address = 10.16.52.16 -node.conn[0].port = 3260 -node.boot_lun = 00000000 -# END RECORD -# BEGIN RECORD -iface.initiatorname = iqn.pjones6 -iface.hwaddress = 00:33:21:98:b9:f1 -iface.bootproto = DHCP -iface.gateway = 10.16.52.254 -iface.primary_dns = 10.16.255.2 -iface.secondary_dns = 10.16.255.3 -iface.vlan_id = 0 -iface.net_ifacename = eth1 -node.name = iqn.1.2008-11.com.blahblah:iscsi1 -node.conn[0].address = 10.16.52.16 -node.conn[0].port = 3260 -node.boot_lun = 00000000 -# END RECORD -EOF - diff --git a/src/settings/plugins/ibft/tests/iscsiadm-test-static b/src/settings/plugins/ibft/tests/iscsiadm-test-static deleted file mode 100755 index 51711480..00000000 --- a/src/settings/plugins/ibft/tests/iscsiadm-test-static +++ /dev/null @@ -1,35 +0,0 @@ -#!/bin/bash - -cat << EOF -# BEGIN RECORD -iface.initiatorname = iqn.pjones6 -iface.hwaddress = 00:33:21:98:b9:f0 -iface.bootproto = STATIC -iface.ipaddress = 192.168.32.72 -iface.subnet_mask = 255.255.252.0 -iface.gateway = 192.168.35.254 -iface.primary_dns = 10.16.255.2 -iface.secondary_dns = 10.16.255.3 -iface.vlan_id = 0 -iface.net_ifacename = eth0 -node.name = iqn.0.2008-11.com.blahblah:iscsi0 -node.conn[0].address = 10.16.52.16 -node.conn[0].port = 3260 -node.boot_lun = 00000000 -# END RECORD -# BEGIN RECORD -iface.initiatorname = iqn.pjones6 -iface.hwaddress = 00:33:21:98:b9:f1 -iface.bootproto = DHCP -iface.gateway = 10.16.52.254 -iface.primary_dns = 10.16.255.2 -iface.secondary_dns = 10.16.255.3 -iface.vlan_id = 0 -iface.net_ifacename = eth1 -node.name = iqn.1.2008-11.com.blahblah:iscsi1 -node.conn[0].address = 10.16.52.16 -node.conn[0].port = 3260 -node.boot_lun = 00000000 -# END RECORD -EOF - diff --git a/src/settings/plugins/ibft/tests/iscsiadm-test-vlan b/src/settings/plugins/ibft/tests/iscsiadm-test-vlan deleted file mode 100755 index 59b80bd0..00000000 --- a/src/settings/plugins/ibft/tests/iscsiadm-test-vlan +++ /dev/null @@ -1,19 +0,0 @@ -#!/bin/bash - -cat << EOF -# BEGIN RECORD 6.2.0.873-21 -iface.initiatorname = iqn.2010-04.org.ipxe:d05faa97-c4be-44f6-a723-efde9aa399a0 -iface.transport_name = tcp -iface.hwaddress = 00:33:21:98:b9:f0 -iface.bootproto = STATIC -iface.ipaddress = 192.168.6.200 -iface.subnet_mask = 255.255.255.0 -iface.vlan_id = 123 -iface.net_ifacename = eth0 -node.name = iqn.2003-01.org.x:disk1 -node.conn[0].address = 192.168.6.32 -node.conn[0].port = 3260 -node.boot_lun = 01000000 -# END RECORD -EOF - diff --git a/src/settings/plugins/ibft/tests/meson.build b/src/settings/plugins/ibft/tests/meson.build index 59f49c31..8b5e143a 100644 --- a/src/settings/plugins/ibft/tests/meson.build +++ b/src/settings/plugins/ibft/tests/meson.build @@ -6,7 +6,6 @@ exe = executable( test_unit, test_unit + '.c', dependencies: test_nm_dep, - c_args: nm_build_cflags, link_with: libnms_ibft_core ) diff --git a/src/settings/plugins/ifcfg-rh/meson.build b/src/settings/plugins/ifcfg-rh/meson.build index 964ce22d..e84ae80c 100644 --- a/src/settings/plugins/ifcfg-rh/meson.build +++ b/src/settings/plugins/ifcfg-rh/meson.build @@ -3,11 +3,6 @@ install_data( install_dir: dbus_conf_dir ) -cflags = [ - '-DSBINDIR="@0@"'.format(nm_sbindir), - '-DSYSCONFDIR="@0@"'.format(nm_sysconfdir) -] - name = 'nmdbus-ifcfg-rh' dbus_sources = gnome.gdbus_codegen( @@ -21,10 +16,9 @@ libnmdbus_ifcfg_rh = static_library( name, sources: dbus_sources, dependencies: glib_dep, - c_args: cflags ) -sources = files( +core_sources = files( 'nm-inotify-helper.c', 'nms-ifcfg-rh-reader.c', 'nms-ifcfg-rh-utils.c', @@ -33,24 +27,21 @@ sources = files( ) deps = [ - crypto_dep, nm_dep ] libnms_ifcfg_rh_core = static_library( 'nms-ifcfg-rh-core', - sources: sources, + sources: core_sources, dependencies: deps, - c_args: cflags ) -sources = [dbus_sources] + files('nms-ifcfg-rh-connection.c') +sources = [dbus_sources] + core_sources + files('nms-ifcfg-rh-connection.c', 'nms-ifcfg-rh-plugin.c') libnm_settings_plugin_ifcfg_rh = shared_module( 'nm-settings-plugin-ifcfg-rh', sources: sources, dependencies: deps, - c_args: cflags, link_with: [libnms_ifcfg_rh_core], link_args: ldflags_linker_script_settings, link_depends: linker_script_settings, @@ -72,6 +63,15 @@ check-local-symbols-settings-ifcfg-rh: src/settings/plugins/ifcfg-rh/libnm-setti $(call check_so_symbols,$(builddir)/src/settings/plugins/ifcfg-rh/.libs/libnm-settings-plugin-ifcfg-rh.so) ''' +install_data( + ['nm-ifup', 'nm-ifdown'], + install_dir: nm_libexecdir, + install_mode: 'rwxr-xr-x', +) + +meson.add_install_script('sh', '-c', + 'mkdir -p $DESTDIR/@0@/sysconfig/network-scripts'.format(nm_sysconfdir)) + if enable_tests subdir('tests') endif diff --git a/src/settings/plugins/ifcfg-rh/nm-inotify-helper.c b/src/settings/plugins/ifcfg-rh/nm-inotify-helper.c index 2863df64..e7a74a1a 100644 --- a/src/settings/plugins/ifcfg-rh/nm-inotify-helper.c +++ b/src/settings/plugins/ifcfg-rh/nm-inotify-helper.c @@ -120,8 +120,8 @@ inotify_event_handler (GIOChannel *channel, GIOCondition cond, gpointer user_dat struct inotify_event evt; /* read the notifications from the watch descriptor */ - while (g_io_channel_read_chars (channel, (gchar *) &evt, sizeof (struct inotify_event), NULL, NULL) == G_IO_STATUS_NORMAL) { - gchar filename[PATH_MAX + 1]; + while (g_io_channel_read_chars (channel, (char *) &evt, sizeof (struct inotify_event), NULL, NULL) == G_IO_STATUS_NORMAL) { + char filename[PATH_MAX + 1]; filename[0] = '\0'; if (evt.len > 0) { diff --git a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-connection.c b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-connection.c index 6979fdaa..ca319ddc 100644 --- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-connection.c +++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-connection.c @@ -143,7 +143,7 @@ devtimeout_expired (gpointer user_data) NMIfcfgConnectionPrivate *priv = NM_IFCFG_CONNECTION_GET_PRIVATE (self); nm_log_info (LOGD_SETTINGS, "Device for connection '%s' did not appear before timeout", - nm_connection_get_id (NM_CONNECTION (self))); + nm_settings_connection_get_id (NM_SETTINGS_CONNECTION (self))); g_signal_handler_disconnect (NM_PLATFORM_GET, priv->devtimeout_link_changed_handler); priv->devtimeout_link_changed_handler = 0; @@ -163,7 +163,7 @@ nm_ifcfg_connection_check_devtimeout (NMIfcfgConnection *self) guint devtimeout; const NMPlatformLink *pllink; - s_con = nm_connection_get_setting_connection (NM_CONNECTION (self)); + s_con = nm_connection_get_setting_connection (nm_settings_connection_get_connection (NM_SETTINGS_CONNECTION (self))); if (!nm_setting_connection_get_autoconnect (s_con)) return; @@ -186,7 +186,7 @@ nm_ifcfg_connection_check_devtimeout (NMIfcfgConnection *self) nm_settings_connection_set_ready (NM_SETTINGS_CONNECTION (self), FALSE); nm_log_info (LOGD_SETTINGS, "Waiting %u seconds for %s to appear for connection '%s'", - devtimeout, ifname, nm_connection_get_id (NM_CONNECTION (self))); + devtimeout, ifname, nm_settings_connection_get_id (NM_SETTINGS_CONNECTION (self))); priv->devtimeout_link_changed_handler = g_signal_connect (NM_PLATFORM_GET, NM_PLATFORM_SIGNAL_LINK_CHANGED, diff --git a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-plugin.c b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-plugin.c index 0fb77b9d..6cac8cb6 100644 --- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-plugin.c +++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-plugin.c @@ -70,19 +70,15 @@ typedef struct { } SettingsPluginIfcfgPrivate; struct _SettingsPluginIfcfg { - GObject parent; + NMSettingsPlugin parent; SettingsPluginIfcfgPrivate _priv; }; struct _SettingsPluginIfcfgClass { - GObjectClass parent; + NMSettingsPluginClass parent; }; -static void settings_plugin_interface_init (NMSettingsPluginInterface *plugin_iface); - -G_DEFINE_TYPE_EXTENDED (SettingsPluginIfcfg, settings_plugin_ifcfg, G_TYPE_OBJECT, 0, - G_IMPLEMENT_INTERFACE (NM_TYPE_SETTINGS_PLUGIN, - settings_plugin_interface_init)) +G_DEFINE_TYPE (SettingsPluginIfcfg, settings_plugin_ifcfg, NM_TYPE_SETTINGS_PLUGIN) #define SETTINGS_PLUGIN_IFCFG_GET_PRIVATE(self) _NM_GET_PRIVATE (self, SettingsPluginIfcfg, SETTINGS_IS_PLUGIN_IFCFG) @@ -139,7 +135,7 @@ static void connection_removed_cb (NMSettingsConnection *obj, gpointer user_data) { g_hash_table_remove (SETTINGS_PLUGIN_IFCFG_GET_PRIVATE ((SettingsPluginIfcfg *) user_data)->connections, - nm_connection_get_uuid (NM_CONNECTION (obj))); + nm_settings_connection_get_uuid (NM_SETTINGS_CONNECTION (obj))); } static void @@ -157,16 +153,16 @@ remove_connection (SettingsPluginIfcfg *self, NMIfcfgConnection *connection) unrecognized = !!nm_ifcfg_connection_get_unrecognized_spec (connection); g_object_ref (connection); - g_hash_table_remove (priv->connections, nm_connection_get_uuid (NM_CONNECTION (connection))); + g_hash_table_remove (priv->connections, nm_settings_connection_get_uuid (NM_SETTINGS_CONNECTION (connection))); if (!unmanaged && !unrecognized) nm_settings_connection_signal_remove (NM_SETTINGS_CONNECTION (connection)); g_object_unref (connection); /* Emit changes _after_ removing the connection */ if (unmanaged) - g_signal_emit_by_name (self, NM_SETTINGS_PLUGIN_UNMANAGED_SPECS_CHANGED); + _nm_settings_plugin_emit_signal_unmanaged_specs_changed (NM_SETTINGS_PLUGIN (self)); if (unrecognized) - g_signal_emit_by_name (self, NM_SETTINGS_PLUGIN_UNRECOGNIZED_SPECS_CHANGED); + _nm_settings_plugin_emit_signal_unrecognized_specs_changed (NM_SETTINGS_PLUGIN (self)); } static NMIfcfgConnection * @@ -228,7 +224,7 @@ update_connection (SettingsPluginIfcfg *self, return NULL; } - uuid = nm_connection_get_uuid (NM_CONNECTION (connection_new)); + uuid = nm_settings_connection_get_uuid (NM_SETTINGS_CONNECTION (connection_new)); connection_by_uuid = g_hash_table_lookup (priv->connections, uuid); if ( connection @@ -285,12 +281,16 @@ update_connection (SettingsPluginIfcfg *self, if ( !unmanaged_changed && !unrecognized_changed - && nm_connection_compare (NM_CONNECTION (connection_by_uuid), - NM_CONNECTION (connection_new), + && nm_connection_compare (nm_settings_connection_get_connection (NM_SETTINGS_CONNECTION (connection_by_uuid)), + nm_settings_connection_get_connection (NM_SETTINGS_CONNECTION (connection_new)), NM_SETTING_COMPARE_FLAG_IGNORE_AGENT_OWNED_SECRETS | NM_SETTING_COMPARE_FLAG_IGNORE_NOT_SAVED_SECRETS)) { - if (old_path && g_strcmp0 (old_path, full_path) != 0) - _LOGI ("rename \"%s\" to "NM_IFCFG_CONNECTION_LOG_FMT" without other changes", nm_settings_connection_get_filename (NM_SETTINGS_CONNECTION (connection_by_uuid)), NM_IFCFG_CONNECTION_LOG_ARG (connection_new)); + if ( old_path + && !nm_streq0 (old_path, full_path)) { + _LOGI ("rename \"%s\" to "NM_IFCFG_CONNECTION_LOG_FMT" without other changes", + nm_settings_connection_get_filename (NM_SETTINGS_CONNECTION (connection_by_uuid)), + NM_IFCFG_CONNECTION_LOG_ARG (connection_new)); + } } else { /******************************************************* @@ -299,7 +299,7 @@ update_connection (SettingsPluginIfcfg *self, if (source) _LOGI ("update "NM_IFCFG_CONNECTION_LOG_FMT" from %s", NM_IFCFG_CONNECTION_LOG_ARG (connection_new), NM_IFCFG_CONNECTION_LOG_PATH (old_path)); - else if (!g_strcmp0 (old_path, nm_settings_connection_get_filename (NM_SETTINGS_CONNECTION (connection_new)))) + else if (nm_streq0 (old_path, nm_settings_connection_get_filename (NM_SETTINGS_CONNECTION (connection_new)))) _LOGI ("update "NM_IFCFG_CONNECTION_LOG_FMT, NM_IFCFG_CONNECTION_LOG_ARG (connection_new)); else if (old_path) _LOGI ("rename \"%s\" to "NM_IFCFG_CONNECTION_LOG_FMT, old_path, NM_IFCFG_CONNECTION_LOG_ARG (connection_new)); @@ -312,7 +312,7 @@ update_connection (SettingsPluginIfcfg *self, NULL); if (!nm_settings_connection_update (NM_SETTINGS_CONNECTION (connection_by_uuid), - NM_CONNECTION (connection_new), + nm_settings_connection_get_connection (NM_SETTINGS_CONNECTION (connection_new)), NM_SETTINGS_CONNECTION_PERSIST_MODE_KEEP_SAVED, NM_SETTINGS_CONNECTION_COMMIT_REASON_NONE, "ifcfg-update", @@ -338,25 +338,27 @@ update_connection (SettingsPluginIfcfg *self, * so add it back now. */ g_hash_table_insert (priv->connections, - g_strdup (nm_connection_get_uuid (NM_CONNECTION (connection_by_uuid))), + g_strdup (nm_settings_connection_get_uuid (NM_SETTINGS_CONNECTION (connection_by_uuid))), connection_by_uuid /* we took reference above and pass it on */); } } else { if (old_unmanaged /* && !new_unmanaged */) { _LOGI ("Managing connection "NM_IFCFG_CONNECTION_LOG_FMT" and its device because NM_CONTROLLED was true.", NM_IFCFG_CONNECTION_LOG_ARG (connection_new)); - g_signal_emit_by_name (self, NM_SETTINGS_PLUGIN_CONNECTION_ADDED, connection_by_uuid); + _nm_settings_plugin_emit_signal_connection_added (NM_SETTINGS_PLUGIN (self), + NM_SETTINGS_CONNECTION (connection_by_uuid)); } else if (old_unrecognized /* && !new_unrecognized */) { _LOGI ("Managing connection "NM_IFCFG_CONNECTION_LOG_FMT" because it is now a recognized type.", NM_IFCFG_CONNECTION_LOG_ARG (connection_new)); - g_signal_emit_by_name (self, NM_SETTINGS_PLUGIN_CONNECTION_ADDED, connection_by_uuid); + _nm_settings_plugin_emit_signal_connection_added (NM_SETTINGS_PLUGIN (self), + NM_SETTINGS_CONNECTION (connection_by_uuid)); } } if (unmanaged_changed) - g_signal_emit_by_name (self, NM_SETTINGS_PLUGIN_UNMANAGED_SPECS_CHANGED); + _nm_settings_plugin_emit_signal_unmanaged_specs_changed (NM_SETTINGS_PLUGIN (self)); if (unrecognized_changed) - g_signal_emit_by_name (self, NM_SETTINGS_PLUGIN_UNRECOGNIZED_SPECS_CHANGED); + _nm_settings_plugin_emit_signal_unrecognized_specs_changed (NM_SETTINGS_PLUGIN (self)); } nm_settings_connection_set_filename (NM_SETTINGS_CONNECTION (connection_by_uuid), full_path); g_object_unref (connection_new); @@ -394,11 +396,13 @@ update_connection (SettingsPluginIfcfg *self, /* Only raise the signal if we were called without source, i.e. if we read the connection from file. * Otherwise, we were called by add_connection() which does not expect the signal. */ if (nm_ifcfg_connection_get_unmanaged_spec (connection_new)) - g_signal_emit_by_name (self, NM_SETTINGS_PLUGIN_UNMANAGED_SPECS_CHANGED); + _nm_settings_plugin_emit_signal_unmanaged_specs_changed (NM_SETTINGS_PLUGIN (self)); else if (nm_ifcfg_connection_get_unrecognized_spec (connection_new)) - g_signal_emit_by_name (self, NM_SETTINGS_PLUGIN_UNRECOGNIZED_SPECS_CHANGED); - else - g_signal_emit_by_name (self, NM_SETTINGS_PLUGIN_CONNECTION_ADDED, connection_new); + _nm_settings_plugin_emit_signal_unrecognized_specs_changed (NM_SETTINGS_PLUGIN (self)); + else { + _nm_settings_plugin_emit_signal_connection_added (NM_SETTINGS_PLUGIN (self), + NM_SETTINGS_CONNECTION (connection_new)); + } } return connection_new; } @@ -731,7 +735,7 @@ impl_ifcfgrh_get_ifcfg_details (SettingsPluginIfcfg *plugin, return; } - s_con = nm_connection_get_setting_connection (NM_CONNECTION (connection)); + s_con = nm_connection_get_setting_connection (nm_settings_connection_get_connection (NM_SETTINGS_CONNECTION (connection))); if (!s_con) { g_dbus_method_invocation_return_error (context, NM_SETTINGS_ERROR, @@ -998,11 +1002,6 @@ config_changed_cb (NMConfig *config, /*****************************************************************************/ static void -init (NMSettingsPlugin *config) -{ -} - -static void settings_plugin_ifcfg_init (SettingsPluginIfcfg *plugin) { SettingsPluginIfcfgPrivate *priv = SETTINGS_PLUGIN_IFCFG_GET_PRIVATE ((SettingsPluginIfcfg *) plugin); @@ -1059,30 +1058,26 @@ dispose (GObject *object) } static void -settings_plugin_ifcfg_class_init (SettingsPluginIfcfgClass *req_class) +settings_plugin_ifcfg_class_init (SettingsPluginIfcfgClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (req_class); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMSettingsPluginClass *plugin_class = NM_SETTINGS_PLUGIN_CLASS (klass); object_class->constructed = constructed; object_class->dispose = dispose; -} -static void -settings_plugin_interface_init (NMSettingsPluginInterface *plugin_iface) -{ - plugin_iface->get_connections = get_connections; - plugin_iface->add_connection = add_connection; - plugin_iface->load_connection = load_connection; - plugin_iface->reload_connections = reload_connections; - plugin_iface->get_unmanaged_specs = get_unmanaged_specs; - plugin_iface->get_unrecognized_specs = get_unrecognized_specs; - plugin_iface->init = init; + plugin_class->get_connections = get_connections; + plugin_class->add_connection = add_connection; + plugin_class->load_connection = load_connection; + plugin_class->reload_connections = reload_connections; + plugin_class->get_unmanaged_specs = get_unmanaged_specs; + plugin_class->get_unrecognized_specs = get_unrecognized_specs; } /*****************************************************************************/ -G_MODULE_EXPORT GObject * +G_MODULE_EXPORT NMSettingsPlugin * nm_settings_plugin_factory (void) { - return G_OBJECT (g_object_ref (settings_plugin_ifcfg_get ())); + return NM_SETTINGS_PLUGIN (g_object_ref (settings_plugin_ifcfg_get ())); } diff --git a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c index c1960846..09a37991 100644 --- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c +++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c @@ -33,6 +33,7 @@ #include <sys/ioctl.h> #include <unistd.h> +#include "nm-utils/nm-secret-utils.h" #include "nm-connection.h" #include "nm-dbus-interface.h" #include "nm-setting-connection.h" @@ -41,6 +42,7 @@ #include "nm-setting-ip6-config.h" #include "nm-setting-wired.h" #include "nm-setting-wireless.h" +#include "nm-setting-ethtool.h" #include "nm-setting-8021x.h" #include "nm-setting-bond.h" #include "nm-setting-team.h" @@ -53,6 +55,7 @@ #include "nm-setting-generic.h" #include "nm-core-internal.h" #include "nm-utils.h" +#include "nm-ethtool-utils.h" #include "platform/nm-platform.h" #include "NetworkManagerUtils.h" @@ -77,6 +80,210 @@ /*****************************************************************************/ +static char * +get_full_file_path (const char *ifcfg_path, const char *file_path) +{ + const char *base = file_path; + char *p, *ret, *dirname; + + g_return_val_if_fail (ifcfg_path != NULL, NULL); + g_return_val_if_fail (file_path != NULL, NULL); + + if (file_path[0] == '/') + return g_strdup (file_path); + + p = strrchr (file_path, '/'); + if (p) + base = p + 1; + + dirname = g_path_get_dirname (ifcfg_path); + ret = g_build_path ("/", dirname, base, NULL); + g_free (dirname); + return ret; +} + +/*****************************************************************************/ + +static NMSettingSecretFlags +_secret_read_ifcfg_flags (shvarFile *ifcfg, const char *flags_key) +{ + NMSettingSecretFlags flags = NM_SETTING_SECRET_FLAG_NONE; + gs_free char *val_free = NULL; + const char *val; + + nm_assert (flags_key); + nm_assert (g_str_has_suffix (flags_key, "_FLAGS")); + + val = svGetValueStr (ifcfg, flags_key, &val_free); + if (val) { + if (strstr (val, SECRET_FLAG_AGENT)) + flags |= NM_SETTING_SECRET_FLAG_AGENT_OWNED; + if (strstr (val, SECRET_FLAG_NOT_SAVED)) + flags |= NM_SETTING_SECRET_FLAG_NOT_SAVED; + if (strstr (val, SECRET_FLAG_NOT_REQUIRED)) + flags |= NM_SETTING_SECRET_FLAG_NOT_REQUIRED; + } + return flags; +} + +static void +_secret_read_ifcfg (shvarFile *ifcfg, + shvarFile *keys_ifcfg, + const char *name, + char **value, + NMSettingSecretFlags *flags) +{ + char flags_key[250]; + + nm_sprintf_buf (flags_key, "%s_FLAGS", name); + + *flags = _secret_read_ifcfg_flags (ifcfg, flags_key); + + if (*flags != NM_SETTING_SECRET_FLAG_NONE) + *value = NULL; + else { + *value = svGetValue_cp (ifcfg, name); + if (!*value && keys_ifcfg) + *value = svGetValue_cp (keys_ifcfg, name); + } +} + +static void +_secret_set_from_ifcfg (gpointer setting, + shvarFile *ifcfg, + shvarFile *keys_ifcfg, + const char *ifcfg_key, + const char *property_name) +{ + nm_auto_free_secret char *secret = NULL; + NMSettingSecretFlags flags; + char flags_key[250]; + + nm_assert (NM_IS_SETTING (setting)); + + _secret_read_ifcfg (ifcfg, keys_ifcfg, ifcfg_key, &secret, &flags); + + g_object_set (setting, + property_name, + secret, + nm_sprintf_buf (flags_key, "%s-flags", property_name), + flags, + NULL); +} + +static gboolean +_secret_password_raw_to_bytes (const char *ifcfg_key, + const char *password_raw, + GBytes **out_bytes, + GError **error) +{ + nm_auto_free_secret_buf NMSecretBuf *secret = NULL; + gsize len; + + if (!password_raw) { + NM_SET_OUT (out_bytes, NULL); + return TRUE; + } + + if (password_raw[0] == '0' && password_raw[1] == 'x') + password_raw += 2; + + secret = nm_secret_buf_new (strlen (password_raw) / 2 + 3); + if (!_nm_utils_str2bin_full (password_raw, FALSE, ":", secret->bin, secret->len, &len)) { + g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, + "Invalid hex password in %s", + ifcfg_key); + return FALSE; + } + + NM_SET_OUT (out_bytes, nm_secret_buf_to_gbytes_take (g_steal_pointer (&secret), len)); + return TRUE; +} + +/*****************************************************************************/ + +static GBytes * +_cert_get_cert_bytes (const char *ifcfg_path, + const char *value, + GError **error) +{ + gs_free char *path = NULL; + + if (g_str_has_prefix (value, "pkcs11:")) + return _nm_setting_802_1x_cert_value_to_bytes (NM_SETTING_802_1X_CK_SCHEME_PKCS11, (guint8 *) value, -1, error); + + path = get_full_file_path (ifcfg_path, value); + return _nm_setting_802_1x_cert_value_to_bytes (NM_SETTING_802_1X_CK_SCHEME_PATH, (guint8 *) path, -1, error); +} + +static gboolean +_cert_get_cert (shvarFile *ifcfg, + const char *ifcfg_key, + GBytes **out_cert, + NMSetting8021xCKScheme *out_scheme, + GError **error) +{ + nm_auto_free_secret char *val_free = NULL; + const char *val; + gs_unref_bytes GBytes *cert = NULL; + GError *local = NULL; + NMSetting8021xCKScheme scheme; + + val = svGetValueStr (ifcfg, ifcfg_key, &val_free); + if (!val) { + NM_SET_OUT (out_cert, NULL); + NM_SET_OUT (out_scheme, NM_SETTING_802_1X_CK_SCHEME_UNKNOWN); + return TRUE; + } + + cert = _cert_get_cert_bytes (svFileGetName (ifcfg), val, &local); + if (!cert) + goto err; + + scheme = _nm_setting_802_1x_cert_get_scheme (cert, &local); + if (scheme == NM_SETTING_802_1X_CK_SCHEME_UNKNOWN) + goto err; + + NM_SET_OUT (out_cert, g_steal_pointer (&cert)); + NM_SET_OUT (out_scheme, scheme); + return TRUE; + +err: + g_set_error (error, + NM_SETTINGS_ERROR, + NM_SETTINGS_ERROR_INVALID_CONNECTION, + "invalid certificate %s: %s", + ifcfg_key, + local->message); + g_error_free (local); + return FALSE; +} + +static gboolean +_cert_set_from_ifcfg (gpointer setting, + shvarFile *ifcfg, + const char *ifcfg_key, + const char *property_name, + GBytes **out_cert, + GError **error) +{ + gs_unref_bytes GBytes *cert = NULL; + + if (!_cert_get_cert (ifcfg, + ifcfg_key, + &cert, + NULL, + error)) + return FALSE; + + g_object_set (setting, property_name, cert, NULL); + + NM_SET_OUT (out_cert, g_steal_pointer (&cert)); + return TRUE; +} + +/*****************************************************************************/ + static void check_if_bond_slave (shvarFile *ifcfg, NMSettingConnection *s_con) @@ -232,13 +439,16 @@ make_connection_setting (const char *file, NM_SETTING_CONNECTION_AUTOCONNECT, svGetValueBoolean (ifcfg, "ONBOOT", TRUE), NM_SETTING_CONNECTION_AUTOCONNECT_PRIORITY, - (gint) svGetValueInt64 (ifcfg, "AUTOCONNECT_PRIORITY", 10, + (int) svGetValueInt64 (ifcfg, "AUTOCONNECT_PRIORITY", 10, NM_SETTING_CONNECTION_AUTOCONNECT_PRIORITY_MIN, NM_SETTING_CONNECTION_AUTOCONNECT_PRIORITY_MAX, NM_SETTING_CONNECTION_AUTOCONNECT_PRIORITY_DEFAULT), NM_SETTING_CONNECTION_AUTOCONNECT_RETRIES, - (gint) svGetValueInt64 (ifcfg, "AUTOCONNECT_RETRIES", 10, + (int) svGetValueInt64 (ifcfg, "AUTOCONNECT_RETRIES", 10, -1, G_MAXINT32, -1), + NM_SETTING_CONNECTION_MULTI_CONNECT, + (gint) svGetValueInt64 (ifcfg, "MULTI_CONNECT", 10, + G_MININT32, G_MAXINT32, NM_CONNECTION_MULTI_CONNECT_DEFAULT), NM_SETTING_CONNECTION_AUTOCONNECT_SLAVES, svGetValueBoolean (ifcfg, "AUTOCONNECT_SLAVES", NM_SETTING_CONNECTION_AUTOCONNECT_SLAVES_DEFAULT), NM_SETTING_CONNECTION_LLDP, lldp, @@ -249,7 +459,7 @@ make_connection_setting (const char *file, if (v) { gs_free const char **items = NULL; - items = nm_utils_strsplit_set (v, " "); + items = nm_utils_strsplit_set (v, " ", FALSE); for (iter = items; iter && *iter; iter++) { if (!nm_setting_connection_add_permission (s_con, "user", *iter, NULL)) PARSE_WARNING ("invalid USERS item '%s'", *iter); @@ -265,7 +475,7 @@ make_connection_setting (const char *file, if (v) { gs_free const char **items = NULL; - items = nm_utils_strsplit_set (v, " \t"); + items = nm_utils_strsplit_set (v, " \t", FALSE); for (iter = items; iter && *iter; iter++) { if (!nm_setting_connection_add_secondary (s_con, *iter)) PARSE_WARNING ("secondary connection UUID '%s' already added", *iter); @@ -335,7 +545,7 @@ make_connection_setting (const char *file, } vint64 = svGetValueInt64 (ifcfg, "AUTH_RETRIES", 10, -1, G_MAXINT32, -1); - g_object_set (s_con, NM_SETTING_CONNECTION_AUTH_RETRIES, (gint) vint64, NULL); + g_object_set (s_con, NM_SETTING_CONNECTION_AUTH_RETRIES, (int) vint64, NULL); i_val = NM_SETTING_CONNECTION_MDNS_DEFAULT; if (!svGetValueEnum (ifcfg, "MDNS", @@ -344,6 +554,13 @@ make_connection_setting (const char *file, PARSE_WARNING ("invalid MDNS setting"); g_object_set (s_con, NM_SETTING_CONNECTION_MDNS, i_val, NULL); + i_val = NM_SETTING_CONNECTION_LLMNR_DEFAULT; + if (!svGetValueEnum (ifcfg, "LLMNR", + nm_setting_connection_llmnr_get_type (), + &i_val, NULL)) + PARSE_WARNING ("invalid LLMNR setting"); + g_object_set (s_con, NM_SETTING_CONNECTION_LLMNR, i_val, NULL); + return NM_SETTING (s_con); } @@ -674,7 +891,7 @@ parse_route_line (const char *line, * Maybe later we want to support some form of quotation here. * Which of course, would be incompatible with initscripts. */ - words_free = nm_utils_strsplit_set (line, " \t\n"); + words_free = nm_utils_strsplit_set (line, " \t\n", FALSE); words = words_free ?: NM_PTRARRAY_EMPTY (const char *); @@ -1110,7 +1327,7 @@ parse_dns_options (NMSettingIPConfig *ip_config, const char *value) if (!nm_setting_ip_config_has_dns_options (ip_config)) nm_setting_ip_config_clear_dns_options (ip_config, TRUE); - options = nm_utils_strsplit_set (value, " "); + options = nm_utils_strsplit_set (value, " ", FALSE); if (options) { for (item = options; *item; item++) { if (!nm_setting_ip_config_add_dns_option (ip_config, *item)) @@ -1178,7 +1395,7 @@ make_user_setting (shvarFile *ifcfg) const char *key; nm_auto_free_gstring GString *str = NULL; - keys = svGetKeys (ifcfg); + keys = svGetKeys (ifcfg, SV_KEY_TYPE_USER); if (!keys) return NULL; @@ -1187,9 +1404,6 @@ make_user_setting (shvarFile *ifcfg) const char *value; gs_free char *value_to_free = NULL; - if (!g_str_has_prefix (key, "NM_USER_")) - continue; - value = svGetValue (ifcfg, key, &value_to_free); if (!value) @@ -1217,6 +1431,32 @@ make_user_setting (shvarFile *ifcfg) } static NMSetting * +make_match_setting (shvarFile *ifcfg) +{ + NMSettingMatch *s_match = NULL; + gs_free const char **strv = NULL; + gs_free char *value = NULL; + const char *v; + gsize i; + + v = svGetValueStr (ifcfg, "MATCH_INTERFACE_NAME", &value); + if (!v) + return NULL; + + strv = nm_utils_strsplit_set (v, " \t", TRUE); + if (strv) { + for (i = 0; strv[i]; i++) { + if (!s_match) + s_match = (NMSettingMatch *) nm_setting_match_new (); + nm_setting_match_add_interface_name (s_match, + _nm_utils_unescape_spaces ((char *) strv[i])); + } + } + + return (NMSetting *) s_match; +} + +static NMSetting * make_proxy_setting (shvarFile *ifcfg) { NMSettingProxy *s_proxy = NULL; @@ -1286,7 +1526,7 @@ make_ip4_setting (shvarFile *ifcfg, shvarFile *route_ifcfg; gboolean never_default; gint64 timeout; - gint priority; + int priority; char inet_buf[NM_UTILS_INET_ADDRSTRLEN]; const char *const *item; guint32 route_table; @@ -1483,7 +1723,7 @@ make_ip4_setting (shvarFile *ifcfg, if (v) { gs_free const char **searches = NULL; - searches = nm_utils_strsplit_set (v, " "); + searches = nm_utils_strsplit_set (v, " ", FALSE); if (searches) { for (item = searches; *item; item++) { if (!nm_setting_ip_config_add_dns_search (s_ip4, *item)) @@ -1544,7 +1784,7 @@ make_ip4_setting (shvarFile *ifcfg, if (v) { gs_free const char **searches = NULL; - searches = nm_utils_strsplit_set (v, " "); + searches = nm_utils_strsplit_set (v, " ", FALSE); if (searches) { for (item = searches; *item; item++) { if (!nm_setting_ip_config_add_dns_search (s_ip4, *item)) @@ -1561,7 +1801,7 @@ make_ip4_setting (shvarFile *ifcfg, if (timeout > 0) timeout *= 1000; } - g_object_set (s_ip4, NM_SETTING_IP_CONFIG_DAD_TIMEOUT, (gint) timeout, NULL); + g_object_set (s_ip4, NM_SETTING_IP_CONFIG_DAD_TIMEOUT, (int) timeout, NULL); return g_steal_pointer (&s_ip4); } @@ -1697,7 +1937,7 @@ make_ip6_setting (shvarFile *ifcfg, guint32 i; int i_val; GError *local = NULL; - gint priority; + int priority; gboolean never_default = FALSE; gboolean ip6_privacy = FALSE, ip6_privacy_prefer_public_ip; NMSettingIP6ConfigPrivacy ip6_privacy_val; @@ -1860,7 +2100,7 @@ make_ip6_setting (shvarFile *ifcfg, ipv6addr_secondaries ?: "", NULL); - list = nm_utils_strsplit_set (value, " "); + list = nm_utils_strsplit_set (value, " ", FALSE); for (iter = list, i = 0; iter && *iter; iter++, i++) { NMIPAddress *addr = NULL; @@ -1953,7 +2193,7 @@ make_ip6_setting (shvarFile *ifcfg, if (v) { gs_free const char **searches = NULL; - searches = nm_utils_strsplit_set (v, " "); + searches = nm_utils_strsplit_set (v, " ", FALSE); if (searches) { for (iter = searches; *iter; iter++) { if (!nm_setting_ip_config_add_dns_search (s_ip6, *iter)) @@ -1982,6 +2222,68 @@ error: } static NMSetting * +make_sriov_setting (shvarFile *ifcfg) +{ + gs_unref_hashtable GHashTable *keys = NULL; + gs_unref_ptrarray GPtrArray *vfs = NULL; + NMTernary autoprobe_drivers; + NMSettingSriov *s_sriov; + int total_vfs; + + total_vfs = svGetValueInt64 (ifcfg, "SRIOV_TOTAL_VFS", 10, 0, G_MAXINT32, 0); + if (!total_vfs) + return NULL; + + autoprobe_drivers = svGetValueInt64 (ifcfg, + "SRIOV_AUTOPROBE_DRIVERS", + 10, + NM_TERNARY_FALSE, + NM_TERNARY_TRUE, + NM_TERNARY_DEFAULT); + + keys = svGetKeys (ifcfg, SV_KEY_TYPE_SRIOV_VF); + if (keys) { + GHashTableIter iter; + const char *key; + + g_hash_table_iter_init (&iter, keys); + while (g_hash_table_iter_next (&iter, (gpointer *) &key, NULL)) { + gs_free_error GError *error = NULL; + gs_free char *value_to_free = NULL; + const char *value; + NMSriovVF *vf; + + nm_assert (g_str_has_prefix (key, "SRIOV_VF")); + + value = svGetValue (ifcfg, key, &value_to_free); + if (!value) + continue; + + key += NM_STRLEN ("SRIOV_VF"); + + vf = _nm_utils_sriov_vf_from_strparts (key, value, &error); + if (!vf) { + PARSE_WARNING ("ignoring invalid SR-IOV VF '%s %s': %s", + key, value, error->message); + continue; + } + if (!vfs) + vfs = g_ptr_array_new_with_free_func ((GDestroyNotify) nm_sriov_vf_unref); + g_ptr_array_add (vfs, vf); + } + } + + s_sriov = (NMSettingSriov *) nm_setting_sriov_new (); + g_object_set (s_sriov, + NM_SETTING_SRIOV_TOTAL_VFS, total_vfs, + NM_SETTING_SRIOV_VFS, vfs, + NM_SETTING_SRIOV_AUTOPROBE_DRIVERS, (int) autoprobe_drivers, + NULL); + + return (NMSetting *) s_sriov; +} + +static NMSetting * make_tc_setting (shvarFile *ifcfg) { NMSettingTCConfig *s_tc = NULL; @@ -2241,7 +2543,7 @@ read_dcb_percent_array (shvarFile *ifcfg, return TRUE; } - split = nm_utils_strsplit_set (val, ","); + split = nm_utils_strsplit_set (val, ",", FALSE); if (NM_PTRARRAY_LEN (split) != 8) { PARSE_WARNING ("invalid %s percentage list value '%s'", prop, val); g_set_error_literal (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, @@ -2518,30 +2820,6 @@ read_wep_keys (shvarFile *ifcfg, return TRUE; } -static NMSettingSecretFlags -read_secret_flags (shvarFile *ifcfg, const char *flags_key) -{ - NMSettingSecretFlags flags = NM_SETTING_SECRET_FLAG_NONE; - char *val; - - g_return_val_if_fail (flags_key != NULL, NM_SETTING_SECRET_FLAG_NONE); - g_return_val_if_fail (flags_key[0] != '\0', NM_SETTING_SECRET_FLAG_NONE); - g_return_val_if_fail (g_str_has_suffix (flags_key, "_FLAGS"), NM_SETTING_SECRET_FLAG_NONE); - - val = svGetValueStr_cp (ifcfg, flags_key); - if (val) { - if (strstr (val, SECRET_FLAG_AGENT)) - flags |= NM_SETTING_SECRET_FLAG_AGENT_OWNED; - if (strstr (val, SECRET_FLAG_NOT_SAVED)) - flags |= NM_SETTING_SECRET_FLAG_NOT_SAVED; - if (strstr (val, SECRET_FLAG_NOT_REQUIRED)) - flags |= NM_SETTING_SECRET_FLAG_NOT_REQUIRED; - - g_free (val); - } - return flags; -} - static NMSetting * make_wep_setting (shvarFile *ifcfg, const char *file, @@ -2573,7 +2851,7 @@ make_wep_setting (shvarFile *ifcfg, } /* Read WEP key flags */ - key_flags = read_secret_flags (ifcfg, "WEP_KEY_FLAGS"); + key_flags = _secret_read_ifcfg_flags (ifcfg, "WEP_KEY_FLAGS"); g_object_set (s_wsec, NM_SETTING_WIRELESS_SECURITY_WEP_KEY_FLAGS, key_flags, NULL); /* Read keys in the ifcfg file if they are system-owned */ @@ -2677,7 +2955,7 @@ fill_wpa_ciphers (shvarFile *ifcfg, if (!p) return TRUE; - list = nm_utils_strsplit_set (p, " "); + list = nm_utils_strsplit_set (p, " ", FALSE); for (iter = list; iter && *iter; iter++, i++) { /* Ad-Hoc configurations cannot have pairwise ciphers, and can only * have one group cipher. Ignore any additional group ciphers and @@ -2772,254 +3050,118 @@ parse_wpa_psk (shvarFile *ifcfg, return g_steal_pointer (&psk); } -static void -read_8021x_password (shvarFile *ifcfg, shvarFile *keys_ifcfg, const char *name, - char **value, NMSettingSecretFlags *flags) -{ - gs_free char *flags_key = NULL; - - *value = NULL; - flags_key = g_strdup_printf ("%s_FLAGS", name); - *flags = read_secret_flags (ifcfg, flags_key); - - if (*flags == NM_SETTING_SECRET_FLAG_NONE) { - *value = svGetValueStr_cp (ifcfg, name); - if (!*value && keys_ifcfg) - *value = svGetValueStr_cp (keys_ifcfg, name); - } -} - static gboolean eap_simple_reader (const char *eap_method, shvarFile *ifcfg, - shvarFile *keys, + shvarFile *keys_ifcfg, NMSetting8021x *s_8021x, gboolean phase2, GError **error) { NMSettingSecretFlags flags; - GBytes *bytes; - char *value; + gs_free char *identity_free = NULL; + nm_auto_free_secret char *password_raw_str = NULL; + gs_unref_bytes GBytes *password_raw_bytes = NULL; - value = svGetValueStr_cp (ifcfg, "IEEE_8021X_IDENTITY"); - if (!value) { - g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, - "Missing IEEE_8021X_IDENTITY for EAP method '%s'.", - eap_method); - return FALSE; - } - g_object_set (s_8021x, NM_SETTING_802_1X_IDENTITY, value, NULL); - nm_clear_g_free (&value); + g_object_set (s_8021x, + NM_SETTING_802_1X_IDENTITY, + svGetValueStr (ifcfg, "IEEE_8021X_IDENTITY", &identity_free), + NULL); - read_8021x_password (ifcfg, keys, "IEEE_8021X_PASSWORD", &value, &flags); - g_object_set (s_8021x, NM_SETTING_802_1X_PASSWORD_FLAGS, flags, NULL); - if (value) { - g_object_set (s_8021x, NM_SETTING_802_1X_PASSWORD, value, NULL); - nm_clear_g_free (&value); - } + _secret_set_from_ifcfg (s_8021x, + ifcfg, + keys_ifcfg, + "IEEE_8021X_PASSWORD", + NM_SETTING_802_1X_PASSWORD); + + _secret_read_ifcfg (ifcfg, keys_ifcfg, "IEEE_8021X_PASSWORD_RAW", &password_raw_str, &flags); + if (!_secret_password_raw_to_bytes ("IEEE_8021X_PASSWORD_RAW", + password_raw_str, + &password_raw_bytes, + error)) + return FALSE; - read_8021x_password (ifcfg, keys, "IEEE_8021X_PASSWORD_RAW", &value, &flags); - g_object_set (s_8021x, NM_SETTING_802_1X_PASSWORD_RAW_FLAGS, flags, NULL); - if (value) { - bytes = nm_utils_hexstr2bin (value); - if (!bytes) { - g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, - "Invalid hex string '%s' in IEEE_8021X_PASSWORD_RAW.", - value); - g_free (value); - return FALSE; - } - g_object_set (s_8021x, NM_SETTING_802_1X_PASSWORD_RAW, bytes, NULL); - g_bytes_unref (bytes); - nm_clear_g_free (&value); - } + g_object_set (s_8021x, + NM_SETTING_802_1X_PASSWORD_RAW_FLAGS, + flags, + NM_SETTING_802_1X_PASSWORD_RAW, + password_raw_bytes, + NULL); return TRUE; } -static char * -get_full_file_path (const char *ifcfg_path, const char *file_path) -{ - const char *base = file_path; - char *p, *ret, *dirname; - - g_return_val_if_fail (ifcfg_path != NULL, NULL); - g_return_val_if_fail (file_path != NULL, NULL); - - if (file_path[0] == '/') - return g_strdup (file_path); - - p = strrchr (file_path, '/'); - if (p) - base = p + 1; - - dirname = g_path_get_dirname (ifcfg_path); - ret = g_build_path ("/", dirname, base, NULL); - g_free (dirname); - return ret; -} - -static char * -get_cert_value (const char *ifcfg_path, const char *value, - NMSetting8021xCKScheme *out_scheme) -{ - if (strncmp (value, "pkcs11:", 7) == 0) { - *out_scheme = NM_SETTING_802_1X_CK_SCHEME_PKCS11; - return g_strdup (value); - } - - *out_scheme = NM_SETTING_802_1X_CK_SCHEME_PATH; - return get_full_file_path (ifcfg_path, value); -} - static gboolean eap_tls_reader (const char *eap_method, shvarFile *ifcfg, - shvarFile *keys, + shvarFile *keys_ifcfg, NMSetting8021x *s_8021x, gboolean phase2, GError **error) { - gs_free char *ca_cert = NULL; - gs_free char *privkey = NULL; - gs_free char *privkey_password = NULL; - char *value; - char *ca_cert_password = NULL; - char *client_cert_password = NULL; - NMSetting8021xCKFormat privkey_format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN; - const char *ca_cert_key = phase2 ? "IEEE_8021X_INNER_CA_CERT" : "IEEE_8021X_CA_CERT"; - const char *ca_cert_pw_key = phase2 ? "IEEE_8021X_INNER_CA_CERT_PASSWORD" : "IEEE_8021X_CA_CERT_PASSWORD"; - const char *ca_cert_pw_prop = phase2 ? NM_SETTING_802_1X_PHASE2_CA_CERT_PASSWORD : NM_SETTING_802_1X_CA_CERT_PASSWORD; - const char *ca_cert_pw_flags_key = phase2 ? "IEEE_8021X_INNER_CA_CERT_PASSWORD_FLAGS" : "IEEE_8021X_CA_CERT_PASSWORD_FLAGS"; - const char *ca_cert_pw_flags_prop = phase2 ? NM_SETTING_802_1X_PHASE2_CA_CERT_PASSWORD_FLAGS : NM_SETTING_802_1X_CA_CERT_PASSWORD_FLAGS; - const char *cli_cert_key = phase2 ? "IEEE_8021X_INNER_CLIENT_CERT" : "IEEE_8021X_CLIENT_CERT"; - const char *cli_cert_pw_key = phase2 ? "IEEE_8021X_INNER_CLIENT_CERT_PASSWORD" : "IEEE_8021X_CLIENT_CERT_PASSWORD"; - const char *cli_cert_pw_prop = phase2 ? NM_SETTING_802_1X_PHASE2_CLIENT_CERT_PASSWORD : NM_SETTING_802_1X_CLIENT_CERT_PASSWORD; - const char *cli_cert_pw_flags_key = phase2 ? "IEEE_8021X_INNER_CLIENT_CERT_PASSWORD_FLAGS" : "IEEE_8021X_CLIENT_CERT_PASSWORD_FLAGS"; - const char *cli_cert_pw_flags_prop = phase2 ? NM_SETTING_802_1X_PHASE2_CLIENT_CERT_PASSWORD_FLAGS : NM_SETTING_802_1X_CLIENT_CERT_PASSWORD_FLAGS; - const char *pk_key = phase2 ? "IEEE_8021X_INNER_PRIVATE_KEY" : "IEEE_8021X_PRIVATE_KEY"; - const char *pk_pw_key = phase2 ? "IEEE_8021X_INNER_PRIVATE_KEY_PASSWORD": "IEEE_8021X_PRIVATE_KEY_PASSWORD"; - const char *pk_pw_flags_key = phase2 ? "IEEE_8021X_INNER_PRIVATE_KEY_PASSWORD_FLAGS" : "IEEE_8021X_PRIVATE_KEY_PASSWORD_FLAGS"; - const char *pk_pw_flags_prop = phase2 ? NM_SETTING_802_1X_PHASE2_PRIVATE_KEY_PASSWORD_FLAGS : NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD_FLAGS; - NMSettingSecretFlags flags; - NMSetting8021xCKScheme scheme; + gs_unref_bytes GBytes *privkey = NULL; + gs_unref_bytes GBytes *client_cert = NULL; + gs_free char *identity_free = NULL; - value = svGetValueStr_cp (ifcfg, "IEEE_8021X_IDENTITY"); - if (value) { - g_object_set (s_8021x, NM_SETTING_802_1X_IDENTITY, value, NULL); - g_free (value); - } - - ca_cert = svGetValueStr_cp (ifcfg, ca_cert_key); - if (ca_cert) { - gs_free char *real_cert_value = NULL; - - real_cert_value = get_cert_value (svFileGetName (ifcfg), ca_cert, &scheme); - if (phase2) { - if (!nm_setting_802_1x_set_phase2_ca_cert (s_8021x, real_cert_value, scheme, NULL, error)) - return FALSE; - } else { - if (!nm_setting_802_1x_set_ca_cert (s_8021x, real_cert_value, scheme, NULL, error)) - return FALSE; - } - - if (scheme == NM_SETTING_802_1X_CK_SCHEME_PKCS11) { - flags = read_secret_flags (ifcfg, ca_cert_pw_flags_key); - g_object_set (s_8021x, ca_cert_pw_flags_prop, flags, NULL); - - if (flags == NM_SETTING_SECRET_FLAG_NONE) { - ca_cert_password = svGetValueStr_cp (ifcfg, ca_cert_pw_key); - g_object_set (s_8021x, ca_cert_pw_prop, ca_cert_password, NULL); - } - } - } else { - PARSE_WARNING ("missing %s for EAP method '%s'; this is insecure!", - ca_cert_key, eap_method); - } - - /* Read and set private key password flags */ - flags = read_secret_flags (ifcfg, pk_pw_flags_key); - g_object_set (s_8021x, pk_pw_flags_prop, flags, NULL); - - /* Read the private key password if it's system-owned */ - if (flags == NM_SETTING_SECRET_FLAG_NONE) { - /* Private key password */ - privkey_password = svGetValueStr_cp (ifcfg, pk_pw_key); - if (!privkey_password && keys) { - /* Try the lookaside keys file */ - privkey_password = svGetValueStr_cp (keys, pk_pw_key); - } - } + g_object_set (s_8021x, + NM_SETTING_802_1X_IDENTITY, + svGetValueStr (ifcfg, "IEEE_8021X_IDENTITY", &identity_free), + NULL); - /* The private key itself */ - privkey = svGetValueStr_cp (ifcfg, pk_key); + if (!_cert_set_from_ifcfg (s_8021x, + ifcfg, + phase2 ? "IEEE_8021X_INNER_CA_CERT" : "IEEE_8021X_CA_CERT", + phase2 ? NM_SETTING_802_1X_PHASE2_CA_CERT : NM_SETTING_802_1X_CA_CERT, + NULL, + error)) + return FALSE; + _secret_set_from_ifcfg (s_8021x, + ifcfg, + keys_ifcfg, + phase2 ? "IEEE_8021X_INNER_CA_CERT_PASSWORD" : "IEEE_8021X_CA_CERT_PASSWORD", + phase2 ? NM_SETTING_802_1X_PHASE2_CA_CERT_PASSWORD : NM_SETTING_802_1X_CA_CERT_PASSWORD); + + if (!_cert_set_from_ifcfg (s_8021x, + ifcfg, + phase2 ? "IEEE_8021X_INNER_PRIVATE_KEY" : "IEEE_8021X_PRIVATE_KEY", + phase2 ? NM_SETTING_802_1X_PHASE2_PRIVATE_KEY : NM_SETTING_802_1X_PRIVATE_KEY, + &privkey, + error)) + return FALSE; + _secret_set_from_ifcfg (s_8021x, + ifcfg, + keys_ifcfg, + phase2 ? "IEEE_8021X_INNER_PRIVATE_KEY_PASSWORD" : "IEEE_8021X_PRIVATE_KEY_PASSWORD", + phase2 ? NM_SETTING_802_1X_PHASE2_PRIVATE_KEY_PASSWORD : NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD); if (!privkey) { g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, "Missing %s for EAP method '%s'.", - pk_key, + phase2 ? "IEEE_8021X_INNER_PRIVATE_KEY" : "IEEE_8021X_PRIVATE_KEY", eap_method); return FALSE; } - { - gs_free char *real_cert_value = NULL; - - real_cert_value = get_cert_value (svFileGetName (ifcfg), privkey, &scheme); - if (phase2) { - if (!nm_setting_802_1x_set_phase2_private_key (s_8021x, - real_cert_value, - privkey_password, - scheme, - &privkey_format, - error)) - return FALSE; - } else { - if (!nm_setting_802_1x_set_private_key (s_8021x, - real_cert_value, - privkey_password, - scheme, - &privkey_format, - error)) - return FALSE; - } - } - - /* Only set the client certificate if the private key is not PKCS#12 format, - * as NM (due to supplicant restrictions) requires. If the key was PKCS#12, - * then nm_setting_802_1x_set_private_key() already set the client certificate - * to the same value as the private key. - */ - if (privkey_format != NM_SETTING_802_1X_CK_FORMAT_PKCS12) { - gs_free char *real_cert_value = NULL; - gs_free char *client_cert = NULL; - - client_cert = svGetValueStr_cp (ifcfg, cli_cert_key); - if (!client_cert) { - g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, - "Missing %s for EAP method '%s'.", - cli_cert_key, - eap_method); - return FALSE; - } - - real_cert_value = get_cert_value (svFileGetName (ifcfg), client_cert, &scheme); - if (phase2) { - if (!nm_setting_802_1x_set_phase2_client_cert (s_8021x, real_cert_value, scheme, NULL, error)) - return FALSE; - } else { - if (!nm_setting_802_1x_set_client_cert (s_8021x, real_cert_value, scheme, NULL, error)) - return FALSE; - } - - if (scheme == NM_SETTING_802_1X_CK_SCHEME_PKCS11) { - flags = read_secret_flags (ifcfg, cli_cert_pw_flags_key); - g_object_set (s_8021x, cli_cert_pw_flags_prop, flags, NULL); - - if (flags == NM_SETTING_SECRET_FLAG_NONE) { - client_cert_password = svGetValueStr_cp (ifcfg, cli_cert_pw_key); - g_object_set (s_8021x, cli_cert_pw_prop, client_cert_password, NULL); - } - } + if (!_cert_set_from_ifcfg (s_8021x, + ifcfg, + phase2 ? "IEEE_8021X_INNER_CLIENT_CERT" : "IEEE_8021X_CLIENT_CERT", + phase2 ? NM_SETTING_802_1X_PHASE2_CLIENT_CERT : NM_SETTING_802_1X_CLIENT_CERT, + &client_cert, + error)) + return FALSE; + /* FIXME: writer does not actually write IEEE_8021X_CLIENT_CERT_PASSWORD and other + * certificate related passwords. It should, because otherwise persisting such profiles + * to ifcfg looses information. As this currently only matters for PKCS11 URIs, it seems + * a seldomly used feature so that it is not fixed yet. */ + _secret_set_from_ifcfg (s_8021x, + ifcfg, + keys_ifcfg, + phase2 ? "IEEE_8021X_INNER_CLIENT_CERT_PASSWORD" : "IEEE_8021X_CLIENT_CERT_PASSWORD", + phase2 ? NM_SETTING_802_1X_PHASE2_CLIENT_CERT_PASSWORD : NM_SETTING_802_1X_CLIENT_CERT_PASSWORD); + if (!client_cert) { + g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, + "Missing certificate for EAP method '%s'.", + eap_method); + return FALSE; } return TRUE; @@ -3028,7 +3170,7 @@ eap_tls_reader (const char *eap_method, static gboolean eap_peap_reader (const char *eap_method, shvarFile *ifcfg, - shvarFile *keys, + shvarFile *keys_ifcfg, NMSetting8021x *s_8021x, gboolean phase2, GError **error) @@ -3037,19 +3179,19 @@ eap_peap_reader (const char *eap_method, const char *v; gs_free const char **list = NULL; const char *const *iter; - NMSetting8021xCKScheme scheme; - - v = svGetValueStr (ifcfg, "IEEE_8021X_CA_CERT", &value); - if (v) { - gs_free char *real_cert_value = NULL; - real_cert_value = get_cert_value (svFileGetName (ifcfg), v, &scheme); - if (!nm_setting_802_1x_set_ca_cert (s_8021x, real_cert_value, scheme, NULL, error)) - return FALSE; - } else { - PARSE_WARNING ("missing IEEE_8021X_CA_CERT for EAP method '%s'; this is insecure!", - eap_method); - } + if (!_cert_set_from_ifcfg (s_8021x, + ifcfg, + "IEEE_8021X_CA_CERT", + NM_SETTING_802_1X_CA_CERT, + NULL, + error)) + return FALSE; + _secret_set_from_ifcfg (s_8021x, + ifcfg, + keys_ifcfg, + "IEEE_8021X_CA_CERT_PASSWORD", + NM_SETTING_802_1X_CA_CERT_PASSWORD); nm_clear_g_free (&value); v = svGetValueStr (ifcfg, "IEEE_8021X_PEAP_VERSION", &value); @@ -3083,16 +3225,16 @@ eap_peap_reader (const char *eap_method, } /* Handle options for the inner auth method */ - list = nm_utils_strsplit_set (v, " "); + list = nm_utils_strsplit_set (v, " ", FALSE); iter = list; if (iter) { if (NM_IN_STRSET (*iter, "MSCHAPV2", "MD5", "GTC")) { - if (!eap_simple_reader (*iter, ifcfg, keys, s_8021x, TRUE, error)) + if (!eap_simple_reader (*iter, ifcfg, keys_ifcfg, s_8021x, TRUE, error)) return FALSE; } else if (nm_streq (*iter, "TLS")) { - if (!eap_tls_reader (*iter, ifcfg, keys, s_8021x, TRUE, error)) + if (!eap_tls_reader (*iter, ifcfg, keys_ifcfg, s_8021x, TRUE, error)) return FALSE; } else { g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, @@ -3121,7 +3263,7 @@ eap_peap_reader (const char *eap_method, static gboolean eap_ttls_reader (const char *eap_method, shvarFile *ifcfg, - shvarFile *keys, + shvarFile *keys_ifcfg, NMSetting8021x *s_8021x, gboolean phase2, GError **error) @@ -3131,19 +3273,19 @@ eap_ttls_reader (const char *eap_method, const char *v; gs_free const char **list = NULL; const char *const *iter; - NMSetting8021xCKScheme scheme; - - v = svGetValueStr (ifcfg, "IEEE_8021X_CA_CERT", &value); - if (v) { - gs_free char *real_cert_value = NULL; - real_cert_value = get_cert_value (svFileGetName (ifcfg), v, &scheme); - if (!nm_setting_802_1x_set_ca_cert (s_8021x, real_cert_value, scheme, NULL, error)) - return FALSE; - } else { - PARSE_WARNING ("missing IEEE_8021X_CA_CERT for EAP method '%s'; this is insecure!", - eap_method); - } + if (!_cert_set_from_ifcfg (s_8021x, + ifcfg, + "IEEE_8021X_CA_CERT", + NM_SETTING_802_1X_CA_CERT, + NULL, + error)) + return FALSE; + _secret_set_from_ifcfg (s_8021x, + ifcfg, + keys_ifcfg, + "IEEE_8021X_CA_CERT_PASSWORD", + NM_SETTING_802_1X_CA_CERT_PASSWORD); nm_clear_g_free (&value); v = svGetValueStr (ifcfg, "IEEE_8021X_ANON_IDENTITY", &value); @@ -3161,24 +3303,24 @@ eap_ttls_reader (const char *eap_method, inner_auth = g_ascii_strdown (v, -1); /* Handle options for the inner auth method */ - list = nm_utils_strsplit_set (inner_auth, " "); + list = nm_utils_strsplit_set (inner_auth, " ", FALSE); iter = list; if (iter) { if (NM_IN_STRSET (*iter, "mschapv2", "mschap", "pap", "chap")) { - if (!eap_simple_reader (*iter, ifcfg, keys, s_8021x, TRUE, error)) + if (!eap_simple_reader (*iter, ifcfg, keys_ifcfg, s_8021x, TRUE, error)) return FALSE; g_object_set (s_8021x, NM_SETTING_802_1X_PHASE2_AUTH, *iter, NULL); } else if (nm_streq (*iter, "eap-tls")) { - if (!eap_tls_reader (*iter, ifcfg, keys, s_8021x, TRUE, error)) + if (!eap_tls_reader (*iter, ifcfg, keys_ifcfg, s_8021x, TRUE, error)) return FALSE; g_object_set (s_8021x, NM_SETTING_802_1X_PHASE2_AUTHEAP, "tls", NULL); } else if (NM_IN_STRSET (*iter, "eap-mschapv2", "eap-md5", "eap-gtc")) { - if (!eap_simple_reader (*iter, ifcfg, keys, s_8021x, TRUE, error)) + if (!eap_simple_reader (*iter, ifcfg, keys_ifcfg, s_8021x, TRUE, error)) return FALSE; g_object_set (s_8021x, NM_SETTING_802_1X_PHASE2_AUTHEAP, (*iter + NM_STRLEN ("eap-")), NULL); } else { @@ -3195,7 +3337,7 @@ eap_ttls_reader (const char *eap_method, static gboolean eap_fast_reader (const char *eap_method, shvarFile *ifcfg, - shvarFile *keys, + shvarFile *keys_ifcfg, NMSetting8021x *s_8021x, gboolean phase2, GError **error) @@ -3222,7 +3364,7 @@ eap_fast_reader (const char *eap_method, if (fast_provisioning) { gs_free const char **list1 = NULL; - list1 = nm_utils_strsplit_set (fast_provisioning, " \t"); + list1 = nm_utils_strsplit_set (fast_provisioning, " \t", FALSE); for (iter = list1; iter && *iter; iter++) { if (strcmp (*iter, "allow-unauth") == 0) allow_unauth = TRUE; @@ -3256,12 +3398,12 @@ eap_fast_reader (const char *eap_method, } /* Handle options for the inner auth method */ - list = nm_utils_strsplit_set (inner_auth, " "); + list = nm_utils_strsplit_set (inner_auth, " ", FALSE); iter = list; if (iter) { if ( !strcmp (*iter, "MSCHAPV2") || !strcmp (*iter, "GTC")) { - if (!eap_simple_reader (*iter, ifcfg, keys, s_8021x, TRUE, error)) + if (!eap_simple_reader (*iter, ifcfg, keys_ifcfg, s_8021x, TRUE, error)) goto done; } else { g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, @@ -3296,7 +3438,7 @@ typedef struct { const char *method; gboolean (*reader) (const char *eap_method, shvarFile *ifcfg, - shvarFile *keys, + shvarFile *keys_ifcfg, NMSetting8021x *s_8021x, gboolean phase2, GError **error); @@ -3336,7 +3478,7 @@ read_8021x_list_value (shvarFile *ifcfg, if (!v) return; - strv = nm_utils_strsplit_set (v, " \t"); + strv = nm_utils_strsplit_set (v, " \t", FALSE); if (strv) g_object_set (setting, prop_name, strv, NULL); } @@ -3348,7 +3490,7 @@ fill_8021x (shvarFile *ifcfg, gboolean wifi, GError **error) { - nm_auto_shvar_file_close shvarFile *keys = NULL; + nm_auto_shvar_file_close shvarFile *keys_ifcfg = NULL; gs_unref_object NMSetting8021x *s_8021x = NULL; gs_free char *value = NULL; const char *v; @@ -3365,12 +3507,12 @@ fill_8021x (shvarFile *ifcfg, return NULL; } - list = nm_utils_strsplit_set (v, " "); + list = nm_utils_strsplit_set (v, " ", FALSE); s_8021x = (NMSetting8021x *) nm_setting_802_1x_new (); - /* Read in the lookaside keys file, if present */ - keys = utils_get_keys_ifcfg (file, FALSE); + /* Read in the lookaside keys_ifcfg file, if present */ + keys_ifcfg = utils_get_keys_ifcfg (file, FALSE); /* Validate and handle each EAP method */ for (iter = list; iter && *iter; iter++) { @@ -3394,7 +3536,7 @@ fill_8021x (shvarFile *ifcfg, } /* Parse EAP method specific options */ - if (!(*eap->reader)(lower, ifcfg, keys, s_8021x, FALSE, error)) + if (!(*eap->reader)(lower, ifcfg, keys_ifcfg, s_8021x, FALSE, error)) return NULL; nm_setting_802_1x_add_eap_method (s_8021x, lower); @@ -3444,7 +3586,7 @@ next: g_object_set (s_8021x, NM_SETTING_802_1X_PHASE2_DOMAIN_SUFFIX_MATCH, v, NULL); timeout = svGetValueInt64 (ifcfg, "IEEE_8021X_AUTH_TIMEOUT", 10, 0, G_MAXINT32, 0); - g_object_set (s_8021x, NM_SETTING_802_1X_AUTH_TIMEOUT, (gint) timeout, NULL); + g_object_set (s_8021x, NM_SETTING_802_1X_AUTH_TIMEOUT, (int) timeout, NULL); return g_steal_pointer (&s_8021x); } @@ -3510,7 +3652,7 @@ make_wpa_setting (shvarFile *ifcfg, if (wpa_psk) { NMSettingSecretFlags psk_flags; - psk_flags = read_secret_flags (ifcfg, "WPA_PSK_FLAGS"); + psk_flags = _secret_read_ifcfg_flags (ifcfg, "WPA_PSK_FLAGS"); g_object_set (wsec, NM_SETTING_WIRELESS_SECURITY_PSK_FLAGS, psk_flags, NULL); /* Read PSK if it's system-owned */ @@ -3597,7 +3739,7 @@ make_leap_setting (shvarFile *ifcfg, return NULL; /* Not LEAP */ nm_clear_g_free (&value); - flags = read_secret_flags (ifcfg, "IEEE_8021X_PASSWORD_FLAGS"); + flags = _secret_read_ifcfg_flags (ifcfg, "IEEE_8021X_PASSWORD_FLAGS"); g_object_set (wsec, NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD_FLAGS, flags, NULL); /* Read LEAP password if it's system-owned */ @@ -3674,7 +3816,7 @@ transform_hwaddr_blacklist (const char *blacklist) const char **strv; gsize i, j; - strv = nm_utils_strsplit_set (blacklist, " \t"); + strv = nm_utils_strsplit_set (blacklist, " \t", FALSE); if (!strv) return NULL; for (i = 0, j = 0; strv[j]; j++) { @@ -3923,7 +4065,7 @@ wireless_connection_from_ifcfg (const char *file, NMSetting8021x *s_8021x = NULL; GBytes *ssid; NMSetting *security_setting = NULL; - char *printable_ssid = NULL; + gs_free char *ssid_utf8 = NULL; const char *mode; gboolean adhoc = FALSE; GError *local = NULL; @@ -3943,12 +4085,6 @@ wireless_connection_from_ifcfg (const char *file, nm_connection_add_setting (connection, wireless_setting); ssid = nm_setting_wireless_get_ssid (NM_SETTING_WIRELESS (wireless_setting)); - if (ssid) { - printable_ssid = nm_utils_ssid_to_utf8 (g_bytes_get_data (ssid, NULL), - g_bytes_get_size (ssid)); - } else - printable_ssid = g_strdup ("unmanaged"); - mode = nm_setting_wireless_get_mode (NM_SETTING_WIRELESS (wireless_setting)); if (mode && !strcmp (mode, "adhoc")) adhoc = TRUE; @@ -3956,7 +4092,6 @@ wireless_connection_from_ifcfg (const char *file, /* Wireless security */ security_setting = make_wireless_security_setting (ifcfg, file, ssid, adhoc, &s_8021x, &local); if (local) { - g_free (printable_ssid); g_object_unref (connection); g_propagate_error (error, local); return NULL; @@ -3967,11 +4102,16 @@ wireless_connection_from_ifcfg (const char *file, nm_connection_add_setting (connection, NM_SETTING (s_8021x)); } + if (ssid) + ssid_utf8 = _nm_utils_ssid_to_utf8 (ssid); + /* Connection */ - con_setting = make_connection_setting (file, ifcfg, + con_setting = make_connection_setting (file, + ifcfg, NM_SETTING_WIRELESS_SETTING_NAME, - printable_ssid, NULL); - g_free (printable_ssid); + nm_str_not_empty (ssid_utf8) ?: "unmanaged", + NULL); + if (!con_setting) { g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, "Failed to create connection setting."); @@ -3984,199 +4124,253 @@ wireless_connection_from_ifcfg (const char *file, } static void -parse_ethtool_option_autoneg (const char *value, gboolean *out_autoneg) +parse_ethtool_option (const char *value, + NMSettingWiredWakeOnLan *out_flags, + char **out_password, + gboolean *out_autoneg, + guint32 *out_speed, + const char **out_duplex, + NMSettingEthtool **out_s_ethtool) { - if (!value) { - PARSE_WARNING ("Auto-negotiation option missing"); + gs_free const char **words = NULL; + guint i; + + words = nm_utils_strsplit_set (value, NULL, FALSE); + if (!words) return; - } - if (g_str_equal (value, "off")) - *out_autoneg = FALSE; - else if (g_str_equal (value, "on")) - *out_autoneg = TRUE; - else - PARSE_WARNING ("Auto-negotiation unknown value: %s", value); -} + if (words[0] && words[0][0] == '-') { + /* /sbin/ethtool $opts */ + if (NM_IN_STRSET (words[0], "-K", "--features", "--offload")) { + if (!words[1]) { + /* first argument must be the interface name. This is invalid. */ + return; + } -static void -parse_ethtool_option_speed (const char *value, guint32 *out_speed) -{ - if (!value) { - PARSE_WARNING ("Speed option missing"); - return; - } + if (!*out_s_ethtool) + *out_s_ethtool = NM_SETTING_ETHTOOL (nm_setting_ethtool_new ()); - *out_speed = _nm_utils_ascii_str_to_int64 (value, 10, 0, G_MAXUINT32, 0); - if (errno) - PARSE_WARNING ("Speed value '%s' is invalid", value); -} + for (i = 2; words[i]; ) { + const char *opt = words[i]; + const char *opt_val = words[++i]; + const NMEthtoolData *d = NULL; + NMTernary onoff = NM_TERNARY_DEFAULT; -static void -parse_ethtool_option_duplex (const char *value, const char **out_duplex) -{ - if (!value) { - PARSE_WARNING ("Duplex option missing"); - return; - } + if (nm_streq0 (opt_val, "on")) + onoff = NM_TERNARY_TRUE; + else if (nm_streq0 (opt_val, "off")) + onoff = NM_TERNARY_FALSE; - if (g_str_equal (value, "half")) - *out_duplex = "half"; - else if (g_str_equal (value, "full")) - *out_duplex = "full"; - else - PARSE_WARNING ("Duplex unknown value: %s", value); + d = nms_ifcfg_rh_utils_get_ethtool_by_name (opt); -} + if (!d) { + if (onoff != NM_TERNARY_DEFAULT) { + /* the next value is just the on/off argument. Skip it too. */ + i++; + } -static void -parse_ethtool_option_wol (const char *value, NMSettingWiredWakeOnLan *out_flags) -{ - NMSettingWiredWakeOnLan wol_flags = NM_SETTING_WIRED_WAKE_ON_LAN_NONE; + /* silently ignore unsupported offloading features. */ + continue; + } - if (!value) { - PARSE_WARNING ("Wake-on-LAN options missing"); + i++; + + if (onoff == NM_TERNARY_DEFAULT) { + PARSE_WARNING ("Expects on/off argument for feature '%s'", opt); + continue; + } + + nm_setting_ethtool_set_feature (*out_s_ethtool, + d->optname, + onoff); + } + } return; } - for (; *value; value++) { - switch (*value) { - case 'p': - wol_flags |= NM_SETTING_WIRED_WAKE_ON_LAN_PHY; - break; - case 'u': - wol_flags |= NM_SETTING_WIRED_WAKE_ON_LAN_UNICAST; - break; - case 'm': - wol_flags |= NM_SETTING_WIRED_WAKE_ON_LAN_MULTICAST; - break; - case 'b': - wol_flags |= NM_SETTING_WIRED_WAKE_ON_LAN_BROADCAST; - break; - case 'a': - wol_flags |= NM_SETTING_WIRED_WAKE_ON_LAN_ARP; - break; - case 'g': - wol_flags |= NM_SETTING_WIRED_WAKE_ON_LAN_MAGIC; - break; - case 's': - break; - case 'd': - wol_flags = NM_SETTING_WIRED_WAKE_ON_LAN_NONE; - break; - default: - PARSE_WARNING ("unrecognized Wake-on-LAN option '%c'", *value); + /* /sbin/ethtool -s ${REALDEVICE} $opts */ + for (i = 0; words[i]; ) { + const char *opt = words[i]; + const char *opt_val = words[++i]; + + if (nm_streq (opt, "autoneg")) { + if (!opt_val) { + PARSE_WARNING ("Auto-negotiation option missing"); + break; + } + i++; + + if (nm_streq (opt_val, "off")) + *out_autoneg = FALSE; + else if (nm_streq (opt_val, "on")) + *out_autoneg = TRUE; + else + PARSE_WARNING ("Auto-negotiation unknown value: %s", opt_val); + continue; } - } - *out_flags = wol_flags; -} + if (nm_streq (opt, "speed")) { + guint32 speed; -static void parse_ethtool_option_sopass (const char *value, char **out_password) -{ - if (!value) { - PARSE_WARNING ("Wake-on-LAN password missing"); - return; - } + if (!opt_val) { + PARSE_WARNING ("Speed option missing"); + break; + } + i++; - g_clear_pointer (out_password, g_free); - if (!nm_utils_hwaddr_valid (value, ETH_ALEN)) { - PARSE_WARNING ("Wake-on-LAN password '%s' is invalid", value); - return; - } + speed = _nm_utils_ascii_str_to_int64 (opt_val, 10, 0, G_MAXUINT32, 0); + if (errno == 0) + *out_speed = speed; + else + PARSE_WARNING ("Speed value '%s' is invalid", opt_val); + continue; + } - *out_password = g_strdup (value); -} + if (nm_streq (opt, "duplex")) { + if (!opt_val) { + PARSE_WARNING ("Duplex option missing"); + break; + } + i++; -static void -parse_ethtool_option (const char *value, - NMSettingWiredWakeOnLan *out_flags, - char **out_password, - gboolean *out_autoneg, - guint32 *out_speed, - const char **out_duplex) -{ - gs_free const char **words = NULL; - const char *const *iter; - const char *opt_val, *opt; + if (nm_streq (opt_val, "half")) + *out_duplex = "half"; + else if (nm_streq (opt_val, "full")) + *out_duplex = "full"; + else + PARSE_WARNING ("Duplex unknown value: %s", opt_val); + continue; + } - words = nm_utils_strsplit_set (value, "\t "); - if (!words) - return; + if (nm_streq (opt, "wol")) { + NMSettingWiredWakeOnLan wol_flags = NM_SETTING_WIRED_WAKE_ON_LAN_NONE; - iter = words; - - while (iter[0]) { - opt = iter++[0]; - opt_val = iter[0]; - - if (nm_streq (opt, "autoneg")) - parse_ethtool_option_autoneg (opt_val, out_autoneg); - else if (nm_streq (opt, "speed")) - parse_ethtool_option_speed (opt_val, out_speed); - else if (nm_streq (opt, "duplex")) - parse_ethtool_option_duplex (opt_val, out_duplex); - else if (nm_streq (opt, "wol")) - parse_ethtool_option_wol (opt_val, out_flags); - else if (nm_streq (opt, "sopass")) - parse_ethtool_option_sopass (opt_val, out_password); - else { - /* Silently skip unknown options */ + if (!opt_val) { + PARSE_WARNING ("Wake-on-LAN options missing"); + break; + } + i++; + + for (; *opt_val; opt_val++) { + switch (*opt_val) { + case 'p': + wol_flags |= NM_SETTING_WIRED_WAKE_ON_LAN_PHY; + break; + case 'u': + wol_flags |= NM_SETTING_WIRED_WAKE_ON_LAN_UNICAST; + break; + case 'm': + wol_flags |= NM_SETTING_WIRED_WAKE_ON_LAN_MULTICAST; + break; + case 'b': + wol_flags |= NM_SETTING_WIRED_WAKE_ON_LAN_BROADCAST; + break; + case 'a': + wol_flags |= NM_SETTING_WIRED_WAKE_ON_LAN_ARP; + break; + case 'g': + wol_flags |= NM_SETTING_WIRED_WAKE_ON_LAN_MAGIC; + break; + case 's': + break; + case 'd': + wol_flags = NM_SETTING_WIRED_WAKE_ON_LAN_NONE; + break; + default: + PARSE_WARNING ("unrecognized Wake-on-LAN option '%c'", *opt_val); + } + } + + *out_flags = wol_flags; continue; } - if (iter[0]) - iter++; + if (nm_streq (opt, "sopass")) { + if (!opt_val) { + PARSE_WARNING ("Wake-on-LAN password missing"); + break; + } + i++; + + if (nm_utils_hwaddr_valid (opt_val, ETH_ALEN)) { + g_clear_pointer (out_password, g_free); + *out_password = g_strdup (opt_val); + } else + PARSE_WARNING ("Wake-on-LAN password '%s' is invalid", opt_val); + continue; + } + + /* Silently skip unknown options */ } } static void -parse_ethtool_options (shvarFile *ifcfg, NMSettingWired *s_wired, const char *value) +parse_ethtool_options (shvarFile *ifcfg, NMConnection *connection) { + NMSettingWired *s_wired; + gs_unref_object NMSettingEthtool *s_ethtool = NULL; NMSettingWiredWakeOnLan wol_flags = NM_SETTING_WIRED_WAKE_ON_LAN_DEFAULT; - gs_free char *wol_password = NULL, *wol_value = NULL; - gboolean ignore_wol_password = FALSE, autoneg = FALSE; + gs_free char *ethtool_opts_free = NULL; + const char *ethtool_opts; + gs_free char *wol_password = NULL; + gs_free char *wol_value_free = NULL; + const char *tmp; + gboolean autoneg = FALSE; guint32 speed = 0; const char *duplex = NULL; - if (value) { - gs_free const char **opts = NULL; - const char *const *iter; - + ethtool_opts = svGetValue (ifcfg, "ETHTOOL_OPTS", ðtool_opts_free); + if (ethtool_opts) { /* WAKE_ON_LAN_IGNORE is inferred from a specified but empty ETHTOOL_OPTS */ - if (!value[0]) + if (!ethtool_opts[0]) wol_flags = NM_SETTING_WIRED_WAKE_ON_LAN_IGNORE; - - opts = nm_utils_strsplit_set (value, ";"); - for (iter = opts; iter && iter[0]; iter++) { - /* in case of repeated wol_passwords, parse_ethtool_option() - * will do the right thing and clear wol_password before resetting. */ - parse_ethtool_option (iter[0], &wol_flags, &wol_password, &autoneg, &speed, &duplex); + else { + gs_free const char **opts = NULL; + const char *const *iter; + + opts = nm_utils_strsplit_set (ethtool_opts, ";", FALSE); + for (iter = opts; iter && iter[0]; iter++) { + /* in case of repeated wol_passwords, parse_ethtool_option() + * will do the right thing and clear wol_password before resetting. */ + parse_ethtool_option (iter[0], + &wol_flags, + &wol_password, + &autoneg, + &speed, + &duplex, + &s_ethtool); + } } } /* ETHTOOL_WAKE_ON_LAN = ignore overrides WoL settings in ETHTOOL_OPTS */ - wol_value = svGetValueStr_cp (ifcfg, "ETHTOOL_WAKE_ON_LAN"); - if (wol_value) { - if (strcmp (wol_value, "ignore") == 0) - wol_flags = NM_SETTING_WIRED_WAKE_ON_LAN_IGNORE; - else - PARSE_WARNING ("invalid ETHTOOL_WAKE_ON_LAN value '%s'", wol_value); - } + tmp = svGetValueStr (ifcfg, "ETHTOOL_WAKE_ON_LAN", &wol_value_free); + if (nm_streq0 (tmp, "ignore")) + wol_flags = NM_SETTING_WIRED_WAKE_ON_LAN_IGNORE; + else if (tmp) + PARSE_WARNING ("invalid ETHTOOL_WAKE_ON_LAN value '%s'", tmp); if ( wol_password && !NM_FLAGS_HAS (wol_flags, NM_SETTING_WIRED_WAKE_ON_LAN_MAGIC)) { PARSE_WARNING ("Wake-on-LAN password not expected"); - ignore_wol_password = TRUE; + nm_clear_g_free (&wol_password); } - g_object_set (s_wired, - NM_SETTING_WIRED_WAKE_ON_LAN, wol_flags, - NM_SETTING_WIRED_WAKE_ON_LAN_PASSWORD, ignore_wol_password ? NULL : wol_password, - NM_SETTING_WIRED_AUTO_NEGOTIATE, autoneg, - NM_SETTING_WIRED_SPEED, speed, - NM_SETTING_WIRED_DUPLEX, duplex, - NULL); + s_wired = nm_connection_get_setting_wired (connection); + if (s_wired) { + g_object_set (s_wired, + NM_SETTING_WIRED_WAKE_ON_LAN, wol_flags, + NM_SETTING_WIRED_WAKE_ON_LAN_PASSWORD, wol_password, + NM_SETTING_WIRED_AUTO_NEGOTIATE, autoneg, + NM_SETTING_WIRED_SPEED, speed, + NM_SETTING_WIRED_DUPLEX, duplex, + NULL); + } + + if (s_ethtool) { + nm_connection_add_setting (connection, + NM_SETTING (g_steal_pointer (&s_ethtool))); + } } static NMSetting * @@ -4230,7 +4424,7 @@ make_wired_setting (shvarFile *ifcfg, gs_free const char **chans = NULL; guint32 num_chans; - chans = nm_utils_strsplit_set (value, ","); + chans = nm_utils_strsplit_set (value, ",", FALSE); num_chans = NM_PTRARRAY_LEN (chans); if (num_chans < 2 || num_chans > 3) { PARSE_WARNING ("invalid SUBCHANNELS '%s' (%u channels, 2 or 3 expected)", @@ -4318,10 +4512,6 @@ make_wired_setting (shvarFile *ifcfg, nm_clear_g_free (&value); } - parse_ethtool_options (ifcfg, s_wired, - svGetValue (ifcfg, "ETHTOOL_OPTS", &value)); - nm_clear_g_free (&value); - return (NMSetting *) g_steal_pointer (&s_wired); } @@ -4557,7 +4747,7 @@ make_bond_setting (shvarFile *ifcfg, gs_free const char **items = NULL; const char *const *iter; - items = nm_utils_strsplit_set (v, " "); + items = nm_utils_strsplit_set (v, " ", FALSE); for (iter = items; iter && *iter; iter++) { gs_strfreev char **keys = NULL; const char *key, *val; @@ -4835,7 +5025,7 @@ handle_bridging_opts (NMSetting *setting, gs_free const char **items = NULL; const char *const *iter; - items = nm_utils_strsplit_set (value, " "); + items = nm_utils_strsplit_set (value, " ", FALSE); for (iter = items; iter && *iter; iter++) { gs_strfreev char **keys = NULL; const char *key, *val; @@ -5055,7 +5245,7 @@ parse_prio_map_list (NMSettingVlan *s_vlan, v = svGetValueStr (ifcfg, key, &value); if (!v) return; - list = nm_utils_strsplit_set (v, ","); + list = nm_utils_strsplit_set (v, ",", FALSE); for (iter = list; iter && *iter; iter++) { if (!strchr (*iter, ':')) @@ -5077,7 +5267,7 @@ make_vlan_setting (shvarFile *ifcfg, const char *v = NULL; int vlan_id = -1; guint32 vlan_flags = 0; - gint gvrp, reorder_hdr; + int gvrp, reorder_hdr; v = svGetValueStr (ifcfg, "VLAN_ID", &value); if (v) { @@ -5160,7 +5350,7 @@ make_vlan_setting (shvarFile *ifcfg, gs_free const char **strv = NULL; const char *const *ptr; - strv = nm_utils_strsplit_set (v, ", "); + strv = nm_utils_strsplit_set (v, ", ", FALSE); for (ptr = strv; ptr && *ptr; ptr++) { if (nm_streq (*ptr, "GVRP") && gvrp == -1) vlan_flags |= NM_VLAN_FLAG_GVRP; @@ -5302,7 +5492,7 @@ check_dns_search_domains (shvarFile *ifcfg, NMSetting *s_ip4, NMSetting *s_ip6) gs_free const char **searches = NULL; const char *const *item; - searches = nm_utils_strsplit_set (v, " "); + searches = nm_utils_strsplit_set (v, " ", FALSE); if (searches) { for (item = searches; *item; item++) { if (!nm_setting_ip_config_add_dns_search (NM_SETTING_IP_CONFIG (s_ip6), *item)) @@ -5321,12 +5511,13 @@ connection_from_file_full (const char *filename, GError **error, gboolean *out_ignore_error) { - nm_auto_shvar_file_close shvarFile *parsed = NULL; + nm_auto_shvar_file_close shvarFile *main_ifcfg = NULL; nm_auto_shvar_file_close shvarFile *network_ifcfg = NULL; gs_unref_object NMConnection *connection = NULL; gs_free char *type = NULL; char *devtype, *bootproto; NMSetting *s_ip4, *s_ip6, *s_tc, *s_proxy, *s_port, *s_dcb = NULL, *s_user; + NMSetting *s_sriov, *s_match; const char *ifcfg_name = NULL; gboolean has_ip4_defroute = FALSE; gboolean has_complex_routes_v4; @@ -5348,14 +5539,14 @@ connection_from_file_full (const char *filename, return NULL; } - parsed = svOpenFile (filename, error); - if (!parsed) + main_ifcfg = svOpenFile (filename, error); + if (!main_ifcfg) return NULL; network_ifcfg = svOpenFile (network_file, NULL); - if (!svGetValueBoolean (parsed, "NM_CONTROLLED", TRUE)) { - connection = create_unhandled_connection (filename, parsed, "unmanaged", out_unhandled); + if (!svGetValueBoolean (main_ifcfg, "NM_CONTROLLED", TRUE)) { + connection = create_unhandled_connection (filename, main_ifcfg, "unmanaged", out_unhandled); if (!connection) { NM_SET_OUT (out_ignore_error, TRUE); g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED, @@ -5365,7 +5556,7 @@ connection_from_file_full (const char *filename, } /* iBFT is handled by the iBFT settings plugin */ - bootproto = svGetValueStr_cp (parsed, "BOOTPROTO"); + bootproto = svGetValueStr_cp (main_ifcfg, "BOOTPROTO"); if (bootproto && !g_ascii_strcasecmp (bootproto, "ibft")) { NM_SET_OUT (out_ignore_error, TRUE); g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, @@ -5375,19 +5566,19 @@ connection_from_file_full (const char *filename, } g_free (bootproto); - devtype = svGetValueStr_cp (parsed, "DEVICETYPE"); + devtype = svGetValueStr_cp (main_ifcfg, "DEVICETYPE"); if (devtype) { if (!strcasecmp (devtype, TYPE_TEAM)) type = g_strdup (TYPE_TEAM); else if (!strcasecmp (devtype, TYPE_TEAM_PORT)) { gs_free char *device = NULL; - type = svGetValueStr_cp (parsed, "TYPE"); - device = svGetValueStr_cp (parsed, "DEVICE"); + type = svGetValueStr_cp (main_ifcfg, "TYPE"); + device = svGetValueStr_cp (main_ifcfg, "DEVICE"); if (type) { /* nothing to do */ - } else if (device && is_vlan_device (device, parsed)) + } else if (device && is_vlan_device (device, main_ifcfg)) type = g_strdup (TYPE_VLAN); else type = g_strdup (TYPE_ETHERNET); @@ -5400,26 +5591,26 @@ connection_from_file_full (const char *filename, /* Team and TeamPort types are also accepted by the mere * presence of TEAM_CONFIG/TEAM_MASTER. They don't require * DEVICETYPE. */ - t = svGetValueStr_cp (parsed, "TEAM_CONFIG"); + t = svGetValueStr_cp (main_ifcfg, "TEAM_CONFIG"); if (t) type = g_strdup (TYPE_TEAM); } if (!type) - type = svGetValueStr_cp (parsed, "TYPE"); + type = svGetValueStr_cp (main_ifcfg, "TYPE"); if (!type) { gs_free char *tmp = NULL; char *device; - if ((tmp = svGetValueStr_cp (parsed, "IPV6TUNNELIPV4"))) { + if ((tmp = svGetValueStr_cp (main_ifcfg, "IPV6TUNNELIPV4"))) { NM_SET_OUT (out_ignore_error, TRUE); g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, "Ignoring unsupported connection due to IPV6TUNNELIPV4"); return NULL; } - device = svGetValueStr_cp (parsed, "DEVICE"); + device = svGetValueStr_cp (main_ifcfg, "DEVICE"); if (!device) { g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, "File '%s' had neither TYPE nor DEVICE keys.", filename); @@ -5435,11 +5626,11 @@ connection_from_file_full (const char *filename, } if (!test_type) { - if (is_bond_device (device, parsed)) + if (is_bond_device (device, main_ifcfg)) type = g_strdup (TYPE_BOND); - else if (is_vlan_device (device, parsed)) + else if (is_vlan_device (device, main_ifcfg)) type = g_strdup (TYPE_VLAN); - else if (is_wifi_device (device, parsed)) + else if (is_wifi_device (device, main_ifcfg)) type = g_strdup (TYPE_WIRELESS); else { gs_free char *p_path = NULL; @@ -5505,14 +5696,14 @@ connection_from_file_full (const char *filename, if (nm_streq0 (type, TYPE_ETHERNET)) { gs_free char *bond_options = NULL; - if (svGetValueStr (parsed, "BONDING_OPTS", &bond_options)) { + if (svGetValueStr (main_ifcfg, "BONDING_OPTS", &bond_options)) { /* initscripts consider these as bond masters */ g_free (type); type = g_strdup (TYPE_BOND); } } - if (svGetValueBoolean (parsed, "BONDING_MASTER", FALSE) && + if (svGetValueBoolean (main_ifcfg, "BONDING_MASTER", FALSE) && strcasecmp (type, TYPE_BOND)) { g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, "BONDING_MASTER=yes key only allowed in TYPE=bond connections"); @@ -5521,21 +5712,21 @@ connection_from_file_full (const char *filename, /* Construct the connection */ if (!strcasecmp (type, TYPE_ETHERNET)) - connection = wired_connection_from_ifcfg (filename, parsed, error); + connection = wired_connection_from_ifcfg (filename, main_ifcfg, error); else if (!strcasecmp (type, TYPE_WIRELESS)) - connection = wireless_connection_from_ifcfg (filename, parsed, error); + connection = wireless_connection_from_ifcfg (filename, main_ifcfg, error); else if (!strcasecmp (type, TYPE_INFINIBAND)) - connection = infiniband_connection_from_ifcfg (filename, parsed, error); + connection = infiniband_connection_from_ifcfg (filename, main_ifcfg, error); else if (!strcasecmp (type, TYPE_BOND)) - connection = bond_connection_from_ifcfg (filename, parsed, error); + connection = bond_connection_from_ifcfg (filename, main_ifcfg, error); else if (!strcasecmp (type, TYPE_TEAM)) - connection = team_connection_from_ifcfg (filename, parsed, error); + connection = team_connection_from_ifcfg (filename, main_ifcfg, error); else if (!strcasecmp (type, TYPE_VLAN)) - connection = vlan_connection_from_ifcfg (filename, parsed, error); + connection = vlan_connection_from_ifcfg (filename, main_ifcfg, error); else if (!strcasecmp (type, TYPE_BRIDGE)) - connection = bridge_connection_from_ifcfg (filename, parsed, error); + connection = bridge_connection_from_ifcfg (filename, main_ifcfg, error); else { - connection = create_unhandled_connection (filename, parsed, "unrecognized", out_unhandled); + connection = create_unhandled_connection (filename, main_ifcfg, "unrecognized", out_unhandled); if (!connection) { PARSE_WARNING ("connection type was unrecognized but device was not uniquely identified; device may be managed"); g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, @@ -5547,6 +5738,8 @@ connection_from_file_full (const char *filename, if (!connection) return NULL; + parse_ethtool_options (main_ifcfg, connection); + has_complex_routes_v4 = utils_has_complex_routes (filename, AF_INET); has_complex_routes_v6 = utils_has_complex_routes (filename, AF_INET6); @@ -5559,7 +5752,7 @@ connection_from_file_full (const char *filename, PARSE_WARNING ("'rule-' and 'rule6-' files are present; you will need to use a dispatcher script to apply these routes"); } - s_ip6 = make_ip6_setting (parsed, + s_ip6 = make_ip6_setting (main_ifcfg, network_ifcfg, !has_complex_routes_v4 && !has_complex_routes_v6, error); @@ -5568,7 +5761,7 @@ connection_from_file_full (const char *filename, else nm_connection_add_setting (connection, s_ip6); - s_ip4 = make_ip4_setting (parsed, + s_ip4 = make_ip4_setting (main_ifcfg, network_ifcfg, !has_complex_routes_v4 && !has_complex_routes_v6, &has_ip4_defroute, @@ -5582,7 +5775,11 @@ connection_from_file_full (const char *filename, nm_connection_add_setting (connection, s_ip4); } - s_tc = make_tc_setting (parsed); + s_sriov = make_sriov_setting (main_ifcfg); + if (s_sriov) + nm_connection_add_setting (connection, s_sriov); + + s_tc = make_tc_setting (main_ifcfg); if (s_tc) nm_connection_add_setting (connection, s_tc); @@ -5590,27 +5787,31 @@ connection_from_file_full (const char *filename, * config fails for some reason, we read DOMAIN and put the * values into IPv6 config instead of IPv4. */ - check_dns_search_domains (parsed, s_ip4, s_ip6); + check_dns_search_domains (main_ifcfg, s_ip4, s_ip6); - s_proxy = make_proxy_setting (parsed); + s_proxy = make_proxy_setting (main_ifcfg); if (s_proxy) nm_connection_add_setting (connection, s_proxy); - s_user = make_user_setting (parsed); + s_user = make_user_setting (main_ifcfg); if (s_user) nm_connection_add_setting (connection, s_user); + s_match = make_match_setting (main_ifcfg); + if (s_match) + nm_connection_add_setting (connection, s_match); + /* Bridge port? */ - s_port = make_bridge_port_setting (parsed); + s_port = make_bridge_port_setting (main_ifcfg); if (s_port) nm_connection_add_setting (connection, s_port); /* Team port? */ - s_port = make_team_port_setting (parsed); + s_port = make_team_port_setting (main_ifcfg); if (s_port) nm_connection_add_setting (connection, s_port); - if (!make_dcb_setting (parsed, &s_dcb, error)) + if (!make_dcb_setting (main_ifcfg, &s_dcb, error)) return NULL; if (s_dcb) nm_connection_add_setting (connection, s_dcb); diff --git a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.c b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.c index 862e640e..49096d26 100644 --- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.c +++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.c @@ -470,3 +470,104 @@ nms_ifcfg_rh_utils_user_key_decode (const char *name, GString *str_buffer) return TRUE; } + +/*****************************************************************************/ + +const char *const _nm_ethtool_ifcfg_names[] = { +#define ETHT_NAME(eid, ename) \ +[eid - _NM_ETHTOOL_ID_FEATURE_FIRST] = ""ename"" + /* indexed by NMEthtoolID - _NM_ETHTOOL_ID_FEATURE_FIRST */ + ETHT_NAME (NM_ETHTOOL_ID_FEATURE_ESP_HW_OFFLOAD, "esp-hw-offload"), + ETHT_NAME (NM_ETHTOOL_ID_FEATURE_ESP_TX_CSUM_HW_OFFLOAD, "esp-tx-csum-hw-offload"), + ETHT_NAME (NM_ETHTOOL_ID_FEATURE_FCOE_MTU, "fcoe-mtu"), + ETHT_NAME (NM_ETHTOOL_ID_FEATURE_GRO, "gro"), + ETHT_NAME (NM_ETHTOOL_ID_FEATURE_GSO, "gso"), + ETHT_NAME (NM_ETHTOOL_ID_FEATURE_HIGHDMA, "highdma"), + ETHT_NAME (NM_ETHTOOL_ID_FEATURE_HW_TC_OFFLOAD, "hw-tc-offload"), + ETHT_NAME (NM_ETHTOOL_ID_FEATURE_L2_FWD_OFFLOAD, "l2-fwd-offload"), + ETHT_NAME (NM_ETHTOOL_ID_FEATURE_LOOPBACK, "loopback"), + ETHT_NAME (NM_ETHTOOL_ID_FEATURE_LRO, "lro"), + ETHT_NAME (NM_ETHTOOL_ID_FEATURE_NTUPLE, "ntuple"), + ETHT_NAME (NM_ETHTOOL_ID_FEATURE_RX, "rx"), + ETHT_NAME (NM_ETHTOOL_ID_FEATURE_RXHASH, "rxhash"), + ETHT_NAME (NM_ETHTOOL_ID_FEATURE_RXVLAN, "rxvlan"), + ETHT_NAME (NM_ETHTOOL_ID_FEATURE_RX_ALL, "rx-all"), + ETHT_NAME (NM_ETHTOOL_ID_FEATURE_RX_FCS, "rx-fcs"), + ETHT_NAME (NM_ETHTOOL_ID_FEATURE_RX_GRO_HW, "rx-gro-hw"), + ETHT_NAME (NM_ETHTOOL_ID_FEATURE_RX_UDP_TUNNEL_PORT_OFFLOAD, "rx-udp_tunnel-port-offload"), + ETHT_NAME (NM_ETHTOOL_ID_FEATURE_RX_VLAN_FILTER, "rx-vlan-filter"), + ETHT_NAME (NM_ETHTOOL_ID_FEATURE_RX_VLAN_STAG_FILTER, "rx-vlan-stag-filter"), + ETHT_NAME (NM_ETHTOOL_ID_FEATURE_RX_VLAN_STAG_HW_PARSE, "rx-vlan-stag-hw-parse"), + ETHT_NAME (NM_ETHTOOL_ID_FEATURE_SG, "sg"), + ETHT_NAME (NM_ETHTOOL_ID_FEATURE_TLS_HW_RECORD, "tls-hw-record"), + ETHT_NAME (NM_ETHTOOL_ID_FEATURE_TLS_HW_TX_OFFLOAD, "tls-hw-tx-offload"), + ETHT_NAME (NM_ETHTOOL_ID_FEATURE_TSO, "tso"), + ETHT_NAME (NM_ETHTOOL_ID_FEATURE_TX, "tx"), + ETHT_NAME (NM_ETHTOOL_ID_FEATURE_TXVLAN, "txvlan"), + ETHT_NAME (NM_ETHTOOL_ID_FEATURE_TX_CHECKSUM_FCOE_CRC, "tx-checksum-fcoe-crc"), + ETHT_NAME (NM_ETHTOOL_ID_FEATURE_TX_CHECKSUM_IPV4, "tx-checksum-ipv4"), + ETHT_NAME (NM_ETHTOOL_ID_FEATURE_TX_CHECKSUM_IPV6, "tx-checksum-ipv6"), + ETHT_NAME (NM_ETHTOOL_ID_FEATURE_TX_CHECKSUM_IP_GENERIC, "tx-checksum-ip-generic"), + ETHT_NAME (NM_ETHTOOL_ID_FEATURE_TX_CHECKSUM_SCTP, "tx-checksum-sctp"), + ETHT_NAME (NM_ETHTOOL_ID_FEATURE_TX_ESP_SEGMENTATION, "tx-esp-segmentation"), + ETHT_NAME (NM_ETHTOOL_ID_FEATURE_TX_FCOE_SEGMENTATION, "tx-fcoe-segmentation"), + ETHT_NAME (NM_ETHTOOL_ID_FEATURE_TX_GRE_CSUM_SEGMENTATION, "tx-gre-csum-segmentation"), + ETHT_NAME (NM_ETHTOOL_ID_FEATURE_TX_GRE_SEGMENTATION, "tx-gre-segmentation"), + ETHT_NAME (NM_ETHTOOL_ID_FEATURE_TX_GSO_PARTIAL, "tx-gso-partial"), + ETHT_NAME (NM_ETHTOOL_ID_FEATURE_TX_GSO_ROBUST, "tx-gso-robust"), + ETHT_NAME (NM_ETHTOOL_ID_FEATURE_TX_IPXIP4_SEGMENTATION, "tx-ipxip4-segmentation"), + ETHT_NAME (NM_ETHTOOL_ID_FEATURE_TX_IPXIP6_SEGMENTATION, "tx-ipxip6-segmentation"), + ETHT_NAME (NM_ETHTOOL_ID_FEATURE_TX_NOCACHE_COPY, "tx-nocache-copy"), + ETHT_NAME (NM_ETHTOOL_ID_FEATURE_TX_SCATTER_GATHER, "tx-scatter-gather"), + ETHT_NAME (NM_ETHTOOL_ID_FEATURE_TX_SCATTER_GATHER_FRAGLIST, "tx-scatter-gather-fraglist"), + ETHT_NAME (NM_ETHTOOL_ID_FEATURE_TX_SCTP_SEGMENTATION, "tx-sctp-segmentation"), + ETHT_NAME (NM_ETHTOOL_ID_FEATURE_TX_TCP6_SEGMENTATION, "tx-tcp6-segmentation"), + ETHT_NAME (NM_ETHTOOL_ID_FEATURE_TX_TCP_ECN_SEGMENTATION, "tx-tcp-ecn-segmentation"), + ETHT_NAME (NM_ETHTOOL_ID_FEATURE_TX_TCP_MANGLEID_SEGMENTATION, "tx-tcp-mangleid-segmentation"), + ETHT_NAME (NM_ETHTOOL_ID_FEATURE_TX_TCP_SEGMENTATION, "tx-tcp-segmentation"), + ETHT_NAME (NM_ETHTOOL_ID_FEATURE_TX_UDP_SEGMENTATION, "tx-udp-segmentation"), + ETHT_NAME (NM_ETHTOOL_ID_FEATURE_TX_UDP_TNL_CSUM_SEGMENTATION, "tx-udp_tnl-csum-segmentation"), + ETHT_NAME (NM_ETHTOOL_ID_FEATURE_TX_UDP_TNL_SEGMENTATION, "tx-udp_tnl-segmentation"), + ETHT_NAME (NM_ETHTOOL_ID_FEATURE_TX_VLAN_STAG_HW_INSERT, "tx-vlan-stag-hw-insert"), +}; + +const NMEthtoolData * +nms_ifcfg_rh_utils_get_ethtool_by_name (const char *name) +{ + static const struct { + NMEthtoolID ethtool_id; + const char *kernel_name; + } kernel_names[] = { + { NM_ETHTOOL_ID_FEATURE_GRO, "rx-gro" }, + { NM_ETHTOOL_ID_FEATURE_GSO, "tx-generic-segmentation" }, + { NM_ETHTOOL_ID_FEATURE_LRO, "rx-lro" }, + { NM_ETHTOOL_ID_FEATURE_NTUPLE, "rx-ntuple-filter" }, + { NM_ETHTOOL_ID_FEATURE_RX, "rx-checksum" }, + { NM_ETHTOOL_ID_FEATURE_RXHASH, "rx-hashing" }, + { NM_ETHTOOL_ID_FEATURE_RXVLAN, "rx-vlan-hw-parse" }, + { NM_ETHTOOL_ID_FEATURE_TXVLAN, "tx-vlan-hw-insert" }, + }; + guint i; + + for (i = 0; i < G_N_ELEMENTS (_nm_ethtool_ifcfg_names); i++) { + if (nm_streq (name, _nm_ethtool_ifcfg_names[i])) + return nm_ethtool_data[i]; + } + + /* Option not found. Note that ethtool utility has built-in features and + * NetworkManager's API follows the naming of these built-in features, whenever + * they exist. + * For example, NM's "ethtool.feature-ntuple" corresponds to ethtool utility's "ntuple" + * feature. However the underlying kernel feature is called "rx-ntuple-filter" (as reported + * for ETH_SS_FEATURES). + * + * With ethtool utility, whose command line we attempt to parse here, the user can also + * specify the name of the underlying kernel feature directly. So, check whether that is + * the case and if yes, map them to the corresponding NetworkManager's features. */ + for (i = 0; i < G_N_ELEMENTS (kernel_names); i++) { + if (nm_streq (name, kernel_names[i].kernel_name)) + return nm_ethtool_data[kernel_names[i].ethtool_id]; + } + + return NULL; +} diff --git a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.h b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.h index 3756af7c..84c22094 100644 --- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.h +++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.h @@ -22,14 +22,15 @@ #define _UTILS_H_ #include "nm-connection.h" +#include "nm-ethtool-utils.h" #include "shvar.h" #define NM_IFCFG_CONNECTION_LOG_PATH(path) ((path) ?: "in-memory") #define NM_IFCFG_CONNECTION_LOG_FMT "%s (%s,\"%s\")" -#define NM_IFCFG_CONNECTION_LOG_ARG(con) NM_IFCFG_CONNECTION_LOG_PATH (nm_settings_connection_get_filename ((NMSettingsConnection *) (con))), nm_connection_get_uuid ((NMConnection *) (con)), nm_connection_get_id ((NMConnection *) (con)) +#define NM_IFCFG_CONNECTION_LOG_ARG(con) NM_IFCFG_CONNECTION_LOG_PATH (nm_settings_connection_get_filename ((NMSettingsConnection *) (con))), nm_settings_connection_get_uuid ((NMSettingsConnection *) (con)), nm_settings_connection_get_id ((NMSettingsConnection *) (con)) #define NM_IFCFG_CONNECTION_LOG_FMTD "%s (%s,\"%s\",%p)" -#define NM_IFCFG_CONNECTION_LOG_ARGD(con) NM_IFCFG_CONNECTION_LOG_PATH (nm_settings_connection_get_filename ((NMSettingsConnection *) (con))), nm_connection_get_uuid ((NMConnection *) (con)), nm_connection_get_id ((NMConnection *) (con)), (con) +#define NM_IFCFG_CONNECTION_LOG_ARGD(con) NM_IFCFG_CONNECTION_LOG_PATH (nm_settings_connection_get_filename ((NMSettingsConnection *) (con))), nm_settings_connection_get_uuid ((NMSettingsConnection *) (con)), nm_settings_connection_get_id ((NMSettingsConnection *) (con)), (con) char *utils_cert_path (const char *parent, const char *suffix, const char *extension); @@ -80,4 +81,20 @@ _nms_ifcfg_rh_utils_numbered_tag (char *buf, gsize buf_len, const char *tag_name _nms_ifcfg_rh_utils_numbered_tag (buf, sizeof (buf), ""tag_name"", (which)); \ }) +/*****************************************************************************/ + +extern const char *const _nm_ethtool_ifcfg_names[_NM_ETHTOOL_ID_FEATURE_NUM]; + +static inline const char * +nms_ifcfg_rh_utils_get_ethtool_name (NMEthtoolID ethtool_id) +{ + nm_assert (ethtool_id >= _NM_ETHTOOL_ID_FEATURE_FIRST && ethtool_id <= _NM_ETHTOOL_ID_FEATURE_LAST); + nm_assert ((ethtool_id - _NM_ETHTOOL_ID_FEATURE_FIRST) < G_N_ELEMENTS (_nm_ethtool_ifcfg_names)); + nm_assert (_nm_ethtool_ifcfg_names[ethtool_id - _NM_ETHTOOL_ID_FEATURE_FIRST]); + + return _nm_ethtool_ifcfg_names[ethtool_id - _NM_ETHTOOL_ID_FEATURE_FIRST]; +} + +const NMEthtoolData *nms_ifcfg_rh_utils_get_ethtool_by_name (const char *name); + #endif /* _UTILS_H_ */ diff --git a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c index fdb2e10a..b70690cc 100644 --- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c +++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c @@ -33,10 +33,12 @@ #include <stdio.h> #include "nm-utils/nm-enum-utils.h" +#include "nm-utils/nm-io-utils.h" #include "nm-manager.h" #include "nm-setting-connection.h" #include "nm-setting-wired.h" #include "nm-setting-wireless.h" +#include "nm-setting-ethtool.h" #include "nm-setting-8021x.h" #include "nm-setting-proxy.h" #include "nm-setting-ip4-config.h" @@ -50,6 +52,7 @@ #include "nm-core-internal.h" #include "NetworkManagerUtils.h" #include "nm-meta-setting.h" +#include "nm-ethtool-utils.h" #include "nms-ifcfg-rh-common.h" #include "nms-ifcfg-rh-reader.h" @@ -809,7 +812,7 @@ write_wireless_setting (NMConnection *connection, const char *device_mac, *cloned_mac; guint32 mtu, chan, i; gboolean adhoc = FALSE, hex_ssid = FALSE; - const char * const *macaddr_blacklist; + const char *const*macaddr_blacklist; s_wireless = nm_connection_get_setting_wireless (connection); if (!s_wireless) { @@ -1041,16 +1044,9 @@ static gboolean write_wired_setting (NMConnection *connection, shvarFile *ifcfg, GError **error) { NMSettingWired *s_wired; - const char *device_mac, *cloned_mac; - char *tmp; - const char *nettype, *portname, *ctcprot, *s390_key, *s390_val, *duplex; - guint32 mtu, num_opts, speed, i; - const char *const *s390_subchannels; - GString *str = NULL; - const char * const *macaddr_blacklist; - gboolean auto_negotiate; - NMSettingWiredWakeOnLan wol; - const char *wol_password; + const char *const*s390_subchannels; + guint32 mtu, num_opts, i; + const char *const*macaddr_blacklist; s_wired = nm_connection_get_setting_wired (connection); if (!s_wired) { @@ -1059,144 +1055,211 @@ write_wired_setting (NMConnection *connection, shvarFile *ifcfg, GError **error) return FALSE; } - device_mac = nm_setting_wired_get_mac_address (s_wired); - svSetValueStr (ifcfg, "HWADDR", device_mac); + svSetValueStr (ifcfg, "HWADDR", + nm_setting_wired_get_mac_address (s_wired)); - cloned_mac = nm_setting_wired_get_cloned_mac_address (s_wired); - svSetValueStr (ifcfg, "MACADDR", cloned_mac); + svSetValueStr (ifcfg, "MACADDR", + nm_setting_wired_get_cloned_mac_address (s_wired)); svSetValueStr (ifcfg, "GENERATE_MAC_ADDRESS_MASK", nm_setting_wired_get_generate_mac_address_mask (s_wired)); - svUnsetValue (ifcfg, "HWADDR_BLACKLIST"); macaddr_blacklist = nm_setting_wired_get_mac_address_blacklist (s_wired); if (macaddr_blacklist[0]) { - char *blacklist_str; + gs_free char *blacklist_str = NULL; blacklist_str = g_strjoinv (" ", (char **) macaddr_blacklist); svSetValueStr (ifcfg, "HWADDR_BLACKLIST", blacklist_str); - g_free (blacklist_str); - } + } else + svUnsetValue (ifcfg, "HWADDR_BLACKLIST"); mtu = nm_setting_wired_get_mtu (s_wired); svSetValueInt64_cond (ifcfg, "MTU", mtu != 0, mtu); - svUnsetValue (ifcfg, "SUBCHANNELS"); s390_subchannels = nm_setting_wired_get_s390_subchannels (s_wired); - if (s390_subchannels) { - int len = g_strv_length ((char **)s390_subchannels); - tmp = NULL; + { + gs_free char *tmp = NULL; + gsize len = NM_PTRARRAY_LEN (s390_subchannels); + if (len == 2) { - tmp = g_strdup_printf ("%s,%s", s390_subchannels[0], s390_subchannels[1]); + tmp = g_strdup_printf ("%s,%s", + s390_subchannels[0], + s390_subchannels[1]); } else if (len == 3) { - tmp = g_strdup_printf ("%s,%s,%s", s390_subchannels[0], s390_subchannels[1], + tmp = g_strdup_printf ("%s,%s,%s", + s390_subchannels[0], + s390_subchannels[1], s390_subchannels[2]); } + svSetValueStr (ifcfg, "SUBCHANNELS", tmp); - g_free (tmp); } - svUnsetValue (ifcfg, "NETTYPE"); - nettype = nm_setting_wired_get_s390_nettype (s_wired); - if (nettype) - svSetValueStr (ifcfg, "NETTYPE", nettype); + svSetValueStr (ifcfg, "NETTYPE", + nm_setting_wired_get_s390_nettype (s_wired)); - svUnsetValue (ifcfg, "PORTNAME"); - portname = nm_setting_wired_get_s390_option_by_key (s_wired, "portname"); - if (portname) - svSetValueStr (ifcfg, "PORTNAME", portname); + svSetValueStr (ifcfg, "PORTNAME", + nm_setting_wired_get_s390_option_by_key (s_wired, "portname")); - svUnsetValue (ifcfg, "CTCPROT"); - ctcprot = nm_setting_wired_get_s390_option_by_key (s_wired, "ctcprot"); - if (ctcprot) - svSetValueStr (ifcfg, "CTCPROT", ctcprot); + svSetValueStr (ifcfg, "CTCPROT", + nm_setting_wired_get_s390_option_by_key (s_wired, "ctcprot")); svUnsetValue (ifcfg, "OPTIONS"); num_opts = nm_setting_wired_get_num_s390_options (s_wired); if (s390_subchannels && num_opts) { - str = g_string_sized_new (30); + nm_auto_free_gstring GString *tmp = NULL; + for (i = 0; i < num_opts; i++) { + const char *s390_key, *s390_val; + nm_setting_wired_get_s390_option (s_wired, i, &s390_key, &s390_val); /* portname is handled separately */ if (!strcmp (s390_key, "portname") || !strcmp (s390_key, "ctcprot")) continue; - if (str->len) - g_string_append_c (str, ' '); - g_string_append_printf (str, "%s=%s", s390_key, s390_val); + if (!tmp) + tmp = g_string_sized_new (30); + else + g_string_append_c (tmp, ' '); + g_string_append_printf (tmp, "%s=%s", s390_key, s390_val); } - if (str->len) - svSetValueStr (ifcfg, "OPTIONS", str->str); - g_string_free (str, TRUE); + if (tmp) + svSetValueStr (ifcfg, "OPTIONS", tmp->str); } - /* Stuff ETHTOOL_OPT with required options */ - str = NULL; - auto_negotiate = nm_setting_wired_get_auto_negotiate (s_wired); - speed = nm_setting_wired_get_speed (s_wired); - duplex = nm_setting_wired_get_duplex (s_wired); + svSetValueStr (ifcfg, "TYPE", TYPE_ETHERNET); - /* autoneg off + speed 0 + duplex NULL, means we want NM - * to skip link configuration which is default. So write - * down link config only if we have auto-negotiate true or - * a valid value for one among speed and duplex. - */ - if (auto_negotiate) { - str = g_string_sized_new (64); - g_string_printf (str, "autoneg on"); - } else if (speed || duplex) { - str = g_string_sized_new (64); - g_string_printf (str, "autoneg off"); + return TRUE; +} + +static gboolean +write_ethtool_setting (NMConnection *connection, shvarFile *ifcfg, GError **error) +{ + NMSettingWired *s_wired; + NMSettingEthtool *s_ethtool; + const char *duplex; + guint32 speed; + GString *str = NULL; + gboolean auto_negotiate; + NMSettingWiredWakeOnLan wol; + const char *wol_password; + + s_wired = nm_connection_get_setting_wired (connection); + s_ethtool = NM_SETTING_ETHTOOL (nm_connection_get_setting (connection, NM_TYPE_SETTING_ETHTOOL)); + + if (!s_wired && !s_ethtool) { + svUnsetValue (ifcfg, "ETHTOOL_WAKE_ON_LAN"); + svUnsetValue (ifcfg, "ETHTOOL_OPTS"); + return TRUE; } - if (speed) - g_string_append_printf (str, " speed %u", speed); - if (duplex) - g_string_append_printf (str, " duplex %s", duplex); - wol = nm_setting_wired_get_wake_on_lan (s_wired); - wol_password = nm_setting_wired_get_wake_on_lan_password (s_wired); + if (s_wired) { + auto_negotiate = nm_setting_wired_get_auto_negotiate (s_wired); + speed = nm_setting_wired_get_speed (s_wired); + duplex = nm_setting_wired_get_duplex (s_wired); + + /* autoneg off + speed 0 + duplex NULL, means we want NM + * to skip link configuration which is default. So write + * down link config only if we have auto-negotiate true or + * a valid value for one among speed and duplex. + */ + if (auto_negotiate) { + str = g_string_sized_new (64); + g_string_printf (str, "autoneg on"); + } else if (speed || duplex) { + str = g_string_sized_new (64); + g_string_printf (str, "autoneg off"); + } + if (speed) + g_string_append_printf (str, " speed %u", speed); + if (duplex) + g_string_append_printf (str, " duplex %s", duplex); + + wol = nm_setting_wired_get_wake_on_lan (s_wired); + wol_password = nm_setting_wired_get_wake_on_lan_password (s_wired); + + svSetValue (ifcfg, "ETHTOOL_WAKE_ON_LAN", + wol == NM_SETTING_WIRED_WAKE_ON_LAN_IGNORE + ? "ignore" + : NULL); + if (!NM_IN_SET (wol, NM_SETTING_WIRED_WAKE_ON_LAN_IGNORE, + NM_SETTING_WIRED_WAKE_ON_LAN_DEFAULT)) { + if (!str) + str = g_string_sized_new (30); + else + g_string_append (str, " "); + + g_string_append (str, "wol "); + + if (NM_FLAGS_HAS (wol, NM_SETTING_WIRED_WAKE_ON_LAN_PHY)) + g_string_append (str, "p"); + if (NM_FLAGS_HAS (wol, NM_SETTING_WIRED_WAKE_ON_LAN_UNICAST)) + g_string_append (str, "u"); + if (NM_FLAGS_HAS (wol, NM_SETTING_WIRED_WAKE_ON_LAN_MULTICAST)) + g_string_append (str, "m"); + if (NM_FLAGS_HAS (wol, NM_SETTING_WIRED_WAKE_ON_LAN_BROADCAST)) + g_string_append (str, "b"); + if (NM_FLAGS_HAS (wol, NM_SETTING_WIRED_WAKE_ON_LAN_ARP)) + g_string_append (str, "a"); + if (NM_FLAGS_HAS (wol, NM_SETTING_WIRED_WAKE_ON_LAN_MAGIC)) + g_string_append (str, "g"); + + if (!NM_FLAGS_ANY (wol, NM_SETTING_WIRED_WAKE_ON_LAN_ALL)) + g_string_append (str, "d"); + + if (wol_password && NM_FLAGS_HAS (wol, NM_SETTING_WIRED_WAKE_ON_LAN_MAGIC)) + g_string_append_printf (str, "s sopass %s", wol_password); + } + } else + svUnsetValue (ifcfg, "ETHTOOL_WAKE_ON_LAN"); + + if (s_ethtool) { + NMEthtoolID ethtool_id; + NMSettingConnection *s_con; + const char *iface = NULL; + + s_con = nm_connection_get_setting_connection (connection); + if (s_con) { + iface = nm_setting_connection_get_interface_name (s_con); + if ( iface + && ( !iface[0] + || !NM_STRCHAR_ALL (iface, ch, (ch >= 'a' && ch <= 'z') + || (ch >= 'A' && ch <= 'Z') + || (ch >= '0' && ch <= '9') + || NM_IN_SET (ch, '_')))) + iface = NULL; + } - if (wol == NM_SETTING_WIRED_WAKE_ON_LAN_IGNORE) - svSetValue (ifcfg, "ETHTOOL_WAKE_ON_LAN", "ignore"); - else if (wol == NM_SETTING_WIRED_WAKE_ON_LAN_DEFAULT) { - if (!str) - svUnsetValue (ifcfg, "ETHTOOL_OPTS"); - } else { if (!str) str = g_string_sized_new (30); else - g_string_append (str, " "); + g_string_append (str, " ; "); + g_string_append (str, "-K "); + g_string_append (str, iface ?: "net0"); - g_string_append (str, "wol "); + for (ethtool_id = _NM_ETHTOOL_ID_FEATURE_FIRST; ethtool_id <= _NM_ETHTOOL_ID_FEATURE_LAST; ethtool_id++) { + const NMEthtoolData *ed = nm_ethtool_data[ethtool_id]; + NMTernary val; - if (NM_FLAGS_HAS (wol, NM_SETTING_WIRED_WAKE_ON_LAN_PHY)) - g_string_append (str, "p"); - if (NM_FLAGS_HAS (wol, NM_SETTING_WIRED_WAKE_ON_LAN_UNICAST)) - g_string_append (str, "u"); - if (NM_FLAGS_HAS (wol, NM_SETTING_WIRED_WAKE_ON_LAN_MULTICAST)) - g_string_append (str, "m"); - if (NM_FLAGS_HAS (wol, NM_SETTING_WIRED_WAKE_ON_LAN_BROADCAST)) - g_string_append (str, "b"); - if (NM_FLAGS_HAS (wol, NM_SETTING_WIRED_WAKE_ON_LAN_ARP)) - g_string_append (str, "a"); - if (NM_FLAGS_HAS (wol, NM_SETTING_WIRED_WAKE_ON_LAN_MAGIC)) - g_string_append (str, "g"); + nm_assert (nms_ifcfg_rh_utils_get_ethtool_name (ethtool_id)); - if (!NM_FLAGS_ANY (wol, NM_SETTING_WIRED_WAKE_ON_LAN_ALL)) - g_string_append (str, "d"); + val = nm_setting_ethtool_get_feature (s_ethtool, ed->optname); + if (val == NM_TERNARY_DEFAULT) + continue; - if (wol_password && NM_FLAGS_HAS (wol, NM_SETTING_WIRED_WAKE_ON_LAN_MAGIC)) - g_string_append_printf (str, "s sopass %s", wol_password); + g_string_append_c (str, ' '); + g_string_append (str, nms_ifcfg_rh_utils_get_ethtool_name (ethtool_id)); + g_string_append (str, val == NM_TERNARY_TRUE ? " on" : " off"); + } } + if (str) { svSetValueStr (ifcfg, "ETHTOOL_OPTS", str->str); g_string_free (str, TRUE); - } - /* End ETHTOOL_OPT stuffing */ - - svSetValueStr (ifcfg, "TYPE", TYPE_ETHERNET); + } else + svUnsetValue (ifcfg, "ETHTOOL_OPTS"); return TRUE; } @@ -1555,7 +1618,7 @@ static void write_dcb_app (shvarFile *ifcfg, const char *tag, NMSettingDcbFlags flags, - gint priority) + int priority) { char prop[NM_STRLEN ("DCB_xxxxxxxxxxxxxxxxxxxxxxx_yyyyyyyyyyyyyyyyyyyy")]; @@ -1725,8 +1788,9 @@ write_connection_setting (NMSettingConnection *s_con, shvarFile *ifcfg) guint32 n, i; GString *str; const char *master, *master_iface = NULL, *type; - gint vint; + int vint; NMSettingConnectionMdns mdns; + NMSettingConnectionLlmnr llmnr; guint32 vuint32; const char *tmp; @@ -1746,6 +1810,11 @@ write_connection_setting (NMSettingConnection *s_con, shvarFile *ifcfg) vint != -1, vint); + vint = nm_setting_connection_get_multi_connect (s_con); + svSetValueInt64_cond (ifcfg, "MULTI_CONNECT", + vint != NM_CONNECTION_MULTI_CONNECT_DEFAULT, + vint); + /* Only save the value for master connections */ type = nm_setting_connection_get_connection_type (s_con); if (_nm_connection_type_is_master (type)) { @@ -1892,6 +1961,13 @@ write_connection_setting (NMSettingConnection *s_con, shvarFile *ifcfg) mdns); } else svUnsetValue (ifcfg, "MDNS"); + + llmnr = nm_setting_connection_get_llmnr (s_con); + if (llmnr != NM_SETTING_CONNECTION_LLMNR_DEFAULT) { + svSetValueEnum (ifcfg, "LLMNR", nm_setting_connection_llmnr_get_type (), + llmnr); + } else + svUnsetValue (ifcfg, "LLMNR"); } static char * @@ -2135,6 +2211,45 @@ write_user_setting (NMConnection *connection, shvarFile *ifcfg, GError **error) return TRUE; } +static void +write_sriov_setting (NMConnection *connection, shvarFile *ifcfg) +{ + NMSettingSriov *s_sriov; + guint i, num = 0; + NMTernary b; + NMSriovVF *vf; + char key[32]; + char *str; + + svUnsetAll (ifcfg, SV_KEY_TYPE_SRIOV_VF); + + s_sriov = NM_SETTING_SRIOV (nm_connection_get_setting (connection, NM_TYPE_SETTING_SRIOV)); + if (s_sriov) + num = nm_setting_sriov_get_total_vfs (s_sriov); + if (num == 0) { + svUnsetValue (ifcfg, "SRIOV_TOTAL_VFS"); + svUnsetValue (ifcfg, "SRIOV_AUTOPROBE_DRIVERS"); + return; + } + + svSetValueInt64 (ifcfg, "SRIOV_TOTAL_VFS", num); + + b = nm_setting_sriov_get_autoprobe_drivers (s_sriov); + if (b != NM_TERNARY_DEFAULT) + svSetValueInt64 (ifcfg, "SRIOV_AUTOPROBE_DRIVERS", b); + else + svUnsetValue (ifcfg, "SRIOV_AUTOPROBE_DRIVERS"); + + num = nm_setting_sriov_get_num_vfs (s_sriov); + for (i = 0; i < num; i++) { + vf = nm_setting_sriov_get_vf (s_sriov, i); + nm_sprintf_buf (key, "SRIOV_VF%u", nm_sriov_vf_get_index (vf)); + str = nm_utils_sriov_vf_to_str (vf, TRUE, NULL); + svSetValueStr (ifcfg, key, str); + g_free (str); + } +} + static gboolean write_tc_setting (NMConnection *connection, shvarFile *ifcfg, GError **error) { @@ -2179,6 +2294,38 @@ write_tc_setting (NMConnection *connection, shvarFile *ifcfg, GError **error) return TRUE; } +static gboolean +write_match_setting (NMConnection *connection, shvarFile *ifcfg, GError **error) +{ + NMSettingMatch *s_match; + nm_auto_free_gstring GString *str = NULL; + guint i, num; + + svUnsetValue (ifcfg, "MATCH_INTERFACE_NAME"); + + s_match = (NMSettingMatch *) nm_connection_get_setting (connection, NM_TYPE_SETTING_MATCH); + if (!s_match) + return TRUE; + + num = nm_setting_match_get_num_interface_names (s_match); + for (i = 0; i < num; i++) { + gs_free char *to_free = NULL; + const char *name; + + if (i == 0) + str = g_string_new (""); + else + g_string_append_c (str, ' '); + name = nm_setting_match_get_interface_name (s_match, i); + g_string_append (str, _nm_utils_escape_spaces (name, &to_free)); + } + + if (str) + svSetValueStr (ifcfg, "MATCH_INTERFACE_NAME", str->str); + + return TRUE; +} + static void write_res_options (shvarFile *ifcfg, NMSettingIPConfig *s_ip, const char *var) { @@ -2212,11 +2359,11 @@ write_ip4_setting (NMConnection *connection, const char *value; char *tmp; char tag[64]; - gint j; + int j; guint i, num, n; gint64 route_metric; NMIPRouteTableSyncMode route_table; - gint priority; + int priority; int timeout; GString *searches; const char *method = NULL; @@ -2548,7 +2695,7 @@ write_ip6_setting (NMConnection *connection, NMSettingIPConfig *s_ip4; const char *value; guint i, num, num4; - gint priority; + int priority; NMIPAddress *addr; const char *dns; gint64 route_metric; @@ -2918,9 +3065,17 @@ do_write_construct (NMConnection *connection, if (!write_proxy_setting (connection, ifcfg, error)) return FALSE; + if (!write_ethtool_setting (connection, ifcfg, error)) + return FALSE; + if (!write_user_setting (connection, ifcfg, error)) return FALSE; + if (!write_match_setting (connection, ifcfg, error)) + return FALSE; + + write_sriov_setting (connection, ifcfg); + if (!write_tc_setting (connection, ifcfg, error)) return FALSE; diff --git a/src/settings/plugins/ifcfg-rh/shvar.c b/src/settings/plugins/ifcfg-rh/shvar.c index 9120b870..fe82fbdd 100644 --- a/src/settings/plugins/ifcfg-rh/shvar.c +++ b/src/settings/plugins/ifcfg-rh/shvar.c @@ -39,6 +39,7 @@ #include "nm-core-internal.h" #include "nm-core-utils.h" #include "nm-utils/nm-enum-utils.h" +#include "nm-utils/nm-io-utils.h" #include "c-list/src/c-list.h" /*****************************************************************************/ @@ -90,8 +91,8 @@ struct _shvarFile { * * Returns: the parsed boolean value or @fallback. */ -gint -svParseBoolean (const char *value, gint fallback) +int +svParseBoolean (const char *value, int fallback) { if (!value) return fallback; @@ -148,8 +149,8 @@ static char * _escape_ansic (const char *source) { const char *p; - gchar *dest; - gchar *q; + char *dest; + char *q; nm_assert (source); @@ -821,6 +822,7 @@ svOpenFileInternal (const char *name, gboolean create, GError **error) if (nm_utils_fd_get_contents (closefd ? nm_steal_fd (&fd) : fd, closefd, 10 * 1024 * 1024, + NM_UTILS_FILE_GET_CONTENTS_FLAG_NONE, &arena, NULL, &local) < 0) { @@ -870,8 +872,61 @@ svCreateFile (const char *name) /*****************************************************************************/ +static gboolean +_is_all_digits (const char *str) +{ + return str[0] + && NM_STRCHAR_ALL (str, ch, g_ascii_isdigit (ch)); +} + +#define IS_NUMBERED_TAG(key, tab_name) \ + ({ \ + const char *_key = (key); \ + \ + ( (strncmp (_key, tab_name, NM_STRLEN (tab_name)) == 0) \ + && _is_all_digits (&_key[NM_STRLEN (tab_name)])); \ + }) + +static gboolean +_svKeyMatchesType (const char *key, SvKeyType match_key_type) +{ + if (NM_FLAGS_HAS (match_key_type, SV_KEY_TYPE_ANY)) + return TRUE; + + if (NM_FLAGS_HAS (match_key_type, SV_KEY_TYPE_ROUTE_SVFORMAT)) { + if ( IS_NUMBERED_TAG (key, "ADDRESS") + || IS_NUMBERED_TAG (key, "NETMASK") + || IS_NUMBERED_TAG (key, "GATEWAY") + || IS_NUMBERED_TAG (key, "METRIC") + || IS_NUMBERED_TAG (key, "OPTIONS")) + return TRUE; + } + if (NM_FLAGS_HAS (match_key_type, SV_KEY_TYPE_IP4_ADDRESS)) { + if ( IS_NUMBERED_TAG (key, "IPADDR") + || IS_NUMBERED_TAG (key, "PREFIX") + || IS_NUMBERED_TAG (key, "NETMASK") + || IS_NUMBERED_TAG (key, "GATEWAY")) + return TRUE; + } + if (NM_FLAGS_HAS (match_key_type, SV_KEY_TYPE_USER)) { + if (g_str_has_prefix (key, "NM_USER_")) + return TRUE; + } + if (NM_FLAGS_HAS (match_key_type, SV_KEY_TYPE_TC)) { + if ( IS_NUMBERED_TAG (key, "QDISC") + || IS_NUMBERED_TAG (key, "FILTER")) + return TRUE; + } + if (NM_FLAGS_HAS (match_key_type, SV_KEY_TYPE_SRIOV_VF)) { + if (IS_NUMBERED_TAG (key, "SRIOV_VF")) + return TRUE; + } + + return FALSE; +} + GHashTable * -svGetKeys (shvarFile *s) +svGetKeys (shvarFile *s, SvKeyType match_key_type) { GHashTable *keys = NULL; CList *current; @@ -881,7 +936,9 @@ svGetKeys (shvarFile *s) c_list_for_each (current, &s->lst_head) { line = c_list_entry (current, shvarLine, lst); - if (line->key && line->line) { + if ( line->key + && line->line + && _svKeyMatchesType (line->key, match_key_type)) { /* we don't clone the keys. The keys are only valid * until @s gets modified. */ if (!keys) @@ -1044,8 +1101,8 @@ svGetValueStr_cp (shvarFile *s, const char *key) * * Returns: the parsed boolean value or @fallback. */ -gint -svGetValueBoolean (shvarFile *s, const char *key, gint fallback) +int +svGetValueBoolean (shvarFile *s, const char *key, int fallback) { gs_free char *to_free = NULL; const char *value; @@ -1120,21 +1177,6 @@ svGetValueEnum (shvarFile *s, const char *key, /*****************************************************************************/ -static gboolean -_is_all_digits (const char *str) -{ - return str[0] - && NM_STRCHAR_ALL (str, ch, g_ascii_isdigit (ch)); -} - -#define IS_NUMBERED_TAG(key, tab_name) \ - ({ \ - const char *_key = (key); \ - \ - ( (strncmp (_key, tab_name, NM_STRLEN (tab_name)) == 0) \ - && _is_all_digits (&_key[NM_STRLEN (tab_name)])); \ - }) - gboolean svUnsetAll (shvarFile *s, SvKeyType match_key_type) { @@ -1150,38 +1192,11 @@ svUnsetAll (shvarFile *s, SvKeyType match_key_type) if (!line->key) continue; - if (NM_FLAGS_HAS (match_key_type, SV_KEY_TYPE_ANY)) - goto do_clear; - if (NM_FLAGS_HAS (match_key_type, SV_KEY_TYPE_ROUTE_SVFORMAT)) { - if ( IS_NUMBERED_TAG (line->key, "ADDRESS") - || IS_NUMBERED_TAG (line->key, "NETMASK") - || IS_NUMBERED_TAG (line->key, "GATEWAY") - || IS_NUMBERED_TAG (line->key, "METRIC") - || IS_NUMBERED_TAG (line->key, "OPTIONS")) - goto do_clear; - } - if (NM_FLAGS_HAS (match_key_type, SV_KEY_TYPE_IP4_ADDRESS)) { - if ( IS_NUMBERED_TAG (line->key, "IPADDR") - || IS_NUMBERED_TAG (line->key, "PREFIX") - || IS_NUMBERED_TAG (line->key, "NETMASK") - || IS_NUMBERED_TAG (line->key, "GATEWAY")) - goto do_clear; - } - if (NM_FLAGS_HAS (match_key_type, SV_KEY_TYPE_USER)) { - if (g_str_has_prefix (line->key, "NM_USER_")) - goto do_clear; - } - if (NM_FLAGS_HAS (match_key_type, SV_KEY_TYPE_TC)) { - if ( IS_NUMBERED_TAG (line->key, "QDISC") - || IS_NUMBERED_TAG (line->key, "FILTER")) - goto do_clear; - } - - continue; -do_clear: - if (nm_clear_g_free (&line->line)) { - ASSERT_shvarLine (line); - changed = TRUE; + if (_svKeyMatchesType (line->key, match_key_type)) { + if (nm_clear_g_free (&line->line)) { + ASSERT_shvarLine (line); + changed = TRUE; + } } } diff --git a/src/settings/plugins/ifcfg-rh/shvar.h b/src/settings/plugins/ifcfg-rh/shvar.h index dbc4d950..622bb474 100644 --- a/src/settings/plugins/ifcfg-rh/shvar.h +++ b/src/settings/plugins/ifcfg-rh/shvar.h @@ -33,6 +33,15 @@ typedef struct _shvarFile shvarFile; +typedef enum { + SV_KEY_TYPE_ANY = (1LL << 0), + SV_KEY_TYPE_ROUTE_SVFORMAT = (1LL << 1), + SV_KEY_TYPE_IP4_ADDRESS = (1LL << 2), + SV_KEY_TYPE_TC = (1LL << 3), + SV_KEY_TYPE_USER = (1LL << 4), + SV_KEY_TYPE_SRIOV_VF = (1LL << 5), +} SvKeyType; + const char *svFileGetName (const shvarFile *s); void _nmtst_svFileSetName (shvarFile *s, const char *fileName); @@ -56,15 +65,15 @@ char *svGetValue_cp (shvarFile *s, const char *key); const char *svGetValueStr (shvarFile *s, const char *key, char **to_free); char *svGetValueStr_cp (shvarFile *s, const char *key); -gint svParseBoolean (const char *value, gint def); +int svParseBoolean (const char *value, int def); -GHashTable *svGetKeys (shvarFile *s); +GHashTable *svGetKeys (shvarFile *s, SvKeyType match_key_type); /* return TRUE if <key> resolves to any truth value (e.g. "yes", "y", "true") * return FALSE if <key> resolves to any non-truth value (e.g. "no", "n", "false") * return <def> otherwise */ -gint svGetValueBoolean (shvarFile *s, const char *key, gint def); +int svGetValueBoolean (shvarFile *s, const char *key, int def); gint64 svGetValueInt64 (shvarFile *s, const char *key, guint base, gint64 min, gint64 max, gint64 fallback); @@ -85,15 +94,6 @@ gboolean svSetValueInt64_cond (shvarFile *s, const char *key, gboolean do_set, g gboolean svSetValueEnum (shvarFile *s, const char *key, GType gtype, int value); gboolean svUnsetValue (shvarFile *s, const char *key); - -typedef enum { - SV_KEY_TYPE_ANY = (1LL << 0), - SV_KEY_TYPE_ROUTE_SVFORMAT = (1LL << 1), - SV_KEY_TYPE_IP4_ADDRESS = (1LL << 2), - SV_KEY_TYPE_TC = (1LL << 3), - SV_KEY_TYPE_USER = (1LL << 4), -} SvKeyType; - gboolean svUnsetAll (shvarFile *s, SvKeyType match_key_type); /* Write the current contents iff modified. Returns FALSE on error diff --git a/src/settings/plugins/ifcfg-rh/tests/meson.build b/src/settings/plugins/ifcfg-rh/tests/meson.build index 3d72d892..0593f12d 100644 --- a/src/settings/plugins/ifcfg-rh/tests/meson.build +++ b/src/settings/plugins/ifcfg-rh/tests/meson.build @@ -6,7 +6,6 @@ exe = executable( test_unit, test_unit + '.c', dependencies: test_nm_dep, - c_args: nm_build_cflags, link_with: libnms_ifcfg_rh_core ) diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wired_Auto-Negotiate.cexpected b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wired_Auto-Negotiate.cexpected index 8f421cfb..214f5da5 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wired_Auto-Negotiate.cexpected +++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wired_Auto-Negotiate.cexpected @@ -1,7 +1,7 @@ -ETHTOOL_OPTS="autoneg off speed 10 duplex half" TYPE=Ethernet PROXY_METHOD=none BROWSER_ONLY=no +ETHTOOL_OPTS="autoneg off speed 10 duplex half" BOOTPROTO=dhcp DEFROUTE=yes IPV4_FAILURE_FATAL=no diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wired_Wake-on-LAN.cexpected b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wired_Wake-on-LAN.cexpected index 398a3017..de66dcdd 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wired_Wake-on-LAN.cexpected +++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wired_Wake-on-LAN.cexpected @@ -1,7 +1,7 @@ -ETHTOOL_OPTS="wol umgs sopass 00:00:00:11:22:33" TYPE=Ethernet PROXY_METHOD=none BROWSER_ONLY=no +ETHTOOL_OPTS="wol umgs sopass 00:00:00:11:22:33" BOOTPROTO=dhcp DEFROUTE=yes IPV4_FAILURE_FATAL=no diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wired_match.cexpected b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wired_match.cexpected new file mode 100644 index 00000000..f0cd36cb --- /dev/null +++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wired_match.cexpected @@ -0,0 +1,11 @@ +TYPE=Ethernet +PROXY_METHOD=none +BROWSER_ONLY=no +MATCH_INTERFACE_NAME="ens* eth\\ 1? !veth*" +BOOTPROTO=dhcp +DEFROUTE=yes +IPV4_FAILURE_FATAL=no +IPV6INIT=no +NAME="Test Write Wired with Match setting" +UUID=${UUID} +ONBOOT=yes diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-sriov b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-sriov new file mode 100644 index 00000000..142f56e4 --- /dev/null +++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-sriov @@ -0,0 +1,19 @@ +TYPE=Ethernet +DEVICE=eth0 +HWADDR=00:11:22:33:44:55 +BOOTPROTO=none +ONBOOT=yes +DNS1=4.2.2.1 +DNS2=4.2.2.2 +IPADDR=192.168.1.5 +PREFIX=24 +NETMASK=255.255.255.0 +GATEWAY=192.168.1.1 +IPV6INIT=no +NAME=ethernet-sriov +UUID=acc703b8-e751-44ce-b456-1550bdf2057e +SRIOV_TOTAL_VFS=16 +SRIOV_AUTOPROBE_DRIVERS=0 +SRIOV_VF15="max-tx-rate=200 mac=01:23:45:67:89:ab vlans=2" +SRIOV_VF12="trust=false min-tx-rate=100 vlans=1.200.ad" +SRIOV_VF3="mac=55:44:33:22:11:00 spoof-check=true" diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-sriov-write.cexpected b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-sriov-write.cexpected new file mode 100644 index 00000000..c882c479 --- /dev/null +++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-sriov-write.cexpected @@ -0,0 +1,18 @@ +TYPE=Ethernet +PROXY_METHOD=none +BROWSER_ONLY=no +SRIOV_TOTAL_VFS=64 +SRIOV_AUTOPROBE_DRIVERS=1 +SRIOV_VF2="mac=55:55:55:55:55:55 vlans=3.10.ad;10" +SRIOV_VF19=spoof-check=true +BOOTPROTO=none +IPADDR=1.1.1.3 +PREFIX=24 +GATEWAY=1.1.1.1 +DEFROUTE=yes +IPV4_FAILURE_FATAL=no +IPV6INIT=no +NAME="Test Write SR-IOV config" +UUID=${UUID} +DEVICE=eth0 +ONBOOT=yes diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test_write_wired_auto_negotiate_on.cexpected b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test_write_wired_auto_negotiate_on.cexpected new file mode 100644 index 00000000..42608576 --- /dev/null +++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test_write_wired_auto_negotiate_on.cexpected @@ -0,0 +1,15 @@ +TYPE=Ethernet +PROXY_METHOD=none +BROWSER_ONLY=no +ETHTOOL_OPTS="autoneg on ; -K net0 rxvlan off tx on" +BOOTPROTO=dhcp +DEFROUTE=yes +IPV4_FAILURE_FATAL=no +IPV6INIT=yes +IPV6_AUTOCONF=yes +IPV6_DEFROUTE=yes +IPV6_FAILURE_FATAL=no +IPV6_ADDR_GEN_MODE=stable-privacy +NAME="Test Write Wired Auto-Negotiate" +UUID=${UUID} +ONBOOT=yes diff --git a/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c b/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c index 1331391d..472bb8a6 100644 --- a/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c +++ b/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c @@ -43,12 +43,14 @@ #include "nm-setting-pppoe.h" #include "nm-setting-ppp.h" #include "nm-setting-vpn.h" +#include "nm-setting-ethtool.h" #include "nm-setting-gsm.h" #include "nm-setting-cdma.h" #include "nm-setting-serial.h" #include "nm-setting-vlan.h" #include "nm-setting-dcb.h" #include "nm-core-internal.h" +#include "nm-ethtool-utils.h" #include "NetworkManagerUtils.h" @@ -185,7 +187,8 @@ _assert_expected_content (NMConnection *connection, const char *filename, const if ( len_expectd != len_written || memcmp (content_expectd, content_written, len_expectd) != 0) { - if (g_getenv ("NMTST_IFCFG_RH_UPDATE_EXPECTED")) { + if ( g_getenv ("NMTST_IFCFG_RH_UPDATE_EXPECTED") + || nm_streq0 (g_getenv ("NM_TEST_REGENERATE"), "1")) { if (uuid) { gs_free char *search = g_strdup_printf ("UUID=%s\n", uuid); const char *s; @@ -1898,10 +1901,8 @@ test_read_write_802_1X_subj_matches (void) gs_unref_object NMConnection *reread = NULL; NMSetting8021x *s_8021x; - NMTST_EXPECT_NM_WARN ("*missing IEEE_8021X_CA_CERT*peap*"); connection = _connection_from_file (TEST_IFCFG_DIR"/ifcfg-test-wired-802-1X-subj-matches", NULL, TYPE_ETHERNET, NULL); - g_test_assert_expected_messages (); /* ===== 802.1x SETTING ===== */ s_8021x = nm_connection_get_setting_802_1x (connection); @@ -1919,16 +1920,12 @@ test_read_write_802_1X_subj_matches (void) g_assert_cmpstr (nm_setting_802_1x_get_phase2_altsubject_match (s_8021x, 0), ==, "x.yourdomain.tld"); g_assert_cmpstr (nm_setting_802_1x_get_phase2_altsubject_match (s_8021x, 1), ==, "y.yourdomain.tld"); - NMTST_EXPECT_NM_WARN ("*missing IEEE_8021X_CA_CERT for EAP method 'peap'; this is insecure!"); _writer_new_connec_exp (connection, TEST_SCRATCH_DIR, TEST_IFCFG_DIR"/ifcfg-System_test-wired-802-1X-subj-matches.cexpected", &testfile); - g_test_assert_expected_messages (); - NMTST_EXPECT_NM_WARN ("*missing IEEE_8021X_CA_CERT for EAP method 'peap'; this is insecure!"); reread = _connection_from_file (testfile, NULL, TYPE_ETHERNET, NULL); - g_test_assert_expected_messages (); nmtst_assert_connection_equals (connection, TRUE, reread, FALSE); @@ -3117,8 +3114,7 @@ test_read_wifi_wpa_psk_hex (void) ssid = nm_setting_wireless_get_ssid (s_wireless); g_assert (ssid); - g_assert_cmpint (g_bytes_get_size (ssid), ==, strlen (expected_ssid)); - g_assert (memcmp (g_bytes_get_data (ssid, NULL), expected_ssid, strlen (expected_ssid)) == 0); + g_assert (nm_utils_gbytes_equal_mem (ssid, expected_ssid, strlen (expected_ssid))); /* ===== WIRELESS SECURITY SETTING ===== */ @@ -3725,6 +3721,7 @@ test_write_wired_auto_negotiate_on (void) gs_unref_object NMConnection *connection = NULL; gs_unref_object NMConnection *reread = NULL; NMSettingWired *s_wired; + NMSettingEthtool *s_ethtool; char *val; shvarFile *f; @@ -3734,8 +3731,14 @@ test_write_wired_auto_negotiate_on (void) NM_SETTING_WIRED_AUTO_NEGOTIATE, TRUE, NULL); - _writer_new_connection (connection, + s_ethtool = NM_SETTING_ETHTOOL (nm_setting_ethtool_new ()); + nm_setting_ethtool_set_feature (s_ethtool, NM_ETHTOOL_OPTNAME_FEATURE_TX, NM_TERNARY_TRUE); + nm_setting_ethtool_set_feature (s_ethtool, NM_ETHTOOL_OPTNAME_FEATURE_RXVLAN, NM_TERNARY_FALSE); + nm_connection_add_setting (connection, NM_SETTING (s_ethtool)); + + _writer_new_connec_exp (connection, TEST_SCRATCH_DIR, + TEST_IFCFG_DIR"/ifcfg-test_write_wired_auto_negotiate_on.cexpected", &testfile); f = _svOpenFile (testfile); @@ -3749,7 +3752,15 @@ test_write_wired_auto_negotiate_on (void) reread = _connection_from_file (testfile, NULL, TYPE_ETHERNET, NULL); + nmtst_assert_connection_verifies_without_normalization (reread); + nmtst_assert_connection_equals (connection, TRUE, reread, FALSE); + + s_ethtool = NM_SETTING_ETHTOOL (nm_connection_get_setting (reread, NM_TYPE_SETTING_ETHTOOL)); + g_assert (s_ethtool); + g_assert_cmpint (nm_setting_ethtool_get_feature (s_ethtool, NM_ETHTOOL_OPTNAME_FEATURE_TX), ==, NM_TERNARY_TRUE); + g_assert_cmpint (nm_setting_ethtool_get_feature (s_ethtool, NM_ETHTOOL_OPTNAME_FEATURE_RXVLAN), ==, NM_TERNARY_FALSE); + g_assert_cmpint (nm_setting_ethtool_get_feature (s_ethtool, NM_ETHTOOL_OPTNAME_FEATURE_TXVLAN), ==, NM_TERNARY_DEFAULT); } static void @@ -4417,6 +4428,67 @@ test_write_wired_dhcp (void) } static void +test_write_wired_match (void) +{ + nmtst_auto_unlinkfile char *testfile = NULL; + gs_unref_object NMConnection *connection = NULL; + gs_unref_object NMConnection *reread = NULL; + NMSettingConnection *s_con; + NMSettingWired *s_wired; + NMSettingMatch *s_match; + NMSettingIPConfig *s_ip4; + NMSettingIPConfig *s_ip6; + + connection = nm_simple_connection_new (); + + /* Connection setting */ + s_con = (NMSettingConnection *) nm_setting_connection_new (); + nm_connection_add_setting (connection, NM_SETTING (s_con)); + + g_object_set (s_con, + NM_SETTING_CONNECTION_ID, "Test Write Wired with Match setting", + NM_SETTING_CONNECTION_UUID, nm_utils_uuid_generate_a (), + NM_SETTING_CONNECTION_AUTOCONNECT, TRUE, + NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRED_SETTING_NAME, + NULL); + + /* Wired setting */ + s_wired = (NMSettingWired *) nm_setting_wired_new (); + nm_connection_add_setting (connection, NM_SETTING (s_wired)); + + /* IP4 setting */ + s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new (); + nm_connection_add_setting (connection, NM_SETTING (s_ip4)); + + g_object_set (s_ip4, + NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, + NULL); + + /* IP6 setting */ + s_ip6 = (NMSettingIPConfig *) nm_setting_ip6_config_new (); + nm_connection_add_setting (connection, NM_SETTING (s_ip6)); + + g_object_set (s_ip6, + NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_IGNORE, + NULL); + + /* Match setting */ + s_match = (NMSettingMatch *) nm_setting_match_new (); + nm_setting_match_add_interface_name (s_match, "ens*"); + nm_setting_match_add_interface_name (s_match, "eth 1?"); + nm_setting_match_add_interface_name (s_match, "!veth*"); + nm_connection_add_setting (connection, NM_SETTING (s_match)); + + nmtst_assert_connection_verifies (connection); + _writer_new_connec_exp (connection, + TEST_SCRATCH_DIR, + TEST_IFCFG_DIR"/ifcfg-Test_Write_Wired_match.cexpected", + &testfile); + reread = _connection_from_file (testfile, NULL, TYPE_ETHERNET, NULL); + nmtst_assert_connection_equals (connection, TRUE, reread, FALSE); +} + +static void test_write_wired_dhcp_plus_ip (void) { nmtst_auto_unlinkfile char *testfile = NULL; @@ -8982,7 +9054,7 @@ test_team_reread_slave (void) "id=142\n" "ingress-priority-map=\n" "parent=enp31s0f1\n" - , "/test_team_reread_slave", NULL); + , "/test_team_reread_slave"); /* to double-check keyfile syntax, re-create the connection by hand. */ connection_2 = nmtst_create_minimal_connection ("team-slave-enp31s0f1-142", "74f435bb-ede4-415a-9d48-f580b60eba04", NM_SETTING_VLAN_SETTING_NAME, &s_con); @@ -9632,6 +9704,153 @@ test_utils_ignore (void) do_test_utils_ignored ("ignored-augtmp", "ifcfg-FooBar" AUGTMP_TAG, TRUE); } +/*****************************************************************************/ + +static void +test_sriov_read (void) +{ + gs_unref_object NMConnection *connection = NULL; + NMSettingSriov *s_sriov; + NMSriovVF *vf; + GVariant *variant; + GError *error = NULL; + char *str; + + connection = _connection_from_file (TEST_IFCFG_DIR "/ifcfg-test-sriov", + NULL, TYPE_ETHERNET,NULL); + + g_assert_cmpstr (nm_connection_get_interface_name (connection), ==, "eth0"); + + s_sriov = NM_SETTING_SRIOV (nm_connection_get_setting (connection, NM_TYPE_SETTING_SRIOV)); + g_assert (s_sriov); + + g_assert_cmpint (nm_setting_sriov_get_total_vfs (s_sriov), ==, 16); + g_assert_cmpint (nm_setting_sriov_get_num_vfs (s_sriov), ==, 3); + g_assert_cmpint (nm_setting_sriov_get_autoprobe_drivers (s_sriov), ==, NM_TERNARY_FALSE); + + /* VF 3 */ + vf = nm_setting_sriov_get_vf (s_sriov, 0); + g_assert (vf); + g_assert_cmpint (nm_sriov_vf_get_index (vf), ==, 3); + + variant = nm_sriov_vf_get_attribute (vf, NM_SRIOV_VF_ATTRIBUTE_MAC); + g_assert (variant); + g_assert (g_variant_is_of_type (variant, G_VARIANT_TYPE_STRING)); + g_assert_cmpstr (g_variant_get_string (variant, NULL), ==, "55:44:33:22:11:00"); + + variant = nm_sriov_vf_get_attribute (vf, NM_SRIOV_VF_ATTRIBUTE_SPOOF_CHECK); + g_assert (variant); + g_assert (g_variant_is_of_type (variant, G_VARIANT_TYPE_BOOLEAN)); + g_assert_cmpint (g_variant_get_boolean (variant), ==, TRUE); + + /* VF 12 */ + vf = nm_setting_sriov_get_vf (s_sriov, 1); + str = nm_utils_sriov_vf_to_str (vf, FALSE, &error); + g_assert_no_error (error); + g_assert_cmpstr (str, ==, "12 min-tx-rate=100 trust=false vlans=1.200.ad"); + g_free (str); + + /* VF 15 */ + vf = nm_setting_sriov_get_vf (s_sriov, 2); + str = nm_utils_sriov_vf_to_str (vf, FALSE, &error); + g_assert_no_error (error); + g_assert_cmpstr (str, ==, "15 mac=01:23:45:67:89:ab max-tx-rate=200 vlans=2"); + g_free (str); +} + +static void +test_sriov_write (void) +{ + nmtst_auto_unlinkfile char *testfile = NULL; + gs_unref_object NMConnection *connection = NULL; + gs_unref_object NMConnection *reread = NULL; + NMSettingConnection *s_con; + NMSettingIPConfig *s_ip4; + NMSettingIPConfig *s_ip6; + NMSettingWired *s_wired; + NMSettingSriov *s_sriov; + NMSriovVF *vf; + gs_unref_ptrarray GPtrArray *vfs = NULL; + NMIPAddress *addr; + GError *error = NULL; + + connection = nm_simple_connection_new (); + + /* Connection setting */ + s_con = (NMSettingConnection *) nm_setting_connection_new (); + nm_connection_add_setting (connection, NM_SETTING (s_con)); + + g_object_set (s_con, + NM_SETTING_CONNECTION_ID, "Test Write SR-IOV config", + NM_SETTING_CONNECTION_UUID, nm_utils_uuid_generate_a (), + NM_SETTING_CONNECTION_AUTOCONNECT, TRUE, + NM_SETTING_CONNECTION_INTERFACE_NAME, "eth0", + NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRED_SETTING_NAME, + NULL); + + /* Wired setting */ + s_wired = (NMSettingWired *) nm_setting_wired_new (); + nm_connection_add_setting (connection, NM_SETTING (s_wired)); + + /* IP4 setting */ + s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new (); + nm_connection_add_setting (connection, NM_SETTING (s_ip4)); + + g_object_set (s_ip4, + NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_MANUAL, + NM_SETTING_IP_CONFIG_GATEWAY, "1.1.1.1", + NM_SETTING_IP_CONFIG_MAY_FAIL, TRUE, + NULL); + + addr = nm_ip_address_new (AF_INET, "1.1.1.3", 24, &error); + g_assert_no_error (error); + nm_setting_ip_config_add_address (s_ip4, addr); + nm_ip_address_unref (addr); + + /* IP6 setting */ + s_ip6 = (NMSettingIPConfig *) nm_setting_ip6_config_new (); + nm_connection_add_setting (connection, NM_SETTING (s_ip6)); + + g_object_set (s_ip6, + NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_IGNORE, + NULL); + + /* SRIOV setting */ + s_sriov = (NMSettingSriov *) nm_setting_sriov_new (); + nm_connection_add_setting (connection, NM_SETTING (s_sriov)); + + vfs = g_ptr_array_new_with_free_func ((GDestroyNotify) nm_sriov_vf_unref); + + vf = nm_utils_sriov_vf_from_str ("2 mac=55:55:55:55:55:55 vlans=3.10.ad;10", &error); + nmtst_assert_success (vf, error); + g_ptr_array_add (vfs, vf); + + vf = nm_utils_sriov_vf_from_str ("19 spoof-check=true", &error); + nmtst_assert_success (vf, error); + g_ptr_array_add (vfs, vf); + + g_object_set (s_sriov, + NM_SETTING_SRIOV_TOTAL_VFS, 64, + NM_SETTING_SRIOV_VFS, vfs, + NM_SETTING_SRIOV_AUTOPROBE_DRIVERS, NM_TERNARY_TRUE, + NULL); + + nm_connection_add_setting (connection, nm_setting_proxy_new ()); + + nmtst_assert_connection_verifies_without_normalization (connection); + + _writer_new_connec_exp (connection, + TEST_SCRATCH_DIR, + TEST_IFCFG_DIR "/ifcfg-test-sriov-write.cexpected", + &testfile); + + reread = _connection_from_file (testfile, NULL, TYPE_ETHERNET, NULL); + + nmtst_assert_connection_equals (connection, TRUE, reread, FALSE); +} + +/*****************************************************************************/ + static void test_tc_read (void) { @@ -9907,6 +10126,7 @@ int main (int argc, char **argv) g_test_add_func (TPATH "wired/write/dhcp", test_write_wired_dhcp); g_test_add_func (TPATH "wired/write-dhcp-plus-ip", test_write_wired_dhcp_plus_ip); g_test_add_func (TPATH "wired/write/dhcp-8021x-peap-mschapv2", test_write_wired_dhcp_8021x_peap_mschapv2); + g_test_add_func (TPATH "wired/write/match", test_write_wired_match); #define _add_test_write_wired_8021x_tls(testpath, scheme, flags) \ nmtst_add_test_func (testpath, test_write_wired_8021x_tls, GINT_TO_POINTER (scheme), GINT_TO_POINTER (flags)) @@ -10033,6 +10253,9 @@ int main (int argc, char **argv) g_test_add_func (TPATH "utils/path", test_utils_path); g_test_add_func (TPATH "utils/ignore", test_utils_ignore); + g_test_add_func (TPATH "sriov/read", test_sriov_read); + g_test_add_func (TPATH "sriov/write", test_sriov_write); + g_test_add_func (TPATH "tc/read", test_tc_read); g_test_add_func (TPATH "tc/write", test_tc_write); diff --git a/src/settings/plugins/ifupdown/meson.build b/src/settings/plugins/ifupdown/meson.build index fd028f4d..826c7458 100644 --- a/src/settings/plugins/ifupdown/meson.build +++ b/src/settings/plugins/ifupdown/meson.build @@ -8,13 +8,10 @@ deps = [ nm_dep ] -cflags = '-DSYSCONFDIR="@0@"'.format(nm_sysconfdir) - libnms_ifupdown_core = static_library( 'nms-ifupdown-core', sources: sources, dependencies: deps, - c_args: cflags ) sources = files( @@ -26,7 +23,6 @@ libnm_settings_plugin_ifupdown = shared_module( 'nm-settings-plugin-ifupdown', sources: sources, dependencies: deps, - c_args: cflags, link_with: libnms_ifupdown_core, link_args: ldflags_linker_script_settings, link_depends: linker_script_settings, diff --git a/src/settings/plugins/ifupdown/nms-ifupdown-connection.c b/src/settings/plugins/ifupdown/nms-ifupdown-connection.c index c3d231fe..1b817044 100644 --- a/src/settings/plugins/ifupdown/nms-ifupdown-connection.c +++ b/src/settings/plugins/ifupdown/nms-ifupdown-connection.c @@ -49,10 +49,20 @@ G_DEFINE_TYPE (NMIfupdownConnection, nm_ifupdown_connection, NM_TYPE_SETTINGS_CO /*****************************************************************************/ +#define _NMLOG_PREFIX_NAME "ifupdown" +#define _NMLOG_DOMAIN LOGD_SETTINGS +#define _NMLOG(level, ...) \ + nm_log ((level), _NMLOG_DOMAIN, NULL, NULL, \ + "%s" _NM_UTILS_MACRO_FIRST (__VA_ARGS__), \ + _NMLOG_PREFIX_NAME": " \ + _NM_UTILS_MACRO_REST (__VA_ARGS__)) + +/*****************************************************************************/ + static gboolean supports_secrets (NMSettingsConnection *connection, const char *setting_name) { - nm_log_info (LOGD_SETTINGS, "supports_secrets() for setting_name: '%s'", setting_name); + _LOGI ("supports_secrets() for setting_name: '%s'", setting_name); return (strcmp (setting_name, NM_SETTING_WIRELESS_SECURITY_SETTING_NAME) == 0); } @@ -64,26 +74,27 @@ nm_ifupdown_connection_init (NMIfupdownConnection *connection) { } -NMIfupdownConnection* +NMIfupdownConnection * nm_ifupdown_connection_new (if_block *block) { - GObject *object; + NMIfupdownConnection *connection; GError *error = NULL; g_return_val_if_fail (block != NULL, NULL); - object = g_object_new (NM_TYPE_IFUPDOWN_CONNECTION, NULL); + connection = g_object_new (NM_TYPE_IFUPDOWN_CONNECTION, NULL); - if (!ifupdown_update_connection_from_if_block (NM_CONNECTION (object), block, &error)) { - nm_log_warn (LOGD_SETTINGS, "%s.%d - invalid connection read from /etc/network/interfaces: %s", - __FILE__, - __LINE__, - error->message); - g_object_unref (object); + /* FIXME(copy-on-write-connection): avoid modifying NMConnection instances and share them via copy-on-write. */ + if (!ifupdown_update_connection_from_if_block (nm_settings_connection_get_connection (NM_SETTINGS_CONNECTION (connection)), + block, + &error)) { + _LOGW ("invalid connection read from /etc/network/interfaces: %s", + error->message); + g_object_unref (connection); return NULL; } - return (NMIfupdownConnection *) object; + return connection; } static void diff --git a/src/settings/plugins/ifupdown/nms-ifupdown-interface-parser.c b/src/settings/plugins/ifupdown/nms-ifupdown-interface-parser.c index 94a65ecb..73ecc2f9 100644 --- a/src/settings/plugins/ifupdown/nms-ifupdown-interface-parser.c +++ b/src/settings/plugins/ifupdown/nms-ifupdown-interface-parser.c @@ -32,78 +32,90 @@ #include "nm-utils.h" -if_block* first; -if_block* last; +/*****************************************************************************/ -if_data* last_data; +static void _ifparser_source (if_parser *parser, const char *path, const char *en_dir, int quiet, int dir); -void add_block(const char *type, const char* name) +/*****************************************************************************/ + +#define _NMLOG_PREFIX_NAME "ifupdown" +#define _NMLOG_DOMAIN LOGD_SETTINGS +#define _NMLOG(level, ...) \ + nm_log ((level), _NMLOG_DOMAIN, NULL, NULL, \ + "%s" _NM_UTILS_MACRO_FIRST (__VA_ARGS__), \ + _NMLOG_PREFIX_NAME": " \ + _NM_UTILS_MACRO_REST (__VA_ARGS__)) + +/*****************************************************************************/ + +static void +add_block (if_parser *parser, const char *type, const char* name) { - if_block *ret = g_slice_new0 (struct _if_block); - ret->name = g_strdup(name); - ret->type = g_strdup(type); - if (first == NULL) - first = last = ret; - else - { - last->next = ret; - last = ret; - } - last_data = NULL; + if_block *ifb; + gsize l_type, l_name; + + l_type = strlen (type) + 1; + l_name = strlen (name) + 1; + + ifb = g_malloc (sizeof (if_block) + l_type + l_name); + memcpy ((char *) ifb->name, name, l_name); + ifb->type = &ifb->name[l_name]; + memcpy ((char *) ifb->type, type, l_type); + c_list_init (&ifb->data_lst_head); + c_list_link_tail (&parser->block_lst_head, &ifb->block_lst); } -void add_data(const char *key,const char *data) +static void +add_data (if_parser *parser, const char *key, const char *data) { - if_data *ret; + if_block *last_block; + if_data *ifd; char *idx; + gsize l_key, l_data; + + last_block = c_list_last_entry (&parser->block_lst_head, if_block, block_lst); /* Check if there is a block where we can attach our data */ - if (first == NULL) + if (!last_block) return; - ret = g_slice_new0 (struct _if_data); - ret->key = g_strdup(key); + l_key = strlen (key) + 1; + l_data = strlen (data) + 1; + + ifd = g_malloc (sizeof (if_data) + l_key + l_data); + memcpy ((char *) ifd->key, key, l_key); + ifd->data = &ifd->key[l_key]; + memcpy ((char *) ifd->data, data, l_data); /* Normalize keys. Convert '_' to '-', as ifupdown accepts both variants. * When querying keys via ifparser_getkey(), use '-'. */ - while ((idx = strrchr(ret->key, '_'))) { - *idx = '-'; - } - ret->data = g_strdup(data); + idx = (char *) ifd->key; + while ((idx = strchr (idx, '_'))) + *(idx++) = '-'; - if (last->info == NULL) - { - last->info = ret; - last_data = ret; - } - else - { - last_data->next = ret; - last_data = last_data->next; - } + c_list_link_tail (&last_block->data_lst_head, &ifd->data_lst); } /* join values in src with spaces into dst; dst needs to be large enough */ -static char *join_values_with_spaces(char *dst, char **src) +static char * +join_values_with_spaces (char *dst, char **src) { if (dst != NULL) { *dst = '\0'; if (src != NULL && *src != NULL) { - strcat(dst, *src); + strcat (dst, *src); for (src++; *src != NULL; src++) { - strcat(dst, " "); - strcat(dst, *src); + strcat (dst, " "); + strcat (dst, *src); } } } - return(dst); + return (dst); } -static void _ifparser_source (const char *path, const char *en_dir, int quiet, int dir); - static void -_recursive_ifparser (const char *eni_file, int quiet) +_recursive_ifparser (if_parser *parser, const char *eni_file, int quiet) { FILE *inp; char line[255]; @@ -114,36 +126,35 @@ _recursive_ifparser (const char *eni_file, int quiet) /* Check if interfaces file exists and open it */ if (!g_file_test (eni_file, G_FILE_TEST_EXISTS)) { if (!quiet) - nm_log_warn (LOGD_SETTINGS, "interfaces file %s doesn't exist\n", eni_file); + _LOGW ("interfaces file %s doesn't exist", eni_file); return; } inp = fopen (eni_file, "re"); if (inp == NULL) { if (!quiet) - nm_log_warn (LOGD_SETTINGS, "Can't open %s\n", eni_file); + _LOGW ("Can't open %s", eni_file); return; } if (!quiet) - nm_log_info (LOGD_SETTINGS, " interface-parser: parsing file %s\n", eni_file); + _LOGI (" interface-parser: parsing file %s", eni_file); - while (!feof(inp)) - { + while (!feof (inp)) { char *token[128]; /* 255 chars can only be split into 127 tokens */ char value[255]; /* large enough to join previously split tokens */ char *safeptr; int toknum; int len = 0; - char *ptr = fgets(line+offs, 255-offs, inp); + char *ptr = fgets (line+offs, 255-offs, inp); if (ptr == NULL) break; - len = strlen(line); + len = strlen (line); /* skip over-long lines */ - if (!feof(inp) && len > 0 && line[len-1] != '\n') { + if (!feof (inp) && len > 0 && line[len-1] != '\n') { if (!skip_long_line) { if (!quiet) - nm_log_warn (LOGD_SETTINGS, "Skipping over-long-line '%s...'\n", line); + _LOGW ("Skipping over-long-line '%s...'", line); } skip_long_line = 1; continue; @@ -170,9 +181,9 @@ _recursive_ifparser (const char *eni_file, int quiet) #define SPACES " \t" /* tokenize input; */ - for (toknum = 0, token[toknum] = strtok_r(line, SPACES, &safeptr); + for (toknum = 0, token[toknum] = strtok_r (line, SPACES, &safeptr); token[toknum] != NULL; - toknum++, token[toknum] = strtok_r(NULL, SPACES, &safeptr)) + toknum++, token[toknum] = strtok_r (NULL, SPACES, &safeptr)) ; /* ignore comments and empty lines */ @@ -181,8 +192,8 @@ _recursive_ifparser (const char *eni_file, int quiet) if (toknum < 2) { if (!quiet) { - nm_log_warn (LOGD_SETTINGS, "Can't parse interface line '%s'\n", - join_values_with_spaces(value, token)); + _LOGW ("Can't parse interface line '%s'", + join_values_with_spaces (value, token)); } skip_to_block = 1; continue; @@ -193,71 +204,71 @@ _recursive_ifparser (const char *eni_file, int quiet) * Create a block for each of them except source and source-directory. */ /* iface stanza takes at least 3 parameters */ - if (strcmp(token[0], "iface") == 0) { + if (nm_streq (token[0], "iface")) { if (toknum < 4) { if (!quiet) { - nm_log_warn (LOGD_SETTINGS, "Can't parse iface line '%s'\n", - join_values_with_spaces(value, token)); + _LOGW ("Can't parse iface line '%s'", + join_values_with_spaces (value, token)); } continue; } - add_block(token[0], token[1]); + add_block (parser, token[0], token[1]); skip_to_block = 0; - add_data(token[2], join_values_with_spaces(value, token + 3)); + add_data (parser, token[2], join_values_with_spaces (value, token + 3)); } /* auto and allow-auto stanzas are equivalent, * both can take multiple interfaces as parameters: add one block for each */ - else if (strcmp(token[0], "auto") == 0 || - strcmp(token[0], "allow-auto") == 0) { + else if (NM_IN_STRSET (token[0], "auto", "allow-auto")) { int i; + for (i = 1; i < toknum; i++) - add_block("auto", token[i]); + add_block (parser, "auto", token[i]); skip_to_block = 0; } - else if (strcmp(token[0], "mapping") == 0) { - add_block(token[0], join_values_with_spaces(value, token + 1)); + else if (nm_streq (token[0], "mapping")) { + add_block (parser, token[0], join_values_with_spaces (value, token + 1)); skip_to_block = 0; } /* allow-* can take multiple interfaces as parameters: add one block for each */ - else if (strncmp(token[0],"allow-",6) == 0) { + else if (g_str_has_prefix (token[0], "allow-")) { int i; for (i = 1; i < toknum; i++) - add_block(token[0], token[i]); + add_block (parser, token[0], token[i]); skip_to_block = 0; } /* source and source-directory stanzas take one or more paths as parameters */ - else if (strcmp (token[0], "source") == 0 || strcmp (token[0], "source-directory") == 0) { + else if (NM_IN_STRSET (token[0], "source", "source-directory")) { int i; char *en_dir; skip_to_block = 0; en_dir = g_path_get_dirname (eni_file); for (i = 1; i < toknum; ++i) { - if (strcmp (token[0], "source-directory") == 0) - _ifparser_source (token[i], en_dir, quiet, TRUE); + if (nm_streq (token[0], "source-directory")) + _ifparser_source (parser, token[i], en_dir, quiet, TRUE); else - _ifparser_source (token[i], en_dir, quiet, FALSE); + _ifparser_source (parser, token[i], en_dir, quiet, FALSE); } g_free (en_dir); } else { if (skip_to_block) { if (!quiet) { - nm_log_warn (LOGD_SETTINGS, "ignoring out-of-block data '%s'\n", - join_values_with_spaces(value, token)); + _LOGW ("ignoring out-of-block data '%s'", + join_values_with_spaces (value, token)); } } else - add_data(token[0], join_values_with_spaces(value, token + 1)); + add_data (parser, token[0], join_values_with_spaces (value, token + 1)); } } - fclose(inp); + fclose (inp); if (!quiet) - nm_log_info (LOGD_SETTINGS, " interface-parser: finished parsing file %s\n", eni_file); + _LOGI (" interface-parser: finished parsing file %s", eni_file); } static void -_ifparser_source (const char *path, const char *en_dir, int quiet, int dir) +_ifparser_source (if_parser *parser, const char *path, const char *en_dir, int quiet, int dir) { char *abs_path; const char *item; @@ -272,132 +283,128 @@ _ifparser_source (const char *path, const char *en_dir, int quiet, int dir) abs_path = g_build_filename (en_dir, path, NULL); if (!quiet) - nm_log_info (LOGD_SETTINGS, " interface-parser: source line includes interfaces file(s) %s\n", abs_path); + _LOGI (" interface-parser: source line includes interfaces file(s) %s", abs_path); /* ifupdown uses WRDE_NOCMD for wordexp. */ if (wordexp (abs_path, &we, WRDE_NOCMD)) { if (!quiet) - nm_log_warn (LOGD_SETTINGS, "word expansion for %s failed\n", abs_path); + _LOGW ("word expansion for %s failed", abs_path); } else { for (i = 0; i < we.we_wordc; i++) { if (dir) { source_dir = g_dir_open (we.we_wordv[i], 0, &error); if (!source_dir) { if (!quiet) { - nm_log_warn (LOGD_SETTINGS, "Failed to open directory %s: %s", - we.we_wordv[i], error->message); + _LOGW ("Failed to open directory %s: %s", + we.we_wordv[i], error->message); } g_clear_error (&error); } else { while ((item = g_dir_read_name (source_dir))) - _ifparser_source (item, we.we_wordv[i], quiet, FALSE); + _ifparser_source (parser, item, we.we_wordv[i], quiet, FALSE); g_dir_close (source_dir); } } else - _recursive_ifparser (we.we_wordv[i], quiet); + _recursive_ifparser (parser, we.we_wordv[i], quiet); } wordfree (&we); } g_free (abs_path); } -void ifparser_init (const char *eni_file, int quiet) +if_parser * +ifparser_parse (const char *eni_file, int quiet) { - first = last = NULL; - _recursive_ifparser (eni_file, quiet); + if_parser *parser; + + parser = g_slice_new (if_parser); + c_list_init (&parser->block_lst_head); + _recursive_ifparser (parser, eni_file, quiet); + return parser; } -void _destroy_data(if_data *ifd) +static void +_destroy_data (if_data *ifd) { - if (ifd == NULL) - return; - _destroy_data(ifd->next); - g_free(ifd->key); - g_free(ifd->data); - g_slice_free(struct _if_data, ifd); - return; + c_list_unlink_stale (&ifd->data_lst); + g_free (ifd); } -void _destroy_block(if_block* ifb) +static void +_destroy_block (if_block* ifb) { - if (ifb == NULL) - return; - _destroy_block(ifb->next); - _destroy_data(ifb->info); - g_free(ifb->name); - g_free(ifb->type); - g_slice_free(struct _if_block, ifb); - return; + if_data *ifd; + + while ((ifd = c_list_first_entry (&ifb->data_lst_head, if_data, data_lst))) + _destroy_data (ifd); + c_list_unlink_stale (&ifb->block_lst); + g_free (ifb); } -void ifparser_destroy(void) +void +ifparser_destroy (if_parser *parser) { - _destroy_block(first); - first = last = NULL; + if_block *ifb; + + while ((ifb = c_list_first_entry (&parser->block_lst_head, if_block, block_lst))) + _destroy_block (ifb); + g_slice_free (if_parser, parser); } -if_block *ifparser_getfirst(void) +if_block * +ifparser_getfirst (if_parser *parser) { - return first; + return c_list_first_entry (&parser->block_lst_head, if_block, block_lst); } -int ifparser_get_num_blocks(void) +guint +ifparser_get_num_blocks (if_parser *parser) { - int i = 0; - if_block *iter = first; - - while (iter) { - i++; - iter = iter->next; - } - return i; + return c_list_length (&parser->block_lst_head); } -if_block *ifparser_getif(const char* iface) +if_block * +ifparser_getif (if_parser *parser, const char* iface) { - if_block *curr = first; - while(curr!=NULL) - { - if (strcmp(curr->type,"iface")==0 && strcmp(curr->name,iface)==0) - return curr; - curr = curr->next; + if_block *ifb; + + c_list_for_each_entry (ifb, &parser->block_lst_head, block_lst) { + if ( nm_streq (ifb->type, "iface") + && nm_streq (ifb->name, iface)) + return ifb; } return NULL; } -const char *ifparser_getkey(if_block* iface, const char *key) +static if_data * +ifparser_findkey (if_block* iface, const char *key) { - if_data *curr = iface->info; - while(curr!=NULL) - { - if (strcmp(curr->key,key)==0) - return curr->data; - curr = curr->next; + if_data *ifd; + + c_list_for_each_entry (ifd, &iface->data_lst_head, data_lst) { + if (nm_streq (ifd->key, key)) + return ifd; } return NULL; } -gboolean -ifparser_haskey(if_block* iface, const char *key) +const char * +ifparser_getkey (if_block* iface, const char *key) { - if_data *curr = iface->info; + if_data *ifd; - while (curr != NULL) { - if (strcmp (curr->key, key) == 0) - return TRUE; - curr = curr->next; - } - return FALSE; + ifd = ifparser_findkey (iface, key); + return ifd ? ifd->data : NULL; } -int ifparser_get_num_info(if_block* iface) +gboolean +ifparser_haskey (if_block* iface, const char *key) { - int i = 0; - if_data *iter = iface->info; + return !!ifparser_findkey (iface, key); +} - while (iter) { - i++; - iter = iter->next; - } - return i; +guint +ifparser_get_num_info (if_block* iface) +{ + return c_list_length (&iface->data_lst_head); } diff --git a/src/settings/plugins/ifupdown/nms-ifupdown-interface-parser.h b/src/settings/plugins/ifupdown/nms-ifupdown-interface-parser.h index 7e6c8e34..f367f626 100644 --- a/src/settings/plugins/ifupdown/nms-ifupdown-interface-parser.h +++ b/src/settings/plugins/ifupdown/nms-ifupdown-interface-parser.h @@ -23,33 +23,37 @@ #ifndef _INTERFACE_PARSER_H #define _INTERFACE_PARSER_H -typedef struct _if_data -{ - char *key; - char *data; - struct _if_data *next; +#include "c-list/src/c-list.h" + +typedef struct { + CList data_lst; + const char *data; + const char key[]; } if_data; -typedef struct _if_block -{ - char *type; - char *name; - if_data *info; - struct _if_block *next; +typedef struct { + CList block_lst; + CList data_lst_head; + const char *type; + const char name[]; } if_block; -void ifparser_init(const char *eni_file, int quiet); -void ifparser_destroy(void); +typedef struct { + CList block_lst_head; +} if_parser; + +if_parser *ifparser_parse (const char *eni_file, int quiet); + +void ifparser_destroy (if_parser *parser); +NM_AUTO_DEFINE_FCN0 (if_parser *, _nm_auto_ifparser, ifparser_destroy); +#define nm_auto_ifparser nm_auto(_nm_auto_ifparser) + +if_block *ifparser_getif (if_parser *parser, const char* iface); +if_block *ifparser_getfirst (if_parser *parser); +const char *ifparser_getkey (if_block* iface, const char *key); +gboolean ifparser_haskey (if_block* iface, const char *key); -if_block *ifparser_getif(const char* iface); -if_block *ifparser_getfirst(void); -const char *ifparser_getkey(if_block* iface, const char *key); -gboolean ifparser_haskey(if_block* iface, const char *key); -int ifparser_get_num_blocks(void); -int ifparser_get_num_info(if_block* iface); +guint ifparser_get_num_blocks (if_parser *parser); +guint ifparser_get_num_info (if_block* iface); -void add_block(const char *type, const char* name); -void add_data(const char *key,const char *data); -void _destroy_data(if_data *ifd); -void _destroy_block(if_block* ifb); #endif diff --git a/src/settings/plugins/ifupdown/nms-ifupdown-parser.c b/src/settings/plugins/ifupdown/nms-ifupdown-parser.c index 884c6591..369fa70d 100644 --- a/src/settings/plugins/ifupdown/nms-ifupdown-parser.c +++ b/src/settings/plugins/ifupdown/nms-ifupdown-parser.c @@ -37,42 +37,64 @@ #include "nms-ifupdown-plugin.h" #include "nms-ifupdown-parser.h" -static const gchar* +/*****************************************************************************/ + +#define _NMLOG_PREFIX_NAME "ifupdown" +#define _NMLOG_DOMAIN LOGD_SETTINGS +#define _NMLOG(level, ...) \ + nm_log ((level), _NMLOG_DOMAIN, NULL, NULL, \ + "%s" _NM_UTILS_MACRO_FIRST (__VA_ARGS__), \ + _NMLOG_PREFIX_NAME": " \ + _NM_UTILS_MACRO_REST (__VA_ARGS__)) + +/*****************************************************************************/ + +#define _str_has_prefix(val, prefix, require_suffix) \ + ({ \ + const char *_val = (val); \ + \ + (strncmp (_val, ""prefix"", NM_STRLEN (prefix)) == 0) \ + && ( !(require_suffix) \ + || _val[NM_STRLEN (prefix)] != '\0'); \ + }) + +static const char* _ifupdownplugin_guess_connection_type (if_block *block) { - if_data *curr = block->info; - const gchar* ret_type = NULL; - const gchar* value = ifparser_getkey(block, "inet"); - if(value && !strcmp("ppp", value)) { - ret_type = NM_SETTING_PPP_SETTING_NAME; - } + const char *ret_type = NULL; - while(!ret_type && curr) { - if(!strncmp("wireless-", curr->key, strlen("wireless-")) || - !strncmp("wpa-", curr->key, strlen("wpa-"))) { - ret_type = NM_SETTING_WIRELESS_SETTING_NAME; + if(nm_streq0 (ifparser_getkey (block, "inet"), "ppp")) + ret_type = NM_SETTING_PPP_SETTING_NAME; + else { + if_data *ifb; + + c_list_for_each_entry (ifb, &block->data_lst_head, data_lst) { + if ( _str_has_prefix (ifb->key, "wireless-", FALSE) + || _str_has_prefix (ifb->key, "wpa-", FALSE)) { + ret_type = NM_SETTING_WIRELESS_SETTING_NAME; + break; + } } - curr = curr->next; + if(!ret_type) + ret_type = NM_SETTING_WIRED_SETTING_NAME; } - if(!ret_type) - ret_type = NM_SETTING_WIRED_SETTING_NAME; - - nm_log_info (LOGD_SETTINGS, "guessed connection type (%s) = %s", block->name, ret_type); + _LOGI ("guessed connection type (%s) = %s", block->name, ret_type); return ret_type; } struct _Mapping { - const gchar *domain; + const char *domain; const gpointer target; }; static gpointer -map_by_mapping(struct _Mapping *mapping, const gchar *key) +map_by_mapping (struct _Mapping *mapping, const char *key) { struct _Mapping *curr = mapping; - while(curr->domain) { - if(!strcmp(curr->domain, key)) + + while (curr->domain) { + if (nm_streq (curr->domain, key)) return curr->target; curr++; } @@ -80,14 +102,11 @@ map_by_mapping(struct _Mapping *mapping, const gchar *key) } static void -update_wireless_setting_from_if_block(NMConnection *connection, - if_block *block) +update_wireless_setting_from_if_block (NMConnection *connection, + if_block *block) { - gint wpa_l= strlen("wpa-"); - gint wireless_l= strlen("wireless-"); - - if_data *curr = block->info; - const gchar* value = ifparser_getkey (block, "inet"); + if_data *curr; + const char *value = ifparser_getkey (block, "inet"); struct _Mapping mapping[] = { {"ssid", "ssid"}, {"essid", "ssid"}, @@ -97,27 +116,26 @@ update_wireless_setting_from_if_block(NMConnection *connection, NMSettingWireless *wireless_setting = NULL; - if(value && !strcmp("ppp", value)) { + if (nm_streq0 (value, "ppp")) return; - } - nm_log_info (LOGD_SETTINGS, "update wireless settings (%s).", block->name); - wireless_setting = NM_SETTING_WIRELESS(nm_setting_wireless_new()); + _LOGI ("update wireless settings (%s).", block->name); + wireless_setting = NM_SETTING_WIRELESS (nm_setting_wireless_new ()); + + c_list_for_each_entry (curr, &block->data_lst_head, data_lst) { + if (_str_has_prefix (curr->key, "wireless-", TRUE)) { + const char* newkey = map_by_mapping (mapping, curr->key + NM_STRLEN ("wireless-")); - while(curr) { - if(strlen(curr->key) > wireless_l && - !strncmp("wireless-", curr->key, wireless_l)) { - const gchar* newkey = map_by_mapping(mapping, curr->key+wireless_l); - nm_log_info (LOGD_SETTINGS, "wireless setting key: %s='%s'", newkey, curr->data); - if(newkey && !strcmp("ssid", newkey)) { + _LOGI ("wireless setting key: %s='%s'", newkey, curr->data); + if (nm_streq0 (newkey, "ssid")) { GBytes *ssid; - gint len = strlen(curr->data); + int len = strlen (curr->data); ssid = g_bytes_new (curr->data, len); g_object_set (wireless_setting, NM_SETTING_WIRELESS_SSID, ssid, NULL); g_bytes_unref (ssid); - nm_log_info (LOGD_SETTINGS, "setting wireless ssid = %d", len); - } else if(newkey && !strcmp("mode", newkey)) { + _LOGI ("setting wireless ssid = %d", len); + } else if (nm_streq0 (newkey, "mode")) { if (!g_ascii_strcasecmp (curr->data, "Managed") || !g_ascii_strcasecmp (curr->data, "Auto")) g_object_set (wireless_setting, NM_SETTING_WIRELESS_MODE, NM_SETTING_WIRELESS_MODE_INFRA, NULL); else if (!g_ascii_strcasecmp (curr->data, "Ad-Hoc")) @@ -125,39 +143,37 @@ update_wireless_setting_from_if_block(NMConnection *connection, else if (!g_ascii_strcasecmp (curr->data, "Master")) g_object_set (wireless_setting, NM_SETTING_WIRELESS_MODE, NM_SETTING_WIRELESS_MODE_AP, NULL); else - nm_log_warn (LOGD_SETTINGS, "Invalid mode '%s' (not 'Ad-Hoc', 'Ap', 'Managed', or 'Auto')", curr->data); + _LOGW ("Invalid mode '%s' (not 'Ad-Hoc', 'Ap', 'Managed', or 'Auto')", curr->data); } else { - g_object_set(wireless_setting, - newkey, curr->data, - NULL); + g_object_set (wireless_setting, + newkey, curr->data, + NULL); } - } else if(strlen(curr->key) > wpa_l && - !strncmp("wpa-", curr->key, wpa_l)) { - const gchar* newkey = map_by_mapping(mapping, curr->key+wpa_l); + } else if (_str_has_prefix (curr->key, "wpa-", TRUE)) { + const char* newkey = map_by_mapping (mapping, curr->key + NM_STRLEN ("wpa-")); - if(newkey && !strcmp("ssid", newkey)) { + if (nm_streq0 (newkey, "ssid")) { GBytes *ssid; - gint len = strlen(curr->data); + int len = strlen (curr->data); ssid = g_bytes_new (curr->data, len); g_object_set (wireless_setting, NM_SETTING_WIRELESS_SSID, ssid, NULL); g_bytes_unref (ssid); - nm_log_info (LOGD_SETTINGS, "setting wpa ssid = %d", len); - } else if(newkey) { + _LOGI ("setting wpa ssid = %d", len); + } else if (newkey) { - g_object_set(wireless_setting, - newkey, curr->data, - NULL); - nm_log_info (LOGD_SETTINGS, "setting wpa newkey(%s)=data(%s)", newkey, curr->data); + g_object_set (wireless_setting, + newkey, curr->data, + NULL); + _LOGI ("setting wpa newkey(%s)=data(%s)", newkey, curr->data); } } - curr = curr->next; } - nm_connection_add_setting(connection, (NMSetting*) wireless_setting); + nm_connection_add_setting (connection, (NMSetting*) wireless_setting); } -typedef gchar* (*IfupdownStrDupeFunc) (gpointer value, gpointer data); -typedef gpointer (*IfupdownStrToTypeFunc) (const gchar* value); +typedef char* (*IfupdownStrDupeFunc) (gconstpointer value, gpointer data); +typedef gpointer (*IfupdownStrToTypeFunc) (const char* value); static char* normalize_dupe_wireless_key (gpointer value, gpointer data) { @@ -177,7 +193,7 @@ normalize_dupe_wireless_key (gpointer value, gpointer data) { result_cur += next - delim; delim = next + 1; } - if (*delim && strlen (valuec) > GPOINTER_TO_UINT(delim - valuec)) { + if (*delim && strlen (valuec) > GPOINTER_TO_UINT (delim - valuec)) { strncpy (result_cur, delim, endc - delim); result_cur += endc - delim; } @@ -187,12 +203,12 @@ normalize_dupe_wireless_key (gpointer value, gpointer data) { static char* normalize_dupe (gpointer value, gpointer data) { - return g_strdup(value); + return g_strdup (value); } static char* normalize_tolower (gpointer value, gpointer data) { - return g_ascii_strdown(value, -1); + return g_ascii_strdown (value, -1); } static char *normalize_psk (gpointer value, gpointer data) @@ -203,25 +219,25 @@ static char *normalize_psk (gpointer value, gpointer data) } static gpointer -string_to_gpointerint(const gchar* data) +string_to_gpointerint (const char* data) { - gint result = (gint) strtol (data, NULL, 10); - return GINT_TO_POINTER(result); + int result = (int) strtol (data, NULL, 10); + return GINT_TO_POINTER (result); } static gpointer -string_to_glist_of_strings(const gchar* data) +string_to_glist_of_strings (const char* data) { GSList *ret = NULL; - gchar *string = (gchar*) data; - while(string) { - gchar* next = NULL; - if( (next = strchr(string, ' ')) || - (next = strchr(string, '\t')) || - (next = strchr(string, '\0')) ) { - - gchar *part = g_strndup(string, (next - string)); - ret = g_slist_append(ret, part); + char *string = (char*) data; + while (string) { + char* next = NULL; + if ( (next = strchr (string, ' ')) || + (next = strchr (string, '\t')) || + (next = strchr (string, '\0')) ) { + + char *part = g_strndup (string, (next - string)); + ret = g_slist_append (ret, part); if (*next) string = next+1; else @@ -234,19 +250,17 @@ string_to_glist_of_strings(const gchar* data) } static void -slist_free_all(gpointer slist) +slist_free_all (gpointer slist) { g_slist_free_full ((GSList *) slist, g_free); } static void -update_wireless_security_setting_from_if_block(NMConnection *connection, - if_block *block) +update_wireless_security_setting_from_if_block (NMConnection *connection, + if_block *block) { - gint wpa_l= strlen("wpa-"); - gint wireless_l= strlen("wireless-"); - if_data *curr = block->info; - const gchar* value = ifparser_getkey (block, "inet"); + if_data *curr; + const char* value = ifparser_getkey (block, "inet"); struct _Mapping mapping[] = { {"psk", "psk"}, {"identity", "leap-username"}, @@ -302,101 +316,93 @@ update_wireless_security_setting_from_if_block(NMConnection *connection, NMSettingWireless *s_wireless; gboolean security = FALSE; - if(value && !strcmp("ppp", value)) { + if (nm_streq0 (value, "ppp")) return; - } - - s_wireless = nm_connection_get_setting_wireless(connection); - g_return_if_fail(s_wireless); - nm_log_info (LOGD_SETTINGS, "update wireless security settings (%s).", block->name); - wireless_security_setting = - NM_SETTING_WIRELESS_SECURITY(nm_setting_wireless_security_new()); + s_wireless = nm_connection_get_setting_wireless (connection); + g_return_if_fail (s_wireless); - while(curr) { - if(strlen(curr->key) > wireless_l && - !strncmp("wireless-", curr->key, wireless_l)) { + _LOGI ("update wireless security settings (%s).", block->name); + wireless_security_setting = NM_SETTING_WIRELESS_SECURITY (nm_setting_wireless_security_new ()); - gchar *property_value = NULL; + c_list_for_each_entry (curr, &block->data_lst_head, data_lst) { + if (_str_has_prefix (curr->key, "wireless-", TRUE)) { + const char *key = curr->key + NM_STRLEN ("wireless-"); + char *property_value = NULL; gpointer typed_property_value = NULL; - const gchar* newkey = map_by_mapping(mapping, curr->key+wireless_l); - IfupdownStrDupeFunc dupe_func = map_by_mapping (dupe_mapping, curr->key+wireless_l); - IfupdownStrToTypeFunc type_map_func = map_by_mapping (type_mapping, curr->key+wireless_l); - GFreeFunc free_func = map_by_mapping (free_type_mapping, curr->key+wireless_l); - if(!newkey || !dupe_func) + const char* newkey = map_by_mapping (mapping, key); + IfupdownStrDupeFunc dupe_func = map_by_mapping (dupe_mapping, key); + IfupdownStrToTypeFunc type_map_func = map_by_mapping (type_mapping, key); + GFreeFunc free_func = map_by_mapping (free_type_mapping, key); + if (!newkey || !dupe_func) goto next; property_value = (*dupe_func) (curr->data, connection); - nm_log_info (LOGD_SETTINGS, "setting wireless security key: %s=%s", - newkey, property_value); + _LOGI ("setting wireless security key: %s=%s", + newkey, property_value); if (type_map_func) { errno = 0; typed_property_value = (*type_map_func) (property_value); - if(errno) + if (errno) goto wireless_next; } - g_object_set(wireless_security_setting, - newkey, typed_property_value ?: property_value, - NULL); + g_object_set (wireless_security_setting, + newkey, typed_property_value ?: property_value, + NULL); security = TRUE; - wireless_next: - g_free(property_value); +wireless_next: + g_free (property_value); if (typed_property_value && free_func) (*free_func) (typed_property_value); - } else if(strlen(curr->key) > wpa_l && - !strncmp("wpa-", curr->key, wpa_l)) { - - gchar *property_value = NULL; + } else if (_str_has_prefix (curr->key, "wpa-", TRUE)) { + const char *key = curr->key + NM_STRLEN ("wpa-"); + char *property_value = NULL; gpointer typed_property_value = NULL; - const gchar* newkey = map_by_mapping(mapping, curr->key+wpa_l); - IfupdownStrDupeFunc dupe_func = map_by_mapping (dupe_mapping, curr->key+wpa_l); - IfupdownStrToTypeFunc type_map_func = map_by_mapping (type_mapping, curr->key+wpa_l); - GFreeFunc free_func = map_by_mapping (free_type_mapping, curr->key+wpa_l); - if(!newkey || !dupe_func) + const char* newkey = map_by_mapping (mapping, key); + IfupdownStrDupeFunc dupe_func = map_by_mapping (dupe_mapping, key); + IfupdownStrToTypeFunc type_map_func = map_by_mapping (type_mapping, key); + GFreeFunc free_func = map_by_mapping (free_type_mapping, key); + if (!newkey || !dupe_func) goto next; property_value = (*dupe_func) (curr->data, connection); - nm_log_info (LOGD_SETTINGS, "setting wpa security key: %s=%s", - newkey, -#ifdef DEBUG_SECRETS - property_value -#else /* DEBUG_SECRETS */ - !strcmp("key", newkey) || - !strcmp("leap-password", newkey) || - !strcmp("pin", newkey) || - !strcmp("psk", newkey) || - !strcmp("wep-key0", newkey) || - !strcmp("wep-key1", newkey) || - !strcmp("wep-key2", newkey) || - !strcmp("wep-key3", newkey) || - NULL ? - "<omitted>" : property_value -#endif /* DEBUG_SECRETS */ - ); + _LOGI ("setting wpa security key: %s=%s", + newkey, + NM_IN_STRSET (newkey, "key", + "leap-password", + "pin", + "psk", + "wep-key0", + "wep-key1", + "wep-key2", + "wep-key3") + ? "<omitted>" + : property_value + ); if (type_map_func) { errno = 0; typed_property_value = (*type_map_func) (property_value); - if(errno) + if (errno) goto wpa_next; } - g_object_set(wireless_security_setting, - newkey, typed_property_value ?: property_value, - NULL); + g_object_set (wireless_security_setting, + newkey, typed_property_value ?: property_value, + NULL); security = TRUE; - wpa_next: - g_free(property_value); +wpa_next: + g_free (property_value); if (free_func && typed_property_value) (*free_func) (typed_property_value); } - next: - curr = curr->next; +next: + ; } if (security) @@ -404,51 +410,52 @@ update_wireless_security_setting_from_if_block(NMConnection *connection, } static void -update_wired_setting_from_if_block(NMConnection *connection, - if_block *block) +update_wired_setting_from_if_block (NMConnection *connection, + if_block *block) { NMSettingWired *s_wired = NULL; - s_wired = NM_SETTING_WIRED(nm_setting_wired_new()); - nm_connection_add_setting(connection, NM_SETTING(s_wired)); + s_wired = NM_SETTING_WIRED (nm_setting_wired_new ()); + nm_connection_add_setting (connection, NM_SETTING (s_wired)); } static void ifupdown_ip4_add_dns (NMSettingIPConfig *s_ip4, const char *dns) { guint32 addr; - char **list, **iter; + gs_strfreev char **list = NULL; + char **iter; if (dns == NULL) return; list = g_strsplit_set (dns, " \t", -1); for (iter = list; iter && *iter; iter++) { - g_strstrip (*iter); - if (g_ascii_isspace (*iter[0])) + if ((*iter)[0] == '\0') continue; if (!inet_pton (AF_INET, *iter, &addr)) { - nm_log_warn (LOGD_SETTINGS, " ignoring invalid nameserver '%s'", *iter); + _LOGW (" ignoring invalid nameserver '%s'", *iter); continue; } if (!nm_setting_ip_config_add_dns (s_ip4, *iter)) - nm_log_warn (LOGD_SETTINGS, " duplicate DNS domain '%s'", *iter); + _LOGW (" duplicate DNS domain '%s'", *iter); } - g_strfreev (list); } static gboolean -update_ip4_setting_from_if_block(NMConnection *connection, - if_block *block, - GError **error) +update_ip4_setting_from_if_block (NMConnection *connection, + if_block *block, + GError **error) { - NMSettingIPConfig *s_ip4 = NM_SETTING_IP_CONFIG (nm_setting_ip4_config_new()); - const char *type = ifparser_getkey(block, "inet"); - gboolean is_static = type && !strcmp("static", type); + gs_unref_object NMSettingIPConfig *s_ip4 = NM_SETTING_IP_CONFIG (nm_setting_ip4_config_new ()); + const char *type = ifparser_getkey (block, "inet"); - if (!is_static) { - g_object_set (s_ip4, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, NULL); + if (!nm_streq0 (type, "static")) { + g_object_set (s_ip4, + NM_SETTING_IP_CONFIG_METHOD, + NM_SETTING_IP4_CONFIG_METHOD_AUTO, + NULL); } else { guint32 tmp_mask; NMIPAddress *addr; @@ -458,7 +465,6 @@ update_ip4_setting_from_if_block(NMConnection *connection, const char *nameserver_v; const char *nameservers_v; const char *search_v; - char **list, **iter; guint32 netmask_int = 32; /* Address */ @@ -466,7 +472,7 @@ update_ip4_setting_from_if_block(NMConnection *connection, if (!address_v) { g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, "Missing IPv4 address"); - goto error; + return FALSE; } /* mask/prefix */ @@ -476,8 +482,8 @@ update_ip4_setting_from_if_block(NMConnection *connection, netmask_int = atoi (netmask_v); } else if (!inet_pton (AF_INET, netmask_v, &tmp_mask)) { g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, - "Invalid IPv4 netmask '%s'", netmask_v); - goto error; + "Invalid IPv4 netmask '%s'", netmask_v); + return FALSE; } else { netmask_int = nm_utils_ip4_netmask_to_prefix (tmp_mask); } @@ -486,13 +492,13 @@ update_ip4_setting_from_if_block(NMConnection *connection, /* Add the new address to the setting */ addr = nm_ip_address_new (AF_INET, address_v, netmask_int, error); if (!addr) - goto error; + return FALSE; if (nm_setting_ip_config_add_address (s_ip4, addr)) { - nm_log_info (LOGD_SETTINGS, "addresses count: %d", - nm_setting_ip_config_get_num_addresses (s_ip4)); + _LOGI ("addresses count: %d", + nm_setting_ip_config_get_num_addresses (s_ip4)); } else { - nm_log_info (LOGD_SETTINGS, "ignoring duplicate IP4 address"); + _LOGI ("ignoring duplicate IP4 address"); } nm_ip_address_unref (addr); @@ -502,7 +508,7 @@ update_ip4_setting_from_if_block(NMConnection *connection, if (!nm_utils_ipaddr_valid (AF_INET, gateway_v)) { g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, "Invalid IPv4 gateway '%s'", gateway_v); - goto error; + return FALSE; } if (!nm_setting_ip_config_get_gateway (s_ip4)) g_object_set (s_ip4, NM_SETTING_IP_CONFIG_GATEWAY, gateway_v, NULL); @@ -515,70 +521,67 @@ update_ip4_setting_from_if_block(NMConnection *connection, ifupdown_ip4_add_dns (s_ip4, nameservers_v); if (!nm_setting_ip_config_get_num_dns (s_ip4)) - nm_log_info (LOGD_SETTINGS, "No dns-nameserver configured in /etc/network/interfaces"); + _LOGI ("No dns-nameserver configured in /etc/network/interfaces"); /* DNS searches */ search_v = ifparser_getkey (block, "dns-search"); if (search_v) { + gs_strfreev char **list = NULL; + char **iter; + list = g_strsplit_set (search_v, " \t", -1); for (iter = list; iter && *iter; iter++) { - g_strstrip (*iter); - if (g_ascii_isspace (*iter[0])) + if ((*iter)[0] == '\0') continue; if (!nm_setting_ip_config_add_dns_search (s_ip4, *iter)) - nm_log_warn (LOGD_SETTINGS, " duplicate DNS domain '%s'", *iter); + _LOGW (" duplicate DNS domain '%s'", *iter); } - g_strfreev (list); } g_object_set (s_ip4, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_MANUAL, NULL); } - nm_connection_add_setting (connection, NM_SETTING (s_ip4)); + nm_connection_add_setting (connection, NM_SETTING (g_steal_pointer (&s_ip4))); return TRUE; - -error: - g_object_unref (s_ip4); - return FALSE; } static void ifupdown_ip6_add_dns (NMSettingIPConfig *s_ip6, const char *dns) { struct in6_addr addr; - char **list, **iter; + gs_strfreev char **list = NULL; + char **iter; if (dns == NULL) return; list = g_strsplit_set (dns, " \t", -1); for (iter = list; iter && *iter; iter++) { - g_strstrip (*iter); - if (g_ascii_isspace (*iter[0])) + if ((*iter)[0] == '\0') continue; if (!inet_pton (AF_INET6, *iter, &addr)) { - nm_log_warn (LOGD_SETTINGS, " ignoring invalid nameserver '%s'", *iter); + _LOGW (" ignoring invalid nameserver '%s'", *iter); continue; } if (!nm_setting_ip_config_add_dns (s_ip6, *iter)) - nm_log_warn (LOGD_SETTINGS, " duplicate DNS domain '%s'", *iter); + _LOGW (" duplicate DNS domain '%s'", *iter); } - g_strfreev (list); } static gboolean -update_ip6_setting_from_if_block(NMConnection *connection, - if_block *block, - GError **error) +update_ip6_setting_from_if_block (NMConnection *connection, + if_block *block, + GError **error) { - NMSettingIPConfig *s_ip6 = NM_SETTING_IP_CONFIG (nm_setting_ip6_config_new()); - const char *type = ifparser_getkey(block, "inet6"); - gboolean is_static = type && (!strcmp("static", type) || - !strcmp("v4tunnel", type)); + gs_unref_object NMSettingIPConfig *s_ip6 = NM_SETTING_IP_CONFIG (nm_setting_ip6_config_new ()); + const char *type = ifparser_getkey (block, "inet6"); - if (!is_static) { - g_object_set(s_ip6, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_AUTO, NULL); + if (!NM_IN_STRSET (type, "static", "v4tunnel")) { + g_object_set (s_ip6, + NM_SETTING_IP_CONFIG_METHOD, + NM_SETTING_IP6_CONFIG_METHOD_AUTO, + NULL); } else { NMIPAddress *addr; const char *address_v; @@ -588,31 +591,30 @@ update_ip6_setting_from_if_block(NMConnection *connection, const char *nameservers_v; const char *search_v; int prefix_int = 128; - char **list, **iter; /* Address */ - address_v = ifparser_getkey(block, "address"); + address_v = ifparser_getkey (block, "address"); if (!address_v) { g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, "Missing IPv6 address"); - goto error; + return FALSE; } /* Prefix */ - prefix_v = ifparser_getkey(block, "netmask"); + prefix_v = ifparser_getkey (block, "netmask"); if (prefix_v) prefix_int = g_ascii_strtoll (prefix_v, NULL, 10); /* Add the new address to the setting */ addr = nm_ip_address_new (AF_INET6, address_v, prefix_int, error); if (!addr) - goto error; + return FALSE; if (nm_setting_ip_config_add_address (s_ip6, addr)) { - nm_log_info (LOGD_SETTINGS, "addresses count: %d", + _LOGI ("addresses count: %d", nm_setting_ip_config_get_num_addresses (s_ip6)); } else { - nm_log_info (LOGD_SETTINGS, "ignoring duplicate IP6 address"); + _LOGI ("ignoring duplicate IP6 address"); } nm_ip_address_unref (addr); @@ -622,33 +624,34 @@ update_ip6_setting_from_if_block(NMConnection *connection, if (!nm_utils_ipaddr_valid (AF_INET6, gateway_v)) { g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, "Invalid IPv6 gateway '%s'", gateway_v); - goto error; + return FALSE; } if (!nm_setting_ip_config_get_gateway (s_ip6)) g_object_set (s_ip6, NM_SETTING_IP_CONFIG_GATEWAY, gateway_v, NULL); } - nameserver_v = ifparser_getkey(block, "dns-nameserver"); + nameserver_v = ifparser_getkey (block, "dns-nameserver"); ifupdown_ip6_add_dns (s_ip6, nameserver_v); - nameservers_v = ifparser_getkey(block, "dns-nameservers"); + nameservers_v = ifparser_getkey (block, "dns-nameservers"); ifupdown_ip6_add_dns (s_ip6, nameservers_v); if (!nm_setting_ip_config_get_num_dns (s_ip6)) - nm_log_info (LOGD_SETTINGS, "No dns-nameserver configured in /etc/network/interfaces"); + _LOGI ("No dns-nameserver configured in /etc/network/interfaces"); /* DNS searches */ search_v = ifparser_getkey (block, "dns-search"); if (search_v) { + gs_strfreev char **list = NULL; + char **iter; + list = g_strsplit_set (search_v, " \t", -1); for (iter = list; iter && *iter; iter++) { - g_strstrip (*iter); - if (isblank (*iter[0])) + if ((*iter)[0] == '\0') continue; if (!nm_setting_ip_config_add_dns_search (s_ip6, *iter)) - nm_log_warn (LOGD_SETTINGS, " duplicate DNS domain '%s'", *iter); + _LOGW (" duplicate DNS domain '%s'", *iter); } - g_strfreev (list); } g_object_set (s_ip6, @@ -656,12 +659,8 @@ update_ip6_setting_from_if_block(NMConnection *connection, NULL); } - nm_connection_add_setting (connection, NM_SETTING (s_ip6)); + nm_connection_add_setting (connection, NM_SETTING (g_steal_pointer (&s_ip6))); return TRUE; - -error: - g_object_unref (s_ip6); - return FALSE; } gboolean @@ -669,25 +668,22 @@ ifupdown_update_connection_from_if_block (NMConnection *connection, if_block *block, GError **error) { - const char *type = NULL; - char *idstr = NULL; - char *uuid_base = NULL; - char *uuid = NULL; + const char *type; + gs_free char *idstr = NULL; + gs_free char *uuid = NULL; NMSettingConnection *s_con; gboolean success = FALSE; s_con = nm_connection_get_setting_connection (connection); - if(!s_con) { - s_con = NM_SETTING_CONNECTION (nm_setting_connection_new()); - g_assert (s_con); + if (!s_con) { + s_con = NM_SETTING_CONNECTION (nm_setting_connection_new ()); nm_connection_add_setting (connection, NM_SETTING (s_con)); } type = _ifupdownplugin_guess_connection_type (block); idstr = g_strconcat ("Ifupdown (", block->name, ")", NULL); - uuid_base = idstr; - uuid = nm_utils_uuid_generate_from_string (uuid_base, -1, NM_UTILS_UUID_TYPE_LEGACY, NULL); + uuid = nm_utils_uuid_generate_from_string (idstr, -1, NM_UTILS_UUID_TYPE_LEGACY, NULL); g_object_set (s_con, NM_SETTING_CONNECTION_TYPE, type, NM_SETTING_CONNECTION_INTERFACE_NAME, block->name, @@ -696,19 +692,18 @@ ifupdown_update_connection_from_if_block (NMConnection *connection, NM_SETTING_CONNECTION_READ_ONLY, TRUE, NM_SETTING_CONNECTION_AUTOCONNECT, FALSE, NULL); - g_free (uuid); - nm_log_info (LOGD_SETTINGS, "update_connection_setting_from_if_block: name:%s, type:%s, id:%s, uuid: %s", - block->name, type, idstr, nm_setting_connection_get_uuid (s_con)); + _LOGI ("update_connection_setting_from_if_block: name:%s, type:%s, id:%s, uuid: %s", + block->name, type, idstr, nm_setting_connection_get_uuid (s_con)); - if (!strcmp (NM_SETTING_WIRED_SETTING_NAME, type)) + if (nm_streq (type, NM_SETTING_WIRED_SETTING_NAME)) update_wired_setting_from_if_block (connection, block); - else if (!strcmp (NM_SETTING_WIRELESS_SETTING_NAME, type)) { + else if (nm_streq (type, NM_SETTING_WIRELESS_SETTING_NAME)) { update_wireless_setting_from_if_block (connection, block); update_wireless_security_setting_from_if_block (connection, block); } - if (ifparser_haskey(block, "inet6")) + if (ifparser_haskey (block, "inet6")) success = update_ip6_setting_from_if_block (connection, block, error); else success = update_ip4_setting_from_if_block (connection, block, error); @@ -716,6 +711,5 @@ ifupdown_update_connection_from_if_block (NMConnection *connection, if (success == TRUE) success = nm_connection_verify (connection, error); - g_free (idstr); return success; } diff --git a/src/settings/plugins/ifupdown/nms-ifupdown-plugin.c b/src/settings/plugins/ifupdown/nms-ifupdown-plugin.c index 8bd72d02..88c651b8 100644 --- a/src/settings/plugins/ifupdown/nms-ifupdown-plugin.c +++ b/src/settings/plugins/ifupdown/nms-ifupdown-plugin.c @@ -29,7 +29,6 @@ #include <string.h> #include <arpa/inet.h> #include <gmodule.h> -#include <libudev.h> #include "nm-setting-connection.h" #include "nm-dbus-interface.h" @@ -42,7 +41,6 @@ #include "nm-core-internal.h" #include "NetworkManagerUtils.h" #include "nm-config.h" -#include "nm-utils/nm-udev-utils.h" #include "nms-ifupdown-interface-parser.h" #include "nms-ifupdown-connection.h" @@ -52,43 +50,27 @@ #define IFUPDOWN_UNMANAGE_WELL_KNOWN_DEFAULT TRUE -/* #define ALWAYS_UNMANAGE TRUE */ -#ifndef ALWAYS_UNMANAGE -#define ALWAYS_UNMANAGE FALSE -#endif - /*****************************************************************************/ typedef struct { - NMUdevClient *udev_client; - - GHashTable *connections; /* /e/n/i block name :: NMIfupdownConnection */ - - /* Stores all blocks/interfaces read from /e/n/i regardless of whether - * there is an NMIfupdownConnection for block. + /* Stores an entry for blocks/interfaces read from /e/n/i and (if exists) + * the NMIfupdownConnection associated with the block. */ GHashTable *eni_ifaces; - /* Stores any network interfaces the kernel knows about */ - GHashTable *kernel_ifaces; - - gboolean unmanage_well_known; + bool ifupdown_managed; } SettingsPluginIfupdownPrivate; struct _SettingsPluginIfupdown { - GObject parent; + NMSettingsPlugin parent; SettingsPluginIfupdownPrivate _priv; }; struct _SettingsPluginIfupdownClass { - GObjectClass parent; + NMSettingsPluginClass parent; }; -static void settings_plugin_interface_init (NMSettingsPluginInterface *plugin_iface); - -G_DEFINE_TYPE_EXTENDED (SettingsPluginIfupdown, settings_plugin_ifupdown, G_TYPE_OBJECT, 0, - G_IMPLEMENT_INTERFACE (NM_TYPE_SETTINGS_PLUGIN, - settings_plugin_interface_init)) +G_DEFINE_TYPE (SettingsPluginIfupdown, settings_plugin_ifupdown, NM_TYPE_SETTINGS_PLUGIN) #define SETTINGS_PLUGIN_IFUPDOWN_GET_PRIVATE(self) _NM_GET_PRIVATE (self, SettingsPluginIfupdown, SETTINGS_IS_PLUGIN_IFUPDOWN) @@ -99,169 +81,41 @@ NM_DEFINE_SINGLETON_GETTER (SettingsPluginIfupdown, settings_plugin_ifupdown_get /*****************************************************************************/ -static void -bind_device_to_connection (SettingsPluginIfupdown *self, - struct udev_device *device, - NMIfupdownConnection *exported) -{ - NMSettingWired *s_wired; - NMSettingWireless *s_wifi; - const char *iface, *address; - - iface = udev_device_get_sysname (device); - if (!iface) { - nm_log_warn (LOGD_SETTINGS, "failed to get ifname for device."); - return; - } - - address = udev_device_get_sysattr_value (device, "address"); - if (!address || !address[0]) { - nm_log_warn (LOGD_SETTINGS, "failed to get MAC address for %s", iface); - return; - } - - if (!nm_utils_hwaddr_valid (address, ETH_ALEN)) { - nm_log_warn (LOGD_SETTINGS, "failed to parse MAC address '%s' for %s", - address, iface); - return; - } - - s_wired = nm_connection_get_setting_wired (NM_CONNECTION (exported)); - s_wifi = nm_connection_get_setting_wireless (NM_CONNECTION (exported)); - if (s_wired) { - nm_log_info (LOGD_SETTINGS, "locking wired connection setting"); - g_object_set (s_wired, NM_SETTING_WIRED_MAC_ADDRESS, address, NULL); - } else if (s_wifi) { - nm_log_info (LOGD_SETTINGS, "locking wireless connection setting"); - g_object_set (s_wifi, NM_SETTING_WIRELESS_MAC_ADDRESS, address, NULL); - } - - nm_settings_connection_update (NM_SETTINGS_CONNECTION (exported), - NULL, - NM_SETTINGS_CONNECTION_PERSIST_MODE_DISK, - NM_SETTINGS_CONNECTION_COMMIT_REASON_NONE, - "ifupdown-new", - NULL); -} - -static void -udev_device_added (SettingsPluginIfupdown *self, struct udev_device *device) -{ - SettingsPluginIfupdownPrivate *priv = SETTINGS_PLUGIN_IFUPDOWN_GET_PRIVATE (self); - const char *iface, *path; - NMIfupdownConnection *exported; - - iface = udev_device_get_sysname (device); - path = udev_device_get_syspath (device); - if (!iface || !path) - return; - - nm_log_info (LOGD_SETTINGS, "devices added (path: %s, iface: %s)", path, iface); - - /* if we have a configured connection for this particular iface - * we want to either unmanage the device or lock it - */ - exported = g_hash_table_lookup (priv->connections, iface); - if (!exported && !g_hash_table_lookup (priv->eni_ifaces, iface)) { - nm_log_info (LOGD_SETTINGS, "device added (path: %s, iface: %s): no ifupdown configuration found.", - path, iface); - return; - } - - g_hash_table_insert (priv->kernel_ifaces, g_strdup (iface), udev_device_ref (device)); - - if (exported) - bind_device_to_connection (self, device, exported); - - if (ALWAYS_UNMANAGE || priv->unmanage_well_known) - g_signal_emit_by_name (G_OBJECT (self), NM_SETTINGS_PLUGIN_UNMANAGED_SPECS_CHANGED); -} - -static void -udev_device_removed (SettingsPluginIfupdown *self, struct udev_device *device) -{ - SettingsPluginIfupdownPrivate *priv = SETTINGS_PLUGIN_IFUPDOWN_GET_PRIVATE (self); - const char *iface, *path; - - iface = udev_device_get_sysname (device); - path = udev_device_get_syspath (device); - if (!iface || !path) - return; - - nm_log_info (LOGD_SETTINGS, "devices removed (path: %s, iface: %s)", path, iface); - - if (!g_hash_table_remove (priv->kernel_ifaces, iface)) - return; - - if (ALWAYS_UNMANAGE || priv->unmanage_well_known) - g_signal_emit_by_name (G_OBJECT (self), NM_SETTINGS_PLUGIN_UNMANAGED_SPECS_CHANGED); -} - -static void -udev_device_changed (SettingsPluginIfupdown *self, struct udev_device *device) -{ - SettingsPluginIfupdownPrivate *priv = SETTINGS_PLUGIN_IFUPDOWN_GET_PRIVATE (self); - const char *iface, *path; - - iface = udev_device_get_sysname (device); - path = udev_device_get_syspath (device); - if (!iface || !path) - return; - - nm_log_info (LOGD_SETTINGS, "device changed (path: %s, iface: %s)", path, iface); - - if (!g_hash_table_lookup (priv->kernel_ifaces, iface)) - return; - - if (ALWAYS_UNMANAGE || priv->unmanage_well_known) - g_signal_emit_by_name (G_OBJECT (self), NM_SETTINGS_PLUGIN_UNMANAGED_SPECS_CHANGED); -} - -static void -handle_uevent (NMUdevClient *client, - struct udev_device *device, - gpointer user_data) -{ - SettingsPluginIfupdown *self = SETTINGS_PLUGIN_IFUPDOWN (user_data); - const char *subsys; - const char *action; - - action = udev_device_get_action (device); - - g_return_if_fail (action != NULL); +#define _NMLOG_PREFIX_NAME "ifupdown" +#define _NMLOG_DOMAIN LOGD_SETTINGS +#define _NMLOG(level, ...) \ + nm_log ((level), _NMLOG_DOMAIN, NULL, NULL, \ + "%s" _NM_UTILS_MACRO_FIRST (__VA_ARGS__), \ + _NMLOG_PREFIX_NAME": " \ + _NM_UTILS_MACRO_REST (__VA_ARGS__)) - /* A bit paranoid */ - subsys = udev_device_get_subsystem (device); - g_return_if_fail (nm_streq0 (subsys, "net")); - - if (!strcmp (action, "add")) - udev_device_added (self, device); - else if (!strcmp (action, "remove")) - udev_device_removed (self, device); - else if (!strcmp (action, "change")) - udev_device_changed (self, device); -} +/*****************************************************************************/ /* Returns the plugins currently known list of connections. The returned * list is freed by the system settings service. */ static GSList* -get_connections (NMSettingsPlugin *config) +get_connections (NMSettingsPlugin *plugin) { - SettingsPluginIfupdownPrivate *priv = SETTINGS_PLUGIN_IFUPDOWN_GET_PRIVATE ((SettingsPluginIfupdown *) config); - GSList *connections; - - nm_log_info (LOGD_SETTINGS, "(%d) ... get_connections.", GPOINTER_TO_UINT(config)); + SettingsPluginIfupdown *self = SETTINGS_PLUGIN_IFUPDOWN (plugin); + SettingsPluginIfupdownPrivate *priv = SETTINGS_PLUGIN_IFUPDOWN_GET_PRIVATE (self); + GSList *list = NULL; + GHashTableIter iter; + void *value; - if(priv->unmanage_well_known) { - nm_log_info (LOGD_SETTINGS, "(%d) ... get_connections (managed=false): return empty list.", GPOINTER_TO_UINT(config)); + if (!priv->ifupdown_managed) { + _LOGD ("get_connections: not connections due to managed=false"); return NULL; } - connections = _nm_utils_hash_values_to_slist (priv->connections); + g_hash_table_iter_init (&iter, priv->eni_ifaces); + while (g_hash_table_iter_next (&iter, NULL, &value)) { + if (value) + list = g_slist_prepend (list, value); + } - nm_log_info (LOGD_SETTINGS, "(%d) connections count: %d", GPOINTER_TO_UINT(config), g_slist_length(connections)); - return connections; + _LOGD ("get_connections: %u connections", g_slist_length (list)); + return list; } /* @@ -270,202 +124,178 @@ get_connections (NMSettingsPlugin *config) * each element must be allocated using g_malloc() or its variants. */ static GSList* -get_unmanaged_specs (NMSettingsPlugin *config) +get_unmanaged_specs (NMSettingsPlugin *plugin) { - SettingsPluginIfupdownPrivate *priv = SETTINGS_PLUGIN_IFUPDOWN_GET_PRIVATE ((SettingsPluginIfupdown *) config); + SettingsPluginIfupdown *self = SETTINGS_PLUGIN_IFUPDOWN (plugin); + SettingsPluginIfupdownPrivate *priv = SETTINGS_PLUGIN_IFUPDOWN_GET_PRIVATE (self); GSList *specs = NULL; GHashTableIter iter; - struct udev_device *device; const char *iface; - if (!ALWAYS_UNMANAGE && !priv->unmanage_well_known) + if (priv->ifupdown_managed) return NULL; - nm_log_info (LOGD_SETTINGS, "get unmanaged devices count: %d", - g_hash_table_size (priv->kernel_ifaces)); - - g_hash_table_iter_init (&iter, priv->kernel_ifaces); - while (g_hash_table_iter_next (&iter, (gpointer) &iface, (gpointer) &device)) { - const char *address; + _LOGD ("unmanaged-specs: unmanaged devices count %u", + g_hash_table_size (priv->eni_ifaces)); - address = udev_device_get_sysattr_value (device, "address"); - if (address) - specs = g_slist_append (specs, g_strdup_printf ("mac:%s", address)); - else - specs = g_slist_append (specs, g_strdup_printf ("interface-name:%s", iface)); - } + g_hash_table_iter_init (&iter, priv->eni_ifaces); + while (g_hash_table_iter_next (&iter, (gpointer) &iface, NULL)) + specs = g_slist_append (specs, g_strdup_printf ("interface-name:=%s", iface)); return specs; } /*****************************************************************************/ static void -_udev_device_unref (gpointer ptr) +initialize (NMSettingsPlugin *plugin) { - udev_device_unref (ptr); -} - -static void -init (NMSettingsPlugin *config) -{ - SettingsPluginIfupdown *self = SETTINGS_PLUGIN_IFUPDOWN (config); + SettingsPluginIfupdown *self = SETTINGS_PLUGIN_IFUPDOWN (plugin); SettingsPluginIfupdownPrivate *priv = SETTINGS_PLUGIN_IFUPDOWN_GET_PRIVATE (self); - GHashTable *auto_ifaces; - if_block *block = NULL; - struct udev_enumerate *enumerate; - struct udev_list_entry *keys; + gs_unref_hashtable GHashTable *auto_ifaces = NULL; + nm_auto_ifparser if_parser *parser = NULL; + if_block *block; GHashTableIter con_iter; const char *block_name; - NMIfupdownConnection *connection; - - auto_ifaces = g_hash_table_new (nm_str_hash, g_str_equal); - - if(!priv->connections) - priv->connections = g_hash_table_new (nm_str_hash, g_str_equal); - - if(!priv->kernel_ifaces) - priv->kernel_ifaces = g_hash_table_new_full (nm_str_hash, g_str_equal, g_free, _udev_device_unref); + NMIfupdownConnection *conn; - if(!priv->eni_ifaces) - priv->eni_ifaces = g_hash_table_new (nm_str_hash, g_str_equal); + parser = ifparser_parse (ENI_INTERFACES_FILE, 0); - nm_log_info (LOGD_SETTINGS, "init!"); + c_list_for_each_entry (block, &parser->block_lst_head, block_lst) { - priv->udev_client = nm_udev_client_new ((const char *[]) { "net", NULL }, - handle_uevent, self); - - /* Read in all the interfaces */ - ifparser_init (ENI_INTERFACES_FILE, 0); - block = ifparser_getfirst (); - while (block) { - if(!strcmp ("auto", block->type) || !strcmp ("allow-hotplug", block->type)) - g_hash_table_insert (auto_ifaces, block->name, GUINT_TO_POINTER (1)); - else if (!strcmp ("iface", block->type)) { - NMIfupdownConnection *exported; + if (NM_IN_STRSET (block->type, "auto", "allow-hotplug")) { + if (!auto_ifaces) + auto_ifaces = g_hash_table_new_full (nm_str_hash, g_str_equal, g_free, NULL); + g_hash_table_add (auto_ifaces, g_strdup (block->name)); + continue; + } + if (nm_streq (block->type, "iface")) { /* Bridge configuration */ - if(!strncmp ("br", block->name, 2)) { + if (g_str_has_prefix (block_name, "br")) { /* Try to find bridge ports */ const char *ports = ifparser_getkey (block, "bridge-ports"); + if (ports) { - int i; + guint i; int state = 0; - char **port_ifaces; + gs_strfreev char **port_ifaces = NULL; - nm_log_info (LOGD_SETTINGS, "found bridge ports %s for %s", ports, block->name); + _LOGD ("parse: found bridge ports %s for %s", ports, block->name); port_ifaces = g_strsplit_set (ports, " \t", -1); - for (i = 0; i < g_strv_length (port_ifaces); i++) { - char *token = port_ifaces[i]; + for (i = 0; port_ifaces[i]; i++) { + const char *token = port_ifaces[i]; + /* Skip crazy stuff like regex or all */ - if (!strcmp ("all", token)) { + if (nm_streq (token, "all")) continue; - } + /* Small SM to skip everything inside regex */ - if (!strcmp ("regex", token)) { + if (nm_streq (token, "regex")) { state++; continue; } - if (!strcmp ("noregex", token)) { + if (nm_streq (token, "noregex")) { state--; continue; } + if (nm_streq (token, "none")) + continue; if (state == 0 && strlen (token) > 0) { - nm_log_info (LOGD_SETTINGS, "adding bridge port %s to eni_ifaces", token); - g_hash_table_insert (priv->eni_ifaces, g_strdup (token), "known"); + conn = g_hash_table_lookup (priv->eni_ifaces, block->name); + if (!conn) { + _LOGD ("parse: adding bridge port \"%s\"", token); + g_hash_table_insert (priv->eni_ifaces, g_strdup (token), NULL); + } else { + _LOGD ("parse: adding bridge port \"%s\" (have connection %s)", token, + nm_settings_connection_get_uuid (NM_SETTINGS_CONNECTION (conn))); + } } } - g_strfreev (port_ifaces); } - goto next; + continue; } /* Skip loopback configuration */ - if(!strcmp ("lo", block->name)) { - goto next; - } + if (nm_streq (block->name, "lo")) + continue; /* Remove any connection for this block that was previously found */ - exported = g_hash_table_lookup (priv->connections, block->name); - if (exported) { - nm_log_info (LOGD_SETTINGS, "deleting %s from connections", block->name); - nm_settings_connection_delete (NM_SETTINGS_CONNECTION (exported), NULL); - g_hash_table_remove (priv->connections, block->name); + conn = g_hash_table_lookup (priv->eni_ifaces, block->name); + if (conn) { + _LOGD ("parse: replace connection \"%s\" (%s)", + block->name, + nm_settings_connection_get_uuid (NM_SETTINGS_CONNECTION (conn))); + nm_settings_connection_delete (NM_SETTINGS_CONNECTION (conn), NULL); + g_hash_table_remove (priv->eni_ifaces, block->name); } /* add the new connection */ - exported = nm_ifupdown_connection_new (block); - if (exported) { - nm_log_info (LOGD_SETTINGS, "adding %s to connections", block->name); - g_hash_table_insert (priv->connections, block->name, exported); + conn = nm_ifupdown_connection_new (block); + if (conn) { + _LOGD ("parse: adding connection \"%s\" (%s)", block->name, + nm_settings_connection_get_uuid (NM_SETTINGS_CONNECTION (conn))); + } else + _LOGD ("parse: adding place holder for connection \"%s\"", block->name); + g_hash_table_insert (priv->eni_ifaces, g_strdup (block->name), conn); + continue; + } + + if (nm_streq (block->type, "mapping")) { + conn = g_hash_table_lookup (priv->eni_ifaces, block->name); + if (!conn) { + _LOGD ("parse: adding mapping \"%s\"", block->name); + g_hash_table_insert (priv->eni_ifaces, g_strdup (block->name), NULL); + } else { + _LOGD ("parse: adding mapping \"%s\" (have connection %s)", block->name, + nm_settings_connection_get_uuid (NM_SETTINGS_CONNECTION (conn))); } - nm_log_info (LOGD_SETTINGS, "adding iface %s to eni_ifaces", block->name); - g_hash_table_insert (priv->eni_ifaces, block->name, "known"); - } else if (!strcmp ("mapping", block->type)) { - g_hash_table_insert (priv->eni_ifaces, block->name, "known"); - nm_log_info (LOGD_SETTINGS, "adding mapping %s to eni_ifaces", block->name); + continue; } - next: - block = block->next; } /* Make 'auto' interfaces autoconnect=TRUE */ - g_hash_table_iter_init (&con_iter, priv->connections); - while (g_hash_table_iter_next (&con_iter, (gpointer) &block_name, (gpointer) &connection)) { + g_hash_table_iter_init (&con_iter, priv->eni_ifaces); + while (g_hash_table_iter_next (&con_iter, (gpointer) &block_name, (gpointer) &conn)) { NMSettingConnection *setting; - if (g_hash_table_lookup (auto_ifaces, block_name)) { - setting = nm_connection_get_setting_connection (NM_CONNECTION (connection)); - g_object_set (setting, NM_SETTING_CONNECTION_AUTOCONNECT, TRUE, NULL); - nm_log_info (LOGD_SETTINGS, "autoconnect"); - } + if ( !conn + || !auto_ifaces + || !g_hash_table_contains (auto_ifaces, block_name)) + continue; + + /* FIXME(copy-on-write-connection): avoid modifying NMConnection instances and share them via copy-on-write. */ + setting = nm_connection_get_setting_connection (nm_settings_connection_get_connection (NM_SETTINGS_CONNECTION (conn))); + g_object_set (setting, NM_SETTING_CONNECTION_AUTOCONNECT, TRUE, NULL); } - g_hash_table_destroy (auto_ifaces); /* Check the config file to find out whether to manage interfaces */ - priv->unmanage_well_known = !nm_config_data_get_value_boolean (NM_CONFIG_GET_DATA_ORIG, - NM_CONFIG_KEYFILE_GROUP_IFUPDOWN, - NM_CONFIG_KEYFILE_KEY_IFUPDOWN_MANAGED, - !IFUPDOWN_UNMANAGE_WELL_KNOWN_DEFAULT); - nm_log_info (LOGD_SETTINGS, "management mode: %s", priv->unmanage_well_known ? "unmanaged" : "managed"); - - /* Add well-known interfaces */ - enumerate = nm_udev_client_enumerate_new (priv->udev_client); - udev_enumerate_scan_devices (enumerate); - keys = udev_enumerate_get_list_entry (enumerate); - for (; keys; keys = udev_list_entry_get_next (keys)) { - struct udev_device *udevice; - - udevice = udev_device_new_from_syspath (udev_enumerate_get_udev (enumerate), - udev_list_entry_get_name (keys)); - if (udevice) { - udev_device_added (self, udevice); - udev_device_unref (udevice); - } - } - udev_enumerate_unref (enumerate); + priv->ifupdown_managed = nm_config_data_get_value_boolean (NM_CONFIG_GET_DATA_ORIG, + NM_CONFIG_KEYFILE_GROUP_IFUPDOWN, + NM_CONFIG_KEYFILE_KEY_IFUPDOWN_MANAGED, + !IFUPDOWN_UNMANAGE_WELL_KNOWN_DEFAULT); + _LOGI ("management mode: %s", priv->ifupdown_managed ? "managed" : "unmanaged"); /* Now if we're running in managed mode, let NM know there are new connections */ - if (!priv->unmanage_well_known) { - GList *con_list = g_hash_table_get_values (priv->connections); - GList *cl_iter; - - for (cl_iter = con_list; cl_iter; cl_iter = g_list_next (cl_iter)) { - g_signal_emit_by_name (self, - NM_SETTINGS_PLUGIN_CONNECTION_ADDED, - NM_SETTINGS_CONNECTION (cl_iter->data)); + if (priv->ifupdown_managed) { + GHashTableIter iter; + + g_hash_table_iter_init (&iter, priv->eni_ifaces); + while (g_hash_table_iter_next (&iter, NULL, (gpointer *) conn)) { + _nm_settings_plugin_emit_signal_connection_added (NM_SETTINGS_PLUGIN (self), + NM_SETTINGS_CONNECTION (conn)); } - g_list_free (con_list); } - - nm_log_info (LOGD_SETTINGS, "end _init."); } /*****************************************************************************/ static void -settings_plugin_ifupdown_init (SettingsPluginIfupdown *plugin) +settings_plugin_ifupdown_init (SettingsPluginIfupdown *self) { + SettingsPluginIfupdownPrivate *priv = SETTINGS_PLUGIN_IFUPDOWN_GET_PRIVATE (self); + + priv->eni_ifaces = g_hash_table_new_full (nm_str_hash, g_str_equal, g_free, g_object_unref); } static void @@ -474,35 +304,28 @@ dispose (GObject *object) SettingsPluginIfupdown *plugin = SETTINGS_PLUGIN_IFUPDOWN (object); SettingsPluginIfupdownPrivate *priv = SETTINGS_PLUGIN_IFUPDOWN_GET_PRIVATE (plugin); - g_clear_pointer (&priv->kernel_ifaces, g_hash_table_destroy); g_clear_pointer (&priv->eni_ifaces, g_hash_table_destroy); - priv->udev_client = nm_udev_client_unref (priv->udev_client); - G_OBJECT_CLASS (settings_plugin_ifupdown_parent_class)->dispose (object); } static void -settings_plugin_ifupdown_class_init (SettingsPluginIfupdownClass *req_class) +settings_plugin_ifupdown_class_init (SettingsPluginIfupdownClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (req_class); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMSettingsPluginClass *plugin_class = NM_SETTINGS_PLUGIN_CLASS (klass); object_class->dispose = dispose; -} -static void -settings_plugin_interface_init (NMSettingsPluginInterface *plugin_iface) -{ - plugin_iface->init = init; - plugin_iface->get_connections = get_connections; - plugin_iface->get_unmanaged_specs = get_unmanaged_specs; + plugin_class->initialize = initialize; + plugin_class->get_connections = get_connections; + plugin_class->get_unmanaged_specs = get_unmanaged_specs; } /*****************************************************************************/ -G_MODULE_EXPORT GObject * +G_MODULE_EXPORT NMSettingsPlugin * nm_settings_plugin_factory (void) { - return G_OBJECT (g_object_ref (settings_plugin_ifupdown_get ())); + return NM_SETTINGS_PLUGIN (g_object_ref (settings_plugin_ifupdown_get ())); } - diff --git a/src/settings/plugins/ifupdown/tests/meson.build b/src/settings/plugins/ifupdown/tests/meson.build index ee3b6a34..5a2383d9 100644 --- a/src/settings/plugins/ifupdown/tests/meson.build +++ b/src/settings/plugins/ifupdown/tests/meson.build @@ -4,7 +4,6 @@ exe = executable( test_unit, test_unit + '.c', dependencies: test_nm_dep, - c_args: nm_build_cflags, link_with: libnms_ifupdown_core ) diff --git a/src/settings/plugins/ifupdown/tests/test-ifupdown.c b/src/settings/plugins/ifupdown/tests/test-ifupdown.c index 18bad65e..82ee1c4a 100644 --- a/src/settings/plugins/ifupdown/tests/test-ifupdown.c +++ b/src/settings/plugins/ifupdown/tests/test-ifupdown.c @@ -130,46 +130,50 @@ expected_free (Expected *e) } static void -compare_expected_to_ifparser (Expected *e) +compare_expected_to_ifparser (if_parser *parser, Expected *e) { if_block *n; GSList *biter, *kiter; - g_assert_cmpint (g_slist_length (e->blocks), ==, ifparser_get_num_blocks ()); + g_assert_cmpint (g_slist_length (e->blocks), ==, ifparser_get_num_blocks (parser)); - for (n = ifparser_getfirst (), biter = e->blocks; - n && biter; - n = n->next, biter = g_slist_next (biter)) { + biter = e->blocks; + c_list_for_each_entry (n, &parser->block_lst_head, block_lst) { if_data *m; ExpectedBlock *b = biter->data; g_assert (b->type && n->type); g_assert_cmpstr (b->type, ==, n->type); - g_assert (b->name && n->name); + g_assert (b->name); g_assert_cmpstr (b->name, ==, n->name); g_assert_cmpint (g_slist_length (b->keys), ==, ifparser_get_num_info (n)); - for (m = n->info, kiter = b->keys; - m && kiter; - m = m->next, kiter = g_slist_next (kiter)) { + kiter = b->keys; + c_list_for_each_entry (m, &n->data_lst_head, data_lst) { ExpectedKey *k = kiter->data; - g_assert (k->key && m->key); + g_assert (k->key); g_assert_cmpstr (k->key, ==, m->key); g_assert (k->data && m->data); g_assert_cmpstr (k->data, ==, m->data); + + kiter = g_slist_next (kiter); } + g_assert (!kiter); + + biter = g_slist_next (biter); } + g_assert (!biter); } static void -dump_blocks (void) +dump_blocks (if_parser *parser) { if_block *n; g_message ("\n***************************************************"); - for (n = ifparser_getfirst (); n != NULL; n = n->next) { + c_list_for_each_entry (n, &parser->block_lst_head, block_lst) { if_data *m; // each block start with its type & name @@ -178,8 +182,8 @@ dump_blocks (void) // each key-value pair within a block is indented & separated by a tab // (single quotes used to show typ & name baoundaries) - for (m = n->info; m != NULL; m = m->next) - g_print("\t'%s'\t'%s'\n", m->key, m->data); + c_list_for_each_entry (m, &n->data_lst_head, data_lst) + g_print("\t'%s'\t'%s'\n", m->key, m->data); // blocks are separated by an empty line g_print("\n"); @@ -187,21 +191,24 @@ dump_blocks (void) g_message ("##################################################\n"); } -static void -init_ifparser_with_file (const char *path, const char *file) +static if_parser * +init_ifparser_with_file (const char *file) { - char *tmp; + if_parser *parser; + gs_free char *tmp = NULL; - tmp = g_strdup_printf ("%s/%s", path, file); - ifparser_init (tmp, 1); - g_free (tmp); + tmp = g_strdup_printf ("%s/%s", TEST_DIR, file); + parser = ifparser_parse (tmp, 1); + g_assert (parser); + return parser; } static void -test1_ignore_line_before_first_block (const char *path) +test1_ignore_line_before_first_block (void) { Expected *e; ExpectedBlock *b; + nm_auto_ifparser if_parser *parser = init_ifparser_with_file ("test1"); e = expected_new (); b = expected_block_new ("auto", "eth0"); @@ -210,35 +217,33 @@ test1_ignore_line_before_first_block (const char *path) expected_add_block (e, b); expected_block_add_key (b, expected_key_new ("inet", "dhcp")); - init_ifparser_with_file (path, "test1"); - compare_expected_to_ifparser (e); + compare_expected_to_ifparser (parser, e); - ifparser_destroy (); expected_free (e); } static void -test2_wrapped_line (const char *path) +test2_wrapped_line (void) { Expected *e; ExpectedBlock *b; + nm_auto_ifparser if_parser *parser = init_ifparser_with_file ("test2"); e = expected_new (); b = expected_block_new ("auto", "lo"); expected_add_block (e, b); - init_ifparser_with_file (path, "test2"); - compare_expected_to_ifparser (e); + compare_expected_to_ifparser (parser, e); - ifparser_destroy (); expected_free (e); } static void -test3_wrapped_multiline_multiarg (const char *path) +test3_wrapped_multiline_multiarg (void) { Expected *e; ExpectedBlock *b; + nm_auto_ifparser if_parser *parser = init_ifparser_with_file ("test3"); e = expected_new (); b = expected_block_new ("allow-hotplug", "eth0"); @@ -248,35 +253,33 @@ test3_wrapped_multiline_multiarg (const char *path) b = expected_block_new ("allow-hotplug", "bnep0"); expected_add_block (e, b); - init_ifparser_with_file (path, "test3"); - compare_expected_to_ifparser (e); + compare_expected_to_ifparser (parser, e); - ifparser_destroy (); expected_free (e); } static void -test4_allow_auto_is_auto (const char *path) +test4_allow_auto_is_auto (void) { Expected *e; ExpectedBlock *b; + nm_auto_ifparser if_parser *parser = init_ifparser_with_file ("test4"); e = expected_new (); b = expected_block_new ("auto", "eth0"); expected_add_block (e, b); - init_ifparser_with_file (path, "test4"); - compare_expected_to_ifparser (e); + compare_expected_to_ifparser (parser, e); - ifparser_destroy (); expected_free (e); } static void -test5_allow_auto_multiarg (const char *path) +test5_allow_auto_multiarg (void) { Expected *e; ExpectedBlock *b; + nm_auto_ifparser if_parser *parser = init_ifparser_with_file ("test5"); e = expected_new (); b = expected_block_new ("allow-hotplug", "eth0"); @@ -284,52 +287,50 @@ test5_allow_auto_multiarg (const char *path) b = expected_block_new ("allow-hotplug", "wlan0"); expected_add_block (e, b); - init_ifparser_with_file (path, "test5"); - compare_expected_to_ifparser (e); + compare_expected_to_ifparser (parser, e); - ifparser_destroy (); expected_free (e); } static void -test6_mixed_whitespace (const char *path) +test6_mixed_whitespace (void) { Expected *e; ExpectedBlock *b; + nm_auto_ifparser if_parser *parser = init_ifparser_with_file ("test6"); e = expected_new (); b = expected_block_new ("iface", "lo"); expected_block_add_key (b, expected_key_new ("inet", "loopback")); expected_add_block (e, b); - init_ifparser_with_file (path, "test6"); - compare_expected_to_ifparser (e); + compare_expected_to_ifparser (parser, e); - ifparser_destroy (); expected_free (e); } static void -test7_long_line (const char *path) +test7_long_line (void) { - init_ifparser_with_file (path, "test7"); - g_assert_cmpint (ifparser_get_num_blocks (), ==, 0); - ifparser_destroy (); + nm_auto_ifparser if_parser *parser = init_ifparser_with_file ("test7"); + + g_assert_cmpint (ifparser_get_num_blocks (parser), ==, 0); } static void -test8_long_line_wrapped (const char *path) +test8_long_line_wrapped (void) { - init_ifparser_with_file (path, "test8"); - g_assert_cmpint (ifparser_get_num_blocks (), ==, 0); - ifparser_destroy (); + nm_auto_ifparser if_parser *parser = init_ifparser_with_file ("test8"); + + g_assert_cmpint (ifparser_get_num_blocks (parser), ==, 0); } static void -test9_wrapped_lines_in_block (const char *path) +test9_wrapped_lines_in_block (void) { Expected *e; ExpectedBlock *b; + nm_auto_ifparser if_parser *parser = init_ifparser_with_file ("test9"); e = expected_new (); b = expected_block_new ("iface", "eth0"); @@ -340,18 +341,17 @@ test9_wrapped_lines_in_block (const char *path) expected_block_add_key (b, expected_key_new ("broadcast", "10.250.2.63")); expected_block_add_key (b, expected_key_new ("gateway", "10.250.2.50")); - init_ifparser_with_file (path, "test9"); - compare_expected_to_ifparser (e); + compare_expected_to_ifparser (parser, e); - ifparser_destroy (); expected_free (e); } static void -test11_complex_wrap (const char *path) +test11_complex_wrap (void) { Expected *e; ExpectedBlock *b; + nm_auto_ifparser if_parser *parser = init_ifparser_with_file ("test11"); e = expected_new (); b = expected_block_new ("iface", "pppoe"); @@ -359,18 +359,17 @@ test11_complex_wrap (const char *path) expected_block_add_key (b, expected_key_new ("inet", "manual")); expected_block_add_key (b, expected_key_new ("pre-up", "/sbin/ifconfig eth0 up")); - init_ifparser_with_file (path, "test11"); - compare_expected_to_ifparser (e); + compare_expected_to_ifparser (parser, e); - ifparser_destroy (); expected_free (e); } static void -test12_complex_wrap_split_word (const char *path) +test12_complex_wrap_split_word (void) { Expected *e; ExpectedBlock *b; + nm_auto_ifparser if_parser *parser = init_ifparser_with_file ("test12"); e = expected_new (); b = expected_block_new ("iface", "pppoe"); @@ -378,36 +377,34 @@ test12_complex_wrap_split_word (const char *path) expected_block_add_key (b, expected_key_new ("inet", "manual")); expected_block_add_key (b, expected_key_new ("up", "ifup ppp0=dsl")); - init_ifparser_with_file (path, "test12"); - compare_expected_to_ifparser (e); + compare_expected_to_ifparser (parser, e); - ifparser_destroy (); expected_free (e); } static void -test13_more_mixed_whitespace (const char *path) +test13_more_mixed_whitespace (void) { Expected *e; ExpectedBlock *b; + nm_auto_ifparser if_parser *parser = init_ifparser_with_file ("test13"); e = expected_new (); b = expected_block_new ("iface", "dsl"); expected_block_add_key (b, expected_key_new ("inet", "ppp")); expected_add_block (e, b); - init_ifparser_with_file (path, "test13"); - compare_expected_to_ifparser (e); + compare_expected_to_ifparser (parser, e); - ifparser_destroy (); expected_free (e); } static void -test14_mixed_whitespace_block_start (const char *path) +test14_mixed_whitespace_block_start (void) { Expected *e; ExpectedBlock *b; + nm_auto_ifparser if_parser *parser = init_ifparser_with_file ("test14"); e = expected_new (); b = expected_block_new ("iface", "wlan0"); @@ -420,47 +417,43 @@ test14_mixed_whitespace_block_start (const char *path) expected_block_add_key (b, expected_key_new ("inet", "dhcp")); expected_add_block (e, b); - init_ifparser_with_file (path, "test14"); - compare_expected_to_ifparser (e); + compare_expected_to_ifparser (parser, e); - ifparser_destroy (); expected_free (e); } static void -test15_trailing_space (const char *path) +test15_trailing_space (void) { Expected *e; ExpectedBlock *b; + nm_auto_ifparser if_parser *parser = init_ifparser_with_file ("test15"); e = expected_new (); b = expected_block_new ("iface", "bnep0"); expected_block_add_key (b, expected_key_new ("inet", "static")); expected_add_block (e, b); - init_ifparser_with_file (path, "test15"); - compare_expected_to_ifparser (e); + compare_expected_to_ifparser (parser, e); - ifparser_destroy (); expected_free (e); } static void -test16_missing_newline (const char *path) +test16_missing_newline (void) { Expected *e; + nm_auto_ifparser if_parser *parser = init_ifparser_with_file ("test16"); e = expected_new (); expected_add_block (e, expected_block_new ("mapping", "eth0")); - init_ifparser_with_file (path, "test16"); - compare_expected_to_ifparser (e); + compare_expected_to_ifparser (parser, e); - ifparser_destroy (); expected_free (e); } static void -test17_read_static_ipv4 (const char *path) +test17_read_static_ipv4 (void) { NMConnection *connection; NMSettingConnection *s_con; @@ -470,13 +463,13 @@ test17_read_static_ipv4 (const char *path) gboolean success; NMIPAddress *ip4_addr; if_block *block = NULL; + nm_auto_ifparser if_parser *parser = init_ifparser_with_file ("test17-wired-static-verify-ip4"); - init_ifparser_with_file (path, "test17-wired-static-verify-ip4"); - block = ifparser_getfirst (); + block = ifparser_getfirst (parser); connection = nm_simple_connection_new(); g_assert (connection); - ifupdown_update_connection_from_if_block(connection, block, &error); + ifupdown_update_connection_from_if_block (connection, block, &error); g_assert_no_error (error); success = nm_connection_verify (connection, &error); @@ -511,12 +504,11 @@ test17_read_static_ipv4 (const char *path) g_assert_cmpstr (nm_setting_ip_config_get_dns_search (s_ip4, 0), ==, "example.com"); g_assert_cmpstr (nm_setting_ip_config_get_dns_search (s_ip4, 1), ==, "foo.example.com"); - ifparser_destroy (); g_object_unref (connection); } static void -test18_read_static_ipv6 (const char *path) +test18_read_static_ipv6 (void) { NMConnection *connection; NMSettingConnection *s_con; @@ -526,12 +518,12 @@ test18_read_static_ipv6 (const char *path) gboolean success; NMIPAddress *ip6_addr; if_block *block = NULL; + nm_auto_ifparser if_parser *parser = init_ifparser_with_file ("test18-wired-static-verify-ip6"); - init_ifparser_with_file (path, "test18-wired-static-verify-ip6"); - block = ifparser_getfirst (); + block = ifparser_getfirst (parser); connection = nm_simple_connection_new(); g_assert (connection); - ifupdown_update_connection_from_if_block(connection, block, &error); + ifupdown_update_connection_from_if_block (connection, block, &error); g_assert_no_error (error); success = nm_connection_verify (connection, &error); @@ -566,12 +558,11 @@ test18_read_static_ipv6 (const char *path) g_assert_cmpstr (nm_setting_ip_config_get_dns_search (s_ip6, 0), ==, "example.com"); g_assert_cmpstr (nm_setting_ip_config_get_dns_search (s_ip6, 1), ==, "foo.example.com"); - ifparser_destroy (); g_object_unref (connection); } static void -test19_read_static_ipv4_plen (const char *path) +test19_read_static_ipv4_plen (void) { NMConnection *connection; NMSettingIPConfig *s_ip4; @@ -579,12 +570,12 @@ test19_read_static_ipv4_plen (const char *path) NMIPAddress *ip4_addr; if_block *block = NULL; gboolean success; + nm_auto_ifparser if_parser *parser = init_ifparser_with_file ("test19-wired-static-verify-ip4-plen"); - init_ifparser_with_file (path, "test19-wired-static-verify-ip4-plen"); - block = ifparser_getfirst (); + block = ifparser_getfirst (parser); connection = nm_simple_connection_new(); g_assert (connection); - ifupdown_update_connection_from_if_block(connection, block, &error); + ifupdown_update_connection_from_if_block (connection, block, &error); g_assert_no_error (error); success = nm_connection_verify (connection, &error); @@ -601,15 +592,15 @@ test19_read_static_ipv4_plen (const char *path) g_assert_cmpstr (nm_ip_address_get_address (ip4_addr), ==, "10.0.0.3"); g_assert_cmpint (nm_ip_address_get_prefix (ip4_addr), ==, 8); - ifparser_destroy (); g_object_unref (connection); } static void -test20_source_stanza (const char *path) +test20_source_stanza (void) { Expected *e; ExpectedBlock *b; + nm_auto_ifparser if_parser *parser = init_ifparser_with_file ("test20-source-stanza"); e = expected_new (); @@ -625,18 +616,17 @@ test20_source_stanza (const char *path) expected_add_block (e, b); expected_block_add_key (b, expected_key_new ("inet", "dhcp")); - init_ifparser_with_file (path, "test20-source-stanza"); - compare_expected_to_ifparser (e); + compare_expected_to_ifparser (parser, e); - ifparser_destroy (); expected_free (e); } static void -test21_source_dir_stanza (const char *path) +test21_source_dir_stanza (void) { Expected *e; ExpectedBlock *b; + nm_auto_ifparser if_parser *parser = init_ifparser_with_file ("test21-source-dir-stanza"); e = expected_new (); @@ -646,10 +636,8 @@ test21_source_dir_stanza (const char *path) expected_add_block (e, b); expected_block_add_key (b, expected_key_new ("inet", "dhcp")); - init_ifparser_with_file (path, "test21-source-dir-stanza"); - compare_expected_to_ifparser (e); + compare_expected_to_ifparser (parser, e); - ifparser_destroy (); expected_free (e); } @@ -660,49 +648,28 @@ main (int argc, char **argv) { nmtst_init_assert_logging (&argc, &argv, "WARN", "DEFAULT"); - if (0) - dump_blocks (); - - g_test_add_data_func ("/ifupdate/ignore_line_before_first_block", TEST_DIR, - (GTestDataFunc) test1_ignore_line_before_first_block); - g_test_add_data_func ("/ifupdate/wrapped_line", TEST_DIR, - (GTestDataFunc) test2_wrapped_line); - g_test_add_data_func ("/ifupdate/wrapped_multiline_multiarg", TEST_DIR, - (GTestDataFunc) test3_wrapped_multiline_multiarg); - g_test_add_data_func ("/ifupdate/allow_auto_is_auto", TEST_DIR, - (GTestDataFunc) test4_allow_auto_is_auto); - g_test_add_data_func ("/ifupdate/allow_auto_multiarg", TEST_DIR, - (GTestDataFunc) test5_allow_auto_multiarg); - g_test_add_data_func ("/ifupdate/mixed_whitespace", TEST_DIR, - (GTestDataFunc) test6_mixed_whitespace); - g_test_add_data_func ("/ifupdate/long_line", TEST_DIR, - (GTestDataFunc) test7_long_line); - g_test_add_data_func ("/ifupdate/long_line_wrapped", TEST_DIR, - (GTestDataFunc) test8_long_line_wrapped); - g_test_add_data_func ("/ifupdate/wrapped_lines_in_block", TEST_DIR, - (GTestDataFunc) test9_wrapped_lines_in_block); - g_test_add_data_func ("/ifupdate/complex_wrap", TEST_DIR, - (GTestDataFunc) test11_complex_wrap); - g_test_add_data_func ("/ifupdate/complex_wrap_split_word", TEST_DIR, - (GTestDataFunc) test12_complex_wrap_split_word); - g_test_add_data_func ("/ifupdate/more_mixed_whitespace", TEST_DIR, - (GTestDataFunc) test13_more_mixed_whitespace); - g_test_add_data_func ("/ifupdate/mixed_whitespace_block_start", TEST_DIR, - (GTestDataFunc) test14_mixed_whitespace_block_start); - g_test_add_data_func ("/ifupdate/trailing_space", TEST_DIR, - (GTestDataFunc) test15_trailing_space); - g_test_add_data_func ("/ifupdate/missing_newline", TEST_DIR, - (GTestDataFunc) test16_missing_newline); - g_test_add_data_func ("/ifupdate/read_static_ipv4", TEST_DIR, - (GTestDataFunc) test17_read_static_ipv4); - g_test_add_data_func ("/ifupdate/read_static_ipv6", TEST_DIR, - (GTestDataFunc) test18_read_static_ipv6); - g_test_add_data_func ("/ifupdate/read_static_ipv4_plen", TEST_DIR, - (GTestDataFunc) test19_read_static_ipv4_plen); - g_test_add_data_func ("/ifupdate/source_stanza", TEST_DIR, - (GTestDataFunc) test20_source_stanza); - g_test_add_data_func ("/ifupdate/source_dir_stanza", TEST_DIR, - (GTestDataFunc) test21_source_dir_stanza); + (void) dump_blocks; + + g_test_add_func ("/ifupdate/ignore_line_before_first_block", test1_ignore_line_before_first_block); + g_test_add_func ("/ifupdate/wrapped_line", test2_wrapped_line); + g_test_add_func ("/ifupdate/wrapped_multiline_multiarg", test3_wrapped_multiline_multiarg); + g_test_add_func ("/ifupdate/allow_auto_is_auto", test4_allow_auto_is_auto); + g_test_add_func ("/ifupdate/allow_auto_multiarg", test5_allow_auto_multiarg); + g_test_add_func ("/ifupdate/mixed_whitespace", test6_mixed_whitespace); + g_test_add_func ("/ifupdate/long_line", test7_long_line); + g_test_add_func ("/ifupdate/long_line_wrapped", test8_long_line_wrapped); + g_test_add_func ("/ifupdate/wrapped_lines_in_block", test9_wrapped_lines_in_block); + g_test_add_func ("/ifupdate/complex_wrap", test11_complex_wrap); + g_test_add_func ("/ifupdate/complex_wrap_split_word", test12_complex_wrap_split_word); + g_test_add_func ("/ifupdate/more_mixed_whitespace", test13_more_mixed_whitespace); + g_test_add_func ("/ifupdate/mixed_whitespace_block_start", test14_mixed_whitespace_block_start); + g_test_add_func ("/ifupdate/trailing_space", test15_trailing_space); + g_test_add_func ("/ifupdate/missing_newline", test16_missing_newline); + g_test_add_func ("/ifupdate/read_static_ipv4", test17_read_static_ipv4); + g_test_add_func ("/ifupdate/read_static_ipv6", test18_read_static_ipv6); + g_test_add_func ("/ifupdate/read_static_ipv4_plen", test19_read_static_ipv4_plen); + g_test_add_func ("/ifupdate/source_stanza", test20_source_stanza); + g_test_add_func ("/ifupdate/source_dir_stanza", test21_source_dir_stanza); return g_test_run (); } diff --git a/src/settings/plugins/keyfile/nms-keyfile-connection.c b/src/settings/plugins/keyfile/nms-keyfile-connection.c index 5f72a9fa..7511f206 100644 --- a/src/settings/plugins/keyfile/nms-keyfile-connection.c +++ b/src/settings/plugins/keyfile/nms-keyfile-connection.c @@ -66,6 +66,7 @@ commit_changes (NMSettingsConnection *connection, nm_assert (!out_logmsg_change || !*out_logmsg_change); if (!nms_keyfile_writer_connection (new_connection, + TRUE, nm_settings_connection_get_filename (connection), NM_FLAGS_ALL (commit_reason, NM_SETTINGS_CONNECTION_COMMIT_REASON_USER_ACTION | NM_SETTINGS_CONNECTION_COMMIT_REASON_ID_CHANGED), @@ -75,9 +76,7 @@ commit_changes (NMSettingsConnection *connection, error)) return FALSE; - /* Update the filename if it changed */ - if ( path - && g_strcmp0 (path, nm_settings_connection_get_filename (connection)) != 0) { + if (!nm_streq0 (path, nm_settings_connection_get_filename (connection))) { gs_free char *old_path = g_strdup (nm_settings_connection_get_filename (connection)); nm_settings_connection_set_filename (connection, path); @@ -125,6 +124,7 @@ nms_keyfile_connection_init (NMSKeyfileConnection *connection) NMSKeyfileConnection * nms_keyfile_connection_new (NMConnection *source, const char *full_path, + const char *profile_dir, GError **error) { GObject *object; @@ -132,17 +132,19 @@ nms_keyfile_connection_new (NMConnection *source, const char *uuid; gboolean update_unsaved = TRUE; - g_assert (source || full_path); + nm_assert (source || full_path); + nm_assert (!full_path || full_path[0] == '/'); + nm_assert (!profile_dir || profile_dir[0] == '/'); /* If we're given a connection already, prefer that instead of re-reading */ if (source) tmp = g_object_ref (source); else { - tmp = nms_keyfile_reader_from_file (full_path, error); + tmp = nms_keyfile_reader_from_file (full_path, profile_dir, error); if (!tmp) return NULL; - uuid = nm_connection_get_uuid (NM_CONNECTION (tmp)); + uuid = nm_connection_get_uuid (tmp); if (!uuid) { g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, "Connection in file %s had no UUID", full_path); @@ -154,9 +156,9 @@ nms_keyfile_connection_new (NMConnection *source, update_unsaved = FALSE; } - object = (GObject *) g_object_new (NMS_TYPE_KEYFILE_CONNECTION, - NM_SETTINGS_CONNECTION_FILENAME, full_path, - NULL); + object = g_object_new (NMS_TYPE_KEYFILE_CONNECTION, + NM_SETTINGS_CONNECTION_FILENAME, full_path, + NULL); /* Update our settings with what was read from the file */ if (!nm_settings_connection_update (NM_SETTINGS_CONNECTION (object), diff --git a/src/settings/plugins/keyfile/nms-keyfile-connection.h b/src/settings/plugins/keyfile/nms-keyfile-connection.h index f96d7590..0773ced0 100644 --- a/src/settings/plugins/keyfile/nms-keyfile-connection.h +++ b/src/settings/plugins/keyfile/nms-keyfile-connection.h @@ -37,7 +37,8 @@ typedef struct _NMSKeyfileConnectionClass NMSKeyfileConnectionClass; GType nms_keyfile_connection_get_type (void); NMSKeyfileConnection *nms_keyfile_connection_new (NMConnection *source, - const char *filename, + const char *full_path, + const char *profile_dir, GError **error); #endif /* __NMS_KEYFILE_CONNECTION_H__ */ diff --git a/src/settings/plugins/keyfile/nms-keyfile-plugin.c b/src/settings/plugins/keyfile/nms-keyfile-plugin.c index 3723db94..346b78c0 100644 --- a/src/settings/plugins/keyfile/nms-keyfile-plugin.c +++ b/src/settings/plugins/keyfile/nms-keyfile-plugin.c @@ -56,19 +56,15 @@ typedef struct { } NMSKeyfilePluginPrivate; struct _NMSKeyfilePlugin { - GObject parent; + NMSettingsPlugin parent; NMSKeyfilePluginPrivate _priv; }; struct _NMSKeyfilePluginClass { - GObjectClass parent; + NMSettingsPluginClass parent; }; -static void settings_plugin_interface_init (NMSettingsPluginInterface *plugin_iface); - -G_DEFINE_TYPE_EXTENDED (NMSKeyfilePlugin, nms_keyfile_plugin, G_TYPE_OBJECT, 0, - G_IMPLEMENT_INTERFACE (NM_TYPE_SETTINGS_PLUGIN, - settings_plugin_interface_init)) +G_DEFINE_TYPE (NMSKeyfilePlugin, nms_keyfile_plugin, NM_TYPE_SETTINGS_PLUGIN) #define NMS_KEYFILE_PLUGIN_GET_PRIVATE(self) _NM_GET_PRIVATE (self, NMSKeyfilePlugin, NMS_IS_KEYFILE_PLUGIN) @@ -85,10 +81,10 @@ G_DEFINE_TYPE_EXTENDED (NMSKeyfilePlugin, nms_keyfile_plugin, G_TYPE_OBJECT, 0, /*****************************************************************************/ static void -connection_removed_cb (NMSettingsConnection *obj, gpointer user_data) +connection_removed_cb (NMSettingsConnection *sett_conn, NMSKeyfilePlugin *self) { - g_hash_table_remove (NMS_KEYFILE_PLUGIN_GET_PRIVATE ((NMSKeyfilePlugin *) user_data)->connections, - nm_connection_get_uuid (NM_CONNECTION (obj))); + g_hash_table_remove (NMS_KEYFILE_PLUGIN_GET_PRIVATE (self)->connections, + nm_settings_connection_get_uuid (sett_conn)); } /* Monitoring */ @@ -106,7 +102,7 @@ remove_connection (NMSKeyfilePlugin *self, NMSKeyfileConnection *connection) g_object_ref (connection); g_signal_handlers_disconnect_by_func (connection, connection_removed_cb, self); removed = g_hash_table_remove (NMS_KEYFILE_PLUGIN_GET_PRIVATE (self)->connections, - nm_connection_get_uuid (NM_CONNECTION (connection))); + nm_settings_connection_get_uuid (NM_SETTINGS_CONNECTION (connection))); nm_settings_connection_signal_remove (NM_SETTINGS_CONNECTION (connection)); g_object_unref (connection); @@ -175,6 +171,7 @@ update_connection (NMSKeyfilePlugin *self, NMSKeyfileConnection *connection_by_uuid; GError *local = NULL; const char *uuid; + int dir_len; g_return_val_if_fail (!source || NM_IS_CONNECTION (source), NULL); g_return_val_if_fail (full_path || source, NULL); @@ -182,7 +179,23 @@ update_connection (NMSKeyfilePlugin *self, if (full_path) _LOGD ("loading from file \"%s\"...", full_path); - connection_new = nms_keyfile_connection_new (source, full_path, &local); + if (g_str_has_prefix (full_path, nms_keyfile_utils_get_path ())) { + dir_len = strlen (nms_keyfile_utils_get_path ()); + } else if (g_str_has_prefix (full_path, NM_CONFIG_KEYFILE_PATH_IN_MEMORY)) { + dir_len = NM_STRLEN (NM_CONFIG_KEYFILE_PATH_IN_MEMORY); + } else { + /* Just make sure the file name is not going go pass the following check. */ + dir_len = strlen (full_path); + } + + if ( full_path[dir_len] != '/' + || strchr (full_path + dir_len + 1, '/') != NULL) { + g_set_error_literal (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED, + "File not in recognized system-connections directory"); + return FALSE; + } + + connection_new = nms_keyfile_connection_new (source, full_path, nms_keyfile_utils_get_path (), &local); if (!connection_new) { /* Error; remove the connection */ if (source) @@ -197,7 +210,7 @@ update_connection (NMSKeyfilePlugin *self, return NULL; } - uuid = nm_connection_get_uuid (NM_CONNECTION (connection_new)); + uuid = nm_settings_connection_get_uuid (NM_SETTINGS_CONNECTION (connection_new)); connection_by_uuid = g_hash_table_lookup (priv->connections, uuid); if ( connection @@ -240,8 +253,8 @@ update_connection (NMSKeyfilePlugin *self, old_path = nm_settings_connection_get_filename (NM_SETTINGS_CONNECTION (connection_by_uuid)); - if (nm_connection_compare (NM_CONNECTION (connection_by_uuid), - NM_CONNECTION (connection_new), + if (nm_connection_compare (nm_settings_connection_get_connection (NM_SETTINGS_CONNECTION (connection_by_uuid)), + nm_settings_connection_get_connection (NM_SETTINGS_CONNECTION (connection_new)), NM_SETTING_COMPARE_FLAG_IGNORE_AGENT_OWNED_SECRETS | NM_SETTING_COMPARE_FLAG_IGNORE_NOT_SAVED_SECRETS)) { /* Nothing to do... except updating the path. */ @@ -259,7 +272,7 @@ update_connection (NMSKeyfilePlugin *self, _LOGI ("update and persist "NMS_KEYFILE_CONNECTION_LOG_FMT, NMS_KEYFILE_CONNECTION_LOG_ARG (connection_new)); if (!nm_settings_connection_update (NM_SETTINGS_CONNECTION (connection_by_uuid), - NM_CONNECTION (connection_new), + nm_settings_connection_get_connection (NM_SETTINGS_CONNECTION (connection_new)), NM_SETTINGS_CONNECTION_PERSIST_MODE_KEEP_SAVED, NM_SETTINGS_CONNECTION_COMMIT_REASON_NONE, "keyfile-update", @@ -287,8 +300,10 @@ update_connection (NMSKeyfilePlugin *self, if (!source) { /* Only raise the signal if we were called without source, i.e. if we read the connection from file. * Otherwise, we were called by add_connection() which does not expect the signal. */ - g_signal_emit_by_name (self, NM_SETTINGS_PLUGIN_CONNECTION_ADDED, connection_new); + _nm_settings_plugin_emit_signal_connection_added (NM_SETTINGS_PLUGIN (self), + NM_SETTINGS_CONNECTION (connection_new)); } + return connection_new; } } @@ -307,7 +322,7 @@ dir_changed (GFileMonitor *monitor, gboolean exists; full_path = g_file_get_path (file); - if (nms_keyfile_utils_should_ignore_file (full_path)) { + if (nms_keyfile_utils_should_ignore_file (full_path, FALSE)) { g_free (full_path); return; } @@ -341,13 +356,14 @@ config_changed_cb (NMConfig *config, NMConfigData *old_data, NMSKeyfilePlugin *self) { - gs_free char *old_value = NULL, *new_value = NULL; + gs_free char *old_value = NULL; + gs_free char *new_value = NULL; old_value = nm_config_data_get_value (old_data, NM_CONFIG_KEYFILE_GROUP_KEYFILE, NM_CONFIG_KEYFILE_KEY_KEYFILE_UNMANAGED_DEVICES, NM_CONFIG_GET_VALUE_TYPE_SPEC); new_value = nm_config_data_get_value (config_data, NM_CONFIG_KEYFILE_GROUP_KEYFILE, NM_CONFIG_KEYFILE_KEY_KEYFILE_UNMANAGED_DEVICES, NM_CONFIG_GET_VALUE_TYPE_SPEC); - if (g_strcmp0 (old_value, new_value) != 0) - g_signal_emit_by_name (self, NM_SETTINGS_PLUGIN_UNMANAGED_SPECS_CHANGED); + if (!nm_streq0 (old_value, new_value)) + _nm_settings_plugin_emit_signal_unmanaged_specs_changed (NM_SETTINGS_PLUGIN (self)); } static void @@ -412,13 +428,35 @@ _sort_paths (const char **f1, const char **f2, GHashTable *paths) } static void +_read_dir (GPtrArray *filenames, + const char *path, + gboolean require_extension) +{ + GDir *dir; + const char *item; + GError *error = NULL; + + dir = g_dir_open (path, 0, &error); + if (!dir) { + _LOGD ("cannot read directory '%s': %s", path, error->message); + g_clear_error (&error); + return; + } + + while ((item = g_dir_read_name (dir))) { + if (nms_keyfile_utils_should_ignore_file (item, require_extension)) + continue; + g_ptr_array_add (filenames, g_build_filename (path, item, NULL)); + } + g_dir_close (dir); +} + + +static void read_connections (NMSettingsPlugin *config) { NMSKeyfilePlugin *self = NMS_KEYFILE_PLUGIN (config); NMSKeyfilePluginPrivate *priv = NMS_KEYFILE_PLUGIN_GET_PRIVATE (self); - GDir *dir; - GError *error = NULL; - const char *item; GHashTable *alive_connections; GHashTableIter iter; NMSKeyfileConnection *connection; @@ -427,24 +465,12 @@ read_connections (NMSettingsPlugin *config) GPtrArray *filenames; GHashTable *paths; - dir = g_dir_open (nms_keyfile_utils_get_path (), 0, &error); - if (!dir) { - _LOGW ("cannot read directory '%s': %s", - nms_keyfile_utils_get_path (), - error->message); - g_clear_error (&error); - return; - } + filenames = g_ptr_array_new_with_free_func (g_free); - alive_connections = g_hash_table_new (nm_direct_hash, NULL); + _read_dir (filenames, NM_CONFIG_KEYFILE_PATH_IN_MEMORY, TRUE); + _read_dir (filenames, nms_keyfile_utils_get_path (), FALSE); - filenames = g_ptr_array_new_with_free_func (g_free); - while ((item = g_dir_read_name (dir))) { - if (nms_keyfile_utils_should_ignore_file (item)) - continue; - g_ptr_array_add (filenames, g_build_filename (nms_keyfile_utils_get_path (), item, NULL)); - } - g_dir_close (dir); + alive_connections = g_hash_table_new (nm_direct_hash, NULL); /* While reloading, we don't replace connections that we already loaded while * iterating over the files. @@ -497,19 +523,61 @@ get_connections (NMSettingsPlugin *config) } static gboolean +_file_is_in_path (const char *abs_filename, + const char *abs_path) +{ + gsize l; + + /* FIXME: ensure that both paths are at least normalized (coalescing ".", + * duplicate '/', and trailing '/'). */ + + nm_assert (abs_filename && abs_filename[0] == '/'); + nm_assert (abs_path && abs_path[0] == '/'); + + l = strlen (abs_path); + if (strncmp (abs_filename, abs_path, l) != 0) + return FALSE; + + abs_filename += l; + while (abs_filename[0] == '/') + abs_filename++; + + if (!abs_filename[0]) + return FALSE; + + if (strchr (abs_filename, '/')) + return FALSE; + + return TRUE; +} + +static gboolean load_connection (NMSettingsPlugin *config, const char *filename) { NMSKeyfilePlugin *self = NMS_KEYFILE_PLUGIN ((NMSKeyfilePlugin *) config); NMSKeyfileConnection *connection; - int dir_len = strlen (nms_keyfile_utils_get_path ()); + gboolean require_extension; - if ( strncmp (filename, nms_keyfile_utils_get_path (), dir_len) != 0 - || filename[dir_len] != '/' - || strchr (filename + dir_len + 1, '/') != NULL) + /* the test whether to require a file extension tries to figure out whether + * the provided filename is inside /etc or /run. + * + * However, on Posix a filename just resolves to an Inode, and there can + * be any kind of paths that point to the same Inode. It's not generally possible + * to check for that (unless, we would stat all files in the target directory + * and see whether their inode matches). + * + * So, when loading the file do something simpler: require that the path + * starts with the well-known prefix. This rejects symlinks or hard links + * which would actually also point to the same file. */ + if (_file_is_in_path (filename, nms_keyfile_utils_get_path ())) + require_extension = FALSE; + else if (_file_is_in_path (filename, NM_CONFIG_KEYFILE_PATH_IN_MEMORY)) + require_extension = TRUE; + else return FALSE; - if (nms_keyfile_utils_should_ignore_file (filename + dir_len + 1)) + if (nms_keyfile_utils_should_ignore_file (filename, require_extension)) return FALSE; connection = update_connection (self, NULL, filename, find_by_path (self, filename), TRUE, NULL, NULL); @@ -533,16 +601,16 @@ add_connection (NMSettingsPlugin *config, gs_free char *path = NULL; gs_unref_object NMConnection *reread = NULL; - if (save_to_disk) { - if (!nms_keyfile_writer_connection (connection, - NULL, - FALSE, - &path, - &reread, - NULL, - error)) - return NULL; - } + if (!nms_keyfile_writer_connection (connection, + save_to_disk, + NULL, + FALSE, + &path, + &reread, + NULL, + error)) + return NULL; + return NM_SETTINGS_CONNECTION (update_connection (self, reread ?: connection, path, NULL, FALSE, NULL, error)); } @@ -616,20 +684,17 @@ dispose (GObject *object) } static void -nms_keyfile_plugin_class_init (NMSKeyfilePluginClass *req_class) +nms_keyfile_plugin_class_init (NMSKeyfilePluginClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (req_class); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMSettingsPluginClass *plugin_class = NM_SETTINGS_PLUGIN_CLASS (klass); object_class->constructed = constructed; - object_class->dispose = dispose; -} + object_class->dispose = dispose; -static void -settings_plugin_interface_init (NMSettingsPluginInterface *plugin_iface) -{ - plugin_iface->get_connections = get_connections; - plugin_iface->load_connection = load_connection; - plugin_iface->reload_connections = reload_connections; - plugin_iface->add_connection = add_connection; - plugin_iface->get_unmanaged_specs = get_unmanaged_specs; + plugin_class->get_connections = get_connections; + plugin_class->load_connection = load_connection; + plugin_class->reload_connections = reload_connections; + plugin_class->add_connection = add_connection; + plugin_class->get_unmanaged_specs = get_unmanaged_specs; } diff --git a/src/settings/plugins/keyfile/nms-keyfile-reader.c b/src/settings/plugins/keyfile/nms-keyfile-reader.c index cb4b8379..580a857a 100644 --- a/src/settings/plugins/keyfile/nms-keyfile-reader.c +++ b/src/settings/plugins/keyfile/nms-keyfile-reader.c @@ -28,6 +28,7 @@ #include "nm-keyfile-internal.h" #include "NetworkManagerUtils.h" +#include "nms-keyfile-utils.h" /*****************************************************************************/ @@ -102,53 +103,87 @@ _handler_read (GKeyFile *keyfile, NMConnection * nms_keyfile_reader_from_keyfile (GKeyFile *key_file, const char *filename, + const char *base_dir, + const char *profile_dir, gboolean verbose, GError **error) { + NMConnection *connection; HandlerReadData data = { .verbose = verbose, }; + gs_free char *base_dir_free = NULL; + gs_free char *profile_filename_free = NULL; + gs_free char *filename_id = NULL; + const char *profile_filename = NULL; + + nm_assert (filename && filename[0]); + nm_assert (!base_dir || base_dir[0] == '/'); + nm_assert (!profile_dir || profile_dir[0] == '/'); + + if (base_dir) + nm_assert (!strchr (filename, '/')); + else { + const char *s; + + nm_assert (filename[0] == '/'); + + /* @base_dir may be NULL, in which case @filename must be an absolute path, + * and the directory is taken as the @base_dir. */ + s = strrchr (filename, '/'); + base_dir = nm_strndup_a (255, filename, s - filename, &base_dir_free); + if ( !profile_dir + || nm_streq (base_dir, profile_dir)) + profile_filename = filename; + filename = &s[1]; + } + + connection = nm_keyfile_read (key_file, base_dir, _handler_read, &data, error); + if (!connection) + return NULL; + + if (g_str_has_suffix (filename, NMS_KEYFILE_PATH_SUFFIX_NMCONNECTION)) { + gsize l = strlen (filename); - return nm_keyfile_read (key_file, filename, NULL, _handler_read, &data, error); + if (l > NM_STRLEN (NMS_KEYFILE_PATH_SUFFIX_NMCONNECTION)) + filename_id = g_strndup (filename, l - NM_STRLEN (NMS_KEYFILE_PATH_SUFFIX_NMCONNECTION)); + } + + nm_keyfile_read_ensure_id (connection, filename_id ?: filename); + + if (!profile_filename) { + profile_filename_free = g_build_filename (profile_dir ?: base_dir, filename, NULL); + profile_filename = profile_filename_free; + } + nm_keyfile_read_ensure_uuid (connection, profile_filename); + + return connection; } NMConnection * -nms_keyfile_reader_from_file (const char *filename, GError **error) +nms_keyfile_reader_from_file (const char *full_filename, + const char *profile_dir, + GError **error) { - GKeyFile *key_file; - struct stat statbuf; + gs_unref_keyfile GKeyFile *key_file = NULL; NMConnection *connection = NULL; GError *verify_error = NULL; - if (stat (filename, &statbuf) != 0 || !S_ISREG (statbuf.st_mode)) { - g_set_error_literal (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, - "File did not exist or was not a regular file"); - return NULL; - } + nm_assert (full_filename && full_filename[0] == '/'); + nm_assert (!profile_dir || profile_dir[0] == '/'); - if (!NM_FLAGS_HAS (nm_utils_get_testing (), NM_UTILS_TEST_NO_KEYFILE_OWNER_CHECK)) { - if (statbuf.st_mode & 0077) { - g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, - "File permissions (%o) were insecure", - statbuf.st_mode); - return NULL; - } - - if (statbuf.st_uid != 0) { - g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, - "File owner (%o) is insecure", - statbuf.st_mode); - return NULL; - } - } + if (!nms_keyfile_utils_check_file_permissions (full_filename, + NULL, + error)) + return NULL; key_file = g_key_file_new (); - if (!g_key_file_load_from_file (key_file, filename, G_KEY_FILE_NONE, error)) - goto out; + if (!g_key_file_load_from_file (key_file, full_filename, G_KEY_FILE_NONE, error)) + return NULL; - connection = nms_keyfile_reader_from_keyfile (key_file, filename, TRUE, error); + connection = nms_keyfile_reader_from_keyfile (key_file, full_filename, NULL, profile_dir, TRUE, error); if (!connection) - goto out; + return NULL; /* Normalize and verify the connection */ if (!nm_connection_normalize (connection, NULL, NULL, &verify_error)) { @@ -160,8 +195,6 @@ nms_keyfile_reader_from_file (const char *filename, GError **error) connection = NULL; } -out: - g_key_file_free (key_file); return connection; } diff --git a/src/settings/plugins/keyfile/nms-keyfile-reader.h b/src/settings/plugins/keyfile/nms-keyfile-reader.h index b60c1e69..c0fb06d1 100644 --- a/src/settings/plugins/keyfile/nms-keyfile-reader.h +++ b/src/settings/plugins/keyfile/nms-keyfile-reader.h @@ -26,9 +26,13 @@ NMConnection *nms_keyfile_reader_from_keyfile (GKeyFile *key_file, const char *filename, + const char *base_dir, + const char *profile_dir, gboolean verbose, GError **error); -NMConnection *nms_keyfile_reader_from_file (const char *filename, GError **error); +NMConnection *nms_keyfile_reader_from_file (const char *full_filename, + const char *profile_dir, + GError **error); #endif /* __NMS_KEYFILE_READER_H__ */ diff --git a/src/settings/plugins/keyfile/nms-keyfile-utils.c b/src/settings/plugins/keyfile/nms-keyfile-utils.c index 03f06670..c3bfcdee 100644 --- a/src/settings/plugins/keyfile/nms-keyfile-utils.c +++ b/src/settings/plugins/keyfile/nms-keyfile-utils.c @@ -24,6 +24,7 @@ #include <stdlib.h> #include <string.h> +#include <sys/stat.h> #include "nm-setting-wired.h" #include "nm-setting-wireless.h" @@ -55,18 +56,11 @@ check_mkstemp_suffix (const char *path) } static gboolean -check_prefix (const char *base, const char *tag) +check_prefix_dot (const char *base) { - int len, tag_len; + nm_assert (base && base[0]); - g_return_val_if_fail (base != NULL, TRUE); - g_return_val_if_fail (tag != NULL, TRUE); - - len = strlen (base); - tag_len = strlen (tag); - if ((len > tag_len) && !g_ascii_strncasecmp (base, tag, tag_len)) - return TRUE; - return FALSE; + return base[0] == '.'; } static gboolean @@ -90,7 +84,7 @@ check_suffix (const char *base, const char *tag) #define DER_TAG ".der" gboolean -nms_keyfile_utils_should_ignore_file (const char *filename) +nms_keyfile_utils_should_ignore_file (const char *filename, gboolean require_extension) { gs_free char *base = NULL; @@ -101,7 +95,7 @@ nms_keyfile_utils_should_ignore_file (const char *filename) /* Ignore hidden and backup files */ /* should_ignore_file() must mirror escape_filename() */ - if (check_prefix (base, ".") || check_suffix (base, "~")) + if (check_prefix_dot (base) || check_suffix (base, "~")) return TRUE; /* Ignore temporary files */ if (check_mkstemp_suffix (base)) @@ -110,18 +104,87 @@ nms_keyfile_utils_should_ignore_file (const char *filename) if (check_suffix (base, PEM_TAG) || check_suffix (base, DER_TAG)) return TRUE; + if (require_extension) { + gsize l = strlen (base); + + if ( l <= NM_STRLEN (NMS_KEYFILE_PATH_SUFFIX_NMCONNECTION) + || !g_str_has_suffix (base, NMS_KEYFILE_PATH_SUFFIX_NMCONNECTION)) + return TRUE; + } + return FALSE; } +/*****************************************************************************/ + +gboolean +nms_keyfile_utils_check_file_permissions_stat (const struct stat *st, + GError **error) +{ + g_return_val_if_fail (st, FALSE); + + if (!S_ISREG (st->st_mode)) { + g_set_error_literal (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, + "file is not a regular file"); + return FALSE; + } + + if (!NM_FLAGS_HAS (nm_utils_get_testing (), NM_UTILS_TEST_NO_KEYFILE_OWNER_CHECK)) { + if (st->st_uid != 0) { + g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, + "File owner (%lld) is insecure", + (long long) st->st_uid); + return FALSE; + } + + if (st->st_mode & 0077) { + g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, + "File permissions (%03o) are insecure", + st->st_mode); + return FALSE; + } + } + + return TRUE; +} + +gboolean +nms_keyfile_utils_check_file_permissions (const char *filename, + struct stat *out_st, + GError **error) +{ + struct stat st; + int errsv; + + g_return_val_if_fail (filename && filename[0] == '/', FALSE); + + if (stat (filename, &st) != 0) { + errsv = errno; + g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, + "cannot access file: %s", g_strerror (errsv)); + return FALSE; + } + + if (!nms_keyfile_utils_check_file_permissions_stat (&st, error)) + return FALSE; + + NM_SET_OUT (out_st, st); + return TRUE; +} + +/*****************************************************************************/ + char * -nms_keyfile_utils_escape_filename (const char *filename) +nms_keyfile_utils_escape_filename (const char *filename, + gboolean with_extension) { GString *str; const char *f = filename; - const char ESCAPE_CHAR = '*'; - /* keyfile used to escape with '*', do not change that behavior. - * But for newly added escapings, use '_' instead. */ + * + * But for newly added escapings, use '_' instead. + * Also, @with_extension is new-style. */ + const char ESCAPE_CHAR = with_extension ? '_' : '*'; const char ESCAPE_CHAR2 = '_'; g_return_val_if_fail (filename && filename[0], NULL); @@ -138,7 +201,7 @@ nms_keyfile_utils_escape_filename (const char *filename) /* escape_filename() must avoid anything that should_ignore_file() would reject. * We can escape here more aggressivly then what we would read back. */ - if (check_prefix (str->str, ".")) + if (check_prefix_dot (str->str)) str->str[0] = ESCAPE_CHAR2; if (check_suffix (str->str, "~")) str->str[str->len - 1] = ESCAPE_CHAR2; @@ -147,6 +210,9 @@ nms_keyfile_utils_escape_filename (const char *filename) || check_suffix (str->str, DER_TAG)) g_string_append_c (str, ESCAPE_CHAR2); + if (with_extension) + g_string_append (str, NMS_KEYFILE_PATH_SUFFIX_NMCONNECTION); + return g_string_free (str, FALSE);; } diff --git a/src/settings/plugins/keyfile/nms-keyfile-utils.h b/src/settings/plugins/keyfile/nms-keyfile-utils.h index cd3f42b9..297dd4ea 100644 --- a/src/settings/plugins/keyfile/nms-keyfile-utils.h +++ b/src/settings/plugins/keyfile/nms-keyfile-utils.h @@ -23,16 +23,28 @@ #include "NetworkManagerUtils.h" +#define NM_CONFIG_KEYFILE_PATH_IN_MEMORY NMRUNDIR "/system-connections" + +#define NMS_KEYFILE_PATH_SUFFIX_NMCONNECTION ".nmconnection" + #define NMS_KEYFILE_CONNECTION_LOG_PATH(path) ((path) ?: "in-memory") #define NMS_KEYFILE_CONNECTION_LOG_FMT "%s (%s,\"%s\")" -#define NMS_KEYFILE_CONNECTION_LOG_ARG(con) NMS_KEYFILE_CONNECTION_LOG_PATH (nm_settings_connection_get_filename ((NMSettingsConnection *) (con))), nm_connection_get_uuid ((NMConnection *) (con)), nm_connection_get_id ((NMConnection *) (con)) +#define NMS_KEYFILE_CONNECTION_LOG_ARG(con) NMS_KEYFILE_CONNECTION_LOG_PATH (nm_settings_connection_get_filename ((NMSettingsConnection *) (con))), nm_settings_connection_get_uuid ((NMSettingsConnection *) (con)), nm_settings_connection_get_id ((NMSettingsConnection *) (con)) #define NMS_KEYFILE_CONNECTION_LOG_FMTD "%s (%s,\"%s\",%p)" -#define NMS_KEYFILE_CONNECTION_LOG_ARGD(con) NMS_KEYFILE_CONNECTION_LOG_PATH (nm_settings_connection_get_filename ((NMSettingsConnection *) (con))), nm_connection_get_uuid ((NMConnection *) (con)), nm_connection_get_id ((NMConnection *) (con)), (con) +#define NMS_KEYFILE_CONNECTION_LOG_ARGD(con) NMS_KEYFILE_CONNECTION_LOG_PATH (nm_settings_connection_get_filename ((NMSettingsConnection *) (con))), nm_settings_connection_get_uuid ((NMSettingsConnection *) (con)), nm_settings_connection_get_id ((NMSettingsConnection *) (con)), (con) -gboolean nms_keyfile_utils_should_ignore_file (const char *filename); +gboolean nms_keyfile_utils_should_ignore_file (const char *filename, gboolean require_extension); -char *nms_keyfile_utils_escape_filename (const char *filename); +char *nms_keyfile_utils_escape_filename (const char *filename, gboolean with_extension); const char *nms_keyfile_utils_get_path (void); +struct stat; +gboolean nms_keyfile_utils_check_file_permissions_stat (const struct stat *st, + GError **error); + +gboolean nms_keyfile_utils_check_file_permissions (const char *filename, + struct stat *out_st, + GError **error); + #endif /* __NMS_KEYFILE_UTILS_H__ */ diff --git a/src/settings/plugins/keyfile/nms-keyfile-writer.c b/src/settings/plugins/keyfile/nms-keyfile-writer.c index 270a217e..df26ea60 100644 --- a/src/settings/plugins/keyfile/nms-keyfile-writer.c +++ b/src/settings/plugins/keyfile/nms-keyfile-writer.c @@ -34,6 +34,8 @@ #include "nms-keyfile-utils.h" #include "nms-keyfile-reader.h" +#include "nm-utils/nm-io-utils.h" + /*****************************************************************************/ typedef struct { @@ -127,7 +129,7 @@ cert_writer (NMConnection *connection, new_path = g_strdup_printf ("%s/%s-%s.%s", info->keyfile_dir, nm_connection_get_uuid (connection), cert_data->vtable->file_suffix, ext); - success = nm_utils_file_set_contents (new_path, (const gchar *) blob_data, + success = nm_utils_file_set_contents (new_path, (const char *) blob_data, blob_len, 0600, &local); if (success) { /* Write the path value to the keyfile. @@ -170,6 +172,8 @@ _handler_write (NMConnection *connection, static gboolean _internal_write_connection (NMConnection *connection, const char *keyfile_dir, + const char *profile_dir, + gboolean with_extension, uid_t owner_uid, pid_t owner_grp, const char *existing_path, @@ -187,10 +191,14 @@ _internal_write_connection (NMConnection *connection, WriteInfo info = { 0 }; GError *local_err = NULL; int errsv; + gboolean rename = force_rename; g_return_val_if_fail (!out_path || !*out_path, FALSE); g_return_val_if_fail (keyfile_dir && keyfile_dir[0] == '/', FALSE); + if (existing_path && !g_str_has_prefix (existing_path, keyfile_dir)) + rename = TRUE; + switch (_nm_connection_verify (connection, error)) { case NM_SETTING_VERIFY_NORMALIZABLE: nm_assert_not_reached (); @@ -219,10 +227,10 @@ _internal_write_connection (NMConnection *connection, /* If we have existing file path, use it. Else generate one from * connection's ID. */ - if (existing_path != NULL && !force_rename) { + if (existing_path != NULL && !rename) { path = g_strdup (existing_path); } else { - char *filename_escaped = nms_keyfile_utils_escape_filename (id); + char *filename_escaped = nms_keyfile_utils_escape_filename (id, with_extension); path = g_build_filename (keyfile_dir, filename_escaped, NULL); g_free (filename_escaped); @@ -248,7 +256,7 @@ _internal_write_connection (NMConnection *connection, else filename = g_strdup_printf ("%s-%s-%u", id, nm_connection_get_uuid (connection), i); - filename_escaped = nms_keyfile_utils_escape_filename (filename); + filename_escaped = nms_keyfile_utils_escape_filename (filename, with_extension); g_free (path); path = g_strdup_printf ("%s/%s", keyfile_dir, filename_escaped); @@ -297,17 +305,12 @@ _internal_write_connection (NMConnection *connection, return FALSE; } - if (out_path && g_strcmp0 (existing_path, path)) { - *out_path = path; /* pass path out to caller */ - path = NULL; - } - if (out_reread || out_reread_same) { gs_unref_object NMConnection *reread = NULL; gboolean reread_same = FALSE; - reread = nms_keyfile_reader_from_keyfile (key_file, path, FALSE, NULL); + reread = nms_keyfile_reader_from_keyfile (key_file, path, NULL, profile_dir, FALSE, NULL); nm_assert (NM_IS_CONNECTION (reread)); @@ -333,11 +336,14 @@ _internal_write_connection (NMConnection *connection, NM_SET_OUT (out_reread_same, reread_same); } + NM_SET_OUT (out_path, g_steal_pointer (&path)); + return TRUE; } gboolean nms_keyfile_writer_connection (NMConnection *connection, + gboolean save_to_disk, const char *existing_path, gboolean force_rename, char **out_path, @@ -345,9 +351,19 @@ nms_keyfile_writer_connection (NMConnection *connection, gboolean *out_reread_same, GError **error) { + const char *keyfile_dir; + + if (save_to_disk) + keyfile_dir = nms_keyfile_utils_get_path (); + else + keyfile_dir = NM_CONFIG_KEYFILE_PATH_IN_MEMORY; + return _internal_write_connection (connection, + keyfile_dir, nms_keyfile_utils_get_path (), - 0, 0, + TRUE, + 0, + 0, existing_path, force_rename, out_path, @@ -368,7 +384,10 @@ nms_keyfile_writer_test_connection (NMConnection *connection, { return _internal_write_connection (connection, keyfile_dir, - owner_uid, owner_grp, + keyfile_dir, + FALSE, + owner_uid, + owner_grp, NULL, FALSE, out_path, diff --git a/src/settings/plugins/keyfile/nms-keyfile-writer.h b/src/settings/plugins/keyfile/nms-keyfile-writer.h index ac41dfa2..030fb7cc 100644 --- a/src/settings/plugins/keyfile/nms-keyfile-writer.h +++ b/src/settings/plugins/keyfile/nms-keyfile-writer.h @@ -25,6 +25,7 @@ #include "nm-connection.h" gboolean nms_keyfile_writer_connection (NMConnection *connection, + gboolean save_to_disk, const char *existing_path, gboolean force_rename, char **out_path, diff --git a/src/settings/plugins/keyfile/tests/meson.build b/src/settings/plugins/keyfile/tests/meson.build index 33aaa264..8b94b256 100644 --- a/src/settings/plugins/keyfile/tests/meson.build +++ b/src/settings/plugins/keyfile/tests/meson.build @@ -6,7 +6,6 @@ exe = executable( test_unit, test_unit + '.c', dependencies: test_nm_dep, - c_args: nm_build_cflags, ) test( diff --git a/src/settings/plugins/keyfile/tests/test-keyfile.c b/src/settings/plugins/keyfile/tests/test-keyfile.c index a3045f7d..4a0e01b3 100644 --- a/src/settings/plugins/keyfile/tests/test-keyfile.c +++ b/src/settings/plugins/keyfile/tests/test-keyfile.c @@ -65,37 +65,32 @@ check_ip_route (NMSettingIPConfig *config, int idx, const char *destination, int g_assert_cmpint (nm_ip_route_get_metric (route), ==, metric); } -static NMConnection * -keyfile_read_connection_from_file (const char *filename) -{ - gs_free_error GError *error = NULL; - NMConnection *connection; - - g_assert (filename); - - connection = nms_keyfile_reader_from_file (filename, &error); - g_assert_no_error (error); - - nmtst_assert_connection_verifies_without_normalization (connection); - - return connection; -} +#define keyfile_read_connection_from_file(full_filename) \ +({ \ + gs_free_error GError *_error = NULL; \ + NMConnection *_connection; \ + \ + g_assert (full_filename && full_filename[0] == '/'); \ + \ + _connection = nms_keyfile_reader_from_file (full_filename, \ + NULL, \ + (nmtst_get_rand_int () % 2) ? &_error : NULL); \ + nmtst_assert_success (_connection, _error); \ + nmtst_assert_connection_verifies_without_normalization (_connection); \ + \ + _connection; \ +}) static void assert_reread (NMConnection *connection, gboolean normalize_connection, const char *testfile) { gs_unref_object NMConnection *reread = NULL; gs_unref_object NMConnection *connection_clone = NULL; - GError *error = NULL; - GError **p_error = (nmtst_get_rand_int () % 2) ? &error : NULL; NMSettingConnection *s_con; g_assert (NM_IS_CONNECTION (connection)); - g_assert (testfile && testfile[0]); - reread = nms_keyfile_reader_from_file (testfile, p_error); - g_assert_no_error (error); - g_assert (NM_IS_CONNECTION (reread)); + reread = keyfile_read_connection_from_file (testfile); if ( !normalize_connection && (s_con = nm_connection_get_setting_connection (connection)) @@ -229,10 +224,8 @@ test_read_valid_wired_connection (void) NMSettingIPConfig *s_ip4; NMSettingIPConfig *s_ip6; NMIPRoute *route; - gs_free_error GError *error = NULL; const char *mac; char expected_mac_address[ETH_ALEN] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 }; - gboolean success; NMTST_EXPECT_NM_INFO ("*ipv4.addresses:*semicolon at the end*addresses1*"); NMTST_EXPECT_NM_INFO ("*ipv4.addresses:*semicolon at the end*addresses2*"); @@ -249,16 +242,9 @@ test_read_valid_wired_connection (void) NMTST_EXPECT_NM_INFO ("*ipv6.address*semicolon at the end*address7*"); NMTST_EXPECT_NM_INFO ("*ipv6.routes*semicolon at the end*routes1*"); NMTST_EXPECT_NM_INFO ("*ipv6.route*semicolon at the end*route6*"); - connection = nms_keyfile_reader_from_file (TEST_KEYFILES_DIR "/Test_Wired_Connection", &error); - g_assert_no_error (error); + connection = keyfile_read_connection_from_file (TEST_KEYFILES_DIR "/Test_Wired_Connection"); g_test_assert_expected_messages (); - g_assert (connection); - - success = nm_connection_verify (connection, &error); - g_assert_no_error (error); - g_assert (success); - /* ===== CONNECTION SETTING ===== */ s_con = nm_connection_get_setting_connection (connection); g_assert (s_con); g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, "Test Wired Connection"); @@ -266,7 +252,6 @@ test_read_valid_wired_connection (void) g_assert_cmpuint (nm_setting_connection_get_timestamp (s_con), ==, 6654332); g_assert (nm_setting_connection_get_autoconnect (s_con)); - /* ===== WIRED SETTING ===== */ s_wired = nm_connection_get_setting_wired (connection); g_assert (s_wired); @@ -275,7 +260,6 @@ test_read_valid_wired_connection (void) g_assert (nm_utils_hwaddr_matches (mac, -1, expected_mac_address, sizeof (expected_mac_address))); g_assert_cmpint (nm_setting_wired_get_mtu (s_wired), ==, 1400); - /* ===== IPv4 SETTING ===== */ s_ip4 = nm_connection_get_setting_ip4_config (connection); g_assert (s_ip4); g_assert_cmpstr (nm_setting_ip_config_get_method (s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_MANUAL); @@ -324,7 +308,6 @@ test_read_valid_wired_connection (void) nmtst_assert_route_attribute_boolean (route, NM_IP_ROUTE_ATTRIBUTE_LOCK_CWND, TRUE); nmtst_assert_route_attribute_string (route, NM_IP_ROUTE_ATTRIBUTE_SRC, "7.7.7.7"); - /* ===== IPv6 SETTING ===== */ s_ip6 = nm_connection_get_setting_ip6_config (connection); g_assert (s_ip6); @@ -535,32 +518,22 @@ test_read_ip6_wired_connection (void) NMSettingWired *s_wired; NMSettingIPConfig *s_ip4; NMSettingIPConfig *s_ip6; - gs_free_error GError *error = NULL; - gboolean success; - connection = nms_keyfile_reader_from_file (TEST_KEYFILES_DIR "/Test_Wired_Connection_IP6", NULL); - g_assert (connection); - success = nm_connection_verify (connection, &error); - g_assert_no_error (error); - g_assert (success); + connection = keyfile_read_connection_from_file (TEST_KEYFILES_DIR "/Test_Wired_Connection_IP6"); - /* ===== CONNECTION SETTING ===== */ s_con = nm_connection_get_setting_connection (connection); g_assert (s_con); g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, "Test Wired Connection IP6"); g_assert_cmpstr (nm_setting_connection_get_uuid (s_con), ==, "4e80a56d-c99f-4aad-a6dd-b449bc398c57"); - /* ===== WIRED SETTING ===== */ s_wired = nm_connection_get_setting_wired (connection); g_assert (s_wired); - /* ===== IPv4 SETTING ===== */ s_ip4 = nm_connection_get_setting_ip4_config (connection); g_assert (s_ip4); g_assert_cmpstr (nm_setting_ip_config_get_method (s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_DISABLED); g_assert_cmpint (nm_setting_ip_config_get_num_addresses (s_ip4), ==, 0); - /* ===== IPv6 SETTING ===== */ s_ip6 = nm_connection_get_setting_ip6_config (connection); g_assert (s_ip6); g_assert_cmpstr (nm_setting_ip_config_get_method (s_ip6), ==, NM_SETTING_IP6_CONFIG_METHOD_MANUAL); @@ -638,28 +611,20 @@ test_read_wired_mac_case (void) gs_unref_object NMConnection *connection = NULL; NMSettingConnection *s_con; NMSettingWired *s_wired; - gs_free_error GError *error = NULL; const char *mac; char expected_mac_address[ETH_ALEN] = { 0x00, 0x11, 0xaa, 0xbb, 0xcc, 0x55 }; - gboolean success; NMTST_EXPECT_NM_INFO ("*ipv4.addresses*semicolon at the end*addresses1*"); NMTST_EXPECT_NM_INFO ("*ipv4.addresses*semicolon at the end*addresses2*"); NMTST_EXPECT_NM_INFO ("*ipv6.routes*semicolon at the end*routes1*"); - connection = nms_keyfile_reader_from_file (TEST_KEYFILES_DIR "/Test_Wired_Connection_MAC_Case", NULL); + connection = keyfile_read_connection_from_file (TEST_KEYFILES_DIR "/Test_Wired_Connection_MAC_Case"); g_test_assert_expected_messages (); - g_assert (connection); - success = nm_connection_verify (connection, &error); - g_assert_no_error (error); - g_assert (success); - /* ===== CONNECTION SETTING ===== */ s_con = nm_connection_get_setting_connection (connection); g_assert (s_con); g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, "Test Wired Connection MAC Case"); g_assert_cmpstr (nm_setting_connection_get_uuid (s_con), ==, "4e80a56d-c99f-4aad-a6dd-b449bc398c57"); - /* ===== WIRED SETTING ===== */ s_wired = nm_connection_get_setting_wired (connection); g_assert (s_wired); mac = nm_setting_wired_get_mac_address (s_wired); @@ -672,29 +637,19 @@ test_read_mac_old_format (void) { gs_unref_object NMConnection *connection = NULL; NMSettingWired *s_wired; - gs_free_error GError *error = NULL; - gboolean success; const char *mac; char expected_mac[ETH_ALEN] = { 0x00, 0x11, 0xaa, 0xbb, 0xcc, 0x55 }; char expected_cloned_mac[ETH_ALEN] = { 0x00, 0x16, 0xaa, 0xbb, 0xcc, 0xfe }; - connection = nms_keyfile_reader_from_file (TEST_KEYFILES_DIR "/Test_MAC_Old_Format", &error); - g_assert_no_error (error); - g_assert (connection); - - success = nm_connection_verify (connection, &error); - g_assert_no_error (error); - g_assert (success); + connection = keyfile_read_connection_from_file (TEST_KEYFILES_DIR "/Test_MAC_Old_Format"); s_wired = nm_connection_get_setting_wired (connection); g_assert (s_wired); - /* MAC address */ mac = nm_setting_wired_get_mac_address (s_wired); g_assert (mac); g_assert (nm_utils_hwaddr_matches (mac, -1, expected_mac, ETH_ALEN)); - /* Cloned MAC address */ mac = nm_setting_wired_get_cloned_mac_address (s_wired); g_assert (mac); g_assert (nm_utils_hwaddr_matches (mac, -1, expected_cloned_mac, ETH_ALEN)); @@ -705,20 +660,12 @@ test_read_mac_ib_old_format (void) { gs_unref_object NMConnection *connection = NULL; NMSettingInfiniband *s_ib; - gs_free_error GError *error = NULL; - gboolean success; const char *mac; guint8 expected_mac[INFINIBAND_ALEN] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, - 0x77, 0x88, 0x99, 0x01, 0x12, 0x23, 0x34, 0x45, 0x56, 0x67, 0x78, 0x89, - 0x90 }; + 0x77, 0x88, 0x99, 0x01, 0x12, 0x23, 0x34, 0x45, 0x56, 0x67, 0x78, 0x89, + 0x90 }; - connection = nms_keyfile_reader_from_file (TEST_KEYFILES_DIR "/Test_MAC_IB_Old_Format", &error); - g_assert_no_error (error); - g_assert (connection); - - success = nm_connection_verify (connection, &error); - g_assert_no_error (error); - g_assert (success); + connection = keyfile_read_connection_from_file (TEST_KEYFILES_DIR "/Test_MAC_IB_Old_Format"); s_ib = nm_connection_get_setting_infiniband (connection); g_assert (s_ib); @@ -736,18 +683,11 @@ test_read_valid_wireless_connection (void) NMSettingConnection *s_con; NMSettingWireless *s_wireless; NMSettingIPConfig *s_ip4; - gs_free_error GError *error = NULL; const char *bssid; const guint8 expected_bssid[ETH_ALEN] = { 0x00, 0x1a, 0x33, 0x44, 0x99, 0x82 }; - gboolean success; - connection = nms_keyfile_reader_from_file (TEST_KEYFILES_DIR "/Test_Wireless_Connection", NULL); - g_assert (connection); - success = nm_connection_verify (connection, &error); - g_assert_no_error (error); - g_assert (success); + connection = keyfile_read_connection_from_file (TEST_KEYFILES_DIR "/Test_Wireless_Connection"); - /* ===== CONNECTION SETTING ===== */ s_con = nm_connection_get_setting_connection (connection); g_assert (s_con); g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, "Test Wireless Connection"); @@ -755,14 +695,12 @@ test_read_valid_wireless_connection (void) g_assert_cmpuint (nm_setting_connection_get_timestamp (s_con), ==, 1226604314); g_assert (nm_setting_connection_get_autoconnect (s_con) == FALSE); - /* ===== WIRELESS SETTING ===== */ s_wireless = nm_connection_get_setting_wireless (connection); g_assert (s_wireless); bssid = nm_setting_wireless_get_bssid (s_wireless); g_assert (bssid); g_assert (nm_utils_hwaddr_matches (bssid, -1, expected_bssid, sizeof (expected_bssid))); - /* ===== IPv4 SETTING ===== */ s_ip4 = nm_connection_get_setting_ip4_config (connection); g_assert (s_ip4); g_assert_cmpstr (nm_setting_ip_config_get_method (s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_AUTO); @@ -838,24 +776,19 @@ test_read_string_ssid (void) { gs_unref_object NMConnection *connection = NULL; NMSettingWireless *s_wireless; - gs_free_error GError *error = NULL; GBytes *ssid; const guint8 *ssid_data; gsize ssid_len; const char *expected_ssid = "blah blah ssid 1234"; - gboolean success; - connection = nms_keyfile_reader_from_file (TEST_KEYFILES_DIR "/Test_String_SSID", NULL); - g_assert (connection); - success = nm_connection_verify (connection, &error); - g_assert_no_error (error); - g_assert (success); + connection = keyfile_read_connection_from_file (TEST_KEYFILES_DIR "/Test_String_SSID"); - /* ===== WIRELESS SETTING ===== */ s_wireless = nm_connection_get_setting_wireless (connection); g_assert (s_wireless); + ssid = nm_setting_wireless_get_ssid (s_wireless); g_assert (ssid); + ssid_data = g_bytes_get_data (ssid, &ssid_len); g_assert_cmpmem (ssid_data, ssid_len, expected_ssid, strlen (expected_ssid)); } @@ -922,22 +855,13 @@ test_read_intlist_ssid (void) { gs_unref_object NMConnection *connection = NULL; NMSettingWireless *s_wifi; - gs_free_error GError *error = NULL; - gboolean success; GBytes *ssid; const guint8 *ssid_data; gsize ssid_len; const char *expected_ssid = "blah1234"; - connection = nms_keyfile_reader_from_file (TEST_KEYFILES_DIR "/Test_Intlist_SSID", &error); - g_assert_no_error (error); - g_assert (connection); - - success = nm_connection_verify (connection, &error); - g_assert_no_error (error); - g_assert (success); + connection = keyfile_read_connection_from_file (TEST_KEYFILES_DIR "/Test_Intlist_SSID"); - /* SSID */ s_wifi = nm_connection_get_setting_wireless (connection); g_assert (s_wifi); @@ -960,7 +884,7 @@ test_write_intlist_ssid (void) unsigned char tmpssid[] = { 65, 49, 50, 51, 0, 50, 50 }; gs_free_error GError *error = NULL; gs_unref_keyfile GKeyFile *keyfile = NULL; - gint *intlist; + int *intlist; gsize len = 0, i; connection = nm_simple_connection_new (); @@ -1015,30 +939,17 @@ test_read_intlike_ssid (void) { gs_unref_object NMConnection *connection = NULL; NMSettingWireless *s_wifi; - gs_free_error GError *error = NULL; - gboolean success; GBytes *ssid; - const guint8 *ssid_data; - gsize ssid_len; const char *expected_ssid = "101"; - connection = nms_keyfile_reader_from_file (TEST_KEYFILES_DIR "/Test_Intlike_SSID", &error); - g_assert_no_error (error); - g_assert (connection); + connection = keyfile_read_connection_from_file (TEST_KEYFILES_DIR "/Test_Intlike_SSID"); - success = nm_connection_verify (connection, &error); - g_assert_no_error (error); - g_assert (success); - - /* SSID */ s_wifi = nm_connection_get_setting_wireless (connection); g_assert (s_wifi); ssid = nm_setting_wireless_get_ssid (s_wifi); - g_assert (ssid != NULL); - ssid_data = g_bytes_get_data (ssid, &ssid_len); - g_assert_cmpint (ssid_len, ==, strlen (expected_ssid)); - g_assert_cmpint (memcmp (ssid_data, expected_ssid, strlen (expected_ssid)), ==, 0); + g_assert (ssid); + g_assert (nm_utils_gbytes_equal_mem (ssid, expected_ssid, strlen (expected_ssid))); } static void @@ -1046,30 +957,17 @@ test_read_intlike_ssid_2 (void) { gs_unref_object NMConnection *connection = NULL; NMSettingWireless *s_wifi; - gs_free_error GError *error = NULL; - gboolean success; GBytes *ssid; - const guint8 *ssid_data; - gsize ssid_len; const char *expected_ssid = "11;12;13;"; - connection = nms_keyfile_reader_from_file (TEST_KEYFILES_DIR "/Test_Intlike_SSID_2", &error); - g_assert_no_error (error); - g_assert (connection); - - success = nm_connection_verify (connection, &error); - g_assert_no_error (error); - g_assert (success); + connection = keyfile_read_connection_from_file (TEST_KEYFILES_DIR "/Test_Intlike_SSID_2"); - /* SSID */ s_wifi = nm_connection_get_setting_wireless (connection); g_assert (s_wifi); ssid = nm_setting_wireless_get_ssid (s_wifi); - g_assert (ssid != NULL); - ssid_data = g_bytes_get_data (ssid, &ssid_len); - g_assert_cmpint (ssid_len, ==, strlen (expected_ssid)); - g_assert_cmpint (memcmp (ssid_data, expected_ssid, strlen (expected_ssid)), ==, 0); + g_assert (ssid); + g_assert (nm_utils_gbytes_equal_mem (ssid, expected_ssid, strlen (expected_ssid))); } static void @@ -1197,24 +1095,16 @@ test_read_bt_dun_connection (void) NMSettingBluetooth *s_bluetooth; NMSettingSerial *s_serial; NMSettingGsm *s_gsm; - gs_free_error GError *error = NULL; const char *bdaddr; const guint8 expected_bdaddr[ETH_ALEN] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 }; - gboolean success; - connection = nms_keyfile_reader_from_file (TEST_KEYFILES_DIR "/ATT_Data_Connect_BT", NULL); - g_assert (connection); - success = nm_connection_verify (connection, &error); - g_assert_no_error (error); - g_assert (success); + connection = keyfile_read_connection_from_file (TEST_KEYFILES_DIR "/ATT_Data_Connect_BT"); - /* ===== CONNECTION SETTING ===== */ s_con = nm_connection_get_setting_connection (connection); g_assert (s_con); g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, "AT&T Data Connect BT"); g_assert_cmpstr (nm_setting_connection_get_uuid (s_con), ==, "089130ab-ce28-46e4-ad77-d44869b03d19"); - /* ===== BLUETOOTH SETTING ===== */ s_bluetooth = nm_connection_get_setting_bluetooth (connection); g_assert (s_bluetooth); bdaddr = nm_setting_bluetooth_get_bdaddr (s_bluetooth); @@ -1222,14 +1112,12 @@ test_read_bt_dun_connection (void) g_assert (nm_utils_hwaddr_matches (bdaddr, -1, expected_bdaddr, sizeof (expected_bdaddr))); g_assert_cmpstr (nm_setting_bluetooth_get_connection_type (s_bluetooth), ==, NM_SETTING_BLUETOOTH_TYPE_DUN); - /* ===== GSM SETTING ===== */ s_gsm = nm_connection_get_setting_gsm (connection); g_assert (s_gsm); g_assert_cmpstr (nm_setting_gsm_get_apn (s_gsm), ==, "ISP.CINGULAR"); g_assert_cmpstr (nm_setting_gsm_get_username (s_gsm), ==, "ISP@CINGULARGPRS.COM"); g_assert_cmpstr (nm_setting_gsm_get_password (s_gsm), ==, "CINGULAR1"); - /* ===== SERIAL SETTING ===== */ s_serial = nm_connection_get_setting_serial (connection); g_assert (s_serial); g_assert (nm_setting_serial_get_parity (s_serial) == NM_SETTING_SERIAL_PARITY_ODD); @@ -1302,28 +1190,17 @@ test_read_gsm_connection (void) NMSettingConnection *s_con; NMSettingSerial *s_serial; NMSettingGsm *s_gsm; - gs_free_error GError *error = NULL; - gboolean success; - connection = nms_keyfile_reader_from_file (TEST_KEYFILES_DIR "/ATT_Data_Connect_Plain", &error); - g_assert_no_error (error); - g_assert (connection); + connection = keyfile_read_connection_from_file (TEST_KEYFILES_DIR "/ATT_Data_Connect_Plain"); - success = nm_connection_verify (connection, &error); - g_assert_no_error (error); - g_assert (success); - - /* ===== CONNECTION SETTING ===== */ s_con = nm_connection_get_setting_connection (connection); g_assert (s_con); g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, "AT&T Data Connect"); g_assert_cmpstr (nm_setting_connection_get_connection_type (s_con), ==, NM_SETTING_GSM_SETTING_NAME); - /* ===== BLUETOOTH SETTING ===== */ /* Plain GSM, so no BT setting expected */ g_assert (nm_connection_get_setting_bluetooth (connection) == NULL); - /* ===== GSM SETTING ===== */ s_gsm = nm_connection_get_setting_gsm (connection); g_assert (s_gsm); g_assert_cmpstr (nm_setting_gsm_get_apn (s_gsm), ==, "ISP.CINGULAR"); @@ -1335,7 +1212,6 @@ test_read_gsm_connection (void) g_assert_cmpstr (nm_setting_gsm_get_sim_id (s_gsm), ==, "89148000000060671234"); g_assert_cmpstr (nm_setting_gsm_get_sim_operator_id (s_gsm), ==, "310260"); - /* ===== SERIAL SETTING ===== */ s_serial = nm_connection_get_setting_serial (connection); g_assert (s_serial); g_assert_cmpint (nm_setting_serial_get_parity (s_serial), ==, NM_SETTING_SERIAL_PARITY_ODD); @@ -1401,25 +1277,16 @@ test_read_wired_8021x_tls_blob_connection (void) gs_unref_object NMConnection *connection = NULL; NMSettingWired *s_wired; NMSetting8021x *s_8021x; - gs_free_error GError *error = NULL; const char *tmp; - gboolean success; GBytes *blob; NMTST_EXPECT_NM_WARN ("keyfile: 802-1x.client-cert: certificate or key file '/CASA/dcbw/Desktop/certinfra/client.pem' does not exist*"); NMTST_EXPECT_NM_WARN ("keyfile: 802-1x.private-key: certificate or key file '/CASA/dcbw/Desktop/certinfra/client.pem' does not exist*"); - connection = nms_keyfile_reader_from_file (TEST_KEYFILES_DIR "/Test_Wired_TLS_Blob", &error); - g_assert_no_error (error); - g_assert (connection); - success = nm_connection_verify (connection, &error); - g_assert_no_error (error); - g_assert (success); + connection = keyfile_read_connection_from_file (TEST_KEYFILES_DIR "/Test_Wired_TLS_Blob"); - /* ===== Wired Setting ===== */ s_wired = nm_connection_get_setting_wired (connection); g_assert (s_wired != NULL); - /* ===== 802.1x Setting ===== */ s_8021x = nm_connection_get_setting_802_1x (connection); g_assert (s_8021x != NULL); @@ -1459,25 +1326,16 @@ test_read_wired_8021x_tls_bad_path_connection (void) gs_unref_object NMConnection *connection = NULL; NMSettingWired *s_wired; NMSetting8021x *s_8021x; - gs_free_error GError *error = NULL; const char *tmp; char *tmp2; - gboolean success; NMTST_EXPECT_NM_WARN ("*does not exist*"); - connection = nms_keyfile_reader_from_file (TEST_KEYFILES_DIR "/Test_Wired_TLS_Path_Missing", &error); + connection = keyfile_read_connection_from_file (TEST_KEYFILES_DIR "/Test_Wired_TLS_Path_Missing"); g_test_assert_expected_messages (); - g_assert_no_error (error); - g_assert (connection); - success = nm_connection_verify (connection, &error); - g_assert_no_error (error); - g_assert (success); - /* ===== Wired Setting ===== */ s_wired = nm_connection_get_setting_wired (connection); g_assert (s_wired != NULL); - /* ===== 802.1x Setting ===== */ s_8021x = nm_connection_get_setting_802_1x (connection); g_assert (s_8021x != NULL); @@ -1513,25 +1371,16 @@ test_read_wired_8021x_tls_old_connection (void) gs_unref_object NMConnection *connection = NULL; NMSettingWired *s_wired; NMSetting8021x *s_8021x; - gs_free_error GError *error = NULL; const char *tmp; - gboolean success; NMTST_EXPECT_NM_WARN ("keyfile: 802-1x.ca-cert: certificate or key file '/CASA/dcbw/Desktop/certinfra/CA/eaptest_ca_cert.pem' does not exist*"); NMTST_EXPECT_NM_WARN ("keyfile: 802-1x.client-cert: certificate or key file '/CASA/dcbw/Desktop/certinfra/client.pem' does not exist*"); NMTST_EXPECT_NM_WARN ("keyfile: 802-1x.private-key: certificate or key file '/CASA/dcbw/Desktop/certinfra/client.pem' does not exist*"); - connection = nms_keyfile_reader_from_file (TEST_KEYFILES_DIR "/Test_Wired_TLS_Old", &error); - g_assert_no_error (error); - g_assert (connection); - success = nm_connection_verify (connection, &error); - g_assert_no_error (error); - g_assert (success); + connection = keyfile_read_connection_from_file (TEST_KEYFILES_DIR "/Test_Wired_TLS_Old"); - /* ===== Wired Setting ===== */ s_wired = nm_connection_get_setting_wired (connection); g_assert (s_wired != NULL); - /* ===== 802.1x Setting ===== */ s_8021x = nm_connection_get_setting_802_1x (connection); g_assert (s_8021x != NULL); @@ -1561,23 +1410,14 @@ test_read_wired_8021x_tls_new_connection (void) gs_unref_object NMConnection *connection = NULL; NMSettingWired *s_wired; NMSetting8021x *s_8021x; - gs_free_error GError *error = NULL; const char *tmp; char *tmp2; - gboolean success; - connection = nms_keyfile_reader_from_file (TEST_KEYFILES_DIR "/Test_Wired_TLS_New", &error); - g_assert_no_error (error); - g_assert (connection); - success = nm_connection_verify (connection, &error); - g_assert_no_error (error); - g_assert (success); + connection = keyfile_read_connection_from_file (TEST_KEYFILES_DIR "/Test_Wired_TLS_New"); - /* ===== Wired Setting ===== */ s_wired = nm_connection_get_setting_wired (connection); g_assert (s_wired != NULL); - /* ===== 802.1x Setting ===== */ s_8021x = nm_connection_get_setting_802_1x (connection); g_assert (s_8021x != NULL); @@ -1698,7 +1538,6 @@ test_write_wired_8021x_tls_connection_path (void) char *tmp, *tmp2; gboolean success; gs_free char *testfile = NULL; - gs_free_error GError *error = NULL; gs_unref_keyfile GKeyFile *keyfile = NULL; gboolean relative = FALSE; gboolean reread_same = FALSE; @@ -1715,12 +1554,7 @@ test_write_wired_8021x_tls_connection_path (void) g_clear_object (&reread); /* Read the connection back in and compare it to the one we just wrote out */ - reread = nms_keyfile_reader_from_file (testfile, &error); - if (!reread) { - g_assert (error); - g_warning ("Failed to re-read test connection: %s", error->message); - g_assert (reread); - } + reread = keyfile_read_connection_from_file (testfile); success = nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT); if (!reread) { @@ -1786,8 +1620,8 @@ test_write_wired_8021x_tls_connection_blob (void) char *new_priv_key; const char *uuid; gboolean reread_same = FALSE; - gs_free_error GError *error = NULL; - GBytes *password_raw = NULL; + GBytes *password_raw; + #define PASSWORD_RAW "password-raw\0test" connection = create_wired_tls_connection (NM_SETTING_802_1X_CK_SCHEME_BLOB); @@ -1830,12 +1664,7 @@ test_write_wired_8021x_tls_connection_blob (void) g_assert (g_file_test (new_priv_key, G_FILE_TEST_EXISTS)); /* Read the connection back in and compare it to the one we just wrote out */ - reread = nms_keyfile_reader_from_file (testfile, &error); - if (!reread) { - g_assert (error); - g_warning ("Failed to re-read test connection: %s", error->message); - g_assert (reread); - } + reread = keyfile_read_connection_from_file (testfile); /* Ensure the re-read connection's certificates use the path scheme */ s_8021x = nm_connection_get_setting_802_1x (reread); @@ -1846,8 +1675,7 @@ test_write_wired_8021x_tls_connection_blob (void) password_raw = nm_setting_802_1x_get_password_raw (s_8021x); g_assert (password_raw); - g_assert (g_bytes_get_size (password_raw) == NM_STRLEN (PASSWORD_RAW)); - g_assert (!memcmp (g_bytes_get_data (password_raw, NULL), PASSWORD_RAW, NM_STRLEN (PASSWORD_RAW))); + g_assert (nm_utils_gbytes_equal_mem (password_raw, PASSWORD_RAW, NM_STRLEN (PASSWORD_RAW))); unlink (testfile); @@ -1876,29 +1704,20 @@ test_read_infiniband_connection (void) gs_unref_object NMConnection *connection = NULL; NMSettingConnection *s_con; NMSettingInfiniband *s_ib; - gs_free_error GError *error = NULL; const char *mac; guint8 expected_mac[INFINIBAND_ALEN] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, - 0x77, 0x88, 0x99, 0x01, 0x12, 0x23, 0x34, 0x45, 0x56, 0x67, 0x78, 0x89, - 0x90 }; + 0x77, 0x88, 0x99, 0x01, 0x12, 0x23, 0x34, 0x45, 0x56, 0x67, 0x78, 0x89, + 0x90 }; const char *expected_id = "Test InfiniBand Connection"; const char *expected_uuid = "4e80a56d-c99f-4aad-a6dd-b449bc398c57"; - gboolean success; - connection = nms_keyfile_reader_from_file (TEST_KEYFILES_DIR "/Test_InfiniBand_Connection", &error); - g_assert_no_error (error); - g_assert (connection); - success = nm_connection_verify (connection, &error); - g_assert_no_error (error); - g_assert (success); + connection = keyfile_read_connection_from_file (TEST_KEYFILES_DIR "/Test_InfiniBand_Connection"); - /* Connection setting */ s_con = nm_connection_get_setting_connection (connection); g_assert (s_con); g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, expected_id); g_assert_cmpstr (nm_setting_connection_get_uuid (s_con), ==, expected_uuid); - /* InfiniBand setting */ s_ib = nm_connection_get_setting_infiniband (connection); g_assert (s_ib); @@ -1966,31 +1785,21 @@ test_read_bridge_main (void) NMSettingConnection *s_con; NMSettingIPConfig *s_ip4; NMSettingBridge *s_bridge; - gs_free_error GError *error = NULL; const char *expected_id = "Test Bridge Main"; const char *expected_uuid = "8f061643-fe41-4d4c-a8d9-097d26e2ad3a"; - gboolean success; - connection = nms_keyfile_reader_from_file (TEST_KEYFILES_DIR "/Test_Bridge_Main", &error); - g_assert_no_error (error); - g_assert (connection); - success = nm_connection_verify (connection, &error); - g_assert_no_error (error); - g_assert (success); + connection = keyfile_read_connection_from_file (TEST_KEYFILES_DIR "/Test_Bridge_Main"); - /* Connection setting */ s_con = nm_connection_get_setting_connection (connection); g_assert (s_con); g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, expected_id); g_assert_cmpstr (nm_setting_connection_get_uuid (s_con), ==, expected_uuid); g_assert_cmpstr (nm_setting_connection_get_interface_name (s_con), ==, "br0"); - /* IPv4 setting */ s_ip4 = nm_connection_get_setting_ip4_config (connection); g_assert (s_ip4); g_assert_cmpstr (nm_setting_ip_config_get_method (s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_AUTO); - /* Bridge setting */ s_bridge = nm_connection_get_setting_bridge (connection); g_assert (s_bridge); g_assert_cmpuint (nm_setting_bridge_get_forward_delay (s_bridge), ==, 2); @@ -2063,19 +1872,11 @@ test_read_bridge_component (void) NMSettingWired *s_wired; const char *mac; guint8 expected_mac[ETH_ALEN] = { 0x00, 0x22, 0x15, 0x59, 0x62, 0x97 }; - gs_free_error GError *error = NULL; const char *expected_id = "Test Bridge Component"; const char *expected_uuid = "d7b4f96c-c45e-4298-bef8-f48574f8c1c0"; - gboolean success; - connection = nms_keyfile_reader_from_file (TEST_KEYFILES_DIR "/Test_Bridge_Component", &error); - g_assert_no_error (error); - g_assert (connection); - success = nm_connection_verify (connection, &error); - g_assert_no_error (error); - g_assert (success); + connection = keyfile_read_connection_from_file (TEST_KEYFILES_DIR "/Test_Bridge_Component"); - /* Connection setting */ s_con = nm_connection_get_setting_connection (connection); g_assert (s_con); g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, expected_id); @@ -2083,14 +1884,12 @@ test_read_bridge_component (void) g_assert_cmpstr (nm_setting_connection_get_master (s_con), ==, "br0"); g_assert (nm_setting_connection_is_slave_type (s_con, NM_SETTING_BRIDGE_SETTING_NAME)); - /* Wired setting */ s_wired = nm_connection_get_setting_wired (connection); g_assert (s_wired); mac = nm_setting_wired_get_mac_address (s_wired); g_assert (mac); g_assert (nm_utils_hwaddr_matches (mac, -1, expected_mac, sizeof (expected_mac))); - /* BridgePort setting */ s_port = nm_connection_get_setting_bridge_port (connection); g_assert (s_port); g_assert (nm_setting_bridge_port_get_hairpin_mode (s_port)); @@ -2155,17 +1954,9 @@ test_read_new_wired_group_name (void) NMSettingWired *s_wired; const char *mac; guint8 expected_mac[ETH_ALEN] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 }; - gs_free_error GError *error = NULL; - gboolean success; - connection = nms_keyfile_reader_from_file (TEST_KEYFILES_DIR"/Test_New_Wired_Group_Name", &error); - g_assert_no_error (error); - g_assert (connection); - success = nm_connection_verify (connection, &error); - g_assert_no_error (error); - g_assert (success); + connection = keyfile_read_connection_from_file (TEST_KEYFILES_DIR"/Test_New_Wired_Group_Name"); - /* Wired setting */ s_wired = nm_connection_get_setting_wired (connection); g_assert (s_wired); g_assert_cmpint (nm_setting_wired_get_mtu (s_wired), ==, 1400); @@ -2186,7 +1977,7 @@ test_write_new_wired_group_name (void) gs_free char *testfile = NULL; gs_free_error GError *error = NULL; char *s; - gint mtu; + int mtu; connection = nm_simple_connection_new (); g_assert (connection); @@ -2234,32 +2025,19 @@ test_read_new_wireless_group_names (void) NMSettingWireless *s_wifi; NMSettingWirelessSecurity *s_wsec; GBytes *ssid; - const guint8 *ssid_data; - gsize ssid_len; const char *expected_ssid = "foobar"; - gs_free_error GError *error = NULL; - gboolean success; - connection = nms_keyfile_reader_from_file (TEST_KEYFILES_DIR"/Test_New_Wireless_Group_Names", &error); - g_assert_no_error (error); - g_assert (connection); - success = nm_connection_verify (connection, &error); - g_assert_no_error (error); - g_assert (success); + connection = keyfile_read_connection_from_file (TEST_KEYFILES_DIR"/Test_New_Wireless_Group_Names"); - /* Wifi setting */ s_wifi = nm_connection_get_setting_wireless (connection); g_assert (s_wifi); ssid = nm_setting_wireless_get_ssid (s_wifi); g_assert (ssid); - ssid_data = g_bytes_get_data (ssid, &ssid_len); - g_assert_cmpint (ssid_len, ==, strlen (expected_ssid)); - g_assert_cmpint (memcmp (ssid_data, expected_ssid, ssid_len), ==, 0); + g_assert (nm_utils_gbytes_equal_mem (ssid, expected_ssid, strlen (expected_ssid))); g_assert_cmpstr (nm_setting_wireless_get_mode (s_wifi), ==, NM_SETTING_WIRELESS_MODE_INFRA); - /* Wifi security setting */ s_wsec = nm_connection_get_setting_wireless_security (connection); g_assert (s_wsec); g_assert_cmpstr (nm_setting_wireless_security_get_key_mgmt (s_wsec), ==, "wpa-psk"); @@ -2344,17 +2122,9 @@ test_read_missing_vlan_setting (void) { gs_unref_object NMConnection *connection = NULL; NMSettingVlan *s_vlan; - gs_free_error GError *error = NULL; - gboolean success; - connection = nms_keyfile_reader_from_file (TEST_KEYFILES_DIR"/Test_Missing_Vlan_Setting", &error); - g_assert_no_error (error); - g_assert (connection); - success = nm_connection_verify (connection, &error); - g_assert_no_error (error); - g_assert (success); + connection = keyfile_read_connection_from_file (TEST_KEYFILES_DIR"/Test_Missing_Vlan_Setting"); - /* Ensure the VLAN setting exists */ s_vlan = nm_connection_get_setting_vlan (connection); g_assert (s_vlan); g_assert_cmpint (nm_setting_vlan_get_id (s_vlan), ==, 0); @@ -2366,17 +2136,9 @@ test_read_missing_vlan_flags (void) { gs_unref_object NMConnection *connection = NULL; NMSettingVlan *s_vlan; - gs_free_error GError *error = NULL; - gboolean success; - connection = nms_keyfile_reader_from_file (TEST_KEYFILES_DIR"/Test_Missing_Vlan_Flags", &error); - g_assert_no_error (error); - g_assert (connection); - success = nm_connection_verify (connection, &error); - g_assert_no_error (error); - g_assert (success); + connection = keyfile_read_connection_from_file (TEST_KEYFILES_DIR"/Test_Missing_Vlan_Flags"); - /* Ensure the VLAN setting exists */ s_vlan = nm_connection_get_setting_vlan (connection); g_assert (s_vlan); @@ -2389,19 +2151,15 @@ static void test_read_missing_id_uuid (void) { gs_unref_object NMConnection *connection = NULL; - gs_free_error GError *error = NULL; - gboolean success; + gs_free char *expected_uuid = NULL; + const char *FILENAME = TEST_KEYFILES_DIR"/Test_Missing_ID_UUID"; - connection = nms_keyfile_reader_from_file (TEST_KEYFILES_DIR"/Test_Missing_ID_UUID", &error); - g_assert_no_error (error); - g_assert (connection); - success = nm_connection_verify (connection, &error); - g_assert_no_error (error); - g_assert (success); + expected_uuid = _nm_utils_uuid_generate_from_strings ("keyfile", FILENAME, NULL); + + connection = keyfile_read_connection_from_file (FILENAME); - /* Ensure the ID and UUID properties are there */ g_assert_cmpstr (nm_connection_get_id (connection), ==, "Test_Missing_ID_UUID"); - g_assert (nm_connection_get_uuid (connection)); + g_assert_cmpstr (nm_connection_get_uuid (connection), ==, expected_uuid); } static void @@ -2489,17 +2247,9 @@ test_read_enum_property (void) { gs_unref_object NMConnection *connection = NULL; NMSettingIPConfig *s_ip6; - gs_free_error GError *error = NULL; - gboolean success; - connection = nms_keyfile_reader_from_file (TEST_KEYFILES_DIR"/Test_Enum_Property", &error); - g_assert_no_error (error); - g_assert (connection); - success = nm_connection_verify (connection, &error); - g_assert_no_error (error); - g_assert (success); + connection = keyfile_read_connection_from_file (TEST_KEYFILES_DIR"/Test_Enum_Property"); - /* IPv6 setting */ s_ip6 = nm_connection_get_setting_ip6_config (connection); g_assert (s_ip6); g_assert_cmpint (nm_setting_ip6_config_get_ip6_privacy (NM_SETTING_IP6_CONFIG (s_ip6)), ==, NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR); @@ -2549,17 +2299,9 @@ test_read_flags_property (void) { gs_unref_object NMConnection *connection = NULL; NMSettingGsm *s_gsm; - gs_free_error GError *error = NULL; - gboolean success; - connection = nms_keyfile_reader_from_file (TEST_KEYFILES_DIR"/Test_Flags_Property", &error); - g_assert_no_error (error); - g_assert (connection); - success = nm_connection_verify (connection, &error); - g_assert_no_error (error); - g_assert (success); + connection = keyfile_read_connection_from_file (TEST_KEYFILES_DIR"/Test_Flags_Property"); - /* GSM setting */ s_gsm = nm_connection_get_setting_gsm (connection); g_assert (s_gsm); g_assert_cmpint (nm_setting_gsm_get_password_flags (s_gsm), ==, @@ -2612,14 +2354,8 @@ test_read_tc_config (void) NMTCQdisc *qdisc1, *qdisc2; NMTCAction *action1, *action2; NMTCTfilter *tfilter1, *tfilter2; - gs_free_error GError *error = NULL; - gboolean success; - connection = nms_keyfile_reader_from_file (TEST_KEYFILES_DIR "/Test_TC_Config", NULL); - g_assert (connection); - success = nm_connection_verify (connection, &error); - g_assert_no_error (error); - g_assert (success); + connection = keyfile_read_connection_from_file (TEST_KEYFILES_DIR "/Test_TC_Config"); s_tc = nm_connection_get_setting_tc_config (connection); g_assert (s_tc); @@ -2724,49 +2460,51 @@ test_write_tc_config (void) /*****************************************************************************/ static void -_escape_filename (const char *filename, gboolean would_be_ignored) +_escape_filename (gboolean with_extension, const char *filename, gboolean would_be_ignored) { gs_free char *esc = NULL; g_assert (filename && filename[0]); - if (!!would_be_ignored != !!nms_keyfile_utils_should_ignore_file (filename)) { + if (!!would_be_ignored != !!nms_keyfile_utils_should_ignore_file (filename, with_extension)) { if (would_be_ignored) g_error ("We expect filename \"%s\" to be ignored, but it isn't", filename); else g_error ("We expect filename \"%s\" not to be ignored, but it is", filename); } - esc = nms_keyfile_utils_escape_filename (filename); + esc = nms_keyfile_utils_escape_filename (filename, with_extension); g_assert (esc && esc[0]); g_assert (!strchr (esc, '/')); - if (nms_keyfile_utils_should_ignore_file (esc)) + if (nms_keyfile_utils_should_ignore_file (esc, with_extension)) g_error ("Escaping filename \"%s\" yielded \"%s\", but this is ignored", filename, esc); } static void test_nm_keyfile_plugin_utils_escape_filename (void) { - _escape_filename ("ab", FALSE); - _escape_filename (".vim-file.swp", TRUE); - _escape_filename (".vim-file.Swp", TRUE); - _escape_filename (".vim-file.SWP", TRUE); - _escape_filename (".vim-file.swpx", TRUE); - _escape_filename (".vim-file.Swpx", TRUE); - _escape_filename (".vim-file.SWPX", TRUE); - _escape_filename (".pem-file.pem", TRUE); - _escape_filename (".pem-file.Pem", TRUE); - _escape_filename (".pem-file.PEM", TRUE); - _escape_filename (".pem-file.der", TRUE); - _escape_filename (".pem-file.Der", TRUE); - _escape_filename (".mkstemp.ABCEDF", TRUE); - _escape_filename (".mkstemp.abcdef", TRUE); - _escape_filename (".mkstemp.123456", TRUE); - _escape_filename (".mkstemp.A23456", TRUE); - _escape_filename (".#emacs-locking", TRUE); - _escape_filename ("file-with-tilde~", TRUE); - _escape_filename (".file-with-dot", TRUE); + _escape_filename (FALSE, "ab", FALSE); + _escape_filename (FALSE, ".vim-file.swp", TRUE); + _escape_filename (FALSE, ".vim-file.Swp", TRUE); + _escape_filename (FALSE, ".vim-file.SWP", TRUE); + _escape_filename (FALSE, ".vim-file.swpx", TRUE); + _escape_filename (FALSE, ".vim-file.Swpx", TRUE); + _escape_filename (FALSE, ".vim-file.SWPX", TRUE); + _escape_filename (FALSE, ".pem-file.pem", TRUE); + _escape_filename (FALSE, ".pem-file.Pem", TRUE); + _escape_filename (FALSE, ".pem-file.PEM", TRUE); + _escape_filename (FALSE, ".pem-file.der", TRUE); + _escape_filename (FALSE, ".pem-file.Der", TRUE); + _escape_filename (FALSE, ".mkstemp.ABCEDF", TRUE); + _escape_filename (FALSE, ".mkstemp.abcdef", TRUE); + _escape_filename (FALSE, ".mkstemp.123456", TRUE); + _escape_filename (FALSE, ".mkstemp.A23456", TRUE); + _escape_filename (FALSE, ".#emacs-locking", TRUE); + _escape_filename (FALSE, "file-with-tilde~", TRUE); + _escape_filename (FALSE, ".file-with-dot", TRUE); + + _escape_filename (TRUE, "lala", TRUE); } /*****************************************************************************/ |