diff --git a/.gitignore b/.gitignore
index f71f1f88a8..494ff707ba 100644
--- a/.gitignore
+++ b/.gitignore
@@ -252,6 +252,9 @@ test-*.trs
/src/dhcp/tests/test-dhcp-options
/src/dhcp/tests/test-dhcp-utils
/src/dnsmasq/tests/test-dnsmasq-utils
+/src/initrd/nm-initrd-generator
+/src/initrd/tests/test-cmdline-reader
+/src/initrd/tests/test-ibft-reader
/src/nm-iface-helper
/src/ndisc/tests/test-ndisc-fake
/src/ndisc/tests/test-ndisc-linux
diff --git a/Makefile.am b/Makefile.am
index afa6cfc852..3f81c38925 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1925,6 +1925,271 @@ $(src_nm_iface_helper_OBJECTS): $(libnm_core_lib_h_pub_mkenums)
###############################################################################
+noinst_LTLIBRARIES += src/initrd/libnmi-core.la
+
+src_initrd_libnmi_core_la_CPPFLAGS = \
+ $(src_cppflags)
+
+src_initrd_libnmi_core_la_SOURCES = \
+ src/initrd/nm-initrd-generator.h \
+ src/initrd/nmi-cmdline-reader.c \
+ src/initrd/nmi-ibft-reader.c \
+ $(NULL)
+
+libexec_PROGRAMS += src/initrd/nm-initrd-generator
+
+src_initrd_nm_initrd_generator_CPPFLAGS = \
+ $(src_cppflags)
+
+src_initrd_nm_initrd_generator_SOURCES = \
+ src/initrd/nm-initrd-generator.c
+
+src_initrd_nm_initrd_generator_LDADD = \
+ libnm-core/libnm-core.la \
+ src/initrd/libnmi-core.la \
+ src/libNetworkManagerBase.la \
+ $(GLIB_LIBS)
+
+src_initrd_nm_initrd_generator_LDFLAGS = \
+ -Wl,--version-script="$(srcdir)/linker-script-binary.ver" \
+ $(SANITIZER_EXEC_LDFLAGS)
+
+check_programs += src/initrd/tests/test-ibft-reader
+
+src_initrd_tests_test_ibft_reader_CPPFLAGS = \
+ -DNETWORKMANAGER_COMPILATION_TEST \
+ -DTEST_INITRD_DIR=\"$(abs_srcdir)/src/initrd/tests\" \
+ $(src_cppflags)
+
+src_initrd_tests_test_ibft_reader_LDFLAGS = \
+ $(CODE_COVERAGE_LDFLAGS) \
+ $(SANITIZER_EXEC_LDFLAGS)
+
+src_initrd_tests_test_ibft_reader_LDADD = \
+ libnm-core/libnm-core.la \
+ src/initrd/libnmi-core.la \
+ src/libNetworkManagerTest.la \
+ $(GLIB_LIBS)
+
+EXTRA_DIST += \
+ src/initrd/tests/sysfs/class/net/eth0/address \
+ src/initrd/tests/sysfs/class/net/eth2/address \
+ src/initrd/tests/sysfs/firmware/ibft/ethernet0/prefix-len \
+ src/initrd/tests/sysfs/firmware/ibft/ethernet0/hostname \
+ src/initrd/tests/sysfs/firmware/ibft/ethernet0/gateway \
+ src/initrd/tests/sysfs/firmware/ibft/ethernet0/mac \
+ src/initrd/tests/sysfs/firmware/ibft/ethernet0/vlan \
+ src/initrd/tests/sysfs/firmware/ibft/ethernet0/primary-dns \
+ src/initrd/tests/sysfs/firmware/ibft/ethernet0/dhcp \
+ src/initrd/tests/sysfs/firmware/ibft/ethernet0/origin \
+ src/initrd/tests/sysfs/firmware/ibft/ethernet0/secondary-dns \
+ src/initrd/tests/sysfs/firmware/ibft/ethernet0/ip-addr \
+ src/initrd/tests/sysfs/firmware/ibft/ethernet0/subnet-mask \
+ src/initrd/tests/sysfs/firmware/ibft/ethernet0/index \
+ src/initrd/tests/sysfs/firmware/ibft/ethernet0/flags \
+ src/initrd/tests/sysfs/firmware/ibft/initiator/isns-server \
+ src/initrd/tests/sysfs/firmware/ibft/initiator/initiator-name \
+ src/initrd/tests/sysfs/firmware/ibft/initiator/pri-radius-server \
+ src/initrd/tests/sysfs/firmware/ibft/initiator/slp-server \
+ src/initrd/tests/sysfs/firmware/ibft/initiator/sec-radius-server \
+ src/initrd/tests/sysfs/firmware/ibft/initiator/index \
+ src/initrd/tests/sysfs/firmware/ibft/initiator/flags \
+ src/initrd/tests/sysfs/firmware/ibft/target0/nic-assoc \
+ src/initrd/tests/sysfs/firmware/ibft/target0/ip-addr \
+ src/initrd/tests/sysfs/firmware/ibft/target0/chap-type \
+ src/initrd/tests/sysfs/firmware/ibft/target0/index \
+ src/initrd/tests/sysfs/firmware/ibft/target0/lun \
+ src/initrd/tests/sysfs/firmware/ibft/target0/flags \
+ src/initrd/tests/sysfs/firmware/ibft/target0/port \
+ src/initrd/tests/sysfs/firmware/ibft/target2/target-name \
+ src/initrd/tests/sysfs/firmware/ibft/target2/nic-assoc \
+ src/initrd/tests/sysfs/firmware/ibft/target2/ip-addr \
+ src/initrd/tests/sysfs/firmware/ibft/target2/chap-type \
+ src/initrd/tests/sysfs/firmware/ibft/target2/index \
+ src/initrd/tests/sysfs/firmware/ibft/target2/lun \
+ src/initrd/tests/sysfs/firmware/ibft/target2/flags \
+ src/initrd/tests/sysfs/firmware/ibft/target2/port \
+ src/initrd/tests/sysfs/firmware/ibft/acpi_header/oem_table_id \
+ src/initrd/tests/sysfs/firmware/ibft/acpi_header/oem_id \
+ src/initrd/tests/sysfs/firmware/ibft/acpi_header/signature \
+ src/initrd/tests/sysfs/firmware/ibft/ethernet2/prefix-len \
+ src/initrd/tests/sysfs/firmware/ibft/ethernet2/hostname \
+ src/initrd/tests/sysfs/firmware/ibft/ethernet2/gateway \
+ src/initrd/tests/sysfs/firmware/ibft/ethernet2/mac \
+ src/initrd/tests/sysfs/firmware/ibft/ethernet2/vlan \
+ src/initrd/tests/sysfs/firmware/ibft/ethernet2/primary-dns \
+ src/initrd/tests/sysfs/firmware/ibft/ethernet2/dhcp \
+ src/initrd/tests/sysfs/firmware/ibft/ethernet2/origin \
+ src/initrd/tests/sysfs/firmware/ibft/ethernet2/secondary-dns \
+ src/initrd/tests/sysfs/firmware/ibft/ethernet2/ip-addr \
+ src/initrd/tests/sysfs/firmware/ibft/ethernet2/subnet-mask \
+ src/initrd/tests/sysfs/firmware/ibft/ethernet2/index \
+ src/initrd/tests/sysfs/firmware/ibft/ethernet2/flags \
+ src/initrd/tests/sysfs-bad-dns1/class/net/eth0/address \
+ src/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/prefix-len \
+ src/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/gateway \
+ src/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/mac \
+ src/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/vlan \
+ src/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/primary-dns \
+ src/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/origin \
+ src/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/secondary-dns \
+ src/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/ip-addr \
+ src/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/subnet-mask \
+ src/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/index \
+ src/initrd/tests/sysfs-bad-dns1/firmware/ibft/initiator/initiator-name \
+ src/initrd/tests/sysfs-bad-dns1/firmware/ibft/target0/target-name \
+ src/initrd/tests/sysfs-bad-dns1/firmware/ibft/target0/ip-addr \
+ src/initrd/tests/sysfs-bad-dns1/firmware/ibft/target0/index \
+ src/initrd/tests/sysfs-bad-dns1/firmware/ibft/target0/lun \
+ src/initrd/tests/sysfs-bad-dns1/firmware/ibft/target0/port \
+ src/initrd/tests/sysfs-bad-dns2/class/net/eth0/address \
+ src/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/prefix-len \
+ src/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/gateway \
+ src/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/mac \
+ src/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/vlan \
+ src/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/primary-dns \
+ src/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/origin \
+ src/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/secondary-dns \
+ src/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/ip-addr \
+ src/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/subnet-mask \
+ src/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/index \
+ src/initrd/tests/sysfs-bad-dns2/firmware/ibft/initiator/initiator-name \
+ src/initrd/tests/sysfs-bad-dns2/firmware/ibft/target0/target-name \
+ src/initrd/tests/sysfs-bad-dns2/firmware/ibft/target0/ip-addr \
+ src/initrd/tests/sysfs-bad-dns2/firmware/ibft/target0/index \
+ src/initrd/tests/sysfs-bad-dns2/firmware/ibft/target0/lun \
+ src/initrd/tests/sysfs-bad-dns2/firmware/ibft/target0/port \
+ src/initrd/tests/sysfs-bad-gateway/class/net/eth0/address \
+ src/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/prefix-len \
+ src/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/gateway \
+ src/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/mac \
+ src/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/vlan \
+ src/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/primary-dns \
+ src/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/origin \
+ src/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/secondary-dns \
+ src/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/ip-addr \
+ src/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/subnet-mask \
+ src/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/index \
+ src/initrd/tests/sysfs-bad-gateway/firmware/ibft/initiator/initiator-name \
+ src/initrd/tests/sysfs-bad-gateway/firmware/ibft/target0/target-name \
+ src/initrd/tests/sysfs-bad-gateway/firmware/ibft/target0/ip-addr \
+ src/initrd/tests/sysfs-bad-gateway/firmware/ibft/target0/index \
+ src/initrd/tests/sysfs-bad-gateway/firmware/ibft/target0/lun \
+ src/initrd/tests/sysfs-bad-gateway/firmware/ibft/target0/port \
+ src/initrd/tests/sysfs-bad-ipaddr/class/net/eth0/address \
+ src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/prefix-len \
+ src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/gateway \
+ src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/mac \
+ src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/vlan \
+ src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/primary-dns \
+ src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/origin \
+ src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/secondary-dns \
+ src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/ip-addr \
+ src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/subnet-mask \
+ src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/index \
+ src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/initiator/initiator-name \
+ src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/target0/target-name \
+ src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/target0/ip-addr \
+ src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/target0/index \
+ src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/target0/lun \
+ src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/target0/port \
+ src/initrd/tests/sysfs-dhcp/class/net/eth0/address \
+ src/initrd/tests/sysfs-dhcp/class/net/eth1/address \
+ src/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet0/gateway \
+ src/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet0/mac \
+ src/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet0/vlan \
+ src/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet0/primary-dns \
+ src/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet0/origin \
+ src/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet0/secondary-dns \
+ src/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet0/index \
+ src/initrd/tests/sysfs-dhcp/firmware/ibft/initiator/initiator-name \
+ src/initrd/tests/sysfs-dhcp/firmware/ibft/target0/target-name \
+ src/initrd/tests/sysfs-dhcp/firmware/ibft/target0/ip-addr \
+ src/initrd/tests/sysfs-dhcp/firmware/ibft/target0/index \
+ src/initrd/tests/sysfs-dhcp/firmware/ibft/target0/lun \
+ src/initrd/tests/sysfs-dhcp/firmware/ibft/target0/port \
+ src/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet1/gateway \
+ src/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet1/mac \
+ src/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet1/vlan \
+ src/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet1/primary-dns \
+ src/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet1/origin \
+ src/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet1/secondary-dns \
+ src/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet1/index \
+ src/initrd/tests/sysfs-dhcp/firmware/ibft/target1/target-name \
+ src/initrd/tests/sysfs-dhcp/firmware/ibft/target1/ip-addr \
+ src/initrd/tests/sysfs-dhcp/firmware/ibft/target1/index \
+ src/initrd/tests/sysfs-dhcp/firmware/ibft/target1/lun \
+ src/initrd/tests/sysfs-dhcp/firmware/ibft/target1/port \
+ src/initrd/tests/sysfs-static/class/net/eth0/address \
+ src/initrd/tests/sysfs-static/class/net/eth1/address \
+ src/initrd/tests/sysfs-static/firmware/ibft/ethernet0/prefix-len \
+ src/initrd/tests/sysfs-static/firmware/ibft/ethernet0/gateway \
+ src/initrd/tests/sysfs-static/firmware/ibft/ethernet0/mac \
+ src/initrd/tests/sysfs-static/firmware/ibft/ethernet0/vlan \
+ src/initrd/tests/sysfs-static/firmware/ibft/ethernet0/primary-dns \
+ src/initrd/tests/sysfs-static/firmware/ibft/ethernet0/origin \
+ src/initrd/tests/sysfs-static/firmware/ibft/ethernet0/secondary-dns \
+ src/initrd/tests/sysfs-static/firmware/ibft/ethernet0/ip-addr \
+ src/initrd/tests/sysfs-static/firmware/ibft/ethernet0/subnet-mask \
+ src/initrd/tests/sysfs-static/firmware/ibft/ethernet0/index \
+ src/initrd/tests/sysfs-static/firmware/ibft/initiator/initiator-name \
+ src/initrd/tests/sysfs-static/firmware/ibft/target0/target-name \
+ src/initrd/tests/sysfs-static/firmware/ibft/target0/ip-addr \
+ src/initrd/tests/sysfs-static/firmware/ibft/target0/index \
+ src/initrd/tests/sysfs-static/firmware/ibft/target0/lun \
+ src/initrd/tests/sysfs-static/firmware/ibft/target0/port \
+ src/initrd/tests/sysfs-static/firmware/ibft/ethernet1/gateway \
+ src/initrd/tests/sysfs-static/firmware/ibft/ethernet1/mac \
+ src/initrd/tests/sysfs-static/firmware/ibft/ethernet1/vlan \
+ src/initrd/tests/sysfs-static/firmware/ibft/ethernet1/primary-dns \
+ src/initrd/tests/sysfs-static/firmware/ibft/ethernet1/origin \
+ src/initrd/tests/sysfs-static/firmware/ibft/ethernet1/secondary-dns \
+ src/initrd/tests/sysfs-static/firmware/ibft/ethernet1/index \
+ src/initrd/tests/sysfs-static/firmware/ibft/target1/target-name \
+ src/initrd/tests/sysfs-static/firmware/ibft/target1/ip-addr \
+ src/initrd/tests/sysfs-static/firmware/ibft/target1/index \
+ src/initrd/tests/sysfs-static/firmware/ibft/target1/lun \
+ src/initrd/tests/sysfs-static/firmware/ibft/target1/port \
+ src/initrd/tests/sysfs-vlan/class/net/eth0/address \
+ src/initrd/tests/sysfs-vlan/firmware/ibft/ethernet0/prefix-len \
+ src/initrd/tests/sysfs-vlan/firmware/ibft/ethernet0/mac \
+ src/initrd/tests/sysfs-vlan/firmware/ibft/ethernet0/vlan \
+ src/initrd/tests/sysfs-vlan/firmware/ibft/ethernet0/origin \
+ src/initrd/tests/sysfs-vlan/firmware/ibft/ethernet0/ip-addr \
+ src/initrd/tests/sysfs-vlan/firmware/ibft/ethernet0/subnet-mask \
+ src/initrd/tests/sysfs-vlan/firmware/ibft/ethernet0/index \
+ src/initrd/tests/sysfs-vlan/firmware/ibft/initiator/initiator-name \
+ src/initrd/tests/sysfs-vlan/firmware/ibft/target0/target-name \
+ src/initrd/tests/sysfs-vlan/firmware/ibft/target0/ip-addr \
+ src/initrd/tests/sysfs-vlan/firmware/ibft/target0/index \
+ src/initrd/tests/sysfs-vlan/firmware/ibft/target0/lun \
+ src/initrd/tests/sysfs-vlan/firmware/ibft/target0/port \
+ $(NULL)
+
+check_programs += src/initrd/tests/test-cmdline-reader
+
+src_initrd_tests_test_cmdline_reader_CPPFLAGS = \
+ -DNETWORKMANAGER_COMPILATION_TEST \
+ -DTEST_INITRD_DIR=\"$(abs_srcdir)/src/initrd/tests\" \
+ $(src_cppflags)
+
+src_initrd_tests_test_cmdline_reader_LDFLAGS = \
+ $(CODE_COVERAGE_LDFLAGS) \
+ $(SANITIZER_EXEC_LDFLAGS)
+
+src_initrd_tests_test_cmdline_reader_LDADD = \
+ libnm-core/libnm-core.la \
+ src/initrd/libnmi-core.la \
+ src/libNetworkManagerTest.la \
+ $(GLIB_LIBS)
+
+$(src_initrd_libnmi_core_la_OBJECTS): $(libnm_core_lib_h_pub_mkenums)
+$(src_initrd_nm_initrd_generator_OBJECTS): $(libnm_core_lib_h_pub_mkenums)
+$(src_initrd_tests_test_cmdline_reader_OBJECTS): $(libnm_core_lib_h_pub_mkenums)
+$(src_initrd_tests_test_ibft_reader_OBJECTS): $(libnm_core_lib_h_pub_mkenums)
+
+###############################################################################
+
EXTRA_DIST += \
src/org.freedesktop.NetworkManager.conf \
src/nm-test-utils-core.h \
@@ -4615,6 +4880,7 @@ man_pages += \
man/NetworkManager.8 \
man/NetworkManager.conf.5 \
man/nm-online.1 \
+ man/nm-initrd-generator.8 \
man/nmcli-examples.7 \
man/nmcli.1 \
man/nmtui.1
diff --git a/configure.ac b/configure.ac
index a8b0083e5f..49d2e5a02f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -134,8 +134,8 @@ AS_IF([test -z "$enable_ifupdown" -a -f /etc/debian_version], enable_
# Otherwise plugins default to "no"
AS_IF([test -z "$enable_ifcfg_rh"], enable_ifcfg_rh=no)
AS_IF([test -z "$enable_ifupdown"], enable_ifupdown=no)
-# Enable ibft by default
-AS_IF([test -z "$enable_config_plugin_ibft"], enable_config_plugin_ibft="yes")
+# Disable obsolete ibft plugin by default
+AS_IF([test -z "$enable_config_plugin_ibft"], enable_config_plugin_ibft="no")
# Create automake conditionals
AM_CONDITIONAL(CONFIG_PLUGIN_IBFT, test "$enable_config_plugin_ibft" = "yes")
AM_CONDITIONAL(CONFIG_PLUGIN_IFCFG_RH, test "$enable_ifcfg_rh" = "yes")
diff --git a/contrib/fedora/rpm/NetworkManager.spec b/contrib/fedora/rpm/NetworkManager.spec
index 753ff08fc2..92386ecd7e 100644
--- a/contrib/fedora/rpm/NetworkManager.spec
+++ b/contrib/fedora/rpm/NetworkManager.spec
@@ -553,7 +553,7 @@ intltoolize --automake --copy --force
--enable-ppp=yes \
%endif
--with-dist-version=%{version}-%{release} \
- --with-config-plugins-default='ifcfg-rh,ibft' \
+ --with-config-plugins-default='ifcfg-rh' \
--with-config-dns-rc-manager-default=symlink \
--with-config-logging-backend-default=journal \
--enable-json-validation \
@@ -687,6 +687,7 @@ fi
%{_libexecdir}/nm-dhcp-helper
%{_libexecdir}/nm-dispatcher
%{_libexecdir}/nm-iface-helper
+%{_libexecdir}/nm-initrd-generator
%dir %{_libdir}/%{name}
%dir %{nmplugindir}
%{nmplugindir}/libnm-settings-plugin*.so
diff --git a/docs/api/Makefile.am b/docs/api/Makefile.am
index 859aa20bc2..1f388b99ec 100644
--- a/docs/api/Makefile.am
+++ b/docs/api/Makefile.am
@@ -83,6 +83,7 @@ content_files = \
$(top_builddir)/man/nmcli.xml \
$(top_builddir)/man/nmtui.xml \
$(top_builddir)/man/nm-online.xml \
+ $(top_builddir)/man/nm-initrd-generator.xml \
$(top_builddir)/man/NetworkManager.xml \
$(top_builddir)/man/NetworkManager.conf.xml \
$(top_builddir)/man/nmcli-examples.xml \
diff --git a/docs/api/network-manager-docs.xml b/docs/api/network-manager-docs.xml
index 047c3086e3..457ec0ac29 100644
--- a/docs/api/network-manager-docs.xml
+++ b/docs/api/network-manager-docs.xml
@@ -77,6 +77,7 @@
+
diff --git a/libnm-core/nm-setting.c b/libnm-core/nm-setting.c
index ff86fb9082..a8f7668aee 100644
--- a/libnm-core/nm-setting.c
+++ b/libnm-core/nm-setting.c
@@ -2037,8 +2037,12 @@ _nm_setting_get_deprecated_virtual_interface_name (NMSetting *setting,
{
NMSettingConnection *s_con;
+ if (!connection)
+ return NULL;
+
s_con = nm_connection_get_setting_connection (connection);
- g_return_val_if_fail (s_con != NULL, NULL);
+ if (!s_con)
+ return NULL;
if (nm_setting_connection_get_interface_name (s_con))
return g_variant_new_string (nm_setting_connection_get_interface_name (s_con));
diff --git a/man/NetworkManager.xml b/man/NetworkManager.xml
index 7b0513bb92..f78a44f4f8 100644
--- a/man/NetworkManager.xml
+++ b/man/NetworkManager.xml
@@ -379,6 +379,13 @@
for more information on configuration file.
+
+ initrd
+ Quit after all devices reach a stable state.
+ The optional initrd parameter enables mode, where no
+ processes are left running after NetworkManager stops, which is useful
+ for running from an initial ramdisk on rearly boot.
+
List plugins used to manage system-wide
diff --git a/man/nm-initrd-generator.xml b/man/nm-initrd-generator.xml
new file mode 100644
index 0000000000..df2cf12a4b
--- /dev/null
+++ b/man/nm-initrd-generator.xml
@@ -0,0 +1,140 @@
+
+
+
+%entities;
+]>
+
+
+
+
+
+
+ nm-initrd-generator
+ NetworkManager developers
+
+
+
+ nm-initrd-generator
+ 8
+ NetworkManager
+ System Administration
+ &NM_VERSION;
+
+
+
+ nm-initrd-generator
+ early boot NetworkManager configuration generator
+
+
+
+
+ nm-initrd-generator
+ OPTIONS
+ --
+ CMDLINE
+
+
+
+ Description
+ nm-initrd-generator scans the command line for options
+ relevant to network configuration and creates configuration files for an early
+ instance of NetworkManager run from the initial ramdisk during early boot.
+
+
+ Options
+
+
+
+
+
+
+
+ path
+
+
+
+ Output connection directory.
+
+
+
+
+
+
+
+
+
+ path
+
+
+
+ The sysfs mount point.
+
+
+
+
+
+
+
+
+
+
+
+
+ Dump connections to standard output. Useful for debugging.
+
+
+
+
+ CMDLINE
+
+
+ The options that appear on the kernel command line. The following options are recognized:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Please consult the dracut.cmdline7
+ manual for the documentation of the precise format of the values supported.
+
+
+
+
+
+ Exit Status
+ nm-initrd-generator exits with status 0. It ignores unrecognized
+ options and prints an error message if it encounters a malformed option.
+
+
+ See Also
+ dracut.cmdline7,
+ NetworkManager8.
+
+
diff --git a/meson.build b/meson.build
index effaabec03..7c7ef7ecc5 100644
--- a/meson.build
+++ b/meson.build
@@ -886,7 +886,6 @@ endif
config_extra_h.set_quoted('PREFIX', nm_prefix)
config_extra_h.set_quoted('RUNDIR', nm_pkgrundir)
config_extra_h.set_quoted('RUNSTATEDIR', nm_runstatedir)
-config_extra_h.set_quoted('SBINDIR', nm_sbindir)
config_extra_h.set_quoted('SYSCONFDIR', nm_sysconfdir)
configure_file(
diff --git a/src/devices/bluetooth/nm-bluez-device.c b/src/devices/bluetooth/nm-bluez-device.c
index b69b432039..b722f692ce 100644
--- a/src/devices/bluetooth/nm-bluez-device.c
+++ b/src/devices/bluetooth/nm-bluez-device.c
@@ -227,21 +227,12 @@ pan_connection_check_create (NMBluezDevice *self)
NULL);
nm_connection_add_setting (connection, setting);
- /* Setting: IPv4 */
- setting = nm_setting_ip4_config_new ();
- g_object_set (G_OBJECT (setting),
- NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO,
- NM_SETTING_IP_CONFIG_MAY_FAIL, FALSE,
- NULL);
- nm_connection_add_setting (connection, setting);
-
- /* Setting: IPv6 */
- setting = nm_setting_ip6_config_new ();
- g_object_set (G_OBJECT (setting),
- NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_AUTO,
- NM_SETTING_IP_CONFIG_MAY_FAIL, TRUE,
- NULL);
- nm_connection_add_setting (connection, setting);
+ if (!nm_connection_normalize (connection, NULL, NULL, &error)) {
+ nm_log_err (LOGD_BT, "bluez[%s] couldn't generate a connection for NAP device: %s",
+ priv->path, error->message);
+ g_error_free (error);
+ g_return_if_reached ();
+ }
/* Adding a new connection raises a signal which eventually calls check_emit_usable (again)
* which then already finds the suitable connection in priv->connections. This is confusing,
diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c
index 7108a85c6e..6347e292b3 100644
--- a/src/devices/nm-device.c
+++ b/src/devices/nm-device.c
@@ -464,6 +464,7 @@ typedef struct _NMDevicePrivate {
gulong state_sigid;
NMDhcp4Config * config;
char * pac_url;
+ char * root_path;
bool was_active;
guint grace_id;
} dhcp4;
@@ -4580,9 +4581,23 @@ nm_device_owns_iface (NMDevice *self, const char *iface)
NMConnection *
nm_device_new_default_connection (NMDevice *self)
{
- if (NM_DEVICE_GET_CLASS (self)->new_default_connection)
- return NM_DEVICE_GET_CLASS (self)->new_default_connection (self);
- return NULL;
+ NMConnection *connection;
+ GError *error = NULL;
+
+ if (!NM_DEVICE_GET_CLASS (self)->new_default_connection)
+ return NULL;
+
+ connection = NM_DEVICE_GET_CLASS (self)->new_default_connection (self);
+ if (!connection)
+ return NULL;
+
+ if (!nm_connection_normalize (connection, NULL, NULL, &error)) {
+ _LOGD (LOGD_DEVICE, "device generated an invalid default connection: %s", error->message);
+ g_error_free (error);
+ g_return_val_if_reached (NULL);
+ }
+
+ return connection;
}
static void
@@ -5041,11 +5056,15 @@ nm_device_removed (NMDevice *self, gboolean unconfigure_ip_config)
nm_device_master_release_one_slave (priv->master, self, FALSE, NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED);
}
- if (!unconfigure_ip_config)
- return;
-
- nm_device_set_ip_config (self, AF_INET, NULL, FALSE, NULL);
- nm_device_set_ip_config (self, AF_INET6, NULL, FALSE, NULL);
+ if (unconfigure_ip_config) {
+ nm_device_set_ip_config (self, AF_INET, NULL, FALSE, NULL);
+ nm_device_set_ip_config (self, AF_INET6, NULL, FALSE, NULL);
+ } else {
+ if (priv->dhcp4.client)
+ nm_dhcp_client_stop (priv->dhcp4.client, FALSE);
+ if (priv->dhcp6.client)
+ nm_dhcp_client_stop (priv->dhcp6.client, FALSE);
+ }
}
static gboolean
@@ -5449,7 +5468,7 @@ nm_device_generate_connection (NMDevice *self,
klass->update_connection (self, connection);
- if (!nm_connection_verify (connection, &local)) {
+ if (!nm_connection_normalize (connection, NULL, NULL, error)) {
g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED,
"generated connection does not verify: %s",
local->message);
@@ -6953,6 +6972,7 @@ dhcp4_cleanup (NMDevice *self, CleanupType cleanup_type, gboolean release)
nm_clear_g_source (&priv->dhcp4.grace_id);
g_clear_pointer (&priv->dhcp4.pac_url, g_free);
+ g_clear_pointer (&priv->dhcp4.root_path, g_free);
if (priv->dhcp4.client) {
/* Stop any ongoing DHCP transaction on this device */
@@ -7326,6 +7346,9 @@ dhcp4_state_changed (NMDhcpClient *client,
priv->dhcp4.pac_url = g_strdup (g_hash_table_lookup (options, "wpad"));
nm_device_set_proxy_config (self, priv->dhcp4.pac_url);
+ g_free (priv->dhcp4.root_path);
+ priv->dhcp4.root_path = g_strdup (g_hash_table_lookup (options, "root_path"));
+
nm_dhcp4_config_set_options (priv->dhcp4.config, options);
_notify (self, PROP_DHCP4_CONFIG);
diff --git a/src/dhcp/nm-dhcp-dhclient-utils.c b/src/dhcp/nm-dhcp-dhclient-utils.c
index d8f8dd98d8..a2c3bfb65d 100644
--- a/src/dhcp/nm-dhcp-dhclient-utils.c
+++ b/src/dhcp/nm-dhcp-dhclient-utils.c
@@ -444,6 +444,7 @@ nm_dhcp_dhclient_create_config (const char *interface,
add_request (reqs, "static-routes");
add_request (reqs, "wpad");
add_request (reqs, "ntp-servers");
+ add_request (reqs, "root-path");
} else {
add_hostname6 (new_contents, hostname);
add_request (reqs, "dhcp6.name-servers");
diff --git a/src/dhcp/nm-dhcp-dhclient.c b/src/dhcp/nm-dhcp-dhclient.c
index 46d2339bf2..4a93617819 100644
--- a/src/dhcp/nm-dhcp-dhclient.c
+++ b/src/dhcp/nm-dhcp-dhclient.c
@@ -41,6 +41,7 @@
#include "nm-utils/nm-dedup-multi.h"
#include "nm-utils.h"
+#include "nm-config.h"
#include "nm-dhcp-dhclient-utils.h"
#include "nm-dhcp-manager.h"
#include "NetworkManagerUtils.h"
@@ -120,8 +121,20 @@ get_dhclient_leasefile (int addr_family,
const char *uuid,
char **out_preferred_path)
{
+ char *rundir_path;
char *path;
+ /* First, see if the lease file is in /run */
+ rundir_path = g_strdup_printf (NMRUNDIR "/dhclient%s-%s-%s.lease",
+ _addr_family_to_path_part (addr_family),
+ uuid,
+ iface);
+
+ if (g_file_test (rundir_path, G_FILE_TEST_EXISTS)) {
+ NM_SET_OUT (out_preferred_path, g_strdup (rundir_path));
+ return rundir_path;
+ }
+
/* /var/lib/NetworkManager is the preferred leasefile path */
path = g_strdup_printf (NMSTATEDIR "/dhclient%s-%s-%s.lease",
_addr_family_to_path_part (addr_family),
@@ -133,6 +146,12 @@ get_dhclient_leasefile (int addr_family,
return path;
}
+ if (nm_config_get_configure_and_quit (nm_config_get ()) == NM_CONFIG_CONFIGURE_AND_QUIT_INITRD) {
+ g_free (path);
+ path = rundir_path;
+ } else {
+ g_free (rundir_path);
+ }
NM_SET_OUT (out_preferred_path, g_steal_pointer (&path));
/* If the leasefile we're looking for doesn't exist yet in the new location
diff --git a/src/dhcp/nm-dhcp-manager.c b/src/dhcp/nm-dhcp-manager.c
index 6c71af9d0b..5ae16d721a 100644
--- a/src/dhcp/nm-dhcp-manager.c
+++ b/src/dhcp/nm-dhcp-manager.c
@@ -413,7 +413,7 @@ nm_dhcp_manager_init (NMDhcpManager *self)
NM_CONFIG_KEYFILE_KEY_MAIN_DHCP,
NM_CONFIG_GET_VALUE_STRIP | NM_CONFIG_GET_VALUE_NO_EMPTY);
client = client_free;
- if (nm_config_get_configure_and_quit (config)) {
+ if (nm_config_get_configure_and_quit (config) == NM_CONFIG_CONFIGURE_AND_QUIT_ENABLED) {
client_factory = &_nm_dhcp_client_factory_internal;
if (client && !nm_streq (client, client_factory->name))
nm_log_info (LOGD_DHCP, "dhcp-init: Using internal DHCP client since configure-and-quit is set.");
diff --git a/src/dhcp/nm-dhcp-systemd.c b/src/dhcp/nm-dhcp-systemd.c
index b51c6e7b24..30f5131586 100644
--- a/src/dhcp/nm-dhcp-systemd.c
+++ b/src/dhcp/nm-dhcp-systemd.c
@@ -32,6 +32,7 @@
#include "nm-utils/unaligned.h"
#include "nm-utils.h"
+#include "nm-config.h"
#include "nm-dhcp-utils.h"
#include "NetworkManagerUtils.h"
#include "platform/nm-platform.h"
@@ -121,6 +122,7 @@ static const ReqOption dhcp4_requests[] = {
{ SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE, REQPREFIX "rfc3442_classless_static_routes", TRUE },
{ SD_DHCP_OPTION_PRIVATE_CLASSLESS_STATIC_ROUTE, REQPREFIX "ms_classless_static_routes", TRUE },
{ SD_DHCP_OPTION_PRIVATE_PROXY_AUTODISCOVERY, REQPREFIX "wpad", TRUE },
+ { SD_DHCP_OPTION_ROOT_PATH, REQPREFIX "root_path", TRUE },
/* Internal values */
{ SD_DHCP_OPTION_IP_ADDRESS_LEASE_TIME, REQPREFIX "expiry", FALSE },
@@ -432,6 +434,13 @@ lease_to_ip4_config (NMDedupMultiIndex *multi_idx,
add_option (options, dhcp4_requests, SD_DHCP_OPTION_NTP_SERVER, str->str);
}
+ /* Root path */
+ r = sd_dhcp_lease_get_root_path (lease, &s);
+ if (r >= 0) {
+ LOG_LEASE (LOGD_DHCP4, "root path '%s'", s);
+ add_option (options, dhcp4_requests, SD_DHCP_OPTION_ROOT_PATH, s);
+ }
+
r = sd_dhcp_lease_get_vendor_specific (lease, &data, &data_len);
if (r >= 0)
metered = !!memmem (data, data_len, "ANDROID_METERED", NM_STRLEN ("ANDROID_METERED"));
@@ -445,10 +454,30 @@ lease_to_ip4_config (NMDedupMultiIndex *multi_idx,
static char *
get_leasefile_path (int addr_family, const char *iface, const char *uuid)
{
- return g_strdup_printf (NMSTATEDIR "/internal%s-%s-%s.lease",
- addr_family == AF_INET6 ? "6" : "",
- uuid,
- iface);
+ char *rundir_path;
+ char *statedir_path;
+
+ rundir_path = g_strdup_printf (NMRUNDIR "/internal%s-%s-%s.lease",
+ addr_family == AF_INET6 ? "6" : "",
+ uuid,
+ iface);
+
+ if (g_file_test (rundir_path, G_FILE_TEST_EXISTS))
+ return rundir_path;
+
+ statedir_path = g_strdup_printf (NMSTATEDIR "/internal%s-%s-%s.lease",
+ addr_family == AF_INET6 ? "6" : "",
+ uuid,
+ iface);
+
+ if ( g_file_test (statedir_path, G_FILE_TEST_EXISTS)
+ || nm_config_get_configure_and_quit (nm_config_get ()) != NM_CONFIG_CONFIGURE_AND_QUIT_INITRD) {
+ g_free (rundir_path);
+ return statedir_path;
+ } else {
+ g_free (statedir_path);
+ return rundir_path;
+ }
}
/*****************************************************************************/
diff --git a/src/dhcp/tests/test-dhcp-dhclient.c b/src/dhcp/tests/test-dhcp-dhclient.c
index 14a1c78634..edac42572d 100644
--- a/src/dhcp/tests/test-dhcp-dhclient.c
+++ b/src/dhcp/tests/test-dhcp-dhclient.c
@@ -104,6 +104,7 @@ static const char *orig_missing_expected = \
"also request static-routes;\n"
"also request wpad;\n"
"also request ntp-servers;\n"
+ "also request root-path;\n"
"\n";
static void
@@ -132,6 +133,7 @@ static const char *override_client_id_expected = \
"also request static-routes;\n"
"also request wpad;\n"
"also request ntp-servers;\n"
+ "also request root-path;\n"
"\n";
static void
@@ -161,6 +163,7 @@ static const char *quote_client_id_expected = \
"also request static-routes;\n"
"also request wpad;\n"
"also request ntp-servers;\n"
+ "also request root-path;\n"
"\n";
static void
@@ -190,6 +193,7 @@ static const char *quote_client_id_expected_2 = \
"also request static-routes;\n"
"also request wpad;\n"
"also request ntp-servers;\n"
+ "also request root-path;\n"
"\n";
static void
@@ -219,6 +223,7 @@ static const char *hex_zero_client_id_expected = \
"also request static-routes;\n"
"also request wpad;\n"
"also request ntp-servers;\n"
+ "also request root-path;\n"
"\n";
static void
@@ -248,6 +253,7 @@ static const char *ascii_client_id_expected = \
"also request static-routes;\n"
"also request wpad;\n"
"also request ntp-servers;\n"
+ "also request root-path;\n"
"\n";
static void
@@ -277,6 +283,7 @@ static const char *hex_single_client_id_expected = \
"also request static-routes;\n"
"also request wpad;\n"
"also request ntp-servers;\n"
+ "also request root-path;\n"
"\n";
static void
@@ -310,6 +317,7 @@ static const char *existing_hex_client_id_expected = \
"also request static-routes;\n"
"also request wpad;\n"
"also request ntp-servers;\n"
+ "also request root-path;\n"
"\n";
static void
@@ -347,6 +355,7 @@ static const char *existing_escaped_client_id_expected = \
"also request static-routes;\n"
"also request wpad;\n"
"also request ntp-servers;\n"
+ "also request root-path;\n"
"\n";
static void
@@ -385,6 +394,7 @@ static const char *existing_ascii_client_id_expected = \
"also request static-routes;\n"
"also request wpad;\n"
"also request ntp-servers;\n"
+ "also request root-path;\n"
"\n";
static void
@@ -419,7 +429,8 @@ static const char *fqdn_expected = \
"also request ms-classless-static-routes;\n"
"also request static-routes;\n"
"also request wpad;\n"
- "also request ntp-servers;\n\n";
+ "also request ntp-servers;\n"
+ "also request root-path;\n\n";
static void
test_fqdn (void)
@@ -455,6 +466,7 @@ static const char *fqdn_options_override_expected = \
"also request static-routes;\n"
"also request wpad;\n"
"also request ntp-servers;\n"
+ "also request root-path;\n"
"\n"
"# FQDN options from /path/to/dhclient.conf\n"
"send fqdn.encoded off;\n"
@@ -492,6 +504,7 @@ static const char *override_hostname_expected = \
"also request static-routes;\n"
"also request wpad;\n"
"also request ntp-servers;\n"
+ "also request root-path;\n"
"\n";
static void
@@ -580,6 +593,7 @@ static const char *existing_alsoreq_expected = \
"also request static-routes;\n"
"also request wpad;\n"
"also request ntp-servers;\n"
+ "also request root-path;\n"
"\n";
static void
@@ -618,6 +632,7 @@ static const char *existing_req_expected = \
"also request static-routes;\n"
"also request wpad;\n"
"also request ntp-servers;\n"
+ "also request root-path;\n"
"\n";
static void
@@ -657,6 +672,7 @@ static const char *existing_multiline_alsoreq_expected = \
"also request static-routes;\n"
"also request wpad;\n"
"also request ntp-servers;\n"
+ "also request root-path;\n"
"\n";
static void
@@ -890,6 +906,7 @@ static const char *interface1_expected = \
"also request static-routes;\n"
"also request wpad;\n"
"also request ntp-servers;\n"
+ "also request root-path;\n"
"\n";
static void
@@ -935,6 +952,7 @@ static const char *interface2_expected = \
"also request static-routes;\n"
"also request wpad;\n"
"also request ntp-servers;\n"
+ "also request root-path;\n"
"\n";
static void
@@ -1030,6 +1048,7 @@ test_structured (void)
"also request static-routes;\n"
"also request wpad;\n"
"also request ntp-servers;\n"
+ "also request root-path;\n"
"\n";
new_client_id = g_bytes_new (bytes, sizeof (bytes) - 1);
@@ -1085,6 +1104,7 @@ test_config_req_intf (void)
"also request ms-classless-static-routes;\n"
"also request static-routes;\n"
"also request wpad;\n"
+ "also request root-path;\n"
"\n";
test_config (orig, expected,
diff --git a/src/dns/nm-dns-dnsmasq.c b/src/dns/nm-dns-dnsmasq.c
index cb7a626c2d..b48c6b87cb 100644
--- a/src/dns/nm-dns-dnsmasq.c
+++ b/src/dns/nm-dns-dnsmasq.c
@@ -306,8 +306,6 @@ start_dnsmasq (NMDnsDnsmasq *self)
const char *argv[15];
GPid pid = 0;
guint idx = 0;
- NMDBusManager *dbus_mgr;
- GDBusConnection *connection;
if (priv->running) {
/* the dnsmasq process is running. Nothing to do. */
@@ -358,22 +356,16 @@ start_dnsmasq (NMDnsDnsmasq *self)
return;
}
- dbus_mgr = nm_dbus_manager_get ();
- g_return_if_fail (dbus_mgr);
-
- connection = nm_dbus_manager_get_connection (dbus_mgr);
- g_return_if_fail (connection);
-
priv->dnsmasq_cancellable = g_cancellable_new ();
- g_dbus_proxy_new (connection,
- G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
- NULL,
- DNSMASQ_DBUS_SERVICE,
- DNSMASQ_DBUS_PATH,
- DNSMASQ_DBUS_SERVICE,
- priv->dnsmasq_cancellable,
- dnsmasq_proxy_cb,
- self);
+ g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM,
+ G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
+ NULL,
+ DNSMASQ_DBUS_SERVICE,
+ DNSMASQ_DBUS_PATH,
+ DNSMASQ_DBUS_SERVICE,
+ priv->dnsmasq_cancellable,
+ dnsmasq_proxy_cb,
+ self);
}
static gboolean
diff --git a/src/dns/nm-dns-systemd-resolved.c b/src/dns/nm-dns-systemd-resolved.c
index 544f19c107..303ceac12e 100644
--- a/src/dns/nm-dns-systemd-resolved.c
+++ b/src/dns/nm-dns-systemd-resolved.c
@@ -391,28 +391,20 @@ static void
nm_dns_systemd_resolved_init (NMDnsSystemdResolved *self)
{
NMDnsSystemdResolvedPrivate *priv = NM_DNS_SYSTEMD_RESOLVED_GET_PRIVATE (self);
- NMDBusManager *dbus_mgr;
- GDBusConnection *connection;
c_list_init (&priv->request_queue_lst_head);
- dbus_mgr = nm_dbus_manager_get ();
- g_return_if_fail (dbus_mgr);
-
- connection = nm_dbus_manager_get_connection (dbus_mgr);
- g_return_if_fail (connection);
-
priv->init_cancellable = g_cancellable_new ();
- g_dbus_proxy_new (connection,
- G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES |
- G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS,
- NULL,
- SYSTEMD_RESOLVED_DBUS_SERVICE,
- SYSTEMD_RESOLVED_DBUS_PATH,
- SYSTEMD_RESOLVED_DBUS_SERVICE ".Manager",
- priv->init_cancellable,
- resolved_proxy_created,
- self);
+ g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM,
+ G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES |
+ G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS,
+ NULL,
+ SYSTEMD_RESOLVED_DBUS_SERVICE,
+ SYSTEMD_RESOLVED_DBUS_PATH,
+ SYSTEMD_RESOLVED_DBUS_SERVICE ".Manager",
+ priv->init_cancellable,
+ resolved_proxy_created,
+ self);
}
NMDnsPlugin *
diff --git a/src/initrd/nm-initrd-generator.c b/src/initrd/nm-initrd-generator.c
new file mode 100644
index 0000000000..5947aef075
--- /dev/null
+++ b/src/initrd/nm-initrd-generator.c
@@ -0,0 +1,138 @@
+/* NetworkManager initrd configuration generator
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA.
+ *
+ * Copyright (C) 2018 Red Hat, Inc.
+ */
+
+#include "nm-default.h"
+#include "nm-core-utils.h"
+#include "nm-core-internal.h"
+#include "nm-keyfile-internal.h"
+
+#include "nm-initrd-generator.h"
+
+/*****************************************************************************/
+
+#define _NMLOG(level, domain, ...) \
+ nm_log ((level), (domain), NULL, NULL, \
+ "initrd-generator: " _NM_UTILS_MACRO_FIRST (__VA_ARGS__) \
+ _NM_UTILS_MACRO_REST (__VA_ARGS__))
+
+/*****************************************************************************/
+
+static void
+output_conn (gpointer key, gpointer value, gpointer user_data)
+{
+ const char *basename = key;
+ NMConnection *connection = value;
+ char *connections_dir = user_data;
+ GKeyFile *file;
+ gs_free char *data = NULL;
+ GError *error = NULL;
+ gsize len;
+
+ if (!nm_connection_normalize (connection, NULL, NULL, &error)) {
+ g_print ("%s\n", error->message);
+ g_error_free (error);
+ return;
+ }
+
+ file = nm_keyfile_write (connection, NULL, NULL, &error);
+ if (file == NULL) {
+ g_print ("%s\n", error->message);
+ g_error_free (error);
+ return;
+ }
+
+ data = g_key_file_to_data (file, &len, &error);
+ if (!data) {
+ g_print ("%s\n", error->message);
+ g_error_free (error);
+ } else if (connections_dir) {
+ char *filename = g_build_filename (connections_dir, basename, NULL);
+
+ if (!nm_utils_file_set_contents (filename, data, len, 0600, &error)) {
+ g_print ("%s\n", error->message);
+ g_error_free (error);
+ }
+ g_free (filename);
+ } else {
+ g_print ("\n*** Connection '%s' ***\n\n%s\n", basename, data);
+ }
+
+ g_key_file_free (file);
+}
+
+#define DEFAULT_CONNECTIONS_DIR NMRUNDIR "/system-connections"
+#define DEFAULT_SYSFS_DIR "/sys"
+
+int
+main (int argc, char *argv[])
+{
+ GHashTable *connections;
+ gs_free char *connections_dir = NULL;
+ gs_free char *sysfs_dir = NULL;
+ gboolean dump_to_stdout = FALSE;
+ gs_strfreev char **remaining = NULL;
+ GOptionEntry option_entries[] = {
+ { "connections-dir", 'c', 0, G_OPTION_ARG_FILENAME, &connections_dir, "Output connection directory", DEFAULT_CONNECTIONS_DIR },
+ { "sysfs-dir", 'd', 0, G_OPTION_ARG_FILENAME, &sysfs_dir, "The sysfs mount point", DEFAULT_SYSFS_DIR },
+ { "stdout", 's', 0, G_OPTION_ARG_NONE, &dump_to_stdout, "Dump connections to standard output", NULL },
+ { G_OPTION_REMAINING, '\0', 0, G_OPTION_ARG_STRING_ARRAY, &remaining, NULL, NULL },
+ { NULL }
+ };
+ GOptionContext *option_context;
+ GError *error = NULL;
+
+ option_context = g_option_context_new ("-- [ip=...] [rd.route=...] [bridge=...] [bond=...] [team=...] [vlan=...] "
+ "[bootdev=...] [nameserver=...] [rd.peerdns=...] [rd.bootif=...] [BOOTIF=...] ... ");
+
+ g_option_context_set_summary (option_context, "Generate early NetworkManager configuration.");
+ g_option_context_set_description (option_context,
+ "This tool scans the command line for options relevant to network\n"
+ "configuration and creates configuration files for an early instance\n"
+ "of NetworkManager run from the initial ramdisk during early boot.");
+ g_option_context_add_main_entries (option_context, option_entries, GETTEXT_PACKAGE);
+
+ if (!g_option_context_parse (option_context, &argc, &argv, &error)) {
+ _LOGW (LOGD_CORE, "%s\n", error->message);
+ return 1;
+ }
+
+ if (!remaining) {
+ /* No arguments, no networking. Don't bother. */
+ return 0;
+ }
+
+ if (!connections_dir)
+ connections_dir = g_strdup (DEFAULT_CONNECTIONS_DIR);
+ if (!sysfs_dir)
+ sysfs_dir = g_strdup (DEFAULT_SYSFS_DIR);
+ if (dump_to_stdout)
+ g_clear_pointer (&connections_dir, g_free);
+
+ if (connections_dir && g_mkdir_with_parents (connections_dir, 0755) != 0) {
+ _LOGW (LOGD_CORE, "%s: %s\n", connections_dir, strerror (errno));
+ return 1;
+ }
+
+ connections = nmi_cmdline_reader_parse (sysfs_dir, remaining);
+ g_hash_table_foreach (connections, output_conn, connections_dir);
+ g_hash_table_destroy (connections);
+
+ return 0;
+}
diff --git a/src/initrd/nm-initrd-generator.h b/src/initrd/nm-initrd-generator.h
new file mode 100644
index 0000000000..1fa858fc6a
--- /dev/null
+++ b/src/initrd/nm-initrd-generator.h
@@ -0,0 +1,45 @@
+/* NetworkManager initrd configuration generator
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright (C) 2014, 2018 Red Hat, Inc.
+ */
+
+#ifndef __NM_INITRD_GENERATOR_H__
+#define __NM_INITRD_GENERATOR_H__
+
+#include "nm-connection.h"
+#include "nm-utils.h"
+
+static inline gboolean
+guess_ip_address_family (const char *str)
+{
+ if (str == NULL)
+ return AF_UNSPEC;
+ else if (strchr (str, '.'))
+ return AF_INET;
+ else if (strchr (str, ':'))
+ return AF_INET6;
+ else
+ return AF_UNSPEC;
+}
+
+GHashTable *nmi_ibft_read (const char *sysfs_dir);
+
+gboolean nmi_ibft_update_connection_from_nic (NMConnection *connection, GHashTable *nic, GError **error);
+
+GHashTable *nmi_cmdline_reader_parse (const char *sysfs_dir, char **argv);
+
+#endif /* __NM_INITRD_GENERATOR_H__ */
diff --git a/src/initrd/nmi-cmdline-reader.c b/src/initrd/nmi-cmdline-reader.c
new file mode 100644
index 0000000000..d54a3179fb
--- /dev/null
+++ b/src/initrd/nmi-cmdline-reader.c
@@ -0,0 +1,714 @@
+/* NetworkManager initrd configuration generator
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA.
+ *
+ * Copyright (C) 2018 Red Hat, Inc.
+ */
+
+#include "nm-default.h"
+#include "nm-core-internal.h"
+
+#include "nm-initrd-generator.h"
+
+#include
+
+/*****************************************************************************/
+
+#define _NMLOG(level, domain, ...) \
+ nm_log ((level), (domain), NULL, NULL, \
+ "cmdline-reader: " _NM_UTILS_MACRO_FIRST (__VA_ARGS__) \
+ _NM_UTILS_MACRO_REST (__VA_ARGS__))
+
+/*****************************************************************************/
+
+static NMConnection *
+get_conn (GHashTable *connections, const char *ifname, const char *type_name)
+{
+ NMConnection *connection;
+ NMSetting *setting;
+ const char *basename = ifname ?: "default_connection";
+
+ connection = g_hash_table_lookup (connections, (gpointer)basename);
+
+ if (connection) {
+ setting = (NMSetting *)nm_connection_get_setting_connection (connection);
+ } else {
+ connection = nm_simple_connection_new ();
+ g_hash_table_insert (connections, g_strdup (basename), connection);
+
+ /* Start off assuming dynamic IP configurations. */
+
+ setting = nm_setting_ip4_config_new ();
+ nm_connection_add_setting (connection, setting);
+ g_object_set (setting,
+ NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO,
+ NM_SETTING_IP_CONFIG_MAY_FAIL, TRUE,
+ NULL);
+
+ setting = nm_setting_ip6_config_new ();
+ nm_connection_add_setting (connection, setting);
+ g_object_set (setting,
+ NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO,
+ NM_SETTING_IP_CONFIG_MAY_FAIL, TRUE,
+ NULL);
+
+ setting = nm_setting_connection_new ();
+ nm_connection_add_setting (connection, setting);
+ g_object_set (setting,
+ NM_SETTING_CONNECTION_ID, ifname ?: "Wired Connection",
+ NM_SETTING_CONNECTION_UUID, nm_utils_uuid_generate_a (),
+ NM_SETTING_CONNECTION_INTERFACE_NAME, ifname,
+ NULL);
+
+ if (!type_name)
+ type_name = NM_SETTING_WIRED_SETTING_NAME;
+ }
+
+ if (type_name) {
+ g_object_set (setting, NM_SETTING_CONNECTION_TYPE, type_name, NULL);
+ if (!nm_connection_get_setting_by_name (connection, type_name)) {
+ setting = g_object_new (nm_setting_lookup_type (type_name), NULL);
+ nm_connection_add_setting (connection, setting);
+ }
+ }
+
+ return connection;
+}
+
+static char *
+get_word (char **argument, const char separator)
+{
+ char *word;
+ int nest = 0;
+
+ if (*argument == NULL)
+ return NULL;
+
+ if (**argument == '[') {
+ nest++;
+ (*argument)++;
+ }
+
+ word = *argument;
+
+ while (**argument != '\0') {
+ if (nest && **argument == ']') {
+ **argument = '\0';
+ (*argument)++;
+ nest--;
+ continue;
+ }
+
+ if (nest == 0 && **argument == separator) {
+ **argument = '\0';
+ (*argument)++;
+ break;
+ }
+ (*argument)++;
+ }
+
+ return *word ? word : NULL;
+}
+
+static void
+_base_setting_set (NMConnection *connection, const char *property, const char *value)
+{
+ NMSetting *setting;
+ const char *type_name = nm_connection_get_connection_type (connection);
+ GObjectClass *object_class = g_type_class_ref (nm_setting_lookup_type (type_name));
+ GParamSpec *spec = g_object_class_find_property (object_class, property);
+
+ if (!spec) {
+ _LOGW (LOGD_CORE, "'%s' does not support setting %s\n", type_name, property);
+ return;
+ }
+
+ setting = nm_connection_get_setting_by_name (connection, type_name);
+
+ if (G_IS_PARAM_SPEC_UINT (spec))
+ g_object_set (setting, property, g_ascii_strtoull (value, NULL, 10), NULL);
+ else if (G_IS_PARAM_SPEC_STRING (spec))
+ g_object_set (setting, property, value, NULL);
+ else
+ _LOGW (LOGD_CORE, "Don't know how to set '%s' of %s\n", property, type_name);
+
+ g_type_class_unref (object_class);
+}
+
+static void
+parse_ip (GHashTable *connections, const char *sysfs_dir, char *argument)
+{
+ NMConnection *connection;
+ NMSettingIPConfig *s_ip4 = NULL, *s_ip6 = NULL;
+ gs_unref_hashtable GHashTable *ibft = NULL;
+ const char *tmp;
+ const char *kind = NULL;
+ const char *client_ip = NULL;
+ const char *peer = NULL;
+ const char *gateway_ip = NULL;
+ const char *netmask = NULL;
+ const char *client_hostname = NULL;
+ const char *ifname = NULL;
+ const char *mtu = NULL;
+ const char *macaddr = NULL;
+ int client_ip_family = AF_UNSPEC;
+ int client_ip_prefix = -1;
+ const char *dns[2] = { 0, };
+ int dns_addr_family[2] = { 0, };
+ int i;
+ GError *error = NULL;
+
+ if (!*argument)
+ return;
+
+ tmp = get_word (&argument, ':');
+ if (!*argument) {
+ /* ip={dhcp|on|any|dhcp6|auto6|ibft} */
+ kind = tmp;
+ } else {
+ client_ip_family = guess_ip_address_family (tmp);
+ if (client_ip_family != AF_UNSPEC) {
+ /* :[]:::: */
+ client_ip = tmp;
+ peer = get_word (&argument, ':');
+ gateway_ip = get_word (&argument, ':');
+ netmask = get_word (&argument, ':');
+ client_hostname = get_word (&argument, ':');
+ ifname = get_word (&argument, ':');
+ } else {
+ ifname = tmp;
+ }
+
+ /* :{none|off|dhcp|on|any|dhcp6|auto6|ibft} */
+
+ kind = get_word (&argument, ':');
+
+ tmp = get_word (&argument, ':');
+ dns_addr_family[0] = guess_ip_address_family (tmp);
+ if (dns_addr_family[0] != AF_UNSPEC) {
+ dns[0] = tmp;
+ dns[1] = get_word (&argument, ':');
+ dns_addr_family[1] = guess_ip_address_family (dns[1]);
+ if (argument && *argument)
+ _LOGW (LOGD_CORE, "Ignoring extra: '%s'.\n", argument);
+ } else {
+ mtu = tmp;
+ macaddr = argument;
+ }
+ }
+
+ if (ifname == NULL && g_strcmp0 (kind, "ibft") == 0) {
+ GHashTableIter iter;
+ const char *mac;
+ GHashTable *nic;
+ const char *index;
+
+ /* This is the ip=ibft case. Just take all we got from iBFT
+ * and don't process anything else, since there's no ifname
+ * specified to apply it to. */
+ if (!ibft)
+ ibft = nmi_ibft_read (sysfs_dir);
+
+ g_hash_table_iter_init (&iter, ibft);
+ while (g_hash_table_iter_next (&iter, (gpointer)&mac, (gpointer)&nic)) {
+ connection = nm_simple_connection_new ();
+
+ index = g_hash_table_lookup (nic, "index");
+ if (!index) {
+ _LOGW (LOGD_CORE, "Ignoring an iBFT entry without an index\n");
+ continue;
+ }
+
+ if (!nmi_ibft_update_connection_from_nic (connection, nic, &error)) {
+ _LOGW (LOGD_CORE, "Unable to merge iBFT configuration: %s\n", error->message);
+ g_error_free (error);
+ }
+
+ g_hash_table_insert (connections,
+ g_strdup_printf ("ibft%s", index),
+ connection);
+ }
+
+ return;
+ }
+
+ /* Parsing done, construct the NMConnection. */
+ connection = get_conn (connections, ifname, NULL);
+ s_ip4 = nm_connection_get_setting_ip4_config (connection);
+ s_ip6 = nm_connection_get_setting_ip6_config (connection);
+
+ if (netmask && *netmask) {
+ NMIPAddr addr;
+
+ if (nm_utils_parse_inaddr_bin (AF_INET, netmask, &addr)) {
+ client_ip_prefix = nm_utils_ip4_netmask_to_prefix (addr.addr4);
+ } else {
+ _LOGW (LOGD_CORE, "Unrecognized address: %s\n", client_ip);
+ }
+ }
+
+ /* Static IP configuration might be present. */
+ if (client_ip && *client_ip) {
+ NMIPAddress *address = NULL;
+ NMIPAddr addr;
+
+ if (nm_utils_parse_inaddr_prefix_bin (client_ip_family, client_ip, &addr,
+ client_ip_prefix == -1 ? &client_ip_prefix : NULL)) {
+ if (client_ip_prefix == -1) {
+ switch (client_ip_family) {
+ case AF_INET:
+ client_ip_prefix = _nm_utils_ip4_get_default_prefix (addr.addr4);
+ break;
+ case AF_INET6:
+ client_ip_prefix = 64;
+ break;
+ }
+ }
+
+ address = nm_ip_address_new_binary (client_ip_family, &addr.addr_ptr, client_ip_prefix, &error);
+ if (!address) {
+ _LOGW (LOGD_CORE, "Invalid address '%s': %s\n", client_ip, error->message);
+ g_clear_error (&error);
+ }
+ } else {
+ _LOGW (LOGD_CORE, "Unrecognized address: %s\n", client_ip);
+ }
+
+ if (address) {
+ switch (client_ip_family) {
+ case AF_INET:
+ g_object_set (s_ip4,
+ NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_MANUAL,
+ NM_SETTING_IP_CONFIG_MAY_FAIL, FALSE,
+ NULL);
+ nm_setting_ip_config_add_address (s_ip4, address);
+ break;
+ case AF_INET6:
+ g_object_set (s_ip6,
+ NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_MANUAL,
+ NM_SETTING_IP_CONFIG_MAY_FAIL, FALSE,
+ NULL);
+ nm_setting_ip_config_add_address (s_ip6, address);
+ break;
+ default:
+ _LOGW (LOGD_CORE, "Unknown address family: %s\n", client_ip);
+ break;
+ }
+ nm_ip_address_unref (address);
+ }
+ }
+
+ /* Dynamic IP configuration configured explicitly. */
+ if (g_strcmp0 (kind, "none") == 0 || (g_strcmp0 (kind, "off") == 0)) {
+ if (nm_setting_ip_config_get_num_addresses (s_ip6) == 0) {
+ g_object_set (s_ip6,
+ NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_IGNORE,
+ NULL);
+ }
+ if (nm_setting_ip_config_get_num_addresses (s_ip4) == 0) {
+ g_object_set (s_ip4,
+ NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_DISABLED,
+ NULL);
+ }
+ } else if (g_strcmp0 (kind, "dhcp") == 0) {
+ g_object_set (s_ip4,
+ NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO,
+ NM_SETTING_IP_CONFIG_MAY_FAIL, FALSE,
+ NULL);
+ if (nm_setting_ip_config_get_num_addresses (s_ip6) == 0) {
+ g_object_set (s_ip6,
+ NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_IGNORE,
+ NULL);
+ }
+ } else if (g_strcmp0 (kind, "dhcp6") == 0) {
+ g_object_set (s_ip6,
+ NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_DHCP,
+ NM_SETTING_IP_CONFIG_MAY_FAIL, FALSE,
+ NULL);
+ if (nm_setting_ip_config_get_num_addresses (s_ip4) == 0) {
+ g_object_set (s_ip4,
+ NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_DISABLED,
+ NULL);
+ }
+ } else if (g_strcmp0 (kind, "auto6") == 0) {
+ g_object_set (s_ip4,
+ NM_SETTING_IP_CONFIG_MAY_FAIL, FALSE,
+ NULL);
+ if (nm_setting_ip_config_get_num_addresses (s_ip4) == 0) {
+ g_object_set (s_ip4,
+ NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_DISABLED,
+ NULL);
+ }
+ } else if (g_strcmp0 (kind, "ibft") == 0) {
+ gs_free char *address_path = g_build_filename (sysfs_dir, "class", "net", ifname, "address", NULL);
+ gs_free char *mac, *mac_up = NULL;
+ GHashTable *nic = NULL;
+
+ if (!g_file_get_contents (address_path, &mac, NULL, &error)) {
+ _LOGW (LOGD_CORE, "Can't get a MAC address for %s: %s", ifname, error->message);
+ g_clear_error (&error);
+ }
+
+ if (mac) {
+ g_strchomp (mac);
+ mac_up = g_ascii_strup (mac, -1);
+ if (!ibft)
+ ibft = nmi_ibft_read (sysfs_dir);
+ nic = g_hash_table_lookup (ibft, mac_up);
+ if (!nic)
+ _LOGW (LOGD_CORE, "No iBFT NIC for %s (%s)\n", ifname, mac_up);
+ }
+
+ if (nic) {
+ if (!nmi_ibft_update_connection_from_nic (connection, nic, &error)) {
+ _LOGW (LOGD_CORE, "Unable to merge iBFT configuration: %s\n", error->message);
+ g_clear_error (&error);
+ }
+ }
+ }
+
+ if (peer && *peer)
+ _LOGW (LOGD_CORE, "Ignoring peer: %s (not implemented)\b", peer);
+
+ if (gateway_ip && *gateway_ip) {
+ int addr_family = guess_ip_address_family (gateway_ip);
+
+ if (nm_utils_ipaddr_valid (addr_family, gateway_ip)) {
+ switch (addr_family) {
+ case AF_INET:
+ g_object_set (s_ip4, NM_SETTING_IP_CONFIG_GATEWAY, gateway_ip, NULL);
+ break;
+ case AF_INET6:
+ g_object_set (s_ip6, NM_SETTING_IP_CONFIG_GATEWAY, gateway_ip, NULL);
+ break;
+ default:
+ _LOGW (LOGD_CORE, "Unknown address family: %s\n", gateway_ip);
+ break;
+ }
+ } else {
+ _LOGW (LOGD_CORE, "Invalid gateway: %s\n", gateway_ip);
+ }
+ }
+
+ if (client_hostname && *client_hostname) {
+ g_object_set (s_ip4, NM_SETTING_IP_CONFIG_DHCP_HOSTNAME, client_hostname, NULL);
+ g_object_set (s_ip6, NM_SETTING_IP_CONFIG_DHCP_HOSTNAME, client_hostname, NULL);
+ }
+
+ for (i = 0; i < 2; i++) {
+ if (dns_addr_family[i] == AF_UNSPEC)
+ break;
+ if (nm_utils_ipaddr_valid (dns_addr_family[i], dns[i])) {
+ switch (dns_addr_family[i]) {
+ case AF_INET:
+ nm_setting_ip_config_add_dns (s_ip4, dns[i]);
+ break;
+ case AF_INET6:
+ nm_setting_ip_config_add_dns (s_ip6, dns[i]);
+ break;
+ default:
+ _LOGW (LOGD_CORE, "Unknown address family: %s\n", dns[i]);
+ break;
+ }
+ } else {
+ _LOGW (LOGD_CORE, "Invalid name server: %s\n", dns[i]);
+ }
+ }
+
+ if (mtu && *mtu)
+ _base_setting_set (connection, "mtu", mtu);
+
+ if (macaddr && *macaddr)
+ _base_setting_set (connection, "cloned-mac-address", macaddr);
+}
+
+static void
+parse_master (GHashTable *connections, char *argument, const char *type_name)
+{
+ NMConnection *connection;
+ NMSettingConnection *s_con;
+ NMSettingBond *s_bond;
+ gs_free char *master_to_free = NULL;
+ const char *master;
+ char *slaves;
+ const char *slave;
+ char *opts;
+ char *opt;
+ const char *opt_name;
+ const char *mtu = NULL;
+
+ master = get_word (&argument, ':');
+ if (!master)
+ master = master_to_free = g_strdup_printf ("%s0", type_name);
+ slaves = get_word (&argument, ':');
+
+ connection = get_conn (connections, master, type_name);
+ s_con = nm_connection_get_setting_connection (connection);
+ master = nm_setting_connection_get_uuid (s_con);
+
+ if (strcmp (type_name, NM_SETTING_BOND_SETTING_NAME) == 0) {
+ s_bond = (NMSettingBond *)nm_connection_get_setting_by_name (connection, type_name);
+
+ opts = get_word (&argument, ':');
+ while (opts && *opts) {
+ opt = get_word (&opts, ',');
+ opt_name = get_word (&opt, '=');
+ nm_setting_bond_add_option (s_bond, opt_name, opt);
+ }
+
+ mtu = get_word (&argument, ':');
+ }
+
+ do {
+ slave = get_word (&slaves, ',');
+ if (slave == NULL)
+ slave = "eth0";
+
+ connection = get_conn (connections, slave, NULL);
+ s_con = nm_connection_get_setting_connection (connection);
+ g_object_set (s_con,
+ NM_SETTING_CONNECTION_SLAVE_TYPE, type_name,
+ NM_SETTING_CONNECTION_MASTER, master,
+ NULL);
+ if (mtu)
+ _base_setting_set (connection, "mtu", mtu);
+ } while (slaves && *slaves != '\0');
+
+ if (argument && *argument)
+ _LOGW (LOGD_CORE, "Ignoring extra: '%s'.\n", argument);
+}
+
+static void
+parse_rd_route (GHashTable *connections, char *argument)
+{
+ NMConnection *connection;
+ const char *net;
+ const char *gateway;
+ const char *interface;
+ int family = AF_UNSPEC;
+ NMIPAddr net_addr = { 0, };
+ NMIPAddr gateway_addr = { 0, };
+ int net_prefix = -1;
+ NMIPRoute *route;
+ NMSettingIPConfig *s_ip;
+ GError *error = NULL;
+
+ net = get_word (&argument, ':');
+ gateway = get_word (&argument, ':');
+ interface = get_word (&argument, ':');
+
+ family = guess_ip_address_family (net);
+ connection = get_conn (connections, interface, NULL);
+
+ if (net && *net) {
+ if (!nm_utils_parse_inaddr_prefix_bin (family, net, &net_addr, &net_prefix)) {
+ _LOGW (LOGD_CORE, "Unrecognized address: %s\n", net);
+ return;
+ }
+ }
+
+ if (gateway && *net) {
+ if (!nm_utils_parse_inaddr_bin (family, gateway, &gateway_addr)) {
+ _LOGW (LOGD_CORE, "Unrecognized address: %s\n", gateway);
+ return;
+ }
+ }
+
+ switch (family) {
+ case AF_INET:
+ s_ip = nm_connection_get_setting_ip4_config (connection);
+ if (net_prefix == -1)
+ net_prefix = 32;
+ break;
+ case AF_INET6:
+ s_ip = nm_connection_get_setting_ip6_config (connection);
+ if (net_prefix == -1)
+ net_prefix = 128;
+ break;
+ default:
+ _LOGW (LOGD_CORE, "Unknown address family: %s\n", net);
+ return;
+ }
+
+ route = nm_ip_route_new_binary (family, &net_addr.addr_ptr, net_prefix, &gateway_addr.addr_ptr, -1, &error);
+ if (!route) {
+ g_warning ("Invalid route '%s via %s': %s\n", net, gateway, error->message);
+ g_clear_error (&error);
+ return;
+ }
+
+ nm_setting_ip_config_add_route (s_ip, route);
+ nm_ip_route_unref (route);
+}
+
+static void
+parse_vlan (GHashTable *connections, char *argument)
+{
+ NMConnection *connection;
+ NMSettingVlan *s_vlan;
+ const char *vlan;
+ const char *phy;
+ const char *vlanid;
+
+ vlan = get_word (&argument, ':');
+ phy = get_word (&argument, ':');
+
+ for (vlanid = vlan + strlen (vlan); vlanid > vlan; vlanid--) {
+ if (!g_ascii_isdigit (*(vlanid - 1)))
+ break;
+ }
+
+ connection = get_conn (connections, vlan, NM_SETTING_VLAN_SETTING_NAME);
+
+ s_vlan = nm_connection_get_setting_vlan (connection);
+ g_object_set (s_vlan,
+ NM_SETTING_VLAN_PARENT, phy,
+ NM_SETTING_VLAN_ID, g_ascii_strtoull (vlanid, NULL, 10),
+ NULL);
+
+ if (argument && *argument)
+ _LOGW (LOGD_CORE, "Ignoring extra: '%s'.\n", argument);
+}
+
+static void
+parse_bootdev (GHashTable *connections, char *argument)
+{
+ NMConnection *connection;
+ NMSettingConnection *s_con;
+
+ connection = get_conn (connections, NULL, NULL);
+
+ s_con = nm_connection_get_setting_connection (connection);
+ g_object_set (s_con,
+ NM_SETTING_CONNECTION_INTERFACE_NAME, argument,
+ NULL);
+}
+
+static void
+parse_nameserver (GHashTable *connections, char *argument)
+{
+ NMConnection *connection;
+ NMSettingIPConfig *s_ip = NULL;
+ char *dns;
+
+ connection = get_conn (connections, NULL, NULL);
+
+ dns = get_word (&argument, '\0');
+
+ switch (guess_ip_address_family (dns)) {
+ case AF_INET:
+ s_ip = nm_connection_get_setting_ip4_config (connection);
+ break;
+ case AF_INET6:
+ s_ip = nm_connection_get_setting_ip6_config (connection);
+ break;
+ default:
+ _LOGW (LOGD_CORE, "Unknown address family: %s\n", dns);
+ break;
+ }
+
+ nm_setting_ip_config_add_dns (s_ip, dns);
+
+ if (argument && *argument)
+ _LOGW (LOGD_CORE, "xIgnoring extra: '%s'.\n", argument);
+}
+
+static void
+parse_rd_peerdns (GHashTable *connections, char *argument)
+{
+ gboolean auto_dns = !_nm_utils_ascii_str_to_bool (argument, TRUE);
+ NMConnection *connection;
+ NMSettingIPConfig *s_ip = NULL;
+
+ connection = get_conn (connections, NULL, NULL);
+
+ s_ip = nm_connection_get_setting_ip4_config (connection);
+ g_object_set (s_ip,
+ NM_SETTING_IP_CONFIG_IGNORE_AUTO_DNS, auto_dns,
+ NULL);
+
+
+ s_ip = nm_connection_get_setting_ip6_config (connection);
+ g_object_set (s_ip,
+ NM_SETTING_IP_CONFIG_IGNORE_AUTO_DNS, auto_dns,
+ NULL);
+}
+
+static void
+_normalize_conn (gpointer key, gpointer value, gpointer user_data)
+{
+ NMConnection *connection = value;
+
+ nm_connection_normalize (connection, NULL, NULL, NULL);
+}
+
+GHashTable *
+nmi_cmdline_reader_parse (const char *sysfs_dir, char **argv)
+{
+ GHashTable *connections;
+ const char *tag;
+ char *argument;
+ gboolean ignore_bootif = FALSE;
+ char *bootif = NULL;
+ int i;
+
+ connections = g_hash_table_new_full (nm_str_hash, g_str_equal, g_free, g_object_unref);
+
+ for (i = 0; argv[i]; i++) {
+ argument = argv[i];
+ tag = get_word (&argument, '=');
+ if (strcmp (tag, "ip") == 0)
+ parse_ip (connections, sysfs_dir, argument);
+ else if (strcmp (tag, "rd.route") == 0)
+ parse_rd_route (connections, argument);
+ else if (strcmp (tag, "bridge") == 0)
+ parse_master (connections, argument, NM_SETTING_BRIDGE_SETTING_NAME);
+ else if (strcmp (tag, "bond") == 0)
+ parse_master (connections, argument, NM_SETTING_BOND_SETTING_NAME);
+ else if (strcmp (tag, "team") == 0)
+ parse_master (connections, argument, NM_SETTING_TEAM_SETTING_NAME);
+ else if (strcmp (tag, "vlan") == 0)
+ parse_vlan (connections, argument);
+ else if (strcmp (tag, "bootdev") == 0)
+ parse_bootdev (connections, argument);
+ else if (strcmp (tag, "nameserver") == 0)
+ parse_nameserver (connections, argument);
+ else if (strcmp (tag, "rd.peerdns") == 0)
+ parse_rd_peerdns (connections, argument);
+ else if (strcmp (tag, "rd.bootif") == 0)
+ ignore_bootif = !_nm_utils_ascii_str_to_bool (argument, TRUE);
+ else if (strcasecmp (tag, "BOOTIF") == 0)
+ bootif = argument;
+ }
+
+ if (ignore_bootif)
+ bootif = NULL;
+ if (bootif) {
+ NMConnection *connection;
+ NMSettingWired *s_wired;
+
+ connection = get_conn (connections, NULL, NM_SETTING_WIRED_SETTING_NAME);
+
+ s_wired = nm_connection_get_setting_wired (connection);
+ g_object_set (s_wired,
+ NM_SETTING_WIRED_MAC_ADDRESS, bootif,
+ NULL);
+ }
+
+ g_hash_table_foreach (connections, _normalize_conn, NULL);
+
+ return connections;
+}
diff --git a/src/initrd/nmi-ibft-reader.c b/src/initrd/nmi-ibft-reader.c
new file mode 100644
index 0000000000..c927546746
--- /dev/null
+++ b/src/initrd/nmi-ibft-reader.c
@@ -0,0 +1,441 @@
+/* NetworkManager initrd configuration generator
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright 2014 - 2018 Red Hat, Inc.
+ */
+
+#include "nm-default.h"
+
+#include "nm-initrd-generator.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "nm-core-internal.h"
+#include "platform/nm-platform.h"
+#include "NetworkManagerUtils.h"
+
+/*****************************************************************************/
+
+#define _NMLOG(level, domain, ...) \
+ nm_log ((level), (domain), NULL, NULL, \
+ "ibft-reader: " _NM_UTILS_MACRO_FIRST (__VA_ARGS__) \
+ _NM_UTILS_MACRO_REST (__VA_ARGS__))
+
+/*****************************************************************************/
+
+static GHashTable *
+load_one_nic (const char *sysfs_dir, const char *dir_name)
+{
+ gs_free char *nic_path = g_build_filename (sysfs_dir, dir_name, NULL);
+ GDir *nic_dir;
+ const char *entry_name;
+ char *content;
+ gs_free_error GError *error = NULL;
+ GHashTable *nic;
+
+ g_return_val_if_fail (sysfs_dir != NULL, FALSE);
+
+ nic_dir = g_dir_open (nic_path, 0, &error);
+ if (!nic_dir) {
+ _LOGW (LOGD_CORE, "Can't open %s: %s", nic_path, error->message);
+ return NULL;
+ }
+
+ nic = g_hash_table_new_full (nm_str_hash, g_str_equal, g_free, g_free);
+ while ((entry_name = g_dir_read_name (nic_dir))) {
+ gs_free char *entry_path = g_build_filename (nic_path, entry_name, NULL);
+
+ if (!g_file_test (entry_path, G_FILE_TEST_IS_REGULAR))
+ continue;
+
+ if (!g_file_get_contents (entry_path, &content, NULL, &error)) {
+ _LOGW (LOGD_CORE, "Can't read %s: %s", entry_path, error->message);
+ g_clear_error (&error);
+ continue;
+ }
+
+ g_strchomp (content);
+ if (!g_hash_table_insert (nic, g_strdup (entry_name), content))
+ _LOGW (LOGD_CORE, "Duplicate iBFT entry: %s", entry_name);
+ }
+
+ g_dir_close (nic_dir);
+
+ return nic;
+}
+
+GHashTable *
+nmi_ibft_read (const char *sysfs_dir)
+{
+ gs_free char *ibft_path = NULL;
+ GDir *ibft_dir;
+ const char *dir_name;
+ GHashTable *ibft, *nic;
+ char *mac;
+ gs_free_error GError *error = NULL;
+
+ g_return_val_if_fail (sysfs_dir != NULL, FALSE);
+
+ ibft_path = g_build_filename (sysfs_dir, "firmware", "ibft", NULL);
+
+ ibft = g_hash_table_new_full (nm_str_hash, g_str_equal, g_free,
+ (GDestroyNotify) g_hash_table_unref);
+
+ if (!g_file_test (ibft_path, G_FILE_TEST_IS_DIR))
+ nm_utils_modprobe (NULL, FALSE, "iscsi_ibft", NULL);
+ if (!g_file_test (ibft_path, G_FILE_TEST_IS_DIR))
+ return ibft;
+
+ ibft_dir = g_dir_open (ibft_path, 0, &error);
+ if (!ibft_dir) {
+ _LOGW (LOGD_CORE, "Unable to open iBFT firmware directory: %s", error->message);
+ return ibft;
+ }
+
+ while ((dir_name = g_dir_read_name (ibft_dir))) {
+ if (!g_str_has_prefix (dir_name, "ethernet"))
+ continue;
+
+ nic = load_one_nic (ibft_path, dir_name);
+ mac = g_hash_table_lookup (nic, "mac");
+
+ if (!mac) {
+ _LOGW (LOGD_CORE, "Ignoring an iBFT record without a MAC address");
+ g_hash_table_unref (nic);
+ continue;
+ }
+
+ mac = g_ascii_strup (mac, -1);
+ if (!g_hash_table_insert (ibft, mac, nic))
+ _LOGW (LOGD_CORE, "Duplicate iBFT record for %s", mac);
+ }
+
+ g_dir_close (ibft_dir);
+
+ return ibft;
+}
+
+static gboolean
+ip_setting_add_from_block (GHashTable *nic,
+ NMConnection *connection,
+ GError **error)
+{
+ NMSettingIPConfig *s_ip = NULL;
+ NMSettingIPConfig *s_ip4 = NULL;
+ NMSettingIPConfig *s_ip6 = NULL;
+ NMIPAddress *addr;
+ const char *s_ipaddr = NULL;
+ const char *s_prefix = NULL;
+ const char *s_gateway = NULL;
+ const char *s_dns1 = NULL;
+ const char *s_dns2 = NULL;
+ const char *s_origin = NULL;
+ const char *method = NULL;
+ int family;
+ gint64 prefix;
+
+ s_ipaddr = (const char *)g_hash_table_lookup (nic, "ip-addr");
+ s_prefix = (const char *)g_hash_table_lookup (nic, "prefix-len");
+ s_gateway = (const char *)g_hash_table_lookup (nic, "gateway");
+ s_dns1 = (const char *)g_hash_table_lookup (nic, "primary-dns");
+ s_dns2 = (const char *)g_hash_table_lookup (nic, "secondary-dns");
+ s_origin = (const char *)g_hash_table_lookup (nic, "origin");
+
+ s_ip4 = nm_connection_get_setting_ip4_config (connection);
+ if (!s_ip4) {
+ s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new ();
+ nm_connection_add_setting (connection, (NMSetting *) s_ip4);
+ }
+
+ s_ip6 = nm_connection_get_setting_ip6_config (connection);
+ if (!s_ip6) {
+ s_ip6 = (NMSettingIPConfig *) nm_setting_ip6_config_new ();
+ nm_connection_add_setting (connection, (NMSetting *) s_ip6);
+ }
+
+ family = guess_ip_address_family (s_ipaddr);
+ if (family == AF_UNSPEC)
+ family = guess_ip_address_family (s_gateway);
+
+ switch (family) {
+ case AF_INET:
+ s_ip = s_ip4;
+ g_object_set (s_ip6, NM_SETTING_IP_CONFIG_METHOD,
+ NM_SETTING_IP6_CONFIG_METHOD_IGNORE, NULL);
+ break;
+ case AF_INET6:
+ s_ip = s_ip6;
+ g_object_set (s_ip4, NM_SETTING_IP_CONFIG_METHOD,
+ NM_SETTING_IP4_CONFIG_METHOD_DISABLED, NULL);
+ break;
+ default:
+ g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION,
+ "iBFT: invalid IP address '%s'.",
+ s_ipaddr);
+ return FALSE;
+ }
+
+ if ( (g_strcmp0 (s_origin, "3") == 0 && family == AF_INET)
+ || (g_strcmp0 (s_origin, "4") == 0 && family == AF_INET)) {
+ method = NM_SETTING_IP4_CONFIG_METHOD_AUTO;
+ } else if (g_strcmp0 (s_origin, "3") == 0 && family == AF_INET6) {
+ method = NM_SETTING_IP6_CONFIG_METHOD_DHCP;
+ } else if (g_strcmp0 (s_origin, "4") == 0 && family == AF_INET6) {
+ method = NM_SETTING_IP6_CONFIG_METHOD_AUTO;
+ } else if (family == AF_INET) {
+ method = NM_SETTING_IP4_CONFIG_METHOD_MANUAL;
+ } else if (family == AF_INET6) {
+ method = NM_SETTING_IP6_CONFIG_METHOD_MANUAL;
+ } else {
+ g_return_val_if_reached (FALSE);
+ }
+ g_object_set (s_ip,
+ NM_SETTING_IP_CONFIG_METHOD, method,
+ NM_SETTING_IP_CONFIG_MAY_FAIL, FALSE,
+ NULL);
+
+ if (s_gateway && !nm_utils_ipaddr_valid (family, s_gateway)) {
+ g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION,
+ "iBFT: invalid IP gateway '%s'.", s_gateway);
+ return FALSE;
+ }
+
+ if (s_dns1 && !nm_utils_ipaddr_valid (family, s_dns1)) {
+ g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION,
+ "iBFT: invalid DNS1 address '%s'.", s_dns1);
+ return FALSE;
+ }
+
+ if (s_dns2 && !nm_utils_ipaddr_valid (family, s_dns2)) {
+ g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION,
+ "iBFT: invalid DNS2 address '%s'.", s_dns2);
+ return FALSE;
+ }
+
+ if (s_ipaddr) {
+ prefix = _nm_utils_ascii_str_to_int64 (s_prefix, 10, 0, 128, -1);
+ if (prefix == -1) {
+ g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION,
+ "iBFT: invalid IP prefix '%s'.", s_prefix);
+ return FALSE;
+ }
+
+ addr = nm_ip_address_new (family, s_ipaddr, prefix, error);
+ if (!addr) {
+ g_prefix_error (error, "iBFT: ");
+ return FALSE;
+ }
+
+ nm_setting_ip_config_add_address (s_ip, addr);
+ nm_ip_address_unref (addr);
+
+ g_object_set (s_ip, NM_SETTING_IP_CONFIG_GATEWAY, s_gateway, NULL);
+ }
+
+ if (s_dns1)
+ nm_setting_ip_config_add_dns (s_ip, s_dns1);
+ if (s_dns2)
+ nm_setting_ip_config_add_dns (s_ip, s_dns2);
+
+ return TRUE;
+}
+
+static gboolean
+connection_setting_add (GHashTable *nic,
+ NMConnection *connection,
+ const char *type,
+ const char *prefix,
+ GError **error)
+{
+ NMSetting *s_con;
+ char *id, *uuid;
+ const char *s_index, *s_hwaddr, *s_ipaddr, *s_vlanid;
+
+ s_index = (const char *)g_hash_table_lookup (nic, "index");
+ s_hwaddr = (const char *)g_hash_table_lookup (nic, "mac");
+ s_ipaddr = (const char *)g_hash_table_lookup (nic, "ip-addr");
+ s_vlanid = (const char *)g_hash_table_lookup (nic, "vlan");
+
+ if (!s_hwaddr) {
+ g_set_error_literal (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION,
+ "iBFT: missing MAC address");
+ return FALSE;
+ }
+
+ id = g_strdup_printf ("iBFT%s%s Connection%s%s",
+ prefix ? " " : "",
+ prefix ? prefix : "",
+ s_index ? " " : "",
+ s_index ? s_index : "");
+
+ uuid = _nm_utils_uuid_generate_from_strings ("ibft",
+ s_hwaddr,
+ s_vlanid ? "V" : "v",
+ s_vlanid ? s_vlanid : "",
+ s_ipaddr ? "A" : "DHCP",
+ s_ipaddr ? s_ipaddr : "",
+ NULL);
+
+ s_con = (NMSetting *) nm_connection_get_setting_connection (connection);
+ if (!s_con) {
+ s_con = nm_setting_connection_new ();
+ nm_connection_add_setting (connection, s_con);
+ }
+
+ g_object_set (s_con,
+ NM_SETTING_CONNECTION_TYPE, type,
+ NM_SETTING_CONNECTION_UUID, uuid,
+ NM_SETTING_CONNECTION_ID, id,
+ NULL);
+
+ g_free (uuid);
+ g_free (id);
+
+ return TRUE;
+}
+
+static gboolean
+is_ibft_vlan_device (GHashTable *nic)
+{
+ const char *s_vlan_id;
+
+ g_assert (nic);
+
+ s_vlan_id = (const char *)g_hash_table_lookup (nic, "vlan");
+
+ if (s_vlan_id) {
+ /* VLAN 0 is normally a valid VLAN ID, but in the iBFT case it
+ * means "no VLAN".
+ */
+ if (_nm_utils_ascii_str_to_int64 (s_vlan_id, 10, 1, 4095, -1) != -1)
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static gboolean
+vlan_setting_add_from_block (GHashTable *nic,
+ NMConnection *connection,
+ GError **error)
+{
+ NMSetting *s_vlan = NULL;
+ const char *vlan_id_str = NULL;
+ gint64 vlan_id = -1;
+
+ g_assert (nic);
+ g_assert (connection);
+
+ /* This won't fail since this function shouldn't be called unless the
+ * iBFT VLAN ID exists and is > 0.
+ */
+ vlan_id_str = (const char *)g_hash_table_lookup (nic, "vlan");
+ g_assert (vlan_id_str);
+
+ /* VLAN 0 is normally a valid VLAN ID, but in the iBFT case it means "no VLAN" */
+ vlan_id = _nm_utils_ascii_str_to_int64 (vlan_id_str, 10, 1, 4095, -1);
+ if (vlan_id == -1) {
+ g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION,
+ "Invalid VLAN_ID '%s'", vlan_id_str);
+ return FALSE;
+ }
+
+ s_vlan = (NMSetting *) nm_connection_get_setting_vlan (connection);
+ if (!s_vlan) {
+ s_vlan = nm_setting_vlan_new ();
+ nm_connection_add_setting (connection, s_vlan);
+ }
+
+ g_object_set (s_vlan, NM_SETTING_VLAN_ID, (guint32) vlan_id, NULL);
+
+ return TRUE;
+}
+
+static gboolean
+wired_setting_add_from_block (GHashTable *nic,
+ NMConnection *connection,
+ GError **error)
+{
+ NMSetting *s_wired = NULL;
+ const char *hwaddr = NULL;
+
+ g_assert (nic);
+ g_assert (connection);
+
+
+ hwaddr = (const char *)g_hash_table_lookup (nic, "mac");
+ if (!hwaddr) {
+ g_set_error_literal (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION,
+ "iBFT: missing MAC address");
+ return FALSE;
+ }
+
+ if (!nm_utils_hwaddr_valid (hwaddr, ETH_ALEN)) {
+ g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION,
+ "iBFT: invalid MAC address '%s'.", hwaddr);
+ return FALSE;
+ }
+
+ s_wired = (NMSetting *) nm_connection_get_setting_wired (connection);
+ if (!s_wired) {
+ s_wired = nm_setting_wired_new ();
+ nm_connection_add_setting (connection, s_wired);
+ }
+
+ g_object_set (s_wired, NM_SETTING_WIRED_MAC_ADDRESS, hwaddr, NULL);
+
+ return TRUE;
+}
+
+gboolean
+nmi_ibft_update_connection_from_nic (NMConnection *connection, GHashTable *nic, GError **error)
+{
+ gboolean is_vlan = FALSE;
+
+ g_assert (nic);
+
+ is_vlan = is_ibft_vlan_device (nic);
+ if (is_vlan && !vlan_setting_add_from_block (nic, connection, error))
+ return FALSE;
+
+ /* Always have a wired setting; for VLAN it defines the parent */
+ if (!wired_setting_add_from_block (nic, connection, error))
+ return FALSE;
+
+ if (!ip_setting_add_from_block (nic, connection, error))
+ return FALSE;
+
+ if (!connection_setting_add (nic,
+ connection,
+ is_vlan ? NM_SETTING_VLAN_SETTING_NAME : NM_SETTING_WIRED_SETTING_NAME,
+ is_vlan ? "VLAN" : NULL,
+ error))
+ return FALSE;
+
+ if (!nm_connection_normalize (connection, NULL, NULL, error))
+ return FALSE;
+
+ return TRUE;
+}
diff --git a/src/initrd/tests/meson.build b/src/initrd/tests/meson.build
new file mode 100644
index 0000000000..0e74ea8d9e
--- /dev/null
+++ b/src/initrd/tests/meson.build
@@ -0,0 +1,22 @@
+test_unit = 'test-ibft'
+
+test_ibft_dir = meson.current_source_dir()
+
+cflags = [
+ '-DTEST_IBFT_DIR="@0@"'.format(test_ibft_dir),
+ '-DTEST_SCRATCH_DIR="@0@"'.format(test_ibft_dir)
+]
+
+exe = executable(
+ test_unit,
+ test_unit + '.c',
+ dependencies: test_nm_dep,
+ c_args: cflags,
+ link_with: libnmi_ibft_core
+)
+
+test(
+ 'ibft/' + test_unit,
+ test_script,
+ args: test_args + [exe.full_path()]
+)
diff --git a/src/initrd/tests/sysfs-bad-dns1/class/net/eth0/address b/src/initrd/tests/sysfs-bad-dns1/class/net/eth0/address
new file mode 100644
index 0000000000..20659db7e8
--- /dev/null
+++ b/src/initrd/tests/sysfs-bad-dns1/class/net/eth0/address
@@ -0,0 +1 @@
+00:33:21:98:b9:f0
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/gateway b/src/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/gateway
new file mode 100644
index 0000000000..bf6cf4543f
--- /dev/null
+++ b/src/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/gateway
@@ -0,0 +1 @@
+192.168.35.254
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/index b/src/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/index
new file mode 100644
index 0000000000..c227083464
--- /dev/null
+++ b/src/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/index
@@ -0,0 +1 @@
+0
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/ip-addr b/src/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/ip-addr
new file mode 100644
index 0000000000..944c8d4565
--- /dev/null
+++ b/src/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/ip-addr
@@ -0,0 +1 @@
+192.168.32.72
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/mac b/src/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/mac
new file mode 100644
index 0000000000..20659db7e8
--- /dev/null
+++ b/src/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/mac
@@ -0,0 +1 @@
+00:33:21:98:b9:f0
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/origin b/src/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/origin
new file mode 100644
index 0000000000..56a6051ca2
--- /dev/null
+++ b/src/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/origin
@@ -0,0 +1 @@
+1
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/prefix-len b/src/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/prefix-len
new file mode 100644
index 0000000000..8fdd954df9
--- /dev/null
+++ b/src/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/prefix-len
@@ -0,0 +1 @@
+22
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/primary-dns b/src/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/primary-dns
new file mode 100644
index 0000000000..2303dbdcbc
--- /dev/null
+++ b/src/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/primary-dns
@@ -0,0 +1 @@
+10000.500.250.1
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/secondary-dns b/src/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/secondary-dns
new file mode 100644
index 0000000000..2eb9e1d0ad
--- /dev/null
+++ b/src/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/secondary-dns
@@ -0,0 +1 @@
+10.16.255.3
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/subnet-mask b/src/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/subnet-mask
new file mode 100644
index 0000000000..7cb9d0a9bb
--- /dev/null
+++ b/src/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/subnet-mask
@@ -0,0 +1 @@
+255.255.252.0
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/vlan b/src/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/vlan
new file mode 100644
index 0000000000..c227083464
--- /dev/null
+++ b/src/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/vlan
@@ -0,0 +1 @@
+0
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-bad-dns1/firmware/ibft/initiator/initiator-name b/src/initrd/tests/sysfs-bad-dns1/firmware/ibft/initiator/initiator-name
new file mode 100644
index 0000000000..509a7ab8be
--- /dev/null
+++ b/src/initrd/tests/sysfs-bad-dns1/firmware/ibft/initiator/initiator-name
@@ -0,0 +1 @@
+iqn.pjones6
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-bad-dns1/firmware/ibft/target0/index b/src/initrd/tests/sysfs-bad-dns1/firmware/ibft/target0/index
new file mode 100644
index 0000000000..c227083464
--- /dev/null
+++ b/src/initrd/tests/sysfs-bad-dns1/firmware/ibft/target0/index
@@ -0,0 +1 @@
+0
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-bad-dns1/firmware/ibft/target0/ip-addr b/src/initrd/tests/sysfs-bad-dns1/firmware/ibft/target0/ip-addr
new file mode 100644
index 0000000000..7450fdf90a
--- /dev/null
+++ b/src/initrd/tests/sysfs-bad-dns1/firmware/ibft/target0/ip-addr
@@ -0,0 +1 @@
+10.16.52.16
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-bad-dns1/firmware/ibft/target0/lun b/src/initrd/tests/sysfs-bad-dns1/firmware/ibft/target0/lun
new file mode 100644
index 0000000000..c43d0930ca
--- /dev/null
+++ b/src/initrd/tests/sysfs-bad-dns1/firmware/ibft/target0/lun
@@ -0,0 +1 @@
+00000000
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-bad-dns1/firmware/ibft/target0/port b/src/initrd/tests/sysfs-bad-dns1/firmware/ibft/target0/port
new file mode 100644
index 0000000000..58f0d919f4
--- /dev/null
+++ b/src/initrd/tests/sysfs-bad-dns1/firmware/ibft/target0/port
@@ -0,0 +1 @@
+3260
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-bad-dns1/firmware/ibft/target0/target-name b/src/initrd/tests/sysfs-bad-dns1/firmware/ibft/target0/target-name
new file mode 100644
index 0000000000..32c9450a2f
--- /dev/null
+++ b/src/initrd/tests/sysfs-bad-dns1/firmware/ibft/target0/target-name
@@ -0,0 +1 @@
+iqn.0.2008-11.com.blahblah:iscsi0
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-bad-dns2/class/net/eth0/address b/src/initrd/tests/sysfs-bad-dns2/class/net/eth0/address
new file mode 100644
index 0000000000..20659db7e8
--- /dev/null
+++ b/src/initrd/tests/sysfs-bad-dns2/class/net/eth0/address
@@ -0,0 +1 @@
+00:33:21:98:b9:f0
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/gateway b/src/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/gateway
new file mode 100644
index 0000000000..bf6cf4543f
--- /dev/null
+++ b/src/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/gateway
@@ -0,0 +1 @@
+192.168.35.254
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/index b/src/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/index
new file mode 100644
index 0000000000..c227083464
--- /dev/null
+++ b/src/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/index
@@ -0,0 +1 @@
+0
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/ip-addr b/src/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/ip-addr
new file mode 100644
index 0000000000..944c8d4565
--- /dev/null
+++ b/src/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/ip-addr
@@ -0,0 +1 @@
+192.168.32.72
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/mac b/src/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/mac
new file mode 100644
index 0000000000..20659db7e8
--- /dev/null
+++ b/src/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/mac
@@ -0,0 +1 @@
+00:33:21:98:b9:f0
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/origin b/src/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/origin
new file mode 100644
index 0000000000..56a6051ca2
--- /dev/null
+++ b/src/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/origin
@@ -0,0 +1 @@
+1
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/prefix-len b/src/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/prefix-len
new file mode 100644
index 0000000000..8fdd954df9
--- /dev/null
+++ b/src/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/prefix-len
@@ -0,0 +1 @@
+22
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/primary-dns b/src/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/primary-dns
new file mode 100644
index 0000000000..2e152cb083
--- /dev/null
+++ b/src/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/primary-dns
@@ -0,0 +1 @@
+10.16.255.2
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/secondary-dns b/src/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/secondary-dns
new file mode 100644
index 0000000000..5ed7b71958
--- /dev/null
+++ b/src/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/secondary-dns
@@ -0,0 +1 @@
+blah.foo.bar.baz
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/subnet-mask b/src/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/subnet-mask
new file mode 100644
index 0000000000..7cb9d0a9bb
--- /dev/null
+++ b/src/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/subnet-mask
@@ -0,0 +1 @@
+255.255.252.0
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/vlan b/src/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/vlan
new file mode 100644
index 0000000000..c227083464
--- /dev/null
+++ b/src/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/vlan
@@ -0,0 +1 @@
+0
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-bad-dns2/firmware/ibft/initiator/initiator-name b/src/initrd/tests/sysfs-bad-dns2/firmware/ibft/initiator/initiator-name
new file mode 100644
index 0000000000..509a7ab8be
--- /dev/null
+++ b/src/initrd/tests/sysfs-bad-dns2/firmware/ibft/initiator/initiator-name
@@ -0,0 +1 @@
+iqn.pjones6
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-bad-dns2/firmware/ibft/target0/index b/src/initrd/tests/sysfs-bad-dns2/firmware/ibft/target0/index
new file mode 100644
index 0000000000..c227083464
--- /dev/null
+++ b/src/initrd/tests/sysfs-bad-dns2/firmware/ibft/target0/index
@@ -0,0 +1 @@
+0
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-bad-dns2/firmware/ibft/target0/ip-addr b/src/initrd/tests/sysfs-bad-dns2/firmware/ibft/target0/ip-addr
new file mode 100644
index 0000000000..7450fdf90a
--- /dev/null
+++ b/src/initrd/tests/sysfs-bad-dns2/firmware/ibft/target0/ip-addr
@@ -0,0 +1 @@
+10.16.52.16
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-bad-dns2/firmware/ibft/target0/lun b/src/initrd/tests/sysfs-bad-dns2/firmware/ibft/target0/lun
new file mode 100644
index 0000000000..c43d0930ca
--- /dev/null
+++ b/src/initrd/tests/sysfs-bad-dns2/firmware/ibft/target0/lun
@@ -0,0 +1 @@
+00000000
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-bad-dns2/firmware/ibft/target0/port b/src/initrd/tests/sysfs-bad-dns2/firmware/ibft/target0/port
new file mode 100644
index 0000000000..58f0d919f4
--- /dev/null
+++ b/src/initrd/tests/sysfs-bad-dns2/firmware/ibft/target0/port
@@ -0,0 +1 @@
+3260
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-bad-dns2/firmware/ibft/target0/target-name b/src/initrd/tests/sysfs-bad-dns2/firmware/ibft/target0/target-name
new file mode 100644
index 0000000000..32c9450a2f
--- /dev/null
+++ b/src/initrd/tests/sysfs-bad-dns2/firmware/ibft/target0/target-name
@@ -0,0 +1 @@
+iqn.0.2008-11.com.blahblah:iscsi0
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-bad-gateway/class/net/eth0/address b/src/initrd/tests/sysfs-bad-gateway/class/net/eth0/address
new file mode 100644
index 0000000000..20659db7e8
--- /dev/null
+++ b/src/initrd/tests/sysfs-bad-gateway/class/net/eth0/address
@@ -0,0 +1 @@
+00:33:21:98:b9:f0
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/gateway b/src/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/gateway
new file mode 100644
index 0000000000..1970856e09
--- /dev/null
+++ b/src/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/gateway
@@ -0,0 +1 @@
+bb.cc.dd.ee
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/index b/src/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/index
new file mode 100644
index 0000000000..c227083464
--- /dev/null
+++ b/src/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/index
@@ -0,0 +1 @@
+0
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/ip-addr b/src/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/ip-addr
new file mode 100644
index 0000000000..944c8d4565
--- /dev/null
+++ b/src/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/ip-addr
@@ -0,0 +1 @@
+192.168.32.72
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/mac b/src/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/mac
new file mode 100644
index 0000000000..20659db7e8
--- /dev/null
+++ b/src/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/mac
@@ -0,0 +1 @@
+00:33:21:98:b9:f0
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/origin b/src/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/origin
new file mode 100644
index 0000000000..56a6051ca2
--- /dev/null
+++ b/src/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/origin
@@ -0,0 +1 @@
+1
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/prefix-len b/src/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/prefix-len
new file mode 100644
index 0000000000..8fdd954df9
--- /dev/null
+++ b/src/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/prefix-len
@@ -0,0 +1 @@
+22
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/primary-dns b/src/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/primary-dns
new file mode 100644
index 0000000000..2e152cb083
--- /dev/null
+++ b/src/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/primary-dns
@@ -0,0 +1 @@
+10.16.255.2
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/secondary-dns b/src/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/secondary-dns
new file mode 100644
index 0000000000..2eb9e1d0ad
--- /dev/null
+++ b/src/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/secondary-dns
@@ -0,0 +1 @@
+10.16.255.3
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/subnet-mask b/src/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/subnet-mask
new file mode 100644
index 0000000000..7cb9d0a9bb
--- /dev/null
+++ b/src/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/subnet-mask
@@ -0,0 +1 @@
+255.255.252.0
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/vlan b/src/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/vlan
new file mode 100644
index 0000000000..c227083464
--- /dev/null
+++ b/src/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/vlan
@@ -0,0 +1 @@
+0
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-bad-gateway/firmware/ibft/initiator/initiator-name b/src/initrd/tests/sysfs-bad-gateway/firmware/ibft/initiator/initiator-name
new file mode 100644
index 0000000000..509a7ab8be
--- /dev/null
+++ b/src/initrd/tests/sysfs-bad-gateway/firmware/ibft/initiator/initiator-name
@@ -0,0 +1 @@
+iqn.pjones6
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-bad-gateway/firmware/ibft/target0/index b/src/initrd/tests/sysfs-bad-gateway/firmware/ibft/target0/index
new file mode 100644
index 0000000000..c227083464
--- /dev/null
+++ b/src/initrd/tests/sysfs-bad-gateway/firmware/ibft/target0/index
@@ -0,0 +1 @@
+0
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-bad-gateway/firmware/ibft/target0/ip-addr b/src/initrd/tests/sysfs-bad-gateway/firmware/ibft/target0/ip-addr
new file mode 100644
index 0000000000..7450fdf90a
--- /dev/null
+++ b/src/initrd/tests/sysfs-bad-gateway/firmware/ibft/target0/ip-addr
@@ -0,0 +1 @@
+10.16.52.16
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-bad-gateway/firmware/ibft/target0/lun b/src/initrd/tests/sysfs-bad-gateway/firmware/ibft/target0/lun
new file mode 100644
index 0000000000..c43d0930ca
--- /dev/null
+++ b/src/initrd/tests/sysfs-bad-gateway/firmware/ibft/target0/lun
@@ -0,0 +1 @@
+00000000
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-bad-gateway/firmware/ibft/target0/port b/src/initrd/tests/sysfs-bad-gateway/firmware/ibft/target0/port
new file mode 100644
index 0000000000..58f0d919f4
--- /dev/null
+++ b/src/initrd/tests/sysfs-bad-gateway/firmware/ibft/target0/port
@@ -0,0 +1 @@
+3260
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-bad-gateway/firmware/ibft/target0/target-name b/src/initrd/tests/sysfs-bad-gateway/firmware/ibft/target0/target-name
new file mode 100644
index 0000000000..32c9450a2f
--- /dev/null
+++ b/src/initrd/tests/sysfs-bad-gateway/firmware/ibft/target0/target-name
@@ -0,0 +1 @@
+iqn.0.2008-11.com.blahblah:iscsi0
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-bad-ipaddr/class/net/eth0/address b/src/initrd/tests/sysfs-bad-ipaddr/class/net/eth0/address
new file mode 100644
index 0000000000..20659db7e8
--- /dev/null
+++ b/src/initrd/tests/sysfs-bad-ipaddr/class/net/eth0/address
@@ -0,0 +1 @@
+00:33:21:98:b9:f0
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/gateway b/src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/gateway
new file mode 100644
index 0000000000..bf6cf4543f
--- /dev/null
+++ b/src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/gateway
@@ -0,0 +1 @@
+192.168.35.254
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/index b/src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/index
new file mode 100644
index 0000000000..c227083464
--- /dev/null
+++ b/src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/index
@@ -0,0 +1 @@
+0
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/ip-addr b/src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/ip-addr
new file mode 100644
index 0000000000..d526f3244f
--- /dev/null
+++ b/src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/ip-addr
@@ -0,0 +1 @@
+aa.bb.cc.dd
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/mac b/src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/mac
new file mode 100644
index 0000000000..20659db7e8
--- /dev/null
+++ b/src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/mac
@@ -0,0 +1 @@
+00:33:21:98:b9:f0
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/origin b/src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/origin
new file mode 100644
index 0000000000..56a6051ca2
--- /dev/null
+++ b/src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/origin
@@ -0,0 +1 @@
+1
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/prefix-len b/src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/prefix-len
new file mode 100644
index 0000000000..8fdd954df9
--- /dev/null
+++ b/src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/prefix-len
@@ -0,0 +1 @@
+22
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/primary-dns b/src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/primary-dns
new file mode 100644
index 0000000000..2e152cb083
--- /dev/null
+++ b/src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/primary-dns
@@ -0,0 +1 @@
+10.16.255.2
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/secondary-dns b/src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/secondary-dns
new file mode 100644
index 0000000000..2eb9e1d0ad
--- /dev/null
+++ b/src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/secondary-dns
@@ -0,0 +1 @@
+10.16.255.3
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/subnet-mask b/src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/subnet-mask
new file mode 100644
index 0000000000..7cb9d0a9bb
--- /dev/null
+++ b/src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/subnet-mask
@@ -0,0 +1 @@
+255.255.252.0
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/vlan b/src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/vlan
new file mode 100644
index 0000000000..c227083464
--- /dev/null
+++ b/src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/vlan
@@ -0,0 +1 @@
+0
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/initiator/initiator-name b/src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/initiator/initiator-name
new file mode 100644
index 0000000000..509a7ab8be
--- /dev/null
+++ b/src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/initiator/initiator-name
@@ -0,0 +1 @@
+iqn.pjones6
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/target0/index b/src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/target0/index
new file mode 100644
index 0000000000..c227083464
--- /dev/null
+++ b/src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/target0/index
@@ -0,0 +1 @@
+0
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/target0/ip-addr b/src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/target0/ip-addr
new file mode 100644
index 0000000000..7450fdf90a
--- /dev/null
+++ b/src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/target0/ip-addr
@@ -0,0 +1 @@
+10.16.52.16
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/target0/lun b/src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/target0/lun
new file mode 100644
index 0000000000..c43d0930ca
--- /dev/null
+++ b/src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/target0/lun
@@ -0,0 +1 @@
+00000000
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/target0/port b/src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/target0/port
new file mode 100644
index 0000000000..58f0d919f4
--- /dev/null
+++ b/src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/target0/port
@@ -0,0 +1 @@
+3260
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/target0/target-name b/src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/target0/target-name
new file mode 100644
index 0000000000..32c9450a2f
--- /dev/null
+++ b/src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/target0/target-name
@@ -0,0 +1 @@
+iqn.0.2008-11.com.blahblah:iscsi0
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-dhcp/class/net/eth0/address b/src/initrd/tests/sysfs-dhcp/class/net/eth0/address
new file mode 100644
index 0000000000..20659db7e8
--- /dev/null
+++ b/src/initrd/tests/sysfs-dhcp/class/net/eth0/address
@@ -0,0 +1 @@
+00:33:21:98:b9:f0
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-dhcp/class/net/eth1/address b/src/initrd/tests/sysfs-dhcp/class/net/eth1/address
new file mode 100644
index 0000000000..befa7850fd
--- /dev/null
+++ b/src/initrd/tests/sysfs-dhcp/class/net/eth1/address
@@ -0,0 +1 @@
+00:33:21:98:b9:f1
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet0/gateway b/src/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet0/gateway
new file mode 100644
index 0000000000..59ea5b826b
--- /dev/null
+++ b/src/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet0/gateway
@@ -0,0 +1 @@
+10.16.52.254
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet0/index b/src/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet0/index
new file mode 100644
index 0000000000..c227083464
--- /dev/null
+++ b/src/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet0/index
@@ -0,0 +1 @@
+0
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet0/mac b/src/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet0/mac
new file mode 100644
index 0000000000..20659db7e8
--- /dev/null
+++ b/src/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet0/mac
@@ -0,0 +1 @@
+00:33:21:98:b9:f0
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet0/origin b/src/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet0/origin
new file mode 100644
index 0000000000..e440e5c842
--- /dev/null
+++ b/src/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet0/origin
@@ -0,0 +1 @@
+3
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet0/primary-dns b/src/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet0/primary-dns
new file mode 100644
index 0000000000..2e152cb083
--- /dev/null
+++ b/src/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet0/primary-dns
@@ -0,0 +1 @@
+10.16.255.2
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet0/secondary-dns b/src/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet0/secondary-dns
new file mode 100644
index 0000000000..2eb9e1d0ad
--- /dev/null
+++ b/src/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet0/secondary-dns
@@ -0,0 +1 @@
+10.16.255.3
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet0/vlan b/src/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet0/vlan
new file mode 100644
index 0000000000..c227083464
--- /dev/null
+++ b/src/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet0/vlan
@@ -0,0 +1 @@
+0
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet1/gateway b/src/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet1/gateway
new file mode 100644
index 0000000000..59ea5b826b
--- /dev/null
+++ b/src/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet1/gateway
@@ -0,0 +1 @@
+10.16.52.254
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet1/index b/src/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet1/index
new file mode 100644
index 0000000000..56a6051ca2
--- /dev/null
+++ b/src/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet1/index
@@ -0,0 +1 @@
+1
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet1/mac b/src/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet1/mac
new file mode 100644
index 0000000000..befa7850fd
--- /dev/null
+++ b/src/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet1/mac
@@ -0,0 +1 @@
+00:33:21:98:b9:f1
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet1/origin b/src/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet1/origin
new file mode 100644
index 0000000000..e440e5c842
--- /dev/null
+++ b/src/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet1/origin
@@ -0,0 +1 @@
+3
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet1/primary-dns b/src/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet1/primary-dns
new file mode 100644
index 0000000000..2e152cb083
--- /dev/null
+++ b/src/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet1/primary-dns
@@ -0,0 +1 @@
+10.16.255.2
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet1/secondary-dns b/src/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet1/secondary-dns
new file mode 100644
index 0000000000..2eb9e1d0ad
--- /dev/null
+++ b/src/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet1/secondary-dns
@@ -0,0 +1 @@
+10.16.255.3
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet1/vlan b/src/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet1/vlan
new file mode 100644
index 0000000000..c227083464
--- /dev/null
+++ b/src/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet1/vlan
@@ -0,0 +1 @@
+0
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-dhcp/firmware/ibft/initiator/initiator-name b/src/initrd/tests/sysfs-dhcp/firmware/ibft/initiator/initiator-name
new file mode 100644
index 0000000000..509a7ab8be
--- /dev/null
+++ b/src/initrd/tests/sysfs-dhcp/firmware/ibft/initiator/initiator-name
@@ -0,0 +1 @@
+iqn.pjones6
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-dhcp/firmware/ibft/target0/index b/src/initrd/tests/sysfs-dhcp/firmware/ibft/target0/index
new file mode 100644
index 0000000000..c227083464
--- /dev/null
+++ b/src/initrd/tests/sysfs-dhcp/firmware/ibft/target0/index
@@ -0,0 +1 @@
+0
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-dhcp/firmware/ibft/target0/ip-addr b/src/initrd/tests/sysfs-dhcp/firmware/ibft/target0/ip-addr
new file mode 100644
index 0000000000..7450fdf90a
--- /dev/null
+++ b/src/initrd/tests/sysfs-dhcp/firmware/ibft/target0/ip-addr
@@ -0,0 +1 @@
+10.16.52.16
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-dhcp/firmware/ibft/target0/lun b/src/initrd/tests/sysfs-dhcp/firmware/ibft/target0/lun
new file mode 100644
index 0000000000..c43d0930ca
--- /dev/null
+++ b/src/initrd/tests/sysfs-dhcp/firmware/ibft/target0/lun
@@ -0,0 +1 @@
+00000000
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-dhcp/firmware/ibft/target0/port b/src/initrd/tests/sysfs-dhcp/firmware/ibft/target0/port
new file mode 100644
index 0000000000..58f0d919f4
--- /dev/null
+++ b/src/initrd/tests/sysfs-dhcp/firmware/ibft/target0/port
@@ -0,0 +1 @@
+3260
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-dhcp/firmware/ibft/target0/target-name b/src/initrd/tests/sysfs-dhcp/firmware/ibft/target0/target-name
new file mode 100644
index 0000000000..32c9450a2f
--- /dev/null
+++ b/src/initrd/tests/sysfs-dhcp/firmware/ibft/target0/target-name
@@ -0,0 +1 @@
+iqn.0.2008-11.com.blahblah:iscsi0
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-dhcp/firmware/ibft/target1/index b/src/initrd/tests/sysfs-dhcp/firmware/ibft/target1/index
new file mode 100644
index 0000000000..56a6051ca2
--- /dev/null
+++ b/src/initrd/tests/sysfs-dhcp/firmware/ibft/target1/index
@@ -0,0 +1 @@
+1
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-dhcp/firmware/ibft/target1/ip-addr b/src/initrd/tests/sysfs-dhcp/firmware/ibft/target1/ip-addr
new file mode 100644
index 0000000000..7450fdf90a
--- /dev/null
+++ b/src/initrd/tests/sysfs-dhcp/firmware/ibft/target1/ip-addr
@@ -0,0 +1 @@
+10.16.52.16
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-dhcp/firmware/ibft/target1/lun b/src/initrd/tests/sysfs-dhcp/firmware/ibft/target1/lun
new file mode 100644
index 0000000000..c43d0930ca
--- /dev/null
+++ b/src/initrd/tests/sysfs-dhcp/firmware/ibft/target1/lun
@@ -0,0 +1 @@
+00000000
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-dhcp/firmware/ibft/target1/port b/src/initrd/tests/sysfs-dhcp/firmware/ibft/target1/port
new file mode 100644
index 0000000000..58f0d919f4
--- /dev/null
+++ b/src/initrd/tests/sysfs-dhcp/firmware/ibft/target1/port
@@ -0,0 +1 @@
+3260
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-dhcp/firmware/ibft/target1/target-name b/src/initrd/tests/sysfs-dhcp/firmware/ibft/target1/target-name
new file mode 100644
index 0000000000..ac3a6a2ab3
--- /dev/null
+++ b/src/initrd/tests/sysfs-dhcp/firmware/ibft/target1/target-name
@@ -0,0 +1 @@
+iqn.1.2008-11.com.blahblah:iscsi1
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-static/class/net/eth0/address b/src/initrd/tests/sysfs-static/class/net/eth0/address
new file mode 100644
index 0000000000..20659db7e8
--- /dev/null
+++ b/src/initrd/tests/sysfs-static/class/net/eth0/address
@@ -0,0 +1 @@
+00:33:21:98:b9:f0
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-static/class/net/eth1/address b/src/initrd/tests/sysfs-static/class/net/eth1/address
new file mode 100644
index 0000000000..befa7850fd
--- /dev/null
+++ b/src/initrd/tests/sysfs-static/class/net/eth1/address
@@ -0,0 +1 @@
+00:33:21:98:b9:f1
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-static/firmware/ibft/ethernet0/gateway b/src/initrd/tests/sysfs-static/firmware/ibft/ethernet0/gateway
new file mode 100644
index 0000000000..bf6cf4543f
--- /dev/null
+++ b/src/initrd/tests/sysfs-static/firmware/ibft/ethernet0/gateway
@@ -0,0 +1 @@
+192.168.35.254
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-static/firmware/ibft/ethernet0/index b/src/initrd/tests/sysfs-static/firmware/ibft/ethernet0/index
new file mode 100644
index 0000000000..c227083464
--- /dev/null
+++ b/src/initrd/tests/sysfs-static/firmware/ibft/ethernet0/index
@@ -0,0 +1 @@
+0
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-static/firmware/ibft/ethernet0/ip-addr b/src/initrd/tests/sysfs-static/firmware/ibft/ethernet0/ip-addr
new file mode 100644
index 0000000000..944c8d4565
--- /dev/null
+++ b/src/initrd/tests/sysfs-static/firmware/ibft/ethernet0/ip-addr
@@ -0,0 +1 @@
+192.168.32.72
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-static/firmware/ibft/ethernet0/mac b/src/initrd/tests/sysfs-static/firmware/ibft/ethernet0/mac
new file mode 100644
index 0000000000..20659db7e8
--- /dev/null
+++ b/src/initrd/tests/sysfs-static/firmware/ibft/ethernet0/mac
@@ -0,0 +1 @@
+00:33:21:98:b9:f0
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-static/firmware/ibft/ethernet0/origin b/src/initrd/tests/sysfs-static/firmware/ibft/ethernet0/origin
new file mode 100644
index 0000000000..56a6051ca2
--- /dev/null
+++ b/src/initrd/tests/sysfs-static/firmware/ibft/ethernet0/origin
@@ -0,0 +1 @@
+1
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-static/firmware/ibft/ethernet0/prefix-len b/src/initrd/tests/sysfs-static/firmware/ibft/ethernet0/prefix-len
new file mode 100644
index 0000000000..8fdd954df9
--- /dev/null
+++ b/src/initrd/tests/sysfs-static/firmware/ibft/ethernet0/prefix-len
@@ -0,0 +1 @@
+22
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-static/firmware/ibft/ethernet0/primary-dns b/src/initrd/tests/sysfs-static/firmware/ibft/ethernet0/primary-dns
new file mode 100644
index 0000000000..2e152cb083
--- /dev/null
+++ b/src/initrd/tests/sysfs-static/firmware/ibft/ethernet0/primary-dns
@@ -0,0 +1 @@
+10.16.255.2
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-static/firmware/ibft/ethernet0/secondary-dns b/src/initrd/tests/sysfs-static/firmware/ibft/ethernet0/secondary-dns
new file mode 100644
index 0000000000..2eb9e1d0ad
--- /dev/null
+++ b/src/initrd/tests/sysfs-static/firmware/ibft/ethernet0/secondary-dns
@@ -0,0 +1 @@
+10.16.255.3
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-static/firmware/ibft/ethernet0/subnet-mask b/src/initrd/tests/sysfs-static/firmware/ibft/ethernet0/subnet-mask
new file mode 100644
index 0000000000..7cb9d0a9bb
--- /dev/null
+++ b/src/initrd/tests/sysfs-static/firmware/ibft/ethernet0/subnet-mask
@@ -0,0 +1 @@
+255.255.252.0
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-static/firmware/ibft/ethernet0/vlan b/src/initrd/tests/sysfs-static/firmware/ibft/ethernet0/vlan
new file mode 100644
index 0000000000..c227083464
--- /dev/null
+++ b/src/initrd/tests/sysfs-static/firmware/ibft/ethernet0/vlan
@@ -0,0 +1 @@
+0
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-static/firmware/ibft/ethernet1/gateway b/src/initrd/tests/sysfs-static/firmware/ibft/ethernet1/gateway
new file mode 100644
index 0000000000..59ea5b826b
--- /dev/null
+++ b/src/initrd/tests/sysfs-static/firmware/ibft/ethernet1/gateway
@@ -0,0 +1 @@
+10.16.52.254
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-static/firmware/ibft/ethernet1/index b/src/initrd/tests/sysfs-static/firmware/ibft/ethernet1/index
new file mode 100644
index 0000000000..56a6051ca2
--- /dev/null
+++ b/src/initrd/tests/sysfs-static/firmware/ibft/ethernet1/index
@@ -0,0 +1 @@
+1
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-static/firmware/ibft/ethernet1/mac b/src/initrd/tests/sysfs-static/firmware/ibft/ethernet1/mac
new file mode 100644
index 0000000000..befa7850fd
--- /dev/null
+++ b/src/initrd/tests/sysfs-static/firmware/ibft/ethernet1/mac
@@ -0,0 +1 @@
+00:33:21:98:b9:f1
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-static/firmware/ibft/ethernet1/origin b/src/initrd/tests/sysfs-static/firmware/ibft/ethernet1/origin
new file mode 100644
index 0000000000..e440e5c842
--- /dev/null
+++ b/src/initrd/tests/sysfs-static/firmware/ibft/ethernet1/origin
@@ -0,0 +1 @@
+3
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-static/firmware/ibft/ethernet1/primary-dns b/src/initrd/tests/sysfs-static/firmware/ibft/ethernet1/primary-dns
new file mode 100644
index 0000000000..2e152cb083
--- /dev/null
+++ b/src/initrd/tests/sysfs-static/firmware/ibft/ethernet1/primary-dns
@@ -0,0 +1 @@
+10.16.255.2
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-static/firmware/ibft/ethernet1/secondary-dns b/src/initrd/tests/sysfs-static/firmware/ibft/ethernet1/secondary-dns
new file mode 100644
index 0000000000..2eb9e1d0ad
--- /dev/null
+++ b/src/initrd/tests/sysfs-static/firmware/ibft/ethernet1/secondary-dns
@@ -0,0 +1 @@
+10.16.255.3
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-static/firmware/ibft/ethernet1/vlan b/src/initrd/tests/sysfs-static/firmware/ibft/ethernet1/vlan
new file mode 100644
index 0000000000..c227083464
--- /dev/null
+++ b/src/initrd/tests/sysfs-static/firmware/ibft/ethernet1/vlan
@@ -0,0 +1 @@
+0
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-static/firmware/ibft/initiator/initiator-name b/src/initrd/tests/sysfs-static/firmware/ibft/initiator/initiator-name
new file mode 100644
index 0000000000..509a7ab8be
--- /dev/null
+++ b/src/initrd/tests/sysfs-static/firmware/ibft/initiator/initiator-name
@@ -0,0 +1 @@
+iqn.pjones6
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-static/firmware/ibft/target0/index b/src/initrd/tests/sysfs-static/firmware/ibft/target0/index
new file mode 100644
index 0000000000..c227083464
--- /dev/null
+++ b/src/initrd/tests/sysfs-static/firmware/ibft/target0/index
@@ -0,0 +1 @@
+0
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-static/firmware/ibft/target0/ip-addr b/src/initrd/tests/sysfs-static/firmware/ibft/target0/ip-addr
new file mode 100644
index 0000000000..7450fdf90a
--- /dev/null
+++ b/src/initrd/tests/sysfs-static/firmware/ibft/target0/ip-addr
@@ -0,0 +1 @@
+10.16.52.16
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-static/firmware/ibft/target0/lun b/src/initrd/tests/sysfs-static/firmware/ibft/target0/lun
new file mode 100644
index 0000000000..c43d0930ca
--- /dev/null
+++ b/src/initrd/tests/sysfs-static/firmware/ibft/target0/lun
@@ -0,0 +1 @@
+00000000
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-static/firmware/ibft/target0/port b/src/initrd/tests/sysfs-static/firmware/ibft/target0/port
new file mode 100644
index 0000000000..58f0d919f4
--- /dev/null
+++ b/src/initrd/tests/sysfs-static/firmware/ibft/target0/port
@@ -0,0 +1 @@
+3260
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-static/firmware/ibft/target0/target-name b/src/initrd/tests/sysfs-static/firmware/ibft/target0/target-name
new file mode 100644
index 0000000000..32c9450a2f
--- /dev/null
+++ b/src/initrd/tests/sysfs-static/firmware/ibft/target0/target-name
@@ -0,0 +1 @@
+iqn.0.2008-11.com.blahblah:iscsi0
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-static/firmware/ibft/target1/index b/src/initrd/tests/sysfs-static/firmware/ibft/target1/index
new file mode 100644
index 0000000000..56a6051ca2
--- /dev/null
+++ b/src/initrd/tests/sysfs-static/firmware/ibft/target1/index
@@ -0,0 +1 @@
+1
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-static/firmware/ibft/target1/ip-addr b/src/initrd/tests/sysfs-static/firmware/ibft/target1/ip-addr
new file mode 100644
index 0000000000..7450fdf90a
--- /dev/null
+++ b/src/initrd/tests/sysfs-static/firmware/ibft/target1/ip-addr
@@ -0,0 +1 @@
+10.16.52.16
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-static/firmware/ibft/target1/lun b/src/initrd/tests/sysfs-static/firmware/ibft/target1/lun
new file mode 100644
index 0000000000..c43d0930ca
--- /dev/null
+++ b/src/initrd/tests/sysfs-static/firmware/ibft/target1/lun
@@ -0,0 +1 @@
+00000000
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-static/firmware/ibft/target1/port b/src/initrd/tests/sysfs-static/firmware/ibft/target1/port
new file mode 100644
index 0000000000..58f0d919f4
--- /dev/null
+++ b/src/initrd/tests/sysfs-static/firmware/ibft/target1/port
@@ -0,0 +1 @@
+3260
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-static/firmware/ibft/target1/target-name b/src/initrd/tests/sysfs-static/firmware/ibft/target1/target-name
new file mode 100644
index 0000000000..ac3a6a2ab3
--- /dev/null
+++ b/src/initrd/tests/sysfs-static/firmware/ibft/target1/target-name
@@ -0,0 +1 @@
+iqn.1.2008-11.com.blahblah:iscsi1
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-vlan/class/net/eth0/address b/src/initrd/tests/sysfs-vlan/class/net/eth0/address
new file mode 100644
index 0000000000..20659db7e8
--- /dev/null
+++ b/src/initrd/tests/sysfs-vlan/class/net/eth0/address
@@ -0,0 +1 @@
+00:33:21:98:b9:f0
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-vlan/firmware/ibft/ethernet0/index b/src/initrd/tests/sysfs-vlan/firmware/ibft/ethernet0/index
new file mode 100644
index 0000000000..c227083464
--- /dev/null
+++ b/src/initrd/tests/sysfs-vlan/firmware/ibft/ethernet0/index
@@ -0,0 +1 @@
+0
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-vlan/firmware/ibft/ethernet0/ip-addr b/src/initrd/tests/sysfs-vlan/firmware/ibft/ethernet0/ip-addr
new file mode 100644
index 0000000000..4923230c8c
--- /dev/null
+++ b/src/initrd/tests/sysfs-vlan/firmware/ibft/ethernet0/ip-addr
@@ -0,0 +1 @@
+192.168.6.200
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-vlan/firmware/ibft/ethernet0/mac b/src/initrd/tests/sysfs-vlan/firmware/ibft/ethernet0/mac
new file mode 100644
index 0000000000..20659db7e8
--- /dev/null
+++ b/src/initrd/tests/sysfs-vlan/firmware/ibft/ethernet0/mac
@@ -0,0 +1 @@
+00:33:21:98:b9:f0
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-vlan/firmware/ibft/ethernet0/origin b/src/initrd/tests/sysfs-vlan/firmware/ibft/ethernet0/origin
new file mode 100644
index 0000000000..56a6051ca2
--- /dev/null
+++ b/src/initrd/tests/sysfs-vlan/firmware/ibft/ethernet0/origin
@@ -0,0 +1 @@
+1
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-vlan/firmware/ibft/ethernet0/prefix-len b/src/initrd/tests/sysfs-vlan/firmware/ibft/ethernet0/prefix-len
new file mode 100644
index 0000000000..cabf43b5dd
--- /dev/null
+++ b/src/initrd/tests/sysfs-vlan/firmware/ibft/ethernet0/prefix-len
@@ -0,0 +1 @@
+24
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-vlan/firmware/ibft/ethernet0/subnet-mask b/src/initrd/tests/sysfs-vlan/firmware/ibft/ethernet0/subnet-mask
new file mode 100644
index 0000000000..5a279b41f0
--- /dev/null
+++ b/src/initrd/tests/sysfs-vlan/firmware/ibft/ethernet0/subnet-mask
@@ -0,0 +1 @@
+255.255.255.0
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-vlan/firmware/ibft/ethernet0/vlan b/src/initrd/tests/sysfs-vlan/firmware/ibft/ethernet0/vlan
new file mode 100644
index 0000000000..d800886d9c
--- /dev/null
+++ b/src/initrd/tests/sysfs-vlan/firmware/ibft/ethernet0/vlan
@@ -0,0 +1 @@
+123
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-vlan/firmware/ibft/initiator/initiator-name b/src/initrd/tests/sysfs-vlan/firmware/ibft/initiator/initiator-name
new file mode 100644
index 0000000000..8e9cd2c42c
--- /dev/null
+++ b/src/initrd/tests/sysfs-vlan/firmware/ibft/initiator/initiator-name
@@ -0,0 +1 @@
+iqn.2010-04.org.ipxe:d05faa97-c4be-44f6-a723-efde9aa399a0
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-vlan/firmware/ibft/target0/index b/src/initrd/tests/sysfs-vlan/firmware/ibft/target0/index
new file mode 100644
index 0000000000..c227083464
--- /dev/null
+++ b/src/initrd/tests/sysfs-vlan/firmware/ibft/target0/index
@@ -0,0 +1 @@
+0
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-vlan/firmware/ibft/target0/ip-addr b/src/initrd/tests/sysfs-vlan/firmware/ibft/target0/ip-addr
new file mode 100644
index 0000000000..a32ce01ba1
--- /dev/null
+++ b/src/initrd/tests/sysfs-vlan/firmware/ibft/target0/ip-addr
@@ -0,0 +1 @@
+192.168.6.32
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-vlan/firmware/ibft/target0/lun b/src/initrd/tests/sysfs-vlan/firmware/ibft/target0/lun
new file mode 100644
index 0000000000..f309ca6a0a
--- /dev/null
+++ b/src/initrd/tests/sysfs-vlan/firmware/ibft/target0/lun
@@ -0,0 +1 @@
+01000000
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-vlan/firmware/ibft/target0/port b/src/initrd/tests/sysfs-vlan/firmware/ibft/target0/port
new file mode 100644
index 0000000000..58f0d919f4
--- /dev/null
+++ b/src/initrd/tests/sysfs-vlan/firmware/ibft/target0/port
@@ -0,0 +1 @@
+3260
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs-vlan/firmware/ibft/target0/target-name b/src/initrd/tests/sysfs-vlan/firmware/ibft/target0/target-name
new file mode 100644
index 0000000000..f0e6115796
--- /dev/null
+++ b/src/initrd/tests/sysfs-vlan/firmware/ibft/target0/target-name
@@ -0,0 +1 @@
+iqn.2003-01.org.x:disk1
\ No newline at end of file
diff --git a/src/initrd/tests/sysfs/class/net/eth0/address b/src/initrd/tests/sysfs/class/net/eth0/address
new file mode 100644
index 0000000000..1f2f610ecc
--- /dev/null
+++ b/src/initrd/tests/sysfs/class/net/eth0/address
@@ -0,0 +1 @@
+00:53:00:AB:00:01
diff --git a/src/initrd/tests/sysfs/class/net/eth2/address b/src/initrd/tests/sysfs/class/net/eth2/address
new file mode 100644
index 0000000000..6ec1078ab8
--- /dev/null
+++ b/src/initrd/tests/sysfs/class/net/eth2/address
@@ -0,0 +1 @@
+00:53:06:66:ab:01
diff --git a/src/initrd/tests/sysfs/firmware/ibft/acpi_header/oem_id b/src/initrd/tests/sysfs/firmware/ibft/acpi_header/oem_id
new file mode 100644
index 0000000000..590d9cd211
--- /dev/null
+++ b/src/initrd/tests/sysfs/firmware/ibft/acpi_header/oem_id
@@ -0,0 +1 @@
+NMTst
diff --git a/src/initrd/tests/sysfs/firmware/ibft/acpi_header/oem_table_id b/src/initrd/tests/sysfs/firmware/ibft/acpi_header/oem_table_id
new file mode 100644
index 0000000000..35d4d09ce2
--- /dev/null
+++ b/src/initrd/tests/sysfs/firmware/ibft/acpi_header/oem_table_id
@@ -0,0 +1 @@
+Whatevs
diff --git a/src/initrd/tests/sysfs/firmware/ibft/acpi_header/signature b/src/initrd/tests/sysfs/firmware/ibft/acpi_header/signature
new file mode 100644
index 0000000000..e3a5d7ef22
--- /dev/null
+++ b/src/initrd/tests/sysfs/firmware/ibft/acpi_header/signature
@@ -0,0 +1 @@
+IBFT
diff --git a/src/initrd/tests/sysfs/firmware/ibft/ethernet0/dhcp b/src/initrd/tests/sysfs/firmware/ibft/ethernet0/dhcp
new file mode 100644
index 0000000000..98a0d79742
--- /dev/null
+++ b/src/initrd/tests/sysfs/firmware/ibft/ethernet0/dhcp
@@ -0,0 +1 @@
+2001:0db8:0000:0000:0000:0000:0000:0002
diff --git a/src/initrd/tests/sysfs/firmware/ibft/ethernet0/flags b/src/initrd/tests/sysfs/firmware/ibft/ethernet0/flags
new file mode 100644
index 0000000000..00750edc07
--- /dev/null
+++ b/src/initrd/tests/sysfs/firmware/ibft/ethernet0/flags
@@ -0,0 +1 @@
+3
diff --git a/src/initrd/tests/sysfs/firmware/ibft/ethernet0/gateway b/src/initrd/tests/sysfs/firmware/ibft/ethernet0/gateway
new file mode 100644
index 0000000000..7f378f8f97
--- /dev/null
+++ b/src/initrd/tests/sysfs/firmware/ibft/ethernet0/gateway
@@ -0,0 +1 @@
+2001:0db8:0000:0000:0000:0000:0000:0001
diff --git a/src/initrd/tests/sysfs/firmware/ibft/ethernet0/hostname b/src/initrd/tests/sysfs/firmware/ibft/ethernet0/hostname
new file mode 100644
index 0000000000..3ed5163c84
--- /dev/null
+++ b/src/initrd/tests/sysfs/firmware/ibft/ethernet0/hostname
@@ -0,0 +1 @@
+host0.example.com
diff --git a/src/initrd/tests/sysfs/firmware/ibft/ethernet0/index b/src/initrd/tests/sysfs/firmware/ibft/ethernet0/index
new file mode 100644
index 0000000000..573541ac97
--- /dev/null
+++ b/src/initrd/tests/sysfs/firmware/ibft/ethernet0/index
@@ -0,0 +1 @@
+0
diff --git a/src/initrd/tests/sysfs/firmware/ibft/ethernet0/ip-addr b/src/initrd/tests/sysfs/firmware/ibft/ethernet0/ip-addr
new file mode 100644
index 0000000000..98a0d79742
--- /dev/null
+++ b/src/initrd/tests/sysfs/firmware/ibft/ethernet0/ip-addr
@@ -0,0 +1 @@
+2001:0db8:0000:0000:0000:0000:0000:0002
diff --git a/src/initrd/tests/sysfs/firmware/ibft/ethernet0/mac b/src/initrd/tests/sysfs/firmware/ibft/ethernet0/mac
new file mode 100644
index 0000000000..f24413198a
--- /dev/null
+++ b/src/initrd/tests/sysfs/firmware/ibft/ethernet0/mac
@@ -0,0 +1 @@
+00:53:00:ab:00:01
diff --git a/src/initrd/tests/sysfs/firmware/ibft/ethernet0/origin b/src/initrd/tests/sysfs/firmware/ibft/ethernet0/origin
new file mode 100644
index 0000000000..b8626c4cff
--- /dev/null
+++ b/src/initrd/tests/sysfs/firmware/ibft/ethernet0/origin
@@ -0,0 +1 @@
+4
diff --git a/src/initrd/tests/sysfs/firmware/ibft/ethernet0/prefix-len b/src/initrd/tests/sysfs/firmware/ibft/ethernet0/prefix-len
new file mode 100644
index 0000000000..900731ffd5
--- /dev/null
+++ b/src/initrd/tests/sysfs/firmware/ibft/ethernet0/prefix-len
@@ -0,0 +1 @@
+64
diff --git a/src/initrd/tests/sysfs/firmware/ibft/ethernet0/primary-dns b/src/initrd/tests/sysfs/firmware/ibft/ethernet0/primary-dns
new file mode 100644
index 0000000000..e7511d5af4
--- /dev/null
+++ b/src/initrd/tests/sysfs/firmware/ibft/ethernet0/primary-dns
@@ -0,0 +1 @@
+2001:0db8:0000:0000:0000:0000:0000:0053
diff --git a/src/initrd/tests/sysfs/firmware/ibft/ethernet0/secondary-dns b/src/initrd/tests/sysfs/firmware/ibft/ethernet0/secondary-dns
new file mode 100644
index 0000000000..1f6c5c9547
--- /dev/null
+++ b/src/initrd/tests/sysfs/firmware/ibft/ethernet0/secondary-dns
@@ -0,0 +1 @@
+2001:0db8:0000:0000:0000:0000:0000:5353
diff --git a/src/initrd/tests/sysfs/firmware/ibft/ethernet0/subnet-mask b/src/initrd/tests/sysfs/firmware/ibft/ethernet0/subnet-mask
new file mode 100644
index 0000000000..5df934545e
--- /dev/null
+++ b/src/initrd/tests/sysfs/firmware/ibft/ethernet0/subnet-mask
@@ -0,0 +1 @@
+255.255.255.255
diff --git a/src/initrd/tests/sysfs/firmware/ibft/ethernet0/vlan b/src/initrd/tests/sysfs/firmware/ibft/ethernet0/vlan
new file mode 100644
index 0000000000..7cc86ad136
--- /dev/null
+++ b/src/initrd/tests/sysfs/firmware/ibft/ethernet0/vlan
@@ -0,0 +1 @@
+666
diff --git a/src/initrd/tests/sysfs/firmware/ibft/ethernet2/dhcp b/src/initrd/tests/sysfs/firmware/ibft/ethernet2/dhcp
new file mode 100644
index 0000000000..61ef5585ef
--- /dev/null
+++ b/src/initrd/tests/sysfs/firmware/ibft/ethernet2/dhcp
@@ -0,0 +1 @@
+192.0.2.2
diff --git a/src/initrd/tests/sysfs/firmware/ibft/ethernet2/flags b/src/initrd/tests/sysfs/firmware/ibft/ethernet2/flags
new file mode 100644
index 0000000000..00750edc07
--- /dev/null
+++ b/src/initrd/tests/sysfs/firmware/ibft/ethernet2/flags
@@ -0,0 +1 @@
+3
diff --git a/src/initrd/tests/sysfs/firmware/ibft/ethernet2/gateway b/src/initrd/tests/sysfs/firmware/ibft/ethernet2/gateway
new file mode 100644
index 0000000000..2096f194ff
--- /dev/null
+++ b/src/initrd/tests/sysfs/firmware/ibft/ethernet2/gateway
@@ -0,0 +1 @@
+192.0.2.1
diff --git a/src/initrd/tests/sysfs/firmware/ibft/ethernet2/hostname b/src/initrd/tests/sysfs/firmware/ibft/ethernet2/hostname
new file mode 100644
index 0000000000..5dc539d584
--- /dev/null
+++ b/src/initrd/tests/sysfs/firmware/ibft/ethernet2/hostname
@@ -0,0 +1 @@
+host2.example.com
diff --git a/src/initrd/tests/sysfs/firmware/ibft/ethernet2/index b/src/initrd/tests/sysfs/firmware/ibft/ethernet2/index
new file mode 100644
index 0000000000..0cfbf08886
--- /dev/null
+++ b/src/initrd/tests/sysfs/firmware/ibft/ethernet2/index
@@ -0,0 +1 @@
+2
diff --git a/src/initrd/tests/sysfs/firmware/ibft/ethernet2/ip-addr b/src/initrd/tests/sysfs/firmware/ibft/ethernet2/ip-addr
new file mode 100644
index 0000000000..61ef5585ef
--- /dev/null
+++ b/src/initrd/tests/sysfs/firmware/ibft/ethernet2/ip-addr
@@ -0,0 +1 @@
+192.0.2.2
diff --git a/src/initrd/tests/sysfs/firmware/ibft/ethernet2/mac b/src/initrd/tests/sysfs/firmware/ibft/ethernet2/mac
new file mode 100644
index 0000000000..2fc3d5253b
--- /dev/null
+++ b/src/initrd/tests/sysfs/firmware/ibft/ethernet2/mac
@@ -0,0 +1 @@
+00:53:06:66:AB:01
diff --git a/src/initrd/tests/sysfs/firmware/ibft/ethernet2/origin b/src/initrd/tests/sysfs/firmware/ibft/ethernet2/origin
new file mode 100644
index 0000000000..00750edc07
--- /dev/null
+++ b/src/initrd/tests/sysfs/firmware/ibft/ethernet2/origin
@@ -0,0 +1 @@
+3
diff --git a/src/initrd/tests/sysfs/firmware/ibft/ethernet2/prefix-len b/src/initrd/tests/sysfs/firmware/ibft/ethernet2/prefix-len
new file mode 100644
index 0000000000..a45fd52cc5
--- /dev/null
+++ b/src/initrd/tests/sysfs/firmware/ibft/ethernet2/prefix-len
@@ -0,0 +1 @@
+24
diff --git a/src/initrd/tests/sysfs/firmware/ibft/ethernet2/primary-dns b/src/initrd/tests/sysfs/firmware/ibft/ethernet2/primary-dns
new file mode 100644
index 0000000000..6fa8c74292
--- /dev/null
+++ b/src/initrd/tests/sysfs/firmware/ibft/ethernet2/primary-dns
@@ -0,0 +1 @@
+192.0.2.53
diff --git a/src/initrd/tests/sysfs/firmware/ibft/ethernet2/secondary-dns b/src/initrd/tests/sysfs/firmware/ibft/ethernet2/secondary-dns
new file mode 100644
index 0000000000..a7269ff5e9
--- /dev/null
+++ b/src/initrd/tests/sysfs/firmware/ibft/ethernet2/secondary-dns
@@ -0,0 +1 @@
+192.0.2.54
diff --git a/src/initrd/tests/sysfs/firmware/ibft/ethernet2/subnet-mask b/src/initrd/tests/sysfs/firmware/ibft/ethernet2/subnet-mask
new file mode 100644
index 0000000000..d30f9e9fdb
--- /dev/null
+++ b/src/initrd/tests/sysfs/firmware/ibft/ethernet2/subnet-mask
@@ -0,0 +1 @@
+255.255.255.0
diff --git a/src/initrd/tests/sysfs/firmware/ibft/ethernet2/vlan b/src/initrd/tests/sysfs/firmware/ibft/ethernet2/vlan
new file mode 100644
index 0000000000..573541ac97
--- /dev/null
+++ b/src/initrd/tests/sysfs/firmware/ibft/ethernet2/vlan
@@ -0,0 +1 @@
+0
diff --git a/src/initrd/tests/sysfs/firmware/ibft/initiator/flags b/src/initrd/tests/sysfs/firmware/ibft/initiator/flags
new file mode 100644
index 0000000000..00750edc07
--- /dev/null
+++ b/src/initrd/tests/sysfs/firmware/ibft/initiator/flags
@@ -0,0 +1 @@
+3
diff --git a/src/initrd/tests/sysfs/firmware/ibft/initiator/index b/src/initrd/tests/sysfs/firmware/ibft/initiator/index
new file mode 100644
index 0000000000..573541ac97
--- /dev/null
+++ b/src/initrd/tests/sysfs/firmware/ibft/initiator/index
@@ -0,0 +1 @@
+0
diff --git a/src/initrd/tests/sysfs/firmware/ibft/initiator/initiator-name b/src/initrd/tests/sysfs/firmware/ibft/initiator/initiator-name
new file mode 100644
index 0000000000..337b5a0f3a
--- /dev/null
+++ b/src/initrd/tests/sysfs/firmware/ibft/initiator/initiator-name
@@ -0,0 +1 @@
+iqn.1994-05.com.example.initiator:48b055856417
diff --git a/src/initrd/tests/sysfs/firmware/ibft/initiator/isns-server b/src/initrd/tests/sysfs/firmware/ibft/initiator/isns-server
new file mode 100644
index 0000000000..4aff93986c
--- /dev/null
+++ b/src/initrd/tests/sysfs/firmware/ibft/initiator/isns-server
@@ -0,0 +1 @@
+2001:0db8:0000:0000:0000:0000:0000:3205
diff --git a/src/initrd/tests/sysfs/firmware/ibft/initiator/pri-radius-server b/src/initrd/tests/sysfs/firmware/ibft/initiator/pri-radius-server
new file mode 100644
index 0000000000..a26fb64927
--- /dev/null
+++ b/src/initrd/tests/sysfs/firmware/ibft/initiator/pri-radius-server
@@ -0,0 +1 @@
+2001:0db8:0000:0000:0000:0000:0000:1812
diff --git a/src/initrd/tests/sysfs/firmware/ibft/initiator/sec-radius-server b/src/initrd/tests/sysfs/firmware/ibft/initiator/sec-radius-server
new file mode 100644
index 0000000000..908be27f4b
--- /dev/null
+++ b/src/initrd/tests/sysfs/firmware/ibft/initiator/sec-radius-server
@@ -0,0 +1 @@
+192.0.2.181
diff --git a/src/initrd/tests/sysfs/firmware/ibft/initiator/slp-server b/src/initrd/tests/sysfs/firmware/ibft/initiator/slp-server
new file mode 100644
index 0000000000..fca9e24bd5
--- /dev/null
+++ b/src/initrd/tests/sysfs/firmware/ibft/initiator/slp-server
@@ -0,0 +1 @@
+2001:0db8:0000:0000:0000:0000:0000:0427
diff --git a/src/initrd/tests/sysfs/firmware/ibft/target0/chap-type b/src/initrd/tests/sysfs/firmware/ibft/target0/chap-type
new file mode 100644
index 0000000000..573541ac97
--- /dev/null
+++ b/src/initrd/tests/sysfs/firmware/ibft/target0/chap-type
@@ -0,0 +1 @@
+0
diff --git a/src/initrd/tests/sysfs/firmware/ibft/target0/flags b/src/initrd/tests/sysfs/firmware/ibft/target0/flags
new file mode 100644
index 0000000000..00750edc07
--- /dev/null
+++ b/src/initrd/tests/sysfs/firmware/ibft/target0/flags
@@ -0,0 +1 @@
+3
diff --git a/src/initrd/tests/sysfs/firmware/ibft/target0/index b/src/initrd/tests/sysfs/firmware/ibft/target0/index
new file mode 100644
index 0000000000..573541ac97
--- /dev/null
+++ b/src/initrd/tests/sysfs/firmware/ibft/target0/index
@@ -0,0 +1 @@
+0
diff --git a/src/initrd/tests/sysfs/firmware/ibft/target0/ip-addr b/src/initrd/tests/sysfs/firmware/ibft/target0/ip-addr
new file mode 100644
index 0000000000..994b6e9c69
--- /dev/null
+++ b/src/initrd/tests/sysfs/firmware/ibft/target0/ip-addr
@@ -0,0 +1 @@
+2001:0db8:0000:0000:0000:0000:0000:3260
diff --git a/src/initrd/tests/sysfs/firmware/ibft/target0/lun b/src/initrd/tests/sysfs/firmware/ibft/target0/lun
new file mode 100644
index 0000000000..7c295bd444
--- /dev/null
+++ b/src/initrd/tests/sysfs/firmware/ibft/target0/lun
@@ -0,0 +1 @@
+01000000
diff --git a/src/initrd/tests/sysfs/firmware/ibft/target0/nic-assoc b/src/initrd/tests/sysfs/firmware/ibft/target0/nic-assoc
new file mode 100644
index 0000000000..573541ac97
--- /dev/null
+++ b/src/initrd/tests/sysfs/firmware/ibft/target0/nic-assoc
@@ -0,0 +1 @@
+0
diff --git a/src/initrd/tests/sysfs/firmware/ibft/target0/port b/src/initrd/tests/sysfs/firmware/ibft/target0/port
new file mode 100644
index 0000000000..53f0295f3f
--- /dev/null
+++ b/src/initrd/tests/sysfs/firmware/ibft/target0/port
@@ -0,0 +1 @@
+3260
diff --git a/src/initrd/tests/sysfs/firmware/ibft/target2/chap-type b/src/initrd/tests/sysfs/firmware/ibft/target2/chap-type
new file mode 100644
index 0000000000..573541ac97
--- /dev/null
+++ b/src/initrd/tests/sysfs/firmware/ibft/target2/chap-type
@@ -0,0 +1 @@
+0
diff --git a/src/initrd/tests/sysfs/firmware/ibft/target2/flags b/src/initrd/tests/sysfs/firmware/ibft/target2/flags
new file mode 100644
index 0000000000..00750edc07
--- /dev/null
+++ b/src/initrd/tests/sysfs/firmware/ibft/target2/flags
@@ -0,0 +1 @@
+3
diff --git a/src/initrd/tests/sysfs/firmware/ibft/target2/index b/src/initrd/tests/sysfs/firmware/ibft/target2/index
new file mode 100644
index 0000000000..0cfbf08886
--- /dev/null
+++ b/src/initrd/tests/sysfs/firmware/ibft/target2/index
@@ -0,0 +1 @@
+2
diff --git a/src/initrd/tests/sysfs/firmware/ibft/target2/ip-addr b/src/initrd/tests/sysfs/firmware/ibft/target2/ip-addr
new file mode 100644
index 0000000000..a210477e6d
--- /dev/null
+++ b/src/initrd/tests/sysfs/firmware/ibft/target2/ip-addr
@@ -0,0 +1 @@
+2001:0db8:0000:0000:0000:0000:0002:3260
diff --git a/src/initrd/tests/sysfs/firmware/ibft/target2/lun b/src/initrd/tests/sysfs/firmware/ibft/target2/lun
new file mode 100644
index 0000000000..7c295bd444
--- /dev/null
+++ b/src/initrd/tests/sysfs/firmware/ibft/target2/lun
@@ -0,0 +1 @@
+01000000
diff --git a/src/initrd/tests/sysfs/firmware/ibft/target2/nic-assoc b/src/initrd/tests/sysfs/firmware/ibft/target2/nic-assoc
new file mode 100644
index 0000000000..0cfbf08886
--- /dev/null
+++ b/src/initrd/tests/sysfs/firmware/ibft/target2/nic-assoc
@@ -0,0 +1 @@
+2
diff --git a/src/initrd/tests/sysfs/firmware/ibft/target2/port b/src/initrd/tests/sysfs/firmware/ibft/target2/port
new file mode 100644
index 0000000000..53f0295f3f
--- /dev/null
+++ b/src/initrd/tests/sysfs/firmware/ibft/target2/port
@@ -0,0 +1 @@
+3260
diff --git a/src/initrd/tests/sysfs/firmware/ibft/target2/target-name b/src/initrd/tests/sysfs/firmware/ibft/target2/target-name
new file mode 100644
index 0000000000..f409432041
--- /dev/null
+++ b/src/initrd/tests/sysfs/firmware/ibft/target2/target-name
@@ -0,0 +1 @@
+iqn.1994-05.com.example.target:48b055851337
diff --git a/src/initrd/tests/test-cmdline-reader.c b/src/initrd/tests/test-cmdline-reader.c
new file mode 100644
index 0000000000..4db7114763
--- /dev/null
+++ b/src/initrd/tests/test-cmdline-reader.c
@@ -0,0 +1,787 @@
+/* NetworkManager initrd configuration generator
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA.
+ *
+ * Copyright 2018 Red Hat, Inc.
+ */
+
+#include "nm-default.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "nm-core-internal.h"
+#include "NetworkManagerUtils.h"
+
+#include "../nm-initrd-generator.h"
+
+#include "nm-test-utils-core.h"
+
+static void
+test_auto (void)
+{
+ gs_unref_hashtable GHashTable *connections = NULL;
+ gs_strfreev char **argv = g_strdupv ((char *[]){ "ip=auto", NULL });
+ NMConnection *connection;
+ NMSettingConnection *s_con;
+ NMSettingWired *s_wired;
+ NMSettingIPConfig *s_ip4;
+ NMSettingIPConfig *s_ip6;
+
+ connections = nmi_cmdline_reader_parse (TEST_INITRD_DIR "/sysfs", argv);
+ g_assert (connections);
+ g_assert_cmpint (g_hash_table_size (connections), ==, 1);
+
+ connection = g_hash_table_lookup (connections, "default_connection");
+ g_assert (connection);
+ nmtst_assert_connection_verifies_without_normalization (connection);
+
+ g_assert (!nm_connection_get_setting_vlan (connection));
+
+ s_con = nm_connection_get_setting_connection (connection);
+ g_assert (s_con);
+ g_assert_cmpstr (nm_setting_connection_get_connection_type (s_con), ==, NM_SETTING_WIRED_SETTING_NAME);
+ g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, "Wired Connection");
+ g_assert_cmpint (nm_setting_connection_get_timestamp (s_con), ==, 0);
+ g_assert (nm_setting_connection_get_autoconnect (s_con));
+
+ s_wired = nm_connection_get_setting_wired (connection);
+ g_assert (s_wired);
+ g_assert (!nm_setting_wired_get_mac_address (s_wired));
+ g_assert_cmpint (nm_setting_wired_get_mtu (s_wired), ==, 0);
+
+ 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);
+ g_assert (!nm_setting_ip_config_get_ignore_auto_dns (s_ip4));
+ g_assert_cmpint (nm_setting_ip_config_get_num_dns (s_ip4), ==, 0);
+ g_assert_cmpint (nm_setting_ip_config_get_num_addresses (s_ip4), ==, 0);
+ g_assert (!nm_setting_ip_config_get_gateway (s_ip4));
+
+ 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_AUTO);
+ g_assert (!nm_setting_ip_config_get_ignore_auto_dns (s_ip6));
+ g_assert_cmpint (nm_setting_ip_config_get_num_dns (s_ip6), ==, 0);
+ g_assert_cmpint (nm_setting_ip_config_get_num_addresses (s_ip6), ==, 0);
+ g_assert (!nm_setting_ip_config_get_gateway (s_ip6));
+}
+
+static void
+test_if_auto_with_mtu (void)
+{
+ gs_unref_hashtable GHashTable *connections = NULL;
+ gs_strfreev char **argv = g_strdupv ((char *[]){ "ip=eth0:auto:1666", NULL });
+ NMConnection *connection;
+ NMSettingWired *s_wired;
+ NMSettingIPConfig *s_ip4;
+ NMSettingIPConfig *s_ip6;
+
+ connections = nmi_cmdline_reader_parse (TEST_INITRD_DIR "/sysfs", argv);
+ g_assert (connections);
+ g_assert_cmpint (g_hash_table_size (connections), ==, 1);
+
+ connection = g_hash_table_lookup (connections, "eth0");
+ g_assert (connection);
+ nmtst_assert_connection_verifies_without_normalization (connection);
+ g_assert_cmpstr (nm_connection_get_id (connection), ==, "eth0");
+
+ s_wired = nm_connection_get_setting_wired (connection);
+ g_assert (s_wired);
+ g_assert_cmpint (nm_setting_wired_get_mtu (s_wired), ==, 1666);
+
+ 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);
+ g_assert (!nm_setting_ip_config_get_ignore_auto_dns (s_ip4));
+
+ 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_AUTO);
+ g_assert (!nm_setting_ip_config_get_ignore_auto_dns (s_ip6));
+}
+
+
+static void
+test_if_dhcp6 (void)
+{
+ gs_unref_hashtable GHashTable *connections = NULL;
+ gs_strfreev char **argv = g_strdupv ((char *[]){ "ip=eth1:dhcp6", NULL });
+ NMConnection *connection;
+ NMSettingIPConfig *s_ip4;
+ NMSettingIPConfig *s_ip6;
+
+ connections = nmi_cmdline_reader_parse (TEST_INITRD_DIR "/sysfs", argv);
+ g_assert (connections);
+ g_assert_cmpint (g_hash_table_size (connections), ==, 1);
+ connection = g_hash_table_lookup (connections, "eth1");
+ g_assert (connection);
+ nmtst_assert_connection_verifies_without_normalization (connection);
+ g_assert_cmpstr (nm_connection_get_id (connection), ==, "eth1");
+
+ 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 (!nm_setting_ip_config_get_ignore_auto_dns (s_ip4));
+
+ 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_DHCP);
+ g_assert (!nm_setting_ip_config_get_ignore_auto_dns (s_ip6));
+}
+
+
+static void
+test_if_auto_with_mtu_and_mac (void)
+{
+ gs_unref_hashtable GHashTable *connections = NULL;
+ gs_strfreev char **argv = g_strdupv ((char *[]){ "ip=eth2:auto6:2048:00:53:ef:12:34:56", NULL });
+ NMConnection *connection;
+ NMSettingWired *s_wired;
+ NMSettingIPConfig *s_ip4;
+ NMSettingIPConfig *s_ip6;
+
+ connections = nmi_cmdline_reader_parse (TEST_INITRD_DIR "/sysfs", argv);
+ g_assert (connections);
+ g_assert_cmpint (g_hash_table_size (connections), ==, 1);
+
+ connection = g_hash_table_lookup (connections, "eth2");
+ g_assert (connection);
+ nmtst_assert_connection_verifies_without_normalization (connection);
+ g_assert_cmpstr (nm_connection_get_id (connection), ==, "eth2");
+
+ s_wired = nm_connection_get_setting_wired (connection);
+ g_assert (s_wired);
+ g_assert_cmpint (nm_setting_wired_get_mtu (s_wired), ==, 2048);
+ g_assert_cmpstr (nm_setting_wired_get_cloned_mac_address (s_wired), ==, "00:53:EF:12:34:56");
+
+ 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 (!nm_setting_ip_config_get_ignore_auto_dns (s_ip4));
+
+ 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_AUTO);
+ g_assert (!nm_setting_ip_config_get_ignore_auto_dns (s_ip6));
+}
+
+
+static void
+test_if_ip4_manual (void)
+{
+ gs_unref_hashtable GHashTable *connections = NULL;
+ gs_strfreev char **argv = g_strdupv ((char *[]){
+ "ip=192.0.2.2::192.0.2.1:255.255.255.0:"
+ "hostname0.example.com:eth3::192.0.2.53", NULL });
+ NMConnection *connection;
+ NMSettingIPConfig *s_ip4;
+ NMIPAddress *ip_addr;
+
+ connections = nmi_cmdline_reader_parse (TEST_INITRD_DIR "/sysfs", argv);
+ g_assert (connections);
+ g_assert_cmpint (g_hash_table_size (connections), ==, 1);
+
+ connection = g_hash_table_lookup (connections, "eth3");
+ g_assert (connection);
+ nmtst_assert_connection_verifies_without_normalization (connection);
+ g_assert_cmpstr (nm_connection_get_id (connection), ==, "eth3");
+
+ 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);
+ g_assert (!nm_setting_ip_config_get_ignore_auto_dns (s_ip4));
+ g_assert_cmpint (nm_setting_ip_config_get_num_dns (s_ip4), ==, 1);
+ g_assert_cmpstr (nm_setting_ip_config_get_dns (s_ip4, 0), ==, "192.0.2.53");
+ g_assert_cmpint (nm_setting_ip_config_get_num_routes (s_ip4), ==, 0);
+ g_assert_cmpint (nm_setting_ip_config_get_num_addresses (s_ip4), ==, 1);
+ ip_addr = nm_setting_ip_config_get_address (s_ip4, 0);
+ g_assert (ip_addr);
+ g_assert_cmpstr (nm_ip_address_get_address (ip_addr), ==, "192.0.2.2");
+ g_assert_cmpint (nm_ip_address_get_prefix (ip_addr), ==, 24);
+ g_assert_cmpstr (nm_setting_ip_config_get_gateway (s_ip4), ==, "192.0.2.1");
+ g_assert_cmpstr (nm_setting_ip_config_get_dhcp_hostname (s_ip4), ==, "hostname0.example.com");
+}
+
+
+static void
+test_if_ip6_manual (void)
+{
+ gs_unref_hashtable GHashTable *connections = NULL;
+ gs_strfreev char **argv = g_strdupv ((char *[]){
+ "ip=[2001:0db8::02]/64::[2001:0db8::01]::"
+ "hostname0.example.com:eth4::[2001:0db8::53]",
+ NULL
+ });
+ NMConnection *connection;
+ NMSettingIPConfig *s_ip6;
+ NMIPAddress *ip_addr;
+
+ connections = nmi_cmdline_reader_parse (TEST_INITRD_DIR "/sysfs", argv);
+ g_assert (connections);
+ g_assert_cmpint (g_hash_table_size (connections), ==, 1);
+
+ connection = g_hash_table_lookup (connections, "eth4");
+ g_assert (connection);
+ nmtst_assert_connection_verifies_without_normalization (connection);
+ g_assert_cmpstr (nm_connection_get_id (connection), ==, "eth4");
+
+ 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);
+ g_assert (!nm_setting_ip_config_get_ignore_auto_dns (s_ip6));
+ g_assert_cmpint (nm_setting_ip_config_get_num_dns (s_ip6), ==, 1);
+ g_assert_cmpstr (nm_setting_ip_config_get_dns (s_ip6, 0), ==, "2001:db8::53");
+ g_assert_cmpint (nm_setting_ip_config_get_num_routes (s_ip6), ==, 0);
+ g_assert_cmpint (nm_setting_ip_config_get_num_addresses (s_ip6), ==, 1);
+ ip_addr = nm_setting_ip_config_get_address (s_ip6, 0);
+ g_assert (ip_addr);
+ g_assert_cmpstr (nm_ip_address_get_address (ip_addr), ==, "2001:db8::2");
+ g_assert_cmpint (nm_ip_address_get_prefix (ip_addr), ==, 64);
+ g_assert_cmpstr (nm_setting_ip_config_get_gateway (s_ip6), ==, "2001:db8::1");
+ g_assert_cmpstr (nm_setting_ip_config_get_dhcp_hostname (s_ip6), ==, "hostname0.example.com");
+}
+
+static void
+test_multiple (void)
+{
+ gs_unref_hashtable GHashTable *connections = NULL;
+ gs_strfreev char **argv = g_strdupv ((char *[]){ "ip=192.0.2.2:::::eth0", "ip=[2001:db8::2]:::::eth0", NULL });
+ NMConnection *connection;
+ NMSettingIPConfig *s_ip4;
+ NMSettingIPConfig *s_ip6;
+ NMIPAddress *ip_addr;
+
+ connections = nmi_cmdline_reader_parse (TEST_INITRD_DIR "/sysfs", argv);
+ g_assert (connections);
+ g_assert_cmpint (g_hash_table_size (connections), ==, 1);
+
+ connection = g_hash_table_lookup (connections, "eth0");
+ g_assert (connection);
+ nmtst_assert_connection_verifies_without_normalization (connection);
+ g_assert_cmpstr (nm_connection_get_id (connection), ==, "eth0");
+
+ 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);
+ g_assert (!nm_setting_ip_config_get_ignore_auto_dns (s_ip4));
+ g_assert_cmpint (nm_setting_ip_config_get_num_addresses (s_ip4), ==, 1);
+ ip_addr = nm_setting_ip_config_get_address (s_ip4, 0);
+ g_assert (ip_addr);
+ g_assert_cmpstr (nm_ip_address_get_address (ip_addr), ==, "192.0.2.2");
+
+ 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);
+ g_assert (!nm_setting_ip_config_get_ignore_auto_dns (s_ip6));
+ g_assert_cmpint (nm_setting_ip_config_get_num_addresses (s_ip6), ==, 1);
+ ip_addr = nm_setting_ip_config_get_address (s_ip6, 0);
+ g_assert (ip_addr);
+ g_assert_cmpstr (nm_ip_address_get_address (ip_addr), ==, "2001:db8::2");
+}
+
+static void
+test_some_more (void)
+{
+ gs_unref_hashtable GHashTable *connections = NULL;
+ gs_strfreev char **argv = g_strdupv ((char *[]){ "bootdev=eth1", "hail", "nameserver=[2001:DB8:3::53]",
+ "satan", "nameserver=192.0.2.53", "worship",
+ "BOOTIF=00-53-AB-cd-02-03", "doom", "rd.peerdns=0",
+ "rd.route=[2001:DB8:3::/48]:[2001:DB8:2::1]:ens10",
+ NULL });
+ NMConnection *connection;
+ NMSettingConnection *s_con;
+ NMSettingWired *s_wired;
+ NMSettingIPConfig *s_ip4;
+ NMSettingIPConfig *s_ip6;
+ NMIPRoute *ip_route;
+
+ connections = nmi_cmdline_reader_parse (TEST_INITRD_DIR "/sysfs", argv);
+ g_assert (connections);
+ g_assert_cmpint (g_hash_table_size (connections), ==, 2);
+
+ connection = g_hash_table_lookup (connections, "default_connection");
+ g_assert (connection);
+ nmtst_assert_connection_verifies_without_normalization (connection);
+
+ s_con = nm_connection_get_setting_connection (connection);
+ g_assert (s_con);
+ g_assert_cmpstr (nm_setting_connection_get_connection_type (s_con), ==, NM_SETTING_WIRED_SETTING_NAME);
+ g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, "Wired Connection");
+ g_assert_cmpstr (nm_setting_connection_get_interface_name (s_con), ==, "eth1");
+
+ s_wired = nm_connection_get_setting_wired (connection);
+ g_assert (s_wired);
+ g_assert_cmpstr (nm_setting_wired_get_mac_address (s_wired), ==, "00:53:AB:CD:02:03");
+
+ 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);
+ g_assert (nm_setting_ip_config_get_ignore_auto_dns (s_ip4));
+ g_assert_cmpint (nm_setting_ip_config_get_num_addresses (s_ip4), ==, 0);
+ g_assert (!nm_setting_ip_config_get_gateway (s_ip4));
+ g_assert_cmpint (nm_setting_ip_config_get_num_dns (s_ip4), ==, 1);
+ g_assert_cmpstr (nm_setting_ip_config_get_dns (s_ip4, 0), ==, "192.0.2.53");
+
+
+ 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_AUTO);
+ g_assert (nm_setting_ip_config_get_ignore_auto_dns (s_ip6));
+ g_assert_cmpint (nm_setting_ip_config_get_num_dns (s_ip6), ==, 1);
+ g_assert (!nm_setting_ip_config_get_gateway (s_ip6));
+ g_assert_cmpstr (nm_setting_ip_config_get_dns (s_ip6, 0), ==, "2001:db8:3::53");
+
+
+ connection = g_hash_table_lookup (connections, "ens10");
+ g_assert (connection);
+ nmtst_assert_connection_verifies_without_normalization (connection);
+
+ s_con = nm_connection_get_setting_connection (connection);
+ g_assert (s_con);
+ g_assert_cmpstr (nm_setting_connection_get_connection_type (s_con), ==, NM_SETTING_WIRED_SETTING_NAME);
+ g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, "ens10");
+ g_assert_cmpstr (nm_setting_connection_get_interface_name (s_con), ==, "ens10");
+
+ s_wired = nm_connection_get_setting_wired (connection);
+ g_assert (s_wired);
+ g_assert (!nm_setting_wired_get_mac_address (s_wired));
+
+ 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_AUTO);
+ g_assert_cmpint (nm_setting_ip_config_get_num_dns (s_ip6), ==, 0);
+ g_assert_cmpint (nm_setting_ip_config_get_num_routes (s_ip6), ==, 1);
+ g_assert (!nm_setting_ip_config_get_gateway (s_ip6));
+ ip_route = nm_setting_ip_config_get_route (s_ip6, 0);
+ g_assert_cmpstr (nm_ip_route_get_dest (ip_route), ==, "2001:db8:3::");
+ g_assert_cmpint (nm_ip_route_get_family (ip_route), ==, AF_INET6);
+ g_assert_cmpint (nm_ip_route_get_metric (ip_route), ==, -1);
+ g_assert_cmpstr (nm_ip_route_get_next_hop (ip_route), ==, "2001:db8:2::1");
+ g_assert_cmpint (nm_ip_route_get_prefix (ip_route), ==, 48);
+}
+
+static void
+test_no_bootif (void)
+{
+ gs_unref_hashtable GHashTable *connections = NULL;
+ gs_strfreev char **argv = g_strdupv ((char *[]){ "BOOTIF=00-53-AB-cd-02-03", "rd.bootif=0", NULL });
+
+ connections = nmi_cmdline_reader_parse (TEST_INITRD_DIR "/sysfs", argv);
+ g_assert (connections);
+ g_assert_cmpint (g_hash_table_size (connections), ==, 0);
+}
+
+static void
+test_bond (void)
+{
+ gs_unref_hashtable GHashTable *connections = NULL;
+ gs_strfreev char **argv = g_strdupv ((char *[]){ "rd.route=192.0.2.53::bong0", "bond=bong0:eth0,eth1:mode=balance-rr", NULL });
+ NMConnection *connection;
+ NMSettingConnection *s_con;
+ NMSettingIPConfig *s_ip4;
+ NMSettingIPConfig *s_ip6;
+ NMSettingBond *s_bond;
+ NMIPRoute *ip_route;
+ const char *master_uuid;
+
+ connections = nmi_cmdline_reader_parse (TEST_INITRD_DIR "/sysfs", argv);
+ g_assert (connections);
+ g_assert_cmpint (g_hash_table_size (connections), ==, 3);
+
+ connection = g_hash_table_lookup (connections, "bong0");
+ g_assert (connection);
+ nmtst_assert_connection_verifies_without_normalization (connection);
+ g_assert_cmpstr (nm_connection_get_connection_type (connection), ==, NM_SETTING_BOND_SETTING_NAME);
+ g_assert_cmpstr (nm_connection_get_id (connection), ==, "bong0");
+ master_uuid = nm_connection_get_uuid (connection);
+ g_assert (master_uuid);
+
+ 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);
+ g_assert (!nm_setting_ip_config_get_ignore_auto_dns (s_ip4));
+ g_assert_cmpint (nm_setting_ip_config_get_num_dns (s_ip4), ==, 0);
+ g_assert (!nm_setting_ip_config_get_gateway (s_ip4));
+ g_assert_cmpint (nm_setting_ip_config_get_num_routes (s_ip4), ==, 1);
+ ip_route = nm_setting_ip_config_get_route (s_ip4, 0);
+ g_assert_cmpstr (nm_ip_route_get_dest (ip_route), ==, "192.0.2.53");
+ g_assert_cmpint (nm_ip_route_get_family (ip_route), ==, AF_INET);
+ g_assert_cmpint (nm_ip_route_get_metric (ip_route), ==, -1);
+ g_assert (!nm_ip_route_get_next_hop (ip_route));
+ g_assert_cmpint (nm_ip_route_get_prefix (ip_route), ==, 32);
+
+ 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_AUTO);
+ g_assert (!nm_setting_ip_config_get_ignore_auto_dns (s_ip6));
+ g_assert_cmpint (nm_setting_ip_config_get_num_dns (s_ip6), ==, 0);
+ g_assert (!nm_setting_ip_config_get_gateway (s_ip6));
+ g_assert_cmpint (nm_setting_ip_config_get_num_routes (s_ip6), ==, 0);
+
+ s_bond = nm_connection_get_setting_bond (connection);
+ g_assert (s_bond);
+ g_assert_cmpint (nm_setting_bond_get_num_options (s_bond), ==, 1);
+ g_assert_cmpstr (nm_setting_bond_get_option_by_name (s_bond, "mode"), ==, "balance-rr");
+
+ connection = g_hash_table_lookup (connections, "eth0");
+ g_assert (connection);
+ nmtst_assert_connection_verifies_without_normalization (connection);
+ g_assert_cmpstr (nm_connection_get_id (connection), ==, "eth0");
+
+ s_con = nm_connection_get_setting_connection (connection);
+ g_assert (s_con);
+ g_assert_cmpstr (nm_setting_connection_get_connection_type (s_con), ==, NM_SETTING_WIRED_SETTING_NAME);
+ g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, "eth0");
+ g_assert_cmpstr (nm_setting_connection_get_slave_type (s_con), ==, NM_SETTING_BOND_SETTING_NAME);
+ g_assert_cmpstr (nm_setting_connection_get_master (s_con), ==, master_uuid);
+
+ connection = g_hash_table_lookup (connections, "eth1");
+ g_assert (connection);
+ nmtst_assert_connection_verifies_without_normalization (connection);
+ g_assert_cmpstr (nm_connection_get_id (connection), ==, "eth1");
+
+ s_con = nm_connection_get_setting_connection (connection);
+ g_assert (s_con);
+ g_assert_cmpstr (nm_setting_connection_get_connection_type (s_con), ==, NM_SETTING_WIRED_SETTING_NAME);
+ g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, "eth1");
+ g_assert_cmpstr (nm_setting_connection_get_slave_type (s_con), ==, NM_SETTING_BOND_SETTING_NAME);
+ g_assert_cmpstr (nm_setting_connection_get_master (s_con), ==, master_uuid);
+}
+
+static void
+test_bond_default (void)
+{
+ gs_unref_hashtable GHashTable *connections = NULL;
+ gs_strfreev char **argv = g_strdupv ((char *[]){ "bond", NULL });
+ NMConnection *connection;
+ NMSettingConnection *s_con;
+ NMSettingIPConfig *s_ip4;
+ NMSettingIPConfig *s_ip6;
+ NMSettingBond *s_bond;
+ const char *master_uuid;
+
+ connections = nmi_cmdline_reader_parse (TEST_INITRD_DIR "/sysfs", argv);
+ g_assert (connections);
+ g_assert_cmpint (g_hash_table_size (connections), ==, 2);
+
+ connection = g_hash_table_lookup (connections, "bond0");
+
+ g_assert (connection);
+ nmtst_assert_connection_verifies_without_normalization (connection);
+ g_assert_cmpstr (nm_connection_get_connection_type (connection), ==, NM_SETTING_BOND_SETTING_NAME);
+ g_assert_cmpstr (nm_connection_get_id (connection), ==, "bond0");
+ master_uuid = nm_connection_get_uuid (connection);
+ g_assert (master_uuid);
+
+ 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);
+ g_assert (!nm_setting_ip_config_get_ignore_auto_dns (s_ip4));
+ g_assert_cmpint (nm_setting_ip_config_get_num_dns (s_ip4), ==, 0);
+ g_assert (!nm_setting_ip_config_get_gateway (s_ip4));
+ g_assert_cmpint (nm_setting_ip_config_get_num_routes (s_ip4), ==, 0);
+
+ 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_AUTO);
+ g_assert (!nm_setting_ip_config_get_ignore_auto_dns (s_ip6));
+ g_assert_cmpint (nm_setting_ip_config_get_num_dns (s_ip6), ==, 0);
+ g_assert (!nm_setting_ip_config_get_gateway (s_ip6));
+ g_assert_cmpint (nm_setting_ip_config_get_num_routes (s_ip6), ==, 0);
+
+ s_bond = nm_connection_get_setting_bond (connection);
+ g_assert (s_bond);
+ g_assert_cmpint (nm_setting_bond_get_num_options (s_bond), ==, 1);
+ g_assert_cmpstr (nm_setting_bond_get_option_by_name (s_bond, "mode"), ==, "balance-rr");
+
+ connection = g_hash_table_lookup (connections, "eth0");
+ g_assert (connection);
+ nmtst_assert_connection_verifies_without_normalization (connection);
+ g_assert_cmpstr (nm_connection_get_id (connection), ==, "eth0");
+
+ s_con = nm_connection_get_setting_connection (connection);
+ g_assert (s_con);
+ g_assert_cmpstr (nm_setting_connection_get_connection_type (s_con), ==, NM_SETTING_WIRED_SETTING_NAME);
+ g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, "eth0");
+ g_assert_cmpstr (nm_setting_connection_get_slave_type (s_con), ==, NM_SETTING_BOND_SETTING_NAME);
+ g_assert_cmpstr (nm_setting_connection_get_master (s_con), ==, master_uuid);
+}
+
+static void
+test_bridge (void)
+{
+ gs_unref_hashtable GHashTable *connections = NULL;
+ gs_strfreev char **argv = g_strdupv ((char *[]){ "bridge=bridge0:eth0,eth1", "rd.route=192.0.2.53::bridge0", NULL });
+ NMConnection *connection;
+ NMSettingConnection *s_con;
+ NMSettingIPConfig *s_ip4;
+ NMSettingIPConfig *s_ip6;
+ NMSettingBridge *s_bridge;
+ NMIPRoute *ip_route;
+ const char *master_uuid;
+
+ connections = nmi_cmdline_reader_parse (TEST_INITRD_DIR "/sysfs", argv);
+ g_assert (connections);
+ g_assert_cmpint (g_hash_table_size (connections), ==, 3);
+
+ connection = g_hash_table_lookup (connections, "bridge0");
+ g_assert (connection);
+ nmtst_assert_connection_verifies_without_normalization (connection);
+ g_assert_cmpstr (nm_connection_get_connection_type (connection), ==, NM_SETTING_BRIDGE_SETTING_NAME);
+ g_assert_cmpstr (nm_connection_get_id (connection), ==, "bridge0");
+ master_uuid = nm_connection_get_uuid (connection);
+ g_assert (master_uuid);
+
+ 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);
+ g_assert (!nm_setting_ip_config_get_ignore_auto_dns (s_ip4));
+ g_assert_cmpint (nm_setting_ip_config_get_num_dns (s_ip4), ==, 0);
+ g_assert (!nm_setting_ip_config_get_gateway (s_ip4));
+ g_assert_cmpint (nm_setting_ip_config_get_num_routes (s_ip4), ==, 1);
+ ip_route = nm_setting_ip_config_get_route (s_ip4, 0);
+ g_assert_cmpstr (nm_ip_route_get_dest (ip_route), ==, "192.0.2.53");
+ g_assert_cmpint (nm_ip_route_get_family (ip_route), ==, AF_INET);
+ g_assert_cmpint (nm_ip_route_get_metric (ip_route), ==, -1);
+ g_assert (!nm_ip_route_get_next_hop (ip_route));
+ g_assert_cmpint (nm_ip_route_get_prefix (ip_route), ==, 32);
+
+ 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_AUTO);
+ g_assert (!nm_setting_ip_config_get_ignore_auto_dns (s_ip6));
+ g_assert_cmpint (nm_setting_ip_config_get_num_dns (s_ip6), ==, 0);
+ g_assert (!nm_setting_ip_config_get_gateway (s_ip6));
+ g_assert_cmpint (nm_setting_ip_config_get_num_routes (s_ip6), ==, 0);
+
+ s_bridge = nm_connection_get_setting_bridge (connection);
+ g_assert (s_bridge);
+
+ connection = g_hash_table_lookup (connections, "eth0");
+ g_assert (connection);
+ nmtst_assert_connection_verifies_without_normalization (connection);
+ g_assert_cmpstr (nm_connection_get_id (connection), ==, "eth0");
+
+ s_con = nm_connection_get_setting_connection (connection);
+ g_assert (s_con);
+ g_assert_cmpstr (nm_setting_connection_get_connection_type (s_con), ==, NM_SETTING_WIRED_SETTING_NAME);
+ g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, "eth0");
+ g_assert_cmpstr (nm_setting_connection_get_slave_type (s_con), ==, NM_SETTING_BRIDGE_SETTING_NAME);
+ g_assert_cmpstr (nm_setting_connection_get_master (s_con), ==, master_uuid);
+
+ connection = g_hash_table_lookup (connections, "eth1");
+ g_assert (connection);
+ nmtst_assert_connection_verifies_without_normalization (connection);
+ g_assert_cmpstr (nm_connection_get_id (connection), ==, "eth1");
+
+ s_con = nm_connection_get_setting_connection (connection);
+ g_assert (s_con);
+ g_assert_cmpstr (nm_setting_connection_get_connection_type (s_con), ==, NM_SETTING_WIRED_SETTING_NAME);
+ g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, "eth1");
+ g_assert_cmpstr (nm_setting_connection_get_slave_type (s_con), ==, NM_SETTING_BRIDGE_SETTING_NAME);
+ g_assert_cmpstr (nm_setting_connection_get_master (s_con), ==, master_uuid);
+}
+
+static void
+test_bridge_default (void)
+{
+ gs_unref_hashtable GHashTable *connections = NULL;
+ gs_strfreev char **argv = g_strdupv ((char *[]){ "bridge", NULL });
+ NMConnection *connection;
+ NMSettingConnection *s_con;
+ NMSettingIPConfig *s_ip4;
+ NMSettingIPConfig *s_ip6;
+ NMSettingBridge *s_bridge;
+ const char *master_uuid;
+
+ connections = nmi_cmdline_reader_parse (TEST_INITRD_DIR "/sysfs", argv);
+ g_assert (connections);
+ g_assert_cmpint (g_hash_table_size (connections), ==, 2);
+
+ connection = g_hash_table_lookup (connections, "bridge0");
+
+ g_assert (connection);
+ nmtst_assert_connection_verifies_without_normalization (connection);
+ g_assert_cmpstr (nm_connection_get_connection_type (connection), ==, NM_SETTING_BRIDGE_SETTING_NAME);
+ g_assert_cmpstr (nm_connection_get_id (connection), ==, "bridge0");
+ master_uuid = nm_connection_get_uuid (connection);
+ g_assert (master_uuid);
+
+ 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);
+ g_assert (!nm_setting_ip_config_get_ignore_auto_dns (s_ip4));
+ g_assert_cmpint (nm_setting_ip_config_get_num_dns (s_ip4), ==, 0);
+ g_assert (!nm_setting_ip_config_get_gateway (s_ip4));
+ g_assert_cmpint (nm_setting_ip_config_get_num_routes (s_ip4), ==, 0);
+
+ 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_AUTO);
+ g_assert (!nm_setting_ip_config_get_ignore_auto_dns (s_ip6));
+ g_assert_cmpint (nm_setting_ip_config_get_num_dns (s_ip6), ==, 0);
+ g_assert (!nm_setting_ip_config_get_gateway (s_ip6));
+ g_assert_cmpint (nm_setting_ip_config_get_num_routes (s_ip6), ==, 0);
+
+ s_bridge = nm_connection_get_setting_bridge (connection);
+ g_assert (s_bridge);
+
+ connection = g_hash_table_lookup (connections, "eth0");
+ g_assert (connection);
+ nmtst_assert_connection_verifies_without_normalization (connection);
+ g_assert_cmpstr (nm_connection_get_id (connection), ==, "eth0");
+
+ s_con = nm_connection_get_setting_connection (connection);
+ g_assert (s_con);
+ g_assert_cmpstr (nm_setting_connection_get_connection_type (s_con), ==, NM_SETTING_WIRED_SETTING_NAME);
+ g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, "eth0");
+ g_assert_cmpstr (nm_setting_connection_get_slave_type (s_con), ==, NM_SETTING_BRIDGE_SETTING_NAME);
+ g_assert_cmpstr (nm_setting_connection_get_master (s_con), ==, master_uuid);
+}
+
+static void
+test_team (void)
+{
+ gs_unref_hashtable GHashTable *connections = NULL;
+ gs_strfreev char **argv = g_strdupv ((char *[]){ "team=team0:eth0,eth1", "ip=team0:dhcp6", NULL });
+ NMConnection *connection;
+ NMSettingConnection *s_con;
+ NMSettingIPConfig *s_ip4;
+ NMSettingIPConfig *s_ip6;
+ NMSettingTeam *s_team;
+ const char *master_uuid;
+
+ connections = nmi_cmdline_reader_parse (TEST_INITRD_DIR "/sysfs", argv);
+ g_assert (connections);
+ g_assert_cmpint (g_hash_table_size (connections), ==, 3);
+
+ connection = g_hash_table_lookup (connections, "team0");
+ g_assert (connection);
+ nmtst_assert_connection_verifies_without_normalization (connection);
+ g_assert_cmpstr (nm_connection_get_connection_type (connection), ==, NM_SETTING_TEAM_SETTING_NAME);
+ g_assert_cmpstr (nm_connection_get_id (connection), ==, "team0");
+ master_uuid = nm_connection_get_uuid (connection);
+ g_assert (master_uuid);
+
+ 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 (!nm_setting_ip_config_get_ignore_auto_dns (s_ip4));
+ g_assert_cmpint (nm_setting_ip_config_get_num_dns (s_ip4), ==, 0);
+ g_assert (!nm_setting_ip_config_get_gateway (s_ip4));
+ g_assert_cmpint (nm_setting_ip_config_get_num_routes (s_ip4), ==, 0);
+
+ 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_DHCP);
+ g_assert (!nm_setting_ip_config_get_ignore_auto_dns (s_ip6));
+ g_assert_cmpint (nm_setting_ip_config_get_num_dns (s_ip6), ==, 0);
+ g_assert (!nm_setting_ip_config_get_gateway (s_ip6));
+ g_assert_cmpint (nm_setting_ip_config_get_num_routes (s_ip6), ==, 0);
+
+ s_team = nm_connection_get_setting_team (connection);
+ g_assert (s_team);
+
+ connection = g_hash_table_lookup (connections, "eth0");
+ g_assert (connection);
+ nmtst_assert_connection_verifies_without_normalization (connection);
+ g_assert_cmpstr (nm_connection_get_id (connection), ==, "eth0");
+
+ s_con = nm_connection_get_setting_connection (connection);
+ g_assert (s_con);
+ g_assert_cmpstr (nm_setting_connection_get_connection_type (s_con), ==, NM_SETTING_WIRED_SETTING_NAME);
+ g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, "eth0");
+ g_assert_cmpstr (nm_setting_connection_get_slave_type (s_con), ==, NM_SETTING_TEAM_SETTING_NAME);
+ g_assert_cmpstr (nm_setting_connection_get_master (s_con), ==, master_uuid);
+
+ connection = g_hash_table_lookup (connections, "eth1");
+ g_assert (connection);
+ nmtst_assert_connection_verifies_without_normalization (connection);
+ g_assert_cmpstr (nm_connection_get_id (connection), ==, "eth1");
+
+ s_con = nm_connection_get_setting_connection (connection);
+ g_assert (s_con);
+ g_assert_cmpstr (nm_setting_connection_get_connection_type (s_con), ==, NM_SETTING_WIRED_SETTING_NAME);
+ g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, "eth1");
+ g_assert_cmpstr (nm_setting_connection_get_slave_type (s_con), ==, NM_SETTING_TEAM_SETTING_NAME);
+ g_assert_cmpstr (nm_setting_connection_get_master (s_con), ==, master_uuid);
+}
+
+static void
+test_ibft (void)
+{
+ gs_unref_hashtable GHashTable *connections = NULL;
+ gs_strfreev char **argv = g_strdupv ((char *[]){ "ip=ibft", NULL });
+ NMConnection *connection;
+
+ connections = nmi_cmdline_reader_parse (TEST_INITRD_DIR "/sysfs", argv);
+ g_assert (connections);
+ g_assert_cmpint (g_hash_table_size (connections), ==, 2);
+
+ connection = g_hash_table_lookup (connections, "ibft0");
+ g_assert (connection);
+ nmtst_assert_connection_verifies_without_normalization (connection);
+ g_assert_cmpstr (nm_connection_get_id (connection), ==, "iBFT VLAN Connection 0");
+
+ connection = g_hash_table_lookup (connections, "ibft2");
+ g_assert (connection);
+ nmtst_assert_connection_verifies_without_normalization (connection);
+ g_assert_cmpstr (nm_connection_get_id (connection), ==, "iBFT Connection 2");
+}
+
+static void
+test_ignore_extra (void)
+{
+ gs_unref_hashtable GHashTable *connections = NULL;
+ gs_strfreev char **argv = g_strdupv ((char *[]){ "blabla", "extra", "lalala", NULL });
+
+ connections = nmi_cmdline_reader_parse (TEST_INITRD_DIR "/sysfs", argv);
+ g_assert (connections);
+ g_assert_cmpint (g_hash_table_size (connections), ==, 0);
+}
+
+NMTST_DEFINE ();
+
+int main (int argc, char **argv)
+{
+ nmtst_init_assert_logging (&argc, &argv, "INFO", "DEFAULT");
+
+ g_test_add_func ("/initrd/cmdline/auto", test_auto);
+ g_test_add_func ("/initrd/cmdline/if_auto_with_mtu", test_if_auto_with_mtu);
+ g_test_add_func ("/initrd/cmdline/if_dhcp6", test_if_dhcp6);
+ g_test_add_func ("/initrd/cmdline/if_auto_with_mtu_and_mac", test_if_auto_with_mtu_and_mac);
+ g_test_add_func ("/initrd/cmdline/if_ip4_manual", test_if_ip4_manual);
+ g_test_add_func ("/initrd/cmdline/if_ip6_manual", test_if_ip6_manual);
+ g_test_add_func ("/initrd/cmdline/multiple", test_multiple);
+ g_test_add_func ("/initrd/cmdline/some_more", test_some_more);
+ g_test_add_func ("/initrd/cmdline/no_bootif", test_no_bootif);
+ g_test_add_func ("/initrd/cmdline/bond", test_bond);
+ g_test_add_func ("/initrd/cmdline/bond/default", test_bond_default);
+ g_test_add_func ("/initrd/cmdline/team", test_team);
+ g_test_add_func ("/initrd/cmdline/bridge", test_bridge);
+ g_test_add_func ("/initrd/cmdline/bridge/default", test_bridge_default);
+ g_test_add_func ("/initrd/cmdline/ibft", test_ibft);
+ g_test_add_func ("/initrd/cmdline/ignore_extra", test_ignore_extra);
+
+ return g_test_run ();
+}
diff --git a/src/initrd/tests/test-ibft-reader.c b/src/initrd/tests/test-ibft-reader.c
new file mode 100644
index 0000000000..340b3896c8
--- /dev/null
+++ b/src/initrd/tests/test-ibft-reader.c
@@ -0,0 +1,286 @@
+/* NetworkManager initrd configuration generator
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright 2014 - 2018 Red Hat, Inc.
+ */
+
+#include "nm-default.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "nm-core-internal.h"
+#include "NetworkManagerUtils.h"
+
+#include "../nm-initrd-generator.h"
+
+#include "nm-test-utils-core.h"
+
+static NMConnection *
+read_connection (const char *sysfs_dir, const char *expected_mac, GError **error)
+{
+ NMConnection *connection = NULL;
+ gs_unref_hashtable GHashTable *ibft = NULL;
+ gs_free char *mac = NULL;
+ GHashTable *nic = NULL;
+
+ ibft = nmi_ibft_read (sysfs_dir);
+
+ mac = g_ascii_strup (expected_mac, -1);
+ nic = g_hash_table_lookup (ibft, mac);
+ if (!nic)
+ return NULL;
+
+ connection = nm_simple_connection_new ();
+
+ if (!nmi_ibft_update_connection_from_nic (connection, nic, error))
+ g_clear_object (&connection);
+
+ return connection;
+}
+
+static void
+test_read_ibft_dhcp (void)
+{
+ NMConnection *connection;
+ NMSettingConnection *s_con;
+ NMSettingWired *s_wired;
+ NMSettingIPConfig *s_ip4;
+ NMSettingIPConfig *s_ip6;
+ GError *error = NULL;
+ const char *mac_address;
+ const char *expected_mac_address = "00:33:21:98:b9:f1";
+
+ connection = read_connection (TEST_INITRD_DIR "/sysfs-dhcp", expected_mac_address, &error);
+ g_assert_no_error (error);
+ nmtst_assert_connection_verifies_without_normalization (connection);
+
+ g_assert (!nm_connection_get_setting_vlan (connection));
+
+ s_con = nm_connection_get_setting_connection (connection);
+ g_assert (s_con);
+ g_assert_cmpstr (nm_setting_connection_get_connection_type (s_con), ==, NM_SETTING_WIRED_SETTING_NAME);
+ g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, "iBFT Connection 1");
+ g_assert_cmpint (nm_setting_connection_get_timestamp (s_con), ==, 0);
+ g_assert (nm_setting_connection_get_autoconnect (s_con));
+
+ s_wired = nm_connection_get_setting_wired (connection);
+ g_assert (s_wired);
+ mac_address = nm_setting_wired_get_mac_address (s_wired);
+ g_assert (mac_address);
+ g_assert (nm_utils_hwaddr_matches (mac_address, -1, expected_mac_address, -1));
+ g_assert_cmpint (nm_setting_wired_get_mtu (s_wired), ==, 0);
+
+ 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);
+
+ 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_IGNORE);
+
+ g_object_unref (connection);
+}
+
+static void
+test_read_ibft_static (void)
+{
+ NMConnection *connection;
+ NMSettingConnection *s_con;
+ NMSettingWired *s_wired;
+ NMSettingIPConfig *s_ip4;
+ NMSettingIPConfig *s_ip6;
+ GError *error = NULL;
+ const char *mac_address;
+ const char *expected_mac_address = "00:33:21:98:b9:f0";
+ NMIPAddress *ip4_addr;
+
+ connection = read_connection (TEST_INITRD_DIR "/sysfs-static", expected_mac_address, &error);
+ g_assert_no_error (error);
+ nmtst_assert_connection_verifies_without_normalization (connection);
+
+ g_assert (!nm_connection_get_setting_vlan (connection));
+
+ s_con = nm_connection_get_setting_connection (connection);
+ g_assert (s_con);
+ g_assert_cmpstr (nm_setting_connection_get_connection_type (s_con), ==, NM_SETTING_WIRED_SETTING_NAME);
+ g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, "iBFT Connection 0");
+ g_assert_cmpint (nm_setting_connection_get_timestamp (s_con), ==, 0);
+ g_assert (nm_setting_connection_get_autoconnect (s_con));
+
+ s_wired = nm_connection_get_setting_wired (connection);
+ g_assert (s_wired);
+ mac_address = nm_setting_wired_get_mac_address (s_wired);
+ g_assert (mac_address);
+ g_assert (nm_utils_hwaddr_matches (mac_address, -1, expected_mac_address, -1));
+ g_assert_cmpint (nm_setting_wired_get_mtu (s_wired), ==, 0);
+
+ 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);
+
+ g_assert_cmpint (nm_setting_ip_config_get_num_dns (s_ip4), ==, 2);
+ g_assert_cmpstr (nm_setting_ip_config_get_dns (s_ip4, 0), ==, "10.16.255.2");
+ g_assert_cmpstr (nm_setting_ip_config_get_dns (s_ip4, 1), ==, "10.16.255.3");
+
+ g_assert_cmpint (nm_setting_ip_config_get_num_addresses (s_ip4), ==, 1);
+ ip4_addr = nm_setting_ip_config_get_address (s_ip4, 0);
+ g_assert (ip4_addr);
+ g_assert_cmpstr (nm_ip_address_get_address (ip4_addr), ==, "192.168.32.72");
+ g_assert_cmpint (nm_ip_address_get_prefix (ip4_addr), ==, 22);
+
+ g_assert_cmpstr (nm_setting_ip_config_get_gateway (s_ip4), ==, "192.168.35.254");
+
+ 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_IGNORE);
+
+ g_object_unref (connection);
+}
+
+
+static void
+test_read_ibft_bad_address (gconstpointer user_data)
+{
+ const char *sysfs_dir = user_data;
+ NMConnection *connection;
+ GError *error = NULL;
+
+ g_assert (g_file_test (sysfs_dir, G_FILE_TEST_EXISTS));
+
+ connection = read_connection (sysfs_dir, "00:33:21:98:b9:f0", &error);
+ g_assert (connection == NULL);
+ g_assert (error);
+ g_clear_error (&error);
+}
+
+static void
+test_read_ibft_vlan (void)
+{
+ NMConnection *connection;
+ NMSettingConnection *s_con;
+ NMSettingWired *s_wired;
+ NMSettingVlan *s_vlan;
+ NMSettingIPConfig *s_ip4;
+ const char *mac_address;
+ const char *expected_mac_address = "00:33:21:98:b9:f0";
+ NMIPAddress *ip4_addr;
+ GError *error = NULL;
+
+ connection = read_connection (TEST_INITRD_DIR "/sysfs-vlan", expected_mac_address, &error);
+ g_assert_no_error (error);
+ nmtst_assert_connection_verifies_without_normalization (connection);
+
+ s_con = nm_connection_get_setting_connection (connection);
+ g_assert (s_con);
+ g_assert_cmpstr (nm_setting_connection_get_connection_type (s_con), ==, NM_SETTING_VLAN_SETTING_NAME);
+
+ /* ===== WIRED SETTING ===== */
+ s_wired = nm_connection_get_setting_wired (connection);
+ g_assert (s_wired);
+ mac_address = nm_setting_wired_get_mac_address (s_wired);
+ g_assert (mac_address);
+ g_assert (nm_utils_hwaddr_matches (mac_address, -1, expected_mac_address, -1));
+
+ /* ===== VLAN SETTING ===== */
+ s_vlan = nm_connection_get_setting_vlan (connection);
+ g_assert (s_vlan);
+ g_assert_cmpint (nm_setting_vlan_get_id (s_vlan), ==, 123);
+ g_assert_cmpstr (nm_setting_vlan_get_parent (s_vlan), ==, NULL);
+
+ /* ===== 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);
+
+ g_assert_cmpint (nm_setting_ip_config_get_num_dns (s_ip4), ==, 0);
+
+ g_assert_cmpint (nm_setting_ip_config_get_num_addresses (s_ip4), ==, 1);
+ ip4_addr = nm_setting_ip_config_get_address (s_ip4, 0);
+ g_assert (ip4_addr);
+ g_assert_cmpstr (nm_ip_address_get_address (ip4_addr), ==, "192.168.6.200");
+ g_assert_cmpint (nm_ip_address_get_prefix (ip4_addr), ==, 24);
+
+ g_assert_cmpstr (nm_setting_ip_config_get_gateway (s_ip4), ==, NULL);
+
+ g_object_unref (connection);
+}
+
+static void
+test_read_ibft (void)
+{
+ NMConnection *connection;
+ NMSettingIPConfig *s_ip4;
+ NMSettingIPConfig *s_ip6;
+ GError *error = NULL;
+
+ /* This test doesn't actually test too much (apart from the presence of
+ * IPv6 that is not covered by other tests), but the test fixture is a good
+ * example of about everything that can be included in iBFT table (as of
+ * ACPI 3.0b). */
+
+ connection = read_connection (TEST_INITRD_DIR "/sysfs", "00:53:00:AB:00:01", &error);
+ g_assert (connection);
+ g_assert_no_error (error);
+
+ s_ip4 = nm_connection_get_setting_ip4_config (connection);
+ nmtst_assert_connection_verifies_without_normalization (connection);
+ g_assert (nm_setting_ip_config_get_num_addresses (s_ip4) == 0);
+ g_assert_cmpstr (nm_setting_ip_config_get_method (s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_DISABLED);
+
+ s_ip6 = nm_connection_get_setting_ip6_config (connection);
+ g_assert (nm_setting_ip_config_get_num_addresses (s_ip6) == 1);
+ g_assert_cmpstr (nm_setting_ip_config_get_method (s_ip6), ==, NM_SETTING_IP6_CONFIG_METHOD_AUTO);
+ g_object_unref (connection);
+
+ connection = read_connection (TEST_INITRD_DIR "/sysfs", "00:53:06:66:AB:01", &error);
+ g_assert (connection);
+ g_assert_no_error (error);
+ nmtst_assert_connection_verifies_without_normalization (connection);
+
+ s_ip4 = nm_connection_get_setting_ip4_config (connection);
+ g_assert (nm_setting_ip_config_get_num_addresses (s_ip4) == 1);
+ g_assert_cmpstr (nm_setting_ip_config_get_method (s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_AUTO);
+
+ s_ip6 = nm_connection_get_setting_ip6_config (connection);
+ g_assert (nm_setting_ip_config_get_num_addresses (s_ip6) == 0);
+ g_assert_cmpstr (nm_setting_ip_config_get_method (s_ip6), ==, NM_SETTING_IP6_CONFIG_METHOD_IGNORE);
+ g_object_unref (connection);
+}
+
+NMTST_DEFINE ();
+
+int main (int argc, char **argv)
+{
+ nmtst_init_assert_logging (&argc, &argv, "INFO", "DEFAULT");
+
+ g_test_add_func ("/initrd/ibft", test_read_ibft);
+ g_test_add_func ("/initrd/ibft/dhcp", test_read_ibft_dhcp);
+ g_test_add_func ("/initrd/ibft/static", test_read_ibft_static);
+ g_test_add_func ("/initrd/ibft/vlan", test_read_ibft_vlan);
+ g_test_add_data_func ("/initrd/ibft/bad-ipaddr-read", TEST_INITRD_DIR "/sysfs-bad-ipaddr", test_read_ibft_bad_address);
+ g_test_add_data_func ("/initrd/ibft/bad-gateway-read", TEST_INITRD_DIR "/sysfs-bad-gateway", test_read_ibft_bad_address);
+ g_test_add_data_func ("/initrd/ibft/bad-dns1-read", TEST_INITRD_DIR "/sysfs-bad-dns1", test_read_ibft_bad_address);
+ g_test_add_data_func ("/initrd/ibft/bad-dns2-read", TEST_INITRD_DIR "/sysfs-bad-dns2", test_read_ibft_bad_address);
+
+ return g_test_run ();
+}
diff --git a/src/main.c b/src/main.c
index a5bfb6af1f..f834fa94fe 100644
--- a/src/main.c
+++ b/src/main.c
@@ -397,8 +397,13 @@ main (int argc, char *argv[])
NM_CONFIG_KEYFILE_KEY_MAIN_AUTH_POLKIT,
NM_CONFIG_DEFAULT_MAIN_AUTH_POLKIT_BOOL));
- if (!nm_dbus_manager_acquire_bus (nm_dbus_manager_get ()))
- goto done_no_manager;
+ if (!nm_config_get_configure_and_quit (config)) {
+ /* D-Bus is useless in configure and quit mode -- we're eventually dropping
+ * off and potential clients would have no way of knowing whether we're
+ * finished already or didn't start yet. */
+ if (!nm_dbus_manager_acquire_bus (nm_dbus_manager_get ()))
+ goto done_no_manager;
+ }
manager = nm_manager_setup ();
nm_dbus_manager_start (nm_dbus_manager_get(),
diff --git a/src/nm-config.c b/src/nm-config.c
index fb4e6a66b5..0be5b15fbd 100644
--- a/src/nm-config.c
+++ b/src/nm-config.c
@@ -51,7 +51,8 @@ struct NMConfigCmdLineOptions {
char *state_file;
char *no_auto_default_file;
char *plugins;
- gboolean configure_and_quit;
+ NMConfigConfigureAndQuitType configure_and_quit;
+
gboolean is_debug;
char *connectivity_uri;
@@ -105,7 +106,7 @@ typedef struct {
char *log_level;
char *log_domains;
- gboolean configure_and_quit;
+ NMConfigConfigureAndQuitType configure_and_quit;
char **atomic_section_prefixes;
@@ -323,7 +324,7 @@ nm_config_get_log_domains (NMConfig *config)
return NM_CONFIG_GET_PRIVATE (config)->log_domains;
}
-gboolean
+NMConfigConfigureAndQuitType
nm_config_get_configure_and_quit (NMConfig *config)
{
return NM_CONFIG_GET_PRIVATE (config)->configure_and_quit;
@@ -392,9 +393,16 @@ no_auto_default_to_file (const char *no_auto_default_file, const char *const*no_
gboolean
nm_config_get_no_auto_default_for_device (NMConfig *self, NMDevice *device)
{
+ NMConfigPrivate *priv;
+
g_return_val_if_fail (NM_IS_CONFIG (self), FALSE);
- return nm_config_data_get_no_auto_default_for_device (NM_CONFIG_GET_PRIVATE (self)->config_data, device);
+ priv = NM_CONFIG_GET_PRIVATE (self);
+
+ if (priv->configure_and_quit == NM_CONFIG_CONFIGURE_AND_QUIT_INITRD)
+ return TRUE;
+
+ return nm_config_data_get_no_auto_default_for_device (priv->config_data, device);
}
void
@@ -457,7 +465,7 @@ _nm_config_cmd_line_options_clear (NMConfigCmdLineOptions *cli)
g_clear_pointer (&cli->intern_config_file, g_free);
g_clear_pointer (&cli->state_file, g_free);
g_clear_pointer (&cli->plugins, g_free);
- cli->configure_and_quit = FALSE;
+ cli->configure_and_quit = NM_CONFIG_CONFIGURE_AND_QUIT_DISABLED;
cli->is_debug = FALSE;
g_clear_pointer (&cli->connectivity_uri, g_free);
g_clear_pointer (&cli->connectivity_response, g_free);
@@ -509,34 +517,72 @@ nm_config_cmd_line_options_free (NMConfigCmdLineOptions *cli)
g_free (cli);
}
+static NMConfigConfigureAndQuitType
+string_to_configure_and_quit (const char *value, GError **error)
+{
+ NMConfigConfigureAndQuitType ret;
+
+ if (value == NULL)
+ return NM_CONFIG_CONFIGURE_AND_QUIT_DISABLED;
+
+ if (strcmp (value, "initrd") == 0)
+ return NM_CONFIG_CONFIGURE_AND_QUIT_INITRD;
+
+ ret = nm_config_parse_boolean (value, NM_CONFIG_CONFIGURE_AND_QUIT_INVALID);
+ if (ret == NM_CONFIG_CONFIGURE_AND_QUIT_INVALID)
+ g_set_error (error, 1, 0, N_("'%s' is not valid"), value);
+
+ return ret;
+}
+
+static gboolean
+parse_configure_and_quit (const char *option_name, const char *value, gpointer user_data, GError **error)
+{
+ NMConfigCmdLineOptions *cli = user_data;
+
+ if (value == NULL)
+ cli->configure_and_quit = NM_CONFIG_CONFIGURE_AND_QUIT_ENABLED;
+ else
+ cli->configure_and_quit = string_to_configure_and_quit (value, error);
+
+ if (cli->configure_and_quit == NM_CONFIG_CONFIGURE_AND_QUIT_INVALID) {
+ g_prefix_error (error, N_("Bad '%s' option: "), option_name);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
void
nm_config_cmd_line_options_add_to_entries (NMConfigCmdLineOptions *cli,
GOptionContext *opt_ctx)
{
+ GOptionGroup *group;
+ GOptionEntry config_options[] = {
+ { "config", 0, 0, G_OPTION_ARG_FILENAME, &cli->config_main_file, N_("Config file location"), DEFAULT_CONFIG_MAIN_FILE },
+ { "config-dir", 0, 0, G_OPTION_ARG_FILENAME, &cli->config_dir, N_("Config directory location"), DEFAULT_CONFIG_DIR },
+ { "system-config-dir", 0, 0, G_OPTION_ARG_FILENAME, &cli->system_config_dir, N_("System config directory location"), DEFAULT_SYSTEM_CONFIG_DIR },
+ { "intern-config", 0, 0, G_OPTION_ARG_FILENAME, &cli->intern_config_file, N_("Internal config file location"), DEFAULT_INTERN_CONFIG_FILE },
+ { "state-file", 0, 0, G_OPTION_ARG_FILENAME, &cli->state_file, N_("State file location"), DEFAULT_STATE_FILE },
+ { "no-auto-default", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_FILENAME, &cli->no_auto_default_file, N_("State file for no-auto-default devices"), DEFAULT_NO_AUTO_DEFAULT_FILE },
+ { "plugins", 0, 0, G_OPTION_ARG_STRING, &cli->plugins, N_("List of plugins separated by ','"), NM_CONFIG_DEFAULT_MAIN_PLUGINS },
+ { "configure-and-quit", 0, G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_CALLBACK, parse_configure_and_quit, N_("Quit after initial configuration"), NULL },
+ { "debug", 'd', 0, G_OPTION_ARG_NONE, &cli->is_debug, N_("Don't become a daemon, and log to stderr"), NULL },
+
+ /* These three are hidden for now, and should eventually just go away. */
+ { "connectivity-uri", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_STRING, &cli->connectivity_uri, N_("An http(s) address for checking internet connectivity"), "http://example.com" },
+ { "connectivity-interval", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_INT, &cli->connectivity_interval, N_("The interval between connectivity checks (in seconds)"), G_STRINGIFY (NM_CONFIG_DEFAULT_CONNECTIVITY_INTERVAL) },
+ { "connectivity-response", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_STRING, &cli->connectivity_response, N_("The expected start of the response"), NM_CONFIG_DEFAULT_CONNECTIVITY_RESPONSE },
+ { 0 },
+ };
+
g_return_if_fail (opt_ctx);
g_return_if_fail (cli);
- {
- GOptionEntry config_options[] = {
- { "config", 0, 0, G_OPTION_ARG_FILENAME, &cli->config_main_file, N_("Config file location"), DEFAULT_CONFIG_MAIN_FILE },
- { "config-dir", 0, 0, G_OPTION_ARG_FILENAME, &cli->config_dir, N_("Config directory location"), DEFAULT_CONFIG_DIR },
- { "system-config-dir", 0, 0, G_OPTION_ARG_FILENAME, &cli->system_config_dir, N_("System config directory location"), DEFAULT_SYSTEM_CONFIG_DIR },
- { "intern-config", 0, 0, G_OPTION_ARG_FILENAME, &cli->intern_config_file, N_("Internal config file location"), DEFAULT_INTERN_CONFIG_FILE },
- { "state-file", 0, 0, G_OPTION_ARG_FILENAME, &cli->state_file, N_("State file location"), DEFAULT_STATE_FILE },
- { "no-auto-default", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_FILENAME, &cli->no_auto_default_file, N_("State file for no-auto-default devices"), DEFAULT_NO_AUTO_DEFAULT_FILE },
- { "plugins", 0, 0, G_OPTION_ARG_STRING, &cli->plugins, N_("List of plugins separated by ','"), NM_CONFIG_DEFAULT_MAIN_PLUGINS },
- { "configure-and-quit", 0, 0, G_OPTION_ARG_NONE, &cli->configure_and_quit, N_("Quit after initial configuration"), NULL },
- { "debug", 'd', 0, G_OPTION_ARG_NONE, &cli->is_debug, N_("Don't become a daemon, and log to stderr"), NULL },
+ group = g_option_group_new ("nm", N_("NetworkManager options" ), N_("Show NetworkManager options"), cli, NULL);
- /* These three are hidden for now, and should eventually just go away. */
- { "connectivity-uri", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_STRING, &cli->connectivity_uri, N_("An http(s) address for checking internet connectivity"), "http://example.com" },
- { "connectivity-interval", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_INT, &cli->connectivity_interval, N_("The interval between connectivity checks (in seconds)"), G_STRINGIFY (NM_CONFIG_DEFAULT_CONNECTIVITY_INTERVAL) },
- { "connectivity-response", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_STRING, &cli->connectivity_response, N_("The expected start of the response"), NM_CONFIG_DEFAULT_CONNECTIVITY_RESPONSE },
- { 0 },
- };
-
- g_option_context_add_main_entries (opt_ctx, config_options, NULL);
- }
+ g_option_group_add_entries (group, config_options);
+ g_option_context_add_group (opt_ctx, group);
}
/*****************************************************************************/
@@ -1046,19 +1092,36 @@ read_entire_config (const NMConfigCmdLineOptions *cli,
/* Merge settings from command line. They overwrite everything read from
* config files. */
- if (cli && cli->plugins) {
- /* plugins is a string list. Set the value directly, so the user has to do proper escaping
- * on the command line. */
- g_key_file_set_value (keyfile, NM_CONFIG_KEYFILE_GROUP_MAIN, "plugins", cli->plugins);
+
+ if (cli) {
+ if (cli->plugins) {
+ /* plugins is a string list. Set the value directly, so the user has to do proper escaping
+ * on the command line. */
+ g_key_file_set_value (keyfile, NM_CONFIG_KEYFILE_GROUP_MAIN, "plugins", cli->plugins);
+ }
+
+ switch (cli->configure_and_quit) {
+ case NM_CONFIG_CONFIGURE_AND_QUIT_INVALID:
+ g_assert_not_reached ();
+ break;
+ case NM_CONFIG_CONFIGURE_AND_QUIT_DISABLED:
+ /* do nothing */
+ break;
+ case NM_CONFIG_CONFIGURE_AND_QUIT_ENABLED:
+ g_key_file_set_boolean (keyfile, NM_CONFIG_KEYFILE_GROUP_MAIN, "configure-and-quit", TRUE);
+ break;
+ case NM_CONFIG_CONFIGURE_AND_QUIT_INITRD:
+ g_key_file_set_string (keyfile, NM_CONFIG_KEYFILE_GROUP_MAIN, "configure-and-quit", "initrd");
+ break;
+ }
+
+ if (cli->connectivity_uri && cli->connectivity_uri[0])
+ g_key_file_set_string (keyfile, NM_CONFIG_KEYFILE_GROUP_CONNECTIVITY, "uri", cli->connectivity_uri);
+ if (cli->connectivity_interval >= 0)
+ g_key_file_set_integer (keyfile, NM_CONFIG_KEYFILE_GROUP_CONNECTIVITY, "interval", cli->connectivity_interval);
+ if (cli->connectivity_response && cli->connectivity_response[0])
+ g_key_file_set_string (keyfile, NM_CONFIG_KEYFILE_GROUP_CONNECTIVITY, "response", cli->connectivity_response);
}
- if (cli && cli->configure_and_quit)
- g_key_file_set_boolean (keyfile, NM_CONFIG_KEYFILE_GROUP_MAIN, "configure-and-quit", TRUE);
- if (cli && cli->connectivity_uri && cli->connectivity_uri[0])
- g_key_file_set_string (keyfile, NM_CONFIG_KEYFILE_GROUP_CONNECTIVITY, "uri", cli->connectivity_uri);
- if (cli && cli->connectivity_interval >= 0)
- g_key_file_set_integer (keyfile, NM_CONFIG_KEYFILE_GROUP_CONNECTIVITY, "interval", cli->connectivity_interval);
- if (cli && cli->connectivity_response && cli->connectivity_response[0])
- g_key_file_set_string (keyfile, NM_CONFIG_KEYFILE_GROUP_CONNECTIVITY, "response", cli->connectivity_response);
if (out_config_description) {
GString *str;
@@ -1837,6 +1900,9 @@ state_write (NMConfig *self)
GString *str;
GError *error = NULL;
+ if (priv->configure_and_quit != NM_CONFIG_CONFIGURE_AND_QUIT_DISABLED)
+ return;
+
filename = state_get_filename (&priv->cli);
if (!filename) {
@@ -1931,6 +1997,7 @@ _nm_config_state_set (NMConfig *self,
#define DEVICE_RUN_STATE_KEYFILE_KEY_DEVICE_NM_OWNED "nm-owned"
#define DEVICE_RUN_STATE_KEYFILE_KEY_DEVICE_ROUTE_METRIC_DEFAULT_ASPIRED "route-metric-default-aspired"
#define DEVICE_RUN_STATE_KEYFILE_KEY_DEVICE_ROUTE_METRIC_DEFAULT_EFFECTIVE "route-metric-default-effective"
+#define DEVICE_RUN_STATE_KEYFILE_KEY_DEVICE_ROOT_PATH "root-path"
NM_UTILS_LOOKUP_STR_DEFINE_STATIC (_device_state_managed_type_to_str, NMConfigDeviceStateManagedType,
NM_UTILS_LOOKUP_DEFAULT_NM_ASSERT ("unknown"),
@@ -2128,7 +2195,8 @@ nm_config_device_state_write (int ifindex,
const char *connection_uuid,
int nm_owned,
guint32 route_metric_default_aspired,
- guint32 route_metric_default_effective)
+ guint32 route_metric_default_effective,
+ const char *root_path)
{
char path[NM_STRLEN (NM_CONFIG_DEVICE_STATE_DIR) + 60];
GError *local = NULL;
@@ -2182,19 +2250,26 @@ nm_config_device_state_write (int ifindex,
route_metric_default_aspired);
}
}
+ if (root_path) {
+ g_key_file_set_string (kf,
+ DEVICE_RUN_STATE_KEYFILE_GROUP_DEVICE,
+ DEVICE_RUN_STATE_KEYFILE_KEY_DEVICE_ROOT_PATH,
+ root_path);
+ }
if (!g_key_file_save_to_file (kf, path, &local)) {
_LOGW ("device-state: write #%d (%s) failed: %s", ifindex, path, local->message);
g_error_free (local);
return FALSE;
}
- _LOGT ("device-state: write #%d (%s); managed=%s%s%s%s%s%s%s, route-metric-default=%"G_GUINT32_FORMAT"-%"G_GUINT32_FORMAT"",
+ _LOGT ("device-state: write #%d (%s); managed=%s%s%s%s%s%s%s, route-metric-default=%"G_GUINT32_FORMAT"-%"G_GUINT32_FORMAT"%s%s%s",
ifindex, path,
_device_state_managed_type_to_str (managed),
NM_PRINT_FMT_QUOTED (connection_uuid, ", connection-uuid=", connection_uuid, "", ""),
NM_PRINT_FMT_QUOTED (perm_hw_addr_fake, ", perm-hw-addr-fake=", perm_hw_addr_fake, "", ""),
route_metric_default_aspired,
- route_metric_default_effective);
+ route_metric_default_effective,
+ NM_PRINT_FMT_QUOTED (root_path, ", root-path=", root_path, "", ""));
return TRUE;
}
@@ -2332,7 +2407,11 @@ nm_config_reload (NMConfig *self, NMConfigChangeFlags reload_flags)
(const char *const*) priv->atomic_section_prefixes, NULL);
}
- new_data = nm_config_data_new (config_main_file, config_description, (const char *const*) no_auto_default, keyfile, keyfile_intern);
+ new_data = nm_config_data_new (config_main_file,
+ config_description,
+ (const char *const*) no_auto_default,
+ keyfile,
+ keyfile_intern);
g_free (config_main_file);
g_free (config_description);
g_key_file_unref (keyfile);
@@ -2482,6 +2561,7 @@ init_sync (GInitable *initable, GCancellable *cancellable, GError **error)
char *config_main_file = NULL;
char *config_description = NULL;
gs_strfreev char **no_auto_default = NULL;
+ gs_free char *configure_and_quit = NULL;
gboolean intern_config_needs_rewrite;
const char *s;
@@ -2528,7 +2608,10 @@ init_sync (GInitable *initable, GCancellable *cancellable, GError **error)
priv->log_level = nm_strstrip (g_key_file_get_string (keyfile, NM_CONFIG_KEYFILE_GROUP_LOGGING, "level", NULL));
priv->log_domains = nm_strstrip (g_key_file_get_string (keyfile, NM_CONFIG_KEYFILE_GROUP_LOGGING, "domains", NULL));
- priv->configure_and_quit = nm_config_keyfile_get_boolean (keyfile, NM_CONFIG_KEYFILE_GROUP_MAIN, "configure-and-quit", FALSE);
+ configure_and_quit = nm_strstrip (g_key_file_get_string (keyfile, NM_CONFIG_KEYFILE_GROUP_MAIN, "configure-and-quit", NULL));
+ priv->configure_and_quit = string_to_configure_and_quit (configure_and_quit, error);
+ if (priv->configure_and_quit == NM_CONFIG_CONFIGURE_AND_QUIT_INVALID)
+ return FALSE;
no_auto_default = no_auto_default_from_file (priv->no_auto_default_file);
@@ -2536,12 +2619,17 @@ init_sync (GInitable *initable, GCancellable *cancellable, GError **error)
keyfile,
(const char *const*) priv->atomic_section_prefixes,
&intern_config_needs_rewrite);
- if (intern_config_needs_rewrite) {
+ if ( intern_config_needs_rewrite
+ && priv->configure_and_quit == NM_CONFIG_CONFIGURE_AND_QUIT_DISABLED) {
intern_config_write (priv->intern_config_file, keyfile_intern, keyfile,
(const char *const*) priv->atomic_section_prefixes, NULL);
}
- priv->config_data_orig = nm_config_data_new (config_main_file, config_description, (const char *const*) no_auto_default, keyfile, keyfile_intern);
+ priv->config_data_orig = nm_config_data_new (config_main_file,
+ config_description,
+ (const char *const*) no_auto_default,
+ keyfile,
+ keyfile_intern);
priv->config_data = g_object_ref (priv->config_data_orig);
diff --git a/src/nm-config.h b/src/nm-config.h
index 1b013ff398..c65572ce3f 100644
--- a/src/nm-config.h
+++ b/src/nm-config.h
@@ -101,6 +101,13 @@ typedef enum {
NM_CONFIG_STATE_PROPERTY_WWAN_ENABLED,
} NMConfigRunStatePropertyType;
+typedef enum {
+ NM_CONFIG_CONFIGURE_AND_QUIT_INVALID = -1,
+ NM_CONFIG_CONFIGURE_AND_QUIT_DISABLED = FALSE,
+ NM_CONFIG_CONFIGURE_AND_QUIT_ENABLED = TRUE,
+ NM_CONFIG_CONFIGURE_AND_QUIT_INITRD,
+} NMConfigConfigureAndQuitType;
+
typedef struct {
bool net_enabled;
bool wifi_enabled;
@@ -127,7 +134,7 @@ NMConfigData *nm_config_get_data_orig (NMConfig *config);
gboolean nm_config_get_monitor_connection_files (NMConfig *config);
const char *nm_config_get_log_level (NMConfig *config);
const char *nm_config_get_log_domains (NMConfig *config);
-gboolean nm_config_get_configure_and_quit (NMConfig *config);
+NMConfigConfigureAndQuitType nm_config_get_configure_and_quit (NMConfig *config);
gboolean nm_config_get_is_debug (NMConfig *config);
gboolean nm_config_get_first_start (NMConfig *config);
@@ -236,7 +243,8 @@ gboolean nm_config_device_state_write (int ifindex,
const char *connection_uuid,
int nm_owned,
guint32 route_metric_default_aspired,
- guint32 route_metric_default_effective);
+ guint32 route_metric_default_effective,
+ const char *root_path);
void nm_config_device_state_prune_unseen (GHashTable *seen_ifindexes);
diff --git a/src/nm-dbus-manager.c b/src/nm-dbus-manager.c
index c74b57a484..17fc24af84 100644
--- a/src/nm-dbus-manager.c
+++ b/src/nm-dbus-manager.c
@@ -1480,7 +1480,11 @@ nm_dbus_manager_start (NMDBusManager *self,
g_return_if_fail (NM_IS_DBUS_MANAGER (self));
priv = NM_DBUS_MANAGER_GET_PRIVATE (self);
- g_return_if_fail (priv->connection);
+
+ if (!priv->connection) {
+ /* Do nothing. We're presumably in the configure-and-quit mode. */
+ return;
+ }
priv->set_property_handler = set_property_handler;
priv->set_property_handler_data = set_property_handler_data;
@@ -1505,29 +1509,17 @@ nm_dbus_manager_acquire_bus (NMDBusManager *self)
priv = NM_DBUS_MANAGER_GET_PRIVATE (self);
- /* we will create the D-Bus connection and registering the name synchronously.
- * The reason why that is necessary is because:
- * (1) if we are unable to create a D-Bus connection, it means D-Bus is not
- * available and we run in D-Bus less mode. We do not support creating
- * a D-Bus connection later on. This disconnected mode is useful for initrd
- * (well, currently not yet, but will be).
- * (2) if we are able to create the connection and register the name,
- * all is good and we run with D-Bus. Note that D-Bus disconnects
- * from D-Bus are ignored. Essentially, we do not support restarting
- * D-Bus.
- * (3) if we are able to create the connection but registration fails,
- * it means that something is borked. Quite possibly another NetworkManager
- * instance is running. We need to exit right away.
- * To appease (1) and (3), we cannot initialize synchronously, because we need
- * to know right away whether another NetworkManager instance is running (3).
- **/
-
+ /* Create the D-Bus connection and registering the name synchronously.
+ * That is necessary because we need to exit right away if we can't
+ * acquire the name despite connecting to the bus successfully.
+ * It means that something is gravely broken -- such as another NetworkManager
+ * instance running. */
connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM,
NULL,
&error);
if (!connection) {
- _LOGI ("cannot connect to D-Bus and proceed without (%s)", error->message);
- return TRUE;
+ _LOGI ("cannot connect to D-Bus: %s", error->message);
+ return FALSE;
}
g_dbus_connection_set_exit_on_close (connection, FALSE);
diff --git a/src/nm-iface-helper.c b/src/nm-iface-helper.c
index 805c6e4fd2..6ae2b9d2f7 100644
--- a/src/nm-iface-helper.c
+++ b/src/nm-iface-helper.c
@@ -627,10 +627,10 @@ nm_config_data_get_value (const NMConfigData *config_data, const char *group, co
return NULL;
}
-gboolean
+NMConfigConfigureAndQuitType
nm_config_get_configure_and_quit (NMConfig *config)
{
- return TRUE;
+ return NM_CONFIG_CONFIGURE_AND_QUIT_ENABLED;
}
NMDBusManager *
diff --git a/src/nm-manager.c b/src/nm-manager.c
index 4f55276b3e..160ec92b14 100644
--- a/src/nm-manager.c
+++ b/src/nm-manager.c
@@ -1632,7 +1632,7 @@ remove_device (NMManager *self,
nm_device_sys_iface_state_set (device, NM_DEVICE_SYS_IFACE_STATE_REMOVED);
nm_device_set_unmanaged_by_flags (device, NM_UNMANAGED_PLATFORM_INIT, TRUE, NM_DEVICE_STATE_REASON_REMOVED);
}
- } else if (quitting && nm_config_get_configure_and_quit (priv->config)) {
+ } else if (quitting && nm_config_get_configure_and_quit (priv->config) == NM_CONFIG_CONFIGURE_AND_QUIT_ENABLED) {
nm_device_spawn_iface_helper (device);
}
}
@@ -6101,6 +6101,8 @@ nm_manager_write_device_state (NMManager *self, NMDevice *device)
guint32 route_metric_default_aspired;
guint32 route_metric_default_effective;
int nm_owned;
+ NMDhcp4Config *dhcp4_config;
+ const char *root_path = NULL;
ifindex = nm_device_get_ip_ifindex (device);
if (ifindex <= 0)
@@ -6117,7 +6119,8 @@ nm_manager_write_device_state (NMManager *self, NMDevice *device)
if (managed) {
NMSettingsConnection *sett_conn;
- sett_conn = nm_device_get_settings_connection (device);
+ if (nm_device_get_state (device) <= NM_DEVICE_STATE_ACTIVATED)
+ sett_conn = nm_device_get_settings_connection (device);
if (sett_conn)
uuid = nm_settings_connection_get_uuid (sett_conn);
managed_type = NM_CONFIG_DEVICE_STATE_MANAGED_TYPE_MANAGED;
@@ -6135,13 +6138,18 @@ nm_manager_write_device_state (NMManager *self, NMDevice *device)
route_metric_default_effective = _device_route_metric_get (self, ifindex, NM_DEVICE_TYPE_UNKNOWN,
TRUE, &route_metric_default_aspired);
+ dhcp4_config = nm_device_get_dhcp4_config (device);
+ if (dhcp4_config)
+ root_path = nm_dhcp4_config_get_option (dhcp4_config, "root_path");
+
return nm_config_device_state_write (ifindex,
managed_type,
perm_hw_addr_fake,
uuid,
nm_owned,
route_metric_default_aspired,
- route_metric_default_effective);
+ route_metric_default_effective,
+ root_path);
}
void
diff --git a/src/settings/nm-settings-connection.c b/src/settings/nm-settings-connection.c
index 248bf811f7..912949a28a 100644
--- a/src/settings/nm-settings-connection.c
+++ b/src/settings/nm-settings-connection.c
@@ -2510,6 +2510,8 @@ nm_settings_connection_update_timestamp (NMSettingsConnection *self,
if (flush_to_disk == FALSE)
return;
+ if (nm_config_get_configure_and_quit (nm_config_get ()) == NM_CONFIG_CONFIGURE_AND_QUIT_INITRD)
+ return;
/* Save timestamp to timestamps database file */
timestamps_file = g_key_file_new ();
diff --git a/src/settings/plugins/keyfile/nms-keyfile-connection.c b/src/settings/plugins/keyfile/nms-keyfile-connection.c
index 64e94b2654..12467b2e20 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),
diff --git a/src/settings/plugins/keyfile/nms-keyfile-plugin.c b/src/settings/plugins/keyfile/nms-keyfile-plugin.c
index 7d307c52f3..3bb872ca27 100644
--- a/src/settings/plugins/keyfile/nms-keyfile-plugin.c
+++ b/src/settings/plugins/keyfile/nms-keyfile-plugin.c
@@ -171,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);
@@ -178,6 +179,22 @@ update_connection (NMSKeyfilePlugin *self,
if (full_path)
_LOGD ("loading from file \"%s\"...", full_path);
+ 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, &local);
if (!connection_new) {
/* Error; remove the connection */
@@ -410,14 +427,34 @@ _sort_paths (const char **f1, const char **f2, GHashTable *paths)
return strcmp (*f1, *f2);
}
+static void
+_read_dir (GPtrArray *filenames, const char *path)
+{
+ 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))
+ 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;
@@ -426,25 +463,13 @@ 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);
+
+ _read_dir (filenames, NM_CONFIG_KEYFILE_PATH_IN_MEMORY);
+ _read_dir (filenames, nms_keyfile_utils_get_path ());
alive_connections = g_hash_table_new (nm_direct_hash, NULL);
- 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);
-
/* While reloading, we don't replace connections that we already loaded while
* iterating over the files.
*
@@ -501,14 +526,8 @@ load_connection (NMSettingsPlugin *config,
{
NMSKeyfilePlugin *self = NMS_KEYFILE_PLUGIN ((NMSKeyfilePlugin *) config);
NMSKeyfileConnection *connection;
- int dir_len = strlen (nms_keyfile_utils_get_path ());
- if ( strncmp (filename, nms_keyfile_utils_get_path (), dir_len) != 0
- || filename[dir_len] != '/'
- || strchr (filename + dir_len + 1, '/') != NULL)
- return FALSE;
-
- if (nms_keyfile_utils_should_ignore_file (filename + dir_len + 1))
+ if (nms_keyfile_utils_should_ignore_file (filename))
return FALSE;
connection = update_connection (self, NULL, filename, find_by_path (self, filename), TRUE, NULL, NULL);
@@ -532,16 +551,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));
}
diff --git a/src/settings/plugins/keyfile/nms-keyfile-utils.h b/src/settings/plugins/keyfile/nms-keyfile-utils.h
index d5ddb8d536..ec3bd4414a 100644
--- a/src/settings/plugins/keyfile/nms-keyfile-utils.h
+++ b/src/settings/plugins/keyfile/nms-keyfile-utils.h
@@ -23,6 +23,8 @@
#include "NetworkManagerUtils.h"
+#define NM_CONFIG_KEYFILE_PATH_IN_MEMORY NMRUNDIR "/system-connections"
+
#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_settings_connection_get_uuid ((NMSettingsConnection *) (con)), nm_settings_connection_get_id ((NMSettingsConnection *) (con))
diff --git a/src/settings/plugins/keyfile/nms-keyfile-writer.c b/src/settings/plugins/keyfile/nms-keyfile-writer.c
index 194b97d4fd..569be76731 100644
--- a/src/settings/plugins/keyfile/nms-keyfile-writer.c
+++ b/src/settings/plugins/keyfile/nms-keyfile-writer.c
@@ -189,10 +189,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 ();
@@ -221,7 +225,7 @@ _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);
@@ -337,6 +341,7 @@ _internal_write_connection (NMConnection *connection,
gboolean
nms_keyfile_writer_connection (NMConnection *connection,
+ gboolean save_to_disk,
const char *existing_path,
gboolean force_rename,
char **out_path,
@@ -344,8 +349,15 @@ 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,
- nms_keyfile_utils_get_path (),
+ keyfile_dir,
0, 0,
existing_path,
force_rename,
diff --git a/src/settings/plugins/keyfile/nms-keyfile-writer.h b/src/settings/plugins/keyfile/nms-keyfile-writer.h
index ac41dfa2f1..030fb7cc34 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,