summaryrefslogtreecommitdiffstats
path: root/src/network/generator/main.c
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-10 20:49:52 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-10 20:49:52 +0000
commit55944e5e40b1be2afc4855d8d2baf4b73d1876b5 (patch)
tree33f869f55a1b149e9b7c2b7e201867ca5dd52992 /src/network/generator/main.c
parentInitial commit. (diff)
downloadsystemd-55944e5e40b1be2afc4855d8d2baf4b73d1876b5.tar.xz
systemd-55944e5e40b1be2afc4855d8d2baf4b73d1876b5.zip
Adding upstream version 255.4.upstream/255.4
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/network/generator/main.c')
-rw-r--r--src/network/generator/main.c218
1 files changed, 218 insertions, 0 deletions
diff --git a/src/network/generator/main.c b/src/network/generator/main.c
new file mode 100644
index 0000000..0439a9d
--- /dev/null
+++ b/src/network/generator/main.c
@@ -0,0 +1,218 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#include <getopt.h>
+
+#include "build.h"
+#include "fd-util.h"
+#include "fs-util.h"
+#include "generator.h"
+#include "macro.h"
+#include "main-func.h"
+#include "mkdir.h"
+#include "network-generator.h"
+#include "path-util.h"
+#include "proc-cmdline.h"
+
+#define NETWORKD_UNIT_DIRECTORY "/run/systemd/network"
+
+static const char *arg_root = NULL;
+
+static int network_save(Network *network, const char *dest_dir) {
+ _cleanup_(unlink_and_freep) char *temp_path = NULL;
+ _cleanup_fclose_ FILE *f = NULL;
+ _cleanup_free_ char *p = NULL;
+ int r;
+
+ assert(network);
+
+ r = generator_open_unit_file_full(dest_dir, NULL, NULL, &f, &temp_path);
+ if (r < 0)
+ return r;
+
+ network_dump(network, f);
+
+ if (asprintf(&p, "%s/%s-%s.network",
+ dest_dir,
+ isempty(network->ifname) ? "71" : "70",
+ isempty(network->ifname) ? "default" : network->ifname) < 0)
+ return log_oom();
+
+ r = conservative_rename(temp_path, p);
+ if (r < 0)
+ return r;
+
+ temp_path = mfree(temp_path);
+ return 0;
+}
+
+static int netdev_save(NetDev *netdev, const char *dest_dir) {
+ _cleanup_(unlink_and_freep) char *temp_path = NULL;
+ _cleanup_fclose_ FILE *f = NULL;
+ _cleanup_free_ char *p = NULL;
+ int r;
+
+ assert(netdev);
+
+ r = generator_open_unit_file_full(dest_dir, NULL, NULL, &f, &temp_path);
+ if (r < 0)
+ return r;
+
+ netdev_dump(netdev, f);
+
+ if (asprintf(&p, "%s/70-%s.netdev", dest_dir, netdev->ifname) < 0)
+ return log_oom();
+
+ r = conservative_rename(temp_path, p);
+ if (r < 0)
+ return r;
+
+ temp_path = mfree(temp_path);
+ return 0;
+}
+
+static int link_save(Link *link, const char *dest_dir) {
+ _cleanup_(unlink_and_freep) char *temp_path = NULL;
+ _cleanup_fclose_ FILE *f = NULL;
+ _cleanup_free_ char *p = NULL;
+ int r;
+
+ assert(link);
+
+ r = generator_open_unit_file_full(dest_dir, NULL, NULL, &f, &temp_path);
+ if (r < 0)
+ return r;
+
+ link_dump(link, f);
+
+ if (asprintf(&p, "%s/%s-%s.link",
+ dest_dir,
+ !isempty(link->ifname) ? "70" : !hw_addr_is_null(&link->mac) ? "71" : "72",
+ link->filename) < 0)
+ return log_oom();
+
+ r = conservative_rename(temp_path, p);
+ if (r < 0)
+ return r;
+
+ temp_path = mfree(temp_path);
+ return 0;
+}
+
+static int context_save(Context *context) {
+ Network *network;
+ NetDev *netdev;
+ Link *link;
+ int r;
+
+ const char *p = prefix_roota(arg_root, NETWORKD_UNIT_DIRECTORY);
+
+ r = mkdir_p(p, 0755);
+ if (r < 0)
+ return log_error_errno(r, "Failed to create directory " NETWORKD_UNIT_DIRECTORY ": %m");
+
+ HASHMAP_FOREACH(network, context->networks_by_name)
+ RET_GATHER(r, network_save(network, p));
+
+ HASHMAP_FOREACH(netdev, context->netdevs_by_name)
+ RET_GATHER(r, netdev_save(netdev, p));
+
+ HASHMAP_FOREACH(link, context->links_by_filename)
+ RET_GATHER(r, link_save(link, p));
+
+ return r;
+}
+
+static int help(void) {
+ printf("%s [OPTIONS...] [-- KERNEL_CMDLINE]\n"
+ " -h --help Show this help\n"
+ " --version Show package version\n"
+ " --root=PATH Operate on an alternate filesystem root\n",
+ program_invocation_short_name);
+
+ return 0;
+}
+
+static int parse_argv(int argc, char *argv[]) {
+ enum {
+ ARG_VERSION = 0x100,
+ ARG_ROOT,
+ };
+ static const struct option options[] = {
+ { "help", no_argument, NULL, 'h' },
+ { "version", no_argument, NULL, ARG_VERSION },
+ { "root", required_argument, NULL, ARG_ROOT },
+ {},
+ };
+ int c;
+
+ assert(argc >= 0);
+ assert(argv);
+
+ while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
+
+ switch (c) {
+
+ case 'h':
+ return help();
+
+ case ARG_VERSION:
+ return version();
+
+ case ARG_ROOT:
+ arg_root = optarg;
+ break;
+
+ case '?':
+ return -EINVAL;
+
+ default:
+ assert_not_reached();
+ }
+
+ return 1;
+}
+
+static int run(int argc, char *argv[]) {
+ _cleanup_(context_clear) Context context = {};
+ int r;
+
+ log_setup();
+
+ umask(0022);
+
+ r = parse_argv(argc, argv);
+ if (r <= 0)
+ return r;
+
+ if (optind >= argc) {
+ r = proc_cmdline_parse(parse_cmdline_item, &context, 0);
+ if (r < 0)
+ return log_warning_errno(r, "Failed to parse kernel command line: %m");
+ } else {
+ for (int i = optind; i < argc; i++) {
+ _cleanup_free_ char *word = NULL;
+ char *value;
+
+ word = strdup(argv[i]);
+ if (!word)
+ return log_oom();
+
+ value = strchr(word, '=');
+ if (value)
+ *(value++) = 0;
+
+ r = parse_cmdline_item(word, value, &context);
+ if (r < 0)
+ return log_warning_errno(r, "Failed to parse command line \"%s%s%s\": %m",
+ word, value ? "=" : "", strempty(value));
+ }
+ }
+
+ r = context_merge_networks(&context);
+ if (r < 0)
+ return log_warning_errno(r, "Failed to merge multiple command line options: %m");
+
+ return context_save(&context);
+}
+
+DEFINE_MAIN_FUNCTION(run);