From 9f9609555d1c8606b2a177151b2e255b34c5594a Mon Sep 17 00:00:00 2001 From: Lubomir Rintel Date: Sat, 28 Apr 2018 20:36:15 +0200 Subject: [PATCH] initrd: add configuration generator 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. --- .gitignore | 1 + Makefile.am | 20 ++++ contrib/fedora/rpm/NetworkManager.spec | 1 + docs/api/Makefile.am | 1 + docs/api/network-manager-docs.xml | 1 + man/nm-initrd-generator.xml | 140 +++++++++++++++++++++++++ src/initrd/nm-initrd-generator.c | 138 ++++++++++++++++++++++++ 7 files changed, 302 insertions(+) create mode 100644 man/nm-initrd-generator.xml create mode 100644 src/initrd/nm-initrd-generator.c diff --git a/.gitignore b/.gitignore index b9b42fc78a..494ff707ba 100644 --- a/.gitignore +++ b/.gitignore @@ -252,6 +252,7 @@ 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 diff --git a/Makefile.am b/Makefile.am index 830d83d00a..3f81c38925 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1936,6 +1936,24 @@ src_initrd_libnmi_core_la_SOURCES = \ 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 = \ @@ -2166,6 +2184,7 @@ src_initrd_tests_test_cmdline_reader_LDADD = \ $(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) @@ -4861,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/contrib/fedora/rpm/NetworkManager.spec b/contrib/fedora/rpm/NetworkManager.spec index 753ff08fc2..644cd705fa 100644 --- a/contrib/fedora/rpm/NetworkManager.spec +++ b/contrib/fedora/rpm/NetworkManager.spec @@ -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/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/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; +}