Compare commits

...

14 Commits

Author SHA1 Message Date
Zbigniew Jędrzejewski-Szmek b014a6161a
Merge pull request #14064 from yuwata/network-unify-send-option-and-send-raw-option
network: unify SendOption= and SendRawOption=
2019-11-18 22:21:37 +01:00
Zbigniew Jędrzejewski-Szmek 3049e6a233
Merge pull request #14030 from keszybz/path-no-trigger
Fix spurious triggering of PathExists=
2019-11-18 22:20:07 +01:00
Zbigniew Jędrzejewski-Szmek fe67137895
Merge pull request #14007 from keszybz/tasks-max-dynamic
Calculate fractional TasksMax= before actual use
2019-11-18 22:18:33 +01:00
Yu Watanabe 0e96961d62 network: unify config_parse_dhcp_server_option_data() and config_parse_dhcp_send_option() 2019-11-18 23:39:03 +09:00
Yu Watanabe 461dbb2fa9 dhcp: remove struct sd_dhcp_raw_option
sd_dhcp_raw_option and sd_dhcp_option are essentially equivalent.
2019-11-18 23:37:22 +09:00
Yu Watanabe d8b736bd0c network: rename SendRawOption= to SendOption=
As DHCPv4.SendOption= and DHCPServer.SendRawOption= take the same
format.
2019-11-18 23:35:48 +09:00
Zbigniew Jędrzejewski-Szmek d7cf8c24d4 core/path: fix spurious triggering of PathExists= on restart/reload
Our handling of the condition was inconsistent. Normally, we'd only fire when
the file was created (or removed and subsequently created again). But on restarts,
we'd do a "recheck" from path_coldplug(), and if the file existed, we'd
always trigger. Daemon restarts and reloads should not be observeable, in
the sense that they should not trigger units which were already triggered and
would not be started again under normal circumstances.

Note that the mechanism for checks is racy: we get a notification from inotify,
and by the time we check, the file could have been created and removed again,
or removed and created again. It would be better if we inotify would give as
an unambiguous signal that the file was created, but it doesn't: IN_DELETE_SELF
triggers on inode removal, not directory entry, so we need to include IN_ATTRIB,
which obviously triggers on other conditions.

Fixes #12801.
2019-11-18 14:20:05 +01:00
Zbigniew Jędrzejewski-Szmek 7a16cd4b05 core/path: serialize the previous_exists state
Without that we are prone to generate spurious events after daemon
reload/restart.
2019-11-18 14:13:05 +01:00
Zbigniew Jędrzejewski-Szmek 6906ac9a69 Remove path_compare_func() alias for path_compare()
Non sunt multiplicanda entia sine necessitate.
2019-11-15 14:47:45 +01:00
Zbigniew Jędrzejewski-Szmek 9161113652 logind: drop unused user_tasks_max field
We would only write to the field, and take the address. All *readers* were
removed in 2841493927. (The explanation for why
the field wasn't removed back then is that the patch underwent a few iterations,
with the initial version adding translation back and forth. Later versions of
the patch simply emit a warning and ignore the old value. Apparently nobody
noticed that the value became unused.)
2019-11-14 18:41:54 +01:00
Zbigniew Jędrzejewski-Szmek 0877d4e0cf core: write cgroup limits as permilles
We allow expressing configuration as a fraction with granularity of 0.001, but
when writing out the unit file, we'd round that up to 0.01.

Longer term, I think it'd be nicer to simply use floats and do away with
arbitrary restrictions on precision.
2019-11-14 18:41:54 +01:00
Zbigniew Jędrzejewski-Szmek e617e2ccd7 core/dbus-cgroup: use %.*s instead of strndupa() 2019-11-14 18:41:54 +01:00
Zbigniew Jędrzejewski-Szmek 1454ab403e core/dbus-cgroup: drop unnecessary parens
'mask' is a macro parameter, so it cannot have commas. We don't need to
parenthesize.
2019-11-14 18:41:54 +01:00
Zbigniew Jędrzejewski-Szmek 3a0f06c41a core: make TasksMax a partially dynamic property
TasksMax= and DefaultTasksMax= can be specified as percentages. We don't
actually document of what the percentage is relative to, but the implementation
uses the smallest of /proc/sys/kernel/pid_max, /proc/sys/kernel/threads-max,
and /sys/fs/cgroup/pids.max (when present). When the value is a percentage,
we immediately convert it to an absolute value. If the limit later changes
(which can happen e.g. when systemd-sysctl runs), the absolute value becomes
outdated.

So let's store either the percentage or absolute value, whatever was specified,
and only convert to an absolute value when the value is used. For example, when
starting a unit, the absolute value will be calculated when the cgroup for
the unit is created.

Fixes #13419.
2019-11-14 18:41:54 +01:00
40 changed files with 486 additions and 536 deletions

View File

@ -1643,14 +1643,13 @@
<term><varname>SendOption=</varname></term>
<listitem>
<para>Send an arbitrary option in the DHCPv4 request. Takes a DHCP option number, data type
and data separated with a colon (<literal><replaceable>option</replaceable>:
<replaceable>type</replaceable>:<replaceable>value</replaceable></literal>). The option
number must be an interger in the range 1..254. The type takes one of
<literal>uint8</literal>, <literal>uint16</literal>, <literal>uint32</literal>,
<literal>ipv4address</literal>, or <literal>string</literal>.
Special characters in the data string may be escaped using
and data separated with a colon
(<literal><replaceable>option</replaceable>:<replaceable>type</replaceable>:<replaceable>value</replaceable></literal>).
The option number must be an interger in the range 1..254. The type takes one of <literal>uint8</literal>,
<literal>uint16</literal>, <literal>uint32</literal>, <literal>ipv4address</literal>, or
<literal>string</literal>. Special characters in the data string may be escaped using
<ulink url="https://en.wikipedia.org/wiki/Escape_sequences_in_C#Table_of_escape_sequences">C-style
escapes</ulink>. This option can be specified multiple times. If an empty string is specified,
escapes</ulink>. This setting can be specified multiple times. If an empty string is specified,
then all options specified earlier are cleared. Defaults to unset.</para>
</listitem>
</varlistentry>
@ -1905,15 +1904,16 @@
</varlistentry>
<varlistentry>
<term><varname>SendRawOption=</varname></term>
<term><varname>SendOption=</varname></term>
<listitem>
<para>Send a raw option with value via DHCPv4 server. Takes a DHCP option, data type and data
(option:type:value). The option ranges [1-254]. The type takes one of <literal>uint8</literal>,
<literal>uint16</literal>, <literal>uint32</literal>, <literal>ipv4address</literal>, or <literal>string</literal>.
Special characters in the data string may be escaped using
<para>Send a raw option with value via DHCPv4 server. Takes a DHCP option number, data type
and data (<literal><replaceable>option</replaceable>:<replaceable>type</replaceable>:<replaceable>value</replaceable></literal>).
The option number is an integer in the range 1..254. The type takes one of <literal>uint8</literal>,
<literal>uint16</literal>, <literal>uint32</literal>, <literal>ipv4address</literal>, or
<literal>string</literal>. Special characters in the data string may be escaped using
<ulink url="https://en.wikipedia.org/wiki/Escape_sequences_in_C#Table_of_escape_sequences">C-style
escapes</ulink>. This option can be specified multiple times. If an empty string is specified, then all
options specified earlier are cleared. Defaults to unset.</para>
escapes</ulink>. This setting can be specified multiple times. If an empty string is specified,
then all options specified earlier are cleared. Defaults to unset.</para>
</listitem>
</varlistentry>

View File

