From bfd7d79fe11e89fd638a260da1ef1165e58d5ee5 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. (cherry picked from commit 9f9609555d1c8606b2a177151b2e255b34c5594a) --- .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 0d55a7a8e2..1e100f603b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1906,6 +1906,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 = \ @@ -2136,6 +2154,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) @@ -4831,6 +4850,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 f9636b3694..bab7a8b659 100644 --- a/contrib/fedora/rpm/NetworkManager.spec +++ b/contrib/fedora/rpm/NetworkManager.spec @@ -798,6 +798,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 f48e132874..2baf40562f 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 23d67db1e7..5679f4b4dc 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; +}