1
0
mirror of https://github.com/systemd/systemd synced 2025-11-08 03:14:45 +01:00

Compare commits

...

27 Commits

Author SHA1 Message Date
Lennart Poettering
0c789b6b81
Merge pull request #15868 from keszybz/fix-failed-to-fix-up-pid1-environment
Fix bad errno checks
2020-05-20 21:07:47 +02:00
Zbigniew Jędrzejewski-Szmek
6b8664cb5b tree-wide: fix bad errno checks 2020-05-20 18:10:58 +02:00
Zbigniew Jędrzejewski-Szmek
a0fa268337 basic/efivars: fix errno propagation
Fixup for 484f4e5b2d62e885998fa3c09ed4d58b6c38f987. Should fix #15730.
2020-05-20 18:08:05 +02:00
Zbigniew Jędrzejewski-Szmek
929d07ddcb
Merge pull request #15274 from ssahani/network-issue-9610
DHCP4: Allow lease time to be set when missing from offer
2020-05-20 16:39:41 +02:00
Lennart Poettering
400530c1e2
Merge pull request #15490 from ssahani/dhcpv6-vendor-class
network: DHCPv6 - Add support to send vendor class information
2020-05-20 16:18:18 +02:00
Zbigniew Jędrzejewski-Szmek
a94d11cc66
Merge pull request #15860 from keszybz/bus-message-empty-fields
Fix crash on message with empty fields structure
2020-05-20 15:53:28 +02:00
Zbigniew Jędrzejewski-Szmek
bb94ded693
Merge pull request #15661 from hundeboll/mount-read-write-only
Mount read write only
2020-05-20 15:48:04 +02:00
Susant Sahani
579ca0a2b2 sd-network: DHCPv4 - Add user class, extra option and send generic options in request state 2020-05-20 15:43:20 +02:00
Zbigniew Jędrzejewski-Szmek
3d45f6b2d0
Merge pull request #15535 from fbuihuu/update-runtime-watchdog-on-reload
pid1: update RuntimeWatchogSec setting on daemon-reload as well
2020-05-20 15:40:34 +02:00
ExtinctFire
929fed02df load-fragment: fix a typo
Correct the typo of “priority” in log message
2020-05-20 15:22:37 +02:00
Martin Hundebøll
ad76560525 man: document x-systemd.rw-only fstab option 2020-05-20 14:26:04 +02:00
Martin Hundebøll
f42aa41683 fstab-generator: add x-systemd.rw-only option support
Support enabling the ReadwriteOnly= unit setting from fstab using
'x-systemd.rw-only'
2020-05-20 14:26:04 +02:00
Martin Hundebøll
75f4bd7fd0 man: document ReadWriteOnly property for mount units 2020-05-20 14:26:04 +02:00
Zbigniew Jędrzejewski-Szmek
a2dd991d0f bus-message: immediately reject messages with invalid type
For whatever reason, we were very permissive with accepting messages
of unknown type. Let's just reject any unknown types as early as
possible.
2020-05-20 09:34:09 +02:00
Zbigniew Jędrzejewski-Szmek
e0c17a7d1b bus-message: fix negative offset with ~empty message
In the linked reproducer, m->fields_size == 0, and we calculate ri == -1, which
of course doesn't end well. Skip the whole calculation if m->fields_size == 0,
and also check that we don't go negative even if it is non-zero.

Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=19446 and #15583.
2020-05-20 09:33:54 +02:00
Susant Sahani
2d3adfa6c4 DHCPv6: MUD URL lengh - use UINT8_MAX instead of 255 2020-05-20 07:59:01 +02:00
Susant Sahani
ed0d1b2e99 network: DHCPv6 - Add support to send vendor class information
Frame 1: 177 bytes on wire (1416 bits), 177 bytes captured (1416 bits) on interface veth-peer, id 0
Ethernet II, Src: 1e:04:f8:b8:2f:d4 (1e:04:f8:b8:2f:d4), Dst: IPv6mcast_01:00:02 (33:33:00:01:00:02)
Internet Protocol Version 6, Src: fe80::1c04:f8ff:feb8:2fd4, Dst: ff02::1:2
User Datagram Protocol, Src Port: 546, Dst Port: 547
DHCPv6
    Message type: Solicit (1)
    Transaction ID: 0x5ca46b
    Rapid Commit
    Identity Association for Non-temporary Address
    Fully Qualified Domain Name
    Vendor Class
        Option: Vendor Class (16)
        Length: 23
        Value: 0000ab11000048656c6c6f3a686f773a6172653a796f75
        Enterprise ID: Tom Gundersen (systemd) (43793)
        vendor-class-data: Hello:how:are:you
    Identity Association for Prefix Delegation
    Option Request
    Client Identifier
    Elapsed time
2020-05-20 07:58:03 +02:00
Susant Sahani
73c8ced784 sd-network: DHCPv6 - Add support to send vendor class data
```
21.16.  Vendor Class Option

   This option is used by a client to identify the vendor that
   manufactured the hardware on which the client is running.  The
   information contained in the data area of this option is contained in
   one or more opaque fields that identify details of the hardware
   configuration.  The format of the Vendor Class option is:

       0                   1                   2                   3
       0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |      OPTION_VENDOR_CLASS      |           option-len          |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                       enterprise-number                       |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      .                                                               .
      .                       vendor-class-data                       .
      .                             . . .                             .
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

                   Figure 28: Vendor Class Option Format

      option-code          OPTION_VENDOR_CLASS (16).

      option-len           4 + length of vendor-class-data field.

      enterprise-number    The vendor's registered Enterprise Number as
                           maintained by IANA [IANA-PEN].  A 4-octet
                           field containing an unsigned integer.

      vendor-class-data    The hardware configuration of the node on
                           which the client is running.  A
                           variable-length field (4 octets less than the
                           value in the option-len field).

   The vendor-class-data field is composed of a series of separate
   items, each of which describes some characteristic of the client's
   hardware configuration.  Examples of vendor-class-data instances
   might include the version of the operating system the client is
   running or the amount of memory installed on the client.

   Each instance of vendor-class-data is formatted as follows:

      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-...-+-+-+-+-+-+-+
      |       vendor-class-len        |          opaque-data          |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-...-+-+-+-+-+-+-+

               Figure 29: Format of vendor-class-data Field

   The vendor-class-len field is 2 octets long and specifies the length
   of the opaque vendor-class-data in network byte order.

   Servers and clients MUST NOT include more than one instance of
   OPTION_VENDOR_CLASS with the same Enterprise Number.  Each instance
   of OPTION_VENDOR_CLASS can carry multiple vendor-class-data
   instances.
   ```
2020-05-20 07:52:19 +02:00
Susant Sahani
d6463307e0 network: DHCPv4- Allow to set DHCP lease lifetime 2020-05-20 06:32:26 +02:00
Susant Sahani
4c0b8d563d sd-dhcpv4: Allow to configure lease lifetime 2020-05-20 06:30:05 +02:00
Franck Bui
b406c6d128 pid1: make manager_deserialize_{uid,gid}_refs() static
No functional change.
2020-05-19 15:48:54 +02:00
Franck Bui
80f605c807 pid1: make manager_serialize_{uid,gid}_refs() static
No functional change.
2020-05-19 15:48:54 +02:00
Franck Bui
06a4eb0737 pid1: make manager_vacuum_{uid,gid}_refs() static
No functional change.
2020-05-19 15:48:54 +02:00
Franck Bui
1addc46c8c pid1: make manager_flip_auto_status() static
No functional change.
2020-05-19 15:48:54 +02:00
Franck Bui
ffe5c01eaa pid1: fold load_configuration() into main()
That's reduce the number of functions dealing with configuration
parsing/loading and should make the code simpler especially since this function
was used only once.

No functional change.
2020-05-19 15:48:54 +02:00
Franck Bui
986935cf6a pid1: update manager settings on reload too
Most complexity of this patch is due to the fact that some manager settings
(basically the watchdog properties) can be set at runtime and in this case the
runtime values must be retained over daemon-reload or daemon-reexec.

For consistency sake, all watchdog properties behaves now the same way, that
is:

  - Values defined by config files can be overridden by writing the new value
    through their respective D-BUS properties. In this case, these values are
    preserved over reload/reexec until the special value '0' or USEC_INFINITY
    is written, which will then restore the last values loaded from the config
    files. If the restored value is '0' or 'USEC_INFINITY', the watchdogs will
    be disabled and the corresponding device will be closed.

  - Reading the properties from a user instance will return the USEC_INFINITY
    value as these properties are only meaningful for PID1.

  - Writing to one of the watchdog properties of a user instance's will be a
    NOP.

Fixes: #15453
2020-05-19 15:31:55 +02:00
Martin Hundebøll
c600357ba6 mount: add ReadWriteOnly property to fail on read-only mounts
Systems where a mount point is expected to be read-write needs a way to
fail mount units that fallback as read-only.