@ -129,10 +129,6 @@ static inline bool CGROUP_BLKIO_WEIGHT_IS_OK(uint64_t x) {
(x >= CGROUP_BLKIO_WEIGHT_MIN && x <= CGROUP_BLKIO_WEIGHT_MAX);
}
/* Default resource limits */
#define DEFAULT_TASKS_MAX_PERCENTAGE 15U /* 15% of PIDs, 4915 on default settings */
#define DEFAULT_USER_TASKS_MAX_PERCENTAGE 33U /* 33% of PIDs, 10813 on default settings */
typedef enum CGroupUnified {
CGROUP_UNIFIED_UNKNOWN = -1,
CGROUP_UNIFIED_NONE = 0, /* Both systemd and controllers on legacy */

View File

@ -52,11 +52,7 @@ void path_hash_func(const char *q, struct siphash *state) {
}
}
int path_compare_func(const char *a, const char *b) {
return path_compare(a, b);
}
DEFINE_HASH_OPS(path_hash_ops, char, path_hash_func, path_compare_func);
DEFINE_HASH_OPS(path_hash_ops, char, path_hash_func, path_compare);
void trivial_hash_func(const void *p, struct siphash *state) {
siphash24_compress(&p, sizeof(p), state);

View File

@ -79,7 +79,6 @@ extern const struct hash_ops string_hash_ops;
extern const struct hash_ops string_hash_ops_free_free;
void path_hash_func(const char *p, struct siphash *state);
int path_compare_func(const char *a, const char *b) _pure_;
extern const struct hash_ops path_hash_ops;
/* This will compare the passed pointers directly, and will not dereference them. This is hence not useful for strings

View File

@ -99,7 +99,6 @@ uint64_t physical_memory_scale(uint64_t v, uint64_t max) {
}
uint64_t system_tasks_max(void) {
uint64_t a = TASKS_MAX, b = TASKS_MAX;
_cleanup_free_ char *root = NULL;
int r;

View File

@ -897,7 +897,7 @@ static const char* counting_what(void) {
return "userspace processes (excl. kernel)";
}
DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(group_hash_ops, char, path_hash_func, path_compare_func, Group, group_free);
DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(group_hash_ops, char, path_hash_func, path_compare, Group, group_free);
static int run(int argc, char *argv[]) {
_cleanup_hashmap_free_ Hashmap *a = NULL, *b = NULL;

View File

@ -16,6 +16,7 @@
#include "fd-util.h"
#include "fileio.h"
#include "fs-util.h"
#include "limits-util.h"
#include "parse-util.h"
#include "path-util.h"
#include "process-util.h"
@ -34,6 +35,13 @@
* out specific attributes from us. */
#define LOG_LEVEL_CGROUP_WRITE(r) (IN_SET(abs(r), ENOENT, EROFS, EACCES, EPERM) ? LOG_DEBUG : LOG_WARNING)
uint64_t tasks_max_resolve(const TasksMax *tasks_max) {
if (tasks_max->scale == 0)
return tasks_max->value;
return system_tasks_max_scale(tasks_max->value, tasks_max->scale);
}
bool manager_owns_host_root_cgroup(Manager *m) {
assert(m);
@ -117,7 +125,7 @@ void cgroup_context_init(CGroupContext *c) {
.blockio_weight = CGROUP_BLKIO_WEIGHT_INVALID,
.startup_blockio_weight = CGROUP_BLKIO_WEIGHT_INVALID,
.tasks_max = CGROUP_LIMIT_MAX,
.tasks_max = TASKS_MAX_UNSET,
};
}
@ -447,7 +455,7 @@ void cgroup_context_dump(Unit *u, FILE* f, const char *prefix) {
prefix, c->memory_max, format_cgroup_memory_limit_comparison(cdd, sizeof(cdd), u, "MemoryMax"),
prefix, c->memory_swap_max, format_cgroup_memory_limit_comparison(cde, sizeof(cde), u, "MemorySwapMax"),
prefix, c->memory_limit,
prefix, c->tasks_max,
prefix, tasks_max_resolve(&c->tasks_max),
prefix, cgroup_device_policy_to_string(c->device_policy),
prefix, strempty(disable_controllers_str),
prefix, yes_no(c->delegate));
@ -1339,9 +1347,9 @@ static void cgroup_context_apply(
* which is desirable so that there's an official way to release control of the sysctl from
* systemd: set the limit to unbounded and reload. */
if (c->tasks_max != CGROUP_LIMIT_MAX) {
if (tasks_max_isset(&c->tasks_max)) {
u->manager->sysctl_pid_max_changed = true;
r = procfs_tasks_set_limit(c->tasks_max);
r = procfs_tasks_set_limit(tasks_max_resolve(&c->tasks_max));
} else if (u->manager->sysctl_pid_max_changed)
r = procfs_tasks_set_limit(TASKS_MAX);
else
@ -1354,10 +1362,10 @@ static void cgroup_context_apply(
/* The attribute itself is not available on the host root cgroup, and in the container case we want to
* leave it for the container manager. */
if (!is_local_root) {
if (c->tasks_max != CGROUP_LIMIT_MAX) {
char buf[DECIMAL_STR_MAX(uint64_t) + 2];
if (tasks_max_isset(&c->tasks_max)) {
char buf[DECIMAL_STR_MAX(uint64_t) + 1];
sprintf(buf, "%" PRIu64 "\n", c->tasks_max);
xsprintf(buf, "%" PRIu64 "\n", tasks_max_resolve(&c->tasks_max));
(void) set_attribute_and_warn(u, "pids", "pids.max", buf);
} else
(void) set_attribute_and_warn(u, "pids", "pids.max", "max\n");
@ -1434,7 +1442,7 @@ static CGroupMask unit_get_cgroup_mask(Unit *u) {
mask |= CGROUP_MASK_DEVICES | CGROUP_MASK_BPF_DEVICES;
if (c->tasks_accounting ||
c->tasks_max != CGROUP_LIMIT_MAX)
tasks_max_isset(&c->tasks_max))
mask |= CGROUP_MASK_PIDS;
return CGROUP_MASK_EXTEND_JOINED(mask);

View File

@ -9,6 +9,21 @@
#include "list.h"
#include "time-util.h"
typedef struct TasksMax {
/* If scale == 0, just use value; otherwise, value / scale.
* See tasks_max_resolve(). */
uint64_t value;
uint64_t scale;
} TasksMax;
#define TASKS_MAX_UNSET ((TasksMax) { .value = UINT64_MAX, .scale = 0 })
static inline bool tasks_max_isset(const TasksMax *tasks_max) {
return tasks_max->value != UINT64_MAX || tasks_max->scale != 0;
}
uint64_t tasks_max_resolve(const TasksMax *tasks_max);
typedef struct CGroupContext CGroupContext;
typedef struct CGroupDeviceAllow CGroupDeviceAllow;
typedef struct CGroupIODeviceWeight CGroupIODeviceWeight;
@ -135,7 +150,7 @@ struct CGroupContext {
LIST_HEAD(CGroupDeviceAllow, device_allow);
/* Common */
uint64_t tasks_max;
TasksMax tasks_max;
};
/* Used when querying IP accounting data */

View File

@ -16,6 +16,8 @@
#include "limits-util.h"
#include "path-util.h"
BUS_DEFINE_PROPERTY_GET(bus_property_get_tasks_max, "t", TasksMax, tasks_max_resolve);
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_cgroup_device_policy, cgroup_device_policy, CGroupDevicePolicy);
static int property_get_cgroup_mask(
@ -382,7 +384,7 @@ const sd_bus_vtable bus_cgroup_vtable[] = {
SD_BUS_PROPERTY("DevicePolicy", "s", property_get_cgroup_device_policy, offsetof(CGroupContext, device_policy), 0),
SD_BUS_PROPERTY("DeviceAllow", "a(ss)", property_get_device_allow, 0, 0),
SD_BUS_PROPERTY("TasksAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, tasks_accounting), 0),
SD_BUS_PROPERTY("TasksMax", "t", NULL, offsetof(CGroupContext, tasks_max), 0),
SD_BUS_PROPERTY("TasksMax", "t", bus_property_get_tasks_max, offsetof(CGroupContext, tasks_max), 0),
SD_BUS_PROPERTY("IPAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, ip_accounting), 0),
SD_BUS_PROPERTY("IPAddressAllow", "a(iayu)", property_get_ip_address_access, offsetof(CGroupContext, ip_address_allow), 0),
SD_BUS_PROPERTY("IPAddressDeny", "a(iayu)", property_get_ip_address_access, offsetof(CGroupContext, ip_address_deny), 0),
@ -617,7 +619,7 @@ static int bus_cgroup_set_boolean(
\
if (!UNIT_WRITE_FLAGS_NOOP(flags)) { \
*p = v; \
unit_invalidate_cgroup(u, (mask)); \
unit_invalidate_cgroup(u, mask); \
\
if (v == (val)) \
unit_write_settingf(u, flags, name, \
@ -654,7 +656,7 @@ static int bus_cgroup_set_boolean(
\
if (!UNIT_WRITE_FLAGS_NOOP(flags)) { \
*p = v; \
unit_invalidate_cgroup(u, (mask)); \
unit_invalidate_cgroup(u, mask); \
\
if (v == CGROUP_LIMIT_MAX) \
unit_write_settingf(u, flags, name, \
@ -690,17 +692,16 @@ static int bus_cgroup_set_boolean(
"Value specified in %s is out of range", name); \
\
if (!UNIT_WRITE_FLAGS_NOOP(flags)) { \
const char *e; \
\
*p = v; \
unit_invalidate_cgroup(u, (mask)); \
unit_invalidate_cgroup(u, mask); \
\
/* Chop off suffix */ \
assert_se(e = endswith(name, "Scale")); \
name = strndupa(name, e - name); \
/* Prepare to chop off suffix */ \
assert_se(endswith(name, "Scale")); \
\
unit_write_settingf(u, flags, name, "%s=%" PRIu32 "%%", name, \
(uint32_t) (DIV_ROUND_UP((uint64_t) raw * 100U, (uint64_t) UINT32_MAX))); \
uint32_t scaled = DIV_ROUND_UP((uint64_t) raw * 1000, (uint64_t) UINT32_MAX); \
unit_write_settingf(u, flags, name, "%.*s=%" PRIu32 ".%" PRIu32 "%%", \
(int)(strlen(name) - strlen("Scale")), name, \
scaled / 10, scaled % 10); \
} \
\
return 1; \
@ -715,9 +716,77 @@ BUS_DEFINE_SET_CGROUP_WEIGHT(blockio_weight, CGROUP_MASK_BLKIO, CGROUP_BLKIO_WEI
BUS_DEFINE_SET_CGROUP_LIMIT(memory, CGROUP_MASK_MEMORY, physical_memory_scale, 1);
BUS_DEFINE_SET_CGROUP_LIMIT(memory_protection, CGROUP_MASK_MEMORY, physical_memory_scale, 0);
BUS_DEFINE_SET_CGROUP_LIMIT(swap, CGROUP_MASK_MEMORY, physical_memory_scale, 0);
BUS_DEFINE_SET_CGROUP_LIMIT(tasks_max, CGROUP_MASK_PIDS, system_tasks_max_scale, 1);
#pragma GCC diagnostic pop
static int bus_cgroup_set_tasks_max(
Unit *u,
const char *name,
TasksMax *p,
sd_bus_message *message,
UnitWriteFlags flags,
sd_bus_error *error) {
uint64_t v;
int r;
assert(p);
r = sd_bus_message_read(message, "t", &v);
if (r < 0)
return r;
if (v < 1)
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
"Value specified in %s is out of range", name);
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
*p = (TasksMax) { .value = v, .scale = 0 }; /* When .scale==0, .value is the absolute value */
unit_invalidate_cgroup(u, CGROUP_MASK_PIDS);
if (v == CGROUP_LIMIT_MAX)
unit_write_settingf(u, flags, name,
"%s=infinity", name);
else
unit_write_settingf(u, flags, name,
"%s=%" PRIu64, name, v);
}
return 1;
}
static int bus_cgroup_set_tasks_max_scale(
Unit *u,
const char *name,
TasksMax *p,
sd_bus_message *message,
UnitWriteFlags flags,
sd_bus_error *error) {
uint32_t v;
int r;
assert(p);
r = sd_bus_message_read(message, "u", &v);
if (r < 0)
return r;
if (v < 1 || v >= UINT32_MAX)
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
"Value specified in %s is out of range", name);
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
*p = (TasksMax) { v, UINT32_MAX }; /* .scale is not 0, so this is interpreted as v/UINT32_MAX. */
unit_invalidate_cgroup(u, CGROUP_MASK_PIDS);
uint32_t scaled = DIV_ROUND_UP((uint64_t) v * 100U, (uint64_t) UINT32_MAX);
unit_write_settingf(u, flags, name, "%s=%" PRIu32 ".%" PRIu32 "%%", "TasksMax",
scaled / 10, scaled % 10);
}
return 1;
}
int bus_cgroup_set_property(
Unit *u,
CGroupContext *c,

View File

@ -9,4 +9,6 @@
extern const sd_bus_vtable bus_cgroup_vtable[];
int bus_property_get_tasks_max(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *ret_error);
int bus_cgroup_set_property(Unit *u, CGroupContext *c, const char *name, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error);

View File

@ -9,6 +9,7 @@
#include "architecture.h"
#include "build.h"
#include "bus-common-errors.h"
#include "dbus-cgroup.h"
#include "dbus-execute.h"
#include "dbus-job.h"
#include "dbus-manager.h"
@ -2465,7 +2466,7 @@ const sd_bus_vtable bus_manager_vtable[] = {
SD_BUS_PROPERTY("DefaultLimitRTPRIOSoft", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_RTPRIO]), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("DefaultLimitRTTIME", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_RTTIME]), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("DefaultLimitRTTIMESoft", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_RTTIME]), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("DefaultTasksMax", "t", NULL, offsetof(Manager, default_tasks_max), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("DefaultTasksMax", "t", bus_property_get_tasks_max, offsetof(Manager, default_tasks_max), 0),
SD_BUS_PROPERTY("TimerSlackNSec", "t", property_get_timer_slack_nsec, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("DefaultOOMPolicy", "s", bus_property_get_oom_policy, offsetof(Manager, default_oom_policy), SD_BUS_VTABLE_PROPERTY_CONST),

View File

@ -3263,36 +3263,39 @@ int config_parse_tasks_max(
void *data,
void *userdata) {
uint64_t *tasks_max = data, v;
const Unit *u = userdata;
TasksMax *tasks_max = data;
uint64_t v;
int r;
if (isempty(rvalue)) {
*tasks_max = u ? u->manager->default_tasks_max : UINT64_MAX;
*tasks_max = u ? u->manager->default_tasks_max : TASKS_MAX_UNSET;
return 0;
}
if (streq(rvalue, "infinity")) {
*tasks_max = CGROUP_LIMIT_MAX;
*tasks_max = TASKS_MAX_UNSET;
return 0;
}
r = parse_permille(rvalue);
if (r < 0) {
if (r >= 0)
*tasks_max = (TasksMax) { r, 1000U }; /* r‰ */
else {
r = safe_atou64(rvalue, &v);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r, "Invalid maximum tasks value '%s', ignoring: %m", rvalue);
return 0;
}
} else
v = system_tasks_max_scale(r, 1000U);
if (v <= 0 || v >= UINT64_MAX) {
log_syntax(unit, LOG_ERR, filename, line, 0, "Maximum tasks value '%s' out of range, ignoring.", rvalue);
return 0;
}
*tasks_max = v;
*tasks_max = (TasksMax) { v };
}
return 0;
}

View File

@ -84,6 +84,8 @@
#include <sanitizer/lsan_interface.h>
#endif
#define DEFAULT_TASKS_MAX ((TasksMax) { 15U, 100U }) /* 15% */
static enum {
ACTION_RUN,
ACTION_HELP,
@ -135,7 +137,7 @@ static bool arg_default_ip_accounting;
static bool arg_default_blockio_accounting;
static bool arg_default_memory_accounting;
static bool arg_default_tasks_accounting;
static uint64_t arg_default_tasks_max;
static TasksMax arg_default_tasks_max;
static sd_id128_t arg_machine_id;
static EmergencyAction arg_cad_burst_action;
static OOMPolicy arg_default_oom_policy;
@ -2131,7 +2133,7 @@ static void reset_arguments(void) {
arg_default_blockio_accounting = false;
arg_default_memory_accounting = MEMORY_ACCOUNTING_DEFAULT;
arg_default_tasks_accounting = true;
arg_default_tasks_max = system_tasks_max_scale(DEFAULT_TASKS_MAX_PERCENTAGE, 100U);
arg_default_tasks_max = DEFAULT_TASKS_MAX;
arg_machine_id = (sd_id128_t) {};
arg_cad_burst_action = EMERGENCY_ACTION_REBOOT_FORCE;
arg_default_oom_policy = OOM_STOP;

View File

@ -762,7 +762,7 @@ int manager_new(UnitFileScope scope, ManagerTestRunFlags test_run_flags, Manager
.default_timer_accuracy_usec = USEC_PER_MINUTE,
.default_memory_accounting = MEMORY_ACCOUNTING_DEFAULT,
.default_tasks_accounting = true,
.default_tasks_max = UINT64_MAX,
.default_tasks_max = TASKS_MAX_UNSET,
.default_timeout_start_usec = DEFAULT_TIMEOUT_USEC,
.default_timeout_stop_usec = DEFAULT_TIMEOUT_USEC,
.default_restart_usec = DEFAULT_RESTART_USEC,

View File

@ -9,6 +9,7 @@
#include "sd-event.h"
#include "cgroup-util.h"
#include "cgroup.h"
#include "fdset.h"
#include "hashmap.h"
#include "ip-address-access.h"
@ -349,7 +350,7 @@ struct Manager {
bool default_tasks_accounting;
bool default_ip_accounting;
uint64_t default_tasks_max;
TasksMax default_tasks_max;
usec_t default_timer_accuracy_usec;
OOMPolicy default_oom_policy;

View File

@ -9,12 +9,14 @@
#include "bus-util.h"
#include "dbus-path.h"
#include "dbus-unit.h"
#include "escape.h"
#include "fd-util.h"
#include "fs-util.h"
#include "glob-util.h"
#include "macro.h"
#include "mkdir.h"
#include "path.h"
#include "path-util.h"
#include "serialize.h"
#include "special.h"
#include "stat-util.h"
@ -27,19 +29,18 @@ static const UnitActiveState state_translation_table[_PATH_STATE_MAX] = {
[PATH_DEAD] = UNIT_INACTIVE,
[PATH_WAITING] = UNIT_ACTIVE,
[PATH_RUNNING] = UNIT_ACTIVE,
[PATH_FAILED] = UNIT_FAILED
[PATH_FAILED] = UNIT_FAILED,
};
static int path_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata);
int path_spec_watch(PathSpec *s, sd_event_io_handler_t handler) {
static const int flags_table[_PATH_TYPE_MAX] = {
[PATH_EXISTS] = IN_DELETE_SELF|IN_MOVE_SELF|IN_ATTRIB,
[PATH_EXISTS_GLOB] = IN_DELETE_SELF|IN_MOVE_SELF|IN_ATTRIB,
[PATH_CHANGED] = IN_DELETE_SELF|IN_MOVE_SELF|IN_ATTRIB|IN_CLOSE_WRITE|IN_CREATE|IN_DELETE|IN_MOVED_FROM|IN_MOVED_TO,
[PATH_MODIFIED] = IN_DELETE_SELF|IN_MOVE_SELF|IN_ATTRIB|IN_CLOSE_WRITE|IN_CREATE|IN_DELETE|IN_MOVED_FROM|IN_MOVED_TO|IN_MODIFY,
[PATH_DIRECTORY_NOT_EMPTY] = IN_DELETE_SELF|IN_MOVE_SELF|IN_ATTRIB|IN_CREATE|IN_MOVED_TO
[PATH_DIRECTORY_NOT_EMPTY] = IN_DELETE_SELF|IN_MOVE_SELF|IN_ATTRIB|IN_CREATE|IN_MOVED_TO,
};
bool exists = false;
@ -174,12 +175,14 @@ int path_spec_fd_event(PathSpec *s, uint32_t revents) {
}
static bool path_spec_check_good(PathSpec *s, bool initial) {
bool good = false;
bool b, good = false;
switch (s->type) {
case PATH_EXISTS:
good = access(s->path, F_OK) >= 0;
b = access(s->path, F_OK) >= 0;
good = b && !s->previous_exists;
s->previous_exists = b;
break;
case PATH_EXISTS_GLOB:
@ -195,14 +198,11 @@ static bool path_spec_check_good(PathSpec *s, bool initial) {
}
case PATH_CHANGED:
case PATH_MODIFIED: {
bool b;
case PATH_MODIFIED:
b = access(s->path, F_OK) >= 0;
good = !initial && b != s->previous_exists;
s->previous_exists = b;
break;
}
default:
;
@ -601,6 +601,7 @@ static int path_stop(Unit *u) {
static int path_serialize(Unit *u, FILE *f, FDSet *fds) {
Path *p = PATH(u);
PathSpec *s;
assert(u);
assert(f);
@ -609,6 +610,19 @@ static int path_serialize(Unit *u, FILE *f, FDSet *fds) {
(void) serialize_item(f, "state", path_state_to_string(p->state));
(void) serialize_item(f, "result", path_result_to_string(p->result));
LIST_FOREACH(spec, s, p->specs) {
_cleanup_free_ char *escaped = NULL;
escaped = cescape(s->path);
if (!escaped)
return log_oom();
(void) serialize_item_format(f, "path-spec", "%s %i %s",
path_type_to_string(s->type),
s->previous_exists,
s->path);
}
return 0;
}
@ -638,6 +652,38 @@ static int path_deserialize_item(Unit *u, const char *key, const char *value, FD
else if (f != PATH_SUCCESS)
p->result = f;
} else if (streq(key, "path-spec")) {
int previous_exists, skip = 0, r;
_cleanup_free_ char *type_str = NULL;
if (sscanf(value, "%ms %i %n", &type_str, &previous_exists, &skip) < 2)
log_unit_debug(u, "Failed to parse path-spec value: %s", value);
else {
_cleanup_free_ char *unescaped = NULL;
PathType type;
PathSpec *s;
type = path_type_from_string(type_str);
if (type < 0) {
log_unit_warning(u, "Unknown path type \"%s\", ignoring.", type_str);
return 0;
}
r = cunescape(value+skip, 0, &unescaped);
if (r < 0) {
log_unit_warning_errno(u, r, "Failed to unescape serialize path: %m");
return 0;
}
LIST_FOREACH(spec, s, p->specs)
if (s->type == type &&
path_equal(s->path, unescaped)) {
s->previous_exists = previous_exists;
break;
}
}
} else
log_unit_debug(u, "Unknown serialization key: %s", key);
@ -670,7 +716,7 @@ static int path_dispatch_io(sd_event_source *source, int fd, uint32_t revents, v
if (!IN_SET(p->state, PATH_WAITING, PATH_RUNNING))
return 0;
/* log_debug("inotify wakeup on %s.", u->id); */
/* log_debug("inotify wakeup on %s.", UNIT(p)->id); */
LIST_FOREACH(spec, s, p->specs)
if (path_spec_owns_inotify_fd(s, fd))

View File

@ -15,6 +15,16 @@
#include "dhcp-protocol.h"
#include "socket-util.h"
typedef struct sd_dhcp_option {
unsigned n_ref;
uint8_t option;
void *data;
size_t length;
} sd_dhcp_option;
extern const struct hash_ops dhcp_option_hash_ops;
int dhcp_network_bind_raw_socket(int ifindex, union sockaddr_union *link,
uint32_t xid, const uint8_t *mac_addr,
size_t mac_addr_len, uint16_t arp_type,

View File

@ -79,7 +79,7 @@ static int option_append(uint8_t options[], size_t size, size_t *offset,
break;
case SD_DHCP_OPTION_VENDOR_SPECIFIC: {
OrderedHashmap *s = (OrderedHashmap *) optval;
struct sd_dhcp_raw_option *p;
struct sd_dhcp_option *p;
size_t l = 0;
Iterator i;
@ -95,7 +95,7 @@ static int option_append(uint8_t options[], size_t size, size_t *offset,
*offset += 2;
ORDERED_HASHMAP_FOREACH(p, s, i) {
options[*offset] = p->type;
options[*offset] = p->option;
options[*offset + 1] = p->length;
memcpy(&options[*offset + 2], p->data, p->length);
*offset += 2 + p->length;
@ -315,3 +315,43 @@ int dhcp_option_parse(DHCPMessage *message, size_t len, dhcp_option_callback_t c
return message_type;
}
static sd_dhcp_option* dhcp_option_free(sd_dhcp_option *i) {
if (!i)
return NULL;
free(i->data);
return mfree(i);
}
int sd_dhcp_option_new(uint8_t option, const void *data, size_t length, sd_dhcp_option **ret) {
assert_return(ret, -EINVAL);
assert_return(length == 0 || data, -EINVAL);
_cleanup_free_ void *q = memdup(data, length);
if (!q)
return -ENOMEM;
sd_dhcp_option *p = new(sd_dhcp_option, 1);
if (!p)
return -ENOMEM;
*p = (sd_dhcp_option) {
.n_ref = 1,
.option = option,
.length = length,
.data = TAKE_PTR(q),
};
*ret = TAKE_PTR(p);
return 0;
}
DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_dhcp_option, sd_dhcp_option, dhcp_option_free);
DEFINE_HASH_OPS_WITH_VALUE_DESTRUCTOR(
dhcp_option_hash_ops,
void,
trivial_hash_func,
trivial_compare_func,
sd_dhcp_option,
sd_dhcp_option_unref);

View File

@ -37,15 +37,6 @@ typedef struct DHCPLease {
usec_t expiration;
} DHCPLease;
struct sd_dhcp_raw_option {
unsigned n_ref;
uint8_t type;
uint8_t length;
void *data;
};
struct sd_dhcp_server {
unsigned n_ref;

View File

@ -34,14 +34,6 @@
#define RESTART_AFTER_NAK_MIN_USEC (1 * USEC_PER_SEC)
#define RESTART_AFTER_NAK_MAX_USEC (30 * USEC_PER_MINUTE)
struct sd_dhcp_option {
unsigned n_ref;
uint8_t option;
void *data;
size_t length;
};
struct sd_dhcp_client {
unsigned n_ref;
@ -548,46 +540,6 @@ int sd_dhcp_client_set_max_attempts(sd_dhcp_client *client, uint64_t max_attempt
return 0;
}
static sd_dhcp_option* dhcp_option_free(sd_dhcp_option *i) {
if (!i)
return NULL;
free(i->data);
return mfree(i);
}
int sd_dhcp_option_new(uint8_t option, void *data, size_t length, sd_dhcp_option **ret) {
assert_return(ret, -EINVAL);
assert_return(length == 0 || data, -EINVAL);
_cleanup_free_ void *q = memdup(data, length);
if (!q)
return -ENOMEM;
sd_dhcp_option *p = new(sd_dhcp_option, 1);
if (!p)
return -ENOMEM;
*p = (sd_dhcp_option) {
.n_ref = 1,
.option = option,
.length = length,
.data = TAKE_PTR(q),
};
*ret = TAKE_PTR(p);
return 0;
}
DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_dhcp_option, sd_dhcp_option, dhcp_option_free);
DEFINE_HASH_OPS_WITH_VALUE_DESTRUCTOR(
dhcp_option_hash_ops,
void,
trivial_hash_func,
trivial_compare_func,
sd_dhcp_option,
sd_dhcp_option_unref);
int sd_dhcp_client_set_dhcp_option(sd_dhcp_client *client, sd_dhcp_option *v) {
int r;

View File

@ -127,46 +127,6 @@ int client_id_compare_func(const DHCPClientId *a, const DHCPClientId *b) {
DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(dhcp_lease_hash_ops, DHCPClientId, client_id_hash_func, client_id_compare_func,
DHCPLease, dhcp_lease_free);
static sd_dhcp_raw_option* raw_option_free(sd_dhcp_raw_option *i) {
if (!i)
return NULL;
free(i->data);
return mfree(i);
}
_public_ int sd_dhcp_raw_option_new(uint8_t type, char *data, size_t length, sd_dhcp_raw_option **ret) {
_cleanup_(sd_dhcp_raw_option_unrefp) sd_dhcp_raw_option *p = NULL;
assert_return(ret, -EINVAL);
p = new(sd_dhcp_raw_option, 1);
if (!p)
return -ENOMEM;
*p = (sd_dhcp_raw_option) {
.n_ref = 1,
.data = memdup(data, length),
.length = length,
.type = type,
};
if (!p->data)
return -ENOMEM;
*ret = TAKE_PTR(p);
return 0;
}
DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_dhcp_raw_option, sd_dhcp_raw_option, raw_option_free);
DEFINE_HASH_OPS_WITH_VALUE_DESTRUCTOR(
dhcp_raw_options_hash_ops,
void,
trivial_hash_func,
trivial_compare_func,
sd_dhcp_raw_option,
sd_dhcp_raw_option_unref);
static sd_dhcp_server *dhcp_server_free(sd_dhcp_server *server) {
assert(server);
@ -1222,13 +1182,13 @@ int sd_dhcp_server_set_emit_router(sd_dhcp_server *server, int enabled) {
return 1;
}
int sd_dhcp_server_add_raw_option(sd_dhcp_server *server, sd_dhcp_raw_option *v) {
int sd_dhcp_server_add_option(sd_dhcp_server *server, sd_dhcp_option *v) {
int r;
assert_return(server, -EINVAL);
assert_return(v, -EINVAL);
r = ordered_hashmap_ensure_allocated(&server->raw_option, &dhcp_raw_options_hash_ops);
r = ordered_hashmap_ensure_allocated(&server->raw_option, &dhcp_option_hash_ops);
if (r < 0)
return -ENOMEM;
@ -1236,7 +1196,7 @@ int sd_dhcp_server_add_raw_option(sd_dhcp_server *server, sd_dhcp_raw_option *v)
if (r < 0)
return r;
sd_dhcp_raw_option_ref(v);
sd_dhcp_option_ref(v);
return 1;
}

View File

@ -54,7 +54,6 @@ void manager_reset_config(Manager *m) {
m->idle_action = HANDLE_IGNORE;
m->runtime_dir_size = physical_memory_scale(10U, 100U); /* 10% */
m->user_tasks_max = system_tasks_max_scale(DEFAULT_USER_TASKS_MAX_PERCENTAGE, 100U); /* 33% */
m->sessions_max = 8192;
m->inhibitors_max = 8192;

View File

@ -41,4 +41,4 @@ Login.RuntimeDirectorySize, config_parse_tmpfs_size, 0, offse
Login.RemoveIPC, config_parse_bool, 0, offsetof(Manager, remove_ipc)
Login.InhibitorsMax, config_parse_uint64, 0, offsetof(Manager, inhibitors_max)
Login.SessionsMax, config_parse_uint64, 0, offsetof(Manager, sessions_max)
Login.UserTasksMax, config_parse_compat_user_tasks_max, 0, offsetof(Manager, user_tasks_max)
Login.UserTasksMax, config_parse_compat_user_tasks_max, 0, 0

View File

@ -849,7 +849,6 @@ int config_parse_compat_user_tasks_max(
assert(filename);
assert(lvalue);
assert(rvalue);
assert(data);
log_syntax(unit, LOG_NOTICE, filename, line, 0,
"Support for option %s= has been removed.",

View File

@ -119,7 +119,6 @@ struct Manager {
sd_event_source *lid_switch_ignore_event_source;
uint64_t runtime_dir_size;
uint64_t user_tasks_max;
uint64_t sessions_max;
uint64_t inhibitors_max;
};

View File

@ -1,5 +1,7 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#include "dhcp-internal.h"
#include "escape.h"
#include "in-addr-util.h"
#include "networkd-dhcp-common.h"
#include "networkd-network.h"
@ -263,6 +265,167 @@ int config_parse_dhcp6_pd_hint(
return 0;
}
int config_parse_dhcp_send_option(
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) {
_cleanup_(sd_dhcp_option_unrefp) sd_dhcp_option *opt = NULL, *old = NULL;
_cleanup_free_ char *word = NULL, *q = NULL;
OrderedHashmap **options = userdata;
union in_addr_union addr;
DHCPOptionDataType type;
uint8_t u, uint8_data;
uint16_t uint16_data;
uint32_t uint32_data;
const void *udata;
const char *p;
ssize_t sz;
int r;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(data);
if (isempty(rvalue)) {
*options = ordered_hashmap_free(*options);
return 0;
}
p = rvalue;
r = extract_first_word(&p, &word, ":", 0);
if (r == -ENOMEM)
return log_oom();
if (r <= 0) {
log_syntax(unit, LOG_ERR, filename, line, r,
"Invalid DHCP option, ignoring assignment: %s", rvalue);
return 0;
}
r = safe_atou8(word, &u);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r,
"Invalid DHCP option, ignoring assignment: %s", rvalue);
return 0;
}
if (u < 1 || u >= 255) {
log_syntax(unit, LOG_ERR, filename, line, 0,
"Invalid DHCP option, valid range is 1-254, ignoring assignment: %s", rvalue);
return 0;
}
free(word);
r = extract_first_word(&p, &word, ":", 0);
if (r == -ENOMEM)
return log_oom();
if (r <= 0) {
log_syntax(unit, LOG_ERR, filename, line, r,
"Invalid DHCP option, ignoring assignment: %s", rvalue);
return 0;
}
type = dhcp_option_data_type_from_string(word);
if (type < 0) {
log_syntax(unit, LOG_ERR, filename, line, 0,
"Invalid DHCP option data type, ignoring assignment: %s", p);
return 0;
}
switch(type) {
case DHCP_OPTION_DATA_UINT8:{
r = safe_atou8(p, &uint8_data);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r,
"Failed to parse DHCPv4 uint8 data, ignoring assignment: %s", p);
return 0;
}
udata = &uint8_data;
sz = sizeof(uint8_t);
break;
}
case DHCP_OPTION_DATA_UINT16:{
r = safe_atou16(p, &uint16_data);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r,
"Failed to parse DHCPv4 uint16 data, ignoring assignment: %s", p);
return 0;
}
udata = &uint16_data;
sz = sizeof(uint16_t);
break;
}
case DHCP_OPTION_DATA_UINT32: {
r = safe_atou32(p, &uint32_data);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r,
"Failed to parse DHCPv4 uint32 data, ignoring assignment: %s", p);
return 0;
}
udata = &uint32_data;
sz = sizeof(uint32_t);
break;
}
case DHCP_OPTION_DATA_IPV4ADDRESS: {
r = in_addr_from_string(AF_INET, p, &addr);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r,
"Failed to parse DHCPv4 ipv4address data, ignoring assignment: %s", p);
return 0;
}
udata = &addr.in;
sz = sizeof(addr.in.s_addr);
break;
}
case DHCP_OPTION_DATA_STRING:
sz = cunescape(p, 0, &q);
if (sz < 0) {
log_syntax(unit, LOG_ERR, filename, line, sz,
"Failed to decode DHCPv4 option data, ignoring assignment: %s", p);
}
udata = q;
break;
default:
return -EINVAL;
}
r = sd_dhcp_option_new(u, udata, sz, &opt);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r,
"Failed to store DHCPv4 option '%s', ignoring assignment: %m", rvalue);
return 0;
}
r = ordered_hashmap_ensure_allocated(options, &dhcp_option_hash_ops);
if (r < 0)
return log_oom();
/* Overwrite existing option */
old = ordered_hashmap_remove(*options, UINT_TO_PTR(u));
r = ordered_hashmap_put(*options, UINT_TO_PTR(u), opt);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r,
"Failed to store DHCPv4 option '%s', ignoring assignment: %m", rvalue);
return 0;
}
TAKE_PTR(opt);
return 0;
}
DEFINE_CONFIG_PARSE_ENUM(config_parse_dhcp_use_domains, dhcp_use_domains, DHCPUseDomains,
"Failed to parse DHCP use domains setting");

View File

@ -48,3 +48,4 @@ CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_use_sip);
CONFIG_PARSER_PROTOTYPE(config_parse_iaid);
CONFIG_PARSER_PROTOTYPE(config_parse_section_route_table);
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp6_pd_hint);
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_send_option);

View File

@ -2,7 +2,6 @@
#include "sd-dhcp-server.h"
#include "escape.h"
#include "networkd-dhcp-server.h"
#include "networkd-link.h"
#include "networkd-manager.h"
@ -192,7 +191,7 @@ static int link_push_uplink_sip_to_dhcp_server(Link *link, sd_dhcp_server *s) {
int dhcp4_server_configure(Link *link) {
bool acquired_uplink = false;
sd_dhcp_raw_option *p;
sd_dhcp_option *p;
Link *uplink = NULL;
Address *address;
Iterator i;
@ -305,8 +304,8 @@ int dhcp4_server_configure(Link *link) {
return log_link_error_errno(link, r, "Failed to set timezone for DHCP server: %m");
}
ORDERED_HASHMAP_FOREACH(p, link->network->dhcp_server_raw_options, i) {
r = sd_dhcp_server_add_raw_option(link->dhcp_server, p);
ORDERED_HASHMAP_FOREACH(p, link->network->dhcp_server_send_options, i) {
r = sd_dhcp_server_add_option(link->dhcp_server, p);
if (r == -EEXIST)
continue;
if (r < 0)
@ -479,167 +478,3 @@ int config_parse_dhcp_server_sip(
n->dhcp_server_sip = m;
}
}
int config_parse_dhcp_server_raw_option_data(
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) {
_cleanup_(sd_dhcp_raw_option_unrefp) sd_dhcp_raw_option *opt = NULL, *old = NULL;
_cleanup_free_ char *word = NULL, *q = NULL;
union in_addr_union addr;
DHCPOptionDataType type;
Network *network = data;
uint16_t uint16_data;
uint32_t uint32_data;
uint8_t uint8_data;
const char *p;
void *udata;
ssize_t sz;
uint8_t u;
int r;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(data);
if (isempty(rvalue)) {
network->dhcp_server_raw_options = ordered_hashmap_free(network->dhcp_server_raw_options);
return 0;
}
p = rvalue;
r = extract_first_word(&p, &word, ":", 0);
if (r == -ENOMEM)
return log_oom();
if (r <= 0) {
log_syntax(unit, LOG_ERR, filename, line, r,
"Invalid DHCP server send raw option, ignoring assignment: %s", rvalue);
return 0;
}
r = safe_atou8(word, &u);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r,
"Failed to parse DHCP server send raw option type, ignoring assignment: %s", rvalue);
return 0;
}
if (u < 1 || u >= 255) {
log_syntax(unit, LOG_ERR, filename, line, 0,
"Invalid DHCP server send raw option, valid range is 1-254, ignoring assignment: %s", rvalue);
return 0;
}
free(word);
r = extract_first_word(&p, &word, ":", 0);
if (r == -ENOMEM)
return log_oom();
if (r <= 0) {
log_syntax(unit, LOG_ERR, filename, line, r,
"Invalid DHCP server send raw option, ignoring assignment: %s", rvalue);
return 0;
}
type = dhcp_option_data_type_from_string(word);
if (type < 0) {
log_syntax(unit, LOG_ERR, filename, line, 0,
"Invalid DHCP server send data type, ignoring assignment: %s", p);
return 0;
}
switch(type) {
case DHCP_OPTION_DATA_UINT8:{
r = safe_atou8(p, &uint8_data);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r,
"Failed to parse DHCPv4 vendor specific uint8 data, ignoring assignment: %s", p);
return 0;
}
udata = &uint8_data;
sz = sizeof(uint8_t);
break;
}
case DHCP_OPTION_DATA_UINT16:{
r = safe_atou16(p, &uint16_data);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r,
"Failed to parse DHCPv4 vendor specific uint16 data, ignoring assignment: %s", p);
return 0;
}
udata = &uint16_data;
sz = sizeof(uint16_t);
break;
}
case DHCP_OPTION_DATA_UINT32: {
r = safe_atou32(p, &uint32_data);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r,
"Failed to parse DHCPv4 vendor specific uint32 data, ignoring assignment: %s", p);
return 0;
}
udata = &uint32_data;
sz = sizeof(uint32_t);
break;
}
case DHCP_OPTION_DATA_IPV4ADDRESS: {
r = in_addr_from_string(AF_INET, p, &addr);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r,
"Failed to parse DHCPv4 vendor specific ipv4address data, ignoring assignment: %s", p);
return 0;
}
udata = &addr.in;
sz = sizeof(addr.in.s_addr);
break;
}
case DHCP_OPTION_DATA_STRING:
sz = cunescape(p, 0, &q);
if (sz < 0) {
log_syntax(unit, LOG_ERR, filename, line, sz,
"Failed to decode option data, ignoring assignment: %s", p);
}
udata = q;
break;
default:
return -EINVAL;
}
r = sd_dhcp_raw_option_new(u, udata, sz, &opt);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r,
"Failed to store DHCP send raw option '%s', ignoring assignment: %m", rvalue);
return 0;
}
r = ordered_hashmap_ensure_allocated(&network->dhcp_server_raw_options, &dhcp_raw_options_hash_ops);
if (r < 0)
return log_oom();
/* Overwrite existing option */
old = ordered_hashmap_remove(network->dhcp_server_raw_options, UINT_TO_PTR(u));
r = ordered_hashmap_put(network->dhcp_server_raw_options, UINT_TO_PTR(u), opt);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r,
"Failed to store DHCP server send raw option '%s'", rvalue);
return 0;
}
TAKE_PTR(opt);
return 0;
}

View File

@ -12,4 +12,3 @@ int dhcp4_server_configure(Link *link);
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_server_dns);
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_server_ntp);
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_server_sip);
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_server_raw_option_data);

