mirror of
https://github.com/systemd/systemd-stable.git
synced 2025-01-11 05:17:44 +03:00
network-generator: introduce new tool systemd-network-generator
The new tool parses dracut's command line options and generates relevant .network, .netdev, and .link files.
This commit is contained in:
parent
e869ba5dcb
commit
426c1d3852
@ -2710,6 +2710,14 @@ if conf.get('ENABLE_NETWORKD') == 1
|
|||||||
install : true,
|
install : true,
|
||||||
install_dir : rootbindir)
|
install_dir : rootbindir)
|
||||||
public_programs += exe
|
public_programs += exe
|
||||||
|
|
||||||
|
executable('systemd-network-generator',
|
||||||
|
network_generator_sources,
|
||||||
|
include_directories : includes,
|
||||||
|
link_with : [libshared],
|
||||||
|
install_rpath : rootlibexecdir,
|
||||||
|
install : true,
|
||||||
|
install_dir : rootlibexecdir)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
executable('systemd-sulogin-shell',
|
executable('systemd-sulogin-shell',
|
||||||
|
206
src/network/generator/main.c
Normal file
206
src/network/generator/main.c
Normal file
@ -0,0 +1,206 @@
|
|||||||
|
/* SPDX-License-Identifier: LGPL-2.1+ */
|
||||||
|
|
||||||
|
#include <getopt.h>
|
||||||
|
|
||||||
|
#include "fd-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_free_ char *filename = NULL;
|
||||||
|
_cleanup_fclose_ FILE *f = NULL;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
assert(network);
|
||||||
|
|
||||||
|
r = asprintf(&filename, "%s-initrd-%s.network",
|
||||||
|
isempty(network->ifname) ? "99" : "98",
|
||||||
|
isempty(network->ifname) ? "default" : network->ifname);
|
||||||
|
if (r < 0)
|
||||||
|
return log_oom();
|
||||||
|
|
||||||
|
r = generator_open_unit_file(dest_dir, "kernel command line", filename, &f);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
network_dump(network, f);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int netdev_save(NetDev *netdev, const char *dest_dir) {
|
||||||
|
_cleanup_free_ char *filename = NULL;
|
||||||
|
_cleanup_fclose_ FILE *f = NULL;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
assert(netdev);
|
||||||
|
|
||||||
|
r = asprintf(&filename, "98-initrd-%s.netdev",
|
||||||
|
netdev->ifname);
|
||||||
|
if (r < 0)
|
||||||
|
return log_oom();
|
||||||
|
|
||||||
|
r = generator_open_unit_file(dest_dir, "kernel command line", filename, &f);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
netdev_dump(netdev, f);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int link_save(Link *link, const char *dest_dir) {
|
||||||
|
_cleanup_free_ char *filename = NULL;
|
||||||
|
_cleanup_fclose_ FILE *f = NULL;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
assert(link);
|
||||||
|
|
||||||
|
r = asprintf(&filename, "98-initrd-%s.link",
|
||||||
|
link->ifname);
|
||||||
|
if (r < 0)
|
||||||
|
return log_oom();
|
||||||
|
|
||||||
|
r = generator_open_unit_file(dest_dir, "kernel command line", filename, &f);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
link_dump(link, f);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int context_save(Context *context) {
|
||||||
|
Network *network;
|
||||||
|
NetDev *netdev;
|
||||||
|
Link *link;
|
||||||
|
Iterator i;
|
||||||
|
int k, r = 0;
|
||||||
|
const char *p;
|
||||||
|
|
||||||
|
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, i) {
|
||||||
|
k = network_save(network, p);
|
||||||
|
if (k < 0 && r >= 0)
|
||||||
|
r = k;
|
||||||
|
}
|
||||||
|
|
||||||
|
HASHMAP_FOREACH(netdev, context->netdevs_by_name, i) {
|
||||||
|
k = netdev_save(netdev, p);
|
||||||
|
if (k < 0 && r >= 0)
|
||||||
|
r = k;
|
||||||
|
}
|
||||||
|
|
||||||
|
HASHMAP_FOREACH(link, context->links_by_name, i) {
|
||||||
|
k = link_save(link, p);
|
||||||
|
if (k < 0 && r >= 0)
|
||||||
|
r = k;
|
||||||
|
}
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int help(void) {
|
||||||
|
printf("%s [OPTIONS...] [-- KERNEL_CMDLINE]\n"
|
||||||
|
" -h --help Show this help\n"
|
||||||
|
" --version Show package version\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("Unhandled option");
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int run(int argc, char *argv[]) {
|
||||||
|
_cleanup_(context_clear) Context context = {};
|
||||||
|
int i, r;
|
||||||
|
|
||||||
|
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 (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);
|
1234
src/network/generator/network-generator.c
Normal file
1234
src/network/generator/network-generator.c
Normal file
File diff suppressed because it is too large
Load Diff
108
src/network/generator/network-generator.h
Normal file
108
src/network/generator/network-generator.h
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
/* SPDX-License-Identifier: LGPL-2.1+ */
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <net/ethernet.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "hashmap.h"
|
||||||
|
#include "in-addr-util.h"
|
||||||
|
#include "list.h"
|
||||||
|
|
||||||
|
typedef enum DHCPType {
|
||||||
|
DHCP_TYPE_NONE,
|
||||||
|
DHCP_TYPE_OFF,
|
||||||
|
DHCP_TYPE_ON,
|
||||||
|
DHCP_TYPE_ANY,
|
||||||
|
DHCP_TYPE_DHCP,
|
||||||
|
DHCP_TYPE_DHCP6,
|
||||||
|
DHCP_TYPE_AUTO6,
|
||||||
|
DHCP_TYPE_EITHER6,
|
||||||
|
DHCP_TYPE_IBFT,
|
||||||
|
_DHCP_TYPE_MAX,
|
||||||
|
_DHCP_TYPE_INVALID = -1,
|
||||||
|
} DHCPType;
|
||||||
|
|
||||||
|
typedef struct Address Address;
|
||||||
|
typedef struct Link Link;
|
||||||
|
typedef struct NetDev NetDev;
|
||||||
|
typedef struct Network Network;
|
||||||
|
typedef struct Route Route;
|
||||||
|
typedef struct Context Context;
|
||||||
|
|
||||||
|
struct Address {
|
||||||
|
Network *network;
|
||||||
|
|
||||||
|
union in_addr_union address, peer;
|
||||||
|
unsigned char prefixlen;
|
||||||
|
int family;
|
||||||
|
|
||||||
|
LIST_FIELDS(Address, addresses);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Route {
|
||||||
|
Network *network;
|
||||||
|
|
||||||
|
union in_addr_union dest, gateway;
|
||||||
|
unsigned char prefixlen;
|
||||||
|
int family;
|
||||||
|
|
||||||
|
LIST_FIELDS(Route, routes);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Network {
|
||||||
|
/* [Match] */
|
||||||
|
char *ifname;
|
||||||
|
|
||||||
|
/* [Link] */
|
||||||
|
struct ether_addr mac;
|
||||||
|
uint32_t mtu;
|
||||||
|
|
||||||
|
/* [Network] */
|
||||||
|
DHCPType dhcp_type;
|
||||||
|
char **dns;
|
||||||
|
char *vlan;
|
||||||
|
char *bridge;
|
||||||
|
char *bond;
|
||||||
|
|
||||||
|
/* [DHCP] */
|
||||||
|
char *hostname;
|
||||||
|
int dhcp_use_dns;
|
||||||
|
|
||||||
|
LIST_HEAD(Address, addresses);
|
||||||
|
LIST_HEAD(Route, routes);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct NetDev {
|
||||||
|
/* [NetDev] */
|
||||||
|
char *ifname;
|
||||||
|
char *kind;
|
||||||
|
uint32_t mtu;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Link {
|
||||||
|
/* [Match] */
|
||||||
|
char *ifname;
|
||||||
|
struct ether_addr mac;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct Context {
|
||||||
|
Hashmap *networks_by_name;
|
||||||
|
Hashmap *netdevs_by_name;
|
||||||
|
Hashmap *links_by_name;
|
||||||
|
} Context;
|
||||||
|
|
||||||
|
int parse_cmdline_item(const char *key, const char *value, void *data);
|
||||||
|
int context_merge_networks(Context *context);
|
||||||
|
void context_clear(Context *context);
|
||||||
|
|
||||||
|
Network *network_get(Context *context, const char *ifname);
|
||||||
|
void network_dump(Network *network, FILE *f);
|
||||||
|
int network_format(Network *network, char **ret);
|
||||||
|
|
||||||
|
NetDev *netdev_get(Context *context, const char *ifname);
|
||||||
|
void netdev_dump(NetDev *netdev, FILE *f);
|
||||||
|
int netdev_format(NetDev *netdev, char **ret);
|
||||||
|
|
||||||
|
Link *link_get(Context *context, const char *ifname);
|
||||||
|
void link_dump(Link *link, FILE *f);
|
||||||
|
int link_format(Link *link, char **ret);
|
@ -114,6 +114,12 @@ systemd_networkd_wait_online_sources = files('''
|
|||||||
|
|
||||||
networkctl_sources = files('networkctl.c')
|
networkctl_sources = files('networkctl.c')
|
||||||
|
|
||||||
|
network_generator_sources = files('''
|
||||||
|
generator/main.c
|
||||||
|
generator/network-generator.c
|
||||||
|
generator/network-generator.h
|
||||||
|
'''.split())
|
||||||
|
|
||||||
network_include_dir = include_directories('.')
|
network_include_dir = include_directories('.')
|
||||||
|
|
||||||
if conf.get('ENABLE_NETWORKD') == 1
|
if conf.get('ENABLE_NETWORKD') == 1
|
||||||
|
Loading…
Reference in New Issue
Block a user