diff --git a/src/backlight/backlight.c b/src/backlight/backlight.c index 0ef362813f..15e0d17b8d 100644 --- a/src/backlight/backlight.c +++ b/src/backlight/backlight.c @@ -348,8 +348,8 @@ static int clamp_brightness( assert(brightness); /* Some systems turn the backlight all the way off at the lowest levels. This clamps the saved - * brightness to at least 1 or 5% of max_brightness in case of 'backlight' subsystem. This - * avoids preserving an unreadably dim screen, which would otherwise force the user to disable + * brightness to at least 1 or 1% of max_brightness (whichever is bigger) in case of 'backlight' subsystem. + * This avoids preserving an unreadably dim screen, which would otherwise force the user to disable * state restoration. */ min_brightness = (unsigned) ((double) max_brightness * percent / 100); diff --git a/src/basic/log-context.h b/src/basic/log-context.h index ccff2eb572..ca112fa862 100644 --- a/src/basic/log-context.h +++ b/src/basic/log-context.h @@ -32,8 +32,6 @@ * message. */ -struct iovec; - typedef struct LogContext { unsigned n_ref; /* Depending on which destructor is used (log_context_free() or log_context_detach()) the memory diff --git a/src/basic/process-util.c b/src/basic/process-util.c index 52af6a01c8..640aa77d6c 100644 --- a/src/basic/process-util.c +++ b/src/basic/process-util.c @@ -1128,10 +1128,6 @@ bool is_main_thread(void) { return cached; } -bool oom_score_adjust_is_valid(int oa) { - return oa >= OOM_SCORE_ADJ_MIN && oa <= OOM_SCORE_ADJ_MAX; -} - unsigned long personality_from_string(const char *s) { Architecture architecture; @@ -1887,6 +1883,10 @@ int namespace_fork_full( return 1; } +bool oom_score_adjust_is_valid(int oa) { + return oa >= OOM_SCORE_ADJ_MIN && oa <= OOM_SCORE_ADJ_MAX; +} + int set_oom_score_adjust(int value) { char t[DECIMAL_STR_MAX(int)]; diff --git a/src/basic/process-util.h b/src/basic/process-util.h index 66bb194bac..85fe81c617 100644 --- a/src/basic/process-util.h +++ b/src/basic/process-util.h @@ -87,8 +87,6 @@ int pidref_from_same_root_fs(PidRef *a, PidRef *b); bool is_main_thread(void); -bool oom_score_adjust_is_valid(int oa); - #ifndef PERSONALITY_INVALID /* personality(2) documents that 0xFFFFFFFFUL is used for querying the * current personality, hence let's use that here as error @@ -220,6 +218,7 @@ static inline int namespace_fork( ret); } +bool oom_score_adjust_is_valid(int oa); int set_oom_score_adjust(int value); int get_oom_score_adjust(int *ret); @@ -235,9 +234,6 @@ int get_oom_score_adjust(int *ret); assert_cc(TASKS_MAX <= (unsigned long) PID_T_MAX); -/* Like TAKE_PTR() but for pid_t, resetting them to 0 */ -#define TAKE_PID(pid) TAKE_GENERIC(pid, pid_t, 0) - int setpriority_closest(int priority); _noreturn_ void freeze(void); diff --git a/src/bootctl/bootctl-status.c b/src/bootctl/bootctl-status.c index 9c53522594..67b590b76f 100644 --- a/src/bootctl/bootctl-status.c +++ b/src/bootctl/bootctl-status.c @@ -642,14 +642,12 @@ int vl_method_list_boot_entries(sd_varlink *link, sd_json_variant *parameters, s int r; assert(link); + assert(FLAGS_SET(flags, SD_VARLINK_METHOD_MORE)); r = sd_varlink_dispatch(link, parameters, /* dispatch_table= */ NULL, /* userdata= */ NULL); if (r != 0) return r; - if (!FLAGS_SET(flags, SD_VARLINK_METHOD_MORE)) - return sd_varlink_error(link, SD_VARLINK_ERROR_EXPECTED_MORE, NULL); - r = acquire_esp(/* unprivileged_mode= */ false, /* graceful= */ false, /* ret_part= */ NULL, diff --git a/src/core/manager-serialize.c b/src/core/manager-serialize.c index 9318d02f9a..2357b9277c 100644 --- a/src/core/manager-serialize.c +++ b/src/core/manager-serialize.c @@ -171,7 +171,11 @@ int manager_serialize( if (r < 0) return r; - r = varlink_server_serialize(m->varlink_server, f, fds); + r = varlink_server_serialize(m->varlink_server, /* name = */ NULL, f, fds); + if (r < 0) + return r; + + r = varlink_server_serialize(m->metrics_varlink_server, "metrics", f, fds); if (r < 0) return r; @@ -282,7 +286,6 @@ static void manager_deserialize_gid_refs_one(Manager *m, const char *value) { } int manager_deserialize(Manager *m, FILE *f, FDSet *fds) { - bool deserialize_varlink_sockets = false; int r; assert(m); @@ -490,23 +493,28 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) { r = strv_extend(&m->subscribed_as_strv, val); if (r < 0) return r; - } else if ((val = startswith(l, "varlink-server-socket-address="))) { - if (!m->varlink_server) { - r = manager_setup_varlink_server(m); - if (r < 0) { - log_warning_errno(r, "Failed to setup varlink server, ignoring: %m"); - continue; - } + } else if ((val = startswith(l, "varlink-server-metrics-"))) { + if (m->objective == MANAGER_RELOAD) + /* We don't destroy varlink server on daemon-reload (in contrast to reexec) -> skip! */ + continue; - deserialize_varlink_sockets = true; - } + r = manager_setup_varlink_metrics_server(m); + if (r < 0) + log_warning_errno(r, "Failed to setup metrics varlink server, ignoring: %m"); + else + (void) varlink_server_deserialize_one(m->metrics_varlink_server, val, fds); - /* To avoid unnecessary deserialization (i.e. during reload vs. reexec) we only deserialize - * the FDs if we had to create a new m->varlink_server. The deserialize_varlink_sockets flag - * is initialized outside of the loop, is flipped after the VarlinkServer is setup, and - * remains set until all serialized contents are handled. */ - if (deserialize_varlink_sockets) + } else if ((val = startswith(l, "varlink-server-"))) { + if (m->objective == MANAGER_RELOAD) + /* We don't destroy varlink server on daemon-reload (in contrast to reexec) -> skip! */ + continue; + + r = manager_setup_varlink_server(m); + if (r < 0) + log_warning_errno(r, "Failed to setup varlink server, ignoring: %m"); + else (void) varlink_server_deserialize_one(m->varlink_server, val, fds); + } else if ((val = startswith(l, "dump-ratelimit="))) deserialize_ratelimit(&m->dump_ratelimit, "dump-ratelimit", val); else if ((val = startswith(l, "reload-reexec-ratelimit="))) diff --git a/src/core/varlink-cgroup.c b/src/core/varlink-cgroup.c index ffa3b7ca6d..65c07ecfad 100644 --- a/src/core/varlink-cgroup.c +++ b/src/core/varlink-cgroup.c @@ -112,7 +112,7 @@ static int ip_address_access_build_json(sd_json_variant **ret, const char *name, r = sd_json_variant_append_arraybo( &v, SD_JSON_BUILD_PAIR_INTEGER("family", i->family), - JSON_BUILD_PAIR_IN_ADDR("address", &i->address, i->family), + JSON_BUILD_PAIR_IN_ADDR("address", i->family, &i->address), SD_JSON_BUILD_PAIR_UNSIGNED("prefixLength", i->prefixlen)); if (r < 0) return r; @@ -299,6 +299,7 @@ int unit_cgroup_context_build_json(sd_json_variant **ret, const char *name, void SD_JSON_BUILD_OBJECT( SD_JSON_BUILD_PAIR_BOOLEAN("isAllowList", c->restrict_network_interfaces_is_allow_list), JSON_BUILD_PAIR_STRING_SET("interfaces", c->restrict_network_interfaces))), + JSON_BUILD_PAIR_STRING_NON_EMPTY("BindNetworkInterface", c->bind_network_interface), JSON_BUILD_PAIR_CALLBACK_NON_NULL("NFTSet", nft_set_build_json, &c->nft_set_context), /* BPF programs */ diff --git a/src/core/varlink-metrics.c b/src/core/varlink-metrics.c index 15bd1f154c..1bfdb1f5d7 100644 --- a/src/core/varlink-metrics.c +++ b/src/core/varlink-metrics.c @@ -1,5 +1,8 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ +#include "sd-json.h" +#include "sd-varlink.h" + #include "hashmap.h" #include "manager.h" #include "metrics.h" @@ -175,10 +178,10 @@ const MetricFamily metric_family_table[] = { {} }; -int vl_method_describe(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata) { +int vl_method_describe_metrics(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata) { return metrics_method_describe(metric_family_table, link, parameters, flags, userdata); } -int vl_method_list(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata) { +int vl_method_list_metrics(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata) { return metrics_method_list(metric_family_table, link, parameters, flags, userdata); } diff --git a/src/core/varlink-metrics.h b/src/core/varlink-metrics.h index 92e7d81cf8..5347774f2d 100644 --- a/src/core/varlink-metrics.h +++ b/src/core/varlink-metrics.h @@ -1,10 +1,9 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ #pragma once -#include "sd-varlink.h" -#include "sd-json.h" +#include "core-forward.h" #define METRIC_IO_SYSTEMD_MANAGER_PREFIX "io.systemd.Manager." -int vl_method_list(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata); -int vl_method_describe(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata); +int vl_method_list_metrics(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata); +int vl_method_describe_metrics(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata); diff --git a/src/core/varlink.c b/src/core/varlink.c index b5b00cdf74..76beeba434 100644 --- a/src/core/varlink.c +++ b/src/core/varlink.c @@ -9,7 +9,6 @@ #include "path-util.h" #include "pidref.h" #include "string-util.h" -#include "strv.h" #include "unit.h" #include "varlink.h" #include "varlink-dynamic-user.h" @@ -375,6 +374,8 @@ int manager_setup_varlink_server(Manager *m) { if (r < 0) return log_debug_errno(r, "Failed to allocate Varlink server: %m"); + (void) sd_varlink_server_set_description(s, "varlink-api"); + r = sd_varlink_server_add_interface_many( s, &vl_interface_io_systemd_Manager, @@ -425,26 +426,64 @@ int manager_setup_varlink_server(Manager *m) { return 1; } -static int manager_setup_varlink_metrics_server(Manager *m) { - sd_varlink_server_flags_t flags = SD_VARLINK_SERVER_INHERIT_USERDATA; - int r; - +int manager_setup_varlink_metrics_server(Manager *m) { assert(m); + sd_varlink_server_flags_t flags = SD_VARLINK_SERVER_INHERIT_USERDATA; if (MANAGER_IS_SYSTEM(m)) flags |= SD_VARLINK_SERVER_ACCOUNT_UID; - r = metrics_setup_varlink_server( - &m->metrics_varlink_server, flags, m->event, vl_method_list, vl_method_describe, m); - if (r < 0) - return r; - - return 0; + return metrics_setup_varlink_server(&m->metrics_varlink_server, flags, + m->event, EVENT_PRIORITY_IPC, + vl_method_list_metrics, vl_method_describe_metrics, + m); } -static int manager_varlink_init_system(Manager *m) { +static int varlink_server_listen_many_idempotent_sentinel( + sd_varlink_server *s, + bool known_fresh, + const char *prefix, + ...) { + + va_list ap; + int r = 0; + + assert(s); + + va_start(ap, prefix); + for (const char *address; (address = va_arg(ap, const char*)); ) { + _cleanup_free_ char *p = NULL; + + if (prefix) { + p = path_join(prefix, address); + if (!p) { + r = log_oom(); + break; + } + + address = p; + } + + /* We might have got sockets through deserialization. Do not bind to them twice. */ + if (!known_fresh && varlink_server_contains_socket(s, address)) + continue; + + r = sd_varlink_server_listen_address(s, address, 0666 | SD_VARLINK_SERVER_MODE_MKDIR_0755); + if (r < 0) { + log_error_errno(r, "Failed to bind to varlink socket '%s': %m", address); + break; + } + } + va_end(ap); + + return r; +} + +#define varlink_server_listen_many_idempotent(s, known_fresh, prefix, ...) \ + varlink_server_listen_many_idempotent_sentinel((s), (known_fresh), (prefix), __VA_ARGS__, NULL) + +static int manager_varlink_init_system_api(Manager *m) { int r; - _cleanup_free_ char *metrics_address = NULL; assert(m); @@ -453,38 +492,21 @@ static int manager_varlink_init_system(Manager *m) { return log_error_errno(r, "Failed to set up varlink server: %m"); bool fresh = r > 0; - r = manager_setup_varlink_metrics_server(m); - if (r < 0) - return log_error_errno(r, "Failed to set up metrics varlink server: %m"); - bool metrics_fresh = r > 0; - - r = runtime_directory_generic(m->runtime_scope, "systemd/report/io.systemd.Manager", &metrics_address); - if (r < 0) - return r; - if (!MANAGER_IS_TEST_RUN(m)) { - FOREACH_STRING(address, - "/run/systemd/userdb/io.systemd.DynamicUser", - VARLINK_PATH_MANAGED_OOM_SYSTEM, - "/run/systemd/io.systemd.Manager", - metrics_address) { - - sd_varlink_server *server = streq(address, metrics_address) ? m->metrics_varlink_server : m->varlink_server; - fresh = streq(address, metrics_address) ? metrics_fresh : fresh; - /* We might have got sockets through deserialization. Do not bind to them twice. */ - if (!fresh && varlink_server_contains_socket(server, address)) - continue; - - r = sd_varlink_server_listen_address(server, address, 0666 | SD_VARLINK_SERVER_MODE_MKDIR_0755); - if (r < 0) - return log_error_errno(r, "Failed to bind to varlink socket '%s': %m", address); - } + r = varlink_server_listen_many_idempotent( + m->varlink_server, fresh, + /* prefix = */ NULL, + "/run/systemd/io.systemd.Manager", + "/run/systemd/userdb/io.systemd.DynamicUser", + VARLINK_PATH_MANAGED_OOM_SYSTEM); + if (r < 0) + return r; } - return 1; + return 0; } -static int manager_varlink_init_user(Manager *m) { +static int manager_varlink_init_user_api(Manager *m) { int r; assert(m); @@ -497,30 +519,46 @@ static int manager_varlink_init_user(Manager *m) { return log_error_errno(r, "Failed to set up varlink server: %m"); bool fresh = r > 0; - FOREACH_STRING(a, - "systemd/io.systemd.Manager") { - _cleanup_free_ char *address = NULL; - address = path_join(m->prefix[EXEC_DIRECTORY_RUNTIME], a); - if (!address) - return -ENOMEM; - /* We might have got sockets through deserialization. Do not bind to them twice. */ - if (!fresh && varlink_server_contains_socket(m->varlink_server, address)) - continue; - - r = sd_varlink_server_listen_address(m->varlink_server, address, 0666 | SD_VARLINK_SERVER_MODE_MKDIR_0755); - if (r < 0) - return log_error_errno(r, "Failed to bind to varlink socket '%s': %m", address); - } - - r = manager_setup_varlink_metrics_server(m); + r = varlink_server_listen_many_idempotent( + m->varlink_server, fresh, + m->prefix[EXEC_DIRECTORY_RUNTIME], + "systemd/io.systemd.Manager"); if (r < 0) - return log_error_errno(r, "Failed to set up metrics varlink server: %m"); + return r; return manager_varlink_managed_oom_connect(m); } +static int manager_varlink_init_metrics(Manager *m) { + int r; + + assert(m); + + if (MANAGER_IS_TEST_RUN(m)) + return 0; + + r = manager_setup_varlink_metrics_server(m); + if (r < 0) + return log_error_errno(r, "Failed to set up metrics varlink server: %m"); + bool fresh = r > 0; + + return varlink_server_listen_many_idempotent( + m->metrics_varlink_server, fresh, + m->prefix[EXEC_DIRECTORY_RUNTIME], + "systemd/report/io.systemd.Manager"); +} + int manager_varlink_init(Manager *m) { - return MANAGER_IS_SYSTEM(m) ? manager_varlink_init_system(m) : manager_varlink_init_user(m); + int r; + + if (MANAGER_IS_SYSTEM(m)) + r = manager_varlink_init_system_api(m); + else + r = manager_varlink_init_user_api(m); + if (r < 0) + return r; + + return manager_varlink_init_metrics(m); } void manager_varlink_done(Manager *m) { @@ -534,6 +572,7 @@ void manager_varlink_done(Manager *m) { m->varlink_server = sd_varlink_server_unref(m->varlink_server); m->managed_oom_varlink = sd_varlink_close_unref(m->managed_oom_varlink); + m->metrics_varlink_server = sd_varlink_server_unref(m->metrics_varlink_server); } diff --git a/src/core/varlink.h b/src/core/varlink.h index f959cf8a67..119394386b 100644 --- a/src/core/varlink.h +++ b/src/core/varlink.h @@ -4,6 +4,7 @@ #include "core-forward.h" int manager_setup_varlink_server(Manager *m); +int manager_setup_varlink_metrics_server(Manager *m); int manager_varlink_init(Manager *m); void manager_varlink_done(Manager *m); diff --git a/src/import/importd.c b/src/import/importd.c index 549bbe712f..280aa88d46 100644 --- a/src/import/importd.c +++ b/src/import/importd.c @@ -1793,14 +1793,12 @@ static int vl_method_list_transfers(sd_varlink *link, sd_json_variant *parameter assert(link); assert(parameters); + assert(FLAGS_SET(flags, SD_VARLINK_METHOD_MORE)); r = sd_varlink_dispatch(link, parameters, dispatch_table, &p); if (r != 0) return r; - if (!FLAGS_SET(flags, SD_VARLINK_METHOD_MORE)) - return sd_varlink_error(link, SD_VARLINK_ERROR_EXPECTED_MORE, NULL); - r = varlink_set_sentinel(link, "io.systemd.Import.NoTransfers"); if (r < 0) return r; diff --git a/src/libsystemd/sd-json/json-util.h b/src/libsystemd/sd-json/json-util.h index 334a2506dc..5365eedcae 100644 --- a/src/libsystemd/sd-json/json-util.h +++ b/src/libsystemd/sd-json/json-util.h @@ -5,8 +5,8 @@ #include "sd-json.h" -#include "sd-forward.h" #include "log.h" +#include "sd-forward.h" #include "string-util.h" /* IWYU pragma: keep */ #define JSON_VARIANT_REPLACE(v, q) \ @@ -175,9 +175,9 @@ enum { _JSON_BUILD_PAIR_VARIANT_NON_EMPTY, /* _SD_JSON_BUILD_PAIR_VARIANT_ARRAY_NON_EMPTY, */ _JSON_BUILD_PAIR_BYTE_ARRAY_NON_EMPTY, - _JSON_BUILD_PAIR_IN4_ADDR_NON_NULL, - _JSON_BUILD_PAIR_IN6_ADDR_NON_NULL, _JSON_BUILD_PAIR_IN_ADDR_NON_NULL, + _JSON_BUILD_PAIR_IN_ADDR_WITH_STRING, + _JSON_BUILD_PAIR_IN_ADDR_WITH_STRING_NON_NULL, _JSON_BUILD_PAIR_ETHER_ADDR_NON_NULL, _JSON_BUILD_PAIR_HW_ADDR_NON_NULL, _JSON_BUILD_PAIR_DUAL_TIMESTAMP_NON_NULL, @@ -190,12 +190,6 @@ enum { _JSON_BUILD_PAIR_TRISTATE_NON_NULL, _JSON_BUILD_PAIR_PIDREF_NON_NULL, _JSON_BUILD_PAIR_DEVNUM, - _JSON_BUILD_PAIR_IN_ADDR_WITH_STRING, - _JSON_BUILD_PAIR_IN6_ADDR_WITH_STRING, - _JSON_BUILD_PAIR_IN4_ADDR_WITH_STRING, - _JSON_BUILD_PAIR_IN_ADDR_WITH_STRING_NON_NULL, - _JSON_BUILD_PAIR_IN6_ADDR_WITH_STRING_NON_NULL, - _JSON_BUILD_PAIR_IN4_ADDR_WITH_STRING_NON_NULL, _SD_JSON_BUILD_REALLYMAX, }; @@ -206,7 +200,7 @@ enum { #define JSON_BUILD_CONST_STRING(s) _SD_JSON_BUILD_VARIANT, JSON_VARIANT_STRING_CONST(s) #define JSON_BUILD_IN4_ADDR(v) SD_JSON_BUILD_BYTE_ARRAY((const struct in_addr*) { v }, sizeof(struct in_addr)) #define JSON_BUILD_IN6_ADDR(v) SD_JSON_BUILD_BYTE_ARRAY((const struct in6_addr*) { v }, sizeof(struct in6_addr)) -#define JSON_BUILD_IN_ADDR(v, f) SD_JSON_BUILD_BYTE_ARRAY(((const union in_addr_union*) { v })->bytes, FAMILY_ADDRESS_SIZE_SAFE(f)) +#define JSON_BUILD_IN_ADDR(f, v) SD_JSON_BUILD_BYTE_ARRAY(((const union in_addr_union*) { v })->bytes, FAMILY_ADDRESS_SIZE_SAFE(f)) #define JSON_BUILD_ETHER_ADDR(v) SD_JSON_BUILD_BYTE_ARRAY(((const struct ether_addr*) { v })->ether_addr_octet, sizeof(struct ether_addr)) #define JSON_BUILD_HW_ADDR(v) _JSON_BUILD_HW_ADDR, (const struct hw_addr_data*) { v } #define JSON_BUILD_STRING_SET(s) _JSON_BUILD_STRING_SET, (Set *) { s } @@ -229,9 +223,15 @@ enum { #define JSON_BUILD_PAIR_VARIANT_NON_NULL(name, v) _JSON_BUILD_PAIR_VARIANT_NON_NULL, (const char*) { name }, (sd_json_variant*) { v } #define JSON_BUILD_PAIR_VARIANT_NON_EMPTY(name, v) _JSON_BUILD_PAIR_VARIANT_NON_EMPTY, (const char*) { name }, (sd_json_variant*) { v } #define JSON_BUILD_PAIR_BYTE_ARRAY_NON_EMPTY(name, v, n) _JSON_BUILD_PAIR_BYTE_ARRAY_NON_EMPTY, (const char*) { name }, (const void*) { v }, (size_t) { n } -#define JSON_BUILD_PAIR_IN4_ADDR_NON_NULL(name, v) _JSON_BUILD_PAIR_IN4_ADDR_NON_NULL, (const char*) { name }, (const struct in_addr*) { v } -#define JSON_BUILD_PAIR_IN6_ADDR_NON_NULL(name, v) _JSON_BUILD_PAIR_IN6_ADDR_NON_NULL, (const char*) { name }, (const struct in6_addr*) { v } -#define JSON_BUILD_PAIR_IN_ADDR_NON_NULL(name, v, f) _JSON_BUILD_PAIR_IN_ADDR_NON_NULL, (const char*) { name }, (const union in_addr_union*) { v }, (int) { f } +#define JSON_BUILD_PAIR_IN_ADDR_NON_NULL(name, f, v) _JSON_BUILD_PAIR_IN_ADDR_NON_NULL, (const char*) { name }, (int) { f }, (const union in_addr_union*) { v } +#define JSON_BUILD_PAIR_IN4_ADDR_NON_NULL(name, v) _JSON_BUILD_PAIR_IN_ADDR_NON_NULL, (const char*) { name }, AF_INET, &(union in_addr_union) { .in = *(v) } +#define JSON_BUILD_PAIR_IN6_ADDR_NON_NULL(name, v) _JSON_BUILD_PAIR_IN_ADDR_NON_NULL, (const char*) { name }, AF_INET6, &(union in_addr_union) { .in6 = *(v) } +#define JSON_BUILD_PAIR_IN_ADDR_WITH_STRING(name, f, v) _JSON_BUILD_PAIR_IN_ADDR_WITH_STRING, (const char*) { name }, (int) { f }, (const union in_addr_union*) { v } +#define JSON_BUILD_PAIR_IN4_ADDR_WITH_STRING(name, v) _JSON_BUILD_PAIR_IN_ADDR_WITH_STRING, (const char*) { name }, AF_INET, &(union in_addr_union) { .in = *(v) } +#define JSON_BUILD_PAIR_IN6_ADDR_WITH_STRING(name, v) _JSON_BUILD_PAIR_IN_ADDR_WITH_STRING, (const char*) { name }, AF_INET6, &(union in_addr_union) { .in6 = *(v) } +#define JSON_BUILD_PAIR_IN_ADDR_WITH_STRING_NON_NULL(name, f, v) _JSON_BUILD_PAIR_IN_ADDR_WITH_STRING_NON_NULL, (const char*) { name }, (int) { f }, (const union in_addr_union*) { v } +#define JSON_BUILD_PAIR_IN4_ADDR_WITH_STRING_NON_NULL(name, v) _JSON_BUILD_PAIR_IN_ADDR_WITH_STRING_NON_NULL, (const char*) { name }, AF_INET, &(union in_addr_union) { .in = *(v) } +#define JSON_BUILD_PAIR_IN6_ADDR_WITH_STRING_NON_NULL(name, v) _JSON_BUILD_PAIR_IN_ADDR_WITH_STRING_NON_NULL, (const char*) { name }, AF_INET6, &(union in_addr_union) { .in6 = *(v) } #define JSON_BUILD_PAIR_ETHER_ADDR_NON_NULL(name, v) _JSON_BUILD_PAIR_ETHER_ADDR_NON_NULL, (const char*) { name }, (const struct ether_addr*) { v } #define JSON_BUILD_PAIR_HW_ADDR_NON_NULL(name, v) _JSON_BUILD_PAIR_HW_ADDR_NON_NULL, (const char*) { name }, (const struct hw_addr_data*) { v } #define JSON_BUILD_PAIR_DUAL_TIMESTAMP_NON_NULL(name, t) _JSON_BUILD_PAIR_DUAL_TIMESTAMP_NON_NULL, (const char*) { name }, (dual_timestamp*) { t } @@ -243,18 +243,12 @@ enum { #define JSON_BUILD_PAIR_OCTESCAPE_NON_EMPTY(name, v, n) _JSON_BUILD_PAIR_HEX_NON_EMPTY, (const char*) { name }, (const void*) { v }, (size_t) { n } #define JSON_BUILD_PAIR_TRISTATE_NON_NULL(name, i) _JSON_BUILD_PAIR_TRISTATE_NON_NULL, (const char*) { name }, (int) { i } #define JSON_BUILD_PAIR_PIDREF_NON_NULL(name, p) _JSON_BUILD_PAIR_PIDREF_NON_NULL, (const char*) { name }, (const PidRef*) { p } -#define JSON_BUILD_PAIR_IN_ADDR_WITH_STRING(name, f, v) _JSON_BUILD_PAIR_IN_ADDR_WITH_STRING, (const char*) { name }, (int) { f }, (const union in_addr_union*) { v } -#define JSON_BUILD_PAIR_IN6_ADDR_WITH_STRING(name, v) _JSON_BUILD_PAIR_IN6_ADDR_WITH_STRING, (const char*) { name }, (const struct in6_addr*) { v } -#define JSON_BUILD_PAIR_IN4_ADDR_WITH_STRING(name, v) _JSON_BUILD_PAIR_IN4_ADDR_WITH_STRING, (const char*) { name }, (const struct in_addr*) { v } -#define JSON_BUILD_PAIR_IN_ADDR_WITH_STRING_NON_NULL(name, f, v) _JSON_BUILD_PAIR_IN_ADDR_WITH_STRING_NON_NULL, (const char*) { name }, (int) { f }, (const union in_addr_union*) { v } -#define JSON_BUILD_PAIR_IN6_ADDR_WITH_STRING_NON_NULL(name, v) _JSON_BUILD_PAIR_IN6_ADDR_WITH_STRING_NON_NULL, (const char*) { name }, (const struct in6_addr*) { v } -#define JSON_BUILD_PAIR_IN4_ADDR_WITH_STRING_NON_NULL(name, v) _JSON_BUILD_PAIR_IN4_ADDR_WITH_STRING_NON_NULL, (const char*) { name }, (const struct in_addr*) { v } #define JSON_BUILD_PAIR_IOVEC_BASE64(name, iov) SD_JSON_BUILD_PAIR(name, JSON_BUILD_IOVEC_BASE64(iov)) #define JSON_BUILD_PAIR_IOVEC_HEX(name, iov) SD_JSON_BUILD_PAIR(name, JSON_BUILD_IOVEC_HEX(iov)) #define JSON_BUILD_PAIR_IN4_ADDR(name, v) SD_JSON_BUILD_PAIR(name, JSON_BUILD_IN4_ADDR(v)) #define JSON_BUILD_PAIR_IN6_ADDR(name, v) SD_JSON_BUILD_PAIR(name, JSON_BUILD_IN6_ADDR(v)) -#define JSON_BUILD_PAIR_IN_ADDR(name, v, f) SD_JSON_BUILD_PAIR(name, JSON_BUILD_IN_ADDR(v, f)) +#define JSON_BUILD_PAIR_IN_ADDR(name, f, v) SD_JSON_BUILD_PAIR(name, JSON_BUILD_IN_ADDR(f, v)) #define JSON_BUILD_PAIR_ETHER_ADDR(name, v) SD_JSON_BUILD_PAIR(name, JSON_BUILD_ETHER_ADDR(v)) #define JSON_BUILD_PAIR_HW_ADDR(name, v) SD_JSON_BUILD_PAIR(name, JSON_BUILD_HW_ADDR(v)) #define JSON_BUILD_PAIR_STRING_SET(name, s) SD_JSON_BUILD_PAIR(name, JSON_BUILD_STRING_SET(s)) diff --git a/src/libsystemd/sd-json/sd-json.c b/src/libsystemd/sd-json/sd-json.c index c0067cb40b..4ac50c20c9 100644 --- a/src/libsystemd/sd-json/sd-json.c +++ b/src/libsystemd/sd-json/sd-json.c @@ -3370,8 +3370,8 @@ done: r = 0; finish: - for (size_t i = 0; i < n_stack; i++) - json_stack_release(stack + i); + FOREACH_ARRAY(i, stack, n_stack) + json_stack_release(i); free(stack); @@ -4666,63 +4666,9 @@ _public_ int sd_json_buildv(sd_json_variant **ret, va_list ap) { break; } - case _JSON_BUILD_PAIR_IN4_ADDR_NON_NULL: { - const struct in_addr *a; - const char *n; - - if (current->expect != EXPECT_OBJECT_KEY) { - r = -EINVAL; - goto finish; - } - - n = va_arg(ap, const char *); - a = va_arg(ap, const struct in_addr *); - - if (a && in4_addr_is_set(a) && current->n_suppress == 0) { - r = sd_json_variant_new_string(&add, n); - if (r < 0) - goto finish; - - r = sd_json_variant_new_array_bytes(&add_more, a, sizeof(struct in_addr)); - if (r < 0) - goto finish; - } - - n_subtract = 2; /* we generated two items */ - - current->expect = EXPECT_OBJECT_KEY; - break; - } - - case _JSON_BUILD_PAIR_IN6_ADDR_NON_NULL: { - const struct in6_addr *a; - const char *n; - - if (current->expect != EXPECT_OBJECT_KEY) { - r = -EINVAL; - goto finish; - } - - n = va_arg(ap, const char *); - a = va_arg(ap, const struct in6_addr *); - - if (a && in6_addr_is_set(a) && current->n_suppress == 0) { - r = sd_json_variant_new_string(&add, n); - if (r < 0) - goto finish; - - r = sd_json_variant_new_array_bytes(&add_more, a, sizeof(struct in6_addr)); - if (r < 0) - goto finish; - } - - n_subtract = 2; /* we generated two items */ - - current->expect = EXPECT_OBJECT_KEY; - break; - } - - case _JSON_BUILD_PAIR_IN_ADDR_NON_NULL: { + case _JSON_BUILD_PAIR_IN_ADDR_NON_NULL: + case _JSON_BUILD_PAIR_IN_ADDR_WITH_STRING_NON_NULL: + case _JSON_BUILD_PAIR_IN_ADDR_WITH_STRING: { const union in_addr_union *a; const char *n; int f; @@ -4733,10 +4679,16 @@ _public_ int sd_json_buildv(sd_json_variant **ret, va_list ap) { } n = va_arg(ap, const char *); - a = va_arg(ap, const union in_addr_union *); f = va_arg(ap, int); + a = va_arg(ap, const union in_addr_union *); + + if (current->n_suppress == 0 && + ((a && in_addr_is_set(f, a)) || + command == _JSON_BUILD_PAIR_IN_ADDR_WITH_STRING)) { + + if (!a) + a = &IN_ADDR_NULL; - if (a && in_addr_is_set(f, a) && current->n_suppress == 0) { r = sd_json_variant_new_string(&add, n); if (r < 0) goto finish; @@ -4744,9 +4696,36 @@ _public_ int sd_json_buildv(sd_json_variant **ret, va_list ap) { r = sd_json_variant_new_array_bytes(&add_more, a->bytes, FAMILY_ADDRESS_SIZE_SAFE(f)); if (r < 0) goto finish; + + if (IN_SET(command, _JSON_BUILD_PAIR_IN_ADDR_WITH_STRING, _JSON_BUILD_PAIR_IN_ADDR_WITH_STRING_NON_NULL)) { + _cleanup_free_ char *string_key_name = NULL; + _cleanup_(sd_json_variant_unrefp) sd_json_variant *string_key = NULL, *string_value = NULL; + + string_key_name = strjoin(n, "String"); + if (!string_key_name) { + r = -ENOMEM; + goto finish; + } + + r = sd_json_variant_new_string(&string_key, string_key_name); + if (r < 0) + goto finish; + + r = sd_json_variant_new_string(&string_value, IN_ADDR_TO_STRING(f, a)); + if (r < 0) + goto finish; + + if (!GREEDY_REALLOC(current->elements, current->n_elements + 2)) { + r = -ENOMEM; + goto finish; + } + + current->elements[current->n_elements++] = TAKE_PTR(string_key); + current->elements[current->n_elements++] = TAKE_PTR(string_value); + } } - n_subtract = 2; /* we generated two items */ + n_subtract = command == _JSON_BUILD_PAIR_IN_ADDR_NON_NULL ? 2 : 4; current->expect = EXPECT_OBJECT_KEY; break; @@ -4896,207 +4875,6 @@ _public_ int sd_json_buildv(sd_json_variant **ret, va_list ap) { break; } - case _JSON_BUILD_PAIR_IN_ADDR_WITH_STRING_NON_NULL: - case _JSON_BUILD_PAIR_IN_ADDR_WITH_STRING: { - const union in_addr_union *a; - const char *n; - int f; - - if (current->expect != EXPECT_OBJECT_KEY) { - r = -EINVAL; - goto finish; - } - - n = va_arg(ap, const char *); - f = va_arg(ap, int); - a = va_arg(ap, const union in_addr_union *); - - if (current->n_suppress == 0) { - bool have_address = a && in_addr_is_set(f, a); - - if (have_address || command != _JSON_BUILD_PAIR_IN_ADDR_WITH_STRING_NON_NULL) { - _cleanup_free_ char *addr_str = NULL, *string_key_name = NULL; - _cleanup_(sd_json_variant_unrefp) sd_json_variant *string_key = NULL, *string_value = NULL; - - /* For non-NON_NULL variant, always convert address to string (even if all zeros). - * For NON_NULL variant, we only get here when have_address is true. */ - if (a) { - r = in_addr_to_string(f, a, &addr_str); - if (r < 0) - goto finish; - } - - string_key_name = strjoin(n, "String"); - if (!string_key_name) { - r = -ENOMEM; - goto finish; - } - - r = sd_json_variant_new_string(&add, n); - if (r < 0) - goto finish; - - r = sd_json_variant_new_array_bytes(&add_more, a->bytes, FAMILY_ADDRESS_SIZE_SAFE(f)); - if (r < 0) - goto finish; - - r = sd_json_variant_new_string(&string_key, string_key_name); - if (r < 0) - goto finish; - - r = sd_json_variant_new_string(&string_value, addr_str); - if (r < 0) - goto finish; - - if (!GREEDY_REALLOC(current->elements, current->n_elements + 2)) { - r = -ENOMEM; - goto finish; - } - - current->elements[current->n_elements++] = TAKE_PTR(string_key); - current->elements[current->n_elements++] = TAKE_PTR(string_value); - } - } - - n_subtract = 4; /* we generated two pairs (binary and string) */ - - current->expect = EXPECT_OBJECT_KEY; - break; - } - - case _JSON_BUILD_PAIR_IN6_ADDR_WITH_STRING_NON_NULL: - case _JSON_BUILD_PAIR_IN6_ADDR_WITH_STRING: { - const struct in6_addr *a; - const char *n; - - if (current->expect != EXPECT_OBJECT_KEY) { - r = -EINVAL; - goto finish; - } - - n = va_arg(ap, const char *); - a = va_arg(ap, const struct in6_addr *); - - if (current->n_suppress == 0) { - bool have_address = a && in6_addr_is_set(a); - - if (have_address || command != _JSON_BUILD_PAIR_IN6_ADDR_WITH_STRING_NON_NULL) { - _cleanup_free_ char *addr_str = NULL, *string_key_name = NULL; - _cleanup_(sd_json_variant_unrefp) sd_json_variant *string_key = NULL, *string_value = NULL; - - /* For non-NON_NULL variant, always convert address to string (even if all zeros). - * For NON_NULL variant, we only get here when have_address is true. */ - if (a) { - r = in6_addr_to_string(a, &addr_str); - if (r < 0) - goto finish; - } - - string_key_name = strjoin(n, "String"); - if (!string_key_name) { - r = -ENOMEM; - goto finish; - } - - r = sd_json_variant_new_string(&add, n); - if (r < 0) - goto finish; - - r = sd_json_variant_new_array_bytes(&add_more, a, sizeof(struct in6_addr)); - if (r < 0) - goto finish; - - r = sd_json_variant_new_string(&string_key, string_key_name); - if (r < 0) - goto finish; - - r = sd_json_variant_new_string(&string_value, addr_str); - if (r < 0) - goto finish; - - if (!GREEDY_REALLOC(current->elements, current->n_elements + 2)) { - r = -ENOMEM; - goto finish; - } - - current->elements[current->n_elements++] = TAKE_PTR(string_key); - current->elements[current->n_elements++] = TAKE_PTR(string_value); - } - } - - n_subtract = 4; /* we generated two pairs (binary and string) */ - - current->expect = EXPECT_OBJECT_KEY; - break; - } - - case _JSON_BUILD_PAIR_IN4_ADDR_WITH_STRING_NON_NULL: - case _JSON_BUILD_PAIR_IN4_ADDR_WITH_STRING: { - const struct in_addr *a; - const char *n; - - if (current->expect != EXPECT_OBJECT_KEY) { - r = -EINVAL; - goto finish; - } - - n = va_arg(ap, const char *); - a = va_arg(ap, const struct in_addr *); - - if (current->n_suppress == 0) { - bool have_address = a && !in4_addr_is_null(a); - - if (have_address || command != _JSON_BUILD_PAIR_IN4_ADDR_WITH_STRING_NON_NULL) { - _cleanup_free_ char *addr_str = NULL, *string_key_name = NULL; - _cleanup_(sd_json_variant_unrefp) sd_json_variant *string_key = NULL, *string_value = NULL; - - /* For non-NON_NULL variant, always convert address to string (even if all zeros). - * For NON_NULL variant, we only get here when have_address is true. */ - if (a) { - union in_addr_union addr_union = { .in = *a }; - r = in_addr_to_string(AF_INET, &addr_union, &addr_str); - if (r < 0) - goto finish; - } - - string_key_name = strjoin(n, "String"); - if (!string_key_name) { - r = -ENOMEM; - goto finish; - } - - r = sd_json_variant_new_string(&add, n); - if (r < 0) - goto finish; - - r = sd_json_variant_new_array_bytes(&add_more, a, sizeof(struct in_addr)); - if (r < 0) - goto finish; - - r = sd_json_variant_new_string(&string_key, string_key_name); - if (r < 0) - goto finish; - - r = sd_json_variant_new_string(&string_value, addr_str); - if (r < 0) - goto finish; - - if (!GREEDY_REALLOC(current->elements, current->n_elements + 2)) { - r = -ENOMEM; - goto finish; - } - - current->elements[current->n_elements++] = TAKE_PTR(string_key); - current->elements[current->n_elements++] = TAKE_PTR(string_value); - } - } - - n_subtract = 4; /* we generated two pairs (binary and string) */ - - current->expect = EXPECT_OBJECT_KEY; - break; - } - case _JSON_BUILD_PAIR_CALLBACK_NON_NULL: { sd_json_build_callback_t cb; void *userdata; @@ -5227,8 +5005,8 @@ done: r = 0; finish: - for (size_t i = 0; i < n_stack; i++) - json_stack_release(stack + i); + FOREACH_ARRAY(i, stack, n_stack) + json_stack_release(i); free(stack); diff --git a/src/libsystemd/sd-varlink/sd-varlink.c b/src/libsystemd/sd-varlink/sd-varlink.c index eecc3c8865..bcb16af89f 100644 --- a/src/libsystemd/sd-varlink/sd-varlink.c +++ b/src/libsystemd/sd-varlink/sd-varlink.c @@ -247,28 +247,20 @@ _public_ int sd_varlink_connect_exec(sd_varlink **ret, const char *_command, cha /* stdio_fds= */ NULL, /* except_fds= */ (int[]) { pair[1] }, /* n_except_fds= */ 1, - FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_REOPEN_LOG|FORK_LOG|FORK_RLIMIT_NOFILE_SAFE, + FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_PACK_FDS|FORK_CLOEXEC_OFF|FORK_REOPEN_LOG|FORK_DEATHSIG_SIGTERM|FORK_RLIMIT_NOFILE_SAFE, &pidref); if (r < 0) return log_debug_errno(r, "Failed to spawn process: %m"); if (r == 0) { char spid[DECIMAL_STR_MAX(pid_t)+1]; const char *setenv_list[] = { - "LISTEN_FDS", "1", "LISTEN_PID", spid, + "LISTEN_FDS", "1", "LISTEN_FDNAMES", "varlink", NULL, NULL, }; /* Child */ - pair[0] = -EBADF; - - r = move_fd(pair[1], 3, /* cloexec= */ false); - if (r < 0) { - log_debug_errno(r, "Failed to move file descriptor to 3: %m"); - _exit(EXIT_FAILURE); - } - xsprintf(spid, PID_FMT, pidref.pid); uint64_t pidfdid; @@ -364,7 +356,7 @@ static int varlink_connect_ssh_unix(sd_varlink **ret, const char *where) { /* stdio_fds= */ (int[]) { pair[1], pair[1], STDERR_FILENO }, /* except_fds= */ NULL, /* n_except_fds= */ 0, - FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_REOPEN_LOG|FORK_LOG|FORK_RLIMIT_NOFILE_SAFE|FORK_REARRANGE_STDIO, + FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_REOPEN_LOG|FORK_RLIMIT_NOFILE_SAFE|FORK_REARRANGE_STDIO, &pidref); if (r < 0) return log_debug_errno(r, "Failed to spawn process: %m"); @@ -448,7 +440,7 @@ static int varlink_connect_ssh_exec(sd_varlink **ret, const char *where) { /* stdio_fds= */ (int[]) { input_pipe[0], output_pipe[1], STDERR_FILENO }, /* except_fds= */ NULL, /* n_except_fds= */ 0, - FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_REOPEN_LOG|FORK_LOG|FORK_RLIMIT_NOFILE_SAFE|FORK_REARRANGE_STDIO, + FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_REOPEN_LOG|FORK_RLIMIT_NOFILE_SAFE|FORK_REARRANGE_STDIO, &pidref); if (r < 0) return log_debug_errno(r, "Failed to spawn process: %m"); @@ -1389,15 +1381,14 @@ static int varlink_format_queue(sd_varlink *v) { * would not corrupt our fd message boundaries */ while (v->output_queue) { - _cleanup_free_ int *array = NULL; - assert(v->n_output_queue > 0); - VarlinkJsonQueueItem *q = v->output_queue; - if (v->n_output_fds > 0) /* unwritten fds? if we'd add more we'd corrupt the fd message boundaries, hence wait */ return 0; + VarlinkJsonQueueItem *q = v->output_queue; + _cleanup_free_ int *array = NULL; + if (q->n_fds > 0) { array = newdup(int, q->fds, q->n_fds); if (!array) @@ -1409,8 +1400,7 @@ static int varlink_format_queue(sd_varlink *v) { return r; /* Take possession of the queue element's fds */ - free(v->output_fds); - v->output_fds = TAKE_PTR(array); + free_and_replace(v->output_fds, array); v->n_output_fds = q->n_fds; q->n_fds = 0; @@ -1593,7 +1583,7 @@ static int varlink_dispatch_method(sd_varlink *v) { r = callback(v, parameters, flags, v->userdata); if (VARLINK_STATE_WANTS_REPLY(v->state)) { if (r < 0) { - varlink_log_errno(v, r, "Callback for %s returned error: %m", method); + varlink_log_errno(v, r, "Callback for '%s' returned error: %m", method); /* We got an error back from the callback. Propagate it to the client * if the method call remains unanswered. */ @@ -1622,6 +1612,16 @@ static int varlink_dispatch_method(sd_varlink *v) { varlink_log_errno(v, r, "Failed to process sentinel for method '%s': %m", method); } else { assert(!v->previous); + + /* We're at the bare minimum referenced by sd_varlink_server and + * sd_varlink_process() */ + if (v->n_ref <= 2) { + r = varlink_log_errno(v, SYNTHETIC_ERRNO(EPROTO), + "Callback for method '%s' returned without enqueuing a reply or stashing connection, failing.", + method); + goto fail; + } + r = 0; } @@ -1857,19 +1857,10 @@ _public_ int sd_varlink_wait(sd_varlink *v, uint64_t timeout) { r = sd_varlink_get_timeout(v, &t); if (r < 0) return r; - if (t != USEC_INFINITY) { - usec_t n; + if (t != USEC_INFINITY) + t = usec_sub_unsigned(t, now(CLOCK_MONOTONIC)); - n = now(CLOCK_MONOTONIC); - if (t < n) - t = 0; - else - t = usec_sub_unsigned(t, n); - } - - if (timeout != USEC_INFINITY && - (t == USEC_INFINITY || timeout < t)) - t = timeout; + t = MIN(t, timeout); events = sd_varlink_get_events(v); if (events < 0) @@ -2019,7 +2010,7 @@ _public_ int sd_varlink_flush(sd_varlink *v) { return varlink_log_errno(v, SYNTHETIC_ERRNO(ENOTCONN), "Not connected."); for (;;) { - if (v->output_buffer_size == 0) + if (v->output_buffer_size == 0 && !v->output_queue) break; if (v->write_disconnected) return -ECONNRESET; @@ -2681,8 +2672,8 @@ _public_ int sd_varlink_reset_fds(sd_varlink *v) { * rollback the fds. Note that this is implicitly called whenever an error reply is sent, see * below. */ - close_many(v->output_fds, v->n_output_fds); - v->n_output_fds = 0; + close_many(v->pushed_fds, v->n_pushed_fds); + v->n_pushed_fds = 0; return 0; } @@ -3556,8 +3547,8 @@ static int validate_connection(sd_varlink_server *server, const struct ucred *uc c = PTR_TO_UINT(hashmap_get(server->by_uid, UID_TO_PTR(ucred->uid))); if (c >= server->connections_per_uid_max) { - varlink_server_log(server, "Per-UID connection limit of %u reached, refusing.", - server->connections_per_uid_max); + varlink_server_log(server, "Per-UID connection limit of %u for '" UID_FMT "' reached, refusing.", + server->connections_per_uid_max, ucred->uid); return 0; } } @@ -3610,7 +3601,7 @@ _public_ int sd_varlink_server_add_connection_pair( assert_return(input_fd >= 0, -EBADF); assert_return(output_fd >= 0, -EBADF); - if ((server->flags & (SD_VARLINK_SERVER_ROOT_ONLY|SD_VARLINK_SERVER_ACCOUNT_UID)) != 0) { + if ((server->flags & (SD_VARLINK_SERVER_ROOT_ONLY|SD_VARLINK_SERVER_MYSELF_ONLY|SD_VARLINK_SERVER_ACCOUNT_UID)) != 0) { if (override_ucred) ucred = *override_ucred; @@ -3752,11 +3743,7 @@ static int varlink_server_create_listen_fd_socket(sd_varlink_server *s, int fd, }; if (s->event) { - r = sd_event_add_io(s->event, &ss->event_source, fd, EPOLLIN, connect_callback, ss); - if (r < 0) - return r; - - r = sd_event_source_set_priority(ss->event_source, s->event_priority); + r = varlink_server_add_socket_event_source(s, ss); if (r < 0) return r; } @@ -4080,13 +4067,14 @@ _public_ int sd_varlink_server_set_exit_on_idle(sd_varlink_server *s, int b) { return 0; } -int varlink_server_add_socket_event_source(sd_varlink_server *s, VarlinkServerSocket *ss, int64_t priority) { +int varlink_server_add_socket_event_source(sd_varlink_server *s, VarlinkServerSocket *ss) { _cleanup_(sd_event_source_unrefp) sd_event_source *es = NULL; int r; assert(s); assert(s->event); assert(ss); + assert(ss->server == s); assert(ss->fd >= 0); assert(!ss->event_source); @@ -4094,7 +4082,7 @@ int varlink_server_add_socket_event_source(sd_varlink_server *s, VarlinkServerSo if (r < 0) return r; - r = sd_event_source_set_priority(es, priority); + r = sd_event_source_set_priority(es, s->event_priority); if (r < 0) return r; @@ -4116,13 +4104,14 @@ _public_ int sd_varlink_server_attach_event(sd_varlink_server *s, sd_event *e, i return r; } + s->event_priority = priority; + LIST_FOREACH(sockets, ss, s->sockets) { - r = varlink_server_add_socket_event_source(s, ss, priority); + r = varlink_server_add_socket_event_source(s, ss); if (r < 0) goto fail; } - s->event_priority = priority; return 0; fail: @@ -4293,20 +4282,16 @@ _public_ int sd_varlink_server_add_interface_many_internal(sd_varlink_server *s, } _public_ unsigned sd_varlink_server_connections_max(sd_varlink_server *s) { - int dts; /* If a server is specified, return the setting for that server, otherwise the default value */ if (s) return s->connections_max; - dts = getdtablesize(); + int dts = getdtablesize(); assert_se(dts > 0); /* Make sure we never use up more than ¾th of RLIMIT_NOFILE for IPC */ - if (VARLINK_DEFAULT_CONNECTIONS_MAX > (unsigned) dts / 4 * 3) - return dts / 4 * 3; - - return VARLINK_DEFAULT_CONNECTIONS_MAX; + return MIN(VARLINK_DEFAULT_CONNECTIONS_MAX, (unsigned) dts / 4 * 3); } _public_ unsigned sd_varlink_server_connections_per_uid_max(sd_varlink_server *s) { diff --git a/src/libsystemd/sd-varlink/varlink-internal.h b/src/libsystemd/sd-varlink/varlink-internal.h index 6486851424..39b15e12a1 100644 --- a/src/libsystemd/sd-varlink/varlink-internal.h +++ b/src/libsystemd/sd-varlink/varlink-internal.h @@ -262,4 +262,4 @@ static inline const char* varlink_server_description(sd_varlink_server *s) { VarlinkServerSocket* varlink_server_socket_free(VarlinkServerSocket *ss); DEFINE_TRIVIAL_CLEANUP_FUNC(VarlinkServerSocket *, varlink_server_socket_free); -int varlink_server_add_socket_event_source(sd_varlink_server *s, VarlinkServerSocket *ss, int64_t priority); +int varlink_server_add_socket_event_source(sd_varlink_server *s, VarlinkServerSocket *ss); diff --git a/src/mute-console/mute-console.c b/src/mute-console/mute-console.c index 40c0839367..b18e79d622 100644 --- a/src/mute-console/mute-console.c +++ b/src/mute-console/mute-console.c @@ -273,6 +273,7 @@ static int vl_method_mute( int r; assert(link); + assert(FLAGS_SET(flags, SD_VARLINK_METHOD_MORE)); _cleanup_free_ Context *nc = new(Context, 1); if (!nc) @@ -294,9 +295,6 @@ static int vl_method_mute( if (r != 0) return r; - if (!FLAGS_SET(flags, SD_VARLINK_METHOD_MORE)) - return sd_varlink_error(link, SD_VARLINK_ERROR_EXPECTED_MORE, NULL); - r = sd_varlink_server_bind_disconnect(sd_varlink_get_server(link), vl_on_disconnect); if (r < 0) return r; diff --git a/src/network/networkd-json.c b/src/network/networkd-json.c index 123594179c..de1a8829ee 100644 --- a/src/network/networkd-json.c +++ b/src/network/networkd-json.c @@ -623,7 +623,7 @@ static int dnr_append_json_one(Link *link, const struct sd_dns_resolver *res, Ne FOREACH_ARRAY(addr, res->addrs, res->n_addrs) { r = sd_json_variant_append_arrayb( &addrs_array, - JSON_BUILD_IN_ADDR(addr, res->family)); + JSON_BUILD_IN_ADDR(res->family, addr)); if (r < 0) return r; } @@ -644,7 +644,7 @@ static int dnr_append_json_one(Link *link, const struct sd_dns_resolver *res, Ne JSON_BUILD_PAIR_STRING_NON_EMPTY("DoHPath", res->dohpath), JSON_BUILD_PAIR_STRV_NON_EMPTY("Transports", transports), SD_JSON_BUILD_PAIR_STRING("ConfigSource", network_config_source_to_string(s)), - JSON_BUILD_PAIR_IN_ADDR_NON_NULL("ConfigProvider", p, res->family))); + JSON_BUILD_PAIR_IN_ADDR_NON_NULL("ConfigProvider", res->family, p))); } static int dnr_append_json(Link *link, sd_json_variant **v) { @@ -733,7 +733,7 @@ static int server_append_json_one_addr(int family, const union in_addr_union *a, return sd_json_variant_append_arraybo( array, SD_JSON_BUILD_PAIR_INTEGER("Family", family), - JSON_BUILD_PAIR_IN_ADDR("Address", a, family), + JSON_BUILD_PAIR_IN_ADDR("Address", family, a), SD_JSON_BUILD_PAIR_STRING("AddressString", address_str), SD_JSON_BUILD_PAIR_STRING("ConfigSource", network_config_source_to_string(s)), JSON_BUILD_PAIR_IN_ADDR_WITH_STRING_NON_NULL("ConfigProvider", family, p)); diff --git a/src/pcrlock/pcrlock.c b/src/pcrlock/pcrlock.c index 396785280c..138841f31c 100644 --- a/src/pcrlock/pcrlock.c +++ b/src/pcrlock/pcrlock.c @@ -5404,6 +5404,7 @@ static int vl_method_read_event_log(sd_varlink *link, sd_json_variant *parameter int r; assert(link); + assert(FLAGS_SET(flags, SD_VARLINK_METHOD_MORE)); r = sd_varlink_dispatch(link, parameters, /* dispatch_table= */ NULL, /* userdata= */ NULL); if (r != 0) diff --git a/src/repart/repart.c b/src/repart/repart.c index ac6cccbcba..3d1846b7e8 100644 --- a/src/repart/repart.c +++ b/src/repart/repart.c @@ -10324,14 +10324,12 @@ static int vl_method_list_candidate_devices( int r; assert(link); + assert(FLAGS_SET(flags, SD_VARLINK_METHOD_MORE)); r = sd_varlink_dispatch(link, parameters, dispatch_table, &p); if (r != 0) return r; - if (!FLAGS_SET(flags, SD_VARLINK_METHOD_MORE)) - return sd_varlink_error(link, SD_VARLINK_ERROR_EXPECTED_MORE, NULL); - BlockDevice *l = NULL; size_t n = 0; CLEANUP_ARRAY(l, n, block_device_array_free); diff --git a/src/resolve/resolved-dns-server.c b/src/resolve/resolved-dns-server.c index 83082631f7..4f04476f2d 100644 --- a/src/resolve/resolved-dns-server.c +++ b/src/resolve/resolved-dns-server.c @@ -1374,7 +1374,7 @@ int dns_server_dump_configuration_to_json(DnsServer *server, sd_json_variant **r return sd_json_buildo( ret, JSON_BUILD_PAIR_STRING_NON_EMPTY("addressString", dns_server_string(server)), - JSON_BUILD_PAIR_IN_ADDR("address", &server->address, server->family), + JSON_BUILD_PAIR_IN_ADDR("address", server->family, &server->address), SD_JSON_BUILD_PAIR_INTEGER("family", server->family), SD_JSON_BUILD_PAIR_UNSIGNED("port", dns_server_port(server)), SD_JSON_BUILD_PAIR_CONDITION(ifindex > 0, "ifindex", SD_JSON_BUILD_UNSIGNED(ifindex)), diff --git a/src/resolve/resolved-varlink.c b/src/resolve/resolved-varlink.c index 760e890426..bb0100b046 100644 --- a/src/resolve/resolved-varlink.c +++ b/src/resolve/resolved-varlink.c @@ -1214,10 +1214,7 @@ static int vl_method_browse_services(sd_varlink* link, sd_json_variant* paramete int r = 0; assert(link); - - /* if the client didn't set the more flag, it is using us incorrectly */ - if (!FLAGS_SET(flags, SD_VARLINK_METHOD_MORE)) - return sd_varlink_error(link, SD_VARLINK_ERROR_EXPECTED_MORE, NULL); + assert(FLAGS_SET(flags, SD_VARLINK_METHOD_MORE)); m = ASSERT_PTR(sd_varlink_server_get_userdata(sd_varlink_get_server(link))); @@ -1239,9 +1236,7 @@ static int vl_method_subscribe_query_results(sd_varlink *link, sd_json_variant * Manager *m = ASSERT_PTR(sd_varlink_get_userdata(ASSERT_PTR(link))); int r; - /* if the client didn't set the more flag, it is using us incorrectly */ - if (!FLAGS_SET(flags, SD_VARLINK_METHOD_MORE)) - return sd_varlink_error(link, SD_VARLINK_ERROR_EXPECTED_MORE, NULL); + assert(FLAGS_SET(flags, SD_VARLINK_METHOD_MORE)); r = verify_polkit(link, parameters, "org.freedesktop.resolve1.subscribe-query-results"); if (r <= 0) @@ -1382,9 +1377,7 @@ static int vl_method_subscribe_dns_configuration(sd_varlink *link, sd_json_varia Manager *m = ASSERT_PTR(sd_varlink_get_userdata(ASSERT_PTR(link))); int r; - /* if the client didn't set the more flag, it is using us incorrectly */ - if (!FLAGS_SET(flags, SD_VARLINK_METHOD_MORE)) - return sd_varlink_error(link, SD_VARLINK_ERROR_EXPECTED_MORE, NULL); + assert(FLAGS_SET(flags, SD_VARLINK_METHOD_MORE)); r = verify_polkit(link, parameters, "org.freedesktop.resolve1.subscribe-dns-configuration"); if (r <= 0) diff --git a/src/shared/apparmor-util.c b/src/shared/apparmor-util.c index 22e7d2d90d..10b57c6090 100644 --- a/src/shared/apparmor-util.c +++ b/src/shared/apparmor-util.c @@ -1,7 +1,5 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ -#if HAVE_APPARMOR - #include #include "alloc-util.h" @@ -67,4 +65,3 @@ bool mac_apparmor_use(void) { return (cached_use = true); } -#endif diff --git a/src/shared/meson.build b/src/shared/meson.build index fea5e22109..b9630bef65 100644 --- a/src/shared/meson.build +++ b/src/shared/meson.build @@ -3,7 +3,6 @@ shared_sources = files( 'acl-util.c', 'acpi-fpdt.c', - 'apparmor-util.c', 'ask-password-agent.c', 'ask-password-api.c', 'async.c', @@ -279,6 +278,10 @@ if conf.get('HAVE_LIBIDN2') == 1 shared_sources += files('idn-util.c') endif +if conf.get('HAVE_APPARMOR') == 1 + shared_sources += files('apparmor-util.c') +endif + generate_ip_protocol_list = files('generate-ip-protocol-list.sh') ip_protocol_list_txt = custom_target( input : [generate_ip_protocol_list, ipproto_sources], diff --git a/src/shared/metrics.c b/src/shared/metrics.c index 9c70f1129b..3b8965dbdc 100644 --- a/src/shared/metrics.c +++ b/src/shared/metrics.c @@ -11,6 +11,7 @@ int metrics_setup_varlink_server( sd_varlink_server **server, /* in and out param */ sd_varlink_server_flags_t flags, sd_event *event, + int64_t priority, sd_varlink_method_t vl_method_list_cb, sd_varlink_method_t vl_method_describe_cb, void *userdata) { @@ -20,6 +21,8 @@ int metrics_setup_varlink_server( assert(server); assert(event); + assert(vl_method_list_cb); + assert(vl_method_describe_cb); if (*server) return 0; @@ -34,24 +37,21 @@ int metrics_setup_varlink_server( r = sd_varlink_server_bind_method_many( s, - "io.systemd.Metrics.List", - vl_method_list_cb, - "io.systemd.Metrics.Describe", - vl_method_describe_cb); + "io.systemd.Metrics.List", vl_method_list_cb, + "io.systemd.Metrics.Describe", vl_method_describe_cb); if (r < 0) return log_debug_errno(r, "Failed to register varlink metrics methods: %m"); - r = sd_varlink_server_set_description(s, "systemd varlink metrics server"); + r = sd_varlink_server_set_description(s, "varlink-metrics"); if (r < 0) return log_debug_errno(r, "Failed to set varlink metrics server description: %m"); - r = sd_varlink_server_attach_event(s, event, SD_EVENT_PRIORITY_NORMAL); + r = sd_varlink_server_attach_event(s, event, priority); if (r < 0) return log_debug_errno(r, "Failed to attach varlink metrics server to event loop: %m"); *server = TAKE_PTR(s); - - return 0; + return 1; } static const char * const metric_family_type_table[_METRIC_FAMILY_TYPE_MAX] = { @@ -84,14 +84,12 @@ int metrics_method_describe( assert(metric_family_table); assert(link); assert(parameters); + assert(FLAGS_SET(flags, SD_VARLINK_METHOD_MORE)); r = sd_varlink_dispatch(link, parameters, /* dispatch_table= */ NULL, /* userdata= */ NULL); if (r != 0) return r; - if (!FLAGS_SET(flags, SD_VARLINK_METHOD_MORE)) - return sd_varlink_error(link, SD_VARLINK_ERROR_EXPECTED_MORE, NULL); - r = varlink_set_sentinel(link, "io.systemd.Metrics.NoSuchMetric"); if (r < 0) return r; @@ -123,14 +121,12 @@ int metrics_method_list( assert(metric_family_table); assert(link); assert(parameters); + assert(FLAGS_SET(flags, SD_VARLINK_METHOD_MORE)); r = sd_varlink_dispatch(link, parameters, /* dispatch_table= */ NULL, /* userdata= */ NULL); if (r != 0) return r; - if (!FLAGS_SET(flags, SD_VARLINK_METHOD_MORE)) - return sd_varlink_error(link, SD_VARLINK_ERROR_EXPECTED_MORE, NULL); - r = varlink_set_sentinel(link, "io.systemd.Metrics.NoSuchMetric"); if (r < 0) return r; diff --git a/src/shared/metrics.h b/src/shared/metrics.h index cec0153e68..ffc28cb0a9 100644 --- a/src/shared/metrics.h +++ b/src/shared/metrics.h @@ -31,6 +31,7 @@ int metrics_setup_varlink_server( sd_varlink_server **server, /* in and out param */ sd_varlink_server_flags_t flags, sd_event *event, + int64_t priority, sd_varlink_method_t vl_method_list_cb, sd_varlink_method_t vl_method_describe_cb, void *userdata); diff --git a/src/shared/varlink-io.systemd.MuteConsole.c b/src/shared/varlink-io.systemd.MuteConsole.c index 0cea5b8554..723b19985e 100644 --- a/src/shared/varlink-io.systemd.MuteConsole.c +++ b/src/shared/varlink-io.systemd.MuteConsole.c @@ -4,8 +4,9 @@ #include "varlink-io.systemd.MuteConsole.h" -static SD_VARLINK_DEFINE_METHOD( +static SD_VARLINK_DEFINE_METHOD_FULL( Mute, + SD_VARLINK_REQUIRES_MORE, SD_VARLINK_FIELD_COMMENT("Whether to mute the kernel's output to the console (defaults to true)."), SD_VARLINK_DEFINE_INPUT(kernel, SD_VARLINK_BOOL, SD_VARLINK_NULLABLE), SD_VARLINK_FIELD_COMMENT("Whether to mute PID1's output to the console (defaults to true)."), diff --git a/src/shared/varlink-io.systemd.Network.c b/src/shared/varlink-io.systemd.Network.c index f7d29521b0..b80070ee5f 100644 --- a/src/shared/varlink-io.systemd.Network.c +++ b/src/shared/varlink-io.systemd.Network.c @@ -4,11 +4,11 @@ #include "varlink-io.systemd.Network.h" /* Helper macro to define address fields with both binary and string representation */ -#define SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(field_name, comment, flags) \ - SD_VARLINK_FIELD_COMMENT(comment), \ - SD_VARLINK_DEFINE_FIELD(field_name, SD_VARLINK_INT, SD_VARLINK_ARRAY | (flags)), \ - SD_VARLINK_FIELD_COMMENT(comment " (human-readable format)"), \ - SD_VARLINK_DEFINE_FIELD(field_name##String, SD_VARLINK_STRING, (flags)) +#define VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(field_name, comment, flags) \ + SD_VARLINK_FIELD_COMMENT(comment), \ + SD_VARLINK_DEFINE_FIELD(field_name, SD_VARLINK_INT, SD_VARLINK_ARRAY | (flags)), \ + SD_VARLINK_FIELD_COMMENT(comment " (human-readable format)"), \ + SD_VARLINK_DEFINE_FIELD(field_name##String, SD_VARLINK_STRING, (flags)) static SD_VARLINK_DEFINE_ENUM_TYPE( LinkState, @@ -43,10 +43,10 @@ static SD_VARLINK_DEFINE_STRUCT_TYPE( RoutingPolicyRule, SD_VARLINK_FIELD_COMMENT("Address family (AF_INET or AF_INET6)"), SD_VARLINK_DEFINE_FIELD(Family, SD_VARLINK_INT, 0), - SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(FromPrefix, "Source address prefix to match", SD_VARLINK_NULLABLE), + VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(FromPrefix, "Source address prefix to match", SD_VARLINK_NULLABLE), SD_VARLINK_FIELD_COMMENT("Length of source prefix in bits"), SD_VARLINK_DEFINE_FIELD(FromPrefixLength, SD_VARLINK_INT, SD_VARLINK_NULLABLE), - SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(ToPrefix, "Destination address prefix to match", SD_VARLINK_NULLABLE), + VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(ToPrefix, "Destination address prefix to match", SD_VARLINK_NULLABLE), SD_VARLINK_FIELD_COMMENT("Length of destination prefix in bits"), SD_VARLINK_DEFINE_FIELD(ToPrefixLength, SD_VARLINK_INT, SD_VARLINK_NULLABLE), SD_VARLINK_FIELD_COMMENT("Routing protocol identifier"), @@ -98,14 +98,14 @@ static SD_VARLINK_DEFINE_STRUCT_TYPE( Route, SD_VARLINK_FIELD_COMMENT("Address family (AF_INET or AF_INET6)"), SD_VARLINK_DEFINE_FIELD(Family, SD_VARLINK_INT, 0), - SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(Destination, "Destination network address", 0), + VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(Destination, "Destination network address", 0), SD_VARLINK_FIELD_COMMENT("Destination network prefix length"), SD_VARLINK_DEFINE_FIELD(DestinationPrefixLength, SD_VARLINK_INT, 0), - SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(Gateway, "Gateway address for this route", SD_VARLINK_NULLABLE), - SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(Source, "Source address prefix for route selection", SD_VARLINK_NULLABLE), + VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(Gateway, "Gateway address for this route", SD_VARLINK_NULLABLE), + VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(Source, "Source address prefix for route selection", SD_VARLINK_NULLABLE), SD_VARLINK_FIELD_COMMENT("Source prefix length"), SD_VARLINK_DEFINE_FIELD(SourcePrefixLength, SD_VARLINK_INT, SD_VARLINK_NULLABLE), - SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(PreferredSource, "Preferred source address for outgoing packets", SD_VARLINK_NULLABLE), + VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(PreferredSource, "Preferred source address for outgoing packets", SD_VARLINK_NULLABLE), SD_VARLINK_FIELD_COMMENT("Type of Service (TOS) field"), SD_VARLINK_DEFINE_FIELD(TOS, SD_VARLINK_INT, 0), SD_VARLINK_FIELD_COMMENT("Route scope (RT_SCOPE_* value)"), @@ -140,7 +140,7 @@ static SD_VARLINK_DEFINE_STRUCT_TYPE( SD_VARLINK_DEFINE_FIELD(LifetimeUSec, SD_VARLINK_INT, SD_VARLINK_NULLABLE), SD_VARLINK_FIELD_COMMENT("Configuration source for this route"), SD_VARLINK_DEFINE_FIELD(ConfigSource, SD_VARLINK_STRING, 0), - SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(ConfigProvider, "Address of the configuration provider", SD_VARLINK_NULLABLE), + VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(ConfigProvider, "Address of the configuration provider", SD_VARLINK_NULLABLE), SD_VARLINK_FIELD_COMMENT("Configuration state of this route"), SD_VARLINK_DEFINE_FIELD(ConfigState, SD_VARLINK_STRING, SD_VARLINK_NULLABLE), SD_VARLINK_FIELD_COMMENT("Interface index for serialization"), @@ -163,7 +163,7 @@ static SD_VARLINK_DEFINE_STRUCT_TYPE( SD_VARLINK_DEFINE_FIELD(ID, SD_VARLINK_INT, 0), SD_VARLINK_FIELD_COMMENT("Address family (AF_INET or AF_INET6)"), SD_VARLINK_DEFINE_FIELD(Family, SD_VARLINK_INT, 0), - SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(Gateway, "Gateway address for this next hop", SD_VARLINK_NULLABLE), + VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(Gateway, "Gateway address for this next hop", SD_VARLINK_NULLABLE), SD_VARLINK_FIELD_COMMENT("Next hop flags (RTNH_F_* values)"), SD_VARLINK_DEFINE_FIELD(Flags, SD_VARLINK_INT, SD_VARLINK_NULLABLE), SD_VARLINK_FIELD_COMMENT("Human-readable flags string"), @@ -178,7 +178,7 @@ static SD_VARLINK_DEFINE_STRUCT_TYPE( SD_VARLINK_DEFINE_FIELD_BY_TYPE(Group, NextHopGroup, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE), SD_VARLINK_FIELD_COMMENT("Configuration source for this next hop"), SD_VARLINK_DEFINE_FIELD(ConfigSource, SD_VARLINK_STRING, 0), - SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(ConfigProvider, "Address of the configuration provider", SD_VARLINK_NULLABLE), + VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(ConfigProvider, "Address of the configuration provider", SD_VARLINK_NULLABLE), SD_VARLINK_FIELD_COMMENT("Configuration state of this next hop"), SD_VARLINK_DEFINE_FIELD(ConfigState, SD_VARLINK_STRING, SD_VARLINK_NULLABLE)); @@ -209,7 +209,7 @@ static SD_VARLINK_DEFINE_STRUCT_TYPE( DNS, SD_VARLINK_FIELD_COMMENT("Address family (AF_INET or AF_INET6)"), SD_VARLINK_DEFINE_FIELD(Family, SD_VARLINK_INT, 0), - SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(Address, "DNS server IP address", 0), + VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(Address, "DNS server IP address", 0), SD_VARLINK_FIELD_COMMENT("DNS server port number"), SD_VARLINK_DEFINE_FIELD(Port, SD_VARLINK_INT, SD_VARLINK_NULLABLE), SD_VARLINK_FIELD_COMMENT("Interface index for link-local DNS servers"), @@ -218,29 +218,29 @@ static SD_VARLINK_DEFINE_STRUCT_TYPE( SD_VARLINK_DEFINE_FIELD(ServerName, SD_VARLINK_STRING, SD_VARLINK_NULLABLE), SD_VARLINK_FIELD_COMMENT("Configuration source for this DNS server"), SD_VARLINK_DEFINE_FIELD(ConfigSource, SD_VARLINK_STRING, 0), - SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(ConfigProvider, "Address of the configuration provider", SD_VARLINK_NULLABLE)); + VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(ConfigProvider, "Address of the configuration provider", SD_VARLINK_NULLABLE)); static SD_VARLINK_DEFINE_STRUCT_TYPE( NTP, SD_VARLINK_FIELD_COMMENT("Address family (AF_INET or AF_INET6) for address-based servers"), SD_VARLINK_DEFINE_FIELD(Family, SD_VARLINK_INT, SD_VARLINK_NULLABLE), - SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(Address, "NTP server IP address", SD_VARLINK_NULLABLE), + VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(Address, "NTP server IP address", SD_VARLINK_NULLABLE), SD_VARLINK_FIELD_COMMENT("NTP server"), SD_VARLINK_DEFINE_FIELD(Server, SD_VARLINK_STRING, SD_VARLINK_NULLABLE), SD_VARLINK_FIELD_COMMENT("Configuration source for this NTP server"), SD_VARLINK_DEFINE_FIELD(ConfigSource, SD_VARLINK_STRING, 0), - SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(ConfigProvider, "Address of the configuration provider", SD_VARLINK_NULLABLE)); + VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(ConfigProvider, "Address of the configuration provider", SD_VARLINK_NULLABLE)); static SD_VARLINK_DEFINE_STRUCT_TYPE( SIP, SD_VARLINK_FIELD_COMMENT("Address family (AF_INET or AF_INET6) for address-based servers"), SD_VARLINK_DEFINE_FIELD(Family, SD_VARLINK_INT, SD_VARLINK_NULLABLE), - SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(Address, "SIP server IP address", SD_VARLINK_NULLABLE), + VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(Address, "SIP server IP address", SD_VARLINK_NULLABLE), SD_VARLINK_FIELD_COMMENT("SIP server domain name"), SD_VARLINK_DEFINE_FIELD(Domain, SD_VARLINK_STRING, SD_VARLINK_NULLABLE), SD_VARLINK_FIELD_COMMENT("Configuration source for this SIP server"), SD_VARLINK_DEFINE_FIELD(ConfigSource, SD_VARLINK_STRING, 0), - SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(ConfigProvider, "Address of the configuration provider", SD_VARLINK_NULLABLE)); + VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(ConfigProvider, "Address of the configuration provider", SD_VARLINK_NULLABLE)); static SD_VARLINK_DEFINE_STRUCT_TYPE( Domain, @@ -248,7 +248,7 @@ static SD_VARLINK_DEFINE_STRUCT_TYPE( SD_VARLINK_DEFINE_FIELD(Domain, SD_VARLINK_STRING, 0), SD_VARLINK_FIELD_COMMENT("Configuration source for this domain"), SD_VARLINK_DEFINE_FIELD(ConfigSource, SD_VARLINK_STRING, 0), - SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(ConfigProvider, "Address of the configuration provider", SD_VARLINK_NULLABLE)); + VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(ConfigProvider, "Address of the configuration provider", SD_VARLINK_NULLABLE)); static SD_VARLINK_DEFINE_STRUCT_TYPE( DNSSECNegativeTrustAnchor, @@ -280,7 +280,7 @@ static SD_VARLINK_DEFINE_STRUCT_TYPE( SD_VARLINK_DEFINE_FIELD(PrefixLength, SD_VARLINK_INT, 0), SD_VARLINK_FIELD_COMMENT("Lifetime of the prefix in microseconds"), SD_VARLINK_DEFINE_FIELD(LifetimeUSec, SD_VARLINK_INT, SD_VARLINK_NULLABLE), - SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(ConfigProvider, "Address of router that provided this prefix", SD_VARLINK_NULLABLE)); + VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(ConfigProvider, "Address of router that provided this prefix", SD_VARLINK_NULLABLE)); static SD_VARLINK_DEFINE_STRUCT_TYPE( NDisc, @@ -291,14 +291,14 @@ static SD_VARLINK_DEFINE_STRUCT_TYPE( Address, SD_VARLINK_FIELD_COMMENT("Address family (AF_INET or AF_INET6)"), SD_VARLINK_DEFINE_FIELD(Family, SD_VARLINK_INT, 0), - SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(Address, "IP address", 0), - SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(Peer, "Peer address for point-to-point interfaces", SD_VARLINK_NULLABLE), + VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(Address, "IP address", 0), + VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(Peer, "Peer address for point-to-point interfaces", SD_VARLINK_NULLABLE), SD_VARLINK_FIELD_COMMENT("Network prefix length"), SD_VARLINK_DEFINE_FIELD(PrefixLength, SD_VARLINK_INT, 0), SD_VARLINK_FIELD_COMMENT("Configuration source for this address"), SD_VARLINK_DEFINE_FIELD(ConfigSource, SD_VARLINK_STRING, 0), - SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(ConfigProvider, "Address of the configuration provider (DHCP server, router, etc.)", SD_VARLINK_NULLABLE), - SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(Broadcast, "Broadcast address for IPv4 networks", SD_VARLINK_NULLABLE), + VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(ConfigProvider, "Address of the configuration provider (DHCP server, router, etc.)", SD_VARLINK_NULLABLE), + VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(Broadcast, "Broadcast address for IPv4 networks", SD_VARLINK_NULLABLE), SD_VARLINK_FIELD_COMMENT("Address scope (RT_SCOPE_* value)"), SD_VARLINK_DEFINE_FIELD(Scope, SD_VARLINK_INT, SD_VARLINK_NULLABLE), SD_VARLINK_FIELD_COMMENT("Human-readable scope string"), @@ -324,7 +324,7 @@ static SD_VARLINK_DEFINE_STRUCT_TYPE( Neighbor, SD_VARLINK_FIELD_COMMENT("Address family (AF_INET or AF_INET6)"), SD_VARLINK_DEFINE_FIELD(Family, SD_VARLINK_INT, 0), - SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(Destination, "IP address of the neighbor", 0), + VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(Destination, "IP address of the neighbor", 0), SD_VARLINK_FIELD_COMMENT("Link layer (MAC) address of the neighbor"), SD_VARLINK_DEFINE_FIELD(LinkLayerAddress, SD_VARLINK_INT, SD_VARLINK_ARRAY), SD_VARLINK_FIELD_COMMENT("Configuration source for this neighbor entry"), @@ -387,7 +387,7 @@ static SD_VARLINK_DEFINE_STRUCT_TYPE( DHCPServerLease, SD_VARLINK_FIELD_COMMENT("DHCP client identifier"), SD_VARLINK_DEFINE_FIELD(ClientId, SD_VARLINK_INT, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE), - SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(Address, "Address assigned to the client", SD_VARLINK_NULLABLE), + VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(Address, "Address assigned to the client", SD_VARLINK_NULLABLE), SD_VARLINK_FIELD_COMMENT("Hostname provided by the DHCP client"), SD_VARLINK_DEFINE_FIELD(Hostname, SD_VARLINK_STRING, SD_VARLINK_NULLABLE), SD_VARLINK_FIELD_COMMENT("Hardware address type (ARPHRD_* value)"), @@ -448,7 +448,7 @@ static SD_VARLINK_DEFINE_STRUCT_TYPE( SD_VARLINK_DEFINE_FIELD(PermanentHardwareAddress, SD_VARLINK_INT, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE), SD_VARLINK_FIELD_COMMENT("Broadcast address for Ethernet interfaces"), SD_VARLINK_DEFINE_FIELD(BroadcastAddress, SD_VARLINK_INT, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE), - SD_VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(IPv6LinkLocalAddress, "IPv6 link-local address", SD_VARLINK_NULLABLE), + VARLINK_DEFINE_IN_ADDR_WITH_STRING_FIELD(IPv6LinkLocalAddress, "IPv6 link-local address", SD_VARLINK_NULLABLE), SD_VARLINK_FIELD_COMMENT("Wireless LAN interface type (NL80211_IFTYPE_* value)"), SD_VARLINK_DEFINE_FIELD(WirelessLanInterfaceType, SD_VARLINK_INT, SD_VARLINK_NULLABLE), SD_VARLINK_FIELD_COMMENT("Human-readable wireless LAN interface type"), diff --git a/src/shared/varlink-io.systemd.Repart.c b/src/shared/varlink-io.systemd.Repart.c index 35b860db9e..8d50454595 100644 --- a/src/shared/varlink-io.systemd.Repart.c +++ b/src/shared/varlink-io.systemd.Repart.c @@ -59,8 +59,9 @@ static SD_VARLINK_DEFINE_METHOD_FULL( SD_VARLINK_FIELD_COMMENT("If used with the 'more' flag, a progress percentrage (specific to the work done for the specified phase+object is sent in progress updates."), SD_VARLINK_DEFINE_OUTPUT(progress, SD_VARLINK_INT, SD_VARLINK_NULLABLE)); -static SD_VARLINK_DEFINE_METHOD( +static SD_VARLINK_DEFINE_METHOD_FULL( ListCandidateDevices, + SD_VARLINK_REQUIRES_MORE, SD_VARLINK_FIELD_COMMENT("Control whether to include the root disk of the currently booted OS in the list. Defaults to false, i.e. the root disk is included."), SD_VARLINK_DEFINE_INPUT(ignoreRoot, SD_VARLINK_BOOL, SD_VARLINK_NULLABLE), SD_VARLINK_FIELD_COMMENT("Control whether to include block devices with zero size in the list, i.e. typically block devices without any inserted medium. Defaults to false, i.e. empty block devices are included."), diff --git a/src/shared/varlink-io.systemd.Resolve.c b/src/shared/varlink-io.systemd.Resolve.c index c84453851b..33398a62f7 100644 --- a/src/shared/varlink-io.systemd.Resolve.c +++ b/src/shared/varlink-io.systemd.Resolve.c @@ -300,7 +300,7 @@ static SD_VARLINK_DEFINE_METHOD( static SD_VARLINK_DEFINE_METHOD_FULL( BrowseServices, - SD_VARLINK_SUPPORTS_MORE, + SD_VARLINK_REQUIRES_MORE, SD_VARLINK_FIELD_COMMENT("The domain to browse for services. If null, the default browsing domain local is used."), SD_VARLINK_DEFINE_INPUT(domain, SD_VARLINK_STRING, SD_VARLINK_NULLABLE), SD_VARLINK_FIELD_COMMENT("The service type to browse for (e.g., '_http._tcp')."), diff --git a/src/shared/varlink-io.systemd.Unit.c b/src/shared/varlink-io.systemd.Unit.c index 19d384dd91..7ea6a7bc54 100644 --- a/src/shared/varlink-io.systemd.Unit.c +++ b/src/shared/varlink-io.systemd.Unit.c @@ -179,6 +179,8 @@ static SD_VARLINK_DEFINE_STRUCT_TYPE( SD_VARLINK_DEFINE_FIELD_BY_TYPE(SocketBindDeny, CGroupSocketBind, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE), SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man/"PROJECT_VERSION_STR"/systemd.resource-control.html#RestrictNetworkInterfaces="), SD_VARLINK_DEFINE_FIELD_BY_TYPE(RestrictNetworkInterfaces, CGroupRestrictNetworkInterfaces, SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man/"PROJECT_VERSION_STR"/systemd.resource-control.html#BindNetworkInterface="), + SD_VARLINK_DEFINE_FIELD(BindNetworkInterface, SD_VARLINK_STRING, SD_VARLINK_NULLABLE), SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man/"PROJECT_VERSION_STR"/systemd.resource-control.html#NFTSet=family:table:set"), SD_VARLINK_DEFINE_FIELD_BY_TYPE(NFTSet, CGroupNFTSet, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE), diff --git a/src/shared/varlink-serialize.c b/src/shared/varlink-serialize.c index 906a1020de..7ea8ca7552 100644 --- a/src/shared/varlink-serialize.c +++ b/src/shared/varlink-serialize.c @@ -1,78 +1,73 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ -#include "sd-event.h" - #include "alloc-util.h" +#include "extract-word.h" +#include "fd-util.h" #include "fdset.h" #include "log.h" -#include "parse-util.h" +#include "serialize.h" #include "socket-util.h" #include "string-util.h" #include "varlink-internal.h" #include "varlink-serialize.h" -int varlink_server_serialize(sd_varlink_server *s, FILE *f, FDSet *fds) { +int varlink_server_serialize(sd_varlink_server *s, const char *name, FILE *f, FDSet *fds) { assert(f); assert(fds); if (!s) return 0; - LIST_FOREACH(sockets, ss, s->sockets) { - int copy; + const char *prefix = name ? strjoina("varlink-server-", name) : "varlink-server"; + LIST_FOREACH(sockets, ss, s->sockets) { assert(ss->address); assert(ss->fd >= 0); - fprintf(f, "varlink-server-socket-address=%s", ss->address); - /* If we fail to serialize the fd, it will be considered an error during deserialization */ - copy = fdset_put_dup(fds, ss->fd); + int copy = fdset_put_dup(fds, ss->fd); if (copy < 0) return copy; - fprintf(f, " varlink-server-socket-fd=%i", copy); - - fputc('\n', f); + fprintf(f, "%s-socket-address=%s varlink-server-socket-fd=%d\n", prefix, ss->address, copy); } return 0; } int varlink_server_deserialize_one(sd_varlink_server *s, const char *value, FDSet *fds) { - _cleanup_(varlink_server_socket_freep) VarlinkServerSocket *ss = NULL; _cleanup_free_ char *address = NULL; - const char *v = ASSERT_PTR(value); - int r, fd = -EBADF; - char *buf; - size_t n; + _cleanup_close_ int fd = -EBADF; + const char *v; + int r; + + /* This function expects a serialization line with "varlink-server(-name)-" prefix stripped! */ assert(s); + assert(value); assert(fds); - n = strcspn(v, " "); - address = strndup(v, n); - if (!address) - return log_oom_debug(); - - if (v[n] != ' ') - return varlink_server_log_errno(s, SYNTHETIC_ERRNO(EINVAL), - "Failed to deserialize sd_varlink_server_socket: %s", value); - v = startswith(v + n + 1, "varlink-server-socket-fd="); + v = startswith(value, "socket-address="); if (!v) - return varlink_server_log_errno(s, SYNTHETIC_ERRNO(EINVAL), - "Failed to deserialize VarlinkServerSocket fd: %s", value); + return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), + "Invalid varlink server serialization entry: %s", value); - n = strcspn(v, " "); - buf = strndupa_safe(v, n); - - fd = parse_fd(buf); - if (fd < 0) - return varlink_server_log_errno(s, fd, "Unable to parse VarlinkServerSocket varlink-server-socket-fd=%s: %m", buf); - if (!fdset_contains(fds, fd)) + r = extract_first_word(&v, &address, " ", /* flags = */ 0); + if (r <= 0) + return varlink_server_log_errno(s, r < 0 ? r : SYNTHETIC_ERRNO(ENODATA), + "Failed to extract socket address from varlink serialization: %s", value); + if (v) + v = startswith(v, "varlink-server-socket-fd="); + if (!v) return varlink_server_log_errno(s, SYNTHETIC_ERRNO(EBADF), - "VarlinkServerSocket varlink-server-socket-fd= has unknown fd: %d", fd); + "Got varlink serialization without socket fd, refusing."); + fd = deserialize_fd(fds, v); + if (fd < 0) + return varlink_server_log_errno(s, fd, "Failed to deserialize varlink socket fd: %m"); + + /* NB: varlink_server_socket_free() does not close the fd! */ + _cleanup_(varlink_server_socket_freep) VarlinkServerSocket *ss = NULL; ss = new(VarlinkServerSocket, 1); if (!ss) return log_oom_debug(); @@ -80,14 +75,16 @@ int varlink_server_deserialize_one(sd_varlink_server *s, const char *value, FDSe *ss = (VarlinkServerSocket) { .server = s, .address = TAKE_PTR(address), - .fd = fdset_remove(fds, fd), + .fd = fd, }; - r = varlink_server_add_socket_event_source(s, ss, SD_EVENT_PRIORITY_NORMAL); + r = varlink_server_add_socket_event_source(s, ss); if (r < 0) return varlink_server_log_errno(s, r, "Failed to add VarlinkServerSocket event source to the event loop: %m"); LIST_PREPEND(sockets, s->sockets, TAKE_PTR(ss)); + TAKE_FD(fd); /* ownership is now transferred to varlink server */ + return 0; } diff --git a/src/shared/varlink-serialize.h b/src/shared/varlink-serialize.h index db5de52161..99bf046f04 100644 --- a/src/shared/varlink-serialize.h +++ b/src/shared/varlink-serialize.h @@ -3,7 +3,7 @@ #include "shared-forward.h" -int varlink_server_serialize(sd_varlink_server *s, FILE *f, FDSet *fds); +int varlink_server_serialize(sd_varlink_server *s, const char *name, FILE *f, FDSet *fds); int varlink_server_deserialize_one(sd_varlink_server *s, const char *value, FDSet *fds); bool varlink_server_contains_socket(sd_varlink_server *s, const char *address); diff --git a/src/sysext/sysext.c b/src/sysext/sysext.c index 5e16ace9f9..3661457d26 100644 --- a/src/sysext/sysext.c +++ b/src/sysext/sysext.c @@ -2749,6 +2749,7 @@ static int vl_method_list(sd_varlink *link, sd_json_variant *parameters, sd_varl int r; assert(link); + assert(FLAGS_SET(flags, SD_VARLINK_METHOD_MORE)); const char *class = NULL; r = sd_varlink_dispatch(link, parameters, dispatch_table, &class);