chiark / gitweb /
socket: introduce SELinuxLabelViaNet option
[elogind.git] / src / core / socket.c
index 44827ad346934382b24243b154b310ae13873195..34ce1b1ffd54c6f84da894447aad23295884921f 100644 (file)
 #include <mqueue.h>
 #include <sys/xattr.h>
 
+#ifdef HAVE_SELINUX
+#include <selinux/selinux.h>
+#endif
+
 #include "sd-event.h"
 #include "log.h"
 #include "load-dropin.h"
@@ -462,6 +466,7 @@ _const_ static const char* listen_lookup(int family, int type) {
 }
 
 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;
@@ -481,14 +486,14 @@ static void socket_dump(Unit *u, FILE *f, const char *prefix) {
                 "%sDirectoryMode: %04o\n"
                 "%sKeepAlive: %s\n"
                 "%sNoDelay: %s\n"
-                "%sFastOpen: %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"
+                "%sSELinuxLabelViaNet: %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),
@@ -497,14 +502,14 @@ static void socket_dump(Unit *u, FILE *f, const char *prefix) {
                 prefix, s->directory_mode,
                 prefix, yes_no(s->keep_alive),
                 prefix, yes_no(s->no_delay),
-                prefix, yes_no(s->fast_open),
                 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_label_via_net));
 
         if (s->control_pid > 0)
                 fprintf(f,
@@ -597,6 +602,29 @@ static void socket_dump(Unit *u, FILE *f, const char *prefix) {
                         prefix, strna(s->user),
                         prefix, strna(s->group));
 
+        if(s->keep_alive_time)
+                fprintf(f,
+                        "%sKeepAliveTime: %s\n",
+                        prefix, format_timespan(time_string, FORMAT_TIMESPAN_MAX,
+                                                s->keep_alive_time, USEC_PER_SEC));
+
+        if(s->keep_alive_interval)
+                fprintf(f,
+                        "%sKeepAliveInterval: %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,
+                        "%sDeferAccept: %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) {
@@ -794,18 +822,36 @@ static void socket_apply_socket_options(Socket *s, int fd) {
                         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->fast_open) {
-                int b = s->fast_open;
-                if (setsockopt(fd, SOL_TCP, TCP_FASTOPEN, &b, sizeof(b)) < 0)
-                        log_warning_unit(UNIT(s)->id, "TCP_FASTOPEN failed: %m");
-        }
-
         if (s->broadcast) {
                 int one = 1;
                 if (setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &one, sizeof(one)) < 0)
@@ -1090,7 +1136,14 @@ static int socket_open_fds(Socket *s) {
                         continue;
 
                 if (p->type == SOCKET_SOCKET) {
-
+#ifdef HAVE_SELINUX
+                        if (!know_label && s->selinux_label_via_net) {
+                                r = getcon(&label);
+                                if (r < 0)
+                                        return r;
+                                know_label = true;
+                        }
+#endif
                         if (!know_label) {
 
                                 r = socket_instantiate_service(s);
@@ -1789,6 +1842,9 @@ static void socket_enter_running(Socket *s, int cfd) {
                 cfd = -1;
                 s->n_connections ++;
 
+                if (s->selinux_label_via_net)
+                        service->exec_context.selinux_label_via_net = true;
+
                 r = manager_add_job(UNIT(s)->manager, JOB_START, UNIT(service), JOB_REPLACE, true, &error, NULL);
                 if (r < 0)
                         goto fail;