Add a property to allow setting the -w option when calling mount(8).
2020-05-01 13:23:30 +02:00
38 changed files with 728 additions and 290 deletions

View File

@ -332,6 +332,7 @@ All mount unit settings are available to transient units:
✓ SloppyOptions=
✓ LazyUnmount=
✓ ForceUnmount=
✓ ReadWriteOnly=
```
## Automount Unit Settings

View File

@ -359,6 +359,17 @@
<varname>Options=</varname> setting in a unit file.</para></listitem>
</varlistentry>
<varlistentry>
<term><option>x-systemd.rw-only</option></term>
<listitem><para>If a mount operation fails to mount the file system
read-write, it normally tries mounting the file system read-only instead.
This option disables that behaviour, and causes the mount to fail
immediately instead. This option is translated into the
<varname>ReadWriteOnly=</varname> setting in a unit file.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>_netdev</option></term>
@ -497,6 +508,19 @@
off.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>ReadWriteOnly=</varname></term>
<listitem><para>Takes a boolean argument. If false, a mount
point that shall be mounted read-write but cannot be mounted
so is retried to be mounted read-only. If true the operation
will fail immediately after the read-write mount attempt did
not succeed. This corresponds with
<citerefentry project='man-pages'><refentrytitle>mount</refentrytitle><manvolnum>8</manvolnum></citerefentry>'s
<parameter>-w</parameter> switch. Defaults to
off.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>ForceUnmount=</varname></term>

View File

@ -1623,6 +1623,15 @@
</listitem>
</varlistentry>
<varlistentry>
<term><varname>FallbackLeaseLifetimeSec=</varname></term>
<listitem>
<para>Allows to set DHCPv4 lease lifetime when DHCPv4 server does not send the lease lifetime.
Takes one of <literal>forever</literal> or <literal>infinity</literal> means that the address
never expires. Defaults to unset.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>SendRelease=</varname></term>
<listitem>
@ -1788,6 +1797,17 @@
currently NUL bytes are not allowed.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>VendorClass=</varname></term>
<listitem>
<para>A DHCPv6 client can use VendorClass option to identify the vendor that
manufactured the hardware on which the client is running. The information
contained in the data area of this option is contained in one or more opaque
fields that identify details of the hardware configuration. Takes a
whitespace-separated list of strings.</para>
</listitem>
</varlistentry>
</variablelist>
</refsect1>

View File

@ -331,7 +331,7 @@ int systemd_efi_options_variable(char **line) {
* does, let's return a recognizable error (EPERM), and if not ENODATA. */
if (access(k, F_OK) < 0)
return errno == -ENOENT ? -ENODATA : -errno;
return errno == ENOENT ? -ENODATA : -errno;
return -EPERM;
}

View File

@ -419,7 +419,7 @@ int read_full_virtual_file(const char *filename, char **ret_contents, size_t *re
break;
}
if (errno != -EINTR)
if (errno != EINTR)
return -errno;
}

View File

@ -517,7 +517,7 @@ static int copy_file_with_version_check(const char *from, const char *to, bool f
if (!force) {
fd_to = open(to, O_RDONLY|O_CLOEXEC|O_NOCTTY);
if (fd_to < 0) {
if (errno != -ENOENT)
if (errno != ENOENT)
return log_error_errno(errno, "Failed to open \"%s\" for reading: %m", to);
} else {
r = version_check(fd_from, from, fd_to, to);

View File

@ -244,6 +244,76 @@ static int property_get_show_status(
return sd_bus_message_append_basic(reply, 'b', &b);
}
static int property_get_runtime_watchdog(
sd_bus *bus,
const char *path,
const char *interface,
const char *property,
sd_bus_message *reply,
void *userdata,
sd_bus_error *error) {
Manager *m = userdata;
assert(m);
assert(bus);
assert(reply);
return sd_bus_message_append(reply, "t", manager_get_watchdog(m, WATCHDOG_RUNTIME));
}
static int property_get_reboot_watchdog(
sd_bus *bus,
const char *path,
const char *interface,
const char *property,
sd_bus_message *reply,
void *userdata,
sd_bus_error *error) {
Manager *m = userdata;
assert(m);
assert(bus);
assert(reply);
return sd_bus_message_append(reply, "t", manager_get_watchdog(m, WATCHDOG_REBOOT));
}
static int property_get_kexec_watchdog(
sd_bus *bus,
const char *path,
const char *interface,
const char *property,
sd_bus_message *reply,
void *userdata,
sd_bus_error *error) {
Manager *m = userdata;
assert(m);
assert(bus);
assert(reply);
return sd_bus_message_append(reply, "t", manager_get_watchdog(m, WATCHDOG_KEXEC));
}
static int property_set_watchdog(Manager *m, WatchdogType type, sd_bus_message *value) {
usec_t timeout;
int r;
assert(m);
assert(value);
assert_cc(sizeof(usec_t) == sizeof(uint64_t));
r = sd_bus_message_read(value, "t", &timeout);
if (r < 0)
return r;
return manager_set_watchdog_overridden(m, type, timeout);
}
static int property_set_runtime_watchdog(
sd_bus *bus,
const char *path,
@ -253,19 +323,37 @@ static int property_set_runtime_watchdog(
void *userdata,
sd_bus_error *error) {
usec_t *t = userdata;
int r;
return property_set_watchdog(userdata, WATCHDOG_RUNTIME, value);
}
static int property_set_reboot_watchdog(
sd_bus *bus,
const char *path,
const char *interface,
const char *property,
sd_bus_message *value,
void *userdata,
sd_bus_error *error) {
return property_set_watchdog(userdata, WATCHDOG_REBOOT, value);
}
static int property_set_kexec_watchdog(
sd_bus *bus,
const char *path,
const char *interface,
const char *property,
sd_bus_message *value,
void *userdata,
sd_bus_error *error) {
Manager *m = userdata;
assert(m);
assert(bus);
assert(value);
assert_cc(sizeof(usec_t) == sizeof(uint64_t));
r = sd_bus_message_read(value, "t", t);
if (r < 0)
return r;
return watchdog_set_timeout(t);
return property_set_watchdog(userdata, WATCHDOG_KEXEC, value);
}
static int bus_get_unit_by_name(Manager *m, sd_bus_message *message, const char *name, Unit **ret_unit, sd_bus_error *error) {
@ -2404,11 +2492,11 @@ const sd_bus_vtable bus_manager_vtable[] = {
SD_BUS_PROPERTY("UnitPath", "as", NULL, offsetof(Manager, lookup_paths.search_path), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("DefaultStandardOutput", "s", bus_property_get_exec_output, offsetof(Manager, default_std_output), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("DefaultStandardError", "s", bus_property_get_exec_output, offsetof(Manager, default_std_output), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_WRITABLE_PROPERTY("RuntimeWatchdogUSec", "t", bus_property_get_usec, property_set_runtime_watchdog, offsetof(Manager, runtime_watchdog), 0),
SD_BUS_WRITABLE_PROPERTY("RebootWatchdogUSec", "t", bus_property_get_usec, bus_property_set_usec, offsetof(Manager, reboot_watchdog), 0),
SD_BUS_WRITABLE_PROPERTY("RuntimeWatchdogUSec", "t", property_get_runtime_watchdog, property_set_runtime_watchdog, 0, 0),
SD_BUS_WRITABLE_PROPERTY("RebootWatchdogUSec", "t", property_get_reboot_watchdog, property_set_reboot_watchdog, 0, 0),
/* The following item is an obsolete alias */
SD_BUS_WRITABLE_PROPERTY("ShutdownWatchdogUSec", "t", bus_property_get_usec, bus_property_set_usec, offsetof(Manager, reboot_watchdog), SD_BUS_VTABLE_HIDDEN),
SD_BUS_WRITABLE_PROPERTY("KExecWatchdogUSec", "t", bus_property_get_usec, bus_property_set_usec, offsetof(Manager, kexec_watchdog), 0),
SD_BUS_WRITABLE_PROPERTY("ShutdownWatchdogUSec", "t", property_get_reboot_watchdog, property_set_reboot_watchdog, 0, SD_BUS_VTABLE_HIDDEN),
SD_BUS_WRITABLE_PROPERTY("KExecWatchdogUSec", "t", property_get_kexec_watchdog, property_set_kexec_watchdog, 0, 0),
SD_BUS_WRITABLE_PROPERTY("ServiceWatchdogs", "b", bus_property_get_bool, bus_property_set_bool, offsetof(Manager, service_watchdogs), 0),
SD_BUS_PROPERTY("ControlGroup", "s", NULL, offsetof(Manager, cgroup_root), 0),
SD_BUS_PROPERTY("SystemState", "s", property_get_system_state, 0, 0),

View File

@ -51,6 +51,7 @@ const sd_bus_vtable bus_mount_vtable[] = {
SD_BUS_PROPERTY("SloppyOptions", "b", bus_property_get_bool, offsetof(Mount, sloppy_options), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("LazyUnmount", "b", bus_property_get_bool, offsetof(Mount, lazy_unmount), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("ForceUnmount", "b", bus_property_get_bool, offsetof(Mount, force_unmount), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("ReadWriteOnly", "b", bus_property_get_bool, offsetof(Mount, read_write_only), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("Result", "s", property_get_result, offsetof(Mount, result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("UID", "u", bus_property_get_uid, offsetof(Unit, ref_uid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("GID", "u", bus_property_get_gid, offsetof(Unit, ref_gid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
@ -102,6 +103,9 @@ static int bus_mount_set_transient_property(
if (streq(name, "ForceUnmount"))
return bus_set_transient_bool(u, name, &m->force_unmount, message, flags, error);
if (streq(name, "ReadWriteOnly"))
return bus_set_transient_bool(u, name, &m->read_write_only, message, flags, error);
return 0;
}

View File

@ -429,6 +429,7 @@ Mount.DirectoryMode, config_parse_mode, 0,
Mount.SloppyOptions, config_parse_bool, 0, offsetof(Mount, sloppy_options)
Mount.LazyUnmount, config_parse_bool, 0, offsetof(Mount, lazy_unmount)
Mount.ForceUnmount, config_parse_bool, 0, offsetof(Mount, force_unmount)
Mount.ReadWriteOnly, config_parse_bool, 0, offsetof(Mount, read_write_only)
EXEC_CONTEXT_CONFIG_ITEMS(Mount)m4_dnl
CGROUP_CONTEXT_CONFIG_ITEMS(Mount)m4_dnl
KILL_CONTEXT_CONFIG_ITEMS(Mount)m4_dnl

View File

@ -5157,7 +5157,7 @@ int config_parse_swap_priority(
r = safe_atoi(rvalue, &priority);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r, "Invalid swap pririty '%s', ignoring.", rvalue);
log_syntax(unit, LOG_ERR, filename, line, r, "Invalid swap priority '%s', ignoring.", rvalue);
return 0;
}

View File

@ -713,16 +713,18 @@ static void set_manager_settings(Manager *m) {
assert(m);
/* Propagates the various manager settings into the manager object, i.e. properties that effect the manager
* itself (as opposed to just being inherited into newly allocated units, see set_manager_defaults() above). */
/* Propagates the various manager settings into the manager object, i.e. properties that
* effect the manager itself (as opposed to just being inherited into newly allocated
* units, see set_manager_defaults() above). */
m->confirm_spawn = arg_confirm_spawn;
m->service_watchdogs = arg_service_watchdogs;
m->runtime_watchdog = arg_runtime_watchdog;
m->reboot_watchdog = arg_reboot_watchdog;
m->kexec_watchdog = arg_kexec_watchdog;
m->cad_burst_action = arg_cad_burst_action;
manager_set_watchdog(m, WATCHDOG_RUNTIME, arg_runtime_watchdog);
manager_set_watchdog(m, WATCHDOG_REBOOT, arg_reboot_watchdog);
manager_set_watchdog(m, WATCHDOG_KEXEC, arg_kexec_watchdog);
manager_set_show_status(m, arg_show_status, "commandline");
m->status_unit_format = arg_status_unit_format;
}
@ -1816,6 +1818,7 @@ static int invoke_main_loop(
(void) parse_configuration(saved_rlimit_nofile, saved_rlimit_memlock);
set_manager_defaults(m);
set_manager_settings(m);
update_cpu_affinity(false);
update_numa_policy(false);
@ -2006,9 +2009,6 @@ static int initialize_runtime(
if (r < 0)
log_warning_errno(r, "Failed to set watchdog device to %s, ignoring: %m", arg_watchdog_device);
}
if (timestamp_is_set(arg_runtime_watchdog))
watchdog_set_timeout(&arg_runtime_watchdog);
}
if (arg_timer_slack_nsec != NSEC_INFINITY)
@ -2282,29 +2282,6 @@ static int parse_configuration(const struct rlimit *saved_rlimit_nofile,
/* Note that this also parses bits from the kernel command line, including "debug". */
log_parse_environment();
return 0;
}
static int load_configuration(
int argc,
char **argv,
const struct rlimit *saved_rlimit_nofile,
const struct rlimit *saved_rlimit_memlock,
const char **ret_error_message) {
int r;
assert(saved_rlimit_nofile);
assert(saved_rlimit_memlock);
assert(ret_error_message);
(void) parse_configuration(saved_rlimit_nofile, saved_rlimit_memlock);
r = parse_argv(argc, argv);
if (r < 0) {
*ret_error_message = "Failed to parse commandline arguments";
return r;
}
/* Initialize the show status setting if it hasn't been set explicitly yet */
if (arg_show_status == _SHOW_STATUS_INVALID)
arg_show_status = SHOW_STATUS_YES;
@ -2650,9 +2627,13 @@ int main(int argc, char *argv[]) {
(void) reset_all_signal_handlers();
(void) ignore_signals(SIGNALS_IGNORE, -1);
r = load_configuration(argc, argv, &saved_rlimit_nofile, &saved_rlimit_memlock, &error_message);
if (r < 0)
(void) parse_configuration(&saved_rlimit_nofile, &saved_rlimit_memlock);
r = parse_argv(argc, argv);
if (r < 0) {
error_message = "Failed to parse commandline arguments";
goto finish;
}
r = safety_checks();
if (r < 0)
@ -2787,8 +2768,8 @@ finish:
pager_close();
if (m) {
arg_reboot_watchdog = m->reboot_watchdog;
arg_kexec_watchdog = m->kexec_watchdog;
arg_reboot_watchdog = manager_get_watchdog(m, WATCHDOG_REBOOT);
arg_kexec_watchdog = manager_get_watchdog(m, WATCHDOG_KEXEC);
m = manager_free(m);
}

View File

@ -110,6 +110,7 @@ static int manager_dispatch_sigchld(sd_event_source *source, void *userdata);
static int manager_dispatch_timezone_change(sd_event_source *source, const struct inotify_event *event, void *userdata);
static int manager_run_environment_generators(Manager *m);
static int manager_run_generators(Manager *m);
static void manager_vacuum(Manager *m);
static usec_t manager_watch_jobs_next_time(Manager *m) {
return usec_add(now(CLOCK_MONOTONIC),
@ -181,7 +182,7 @@ static void draw_cylon(char buffer[], size_t buflen, unsigned width, unsigned po
}
}
void manager_flip_auto_status(Manager *m, bool enable, const char *reason) {
static void manager_flip_auto_status(Manager *m, bool enable, const char *reason) {
assert(m);
if (enable) {
@ -779,6 +780,10 @@ int manager_new(UnitFileScope scope, ManagerTestRunFlags test_run_flags, Manager
.original_log_level = -1,
.original_log_target = _LOG_TARGET_INVALID,
.watchdog_overridden[WATCHDOG_RUNTIME] = USEC_INFINITY,
.watchdog_overridden[WATCHDOG_REBOOT] = USEC_INFINITY,
.watchdog_overridden[WATCHDOG_KEXEC] = USEC_INFINITY,
.notify_fd = -1,
.cgroups_agent_fd = -1,
.signal_fd = -1,
@ -1596,20 +1601,6 @@ static void manager_preset_all(Manager *m) {
log_info("Populated /etc with preset unit settings.");
}
static void manager_vacuum(Manager *m) {
assert(m);
/* Release any dynamic users no longer referenced */
dynamic_user_vacuum(m, true);
/* Release any references to UIDs/GIDs no longer referenced, and destroy any IPC owned by them */
manager_vacuum_uid_refs(m);
manager_vacuum_gid_refs(m);
/* Release any runtimes no longer referenced */
exec_runtime_vacuum(m);
}
static void manager_ready(Manager *m) {
assert(m);
@ -2922,9 +2913,10 @@ int manager_loop(Manager *m) {
return log_error_errno(r, "Failed to enable SIGCHLD event source: %m");
while (m->objective == MANAGER_OK) {
usec_t wait_usec;
usec_t wait_usec, watchdog_usec;
if (timestamp_is_set(m->runtime_watchdog) && MANAGER_IS_SYSTEM(m))
watchdog_usec = manager_get_watchdog(m, WATCHDOG_RUNTIME);
if (timestamp_is_set(watchdog_usec))
watchdog_ping();
if (!ratelimit_below(&rl)) {
@ -2955,7 +2947,7 @@ int manager_loop(Manager *m) {
continue;
/* Sleep for watchdog runtime wait time */
if (MANAGER_IS_SYSTEM(m))
if (timestamp_is_set(watchdog_usec))
wait_usec = watchdog_runtime_wait();
else
wait_usec = USEC_INFINITY;
@ -3158,6 +3150,47 @@ static bool manager_timestamp_shall_serialize(ManagerTimestamp t) {
MANAGER_TIMESTAMP_UNITS_LOAD_START, MANAGER_TIMESTAMP_UNITS_LOAD_FINISH);
}
#define DESTROY_IPC_FLAG (UINT32_C(1) << 31)
static void manager_serialize_uid_refs_internal(
Manager *m,
FILE *f,
Hashmap **uid_refs,
const char *field_name) {
Iterator i;
void *p, *k;
assert(m);
assert(f);
assert(uid_refs);
assert(field_name);
/* Serialize the UID reference table. Or actually, just the IPC destruction flag of it, as
* the actual counter of it is better rebuild after a reload/reexec. */
HASHMAP_FOREACH_KEY(p, k, *uid_refs, i) {
uint32_t c;
uid_t uid;
uid = PTR_TO_UID(k);
c = PTR_TO_UINT32(p);
if (!(c & DESTROY_IPC_FLAG))
continue;
(void) serialize_item_format(f, field_name, UID_FMT, uid);
}
}
static void manager_serialize_uid_refs(Manager *m, FILE *f) {
manager_serialize_uid_refs_internal(m, f, &m->uid_refs, "destroy-ipc-uid");
}
static void manager_serialize_gid_refs(Manager *m, FILE *f) {
manager_serialize_uid_refs_internal(m, f, &m->gid_refs, "destroy-ipc-gid");
}
int manager_serialize(
Manager *m,
FILE *f,
@ -3196,6 +3229,10 @@ int manager_serialize(
if (m->log_target_overridden)
(void) serialize_item(f, "log-target-override", log_target_to_string(log_get_target()));
(void) serialize_usec(f, "runtime-watchdog-overridden", m->watchdog_overridden[WATCHDOG_RUNTIME]);
(void) serialize_usec(f, "reboot-watchdog-overridden", m->watchdog_overridden[WATCHDOG_REBOOT]);
(void) serialize_usec(f, "kexec-watchdog-overridden", m->watchdog_overridden[WATCHDOG_KEXEC]);
for (q = 0; q < _MANAGER_TIMESTAMP_MAX; q++) {
_cleanup_free_ char *joined = NULL;
@ -3328,6 +3365,114 @@ static int manager_deserialize_units(Manager *m, FILE *f, FDSet *fds) {
return 0;
}
usec_t manager_get_watchdog(Manager *m, WatchdogType t) {
assert(m);
if (MANAGER_IS_USER(m))
return USEC_INFINITY;
if (timestamp_is_set(m->watchdog_overridden[t]))
return m->watchdog_overridden[t];
return m->watchdog[t];
}
void manager_set_watchdog(Manager *m, WatchdogType t, usec_t timeout) {
int r = 0;
assert(m);
if (MANAGER_IS_USER(m))
return;
if (m->watchdog[t] == timeout)
return;
if (t == WATCHDOG_RUNTIME)
if (!timestamp_is_set(m->watchdog_overridden[WATCHDOG_RUNTIME])) {
if (timestamp_is_set(timeout))
r = watchdog_set_timeout(&timeout);
else
watchdog_close(true);
}
if (r >= 0)
m->watchdog[t] = timeout;
}
int manager_set_watchdog_overridden(Manager *m, WatchdogType t, usec_t timeout) {
int r = 0;
assert(m);
if (MANAGER_IS_USER(m))
return 0;
if (m->watchdog_overridden[t] == timeout)
return 0;
if (t == WATCHDOG_RUNTIME) {
usec_t *p;
p = timestamp_is_set(timeout) ? &timeout : &m->watchdog[t];
if (timestamp_is_set(*p))
r = watchdog_set_timeout(p);
else
watchdog_close(true);
}
if (r >= 0)
m->watchdog_overridden[t] = timeout;
return 0;
}
static void manager_deserialize_uid_refs_one_internal(
Manager *m,
Hashmap** uid_refs,
const char *value) {
uid_t uid;
uint32_t c;
int r;
assert(m);
assert(uid_refs);
assert(value);
r = parse_uid(value, &uid);
if (r < 0 || uid == 0) {
log_debug("Unable to parse UID reference serialization: " UID_FMT, uid);
return;
}
r = hashmap_ensure_allocated(uid_refs, &trivial_hash_ops);
if (r < 0) {
log_oom();
return;
}
c = PTR_TO_UINT32(hashmap_get(*uid_refs, UID_TO_PTR(uid)));
if (c & DESTROY_IPC_FLAG)
return;
c |= DESTROY_IPC_FLAG;
r = hashmap_replace(*uid_refs, UID_TO_PTR(uid), UINT32_TO_PTR(c));
if (r < 0) {
log_debug_errno(r, "Failed to add UID reference entry: %m");
return;
}
}
static void manager_deserialize_uid_refs_one(Manager *m, const char *value) {
manager_deserialize_uid_refs_one_internal(m, &m->uid_refs, value);
}
static void manager_deserialize_gid_refs_one(Manager *m, const char *value) {
manager_deserialize_uid_refs_one_internal(m, &m->gid_refs, value);
}
int manager_deserialize(Manager *m, FILE *f, FDSet *fds) {
int r = 0;
@ -3451,6 +3596,30 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) {
else
manager_override_log_target(m, target);
} else if ((val = startswith(l, "runtime-watchdog-overridden="))) {
usec_t t;
if (deserialize_usec(val, &t) < 0)
log_notice("Failed to parse runtime-watchdog-overridden value '%s', ignoring.", val);
else
manager_set_watchdog_overridden(m, WATCHDOG_RUNTIME, t);
} else if ((val = startswith(l, "reboot-watchdog-overridden="))) {
usec_t t;
if (deserialize_usec(val, &t) < 0)
log_notice("Failed to parse reboot-watchdog-overridden value '%s', ignoring.", val);
else
manager_set_watchdog_overridden(m, WATCHDOG_REBOOT, t);
} else if ((val = startswith(l, "kexec-watchdog-overridden="))) {
usec_t t;
if (deserialize_usec(val, &t) < 0)
log_notice("Failed to parse kexec-watchdog-overridden value '%s', ignoring.", val);
else
manager_set_watchdog_overridden(m, WATCHDOG_KEXEC, t);
} else if (startswith(l, "env=")) {
r = deserialize_environment(l + 4, &m->client_environment);
if (r < 0)
@ -4301,8 +4470,6 @@ ManagerState manager_state(Manager *m) {
return MANAGER_RUNNING;
}
#define DESTROY_IPC_FLAG (UINT32_C(1) << 31)
static void manager_unref_uid_internal(
Manager *m,
Hashmap **uid_refs,
@ -4441,97 +4608,26 @@ static void manager_vacuum_uid_refs_internal(
}
}
void manager_vacuum_uid_refs(Manager *m) {
static void manager_vacuum_uid_refs(Manager *m) {
manager_vacuum_uid_refs_internal(m, &m->uid_refs, clean_ipc_by_uid);
}
void manager_vacuum_gid_refs(Manager *m) {
static void manager_vacuum_gid_refs(Manager *m) {
manager_vacuum_uid_refs_internal(m, &m->gid_refs, clean_ipc_by_gid);
}
static void manager_serialize_uid_refs_internal(
Manager *m,
FILE *f,
Hashmap **uid_refs,
const char *field_name) {
Iterator i;
void *p, *k;
static void manager_vacuum(Manager *m) {
assert(m);
assert(f);
assert(uid_refs);
assert(field_name);
/* Serialize the UID reference table. Or actually, just the IPC destruction flag of it, as the actual counter
* of it is better rebuild after a reload/reexec. */
/* Release any dynamic users no longer referenced */
dynamic_user_vacuum(m, true);
HASHMAP_FOREACH_KEY(p, k, *uid_refs, i) {
uint32_t c;
uid_t uid;
/* Release any references to UIDs/GIDs no longer referenced, and destroy any IPC owned by them */
manager_vacuum_uid_refs(m);
manager_vacuum_gid_refs(m);
uid = PTR_TO_UID(k);
c = PTR_TO_UINT32(p);
if (!(c & DESTROY_IPC_FLAG))
continue;
(void) serialize_item_format(f, field_name, UID_FMT, uid);
}
}
void manager_serialize_uid_refs(Manager *m, FILE *f) {
manager_serialize_uid_refs_internal(m, f, &m->uid_refs, "destroy-ipc-uid");
}
void manager_serialize_gid_refs(Manager *m, FILE *f) {
manager_serialize_uid_refs_internal(m, f, &m->gid_refs, "destroy-ipc-gid");
}
static void manager_deserialize_uid_refs_one_internal(
Manager *m,
Hashmap** uid_refs,
const char *value) {
uid_t uid;
uint32_t c;
int r;
assert(m);
assert(uid_refs);
assert(value);
r = parse_uid(value, &uid);
if (r < 0 || uid == 0) {
log_debug("Unable to parse UID reference serialization: " UID_FMT, uid);
return;
}
r = hashmap_ensure_allocated(uid_refs, &trivial_hash_ops);
if (r < 0) {
log_oom();
return;
}
c = PTR_TO_UINT32(hashmap_get(*uid_refs, UID_TO_PTR(uid)));
if (c & DESTROY_IPC_FLAG)
return;
c |= DESTROY_IPC_FLAG;
r = hashmap_replace(*uid_refs, UID_TO_PTR(uid), UINT32_TO_PTR(c));
if (r < 0) {
log_debug_errno(r, "Failed to add UID reference entry: %m");
return;
}
}
void manager_deserialize_uid_refs_one(Manager *m, const char *value) {
manager_deserialize_uid_refs_one_internal(m, &m->uid_refs, value);
}
void manager_deserialize_gid_refs_one(Manager *m, const char *value) {
manager_deserialize_uid_refs_one_internal(m, &m->gid_refs, value);
/* Release any runtimes no longer referenced */
exec_runtime_vacuum(m);
}
int manager_dispatch_user_lookup_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata) {

View File

@ -114,6 +114,13 @@ typedef enum ManagerTimestamp {
_MANAGER_TIMESTAMP_INVALID = -1,
} ManagerTimestamp;
typedef enum WatchdogType {
WATCHDOG_RUNTIME,
WATCHDOG_REBOOT,
WATCHDOG_KEXEC,
_WATCHDOG_TYPE_MAX,
} WatchdogType;
#include "execute.h"
#include "job.h"
#include "path-lookup.h"
@ -231,9 +238,8 @@ struct Manager {
char **transient_environment; /* The environment, as determined from config files, kernel cmdline and environment generators */
char **client_environment; /* Environment variables created by clients through the bus API */
usec_t runtime_watchdog;
usec_t reboot_watchdog;
usec_t kexec_watchdog;
usec_t watchdog[_WATCHDOG_TYPE_MAX];
usec_t watchdog_overridden[_WATCHDOG_TYPE_MAX];
dual_timestamp timestamps[_MANAGER_TIMESTAMP_MAX];
@ -510,7 +516,6 @@ void manager_set_show_status(Manager *m, ShowStatus mode, const char *reason);
void manager_set_first_boot(Manager *m, bool b);
void manager_status_printf(Manager *m, StatusType type, const char *status, const char *format, ...) _printf_(4,5);
void manager_flip_auto_status(Manager *m, bool enable, const char *reason);
Set *manager_get_units_requiring_mounts_for(Manager *m, const char *path);
@ -524,15 +529,6 @@ int manager_ref_uid(Manager *m, uid_t uid, bool clean_ipc);
void manager_unref_gid(Manager *m, gid_t gid, bool destroy_now);
int manager_ref_gid(Manager *m, gid_t gid, bool destroy_now);
void manager_vacuum_uid_refs(Manager *m);
void manager_vacuum_gid_refs(Manager *m);
void manager_serialize_uid_refs(Manager *m, FILE *f);
void manager_deserialize_uid_refs_one(Manager *m, const char *value);
void manager_serialize_gid_refs(Manager *m, FILE *f);
void manager_deserialize_gid_refs_one(Manager *m, const char *value);
char *manager_taint_string(Manager *m);
void manager_ref_console(Manager *m);
@ -555,5 +551,9 @@ const char *manager_timestamp_to_string(ManagerTimestamp m) _const_;
ManagerTimestamp manager_timestamp_from_string(const char *s) _pure_;
ManagerTimestamp manager_timestamp_initrd_mangle(ManagerTimestamp s);
usec_t manager_get_watchdog(Manager *m, WatchdogType t);
void manager_set_watchdog(Manager *m, WatchdogType t, usec_t timeout);
int manager_set_watchdog_overridden(Manager *m, WatchdogType t, usec_t timeout);
const char* oom_policy_to_string(OOMPolicy i) _const_;
OOMPolicy oom_policy_from_string(const char *s) _pure_;

View File

@ -780,6 +780,7 @@ static void mount_dump(Unit *u, FILE *f, const char *prefix) {
"%sSloppyOptions: %s\n"
"%sLazyUnmount: %s\n"
"%sForceUnmount: %s\n"
"%sReadWriteOnly: %s\n"
"%sTimeoutSec: %s\n",
prefix, mount_state_to_string(m->state),
prefix, mount_result_to_string(m->result),
@ -795,6 +796,7 @@ static void mount_dump(Unit *u, FILE *f, const char *prefix) {
prefix, yes_no(m->sloppy_options),
prefix, yes_no(m->lazy_unmount),
prefix, yes_no(m->force_unmount),
prefix, yes_no(m->read_write_only),
prefix, format_timespan(buf, sizeof(buf), m->timeout_usec, USEC_PER_SEC));
if (m->control_pid > 0)
@ -1026,6 +1028,8 @@ static void mount_enter_mounting(Mount *m) {
r = exec_command_set(m->control_command, MOUNT_PATH, p->what, m->where, NULL);
if (r >= 0 && m->sloppy_options)
r = exec_command_append(m->control_command, "-s", NULL);
if (r >= 0 && m->read_write_only)
r = exec_command_append(m->control_command, "-w", NULL);
if (r >= 0 && p->fstype)
r = exec_command_append(m->control_command, "-t", p->fstype, NULL);
if (r >= 0 && !isempty(opts))
@ -1086,6 +1090,8 @@ static void mount_enter_remounting(Mount *m) {
"-o", o, NULL);
if (r >= 0 && m->sloppy_options)
r = exec_command_append(m->control_command, "-s", NULL);
if (r >= 0 && m->read_write_only)
r = exec_command_append(m->control_command, "-w", NULL);
if (r >= 0 && p->fstype)
r = exec_command_append(m->control_command, "-t", p->fstype, NULL);
} else

View File

@ -59,6 +59,8 @@ struct Mount {
bool lazy_unmount;
bool force_unmount;
bool read_write_only;
MountResult result;
MountResult reload_result;
MountResult clean_result;

View File

@ -35,6 +35,7 @@ typedef enum MountpointFlags {
AUTOMOUNT = 1 << 2,
MAKEFS = 1 << 3,
GROWFS = 1 << 4,
RWONLY = 1 << 5,
} MountpointFlags;
static const char *arg_dest = NULL;
@ -472,6 +473,9 @@ static int add_mount(
if (r < 0)
return r;
if (flags & RWONLY)
fprintf(f, "ReadWriteOnly=yes\n");
r = fflush_and_check(f);
if (r < 0)
return log_error_errno(r, "Failed to write unit file %s: %m", name);
@ -583,7 +587,7 @@ static int parse_fstab(bool initrd) {
while ((me = getmntent(f))) {
_cleanup_free_ char *where = NULL, *what = NULL, *canonical_where = NULL;
bool makefs, growfs, noauto, nofail;
bool makefs, growfs, noauto, nofail, rwonly;
int k;
if (initrd && !mount_in_initrd(me))
@ -623,6 +627,7 @@ static int parse_fstab(bool initrd) {
makefs = fstab_test_option(me->mnt_opts, "x-systemd.makefs\0");
growfs = fstab_test_option(me->mnt_opts, "x-systemd.growfs\0");
rwonly = fstab_test_option(me->mnt_opts, "x-systemd.rw-only\0");
noauto = fstab_test_yes_no_option(me->mnt_opts, "noauto\0" "auto\0");
nofail = fstab_test_yes_no_option(me->mnt_opts, "nofail\0" "fail\0");
@ -655,7 +660,7 @@ static int parse_fstab(bool initrd) {
me->mnt_type,
me->mnt_opts,
me->mnt_passno,
makefs*MAKEFS | growfs*GROWFS | noauto*NOAUTO | nofail*NOFAIL | automount*AUTOMOUNT,
makefs*MAKEFS | growfs*GROWFS | noauto*NOAUTO | nofail*NOFAIL | automount*AUTOMOUNT | rwonly*RWONLY,
post,
fstab);
}

View File

@ -1051,7 +1051,7 @@ static int home_remove(UserRecord *h) {
assert(ip);
if (stat(ip, &st) < 0) {
if (errno != -ENOENT)
if (errno != ENOENT)
return log_error_errno(errno, "Failed to stat() %s: %m", ip);
} else {

View File

@ -15,7 +15,6 @@
#include "udev-util.h"
#include "virt.h"
#define SYSTEMD_PEN 43793
#define HASH_KEY SD_ID128_MAKE(80,11,8c,c2,fe,4a,03,ee,3e,d6,0c,6f,36,39,14,09)
#define APPLICATION_ID SD_ID128_MAKE(a5,0a,d1,12,bf,60,45,77,a2,fb,74,1a,b1,95,5b,03)
#define USEC_2000 ((usec_t) 946684800000000) /* 2000-01-01 00:00:00 UTC */

View File

@ -8,6 +8,8 @@
#include "time-util.h"
#include "unaligned.h"
#define SYSTEMD_PEN 43793
typedef enum DUIDType {
DUID_TYPE_LLT = 1,
DUID_TYPE_EN = 2,

View File

@ -98,6 +98,7 @@ int dhcp6_option_append_ia(uint8_t **buf, size_t *buflen, const DHCP6IA *ia);
int dhcp6_option_append_pd(uint8_t *buf, size_t len, const DHCP6IA *pd, DHCP6Address *hint_pd_prefix);
int dhcp6_option_append_fqdn(uint8_t **buf, size_t *buflen, const char *fqdn);
int dhcp6_option_append_user_class(uint8_t **buf, size_t *buflen, char **user_class);
int dhcp6_option_append_vendor_class(uint8_t **buf, size_t *buflen, char **user_class);
int dhcp6_option_parse(uint8_t **buf, size_t *buflen, uint16_t *optcode,
size_t *optlen, uint8_t **optvalue);
int dhcp6_option_parse_status(DHCP6Option *option, size_t len);

View File

@ -9,6 +9,7 @@
#include "sd-dhcp6-client.h"
#include "alloc-util.h"
#include "dhcp-identifier.h"
#include "dhcp6-internal.h"
#include "dhcp6-lease-internal.h"
#include "dhcp6-protocol.h"
@ -180,7 +181,6 @@ int dhcp6_option_append_user_class(uint8_t **buf, size_t *buflen, char **user_cl
if (len > 0xffff)
return -ENAMETOOLONG;
q = realloc(p, total + len + 2);
if (!q)
return -ENOMEM;
@ -197,6 +197,46 @@ int dhcp6_option_append_user_class(uint8_t **buf, size_t *buflen, char **user_cl
return dhcp6_option_append(buf, buflen, SD_DHCP6_OPTION_USER_CLASS, total, p);
}
int dhcp6_option_append_vendor_class(uint8_t **buf, size_t *buflen, char **vendor_class) {
_cleanup_free_ uint8_t *p = NULL;
uint32_t enterprise_identifier;
size_t total, offset;
char **s;
assert(buf);
assert(*buf);
assert(buflen);
assert(vendor_class);
enterprise_identifier = htobe32(SYSTEMD_PEN);
p = memdup(&enterprise_identifier, sizeof(enterprise_identifier));
if (!p)
return -ENOMEM;
total = sizeof(enterprise_identifier);
offset = total;
STRV_FOREACH(s, vendor_class) {
size_t len = strlen(*s);
uint8_t *q;
q = realloc(p, total + len + 2);
if (!q)
return -ENOMEM;
p = q;
unaligned_write_be16(&p[offset], len);
memcpy(&p[offset + 2], *s, len);
offset += 2 + len;
total += 2 + len;
}
return dhcp6_option_append(buf, buflen, SD_DHCP6_OPTION_VENDOR_CLASS, total, p);
}
int dhcp6_option_append_pd(uint8_t *buf, size_t len, const DHCP6IA *pd, DHCP6Address *hint_pd_prefix) {
DHCP6Option *option = (DHCP6Option *)buf;
size_t i = sizeof(*option) + sizeof(pd->ia_pd);

View File

@ -87,6 +87,7 @@ struct sd_dhcp_client {
char *mudurl;
char **user_class;
uint32_t mtu;
uint32_t fallback_lease_lifetime;
uint32_t xid;
usec_t start_time;
uint64_t attempt;
@ -612,6 +613,15 @@ int sd_dhcp_client_set_service_type(sd_dhcp_client *client, int type) {
return 0;
}
int sd_dhcp_client_set_fallback_lease_lifetime(sd_dhcp_client *client, uint32_t fallback_lease_lifetime) {
assert_return(client, -EINVAL);
assert_return(fallback_lease_lifetime > 0, -EINVAL);
client->fallback_lease_lifetime = fallback_lease_lifetime;
return 0;
}
static int client_notify(sd_dhcp_client *client, int event) {
assert(client);
@ -850,11 +860,82 @@ static int dhcp_client_send_raw(
packet, len);
}
static int client_append_common_discover_request_options(sd_dhcp_client *client, DHCPPacket *packet, size_t *optoffset, size_t optlen) {
sd_dhcp_option *j;
Iterator i;
int r;
assert(client);
if (client->hostname) {
/* According to RFC 4702 "clients that send the Client FQDN option in
their messages MUST NOT also send the Host Name option". Just send
one of the two depending on the hostname type.
*/
if (dns_name_is_single_label(client->hostname)) {
/* it is unclear from RFC 2131 if client should send hostname in
DHCPDISCOVER but dhclient does and so we do as well
*/
r = dhcp_option_append(&packet->dhcp, optlen, optoffset, 0,
SD_DHCP_OPTION_HOST_NAME,
strlen(client->hostname), client->hostname);
} else
r = client_append_fqdn_option(&packet->dhcp, optlen, optoffset,
client->hostname);
if (r < 0)
return r;
}
if (client->vendor_class_identifier) {
r = dhcp_option_append(&packet->dhcp, optlen, optoffset, 0,
SD_DHCP_OPTION_VENDOR_CLASS_IDENTIFIER,
strlen(client->vendor_class_identifier),
client->vendor_class_identifier);
if (r < 0)
return r;
}
if (client->mudurl) {
r = dhcp_option_append(&packet->dhcp, optlen, optoffset, 0,
SD_DHCP_OPTION_MUD_URL,
strlen(client->mudurl),
client->mudurl);
if (r < 0)
return r;
}
if (client->user_class) {
r = dhcp_option_append(&packet->dhcp, optlen, optoffset, 0,
SD_DHCP_OPTION_USER_CLASS,
strv_length(client->user_class),
client->user_class);
if (r < 0)
return r;
}
ORDERED_HASHMAP_FOREACH(j, client->extra_options, i) {
r = dhcp_option_append(&packet->dhcp, optlen, optoffset, 0,
j->option, j->length, j->data);
if (r < 0)
return r;
}
if (!ordered_hashmap_isempty(client->vendor_options)) {
r = dhcp_option_append(
&packet->dhcp, optlen, optoffset, 0,
SD_DHCP_OPTION_VENDOR_SPECIFIC,
ordered_hashmap_size(client->vendor_options), client->vendor_options);
if (r < 0)
return r;
}
return 0;
}
static int client_send_discover(sd_dhcp_client *client) {
_cleanup_free_ DHCPPacket *discover = NULL;
size_t optoffset, optlen;
sd_dhcp_option *j;
Iterator i;
int r;
assert(client);
@ -881,67 +962,9 @@ static int client_send_discover(sd_dhcp_client *client) {
return r;
}
if (client->hostname) {
/* According to RFC 4702 "clients that send the Client FQDN option in
their messages MUST NOT also send the Host Name option". Just send
one of the two depending on the hostname type.
*/
if (dns_name_is_single_label(client->hostname)) {
/* it is unclear from RFC 2131 if client should send hostname in
DHCPDISCOVER but dhclient does and so we do as well
*/
r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0,
SD_DHCP_OPTION_HOST_NAME,
strlen(client->hostname), client->hostname);
} else
r = client_append_fqdn_option(&discover->dhcp, optlen, &optoffset,
client->hostname);
if (r < 0)
return r;
}
if (client->vendor_class_identifier) {
r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0,
SD_DHCP_OPTION_VENDOR_CLASS_IDENTIFIER,
strlen(client->vendor_class_identifier),
client->vendor_class_identifier);
if (r < 0)
return r;
}
if (client->mudurl) {
r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0,
SD_DHCP_OPTION_MUD_URL,
strlen(client->mudurl),
client->mudurl);
if (r < 0)
return r;
}
if (client->user_class) {
r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0,
SD_DHCP_OPTION_USER_CLASS,
strv_length(client->user_class),
client->user_class);
if (r < 0)
return r;
}
ORDERED_HASHMAP_FOREACH(j, client->extra_options, i) {
r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0,
j->option, j->length, j->data);
if (r < 0)
return r;
}
if (!ordered_hashmap_isempty(client->vendor_options)) {
r = dhcp_option_append(
&discover->dhcp, optlen, &optoffset, 0,
SD_DHCP_OPTION_VENDOR_SPECIFIC,
ordered_hashmap_size(client->vendor_options), client->vendor_options);
if (r < 0)
return r;
}
r = client_append_common_discover_request_options(client, discover, &optoffset, optlen);
if (r < 0)
return r;
r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0,
SD_DHCP_OPTION_END, 0, NULL);
@ -1034,36 +1057,9 @@ static int client_send_request(sd_dhcp_client *client) {
return -EINVAL;
}
if (client->hostname) {
if (dns_name_is_single_label(client->hostname))
r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0,
SD_DHCP_OPTION_HOST_NAME,
strlen(client->hostname), client->hostname);
else
r = client_append_fqdn_option(&request->dhcp, optlen, &optoffset,
client->hostname);
if (r < 0)
return r;
}
if (client->vendor_class_identifier) {
r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0,
SD_DHCP_OPTION_VENDOR_CLASS_IDENTIFIER,
strlen(client->vendor_class_identifier),
client->vendor_class_identifier);
if (r < 0)
return r;
}
if (client->mudurl) {
r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0,
SD_DHCP_OPTION_MUD_URL,
strlen(client->mudurl),
client->mudurl);
if (r < 0)
return r;
}
r = client_append_common_discover_request_options(client, request, &optoffset, optlen);
if (r < 0)
return r;
r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0,
SD_DHCP_OPTION_END, 0, NULL);
@ -1419,6 +1415,9 @@ static int client_handle_offer(sd_dhcp_client *client, DHCPMessage *offer, size_
lease->next_server = offer->siaddr;
lease->address = offer->yiaddr;
if (lease->lifetime == 0 && client->fallback_lease_lifetime > 0)
lease->lifetime = client->fallback_lease_lifetime;
if (lease->address == 0 ||
lease->server_address == 0 ||
lease->lifetime == 0) {

View File

@ -68,6 +68,7 @@ struct sd_dhcp6_client {
char *fqdn;
char *mudurl;
char **user_class;
char **vendor_class;
sd_event_source *receive_message;
usec_t retransmit_time;
uint8_t retransmit_count;
@ -359,7 +360,7 @@ int sd_dhcp6_client_set_request_option(sd_dhcp6_client *client, uint16_t option)
assert_return(client, -EINVAL);
assert_return(client->state == DHCP6_STATE_STOPPED, -EBUSY);
if (option <= 0 || option >= 255)
if (option <= 0 || option >= UINT8_MAX)
return -EINVAL;
for (t = 0; t < client->req_opts_len; t++)
@ -380,7 +381,7 @@ int sd_dhcp6_client_set_request_mud_url(sd_dhcp6_client *client, const char *mud
assert_return(client, -EINVAL);
assert_return(client->state == DHCP6_STATE_STOPPED, -EBUSY);
assert_return(mudurl, -EINVAL);
assert_return(strlen(mudurl) <= 255, -EINVAL);
assert_return(strlen(mudurl) <= UINT8_MAX, -EINVAL);
assert_return(http_url_is_valid(mudurl), -EINVAL);
return free_and_strdup(&client->mudurl, mudurl);
@ -392,13 +393,14 @@ int sd_dhcp6_client_set_request_user_class(sd_dhcp6_client *client, char **user_
assert_return(client, -EINVAL);
assert_return(client->state == DHCP6_STATE_STOPPED, -EBUSY);
assert_return(user_class, -EINVAL);
STRV_FOREACH(p, user_class)
if (strlen(*p) > UINT16_MAX)
return -ENAMETOOLONG;
s = strv_copy((char **) user_class);
s = strv_copy(user_class);
if (!s)
return -ENOMEM;
@ -407,6 +409,27 @@ int sd_dhcp6_client_set_request_user_class(sd_dhcp6_client *client, char **user_
return 0;
}
int sd_dhcp6_client_set_request_vendor_class(sd_dhcp6_client *client, char **vendor_class) {
_cleanup_strv_free_ char **s = NULL;
char **p;
assert_return(client, -EINVAL);
assert_return(client->state == DHCP6_STATE_STOPPED, -EBUSY);
assert_return(vendor_class, -EINVAL);
STRV_FOREACH(p, vendor_class)
if (strlen(*p) > UINT8_MAX)
return -ENAMETOOLONG;
s = strv_copy(vendor_class);
if (!s)
return -ENOMEM;
client->vendor_class = TAKE_PTR(s);
return 0;
}
int sd_dhcp6_client_get_prefix_delegation(sd_dhcp6_client *client, int *delegation) {
assert_return(client, -EINVAL);
assert_return(delegation, -EINVAL);
@ -593,6 +616,12 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) {
return r;
}
if (client->vendor_class) {
r = dhcp6_option_append_vendor_class(&opt, &optlen, client->vendor_class);
if (r < 0)
return r;
}
if (FLAGS_SET(client->request, DHCP6_REQUEST_IA_PD)) {
r = dhcp6_option_append_pd(opt, optlen, &client->ia_pd, &client->hint_pd_prefix);
if (r < 0)
@ -645,6 +674,12 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) {
return r;
}
if (client->vendor_class) {
r = dhcp6_option_append_vendor_class(&opt, &optlen, client->vendor_class);
if (r < 0)
return r;
}
if (FLAGS_SET(client->request, DHCP6_REQUEST_IA_PD)) {
r = dhcp6_option_append_pd(opt, optlen, &client->lease->pd, NULL);
if (r < 0)
@ -685,6 +720,12 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) {
return r;
}
if (client->vendor_class) {
r = dhcp6_option_append_vendor_class(&opt, &optlen, client->vendor_class);
if (r < 0)
return r;
}
if (FLAGS_SET(client->request, DHCP6_REQUEST_IA_PD)) {
r = dhcp6_option_append_pd(opt, optlen, &client->lease->pd, NULL);
if (r < 0)
@ -1645,6 +1686,7 @@ static sd_dhcp6_client *dhcp6_client_free(sd_dhcp6_client *client) {
ordered_hashmap_free(client->extra_options);
strv_free(client->user_class);
strv_free(client->vendor_class);
return mfree(client);
}

View File

@ -451,7 +451,7 @@ int bus_message_from_header(
if (!IN_SET(h->version, 1, 2))
return -EBADMSG;
if (h->type == _SD_BUS_MESSAGE_TYPE_INVALID)
if (h->type <= _SD_BUS_MESSAGE_TYPE_INVALID || h->type >= _SD_BUS_MESSAGE_TYPE_MAX)
return -EBADMSG;
if (!IN_SET(h->endian, BUS_LITTLE_ENDIAN, BUS_BIG_ENDIAN))
@ -589,7 +589,7 @@ _public_ int sd_bus_message_new(
assert_return(bus = bus_resolve(bus), -ENOPKG);
assert_return(bus->state != BUS_UNSET, -ENOTCONN);
assert_return(m, -EINVAL);
assert_return(type < _SD_BUS_MESSAGE_TYPE_MAX, -EINVAL);
assert_return(type > _SD_BUS_MESSAGE_TYPE_INVALID && type < _SD_BUS_MESSAGE_TYPE_MAX, -EINVAL);
sd_bus_message *t = malloc0(ALIGN(sizeof(sd_bus_message)) + sizeof(struct bus_header));
if (!t)
@ -5202,29 +5202,34 @@ int bus_message_parse_fields(sd_bus_message *m) {
* table */
m->user_body_size = m->body_size - ((char*) m->footer + m->footer_accessible - p);
/* Pull out the offset table for the fields array */
sz = bus_gvariant_determine_word_size(m->fields_size, 0);
if (sz > 0) {
size_t framing;
void *q;
/* Pull out the offset table for the fields array, if any */
if (m->fields_size > 0) {
sz = bus_gvariant_determine_word_size(m->fields_size, 0);
if (sz > 0) {
size_t framing;
void *q;
ri = m->fields_size - sz;
r = message_peek_fields(m, &ri, 1, sz, &q);
if (r < 0)
return r;
if (m->fields_size < sz)
return -EBADMSG;
framing = bus_gvariant_read_word_le(q, sz);
if (framing >= m->fields_size - sz)
return -EBADMSG;
if ((m->fields_size - framing) % sz != 0)
return -EBADMSG;
ri = m->fields_size - sz;
r = message_peek_fields(m, &ri, 1, sz, &q);
if (r < 0)
return r;
ri = framing;
r = message_peek_fields(m, &ri, 1, m->fields_size - framing, &offsets);
if (r < 0)
return r;
framing = bus_gvariant_read_word_le(q, sz);
if (framing >= m->fields_size - sz)
return -EBADMSG;
if ((m->fields_size - framing) % sz != 0)
return -EBADMSG;
n_offsets = (m->fields_size - framing) / sz;
ri = framing;
r = message_peek_fields(m, &ri, 1, m->fields_size - framing, &offsets);
if (r < 0)
return r;
n_offsets = (m->fields_size - framing) / sz;
}
}
} else
m->user_body_size = m->body_size;
@ -5492,6 +5497,9 @@ int bus_message_parse_fields(sd_bus_message *m) {
if (m->reply_cookie == 0 || !m->error.name)
return -EBADMSG;
break;
default:
assert_not_reached("Bad message type");
}
/* Refuse non-local messages that claim they are local */

View File

@ -329,6 +329,59 @@ int config_parse_dhcp_user_class(
return 0;
}
int config_parse_dhcp_vendor_class(
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 ***l = data;
int r;
assert(l);
assert(lvalue);
assert(rvalue);
if (isempty(rvalue)) {
*l = strv_free(*l);
return 0;
}
for (;;) {
_cleanup_free_ char *w = NULL;
r = extract_first_word(&rvalue, &w, NULL, EXTRACT_CUNESCAPE|EXTRACT_UNQUOTE);
if (r == -ENOMEM)
return log_oom();
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r,
"Failed to split vendor classes option, ignoring: %s", rvalue);
break;
}
if (r == 0)
break;
if (strlen(w) > UINT8_MAX) {
log_syntax(unit, LOG_ERR, filename, line, 0,
"%s length is not in the range 1-255, ignoring.", w);
continue;
}
r = strv_push(l, w);
if (r < 0)
return log_oom();
w = NULL;
}
return 0;
}
int config_parse_dhcp6_mud_url(
const char *unit,
const char *filename,

View File

@ -51,5 +51,6 @@ CONFIG_PARSER_PROTOTYPE(config_parse_section_route_table);
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp6_pd_hint);
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp6_mud_url);
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_user_class);
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_vendor_class);
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_send_option);
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_request_options);

View File

@ -1488,6 +1488,12 @@ int dhcp4_configure(Link *link) {
return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set ip service type: %m");
}
if (link->network->dhcp_fallback_lease_lifetime > 0) {
r = sd_dhcp_client_set_fallback_lease_lifetime(link->dhcp_client, link->network->dhcp_fallback_lease_lifetime);
if (r < 0)
return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed set to lease lifetime: %m");
}
if (link->network->dhcp_send_decline) {
r = configure_dhcpv4_duplicate_address_detection(link);
if (r < 0)
@ -1674,6 +1680,44 @@ int config_parse_dhcp_mud_url(
return free_and_strdup_warn(&network->dhcp_mudurl, unescaped);
}
int config_parse_dhcp_fallback_lease_lifetime(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) {
Network *network = userdata;
unsigned k;
assert(filename);
assert(section);
assert(lvalue);
assert(rvalue);
assert(data);
if (isempty(rvalue)) {
network->dhcp_fallback_lease_lifetime = 0;
return 0;
}
/* We accept only "forever" or "infinity". */
if (STR_IN_SET(rvalue, "forever", "infinity"))
k = CACHE_INFO_INFINITY_LIFE_TIME;
else {
log_syntax(unit, LOG_ERR, filename, line, 0,
"Invalid LeaseLifetime= value, ignoring: %s", rvalue);
return 0;
}
network->dhcp_fallback_lease_lifetime = k;
return 0;
}
static const char* const dhcp_client_identifier_table[_DHCP_CLIENT_ID_MAX] = {
[DHCP_CLIENT_ID_MAC] = "mac",
[DHCP_CLIENT_ID_DUID] = "duid",

View File

@ -27,3 +27,4 @@ CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_black_listed_ip_address);
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_max_attempts);
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_ip_service_type);
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_mud_url);
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_fallback_lease_lifetime);

View File

@ -712,6 +712,12 @@ int dhcp6_configure(Link *link) {
return log_link_error_errno(link, r, "DHCP6 CLIENT: Failed to set user class: %m");
}
if (link->network->dhcp6_vendor_class) {
r = sd_dhcp6_client_set_request_vendor_class(client, link->network->dhcp6_vendor_class);
if (r < 0)
return log_link_error_errno(link, r, "DHCP6 CLIENT: Failed to set vendor class: %m");
}
r = sd_dhcp6_client_set_callback(client, dhcp6_handler, link);
if (r < 0)
return log_link_error_errno(link, r, "DHCP6 CLIENT: Failed to set callback: %m");

View File

@ -189,12 +189,14 @@ DHCPv4.IPServiceType, config_parse_dhcp_ip_service_type,
DHCPv4.SendOption, config_parse_dhcp_send_option, AF_INET, offsetof(Network, dhcp_client_send_options)
DHCPv4.SendVendorOption, config_parse_dhcp_send_option, 0, offsetof(Network, dhcp_client_send_vendor_options)
DHCPv4.RouteMTUBytes, config_parse_mtu, AF_INET, offsetof(Network, dhcp_route_mtu)
DHCPv4.FallbackLeaseLifetimeSec, config_parse_dhcp_fallback_lease_lifetime, 0, 0
DHCPv6.UseDNS, config_parse_bool, 0, offsetof(Network, dhcp6_use_dns)
DHCPv6.UseNTP, config_parse_bool, 0, offsetof(Network, dhcp6_use_ntp)
DHCPv6.RapidCommit, config_parse_bool, 0, offsetof(Network, rapid_commit)
DHCPv6.MUDURL, config_parse_dhcp6_mud_url, 0, 0
DHCPv6.RequestOptions, config_parse_dhcp_request_options, AF_INET6, 0
DHCPv6.UserClass, config_parse_dhcp_user_class, AF_INET6, offsetof(Network, dhcp6_user_class)
DHCPv6.VendorClass, config_parse_dhcp_vendor_class, 0, offsetof(Network, dhcp6_vendor_class)
DHCPv6.ForceDHCPv6PDOtherInformation, config_parse_bool, 0, offsetof(Network, dhcp6_force_pd_other_information)
DHCPv6.PrefixDelegationHint, config_parse_dhcp6_pd_hint, 0, 0
DHCPv6.WithoutRA, config_parse_bool, 0, offsetof(Network, dhcp6_without_ra)

View File

@ -654,6 +654,7 @@ static Network *network_free(Network *network) {
free(network->mac);
free(network->dhcp6_mudurl);
strv_free(network->dhcp6_user_class);
strv_free(network->dhcp6_vendor_class);
if (network->dhcp_acd)
sd_ipv4acd_unref(network->dhcp_acd);

View File

@ -97,6 +97,7 @@ struct Network {
uint64_t dhcp_max_attempts;
unsigned dhcp_route_metric;
uint32_t dhcp_route_table;
uint32_t dhcp_fallback_lease_lifetime;
uint32_t dhcp_route_mtu;
uint16_t dhcp_client_port;
int dhcp_critical;
@ -133,6 +134,7 @@ struct Network {
uint8_t dhcp6_pd_length;
char *dhcp6_mudurl;
char **dhcp6_user_class;
char **dhcp6_vendor_class;
struct in6_addr dhcp6_pd_address;
OrderedHashmap *dhcp6_client_send_options;
Set *dhcp6_request_options;

View File

@ -1436,7 +1436,8 @@ static int bus_append_mount_property(sd_bus_message *m, const char *field, const
if (STR_IN_SET(field, "SloppyOptions",
"LazyUnmount",
"ForceUnmount"))
"ForceUnmount",
"ReadwriteOnly"))
return bus_append_parse_boolean(m, field, eq);
return 0;

View File

@ -185,6 +185,9 @@ int sd_dhcp_client_get_lease(
int sd_dhcp_client_set_service_type(
sd_dhcp_client *client,
int type);
int sd_dhcp_client_set_fallback_lease_lifetime(
sd_dhcp_client *client,
uint32_t fallback_lease_lifetime);
int sd_dhcp_client_add_option(sd_dhcp_client *client, sd_dhcp_option *v);
int sd_dhcp_client_add_vendor_option(sd_dhcp_client *client, sd_dhcp_option *v);

View File

@ -125,10 +125,12 @@ int sd_dhcp6_client_set_request_option(
int sd_dhcp6_client_set_request_mud_url(
sd_dhcp6_client *client,
const char *mudurl);
int sd_dhcp6_client_set_request_user_class(
sd_dhcp6_client *client,
char** user_class);
int sd_dhcp6_client_set_request_vendor_class(
sd_dhcp6_client *client,
char** vendor_class);
int sd_dhcp6_client_set_prefix_delegation_hint(
sd_dhcp6_client *client,
uint8_t prefixlen,

Binary file not shown.

View File

@ -105,6 +105,7 @@ SendVendorOption=
SendDecline=
MUDURL=
RouteMTUBytes=
FallbackLeaseLifetimeSec=
[DHCPv6]
UseNTP=
UseDNS=
@ -116,6 +117,7 @@ MUDURL=
SendOption=
RequestOptions=
UserClass=
VendorClass=
[Route]
Destination=
Protocol=

View File

@ -856,6 +856,7 @@ RateLimitIntervalSec=
ReadKMsg=
ReadOnly=
ReadOnlyPaths=
ReadWriteOnly=
ReadWritePaths=
RemoveIPC=
ReserveVT=