NetworkManager/src/initrd/nm-initrd-generator.c
Thomas Haller d964decbbd libnm/keyfile: build keyfile code as separate GPL licensed internal library
Keyfile support was initially added under GPL-2.0+ license as part of
core. It was moved to "libnm-core" in commit 59eb5312a5 ('keyfile: merge
branch 'th/libnm-keyfile-bgo744699'').

"libnm-core" is statically linked with by core and "libnm". In
the former case under terms of GPL-2.0+ (good) and in the latter case
under terms of LGPL-2.1+ (bad).

In fact, to this day, "libnm" doesn't actually use the code. The linker
will probably remove all the GPL-2.0+ symbols when compiled with
gc-sections or LTO. Still, linking them together in the first place
makes "libnm" only available under GPL code (despite the code
not actually being used).

Instead, move the GPL code to a separate static library
"shared/nm-keyfile/libnm-keyfile.la" and only link it to the part
that actually uses the code (and which is GPL licensed too).

This fixes the license violation.

Eventually, it would be very useful to be able to expose keyfile
handling via "libnm". However that is not straight forward due to the
licensing conflict.

https://gitlab.freedesktop.org/NetworkManager/NetworkManager/merge_requests/381
2020-01-07 13:17:47 +01:00

125 lines
4 KiB
C

// SPDX-License-Identifier: LGPL-2.1+
/*
* Copyright (C) 2018 Red Hat, Inc.
*/
#include "nm-default.h"
#include "nm-core-utils.h"
#include "nm-core-internal.h"
#include "nm-keyfile/nm-keyfile-internal.h"
#include "nm-initrd-generator.h"
#include "nm-glib-aux/nm-io-utils.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;
gs_unref_keyfile GKeyFile *file = NULL;
gs_free char *data = NULL;
gs_free_error GError *error = NULL;
gsize len;
if (!nm_connection_normalize (connection, NULL, NULL, &error))
goto err_out;
file = nm_keyfile_write (connection, NULL, NULL, &error);
if (file == NULL)
goto err_out;
data = g_key_file_to_data (file, &len, &error);
if (!data)
goto err_out;
if (connections_dir) {
gs_free char *filename = NULL;
gs_free char *full_filename = NULL;
filename = nm_keyfile_utils_create_filename (basename, TRUE);
full_filename = g_build_filename (connections_dir, filename, NULL);
if (!nm_utils_file_set_contents (full_filename,
data,
len,
0600,
NULL,
&error))
goto err_out;
} else
g_print ("\n*** Connection '%s' ***\n\n%s", basename, data);
return;
err_out:
g_print ("%s\n", error->message);
}
#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", NM_KEYFILE_PATH_NAME_RUN },
{ "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;
int errsv;
option_context = g_option_context_new ("-- [ip=...] [rd.route=...] [bridge=...] [bond=...] [team=...] [vlan=...] "
"[bootdev=...] [nameserver=...] [rd.peerdns=...] [rd.bootif=...] [BOOTIF=...] [rd.znet=...] ... ");
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", error->message);
return 1;
}
if (!remaining) {
/* No arguments, no networking. Don't bother. */
return 0;
}
if (!connections_dir)
connections_dir = g_strdup (NM_KEYFILE_PATH_NAME_RUN);
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) {
errsv = errno;
_LOGW (LOGD_CORE, "%s: %s", connections_dir, nm_strerror_native (errsv));
return 1;
}
connections = nmi_cmdline_reader_parse (sysfs_dir, (const char *const*) remaining);
g_hash_table_foreach (connections, output_conn, connections_dir);
g_hash_table_destroy (connections);
return 0;
}