View File

@ -6,7 +6,6 @@
#include "alloc-util.h"
#include "dhcp-client-internal.h"
#include "escape.h"
#include "hostname-util.h"
#include "parse-util.h"
#include "network-internal.h"
@ -1295,7 +1294,7 @@ int dhcp4_configure(Link *link) {
return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set request flag for '%u': %m", option);
}
ORDERED_HASHMAP_FOREACH(send_option, link->network->dhcp_send_options, i) {
ORDERED_HASHMAP_FOREACH(send_option, link->network->dhcp_client_send_options, i) {
r = sd_dhcp_client_set_dhcp_option(link->dhcp_client, send_option);
if (r < 0)
return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set send option: %m");
@ -1566,167 +1565,6 @@ int config_parse_dhcp_request_options(
return 0;
}
int config_parse_dhcp_send_option(
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) {
_cleanup_(sd_dhcp_option_unrefp) sd_dhcp_option *opt = NULL, *old = NULL;
_cleanup_free_ char *word = NULL, *q = NULL;
union in_addr_union addr;
DHCPOptionDataType type;
Network *network = data;
uint8_t u, uint8_data;
uint16_t uint16_data;
uint32_t uint32_data;
const char *p;
void *udata;
ssize_t sz;
int r;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(data);
if (isempty(rvalue)) {
network->dhcp_send_options = ordered_hashmap_free(network->dhcp_send_options);
return 0;
}
p = rvalue;
r = extract_first_word(&p, &word, ":", 0);
if (r == -ENOMEM)
return log_oom();
if (r <= 0) {
log_syntax(unit, LOG_ERR, filename, line, r,
"Invalid DHCP send option, ignoring assignment: %s", rvalue);
return 0;
}
r = safe_atou8(word, &u);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r,
"Invalid DHCP send option, ignoring assignment: %s", rvalue);
return 0;
}
if (u < 1 || u >= 255) {
log_syntax(unit, LOG_ERR, filename, line, 0,
"Invalid DHCP send option, valid range is 1-254, ignoring assignment: %s", rvalue);
return 0;
}
free(word);
r = extract_first_word(&p, &word, ":", 0);
if (r == -ENOMEM)
return log_oom();
if (r <= 0) {
log_syntax(unit, LOG_ERR, filename, line, r,
"Invalid DHCP send option, ignoring assignment: %s", rvalue);
return 0;
}
type = dhcp_option_data_type_from_string(word);
if (type < 0) {
log_syntax(unit, LOG_ERR, filename, line, 0,
"Invalid DHCP send data type, ignoring assignment: %s", p);
return 0;
}
switch(type) {
case DHCP_OPTION_DATA_UINT8:{
r = safe_atou8(p, &uint8_data);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r,
"Failed to parse DHCPv4 uint8 data, ignoring assignment: %s", p);
return 0;
}
udata = &uint8_data;
sz = sizeof(uint8_t);
break;
}
case DHCP_OPTION_DATA_UINT16:{
r = safe_atou16(p, &uint16_data);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r,
"Failed to parse DHCPv4 uint16 data, ignoring assignment: %s", p);
return 0;
}
udata = &uint16_data;
sz = sizeof(uint16_t);
break;
}
case DHCP_OPTION_DATA_UINT32: {
r = safe_atou32(p, &uint32_data);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r,
"Failed to parse DHCPv4 uint32 data, ignoring assignment: %s", p);
return 0;
}
udata = &uint32_data;
sz = sizeof(uint32_t);
break;
}
case DHCP_OPTION_DATA_IPV4ADDRESS: {
r = in_addr_from_string(AF_INET, p, &addr);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r,
"Failed to parse DHCPv4 ipv4address data, ignoring assignment: %s", p);
return 0;
}
udata = &addr.in;
sz = sizeof(addr.in.s_addr);
break;
}
case DHCP_OPTION_DATA_STRING:
sz = cunescape(p, 0, &q);
if (sz < 0) {
log_syntax(unit, LOG_ERR, filename, line, sz,
"Failed to decode option data, ignoring assignment: %s", p);
}
udata = q;
break;
default:
return -EINVAL;
}
r = sd_dhcp_option_new(u, udata, sz, &opt);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r,
"Failed to store DHCP send option '%s', ignoring assignment: %m", rvalue);
return 0;
}
r = ordered_hashmap_ensure_allocated(&network->dhcp_send_options, &dhcp_option_hash_ops);
if (r < 0)
return log_oom();
/* Overwrite existing option */
old = ordered_hashmap_remove(network->dhcp_send_options, UINT_TO_PTR(u));
r = ordered_hashmap_put(network->dhcp_send_options, UINT_TO_PTR(u), opt);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r,
"Failed to store DHCP send option '%s'", rvalue);
return 0;
}
TAKE_PTR(opt);
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,4 +27,3 @@ CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_black_listed_ip_address);
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_max_attempts);
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_user_class);
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_request_options);
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_send_option);

