diff --git a/src/shared/meson.build b/src/shared/meson.build index 5b20155b24..0ef34d4bc8 100644 --- a/src/shared/meson.build +++ b/src/shared/meson.build @@ -176,6 +176,7 @@ shared_sources = files( 'varlink-io.systemd.Resolve.c', 'varlink-io.systemd.UserDatabase.c', 'varlink-io.systemd.oom.c', + 'varlink-io.systemd.service.c', 'varlink-io.systemd.sysext.c', 'varlink-org.varlink.service.c', 'verb-log-control.c', diff --git a/src/shared/varlink-io.systemd.service.c b/src/shared/varlink-io.systemd.service.c new file mode 100644 index 0000000000..675f949929 --- /dev/null +++ b/src/shared/varlink-io.systemd.service.c @@ -0,0 +1,70 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include + +#include "varlink-io.systemd.service.h" + +static VARLINK_DEFINE_METHOD(Ping); + +static VARLINK_DEFINE_METHOD(Reload); + +static VARLINK_DEFINE_METHOD( + SetLogLevel, + VARLINK_DEFINE_INPUT(level, VARLINK_INT, 0)); + +VARLINK_DEFINE_INTERFACE( + io_systemd_service, + "io.systemd.service", + &vl_method_Ping, + &vl_method_Reload, + &vl_method_SetLogLevel); + +int varlink_method_ping(Varlink *link, JsonVariant *parameters, VarlinkMethodFlags flags, void *userdata) { + assert(link); + + if (json_variant_elements(parameters) > 0) + return varlink_error_invalid_parameter(link, parameters); + + log_debug("Received io.systemd.service.Ping"); + + return varlink_reply(link, NULL); +} + +int varlink_method_set_log_level(Varlink *link, JsonVariant *parameters, VarlinkMethodFlags flags, void *userdata) { + static const JsonDispatch dispatch_table[] = { + {"level", JSON_VARIANT_INTEGER, json_dispatch_int64, 0, JSON_MANDATORY}, + {} + }; + + int64_t level; + uid_t uid; + int r; + + assert(link); + assert(parameters); + + /* NOTE: The method does have 1 parameter, but we must compare to 2 here, because + * json_variant_elements() breaks abstraction and exposes internal structure of JsonObject. */ + if (json_variant_elements(parameters) != 2) + return varlink_error_invalid_parameter(link, parameters); + + r = json_dispatch(parameters, dispatch_table, NULL, 0, &level); + if (r < 0) + return r; + + if (LOG_PRI(level) != level) + return varlink_error_invalid_parameter(link, parameters); + + r = varlink_get_peer_uid(link, &uid); + if (r < 0) + return r; + + if (uid != getuid() && uid != 0) + return varlink_error(link, VARLINK_ERROR_PERMISSION_DENIED, parameters); + + log_debug("Received io.systemd.service.SetLogLevel(%" PRIi64 ")", level); + + log_set_max_level(level); + + return varlink_reply(link, NULL); +} diff --git a/src/shared/varlink-io.systemd.service.h b/src/shared/varlink-io.systemd.service.h new file mode 100644 index 0000000000..bc90ff0986 --- /dev/null +++ b/src/shared/varlink-io.systemd.service.h @@ -0,0 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +#pragma once + +#include "varlink.h" +#include "varlink-idl.h" + +extern const VarlinkInterface vl_interface_io_systemd_service; + +int varlink_method_ping(Varlink *link, JsonVariant *parameters, VarlinkMethodFlags flags, void *userdata); +int varlink_method_set_log_level(Varlink *link, JsonVariant *parameters, VarlinkMethodFlags flags, void *userdata); diff --git a/src/test/test-varlink-idl.c b/src/test/test-varlink-idl.c index 670fc0515d..167e8eaff6 100644 --- a/src/test/test-varlink-idl.c +++ b/src/test/test-varlink-idl.c @@ -15,6 +15,7 @@ #include "varlink-io.systemd.Resolve.h" #include "varlink-io.systemd.UserDatabase.h" #include "varlink-io.systemd.oom.h" +#include "varlink-io.systemd.service.h" #include "varlink-io.systemd.sysext.h" #include "varlink-org.varlink.service.h" @@ -138,6 +139,8 @@ TEST(parse_format) { print_separator(); test_parse_format_one(&vl_interface_io_systemd_PCRExtend); print_separator(); + test_parse_format_one(&vl_interface_io_systemd_service); + print_separator(); test_parse_format_one(&vl_interface_io_systemd_sysext); print_separator(); test_parse_format_one(&vl_interface_xyz_test);