socket_dispatch_timer, s);
}
-static int socket_instantiate_service(Socket *s) {
- _cleanup_free_ char *prefix = NULL;
- _cleanup_free_ char *name = NULL;
+int socket_instantiate_service(Socket *s) {
+ _cleanup_free_ char *prefix = NULL, *name = NULL;
int r;
Unit *u;
* here. For Accept=no this is mostly a NOP since the service
* is figured out at load time anyway. */
- if (UNIT_DEREF(s->service))
+ if (UNIT_DEREF(s->service) || !s->accept)
return 0;
- assert(s->accept);
-
prefix = unit_name_to_prefix(UNIT(s)->id);
if (!prefix)
return -ENOMEM;
if (r < 0)
return r;
-#ifdef HAVE_SYSV_COMPAT
- if (SERVICE(u)->is_sysv) {
- log_error("Using SysV services for socket activation is not supported. Refusing.");
- return -ENOENT;
- }
-#endif
-
u->no_gc = true;
unit_ref_set(&s->service, u);
}
static void socket_dump(Unit *u, FILE *f, const char *prefix) {
+ char time_string[FORMAT_TIMESPAN_MAX];
SocketExecCommand c;
Socket *s = SOCKET(u);
SocketPort *p;
assert(s);
assert(f);
+ prefix = strempty(prefix);
prefix2 = strappenda(prefix, "\t");
fprintf(f,
"%sSocketMode: %04o\n"
"%sDirectoryMode: %04o\n"
"%sKeepAlive: %s\n"
+ "%sNoDelay: %s\n"
"%sFreeBind: %s\n"
"%sTransparent: %s\n"
"%sBroadcast: %s\n"
"%sPassCredentials: %s\n"
"%sPassSecurity: %s\n"
"%sTCPCongestion: %s\n"
- "%sRemoveOnStop: %s\n",
+ "%sRemoveOnStop: %s\n"
+ "%sSELinuxContextFromNet: %s\n",
prefix, socket_state_to_string(s->state),
prefix, socket_result_to_string(s->result),
prefix, socket_address_bind_ipv6_only_to_string(s->bind_ipv6_only),
prefix, s->socket_mode,
prefix, s->directory_mode,
prefix, yes_no(s->keep_alive),
+ prefix, yes_no(s->no_delay),
prefix, yes_no(s->free_bind),
prefix, yes_no(s->transparent),
prefix, yes_no(s->broadcast),
prefix, yes_no(s->pass_cred),
prefix, yes_no(s->pass_sec),
prefix, strna(s->tcp_congestion),
- prefix, yes_no(s->remove_on_stop));
+ prefix, yes_no(s->remove_on_stop),
+ prefix, yes_no(s->selinux_context_from_net));
if (s->control_pid > 0)
fprintf(f,
prefix, strna(s->user),
prefix, strna(s->group));
+ if (s->keep_alive_time > 0)
+ fprintf(f,
+ "%sKeepAliveTimeSec: %s\n",
+ prefix, format_timespan(time_string, FORMAT_TIMESPAN_MAX, s->keep_alive_time, USEC_PER_SEC));
+
+ if (s->keep_alive_interval)
+ fprintf(f,
+ "%sKeepAliveIntervalSec: %s\n",
+ prefix, format_timespan(time_string, FORMAT_TIMESPAN_MAX, s->keep_alive_interval, USEC_PER_SEC));
+
+ if (s->keep_alive_cnt)
+ fprintf(f,
+ "%sKeepAliveProbes: %u\n",
+ prefix, s->keep_alive_cnt);
+
+ if (s->defer_accept)
+ fprintf(f,
+ "%sDeferAcceptSec: %s\n",
+ prefix, format_timespan(time_string, FORMAT_TIMESPAN_MAX, s->defer_accept, USEC_PER_SEC));
+
LIST_FOREACH(port, p, s->ports) {
if (p->type == SOCKET_SOCKET) {
log_warning_unit(UNIT(s)->id, "SO_KEEPALIVE failed: %m");
}
+ if (s->keep_alive_time) {
+ int value = s->keep_alive_time / USEC_PER_SEC;
+ if (setsockopt(fd, SOL_TCP, TCP_KEEPIDLE, &value, sizeof(value)) < 0)
+ log_warning_unit(UNIT(s)->id, "TCP_KEEPIDLE failed: %m");
+ }
+
+ if (s->keep_alive_interval) {
+ int value = s->keep_alive_interval / USEC_PER_SEC;
+ if (setsockopt(fd, SOL_TCP, TCP_KEEPINTVL, &value, sizeof(value)) < 0)
+ log_warning_unit(UNIT(s)->id, "TCP_KEEPINTVL failed: %m");
+ }
+
+ if (s->keep_alive_cnt) {
+ int value = s->keep_alive_cnt;
+ if (setsockopt(fd, SOL_SOCKET, TCP_KEEPCNT, &value, sizeof(value)) < 0)
+ log_warning_unit(UNIT(s)->id, "TCP_KEEPCNT failed: %m");
+ }
+
+ if (s->defer_accept) {
+ int value = s->defer_accept / USEC_PER_SEC;
+ if (setsockopt(fd, SOL_TCP, TCP_DEFER_ACCEPT, &value, sizeof(value)) < 0)
+ log_warning_unit(UNIT(s)->id, "TCP_DEFER_ACCEPT failed: %m");
+ }
+
+ if (s->no_delay) {
+ int b = s->no_delay;
+ if (setsockopt(fd, SOL_TCP, TCP_NODELAY, &b, sizeof(b)) < 0)
+ log_warning_unit(UNIT(s)->id, "TCP_NODELAY failed: %m");
+ }
+
if (s->broadcast) {
int one = 1;
if (setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &one, sizeof(one)) < 0)
continue;
if (p->type == SOCKET_SOCKET) {
-
- if (!know_label) {
+ if (!know_label && s->selinux_context_from_net) {
+ r = label_get_our_label(&label);
+ if (r < 0)
+ return r;
+ know_label = true;
+ } else if (!know_label) {
r = socket_instantiate_service(s);
if (r < 0)
if (p->fd < 0)
continue;
- if (p->event_source) {
- r = sd_event_source_set_enabled(p->event_source, SD_EVENT_OFF);
- if (r < 0)
- log_debug_unit(UNIT(s)->id, "Failed to disable event source.");
- }
+ if (!p->event_source)
+ continue;
+
+ r = sd_event_source_set_enabled(p->event_source, SD_EVENT_OFF);
+ if (r < 0)
+ log_debug_unit(UNIT(s)->id, "Failed to disable event source.");
}
}
_cleanup_free_ char **argv = NULL;
pid_t pid;
int r;
+ ExecParameters exec_params = {
+ .apply_permissions = true,
+ .apply_chroot = true,
+ .apply_tty_stdin = true,
+ };
assert(s);
assert(c);
if (r < 0)
goto fail;
+ exec_params.argv = argv;
+ exec_params.environment = UNIT(s)->manager->environment;
+ exec_params.confirm_spawn = UNIT(s)->manager->confirm_spawn;
+ exec_params.cgroup_supported = UNIT(s)->manager->cgroup_supported;
+ exec_params.cgroup_path = UNIT(s)->cgroup_path;
+ exec_params.runtime_prefix = manager_get_runtime_prefix(UNIT(s)->manager);
+ exec_params.unit_id = UNIT(s)->id;
+
r = exec_spawn(c,
- argv,
&s->exec_context,
- NULL, 0,
- UNIT(s)->manager->environment,
- true,
- true,
- true,
- UNIT(s)->manager->confirm_spawn,
- UNIT(s)->manager->cgroup_supported,
- UNIT(s)->cgroup_path,
- manager_get_runtime_prefix(UNIT(s)->manager),
- UNIT(s)->id,
- 0,
- NULL,
+ &exec_params,
s->exec_runtime,
&pid);
+ if (r < 0)
+ goto fail;
r = unit_watch_pid(UNIT(s), pid);
if (r < 0)
}
LIST_FOREACH(port, p, s->ports) {
- const char *path;
+ const char *path = NULL;
if (p->type == SOCKET_SOCKET)
path = socket_address_get_path(&p->address);
unit_choose_id(UNIT(service), name);
- r = service_set_socket_fd(service, cfd, s);
+ r = service_set_socket_fd(service, cfd, s, s->selinux_context_from_net);
if (r < 0)
goto fail;
SOCKET_FINAL_SIGKILL))
return -EAGAIN;
+ /* Already on it! */
if (IN_SET(s->state,
SOCKET_START_PRE,
SOCKET_START_CHOWN,
log_error_unit(u->id, "Socket service %s already active, refusing.", UNIT(service)->id);
return -EBUSY;
}
-
-#ifdef HAVE_SYSV_COMPAT
- if (service->is_sysv) {
- log_error_unit(u->id,
- "Using SysV services for socket activation is not supported. Refusing.");
- return -ENOENT;
- }
-#endif
}
assert(s->state == SOCKET_DEAD || s->state == SOCKET_FAILED);
else if (code == CLD_DUMPED)
f = SOCKET_FAILURE_CORE_DUMP;
else
- assert_not_reached("Unknown code");
+ assert_not_reached("Unknown sigchld code");
if (s->control_command) {
exec_status_exit(&s->control_command->exec_status, &s->exec_context, pid, code, status);