summaryrefslogtreecommitdiffstats
path: root/src/core/socket.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/socket.c')
-rw-r--r--src/core/socket.c382
1 files changed, 192 insertions, 190 deletions
diff --git a/src/core/socket.c b/src/core/socket.c
index 9adae16..41147d4 100644
--- a/src/core/socket.c
+++ b/src/core/socket.c
@@ -53,29 +53,44 @@ struct SocketPeer {
Socket *socket;
union sockaddr_union peer;
socklen_t peer_salen;
+ struct ucred peer_cred;
};
static const UnitActiveState state_translation_table[_SOCKET_STATE_MAX] = {
- [SOCKET_DEAD] = UNIT_INACTIVE,
- [SOCKET_START_PRE] = UNIT_ACTIVATING,
- [SOCKET_START_CHOWN] = UNIT_ACTIVATING,
- [SOCKET_START_POST] = UNIT_ACTIVATING,
- [SOCKET_LISTENING] = UNIT_ACTIVE,
- [SOCKET_RUNNING] = UNIT_ACTIVE,
- [SOCKET_STOP_PRE] = UNIT_DEACTIVATING,
+ [SOCKET_DEAD] = UNIT_INACTIVE,
+ [SOCKET_START_PRE] = UNIT_ACTIVATING,
+ [SOCKET_START_CHOWN] = UNIT_ACTIVATING,
+ [SOCKET_START_POST] = UNIT_ACTIVATING,
+ [SOCKET_LISTENING] = UNIT_ACTIVE,
+ [SOCKET_RUNNING] = UNIT_ACTIVE,
+ [SOCKET_STOP_PRE] = UNIT_DEACTIVATING,
[SOCKET_STOP_PRE_SIGTERM] = UNIT_DEACTIVATING,
[SOCKET_STOP_PRE_SIGKILL] = UNIT_DEACTIVATING,
- [SOCKET_STOP_POST] = UNIT_DEACTIVATING,
- [SOCKET_FINAL_SIGTERM] = UNIT_DEACTIVATING,
- [SOCKET_FINAL_SIGKILL] = UNIT_DEACTIVATING,
- [SOCKET_FAILED] = UNIT_FAILED,
- [SOCKET_CLEANING] = UNIT_MAINTENANCE,
+ [SOCKET_STOP_POST] = UNIT_DEACTIVATING,
+ [SOCKET_FINAL_SIGTERM] = UNIT_DEACTIVATING,
+ [SOCKET_FINAL_SIGKILL] = UNIT_DEACTIVATING,
+ [SOCKET_FAILED] = UNIT_FAILED,
+ [SOCKET_CLEANING] = UNIT_MAINTENANCE,
};
static int socket_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata);
static int socket_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata);
static void flush_ports(Socket *s);
+static bool SOCKET_STATE_WITH_PROCESS(SocketState state) {
+ return IN_SET(state,
+ SOCKET_START_PRE,
+ SOCKET_START_CHOWN,
+ SOCKET_START_POST,
+ SOCKET_STOP_PRE,
+ SOCKET_STOP_PRE_SIGTERM,
+ SOCKET_STOP_PRE_SIGKILL,
+ SOCKET_STOP_POST,
+ SOCKET_FINAL_SIGTERM,
+ SOCKET_FINAL_SIGKILL,
+ SOCKET_CLEANING);
+}
+
static void socket_init(Unit *u) {
Socket *s = SOCKET(u);
@@ -108,12 +123,7 @@ static void socket_init(Unit *u) {
static void socket_unwatch_control_pid(Socket *s) {
assert(s);
-
- if (!pidref_is_set(&s->control_pid))
- return;
-
- unit_unwatch_pidref(UNIT(s), &s->control_pid);
- pidref_done(&s->control_pid);
+ unit_unwatch_pidref_done(UNIT(s), &s->control_pid);
}
static void socket_cleanup_fd_list(SocketPort *p) {
@@ -144,11 +154,9 @@ void socket_free_ports(Socket *s) {
}
static void socket_done(Unit *u) {
- Socket *s = SOCKET(u);
+ Socket *s = ASSERT_PTR(SOCKET(u));
SocketPeer *p;
- assert(s);
-
socket_free_ports(s);
while ((p = set_steal_first(s->peers_by_address)))
@@ -157,6 +165,7 @@ static void socket_done(Unit *u) {
s->peers_by_address = set_free(s->peers_by_address);
s->exec_runtime = exec_runtime_free(s->exec_runtime);
+
exec_command_free_array(s->exec_command, _SOCKET_EXEC_COMMAND_MAX);
s->control_command = NULL;
@@ -221,7 +230,7 @@ static int socket_add_mount_dependencies(Socket *s) {
if (!path)
continue;
- r = unit_require_mounts_for(UNIT(s), path, UNIT_DEPENDENCY_FILE);
+ r = unit_add_mounts_for(UNIT(s), path, UNIT_DEPENDENCY_FILE, UNIT_MOUNT_REQUIRES);
if (r < 0)
return r;
}
@@ -243,6 +252,7 @@ static int socket_add_device_dependencies(Socket *s) {
static int socket_add_default_dependencies(Socket *s) {
int r;
+
assert(s);
if (!UNIT(s)->default_dependencies)
@@ -263,6 +273,7 @@ static int socket_add_default_dependencies(Socket *s) {
static bool socket_has_exec(Socket *s) {
unsigned i;
+
assert(s);
for (i = 0; i < _SOCKET_EXEC_COMMAND_MAX; i++)
@@ -273,11 +284,9 @@ static bool socket_has_exec(Socket *s) {
}
static int socket_add_extras(Socket *s) {
- Unit *u = UNIT(s);
+ Unit *u = UNIT(ASSERT_PTR(s));
int r;
- assert(s);
-
/* Pick defaults for the trigger limit, if nothing was explicitly configured. We pick a relatively high limit
* in Accept=yes mode, and a lower limit for Accept=no. Reason: in Accept=yes mode we are invoking accept()
* ourselves before the trigger limit can hit, thus incoming connections are taken off the socket queue quickly
@@ -406,11 +415,13 @@ static void peer_address_hash_func(const SocketPeer *s, struct siphash *state) {
assert(s);
if (s->peer.sa.sa_family == AF_INET)
- siphash24_compress(&s->peer.in.sin_addr, sizeof(s->peer.in.sin_addr), state);
+ siphash24_compress_typesafe(s->peer.in.sin_addr, state);
else if (s->peer.sa.sa_family == AF_INET6)
- siphash24_compress(&s->peer.in6.sin6_addr, sizeof(s->peer.in6.sin6_addr), state);
+ siphash24_compress_typesafe(s->peer.in6.sin6_addr, state);
else if (s->peer.sa.sa_family == AF_VSOCK)
- siphash24_compress(&s->peer.vm.svm_cid, sizeof(s->peer.vm.svm_cid), state);
+ siphash24_compress_typesafe(s->peer.vm.svm_cid, state);
+ else if (s->peer.sa.sa_family == AF_UNIX)
+ siphash24_compress_typesafe(s->peer_cred.uid, state);
else
assert_not_reached();
}
@@ -429,6 +440,8 @@ static int peer_address_compare_func(const SocketPeer *x, const SocketPeer *y) {
return memcmp(&x->peer.in6.sin6_addr, &y->peer.in6.sin6_addr, sizeof(x->peer.in6.sin6_addr));
case AF_VSOCK:
return CMP(x->peer.vm.svm_cid, y->peer.vm.svm_cid);
+ case AF_UNIX:
+ return CMP(x->peer_cred.uid, y->peer_cred.uid);
}
assert_not_reached();
}
@@ -436,10 +449,9 @@ static int peer_address_compare_func(const SocketPeer *x, const SocketPeer *y) {
DEFINE_PRIVATE_HASH_OPS(peer_address_hash_ops, SocketPeer, peer_address_hash_func, peer_address_compare_func);
static int socket_load(Unit *u) {
- Socket *s = SOCKET(u);
+ Socket *s = ASSERT_PTR(SOCKET(u));
int r;
- assert(u);
assert(u->load_state == UNIT_STUB);
r = unit_load_fragment_and_dropin(u, true);
@@ -457,16 +469,22 @@ static int socket_load(Unit *u) {
return socket_verify(s);
}
-static SocketPeer *socket_peer_new(void) {
+static SocketPeer *socket_peer_dup(const SocketPeer *q) {
SocketPeer *p;
+ assert(q);
+
p = new(SocketPeer, 1);
if (!p)
return NULL;
*p = (SocketPeer) {
.n_ref = 1,
+ .peer = q->peer,
+ .peer_salen = q->peer_salen,
+ .peer_cred = q->peer_cred,
};
+
return p;
}
@@ -483,36 +501,46 @@ DEFINE_TRIVIAL_REF_UNREF_FUNC(SocketPeer, socket_peer, socket_peer_free);
int socket_acquire_peer(Socket *s, int fd, SocketPeer **ret) {
_cleanup_(socket_peer_unrefp) SocketPeer *remote = NULL;
- SocketPeer sa = {
+ SocketPeer key = {
.peer_salen = sizeof(union sockaddr_union),
+ .peer_cred = UCRED_INVALID,
}, *i;
int r;
- assert(fd >= 0);
assert(s);
+ assert(fd >= 0);
assert(ret);
- if (getpeername(fd, &sa.peer.sa, &sa.peer_salen) < 0)
+ if (getpeername(fd, &key.peer.sa, &key.peer_salen) < 0)
return log_unit_error_errno(UNIT(s), errno, "getpeername() failed: %m");
- if (!IN_SET(sa.peer.sa.sa_family, AF_INET, AF_INET6, AF_VSOCK)) {
+ switch (key.peer.sa.sa_family) {
+ case AF_INET:
+ case AF_INET6:
+ case AF_VSOCK:
+ break;
+
+ case AF_UNIX:
+ r = getpeercred(fd, &key.peer_cred);
+ if (r < 0)
+ return log_unit_error_errno(UNIT(s), r, "Failed to get peer credentials of socket: %m");
+ break;
+
+ default:
*ret = NULL;
return 0;
}
- i = set_get(s->peers_by_address, &sa);
+ i = set_get(s->peers_by_address, &key);
if (i) {
*ret = socket_peer_ref(i);
return 1;
}
- remote = socket_peer_new();
+ remote = socket_peer_dup(&key);
if (!remote)
return log_oom();
- remote->peer = sa.peer;
- remote->peer_salen = sa.peer_salen;
-
r = set_ensure_put(&s->peers_by_address, &peer_address_hash_ops, remote);
if (r < 0)
return log_unit_error_errno(UNIT(s), r, "Failed to insert peer info into hash table: %m");
@@ -540,10 +568,9 @@ static const char* listen_lookup(int family, int type) {
}
static void socket_dump(Unit *u, FILE *f, const char *prefix) {
- Socket *s = SOCKET(u);
+ Socket *s = ASSERT_PTR(SOCKET(u));
const char *prefix2, *str;
- assert(s);
assert(f);
prefix = strempty(prefix);
@@ -563,6 +590,7 @@ static void socket_dump(Unit *u, FILE *f, const char *prefix) {
"%sTransparent: %s\n"
"%sBroadcast: %s\n"
"%sPassCredentials: %s\n"
+ "%sPassFileDescriptorsToExec: %s\n"
"%sPassSecurity: %s\n"
"%sPassPacketInfo: %s\n"
"%sTCPCongestion: %s\n"
@@ -583,6 +611,7 @@ static void socket_dump(Unit *u, FILE *f, const char *prefix) {
prefix, yes_no(s->transparent),
prefix, yes_no(s->broadcast),
prefix, yes_no(s->pass_cred),
+ prefix, yes_no(s->pass_fds_to_exec),
prefix, yes_no(s->pass_sec),
prefix, yes_no(s->pass_pktinfo),
prefix, strna(s->tcp_congestion),
@@ -776,8 +805,8 @@ static void socket_dump(Unit *u, FILE *f, const char *prefix) {
if (!s->exec_command[c])
continue;
- fprintf(f, "%s-> %s:\n",
- prefix, socket_exec_command_to_string(c));
+ fprintf(f, "%s%s %s:\n",
+ prefix, special_glyph(SPECIAL_GLYPH_ARROW_RIGHT), socket_exec_command_to_string(c));
exec_command_dump_list(s->exec_command[c], f, prefix2);
}
@@ -1274,6 +1303,9 @@ static int socket_symlink(Socket *s) {
static int usbffs_write_descs(int fd, Service *s) {
int r;
+ assert(fd >= 0);
+ assert(s);
+
if (!s->usb_function_descriptors || !s->usb_function_strings)
return -EINVAL;
@@ -1339,12 +1371,17 @@ clear:
}
int socket_load_service_unit(Socket *s, int cfd, Unit **ret) {
+ int r;
+
/* Figure out what the unit that will be used to handle the connections on the socket looks like.
*
* If cfd < 0, then we don't have a connection yet. In case of Accept=yes sockets, use a fake
* instance name.
*/
+ assert(s);
+ assert(ret);
+
if (UNIT_ISSET(s->service)) {
*ret = UNIT_DEREF(s->service);
return 0;
@@ -1355,7 +1392,6 @@ int socket_load_service_unit(Socket *s, int cfd, Unit **ret) {
/* Build the instance name and load the unit */
_cleanup_free_ char *prefix = NULL, *instance = NULL, *name = NULL;
- int r;
r = unit_name_to_prefix(UNIT(s)->id, &prefix);
if (r < 0)
@@ -1385,50 +1421,26 @@ int socket_load_service_unit(Socket *s, int cfd, Unit **ret) {
}
static int socket_determine_selinux_label(Socket *s, char **ret) {
+ Unit *service;
int r;
assert(s);
assert(ret);
- Unit *service;
- ExecCommand *c;
- const char *exec_context;
- _cleanup_free_ char *path = NULL;
-
- r = socket_load_service_unit(s, -1, &service);
- if (r == -ENODATA)
- goto no_label;
+ r = socket_load_service_unit(s, /* cfd= */ -EBADF, &service);
+ if (r == -ENODATA) {
+ *ret = NULL;
+ return 0;
+ }
if (r < 0)
return r;
- exec_context = SERVICE(service)->exec_context.selinux_context;
- if (exec_context) {
- char *con;
-
- con = strdup(exec_context);
- if (!con)
- return -ENOMEM;
-
- *ret = TAKE_PTR(con);
+ r = service_determine_exec_selinux_label(SERVICE(service), ret);
+ if (r == -ENODATA) {
+ *ret = NULL;
return 0;
}
-
- c = SERVICE(service)->exec_command[SERVICE_EXEC_START];
- if (!c)
- goto no_label;
-
- r = chase(c->path, SERVICE(service)->exec_context.root_directory, CHASE_PREFIX_ROOT, &path, NULL);
- if (r < 0)
- goto no_label;
-
- r = mac_selinux_get_create_label_from_exe(path, ret);
- if (IN_SET(r, -EPERM, -EOPNOTSUPP))
- goto no_label;
return r;
-
-no_label:
- *ret = NULL;
- return 0;
}
static int socket_address_listen_do(
@@ -1794,6 +1806,7 @@ static int socket_check_open(Socket *s) {
static void socket_set_state(Socket *s, SocketState state) {
SocketState old_state;
+
assert(s);
if (s->state != state)
@@ -1802,18 +1815,7 @@ static void socket_set_state(Socket *s, SocketState state) {
old_state = s->state;
s->state = state;
- if (!IN_SET(state,
- SOCKET_START_PRE,
- SOCKET_START_CHOWN,
- SOCKET_START_POST,
- SOCKET_STOP_PRE,
- SOCKET_STOP_PRE_SIGTERM,
- SOCKET_STOP_PRE_SIGKILL,
- SOCKET_STOP_POST,
- SOCKET_FINAL_SIGTERM,
- SOCKET_FINAL_SIGKILL,
- SOCKET_CLEANING)) {
-
+ if (!SOCKET_STATE_WITH_PROCESS(state)) {
s->timer_event_source = sd_event_source_disable_unref(s->timer_event_source);
socket_unwatch_control_pid(s);
s->control_command = NULL;
@@ -1841,10 +1843,9 @@ static void socket_set_state(Socket *s, SocketState state) {
}
static int socket_coldplug(Unit *u) {
- Socket *s = SOCKET(u);
+ Socket *s = ASSERT_PTR(SOCKET(u));
int r;
- assert(s);
assert(s->state == SOCKET_DEAD);
if (s->deserialized_state == s->state)
@@ -1852,17 +1853,7 @@ static int socket_coldplug(Unit *u) {
if (pidref_is_set(&s->control_pid) &&
pidref_is_unwaited(&s->control_pid) > 0 &&
- IN_SET(s->deserialized_state,
- SOCKET_START_PRE,
- SOCKET_START_CHOWN,
- SOCKET_START_POST,
- SOCKET_STOP_PRE,
- SOCKET_STOP_PRE_SIGTERM,
- SOCKET_STOP_PRE_SIGKILL,
- SOCKET_STOP_POST,
- SOCKET_FINAL_SIGTERM,
- SOCKET_FINAL_SIGKILL,
- SOCKET_CLEANING)) {
+ SOCKET_STATE_WITH_PROCESS(s->deserialized_state)) {
r = unit_watch_pidref(UNIT(s), &s->control_pid, /* exclusive= */ false);
if (r < 0)
@@ -1911,11 +1902,9 @@ static int socket_coldplug(Unit *u) {
}
static int socket_spawn(Socket *s, ExecCommand *c, PidRef *ret_pid) {
-
_cleanup_(exec_params_shallow_clear) ExecParameters exec_params = EXEC_PARAMETERS_INIT(
EXEC_APPLY_SANDBOXING|EXEC_APPLY_CHROOT|EXEC_APPLY_TTY_STDIN);
_cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
- pid_t pid;
int r;
assert(s);
@@ -1934,17 +1923,33 @@ static int socket_spawn(Socket *s, ExecCommand *c, PidRef *ret_pid) {
if (r < 0)
return r;
+ /* Note that ExecStartPre= command doesn't inherit any FDs. It runs before we open listen FDs. */
+ if (s->pass_fds_to_exec) {
+ _cleanup_strv_free_ char **fd_names = NULL;
+ _cleanup_free_ int *fds = NULL;
+ int n_fds;
+
+ n_fds = socket_collect_fds(s, &fds);
+ if (n_fds < 0)
+ return n_fds;
+
+ r = strv_extend_n(&fd_names, socket_fdname(s), n_fds);
+ if (r < 0)
+ return r;
+
+ exec_params.flags |= EXEC_PASS_FDS;
+ exec_params.fds = TAKE_PTR(fds);
+ exec_params.fd_names = TAKE_PTR(fd_names);
+ exec_params.n_socket_fds = n_fds;
+ }
+
r = exec_spawn(UNIT(s),
c,
&s->exec_context,
&exec_params,
s->exec_runtime,
&s->cgroup_context,
- &pid);
- if (r < 0)
- return r;
-
- r = pidref_set_pid(&pidref, pid);
+ &pidref);
if (r < 0)
return r;
@@ -2052,6 +2057,7 @@ static void socket_enter_signal(Socket *s, SocketState state, SocketResult f);
static void socket_enter_stop_post(Socket *s, SocketResult f) {
int r;
+
assert(s);
if (s->result == SOCKET_SUCCESS)
@@ -2094,13 +2100,7 @@ static void socket_enter_signal(Socket *s, SocketState state, SocketResult f) {
if (s->result == SOCKET_SUCCESS)
s->result = f;
- r = unit_kill_context(
- UNIT(s),
- &s->kill_context,
- state_to_kill_operation(s, state),
- /* main_pid= */ NULL,
- &s->control_pid,
- /* main_pid_alien= */ false);
+ r = unit_kill_context(UNIT(s), state_to_kill_operation(s, state));
if (r < 0) {
log_unit_warning_errno(UNIT(s), r, "Failed to kill processes: %m");
goto fail;
@@ -2134,6 +2134,7 @@ fail:
static void socket_enter_stop_pre(Socket *s, SocketResult f) {
int r;
+
assert(s);
if (s->result == SOCKET_SUCCESS)
@@ -2160,6 +2161,7 @@ static void socket_enter_stop_pre(Socket *s, SocketResult f) {
static void socket_enter_listening(Socket *s) {
int r;
+
assert(s);
if (!s->accept && s->flush_pending) {
@@ -2179,6 +2181,7 @@ static void socket_enter_listening(Socket *s) {
static void socket_enter_start_post(Socket *s) {
int r;
+
assert(s);
socket_unwatch_control_pid(s);
@@ -2235,6 +2238,7 @@ fail:
static void socket_enter_start_pre(Socket *s) {
int r;
+
assert(s);
socket_unwatch_control_pid(s);
@@ -2278,7 +2282,6 @@ static void socket_enter_running(Socket *s, int cfd_in) {
/* Note that this call takes possession of the connection fd passed. It either has to assign it
* somewhere or close it. */
_cleanup_close_ int cfd = cfd_in;
-
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
int r;
@@ -2315,8 +2318,8 @@ static void socket_enter_running(Socket *s, int cfd_in) {
if (!pending) {
if (!UNIT_ISSET(s->service)) {
- r = log_unit_warning_errno(UNIT(s), SYNTHETIC_ERRNO(ENOENT),
- "Service to activate vanished, refusing activation.");
+ log_unit_warning(UNIT(s),
+ "Service to activate vanished, refusing activation.");
goto fail;
}
@@ -2347,7 +2350,10 @@ static void socket_enter_running(Socket *s, int cfd_in) {
if (r > 0 && p->n_ref > s->max_connections_per_source) {
_cleanup_free_ char *t = NULL;
- (void) sockaddr_pretty(&p->peer.sa, p->peer_salen, true, false, &t);
+ if (p->peer.sa.sa_family == AF_UNIX)
+ (void) asprintf(&t, "UID " UID_FMT, p->peer_cred.uid);
+ else
+ (void) sockaddr_pretty(&p->peer.sa, p->peer_salen, /* translate_ipv6= */ true, /* include_port= */ false, &t);
log_unit_warning(UNIT(s),
"Too many incoming connections (%u) from source %s, dropping connection.",
@@ -2357,18 +2363,15 @@ static void socket_enter_running(Socket *s, int cfd_in) {
}
r = socket_load_service_unit(s, cfd, &service);
- if (r < 0) {
- if (ERRNO_IS_DISCONNECT(r))
- return;
-
- log_unit_warning_errno(UNIT(s), r, "Failed to load connection service unit: %m");
+ if (ERRNO_IS_NEG_DISCONNECT(r))
+ return;
+ if (r < 0 || UNIT_IS_LOAD_ERROR(service->load_state)) {
+ log_unit_warning_errno(UNIT(s), r < 0 ? r : service->load_error,
+ "Failed to load connection service unit: %m");
goto fail;
}
-
- r = unit_add_two_dependencies(UNIT(s), UNIT_BEFORE, UNIT_TRIGGERS, service,
- false, UNIT_DEPENDENCY_IMPLICIT);
- if (r < 0) {
- log_unit_warning_errno(UNIT(s), r, "Failed to add Before=/Triggers= dependencies on connection unit: %m");
+ if (service->load_state == UNIT_MASKED) {
+ log_unit_warning(UNIT(s), "Connection service unit is masked, refusing.");
goto fail;
}
@@ -2383,7 +2386,10 @@ static void socket_enter_running(Socket *s, int cfd_in) {
goto fail;
}
- TAKE_FD(cfd); /* We passed ownership of the fd to the service now. Forget it here. */
+ /* We passed ownership of the fd and socket peer to the service now. */
+ TAKE_FD(cfd);
+ TAKE_PTR(p);
+
s->n_connections++;
r = manager_add_job(UNIT(s)->manager, JOB_START, service, JOB_REPLACE, NULL, &error, NULL);
@@ -2405,13 +2411,9 @@ refuse:
return;
queue_error:
- if (ERRNO_IS_RESOURCE(r))
- log_unit_warning(UNIT(s), "Failed to queue service startup job: %s",
- bus_error_message(&error, r));
- else
- log_unit_warning(UNIT(s), "Failed to queue service startup job (Maybe the service file is missing or not a %s unit?): %s",
- cfd >= 0 ? "template" : "non-template",
- bus_error_message(&error, r));
+ log_unit_warning_errno(UNIT(s), r, "Failed to queue service startup job%s: %s",
+ cfd >= 0 && !ERRNO_IS_RESOURCE(r) ? " (Maybe the service is missing or is a template unit?)" : "",
+ bus_error_message(&error, r));
fail:
socket_enter_stop_pre(s, SOCKET_FAILURE_RESOURCES);
@@ -2444,11 +2446,9 @@ static void socket_run_next(Socket *s) {
}
static int socket_start(Unit *u) {
- Socket *s = SOCKET(u);
+ Socket *s = ASSERT_PTR(SOCKET(u));
int r;
- assert(s);
-
/* We cannot fulfill this request right now, try again later
* please! */
if (IN_SET(s->state,
@@ -2496,16 +2496,15 @@ static int socket_start(Unit *u) {
s->result = SOCKET_SUCCESS;
exec_command_reset_status_list_array(s->exec_command, _SOCKET_EXEC_COMMAND_MAX);
- u->reset_accounting = true;
+ if (s->cgroup_runtime)
+ s->cgroup_runtime->reset_accounting = true;
socket_enter_start_pre(s);
return 1;
}
static int socket_stop(Unit *u) {
- Socket *s = SOCKET(u);
-
- assert(s);
+ Socket *s = ASSERT_PTR(SOCKET(u));
/* Already on it */
if (IN_SET(s->state,
@@ -2540,10 +2539,9 @@ static int socket_stop(Unit *u) {
}
static int socket_serialize(Unit *u, FILE *f, FDSet *fds) {
- Socket *s = SOCKET(u);
+ Socket *s = ASSERT_PTR(SOCKET(u));
int r;
- assert(u);
assert(f);
assert(fds);
@@ -2595,10 +2593,9 @@ static int socket_serialize(Unit *u, FILE *f, FDSet *fds) {
}
static int socket_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
- Socket *s = SOCKET(u);
+ Socket *s = ASSERT_PTR(SOCKET(u));
int r;
- assert(u);
assert(key);
assert(value);
@@ -2836,9 +2833,7 @@ static int socket_deserialize_item(Unit *u, const char *key, const char *value,
}
static void socket_distribute_fds(Unit *u, FDSet *fds) {
- Socket *s = SOCKET(u);
-
- assert(u);
+ Socket *s = ASSERT_PTR(SOCKET(u));
LIST_FOREACH(port, p, s->ports) {
int fd;
@@ -2860,15 +2855,15 @@ static void socket_distribute_fds(Unit *u, FDSet *fds) {
}
static UnitActiveState socket_active_state(Unit *u) {
- assert(u);
+ Socket *s = ASSERT_PTR(SOCKET(u));
- return state_translation_table[SOCKET(u)->state];
+ return state_translation_table[s->state];
}
static const char *socket_sub_state_to_string(Unit *u) {
- assert(u);
+ Socket *s = ASSERT_PTR(SOCKET(u));
- return socket_state_to_string(SOCKET(u)->state);
+ return socket_state_to_string(s->state);
}
int socket_port_to_address(const SocketPort *p, char **ret) {
@@ -2906,7 +2901,6 @@ int socket_port_to_address(const SocketPort *p, char **ret) {
}
const char* socket_port_type_to_string(SocketPort *p) {
-
assert(p);
switch (p->type) {
@@ -2968,9 +2962,7 @@ SocketType socket_port_type_from_string(const char *s) {
}
static bool socket_may_gc(Unit *u) {
- Socket *s = SOCKET(u);
-
- assert(u);
+ Socket *s = ASSERT_PTR(SOCKET(u));
return s->n_connections == 0;
}
@@ -3108,10 +3100,9 @@ fail:
}
static void socket_sigchld_event(Unit *u, pid_t pid, int code, int status) {
- Socket *s = SOCKET(u);
+ Socket *s = ASSERT_PTR(SOCKET(u));
SocketResult f;
- assert(s);
assert(pid >= 0);
if (pid != s->control_pid.pid)
@@ -3215,9 +3206,8 @@ static void socket_sigchld_event(Unit *u, pid_t pid, int code, int status) {
}
static int socket_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata) {
- Socket *s = SOCKET(userdata);
+ Socket *s = ASSERT_PTR(SOCKET(userdata));
- assert(s);
assert(s->timer_event_source == source);
switch (s->state) {
@@ -3289,12 +3279,11 @@ static int socket_dispatch_timer(sd_event_source *source, usec_t usec, void *use
return 0;
}
-int socket_collect_fds(Socket *s, int **fds) {
- size_t k = 0, n = 0;
- int *rfds;
+int socket_collect_fds(Socket *s, int **ret) {
+ size_t n = 0, k = 0;
assert(s);
- assert(fds);
+ assert(ret);
/* Called from the service code for requesting our fds */
@@ -3304,25 +3293,25 @@ int socket_collect_fds(Socket *s, int **fds) {
n += p->n_auxiliary_fds;
}
- if (n <= 0) {
- *fds = NULL;
+ if (n == 0) {
+ *ret = NULL;
return 0;
}
- rfds = new(int, n);
- if (!rfds)
+ int *fds = new(int, n);
+ if (!fds)
return -ENOMEM;
LIST_FOREACH(port, p, s->ports) {
if (p->fd >= 0)
- rfds[k++] = p->fd;
- for (size_t i = 0; i < p->n_auxiliary_fds; ++i)
- rfds[k++] = p->auxiliary_fds[i];
+ fds[k++] = p->fd;
+ FOREACH_ARRAY(i, p->auxiliary_fds, p->n_auxiliary_fds)
+ fds[k++] = *i;
}
assert(k == n);
- *fds = rfds;
+ *ret = fds;
return (int) n;
}
@@ -3353,9 +3342,8 @@ void socket_connection_unref(Socket *s) {
}
static void socket_trigger_notify(Unit *u, Unit *other) {
- Socket *s = SOCKET(u);
+ Socket *s = ASSERT_PTR(SOCKET(u));
- assert(u);
assert(other);
/* Filter out invocations with bogus state */
@@ -3390,8 +3378,24 @@ static void socket_trigger_notify(Unit *u, Unit *other) {
socket_set_state(s, SOCKET_RUNNING);
}
+static void socket_handoff_timestamp(
+ Unit *u,
+ const struct ucred *ucred,
+ const dual_timestamp *ts) {
+
+ Socket *s = ASSERT_PTR(SOCKET(u));
+
+ assert(ucred);
+ assert(ts);
+
+ if (s->control_pid.pid == ucred->pid && s->control_command) {
+ exec_status_handoff(&s->control_command->exec_status, ucred, ts);
+ unit_add_to_dbus_queue(u);
+ }
+}
+
static int socket_get_timeout(Unit *u, usec_t *timeout) {
- Socket *s = SOCKET(u);
+ Socket *s = ASSERT_PTR(SOCKET(u));
usec_t t;
int r;
@@ -3423,11 +3427,10 @@ static PidRef *socket_control_pid(Unit *u) {
}
static int socket_clean(Unit *u, ExecCleanMask mask) {
+ Socket *s = ASSERT_PTR(SOCKET(u));
_cleanup_strv_free_ char **l = NULL;
- Socket *s = SOCKET(u);
int r;
- assert(s);
assert(mask != 0);
if (s->state != SOCKET_DEAD)
@@ -3467,19 +3470,15 @@ fail:
}
static int socket_can_clean(Unit *u, ExecCleanMask *ret) {
- Socket *s = SOCKET(u);
-
- assert(s);
+ Socket *s = ASSERT_PTR(SOCKET(u));
return exec_context_get_clean_mask(&s->exec_context, ret);
}
static int socket_can_start(Unit *u) {
- Socket *s = SOCKET(u);
+ Socket *s = ASSERT_PTR(SOCKET(u));
int r;
- assert(s);
-
r = unit_test_start_limit(u);
if (r < 0) {
socket_enter_dead(s, SOCKET_FAILURE_START_LIMIT_HIT);
@@ -3494,7 +3493,7 @@ static const char* const socket_exec_command_table[_SOCKET_EXEC_COMMAND_MAX] = {
[SOCKET_EXEC_START_CHOWN] = "ExecStartChown",
[SOCKET_EXEC_START_POST] = "ExecStartPost",
[SOCKET_EXEC_STOP_PRE] = "ExecStopPre",
- [SOCKET_EXEC_STOP_POST] = "ExecStopPost"
+ [SOCKET_EXEC_STOP_POST] = "ExecStopPost",
};
DEFINE_STRING_TABLE_LOOKUP(socket_exec_command, SocketExecCommand);
@@ -3508,7 +3507,7 @@ static const char* const socket_result_table[_SOCKET_RESULT_MAX] = {
[SOCKET_FAILURE_CORE_DUMP] = "core-dump",
[SOCKET_FAILURE_START_LIMIT_HIT] = "start-limit-hit",
[SOCKET_FAILURE_TRIGGER_LIMIT_HIT] = "trigger-limit-hit",
- [SOCKET_FAILURE_SERVICE_START_LIMIT_HIT] = "service-start-limit-hit"
+ [SOCKET_FAILURE_SERVICE_START_LIMIT_HIT] = "service-start-limit-hit",
};
DEFINE_STRING_TABLE_LOOKUP(socket_result, SocketResult);
@@ -3552,6 +3551,7 @@ const UnitVTable socket_vtable = {
.cgroup_context_offset = offsetof(Socket, cgroup_context),
.kill_context_offset = offsetof(Socket, kill_context),
.exec_runtime_offset = offsetof(Socket, exec_runtime),
+ .cgroup_runtime_offset = offsetof(Socket, cgroup_runtime),
.sections =
"Unit\0"
@@ -3596,6 +3596,8 @@ const UnitVTable socket_vtable = {
.reset_failed = socket_reset_failed,
+ .notify_handoff_timestamp = socket_handoff_timestamp,
+
.control_pid = socket_control_pid,
.bus_set_property = bus_socket_set_property,