View File

@ -175,7 +175,7 @@ DHCPv4.ListenPort, config_parse_uint16,
DHCPv4.SendRelease, config_parse_bool, 0, offsetof(Network, dhcp_send_release)
DHCPv4.BlackList, config_parse_dhcp_black_listed_ip_address, 0, 0
DHCPv4.IPServiceType, config_parse_ip_service_type, 0, offsetof(Network, ip_service_type)
DHCPv4.SendOption, config_parse_dhcp_send_option, 0, 0
DHCPv4.SendOption, config_parse_dhcp_send_option, 0, offsetof(Network, dhcp_client_send_options)
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)
@ -200,7 +200,7 @@ DHCPServer.EmitTimezone, config_parse_bool,
DHCPServer.Timezone, config_parse_timezone, 0, offsetof(Network, dhcp_server_timezone)
DHCPServer.PoolOffset, config_parse_uint32, 0, offsetof(Network, dhcp_server_pool_offset)
DHCPServer.PoolSize, config_parse_uint32, 0, offsetof(Network, dhcp_server_pool_size)
DHCPServer.SendRawOption, config_parse_dhcp_server_raw_option_data, 0, 0
DHCPServer.SendOption, config_parse_dhcp_send_option, 0, offsetof(Network, dhcp_server_send_options)
Bridge.Cost, config_parse_uint32, 0, offsetof(Network, cost)
Bridge.UseBPDU, config_parse_tristate, 0, offsetof(Network, use_bpdu)
Bridge.HairPin, config_parse_tristate, 0, offsetof(Network, hairpin)

