mirror of
https://github.com/systemd/systemd
synced 2026-04-23 07:24:51 +02:00
Compare commits
No commits in common. "1bd29614ffcea78a4002f88a58dba226789892dc" and "0d3c36641d071bc0370237245aecab1380a4f189" have entirely different histories.
1bd29614ff
...
0d3c36641d
1
.gitignore
vendored
1
.gitignore
vendored
@ -31,7 +31,6 @@ __pycache__/
|
||||
/mkosi.builddir/
|
||||
/mkosi.output/
|
||||
/mkosi.default
|
||||
/mkosi.installdir/
|
||||
# Ignore any mkosi config files with "local" in the name
|
||||
/mkosi.default.d/**/*local*.conf
|
||||
/tags
|
||||
|
||||
@ -68,10 +68,10 @@
|
||||
|
||||
<funcprototype>
|
||||
<funcdef>int <function>sd_journal_print_with_location</function></funcdef>
|
||||
<paramdef>int <parameter>priority</parameter></paramdef>
|
||||
<paramdef>const char *<parameter>file</parameter></paramdef>
|
||||
<paramdef>const char *<parameter>line</parameter></paramdef>
|
||||
<paramdef>const char *<parameter>func</parameter></paramdef>
|
||||
<paramdef>int <parameter>priority</parameter></paramdef>
|
||||
<paramdef>const char *<parameter>format</parameter></paramdef>
|
||||
<paramdef>…</paramdef>
|
||||
</funcprototype>
|
||||
|
||||
@ -2626,38 +2626,19 @@ Token=prefixstable:2002:da8:1::</programlisting></para>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>BootServerAddress=</varname></term>
|
||||
<term><varname>NextServer=</varname></term>
|
||||
|
||||
<listitem>
|
||||
<para>Takes an IPv4 address of the boot server used by e.g. PXE boot systems. When specified,
|
||||
the address is set to the <literal>siaddr</literal> field of the DHCP message header. See
|
||||
<ulink url="https://www.rfc-editor.org/rfc/rfc2131.html">RFC 2131</ulink> for more details.
|
||||
<para>Takes an IPv4 address. Configures the next server used by e.g. PXE boot systems.
|
||||
Defaults to unset.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>BootServerName=</varname></term>
|
||||
<term><varname>Filename=</varname></term>
|
||||
|
||||
<listitem>
|
||||
<para>Takes a name of the boot server used by e.g. PXE boot systems. When specified, the
|
||||
server name is set to the DHCP option 66. See
|
||||
<ulink url="https://www.rfc-editor.org/rfc/rfc2132.html">RFC 2132</ulink> for more details.
|
||||
Defaults to unset.</para>
|
||||
<para>Note that typically one of
|
||||
<varname>BootServerName=</varname>/<varname>BootServerAddress=</varname> is sufficient to be
|
||||
set, but both can be set too, if desired.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>BootFilename=</varname></term>
|
||||
|
||||
<listitem>
|
||||
<para>Takes a path or URL to a file loaded by e.g. a PXE boot loader. The specified path is
|
||||
set to the DHCP option 67. See
|
||||
<ulink url="https://www.rfc-editor.org/rfc/rfc2132.html">RFC 2132</ulink> for more details.
|
||||
Defaults to unset.</para>
|
||||
<para>Takes a path or url to a file loaded by e.g. a PXE boot loader. Defaults to unset.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
|
||||
@ -13,7 +13,6 @@
|
||||
#endif
|
||||
|
||||
typedef void (*free_func_t)(void *p);
|
||||
typedef void* (*mfree_func_t)(void *p);
|
||||
|
||||
/* If for some reason more than 4M are allocated on the stack, let's abort immediately. It's better than
|
||||
* proceeding and smashing the stack limits. Note that by default RLIMIT_STACK is 8M on Linux. */
|
||||
|
||||
@ -6173,6 +6173,7 @@ void unit_dump_config_items(FILE *f) {
|
||||
{ config_parse_si_uint64, "SIZE" },
|
||||
{ config_parse_bool, "BOOLEAN" },
|
||||
{ config_parse_string, "STRING" },
|
||||
{ config_parse_safe_string, "STRING" },
|
||||
{ config_parse_path, "PATH" },
|
||||
{ config_parse_unit_path_printf, "PATH" },
|
||||
{ config_parse_colon_separated_paths, "PATH" },
|
||||
|
||||
130
src/core/main.c
130
src/core/main.c
@ -589,73 +589,73 @@ static int config_parse_oom_score_adjust(
|
||||
|
||||
static int parse_config_file(void) {
|
||||
const ConfigTableItem items[] = {
|
||||
{ "Manager", "LogLevel", config_parse_level2, 0, NULL },
|
||||
{ "Manager", "LogTarget", config_parse_target, 0, NULL },
|
||||
{ "Manager", "LogColor", config_parse_color, 0, NULL },
|
||||
{ "Manager", "LogLocation", config_parse_location, 0, NULL },
|
||||
{ "Manager", "LogTime", config_parse_time, 0, NULL },
|
||||
{ "Manager", "DumpCore", config_parse_bool, 0, &arg_dump_core },
|
||||
{ "Manager", "CrashChVT", /* legacy */ config_parse_crash_chvt, 0, &arg_crash_chvt },
|
||||
{ "Manager", "CrashChangeVT", config_parse_crash_chvt, 0, &arg_crash_chvt },
|
||||
{ "Manager", "CrashShell", config_parse_bool, 0, &arg_crash_shell },
|
||||
{ "Manager", "CrashReboot", config_parse_bool, 0, &arg_crash_reboot },
|
||||
{ "Manager", "ShowStatus", config_parse_show_status, 0, &arg_show_status },
|
||||
{ "Manager", "StatusUnitFormat", config_parse_status_unit_format, 0, &arg_status_unit_format },
|
||||
{ "Manager", "CPUAffinity", config_parse_cpu_affinity2, 0, &arg_cpu_affinity },
|
||||
{ "Manager", "NUMAPolicy", config_parse_numa_policy, 0, &arg_numa_policy.type },
|
||||
{ "Manager", "NUMAMask", config_parse_numa_mask, 0, &arg_numa_policy },
|
||||
{ "Manager", "JoinControllers", config_parse_warn_compat, DISABLED_CONFIGURATION, NULL },
|
||||
{ "Manager", "RuntimeWatchdogSec", config_parse_watchdog_sec, 0, &arg_runtime_watchdog },
|
||||
{ "Manager", "RuntimeWatchdogPreSec", config_parse_watchdog_sec, 0, &arg_pretimeout_watchdog },
|
||||
{ "Manager", "RebootWatchdogSec", config_parse_watchdog_sec, 0, &arg_reboot_watchdog },
|
||||
{ "Manager", "ShutdownWatchdogSec", config_parse_watchdog_sec, 0, &arg_reboot_watchdog }, /* obsolete alias */
|
||||
{ "Manager", "KExecWatchdogSec", config_parse_watchdog_sec, 0, &arg_kexec_watchdog },
|
||||
{ "Manager", "WatchdogDevice", config_parse_path, 0, &arg_watchdog_device },
|
||||
{ "Manager", "RuntimeWatchdogPreGovernor", config_parse_string, CONFIG_PARSE_STRING_SAFE, &arg_watchdog_pretimeout_governor },
|
||||
{ "Manager", "CapabilityBoundingSet", config_parse_capability_set, 0, &arg_capability_bounding_set },
|
||||
{ "Manager", "NoNewPrivileges", config_parse_bool, 0, &arg_no_new_privs },
|
||||
{ "Manager", "LogLevel", config_parse_level2, 0, NULL },
|
||||
{ "Manager", "LogTarget", config_parse_target, 0, NULL },
|
||||
{ "Manager", "LogColor", config_parse_color, 0, NULL },
|
||||
{ "Manager", "LogLocation", config_parse_location, 0, NULL },
|
||||
{ "Manager", "LogTime", config_parse_time, 0, NULL },
|
||||
{ "Manager", "DumpCore", config_parse_bool, 0, &arg_dump_core },
|
||||
{ "Manager", "CrashChVT", /* legacy */ config_parse_crash_chvt, 0, &arg_crash_chvt },
|
||||
{ "Manager", "CrashChangeVT", config_parse_crash_chvt, 0, &arg_crash_chvt },
|
||||
{ "Manager", "CrashShell", config_parse_bool, 0, &arg_crash_shell },
|
||||
{ "Manager", "CrashReboot", config_parse_bool, 0, &arg_crash_reboot },
|
||||
{ "Manager", "ShowStatus", config_parse_show_status, 0, &arg_show_status },
|
||||
{ "Manager", "StatusUnitFormat", config_parse_status_unit_format, 0, &arg_status_unit_format },
|
||||
{ "Manager", "CPUAffinity", config_parse_cpu_affinity2, 0, &arg_cpu_affinity },
|
||||
{ "Manager", "NUMAPolicy", config_parse_numa_policy, 0, &arg_numa_policy.type },
|
||||
{ "Manager", "NUMAMask", config_parse_numa_mask, 0, &arg_numa_policy },
|
||||
{ "Manager", "JoinControllers", config_parse_warn_compat, DISABLED_CONFIGURATION, NULL },
|
||||
{ "Manager", "RuntimeWatchdogSec", config_parse_watchdog_sec, 0, &arg_runtime_watchdog },
|
||||
{ "Manager", "RuntimeWatchdogPreSec", config_parse_watchdog_sec, 0, &arg_pretimeout_watchdog },
|
||||
{ "Manager", "RebootWatchdogSec", config_parse_watchdog_sec, 0, &arg_reboot_watchdog },
|
||||
{ "Manager", "ShutdownWatchdogSec", config_parse_watchdog_sec, 0, &arg_reboot_watchdog }, /* obsolete alias */
|
||||
{ "Manager", "KExecWatchdogSec", config_parse_watchdog_sec, 0, &arg_kexec_watchdog },
|
||||
{ "Manager", "WatchdogDevice", config_parse_path, 0, &arg_watchdog_device },
|
||||
{ "Manager", "RuntimeWatchdogPreGovernor", config_parse_safe_string, 0, &arg_watchdog_pretimeout_governor },
|
||||
{ "Manager", "CapabilityBoundingSet", config_parse_capability_set, 0, &arg_capability_bounding_set },
|
||||
{ "Manager", "NoNewPrivileges", config_parse_bool, 0, &arg_no_new_privs },
|
||||
#if HAVE_SECCOMP
|
||||
{ "Manager", "SystemCallArchitectures", config_parse_syscall_archs, 0, &arg_syscall_archs },
|
||||
{ "Manager", "SystemCallArchitectures", config_parse_syscall_archs, 0, &arg_syscall_archs },
|
||||
#endif
|
||||
{ "Manager", "TimerSlackNSec", config_parse_nsec, 0, &arg_timer_slack_nsec },
|
||||
{ "Manager", "DefaultTimerAccuracySec", config_parse_sec, 0, &arg_default_timer_accuracy_usec },
|
||||
{ "Manager", "DefaultStandardOutput", config_parse_output_restricted, 0, &arg_default_std_output },
|
||||
{ "Manager", "DefaultStandardError", config_parse_output_restricted, 0, &arg_default_std_error },
|
||||
{ "Manager", "DefaultTimeoutStartSec", config_parse_sec, 0, &arg_default_timeout_start_usec },
|
||||
{ "Manager", "DefaultTimeoutStopSec", config_parse_sec, 0, &arg_default_timeout_stop_usec },
|
||||
{ "Manager", "DefaultTimeoutAbortSec", config_parse_default_timeout_abort, 0, NULL },
|
||||
{ "Manager", "DefaultRestartSec", config_parse_sec, 0, &arg_default_restart_usec },
|
||||
{ "Manager", "DefaultStartLimitInterval", config_parse_sec, 0, &arg_default_start_limit_interval }, /* obsolete alias */
|
||||
{ "Manager", "DefaultStartLimitIntervalSec", config_parse_sec, 0, &arg_default_start_limit_interval },
|
||||
{ "Manager", "DefaultStartLimitBurst", config_parse_unsigned, 0, &arg_default_start_limit_burst },
|
||||
{ "Manager", "DefaultEnvironment", config_parse_environ, 0, &arg_default_environment },
|
||||
{ "Manager", "ManagerEnvironment", config_parse_environ, 0, &arg_manager_environment },
|
||||
{ "Manager", "DefaultLimitCPU", config_parse_rlimit, RLIMIT_CPU, arg_default_rlimit },
|
||||
{ "Manager", "DefaultLimitFSIZE", config_parse_rlimit, RLIMIT_FSIZE, arg_default_rlimit },
|
||||
{ "Manager", "DefaultLimitDATA", config_parse_rlimit, RLIMIT_DATA, arg_default_rlimit },
|
||||
{ "Manager", "DefaultLimitSTACK", config_parse_rlimit, RLIMIT_STACK, arg_default_rlimit },
|
||||
{ "Manager", "DefaultLimitCORE", config_parse_rlimit, RLIMIT_CORE, arg_default_rlimit },
|
||||
{ "Manager", "DefaultLimitRSS", config_parse_rlimit, RLIMIT_RSS, arg_default_rlimit },
|
||||
{ "Manager", "DefaultLimitNOFILE", config_parse_rlimit, RLIMIT_NOFILE, arg_default_rlimit },
|
||||
{ "Manager", "DefaultLimitAS", config_parse_rlimit, RLIMIT_AS, arg_default_rlimit },
|
||||
{ "Manager", "DefaultLimitNPROC", config_parse_rlimit, RLIMIT_NPROC, arg_default_rlimit },
|
||||
{ "Manager", "DefaultLimitMEMLOCK", config_parse_rlimit, RLIMIT_MEMLOCK, arg_default_rlimit },
|
||||
{ "Manager", "DefaultLimitLOCKS", config_parse_rlimit, RLIMIT_LOCKS, arg_default_rlimit },
|
||||
{ "Manager", "DefaultLimitSIGPENDING", config_parse_rlimit, RLIMIT_SIGPENDING, arg_default_rlimit },
|
||||
{ "Manager", "DefaultLimitMSGQUEUE", config_parse_rlimit, RLIMIT_MSGQUEUE, arg_default_rlimit },
|
||||
{ "Manager", "DefaultLimitNICE", config_parse_rlimit, RLIMIT_NICE, arg_default_rlimit },
|
||||
{ "Manager", "DefaultLimitRTPRIO", config_parse_rlimit, RLIMIT_RTPRIO, arg_default_rlimit },
|
||||
{ "Manager", "DefaultLimitRTTIME", config_parse_rlimit, RLIMIT_RTTIME, arg_default_rlimit },
|
||||
{ "Manager", "DefaultCPUAccounting", config_parse_tristate, 0, &arg_default_cpu_accounting },
|
||||
{ "Manager", "DefaultIOAccounting", config_parse_bool, 0, &arg_default_io_accounting },
|
||||
{ "Manager", "DefaultIPAccounting", config_parse_bool, 0, &arg_default_ip_accounting },
|
||||
{ "Manager", "DefaultBlockIOAccounting", config_parse_bool, 0, &arg_default_blockio_accounting },
|
||||
{ "Manager", "DefaultMemoryAccounting", config_parse_bool, 0, &arg_default_memory_accounting },
|
||||
{ "Manager", "DefaultTasksAccounting", config_parse_bool, 0, &arg_default_tasks_accounting },
|
||||
{ "Manager", "DefaultTasksMax", config_parse_tasks_max, 0, &arg_default_tasks_max },
|
||||
{ "Manager", "CtrlAltDelBurstAction", config_parse_emergency_action, 0, &arg_cad_burst_action },
|
||||
{ "Manager", "DefaultOOMPolicy", config_parse_oom_policy, 0, &arg_default_oom_policy },
|
||||
{ "Manager", "DefaultOOMScoreAdjust", config_parse_oom_score_adjust, 0, NULL },
|
||||
{ "Manager", "TimerSlackNSec", config_parse_nsec, 0, &arg_timer_slack_nsec },
|
||||
{ "Manager", "DefaultTimerAccuracySec", config_parse_sec, 0, &arg_default_timer_accuracy_usec },
|
||||
{ "Manager", "DefaultStandardOutput", config_parse_output_restricted, 0, &arg_default_std_output },
|
||||
{ "Manager", "DefaultStandardError", config_parse_output_restricted, 0, &arg_default_std_error },
|
||||
{ "Manager", "DefaultTimeoutStartSec", config_parse_sec, 0, &arg_default_timeout_start_usec },
|
||||
{ "Manager", "DefaultTimeoutStopSec", config_parse_sec, 0, &arg_default_timeout_stop_usec },
|
||||
{ "Manager", "DefaultTimeoutAbortSec", config_parse_default_timeout_abort, 0, NULL },
|
||||
{ "Manager", "DefaultRestartSec", config_parse_sec, 0, &arg_default_restart_usec },
|
||||
{ "Manager", "DefaultStartLimitInterval", config_parse_sec, 0, &arg_default_start_limit_interval }, /* obsolete alias */
|
||||
{ "Manager", "DefaultStartLimitIntervalSec", config_parse_sec, 0, &arg_default_start_limit_interval },
|
||||
{ "Manager", "DefaultStartLimitBurst", config_parse_unsigned, 0, &arg_default_start_limit_burst },
|
||||
{ "Manager", "DefaultEnvironment", config_parse_environ, 0, &arg_default_environment },
|
||||
{ "Manager", "ManagerEnvironment", config_parse_environ, 0, &arg_manager_environment },
|
||||
{ "Manager", "DefaultLimitCPU", config_parse_rlimit, RLIMIT_CPU, arg_default_rlimit },
|
||||
{ "Manager", "DefaultLimitFSIZE", config_parse_rlimit, RLIMIT_FSIZE, arg_default_rlimit },
|
||||
{ "Manager", "DefaultLimitDATA", config_parse_rlimit, RLIMIT_DATA, arg_default_rlimit },
|
||||
{ "Manager", "DefaultLimitSTACK", config_parse_rlimit, RLIMIT_STACK, arg_default_rlimit },
|
||||
{ "Manager", "DefaultLimitCORE", config_parse_rlimit, RLIMIT_CORE, arg_default_rlimit },
|
||||
{ "Manager", "DefaultLimitRSS", config_parse_rlimit, RLIMIT_RSS, arg_default_rlimit },
|
||||
{ "Manager", "DefaultLimitNOFILE", config_parse_rlimit, RLIMIT_NOFILE, arg_default_rlimit },
|
||||
{ "Manager", "DefaultLimitAS", config_parse_rlimit, RLIMIT_AS, arg_default_rlimit },
|
||||
{ "Manager", "DefaultLimitNPROC", config_parse_rlimit, RLIMIT_NPROC, arg_default_rlimit },
|
||||
{ "Manager", "DefaultLimitMEMLOCK", config_parse_rlimit, RLIMIT_MEMLOCK, arg_default_rlimit },
|
||||
{ "Manager", "DefaultLimitLOCKS", config_parse_rlimit, RLIMIT_LOCKS, arg_default_rlimit },
|
||||
{ "Manager", "DefaultLimitSIGPENDING", config_parse_rlimit, RLIMIT_SIGPENDING, arg_default_rlimit },
|
||||
{ "Manager", "DefaultLimitMSGQUEUE", config_parse_rlimit, RLIMIT_MSGQUEUE, arg_default_rlimit },
|
||||
{ "Manager", "DefaultLimitNICE", config_parse_rlimit, RLIMIT_NICE, arg_default_rlimit },
|
||||
{ "Manager", "DefaultLimitRTPRIO", config_parse_rlimit, RLIMIT_RTPRIO, arg_default_rlimit },
|
||||
{ "Manager", "DefaultLimitRTTIME", config_parse_rlimit, RLIMIT_RTTIME, arg_default_rlimit },
|
||||
{ "Manager", "DefaultCPUAccounting", config_parse_tristate, 0, &arg_default_cpu_accounting },
|
||||
{ "Manager", "DefaultIOAccounting", config_parse_bool, 0, &arg_default_io_accounting },
|
||||
{ "Manager", "DefaultIPAccounting", config_parse_bool, 0, &arg_default_ip_accounting },
|
||||
{ "Manager", "DefaultBlockIOAccounting", config_parse_bool, 0, &arg_default_blockio_accounting },
|
||||
{ "Manager", "DefaultMemoryAccounting", config_parse_bool, 0, &arg_default_memory_accounting },
|
||||
{ "Manager", "DefaultTasksAccounting", config_parse_bool, 0, &arg_default_tasks_accounting },
|
||||
{ "Manager", "DefaultTasksMax", config_parse_tasks_max, 0, &arg_default_tasks_max },
|
||||
{ "Manager", "CtrlAltDelBurstAction", config_parse_emergency_action, 0, &arg_cad_burst_action },
|
||||
{ "Manager", "DefaultOOMPolicy", config_parse_oom_policy, 0, &arg_default_oom_policy },
|
||||
{ "Manager", "DefaultOOMScoreAdjust", config_parse_oom_score_adjust, 0, NULL },
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
@ -569,11 +569,11 @@ finalize:
|
||||
|
||||
static int parse_config(void) {
|
||||
const ConfigTableItem items[] = {
|
||||
{ "Upload", "URL", config_parse_string, CONFIG_PARSE_STRING_SAFE, &arg_url },
|
||||
{ "Upload", "ServerKeyFile", config_parse_path_or_ignore, 0, &arg_key },
|
||||
{ "Upload", "ServerCertificateFile", config_parse_path_or_ignore, 0, &arg_cert },
|
||||
{ "Upload", "TrustedCertificateFile", config_parse_path_or_ignore, 0, &arg_trust },
|
||||
{ "Upload", "NetworkTimeoutSec", config_parse_sec, 0, &arg_network_timeout_usec },
|
||||
{ "Upload", "URL", config_parse_safe_string, 0, &arg_url },
|
||||
{ "Upload", "ServerKeyFile", config_parse_path_or_ignore, 0, &arg_key },
|
||||
{ "Upload", "ServerCertificateFile", config_parse_path_or_ignore, 0, &arg_cert },
|
||||
{ "Upload", "TrustedCertificateFile", config_parse_path_or_ignore, 0, &arg_trust },
|
||||
{ "Upload", "NetworkTimeoutSec", config_parse_sec, 0, &arg_network_timeout_usec },
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
@ -73,24 +73,15 @@ enum {
|
||||
};
|
||||
|
||||
enum {
|
||||
DHCP_DISCOVER = 1, /* [RFC2132] */
|
||||
DHCP_OFFER = 2, /* [RFC2132] */
|
||||
DHCP_REQUEST = 3, /* [RFC2132] */
|
||||
DHCP_DECLINE = 4, /* [RFC2132] */
|
||||
DHCP_ACK = 5, /* [RFC2132] */
|
||||
DHCP_NAK = 6, /* [RFC2132] */
|
||||
DHCP_RELEASE = 7, /* [RFC2132] */
|
||||
DHCP_INFORM = 8, /* [RFC2132] */
|
||||
DHCP_FORCERENEW = 9, /* [RFC3203] */
|
||||
DHCPLEASEQUERY = 10, /* [RFC4388] */
|
||||
DHCPLEASEUNASSIGNED = 11, /* [RFC4388] */
|
||||
DHCPLEASEUNKNOWN = 12, /* [RFC4388] */
|
||||
DHCPLEASEACTIVE = 13, /* [RFC4388] */
|
||||
DHCPBULKLEASEQUERY = 14, /* [RFC6926] */
|
||||
DHCPLEASEQUERYDONE = 15, /* [RFC6926] */
|
||||
DHCPACTIVELEASEQUERY = 16, /* [RFC7724] */
|
||||
DHCPLEASEQUERYSTATUS = 17, /* [RFC7724] */
|
||||
DHCPTLS = 18, /* [RFC7724] */
|
||||
DHCP_DISCOVER = 1,
|
||||
DHCP_OFFER = 2,
|
||||
DHCP_REQUEST = 3,
|
||||
DHCP_DECLINE = 4,
|
||||
DHCP_ACK = 5,
|
||||
DHCP_NAK = 6,
|
||||
DHCP_RELEASE = 7,
|
||||
DHCP_INFORM = 8,
|
||||
DHCP_FORCERENEW = 9,
|
||||
};
|
||||
|
||||
enum {
|
||||
|
||||
@ -65,9 +65,8 @@ struct sd_dhcp_server {
|
||||
char *timezone;
|
||||
|
||||
DHCPServerData servers[_SD_DHCP_LEASE_SERVER_TYPE_MAX];
|
||||
struct in_addr boot_server_address;
|
||||
char *boot_server_name;
|
||||
char *boot_filename;
|
||||
struct in_addr next_server;
|
||||
char *filename;
|
||||
|
||||
OrderedSet *extra_options;
|
||||
OrderedSet *vendor_options;
|
||||
|
||||
@ -72,8 +72,8 @@ bool dhcp6_option_can_request(uint16_t option) {
|
||||
return false;
|
||||
case SD_DHCP6_OPTION_CLIENT_FQDN:
|
||||
case SD_DHCP6_OPTION_PANA_AGENT:
|
||||
case SD_DHCP6_OPTION_POSIX_TIMEZONE:
|
||||
case SD_DHCP6_OPTION_TZDB_TIMEZONE:
|
||||
case SD_DHCP6_OPTION_NEW_POSIX_TIMEZONE:
|
||||
case SD_DHCP6_OPTION_NEW_TZDB_TIMEZONE:
|
||||
return true;
|
||||
case SD_DHCP6_OPTION_ERO:
|
||||
case SD_DHCP6_OPTION_LQ_QUERY:
|
||||
|
||||
@ -145,11 +145,11 @@ static const uint8_t default_req_opts_anonymize[] = {
|
||||
SD_DHCP_OPTION_ROUTER, /* 3 */
|
||||
SD_DHCP_OPTION_DOMAIN_NAME_SERVER, /* 6 */
|
||||
SD_DHCP_OPTION_DOMAIN_NAME, /* 15 */
|
||||
SD_DHCP_OPTION_ROUTER_DISCOVERY, /* 31 */
|
||||
SD_DHCP_OPTION_ROUTER_DISCOVER, /* 31 */
|
||||
SD_DHCP_OPTION_STATIC_ROUTE, /* 33 */
|
||||
SD_DHCP_OPTION_VENDOR_SPECIFIC, /* 43 */
|
||||
SD_DHCP_OPTION_NETBIOS_NAME_SERVER, /* 44 */
|
||||
SD_DHCP_OPTION_NETBIOS_NODE_TYPE, /* 46 */
|
||||
SD_DHCP_OPTION_NETBIOS_NAMESERVER, /* 44 */
|
||||
SD_DHCP_OPTION_NETBIOS_NODETYPE, /* 46 */
|
||||
SD_DHCP_OPTION_NETBIOS_SCOPE, /* 47 */
|
||||
SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE, /* 121 */
|
||||
SD_DHCP_OPTION_PRIVATE_CLASSLESS_STATIC_ROUTE, /* 249 */
|
||||
|
||||
@ -709,7 +709,7 @@ int dhcp_lease_parse_options(uint8_t code, uint8_t len, const void *option, void
|
||||
log_debug_errno(r, "Failed to parse static routes, ignoring: %m");
|
||||
break;
|
||||
|
||||
case SD_DHCP_OPTION_MTU_INTERFACE:
|
||||
case SD_DHCP_OPTION_INTERFACE_MTU:
|
||||
r = lease_parse_u16(option, len, &lease->mtu, 68);
|
||||
if (r < 0)
|
||||
log_debug_errno(r, "Failed to parse MTU, ignoring: %m");
|
||||
@ -729,7 +729,7 @@ int dhcp_lease_parse_options(uint8_t code, uint8_t len, const void *option, void
|
||||
|
||||
break;
|
||||
|
||||
case SD_DHCP_OPTION_DOMAIN_SEARCH:
|
||||
case SD_DHCP_OPTION_DOMAIN_SEARCH_LIST:
|
||||
r = dhcp_lease_parse_search_domains(option, len, &lease->search_domains);
|
||||
if (r < 0)
|
||||
log_debug_errno(r, "Failed to parse Domain Search List, ignoring: %m");
|
||||
@ -750,13 +750,13 @@ int dhcp_lease_parse_options(uint8_t code, uint8_t len, const void *option, void
|
||||
log_debug_errno(r, "Failed to parse root path, ignoring: %m");
|
||||
break;
|
||||
|
||||
case SD_DHCP_OPTION_RENEWAL_TIME:
|
||||
case SD_DHCP_OPTION_RENEWAL_T1_TIME:
|
||||
r = lease_parse_u32(option, len, &lease->t1, 1);
|
||||
if (r < 0)
|
||||
log_debug_errno(r, "Failed to parse T1 time, ignoring: %m");
|
||||
break;
|
||||
|
||||
case SD_DHCP_OPTION_REBINDING_TIME:
|
||||
case SD_DHCP_OPTION_REBINDING_T2_TIME:
|
||||
r = lease_parse_u32(option, len, &lease->t2, 1);
|
||||
if (r < 0)
|
||||
log_debug_errno(r, "Failed to parse T2 time, ignoring: %m");
|
||||
@ -768,7 +768,7 @@ int dhcp_lease_parse_options(uint8_t code, uint8_t len, const void *option, void
|
||||
log_debug_errno(r, "Failed to parse classless routes, ignoring: %m");
|
||||
break;
|
||||
|
||||
case SD_DHCP_OPTION_TZDB_TIMEZONE: {
|
||||
case SD_DHCP_OPTION_NEW_TZDB_TIMEZONE: {
|
||||
_cleanup_free_ char *tz = NULL;
|
||||
|
||||
r = lease_parse_string(option, len, &tz);
|
||||
|
||||
@ -12,7 +12,6 @@
|
||||
#include "alloc-util.h"
|
||||
#include "dhcp-internal.h"
|
||||
#include "dhcp-server-internal.h"
|
||||
#include "dns-domain.h"
|
||||
#include "fd-util.h"
|
||||
#include "in-addr-util.h"
|
||||
#include "io-util.h"
|
||||
@ -164,8 +163,7 @@ static sd_dhcp_server *dhcp_server_free(sd_dhcp_server *server) {
|
||||
|
||||
sd_event_unref(server->event);
|
||||
|
||||
free(server->boot_server_name);
|
||||
free(server->boot_filename);
|
||||
free(server->filename);
|
||||
free(server->timezone);
|
||||
|
||||
for (sd_dhcp_lease_server_type_t i = 0; i < _SD_DHCP_LEASE_SERVER_TYPE_MAX; i++)
|
||||
@ -274,40 +272,24 @@ sd_event *sd_dhcp_server_get_event(sd_dhcp_server *server) {
|
||||
return server->event;
|
||||
}
|
||||
|
||||
int sd_dhcp_server_set_boot_server_address(sd_dhcp_server *server, const struct in_addr *address) {
|
||||
int sd_dhcp_server_set_next_server(sd_dhcp_server *server, const struct in_addr *next_server) {
|
||||
assert_return(server, -EINVAL);
|
||||
|
||||
if (address)
|
||||
server->boot_server_address = *address;
|
||||
if (next_server)
|
||||
server->next_server = *next_server;
|
||||
else
|
||||
server->boot_server_address = (struct in_addr) {};
|
||||
server->next_server = (struct in_addr) {};
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sd_dhcp_server_set_boot_server_name(sd_dhcp_server *server, const char *name) {
|
||||
int r;
|
||||
|
||||
int sd_dhcp_server_set_filename(sd_dhcp_server *server, const char *filename) {
|
||||
assert_return(server, -EINVAL);
|
||||
|
||||
if (name) {
|
||||
r = dns_name_is_valid(name);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return free_and_strdup(&server->boot_server_name, name);
|
||||
}
|
||||
|
||||
int sd_dhcp_server_set_boot_filename(sd_dhcp_server *server, const char *filename) {
|
||||
assert_return(server, -EINVAL);
|
||||
|
||||
if (filename && (!string_is_safe(filename) || !ascii_is_valid(filename)))
|
||||
if (filename && !ascii_is_valid(filename))
|
||||
return -EINVAL;
|
||||
|
||||
return free_and_strdup(&server->boot_filename, filename);
|
||||
return free_and_strdup(&server->filename, filename);
|
||||
}
|
||||
|
||||
int sd_dhcp_server_stop(sd_dhcp_server *server) {
|
||||
@ -579,7 +561,7 @@ static int server_send_offer_or_ack(
|
||||
return r;
|
||||
|
||||
packet->dhcp.yiaddr = address;
|
||||
packet->dhcp.siaddr = server->boot_server_address.s_addr;
|
||||
packet->dhcp.siaddr = server->next_server.s_addr;
|
||||
|
||||
lease_time = htobe32(req->lifetime);
|
||||
r = dhcp_option_append(&packet->dhcp, req->max_optlen, &offset, 0,
|
||||
@ -603,18 +585,18 @@ static int server_send_offer_or_ack(
|
||||
return r;
|
||||
}
|
||||
|
||||
if (server->boot_server_name) {
|
||||
if (server->filename) {
|
||||
/* The pxelinux magic option is marked as deprecated, but let's append it for older
|
||||
* implementations. */
|
||||
r = dhcp_option_append(&packet->dhcp, req->max_optlen, &offset, 0,
|
||||
SD_DHCP_OPTION_BOOT_SERVER_NAME,
|
||||
strlen(server->boot_server_name), server->boot_server_name);
|
||||
SD_DHCP_OPTION_PXELINUX_MAGIC, 4,
|
||||
(const uint8_t[]) { 0xf1, 0x00, 0x74, 0x7e });
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (server->boot_filename) {
|
||||
r = dhcp_option_append(&packet->dhcp, req->max_optlen, &offset, 0,
|
||||
SD_DHCP_OPTION_BOOT_FILENAME,
|
||||
strlen(server->boot_filename), server->boot_filename);
|
||||
SD_DHCP_OPTION_CONFIGURATION_FILE,
|
||||
strlen(server->filename), server->filename);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
@ -646,7 +628,7 @@ static int server_send_offer_or_ack(
|
||||
if (server->timezone) {
|
||||
r = dhcp_option_append(
|
||||
&packet->dhcp, req->max_optlen, &offset, 0,
|
||||
SD_DHCP_OPTION_TZDB_TIMEZONE,
|
||||
SD_DHCP_OPTION_NEW_TZDB_TIMEZONE,
|
||||
strlen(server->timezone), server->timezone);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -109,7 +109,7 @@ static void test_request_anonymize(sd_event *e) {
|
||||
r = sd_dhcp_client_attach_event(client, e, 0);
|
||||
assert_se(r >= 0);
|
||||
|
||||
assert_se(sd_dhcp_client_set_request_option(client, SD_DHCP_OPTION_NETBIOS_NAME_SERVER) == 0);
|
||||
assert_se(sd_dhcp_client_set_request_option(client, SD_DHCP_OPTION_NETBIOS_NAMESERVER) == 0);
|
||||
/* This PRL option is not set when using Anonymize */
|
||||
assert_se(sd_dhcp_client_set_request_option(client, SD_DHCP_OPTION_HOST_NAME) == 1);
|
||||
assert_se(sd_dhcp_client_set_request_option(client, SD_DHCP_OPTION_PARAMETER_REQUEST_LIST) == -EINVAL);
|
||||
|
||||
@ -179,14 +179,14 @@ Tun.OneQueue, config_parse_warn_compat,
|
||||
Tun.MultiQueue, config_parse_bool, 0, offsetof(TunTap, multi_queue)
|
||||
Tun.PacketInfo, config_parse_bool, 0, offsetof(TunTap, packet_info)
|
||||
Tun.VNetHeader, config_parse_bool, 0, offsetof(TunTap, vnet_hdr)
|
||||
Tun.User, config_parse_string, CONFIG_PARSE_STRING_SAFE, offsetof(TunTap, user_name)
|
||||
Tun.Group, config_parse_string, CONFIG_PARSE_STRING_SAFE, offsetof(TunTap, group_name)
|
||||
Tun.User, config_parse_safe_string, 0, offsetof(TunTap, user_name)
|
||||
Tun.Group, config_parse_safe_string, 0, offsetof(TunTap, group_name)
|
||||
Tap.OneQueue, config_parse_warn_compat, DISABLED_LEGACY, 0
|
||||
Tap.MultiQueue, config_parse_bool, 0, offsetof(TunTap, multi_queue)
|
||||
Tap.PacketInfo, config_parse_bool, 0, offsetof(TunTap, packet_info)
|
||||
Tap.VNetHeader, config_parse_bool, 0, offsetof(TunTap, vnet_hdr)
|
||||
Tap.User, config_parse_string, CONFIG_PARSE_STRING_SAFE, offsetof(TunTap, user_name)
|
||||
Tap.Group, config_parse_string, CONFIG_PARSE_STRING_SAFE, offsetof(TunTap, group_name)
|
||||
Tap.User, config_parse_safe_string, 0, offsetof(TunTap, user_name)
|
||||
Tap.Group, config_parse_safe_string, 0, offsetof(TunTap, group_name)
|
||||
Bond.Mode, config_parse_bond_mode, 0, offsetof(Bond, mode)
|
||||
Bond.TransmitHashPolicy, config_parse_bond_xmit_hash_policy, 0, offsetof(Bond, xmit_hash_policy)
|
||||
Bond.LACPTransmitRate, config_parse_bond_lacp_rate, 0, offsetof(Bond, lacp_rate)
|
||||
|
||||
@ -578,14 +578,14 @@ static int independent_netdev_create(NetDev *netdev) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int stacked_netdev_create(NetDev *netdev, Link *link, Request *req) {
|
||||
static int stacked_netdev_create(NetDev *netdev, Link *link, link_netlink_message_handler_t callback) {
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
|
||||
int r;
|
||||
|
||||
assert(netdev);
|
||||
assert(netdev->manager);
|
||||
assert(link);
|
||||
assert(req);
|
||||
assert(callback);
|
||||
|
||||
r = sd_rtnl_message_new_link(netdev->manager->rtnl, &m, RTM_NEWLINK, 0);
|
||||
if (r < 0)
|
||||
@ -595,10 +595,13 @@ static int stacked_netdev_create(NetDev *netdev, Link *link, Request *req) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = request_call_netlink_async(netdev->manager->rtnl, m, req);
|
||||
r = netlink_call_async(netdev->manager->rtnl, NULL, m, callback,
|
||||
link_netlink_destroy_callback, link);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
link_ref(link);
|
||||
|
||||
netdev->state = NETDEV_STATE_CREATING;
|
||||
log_netdev_debug(netdev, "Creating");
|
||||
return 0;
|
||||
@ -629,29 +632,40 @@ static int netdev_is_ready_to_create(NetDev *netdev, Link *link) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static int stacked_netdev_process_request(Request *req, Link *link, void *userdata) {
|
||||
NetDev *netdev = ASSERT_PTR(userdata);
|
||||
int request_process_stacked_netdev(Request *req) {
|
||||
NetDev *netdev;
|
||||
Link *link;
|
||||
int r;
|
||||
|
||||
assert(req);
|
||||
assert(link);
|
||||
assert(req->type == REQUEST_TYPE_NETDEV_STACKED);
|
||||
assert(req->netlink_handler);
|
||||
|
||||
netdev = ASSERT_PTR(req->netdev);
|
||||
link = ASSERT_PTR(req->link);
|
||||
|
||||
r = netdev_is_ready_to_create(netdev, link);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
|
||||
r = stacked_netdev_create(netdev, link, req);
|
||||
r = stacked_netdev_create(netdev, link, req->netlink_handler);
|
||||
if (r < 0)
|
||||
return log_netdev_warning_errno(netdev, r, "Failed to create netdev: %m");
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int create_stacked_netdev_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, void *userdata) {
|
||||
static int link_create_stacked_netdev_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
assert(link);
|
||||
assert(link->create_stacked_netdev_messages > 0);
|
||||
|
||||
link->create_stacked_netdev_messages--;
|
||||
|
||||
if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
|
||||
return 0;
|
||||
|
||||
r = sd_netlink_message_get_errno(m);
|
||||
if (r < 0 && r != -EEXIST) {
|
||||
@ -682,12 +696,10 @@ int link_request_stacked_netdev(Link *link, NetDev *netdev) {
|
||||
return 0; /* Already created. */
|
||||
|
||||
link->stacked_netdevs_created = false;
|
||||
r = link_queue_request_full(link, REQUEST_TYPE_NETDEV_STACKED,
|
||||
netdev_ref(netdev), (mfree_func_t) netdev_unref,
|
||||
trivial_hash_func, trivial_compare_func,
|
||||
stacked_netdev_process_request,
|
||||
&link->create_stacked_netdev_messages,
|
||||
create_stacked_netdev_handler, NULL);
|
||||
r = link_queue_request(link, REQUEST_TYPE_NETDEV_STACKED, netdev_ref(netdev), true,
|
||||
&link->create_stacked_netdev_messages,
|
||||
link_create_stacked_netdev_handler,
|
||||
NULL);
|
||||
if (r < 0)
|
||||
return log_link_error_errno(link, r, "Failed to request stacked netdev '%s': %m",
|
||||
netdev->ifname);
|
||||
@ -696,11 +708,14 @@ int link_request_stacked_netdev(Link *link, NetDev *netdev) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int independent_netdev_process_request(Request *req, Link *link, void *userdata) {
|
||||
NetDev *netdev = ASSERT_PTR(userdata);
|
||||
int request_process_independent_netdev(Request *req) {
|
||||
NetDev *netdev;
|
||||
int r;
|
||||
|
||||
assert(!link);
|
||||
assert(req);
|
||||
assert(req->type == REQUEST_TYPE_NETDEV_INDEPENDENT);
|
||||
|
||||
netdev = ASSERT_PTR(req->netdev);
|
||||
|
||||
r = netdev_is_ready_to_create(netdev, NULL);
|
||||
if (r <= 0)
|
||||
@ -732,9 +747,9 @@ static int netdev_request_to_create(NetDev *netdev) {
|
||||
|
||||
} else {
|
||||
/* Otherwise, wait for the dependencies being resolved. */
|
||||
r = netdev_queue_request(netdev, independent_netdev_process_request, NULL);
|
||||
r = netdev_queue_request(netdev, NULL);
|
||||
if (r < 0)
|
||||
return log_netdev_warning_errno(netdev, r, "Failed to request to create netdev: %m");
|
||||
return log_netdev_warning_errno(netdev, r, "Failed to request to create: %m");
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
@ -109,6 +109,7 @@ typedef enum NetDevCreateType {
|
||||
|
||||
typedef struct Manager Manager;
|
||||
typedef struct Condition Condition;
|
||||
typedef struct Request Request;
|
||||
|
||||
typedef struct NetDev {
|
||||
Manager *manager;
|
||||
@ -208,6 +209,8 @@ int netdev_set_ifindex(NetDev *netdev, sd_netlink_message *newlink);
|
||||
int netdev_generate_hw_addr(NetDev *netdev, Link *link, const char *name,
|
||||
const struct hw_addr_data *hw_addr, struct hw_addr_data *ret);
|
||||
|
||||
int request_process_independent_netdev(Request *req);
|
||||
int request_process_stacked_netdev(Request *req);
|
||||
int link_request_stacked_netdev(Link *link, NetDev *netdev);
|
||||
|
||||
const char *netdev_kind_to_string(NetDevKind d) _const_;
|
||||
|
||||
@ -65,17 +65,19 @@ static int address_label_new_static(Network *network, const char *filename, unsi
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int address_label_configure_handler(
|
||||
sd_netlink *rtnl,
|
||||
sd_netlink_message *m,
|
||||
Request *req,
|
||||
Link *link,
|
||||
void *userdata) {
|
||||
|
||||
static int address_label_configure_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
|
||||
int r;
|
||||
|
||||
assert(rtnl);
|
||||
assert(m);
|
||||
assert(link);
|
||||
assert(link->ifname);
|
||||
assert(link->static_address_label_messages > 0);
|
||||
|
||||
link->static_address_label_messages--;
|
||||
|
||||
if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
|
||||
return 1;
|
||||
|
||||
r = sd_netlink_message_get_errno(m);
|
||||
if (r < 0 && r != -EEXIST) {
|
||||
@ -93,7 +95,7 @@ static int address_label_configure_handler(
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int address_label_configure(AddressLabel *label, Link *link, Request *req) {
|
||||
static int address_label_configure(AddressLabel *label, Link *link, link_netlink_message_handler_t callback) {
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
|
||||
int r;
|
||||
|
||||
@ -102,7 +104,7 @@ static int address_label_configure(AddressLabel *label, Link *link, Request *req
|
||||
assert(link->ifindex > 0);
|
||||
assert(link->manager);
|
||||
assert(link->manager->rtnl);
|
||||
assert(req);
|
||||
assert(callback);
|
||||
|
||||
r = sd_rtnl_message_new_addrlabel(link->manager->rtnl, &m, RTM_NEWADDRLABEL,
|
||||
link->ifindex, AF_INET6);
|
||||
@ -121,20 +123,29 @@ static int address_label_configure(AddressLabel *label, Link *link, Request *req
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return request_call_netlink_async(link->manager->rtnl, m, req);
|
||||
r = netlink_call_async(link->manager->rtnl, NULL, m, callback,
|
||||
link_netlink_destroy_callback, link);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
link_ref(link);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int address_label_process_request(Request *req, Link *link, void *userdata) {
|
||||
AddressLabel *label = ASSERT_PTR(userdata);
|
||||
int request_process_address_label(Request *req) {
|
||||
Link *link;
|
||||
int r;
|
||||
|
||||
assert(req);
|
||||
assert(link);
|
||||
assert(req->label);
|
||||
assert(req->type == REQUEST_TYPE_ADDRESS_LABEL);
|
||||
|
||||
link = ASSERT_PTR(req->link);
|
||||
|
||||
if (!link_is_ready_to_configure(link, false))
|
||||
return 0;
|
||||
|
||||
r = address_label_configure(label, link, req);
|
||||
r = address_label_configure(req->label, link, req->netlink_handler);
|
||||
if (r < 0)
|
||||
return log_link_warning_errno(link, r, "Failed to configure address label: %m");
|
||||
|
||||
@ -151,11 +162,8 @@ int link_request_static_address_labels(Link *link) {
|
||||
link->static_address_labels_configured = false;
|
||||
|
||||
HASHMAP_FOREACH(label, link->network->address_labels_by_section) {
|
||||
r = link_queue_request_full(link, REQUEST_TYPE_ADDRESS_LABEL,
|
||||
label, NULL, trivial_hash_func, trivial_compare_func,
|
||||
address_label_process_request,
|
||||
&link->static_address_label_messages,
|
||||
address_label_configure_handler, NULL);
|
||||
r = link_queue_request(link, REQUEST_TYPE_ADDRESS_LABEL, label, false,
|
||||
&link->static_address_label_messages, address_label_configure_handler, NULL);
|
||||
if (r < 0)
|
||||
return log_link_warning_errno(link, r, "Failed to request address label: %m");
|
||||
}
|
||||
|
||||
@ -9,6 +9,7 @@
|
||||
|
||||
typedef struct Link Link;
|
||||
typedef struct Network Network;
|
||||
typedef struct Request Request;
|
||||
|
||||
typedef struct AddressLabel {
|
||||
Network *network;
|
||||
@ -25,6 +26,7 @@ AddressLabel *address_label_free(AddressLabel *label);
|
||||
void network_drop_invalid_address_labels(Network *network);
|
||||
|
||||
int link_request_static_address_labels(Link *link);
|
||||
int request_process_address_label(Request *req);
|
||||
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_address_label);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_address_label_prefix);
|
||||
|
||||
@ -316,7 +316,7 @@ DEFINE_PRIVATE_HASH_OPS(
|
||||
address_kernel_hash_func,
|
||||
address_kernel_compare_func);
|
||||
|
||||
static void address_hash_func(const Address *a, struct siphash *state) {
|
||||
void address_hash_func(const Address *a, struct siphash *state) {
|
||||
assert(a);
|
||||
|
||||
siphash24_compress(&a->family, sizeof(a->family), state);
|
||||
@ -1023,6 +1023,9 @@ int address_configure_handler_internal(sd_netlink *rtnl, sd_netlink_message *m,
|
||||
assert(link);
|
||||
assert(error_msg);
|
||||
|
||||
if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
|
||||
return 0;
|
||||
|
||||
r = sd_netlink_message_get_errno(m);
|
||||
if (r < 0 && r != -EEXIST) {
|
||||
log_link_message_warning_errno(link, m, r, error_msg);
|
||||
@ -1033,7 +1036,11 @@ int address_configure_handler_internal(sd_netlink *rtnl, sd_netlink_message *m,
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int address_configure(const Address *address, Link *link, Request *req) {
|
||||
static int address_configure(
|
||||
const Address *address,
|
||||
Link *link,
|
||||
link_netlink_message_handler_t callback) {
|
||||
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
|
||||
int r;
|
||||
|
||||
@ -1043,7 +1050,7 @@ static int address_configure(const Address *address, Link *link, Request *req) {
|
||||
assert(link->ifindex > 0);
|
||||
assert(link->manager);
|
||||
assert(link->manager->rtnl);
|
||||
assert(req);
|
||||
assert(callback);
|
||||
|
||||
log_address_debug(address, "Configuring", link);
|
||||
|
||||
@ -1084,7 +1091,12 @@ static int address_configure(const Address *address, Link *link, Request *req) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return request_call_netlink_async(link->manager->rtnl, m, req);
|
||||
r = netlink_call_async(link->manager->rtnl, NULL, m, callback, link_netlink_destroy_callback, link);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
link_ref(link);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool address_is_ready_to_configure(Link *link, const Address *address) {
|
||||
@ -1104,17 +1116,21 @@ static bool address_is_ready_to_configure(Link *link, const Address *address) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static int address_process_request(Request *req, Link *link, Address *address) {
|
||||
int request_process_address(Request *req) {
|
||||
Address *address;
|
||||
Link *link;
|
||||
int r;
|
||||
|
||||
assert(req);
|
||||
assert(link);
|
||||
assert(address);
|
||||
assert(req->type == REQUEST_TYPE_ADDRESS);
|
||||
|
||||
address = ASSERT_PTR(req->address);
|
||||
link = ASSERT_PTR(req->link);
|
||||
|
||||
if (!address_is_ready_to_configure(link, address))
|
||||
return 0;
|
||||
|
||||
r = address_configure(address, link, req);
|
||||
r = address_configure(address, link, req->netlink_handler);
|
||||
if (r < 0)
|
||||
return log_link_warning_errno(link, r, "Failed to configure address: %m");
|
||||
|
||||
@ -1127,7 +1143,7 @@ int link_request_address(
|
||||
Address *address,
|
||||
bool consume_object,
|
||||
unsigned *message_counter,
|
||||
address_netlink_handler_t netlink_handler,
|
||||
link_netlink_message_handler_t netlink_handler,
|
||||
Request **ret) {
|
||||
|
||||
Address *acquired, *existing;
|
||||
@ -1196,12 +1212,8 @@ int link_request_address(
|
||||
return r;
|
||||
|
||||
log_address_debug(existing, "Requesting", link);
|
||||
r = link_queue_request_safe(link, REQUEST_TYPE_ADDRESS,
|
||||
existing, NULL,
|
||||
address_hash_func,
|
||||
address_compare_func,
|
||||
address_process_request,
|
||||
message_counter, netlink_handler, ret);
|
||||
r = link_queue_request(link, REQUEST_TYPE_ADDRESS, existing, false,
|
||||
message_counter, netlink_handler, ret);
|
||||
if (r < 0)
|
||||
return log_link_warning_errno(link, r, "Failed to request address: %m");
|
||||
if (r == 0)
|
||||
@ -1212,10 +1224,13 @@ int link_request_address(
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int static_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, Address *address) {
|
||||
static int static_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
assert(link->static_address_messages > 0);
|
||||
|
||||
link->static_address_messages--;
|
||||
|
||||
r = address_configure_handler_internal(rtnl, m, link, "Failed to set static address");
|
||||
if (r <= 0)
|
||||
@ -1285,12 +1300,10 @@ void address_cancel_request(Address *address) {
|
||||
req = (Request) {
|
||||
.link = address->link,
|
||||
.type = REQUEST_TYPE_ADDRESS,
|
||||
.userdata = address,
|
||||
.hash_func = (hash_func_t) address_hash_func,
|
||||
.compare_func = (compare_func_t) address_compare_func,
|
||||
.address = address,
|
||||
};
|
||||
|
||||
request_detach(address->link->manager, &req);
|
||||
request_drop(ordered_set_get(address->link->manager->request_queue, &req));
|
||||
address_cancel_requesting(address);
|
||||
}
|
||||
|
||||
|
||||
@ -18,12 +18,6 @@ typedef struct Manager Manager;
|
||||
typedef struct Network Network;
|
||||
typedef struct Request Request;
|
||||
typedef int (*address_ready_callback_t)(Address *address);
|
||||
typedef int (*address_netlink_handler_t)(
|
||||
sd_netlink *rtnl,
|
||||
sd_netlink_message *m,
|
||||
Request *req,
|
||||
Link *link,
|
||||
Address *address);
|
||||
|
||||
struct Address {
|
||||
Link *link;
|
||||
@ -103,15 +97,17 @@ int link_request_address(
|
||||
Address *address,
|
||||
bool consume_object,
|
||||
unsigned *message_counter,
|
||||
address_netlink_handler_t netlink_handler,
|
||||
link_netlink_message_handler_t netlink_handler,
|
||||
Request **ret);
|
||||
int link_request_static_address(Link *link, Address *address, bool consume);
|
||||
int link_request_static_addresses(Link *link);
|
||||
int request_process_address(Request *req);
|
||||
|
||||
int manager_rtnl_process_address(sd_netlink *nl, sd_netlink_message *message, Manager *m);
|
||||
|
||||
int network_drop_invalid_addresses(Network *network);
|
||||
|
||||
void address_hash_func(const Address *a, struct siphash *state);
|
||||
int address_compare_func(const Address *a1, const Address *a2);
|
||||
|
||||
DEFINE_NETWORK_CONFIG_STATE_FUNCTIONS(Address, address);
|
||||
|
||||
@ -93,11 +93,16 @@ static int bridge_fdb_new_static(
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bridge_fdb_configure_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, void *userdata) {
|
||||
static int bridge_fdb_configure_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
assert(link);
|
||||
assert(link->static_bridge_fdb_messages > 0);
|
||||
|
||||
link->static_bridge_fdb_messages--;
|
||||
|
||||
if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
|
||||
return 0;
|
||||
|
||||
r = sd_netlink_message_get_errno(m);
|
||||
if (r < 0 && r != -EEXIST) {
|
||||
@ -163,14 +168,14 @@ static int bridge_fdb_configure_message(const BridgeFDB *fdb, Link *link, sd_net
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bridge_fdb_configure(BridgeFDB *fdb, Link *link, Request *req) {
|
||||
static int bridge_fdb_configure(BridgeFDB *fdb, Link *link, link_netlink_message_handler_t callback) {
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
|
||||
int r;
|
||||
|
||||
assert(fdb);
|
||||
assert(link);
|
||||
assert(link->manager);
|
||||
assert(req);
|
||||
assert(callback);
|
||||
|
||||
r = sd_rtnl_message_new_neigh(link->manager->rtnl, &m, RTM_NEWNEIGH, link->ifindex, AF_BRIDGE);
|
||||
if (r < 0)
|
||||
@ -180,7 +185,13 @@ static int bridge_fdb_configure(BridgeFDB *fdb, Link *link, Request *req) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return request_call_netlink_async(link->manager->rtnl, m, req);
|
||||
r = netlink_call_async(link->manager->rtnl, NULL, m, callback,
|
||||
link_netlink_destroy_callback, link);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
link_ref(link);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool bridge_fdb_is_ready_to_configure(BridgeFDB *fdb, Link *link) {
|
||||
@ -208,17 +219,20 @@ static bool bridge_fdb_is_ready_to_configure(BridgeFDB *fdb, Link *link) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static int bridge_fdb_process_request(Request *req, Link *link, void *userdata) {
|
||||
BridgeFDB *fdb = ASSERT_PTR(userdata);
|
||||
int request_process_bridge_fdb(Request *req) {
|
||||
BridgeFDB *fdb;
|
||||
Link *link;
|
||||
int r;
|
||||
|
||||
assert(req);
|
||||
assert(link);
|
||||
assert(req->type == REQUEST_TYPE_BRIDGE_FDB);
|
||||
assert_se(link = req->link);
|
||||
assert_se(fdb = req->fdb);
|
||||
|
||||
if (!bridge_fdb_is_ready_to_configure(fdb, link))
|
||||
return 0;
|
||||
|
||||
r = bridge_fdb_configure(fdb, link, req);
|
||||
r = bridge_fdb_configure(fdb, link, req->netlink_handler);
|
||||
if (r < 0)
|
||||
return log_link_warning_errno(link, r, "Failed to configure bridge FDB: %m");
|
||||
|
||||
@ -235,14 +249,8 @@ int link_request_static_bridge_fdb(Link *link) {
|
||||
link->static_bridge_fdb_configured = false;
|
||||
|
||||
HASHMAP_FOREACH(fdb, link->network->bridge_fdb_entries_by_section) {
|
||||
r = link_queue_request_full(link, REQUEST_TYPE_BRIDGE_FDB,
|
||||
fdb, NULL,
|
||||
trivial_hash_func,
|
||||
trivial_compare_func,
|
||||
bridge_fdb_process_request,
|
||||
&link->static_bridge_fdb_messages,
|
||||
bridge_fdb_configure_handler,
|
||||
NULL);
|
||||
r = link_queue_request(link, REQUEST_TYPE_BRIDGE_FDB, fdb, false,
|
||||
&link->static_bridge_fdb_messages, bridge_fdb_configure_handler, NULL);
|
||||
if (r < 0)
|
||||
return log_link_error_errno(link, r, "Failed to request static bridge FDB entry: %m");
|
||||
}
|
||||
|
||||
@ -14,6 +14,7 @@
|
||||
|
||||
typedef struct Link Link;
|
||||
typedef struct Network Network;
|
||||
typedef struct Request Request;
|
||||
|
||||
typedef enum NeighborCacheEntryFlags {
|
||||
NEIGHBOR_CACHE_ENTRY_FLAGS_USE = NTF_USE,
|
||||
@ -46,6 +47,8 @@ void network_drop_invalid_bridge_fdb_entries(Network *network);
|
||||
|
||||
int link_request_static_bridge_fdb(Link *link);
|
||||
|
||||
int request_process_bridge_fdb(Request *req);
|
||||
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_fdb_hwaddr);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_fdb_vlan_id);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_fdb_destination);
|
||||
|
||||
@ -81,11 +81,16 @@ static int bridge_mdb_new_static(
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bridge_mdb_configure_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, void *userdata) {
|
||||
static int bridge_mdb_configure_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
assert(link);
|
||||
assert(link->static_bridge_mdb_messages > 0);
|
||||
|
||||
link->static_bridge_mdb_messages--;
|
||||
|
||||
if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
|
||||
return 1;
|
||||
|
||||
r = sd_netlink_message_get_errno(m);
|
||||
if (r == -EINVAL && streq_ptr(link->kind, "bridge") && link->master_ifindex <= 0) {
|
||||
@ -109,7 +114,7 @@ static int bridge_mdb_configure_handler(sd_netlink *rtnl, sd_netlink_message *m,
|
||||
}
|
||||
|
||||
/* send a request to the kernel to add an MDB entry */
|
||||
static int bridge_mdb_configure(BridgeMDB *mdb, Link *link, Request *req) {
|
||||
static int bridge_mdb_configure(BridgeMDB *mdb, Link *link, link_netlink_message_handler_t callback) {
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
|
||||
struct br_mdb_entry entry;
|
||||
int r;
|
||||
@ -117,7 +122,7 @@ static int bridge_mdb_configure(BridgeMDB *mdb, Link *link, Request *req) {
|
||||
assert(mdb);
|
||||
assert(link);
|
||||
assert(link->manager);
|
||||
assert(req);
|
||||
assert(callback);
|
||||
|
||||
if (DEBUG_LOGGING) {
|
||||
_cleanup_free_ char *a = NULL;
|
||||
@ -159,7 +164,13 @@ static int bridge_mdb_configure(BridgeMDB *mdb, Link *link, Request *req) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return request_call_netlink_async(link->manager->rtnl, m, req);
|
||||
r = netlink_call_async(link->manager->rtnl, NULL, m, callback,
|
||||
link_netlink_destroy_callback, link);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
link_ref(link);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool bridge_mdb_is_ready_to_configure(Link *link) {
|
||||
@ -194,17 +205,19 @@ static bool bridge_mdb_is_ready_to_configure(Link *link) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static int bridge_mdb_process_request(Request *req, Link *link, void *userdata) {
|
||||
BridgeMDB *mdb = ASSERT_PTR(userdata);
|
||||
int request_process_bridge_mdb(Request *req) {
|
||||
Link *link;
|
||||
int r;
|
||||
|
||||
assert(req);
|
||||
assert(link);
|
||||
assert(req->mdb);
|
||||
assert(req->type == REQUEST_TYPE_BRIDGE_MDB);
|
||||
assert_se(link = req->link);
|
||||
|
||||
if (!bridge_mdb_is_ready_to_configure(link))
|
||||
return 0;
|
||||
|
||||
r = bridge_mdb_configure(mdb, link, req);
|
||||
r = bridge_mdb_configure(req->mdb, link, req->netlink_handler);
|
||||
if (r < 0)
|
||||
return log_link_warning_errno(link, r, "Failed to configure bridge MDB: %m");
|
||||
|
||||
@ -227,14 +240,8 @@ int link_request_static_bridge_mdb(Link *link) {
|
||||
goto finish;
|
||||
|
||||
HASHMAP_FOREACH(mdb, link->network->bridge_mdb_entries_by_section) {
|
||||
r = link_queue_request_full(link, REQUEST_TYPE_BRIDGE_MDB,
|
||||
mdb, NULL,
|
||||
trivial_hash_func,
|
||||
trivial_compare_func,
|
||||
bridge_mdb_process_request,
|
||||
&link->static_bridge_mdb_messages,
|
||||
bridge_mdb_configure_handler,
|
||||
NULL);
|
||||
r = link_queue_request(link, REQUEST_TYPE_BRIDGE_MDB, mdb, false,
|
||||
&link->static_bridge_mdb_messages, bridge_mdb_configure_handler, NULL);
|
||||
if (r < 0)
|
||||
return log_link_error_errno(link, r, "Failed to request MDB entry to multicast group database: %m");
|
||||
}
|
||||
|
||||
@ -9,6 +9,7 @@
|
||||
|
||||
typedef struct Link Link;
|
||||
typedef struct Network Network;
|
||||
typedef struct Request Request;
|
||||
|
||||
typedef struct BridgeMDB {
|
||||
Network *network;
|
||||
@ -24,6 +25,7 @@ BridgeMDB *bridge_mdb_free(BridgeMDB *mdb);
|
||||
void network_drop_invalid_bridge_mdb_entries(Network *network);
|
||||
|
||||
int link_request_static_bridge_mdb(Link *link);
|
||||
int request_process_bridge_mdb(Request *req);
|
||||
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_mdb_group_address);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_mdb_vlan_id);
|
||||
|
||||
@ -288,10 +288,13 @@ static int dhcp_pd_check_ready(Link *link) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int dhcp_pd_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, Route *route) {
|
||||
static int dhcp_pd_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
assert(link->dhcp_pd_messages > 0);
|
||||
|
||||
link->dhcp_pd_messages--;
|
||||
|
||||
r = route_configure_handler_internal(rtnl, m, link, "Failed to add prefix route for DHCP delegated subnet prefix");
|
||||
if (r <= 0)
|
||||
@ -341,10 +344,13 @@ static int dhcp_pd_request_route(Link *link, const struct in6_addr *prefix, usec
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dhcp_pd_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, Address *address) {
|
||||
static int dhcp_pd_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
assert(link->dhcp_pd_messages > 0);
|
||||
|
||||
link->dhcp_pd_messages--;
|
||||
|
||||
r = address_configure_handler_internal(rtnl, m, link, "Could not set DHCP-PD address");
|
||||
if (r <= 0)
|
||||
@ -652,10 +658,13 @@ void dhcp4_pd_prefix_lost(Link *uplink) {
|
||||
(void) link_remove(tunnel);
|
||||
}
|
||||
|
||||
static int dhcp4_unreachable_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, Route *route) {
|
||||
static int dhcp4_unreachable_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
assert(link->dhcp4_messages > 0);
|
||||
|
||||
link->dhcp4_messages--;
|
||||
|
||||
r = route_configure_handler_internal(rtnl, m, link, "Failed to set unreachable route for DHCPv4 delegated prefix");
|
||||
if (r <= 0)
|
||||
@ -668,10 +677,13 @@ static int dhcp4_unreachable_route_handler(sd_netlink *rtnl, sd_netlink_message
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int dhcp6_unreachable_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, Route *route) {
|
||||
static int dhcp6_unreachable_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
assert(link->dhcp6_messages > 0);
|
||||
|
||||
link->dhcp6_messages--;
|
||||
|
||||
r = route_configure_handler_internal(rtnl, m, link, "Failed to set unreachable route for DHCPv6 delegated prefix");
|
||||
if (r <= 0)
|
||||
@ -692,7 +704,7 @@ static int dhcp_request_unreachable_route(
|
||||
NetworkConfigSource source,
|
||||
const union in_addr_union *server_address,
|
||||
unsigned *counter,
|
||||
route_netlink_handler_t callback) {
|
||||
link_netlink_message_handler_t callback) {
|
||||
|
||||
_cleanup_(route_freep) Route *route = NULL;
|
||||
Route *existing;
|
||||
|
||||
@ -416,17 +416,13 @@ static int dhcp4_server_configure(Link *link) {
|
||||
return log_link_error_errno(link, r, "Failed to set default lease time for DHCPv4 server instance: %m");
|
||||
}
|
||||
|
||||
r = sd_dhcp_server_set_boot_server_address(link->dhcp_server, &link->network->dhcp_server_boot_server_address);
|
||||
r = sd_dhcp_server_set_next_server(link->dhcp_server, &link->network->dhcp_server_next_server);
|
||||
if (r < 0)
|
||||
return log_link_warning_errno(link, r, "Failed to set boot server address for DHCPv4 server instance: %m");
|
||||
return log_link_warning_errno(link, r, "Failed to set next server for DHCPv4 server instance: %m");
|
||||
|
||||
r = sd_dhcp_server_set_boot_server_name(link->dhcp_server, link->network->dhcp_server_boot_server_name);
|
||||
r = sd_dhcp_server_set_filename(link->dhcp_server, link->network->dhcp_server_filename);
|
||||
if (r < 0)
|
||||
return log_link_warning_errno(link, r, "Failed to set boot server name for DHCPv4 server instance: %m");
|
||||
|
||||
r = sd_dhcp_server_set_boot_filename(link->dhcp_server, link->network->dhcp_server_boot_filename);
|
||||
if (r < 0)
|
||||
return log_link_warning_errno(link, r, "Failed to set boot filename for DHCPv4 server instance: %m");
|
||||
return log_link_warning_errno(link, r, "Failed to set filename for DHCPv4 server instance: %m");
|
||||
|
||||
for (sd_dhcp_lease_server_type_t type = 0; type < _SD_DHCP_LEASE_SERVER_TYPE_MAX; type ++) {
|
||||
|
||||
@ -571,10 +567,13 @@ static bool dhcp_server_is_ready_to_configure(Link *link) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static int dhcp_server_process_request(Request *req, Link *link, void *userdata) {
|
||||
int request_process_dhcp_server(Request *req) {
|
||||
Link *link;
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
assert(req);
|
||||
assert(req->type == REQUEST_TYPE_DHCP_SERVER);
|
||||
assert_se(link = req->link);
|
||||
|
||||
if (!dhcp_server_is_ready_to_configure(link))
|
||||
return 0;
|
||||
@ -598,7 +597,7 @@ int link_request_dhcp_server(Link *link) {
|
||||
return 0;
|
||||
|
||||
log_link_debug(link, "Requesting DHCP server.");
|
||||
r = link_queue_request(link, REQUEST_TYPE_DHCP_SERVER, dhcp_server_process_request, NULL);
|
||||
r = link_queue_request(link, REQUEST_TYPE_DHCP_SERVER, NULL, false, NULL, NULL, NULL);
|
||||
if (r < 0)
|
||||
return log_link_warning_errno(link, r, "Failed to request configuration of DHCP server: %m");
|
||||
|
||||
@ -713,7 +712,7 @@ int config_parse_dhcp_server_address(
|
||||
void *data,
|
||||
void *userdata) {
|
||||
|
||||
Network *network = ASSERT_PTR(userdata);
|
||||
Network *network = userdata;
|
||||
union in_addr_union a;
|
||||
unsigned char prefixlen;
|
||||
int r;
|
||||
|
||||
@ -5,11 +5,13 @@
|
||||
|
||||
typedef struct Link Link;
|
||||
typedef struct Network Network;
|
||||
typedef struct Request Request;
|
||||
|
||||
void network_adjust_dhcp_server(Network *network);
|
||||
|
||||
int link_request_dhcp_server_address(Link *link);
|
||||
int link_request_dhcp_server(Link *link);
|
||||
int request_process_dhcp_server(Request *req);
|
||||
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_server_relay_agent_suboption);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_server_emit);
|
||||
|
||||
@ -177,11 +177,16 @@ static int dhcp4_retry(Link *link) {
|
||||
return dhcp4_request_address_and_routes(link, false);
|
||||
}
|
||||
|
||||
static int dhcp4_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, Route *route) {
|
||||
static int dhcp4_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
assert(link);
|
||||
assert(link->dhcp4_messages > 0);
|
||||
|
||||
link->dhcp4_messages--;
|
||||
|
||||
if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
|
||||
return 1;
|
||||
|
||||
r = sd_netlink_message_get_errno(m);
|
||||
if (r == -ENETUNREACH && !link->dhcp4_route_retrying) {
|
||||
@ -824,10 +829,13 @@ int dhcp4_lease_lost(Link *link) {
|
||||
return link_request_static_routes(link, true);
|
||||
}
|
||||
|
||||
static int dhcp4_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, Address *address) {
|
||||
static int dhcp4_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
assert(link->dhcp4_messages > 0);
|
||||
|
||||
link->dhcp4_messages--;
|
||||
|
||||
r = address_configure_handler_internal(rtnl, m, link, "Could not set DHCPv4 address");
|
||||
if (r <= 0)
|
||||
@ -1418,7 +1426,7 @@ static int dhcp4_configure(Link *link) {
|
||||
|
||||
if (!link->network->dhcp_anonymize) {
|
||||
if (link->network->dhcp_use_mtu) {
|
||||
r = sd_dhcp_client_set_request_option(link->dhcp_client, SD_DHCP_OPTION_MTU_INTERFACE);
|
||||
r = sd_dhcp_client_set_request_option(link->dhcp_client, SD_DHCP_OPTION_INTERFACE_MTU);
|
||||
if (r < 0)
|
||||
return log_link_debug_errno(link, r, "DHCPv4 CLIENT: Failed to set request flag for MTU: %m");
|
||||
}
|
||||
@ -1434,7 +1442,7 @@ static int dhcp4_configure(Link *link) {
|
||||
}
|
||||
|
||||
if (link->network->dhcp_use_domains != DHCP_USE_DOMAINS_NO) {
|
||||
r = sd_dhcp_client_set_request_option(link->dhcp_client, SD_DHCP_OPTION_DOMAIN_SEARCH);
|
||||
r = sd_dhcp_client_set_request_option(link->dhcp_client, SD_DHCP_OPTION_DOMAIN_SEARCH_LIST);
|
||||
if (r < 0)
|
||||
return log_link_debug_errno(link, r, "DHCPv4 CLIENT: Failed to set request flag for domain search list: %m");
|
||||
}
|
||||
@ -1452,7 +1460,7 @@ static int dhcp4_configure(Link *link) {
|
||||
}
|
||||
|
||||
if (link->network->dhcp_use_timezone) {
|
||||
r = sd_dhcp_client_set_request_option(link->dhcp_client, SD_DHCP_OPTION_TZDB_TIMEZONE);
|
||||
r = sd_dhcp_client_set_request_option(link->dhcp_client, SD_DHCP_OPTION_NEW_TZDB_TIMEZONE);
|
||||
if (r < 0)
|
||||
return log_link_debug_errno(link, r, "DHCPv4 CLIENT: Failed to set request flag for timezone: %m");
|
||||
}
|
||||
@ -1589,10 +1597,15 @@ static int dhcp4_configure_duid(Link *link) {
|
||||
return dhcp_configure_duid(link, link_get_dhcp4_duid(link));
|
||||
}
|
||||
|
||||
static int dhcp4_process_request(Request *req, Link *link, void *userdata) {
|
||||
int request_process_dhcp4_client(Request *req) {
|
||||
Link *link;
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
assert(req);
|
||||
assert(req->link);
|
||||
assert(req->type == REQUEST_TYPE_DHCP4_CLIENT);
|
||||
|
||||
link = req->link;
|
||||
|
||||
if (!IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED))
|
||||
return 0;
|
||||
@ -1606,7 +1619,7 @@ static int dhcp4_process_request(Request *req, Link *link, void *userdata) {
|
||||
if (r <= 0)
|
||||
return r;
|
||||
|
||||
r = dhcp4_configure(link);
|
||||
r = dhcp4_configure(req->link);
|
||||
if (r < 0)
|
||||
return log_link_warning_errno(link, r, "Failed to configure DHCPv4 client: %m");
|
||||
|
||||
@ -1616,6 +1629,7 @@ static int dhcp4_process_request(Request *req, Link *link, void *userdata) {
|
||||
|
||||
log_link_debug(link, "DHCPv4 client is configured%s.",
|
||||
r > 0 ? ", acquiring DHCPv4 lease" : "");
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -1630,7 +1644,7 @@ int link_request_dhcp4_client(Link *link) {
|
||||
if (link->dhcp_client)
|
||||
return 0;
|
||||
|
||||
r = link_queue_request(link, REQUEST_TYPE_DHCP4_CLIENT, dhcp4_process_request, NULL);
|
||||
r = link_queue_request(link, REQUEST_TYPE_DHCP4_CLIENT, NULL, false, NULL, NULL, NULL);
|
||||
if (r < 0)
|
||||
return log_link_warning_errno(link, r, "Failed to request configuring of the DHCPv4 client: %m");
|
||||
|
||||
|
||||
@ -5,6 +5,7 @@
|
||||
|
||||
typedef struct Link Link;
|
||||
typedef struct Network Network;
|
||||
typedef struct Request Request;
|
||||
|
||||
typedef enum DHCPClientIdentifier {
|
||||
DHCP_CLIENT_ID_MAC,
|
||||
@ -24,6 +25,7 @@ int dhcp4_start(Link *link);
|
||||
int dhcp4_lease_lost(Link *link);
|
||||
int dhcp4_check_ready(Link *link);
|
||||
|
||||
int request_process_dhcp4_client(Request *req);
|
||||
int link_request_dhcp4_client(Link *link);
|
||||
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_client_identifier);
|
||||
|
||||
@ -136,10 +136,13 @@ int dhcp6_check_ready(Link *link) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dhcp6_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, Address *address) {
|
||||
static int dhcp6_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
assert(link->dhcp6_messages > 0);
|
||||
|
||||
link->dhcp6_messages--;
|
||||
|
||||
r = address_configure_handler_internal(rtnl, m, link, "Could not set DHCPv6 address");
|
||||
if (r <= 0)
|
||||
@ -712,10 +715,15 @@ int dhcp6_update_mac(Link *link) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dhcp6_process_request(Request *req, Link *link, void *userdata) {
|
||||
int request_process_dhcp6_client(Request *req) {
|
||||
Link *link;
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
assert(req);
|
||||
assert(req->link);
|
||||
assert(req->type == REQUEST_TYPE_DHCP6_CLIENT);
|
||||
|
||||
link = req->link;
|
||||
|
||||
if (!IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED))
|
||||
return 0;
|
||||
@ -743,6 +751,7 @@ static int dhcp6_process_request(Request *req, Link *link, void *userdata) {
|
||||
|
||||
log_link_debug(link, "DHCPv6 client is configured%s.",
|
||||
r > 0 ? ", acquiring DHCPv6 lease" : "");
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -757,7 +766,7 @@ int link_request_dhcp6_client(Link *link) {
|
||||
if (link->dhcp6_client)
|
||||
return 0;
|
||||
|
||||
r = link_queue_request(link, REQUEST_TYPE_DHCP6_CLIENT, dhcp6_process_request, NULL);
|
||||
r = link_queue_request(link, REQUEST_TYPE_DHCP6_CLIENT, NULL, false, NULL, NULL, NULL);
|
||||
if (r < 0)
|
||||
return log_link_warning_errno(link, r, "Failed to request configuring of the DHCPv6 client: %m");
|
||||
|
||||
|
||||
@ -13,6 +13,7 @@ typedef enum DHCP6ClientStartMode {
|
||||
} DHCP6ClientStartMode;
|
||||
|
||||
typedef struct Link Link;
|
||||
typedef struct Request Request;
|
||||
|
||||
bool link_dhcp6_with_address_enabled(Link *link);
|
||||
int dhcp6_check_ready(Link *link);
|
||||
@ -20,6 +21,7 @@ int dhcp6_update_mac(Link *link);
|
||||
int dhcp6_start(Link *link);
|
||||
int dhcp6_start_on_ra(Link *link, bool information_request);
|
||||
|
||||
int request_process_dhcp6_client(Request *req);
|
||||
int link_request_dhcp6_client(Link *link);
|
||||
|
||||
int link_serialize_dhcp6_client(Link *link, FILE *f);
|
||||
|
||||
@ -70,7 +70,7 @@ static int ipv4ll_address_lost(Link *link) {
|
||||
return address_remove(existing);
|
||||
}
|
||||
|
||||
static int ipv4ll_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, Address *address) {
|
||||
static int ipv4ll_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
|
||||
@ -26,17 +26,13 @@ void network_adjust_ipv6_proxy_ndp(Network *network) {
|
||||
}
|
||||
}
|
||||
|
||||
static int ipv6_proxy_ndp_address_configure_handler(
|
||||
sd_netlink *rtnl,
|
||||
sd_netlink_message *m,
|
||||
Request *req,
|
||||
Link *link,
|
||||
struct in6_addr *address) {
|
||||
|
||||
static int ipv6_proxy_ndp_address_configure_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
assert(link);
|
||||
assert(link->static_ipv6_proxy_ndp_messages > 0);
|
||||
|
||||
link->static_ipv6_proxy_ndp_messages--;
|
||||
|
||||
r = sd_netlink_message_get_errno(m);
|
||||
if (r < 0)
|
||||
@ -52,7 +48,11 @@ static int ipv6_proxy_ndp_address_configure_handler(
|
||||
}
|
||||
|
||||
/* send a request to the kernel to add an IPv6 Proxy entry to the neighbour table */
|
||||
static int ipv6_proxy_ndp_address_configure(const struct in6_addr *address, Link *link, Request *req) {
|
||||
static int ipv6_proxy_ndp_address_configure(
|
||||
const struct in6_addr *address,
|
||||
Link *link,
|
||||
link_netlink_message_handler_t callback) {
|
||||
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
|
||||
int r;
|
||||
|
||||
@ -60,7 +60,7 @@ static int ipv6_proxy_ndp_address_configure(const struct in6_addr *address, Link
|
||||
assert(link);
|
||||
assert(link->manager);
|
||||
assert(link->manager->rtnl);
|
||||
assert(req);
|
||||
assert(callback);
|
||||
|
||||
/* create new netlink message */
|
||||
r = sd_rtnl_message_new_neigh(link->manager->rtnl, &m, RTM_NEWNEIGH, link->ifindex, AF_INET6);
|
||||
@ -75,20 +75,28 @@ static int ipv6_proxy_ndp_address_configure(const struct in6_addr *address, Link
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return request_call_netlink_async(link->manager->rtnl, m, req);
|
||||
r = netlink_call_async(link->manager->rtnl, NULL, m, callback,
|
||||
link_netlink_destroy_callback, link);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
link_ref(link);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ipv6_proxy_ndp_address_process_request(Request *req, Link *link, struct in6_addr *address) {
|
||||
int request_process_ipv6_proxy_ndp_address(Request *req) {
|
||||
Link *link;
|
||||
int r;
|
||||
|
||||
assert(req);
|
||||
assert(link);
|
||||
assert(address);
|
||||
assert(req->ipv6_proxy_ndp);
|
||||
assert(req->type == REQUEST_TYPE_IPV6_PROXY_NDP);
|
||||
assert_se(link = req->link);
|
||||
|
||||
if (!link_is_ready_to_configure(link, false))
|
||||
return 0;
|
||||
|
||||
r = ipv6_proxy_ndp_address_configure(address, link, req);
|
||||
r = ipv6_proxy_ndp_address_configure(req->ipv6_proxy_ndp, link, req->netlink_handler);
|
||||
if (r < 0)
|
||||
return log_link_warning_errno(link, r, "Failed to configure IPv6 proxy NDP address: %m");
|
||||
|
||||
@ -105,14 +113,9 @@ int link_request_static_ipv6_proxy_ndp_addresses(Link *link) {
|
||||
link->static_ipv6_proxy_ndp_configured = false;
|
||||
|
||||
SET_FOREACH(address, link->network->ipv6_proxy_ndp_addresses) {
|
||||
r = link_queue_request_safe(link, REQUEST_TYPE_IPV6_PROXY_NDP,
|
||||
address, NULL,
|
||||
in6_addr_hash_func,
|
||||
in6_addr_compare_func,
|
||||
ipv6_proxy_ndp_address_process_request,
|
||||
&link->static_ipv6_proxy_ndp_messages,
|
||||
ipv6_proxy_ndp_address_configure_handler,
|
||||
NULL);
|
||||
r = link_queue_request(link, REQUEST_TYPE_IPV6_PROXY_NDP, address, false,
|
||||
&link->static_ipv6_proxy_ndp_messages,
|
||||
ipv6_proxy_ndp_address_configure_handler, NULL);
|
||||
if (r < 0)
|
||||
return log_link_warning_errno(link, r, "Failed to request IPv6 proxy NDP address: %m");
|
||||
}
|
||||
|
||||
@ -5,9 +5,11 @@
|
||||
|
||||
typedef struct Link Link;
|
||||
typedef struct Network Network;
|
||||
typedef struct Request Request;
|
||||
|
||||
void network_adjust_ipv6_proxy_ndp(Network *network);
|
||||
|
||||
int link_request_static_ipv6_proxy_ndp_addresses(Link *link);
|
||||
int request_process_ipv6_proxy_ndp_address(Request *req);
|
||||
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_ipv6_proxy_ndp_address);
|
||||
|
||||
@ -906,7 +906,7 @@ static void link_drop_requests(Link *link) {
|
||||
|
||||
ORDERED_SET_FOREACH(req, link->manager->request_queue)
|
||||
if (req->link == link)
|
||||
request_detach(link->manager, req);
|
||||
request_drop(req);
|
||||
}
|
||||
|
||||
static Link *link_drop(Link *link) {
|
||||
|
||||
@ -203,10 +203,13 @@ static int ndisc_check_ready(Link *link) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ndisc_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, Route *route) {
|
||||
static int ndisc_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
assert(link->ndisc_messages > 0);
|
||||
|
||||
link->ndisc_messages--;
|
||||
|
||||
r = route_configure_handler_internal(rtnl, m, link, "Could not set NDisc route");
|
||||
if (r <= 0)
|
||||
@ -251,10 +254,13 @@ static int ndisc_request_route(Route *in, Link *link, sd_ndisc_router *rt) {
|
||||
ndisc_route_handler, NULL);
|
||||
}
|
||||
|
||||
static int ndisc_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, Address *address) {
|
||||
static int ndisc_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
assert(link->ndisc_messages > 0);
|
||||
|
||||
link->ndisc_messages--;
|
||||
|
||||
r = address_configure_handler_internal(rtnl, m, link, "Could not set NDisc address");
|
||||
if (r <= 0)
|
||||
@ -1116,10 +1122,14 @@ int ndisc_start(Link *link) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int ndisc_process_request(Request *req, Link *link, void *userdata) {
|
||||
int request_process_ndisc(Request *req) {
|
||||
Link *link;
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
assert(req);
|
||||
assert(req->type == REQUEST_TYPE_NDISC);
|
||||
|
||||
link = ASSERT_PTR(req->link);
|
||||
|
||||
if (!IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED))
|
||||
return 0;
|
||||
@ -1138,6 +1148,7 @@ static int ndisc_process_request(Request *req, Link *link, void *userdata) {
|
||||
|
||||
log_link_debug(link, "IPv6 Router Discovery is configured%s.",
|
||||
r > 0 ? " and started" : "");
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -1152,7 +1163,7 @@ int link_request_ndisc(Link *link) {
|
||||
if (link->ndisc)
|
||||
return 0;
|
||||
|
||||
r = link_queue_request(link, REQUEST_TYPE_NDISC, ndisc_process_request, NULL);
|
||||
r = link_queue_request(link, REQUEST_TYPE_NDISC, NULL, false, NULL, NULL, NULL);
|
||||
if (r < 0)
|
||||
return log_link_warning_errno(link, r, "Failed to request configuring of the IPv6 Router Discovery: %m");
|
||||
|
||||
|
||||
@ -6,6 +6,7 @@
|
||||
|
||||
typedef struct Link Link;
|
||||
typedef struct Network Network;
|
||||
typedef struct Request Request;
|
||||
|
||||
typedef enum IPv6AcceptRAStartDHCP6Client {
|
||||
IPV6_ACCEPT_RA_START_DHCP6_CLIENT_NO,
|
||||
@ -47,6 +48,7 @@ int ndisc_start(Link *link);
|
||||
void ndisc_vacuum(Link *link);
|
||||
void ndisc_flush(Link *link);
|
||||
|
||||
int request_process_ndisc(Request *req);
|
||||
int link_request_ndisc(Link *link);
|
||||
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_ipv6_accept_ra_start_dhcp6_client);
|
||||
|
||||
@ -87,7 +87,7 @@ static int neighbor_dup(const Neighbor *neighbor, Neighbor **ret) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void neighbor_hash_func(const Neighbor *neighbor, struct siphash *state) {
|
||||
void neighbor_hash_func(const Neighbor *neighbor, struct siphash *state) {
|
||||
assert(neighbor);
|
||||
|
||||
siphash24_compress(&neighbor->family, sizeof(neighbor->family), state);
|
||||
@ -106,7 +106,7 @@ static void neighbor_hash_func(const Neighbor *neighbor, struct siphash *state)
|
||||
hw_addr_hash_func(&neighbor->ll_addr, state);
|
||||
}
|
||||
|
||||
static int neighbor_compare_func(const Neighbor *a, const Neighbor *b) {
|
||||
int neighbor_compare_func(const Neighbor *a, const Neighbor *b) {
|
||||
int r;
|
||||
|
||||
r = CMP(a->family, b->family);
|
||||
@ -193,7 +193,11 @@ static int neighbor_configure_message(Neighbor *neighbor, Link *link, sd_netlink
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int neighbor_configure(Neighbor *neighbor, Link *link, Request *req) {
|
||||
static int neighbor_configure(
|
||||
Neighbor *neighbor,
|
||||
Link *link,
|
||||
link_netlink_message_handler_t callback) {
|
||||
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
|
||||
int r;
|
||||
|
||||
@ -202,7 +206,7 @@ static int neighbor_configure(Neighbor *neighbor, Link *link, Request *req) {
|
||||
assert(link->ifindex > 0);
|
||||
assert(link->manager);
|
||||
assert(link->manager->rtnl);
|
||||
assert(req);
|
||||
assert(callback);
|
||||
|
||||
log_neighbor_debug(neighbor, "Configuring", link);
|
||||
|
||||
@ -215,20 +219,31 @@ static int neighbor_configure(Neighbor *neighbor, Link *link, Request *req) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return request_call_netlink_async(link->manager->rtnl, m, req);
|
||||
r = netlink_call_async(link->manager->rtnl, NULL, m, callback,
|
||||
link_netlink_destroy_callback, link);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
link_ref(link);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int neighbor_process_request(Request *req, Link *link, Neighbor *neighbor) {
|
||||
int request_process_neighbor(Request *req) {
|
||||
Neighbor *neighbor;
|
||||
Link *link;
|
||||
int r;
|
||||
|
||||
assert(req);
|
||||
assert(link);
|
||||
assert(neighbor);
|
||||
assert(req->type == REQUEST_TYPE_NEIGHBOR);
|
||||
|
||||
neighbor = ASSERT_PTR(req->neighbor);
|
||||
link = ASSERT_PTR(req->link);
|
||||
|
||||
if (!link_is_ready_to_configure(link, false))
|
||||
return 0;
|
||||
|
||||
r = neighbor_configure(neighbor, link, req);
|
||||
r = neighbor_configure(neighbor, link, req->netlink_handler);
|
||||
if (r < 0)
|
||||
return log_link_warning_errno(link, r, "Failed to configure neighbor: %m");
|
||||
|
||||
@ -236,11 +251,17 @@ static int neighbor_process_request(Request *req, Link *link, Neighbor *neighbor
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int static_neighbor_configure_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, Neighbor *neighbor) {
|
||||
static int static_neighbor_configure_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
assert(link);
|
||||
assert(link->static_neighbor_messages > 0);
|
||||
|
||||
link->static_neighbor_messages--;
|
||||
|
||||
if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
|
||||
return 1;
|
||||
|
||||
r = sd_netlink_message_get_errno(m);
|
||||
if (r < 0 && r != -EEXIST) {
|
||||
@ -258,7 +279,13 @@ static int static_neighbor_configure_handler(sd_netlink *rtnl, sd_netlink_messag
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int link_request_neighbor(Link *link, const Neighbor *neighbor) {
|
||||
static int link_request_neighbor(
|
||||
Link *link,
|
||||
const Neighbor *neighbor,
|
||||
unsigned *message_counter,
|
||||
link_netlink_message_handler_t netlink_handler,
|
||||
Request **ret) {
|
||||
|
||||
Neighbor *existing;
|
||||
int r;
|
||||
|
||||
@ -282,14 +309,8 @@ static int link_request_neighbor(Link *link, const Neighbor *neighbor) {
|
||||
existing->source = neighbor->source;
|
||||
|
||||
log_neighbor_debug(existing, "Requesting", link);
|
||||
r = link_queue_request_safe(link, REQUEST_TYPE_NEIGHBOR,
|
||||
existing, NULL,
|
||||
neighbor_hash_func,
|
||||
neighbor_compare_func,
|
||||
neighbor_process_request,
|
||||
&link->static_neighbor_messages,
|
||||
static_neighbor_configure_handler,
|
||||
NULL);
|
||||
r = link_queue_request(link, REQUEST_TYPE_NEIGHBOR, existing, false,
|
||||
message_counter, netlink_handler, ret);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
|
||||
@ -308,7 +329,8 @@ int link_request_static_neighbors(Link *link) {
|
||||
link->static_neighbors_configured = false;
|
||||
|
||||
HASHMAP_FOREACH(neighbor, link->network->neighbors_by_section) {
|
||||
r = link_request_neighbor(link, neighbor);
|
||||
r = link_request_neighbor(link, neighbor, &link->static_neighbor_messages,
|
||||
static_neighbor_configure_handler, NULL);
|
||||
if (r < 0)
|
||||
return log_link_warning_errno(link, r, "Could not request neighbor: %m");
|
||||
}
|
||||
|
||||
@ -13,6 +13,7 @@
|
||||
typedef struct Link Link;
|
||||
typedef struct Manager Manager;
|
||||
typedef struct Network Network;
|
||||
typedef struct Request Request;
|
||||
|
||||
typedef struct Neighbor {
|
||||
Network *network;
|
||||
@ -28,6 +29,9 @@ typedef struct Neighbor {
|
||||
|
||||
Neighbor *neighbor_free(Neighbor *neighbor);
|
||||
|
||||
void neighbor_hash_func(const Neighbor *neighbor, struct siphash *state);
|
||||
int neighbor_compare_func(const Neighbor *a, const Neighbor *b);
|
||||
|
||||
void network_drop_invalid_neighbors(Network *network);
|
||||
|
||||
int link_drop_managed_neighbors(Link *link);
|
||||
@ -35,6 +39,7 @@ int link_drop_foreign_neighbors(Link *link);
|
||||
void link_foreignize_neighbors(Link *link);
|
||||
|
||||
int link_request_static_neighbors(Link *link);
|
||||
int request_process_neighbor(Request *req);
|
||||
|
||||
int manager_rtnl_process_neighbor(sd_netlink *rtnl, sd_netlink_message *message, Manager *m);
|
||||
|
||||
|
||||
@ -222,7 +222,7 @@ DHCPv4.SendHostname, config_parse_bool,
|
||||
DHCPv4.Hostname, config_parse_hostname, 0, offsetof(Network, dhcp_hostname)
|
||||
DHCPv4.Label, config_parse_dhcp_label, 0, offsetof(Network, dhcp_label)
|
||||
DHCPv4.RequestBroadcast, config_parse_tristate, 0, offsetof(Network, dhcp_broadcast)
|
||||
DHCPv4.VendorClassIdentifier, config_parse_string, CONFIG_PARSE_STRING_SAFE, offsetof(Network, dhcp_vendor_class_identifier)
|
||||
DHCPv4.VendorClassIdentifier, config_parse_safe_string, 0, offsetof(Network, dhcp_vendor_class_identifier)
|
||||
DHCPv4.MUDURL, config_parse_mud_url, 0, offsetof(Network, dhcp_mudurl)
|
||||
DHCPv4.MaxAttempts, config_parse_dhcp_max_attempts, 0, 0
|
||||
DHCPv4.UserClass, config_parse_dhcp_user_or_vendor_class, AF_INET, offsetof(Network, dhcp_user_class)
|
||||
@ -305,9 +305,8 @@ DHCPServer.PoolSize, config_parse_uint32,
|
||||
DHCPServer.SendVendorOption, config_parse_dhcp_send_option, 0, offsetof(Network, dhcp_server_send_vendor_options)
|
||||
DHCPServer.SendOption, config_parse_dhcp_send_option, 0, offsetof(Network, dhcp_server_send_options)
|
||||
DHCPServer.BindToInterface, config_parse_bool, 0, offsetof(Network, dhcp_server_bind_to_interface)
|
||||
DHCPServer.BootServerAddress, config_parse_in_addr_non_null, AF_INET, offsetof(Network, dhcp_server_boot_server_address)
|
||||
DHCPServer.BootServerName, config_parse_dns_name, 0, offsetof(Network, dhcp_server_boot_server_name)
|
||||
DHCPServer.BootFilename, config_parse_string, CONFIG_PARSE_STRING_SAFE_AND_ASCII, offsetof(Network, dhcp_server_boot_filename)
|
||||
DHCPServer.NextServer, config_parse_in_addr_non_null, AF_INET, offsetof(Network, dhcp_server_next_server)
|
||||
DHCPServer.Filename, config_parse_string, 0, offsetof(Network, dhcp_server_filename)
|
||||
DHCPServerStaticLease.Address, config_parse_dhcp_static_lease_address, 0, 0
|
||||
DHCPServerStaticLease.MACAddress, config_parse_dhcp_static_lease_hwaddr, 0, 0
|
||||
Bridge.Cost, config_parse_uint32, 0, offsetof(Network, cost)
|
||||
@ -544,7 +543,7 @@ DHCP.SendHostname, config_parse_bool,
|
||||
DHCP.Hostname, config_parse_hostname, 0, offsetof(Network, dhcp_hostname)
|
||||
DHCP.RequestBroadcast, config_parse_tristate, 0, offsetof(Network, dhcp_broadcast)
|
||||
DHCP.CriticalConnection, config_parse_tristate, 0, offsetof(Network, dhcp_critical)
|
||||
DHCP.VendorClassIdentifier, config_parse_string, CONFIG_PARSE_STRING_SAFE, offsetof(Network, dhcp_vendor_class_identifier)
|
||||
DHCP.VendorClassIdentifier, config_parse_safe_string, 0, offsetof(Network, dhcp_vendor_class_identifier)
|
||||
DHCP.UserClass, config_parse_dhcp_user_or_vendor_class, AF_INET, offsetof(Network, dhcp_user_class)
|
||||
DHCP.IAID, config_parse_iaid, AF_INET, 0
|
||||
DHCP.DUIDType, config_parse_network_duid_type, 0, 0
|
||||
|
||||
@ -702,8 +702,7 @@ static Network *network_free(Network *network) {
|
||||
|
||||
free(network->dhcp_server_relay_agent_circuit_id);
|
||||
free(network->dhcp_server_relay_agent_remote_id);
|
||||
free(network->dhcp_server_boot_server_name);
|
||||
free(network->dhcp_server_boot_filename);
|
||||
free(network->dhcp_server_filename);
|
||||
|
||||
free(network->description);
|
||||
free(network->dhcp_vendor_class_identifier);
|
||||
@ -983,6 +982,52 @@ int config_parse_domains(
|
||||
}
|
||||
}
|
||||
|
||||
int config_parse_hostname(
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
const char *section,
|
||||
unsigned section_line,
|
||||
const char *lvalue,
|
||||
int ltype,
|
||||
const char *rvalue,
|
||||
void *data,
|
||||
void *userdata) {
|
||||
|
||||
char **hostname = data;
|
||||
int r;
|
||||
|
||||
assert(filename);
|
||||
assert(lvalue);
|
||||
assert(rvalue);
|
||||
assert(data);
|
||||
|
||||
if (isempty(rvalue)) {
|
||||
*hostname = mfree(*hostname);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!hostname_is_valid(rvalue, 0)) {
|
||||
log_syntax(unit, LOG_WARNING, filename, line, 0,
|
||||
"Hostname is not valid, ignoring assignment: %s", rvalue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = dns_name_is_valid(rvalue);
|
||||
if (r < 0) {
|
||||
log_syntax(unit, LOG_WARNING, filename, line, r,
|
||||
"Failed to check validity of hostname '%s', ignoring assignment: %m", rvalue);
|
||||
return 0;
|
||||
}
|
||||
if (r == 0) {
|
||||
log_syntax(unit, LOG_WARNING, filename, line, 0,
|
||||
"Hostname is not a valid DNS domain name, ignoring assignment: %s", rvalue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return free_and_strdup_warn(hostname, rvalue);
|
||||
}
|
||||
|
||||
int config_parse_timezone(
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
|
||||
@ -200,9 +200,8 @@ struct Network {
|
||||
uint32_t dhcp_server_pool_size;
|
||||
OrderedHashmap *dhcp_server_send_options;
|
||||
OrderedHashmap *dhcp_server_send_vendor_options;
|
||||
struct in_addr dhcp_server_boot_server_address;
|
||||
char *dhcp_server_boot_server_name;
|
||||
char *dhcp_server_boot_filename;
|
||||
struct in_addr dhcp_server_next_server;
|
||||
char *dhcp_server_filename;
|
||||
|
||||
/* link local addressing support */
|
||||
AddressFamily link_local;
|
||||
@ -375,6 +374,7 @@ CONFIG_PARSER_PROTOTYPE(config_parse_stacked_netdev);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_tunnel);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_domains);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_dns);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_hostname);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_timezone);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_dnssec_negative_trust_anchors);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_ntp);
|
||||
|
||||
@ -104,7 +104,7 @@ static int nexthop_new_static(Network *network, const char *filename, unsigned s
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void nexthop_hash_func(const NextHop *nexthop, struct siphash *state) {
|
||||
void nexthop_hash_func(const NextHop *nexthop, struct siphash *state) {
|
||||
assert(nexthop);
|
||||
|
||||
siphash24_compress(&nexthop->protocol, sizeof(nexthop->protocol), state);
|
||||
@ -124,7 +124,7 @@ static void nexthop_hash_func(const NextHop *nexthop, struct siphash *state) {
|
||||
}
|
||||
}
|
||||
|
||||
static int nexthop_compare_func(const NextHop *a, const NextHop *b) {
|
||||
int nexthop_compare_func(const NextHop *a, const NextHop *b) {
|
||||
int r;
|
||||
|
||||
r = CMP(a->protocol, b->protocol);
|
||||
@ -425,7 +425,11 @@ static int nexthop_remove(NextHop *nexthop) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nexthop_configure(NextHop *nexthop, Link *link, Request *req) {
|
||||
static int nexthop_configure(
|
||||
NextHop *nexthop,
|
||||
Link *link,
|
||||
link_netlink_message_handler_t callback) {
|
||||
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
|
||||
int r;
|
||||
|
||||
@ -435,7 +439,7 @@ static int nexthop_configure(NextHop *nexthop, Link *link, Request *req) {
|
||||
assert(link->manager);
|
||||
assert(link->manager->rtnl);
|
||||
assert(link->ifindex > 0);
|
||||
assert(req);
|
||||
assert(callback);
|
||||
|
||||
log_nexthop_debug(nexthop, "Configuring", link);
|
||||
|
||||
@ -485,14 +489,25 @@ static int nexthop_configure(NextHop *nexthop, Link *link, Request *req) {
|
||||
}
|
||||
}
|
||||
|
||||
return request_call_netlink_async(link->manager->rtnl, m, req);
|
||||
r = netlink_call_async(link->manager->rtnl, NULL, m, callback,
|
||||
link_netlink_destroy_callback, link);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
link_ref(link);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int static_nexthop_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, NextHop *nexthop) {
|
||||
static int static_nexthop_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
assert(link);
|
||||
assert(link->static_nexthop_messages > 0);
|
||||
|
||||
link->static_nexthop_messages--;
|
||||
|
||||
if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
|
||||
return 1;
|
||||
|
||||
r = sd_netlink_message_get_errno(m);
|
||||
if (r < 0 && r != -EEXIST) {
|
||||
@ -546,7 +561,7 @@ static bool nexthop_is_ready_to_configure(Link *link, const NextHop *nexthop) {
|
||||
ORDERED_SET_FOREACH(req, link->manager->request_queue) {
|
||||
if (req->type != REQUEST_TYPE_NEXTHOP)
|
||||
continue;
|
||||
if (((NextHop*) req->userdata)->id != 0)
|
||||
if (req->nexthop->id != 0)
|
||||
return false; /* first configure nexthop with id. */
|
||||
}
|
||||
}
|
||||
@ -554,17 +569,21 @@ static bool nexthop_is_ready_to_configure(Link *link, const NextHop *nexthop) {
|
||||
return gateway_is_ready(link, FLAGS_SET(nexthop->flags, RTNH_F_ONLINK), nexthop->family, &nexthop->gw);
|
||||
}
|
||||
|
||||
static int nexthop_process_request(Request *req, Link *link, NextHop *nexthop) {
|
||||
int request_process_nexthop(Request *req) {
|
||||
NextHop *nexthop;
|
||||
Link *link;
|
||||
int r;
|
||||
|
||||
assert(req);
|
||||
assert(link);
|
||||
assert(nexthop);
|
||||
assert(req->type == REQUEST_TYPE_NEXTHOP);
|
||||
|
||||
nexthop = ASSERT_PTR(req->nexthop);
|
||||
link = ASSERT_PTR(req->link);
|
||||
|
||||
if (!nexthop_is_ready_to_configure(link, nexthop))
|
||||
return 0;
|
||||
|
||||
r = nexthop_configure(nexthop, link, req);
|
||||
r = nexthop_configure(nexthop, link, req->netlink_handler);
|
||||
if (r < 0)
|
||||
return log_link_warning_errno(link, r, "Failed to configure nexthop");
|
||||
|
||||
@ -572,7 +591,13 @@ static int nexthop_process_request(Request *req, Link *link, NextHop *nexthop) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int link_request_nexthop(Link *link, NextHop *nexthop) {
|
||||
static int link_request_nexthop(
|
||||
Link *link,
|
||||
NextHop *nexthop,
|
||||
unsigned *message_counter,
|
||||
link_netlink_message_handler_t netlink_handler,
|
||||
Request **ret) {
|
||||
|
||||
NextHop *existing;
|
||||
int r;
|
||||
|
||||
@ -600,14 +625,8 @@ static int link_request_nexthop(Link *link, NextHop *nexthop) {
|
||||
existing->source = nexthop->source;
|
||||
|
||||
log_nexthop_debug(existing, "Requesting", link);
|
||||
r = link_queue_request_safe(link, REQUEST_TYPE_NEXTHOP,
|
||||
existing, NULL,
|
||||
nexthop_hash_func,
|
||||
nexthop_compare_func,
|
||||
nexthop_process_request,
|
||||
&link->static_nexthop_messages,
|
||||
static_nexthop_handler,
|
||||
NULL);
|
||||
r = link_queue_request(link, REQUEST_TYPE_NEXTHOP, existing, false,
|
||||
message_counter, netlink_handler, ret);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
|
||||
@ -628,7 +647,8 @@ int link_request_static_nexthops(Link *link, bool only_ipv4) {
|
||||
if (only_ipv4 && nh->family != AF_INET)
|
||||
continue;
|
||||
|
||||
r = link_request_nexthop(link, nh);
|
||||
r = link_request_nexthop(link, nh, &link->static_nexthop_messages,
|
||||
static_nexthop_handler, NULL);
|
||||
if (r < 0)
|
||||
return log_link_warning_errno(link, r, "Could not request nexthop: %m");
|
||||
}
|
||||
|
||||
@ -16,6 +16,7 @@
|
||||
typedef struct Link Link;
|
||||
typedef struct Manager Manager;
|
||||
typedef struct Network Network;
|
||||
typedef struct Request Request;
|
||||
|
||||
typedef struct NextHop {
|
||||
Network *network;
|
||||
@ -38,6 +39,9 @@ typedef struct NextHop {
|
||||
|
||||
NextHop *nexthop_free(NextHop *nexthop);
|
||||
|
||||
void nexthop_hash_func(const NextHop *nexthop, struct siphash *state);
|
||||
int nexthop_compare_func(const NextHop *a, const NextHop *b);
|
||||
|
||||
void network_drop_invalid_nexthops(Network *network);
|
||||
|
||||
int link_drop_managed_nexthops(Link *link);
|
||||
@ -45,6 +49,7 @@ int link_drop_foreign_nexthops(Link *link);
|
||||
void link_foreignize_nexthops(Link *link);
|
||||
|
||||
int link_request_static_nexthops(Link *link, bool only_ipv4);
|
||||
int request_process_nexthop(Request *req);
|
||||
|
||||
int manager_get_nexthop_by_id(Manager *manager, uint32_t id, NextHop **ret);
|
||||
int manager_rtnl_process_nexthop(sd_netlink *rtnl, sd_netlink_message *message, Manager *m);
|
||||
|
||||
@ -1,47 +1,107 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include "netdev.h"
|
||||
#include "netlink-util.h"
|
||||
#include "networkd-link.h"
|
||||
#include "networkd-address.h"
|
||||
#include "networkd-address-label.h"
|
||||
#include "networkd-bridge-fdb.h"
|
||||
#include "networkd-bridge-mdb.h"
|
||||
#include "networkd-dhcp-server.h"
|
||||
#include "networkd-dhcp4.h"
|
||||
#include "networkd-dhcp6.h"
|
||||
#include "networkd-ipv6-proxy-ndp.h"
|
||||
#include "networkd-manager.h"
|
||||
#include "networkd-ndisc.h"
|
||||
#include "networkd-neighbor.h"
|
||||
#include "networkd-nexthop.h"
|
||||
#include "networkd-route.h"
|
||||
#include "networkd-routing-policy-rule.h"
|
||||
#include "networkd-queue.h"
|
||||
#include "string-table.h"
|
||||
#include "networkd-setlink.h"
|
||||
#include "qdisc.h"
|
||||
#include "tclass.h"
|
||||
|
||||
static void request_free_object(RequestType type, void *object) {
|
||||
switch (type) {
|
||||
case REQUEST_TYPE_ACTIVATE_LINK:
|
||||
break;
|
||||
case REQUEST_TYPE_ADDRESS:
|
||||
address_free(object);
|
||||
break;
|
||||
case REQUEST_TYPE_ADDRESS_LABEL:
|
||||
address_label_free(object);
|
||||
break;
|
||||
case REQUEST_TYPE_BRIDGE_FDB:
|
||||
bridge_fdb_free(object);
|
||||
break;
|
||||
case REQUEST_TYPE_BRIDGE_MDB:
|
||||
bridge_mdb_free(object);
|
||||
break;
|
||||
case REQUEST_TYPE_DHCP_SERVER:
|
||||
case REQUEST_TYPE_DHCP4_CLIENT:
|
||||
case REQUEST_TYPE_DHCP6_CLIENT:
|
||||
break;
|
||||
case REQUEST_TYPE_IPV6_PROXY_NDP:
|
||||
free(object);
|
||||
break;
|
||||
case REQUEST_TYPE_NDISC:
|
||||
break;
|
||||
case REQUEST_TYPE_NEIGHBOR:
|
||||
neighbor_free(object);
|
||||
break;
|
||||
case REQUEST_TYPE_NETDEV_INDEPENDENT:
|
||||
case REQUEST_TYPE_NETDEV_STACKED:
|
||||
netdev_unref(object);
|
||||
break;
|
||||
case REQUEST_TYPE_NEXTHOP:
|
||||
nexthop_free(object);
|
||||
break;
|
||||
case REQUEST_TYPE_RADV:
|
||||
break;
|
||||
case REQUEST_TYPE_ROUTE:
|
||||
route_free(object);
|
||||
break;
|
||||
case REQUEST_TYPE_ROUTING_POLICY_RULE:
|
||||
routing_policy_rule_free(object);
|
||||
break;
|
||||
case REQUEST_TYPE_SET_LINK:
|
||||
break;
|
||||
case REQUEST_TYPE_TC_QDISC:
|
||||
qdisc_free(object);
|
||||
break;
|
||||
case REQUEST_TYPE_TC_CLASS:
|
||||
tclass_free(object);
|
||||
break;
|
||||
case REQUEST_TYPE_UP_DOWN:
|
||||
break;
|
||||
default:
|
||||
assert_not_reached();
|
||||
}
|
||||
}
|
||||
|
||||
static Request *request_free(Request *req) {
|
||||
if (!req)
|
||||
return NULL;
|
||||
|
||||
/* To prevent from triggering assertions in the hash and compare functions, remove this request
|
||||
* before freeing userdata below. */
|
||||
if (req->manager)
|
||||
ordered_set_remove(req->manager->request_queue, req);
|
||||
|
||||
if (req->free_func)
|
||||
req->free_func(req->userdata);
|
||||
|
||||
if (req->counter)
|
||||
(*req->counter)--;
|
||||
|
||||
link_unref(req->link); /* link may be NULL, but link_unref() can handle it gracefully. */
|
||||
if (req->link && req->link->manager)
|
||||
/* To prevent from triggering assertions in hash functions, remove this request before
|
||||
* freeing object below. */
|
||||
ordered_set_remove(req->link->manager->request_queue, req);
|
||||
if (req->consume_object)
|
||||
request_free_object(req->type, req->object);
|
||||
link_unref(req->link);
|
||||
|
||||
return mfree(req);
|
||||
}
|
||||
|
||||
DEFINE_TRIVIAL_REF_UNREF_FUNC(Request, request, request_free);
|
||||
DEFINE_TRIVIAL_DESTRUCTOR(request_destroy_callback, Request, request_unref);
|
||||
|
||||
void request_detach(Manager *manager, Request *req) {
|
||||
assert(manager);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(Request*, request_free);
|
||||
|
||||
void request_drop(Request *req) {
|
||||
if (!req)
|
||||
return;
|
||||
|
||||
req = ordered_set_remove(manager->request_queue, req);
|
||||
if (!req)
|
||||
return;
|
||||
if (req->message_counter)
|
||||
(*req->message_counter)--;
|
||||
|
||||
req->manager = NULL;
|
||||
request_unref(req);
|
||||
request_free(req);
|
||||
}
|
||||
|
||||
static void request_hash_func(const Request *req, struct siphash *state) {
|
||||
@ -54,11 +114,61 @@ static void request_hash_func(const Request *req, struct siphash *state) {
|
||||
|
||||
siphash24_compress(&req->type, sizeof(req->type), state);
|
||||
|
||||
siphash24_compress(&req->hash_func, sizeof(req->hash_func), state);
|
||||
siphash24_compress(&req->compare_func, sizeof(req->compare_func), state);
|
||||
|
||||
if (req->hash_func)
|
||||
req->hash_func(req->userdata, state);
|
||||
switch (req->type) {
|
||||
case REQUEST_TYPE_ACTIVATE_LINK:
|
||||
break;
|
||||
case REQUEST_TYPE_ADDRESS:
|
||||
address_hash_func(req->address, state);
|
||||
break;
|
||||
case REQUEST_TYPE_ADDRESS_LABEL:
|
||||
case REQUEST_TYPE_BRIDGE_FDB:
|
||||
case REQUEST_TYPE_BRIDGE_MDB:
|
||||
case REQUEST_TYPE_NETDEV_INDEPENDENT:
|
||||
case REQUEST_TYPE_NETDEV_STACKED:
|
||||
/* TODO: Currently, these types do not have any specific hash and compare functions.
|
||||
* Fortunately, all these objects are 'static', thus we can use the trivial functions. */
|
||||
trivial_hash_func(req->object, state);
|
||||
break;
|
||||
case REQUEST_TYPE_DHCP_SERVER:
|
||||
case REQUEST_TYPE_DHCP4_CLIENT:
|
||||
case REQUEST_TYPE_DHCP6_CLIENT:
|
||||
/* These types do not have an object. */
|
||||
break;
|
||||
case REQUEST_TYPE_IPV6_PROXY_NDP:
|
||||
in6_addr_hash_func(req->ipv6_proxy_ndp, state);
|
||||
break;
|
||||
case REQUEST_TYPE_NDISC:
|
||||
/* This type does not have an object. */
|
||||
break;
|
||||
case REQUEST_TYPE_NEIGHBOR:
|
||||
neighbor_hash_func(req->neighbor, state);
|
||||
break;
|
||||
case REQUEST_TYPE_NEXTHOP:
|
||||
nexthop_hash_func(req->nexthop, state);
|
||||
break;
|
||||
case REQUEST_TYPE_RADV:
|
||||
/* This type does not have an object. */
|
||||
break;
|
||||
case REQUEST_TYPE_ROUTE:
|
||||
route_hash_func(req->route, state);
|
||||
break;
|
||||
case REQUEST_TYPE_ROUTING_POLICY_RULE:
|
||||
routing_policy_rule_hash_func(req->rule, state);
|
||||
break;
|
||||
case REQUEST_TYPE_SET_LINK:
|
||||
trivial_hash_func(req->set_link_operation_ptr, state);
|
||||
break;
|
||||
case REQUEST_TYPE_TC_QDISC:
|
||||
qdisc_hash_func(req->qdisc, state);
|
||||
break;
|
||||
case REQUEST_TYPE_TC_CLASS:
|
||||
tclass_hash_func(req->tclass, state);
|
||||
break;
|
||||
case REQUEST_TYPE_UP_DOWN:
|
||||
break;
|
||||
default:
|
||||
assert_not_reached();
|
||||
}
|
||||
}
|
||||
|
||||
static int request_compare_func(const struct Request *a, const struct Request *b) {
|
||||
@ -81,18 +191,46 @@ static int request_compare_func(const struct Request *a, const struct Request *b
|
||||
if (r != 0)
|
||||
return r;
|
||||
|
||||
r = CMP(PTR_TO_UINT64(a->hash_func), PTR_TO_UINT64(b->hash_func));
|
||||
if (r != 0)
|
||||
return r;
|
||||
|
||||
r = CMP(PTR_TO_UINT64(a->compare_func), PTR_TO_UINT64(b->compare_func));
|
||||
if (r != 0)
|
||||
return r;
|
||||
|
||||
if (a->compare_func)
|
||||
return a->compare_func(a->userdata, b->userdata);
|
||||
|
||||
return 0;
|
||||
switch (a->type) {
|
||||
case REQUEST_TYPE_ACTIVATE_LINK:
|
||||
return 0;
|
||||
case REQUEST_TYPE_ADDRESS:
|
||||
return address_compare_func(a->address, b->address);
|
||||
case REQUEST_TYPE_ADDRESS_LABEL:
|
||||
case REQUEST_TYPE_BRIDGE_FDB:
|
||||
case REQUEST_TYPE_BRIDGE_MDB:
|
||||
case REQUEST_TYPE_NETDEV_INDEPENDENT:
|
||||
case REQUEST_TYPE_NETDEV_STACKED:
|
||||
return trivial_compare_func(a->object, b->object);
|
||||
case REQUEST_TYPE_DHCP_SERVER:
|
||||
case REQUEST_TYPE_DHCP4_CLIENT:
|
||||
case REQUEST_TYPE_DHCP6_CLIENT:
|
||||
return 0;
|
||||
case REQUEST_TYPE_IPV6_PROXY_NDP:
|
||||
return in6_addr_compare_func(a->ipv6_proxy_ndp, b->ipv6_proxy_ndp);
|
||||
case REQUEST_TYPE_NDISC:
|
||||
return 0;
|
||||
case REQUEST_TYPE_NEIGHBOR:
|
||||
return neighbor_compare_func(a->neighbor, b->neighbor);
|
||||
case REQUEST_TYPE_NEXTHOP:
|
||||
return nexthop_compare_func(a->nexthop, b->nexthop);
|
||||
case REQUEST_TYPE_ROUTE:
|
||||
return route_compare_func(a->route, b->route);
|
||||
case REQUEST_TYPE_RADV:
|
||||
return 0;
|
||||
case REQUEST_TYPE_ROUTING_POLICY_RULE:
|
||||
return routing_policy_rule_compare_func(a->rule, b->rule);
|
||||
case REQUEST_TYPE_SET_LINK:
|
||||
return trivial_compare_func(a->set_link_operation_ptr, b->set_link_operation_ptr);
|
||||
case REQUEST_TYPE_TC_QDISC:
|
||||
return qdisc_compare_func(a->qdisc, b->qdisc);
|
||||
case REQUEST_TYPE_TC_CLASS:
|
||||
return tclass_compare_func(a->tclass, b->tclass);
|
||||
case REQUEST_TYPE_UP_DOWN:
|
||||
return 0;
|
||||
default:
|
||||
assert_not_reached();
|
||||
}
|
||||
}
|
||||
|
||||
DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(
|
||||
@ -100,63 +238,43 @@ DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(
|
||||
Request,
|
||||
request_hash_func,
|
||||
request_compare_func,
|
||||
request_unref);
|
||||
request_free);
|
||||
|
||||
static int request_new(
|
||||
Manager *manager,
|
||||
Link *link,
|
||||
RequestType type,
|
||||
void *userdata,
|
||||
mfree_func_t free_func,
|
||||
hash_func_t hash_func,
|
||||
compare_func_t compare_func,
|
||||
request_process_func_t process,
|
||||
unsigned *counter,
|
||||
request_netlink_handler_t netlink_handler,
|
||||
int netdev_queue_request(
|
||||
NetDev *netdev,
|
||||
Request **ret) {
|
||||
|
||||
_cleanup_(request_unrefp) Request *req = NULL;
|
||||
_cleanup_(request_freep) Request *req = NULL;
|
||||
Request *existing;
|
||||
int r;
|
||||
|
||||
assert(manager);
|
||||
assert(process);
|
||||
assert(netdev);
|
||||
assert(netdev->manager);
|
||||
|
||||
req = new(Request, 1);
|
||||
if (!req) {
|
||||
if (free_func)
|
||||
free_func(userdata);
|
||||
if (!req)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
*req = (Request) {
|
||||
.n_ref = 1,
|
||||
.link = link_ref(link), /* link may be NULL, but link_ref() handles it gracefully. */
|
||||
.type = type,
|
||||
.userdata = userdata,
|
||||
.free_func = free_func,
|
||||
.hash_func = hash_func,
|
||||
.compare_func = compare_func,
|
||||
.process = process,
|
||||
.netlink_handler = netlink_handler,
|
||||
.netdev = netdev_ref(netdev),
|
||||
.type = REQUEST_TYPE_NETDEV_INDEPENDENT,
|
||||
.consume_object = true,
|
||||
};
|
||||
|
||||
existing = ordered_set_get(manager->request_queue, req);
|
||||
existing = ordered_set_get(netdev->manager->request_queue, req);
|
||||
if (existing) {
|
||||
/* To prevent from removing the existing request. */
|
||||
req->netdev = netdev_unref(req->netdev);
|
||||
|
||||
if (ret)
|
||||
*ret = existing;
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = ordered_set_ensure_put(&manager->request_queue, &request_hash_ops, req);
|
||||
r = ordered_set_ensure_put(&netdev->manager->request_queue, &request_hash_ops, req);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
req->manager = manager;
|
||||
req->counter = counter;
|
||||
if (req->counter)
|
||||
(*req->counter)++;
|
||||
|
||||
if (ret)
|
||||
*ret = req;
|
||||
|
||||
@ -164,140 +282,173 @@ static int request_new(
|
||||
return 1;
|
||||
}
|
||||
|
||||
int netdev_queue_request(
|
||||
NetDev *netdev,
|
||||
request_process_func_t process,
|
||||
Request **ret) {
|
||||
|
||||
assert(netdev);
|
||||
|
||||
return request_new(netdev->manager, NULL, REQUEST_TYPE_NETDEV_INDEPENDENT,
|
||||
netdev_ref(netdev), (mfree_func_t) netdev_unref,
|
||||
trivial_hash_func, trivial_compare_func,
|
||||
process, NULL, NULL, ret);
|
||||
}
|
||||
|
||||
int link_queue_request_full(
|
||||
int link_queue_request(
|
||||
Link *link,
|
||||
RequestType type,
|
||||
void *userdata,
|
||||
mfree_func_t free_func,
|
||||
hash_func_t hash_func,
|
||||
compare_func_t compare_func,
|
||||
request_process_func_t process,
|
||||
unsigned *counter,
|
||||
request_netlink_handler_t netlink_handler,
|
||||
void *object,
|
||||
bool consume_object,
|
||||
unsigned *message_counter,
|
||||
link_netlink_message_handler_t netlink_handler,
|
||||
Request **ret) {
|
||||
|
||||
assert(link);
|
||||
_cleanup_(request_freep) Request *req = NULL;
|
||||
Request *existing;
|
||||
int r;
|
||||
|
||||
return request_new(link->manager, link, type,
|
||||
userdata, free_func, hash_func, compare_func,
|
||||
process, counter, netlink_handler, ret);
|
||||
assert(link);
|
||||
assert(link->manager);
|
||||
assert(type >= 0 && type < _REQUEST_TYPE_MAX);
|
||||
assert(IN_SET(type,
|
||||
REQUEST_TYPE_ACTIVATE_LINK,
|
||||
REQUEST_TYPE_DHCP_SERVER,
|
||||
REQUEST_TYPE_DHCP4_CLIENT,
|
||||
REQUEST_TYPE_DHCP6_CLIENT,
|
||||
REQUEST_TYPE_NDISC,
|
||||
REQUEST_TYPE_RADV,
|
||||
REQUEST_TYPE_SET_LINK,
|
||||
REQUEST_TYPE_UP_DOWN) ||
|
||||
object);
|
||||
assert(IN_SET(type,
|
||||
REQUEST_TYPE_DHCP_SERVER,
|
||||
REQUEST_TYPE_DHCP4_CLIENT,
|
||||
REQUEST_TYPE_DHCP6_CLIENT,
|
||||
REQUEST_TYPE_NDISC,
|
||||
REQUEST_TYPE_RADV,
|
||||
REQUEST_TYPE_TC_QDISC,
|
||||
REQUEST_TYPE_TC_CLASS) ||
|
||||
netlink_handler);
|
||||
|
||||
req = new(Request, 1);
|
||||
if (!req) {
|
||||
if (consume_object)
|
||||
request_free_object(type, object);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
*req = (Request) {
|
||||
.link = link_ref(link),
|
||||
.type = type,
|
||||
.object = object,
|
||||
.consume_object = consume_object,
|
||||
.message_counter = message_counter,
|
||||
.netlink_handler = netlink_handler,
|
||||
};
|
||||
|
||||
existing = ordered_set_get(link->manager->request_queue, req);
|
||||
if (existing) {
|
||||
/* To prevent from removing the existing request. */
|
||||
req->link = link_unref(req->link);
|
||||
|
||||
if (ret)
|
||||
*ret = existing;
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = ordered_set_ensure_put(&link->manager->request_queue, &request_hash_ops, req);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (req->message_counter)
|
||||
(*req->message_counter)++;
|
||||
|
||||
if (ret)
|
||||
*ret = req;
|
||||
|
||||
TAKE_PTR(req);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int manager_process_requests(sd_event_source *s, void *userdata) {
|
||||
Manager *manager = ASSERT_PTR(userdata);
|
||||
Manager *manager = userdata;
|
||||
int r;
|
||||
|
||||
assert(manager);
|
||||
|
||||
for (;;) {
|
||||
bool processed = false;
|
||||
Request *req;
|
||||
|
||||
ORDERED_SET_FOREACH(req, manager->request_queue) {
|
||||
_unused_ _cleanup_(request_unrefp) Request *ref = request_ref(req);
|
||||
_cleanup_(link_unrefp) Link *link = link_ref(req->link);
|
||||
|
||||
assert(req->process);
|
||||
|
||||
r = req->process(req, link, req->userdata);
|
||||
if (r == 0)
|
||||
continue;
|
||||
|
||||
processed = true;
|
||||
request_detach(manager, req);
|
||||
|
||||
if (r < 0 && link) {
|
||||
link_enter_failed(link);
|
||||
/* link_enter_failed() may remove multiple requests,
|
||||
* hence we need to exit from the loop. */
|
||||
switch (req->type) {
|
||||
case REQUEST_TYPE_ACTIVATE_LINK:
|
||||
r = request_process_activation(req);
|
||||
break;
|
||||
case REQUEST_TYPE_ADDRESS:
|
||||
r = request_process_address(req);
|
||||
break;
|
||||
case REQUEST_TYPE_ADDRESS_LABEL:
|
||||
r = request_process_address_label(req);
|
||||
break;
|
||||
case REQUEST_TYPE_BRIDGE_FDB:
|
||||
r = request_process_bridge_fdb(req);
|
||||
break;
|
||||
case REQUEST_TYPE_BRIDGE_MDB:
|
||||
r = request_process_bridge_mdb(req);
|
||||
break;
|
||||
case REQUEST_TYPE_DHCP_SERVER:
|
||||
r = request_process_dhcp_server(req);
|
||||
break;
|
||||
case REQUEST_TYPE_DHCP4_CLIENT:
|
||||
r = request_process_dhcp4_client(req);
|
||||
break;
|
||||
case REQUEST_TYPE_DHCP6_CLIENT:
|
||||
r = request_process_dhcp6_client(req);
|
||||
break;
|
||||
case REQUEST_TYPE_IPV6_PROXY_NDP:
|
||||
r = request_process_ipv6_proxy_ndp_address(req);
|
||||
break;
|
||||
case REQUEST_TYPE_NDISC:
|
||||
r = request_process_ndisc(req);
|
||||
break;
|
||||
case REQUEST_TYPE_NEIGHBOR:
|
||||
r = request_process_neighbor(req);
|
||||
break;
|
||||
case REQUEST_TYPE_NETDEV_INDEPENDENT:
|
||||
r = request_process_independent_netdev(req);
|
||||
break;
|
||||
case REQUEST_TYPE_NETDEV_STACKED:
|
||||
r = request_process_stacked_netdev(req);
|
||||
break;
|
||||
case REQUEST_TYPE_NEXTHOP:
|
||||
r = request_process_nexthop(req);
|
||||
break;
|
||||
case REQUEST_TYPE_RADV:
|
||||
r = request_process_radv(req);
|
||||
break;
|
||||
case REQUEST_TYPE_ROUTE:
|
||||
r = request_process_route(req);
|
||||
break;
|
||||
case REQUEST_TYPE_ROUTING_POLICY_RULE:
|
||||
r = request_process_routing_policy_rule(req);
|
||||
break;
|
||||
case REQUEST_TYPE_SET_LINK:
|
||||
r = request_process_set_link(req);
|
||||
break;
|
||||
case REQUEST_TYPE_TC_QDISC:
|
||||
r = request_process_qdisc(req);
|
||||
break;
|
||||
case REQUEST_TYPE_TC_CLASS:
|
||||
r = request_process_tclass(req);
|
||||
break;
|
||||
case REQUEST_TYPE_UP_DOWN:
|
||||
r = request_process_link_up_or_down(req);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
if (r < 0) {
|
||||
if (req->link)
|
||||
link_enter_failed(req->link);
|
||||
} else if (r > 0) {
|
||||
ordered_set_remove(manager->request_queue, req);
|
||||
request_free(req);
|
||||
processed = true;
|
||||
}
|
||||
}
|
||||
|
||||
/* When at least one request is processed, then another request may be ready now. */
|
||||
if (!processed)
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int request_netlink_handler(sd_netlink *nl, sd_netlink_message *m, Request *req) {
|
||||
assert(req);
|
||||
|
||||
if (req->counter) {
|
||||
assert(*req->counter > 0);
|
||||
(*req->counter)--;
|
||||
req->counter = NULL; /* To prevent double decrement on free. */
|
||||
}
|
||||
|
||||
if (req->link && IN_SET(req->link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
|
||||
return 0;
|
||||
|
||||
if (req->netlink_handler)
|
||||
return req->netlink_handler(nl, m, req, req->link, req->userdata);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int request_call_netlink_async(sd_netlink *nl, sd_netlink_message *m, Request *req) {
|
||||
int r;
|
||||
|
||||
assert(nl);
|
||||
assert(m);
|
||||
assert(req);
|
||||
|
||||
r = netlink_call_async(nl, NULL, m, request_netlink_handler, request_destroy_callback, req);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
request_ref(req);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char *const request_type_table[_REQUEST_TYPE_MAX] = {
|
||||
[REQUEST_TYPE_ACTIVATE_LINK] = "activate link",
|
||||
[REQUEST_TYPE_ADDRESS] = "address",
|
||||
[REQUEST_TYPE_ADDRESS_LABEL] = "address label",
|
||||
[REQUEST_TYPE_BRIDGE_FDB] = "bridge FDB",
|
||||
[REQUEST_TYPE_BRIDGE_MDB] = "bridge MDB",
|
||||
[REQUEST_TYPE_DHCP_SERVER] = "DHCP server",
|
||||
[REQUEST_TYPE_DHCP4_CLIENT] = "DHCPv4 client",
|
||||
[REQUEST_TYPE_DHCP6_CLIENT] = "DHCPv6 client",
|
||||
[REQUEST_TYPE_IPV6_PROXY_NDP] = "IPv6 proxy NDP",
|
||||
[REQUEST_TYPE_NDISC] = "NDisc",
|
||||
[REQUEST_TYPE_NEIGHBOR] = "neighbor",
|
||||
[REQUEST_TYPE_NETDEV_INDEPENDENT] = "independent netdev",
|
||||
[REQUEST_TYPE_NETDEV_STACKED] = "stacked netdev",
|
||||
[REQUEST_TYPE_NEXTHOP] = "nexthop",
|
||||
[REQUEST_TYPE_RADV] = "RADV",
|
||||
[REQUEST_TYPE_ROUTE] = "route",
|
||||
[REQUEST_TYPE_ROUTING_POLICY_RULE] = "routing policy rule",
|
||||
[REQUEST_TYPE_SET_LINK_ADDRESS_GENERATION_MODE] = "IPv6LL address generation mode",
|
||||
[REQUEST_TYPE_SET_LINK_BOND] = "bond configurations",
|
||||
[REQUEST_TYPE_SET_LINK_BRIDGE] = "bridge configurations",
|
||||
[REQUEST_TYPE_SET_LINK_BRIDGE_VLAN] = "bridge VLAN configurations",
|
||||
[REQUEST_TYPE_SET_LINK_CAN] = "CAN interface configurations",
|
||||
[REQUEST_TYPE_SET_LINK_FLAGS] = "link flags",
|
||||
[REQUEST_TYPE_SET_LINK_GROUP] = "interface group",
|
||||
[REQUEST_TYPE_SET_LINK_IPOIB] = "IPoIB configurations",
|
||||
[REQUEST_TYPE_SET_LINK_MAC] = "MAC address",
|
||||
[REQUEST_TYPE_SET_LINK_MASTER] = "master interface",
|
||||
[REQUEST_TYPE_SET_LINK_MTU] = "MTU",
|
||||
[REQUEST_TYPE_TC_QDISC] = "QDisc",
|
||||
[REQUEST_TYPE_TC_CLASS] = "TClass",
|
||||
[REQUEST_TYPE_UP_DOWN] = "bring link up or down",
|
||||
};
|
||||
|
||||
DEFINE_STRING_TABLE_LOOKUP_TO_STRING(request_type, RequestType);
|
||||
|
||||
@ -2,18 +2,20 @@
|
||||
#pragma once
|
||||
|
||||
#include "sd-event.h"
|
||||
#include "sd-netlink.h"
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "hash-funcs.h"
|
||||
#include "networkd-link.h"
|
||||
|
||||
typedef struct Link Link;
|
||||
typedef struct Address Address;
|
||||
typedef struct AddressLabel AddressLabel;
|
||||
typedef struct BridgeFDB BridgeFDB;
|
||||
typedef struct BridgeMDB BridgeMDB;
|
||||
typedef struct Neighbor Neighbor;
|
||||
typedef struct NetDev NetDev;
|
||||
typedef struct Manager Manager;
|
||||
typedef struct Request Request;
|
||||
|
||||
typedef int (*request_process_func_t)(Request *req, Link *link, void *userdata);
|
||||
typedef int (*request_netlink_handler_t)(sd_netlink *nl, sd_netlink_message *m, Request *req, Link *link, void *userdata);
|
||||
typedef struct NextHop NextHop;
|
||||
typedef struct Route Route;
|
||||
typedef struct RoutingPolicyRule RoutingPolicyRule;
|
||||
typedef struct QDisc QDisc;
|
||||
typedef struct TClass TClass;
|
||||
|
||||
typedef enum RequestType {
|
||||
REQUEST_TYPE_ACTIVATE_LINK,
|
||||
@ -33,17 +35,7 @@ typedef enum RequestType {
|
||||
REQUEST_TYPE_RADV,
|
||||
REQUEST_TYPE_ROUTE,
|
||||
REQUEST_TYPE_ROUTING_POLICY_RULE,
|
||||
REQUEST_TYPE_SET_LINK_ADDRESS_GENERATION_MODE, /* Setting IPv6LL address generation mode. */
|
||||
REQUEST_TYPE_SET_LINK_BOND, /* Setting bond configs. */
|
||||
REQUEST_TYPE_SET_LINK_BRIDGE, /* Setting bridge configs. */
|
||||
REQUEST_TYPE_SET_LINK_BRIDGE_VLAN, /* Setting bridge VLAN configs. */
|
||||
REQUEST_TYPE_SET_LINK_CAN, /* Setting CAN interface configs. */
|
||||
REQUEST_TYPE_SET_LINK_FLAGS, /* Setting IFF_NOARP or friends. */
|
||||
REQUEST_TYPE_SET_LINK_GROUP, /* Setting interface group. */
|
||||
REQUEST_TYPE_SET_LINK_IPOIB, /* Setting IPoIB configs. */
|
||||
REQUEST_TYPE_SET_LINK_MAC, /* Setting MAC address. */
|
||||
REQUEST_TYPE_SET_LINK_MASTER, /* Setting IFLA_MASTER. */
|
||||
REQUEST_TYPE_SET_LINK_MTU, /* Setting MTU. */
|
||||
REQUEST_TYPE_SET_LINK,
|
||||
REQUEST_TYPE_TC_CLASS,
|
||||
REQUEST_TYPE_TC_QDISC,
|
||||
REQUEST_TYPE_UP_DOWN,
|
||||
@ -51,88 +43,44 @@ typedef enum RequestType {
|
||||
_REQUEST_TYPE_INVALID = -EINVAL,
|
||||
} RequestType;
|
||||
|
||||
struct Request {
|
||||
unsigned n_ref;
|
||||
|
||||
Manager *manager; /* must be non-NULL */
|
||||
Link *link; /* can be NULL */
|
||||
|
||||
typedef struct Request {
|
||||
Link *link;
|
||||
RequestType type;
|
||||
|
||||
/* Target object, e.g. Address, Route, NetDev, and so on. */
|
||||
bool consume_object;
|
||||
union {
|
||||
Address *address;
|
||||
AddressLabel *label;
|
||||
BridgeFDB *fdb;
|
||||
BridgeMDB *mdb;
|
||||
struct in6_addr *ipv6_proxy_ndp;
|
||||
Neighbor *neighbor;
|
||||
NextHop *nexthop;
|
||||
Route *route;
|
||||
RoutingPolicyRule *rule;
|
||||
void *set_link_operation_ptr;
|
||||
NetDev *netdev;
|
||||
QDisc *qdisc;
|
||||
TClass *tclass;
|
||||
void *object;
|
||||
};
|
||||
void *userdata;
|
||||
/* freeing userdata when the request is completed or failed. */
|
||||
mfree_func_t free_func;
|
||||
unsigned *message_counter;
|
||||
link_netlink_message_handler_t netlink_handler;
|
||||
} Request;
|
||||
|
||||
/* hash and compare functions for userdata, used for dedup requests. */
|
||||
hash_func_t hash_func;
|
||||
compare_func_t compare_func;
|
||||
|
||||
/* Checks the request dependencies, and then processes this request, e.g. call address_configure().
|
||||
* Return 1 when processed, 0 when its dependencies not resolved, and negative errno on failure. */
|
||||
request_process_func_t process;
|
||||
|
||||
/* incremented when requested, decremented when request is completed or failed. */
|
||||
unsigned *counter;
|
||||
/* called in netlink handler, the 'counter' is decremented before this is called.
|
||||
* If this is specified, then the 'process' function must increment the reference of this
|
||||
* request, and pass this request to the netlink_call_async(), and set the destroy function
|
||||
* to the slot. */
|
||||
request_netlink_handler_t netlink_handler;
|
||||
};
|
||||
|
||||
Request *request_ref(Request *req);
|
||||
Request *request_unref(Request *req);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(Request*, request_unref);
|
||||
|
||||
void request_detach(Manager *manager, Request *req);
|
||||
void request_drop(Request *req);
|
||||
|
||||
int netdev_queue_request(
|
||||
NetDev *netdev,
|
||||
request_process_func_t process,
|
||||
Request **ret);
|
||||
|
||||
int link_queue_request_full(
|
||||
int link_queue_request(
|
||||
Link *link,
|
||||
RequestType type,
|
||||
void *userdata,
|
||||
mfree_func_t free_func,
|
||||
hash_func_t hash_func,
|
||||
compare_func_t compare_func,
|
||||
request_process_func_t process,
|
||||
unsigned *counter,
|
||||
request_netlink_handler_t netlink_handler,
|
||||
void *object,
|
||||
bool consume_object,
|
||||
unsigned *message_counter,
|
||||
link_netlink_message_handler_t netlink_handler,
|
||||
Request **ret);
|
||||
|
||||
static inline int link_queue_request(
|
||||
Link *link,
|
||||
RequestType type,
|
||||
request_process_func_t process,
|
||||
Request **ret) {
|
||||
|
||||
return link_queue_request_full(link, type, NULL, NULL, NULL, NULL,
|
||||
process, NULL, NULL, ret);
|
||||
}
|
||||
|
||||
#define link_queue_request_safe(link, type, userdata, free_func, hash_func, compare_func, process, counter, netlink_handler, ret) \
|
||||
({ \
|
||||
typeof(userdata) (*_f)(typeof(userdata)) = (free_func); \
|
||||
void (*_h)(const typeof(*userdata)*, struct siphash*) = (hash_func); \
|
||||
int (*_c)(const typeof(*userdata)*, const typeof(*userdata)*) = (compare_func); \
|
||||
int (*_p)(Request*, Link*, typeof(userdata)) = (process); \
|
||||
int (*_n)(sd_netlink*, sd_netlink_message*, Request*, Link*, typeof(userdata)) = (netlink_handler); \
|
||||
\
|
||||
link_queue_request_full(link, type, userdata, \
|
||||
(mfree_func_t) _f, \
|
||||
(hash_func_t) _h, \
|
||||
(compare_func_t) _c, \
|
||||
(request_process_func_t) _p, \
|
||||
counter, \
|
||||
(request_netlink_handler_t) _n, \
|
||||
ret); \
|
||||
})
|
||||
|
||||
int manager_process_requests(sd_event_source *s, void *userdata);
|
||||
int request_call_netlink_async(sd_netlink *nl, sd_netlink_message *m, Request *req);
|
||||
|
||||
const char* request_type_to_string(RequestType t) _const_;
|
||||
|
||||
@ -582,10 +582,15 @@ static int radv_is_ready_to_configure(Link *link) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static int radv_process_request(Request *req, Link *link, void *userdata) {
|
||||
int request_process_radv(Request *req) {
|
||||
Link *link;
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
assert(req);
|
||||
assert(req->link);
|
||||
assert(req->type == REQUEST_TYPE_RADV);
|
||||
|
||||
link = req->link;
|
||||
|
||||
r = radv_is_ready_to_configure(link);
|
||||
if (r <= 0)
|
||||
@ -617,7 +622,7 @@ int link_request_radv(Link *link) {
|
||||
if (link->radv)
|
||||
return 0;
|
||||
|
||||
r = link_queue_request(link, REQUEST_TYPE_RADV, radv_process_request, NULL);
|
||||
r = link_queue_request(link, REQUEST_TYPE_RADV, NULL, false, NULL, NULL, NULL);
|
||||
if (r < 0)
|
||||
return log_link_warning_errno(link, r, "Failed to request configuring of the IPv6 Router Advertisement engine: %m");
|
||||
|
||||
|
||||
@ -16,6 +16,7 @@
|
||||
|
||||
typedef struct Link Link;
|
||||
typedef struct Network Network;
|
||||
typedef struct Request Request;
|
||||
|
||||
typedef enum RADVPrefixDelegation {
|
||||
RADV_PREFIX_DELEGATION_NONE = 0,
|
||||
@ -67,6 +68,7 @@ int radv_update_mac(Link *link);
|
||||
int radv_add_prefix(Link *link, const struct in6_addr *prefix, uint8_t prefix_len,
|
||||
usec_t lifetime_preferred_usec, usec_t lifetime_valid_usec);
|
||||
|
||||
int request_process_radv(Request *req);
|
||||
int link_request_radv(Link *link);
|
||||
|
||||
const char* radv_prefix_delegation_to_string(RADVPrefixDelegation i) _const_;
|
||||
|
||||
@ -110,7 +110,7 @@ Route *route_free(Route *route) {
|
||||
return mfree(route);
|
||||
}
|
||||
|
||||
static void route_hash_func(const Route *route, struct siphash *state) {
|
||||
void route_hash_func(const Route *route, struct siphash *state) {
|
||||
assert(route);
|
||||
|
||||
siphash24_compress(&route->family, sizeof(route->family), state);
|
||||
@ -152,7 +152,7 @@ static void route_hash_func(const Route *route, struct siphash *state) {
|
||||
}
|
||||
}
|
||||
|
||||
static int route_compare_func(const Route *a, const Route *b) {
|
||||
int route_compare_func(const Route *a, const Route *b) {
|
||||
int r;
|
||||
|
||||
r = CMP(a->family, b->family);
|
||||
@ -1141,6 +1141,9 @@ int route_configure_handler_internal(sd_netlink *rtnl, sd_netlink_message *m, Li
|
||||
assert(link);
|
||||
assert(error_msg);
|
||||
|
||||
if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
|
||||
return 0;
|
||||
|
||||
r = sd_netlink_message_get_errno(m);
|
||||
if (r < 0 && r != -EEXIST) {
|
||||
log_link_message_warning_errno(link, m, r, "Could not set route");
|
||||
@ -1151,7 +1154,11 @@ int route_configure_handler_internal(sd_netlink *rtnl, sd_netlink_message *m, Li
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int route_configure(const Route *route, Link *link, Request *req) {
|
||||
static int route_configure(
|
||||
const Route *route,
|
||||
Link *link,
|
||||
link_netlink_message_handler_t callback) {
|
||||
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
|
||||
int r;
|
||||
|
||||
@ -1161,7 +1168,7 @@ static int route_configure(const Route *route, Link *link, Request *req) {
|
||||
assert(link->manager);
|
||||
assert(link->manager->rtnl);
|
||||
assert(link->ifindex > 0);
|
||||
assert(req);
|
||||
assert(callback);
|
||||
|
||||
log_route_debug(route, "Configuring", link, link->manager);
|
||||
|
||||
@ -1243,7 +1250,13 @@ static int route_configure(const Route *route, Link *link, Request *req) {
|
||||
return r;
|
||||
}
|
||||
|
||||
return request_call_netlink_async(link->manager->rtnl, m, req);
|
||||
r = netlink_call_async(link->manager->rtnl, NULL, m, callback,
|
||||
link_netlink_destroy_callback, link);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
link_ref(link);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int route_is_ready_to_configure(const Route *route, Link *link) {
|
||||
@ -1310,13 +1323,19 @@ static int route_is_ready_to_configure(const Route *route, Link *link) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static int route_process_request(Request *req, Link *link, Route *route) {
|
||||
int request_process_route(Request *req) {
|
||||
_cleanup_(converted_routes_freep) ConvertedRoutes *converted = NULL;
|
||||
Route *route;
|
||||
Link *link;
|
||||
int r;
|
||||
|
||||
assert(req);
|
||||
assert(link);
|
||||
assert(route);
|
||||
assert(req->link);
|
||||
assert(req->route);
|
||||
assert(req->type == REQUEST_TYPE_ROUTE);
|
||||
|
||||
link = req->link;
|
||||
route = req->route;
|
||||
|
||||
r = route_is_ready_to_configure(route, link);
|
||||
if (r < 0)
|
||||
@ -1354,7 +1373,7 @@ static int route_process_request(Request *req, Link *link, Route *route) {
|
||||
}
|
||||
}
|
||||
|
||||
r = route_configure(route, link, req);
|
||||
r = route_configure(route, link, req->netlink_handler);
|
||||
if (r < 0)
|
||||
return log_link_warning_errno(link, r, "Failed to configure route: %m");
|
||||
|
||||
@ -1376,7 +1395,7 @@ int link_request_route(
|
||||
Route *route,
|
||||
bool consume_object,
|
||||
unsigned *message_counter,
|
||||
route_netlink_handler_t netlink_handler,
|
||||
link_netlink_message_handler_t netlink_handler,
|
||||
Request **ret) {
|
||||
|
||||
Route *existing;
|
||||
@ -1423,12 +1442,8 @@ int link_request_route(
|
||||
}
|
||||
|
||||
log_route_debug(existing, "Requesting", link, link->manager);
|
||||
r = link_queue_request_safe(link, REQUEST_TYPE_ROUTE,
|
||||
existing, NULL,
|
||||
route_hash_func,
|
||||
route_compare_func,
|
||||
route_process_request,
|
||||
message_counter, netlink_handler, ret);
|
||||
r = link_queue_request(link, REQUEST_TYPE_ROUTE, existing, false,
|
||||
message_counter, netlink_handler, ret);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
|
||||
@ -1436,10 +1451,13 @@ int link_request_route(
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int static_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, Route *route) {
|
||||
static int static_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
assert(link->static_route_messages > 0);
|
||||
|
||||
link->static_route_messages--;
|
||||
|
||||
r = route_configure_handler_internal(rtnl, m, link, "Could not set route");
|
||||
if (r <= 0)
|
||||
@ -1464,10 +1482,8 @@ static int link_request_static_route(Link *link, Route *route) {
|
||||
static_route_handler, NULL);
|
||||
|
||||
log_route_debug(route, "Requesting", link, link->manager);
|
||||
return link_queue_request_safe(link, REQUEST_TYPE_ROUTE,
|
||||
route, NULL, route_hash_func, route_compare_func,
|
||||
route_process_request,
|
||||
&link->static_route_messages, static_route_handler, NULL);
|
||||
return link_queue_request(link, REQUEST_TYPE_ROUTE, route, false,
|
||||
&link->static_route_messages, static_route_handler, NULL);
|
||||
}
|
||||
|
||||
static int link_request_wireguard_routes(Link *link, bool only_ipv4) {
|
||||
@ -1551,12 +1567,10 @@ void route_cancel_request(Route *route, Link *link) {
|
||||
req = (Request) {
|
||||
.link = link,
|
||||
.type = REQUEST_TYPE_ROUTE,
|
||||
.userdata = route,
|
||||
.hash_func = (hash_func_t) route_hash_func,
|
||||
.compare_func = (compare_func_t) route_compare_func,
|
||||
.route = route,
|
||||
};
|
||||
|
||||
request_detach(link->manager, &req);
|
||||
request_drop(ordered_set_get(link->manager->request_queue, &req));
|
||||
route_cancel_requesting(route);
|
||||
}
|
||||
|
||||
|
||||
@ -14,15 +14,8 @@
|
||||
typedef struct Manager Manager;
|
||||
typedef struct Network Network;
|
||||
typedef struct Request Request;
|
||||
typedef struct Route Route;
|
||||
typedef int (*route_netlink_handler_t)(
|
||||
sd_netlink *rtnl,
|
||||
sd_netlink_message *m,
|
||||
Request *req,
|
||||
Link *link,
|
||||
Route *route);
|
||||
|
||||
struct Route {
|
||||
typedef struct Route {
|
||||
Link *link;
|
||||
Manager *manager;
|
||||
Network *network;
|
||||
@ -73,8 +66,10 @@ struct Route {
|
||||
usec_t lifetime_usec;
|
||||
/* Used when kernel does not support RTA_EXPIRES attribute. */
|
||||
sd_event_source *expire;
|
||||
};
|
||||
} Route;
|
||||
|
||||
void route_hash_func(const Route *route, struct siphash *state);
|
||||
int route_compare_func(const Route *a, const Route *b);
|
||||
extern const struct hash_ops route_hash_ops;
|
||||
|
||||
int route_new(Route **ret);
|
||||
@ -97,9 +92,10 @@ int link_request_route(
|
||||
Route *route,
|
||||
bool consume_object,
|
||||
unsigned *message_counter,
|
||||
route_netlink_handler_t netlink_handler,
|
||||
link_netlink_message_handler_t netlink_handler,
|
||||
Request **ret);
|
||||
int link_request_static_routes(Link *link, bool only_ipv4);
|
||||
int request_process_route(Request *req);
|
||||
|
||||
int manager_rtnl_process_route(sd_netlink *rtnl, sd_netlink_message *message, Manager *m);
|
||||
|
||||
|
||||
@ -153,7 +153,7 @@ static int routing_policy_rule_dup(const RoutingPolicyRule *src, RoutingPolicyRu
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void routing_policy_rule_hash_func(const RoutingPolicyRule *rule, struct siphash *state) {
|
||||
void routing_policy_rule_hash_func(const RoutingPolicyRule *rule, struct siphash *state) {
|
||||
assert(rule);
|
||||
|
||||
siphash24_compress(&rule->family, sizeof(rule->family), state);
|
||||
@ -194,7 +194,7 @@ static void routing_policy_rule_hash_func(const RoutingPolicyRule *rule, struct
|
||||
}
|
||||
}
|
||||
|
||||
static int routing_policy_rule_compare_func(const RoutingPolicyRule *a, const RoutingPolicyRule *b) {
|
||||
int routing_policy_rule_compare_func(const RoutingPolicyRule *a, const RoutingPolicyRule *b) {
|
||||
int r;
|
||||
|
||||
r = CMP(a->family, b->family);
|
||||
@ -604,7 +604,11 @@ static int routing_policy_rule_remove(RoutingPolicyRule *rule) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int routing_policy_rule_configure(RoutingPolicyRule *rule, Link *link, Request *req) {
|
||||
static int routing_policy_rule_configure(
|
||||
RoutingPolicyRule *rule,
|
||||
Link *link,
|
||||
link_netlink_message_handler_t callback) {
|
||||
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
|
||||
int r;
|
||||
|
||||
@ -614,7 +618,7 @@ static int routing_policy_rule_configure(RoutingPolicyRule *rule, Link *link, Re
|
||||
assert(link->ifindex > 0);
|
||||
assert(link->manager);
|
||||
assert(link->manager->rtnl);
|
||||
assert(req);
|
||||
assert(callback);
|
||||
|
||||
log_routing_policy_rule_debug(rule, "Configuring", link, link->manager);
|
||||
|
||||
@ -626,7 +630,13 @@ static int routing_policy_rule_configure(RoutingPolicyRule *rule, Link *link, Re
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return request_call_netlink_async(link->manager->rtnl, m, req);
|
||||
r = netlink_call_async(link->manager->rtnl, NULL, m, callback,
|
||||
link_netlink_destroy_callback, link);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
link_ref(link);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void manager_mark_routing_policy_rules(Manager *m, bool foreign, const Link *except) {
|
||||
@ -718,17 +728,21 @@ void link_foreignize_routing_policy_rules(Link *link) {
|
||||
}
|
||||
}
|
||||
|
||||
static int routing_policy_rule_process_request(Request *req, Link *link, RoutingPolicyRule *rule) {
|
||||
int request_process_routing_policy_rule(Request *req) {
|
||||
RoutingPolicyRule *rule;
|
||||
Link *link;
|
||||
int r;
|
||||
|
||||
assert(req);
|
||||
assert(link);
|
||||
assert(rule);
|
||||
assert(req->type == REQUEST_TYPE_ROUTING_POLICY_RULE);
|
||||
|
||||
link = ASSERT_PTR(req->link);
|
||||
rule = ASSERT_PTR(req->rule);
|
||||
|
||||
if (!link_is_ready_to_configure(link, false))
|
||||
return 0;
|
||||
|
||||
r = routing_policy_rule_configure(rule, link, req);
|
||||
r = routing_policy_rule_configure(rule, link, req->netlink_handler);
|
||||
if (r < 0)
|
||||
return log_link_warning_errno(link, r, "Failed to configure routing policy rule: %m");
|
||||
|
||||
@ -736,17 +750,19 @@ static int routing_policy_rule_process_request(Request *req, Link *link, Routing
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int static_routing_policy_rule_configure_handler(
|
||||
sd_netlink *rtnl,
|
||||
sd_netlink_message *m,
|
||||
Request *req,
|
||||
Link *link,
|
||||
RoutingPolicyRule *rule) {
|
||||
|
||||
static int static_routing_policy_rule_configure_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
|
||||
int r;
|
||||
|
||||
assert(rtnl);
|
||||
assert(m);
|
||||
assert(link);
|
||||
assert(link->ifname);
|
||||
assert(link->static_routing_policy_rule_messages > 0);
|
||||
|
||||
link->static_routing_policy_rule_messages--;
|
||||
|
||||
if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
|
||||
return 1;
|
||||
|
||||
r = sd_netlink_message_get_errno(m);
|
||||
if (r < 0 && r != -EEXIST) {
|
||||
@ -764,7 +780,13 @@ static int static_routing_policy_rule_configure_handler(
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int link_request_routing_policy_rule(Link *link, RoutingPolicyRule *rule) {
|
||||
static int link_request_routing_policy_rule(
|
||||
Link *link,
|
||||
RoutingPolicyRule *rule,
|
||||
unsigned *message_counter,
|
||||
link_netlink_message_handler_t netlink_handler,
|
||||
Request **ret) {
|
||||
|
||||
RoutingPolicyRule *existing;
|
||||
int r;
|
||||
|
||||
@ -793,14 +815,8 @@ static int link_request_routing_policy_rule(Link *link, RoutingPolicyRule *rule)
|
||||
existing->source = rule->source;
|
||||
|
||||
log_routing_policy_rule_debug(existing, "Requesting", link, link->manager);
|
||||
r = link_queue_request_safe(link, REQUEST_TYPE_ROUTING_POLICY_RULE,
|
||||
existing, NULL,
|
||||
routing_policy_rule_hash_func,
|
||||
routing_policy_rule_compare_func,
|
||||
routing_policy_rule_process_request,
|
||||
&link->static_routing_policy_rule_messages,
|
||||
static_routing_policy_rule_configure_handler,
|
||||
NULL);
|
||||
r = link_queue_request(link, REQUEST_TYPE_ROUTING_POLICY_RULE, existing, false,
|
||||
message_counter, netlink_handler, ret);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
|
||||
@ -812,17 +828,26 @@ static int link_request_static_routing_policy_rule(Link *link, RoutingPolicyRule
|
||||
int r;
|
||||
|
||||
if (IN_SET(rule->family, AF_INET, AF_INET6))
|
||||
return link_request_routing_policy_rule(link, rule);
|
||||
return link_request_routing_policy_rule(link, rule,
|
||||
&link->static_routing_policy_rule_messages,
|
||||
static_routing_policy_rule_configure_handler,
|
||||
NULL);
|
||||
|
||||
rule->family = AF_INET;
|
||||
r = link_request_routing_policy_rule(link, rule);
|
||||
r = link_request_routing_policy_rule(link, rule,
|
||||
&link->static_routing_policy_rule_messages,
|
||||
static_routing_policy_rule_configure_handler,
|
||||
NULL);
|
||||
if (r < 0) {
|
||||
rule->family = AF_UNSPEC;
|
||||
return r;
|
||||
}
|
||||
|
||||
rule->family = AF_INET6;
|
||||
r = link_request_routing_policy_rule(link, rule);
|
||||
r = link_request_routing_policy_rule(link, rule,
|
||||
&link->static_routing_policy_rule_messages,
|
||||
static_routing_policy_rule_configure_handler,
|
||||
NULL);
|
||||
rule->family = AF_UNSPEC;
|
||||
return r;
|
||||
}
|
||||
|
||||
@ -12,6 +12,7 @@
|
||||
typedef struct Link Link;
|
||||
typedef struct Manager Manager;
|
||||
typedef struct Network Network;
|
||||
typedef struct Request Request;
|
||||
|
||||
typedef struct RoutingPolicyRule {
|
||||
Manager *manager;
|
||||
@ -57,9 +58,13 @@ const char *fr_act_type_full_to_string(int t) _const_;
|
||||
|
||||
RoutingPolicyRule *routing_policy_rule_free(RoutingPolicyRule *rule);
|
||||
|
||||
void routing_policy_rule_hash_func(const RoutingPolicyRule *rule, struct siphash *state);
|
||||
int routing_policy_rule_compare_func(const RoutingPolicyRule *a, const RoutingPolicyRule *b);
|
||||
|
||||
void network_drop_invalid_routing_policy_rules(Network *network);
|
||||
|
||||
int link_request_static_routing_policy_rules(Link *link);
|
||||
int request_process_routing_policy_rule(Request *req);
|
||||
|
||||
int manager_rtnl_process_rule(sd_netlink *rtnl, sd_netlink_message *message, Manager *m);
|
||||
int manager_drop_routing_policy_rules_internal(Manager *m, bool foreign, const Link *except);
|
||||
|
||||
@ -14,6 +14,23 @@
|
||||
#include "networkd-manager.h"
|
||||
#include "networkd-queue.h"
|
||||
#include "networkd-setlink.h"
|
||||
#include "string-table.h"
|
||||
|
||||
static const char *const set_link_operation_table[_SET_LINK_OPERATION_MAX] = {
|
||||
[SET_LINK_ADDRESS_GENERATION_MODE] = "IPv6LL address generation mode",
|
||||
[SET_LINK_BOND] = "bond configurations",
|
||||
[SET_LINK_BRIDGE] = "bridge configurations",
|
||||
[SET_LINK_BRIDGE_VLAN] = "bridge VLAN configurations",
|
||||
[SET_LINK_CAN] = "CAN interface configurations",
|
||||
[SET_LINK_FLAGS] = "link flags",
|
||||
[SET_LINK_GROUP] = "interface group",
|
||||
[SET_LINK_IPOIB] = "IPoIB configurations",
|
||||
[SET_LINK_MAC] = "MAC address",
|
||||
[SET_LINK_MASTER] = "master interface",
|
||||
[SET_LINK_MTU] = "MTU",
|
||||
};
|
||||
|
||||
DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(set_link_operation, SetLinkOperation);
|
||||
|
||||
static int get_link_default_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
|
||||
return link_getlink_handler_internal(rtnl, m, link, "Failed to sync link information");
|
||||
@ -37,36 +54,42 @@ static int get_link_update_flag_handler(sd_netlink *rtnl, sd_netlink_message *m,
|
||||
static int set_link_handler_internal(
|
||||
sd_netlink *rtnl,
|
||||
sd_netlink_message *m,
|
||||
Request *req,
|
||||
Link *link,
|
||||
SetLinkOperation op,
|
||||
bool ignore,
|
||||
link_netlink_message_handler_t get_link_handler) {
|
||||
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
assert(req);
|
||||
assert(link);
|
||||
assert(link->set_link_messages > 0);
|
||||
assert(op >= 0 && op < _SET_LINK_OPERATION_MAX);
|
||||
|
||||
link->set_link_messages--;
|
||||
|
||||
if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
|
||||
goto on_error;
|
||||
|
||||
r = sd_netlink_message_get_errno(m);
|
||||
if (r < 0) {
|
||||
const char *error_msg;
|
||||
|
||||
error_msg = strjoina("Failed to set ", request_type_to_string(req->type), ignore ? ", ignoring" : "");
|
||||
error_msg = strjoina("Failed to set ", set_link_operation_to_string(op), ignore ? ", ignoring" : "");
|
||||
log_link_message_warning_errno(link, m, r, error_msg);
|
||||
|
||||
if (!ignore)
|
||||
link_enter_failed(link);
|
||||
return 0;
|
||||
goto on_error;
|
||||
}
|
||||
|
||||
log_link_debug(link, "%s set.", request_type_to_string(req->type));
|
||||
log_link_debug(link, "%s set.", set_link_operation_to_string(op));
|
||||
|
||||
if (get_link_handler) {
|
||||
r = link_call_getlink(link, get_link_handler);
|
||||
if (r < 0) {
|
||||
link_enter_failed(link);
|
||||
return 0;
|
||||
goto on_error;
|
||||
}
|
||||
}
|
||||
|
||||
@ -74,12 +97,27 @@ static int set_link_handler_internal(
|
||||
link_check_ready(link);
|
||||
|
||||
return 1;
|
||||
|
||||
on_error:
|
||||
switch (op) {
|
||||
case SET_LINK_FLAGS:
|
||||
assert(link->set_flags_messages > 0);
|
||||
link->set_flags_messages--;
|
||||
break;
|
||||
case SET_LINK_MASTER:
|
||||
link->master_set = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int link_set_addrgen_mode_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, void *userdata) {
|
||||
static int link_set_addrgen_mode_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
|
||||
int r;
|
||||
|
||||
r = set_link_handler_internal(rtnl, m, req, link, /* ignore = */ true, NULL);
|
||||
r = set_link_handler_internal(rtnl, m, link, SET_LINK_ADDRESS_GENERATION_MODE, /* ignore = */ true, NULL);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
|
||||
@ -92,43 +130,49 @@ static int link_set_addrgen_mode_handler(sd_netlink *rtnl, sd_netlink_message *m
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int link_set_bond_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, void *userdata) {
|
||||
return set_link_handler_internal(rtnl, m, req, link, /* ignore = */ false, NULL);
|
||||
static int link_set_bond_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
|
||||
return set_link_handler_internal(rtnl, m, link, SET_LINK_BOND, /* ignore = */ false, NULL);
|
||||
}
|
||||
|
||||
static int link_set_bridge_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, void *userdata) {
|
||||
return set_link_handler_internal(rtnl, m, req, link, /* ignore = */ true, NULL);
|
||||
static int link_set_bridge_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
|
||||
return set_link_handler_internal(rtnl, m, link, SET_LINK_BRIDGE, /* ignore = */ true, NULL);
|
||||
}
|
||||
|
||||
static int link_set_bridge_vlan_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, void *userdata) {
|
||||
return set_link_handler_internal(rtnl, m, req, link, /* ignore = */ false, NULL);
|
||||
static int link_set_bridge_vlan_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
|
||||
return set_link_handler_internal(rtnl, m, link, SET_LINK_BRIDGE_VLAN, /* ignore = */ false, NULL);
|
||||
}
|
||||
|
||||
static int link_set_can_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, void *userdata) {
|
||||
return set_link_handler_internal(rtnl, m, req, link, /* ignore = */ false, NULL);
|
||||
static int link_set_can_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
|
||||
return set_link_handler_internal(rtnl, m, link, SET_LINK_CAN, /* ignore = */ false, NULL);
|
||||
}
|
||||
|
||||
static int link_set_flags_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, void *userdata) {
|
||||
return set_link_handler_internal(rtnl, m, req, link, /* ignore = */ false, get_link_default_handler);
|
||||
static int link_set_flags_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
|
||||
return set_link_handler_internal(rtnl, m, link, SET_LINK_FLAGS, /* ignore = */ false, get_link_update_flag_handler);
|
||||
}
|
||||
|
||||
static int link_set_group_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, void *userdata) {
|
||||
return set_link_handler_internal(rtnl, m, req, link, /* ignore = */ false, NULL);
|
||||
static int link_set_group_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
|
||||
return set_link_handler_internal(rtnl, m, link, SET_LINK_GROUP, /* ignore = */ false, NULL);
|
||||
}
|
||||
|
||||
static int link_set_ipoib_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, void *userdata) {
|
||||
return set_link_handler_internal(rtnl, m, req, link, /* ignore = */ true, NULL);
|
||||
static int link_set_ipoib_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
|
||||
return set_link_handler_internal(rtnl, m, link, SET_LINK_IPOIB, /* ignore = */ true, NULL);
|
||||
}
|
||||
|
||||
static int link_set_mac_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, void *userdata) {
|
||||
return set_link_handler_internal(rtnl, m, req, link, /* ignore = */ true, get_link_default_handler);
|
||||
static int link_set_mac_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
|
||||
return set_link_handler_internal(rtnl, m, link, SET_LINK_MAC, /* ignore = */ true, get_link_default_handler);
|
||||
}
|
||||
|
||||
static int link_set_mac_allow_retry_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, void *userdata) {
|
||||
static int link_set_mac_allow_retry_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
assert(link);
|
||||
assert(link->set_link_messages > 0);
|
||||
|
||||
link->set_link_messages--;
|
||||
|
||||
if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
|
||||
return 0;
|
||||
|
||||
r = sd_netlink_message_get_errno(m);
|
||||
if (r == -EBUSY) {
|
||||
@ -145,22 +189,24 @@ static int link_set_mac_allow_retry_handler(sd_netlink *rtnl, sd_netlink_message
|
||||
return 0;
|
||||
}
|
||||
|
||||
return link_set_mac_handler(rtnl, m, req, link, userdata);
|
||||
/* set_link_mac_handler() also decrements set_link_messages, so increment the value once. */
|
||||
link->set_link_messages++;
|
||||
return link_set_mac_handler(rtnl, m, link);
|
||||
}
|
||||
|
||||
static int link_set_master_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, void *userdata) {
|
||||
return set_link_handler_internal(rtnl, m, req, link, /* ignore = */ false, get_link_master_handler);
|
||||
static int link_set_master_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
|
||||
return set_link_handler_internal(rtnl, m, link, SET_LINK_MASTER, /* ignore = */ false, get_link_master_handler);
|
||||
}
|
||||
|
||||
static int link_unset_master_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, void *userdata) {
|
||||
static int link_unset_master_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
|
||||
/* Some devices do not support setting master ifindex. Let's ignore error on unsetting master ifindex. */
|
||||
return set_link_handler_internal(rtnl, m, req, link, /* ignore = */ true, get_link_master_handler);
|
||||
return set_link_handler_internal(rtnl, m, link, SET_LINK_MASTER, /* ignore = */ true, get_link_master_handler);
|
||||
}
|
||||
|
||||
static int link_set_mtu_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, void *userdata) {
|
||||
static int link_set_mtu_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
|
||||
int r;
|
||||
|
||||
r = set_link_handler_internal(rtnl, m, req, link, /* ignore = */ true, get_link_default_handler);
|
||||
r = set_link_handler_internal(rtnl, m, link, SET_LINK_MTU, /* ignore = */ true, get_link_default_handler);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
|
||||
@ -176,17 +222,17 @@ static int link_set_mtu_handler(sd_netlink *rtnl, sd_netlink_message *m, Request
|
||||
static int link_configure_fill_message(
|
||||
Link *link,
|
||||
sd_netlink_message *req,
|
||||
RequestType type,
|
||||
SetLinkOperation op,
|
||||
void *userdata) {
|
||||
int r;
|
||||
|
||||
switch (type) {
|
||||
case REQUEST_TYPE_SET_LINK_ADDRESS_GENERATION_MODE:
|
||||
switch (op) {
|
||||
case SET_LINK_ADDRESS_GENERATION_MODE:
|
||||
r = ipv6ll_addrgen_mode_fill_message(req, PTR_TO_UINT8(userdata));
|
||||
if (r < 0)
|
||||
return r;
|
||||
break;
|
||||
case REQUEST_TYPE_SET_LINK_BOND:
|
||||
case SET_LINK_BOND:
|
||||
r = sd_netlink_message_set_flags(req, NLM_F_REQUEST | NLM_F_ACK);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@ -220,7 +266,7 @@ static int link_configure_fill_message(
|
||||
return r;
|
||||
|
||||
break;
|
||||
case REQUEST_TYPE_SET_LINK_BRIDGE:
|
||||
case SET_LINK_BRIDGE:
|
||||
r = sd_rtnl_message_link_set_family(req, AF_BRIDGE);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@ -323,7 +369,7 @@ static int link_configure_fill_message(
|
||||
if (r < 0)
|
||||
return r;
|
||||
break;
|
||||
case REQUEST_TYPE_SET_LINK_BRIDGE_VLAN:
|
||||
case SET_LINK_BRIDGE_VLAN:
|
||||
r = sd_rtnl_message_link_set_family(req, AF_BRIDGE);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@ -348,12 +394,12 @@ static int link_configure_fill_message(
|
||||
return r;
|
||||
|
||||
break;
|
||||
case REQUEST_TYPE_SET_LINK_CAN:
|
||||
case SET_LINK_CAN:
|
||||
r = can_set_netlink_message(link, req);
|
||||
if (r < 0)
|
||||
return r;
|
||||
break;
|
||||
case REQUEST_TYPE_SET_LINK_FLAGS: {
|
||||
case SET_LINK_FLAGS: {
|
||||
unsigned ifi_change = 0, ifi_flags = 0;
|
||||
|
||||
if (link->network->arp >= 0) {
|
||||
@ -382,27 +428,27 @@ static int link_configure_fill_message(
|
||||
|
||||
break;
|
||||
}
|
||||
case REQUEST_TYPE_SET_LINK_GROUP:
|
||||
case SET_LINK_GROUP:
|
||||
r = sd_netlink_message_append_u32(req, IFLA_GROUP, (uint32_t) link->network->group);
|
||||
if (r < 0)
|
||||
return r;
|
||||
break;
|
||||
case REQUEST_TYPE_SET_LINK_MAC:
|
||||
case SET_LINK_MAC:
|
||||
r = netlink_message_append_hw_addr(req, IFLA_ADDRESS, &link->requested_hw_addr);
|
||||
if (r < 0)
|
||||
return r;
|
||||
break;
|
||||
case REQUEST_TYPE_SET_LINK_IPOIB:
|
||||
case SET_LINK_IPOIB:
|
||||
r = ipoib_set_netlink_message(link, req);
|
||||
if (r < 0)
|
||||
return r;
|
||||
break;
|
||||
case REQUEST_TYPE_SET_LINK_MASTER:
|
||||
case SET_LINK_MASTER:
|
||||
r = sd_netlink_message_append_u32(req, IFLA_MASTER, PTR_TO_UINT32(userdata));
|
||||
if (r < 0)
|
||||
return r;
|
||||
break;
|
||||
case REQUEST_TYPE_SET_LINK_MTU:
|
||||
case SET_LINK_MTU:
|
||||
r = sd_netlink_message_append_u32(req, IFLA_MTU, PTR_TO_UINT32(userdata));
|
||||
if (r < 0)
|
||||
return r;
|
||||
@ -414,30 +460,44 @@ static int link_configure_fill_message(
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int link_configure(Link *link, Request *req) {
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
|
||||
static int link_configure(
|
||||
Link *link,
|
||||
SetLinkOperation op,
|
||||
void *userdata,
|
||||
link_netlink_message_handler_t callback) {
|
||||
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
assert(link->manager);
|
||||
assert(req);
|
||||
assert(link->manager->rtnl);
|
||||
assert(link->network);
|
||||
assert(op >= 0 && op < _SET_LINK_OPERATION_MAX);
|
||||
assert(callback);
|
||||
|
||||
log_link_debug(link, "Setting %s", request_type_to_string(req->type));
|
||||
log_link_debug(link, "Setting %s", set_link_operation_to_string(op));
|
||||
|
||||
if (req->type == REQUEST_TYPE_SET_LINK_BOND)
|
||||
r = sd_rtnl_message_new_link(link->manager->rtnl, &m, RTM_NEWLINK, link->master_ifindex);
|
||||
else if (IN_SET(req->type, REQUEST_TYPE_SET_LINK_CAN, REQUEST_TYPE_SET_LINK_IPOIB))
|
||||
r = sd_rtnl_message_new_link(link->manager->rtnl, &m, RTM_NEWLINK, link->ifindex);
|
||||
if (op == SET_LINK_BOND)
|
||||
r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_NEWLINK, link->master_ifindex);
|
||||
else if (IN_SET(op, SET_LINK_CAN, SET_LINK_IPOIB))
|
||||
r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_NEWLINK, link->ifindex);
|
||||
else
|
||||
r = sd_rtnl_message_new_link(link->manager->rtnl, &m, RTM_SETLINK, link->ifindex);
|
||||
r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_SETLINK, link->ifindex);
|
||||
if (r < 0)
|
||||
return r;
|
||||
return log_link_debug_errno(link, r, "Could not allocate netlink message: %m");
|
||||
|
||||
r = link_configure_fill_message(link, m, req->type, req->userdata);
|
||||
r = link_configure_fill_message(link, req, op, userdata);
|
||||
if (r < 0)
|
||||
return r;
|
||||
return log_link_debug_errno(link, r, "Could not create netlink message: %m");
|
||||
|
||||
return request_call_netlink_async(link->manager->rtnl, m, req);
|
||||
r = netlink_call_async(link->manager->rtnl, NULL, req, callback,
|
||||
link_netlink_destroy_callback, link);
|
||||
if (r < 0)
|
||||
return log_link_debug_errno(link, r, "Could not send netlink message: %m");
|
||||
|
||||
link_ref(link);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool netdev_is_ready(NetDev *netdev) {
|
||||
@ -451,63 +511,66 @@ static bool netdev_is_ready(NetDev *netdev) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static int link_is_ready_to_set_link(Link *link, Request *req) {
|
||||
static bool link_is_ready_to_call_set_link(Request *req) {
|
||||
SetLinkOperation op;
|
||||
Link *link;
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
assert(link->manager);
|
||||
assert(link->network);
|
||||
assert(req);
|
||||
assert(req->link);
|
||||
assert(req->link->manager);
|
||||
assert(req->link->network);
|
||||
|
||||
if (!IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED))
|
||||
link = req->link;
|
||||
op = PTR_TO_INT(req->set_link_operation_ptr);
|
||||
|
||||
if (!IN_SET(link->state, LINK_STATE_INITIALIZED, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED))
|
||||
return false;
|
||||
|
||||
switch (req->type) {
|
||||
case REQUEST_TYPE_SET_LINK_BOND:
|
||||
case REQUEST_TYPE_SET_LINK_BRIDGE:
|
||||
switch (op) {
|
||||
case SET_LINK_BOND:
|
||||
case SET_LINK_BRIDGE:
|
||||
if (!link->master_set)
|
||||
return false;
|
||||
|
||||
if (link->network->keep_master && link->master_ifindex <= 0)
|
||||
return false;
|
||||
break;
|
||||
|
||||
case REQUEST_TYPE_SET_LINK_BRIDGE_VLAN:
|
||||
case SET_LINK_BRIDGE_VLAN:
|
||||
if (!link->master_set)
|
||||
return false;
|
||||
|
||||
if (link->network->keep_master && link->master_ifindex <= 0 && !streq_ptr(link->kind, "bridge"))
|
||||
return false;
|
||||
|
||||
break;
|
||||
|
||||
case REQUEST_TYPE_SET_LINK_CAN:
|
||||
case SET_LINK_CAN:
|
||||
/* Do not check link->set_flgas_messages here, as it is ok even if link->flags
|
||||
* is outdated, and checking the counter causes a deadlock. */
|
||||
if (FLAGS_SET(link->flags, IFF_UP)) {
|
||||
/* The CAN interface must be down to configure bitrate, etc... */
|
||||
r = link_down_now(link);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r < 0) {
|
||||
link_enter_failed(link);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case REQUEST_TYPE_SET_LINK_MAC:
|
||||
case SET_LINK_MAC:
|
||||
if (req->netlink_handler == link_set_mac_handler) {
|
||||
/* This is the second attempt to set hardware address. On the first attempt
|
||||
* req->netlink_handler points to link_set_mac_allow_retry_handler().
|
||||
* The first attempt failed as the interface was up. */
|
||||
r = link_down_now(link);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r < 0) {
|
||||
link_enter_failed(link);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case REQUEST_TYPE_SET_LINK_MASTER: {
|
||||
case SET_LINK_MASTER: {
|
||||
uint32_t m = 0;
|
||||
Request req_mac = {
|
||||
.link = link,
|
||||
.type = REQUEST_TYPE_SET_LINK_MAC,
|
||||
.type = REQUEST_TYPE_SET_LINK,
|
||||
.set_link_operation_ptr = INT_TO_PTR(SET_LINK_MAC),
|
||||
};
|
||||
|
||||
if (link->network->batadv) {
|
||||
@ -526,8 +589,10 @@ static int link_is_ready_to_set_link(Link *link, Request *req) {
|
||||
if (FLAGS_SET(link->flags, IFF_UP)) {
|
||||
/* link must be down when joining to bond master. */
|
||||
r = link_down_now(link);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r < 0) {
|
||||
link_enter_failed(link);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else if (link->network->bridge) {
|
||||
if (ordered_set_contains(link->manager->request_queue, &req_mac))
|
||||
@ -544,10 +609,11 @@ static int link_is_ready_to_set_link(Link *link, Request *req) {
|
||||
req->userdata = UINT32_TO_PTR(m);
|
||||
break;
|
||||
}
|
||||
case REQUEST_TYPE_SET_LINK_MTU: {
|
||||
case SET_LINK_MTU: {
|
||||
Request req_ipoib = {
|
||||
.link = link,
|
||||
.type = REQUEST_TYPE_SET_LINK_IPOIB,
|
||||
.type = REQUEST_TYPE_SET_LINK,
|
||||
.set_link_operation_ptr = INT_TO_PTR(SET_LINK_IPOIB),
|
||||
};
|
||||
|
||||
return !ordered_set_contains(link->manager->request_queue, &req_ipoib);
|
||||
@ -559,44 +625,53 @@ static int link_is_ready_to_set_link(Link *link, Request *req) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static int link_process_set_link(Request *req, Link *link, void *userdata) {
|
||||
int request_process_set_link(Request *req) {
|
||||
SetLinkOperation op;
|
||||
int r;
|
||||
|
||||
assert(req);
|
||||
assert(link);
|
||||
assert(req->link);
|
||||
assert(req->type == REQUEST_TYPE_SET_LINK);
|
||||
assert(req->netlink_handler);
|
||||
|
||||
r = link_is_ready_to_set_link(link, req);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
op = PTR_TO_INT(req->set_link_operation_ptr);
|
||||
|
||||
r = link_configure(link, req);
|
||||
assert(op >= 0 && op < _SET_LINK_OPERATION_MAX);
|
||||
|
||||
if (!link_is_ready_to_call_set_link(req))
|
||||
return 0;
|
||||
|
||||
r = link_configure(req->link, op, req->userdata, req->netlink_handler);
|
||||
if (r < 0)
|
||||
return log_link_warning_errno(link, r, "Failed to set %s", request_type_to_string(req->type));
|
||||
return log_link_error_errno(req->link, r, "Failed to set %s: %m",
|
||||
set_link_operation_to_string(op));
|
||||
|
||||
if (op == SET_LINK_FLAGS)
|
||||
req->link->set_flags_messages++;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int link_request_set_link(
|
||||
Link *link,
|
||||
RequestType type,
|
||||
request_netlink_handler_t netlink_handler,
|
||||
SetLinkOperation op,
|
||||
link_netlink_message_handler_t netlink_handler,
|
||||
Request **ret) {
|
||||
|
||||
Request *req;
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
assert(op >= 0 && op < _SET_LINK_OPERATION_MAX);
|
||||
assert(netlink_handler);
|
||||
|
||||
r = link_queue_request_full(link, type, NULL, NULL, NULL, NULL,
|
||||
link_process_set_link,
|
||||
&link->set_link_messages,
|
||||
netlink_handler,
|
||||
&req);
|
||||
r = link_queue_request(link, REQUEST_TYPE_SET_LINK, INT_TO_PTR(op), false,
|
||||
&link->set_link_messages, netlink_handler, &req);
|
||||
if (r < 0)
|
||||
return log_link_warning_errno(link, r, "Failed to request to set %s: %m",
|
||||
request_type_to_string(type));
|
||||
return log_link_error_errno(link, r, "Failed to request to set %s: %m",
|
||||
set_link_operation_to_string(op));
|
||||
|
||||
log_link_debug(link, "Requested to set %s", request_type_to_string(type));
|
||||
log_link_debug(link, "Requested to set %s", set_link_operation_to_string(op));
|
||||
|
||||
if (ret)
|
||||
*ret = req;
|
||||
@ -632,9 +707,7 @@ int link_request_to_set_addrgen_mode(Link *link) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = link_request_set_link(link, REQUEST_TYPE_SET_LINK_ADDRESS_GENERATION_MODE,
|
||||
link_set_addrgen_mode_handler,
|
||||
&req);
|
||||
r = link_request_set_link(link, SET_LINK_ADDRESS_GENERATION_MODE, link_set_addrgen_mode_handler, &req);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -659,8 +732,7 @@ int link_request_to_set_bond(Link *link) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return link_request_set_link(link, REQUEST_TYPE_SET_LINK_BOND,
|
||||
link_set_bond_handler, NULL);
|
||||
return link_request_set_link(link, SET_LINK_BOND, link_set_bond_handler, NULL);
|
||||
}
|
||||
|
||||
int link_request_to_set_bridge(Link *link) {
|
||||
@ -680,9 +752,7 @@ int link_request_to_set_bridge(Link *link) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return link_request_set_link(link, REQUEST_TYPE_SET_LINK_BRIDGE,
|
||||
link_set_bridge_handler,
|
||||
NULL);
|
||||
return link_request_set_link(link, SET_LINK_BRIDGE, link_set_bridge_handler, NULL);
|
||||
}
|
||||
|
||||
int link_request_to_set_bridge_vlan(Link *link) {
|
||||
@ -705,9 +775,7 @@ int link_request_to_set_bridge_vlan(Link *link) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return link_request_set_link(link, REQUEST_TYPE_SET_LINK_BRIDGE_VLAN,
|
||||
link_set_bridge_vlan_handler,
|
||||
NULL);
|
||||
return link_request_set_link(link, SET_LINK_BRIDGE_VLAN, link_set_bridge_vlan_handler, NULL);
|
||||
}
|
||||
|
||||
int link_request_to_set_can(Link *link) {
|
||||
@ -720,9 +788,7 @@ int link_request_to_set_can(Link *link) {
|
||||
if (!streq_ptr(link->kind, "can"))
|
||||
return 0;
|
||||
|
||||
return link_request_set_link(link, REQUEST_TYPE_SET_LINK_CAN,
|
||||
link_set_can_handler,
|
||||
NULL);
|
||||
return link_request_set_link(link, SET_LINK_CAN, link_set_can_handler, NULL);
|
||||
}
|
||||
|
||||
int link_request_to_set_flags(Link *link) {
|
||||
@ -735,9 +801,7 @@ int link_request_to_set_flags(Link *link) {
|
||||
link->network->promiscuous < 0)
|
||||
return 0;
|
||||
|
||||
return link_request_set_link(link, REQUEST_TYPE_SET_LINK_FLAGS,
|
||||
link_set_flags_handler,
|
||||
NULL);
|
||||
return link_request_set_link(link, SET_LINK_FLAGS, link_set_flags_handler, NULL);
|
||||
}
|
||||
|
||||
int link_request_to_set_group(Link *link) {
|
||||
@ -747,9 +811,7 @@ int link_request_to_set_group(Link *link) {
|
||||
if (link->network->group < 0)
|
||||
return 0;
|
||||
|
||||
return link_request_set_link(link, REQUEST_TYPE_SET_LINK_GROUP,
|
||||
link_set_group_handler,
|
||||
NULL);
|
||||
return link_request_set_link(link, SET_LINK_GROUP, link_set_group_handler, NULL);
|
||||
}
|
||||
|
||||
int link_request_to_set_mac(Link *link, bool allow_retry) {
|
||||
@ -770,7 +832,7 @@ int link_request_to_set_mac(Link *link, bool allow_retry) {
|
||||
if (hw_addr_equal(&link->hw_addr, &link->requested_hw_addr))
|
||||
return 0;
|
||||
|
||||
return link_request_set_link(link, REQUEST_TYPE_SET_LINK_MAC,
|
||||
return link_request_set_link(link, SET_LINK_MAC,
|
||||
allow_retry ? link_set_mac_allow_retry_handler : link_set_mac_handler,
|
||||
NULL);
|
||||
}
|
||||
@ -786,9 +848,7 @@ int link_request_to_set_ipoib(Link *link) {
|
||||
link->network->ipoib_umcast < 0)
|
||||
return 0;
|
||||
|
||||
return link_request_set_link(link, REQUEST_TYPE_SET_LINK_IPOIB,
|
||||
link_set_ipoib_handler,
|
||||
NULL);
|
||||
return link_request_set_link(link, SET_LINK_IPOIB, link_set_ipoib_handler, NULL);
|
||||
}
|
||||
|
||||
int link_request_to_set_master(Link *link) {
|
||||
@ -803,19 +863,15 @@ int link_request_to_set_master(Link *link) {
|
||||
link->master_set = false;
|
||||
|
||||
if (link->network->batadv || link->network->bond || link->network->bridge || link->network->vrf)
|
||||
return link_request_set_link(link, REQUEST_TYPE_SET_LINK_MASTER,
|
||||
link_set_master_handler,
|
||||
NULL);
|
||||
return link_request_set_link(link, SET_LINK_MASTER, link_set_master_handler, NULL);
|
||||
else
|
||||
return link_request_set_link(link, REQUEST_TYPE_SET_LINK_MASTER,
|
||||
link_unset_master_handler,
|
||||
NULL);
|
||||
return link_request_set_link(link, SET_LINK_MASTER, link_unset_master_handler, NULL);
|
||||
}
|
||||
|
||||
int link_request_to_set_mtu(Link *link, uint32_t mtu) {
|
||||
Request *req;
|
||||
const char *origin;
|
||||
uint32_t min_mtu;
|
||||
Request *req;
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
@ -851,9 +907,7 @@ int link_request_to_set_mtu(Link *link, uint32_t mtu) {
|
||||
if (link->mtu == mtu)
|
||||
return 0;
|
||||
|
||||
r = link_request_set_link(link, REQUEST_TYPE_SET_LINK_MTU,
|
||||
link_set_mtu_handler,
|
||||
&req);
|
||||
r = link_request_set_link(link, SET_LINK_MTU, link_set_mtu_handler, &req);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -937,16 +991,14 @@ static int link_up_dsa_slave(Link *link) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int link_up_or_down_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, void *userdata) {
|
||||
bool on_activate, up;
|
||||
static int link_up_or_down_handler_internal(sd_netlink *rtnl, sd_netlink_message *m, Link *link, bool up, bool on_activate) {
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
assert(req);
|
||||
assert(link);
|
||||
|
||||
on_activate = req->type == REQUEST_TYPE_ACTIVATE_LINK;
|
||||
up = PTR_TO_INT(req->userdata);
|
||||
if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
|
||||
goto on_error;
|
||||
|
||||
r = sd_netlink_message_get_errno(m);
|
||||
if (r == -ENETDOWN && up && link_up_dsa_slave(link) > 0)
|
||||
@ -960,55 +1012,82 @@ static int link_up_or_down_handler(sd_netlink *rtnl, sd_netlink_message *m, Requ
|
||||
|
||||
log_link_message_warning_errno(link, m, r, error_msg);
|
||||
if (on_activate)
|
||||
return 0;
|
||||
goto on_error;
|
||||
}
|
||||
|
||||
r = link_call_getlink(link, get_link_update_flag_handler);
|
||||
if (r < 0) {
|
||||
link_enter_failed(link);
|
||||
return 0;
|
||||
goto on_error;
|
||||
}
|
||||
|
||||
link->set_flags_messages++;
|
||||
|
||||
if (on_activate) {
|
||||
link->activated = true;
|
||||
link_check_ready(link);
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
on_error:
|
||||
assert(link->set_flags_messages > 0);
|
||||
link->set_flags_messages--;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int link_activate_up_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
|
||||
return link_up_or_down_handler_internal(rtnl, m, link, /* up = */ true, /* on_activate = */ true);
|
||||
}
|
||||
|
||||
static int link_activate_down_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
|
||||
return link_up_or_down_handler_internal(rtnl, m, link, /* up = */ false, /* on_activate = */ true);
|
||||
}
|
||||
|
||||
static int link_up_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
|
||||
return link_up_or_down_handler_internal(rtnl, m, link, /* up = */ true, /* on_activate = */ false);
|
||||
}
|
||||
|
||||
static int link_down_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
|
||||
return link_up_or_down_handler_internal(rtnl, m, link, /* up = */ false, /* on_activate = */ false);
|
||||
}
|
||||
|
||||
static const char *up_or_down(bool up) {
|
||||
return up ? "up" : "down";
|
||||
}
|
||||
|
||||
static int link_up_or_down(Link *link, bool up, Request *req) {
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
|
||||
static int link_up_or_down(Link *link, bool up, link_netlink_message_handler_t callback) {
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
assert(link->manager);
|
||||
assert(link->manager->rtnl);
|
||||
assert(req);
|
||||
assert(callback);
|
||||
|
||||
log_link_debug(link, "Bringing link %s", up_or_down(up));
|
||||
|
||||
r = sd_rtnl_message_new_link(link->manager->rtnl, &m, RTM_SETLINK, link->ifindex);
|
||||
r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_SETLINK, link->ifindex);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_rtnl_message_link_set_flags(m, up ? IFF_UP : 0, IFF_UP);
|
||||
r = sd_rtnl_message_link_set_flags(req, up ? IFF_UP : 0, IFF_UP);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return request_call_netlink_async(link->manager->rtnl, m, req);
|
||||
r = netlink_call_async(link->manager->rtnl, NULL, req, callback,
|
||||
link_netlink_destroy_callback, link);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
link_ref(link);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool link_is_ready_to_activate(Link *link) {
|
||||
assert(link);
|
||||
|
||||
if (!IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED))
|
||||
if (!IN_SET(link->state, LINK_STATE_INITIALIZED, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED))
|
||||
return false;
|
||||
|
||||
if (link->set_link_messages > 0)
|
||||
@ -1017,17 +1096,23 @@ static bool link_is_ready_to_activate(Link *link) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static int link_process_activation(Request *req, Link *link, void *userdata) {
|
||||
bool up = PTR_TO_INT(userdata);
|
||||
int request_process_activation(Request *req) {
|
||||
Link *link;
|
||||
bool up;
|
||||
int r;
|
||||
|
||||
assert(req);
|
||||
assert(link);
|
||||
assert(req->link);
|
||||
assert(req->type == REQUEST_TYPE_ACTIVATE_LINK);
|
||||
assert(req->netlink_handler);
|
||||
|
||||
link = req->link;
|
||||
up = PTR_TO_INT(req->userdata);
|
||||
|
||||
if (!link_is_ready_to_activate(link))
|
||||
return 0;
|
||||
|
||||
r = link_up_or_down(link, up, req);
|
||||
r = link_up_or_down(link, up, req->netlink_handler);
|
||||
if (r < 0)
|
||||
return log_link_warning_errno(link, r, "Failed to activate link: %m");
|
||||
|
||||
@ -1035,6 +1120,7 @@ static int link_process_activation(Request *req, Link *link, void *userdata) {
|
||||
}
|
||||
|
||||
int link_request_to_activate(Link *link) {
|
||||
Request *req;
|
||||
bool up;
|
||||
int r;
|
||||
|
||||
@ -1065,14 +1151,13 @@ int link_request_to_activate(Link *link) {
|
||||
|
||||
link->activated = false;
|
||||
|
||||
r = link_queue_request_full(link, REQUEST_TYPE_ACTIVATE_LINK,
|
||||
INT_TO_PTR(up), NULL, NULL, NULL,
|
||||
link_process_activation,
|
||||
&link->set_flags_messages,
|
||||
link_up_or_down_handler, NULL);
|
||||
r = link_queue_request(link, REQUEST_TYPE_ACTIVATE_LINK, NULL, false, &link->set_flags_messages,
|
||||
up ? link_activate_up_handler : link_activate_down_handler, &req);
|
||||
if (r < 0)
|
||||
return log_link_error_errno(link, r, "Failed to request to activate link: %m");
|
||||
|
||||
req->userdata = INT_TO_PTR(up);
|
||||
|
||||
log_link_debug(link, "Requested to activate link");
|
||||
return 0;
|
||||
}
|
||||
@ -1107,17 +1192,22 @@ static bool link_is_ready_to_bring_up_or_down(Link *link, bool up) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static int link_process_up_or_down(Request *req, Link *link, void *userdata) {
|
||||
bool up = PTR_TO_INT(userdata);
|
||||
int request_process_link_up_or_down(Request *req) {
|
||||
Link *link;
|
||||
bool up;
|
||||
int r;
|
||||
|
||||
assert(req);
|
||||
assert(link);
|
||||
assert(req->link);
|
||||
assert(req->type == REQUEST_TYPE_UP_DOWN);
|
||||
|
||||
link = req->link;
|
||||
up = PTR_TO_INT(req->userdata);
|
||||
|
||||
if (!link_is_ready_to_bring_up_or_down(link, up))
|
||||
return 0;
|
||||
|
||||
r = link_up_or_down(link, up, req);
|
||||
r = link_up_or_down(link, up, req->netlink_handler);
|
||||
if (r < 0)
|
||||
return log_link_warning_errno(link, r, "Failed to bring link %s: %m", up_or_down(up));
|
||||
|
||||
@ -1125,19 +1215,19 @@ static int link_process_up_or_down(Request *req, Link *link, void *userdata) {
|
||||
}
|
||||
|
||||
int link_request_to_bring_up_or_down(Link *link, bool up) {
|
||||
Request *req;
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
|
||||
r = link_queue_request_full(link, REQUEST_TYPE_UP_DOWN,
|
||||
INT_TO_PTR(up), NULL, NULL, NULL,
|
||||
link_process_up_or_down,
|
||||
&link->set_flags_messages,
|
||||
link_up_or_down_handler, NULL);
|
||||
r = link_queue_request(link, REQUEST_TYPE_UP_DOWN, NULL, false, &link->set_flags_messages,
|
||||
up ? link_up_handler : link_down_handler, &req);
|
||||
if (r < 0)
|
||||
return log_link_warning_errno(link, r, "Failed to request to bring link %s: %m",
|
||||
up_or_down(up));
|
||||
|
||||
req->userdata = INT_TO_PTR(up);
|
||||
|
||||
log_link_debug(link, "Requested to bring link %s", up_or_down(up));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -2,9 +2,29 @@
|
||||
#pragma once
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
typedef struct Link Link;
|
||||
typedef struct Request Request;
|
||||
|
||||
typedef enum SetLinkOperation {
|
||||
SET_LINK_ADDRESS_GENERATION_MODE, /* Setting IPv6LL address generation mode. */
|
||||
SET_LINK_BOND, /* Setting bond configs. */
|
||||
SET_LINK_BRIDGE, /* Setting bridge configs. */
|
||||
SET_LINK_BRIDGE_VLAN, /* Setting bridge VLAN configs. */
|
||||
SET_LINK_CAN, /* Setting CAN interface configs. */
|
||||
SET_LINK_FLAGS, /* Setting IFF_NOARP or friends. */
|
||||
SET_LINK_GROUP, /* Setting interface group. */
|
||||
SET_LINK_IPOIB, /* Setting IPoIB configs. */
|
||||
SET_LINK_MAC, /* Setting MAC address. */
|
||||
SET_LINK_MASTER, /* Setting IFLA_MASTER. */
|
||||
SET_LINK_MTU, /* Setting MTU. */
|
||||
_SET_LINK_OPERATION_MAX,
|
||||
_SET_LINK_OPERATION_INVALID = -EINVAL,
|
||||
} SetLinkOperation;
|
||||
|
||||
/* SetLinkOperation is casted to int, then stored in void* with INT_TO_PTR(). */
|
||||
assert_cc(sizeof(SetLinkOperation) <= sizeof(void*));
|
||||
assert_cc(sizeof(SetLinkOperation) <= sizeof(int));
|
||||
|
||||
int link_request_to_set_addrgen_mode(Link *link);
|
||||
int link_request_to_set_bond(Link *link);
|
||||
@ -20,8 +40,12 @@ int link_request_to_set_mtu(Link *link, uint32_t mtu);
|
||||
|
||||
int link_configure_mtu(Link *link);
|
||||
|
||||
int request_process_set_link(Request *req);
|
||||
|
||||
int request_process_activation(Request *req);
|
||||
int link_request_to_activate(Link *link);
|
||||
|
||||
int request_process_link_up_or_down(Request *req);
|
||||
int link_request_to_bring_up_or_down(Link *link, bool up);
|
||||
|
||||
int link_down_now(Link *link);
|
||||
|
||||
@ -151,7 +151,7 @@ static const char *qdisc_get_tca_kind(const QDisc *qdisc) {
|
||||
QDISC_VTABLE(qdisc)->tca_kind : qdisc->tca_kind;
|
||||
}
|
||||
|
||||
static void qdisc_hash_func(const QDisc *qdisc, struct siphash *state) {
|
||||
void qdisc_hash_func(const QDisc *qdisc, struct siphash *state) {
|
||||
assert(qdisc);
|
||||
assert(state);
|
||||
|
||||
@ -160,7 +160,7 @@ static void qdisc_hash_func(const QDisc *qdisc, struct siphash *state) {
|
||||
siphash24_compress_string(qdisc_get_tca_kind(qdisc), state);
|
||||
}
|
||||
|
||||
static int qdisc_compare_func(const QDisc *a, const QDisc *b) {
|
||||
int qdisc_compare_func(const QDisc *a, const QDisc *b) {
|
||||
int r;
|
||||
|
||||
assert(a);
|
||||
@ -293,11 +293,15 @@ int link_find_qdisc(Link *link, uint32_t handle, uint32_t parent, const char *ki
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
static int qdisc_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, QDisc *qdisc) {
|
||||
static int qdisc_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
assert(link);
|
||||
assert(link->tc_messages > 0);
|
||||
link->tc_messages--;
|
||||
|
||||
if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
|
||||
return 1;
|
||||
|
||||
r = sd_netlink_message_get_errno(m);
|
||||
if (r < 0 && r != -EEXIST) {
|
||||
@ -315,7 +319,7 @@ static int qdisc_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req,
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int qdisc_configure(QDisc *qdisc, Link *link, Request *req) {
|
||||
static int qdisc_configure(QDisc *qdisc, Link *link) {
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
|
||||
int r;
|
||||
|
||||
@ -324,7 +328,6 @@ static int qdisc_configure(QDisc *qdisc, Link *link, Request *req) {
|
||||
assert(link->manager);
|
||||
assert(link->manager->rtnl);
|
||||
assert(link->ifindex > 0);
|
||||
assert(req);
|
||||
|
||||
log_qdisc_debug(qdisc, link, "Configuring");
|
||||
|
||||
@ -343,7 +346,12 @@ static int qdisc_configure(QDisc *qdisc, Link *link, Request *req) {
|
||||
return r;
|
||||
}
|
||||
|
||||
return request_call_netlink_async(link->manager->rtnl, m, req);
|
||||
r = netlink_call_async(link->manager->rtnl, NULL, m, qdisc_handler, link_netlink_destroy_callback, link);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
link_ref(link);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool qdisc_is_ready_to_configure(QDisc *qdisc, Link *link) {
|
||||
@ -359,17 +367,19 @@ static bool qdisc_is_ready_to_configure(QDisc *qdisc, Link *link) {
|
||||
return link_find_tclass(link, qdisc->parent, NULL) >= 0;
|
||||
}
|
||||
|
||||
static int qdisc_process_request(Request *req, Link *link, QDisc *qdisc) {
|
||||
int request_process_qdisc(Request *req) {
|
||||
QDisc *qdisc;
|
||||
Link *link;
|
||||
int r;
|
||||
|
||||
assert(req);
|
||||
assert(link);
|
||||
assert(qdisc);
|
||||
assert_se(link = req->link);
|
||||
assert_se(qdisc = req->qdisc);
|
||||
|
||||
if (!qdisc_is_ready_to_configure(qdisc, link))
|
||||
return 0;
|
||||
|
||||
r = qdisc_configure(qdisc, link, req);
|
||||
r = qdisc_configure(qdisc, link);
|
||||
if (r < 0)
|
||||
return log_link_warning_errno(link, r, "Failed to configure QDisc: %m");
|
||||
|
||||
@ -400,14 +410,8 @@ int link_request_qdisc(Link *link, QDisc *qdisc) {
|
||||
existing->source = qdisc->source;
|
||||
|
||||
log_qdisc_debug(existing, link, "Requesting");
|
||||
r = link_queue_request_safe(link, REQUEST_TYPE_TC_QDISC,
|
||||
existing, NULL,
|
||||
qdisc_hash_func,
|
||||
qdisc_compare_func,
|
||||
qdisc_process_request,
|
||||
&link->tc_messages,
|
||||
qdisc_handler,
|
||||
NULL);
|
||||
r = link_queue_request(link, REQUEST_TYPE_TC_QDISC, existing, false,
|
||||
&link->tc_messages, NULL, NULL);
|
||||
if (r < 0)
|
||||
return log_link_warning_errno(link, r, "Failed to request QDisc: %m");
|
||||
if (r == 0)
|
||||
|
||||
@ -8,6 +8,7 @@
|
||||
typedef struct Link Link;
|
||||
typedef struct Manager Manager;
|
||||
typedef struct Network Network;
|
||||
typedef struct Request Request;
|
||||
|
||||
typedef enum QDiscKind {
|
||||
QDISC_KIND_BFIFO,
|
||||
@ -76,8 +77,12 @@ DEFINE_NETWORK_CONFIG_STATE_FUNCTIONS(QDisc, qdisc);
|
||||
QDisc* qdisc_free(QDisc *qdisc);
|
||||
int qdisc_new_static(QDiscKind kind, Network *network, const char *filename, unsigned section_line, QDisc **ret);
|
||||
|
||||
void qdisc_hash_func(const QDisc *qdisc, struct siphash *state);
|
||||
int qdisc_compare_func(const QDisc *a, const QDisc *b);
|
||||
|
||||
int link_find_qdisc(Link *link, uint32_t handle, uint32_t parent, const char *kind, QDisc **qdisc);
|
||||
|
||||
int request_process_qdisc(Request *req);
|
||||
int link_request_qdisc(Link *link, QDisc *qdisc);
|
||||
|
||||
void network_drop_invalid_qdisc(Network *network);
|
||||
|
||||
@ -121,7 +121,7 @@ static const char *tclass_get_tca_kind(const TClass *tclass) {
|
||||
TCLASS_VTABLE(tclass)->tca_kind : tclass->tca_kind;
|
||||
}
|
||||
|
||||
static void tclass_hash_func(const TClass *tclass, struct siphash *state) {
|
||||
void tclass_hash_func(const TClass *tclass, struct siphash *state) {
|
||||
assert(tclass);
|
||||
assert(state);
|
||||
|
||||
@ -130,7 +130,7 @@ static void tclass_hash_func(const TClass *tclass, struct siphash *state) {
|
||||
siphash24_compress_string(tclass_get_tca_kind(tclass), state);
|
||||
}
|
||||
|
||||
static int tclass_compare_func(const TClass *a, const TClass *b) {
|
||||
int tclass_compare_func(const TClass *a, const TClass *b) {
|
||||
int r;
|
||||
|
||||
assert(a);
|
||||
@ -255,11 +255,15 @@ static void log_tclass_debug(TClass *tclass, Link *link, const char *str) {
|
||||
strna(tclass_get_tca_kind(tclass)));
|
||||
}
|
||||
|
||||
static int tclass_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, TClass *tclass) {
|
||||
static int tclass_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
assert(link);
|
||||
assert(link->tc_messages > 0);
|
||||
link->tc_messages--;
|
||||
|
||||
if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
|
||||
return 1;
|
||||
|
||||
r = sd_netlink_message_get_errno(m);
|
||||
if (r < 0 && r != -EEXIST) {
|
||||
@ -277,7 +281,7 @@ static int tclass_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req,
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int tclass_configure(TClass *tclass, Link *link, Request *req) {
|
||||
static int tclass_configure(TClass *tclass, Link *link) {
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
|
||||
int r;
|
||||
|
||||
@ -286,7 +290,6 @@ static int tclass_configure(TClass *tclass, Link *link, Request *req) {
|
||||
assert(link->manager);
|
||||
assert(link->manager->rtnl);
|
||||
assert(link->ifindex > 0);
|
||||
assert(req);
|
||||
|
||||
log_tclass_debug(tclass, link, "Configuring");
|
||||
|
||||
@ -305,7 +308,12 @@ static int tclass_configure(TClass *tclass, Link *link, Request *req) {
|
||||
return r;
|
||||
}
|
||||
|
||||
return request_call_netlink_async(link->manager->rtnl, m, req);
|
||||
r = netlink_call_async(link->manager->rtnl, NULL, m, tclass_handler, link_netlink_destroy_callback, link);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
link_ref(link);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool tclass_is_ready_to_configure(TClass *tclass, Link *link) {
|
||||
@ -318,17 +326,19 @@ static bool tclass_is_ready_to_configure(TClass *tclass, Link *link) {
|
||||
return link_find_qdisc(link, tclass->classid, tclass->parent, tclass_get_tca_kind(tclass), NULL) >= 0;
|
||||
}
|
||||
|
||||
static int tclass_process_request(Request *req, Link *link, TClass *tclass) {
|
||||
int request_process_tclass(Request *req) {
|
||||
TClass *tclass;
|
||||
Link *link;
|
||||
int r;
|
||||
|
||||
assert(req);
|
||||
assert(link);
|
||||
assert(tclass);
|
||||
assert_se(link = req->link);
|
||||
assert_se(tclass = req->tclass);
|
||||
|
||||
if (!tclass_is_ready_to_configure(tclass, link))
|
||||
return 0;
|
||||
|
||||
r = tclass_configure(tclass, link, req);
|
||||
r = tclass_configure(tclass, link);
|
||||
if (r < 0)
|
||||
return log_link_warning_errno(link, r, "Failed to configure TClass: %m");
|
||||
|
||||
@ -359,14 +369,8 @@ int link_request_tclass(Link *link, TClass *tclass) {
|
||||
existing->source = tclass->source;
|
||||
|
||||
log_tclass_debug(existing, link, "Requesting");
|
||||
r = link_queue_request_safe(link, REQUEST_TYPE_TC_CLASS,
|
||||
existing, NULL,
|
||||
tclass_hash_func,
|
||||
tclass_compare_func,
|
||||
tclass_process_request,
|
||||
&link->tc_messages,
|
||||
tclass_handler,
|
||||
NULL);
|
||||
r = link_queue_request(link, REQUEST_TYPE_TC_CLASS, existing, false,
|
||||
&link->tc_messages, NULL, NULL);
|
||||
if (r < 0)
|
||||
return log_link_warning_errno(link, r, "Failed to request TClass: %m");
|
||||
if (r == 0)
|
||||
|
||||
@ -8,6 +8,7 @@
|
||||
typedef struct Link Link;
|
||||
typedef struct Manager Manager;
|
||||
typedef struct Network Network;
|
||||
typedef struct Request Request;
|
||||
|
||||
typedef enum TClassKind {
|
||||
TCLASS_KIND_DRR,
|
||||
@ -58,8 +59,12 @@ DEFINE_NETWORK_CONFIG_STATE_FUNCTIONS(TClass, tclass);
|
||||
TClass* tclass_free(TClass *tclass);
|
||||
int tclass_new_static(TClassKind kind, Network *network, const char *filename, unsigned section_line, TClass **ret);
|
||||
|
||||
void tclass_hash_func(const TClass *qdisc, struct siphash *state);
|
||||
int tclass_compare_func(const TClass *a, const TClass *b);
|
||||
|
||||
int link_find_tclass(Link *link, uint32_t classid, TClass **ret);
|
||||
|
||||
int request_process_tclass(Request *req);
|
||||
int link_request_tclass(Link *link, TClass *tclass);
|
||||
|
||||
void network_drop_invalid_tclass(Network *network);
|
||||
|
||||
@ -19,64 +19,64 @@ struct ConfigPerfItem;
|
||||
%struct-type
|
||||
%includes
|
||||
%%
|
||||
Exec.Boot, config_parse_boot, 0, 0
|
||||
Exec.Ephemeral, config_parse_tristate, 0, offsetof(Settings, ephemeral)
|
||||
Exec.ProcessTwo, config_parse_pid2, 0, 0
|
||||
Exec.Parameters, config_parse_strv, 0, offsetof(Settings, parameters)
|
||||
Exec.Environment, config_parse_strv, 0, offsetof(Settings, environment)
|
||||
Exec.User, config_parse_string, CONFIG_PARSE_STRING_SAFE, offsetof(Settings, user)
|
||||
Exec.Capability, config_parse_capability, 0, offsetof(Settings, capability)
|
||||
Exec.AmbientCapability, config_parse_capability, 0, offsetof(Settings, ambient_capability)
|
||||
Exec.DropCapability, config_parse_capability, 0, offsetof(Settings, drop_capability)
|
||||
Exec.KillSignal, config_parse_signal, 0, offsetof(Settings, kill_signal)
|
||||
Exec.Personality, config_parse_personality, 0, offsetof(Settings, personality)
|
||||
Exec.MachineID, config_parse_id128, 0, offsetof(Settings, machine_id)
|
||||
Exec.WorkingDirectory, config_parse_path, 0, offsetof(Settings, working_directory)
|
||||
Exec.PivotRoot, config_parse_pivot_root, 0, 0
|
||||
Exec.PrivateUsers, config_parse_private_users, 0, 0
|
||||
Exec.NotifyReady, config_parse_tristate, 0, offsetof(Settings, notify_ready)
|
||||
Exec.SystemCallFilter, config_parse_syscall_filter, 0, 0
|
||||
Exec.LimitCPU, config_parse_rlimit, RLIMIT_CPU, offsetof(Settings, rlimit)
|
||||
Exec.LimitFSIZE, config_parse_rlimit, RLIMIT_FSIZE, offsetof(Settings, rlimit)
|
||||
Exec.LimitDATA, config_parse_rlimit, RLIMIT_DATA, offsetof(Settings, rlimit)
|
||||
Exec.LimitSTACK, config_parse_rlimit, RLIMIT_STACK, offsetof(Settings, rlimit)
|
||||
Exec.LimitCORE, config_parse_rlimit, RLIMIT_CORE, offsetof(Settings, rlimit)
|
||||
Exec.LimitRSS, config_parse_rlimit, RLIMIT_RSS, offsetof(Settings, rlimit)
|
||||
Exec.LimitNOFILE, config_parse_rlimit, RLIMIT_NOFILE, offsetof(Settings, rlimit)
|
||||
Exec.LimitAS, config_parse_rlimit, RLIMIT_AS, offsetof(Settings, rlimit)
|
||||
Exec.LimitNPROC, config_parse_rlimit, RLIMIT_NPROC, offsetof(Settings, rlimit)
|
||||
Exec.LimitMEMLOCK, config_parse_rlimit, RLIMIT_MEMLOCK, offsetof(Settings, rlimit)
|
||||
Exec.LimitLOCKS, config_parse_rlimit, RLIMIT_LOCKS, offsetof(Settings, rlimit)
|
||||
Exec.LimitSIGPENDING, config_parse_rlimit, RLIMIT_SIGPENDING, offsetof(Settings, rlimit)
|
||||
Exec.LimitMSGQUEUE, config_parse_rlimit, RLIMIT_MSGQUEUE, offsetof(Settings, rlimit)
|
||||
Exec.LimitNICE, config_parse_rlimit, RLIMIT_NICE, offsetof(Settings, rlimit)
|
||||
Exec.LimitRTPRIO, config_parse_rlimit, RLIMIT_RTPRIO, offsetof(Settings, rlimit)
|
||||
Exec.LimitRTTIME, config_parse_rlimit, RLIMIT_RTTIME, offsetof(Settings, rlimit)
|
||||
Exec.Hostname, config_parse_hostname, 0, offsetof(Settings, hostname)
|
||||
Exec.NoNewPrivileges, config_parse_tristate, 0, offsetof(Settings, no_new_privileges)
|
||||
Exec.OOMScoreAdjust, config_parse_oom_score_adjust, 0, 0
|
||||
Exec.CPUAffinity, config_parse_cpu_affinity, 0, 0
|
||||
Exec.ResolvConf, config_parse_resolv_conf, 0, offsetof(Settings, resolv_conf)
|
||||
Exec.LinkJournal, config_parse_link_journal, 0, 0
|
||||
Exec.Timezone, config_parse_timezone, 0, offsetof(Settings, timezone)
|
||||
Exec.SuppressSync, config_parse_tristate, 0, offsetof(Settings, suppress_sync)
|
||||
Files.ReadOnly, config_parse_tristate, 0, offsetof(Settings, read_only)
|
||||
Files.Volatile, config_parse_volatile_mode, 0, offsetof(Settings, volatile_mode)
|
||||
Files.Bind, config_parse_bind, 0, 0
|
||||
Files.BindReadOnly, config_parse_bind, 1, 0
|
||||
Files.TemporaryFileSystem, config_parse_tmpfs, 0, 0
|
||||
Files.Inaccessible, config_parse_inaccessible, 0, 0
|
||||
Files.Overlay, config_parse_overlay, 0, 0
|
||||
Files.OverlayReadOnly, config_parse_overlay, 1, 0
|
||||
Files.PrivateUsersChown, config_parse_userns_chown, 0, offsetof(Settings, userns_ownership)
|
||||
Files.PrivateUsersOwnership, config_parse_userns_ownership, 0, offsetof(Settings, userns_ownership)
|
||||
Files.BindUser, config_parse_bind_user, 0, offsetof(Settings, bind_user)
|
||||
Network.Private, config_parse_tristate, 0, offsetof(Settings, private_network)
|
||||
Network.Interface, config_parse_strv, 0, offsetof(Settings, network_interfaces)
|
||||
Network.MACVLAN, config_parse_strv, 0, offsetof(Settings, network_macvlan)
|
||||
Network.IPVLAN, config_parse_strv, 0, offsetof(Settings, network_ipvlan)
|
||||
Network.VirtualEthernet, config_parse_tristate, 0, offsetof(Settings, network_veth)
|
||||
Network.VirtualEthernetExtra, config_parse_veth_extra, 0, 0
|
||||
Network.Bridge, config_parse_ifname, 0, offsetof(Settings, network_bridge)
|
||||
Network.Zone, config_parse_network_zone, 0, 0
|
||||
Network.Port, config_parse_expose_port, 0, 0
|
||||
Exec.Boot, config_parse_boot, 0, 0
|
||||
Exec.Ephemeral, config_parse_tristate, 0, offsetof(Settings, ephemeral)
|
||||
Exec.ProcessTwo, config_parse_pid2, 0, 0
|
||||
Exec.Parameters, config_parse_strv, 0, offsetof(Settings, parameters)
|
||||
Exec.Environment, config_parse_strv, 0, offsetof(Settings, environment)
|
||||
Exec.User, config_parse_safe_string, 0, offsetof(Settings, user)
|
||||
Exec.Capability, config_parse_capability, 0, offsetof(Settings, capability)
|
||||
Exec.AmbientCapability, config_parse_capability, 0, offsetof(Settings, ambient_capability)
|
||||
Exec.DropCapability, config_parse_capability, 0, offsetof(Settings, drop_capability)
|
||||
Exec.KillSignal, config_parse_signal, 0, offsetof(Settings, kill_signal)
|
||||
Exec.Personality, config_parse_personality, 0, offsetof(Settings, personality)
|
||||
Exec.MachineID, config_parse_id128, 0, offsetof(Settings, machine_id)
|
||||
Exec.WorkingDirectory, config_parse_path, 0, offsetof(Settings, working_directory)
|
||||
Exec.PivotRoot, config_parse_pivot_root, 0, 0
|
||||
Exec.PrivateUsers, config_parse_private_users, 0, 0
|
||||
Exec.NotifyReady, config_parse_tristate, 0, offsetof(Settings, notify_ready)
|
||||
Exec.SystemCallFilter, config_parse_syscall_filter, 0, 0,
|
||||
Exec.LimitCPU, config_parse_rlimit, RLIMIT_CPU, offsetof(Settings, rlimit)
|
||||
Exec.LimitFSIZE, config_parse_rlimit, RLIMIT_FSIZE, offsetof(Settings, rlimit)
|
||||
Exec.LimitDATA, config_parse_rlimit, RLIMIT_DATA, offsetof(Settings, rlimit)
|
||||
Exec.LimitSTACK, config_parse_rlimit, RLIMIT_STACK, offsetof(Settings, rlimit)
|
||||
Exec.LimitCORE, config_parse_rlimit, RLIMIT_CORE, offsetof(Settings, rlimit)
|
||||
Exec.LimitRSS, config_parse_rlimit, RLIMIT_RSS, offsetof(Settings, rlimit)
|
||||
Exec.LimitNOFILE, config_parse_rlimit, RLIMIT_NOFILE, offsetof(Settings, rlimit)
|
||||
Exec.LimitAS, config_parse_rlimit, RLIMIT_AS, offsetof(Settings, rlimit)
|
||||
Exec.LimitNPROC, config_parse_rlimit, RLIMIT_NPROC, offsetof(Settings, rlimit)
|
||||
Exec.LimitMEMLOCK, config_parse_rlimit, RLIMIT_MEMLOCK, offsetof(Settings, rlimit)
|
||||
Exec.LimitLOCKS, config_parse_rlimit, RLIMIT_LOCKS, offsetof(Settings, rlimit)
|
||||
Exec.LimitSIGPENDING, config_parse_rlimit, RLIMIT_SIGPENDING, offsetof(Settings, rlimit)
|
||||
Exec.LimitMSGQUEUE, config_parse_rlimit, RLIMIT_MSGQUEUE, offsetof(Settings, rlimit)
|
||||
Exec.LimitNICE, config_parse_rlimit, RLIMIT_NICE, offsetof(Settings, rlimit)
|
||||
Exec.LimitRTPRIO, config_parse_rlimit, RLIMIT_RTPRIO, offsetof(Settings, rlimit)
|
||||
Exec.LimitRTTIME, config_parse_rlimit, RLIMIT_RTTIME, offsetof(Settings, rlimit)
|
||||
Exec.Hostname, config_parse_hostname, 0, offsetof(Settings, hostname)
|
||||
Exec.NoNewPrivileges, config_parse_tristate, 0, offsetof(Settings, no_new_privileges)
|
||||
Exec.OOMScoreAdjust, config_parse_oom_score_adjust, 0, 0
|
||||
Exec.CPUAffinity, config_parse_cpu_affinity, 0, 0
|
||||
Exec.ResolvConf, config_parse_resolv_conf, 0, offsetof(Settings, resolv_conf)
|
||||
Exec.LinkJournal, config_parse_link_journal, 0, 0
|
||||
Exec.Timezone, config_parse_timezone, 0, offsetof(Settings, timezone)
|
||||
Exec.SuppressSync, config_parse_tristate, 0, offsetof(Settings, suppress_sync)
|
||||
Files.ReadOnly, config_parse_tristate, 0, offsetof(Settings, read_only)
|
||||
Files.Volatile, config_parse_volatile_mode, 0, offsetof(Settings, volatile_mode)
|
||||
Files.Bind, config_parse_bind, 0, 0
|
||||
Files.BindReadOnly, config_parse_bind, 1, 0
|
||||
Files.TemporaryFileSystem, config_parse_tmpfs, 0, 0
|
||||
Files.Inaccessible, config_parse_inaccessible, 0, 0
|
||||
Files.Overlay, config_parse_overlay, 0, 0
|
||||
Files.OverlayReadOnly, config_parse_overlay, 1, 0
|
||||
Files.PrivateUsersChown, config_parse_userns_chown, 0, offsetof(Settings, userns_ownership)
|
||||
Files.PrivateUsersOwnership, config_parse_userns_ownership, 0, offsetof(Settings, userns_ownership)
|
||||
Files.BindUser, config_parse_bind_user, 0, offsetof(Settings, bind_user)
|
||||
Network.Private, config_parse_tristate, 0, offsetof(Settings, private_network)
|
||||
Network.Interface, config_parse_strv, 0, offsetof(Settings, network_interfaces)
|
||||
Network.MACVLAN, config_parse_strv, 0, offsetof(Settings, network_macvlan)
|
||||
Network.IPVLAN, config_parse_strv, 0, offsetof(Settings, network_ipvlan)
|
||||
Network.VirtualEthernet, config_parse_tristate, 0, offsetof(Settings, network_veth)
|
||||
Network.VirtualEthernetExtra, config_parse_veth_extra, 0, 0
|
||||
Network.Bridge, config_parse_ifname, 0, offsetof(Settings, network_bridge)
|
||||
Network.Zone, config_parse_network_zone, 0, 0
|
||||
Network.Port, config_parse_expose_port, 0, 0
|
||||
|
||||
@ -710,6 +710,31 @@ int config_parse_syscall_filter(
|
||||
}
|
||||
}
|
||||
|
||||
int config_parse_hostname(
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
const char *section,
|
||||
unsigned section_line,
|
||||
const char *lvalue,
|
||||
int ltype,
|
||||
const char *rvalue,
|
||||
void *data,
|
||||
void *userdata) {
|
||||
|
||||
char **s = data;
|
||||
|
||||
assert(rvalue);
|
||||
assert(s);
|
||||
|
||||
if (!hostname_is_valid(rvalue, 0)) {
|
||||
log_syntax(unit, LOG_WARNING, filename, line, 0, "Invalid hostname, ignoring: %s", rvalue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return free_and_strdup_warn(s, empty_to_null(rvalue));
|
||||
}
|
||||
|
||||
int config_parse_oom_score_adjust(
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
|
||||
@ -264,6 +264,7 @@ CONFIG_PARSER_PROTOTYPE(config_parse_boot);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_pid2);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_private_users);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_syscall_filter);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_hostname);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_oom_score_adjust);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_cpu_affinity);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_resolv_conf);
|
||||
|
||||
@ -11,14 +11,11 @@
|
||||
#include "conf-files.h"
|
||||
#include "conf-parser.h"
|
||||
#include "def.h"
|
||||
#include "dns-domain.h"
|
||||
#include "escape.h"
|
||||
#include "ether-addr-util.h"
|
||||
#include "extract-word.h"
|
||||
#include "fd-util.h"
|
||||
#include "fileio.h"
|
||||
#include "fs-util.h"
|
||||
#include "hostname-util.h"
|
||||
#include "in-addr-util.h"
|
||||
#include "log.h"
|
||||
#include "macro.h"
|
||||
@ -876,39 +873,17 @@ int config_parse_string(
|
||||
void *data,
|
||||
void *userdata) {
|
||||
|
||||
char **s = ASSERT_PTR(data);
|
||||
char **s = data;
|
||||
|
||||
assert(filename);
|
||||
assert(lvalue);
|
||||
assert(rvalue);
|
||||
|
||||
if (isempty(rvalue)) {
|
||||
*s = mfree(*s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (FLAGS_SET(ltype, CONFIG_PARSE_STRING_SAFE) && !string_is_safe(rvalue)) {
|
||||
_cleanup_free_ char *escaped = NULL;
|
||||
|
||||
escaped = cescape(rvalue);
|
||||
log_syntax(unit, LOG_WARNING, filename, line, 0,
|
||||
"Specified string contains unsafe characters, ignoring: %s", strna(escaped));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (FLAGS_SET(ltype, CONFIG_PARSE_STRING_ASCII) && !ascii_is_valid(rvalue)) {
|
||||
_cleanup_free_ char *escaped = NULL;
|
||||
|
||||
escaped = cescape(rvalue);
|
||||
log_syntax(unit, LOG_WARNING, filename, line, 0,
|
||||
"Specified string contains invalid ASCII characters, ignoring: %s", strna(escaped));
|
||||
return 0;
|
||||
}
|
||||
assert(data);
|
||||
|
||||
return free_and_strdup_warn(s, empty_to_null(rvalue));
|
||||
}
|
||||
|
||||
int config_parse_dns_name(
|
||||
int config_parse_safe_string(
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
@ -920,64 +895,19 @@ int config_parse_dns_name(
|
||||
void *data,
|
||||
void *userdata) {
|
||||
|
||||
char **hostname = ASSERT_PTR(data);
|
||||
int r;
|
||||
char **s = data;
|
||||
|
||||
assert(filename);
|
||||
assert(lvalue);
|
||||
assert(rvalue);
|
||||
assert(data);
|
||||
|
||||
if (isempty(rvalue)) {
|
||||
*hostname = mfree(*hostname);
|
||||
if (!string_is_safe(rvalue)) {
|
||||
log_syntax(unit, LOG_WARNING, filename, line, 0, "Specified string contains unsafe characters, ignoring: %s", rvalue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = dns_name_is_valid(rvalue);
|
||||
if (r < 0) {
|
||||
log_syntax(unit, LOG_WARNING, filename, line, r,
|
||||
"Failed to check validity of DNS domain name '%s', ignoring assignment: %m", rvalue);
|
||||
return 0;
|
||||
}
|
||||
if (r == 0) {
|
||||
log_syntax(unit, LOG_WARNING, filename, line, 0,
|
||||
"Specified invalid DNS domain name, ignoring assignment: %s", rvalue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return free_and_strdup_warn(hostname, rvalue);
|
||||
}
|
||||
|
||||
int config_parse_hostname(
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
const char *section,
|
||||
unsigned section_line,
|
||||
const char *lvalue,
|
||||
int ltype,
|
||||
const char *rvalue,
|
||||
void *data,
|
||||
void *userdata) {
|
||||
|
||||
char **hostname = ASSERT_PTR(data);
|
||||
|
||||
assert(filename);
|
||||
assert(lvalue);
|
||||
assert(rvalue);
|
||||
|
||||
if (isempty(rvalue)) {
|
||||
*hostname = mfree(*hostname);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!hostname_is_valid(rvalue, 0)) {
|
||||
log_syntax(unit, LOG_WARNING, filename, line, 0,
|
||||
"Specified invalid hostname, ignoring assignment: %s", rvalue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return config_parse_dns_name(unit, filename, line, section, section_line,
|
||||
lvalue, ltype, rvalue, data, userdata);
|
||||
return free_and_strdup_warn(s, empty_to_null(rvalue));
|
||||
}
|
||||
|
||||
int config_parse_path(
|
||||
|
||||
@ -168,8 +168,7 @@ CONFIG_PARSER_PROTOTYPE(config_parse_bool);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_id128);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_tristate);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_string);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_dns_name);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_hostname);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_safe_string);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_path);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_strv);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_sec);
|
||||
@ -204,13 +203,6 @@ typedef enum Disabled {
|
||||
DISABLED_EXPERIMENTAL,
|
||||
} Disabled;
|
||||
|
||||
typedef enum ConfigParseStringFlags {
|
||||
CONFIG_PARSE_STRING_SAFE = 1 << 0,
|
||||
CONFIG_PARSE_STRING_ASCII = 1 << 1,
|
||||
|
||||
CONFIG_PARSE_STRING_SAFE_AND_ASCII = CONFIG_PARSE_STRING_SAFE | CONFIG_PARSE_STRING_ASCII,
|
||||
} ConfigParseStringFlags;
|
||||
|
||||
#define DEFINE_CONFIG_PARSE(function, parser, msg) \
|
||||
CONFIG_PARSER_PROTOTYPE(function) { \
|
||||
int *i = data, r; \
|
||||
|
||||
@ -44,175 +44,71 @@ enum {
|
||||
* The client may want to start acquiring link-local addresses. */
|
||||
};
|
||||
|
||||
/* https://www.iana.org/assignments/bootp-dhcp-parameters/bootp-dhcp-parameters.xhtml#options */
|
||||
enum {
|
||||
SD_DHCP_OPTION_PAD = 0, /* [RFC2132] */
|
||||
SD_DHCP_OPTION_SUBNET_MASK = 1, /* [RFC2132] */
|
||||
SD_DHCP_OPTION_TIME_OFFSET = 2, /* [RFC2132], deprecated by 100 and 101 */
|
||||
SD_DHCP_OPTION_ROUTER = 3, /* [RFC2132] */
|
||||
SD_DHCP_OPTION_TIME_SERVER = 4, /* [RFC2132] */
|
||||
SD_DHCP_OPTION_NAME_SERVER = 5, /* [RFC2132] */
|
||||
SD_DHCP_OPTION_DOMAIN_NAME_SERVER = 6, /* [RFC2132] */
|
||||
SD_DHCP_OPTION_LOG_SERVER = 7, /* [RFC2132] */
|
||||
SD_DHCP_OPTION_QUOTES_SERVER = 8, /* [RFC2132] */
|
||||
SD_DHCP_OPTION_LPR_SERVER = 9, /* [RFC2132] */
|
||||
SD_DHCP_OPTION_IMPRESS_SERVER = 10, /* [RFC2132] */
|
||||
SD_DHCP_OPTION_RLP_SERVER = 11, /* [RFC2132] */
|
||||
SD_DHCP_OPTION_HOST_NAME = 12, /* [RFC2132] */
|
||||
SD_DHCP_OPTION_BOOT_FILE_SIZE = 13, /* [RFC2132] */
|
||||
SD_DHCP_OPTION_MERIT_DUMP_FILE = 14, /* [RFC2132] */
|
||||
SD_DHCP_OPTION_DOMAIN_NAME = 15, /* [RFC2132] */
|
||||
SD_DHCP_OPTION_SWAP_SERVER = 16, /* [RFC2132] */
|
||||
SD_DHCP_OPTION_ROOT_PATH = 17, /* [RFC2132] */
|
||||
SD_DHCP_OPTION_EXTENSION_FILE = 18, /* [RFC2132] */
|
||||
SD_DHCP_OPTION_FORWARD = 19, /* [RFC2132] */
|
||||
SD_DHCP_OPTION_SOURCE_ROUTE = 20, /* [RFC2132] */
|
||||
SD_DHCP_OPTION_POLICY_FILTER = 21, /* [RFC2132] */
|
||||
SD_DHCP_OPTION_MAX_DATAGRAM_ASSEMBLY = 22, /* [RFC2132] */
|
||||
SD_DHCP_OPTION_DEFAULT_IP_TTL = 23, /* [RFC2132] */
|
||||
SD_DHCP_OPTION_MTU_TIMEOUT = 24, /* [RFC2132] */
|
||||
SD_DHCP_OPTION_MTU_PLATEAU = 25, /* [RFC2132] */
|
||||
SD_DHCP_OPTION_MTU_INTERFACE = 26, /* [RFC2132] */
|
||||
SD_DHCP_OPTION_MTU_SUBNET = 27, /* [RFC2132] */
|
||||
SD_DHCP_OPTION_BROADCAST = 28, /* [RFC2132] */
|
||||
SD_DHCP_OPTION_MASK_DISCOVERY = 29, /* [RFC2132] */
|
||||
SD_DHCP_OPTION_MASK_SUPPLIER = 30, /* [RFC2132] */
|
||||
SD_DHCP_OPTION_ROUTER_DISCOVERY = 31, /* [RFC2132] */
|
||||
SD_DHCP_OPTION_ROUTER_REQUEST = 32, /* [RFC2132] */
|
||||
SD_DHCP_OPTION_STATIC_ROUTE = 33, /* [RFC2132] */
|
||||
SD_DHCP_OPTION_TRAILERS = 34, /* [RFC2132] */
|
||||
SD_DHCP_OPTION_ARP_TIMEOUT = 35, /* [RFC2132] */
|
||||
SD_DHCP_OPTION_ETHERNET = 36, /* [RFC2132] */
|
||||
SD_DHCP_OPTION_DEFAULT_TCP_TTL = 37, /* [RFC2132] */
|
||||
SD_DHCP_OPTION_KEEPALIVE_TIME = 38, /* [RFC2132] */
|
||||
SD_DHCP_OPTION_KEEPALIVE_DATA = 39, /* [RFC2132] */
|
||||
SD_DHCP_OPTION_NIS_DOMAIN = 40, /* [RFC2132] */
|
||||
SD_DHCP_OPTION_NIS_SERVER = 41, /* [RFC2132] */
|
||||
SD_DHCP_OPTION_NTP_SERVER = 42, /* [RFC2132] */
|
||||
SD_DHCP_OPTION_VENDOR_SPECIFIC = 43, /* [RFC2132] */
|
||||
SD_DHCP_OPTION_NETBIOS_NAME_SERVER = 44, /* [RFC2132] */
|
||||
SD_DHCP_OPTION_NETBIOS_DIST_SERVER = 45, /* [RFC2132] */
|
||||
SD_DHCP_OPTION_NETBIOS_NODE_TYPE = 46, /* [RFC2132] */
|
||||
SD_DHCP_OPTION_NETBIOS_SCOPE = 47, /* [RFC2132] */
|
||||
SD_DHCP_OPTION_X_WINDOW_FONT = 48, /* [RFC2132] */
|
||||
SD_DHCP_OPTION_X_WINDOW_MANAGER = 49, /* [RFC2132] */
|
||||
SD_DHCP_OPTION_REQUESTED_IP_ADDRESS = 50, /* [RFC2132] */
|
||||
SD_DHCP_OPTION_IP_ADDRESS_LEASE_TIME = 51, /* [RFC2132] */
|
||||
SD_DHCP_OPTION_OVERLOAD = 52, /* [RFC2132] */
|
||||
SD_DHCP_OPTION_MESSAGE_TYPE = 53, /* [RFC2132] */
|
||||
SD_DHCP_OPTION_SERVER_IDENTIFIER = 54, /* [RFC2132] */
|
||||
SD_DHCP_OPTION_PARAMETER_REQUEST_LIST = 55, /* [RFC2132] */
|
||||
SD_DHCP_OPTION_ERROR_MESSAGE = 56, /* [RFC2132] */
|
||||
SD_DHCP_OPTION_MAXIMUM_MESSAGE_SIZE = 57, /* [RFC2132] */
|
||||
SD_DHCP_OPTION_RENEWAL_TIME = 58, /* [RFC2132] */
|
||||
SD_DHCP_OPTION_REBINDING_TIME = 59, /* [RFC2132] */
|
||||
SD_DHCP_OPTION_VENDOR_CLASS_IDENTIFIER = 60, /* [RFC2132] */
|
||||
SD_DHCP_OPTION_CLIENT_IDENTIFIER = 61, /* [RFC2132] */
|
||||
SD_DHCP_OPTION_NETWARE_IP_DOMAIN = 62, /* [RFC2242] */
|
||||
SD_DHCP_OPTION_NETWARE_IP_OPTION = 63, /* [RFC2242] */
|
||||
SD_DHCP_OPTION_NIS_DOMAIN_NAME = 64, /* [RFC2132] */
|
||||
SD_DHCP_OPTION_NIS_SERVER_ADDR = 65, /* [RFC2132] */
|
||||
SD_DHCP_OPTION_BOOT_SERVER_NAME = 66, /* [RFC2132] */
|
||||
SD_DHCP_OPTION_BOOT_FILENAME = 67, /* [RFC2132] */
|
||||
SD_DHCP_OPTION_HOME_AGENT_ADDRESSES = 68, /* [RFC2132] */
|
||||
SD_DHCP_OPTION_SMTP_SERVER = 69, /* [RFC2132] */
|
||||
SD_DHCP_OPTION_POP3_SERVER = 70, /* [RFC2132] */
|
||||
SD_DHCP_OPTION_NNTP_SERVER = 71, /* [RFC2132] */
|
||||
SD_DHCP_OPTION_WWW_SERVER = 72, /* [RFC2132] */
|
||||
SD_DHCP_OPTION_FINGER_SERVER = 73, /* [RFC2132] */
|
||||
SD_DHCP_OPTION_IRC_SERVER = 74, /* [RFC2132] */
|
||||
SD_DHCP_OPTION_STREETTALK_SERVER = 75, /* [RFC2132] */
|
||||
SD_DHCP_OPTION_STDA_SERVER = 76, /* [RFC2132] */
|
||||
SD_DHCP_OPTION_USER_CLASS = 77, /* [RFC3004] */
|
||||
SD_DHCP_OPTION_DIRECTORY_AGENT = 78, /* [RFC2610] */
|
||||
SD_DHCP_OPTION_SERVICE_SCOPE = 79, /* [RFC2610] */
|
||||
SD_DHCP_OPTION_RAPID_COMMIT = 80, /* [RFC4039] */
|
||||
SD_DHCP_OPTION_FQDN = 81, /* [RFC4702] */
|
||||
SD_DHCP_OPTION_RELAY_AGENT_INFORMATION = 82, /* [RFC3046] */
|
||||
SD_DHCP_OPTION_ISNS = 83, /* [RFC4174] */
|
||||
/* option code 84 is unassigned [RFC3679] */
|
||||
SD_DHCP_OPTION_NDS_SERVER = 85, /* [RFC2241] */
|
||||
SD_DHCP_OPTION_NDS_TREE_NAME = 86, /* [RFC2241] */
|
||||
SD_DHCP_OPTION_NDS_CONTEXT = 87, /* [RFC2241] */
|
||||
SD_DHCP_OPTION_BCMCS_CONTROLLER_DOMAIN_NAM = 88, /* [RFC4280] */
|
||||
SD_DHCP_OPTION_BCMCS_CONTROLLER_ADDRESS = 89, /* [RFC4280] */
|
||||
SD_DHCP_OPTION_AUTHENTICATION = 90, /* [RFC3118] */
|
||||
SD_DHCP_OPTION_CLIENT_LAST_TRANSACTION_TIME = 91, /* [RFC4388] */
|
||||
SD_DHCP_OPTION_ASSOCIATED_IP = 92, /* [RFC4388] */
|
||||
SD_DHCP_OPTION_CLIENT_SYSTEM = 93, /* [RFC4578] */
|
||||
SD_DHCP_OPTION_CLIENT_NDI = 94, /* [RFC4578] */
|
||||
SD_DHCP_OPTION_LDAP = 95, /* [RFC3679] */
|
||||
/* option code 96 is unassigned [RFC3679] */
|
||||
SD_DHCP_OPTION_UUID = 97, /* [RFC4578] */
|
||||
SD_DHCP_OPTION_USER_AUTHENTICATION = 98, /* [RFC2485] */
|
||||
SD_DHCP_OPTION_GEOCONF_CIVIC = 99, /* [RFC4776] */
|
||||
SD_DHCP_OPTION_POSIX_TIMEZONE = 100, /* [RFC4833] */
|
||||
SD_DHCP_OPTION_TZDB_TIMEZONE = 101, /* [RFC4833] */
|
||||
/* option codes 102-107 are unassigned [RFC3679] */
|
||||
SD_DHCP_OPTION_IPV6_ONLY_PREFERRED = 108, /* [RFC8925] */
|
||||
SD_DHCP_OPTION_DHCP4O6_SOURCE_ADDRESS = 109, /* [RFC8539] */
|
||||
/* option codes 110-111 are unassigned [RFC3679] */
|
||||
SD_DHCP_OPTION_NETINFO_ADDRESS = 112, /* [RFC3679] */
|
||||
SD_DHCP_OPTION_NETINFO_TAG = 113, /* [RFC3679] */
|
||||
SD_DHCP_OPTION_DHCP_CAPTIVE_PORTAL = 114, /* [RFC8910] */
|
||||
/* option code 115 is unassigned [RFC3679] */
|
||||
SD_DHCP_OPTION_AUTO_CONFIG = 116, /* [RFC2563] */
|
||||
SD_DHCP_OPTION_NAME_SERVICE_SEARCH = 117, /* [RFC2937] */
|
||||
SD_DHCP_OPTION_SUBNET_SELECTION = 118, /* [RFC3011] */
|
||||
SD_DHCP_OPTION_DOMAIN_SEARCH = 119, /* [RFC3397] */
|
||||
SD_DHCP_OPTION_SIP_SERVER = 120, /* [RFC3361] */
|
||||
SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE = 121, /* [RFC3442] */
|
||||
SD_DHCP_OPTION_CABLELABS_CLIENT_CONFIGURATION = 122, /* [RFC3495] */
|
||||
SD_DHCP_OPTION_GEOCONF = 123, /* [RFC6225] */
|
||||
SD_DHCP_OPTION_VENDOR_CLASS = 124, /* [RFC3925] */
|
||||
SD_DHCP_OPTION_VENDOR_SPECIFIC_INFORMATION = 125, /* [RFC3925] */
|
||||
/* option codes 126-127 are unassigned [RFC3679] */
|
||||
/* option codes 128-135 are assigned to use by PXE, but they are vendor specific [RFC4578] */
|
||||
SD_DHCP_OPTION_PANA_AGENT = 136, /* [RFC5192] */
|
||||
SD_DHCP_OPTION_LOST_SERVER_FQDN = 137, /* [RFC5223] */
|
||||
SD_DHCP_OPTION_CAPWAP_AC_ADDRESS = 138, /* [RFC5417] */
|
||||
SD_DHCP_OPTION_MOS_ADDRESS = 139, /* [RFC5678] */
|
||||
SD_DHCP_OPTION_MOS_FQDN = 140, /* [RFC5678] */
|
||||
SD_DHCP_OPTION_SIP_SERVICE_DOMAINS = 141, /* [RFC6011] */
|
||||
SD_DHCP_OPTION_ANDSF_ADDRESS = 142, /* [RFC6153] */
|
||||
SD_DHCP_OPTION_SZTP_REDIRECT = 143, /* [RFC8572] */
|
||||
SD_DHCP_OPTION_GEOLOC = 144, /* [RFC6225] */
|
||||
SD_DHCP_OPTION_FORCERENEW_NONCE_CAPABLE = 145, /* [RFC6704] */
|
||||
SD_DHCP_OPTION_RDNSS_SELECTION = 146, /* [RFC6731] */
|
||||
SD_DHCP_OPTION_DOTS_RI = 147, /* [RFC8973] */
|
||||
SD_DHCP_OPTION_DOTS_ADDRESS = 148, /* [RFC8973] */
|
||||
/* option code 149 is unassigned [RFC3942] */
|
||||
SD_DHCP_OPTION_TFTP_SERVER_ADDRESS = 150, /* [RFC5859] */
|
||||
SD_DHCP_OPTION_STATUS_CODE = 151, /* [RFC6926] */
|
||||
SD_DHCP_OPTION_BASE_TIME = 152, /* [RFC6926] */
|
||||
SD_DHCP_OPTION_START_TIME_OF_STATE = 153, /* [RFC6926] */
|
||||
SD_DHCP_OPTION_QUERY_START_TIME = 154, /* [RFC6926] */
|
||||
SD_DHCP_OPTION_QUERY_END_TIME = 155, /* [RFC6926] */
|
||||
SD_DHCP_OPTION_DHCP_STATE = 156, /* [RFC6926] */
|
||||
SD_DHCP_OPTION_DATA_SOURCE = 157, /* [RFC6926] */
|
||||
SD_DHCP_OPTION_PCP_SERVER = 158, /* [RFC7291] */
|
||||
SD_DHCP_OPTION_PORT_PARAMS = 159, /* [RFC7618] */
|
||||
/* option code 160 is unassigned [RFC7710][RFC8910] */
|
||||
SD_DHCP_OPTION_MUD_URL = 161, /* [RFC8520] */
|
||||
/* option codes 162-174 are unassigned [RFC3942] */
|
||||
/* option codes 175-177 are temporary assigned. */
|
||||
/* option codes 178-207 are unassigned [RFC3942] */
|
||||
SD_DHCP_OPTION_PXELINUX_MAGIC = 208, /* [RFC5071] Deprecated */
|
||||
SD_DHCP_OPTION_CONFIGURATION_FILE = 209, /* [RFC5071] */
|
||||
SD_DHCP_OPTION_PATH_PREFIX = 210, /* [RFC5071] */
|
||||
SD_DHCP_OPTION_REBOOT_TIME = 211, /* [RFC5071] */
|
||||
SD_DHCP_OPTION_6RD = 212, /* [RFC5969] */
|
||||
SD_DHCP_OPTION_ACCESS_DOMAIN = 213, /* [RFC5986] */
|
||||
/* option codes 214-219 are unassigned */
|
||||
SD_DHCP_OPTION_SUBNET_ALLOCATION = 220, /* [RFC6656] */
|
||||
SD_DHCP_OPTION_VIRTUAL_SUBNET_SELECTION = 221, /* [RFC6607] */
|
||||
/* option codes 222-223 are unassigned [RFC3942] */
|
||||
/* option codes 224-254 are reserved for private use */
|
||||
SD_DHCP_OPTION_PAD = 0,
|
||||
SD_DHCP_OPTION_SUBNET_MASK = 1,
|
||||
SD_DHCP_OPTION_TIME_OFFSET = 2,
|
||||
SD_DHCP_OPTION_ROUTER = 3,
|
||||
SD_DHCP_OPTION_DOMAIN_NAME_SERVER = 6,
|
||||
SD_DHCP_OPTION_LPR_SERVER = 9,
|
||||
SD_DHCP_OPTION_HOST_NAME = 12,
|
||||
SD_DHCP_OPTION_BOOT_FILE_SIZE = 13,
|
||||
SD_DHCP_OPTION_DOMAIN_NAME = 15,
|
||||
SD_DHCP_OPTION_ROOT_PATH = 17,
|
||||
SD_DHCP_OPTION_ENABLE_IP_FORWARDING = 19,
|
||||
SD_DHCP_OPTION_ENABLE_IP_FORWARDING_NL = 20,
|
||||
SD_DHCP_OPTION_POLICY_FILTER = 21,
|
||||
SD_DHCP_OPTION_INTERFACE_MDR = 22,
|
||||
SD_DHCP_OPTION_INTERFACE_TTL = 23,
|
||||
SD_DHCP_OPTION_INTERFACE_MTU_AGING_TIMEOUT = 24,
|
||||
SD_DHCP_OPTION_INTERFACE_MTU = 26,
|
||||
SD_DHCP_OPTION_BROADCAST = 28,
|
||||
/* Windows 10 option to send when Anonymize=true */
|
||||
SD_DHCP_OPTION_ROUTER_DISCOVER = 31,
|
||||
SD_DHCP_OPTION_STATIC_ROUTE = 33,
|
||||
SD_DHCP_OPTION_NTP_SERVER = 42,
|
||||
SD_DHCP_OPTION_VENDOR_SPECIFIC = 43,
|
||||
/* Windows 10 option to send when Anonymize=true */
|
||||
SD_DHCP_OPTION_NETBIOS_NAMESERVER = 44,
|
||||
/* Windows 10 option to send when Anonymize=true */
|
||||
SD_DHCP_OPTION_NETBIOS_NODETYPE = 46,
|
||||
/* Windows 10 option to send when Anonymize=true */
|
||||
SD_DHCP_OPTION_NETBIOS_SCOPE = 47,
|
||||
SD_DHCP_OPTION_REQUESTED_IP_ADDRESS = 50,
|
||||
SD_DHCP_OPTION_IP_ADDRESS_LEASE_TIME = 51,
|
||||
SD_DHCP_OPTION_OVERLOAD = 52,
|
||||
SD_DHCP_OPTION_MESSAGE_TYPE = 53,
|
||||
SD_DHCP_OPTION_SERVER_IDENTIFIER = 54,
|
||||
SD_DHCP_OPTION_PARAMETER_REQUEST_LIST = 55,
|
||||
SD_DHCP_OPTION_ERROR_MESSAGE = 56,
|
||||
SD_DHCP_OPTION_MAXIMUM_MESSAGE_SIZE = 57,
|
||||
SD_DHCP_OPTION_RENEWAL_T1_TIME = 58,
|
||||
SD_DHCP_OPTION_REBINDING_T2_TIME = 59,
|
||||
SD_DHCP_OPTION_VENDOR_CLASS_IDENTIFIER = 60,
|
||||
SD_DHCP_OPTION_CLIENT_IDENTIFIER = 61,
|
||||
SD_DHCP_OPTION_SMTP_SERVER = 69,
|
||||
SD_DHCP_OPTION_POP3_SERVER = 70,
|
||||
SD_DHCP_OPTION_USER_CLASS = 77,
|
||||
SD_DHCP_OPTION_FQDN = 81,
|
||||
SD_DHCP_OPTION_RELAY_AGENT_INFORMATION = 82,
|
||||
SD_DHCP_OPTION_NEW_POSIX_TIMEZONE = 100,
|
||||
SD_DHCP_OPTION_NEW_TZDB_TIMEZONE = 101,
|
||||
SD_DHCP_OPTION_DOMAIN_SEARCH_LIST = 119,
|
||||
SD_DHCP_OPTION_SIP_SERVER = 120,
|
||||
SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE = 121,
|
||||
SD_DHCP_OPTION_MUD_URL = 161,
|
||||
SD_DHCP_OPTION_PXELINUX_MAGIC = 208, /* deprecated */
|
||||
SD_DHCP_OPTION_CONFIGURATION_FILE = 209,
|
||||
SD_DHCP_OPTION_PATH_PREFIX = 210,
|
||||
SD_DHCP_OPTION_REBOOT_TIME = 211,
|
||||
SD_DHCP_OPTION_6RD = 212,
|
||||
SD_DHCP_OPTION_PRIVATE_BASE = 224,
|
||||
SD_DHCP_OPTION_PRIVATE_CLASSLESS_STATIC_ROUTE = 249, /* [RFC7844] */
|
||||
SD_DHCP_OPTION_PRIVATE_PROXY_AUTODISCOVERY = 252, /* [RFC7844] */
|
||||
/* Windows 10 option to send when Anonymize=true */
|
||||
SD_DHCP_OPTION_PRIVATE_CLASSLESS_STATIC_ROUTE = 249,
|
||||
/* Windows 10 option to send when Anonymize=true */
|
||||
SD_DHCP_OPTION_PRIVATE_PROXY_AUTODISCOVERY = 252,
|
||||
SD_DHCP_OPTION_PRIVATE_LAST = 254,
|
||||
SD_DHCP_OPTION_END = 255, /* [RFC2132] */
|
||||
SD_DHCP_OPTION_END = 255,
|
||||
};
|
||||
|
||||
/* Suboptions for SD_DHCP_OPTION_RELAY_AGENT_INFORMATION option */
|
||||
|
||||
@ -58,9 +58,8 @@ int sd_dhcp_server_stop(sd_dhcp_server *server);
|
||||
|
||||
int sd_dhcp_server_configure_pool(sd_dhcp_server *server, const struct in_addr *address, unsigned char prefixlen, uint32_t offset, uint32_t size);
|
||||
|
||||
int sd_dhcp_server_set_boot_server_address(sd_dhcp_server *server, const struct in_addr *address);
|
||||
int sd_dhcp_server_set_boot_server_name(sd_dhcp_server *server, const char *name);
|
||||
int sd_dhcp_server_set_boot_filename(sd_dhcp_server *server, const char *filename);
|
||||
int sd_dhcp_server_set_next_server(sd_dhcp_server *server, const struct in_addr *next_server);
|
||||
int sd_dhcp_server_set_filename(sd_dhcp_server *server, const char *filename);
|
||||
int sd_dhcp_server_set_bind_to_interface(sd_dhcp_server *server, int enabled);
|
||||
int sd_dhcp_server_set_timezone(sd_dhcp_server *server, const char *timezone);
|
||||
int sd_dhcp_server_set_router(sd_dhcp_server *server, const struct in_addr *address);
|
||||
|
||||
@ -81,8 +81,8 @@ enum {
|
||||
SD_DHCP6_OPTION_SUBSCRIBER_ID = 38, /* RFC 4580 */
|
||||
SD_DHCP6_OPTION_CLIENT_FQDN = 39, /* RFC 4704 */
|
||||
SD_DHCP6_OPTION_PANA_AGENT = 40, /* RFC 5192 */
|
||||
SD_DHCP6_OPTION_POSIX_TIMEZONE = 41, /* RFC 4833 */
|
||||
SD_DHCP6_OPTION_TZDB_TIMEZONE = 42, /* RFC 4833 */
|
||||
SD_DHCP6_OPTION_NEW_POSIX_TIMEZONE = 41, /* RFC 4833 */
|
||||
SD_DHCP6_OPTION_NEW_TZDB_TIMEZONE = 42, /* RFC 4833 */
|
||||
SD_DHCP6_OPTION_ERO = 43, /* RFC 4994 */
|
||||
SD_DHCP6_OPTION_LQ_QUERY = 44, /* RFC 5007 */
|
||||
SD_DHCP6_OPTION_CLIENT_DATA = 45, /* RFC 5007 */
|
||||
|
||||
@ -177,13 +177,13 @@ static int process_one_password_file(const char *filename) {
|
||||
pid_t pid = 0;
|
||||
|
||||
const ConfigTableItem items[] = {
|
||||
{ "Ask", "Socket", config_parse_string, CONFIG_PARSE_STRING_SAFE, &socket_name },
|
||||
{ "Ask", "NotAfter", config_parse_uint64, 0, ¬_after },
|
||||
{ "Ask", "Message", config_parse_string, 0, &message },
|
||||
{ "Ask", "PID", config_parse_pid, 0, &pid },
|
||||
{ "Ask", "AcceptCached", config_parse_bool, 0, &accept_cached },
|
||||
{ "Ask", "Echo", config_parse_bool, 0, &echo },
|
||||
{ "Ask", "Silent", config_parse_bool, 0, &silent },
|
||||
{ "Ask", "Socket", config_parse_safe_string, 0, &socket_name },
|
||||
{ "Ask", "NotAfter", config_parse_uint64, 0, ¬_after },
|
||||
{ "Ask", "Message", config_parse_string, 0, &message },
|
||||
{ "Ask", "PID", config_parse_pid, 0, &pid },
|
||||
{ "Ask", "AcceptCached", config_parse_bool, 0, &accept_cached },
|
||||
{ "Ask", "Echo", config_parse_bool, 0, &echo },
|
||||
{ "Ask", "Silent", config_parse_bool, 0, &silent },
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
@ -409,9 +409,8 @@ RelayAgentCircuitId=
|
||||
RelayAgentRemoteId=
|
||||
ServerAddress=
|
||||
UplinkInterface=
|
||||
BootServerAddress=
|
||||
BootServerName=
|
||||
BootFilename=
|
||||
NextServer=
|
||||
Filename=
|
||||
[DHCPServerStaticLease]
|
||||
MACAddress=
|
||||
Address=
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user