#include "dbus-execute.h"
#include "dbus-kill.h"
#include "dbus-socket.h"
+#include "dbus-util.h"
#include "fd-util.h"
#include "parse-util.h"
#include "path-util.h"
#include "socket-util.h"
#include "string-util.h"
#include "unit.h"
-#include "user-util.h"
-#include "utf8.h"
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_result, socket_result, SocketResult);
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_bind_ipv6_only, socket_address_bind_ipv6_only, SocketAddressBindIPv6Only);
SD_BUS_VTABLE_END
};
+static inline bool check_size_t_truncation(uint64_t t) {
+ return (size_t) t == t;
+}
+
+static inline const char* socket_protocol_to_name_supported(int32_t i) {
+ if (!IN_SET(i, IPPROTO_UDPLITE, IPPROTO_SCTP))
+ return NULL;
+
+ return socket_protocol_to_name(i);
+}
+
+static BUS_DEFINE_SET_TRANSIENT(int, "i", int32_t, int, "%" PRIi32);
+static BUS_DEFINE_SET_TRANSIENT(message_queue, "x", int64_t, long, "%" PRIi64);
+static BUS_DEFINE_SET_TRANSIENT_IS_VALID(size_t_check_truncation, "t", uint64_t, size_t, "%" PRIu64, check_size_t_truncation);
+static BUS_DEFINE_SET_TRANSIENT_PARSE(bind_ipv6_only, SocketAddressBindIPv6Only, parse_socket_address_bind_ipv6_only_or_bool);
+static BUS_DEFINE_SET_TRANSIENT_STRING_WITH_CHECK(fdname, fdname_is_valid);
+static BUS_DEFINE_SET_TRANSIENT_STRING_WITH_CHECK(ifname, ifname_valid);
+static BUS_DEFINE_SET_TRANSIENT_TO_STRING_ALLOC(ip_tos, "i", int32_t, int, "%" PRIi32, ip_tos_to_string_alloc);
+static BUS_DEFINE_SET_TRANSIENT_TO_STRING(socket_protocol, "i", int32_t, int, "%" PRIi32, socket_protocol_to_name_supported);
+
static int bus_socket_set_transient_property(
Socket *s,
const char *name,
flags |= UNIT_PRIVATE;
- if (STR_IN_SET(name,
- "Accept", "Writable", "KeepAlive", "NoDelay", "FreeBind", "Transparent", "Broadcast",
- "PassCredentials", "PassSecurity", "ReusePort", "RemoveOnStop", "SELinuxContextFromNet")) {
- int b;
-
- r = sd_bus_message_read(message, "b", &b);
- if (r < 0)
- return r;
+ if (streq(name, "Accept"))
+ return bus_set_transient_bool(u, name, &s->accept, message, flags, error);
- if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
- if (streq(name, "Accept"))
- s->accept = b;
- else if (streq(name, "Writable"))
- s->writable = b;
- else if (streq(name, "KeepAlive"))
- s->keep_alive = b;
- else if (streq(name, "NoDelay"))
- s->no_delay = b;
- else if (streq(name, "FreeBind"))
- s->free_bind = b;
- else if (streq(name, "Transparent"))
- s->transparent = b;
- else if (streq(name, "Broadcast"))
- s->broadcast = b;
- else if (streq(name, "PassCredentials"))
- s->pass_cred = b;
- else if (streq(name, "PassSecurity"))
- s->pass_sec = b;
- else if (streq(name, "ReusePort"))
- s->reuse_port = b;
- else if (streq(name, "RemoveOnStop"))
- s->remove_on_stop = b;
- else /* "SELinuxContextFromNet" */
- s->selinux_context_from_net = b;
-
- unit_write_settingf(u, flags, name, "%s=%s", name, yes_no(b));
- }
+ if (streq(name, "Writable"))
+ return bus_set_transient_bool(u, name, &s->writable, message, flags, error);
- return 1;
+ if (streq(name, "KeepAlive"))
+ return bus_set_transient_bool(u, name, &s->keep_alive, message, flags, error);
- } else if (STR_IN_SET(name, "Priority", "IPTTL", "Mark")) {
- int32_t i;
+ if (streq(name, "NoDelay"))
+ return bus_set_transient_bool(u, name, &s->no_delay, message, flags, error);
- r = sd_bus_message_read(message, "i", &i);
- if (r < 0)
- return r;
+ if (streq(name, "FreeBind"))
+ return bus_set_transient_bool(u, name, &s->free_bind, message, flags, error);
- if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
- if (streq(name, "Priority"))
- s->priority = i;
- else if (streq(name, "IPTTL"))
- s->ip_ttl = i;
- else /* "Mark" */
- s->mark = i;
-
- unit_write_settingf(u, flags, name, "%s=%i", name, i);
- }
+ if (streq(name, "Transparent"))
+ return bus_set_transient_bool(u, name, &s->transparent, message, flags, error);
- return 1;
+ if (streq(name, "Broadcast"))
+ return bus_set_transient_bool(u, name, &s->broadcast, message, flags, error);
- } else if (streq(name, "IPTOS")) {
- _cleanup_free_ char *str = NULL;
- int32_t i;
+ if (streq(name, "PassCredentials"))
+ return bus_set_transient_bool(u, name, &s->pass_cred, message, flags, error);
- r = sd_bus_message_read(message, "i", &i);
- if (r < 0)
- return r;
+ if (streq(name, "PassSecurity"))
+ return bus_set_transient_bool(u, name, &s->pass_sec, message, flags, error);
- r = ip_tos_to_string_alloc(i, &str);
- if (r < 0)
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid %s: %i", name, i);
+ if (streq(name, "ReusePort"))
+ return bus_set_transient_bool(u, name, &s->reuse_port, message, flags, error);
- if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
- s->ip_tos = i;
+ if (streq(name, "RemoveOnStop"))
+ return bus_set_transient_bool(u, name, &s->remove_on_stop, message, flags, error);
- unit_write_settingf(u, flags, name, "%s=%s", name, str);
- }
+ if (streq(name, "SELinuxContextFromNet"))
+ return bus_set_transient_bool(u, name, &s->selinux_context_from_net, message, flags, error);
- return 1;
+ if (streq(name, "Priority"))
+ return bus_set_transient_int(u, name, &s->priority, message, flags, error);
- } else if (streq(name, "SocketProtocol")) {
- const char *p;
- int32_t i;
+ if (streq(name, "IPTTL"))
+ return bus_set_transient_int(u, name, &s->ip_ttl, message, flags, error);
- r = sd_bus_message_read(message, "i", &i);
- if (r < 0)
- return r;
+ if (streq(name, "Mark"))
+ return bus_set_transient_int(u, name, &s->mark, message, flags, error);
- p = socket_protocol_to_name(i);
- if (!p)
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid %s: %i", name, i);
+ if (streq(name, "Backlog"))
+ return bus_set_transient_unsigned(u, name, &s->backlog, message, flags, error);
- if (!IN_SET(i, IPPROTO_UDPLITE, IPPROTO_SCTP))
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unsupported socket protocol: %s", p);
+ if (streq(name, "MaxConnections"))
+ return bus_set_transient_unsigned(u, name, &s->max_connections, message, flags, error);
- if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
- s->socket_protocol = i;
- unit_write_settingf(u, flags, name, "%s=%s", name, p);
- }
+ if (streq(name, "MaxConnectionsPerSource"))
+ return bus_set_transient_unsigned(u, name, &s->max_connections_per_source, message, flags, error);
- return 1;
+ if (streq(name, "KeepAliveProbes"))
+ return bus_set_transient_unsigned(u, name, &s->keep_alive_cnt, message, flags, error);
- } else if (STR_IN_SET(name, "Backlog", "MaxConnections", "MaxConnectionsPerSource", "KeepAliveProbes", "TriggerLimitBurst")) {
- uint32_t n;
+ if (streq(name, "TriggerLimitBurst"))
+ return bus_set_transient_unsigned(u, name, &s->trigger_limit.burst, message, flags, error);
- r = sd_bus_message_read(message, "u", &n);
- if (r < 0)
- return r;
+ if (streq(name, "SocketMode"))
+ return bus_set_transient_mode_t(u, name, &s->socket_mode, message, flags, error);
- if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
- if (streq(name, "Backlog"))
- s->backlog = n;
- else if (streq(name, "MaxConnections"))
- s->max_connections = n;
- else if (streq(name, "MaxConnectionsPerSource"))
- s->max_connections_per_source = n;
- else if (streq(name, "KeepAliveProbes"))
- s->keep_alive_cnt = n;
- else /* "TriggerLimitBurst" */
- s->trigger_limit.burst = n;
-
- unit_write_settingf(u, flags, name, "%s=%u", name, n);
- }
+ if (streq(name, "DirectoryMode"))
+ return bus_set_transient_mode_t(u, name, &s->directory_mode, message, flags, error);
- return 1;
+ if (streq(name, "MessageQueueMaxMessages"))
+ return bus_set_transient_message_queue(u, name, &s->mq_maxmsg, message, flags, error);
- } else if (STR_IN_SET(name, "SocketMode", "DirectoryMode")) {
- mode_t m;
+ if (streq(name, "MessageQueueMessageSize"))
+ return bus_set_transient_message_queue(u, name, &s->mq_msgsize, message, flags, error);
- r = sd_bus_message_read(message, "u", &m);
- if (r < 0)
- return r;
+ if (streq(name, "TimeoutUSec"))
+ return bus_set_transient_usec_fix_0(u, name, &s->timeout_usec, message, flags, error);
- if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
- if (streq(name, "SocketMode"))
- s->socket_mode = m;
- else /* "DirectoryMode" */
- s->directory_mode = m;
+ if (streq(name, "KeepAliveTimeUSec"))
+ return bus_set_transient_usec(u, name, &s->keep_alive_time, message, flags, error);
- unit_write_settingf(u, flags, name, "%s=%040o", name, m);
- }
+ if (streq(name, "KeepAliveIntervalUSec"))
+ return bus_set_transient_usec(u, name, &s->keep_alive_interval, message, flags, error);
- return 1;
+ if (streq(name, "DeferAcceptUSec"))
+ return bus_set_transient_usec(u, name, &s->defer_accept, message, flags, error);
- } else if (STR_IN_SET(name, "MessageQueueMaxMessages", "MessageQueueMessageSize")) {
- int64_t n;
+ if (streq(name, "TriggerLimitIntervalUSec"))
+ return bus_set_transient_usec(u, name, &s->trigger_limit.interval, message, flags, error);
- r = sd_bus_message_read(message, "x", &n);
- if (r < 0)
- return r;
+ if (streq(name, "SmackLabel"))
+ return bus_set_transient_string(u, name, &s->smack, message, flags, error);
- if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
- if (streq(name, "MessageQueueMaxMessages"))
- s->mq_maxmsg = (long) n;
- else /* "MessageQueueMessageSize" */
- s->mq_msgsize = (long) n;
+ if (streq(name, "SmackLabelIPin"))
+ return bus_set_transient_string(u, name, &s->smack_ip_in, message, flags, error);
- unit_write_settingf(u, flags, name, "%s=%" PRIi64, name, n);
- }
+ if (streq(name, "SmackLabelIPOut"))
+ return bus_set_transient_string(u, name, &s->smack_ip_out, message, flags, error);
- return 1;
+ if (streq(name, "TCPCongestion"))
+ return bus_set_transient_string(u, name, &s->tcp_congestion, message, flags, error);
- } else if (STR_IN_SET(name, "TimeoutUSec", "KeepAliveTimeUSec", "KeepAliveIntervalUSec", "DeferAcceptUSec", "TriggerLimitIntervalUSec")) {
- usec_t t;
+ if (streq(name, "FileDescriptorName"))
+ return bus_set_transient_fdname(u, name, &s->fdname, message, flags, error);
- r = sd_bus_message_read(message, "t", &t);
- if (r < 0)
- return r;
+ if (streq(name, "SocketUser"))
+ return bus_set_transient_user(u, name, &s->user, message, flags, error);
- if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
- if (streq(name, "TimeoutUSec"))
- s->timeout_usec = t ?: USEC_INFINITY;
- else if (streq(name, "KeepAliveTimeUSec"))
- s->keep_alive_time = t;
- else if (streq(name, "KeepAliveIntervalUSec"))
- s->keep_alive_interval = t;
- else if (streq(name, "DeferAcceptUSec"))
- s->defer_accept = t;
- else /* "TriggerLimitIntervalUSec" */
- s->trigger_limit.interval = t;
-
- unit_write_settingf(u, flags, name, "%s=" USEC_FMT, name, t);
- }
+ if (streq(name, "SocketGroup"))
+ return bus_set_transient_user(u, name, &s->group, message, flags, error);
- return 1;
+ if (streq(name, "BindIPv6Only"))
+ return bus_set_transient_bind_ipv6_only(u, name, &s->bind_ipv6_only, message, flags, error);
- } else if (STR_IN_SET(name, "ReceiveBuffer", "SendBuffer", "PipeSize")) {
- uint64_t t;
+ if (streq(name, "ReceiveBuffer"))
+ return bus_set_transient_size_t_check_truncation(u, name, &s->receive_buffer, message, flags, error);
- r = sd_bus_message_read(message, "t", &t);
- if (r < 0)
- return r;
+ if (streq(name, "SendBuffer"))
+ return bus_set_transient_size_t_check_truncation(u, name, &s->send_buffer, message, flags, error);
- if ((uint64_t) (size_t) t != t)
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid %s: %" PRIu64, name, t);
+ if (streq(name, "PipeSize"))
+ return bus_set_transient_size_t_check_truncation(u, name, &s->pipe_size, message, flags, error);
- if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
- if (streq(name, "ReceiveBuffer"))
- s->receive_buffer = t;
- else if (streq(name, "SendBuffer"))
- s->send_buffer = t;
- else /* "PipeSize" */
- s->pipe_size = t;
-
- unit_write_settingf(u, flags, name, "%s=%" PRIu64, name, t);
- }
+ if (streq(name, "BindToDevice"))
+ return bus_set_transient_ifname(u, name, &s->bind_to_device, message, flags, error);
- return 1;
+ if (streq(name, "IPTOS"))
+ return bus_set_transient_ip_tos(u, name, &s->ip_tos, message, flags, error);
- } else if (STR_IN_SET(name, "SmackLabel", "SmackLabelIPIn", "SmackLabelIPOut", "TCPCongestion")) {
- const char *n;
+ if (streq(name, "SocketProtocol"))
+ return bus_set_transient_socket_protocol(u, name, &s->socket_protocol, message, flags, error);
- r = sd_bus_message_read(message, "s", &n);
- if (r < 0)
- return r;
+ if ((ci = socket_exec_command_from_string(name)) >= 0)
+ return bus_set_transient_exec_command(u, name, &s->exec_command[ci], message, flags, error);
- if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
-
- if (streq(name, "SmackLabel"))
- r = free_and_strdup(&s->smack, empty_to_null(n));
- else if (streq(name, "SmackLabelIPin"))
- r = free_and_strdup(&s->smack_ip_in, empty_to_null(n));
- else if (streq(name, "SmackLabelIPOut"))
- r = free_and_strdup(&s->smack_ip_out, empty_to_null(n));
- else /* "TCPCongestion" */
- r = free_and_strdup(&s->tcp_congestion, empty_to_null(n));
- if (r < 0)
- return r;
-
- unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "%s=%s", name, strempty(n));
- }
-
- return 1;
-
- } else if (streq(name, "BindToDevice")) {
- const char *n;
-
- r = sd_bus_message_read(message, "s", &n);
- if (r < 0)
- return r;
-
- if (n[0] && !streq(n, "*")) {
- if (!ifname_valid(n))
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid interface name for %s: %s", name, n);
- } else
- n = NULL;
-
- if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
-
- r = free_and_strdup(&s->bind_to_device, empty_to_null(n));
- if (r < 0)
- return r;
-
- unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "%s=%s", name, strempty(n));
- }
-
- return 1;
-
- } else if (streq(name, "BindIPv6Only")) {
- SocketAddressBindIPv6Only b;
- const char *n;
-
- r = sd_bus_message_read(message, "s", &n);
- if (r < 0)
- return r;
-
- b = socket_address_bind_ipv6_only_from_string(n);
- if (b < 0) {
- r = parse_boolean(n);
- if (r < 0)
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid %s: %s", name, n);
-
- b = r ? SOCKET_ADDRESS_IPV6_ONLY : SOCKET_ADDRESS_BOTH;
- }
-
- if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
- s->bind_ipv6_only = b;
- unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "%s=%s", name, n);
- }
-
- return 1;
-
- } else if (streq(name, "FileDescriptorName")) {
- const char *n;
-
- r = sd_bus_message_read(message, "s", &n);
- if (r < 0)
- return r;
-
- if (!isempty(n) && !fdname_is_valid(n))
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid %s: %s", name, n);
-
- if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
- r = free_and_strdup(&s->fdname, empty_to_null(n));
- if (r < 0)
- return r;
-
- unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "%s=%s", name, strempty(n));
- }
-
- return 1;
-
- } else if (STR_IN_SET(name, "SocketUser", "SocketGroup")) {
- const char *n;
-
- r = sd_bus_message_read(message, "s", &n);
- if (r < 0)
- return r;
-
- if (!isempty(n) && !valid_user_group_name_or_id(n))
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid %s: %s", name, n);
-
- if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
-
- if (streq(name, "SocketUser"))
- r = free_and_strdup(&s->user, empty_to_null(n));
- else /* "SocketGroup" */
- r = free_and_strdup(&s->user, empty_to_null(n));
- if (r < 0)
- return r;
-
- unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "%s=%s", name, strempty(n));
- }
-
- return 1;
-
- } else if (streq(name, "Symlinks")) {
+ if (streq(name, "Symlinks")) {
_cleanup_strv_free_ char **l = NULL;
char **p;
return r;
STRV_FOREACH(p, l) {
- if (!utf8_is_valid(*p))
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "String is not UTF-8 clean, ignoring assignment: %s", *p);
-
if (!path_is_absolute(*p))
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Symlink path is not absolute: %s", *p);
}
}
return 1;
-
- } else if ((ci = socket_exec_command_from_string(name)) >= 0)
- return bus_set_transient_exec_command(UNIT(s), name, &s->exec_command[ci], message, flags, error);
+ }
return 0;
}