View File

@ -686,8 +686,8 @@ static Network *network_free(Network *network) {
set_free_free(network->dnssec_negative_trust_anchors);
ordered_hashmap_free(network->dhcp_send_options);
ordered_hashmap_free(network->dhcp_server_raw_options);
ordered_hashmap_free(network->dhcp_client_send_options);
ordered_hashmap_free(network->dhcp_server_send_options);
return mfree(network);
}

View File

@ -114,8 +114,8 @@ struct Network {
DHCPUseDomains dhcp_use_domains;
Set *dhcp_black_listed_ip;
Set *dhcp_request_options;
OrderedHashmap *dhcp_send_options;
OrderedHashmap *dhcp_server_raw_options;
OrderedHashmap *dhcp_client_send_options;
OrderedHashmap *dhcp_server_send_options;
/* DHCPv6 Client support*/
bool dhcp6_use_dns;

View File

@ -22,6 +22,7 @@ _not_installed_headers = '''
sd-dhcp6-lease.h
sd-dhcp-client.h
sd-dhcp-lease.h
sd-dhcp-option.h
sd-dhcp-server.h
sd-ipv4acd.h
sd-ipv4ll.h

View File

@ -26,6 +26,7 @@
#include <stdbool.h>
#include "sd-dhcp-lease.h"
#include "sd-dhcp-option.h"
#include "sd-event.h"
#include "_sd-common.h"
@ -99,7 +100,6 @@ enum {
};
typedef struct sd_dhcp_client sd_dhcp_client;
typedef struct sd_dhcp_option sd_dhcp_option;
typedef int (*sd_dhcp_client_callback_t)(sd_dhcp_client *client, int event, void *userdata);
int sd_dhcp_client_set_callback(
@ -179,9 +179,6 @@ int sd_dhcp_client_set_service_type(
sd_dhcp_client *client,
int type);
int sd_dhcp_option_new(uint8_t option, void *data, size_t length, sd_dhcp_option **ret);
sd_dhcp_option* sd_dhcp_option_ref(sd_dhcp_option *i);
sd_dhcp_option* sd_dhcp_option_unref(sd_dhcp_option *i);
int sd_dhcp_client_set_dhcp_option(sd_dhcp_client *client, sd_dhcp_option *v);
int sd_dhcp_client_stop(sd_dhcp_client *client);
@ -204,7 +201,6 @@ int sd_dhcp_client_detach_event(sd_dhcp_client *client);
sd_event *sd_dhcp_client_get_event(sd_dhcp_client *client);
_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_dhcp_client, sd_dhcp_client_unref);
_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_dhcp_option, sd_dhcp_option_unref);
_SD_END_DECLARATIONS;

View File

@ -0,0 +1,38 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#ifndef foosddhcpoptionhfoo
#define foosddhcpoptionhfoo
/***
Copyright © 2013 Intel Corporation. All rights reserved.
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
systemd is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include <inttypes.h>
#include <sys/types.h>
#include "_sd-common.h"
_SD_BEGIN_DECLARATIONS;
typedef struct sd_dhcp_option sd_dhcp_option;
int sd_dhcp_option_new(uint8_t option, const void *data, size_t length, sd_dhcp_option **ret);
sd_dhcp_option *sd_dhcp_option_ref(sd_dhcp_option *ra);
sd_dhcp_option *sd_dhcp_option_unref(sd_dhcp_option *ra);
_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_dhcp_option, sd_dhcp_option_unref);
_SD_END_DECLARATIONS;
#endif

View File

@ -21,26 +21,20 @@
#include <inttypes.h>
#include <netinet/in.h>
#include "sd-dhcp-option.h"
#include "sd-event.h"
#include "_sd-common.h"
_SD_BEGIN_DECLARATIONS;
extern const struct hash_ops dhcp_raw_options_hash_ops;
typedef struct sd_dhcp_server sd_dhcp_server;
typedef struct sd_dhcp_raw_option sd_dhcp_raw_option;
int sd_dhcp_server_new(sd_dhcp_server **ret, int ifindex);
sd_dhcp_server *sd_dhcp_server_ref(sd_dhcp_server *server);
sd_dhcp_server *sd_dhcp_server_unref(sd_dhcp_server *server);
int sd_dhcp_raw_option_new(uint8_t type, char *data, size_t lengt, sd_dhcp_raw_option **ret);
sd_dhcp_raw_option *sd_dhcp_raw_option_ref(sd_dhcp_raw_option *ra);
sd_dhcp_raw_option *sd_dhcp_raw_option_unref(sd_dhcp_raw_option *ra);
int sd_dhcp_server_attach_event(sd_dhcp_server *client, sd_event *event, int64_t priority);
int sd_dhcp_server_detach_event(sd_dhcp_server *client);
sd_event *sd_dhcp_server_get_event(sd_dhcp_server *client);
@ -58,7 +52,7 @@ int sd_dhcp_server_set_ntp(sd_dhcp_server *server, const struct in_addr ntp[], u
int sd_dhcp_server_set_sip(sd_dhcp_server *server, const struct in_addr sip[], unsigned n);
int sd_dhcp_server_set_emit_router(sd_dhcp_server *server, int enabled);
int sd_dhcp_server_add_raw_option(sd_dhcp_server *server, sd_dhcp_raw_option *v);
int sd_dhcp_server_add_option(sd_dhcp_server *server, sd_dhcp_option *v);
int sd_dhcp_server_set_max_lease_time(sd_dhcp_server *server, uint32_t t);
int sd_dhcp_server_set_default_lease_time(sd_dhcp_server *server, uint32_t t);
@ -66,7 +60,6 @@ int sd_dhcp_server_set_default_lease_time(sd_dhcp_server *server, uint32_t t);
int sd_dhcp_server_forcerenew(sd_dhcp_server *server);
_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_dhcp_server, sd_dhcp_server_unref);
_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_dhcp_raw_option, sd_dhcp_raw_option_unref);
_SD_END_DECLARATIONS;

View File

@ -56,7 +56,7 @@ static int test_cgroup_mask(void) {
m->default_blockio_accounting =
m->default_io_accounting =
m->default_tasks_accounting = false;
m->default_tasks_max = (uint64_t) -1;
m->default_tasks_max = TASKS_MAX_UNSET;
assert_se(manager_startup(m, NULL, NULL) >= 0);

View File

@ -259,7 +259,7 @@ MaxLeaseTimeSec=
DefaultLeaseTimeSec=
EmitTimezone=
DNS=
SendRawOption=
SendOption=
[NextHop]
Id=
Gateway=