core: implement transient socket unit
This commit is contained in:
@@ -1036,6 +1036,121 @@ int bus_property_get_exec_command_list(
|
||||
return sd_bus_message_close_container(reply);
|
||||
}
|
||||
|
||||
int bus_exec_command_set_transient_property(
|
||||
Unit *u,
|
||||
const char *name,
|
||||
ExecCommand **exec_command,
|
||||
sd_bus_message *message,
|
||||
UnitWriteFlags flags,
|
||||
sd_bus_error *error) {
|
||||
unsigned n = 0;
|
||||
int r;
|
||||
|
||||
r = sd_bus_message_enter_container(message, 'a', "(sasb)");
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
while ((r = sd_bus_message_enter_container(message, 'r', "sasb")) > 0) {
|
||||
_cleanup_strv_free_ char **argv = NULL;
|
||||
const char *path;
|
||||
int b;
|
||||
|
||||
r = sd_bus_message_read(message, "s", &path);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (!path_is_absolute(path))
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path %s is not absolute.", path);
|
||||
|
||||
r = sd_bus_message_read_strv(message, &argv);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_bus_message_read(message, "b", &b);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_bus_message_exit_container(message);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
|
||||
ExecCommand *c;
|
||||
|
||||
c = new0(ExecCommand, 1);
|
||||
if (!c)
|
||||
return -ENOMEM;
|
||||
|
||||
c->path = strdup(path);
|
||||
if (!c->path) {
|
||||
free(c);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
c->argv = argv;
|
||||
argv = NULL;
|
||||
|
||||
c->flags = b ? EXEC_COMMAND_IGNORE_FAILURE : 0;
|
||||
|
||||
path_kill_slashes(c->path);
|
||||
exec_command_append_list(exec_command, c);
|
||||
}
|
||||
|
||||
n++;
|
||||
}
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_bus_message_exit_container(message);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
|
||||
_cleanup_free_ char *buf = NULL;
|
||||
_cleanup_fclose_ FILE *f = NULL;
|
||||
ExecCommand *c;
|
||||
size_t size = 0;
|
||||
|
||||
if (n == 0)
|
||||
*exec_command = exec_command_free_list(*exec_command);
|
||||
|
||||
f = open_memstream(&buf, &size);
|
||||
if (!f)
|
||||
return -ENOMEM;
|
||||
|
||||
(void) __fsetlocking(f, FSETLOCKING_BYCALLER);
|
||||
|
||||
fputs("ExecStart=\n", f);
|
||||
|
||||
LIST_FOREACH(command, c, *exec_command) {
|
||||
_cleanup_free_ char *a = NULL, *t = NULL;
|
||||
const char *p;
|
||||
|
||||
p = unit_escape_setting(c->path, UNIT_ESCAPE_C|UNIT_ESCAPE_SPECIFIERS, &t);
|
||||
if (!p)
|
||||
return -ENOMEM;
|
||||
|
||||
a = unit_concat_strv(c->argv, UNIT_ESCAPE_C|UNIT_ESCAPE_SPECIFIERS);
|
||||
if (!a)
|
||||
return -ENOMEM;
|
||||
|
||||
fprintf(f, "%s=%s@%s %s\n",
|
||||
name,
|
||||
c->flags & EXEC_COMMAND_IGNORE_FAILURE ? "-" : "",
|
||||
p,
|
||||
a);
|
||||
}
|
||||
|
||||
r = fflush_and_check(f);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
unit_write_setting(u, flags, name, buf);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int bus_exec_context_set_transient_property(
|
||||
Unit *u,
|
||||
ExecContext *c,
|
||||
|
||||
@@ -44,3 +44,4 @@ int bus_property_get_exec_command(sd_bus *bus, const char *path, const char *int
|
||||
int bus_property_get_exec_command_list(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *ret_error);
|
||||
|
||||
int bus_exec_context_set_transient_property(Unit *u, ExecContext *c, const char *name, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error);
|
||||
int bus_exec_command_set_transient_property(Unit *u, const char *name, ExecCommand **exec_command, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error);
|
||||
|
||||
+2
-108
@@ -239,114 +239,8 @@ static int bus_service_set_transient_property(
|
||||
|
||||
return 1;
|
||||
|
||||
} else if ((ci = service_exec_command_from_string(name)) >= 0) {
|
||||
unsigned n = 0;
|
||||
|
||||
r = sd_bus_message_enter_container(message, 'a', "(sasb)");
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
while ((r = sd_bus_message_enter_container(message, 'r', "sasb")) > 0) {
|
||||
_cleanup_strv_free_ char **argv = NULL;
|
||||
const char *path;
|
||||
int b;
|
||||
|
||||
r = sd_bus_message_read(message, "s", &path);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (!path_is_absolute(path))
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path %s is not absolute.", path);
|
||||
|
||||
r = sd_bus_message_read_strv(message, &argv);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_bus_message_read(message, "b", &b);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_bus_message_exit_container(message);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
|
||||
ExecCommand *c;
|
||||
|
||||
c = new0(ExecCommand, 1);
|
||||
if (!c)
|
||||
return -ENOMEM;
|
||||
|
||||
c->path = strdup(path);
|
||||
if (!c->path) {
|
||||
free(c);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
c->argv = argv;
|
||||
argv = NULL;
|
||||
|
||||
c->flags = b ? EXEC_COMMAND_IGNORE_FAILURE : 0;
|
||||
|
||||
path_kill_slashes(c->path);
|
||||
exec_command_append_list(&s->exec_command[ci], c);
|
||||
}
|
||||
|
||||
n++;
|
||||
}
|
||||
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_bus_message_exit_container(message);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
|
||||
_cleanup_free_ char *buf = NULL;
|
||||
_cleanup_fclose_ FILE *f = NULL;
|
||||
ExecCommand *c;
|
||||
size_t size = 0;
|
||||
|
||||
if (n == 0)
|
||||
s->exec_command[ci] = exec_command_free_list(s->exec_command[ci]);
|
||||
|
||||
f = open_memstream(&buf, &size);
|
||||
if (!f)
|
||||
return -ENOMEM;
|
||||
|
||||
(void) __fsetlocking(f, FSETLOCKING_BYCALLER);
|
||||
|
||||
fputs("ExecStart=\n", f);
|
||||
|
||||
LIST_FOREACH(command, c, s->exec_command[ci]) {
|
||||
_cleanup_free_ char *a = NULL, *t = NULL;
|
||||
const char *p;
|
||||
|
||||
p = unit_escape_setting(c->path, UNIT_ESCAPE_C|UNIT_ESCAPE_SPECIFIERS, &t);
|
||||
if (!p)
|
||||
return -ENOMEM;
|
||||
|
||||
a = unit_concat_strv(c->argv, UNIT_ESCAPE_C|UNIT_ESCAPE_SPECIFIERS);
|
||||
if (!a)
|
||||
return -ENOMEM;
|
||||
|
||||
fprintf(f, "%s=%s@%s %s\n",
|
||||
name,
|
||||
c->flags & EXEC_COMMAND_IGNORE_FAILURE ? "-" : "",
|
||||
p,
|
||||
a);
|
||||
}
|
||||
|
||||
r = fflush_and_check(f);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
unit_write_setting(UNIT(s), flags, name, buf);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
} else if ((ci = service_exec_command_from_string(name)) >= 0)
|
||||
return bus_exec_command_set_transient_property(UNIT(s), name, &s->exec_command[ci], message, flags, error);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
+485
-1
@@ -22,10 +22,17 @@
|
||||
#include "bus-util.h"
|
||||
#include "dbus-cgroup.h"
|
||||
#include "dbus-execute.h"
|
||||
#include "dbus-kill.h"
|
||||
#include "dbus-socket.h"
|
||||
#include "fd-util.h"
|
||||
#include "parse-util.h"
|
||||
#include "path-util.h"
|
||||
#include "socket.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);
|
||||
@@ -141,6 +148,7 @@ const sd_bus_vtable bus_socket_vtable[] = {
|
||||
SD_BUS_PROPERTY("MaxConnectionsPerSource", "u", bus_property_get_unsigned, offsetof(Socket, max_connections_per_source), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("MessageQueueMaxMessages", "x", bus_property_get_long, offsetof(Socket, mq_maxmsg), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("MessageQueueMessageSize", "x", bus_property_get_long, offsetof(Socket, mq_msgsize), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("TCPCongestion", "s", NULL, offsetof(Socket, tcp_congestion), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("ReusePort", "b", bus_property_get_bool, offsetof(Socket, reuse_port), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("SmackLabel", "s", NULL, offsetof(Socket, smack), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("SmackLabelIPIn", "s", NULL, offsetof(Socket, smack_ip_in), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
@@ -162,6 +170,457 @@ const sd_bus_vtable bus_socket_vtable[] = {
|
||||
SD_BUS_VTABLE_END
|
||||
};
|
||||
|
||||
static int bus_socket_set_transient_property(
|
||||
Socket *s,
|
||||
const char *name,
|
||||
sd_bus_message *message,
|
||||
UnitWriteFlags flags,
|
||||
sd_bus_error *error) {
|
||||
|
||||
SocketExecCommand ci;
|
||||
Unit *u = UNIT(s);
|
||||
int r;
|
||||
|
||||
assert(s);
|
||||
assert(name);
|
||||
assert(message);
|
||||
|
||||
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 (!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));
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
} else if (STR_IN_SET(name, "Priority", "IPTTL", "Mark")) {
|
||||
int32_t i;
|
||||
|
||||
r = sd_bus_message_read(message, "i", &i);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
} else if (streq(name, "IPTOS")) {
|
||||
_cleanup_free_ char *str = NULL;
|
||||
int32_t i;
|
||||
|
||||
r = sd_bus_message_read(message, "i", &i);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
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 (!UNIT_WRITE_FLAGS_NOOP(flags)) {
|
||||
s->ip_tos = i;
|
||||
|
||||
unit_write_settingf(u, flags, name, "%s=%s", name, str);
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
} else if (streq(name, "SocketProtocol")) {
|
||||
int32_t i;
|
||||
|
||||
r = sd_bus_message_read(message, "i", &i);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (!IN_SET(i, IPPROTO_UDPLITE, IPPROTO_SCTP))
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid %s: %i", name, i);
|
||||
|
||||
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
|
||||
s->socket_protocol = i;
|
||||
unit_write_settingf(u, flags, name, "%s=%s", name, i == IPPROTO_UDPLITE ? "udplite" : "sctp");
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
} else if (STR_IN_SET(name, "Backlog", "MaxConnections", "MaxConnectionsPerSource", "KeepAliveProbes", "TriggerLimitBurst")) {
|
||||
uint32_t n;
|
||||
|
||||
r = sd_bus_message_read(message, "u", &n);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
} else if (STR_IN_SET(name, "SocketMode", "DirectoryMode")) {
|
||||
mode_t m;
|
||||
|
||||
r = sd_bus_message_read(message, "u", &m);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
|
||||
if (streq(name, "SocketMode"))
|
||||
s->socket_mode = m;
|
||||
else /* "DirectoryMode" */
|
||||
s->directory_mode = m;
|
||||
|
||||
unit_write_settingf(u, flags, name, "%s=%040o", name, m);
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
} else if (STR_IN_SET(name, "MessageQueueMaxMessages", "MessageQueueMessageSize")) {
|
||||
int64_t n;
|
||||
|
||||
r = sd_bus_message_read(message, "x", &n);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
|
||||
if (streq(name, "MessageQueueMaxMessages"))
|
||||
s->mq_maxmsg = (long) n;
|
||||
else /* "MessageQueueMessageSize" */
|
||||
s->mq_msgsize = (long) n;
|
||||
|
||||
unit_write_settingf(u, flags, name, "%s=%" PRIi64, name, n);
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
} else if (STR_IN_SET(name, "TimeoutUSec", "KeepAliveTimeUSec", "KeepAliveIntervalUSec", "DeferAcceptUSec", "TriggerLimitIntervalUSec")) {
|
||||
usec_t t;
|
||||
|
||||
r = sd_bus_message_read(message, "t", &t);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
} else if (STR_IN_SET(name, "ReceiveBuffer", "SendBuffer", "PipeSize")) {
|
||||
uint64_t t;
|
||||
|
||||
r = sd_bus_message_read(message, "t", &t);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
} else if (STR_IN_SET(name, "SmackLabel", "SmackLabelIPIn", "SmackLabelIPOut", "TCPCongestion")) {
|
||||
const char *n;
|
||||
|
||||
r = sd_bus_message_read(message, "s", &n);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
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")) {
|
||||
_cleanup_strv_free_ char **l = NULL;
|
||||
char **p;
|
||||
|
||||
r = sd_bus_message_read_strv(message, &l);
|
||||
if (r < 0)
|
||||
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);
|
||||
}
|
||||
|
||||
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
|
||||
if (strv_isempty(l)) {
|
||||
s->symlinks = strv_free(s->symlinks);
|
||||
unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "%s=", name);
|
||||
} else {
|
||||
_cleanup_free_ char *joined = NULL;
|
||||
|
||||
r = strv_extend_strv(&s->symlinks, l, true);
|
||||
if (r < 0)
|
||||
return -ENOMEM;
|
||||
|
||||
joined = strv_join(l, " ");
|
||||
if (!joined)
|
||||
return -ENOMEM;
|
||||
|
||||
unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "%s=%s", name, joined);
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
} else if (streq(name, "Listen")) {
|
||||
const char *t, *a;
|
||||
bool empty = true;
|
||||
|
||||
r = sd_bus_message_enter_container(message, 'a', "(ss)");
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
while ((r = sd_bus_message_read(message, "(ss)", &t, &a)) > 0) {
|
||||
_cleanup_free_ SocketPort *p = NULL;
|
||||
|
||||
p = new0(SocketPort, 1);
|
||||
if (!p)
|
||||
return log_oom();
|
||||
|
||||
p->type = socket_type_from_string(t);
|
||||
if (p->type < 0)
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown Socket type: %s", t);
|
||||
|
||||
if (p->type != SOCKET_SOCKET) {
|
||||
p->path = strdup(a);
|
||||
path_kill_slashes(p->path);
|
||||
|
||||
} else if (streq(t, "Netlink")) {
|
||||
r = socket_address_parse_netlink(&p->address, a);
|
||||
if (r < 0)
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid netlink address: %s", a);
|
||||
|
||||
} else {
|
||||
r = socket_address_parse(&p->address, a);
|
||||
if (r < 0)
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid address: %s", a);
|
||||
|
||||
p->address.type = socket_address_type_from_string(t);
|
||||
if (p->address.type < 0)
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid address type: %s", t);
|
||||
|
||||
if (socket_address_family(&p->address) != AF_LOCAL && p->address.type == SOCK_SEQPACKET)
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Address family not supported: %s", a);
|
||||
}
|
||||
|
||||
p->fd = -1;
|
||||
p->auxiliary_fds = NULL;
|
||||
p->n_auxiliary_fds = 0;
|
||||
p->socket = s;
|
||||
|
||||
empty = false;
|
||||
|
||||
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
|
||||
SocketPort *tail;
|
||||
|
||||
LIST_FIND_TAIL(port, s->ports, tail);
|
||||
LIST_INSERT_AFTER(port, s->ports, tail, p);
|
||||
|
||||
p = NULL;
|
||||
|
||||
unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "Listen%s=%s", t, a);
|
||||
}
|
||||
}
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_bus_message_exit_container(message);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (!UNIT_WRITE_FLAGS_NOOP(flags) && empty) {
|
||||
socket_free_ports(s);
|
||||
unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "ListenStream=");
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
} else if ((ci = socket_exec_command_from_string(name)) >= 0)
|
||||
return bus_exec_command_set_transient_property(UNIT(s), name, &s->exec_command[ci], message, flags, error);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bus_socket_set_property(
|
||||
Unit *u,
|
||||
const char *name,
|
||||
@@ -170,12 +629,37 @@ int bus_socket_set_property(
|
||||
sd_bus_error *error) {
|
||||
|
||||
Socket *s = SOCKET(u);
|
||||
int r;
|
||||
|
||||
assert(s);
|
||||
assert(name);
|
||||
assert(message);
|
||||
|
||||
return bus_cgroup_set_property(u, &s->cgroup_context, name, message, flags, error);
|
||||
assert(s);
|
||||
assert(name);
|
||||
assert(message);
|
||||
|
||||
r = bus_cgroup_set_property(u, &s->cgroup_context, name, message, flags, error);
|
||||
if (r != 0)
|
||||
return r;
|
||||
|
||||
if (u->transient && u->load_state == UNIT_STUB) {
|
||||
/* This is a transient unit, let's load a little more */
|
||||
|
||||
r = bus_socket_set_transient_property(s, name, message, flags, error);
|
||||
if (r != 0)
|
||||
return r;
|
||||
|
||||
r = bus_exec_context_set_transient_property(u, &s->exec_context, name, message, flags, error);
|
||||
if (r != 0)
|
||||
return r;
|
||||
|
||||
r = bus_kill_context_set_transient_property(u, &s->kill_context, name, message, flags, error);
|
||||
if (r != 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bus_socket_commit_properties(Unit *u) {
|
||||
|
||||
@@ -3281,6 +3281,8 @@ const UnitVTable socket_vtable = {
|
||||
"Install\0",
|
||||
.private_section = "Socket",
|
||||
|
||||
.can_transient = true,
|
||||
|
||||
.init = socket_init,
|
||||
.done = socket_done,
|
||||
.load = socket_load,
|
||||
|
||||
Reference in New Issue
Block a user