| File: | build-scan/../src/core/socket.c |
| Warning: | line 2391, column 9 Potential leak of memory pointed to by 'p' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | /* SPDX-License-Identifier: LGPL-2.1+ */ | ||||
| 2 | |||||
| 3 | #include <arpa/inet.h> | ||||
| 4 | #include <errno(*__errno_location ()).h> | ||||
| 5 | #include <fcntl.h> | ||||
| 6 | #include <mqueue.h> | ||||
| 7 | #include <netinet/tcp.h> | ||||
| 8 | #include <signal.h> | ||||
| 9 | #include <sys/epoll.h> | ||||
| 10 | #include <sys/stat.h> | ||||
| 11 | #include <unistd.h> | ||||
| 12 | #include <linux1/sctp.h> | ||||
| 13 | |||||
| 14 | #include "alloc-util.h" | ||||
| 15 | #include "bpf-firewall.h" | ||||
| 16 | #include "bus-error.h" | ||||
| 17 | #include "bus-util.h" | ||||
| 18 | #include "copy.h" | ||||
| 19 | #include "dbus-socket.h" | ||||
| 20 | #include "def.h" | ||||
| 21 | #include "exit-status.h" | ||||
| 22 | #include "fd-util.h" | ||||
| 23 | #include "format-util.h" | ||||
| 24 | #include "fs-util.h" | ||||
| 25 | #include "in-addr-util.h" | ||||
| 26 | #include "io-util.h" | ||||
| 27 | #include "label.h" | ||||
| 28 | #include "log.h" | ||||
| 29 | #include "missing.h" | ||||
| 30 | #include "mkdir.h" | ||||
| 31 | #include "parse-util.h" | ||||
| 32 | #include "path-util.h" | ||||
| 33 | #include "process-util.h" | ||||
| 34 | #include "selinux-util.h" | ||||
| 35 | #include "signal-util.h" | ||||
| 36 | #include "smack-util.h" | ||||
| 37 | #include "socket.h" | ||||
| 38 | #include "socket-protocol-list.h" | ||||
| 39 | #include "special.h" | ||||
| 40 | #include "string-table.h" | ||||
| 41 | #include "string-util.h" | ||||
| 42 | #include "strv.h" | ||||
| 43 | #include "unit-name.h" | ||||
| 44 | #include "unit.h" | ||||
| 45 | #include "user-util.h" | ||||
| 46 | |||||
| 47 | struct SocketPeer { | ||||
| 48 | unsigned n_ref; | ||||
| 49 | |||||
| 50 | Socket *socket; | ||||
| 51 | union sockaddr_union peer; | ||||
| 52 | socklen_t peer_salen; | ||||
| 53 | }; | ||||
| 54 | |||||
| 55 | static const UnitActiveState state_translation_table[_SOCKET_STATE_MAX] = { | ||||
| 56 | [SOCKET_DEAD] = UNIT_INACTIVE, | ||||
| 57 | [SOCKET_START_PRE] = UNIT_ACTIVATING, | ||||
| 58 | [SOCKET_START_CHOWN] = UNIT_ACTIVATING, | ||||
| 59 | [SOCKET_START_POST] = UNIT_ACTIVATING, | ||||
| 60 | [SOCKET_LISTENING] = UNIT_ACTIVE, | ||||
| 61 | [SOCKET_RUNNING] = UNIT_ACTIVE, | ||||
| 62 | [SOCKET_STOP_PRE] = UNIT_DEACTIVATING, | ||||
| 63 | [SOCKET_STOP_PRE_SIGTERM] = UNIT_DEACTIVATING, | ||||
| 64 | [SOCKET_STOP_PRE_SIGKILL] = UNIT_DEACTIVATING, | ||||
| 65 | [SOCKET_STOP_POST] = UNIT_DEACTIVATING, | ||||
| 66 | [SOCKET_FINAL_SIGTERM] = UNIT_DEACTIVATING, | ||||
| 67 | [SOCKET_FINAL_SIGKILL] = UNIT_DEACTIVATING, | ||||
| 68 | [SOCKET_FAILED] = UNIT_FAILED | ||||
| 69 | }; | ||||
| 70 | |||||
| 71 | static int socket_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata); | ||||
| 72 | static int socket_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata); | ||||
| 73 | static void flush_ports(Socket *s); | ||||
| 74 | |||||
| 75 | static void socket_init(Unit *u) { | ||||
| 76 | Socket *s = SOCKET(u); | ||||
| 77 | |||||
| 78 | assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("u"), "../src/core/socket.c", 78, __PRETTY_FUNCTION__ ); } while (0); | ||||
| 79 | assert(u->load_state == UNIT_STUB)do { if ((__builtin_expect(!!(!(u->load_state == UNIT_STUB )),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("u->load_state == UNIT_STUB" ), "../src/core/socket.c", 79, __PRETTY_FUNCTION__); } while ( 0); | ||||
| 80 | |||||
| 81 | s->backlog = SOMAXCONN4096; | ||||
| 82 | s->timeout_usec = u->manager->default_timeout_start_usec; | ||||
| 83 | s->directory_mode = 0755; | ||||
| 84 | s->socket_mode = 0666; | ||||
| 85 | |||||
| 86 | s->max_connections = 64; | ||||
| 87 | |||||
| 88 | s->priority = -1; | ||||
| 89 | s->ip_tos = -1; | ||||
| 90 | s->ip_ttl = -1; | ||||
| 91 | s->mark = -1; | ||||
| 92 | |||||
| 93 | s->exec_context.std_output = u->manager->default_std_output; | ||||
| 94 | s->exec_context.std_error = u->manager->default_std_error; | ||||
| 95 | |||||
| 96 | s->control_command_id = _SOCKET_EXEC_COMMAND_INVALID; | ||||
| 97 | |||||
| 98 | s->trigger_limit.interval = USEC_INFINITY((usec_t) -1); | ||||
| 99 | s->trigger_limit.burst = (unsigned) -1; | ||||
| 100 | } | ||||
| 101 | |||||
| 102 | static void socket_unwatch_control_pid(Socket *s) { | ||||
| 103 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/socket.c", 103, __PRETTY_FUNCTION__ ); } while (0); | ||||
| 104 | |||||
| 105 | if (s->control_pid <= 0) | ||||
| 106 | return; | ||||
| 107 | |||||
| 108 | unit_unwatch_pid(UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; }), s->control_pid); | ||||
| 109 | s->control_pid = 0; | ||||
| 110 | } | ||||
| 111 | |||||
| 112 | static void socket_cleanup_fd_list(SocketPort *p) { | ||||
| 113 | assert(p)do { if ((__builtin_expect(!!(!(p)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("p"), "../src/core/socket.c", 113, __PRETTY_FUNCTION__ ); } while (0); | ||||
| 114 | |||||
| 115 | close_many(p->auxiliary_fds, p->n_auxiliary_fds); | ||||
| 116 | p->auxiliary_fds = mfree(p->auxiliary_fds); | ||||
| 117 | p->n_auxiliary_fds = 0; | ||||
| 118 | } | ||||
| 119 | |||||
| 120 | void socket_free_ports(Socket *s) { | ||||
| 121 | SocketPort *p; | ||||
| 122 | |||||
| 123 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/socket.c", 123, __PRETTY_FUNCTION__ ); } while (0); | ||||
| 124 | |||||
| 125 | while ((p = s->ports)) { | ||||
| 126 | LIST_REMOVE(port, s->ports, p)do { typeof(*(s->ports)) **_head = &(s->ports), *_item = (p); do { if ((__builtin_expect(!!(!(_item)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("_item"), "../src/core/socket.c", 126, __PRETTY_FUNCTION__ ); } while (0); if (_item->port_next) _item->port_next-> port_prev = _item->port_prev; if (_item->port_prev) _item ->port_prev->port_next = _item->port_next; else { do { if ((__builtin_expect(!!(!(*_head == _item)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("*_head == _item"), "../src/core/socket.c" , 126, __PRETTY_FUNCTION__); } while (0); *_head = _item-> port_next; } _item->port_next = _item->port_prev = ((void *)0); } while (0); | ||||
| 127 | |||||
| 128 | sd_event_source_unref(p->event_source); | ||||
| 129 | |||||
| 130 | socket_cleanup_fd_list(p); | ||||
| 131 | safe_close(p->fd); | ||||
| 132 | free(p->path); | ||||
| 133 | free(p); | ||||
| 134 | } | ||||
| 135 | } | ||||
| 136 | |||||
| 137 | static void socket_done(Unit *u) { | ||||
| 138 | Socket *s = SOCKET(u); | ||||
| 139 | SocketPeer *p; | ||||
| 140 | |||||
| 141 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/socket.c", 141, __PRETTY_FUNCTION__ ); } while (0); | ||||
| 142 | |||||
| 143 | socket_free_ports(s); | ||||
| 144 | |||||
| 145 | while ((p = set_steal_first(s->peers_by_address))) | ||||
| 146 | p->socket = NULL((void*)0); | ||||
| 147 | |||||
| 148 | s->peers_by_address = set_free(s->peers_by_address); | ||||
| 149 | |||||
| 150 | s->exec_runtime = exec_runtime_unref(s->exec_runtime, false0); | ||||
| 151 | exec_command_free_array(s->exec_command, _SOCKET_EXEC_COMMAND_MAX); | ||||
| 152 | s->control_command = NULL((void*)0); | ||||
| 153 | |||||
| 154 | dynamic_creds_unref(&s->dynamic_creds); | ||||
| 155 | |||||
| 156 | socket_unwatch_control_pid(s); | ||||
| 157 | |||||
| 158 | unit_ref_unset(&s->service); | ||||
| 159 | |||||
| 160 | s->tcp_congestion = mfree(s->tcp_congestion); | ||||
| 161 | s->bind_to_device = mfree(s->bind_to_device); | ||||
| 162 | |||||
| 163 | s->smack = mfree(s->smack); | ||||
| 164 | s->smack_ip_in = mfree(s->smack_ip_in); | ||||
| 165 | s->smack_ip_out = mfree(s->smack_ip_out); | ||||
| 166 | |||||
| 167 | strv_free(s->symlinks); | ||||
| 168 | |||||
| 169 | s->user = mfree(s->user); | ||||
| 170 | s->group = mfree(s->group); | ||||
| 171 | |||||
| 172 | s->fdname = mfree(s->fdname); | ||||
| 173 | |||||
| 174 | s->timer_event_source = sd_event_source_unref(s->timer_event_source); | ||||
| 175 | } | ||||
| 176 | |||||
| 177 | static int socket_arm_timer(Socket *s, usec_t usec) { | ||||
| 178 | int r; | ||||
| 179 | |||||
| 180 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/socket.c", 180, __PRETTY_FUNCTION__ ); } while (0); | ||||
| 181 | |||||
| 182 | if (s->timer_event_source) { | ||||
| 183 | r = sd_event_source_set_time(s->timer_event_source, usec); | ||||
| 184 | if (r < 0) | ||||
| 185 | return r; | ||||
| 186 | |||||
| 187 | return sd_event_source_set_enabled(s->timer_event_source, SD_EVENT_ONESHOT); | ||||
| 188 | } | ||||
| 189 | |||||
| 190 | if (usec == USEC_INFINITY((usec_t) -1)) | ||||
| 191 | return 0; | ||||
| 192 | |||||
| 193 | r = sd_event_add_time( | ||||
| 194 | UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })->manager->event, | ||||
| 195 | &s->timer_event_source, | ||||
| 196 | CLOCK_MONOTONIC1, | ||||
| 197 | usec, 0, | ||||
| 198 | socket_dispatch_timer, s); | ||||
| 199 | if (r < 0) | ||||
| 200 | return r; | ||||
| 201 | |||||
| 202 | (void) sd_event_source_set_description(s->timer_event_source, "socket-timer"); | ||||
| 203 | |||||
| 204 | return 0; | ||||
| 205 | } | ||||
| 206 | |||||
| 207 | int socket_instantiate_service(Socket *s) { | ||||
| 208 | _cleanup_free___attribute__((cleanup(freep))) char *prefix = NULL((void*)0), *name = NULL((void*)0); | ||||
| 209 | int r; | ||||
| 210 | Unit *u; | ||||
| 211 | |||||
| 212 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/socket.c", 212, __PRETTY_FUNCTION__ ); } while (0); | ||||
| 213 | |||||
| 214 | /* This fills in s->service if it isn't filled in yet. For | ||||
| 215 | * Accept=yes sockets we create the next connection service | ||||
| 216 | * here. For Accept=no this is mostly a NOP since the service | ||||
| 217 | * is figured out at load time anyway. */ | ||||
| 218 | |||||
| 219 | if (UNIT_DEREF(s->service)((s->service).target)) | ||||
| 220 | return 0; | ||||
| 221 | |||||
| 222 | if (!s->accept) | ||||
| 223 | return 0; | ||||
| 224 | |||||
| 225 | r = unit_name_to_prefix(UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })->id, &prefix); | ||||
| 226 | if (r < 0) | ||||
| 227 | return r; | ||||
| 228 | |||||
| 229 | if (asprintf(&name, "%s@%u.service", prefix, s->n_accepted) < 0) | ||||
| 230 | return -ENOMEM12; | ||||
| 231 | |||||
| 232 | r = manager_load_unit(UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })->manager, name, NULL((void*)0), NULL((void*)0), &u); | ||||
| 233 | if (r < 0) | ||||
| 234 | return r; | ||||
| 235 | |||||
| 236 | unit_ref_set(&s->service, UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; }), u); | ||||
| 237 | |||||
| 238 | return unit_add_two_dependencies(UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; }), UNIT_BEFORE, UNIT_TRIGGERS, u, false0, UNIT_DEPENDENCY_IMPLICIT); | ||||
| 239 | } | ||||
| 240 | |||||
| 241 | static bool_Bool have_non_accept_socket(Socket *s) { | ||||
| 242 | SocketPort *p; | ||||
| 243 | |||||
| 244 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/socket.c", 244, __PRETTY_FUNCTION__ ); } while (0); | ||||
| 245 | |||||
| 246 | if (!s->accept) | ||||
| 247 | return true1; | ||||
| 248 | |||||
| 249 | LIST_FOREACH(port, p, s->ports)for ((p) = (s->ports); (p); (p) = (p)->port_next) { | ||||
| 250 | |||||
| 251 | if (p->type != SOCKET_SOCKET) | ||||
| 252 | return true1; | ||||
| 253 | |||||
| 254 | if (!socket_address_can_accept(&p->address)) | ||||
| 255 | return true1; | ||||
| 256 | } | ||||
| 257 | |||||
| 258 | return false0; | ||||
| 259 | } | ||||
| 260 | |||||
| 261 | static int socket_add_mount_dependencies(Socket *s) { | ||||
| 262 | SocketPort *p; | ||||
| 263 | int r; | ||||
| 264 | |||||
| 265 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/socket.c", 265, __PRETTY_FUNCTION__ ); } while (0); | ||||
| 266 | |||||
| 267 | LIST_FOREACH(port, p, s->ports)for ((p) = (s->ports); (p); (p) = (p)->port_next) { | ||||
| 268 | const char *path = NULL((void*)0); | ||||
| 269 | |||||
| 270 | if (p->type == SOCKET_SOCKET) | ||||
| 271 | path = socket_address_get_path(&p->address); | ||||
| 272 | else if (IN_SET(p->type, SOCKET_FIFO, SOCKET_SPECIAL, SOCKET_USB_FUNCTION)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SOCKET_FIFO, SOCKET_SPECIAL, SOCKET_USB_FUNCTION })/sizeof(int)]; switch(p->type) { case SOCKET_FIFO: case SOCKET_SPECIAL : case SOCKET_USB_FUNCTION: _found = 1; break; default: break ; } _found; })) | ||||
| 273 | path = p->path; | ||||
| 274 | |||||
| 275 | if (!path) | ||||
| 276 | continue; | ||||
| 277 | |||||
| 278 | r = unit_require_mounts_for(UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; }), path, UNIT_DEPENDENCY_FILE); | ||||
| 279 | if (r < 0) | ||||
| 280 | return r; | ||||
| 281 | } | ||||
| 282 | |||||
| 283 | return 0; | ||||
| 284 | } | ||||
| 285 | |||||
| 286 | static int socket_add_device_dependencies(Socket *s) { | ||||
| 287 | char *t; | ||||
| 288 | |||||
| 289 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/socket.c", 289, __PRETTY_FUNCTION__ ); } while (0); | ||||
| 290 | |||||
| 291 | if (!s->bind_to_device || streq(s->bind_to_device, "lo")(strcmp((s->bind_to_device),("lo")) == 0)) | ||||
| 292 | return 0; | ||||
| 293 | |||||
| 294 | t = strjoina("/sys/subsystem/net/devices/", s->bind_to_device)({ const char *_appendees_[] = { "/sys/subsystem/net/devices/" , s->bind_to_device }; char *_d_, *_p_; size_t _len_ = 0; size_t _i_; for (_i_ = 0; _i_ < __extension__ (__builtin_choose_expr ( !__builtin_types_compatible_p(typeof(_appendees_), typeof(& *(_appendees_))), sizeof(_appendees_)/sizeof((_appendees_)[0] ), ((void)0))) && _appendees_[_i_]; _i_++) _len_ += strlen (_appendees_[_i_]); _p_ = _d_ = __builtin_alloca (_len_ + 1); for (_i_ = 0; _i_ < __extension__ (__builtin_choose_expr( !__builtin_types_compatible_p(typeof(_appendees_), typeof(& *(_appendees_))), sizeof(_appendees_)/sizeof((_appendees_)[0] ), ((void)0))) && _appendees_[_i_]; _i_++) _p_ = stpcpy (_p_, _appendees_[_i_]); *_p_ = 0; _d_; }); | ||||
| 295 | return unit_add_node_dependency(UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; }), t, false0, UNIT_BINDS_TO, UNIT_DEPENDENCY_FILE); | ||||
| 296 | } | ||||
| 297 | |||||
| 298 | static int socket_add_default_dependencies(Socket *s) { | ||||
| 299 | int r; | ||||
| 300 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/socket.c", 300, __PRETTY_FUNCTION__ ); } while (0); | ||||
| 301 | |||||
| 302 | if (!UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })->default_dependencies) | ||||
| 303 | return 0; | ||||
| 304 | |||||
| 305 | r = unit_add_dependency_by_name(UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; }), UNIT_BEFORE, SPECIAL_SOCKETS_TARGET"sockets.target", NULL((void*)0), true1, UNIT_DEPENDENCY_DEFAULT); | ||||
| 306 | if (r < 0) | ||||
| 307 | return r; | ||||
| 308 | |||||
| 309 | if (MANAGER_IS_SYSTEM(UNIT(s)->manager)((({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })->manager)->unit_file_scope == UNIT_FILE_SYSTEM )) { | ||||
| 310 | r = unit_add_two_dependencies_by_name(UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; }), UNIT_AFTER, UNIT_REQUIRES, SPECIAL_SYSINIT_TARGET"sysinit.target", NULL((void*)0), true1, UNIT_DEPENDENCY_DEFAULT); | ||||
| 311 | if (r < 0) | ||||
| 312 | return r; | ||||
| 313 | } | ||||
| 314 | |||||
| 315 | return unit_add_two_dependencies_by_name(UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; }), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_SHUTDOWN_TARGET"shutdown.target", NULL((void*)0), true1, UNIT_DEPENDENCY_DEFAULT); | ||||
| 316 | } | ||||
| 317 | |||||
| 318 | _pure___attribute__ ((pure)) static bool_Bool socket_has_exec(Socket *s) { | ||||
| 319 | unsigned i; | ||||
| 320 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/socket.c", 320, __PRETTY_FUNCTION__ ); } while (0); | ||||
| 321 | |||||
| 322 | for (i = 0; i < _SOCKET_EXEC_COMMAND_MAX; i++) | ||||
| 323 | if (s->exec_command[i]) | ||||
| 324 | return true1; | ||||
| 325 | |||||
| 326 | return false0; | ||||
| 327 | } | ||||
| 328 | |||||
| 329 | static int socket_add_extras(Socket *s) { | ||||
| 330 | Unit *u = UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; }); | ||||
| 331 | int r; | ||||
| 332 | |||||
| 333 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/socket.c", 333, __PRETTY_FUNCTION__ ); } while (0); | ||||
| 334 | |||||
| 335 | /* Pick defaults for the trigger limit, if nothing was explicitly configured. We pick a relatively high limit | ||||
| 336 | * in Accept=yes mode, and a lower limit for Accept=no. Reason: in Accept=yes mode we are invoking accept() | ||||
| 337 | * ourselves before the trigger limit can hit, thus incoming connections are taken off the socket queue quickly | ||||
| 338 | * and reliably. This is different for Accept=no, where the spawned service has to take the incoming traffic | ||||
| 339 | * off the queues, which it might not necessarily do. Moreover, while Accept=no services are supposed to | ||||
| 340 | * process whatever is queued in one go, and thus should normally never have to be started frequently. This is | ||||
| 341 | * different for Accept=yes where each connection is processed by a new service instance, and thus frequent | ||||
| 342 | * service starts are typical. */ | ||||
| 343 | |||||
| 344 | if (s->trigger_limit.interval == USEC_INFINITY((usec_t) -1)) | ||||
| 345 | s->trigger_limit.interval = 2 * USEC_PER_SEC((usec_t) 1000000ULL); | ||||
| 346 | |||||
| 347 | if (s->trigger_limit.burst == (unsigned) -1) { | ||||
| 348 | if (s->accept) | ||||
| 349 | s->trigger_limit.burst = 200; | ||||
| 350 | else | ||||
| 351 | s->trigger_limit.burst = 20; | ||||
| 352 | } | ||||
| 353 | |||||
| 354 | if (have_non_accept_socket(s)) { | ||||
| 355 | |||||
| 356 | if (!UNIT_DEREF(s->service)((s->service).target)) { | ||||
| 357 | Unit *x; | ||||
| 358 | |||||
| 359 | r = unit_load_related_unit(u, ".service", &x); | ||||
| 360 | if (r < 0) | ||||
| 361 | return r; | ||||
| 362 | |||||
| 363 | unit_ref_set(&s->service, u, x); | ||||
| 364 | } | ||||
| 365 | |||||
| 366 | r = unit_add_two_dependencies(u, UNIT_BEFORE, UNIT_TRIGGERS, UNIT_DEREF(s->service)((s->service).target), true1, UNIT_DEPENDENCY_IMPLICIT); | ||||
| 367 | if (r < 0) | ||||
| 368 | return r; | ||||
| 369 | } | ||||
| 370 | |||||
| 371 | r = socket_add_mount_dependencies(s); | ||||
| 372 | if (r < 0) | ||||
| 373 | return r; | ||||
| 374 | |||||
| 375 | r = socket_add_device_dependencies(s); | ||||
| 376 | if (r < 0) | ||||
| 377 | return r; | ||||
| 378 | |||||
| 379 | r = unit_patch_contexts(u); | ||||
| 380 | if (r < 0) | ||||
| 381 | return r; | ||||
| 382 | |||||
| 383 | if (socket_has_exec(s)) { | ||||
| 384 | r = unit_add_exec_dependencies(u, &s->exec_context); | ||||
| 385 | if (r < 0) | ||||
| 386 | return r; | ||||
| 387 | } | ||||
| 388 | |||||
| 389 | r = unit_set_default_slice(u); | ||||
| 390 | if (r < 0) | ||||
| 391 | return r; | ||||
| 392 | |||||
| 393 | r = socket_add_default_dependencies(s); | ||||
| 394 | if (r < 0) | ||||
| 395 | return r; | ||||
| 396 | |||||
| 397 | return 0; | ||||
| 398 | } | ||||
| 399 | |||||
| 400 | static const char *socket_find_symlink_target(Socket *s) { | ||||
| 401 | const char *found = NULL((void*)0); | ||||
| 402 | SocketPort *p; | ||||
| 403 | |||||
| 404 | LIST_FOREACH(port, p, s->ports)for ((p) = (s->ports); (p); (p) = (p)->port_next) { | ||||
| 405 | const char *f = NULL((void*)0); | ||||
| 406 | |||||
| 407 | switch (p->type) { | ||||
| 408 | |||||
| 409 | case SOCKET_FIFO: | ||||
| 410 | f = p->path; | ||||
| 411 | break; | ||||
| 412 | |||||
| 413 | case SOCKET_SOCKET: | ||||
| 414 | f = socket_address_get_path(&p->address); | ||||
| 415 | break; | ||||
| 416 | |||||
| 417 | default: | ||||
| 418 | break; | ||||
| 419 | } | ||||
| 420 | |||||
| 421 | if (f) { | ||||
| 422 | if (found) | ||||
| 423 | return NULL((void*)0); | ||||
| 424 | |||||
| 425 | found = f; | ||||
| 426 | } | ||||
| 427 | } | ||||
| 428 | |||||
| 429 | return found; | ||||
| 430 | } | ||||
| 431 | |||||
| 432 | static int socket_verify(Socket *s) { | ||||
| 433 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/socket.c", 433, __PRETTY_FUNCTION__ ); } while (0); | ||||
| 434 | |||||
| 435 | if (UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })->load_state != UNIT_LOADED) | ||||
| 436 | return 0; | ||||
| 437 | |||||
| 438 | if (!s->ports) { | ||||
| 439 | log_unit_error(UNIT(s), "Unit has no Listen setting (ListenStream=, ListenDatagram=, ListenFIFO=, ...). Refusing.")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (3, 0, "../src/core/socket.c", 439, __func__, _u->manager-> unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Unit has no Listen setting (ListenStream=, ListenDatagram=, ListenFIFO=, ...). Refusing." ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3 ))), 0, "../src/core/socket.c", 439, __func__, "Unit has no Listen setting (ListenStream=, ListenDatagram=, ListenFIFO=, ...). Refusing." ); }); | ||||
| 440 | return -ENOEXEC8; | ||||
| 441 | } | ||||
| 442 | |||||
| 443 | if (s->accept && have_non_accept_socket(s)) { | ||||
| 444 | log_unit_error(UNIT(s), "Unit configured for accepting sockets, but sockets are non-accepting. Refusing.")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (3, 0, "../src/core/socket.c", 444, __func__, _u->manager-> unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Unit configured for accepting sockets, but sockets are non-accepting. Refusing." ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3 ))), 0, "../src/core/socket.c", 444, __func__, "Unit configured for accepting sockets, but sockets are non-accepting. Refusing." ); }); | ||||
| 445 | return -ENOEXEC8; | ||||
| 446 | } | ||||
| 447 | |||||
| 448 | if (s->accept && s->max_connections <= 0) { | ||||
| 449 | log_unit_error(UNIT(s), "MaxConnection= setting too small. Refusing.")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (3, 0, "../src/core/socket.c", 449, __func__, _u->manager-> unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "MaxConnection= setting too small. Refusing." ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3 ))), 0, "../src/core/socket.c", 449, __func__, "MaxConnection= setting too small. Refusing." ); }); | ||||
| 450 | return -ENOEXEC8; | ||||
| 451 | } | ||||
| 452 | |||||
| 453 | if (s->accept && UNIT_DEREF(s->service)((s->service).target)) { | ||||
| 454 | log_unit_error(UNIT(s), "Explicit service configuration for accepting socket units not supported. Refusing.")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (3, 0, "../src/core/socket.c", 454, __func__, _u->manager-> unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Explicit service configuration for accepting socket units not supported. Refusing." ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3 ))), 0, "../src/core/socket.c", 454, __func__, "Explicit service configuration for accepting socket units not supported. Refusing." ); }); | ||||
| 455 | return -ENOEXEC8; | ||||
| 456 | } | ||||
| 457 | |||||
| 458 | if (s->exec_context.pam_name && s->kill_context.kill_mode != KILL_CONTROL_GROUP) { | ||||
| 459 | log_unit_error(UNIT(s), "Unit has PAM enabled. Kill mode must be set to 'control-group'. Refusing.")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (3, 0, "../src/core/socket.c", 459, __func__, _u->manager-> unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Unit has PAM enabled. Kill mode must be set to 'control-group'. Refusing." ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3 ))), 0, "../src/core/socket.c", 459, __func__, "Unit has PAM enabled. Kill mode must be set to 'control-group'. Refusing." ); }); | ||||
| 460 | return -ENOEXEC8; | ||||
| 461 | } | ||||
| 462 | |||||
| 463 | if (!strv_isempty(s->symlinks) && !socket_find_symlink_target(s)) { | ||||
| 464 | log_unit_error(UNIT(s), "Unit has symlinks set but none or more than one node in the file system. Refusing.")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (3, 0, "../src/core/socket.c", 464, __func__, _u->manager-> unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Unit has symlinks set but none or more than one node in the file system. Refusing." ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3 ))), 0, "../src/core/socket.c", 464, __func__, "Unit has symlinks set but none or more than one node in the file system. Refusing." ); }); | ||||
| 465 | return -ENOEXEC8; | ||||
| 466 | } | ||||
| 467 | |||||
| 468 | return 0; | ||||
| 469 | } | ||||
| 470 | |||||
| 471 | static void peer_address_hash_func(const void *p, struct siphash *state) { | ||||
| 472 | const SocketPeer *s = p; | ||||
| 473 | |||||
| 474 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/socket.c", 474, __PRETTY_FUNCTION__ ); } while (0); | ||||
| 475 | |||||
| 476 | if (s->peer.sa.sa_family == AF_INET2) | ||||
| 477 | siphash24_compress(&s->peer.in.sin_addr, sizeof(s->peer.in.sin_addr), state); | ||||
| 478 | else if (s->peer.sa.sa_family == AF_INET610) | ||||
| 479 | siphash24_compress(&s->peer.in6.sin6_addr, sizeof(s->peer.in6.sin6_addr), state); | ||||
| 480 | else if (s->peer.sa.sa_family == AF_VSOCK40) | ||||
| 481 | siphash24_compress(&s->peer.vm.svm_cid, sizeof(s->peer.vm.svm_cid), state); | ||||
| 482 | else | ||||
| 483 | assert_not_reached("Unknown address family.")do { log_assert_failed_unreachable_realm(LOG_REALM_SYSTEMD, ( "Unknown address family."), "../src/core/socket.c", 483, __PRETTY_FUNCTION__ ); } while (0); | ||||
| 484 | } | ||||
| 485 | |||||
| 486 | static int peer_address_compare_func(const void *a, const void *b) { | ||||
| 487 | const SocketPeer *x = a, *y = b; | ||||
| 488 | |||||
| 489 | if (x->peer.sa.sa_family < y->peer.sa.sa_family) | ||||
| 490 | return -1; | ||||
| 491 | if (x->peer.sa.sa_family > y->peer.sa.sa_family) | ||||
| 492 | return 1; | ||||
| 493 | |||||
| 494 | switch(x->peer.sa.sa_family) { | ||||
| 495 | case AF_INET2: | ||||
| 496 | return memcmp(&x->peer.in.sin_addr, &y->peer.in.sin_addr, sizeof(x->peer.in.sin_addr)); | ||||
| 497 | case AF_INET610: | ||||
| 498 | return memcmp(&x->peer.in6.sin6_addr, &y->peer.in6.sin6_addr, sizeof(x->peer.in6.sin6_addr)); | ||||
| 499 | case AF_VSOCK40: | ||||
| 500 | if (x->peer.vm.svm_cid < y->peer.vm.svm_cid) | ||||
| 501 | return -1; | ||||
| 502 | if (x->peer.vm.svm_cid > y->peer.vm.svm_cid) | ||||
| 503 | return 1; | ||||
| 504 | return 0; | ||||
| 505 | } | ||||
| 506 | assert_not_reached("Black sheep in the family!")do { log_assert_failed_unreachable_realm(LOG_REALM_SYSTEMD, ( "Black sheep in the family!"), "../src/core/socket.c", 506, __PRETTY_FUNCTION__ ); } while (0); | ||||
| 507 | } | ||||
| 508 | |||||
| 509 | const struct hash_ops peer_address_hash_ops = { | ||||
| 510 | .hash = peer_address_hash_func, | ||||
| 511 | .compare = peer_address_compare_func | ||||
| 512 | }; | ||||
| 513 | |||||
| 514 | static int socket_load(Unit *u) { | ||||
| 515 | Socket *s = SOCKET(u); | ||||
| 516 | int r; | ||||
| 517 | |||||
| 518 | assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("u"), "../src/core/socket.c", 518, __PRETTY_FUNCTION__ ); } while (0); | ||||
| 519 | assert(u->load_state == UNIT_STUB)do { if ((__builtin_expect(!!(!(u->load_state == UNIT_STUB )),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("u->load_state == UNIT_STUB" ), "../src/core/socket.c", 519, __PRETTY_FUNCTION__); } while (0); | ||||
| 520 | |||||
| 521 | r = set_ensure_allocated(&s->peers_by_address, &peer_address_hash_ops)internal_set_ensure_allocated(&s->peers_by_address, & peer_address_hash_ops ); | ||||
| 522 | if (r < 0) | ||||
| 523 | return r; | ||||
| 524 | |||||
| 525 | r = unit_load_fragment_and_dropin(u); | ||||
| 526 | if (r < 0) | ||||
| 527 | return r; | ||||
| 528 | |||||
| 529 | if (u->load_state == UNIT_LOADED) { | ||||
| 530 | /* This is a new unit? Then let's add in some extras */ | ||||
| 531 | r = socket_add_extras(s); | ||||
| 532 | if (r < 0) | ||||
| 533 | return r; | ||||
| 534 | } | ||||
| 535 | |||||
| 536 | return socket_verify(s); | ||||
| 537 | } | ||||
| 538 | |||||
| 539 | static SocketPeer *socket_peer_new(void) { | ||||
| 540 | SocketPeer *p; | ||||
| 541 | |||||
| 542 | p = new0(SocketPeer, 1)((SocketPeer*) calloc((1), sizeof(SocketPeer))); | ||||
| 543 | if (!p) | ||||
| 544 | return NULL((void*)0); | ||||
| 545 | |||||
| 546 | p->n_ref = 1; | ||||
| 547 | |||||
| 548 | return p; | ||||
| 549 | } | ||||
| 550 | |||||
| 551 | SocketPeer *socket_peer_ref(SocketPeer *p) { | ||||
| 552 | if (!p) | ||||
| 553 | return NULL((void*)0); | ||||
| 554 | |||||
| 555 | assert(p->n_ref > 0)do { if ((__builtin_expect(!!(!(p->n_ref > 0)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("p->n_ref > 0"), "../src/core/socket.c" , 555, __PRETTY_FUNCTION__); } while (0); | ||||
| 556 | p->n_ref++; | ||||
| 557 | |||||
| 558 | return p; | ||||
| 559 | } | ||||
| 560 | |||||
| 561 | SocketPeer *socket_peer_unref(SocketPeer *p) { | ||||
| 562 | if (!p) | ||||
| 563 | return NULL((void*)0); | ||||
| 564 | |||||
| 565 | assert(p->n_ref > 0)do { if ((__builtin_expect(!!(!(p->n_ref > 0)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("p->n_ref > 0"), "../src/core/socket.c" , 565, __PRETTY_FUNCTION__); } while (0); | ||||
| 566 | |||||
| 567 | p->n_ref--; | ||||
| 568 | |||||
| 569 | if (p->n_ref > 0) | ||||
| 570 | return NULL((void*)0); | ||||
| 571 | |||||
| 572 | if (p->socket) | ||||
| 573 | set_remove(p->socket->peers_by_address, p); | ||||
| 574 | |||||
| 575 | return mfree(p); | ||||
| 576 | } | ||||
| 577 | |||||
| 578 | int socket_acquire_peer(Socket *s, int fd, SocketPeer **p) { | ||||
| 579 | _cleanup_(socket_peer_unrefp)__attribute__((cleanup(socket_peer_unrefp))) SocketPeer *remote = NULL((void*)0); | ||||
| 580 | SocketPeer sa = {}, *i; | ||||
| 581 | socklen_t salen = sizeof(sa.peer); | ||||
| 582 | int r; | ||||
| 583 | |||||
| 584 | assert(fd >= 0)do { if ((__builtin_expect(!!(!(fd >= 0)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("fd >= 0"), "../src/core/socket.c", 584 , __PRETTY_FUNCTION__); } while (0); | ||||
| 585 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/socket.c", 585, __PRETTY_FUNCTION__ ); } while (0); | ||||
| 586 | |||||
| 587 | r = getpeername(fd, &sa.peer.sa, &salen); | ||||
| 588 | if (r < 0) | ||||
| 589 | return log_error_errno(errno, "getpeername failed: %m")({ int _level = ((3)), _e = (((*__errno_location ()))), _realm = (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >= ((_level) & 0x07)) ? log_internal_realm(((_realm) << 10 | (_level)), _e, "../src/core/socket.c", 589, __func__, "getpeername failed: %m" ) : -abs(_e); }); | ||||
| 590 | |||||
| 591 | if (!IN_SET(sa.peer.sa.sa_family, AF_INET, AF_INET6, AF_VSOCK)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){2, 10, 40})/sizeof(int)]; switch(sa.peer .sa.sa_family) { case 2: case 10: case 40: _found = 1; break; default: break; } _found; })) { | ||||
| 592 | *p = NULL((void*)0); | ||||
| 593 | return 0; | ||||
| 594 | } | ||||
| 595 | |||||
| 596 | i = set_get(s->peers_by_address, &sa); | ||||
| 597 | if (i) { | ||||
| 598 | *p = socket_peer_ref(i); | ||||
| 599 | return 1; | ||||
| 600 | } | ||||
| 601 | |||||
| 602 | remote = socket_peer_new(); | ||||
| 603 | if (!remote
| ||||
| 604 | return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/core/socket.c", 604 , __func__); | ||||
| 605 | |||||
| 606 | remote->peer = sa.peer; | ||||
| 607 | remote->peer_salen = salen; | ||||
| 608 | |||||
| 609 | r = set_put(s->peers_by_address, remote); | ||||
| 610 | if (r < 0) | ||||
| 611 | return r; | ||||
| 612 | |||||
| 613 | remote->socket = s; | ||||
| 614 | |||||
| 615 | *p = TAKE_PTR(remote)({ typeof(remote) _ptr_ = (remote); (remote) = ((void*)0); _ptr_ ; }); | ||||
| 616 | |||||
| 617 | return 1; | ||||
| 618 | } | ||||
| 619 | |||||
| 620 | _const___attribute__ ((const)) static const char* listen_lookup(int family, int type) { | ||||
| 621 | |||||
| 622 | if (family == AF_NETLINK16) | ||||
| 623 | return "ListenNetlink"; | ||||
| 624 | |||||
| 625 | if (type == SOCK_STREAMSOCK_STREAM) | ||||
| 626 | return "ListenStream"; | ||||
| 627 | else if (type == SOCK_DGRAMSOCK_DGRAM) | ||||
| 628 | return "ListenDatagram"; | ||||
| 629 | else if (type == SOCK_SEQPACKETSOCK_SEQPACKET) | ||||
| 630 | return "ListenSequentialPacket"; | ||||
| 631 | |||||
| 632 | assert_not_reached("Unknown socket type")do { log_assert_failed_unreachable_realm(LOG_REALM_SYSTEMD, ( "Unknown socket type"), "../src/core/socket.c", 632, __PRETTY_FUNCTION__ ); } while (0); | ||||
| 633 | return NULL((void*)0); | ||||
| 634 | } | ||||
| 635 | |||||
| 636 | static void socket_dump(Unit *u, FILE *f, const char *prefix) { | ||||
| 637 | char time_string[FORMAT_TIMESPAN_MAX64]; | ||||
| 638 | SocketExecCommand c; | ||||
| 639 | Socket *s = SOCKET(u); | ||||
| 640 | SocketPort *p; | ||||
| 641 | const char *prefix2, *str; | ||||
| 642 | |||||
| 643 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/socket.c", 643, __PRETTY_FUNCTION__ ); } while (0); | ||||
| 644 | assert(f)do { if ((__builtin_expect(!!(!(f)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("f"), "../src/core/socket.c", 644, __PRETTY_FUNCTION__ ); } while (0); | ||||
| 645 | |||||
| 646 | prefix = strempty(prefix); | ||||
| 647 | prefix2 = strjoina(prefix, "\t")({ const char *_appendees_[] = { prefix, "\t" }; char *_d_, * _p_; size_t _len_ = 0; size_t _i_; for (_i_ = 0; _i_ < __extension__ (__builtin_choose_expr( !__builtin_types_compatible_p(typeof (_appendees_), typeof(&*(_appendees_))), sizeof(_appendees_ )/sizeof((_appendees_)[0]), ((void)0))) && _appendees_ [_i_]; _i_++) _len_ += strlen(_appendees_[_i_]); _p_ = _d_ = __builtin_alloca (_len_ + 1); for (_i_ = 0; _i_ < __extension__ (__builtin_choose_expr ( !__builtin_types_compatible_p(typeof(_appendees_), typeof(& *(_appendees_))), sizeof(_appendees_)/sizeof((_appendees_)[0] ), ((void)0))) && _appendees_[_i_]; _i_++) _p_ = stpcpy (_p_, _appendees_[_i_]); *_p_ = 0; _d_; }); | ||||
| 648 | |||||
| 649 | fprintf(f, | ||||
| 650 | "%sSocket State: %s\n" | ||||
| 651 | "%sResult: %s\n" | ||||
| 652 | "%sBindIPv6Only: %s\n" | ||||
| 653 | "%sBacklog: %u\n" | ||||
| 654 | "%sSocketMode: %04o\n" | ||||
| 655 | "%sDirectoryMode: %04o\n" | ||||
| 656 | "%sKeepAlive: %s\n" | ||||
| 657 | "%sNoDelay: %s\n" | ||||
| 658 | "%sFreeBind: %s\n" | ||||
| 659 | "%sTransparent: %s\n" | ||||
| 660 | "%sBroadcast: %s\n" | ||||
| 661 | "%sPassCredentials: %s\n" | ||||
| 662 | "%sPassSecurity: %s\n" | ||||
| 663 | "%sPassPacketInfo: %s\n" | ||||
| 664 | "%sTCPCongestion: %s\n" | ||||
| 665 | "%sRemoveOnStop: %s\n" | ||||
| 666 | "%sWritable: %s\n" | ||||
| 667 | "%sFileDescriptorName: %s\n" | ||||
| 668 | "%sSELinuxContextFromNet: %s\n", | ||||
| 669 | prefix, socket_state_to_string(s->state), | ||||
| 670 | prefix, socket_result_to_string(s->result), | ||||
| 671 | prefix, socket_address_bind_ipv6_only_to_string(s->bind_ipv6_only), | ||||
| 672 | prefix, s->backlog, | ||||
| 673 | prefix, s->socket_mode, | ||||
| 674 | prefix, s->directory_mode, | ||||
| 675 | prefix, yes_no(s->keep_alive), | ||||
| 676 | prefix, yes_no(s->no_delay), | ||||
| 677 | prefix, yes_no(s->free_bind), | ||||
| 678 | prefix, yes_no(s->transparent), | ||||
| 679 | prefix, yes_no(s->broadcast), | ||||
| 680 | prefix, yes_no(s->pass_cred), | ||||
| 681 | prefix, yes_no(s->pass_sec), | ||||
| 682 | prefix, yes_no(s->pass_pktinfo), | ||||
| 683 | prefix, strna(s->tcp_congestion), | ||||
| 684 | prefix, yes_no(s->remove_on_stop), | ||||
| 685 | prefix, yes_no(s->writable), | ||||
| 686 | prefix, socket_fdname(s), | ||||
| 687 | prefix, yes_no(s->selinux_context_from_net)); | ||||
| 688 | |||||
| 689 | if (s->control_pid > 0) | ||||
| 690 | fprintf(f, | ||||
| 691 | "%sControl PID: "PID_FMT"%" "i""\n", | ||||
| 692 | prefix, s->control_pid); | ||||
| 693 | |||||
| 694 | if (s->bind_to_device) | ||||
| 695 | fprintf(f, | ||||
| 696 | "%sBindToDevice: %s\n", | ||||
| 697 | prefix, s->bind_to_device); | ||||
| 698 | |||||
| 699 | if (s->accept) | ||||
| 700 | fprintf(f, | ||||
| 701 | "%sAccepted: %u\n" | ||||
| 702 | "%sNConnections: %u\n" | ||||
| 703 | "%sMaxConnections: %u\n" | ||||
| 704 | "%sMaxConnectionsPerSource: %u\n", | ||||
| 705 | prefix, s->n_accepted, | ||||
| 706 | prefix, s->n_connections, | ||||
| 707 | prefix, s->max_connections, | ||||
| 708 | prefix, s->max_connections_per_source); | ||||
| 709 | else | ||||
| 710 | fprintf(f, | ||||
| 711 | "%sFlushPending: %s\n", | ||||
| 712 | prefix, yes_no(s->flush_pending)); | ||||
| 713 | |||||
| 714 | |||||
| 715 | if (s->priority >= 0) | ||||
| 716 | fprintf(f, | ||||
| 717 | "%sPriority: %i\n", | ||||
| 718 | prefix, s->priority); | ||||
| 719 | |||||
| 720 | if (s->receive_buffer > 0) | ||||
| 721 | fprintf(f, | ||||
| 722 | "%sReceiveBuffer: %zu\n", | ||||
| 723 | prefix, s->receive_buffer); | ||||
| 724 | |||||
| 725 | if (s->send_buffer > 0) | ||||
| 726 | fprintf(f, | ||||
| 727 | "%sSendBuffer: %zu\n", | ||||
| 728 | prefix, s->send_buffer); | ||||
| 729 | |||||
| 730 | if (s->ip_tos >= 0) | ||||
| 731 | fprintf(f, | ||||
| 732 | "%sIPTOS: %i\n", | ||||
| 733 | prefix, s->ip_tos); | ||||
| 734 | |||||
| 735 | if (s->ip_ttl >= 0) | ||||
| 736 | fprintf(f, | ||||
| 737 | "%sIPTTL: %i\n", | ||||
| 738 | prefix, s->ip_ttl); | ||||
| 739 | |||||
| 740 | if (s->pipe_size > 0) | ||||
| 741 | fprintf(f, | ||||
| 742 | "%sPipeSize: %zu\n", | ||||
| 743 | prefix, s->pipe_size); | ||||
| 744 | |||||
| 745 | if (s->mark >= 0) | ||||
| 746 | fprintf(f, | ||||
| 747 | "%sMark: %i\n", | ||||
| 748 | prefix, s->mark); | ||||
| 749 | |||||
| 750 | if (s->mq_maxmsg > 0) | ||||
| 751 | fprintf(f, | ||||
| 752 | "%sMessageQueueMaxMessages: %li\n", | ||||
| 753 | prefix, s->mq_maxmsg); | ||||
| 754 | |||||
| 755 | if (s->mq_msgsize > 0) | ||||
| 756 | fprintf(f, | ||||
| 757 | "%sMessageQueueMessageSize: %li\n", | ||||
| 758 | prefix, s->mq_msgsize); | ||||
| 759 | |||||
| 760 | if (s->reuse_port) | ||||
| 761 | fprintf(f, | ||||
| 762 | "%sReusePort: %s\n", | ||||
| 763 | prefix, yes_no(s->reuse_port)); | ||||
| 764 | |||||
| 765 | if (s->smack) | ||||
| 766 | fprintf(f, | ||||
| 767 | "%sSmackLabel: %s\n", | ||||
| 768 | prefix, s->smack); | ||||
| 769 | |||||
| 770 | if (s->smack_ip_in) | ||||
| 771 | fprintf(f, | ||||
| 772 | "%sSmackLabelIPIn: %s\n", | ||||
| 773 | prefix, s->smack_ip_in); | ||||
| 774 | |||||
| 775 | if (s->smack_ip_out) | ||||
| 776 | fprintf(f, | ||||
| 777 | "%sSmackLabelIPOut: %s\n", | ||||
| 778 | prefix, s->smack_ip_out); | ||||
| 779 | |||||
| 780 | if (!isempty(s->user) || !isempty(s->group)) | ||||
| 781 | fprintf(f, | ||||
| 782 | "%sSocketUser: %s\n" | ||||
| 783 | "%sSocketGroup: %s\n", | ||||
| 784 | prefix, strna(s->user), | ||||
| 785 | prefix, strna(s->group)); | ||||
| 786 | |||||
| 787 | if (s->keep_alive_time > 0) | ||||
| 788 | fprintf(f, | ||||
| 789 | "%sKeepAliveTimeSec: %s\n", | ||||
| 790 | prefix, format_timespan(time_string, FORMAT_TIMESPAN_MAX64, s->keep_alive_time, USEC_PER_SEC((usec_t) 1000000ULL))); | ||||
| 791 | |||||
| 792 | if (s->keep_alive_interval > 0) | ||||
| 793 | fprintf(f, | ||||
| 794 | "%sKeepAliveIntervalSec: %s\n", | ||||
| 795 | prefix, format_timespan(time_string, FORMAT_TIMESPAN_MAX64, s->keep_alive_interval, USEC_PER_SEC((usec_t) 1000000ULL))); | ||||
| 796 | |||||
| 797 | if (s->keep_alive_cnt > 0) | ||||
| 798 | fprintf(f, | ||||
| 799 | "%sKeepAliveProbes: %u\n", | ||||
| 800 | prefix, s->keep_alive_cnt); | ||||
| 801 | |||||
| 802 | if (s->defer_accept > 0) | ||||
| 803 | fprintf(f, | ||||
| 804 | "%sDeferAcceptSec: %s\n", | ||||
| 805 | prefix, format_timespan(time_string, FORMAT_TIMESPAN_MAX64, s->defer_accept, USEC_PER_SEC((usec_t) 1000000ULL))); | ||||
| 806 | |||||
| 807 | LIST_FOREACH(port, p, s->ports)for ((p) = (s->ports); (p); (p) = (p)->port_next) { | ||||
| 808 | |||||
| 809 | switch (p->type) { | ||||
| 810 | case SOCKET_SOCKET: { | ||||
| 811 | _cleanup_free___attribute__((cleanup(freep))) char *k = NULL((void*)0); | ||||
| 812 | const char *t; | ||||
| 813 | int r; | ||||
| 814 | |||||
| 815 | r = socket_address_print(&p->address, &k); | ||||
| 816 | if (r < 0) | ||||
| 817 | t = strerror(-r); | ||||
| 818 | else | ||||
| 819 | t = k; | ||||
| 820 | |||||
| 821 | fprintf(f, "%s%s: %s\n", prefix, listen_lookup(socket_address_family(&p->address)((&p->address)->sockaddr.sa.sa_family), p->address.type), t); | ||||
| 822 | break; | ||||
| 823 | } | ||||
| 824 | case SOCKET_SPECIAL: | ||||
| 825 | fprintf(f, "%sListenSpecial: %s\n", prefix, p->path); | ||||
| 826 | break; | ||||
| 827 | case SOCKET_USB_FUNCTION: | ||||
| 828 | fprintf(f, "%sListenUSBFunction: %s\n", prefix, p->path); | ||||
| 829 | break; | ||||
| 830 | case SOCKET_MQUEUE: | ||||
| 831 | fprintf(f, "%sListenMessageQueue: %s\n", prefix, p->path); | ||||
| 832 | break; | ||||
| 833 | default: | ||||
| 834 | fprintf(f, "%sListenFIFO: %s\n", prefix, p->path); | ||||
| 835 | } | ||||
| 836 | } | ||||
| 837 | |||||
| 838 | fprintf(f, | ||||
| 839 | "%sTriggerLimitIntervalSec: %s\n" | ||||
| 840 | "%sTriggerLimitBurst: %u\n", | ||||
| 841 | prefix, format_timespan(time_string, FORMAT_TIMESPAN_MAX64, s->trigger_limit.interval, USEC_PER_SEC((usec_t) 1000000ULL)), | ||||
| 842 | prefix, s->trigger_limit.burst); | ||||
| 843 | |||||
| 844 | str = socket_protocol_to_name(s->socket_protocol); | ||||
| 845 | if (str) | ||||
| 846 | fprintf(f, "%sSocketProtocol: %s\n", prefix, str); | ||||
| 847 | |||||
| 848 | if (!strv_isempty(s->symlinks)) { | ||||
| 849 | char **q; | ||||
| 850 | |||||
| 851 | fprintf(f, "%sSymlinks:", prefix); | ||||
| 852 | STRV_FOREACH(q, s->symlinks)for ((q) = (s->symlinks); (q) && *(q); (q)++) | ||||
| 853 | fprintf(f, " %s", *q); | ||||
| 854 | |||||
| 855 | fprintf(f, "\n"); | ||||
| 856 | } | ||||
| 857 | |||||
| 858 | fprintf(f, | ||||
| 859 | "%sTimeoutSec: %s\n", | ||||
| 860 | prefix, format_timespan(time_string, FORMAT_TIMESPAN_MAX64, s->timeout_usec, USEC_PER_SEC((usec_t) 1000000ULL))); | ||||
| 861 | |||||
| 862 | exec_context_dump(&s->exec_context, f, prefix); | ||||
| 863 | kill_context_dump(&s->kill_context, f, prefix); | ||||
| 864 | |||||
| 865 | for (c = 0; c < _SOCKET_EXEC_COMMAND_MAX; c++) { | ||||
| 866 | if (!s->exec_command[c]) | ||||
| 867 | continue; | ||||
| 868 | |||||
| 869 | fprintf(f, "%s-> %s:\n", | ||||
| 870 | prefix, socket_exec_command_to_string(c)); | ||||
| 871 | |||||
| 872 | exec_command_dump_list(s->exec_command[c], f, prefix2); | ||||
| 873 | } | ||||
| 874 | |||||
| 875 | cgroup_context_dump(&s->cgroup_context, f, prefix); | ||||
| 876 | } | ||||
| 877 | |||||
| 878 | static int instance_from_socket(int fd, unsigned nr, char **instance) { | ||||
| 879 | socklen_t l; | ||||
| 880 | char *r; | ||||
| 881 | union sockaddr_union local, remote; | ||||
| 882 | |||||
| 883 | assert(fd >= 0)do { if ((__builtin_expect(!!(!(fd >= 0)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("fd >= 0"), "../src/core/socket.c", 883 , __PRETTY_FUNCTION__); } while (0); | ||||
| 884 | assert(instance)do { if ((__builtin_expect(!!(!(instance)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("instance"), "../src/core/socket.c", 884 , __PRETTY_FUNCTION__); } while (0); | ||||
| 885 | |||||
| 886 | l = sizeof(local); | ||||
| 887 | if (getsockname(fd, &local.sa, &l) < 0) | ||||
| 888 | return -errno(*__errno_location ()); | ||||
| 889 | |||||
| 890 | l = sizeof(remote); | ||||
| 891 | if (getpeername(fd, &remote.sa, &l) < 0) | ||||
| 892 | return -errno(*__errno_location ()); | ||||
| 893 | |||||
| 894 | switch (local.sa.sa_family) { | ||||
| 895 | |||||
| 896 | case AF_INET2: { | ||||
| 897 | uint32_t | ||||
| 898 | a = be32toh(local.in.sin_addr.s_addr)__bswap_32 (local.in.sin_addr.s_addr), | ||||
| 899 | b = be32toh(remote.in.sin_addr.s_addr)__bswap_32 (remote.in.sin_addr.s_addr); | ||||
| 900 | |||||
| 901 | if (asprintf(&r, | ||||
| 902 | "%u-%u.%u.%u.%u:%u-%u.%u.%u.%u:%u", | ||||
| 903 | nr, | ||||
| 904 | a >> 24, (a >> 16) & 0xFF, (a >> 8) & 0xFF, a & 0xFF, | ||||
| 905 | be16toh(local.in.sin_port)__bswap_16 (local.in.sin_port), | ||||
| 906 | b >> 24, (b >> 16) & 0xFF, (b >> 8) & 0xFF, b & 0xFF, | ||||
| 907 | be16toh(remote.in.sin_port)__bswap_16 (remote.in.sin_port)) < 0) | ||||
| 908 | return -ENOMEM12; | ||||
| 909 | |||||
| 910 | break; | ||||
| 911 | } | ||||
| 912 | |||||
| 913 | case AF_INET610: { | ||||
| 914 | static const unsigned char ipv4_prefix[] = { | ||||
| 915 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF | ||||
| 916 | }; | ||||
| 917 | |||||
| 918 | if (memcmp(&local.in6.sin6_addr, ipv4_prefix, sizeof(ipv4_prefix)) == 0 && | ||||
| 919 | memcmp(&remote.in6.sin6_addr, ipv4_prefix, sizeof(ipv4_prefix)) == 0) { | ||||
| 920 | const uint8_t | ||||
| 921 | *a = local.in6.sin6_addr.s6_addr__in6_u.__u6_addr8+12, | ||||
| 922 | *b = remote.in6.sin6_addr.s6_addr__in6_u.__u6_addr8+12; | ||||
| 923 | |||||
| 924 | if (asprintf(&r, | ||||
| 925 | "%u-%u.%u.%u.%u:%u-%u.%u.%u.%u:%u", | ||||
| 926 | nr, | ||||
| 927 | a[0], a[1], a[2], a[3], | ||||
| 928 | be16toh(local.in6.sin6_port)__bswap_16 (local.in6.sin6_port), | ||||
| 929 | b[0], b[1], b[2], b[3], | ||||
| 930 | be16toh(remote.in6.sin6_port)__bswap_16 (remote.in6.sin6_port)) < 0) | ||||
| 931 | return -ENOMEM12; | ||||
| 932 | } else { | ||||
| 933 | char a[INET6_ADDRSTRLEN46], b[INET6_ADDRSTRLEN46]; | ||||
| 934 | |||||
| 935 | if (asprintf(&r, | ||||
| 936 | "%u-%s:%u-%s:%u", | ||||
| 937 | nr, | ||||
| 938 | inet_ntop(AF_INET610, &local.in6.sin6_addr, a, sizeof(a)), | ||||
| 939 | be16toh(local.in6.sin6_port)__bswap_16 (local.in6.sin6_port), | ||||
| 940 | inet_ntop(AF_INET610, &remote.in6.sin6_addr, b, sizeof(b)), | ||||
| 941 | be16toh(remote.in6.sin6_port)__bswap_16 (remote.in6.sin6_port)) < 0) | ||||
| 942 | return -ENOMEM12; | ||||
| 943 | } | ||||
| 944 | |||||
| 945 | break; | ||||
| 946 | } | ||||
| 947 | |||||
| 948 | case AF_UNIX1: { | ||||
| 949 | struct ucred ucred; | ||||
| 950 | int k; | ||||
| 951 | |||||
| 952 | k = getpeercred(fd, &ucred); | ||||
| 953 | if (k >= 0) { | ||||
| 954 | if (asprintf(&r, | ||||
| 955 | "%u-"PID_FMT"%" "i""-"UID_FMT"%" "u", | ||||
| 956 | nr, ucred.pid, ucred.uid) < 0) | ||||
| 957 | return -ENOMEM12; | ||||
| 958 | } else if (k == -ENODATA61) { | ||||
| 959 | /* This handles the case where somebody is | ||||
| 960 | * connecting from another pid/uid namespace | ||||
| 961 | * (e.g. from outside of our container). */ | ||||
| 962 | if (asprintf(&r, | ||||
| 963 | "%u-unknown", | ||||
| 964 | nr) < 0) | ||||
| 965 | return -ENOMEM12; | ||||
| 966 | } else | ||||
| 967 | return k; | ||||
| 968 | |||||
| 969 | break; | ||||
| 970 | } | ||||
| 971 | |||||
| 972 | case AF_VSOCK40: | ||||
| 973 | if (asprintf(&r, | ||||
| 974 | "%u-%u:%u-%u:%u", | ||||
| 975 | nr, | ||||
| 976 | local.vm.svm_cid, local.vm.svm_port, | ||||
| 977 | remote.vm.svm_cid, remote.vm.svm_port) < 0) | ||||
| 978 | return -ENOMEM12; | ||||
| 979 | |||||
| 980 | break; | ||||
| 981 | |||||
| 982 | default: | ||||
| 983 | assert_not_reached("Unhandled socket type.")do { log_assert_failed_unreachable_realm(LOG_REALM_SYSTEMD, ( "Unhandled socket type."), "../src/core/socket.c", 983, __PRETTY_FUNCTION__ ); } while (0); | ||||
| 984 | } | ||||
| 985 | |||||
| 986 | *instance = r; | ||||
| 987 | return 0; | ||||
| 988 | } | ||||
| 989 | |||||
| 990 | static void socket_close_fds(Socket *s) { | ||||
| 991 | SocketPort *p; | ||||
| 992 | char **i; | ||||
| 993 | |||||
| 994 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/socket.c", 994, __PRETTY_FUNCTION__ ); } while (0); | ||||
| 995 | |||||
| 996 | LIST_FOREACH(port, p, s->ports)for ((p) = (s->ports); (p); (p) = (p)->port_next) { | ||||
| 997 | bool_Bool was_open; | ||||
| 998 | |||||
| 999 | was_open = p->fd >= 0; | ||||
| 1000 | |||||
| 1001 | p->event_source = sd_event_source_unref(p->event_source); | ||||
| 1002 | p->fd = safe_close(p->fd); | ||||
| 1003 | socket_cleanup_fd_list(p); | ||||
| 1004 | |||||
| 1005 | /* One little note: we should normally not delete any sockets in the file system here! After all some | ||||
| 1006 | * other process we spawned might still have a reference of this fd and wants to continue to use | ||||
| 1007 | * it. Therefore we normally delete sockets in the file system before we create a new one, not after we | ||||
| 1008 | * stopped using one! That all said, if the user explicitly requested this, we'll delete them here | ||||
| 1009 | * anyway, but only then. */ | ||||
| 1010 | |||||
| 1011 | if (!was_open || !s->remove_on_stop) | ||||
| 1012 | continue; | ||||
| 1013 | |||||
| 1014 | switch (p->type) { | ||||
| 1015 | |||||
| 1016 | case SOCKET_FIFO: | ||||
| 1017 | (void) unlink(p->path); | ||||
| 1018 | break; | ||||
| 1019 | |||||
| 1020 | case SOCKET_MQUEUE: | ||||
| 1021 | (void) mq_unlink(p->path); | ||||
| 1022 | break; | ||||
| 1023 | |||||
| 1024 | case SOCKET_SOCKET: | ||||
| 1025 | (void) socket_address_unlink(&p->address); | ||||
| 1026 | break; | ||||
| 1027 | |||||
| 1028 | default: | ||||
| 1029 | break; | ||||
| 1030 | } | ||||
| 1031 | } | ||||
| 1032 | |||||
| 1033 | if (s->remove_on_stop) | ||||
| 1034 | STRV_FOREACH(i, s->symlinks)for ((i) = (s->symlinks); (i) && *(i); (i)++) | ||||
| 1035 | (void) unlink(*i); | ||||
| 1036 | } | ||||
| 1037 | |||||
| 1038 | static void socket_apply_socket_options(Socket *s, int fd) { | ||||
| 1039 | int r; | ||||
| 1040 | |||||
| 1041 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/socket.c", 1041, __PRETTY_FUNCTION__ ); } while (0); | ||||
| 1042 | assert(fd >= 0)do { if ((__builtin_expect(!!(!(fd >= 0)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("fd >= 0"), "../src/core/socket.c", 1042 , __PRETTY_FUNCTION__); } while (0); | ||||
| 1043 | |||||
| 1044 | if (s->keep_alive) { | ||||
| 1045 | int one = 1; | ||||
| 1046 | if (setsockopt(fd, SOL_SOCKET1, SO_KEEPALIVE9, &one, sizeof(one)) < 0) | ||||
| 1047 | log_unit_warning_errno(UNIT(s), errno, "SO_KEEPALIVE failed: %m")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, (*__errno_location ()), "../src/core/socket.c", 1047, __func__ , _u->manager->unit_log_field, _u->id, _u->manager ->invocation_log_field, _u->invocation_id_string, "SO_KEEPALIVE failed: %m" ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((4 ))), (*__errno_location ()), "../src/core/socket.c", 1047, __func__ , "SO_KEEPALIVE failed: %m"); }); | ||||
| 1048 | } | ||||
| 1049 | |||||
| 1050 | if (s->keep_alive_time > 0) { | ||||
| 1051 | int value = s->keep_alive_time / USEC_PER_SEC((usec_t) 1000000ULL); | ||||
| 1052 | if (setsockopt(fd, SOL_TCP6, TCP_KEEPIDLE4, &value, sizeof(value)) < 0) | ||||
| 1053 | log_unit_warning_errno(UNIT(s), errno, "TCP_KEEPIDLE failed: %m")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, (*__errno_location ()), "../src/core/socket.c", 1053, __func__ , _u->manager->unit_log_field, _u->id, _u->manager ->invocation_log_field, _u->invocation_id_string, "TCP_KEEPIDLE failed: %m" ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((4 ))), (*__errno_location ()), "../src/core/socket.c", 1053, __func__ , "TCP_KEEPIDLE failed: %m"); }); | ||||
| 1054 | } | ||||
| 1055 | |||||
| 1056 | if (s->keep_alive_interval > 0) { | ||||
| 1057 | int value = s->keep_alive_interval / USEC_PER_SEC((usec_t) 1000000ULL); | ||||
| 1058 | if (setsockopt(fd, SOL_TCP6, TCP_KEEPINTVL5, &value, sizeof(value)) < 0) | ||||
| 1059 | log_unit_warning_errno(UNIT(s), errno, "TCP_KEEPINTVL failed: %m")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, (*__errno_location ()), "../src/core/socket.c", 1059, __func__ , _u->manager->unit_log_field, _u->id, _u->manager ->invocation_log_field, _u->invocation_id_string, "TCP_KEEPINTVL failed: %m" ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((4 ))), (*__errno_location ()), "../src/core/socket.c", 1059, __func__ , "TCP_KEEPINTVL failed: %m"); }); | ||||
| 1060 | } | ||||
| 1061 | |||||
| 1062 | if (s->keep_alive_cnt > 0) { | ||||
| 1063 | int value = s->keep_alive_cnt; | ||||
| 1064 | if (setsockopt(fd, SOL_TCP6, TCP_KEEPCNT6, &value, sizeof(value)) < 0) | ||||
| 1065 | log_unit_warning_errno(UNIT(s), errno, "TCP_KEEPCNT failed: %m")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, (*__errno_location ()), "../src/core/socket.c", 1065, __func__ , _u->manager->unit_log_field, _u->id, _u->manager ->invocation_log_field, _u->invocation_id_string, "TCP_KEEPCNT failed: %m" ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((4 ))), (*__errno_location ()), "../src/core/socket.c", 1065, __func__ , "TCP_KEEPCNT failed: %m"); }); | ||||
| 1066 | } | ||||
| 1067 | |||||
| 1068 | if (s->defer_accept > 0) { | ||||
| 1069 | int value = s->defer_accept / USEC_PER_SEC((usec_t) 1000000ULL); | ||||
| 1070 | if (setsockopt(fd, SOL_TCP6, TCP_DEFER_ACCEPT9, &value, sizeof(value)) < 0) | ||||
| 1071 | log_unit_warning_errno(UNIT(s), errno, "TCP_DEFER_ACCEPT failed: %m")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, (*__errno_location ()), "../src/core/socket.c", 1071, __func__ , _u->manager->unit_log_field, _u->id, _u->manager ->invocation_log_field, _u->invocation_id_string, "TCP_DEFER_ACCEPT failed: %m" ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((4 ))), (*__errno_location ()), "../src/core/socket.c", 1071, __func__ , "TCP_DEFER_ACCEPT failed: %m"); }); | ||||
| 1072 | } | ||||
| 1073 | |||||
| 1074 | if (s->no_delay) { | ||||
| 1075 | int one = 1; | ||||
| 1076 | |||||
| 1077 | if (s->socket_protocol == IPPROTO_SCTPIPPROTO_SCTP) { | ||||
| 1078 | if (setsockopt(fd, SOL_SCTP132, SCTP_NODELAY3, &one, sizeof(one)) < 0) | ||||
| 1079 | log_unit_warning_errno(UNIT(s), errno, "SCTP_NODELAY failed: %m")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, (*__errno_location ()), "../src/core/socket.c", 1079, __func__ , _u->manager->unit_log_field, _u->id, _u->manager ->invocation_log_field, _u->invocation_id_string, "SCTP_NODELAY failed: %m" ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((4 ))), (*__errno_location ()), "../src/core/socket.c", 1079, __func__ , "SCTP_NODELAY failed: %m"); }); | ||||
| 1080 | } else { | ||||
| 1081 | if (setsockopt(fd, SOL_TCP6, TCP_NODELAY1, &one, sizeof(one)) < 0) | ||||
| 1082 | log_unit_warning_errno(UNIT(s), errno, "TCP_NODELAY failed: %m")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, (*__errno_location ()), "../src/core/socket.c", 1082, __func__ , _u->manager->unit_log_field, _u->id, _u->manager ->invocation_log_field, _u->invocation_id_string, "TCP_NODELAY failed: %m" ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((4 ))), (*__errno_location ()), "../src/core/socket.c", 1082, __func__ , "TCP_NODELAY failed: %m"); }); | ||||
| 1083 | } | ||||
| 1084 | } | ||||
| 1085 | |||||
| 1086 | if (s->broadcast) { | ||||
| 1087 | int one = 1; | ||||
| 1088 | if (setsockopt(fd, SOL_SOCKET1, SO_BROADCAST6, &one, sizeof(one)) < 0) | ||||
| 1089 | log_unit_warning_errno(UNIT(s), errno, "SO_BROADCAST failed: %m")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, (*__errno_location ()), "../src/core/socket.c", 1089, __func__ , _u->manager->unit_log_field, _u->id, _u->manager ->invocation_log_field, _u->invocation_id_string, "SO_BROADCAST failed: %m" ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((4 ))), (*__errno_location ()), "../src/core/socket.c", 1089, __func__ , "SO_BROADCAST failed: %m"); }); | ||||
| 1090 | } | ||||
| 1091 | |||||
| 1092 | if (s->pass_cred) { | ||||
| 1093 | int one = 1; | ||||
| 1094 | if (setsockopt(fd, SOL_SOCKET1, SO_PASSCRED16, &one, sizeof(one)) < 0) | ||||
| 1095 | log_unit_warning_errno(UNIT(s), errno, "SO_PASSCRED failed: %m")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, (*__errno_location ()), "../src/core/socket.c", 1095, __func__ , _u->manager->unit_log_field, _u->id, _u->manager ->invocation_log_field, _u->invocation_id_string, "SO_PASSCRED failed: %m" ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((4 ))), (*__errno_location ()), "../src/core/socket.c", 1095, __func__ , "SO_PASSCRED failed: %m"); }); | ||||
| 1096 | } | ||||
| 1097 | |||||
| 1098 | if (s->pass_sec) { | ||||
| 1099 | int one = 1; | ||||
| 1100 | if (setsockopt(fd, SOL_SOCKET1, SO_PASSSEC34, &one, sizeof(one)) < 0) | ||||
| 1101 | log_unit_warning_errno(UNIT(s), errno, "SO_PASSSEC failed: %m")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, (*__errno_location ()), "../src/core/socket.c", 1101, __func__ , _u->manager->unit_log_field, _u->id, _u->manager ->invocation_log_field, _u->invocation_id_string, "SO_PASSSEC failed: %m" ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((4 ))), (*__errno_location ()), "../src/core/socket.c", 1101, __func__ , "SO_PASSSEC failed: %m"); }); | ||||
| 1102 | } | ||||
| 1103 | |||||
| 1104 | if (s->pass_pktinfo) { | ||||
| 1105 | r = socket_pass_pktinfo(fd, true1); | ||||
| 1106 | if (r < 0) | ||||
| 1107 | log_unit_warning_errno(UNIT(s), r, "Failed to enable packet info socket option: %m")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, r, "../src/core/socket.c", 1107, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Failed to enable packet info socket option: %m" ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((4 ))), r, "../src/core/socket.c", 1107, __func__, "Failed to enable packet info socket option: %m" ); }); | ||||
| 1108 | } | ||||
| 1109 | |||||
| 1110 | if (s->priority >= 0) | ||||
| 1111 | if (setsockopt(fd, SOL_SOCKET1, SO_PRIORITY12, &s->priority, sizeof(s->priority)) < 0) | ||||
| 1112 | log_unit_warning_errno(UNIT(s), errno, "SO_PRIORITY failed: %m")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, (*__errno_location ()), "../src/core/socket.c", 1112, __func__ , _u->manager->unit_log_field, _u->id, _u->manager ->invocation_log_field, _u->invocation_id_string, "SO_PRIORITY failed: %m" ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((4 ))), (*__errno_location ()), "../src/core/socket.c", 1112, __func__ , "SO_PRIORITY failed: %m"); }); | ||||
| 1113 | |||||
| 1114 | if (s->receive_buffer > 0) { | ||||
| 1115 | int value = (int) s->receive_buffer; | ||||
| 1116 | |||||
| 1117 | /* We first try with SO_RCVBUFFORCE, in case we have the perms for that */ | ||||
| 1118 | if (setsockopt(fd, SOL_SOCKET1, SO_RCVBUFFORCE33, &value, sizeof(value)) < 0) | ||||
| 1119 | if (setsockopt(fd, SOL_SOCKET1, SO_RCVBUF8, &value, sizeof(value)) < 0) | ||||
| 1120 | log_unit_warning_errno(UNIT(s), errno, "SO_RCVBUF failed: %m")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, (*__errno_location ()), "../src/core/socket.c", 1120, __func__ , _u->manager->unit_log_field, _u->id, _u->manager ->invocation_log_field, _u->invocation_id_string, "SO_RCVBUF failed: %m" ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((4 ))), (*__errno_location ()), "../src/core/socket.c", 1120, __func__ , "SO_RCVBUF failed: %m"); }); | ||||
| 1121 | } | ||||
| 1122 | |||||
| 1123 | if (s->send_buffer > 0) { | ||||
| 1124 | int value = (int) s->send_buffer; | ||||
| 1125 | if (setsockopt(fd, SOL_SOCKET1, SO_SNDBUFFORCE32, &value, sizeof(value)) < 0) | ||||
| 1126 | if (setsockopt(fd, SOL_SOCKET1, SO_SNDBUF7, &value, sizeof(value)) < 0) | ||||
| 1127 | log_unit_warning_errno(UNIT(s), errno, "SO_SNDBUF failed: %m")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, (*__errno_location ()), "../src/core/socket.c", 1127, __func__ , _u->manager->unit_log_field, _u->id, _u->manager ->invocation_log_field, _u->invocation_id_string, "SO_SNDBUF failed: %m" ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((4 ))), (*__errno_location ()), "../src/core/socket.c", 1127, __func__ , "SO_SNDBUF failed: %m"); }); | ||||
| 1128 | } | ||||
| 1129 | |||||
| 1130 | if (s->mark >= 0) | ||||
| 1131 | if (setsockopt(fd, SOL_SOCKET1, SO_MARK36, &s->mark, sizeof(s->mark)) < 0) | ||||
| 1132 | log_unit_warning_errno(UNIT(s), errno, "SO_MARK failed: %m")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, (*__errno_location ()), "../src/core/socket.c", 1132, __func__ , _u->manager->unit_log_field, _u->id, _u->manager ->invocation_log_field, _u->invocation_id_string, "SO_MARK failed: %m" ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((4 ))), (*__errno_location ()), "../src/core/socket.c", 1132, __func__ , "SO_MARK failed: %m"); }); | ||||
| 1133 | |||||
| 1134 | if (s->ip_tos >= 0) | ||||
| 1135 | if (setsockopt(fd, IPPROTO_IPIPPROTO_IP, IP_TOS1, &s->ip_tos, sizeof(s->ip_tos)) < 0) | ||||
| 1136 | log_unit_warning_errno(UNIT(s), errno, "IP_TOS failed: %m")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, (*__errno_location ()), "../src/core/socket.c", 1136, __func__ , _u->manager->unit_log_field, _u->id, _u->manager ->invocation_log_field, _u->invocation_id_string, "IP_TOS failed: %m" ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((4 ))), (*__errno_location ()), "../src/core/socket.c", 1136, __func__ , "IP_TOS failed: %m"); }); | ||||
| 1137 | |||||
| 1138 | if (s->ip_ttl >= 0) { | ||||
| 1139 | int x; | ||||
| 1140 | |||||
| 1141 | r = setsockopt(fd, IPPROTO_IPIPPROTO_IP, IP_TTL2, &s->ip_ttl, sizeof(s->ip_ttl)); | ||||
| 1142 | |||||
| 1143 | if (socket_ipv6_is_supported()) | ||||
| 1144 | x = setsockopt(fd, IPPROTO_IPV6IPPROTO_IPV6, IPV6_UNICAST_HOPS16, &s->ip_ttl, sizeof(s->ip_ttl)); | ||||
| 1145 | else { | ||||
| 1146 | x = -1; | ||||
| 1147 | errno(*__errno_location ()) = EAFNOSUPPORT97; | ||||
| 1148 | } | ||||
| 1149 | |||||
| 1150 | if (r < 0 && x < 0) | ||||
| 1151 | log_unit_warning_errno(UNIT(s), errno, "IP_TTL/IPV6_UNICAST_HOPS failed: %m")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, (*__errno_location ()), "../src/core/socket.c", 1151, __func__ , _u->manager->unit_log_field, _u->id, _u->manager ->invocation_log_field, _u->invocation_id_string, "IP_TTL/IPV6_UNICAST_HOPS failed: %m" ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((4 ))), (*__errno_location ()), "../src/core/socket.c", 1151, __func__ , "IP_TTL/IPV6_UNICAST_HOPS failed: %m"); }); | ||||
| 1152 | } | ||||
| 1153 | |||||
| 1154 | if (s->tcp_congestion) | ||||
| 1155 | if (setsockopt(fd, SOL_TCP6, TCP_CONGESTION13, s->tcp_congestion, strlen(s->tcp_congestion)+1) < 0) | ||||
| 1156 | log_unit_warning_errno(UNIT(s), errno, "TCP_CONGESTION failed: %m")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, (*__errno_location ()), "../src/core/socket.c", 1156, __func__ , _u->manager->unit_log_field, _u->id, _u->manager ->invocation_log_field, _u->invocation_id_string, "TCP_CONGESTION failed: %m" ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((4 ))), (*__errno_location ()), "../src/core/socket.c", 1156, __func__ , "TCP_CONGESTION failed: %m"); }); | ||||
| 1157 | |||||
| 1158 | if (s->smack_ip_in) { | ||||
| 1159 | r = mac_smack_apply_fd(fd, SMACK_ATTR_IPIN, s->smack_ip_in); | ||||
| 1160 | if (r < 0) | ||||
| 1161 | log_unit_error_errno(UNIT(s), r, "mac_smack_apply_ip_in_fd: %m")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (3, r, "../src/core/socket.c", 1161, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "mac_smack_apply_ip_in_fd: %m" ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3 ))), r, "../src/core/socket.c", 1161, __func__, "mac_smack_apply_ip_in_fd: %m" ); }); | ||||
| 1162 | } | ||||
| 1163 | |||||
| 1164 | if (s->smack_ip_out) { | ||||
| 1165 | r = mac_smack_apply_fd(fd, SMACK_ATTR_IPOUT, s->smack_ip_out); | ||||
| 1166 | if (r < 0) | ||||
| 1167 | log_unit_error_errno(UNIT(s), r, "mac_smack_apply_ip_out_fd: %m")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (3, r, "../src/core/socket.c", 1167, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "mac_smack_apply_ip_out_fd: %m" ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3 ))), r, "../src/core/socket.c", 1167, __func__, "mac_smack_apply_ip_out_fd: %m" ); }); | ||||
| 1168 | } | ||||
| 1169 | } | ||||
| 1170 | |||||
| 1171 | static void socket_apply_fifo_options(Socket *s, int fd) { | ||||
| 1172 | int r; | ||||
| 1173 | |||||
| 1174 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/socket.c", 1174, __PRETTY_FUNCTION__ ); } while (0); | ||||
| 1175 | assert(fd >= 0)do { if ((__builtin_expect(!!(!(fd >= 0)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("fd >= 0"), "../src/core/socket.c", 1175 , __PRETTY_FUNCTION__); } while (0); | ||||
| 1176 | |||||
| 1177 | if (s->pipe_size > 0) | ||||
| 1178 | if (fcntl(fd, F_SETPIPE_SZ1031, s->pipe_size) < 0) | ||||
| 1179 | log_unit_warning_errno(UNIT(s), errno, "Setting pipe size failed, ignoring: %m")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, (*__errno_location ()), "../src/core/socket.c", 1179, __func__ , _u->manager->unit_log_field, _u->id, _u->manager ->invocation_log_field, _u->invocation_id_string, "Setting pipe size failed, ignoring: %m" ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((4 ))), (*__errno_location ()), "../src/core/socket.c", 1179, __func__ , "Setting pipe size failed, ignoring: %m"); }); | ||||
| 1180 | |||||
| 1181 | if (s->smack) { | ||||
| 1182 | r = mac_smack_apply_fd(fd, SMACK_ATTR_ACCESS, s->smack); | ||||
| 1183 | if (r < 0) | ||||
| 1184 | log_unit_error_errno(UNIT(s), r, "SMACK relabelling failed, ignoring: %m")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (3, r, "../src/core/socket.c", 1184, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "SMACK relabelling failed, ignoring: %m" ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3 ))), r, "../src/core/socket.c", 1184, __func__, "SMACK relabelling failed, ignoring: %m" ); }); | ||||
| 1185 | } | ||||
| 1186 | } | ||||
| 1187 | |||||
| 1188 | static int fifo_address_create( | ||||
| 1189 | const char *path, | ||||
| 1190 | mode_t directory_mode, | ||||
| 1191 | mode_t socket_mode) { | ||||
| 1192 | |||||
| 1193 | _cleanup_close___attribute__((cleanup(closep))) int fd = -1; | ||||
| 1194 | mode_t old_mask; | ||||
| 1195 | struct stat st; | ||||
| 1196 | int r; | ||||
| 1197 | |||||
| 1198 | assert(path)do { if ((__builtin_expect(!!(!(path)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("path"), "../src/core/socket.c", 1198, __PRETTY_FUNCTION__ ); } while (0); | ||||
| 1199 | |||||
| 1200 | (void) mkdir_parents_label(path, directory_mode); | ||||
| 1201 | |||||
| 1202 | r = mac_selinux_create_file_prepare(path, S_IFIFO0010000); | ||||
| 1203 | if (r < 0) | ||||
| 1204 | return r; | ||||
| 1205 | |||||
| 1206 | /* Enforce the right access mode for the fifo */ | ||||
| 1207 | old_mask = umask(~socket_mode); | ||||
| 1208 | |||||
| 1209 | /* Include the original umask in our mask */ | ||||
| 1210 | (void) umask(~socket_mode | old_mask); | ||||
| 1211 | |||||
| 1212 | r = mkfifo(path, socket_mode); | ||||
| 1213 | (void) umask(old_mask); | ||||
| 1214 | |||||
| 1215 | if (r < 0 && errno(*__errno_location ()) != EEXIST17) { | ||||
| 1216 | r = -errno(*__errno_location ()); | ||||
| 1217 | goto fail; | ||||
| 1218 | } | ||||
| 1219 | |||||
| 1220 | fd = open(path, O_RDWR02 | O_CLOEXEC02000000 | O_NOCTTY0400 | O_NONBLOCK04000 | O_NOFOLLOW0400000); | ||||
| 1221 | if (fd < 0) { | ||||
| 1222 | r = -errno(*__errno_location ()); | ||||
| 1223 | goto fail; | ||||
| 1224 | } | ||||
| 1225 | |||||
| 1226 | mac_selinux_create_file_clear(); | ||||
| 1227 | |||||
| 1228 | if (fstat(fd, &st) < 0) { | ||||
| 1229 | r = -errno(*__errno_location ()); | ||||
| 1230 | goto fail; | ||||
| 1231 | } | ||||
| 1232 | |||||
| 1233 | if (!S_ISFIFO(st.st_mode)((((st.st_mode)) & 0170000) == (0010000)) || | ||||
| 1234 | (st.st_mode & 0777) != (socket_mode & ~old_mask) || | ||||
| 1235 | st.st_uid != getuid() || | ||||
| 1236 | st.st_gid != getgid()) { | ||||
| 1237 | r = -EEXIST17; | ||||
| 1238 | goto fail; | ||||
| 1239 | } | ||||
| 1240 | |||||
| 1241 | return TAKE_FD(fd)({ int _fd_ = (fd); (fd) = -1; _fd_; }); | ||||
| 1242 | |||||
| 1243 | fail: | ||||
| 1244 | mac_selinux_create_file_clear(); | ||||
| 1245 | return r; | ||||
| 1246 | } | ||||
| 1247 | |||||
| 1248 | static int special_address_create(const char *path, bool_Bool writable) { | ||||
| 1249 | _cleanup_close___attribute__((cleanup(closep))) int fd = -1; | ||||
| 1250 | struct stat st; | ||||
| 1251 | |||||
| 1252 | assert(path)do { if ((__builtin_expect(!!(!(path)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("path"), "../src/core/socket.c", 1252, __PRETTY_FUNCTION__ ); } while (0); | ||||
| 1253 | |||||
| 1254 | fd = open(path, (writable ? O_RDWR02 : O_RDONLY00)|O_CLOEXEC02000000|O_NOCTTY0400|O_NONBLOCK04000|O_NOFOLLOW0400000); | ||||
| 1255 | if (fd < 0) | ||||
| 1256 | return -errno(*__errno_location ()); | ||||
| 1257 | |||||
| 1258 | if (fstat(fd, &st) < 0) | ||||
| 1259 | return -errno(*__errno_location ()); | ||||
| 1260 | |||||
| 1261 | /* Check whether this is a /proc, /sys or /dev file or char device */ | ||||
| 1262 | if (!S_ISREG(st.st_mode)((((st.st_mode)) & 0170000) == (0100000)) && !S_ISCHR(st.st_mode)((((st.st_mode)) & 0170000) == (0020000))) | ||||
| 1263 | return -EEXIST17; | ||||
| 1264 | |||||
| 1265 | return TAKE_FD(fd)({ int _fd_ = (fd); (fd) = -1; _fd_; }); | ||||
| 1266 | } | ||||
| 1267 | |||||
| 1268 | static int usbffs_address_create(const char *path) { | ||||
| 1269 | _cleanup_close___attribute__((cleanup(closep))) int fd = -1; | ||||
| 1270 | struct stat st; | ||||
| 1271 | |||||
| 1272 | assert(path)do { if ((__builtin_expect(!!(!(path)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("path"), "../src/core/socket.c", 1272, __PRETTY_FUNCTION__ ); } while (0); | ||||
| 1273 | |||||
| 1274 | fd = open(path, O_RDWR02|O_CLOEXEC02000000|O_NOCTTY0400|O_NONBLOCK04000|O_NOFOLLOW0400000); | ||||
| 1275 | if (fd < 0) | ||||
| 1276 | return -errno(*__errno_location ()); | ||||
| 1277 | |||||
| 1278 | if (fstat(fd, &st) < 0) | ||||
| 1279 | return -errno(*__errno_location ()); | ||||
| 1280 | |||||
| 1281 | /* Check whether this is a regular file (ffs endpoint) */ | ||||
| 1282 | if (!S_ISREG(st.st_mode)((((st.st_mode)) & 0170000) == (0100000))) | ||||
| 1283 | return -EEXIST17; | ||||
| 1284 | |||||
| 1285 | return TAKE_FD(fd)({ int _fd_ = (fd); (fd) = -1; _fd_; }); | ||||
| 1286 | } | ||||
| 1287 | |||||
| 1288 | static int mq_address_create( | ||||
| 1289 | const char *path, | ||||
| 1290 | mode_t mq_mode, | ||||
| 1291 | long maxmsg, | ||||
| 1292 | long msgsize) { | ||||
| 1293 | |||||
| 1294 | _cleanup_close___attribute__((cleanup(closep))) int fd = -1; | ||||
| 1295 | struct stat st; | ||||
| 1296 | mode_t old_mask; | ||||
| 1297 | struct mq_attr _attr, *attr = NULL((void*)0); | ||||
| 1298 | |||||
| 1299 | assert(path)do { if ((__builtin_expect(!!(!(path)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("path"), "../src/core/socket.c", 1299, __PRETTY_FUNCTION__ ); } while (0); | ||||
| 1300 | |||||
| 1301 | if (maxmsg > 0 && msgsize > 0) { | ||||
| 1302 | _attr = (struct mq_attr) { | ||||
| 1303 | .mq_flags = O_NONBLOCK04000, | ||||
| 1304 | .mq_maxmsg = maxmsg, | ||||
| 1305 | .mq_msgsize = msgsize, | ||||
| 1306 | }; | ||||
| 1307 | attr = &_attr; | ||||
| 1308 | } | ||||
| 1309 | |||||
| 1310 | /* Enforce the right access mode for the mq */ | ||||
| 1311 | old_mask = umask(~mq_mode); | ||||
| 1312 | |||||
| 1313 | /* Include the original umask in our mask */ | ||||
| 1314 | (void) umask(~mq_mode | old_mask); | ||||
| 1315 | fd = mq_open(path, O_RDONLY00|O_CLOEXEC02000000|O_NONBLOCK04000|O_CREAT0100, mq_mode, attr); | ||||
| 1316 | (void) umask(old_mask); | ||||
| 1317 | |||||
| 1318 | if (fd < 0) | ||||
| 1319 | return -errno(*__errno_location ()); | ||||
| 1320 | |||||
| 1321 | if (fstat(fd, &st) < 0) | ||||
| 1322 | return -errno(*__errno_location ()); | ||||
| 1323 | |||||
| 1324 | if ((st.st_mode & 0777) != (mq_mode & ~old_mask) || | ||||
| 1325 | st.st_uid != getuid() || | ||||
| 1326 | st.st_gid != getgid()) | ||||
| 1327 | return -EEXIST17; | ||||
| 1328 | |||||
| 1329 | return TAKE_FD(fd)({ int _fd_ = (fd); (fd) = -1; _fd_; }); | ||||
| 1330 | } | ||||
| 1331 | |||||
| 1332 | static int socket_symlink(Socket *s) { | ||||
| 1333 | const char *p; | ||||
| 1334 | char **i; | ||||
| 1335 | int r; | ||||
| 1336 | |||||
| 1337 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/socket.c", 1337, __PRETTY_FUNCTION__ ); } while (0); | ||||
| 1338 | |||||
| 1339 | p = socket_find_symlink_target(s); | ||||
| 1340 | if (!p) | ||||
| 1341 | return 0; | ||||
| 1342 | |||||
| 1343 | STRV_FOREACH(i, s->symlinks)for ((i) = (s->symlinks); (i) && *(i); (i)++) { | ||||
| 1344 | (void) mkdir_parents_label(*i, s->directory_mode); | ||||
| 1345 | |||||
| 1346 | r = symlink_idempotent(p, *i); | ||||
| 1347 | |||||
| 1348 | if (r == -EEXIST17 && s->remove_on_stop) { | ||||
| 1349 | /* If there's already something where we want to create the symlink, and the destructive | ||||
| 1350 | * RemoveOnStop= mode is set, then we might as well try to remove what already exists and try | ||||
| 1351 | * again. */ | ||||
| 1352 | |||||
| 1353 | if (unlink(*i) >= 0) | ||||
| 1354 | r = symlink_idempotent(p, *i); | ||||
| 1355 | } | ||||
| 1356 | |||||
| 1357 | if (r < 0) | ||||
| 1358 | log_unit_warning_errno(UNIT(s), r, "Failed to create symlink %s → %s, ignoring: %m", p, *i)({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, r, "../src/core/socket.c", 1358, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Failed to create symlink %s → %s, ignoring: %m" , p, *i) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((4))), r, "../src/core/socket.c", 1358, __func__, "Failed to create symlink %s → %s, ignoring: %m" , p, *i); }); | ||||
| 1359 | } | ||||
| 1360 | |||||
| 1361 | return 0; | ||||
| 1362 | } | ||||
| 1363 | |||||
| 1364 | static int usbffs_write_descs(int fd, Service *s) { | ||||
| 1365 | int r; | ||||
| 1366 | |||||
| 1367 | if (!s->usb_function_descriptors || !s->usb_function_strings) | ||||
| 1368 | return -EINVAL22; | ||||
| 1369 | |||||
| 1370 | r = copy_file_fd(s->usb_function_descriptors, fd, 0); | ||||
| 1371 | if (r < 0) | ||||
| 1372 | return r; | ||||
| 1373 | |||||
| 1374 | return copy_file_fd(s->usb_function_strings, fd, 0); | ||||
| 1375 | } | ||||
| 1376 | |||||
| 1377 | static int usbffs_select_ep(const struct dirent *d) { | ||||
| 1378 | return d->d_name[0] != '.' && !streq(d->d_name, "ep0")(strcmp((d->d_name),("ep0")) == 0); | ||||
| 1379 | } | ||||
| 1380 | |||||
| 1381 | static int usbffs_dispatch_eps(SocketPort *p) { | ||||
| 1382 | _cleanup_free___attribute__((cleanup(freep))) struct dirent **ent = NULL((void*)0); | ||||
| 1383 | size_t n, k, i; | ||||
| 1384 | int r; | ||||
| 1385 | |||||
| 1386 | r = scandir(p->path, &ent, usbffs_select_ep, alphasort); | ||||
| 1387 | if (r < 0) | ||||
| 1388 | return -errno(*__errno_location ()); | ||||
| 1389 | |||||
| 1390 | n = (size_t) r; | ||||
| 1391 | p->auxiliary_fds = new(int, n)((int*) malloc_multiply(sizeof(int), (n))); | ||||
| 1392 | if (!p->auxiliary_fds) | ||||
| 1393 | return -ENOMEM12; | ||||
| 1394 | |||||
| 1395 | p->n_auxiliary_fds = n; | ||||
| 1396 | |||||
| 1397 | k = 0; | ||||
| 1398 | for (i = 0; i < n; ++i) { | ||||
| 1399 | _cleanup_free___attribute__((cleanup(freep))) char *ep = NULL((void*)0); | ||||
| 1400 | |||||
| 1401 | ep = path_make_absolute(ent[i]->d_name, p->path); | ||||
| 1402 | if (!ep) | ||||
| 1403 | return -ENOMEM12; | ||||
| 1404 | |||||
| 1405 | path_simplify(ep, false0); | ||||
| 1406 | |||||
| 1407 | r = usbffs_address_create(ep); | ||||
| 1408 | if (r < 0) | ||||
| 1409 | goto fail; | ||||
| 1410 | |||||
| 1411 | p->auxiliary_fds[k++] = r; | ||||
| 1412 | free(ent[i]); | ||||
| 1413 | } | ||||
| 1414 | |||||
| 1415 | return r; | ||||
| 1416 | |||||
| 1417 | fail: | ||||
| 1418 | close_many(p->auxiliary_fds, k); | ||||
| 1419 | p->auxiliary_fds = mfree(p->auxiliary_fds); | ||||
| 1420 | p->n_auxiliary_fds = 0; | ||||
| 1421 | |||||
| 1422 | return r; | ||||
| 1423 | } | ||||
| 1424 | |||||
| 1425 | static int socket_determine_selinux_label(Socket *s, char **ret) { | ||||
| 1426 | Service *service; | ||||
| 1427 | ExecCommand *c; | ||||
| 1428 | _cleanup_free___attribute__((cleanup(freep))) char *path = NULL((void*)0); | ||||
| 1429 | int r; | ||||
| 1430 | |||||
| 1431 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/socket.c", 1431, __PRETTY_FUNCTION__ ); } while (0); | ||||
| 1432 | assert(ret)do { if ((__builtin_expect(!!(!(ret)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("ret"), "../src/core/socket.c", 1432, __PRETTY_FUNCTION__ ); } while (0); | ||||
| 1433 | |||||
| 1434 | if (s->selinux_context_from_net) { | ||||
| 1435 | /* If this is requested, get label from the network label */ | ||||
| 1436 | |||||
| 1437 | r = mac_selinux_get_our_label(ret); | ||||
| 1438 | if (r == -EOPNOTSUPP95) | ||||
| 1439 | goto no_label; | ||||
| 1440 | |||||
| 1441 | } else { | ||||
| 1442 | /* Otherwise, get it from the executable we are about to start */ | ||||
| 1443 | r = socket_instantiate_service(s); | ||||
| 1444 | if (r < 0) | ||||
| 1445 | return r; | ||||
| 1446 | |||||
| 1447 | if (!UNIT_ISSET(s->service)(!!(s->service).target)) | ||||
| 1448 | goto no_label; | ||||
| 1449 | |||||
| 1450 | service = SERVICE(UNIT_DEREF(s->service)((s->service).target)); | ||||
| 1451 | c = service->exec_command[SERVICE_EXEC_START]; | ||||
| 1452 | if (!c) | ||||
| 1453 | goto no_label; | ||||
| 1454 | |||||
| 1455 | r = chase_symlinks(c->path, service->exec_context.root_directory, CHASE_PREFIX_ROOT, &path); | ||||
| 1456 | if (r < 0) | ||||
| 1457 | goto no_label; | ||||
| 1458 | |||||
| 1459 | r = mac_selinux_get_create_label_from_exe(path, ret); | ||||
| 1460 | if (IN_SET(r, -EPERM, -EOPNOTSUPP)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){-1, -95})/sizeof(int)]; switch(r) { case -1: case -95: _found = 1; break; default: break; } _found; } )) | ||||
| 1461 | goto no_label; | ||||
| 1462 | } | ||||
| 1463 | |||||
| 1464 | return r; | ||||
| 1465 | |||||
| 1466 | no_label: | ||||
| 1467 | *ret = NULL((void*)0); | ||||
| 1468 | return 0; | ||||
| 1469 | } | ||||
| 1470 | |||||
| 1471 | static int socket_address_listen_do( | ||||
| 1472 | Socket *s, | ||||
| 1473 | const SocketAddress *address, | ||||
| 1474 | const char *label) { | ||||
| 1475 | |||||
| 1476 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/socket.c", 1476, __PRETTY_FUNCTION__ ); } while (0); | ||||
| 1477 | assert(address)do { if ((__builtin_expect(!!(!(address)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("address"), "../src/core/socket.c", 1477 , __PRETTY_FUNCTION__); } while (0); | ||||
| 1478 | |||||
| 1479 | return socket_address_listen( | ||||
| 1480 | address, | ||||
| 1481 | SOCK_CLOEXECSOCK_CLOEXEC|SOCK_NONBLOCKSOCK_NONBLOCK, | ||||
| 1482 | s->backlog, | ||||
| 1483 | s->bind_ipv6_only, | ||||
| 1484 | s->bind_to_device, | ||||
| 1485 | s->reuse_port, | ||||
| 1486 | s->free_bind, | ||||
| 1487 | s->transparent, | ||||
| 1488 | s->directory_mode, | ||||
| 1489 | s->socket_mode, | ||||
| 1490 | label); | ||||
| 1491 | } | ||||
| 1492 | |||||
| 1493 | static int socket_address_listen_in_cgroup( | ||||
| 1494 | Socket *s, | ||||
| 1495 | const SocketAddress *address, | ||||
| 1496 | const char *label) { | ||||
| 1497 | |||||
| 1498 | _cleanup_close_pair___attribute__((cleanup(close_pairp))) int pair[2] = { -1, -1 }; | ||||
| 1499 | int fd, r; | ||||
| 1500 | pid_t pid; | ||||
| 1501 | |||||
| 1502 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/socket.c", 1502, __PRETTY_FUNCTION__ ); } while (0); | ||||
| 1503 | assert(address)do { if ((__builtin_expect(!!(!(address)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("address"), "../src/core/socket.c", 1503 , __PRETTY_FUNCTION__); } while (0); | ||||
| 1504 | |||||
| 1505 | /* This is a wrapper around socket_address_listen(), that forks off a helper process inside the socket's cgroup | ||||
| 1506 | * in which the socket is actually created. This way we ensure the socket is actually properly attached to the | ||||
| 1507 | * unit's cgroup for the purpose of BPF filtering and such. */ | ||||
| 1508 | |||||
| 1509 | if (!IN_SET(address->sockaddr.sa.sa_family, AF_INET, AF_INET6)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){2, 10})/sizeof(int)]; switch(address-> sockaddr.sa.sa_family) { case 2: case 10: _found = 1; break; default : break; } _found; })) | ||||
| 1510 | goto shortcut; /* BPF filtering only applies to IPv4 + IPv6, shortcut things for other protocols */ | ||||
| 1511 | |||||
| 1512 | r = bpf_firewall_supported(); | ||||
| 1513 | if (r < 0) | ||||
| 1514 | return r; | ||||
| 1515 | if (r == BPF_FIREWALL_UNSUPPORTED) /* If BPF firewalling isn't supported anyway — there's no point in this forking complexity */ | ||||
| 1516 | goto shortcut; | ||||
| 1517 | |||||
| 1518 | if (socketpair(AF_UNIX1, SOCK_SEQPACKETSOCK_SEQPACKET|SOCK_CLOEXECSOCK_CLOEXEC, 0, pair) < 0) | ||||
| 1519 | return log_unit_error_errno(UNIT(s), errno, "Failed to create communication channel: %m")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (3, (*__errno_location ()), "../src/core/socket.c", 1519, __func__ , _u->manager->unit_log_field, _u->id, _u->manager ->invocation_log_field, _u->invocation_id_string, "Failed to create communication channel: %m" ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3 ))), (*__errno_location ()), "../src/core/socket.c", 1519, __func__ , "Failed to create communication channel: %m"); }); | ||||
| 1520 | |||||
| 1521 | r = unit_fork_helper_process(UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; }), "(sd-listen)", &pid); | ||||
| 1522 | if (r < 0) | ||||
| 1523 | return log_unit_error_errno(UNIT(s), r, "Failed to fork off listener stub process: %m")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (3, r, "../src/core/socket.c", 1523, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Failed to fork off listener stub process: %m" ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3 ))), r, "../src/core/socket.c", 1523, __func__, "Failed to fork off listener stub process: %m" ); }); | ||||
| 1524 | if (r == 0) { | ||||
| 1525 | /* Child */ | ||||
| 1526 | |||||
| 1527 | pair[0] = safe_close(pair[0]); | ||||
| 1528 | |||||
| 1529 | fd = socket_address_listen_do(s, address, label); | ||||
| 1530 | if (fd < 0) { | ||||
| 1531 | log_unit_error_errno(UNIT(s), fd, "Failed to create listening socket: %m")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (3, fd, "../src/core/socket.c", 1531, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Failed to create listening socket: %m" ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3 ))), fd, "../src/core/socket.c", 1531, __func__, "Failed to create listening socket: %m" ); }); | ||||
| 1532 | _exit(EXIT_FAILURE1); | ||||
| 1533 | } | ||||
| 1534 | |||||
| 1535 | r = send_one_fd(pair[1], fd, 0)send_one_fd_iov_sa(pair[1], fd, ((void*)0), 0, ((void*)0), 0, 0); | ||||
| 1536 | if (r < 0) { | ||||
| 1537 | log_unit_error_errno(UNIT(s), r, "Failed to send listening socket to parent: %m")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (3, r, "../src/core/socket.c", 1537, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Failed to send listening socket to parent: %m" ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3 ))), r, "../src/core/socket.c", 1537, __func__, "Failed to send listening socket to parent: %m" ); }); | ||||
| 1538 | _exit(EXIT_FAILURE1); | ||||
| 1539 | } | ||||
| 1540 | |||||
| 1541 | _exit(EXIT_SUCCESS0); | ||||
| 1542 | } | ||||
| 1543 | |||||
| 1544 | pair[1] = safe_close(pair[1]); | ||||
| 1545 | fd = receive_one_fd(pair[0], 0); | ||||
| 1546 | |||||
| 1547 | /* We synchronously wait for the helper, as it shouldn't be slow */ | ||||
| 1548 | r = wait_for_terminate_and_check("(sd-listen)", pid, WAIT_LOG_ABNORMAL); | ||||
| 1549 | if (r < 0) { | ||||
| 1550 | safe_close(fd); | ||||
| 1551 | return r; | ||||
| 1552 | } | ||||
| 1553 | |||||
| 1554 | if (fd < 0) | ||||
| 1555 | return log_unit_error_errno(UNIT(s), fd, "Failed to receive listening socket: %m")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (3, fd, "../src/core/socket.c", 1555, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Failed to receive listening socket: %m" ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3 ))), fd, "../src/core/socket.c", 1555, __func__, "Failed to receive listening socket: %m" ); }); | ||||
| 1556 | |||||
| 1557 | return fd; | ||||
| 1558 | |||||
| 1559 | shortcut: | ||||
| 1560 | fd = socket_address_listen_do(s, address, label); | ||||
| 1561 | if (fd < 0) | ||||
| 1562 | return log_error_errno(fd, "Failed to create listening socket: %m")({ int _level = ((3)), _e = ((fd)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/core/socket.c", 1562, __func__, "Failed to create listening socket: %m" ) : -abs(_e); }); | ||||
| 1563 | |||||
| 1564 | return fd; | ||||
| 1565 | } | ||||
| 1566 | |||||
| 1567 | static int socket_open_fds(Socket *s) { | ||||
| 1568 | _cleanup_(mac_selinux_freep)__attribute__((cleanup(mac_selinux_freep))) char *label = NULL((void*)0); | ||||
| 1569 | bool_Bool know_label = false0; | ||||
| 1570 | SocketPort *p; | ||||
| 1571 | int r; | ||||
| 1572 | |||||
| 1573 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/socket.c", 1573, __PRETTY_FUNCTION__ ); } while (0); | ||||
| 1574 | |||||
| 1575 | LIST_FOREACH(port, p, s->ports)for ((p) = (s->ports); (p); (p) = (p)->port_next) { | ||||
| 1576 | |||||
| 1577 | if (p->fd >= 0) | ||||
| 1578 | continue; | ||||
| 1579 | |||||
| 1580 | switch (p->type) { | ||||
| 1581 | |||||
| 1582 | case SOCKET_SOCKET: | ||||
| 1583 | |||||
| 1584 | if (!know_label) { | ||||
| 1585 | /* Figure out label, if we don't it know yet. We do it once, for the first socket where | ||||
| 1586 | * we need this and remember it for the rest. */ | ||||
| 1587 | |||||
| 1588 | r = socket_determine_selinux_label(s, &label); | ||||
| 1589 | if (r < 0) | ||||
| 1590 | goto rollback; | ||||
| 1591 | |||||
| 1592 | know_label = true1; | ||||
| 1593 | } | ||||
| 1594 | |||||
| 1595 | /* Apply the socket protocol */ | ||||
| 1596 | switch (p->address.type) { | ||||
| 1597 | |||||
| 1598 | case SOCK_STREAMSOCK_STREAM: | ||||
| 1599 | case SOCK_SEQPACKETSOCK_SEQPACKET: | ||||
| 1600 | if (s->socket_protocol == IPPROTO_SCTPIPPROTO_SCTP) | ||||
| 1601 | p->address.protocol = s->socket_protocol; | ||||
| 1602 | break; | ||||
| 1603 | |||||
| 1604 | case SOCK_DGRAMSOCK_DGRAM: | ||||
| 1605 | if (s->socket_protocol == IPPROTO_UDPLITEIPPROTO_UDPLITE) | ||||
| 1606 | p->address.protocol = s->socket_protocol; | ||||
| 1607 | break; | ||||
| 1608 | } | ||||
| 1609 | |||||
| 1610 | r = socket_address_listen_in_cgroup(s, &p->address, label); | ||||
| 1611 | if (r < 0) | ||||
| 1612 | goto rollback; | ||||
| 1613 | |||||
| 1614 | p->fd = r; | ||||
| 1615 | socket_apply_socket_options(s, p->fd); | ||||
| 1616 | socket_symlink(s); | ||||
| 1617 | break; | ||||
| 1618 | |||||
| 1619 | case SOCKET_SPECIAL: | ||||
| 1620 | |||||
| 1621 | p->fd = special_address_create(p->path, s->writable); | ||||
| 1622 | if (p->fd < 0) { | ||||
| 1623 | r = p->fd; | ||||
| 1624 | goto rollback; | ||||
| 1625 | } | ||||
| 1626 | break; | ||||
| 1627 | |||||
| 1628 | case SOCKET_FIFO: | ||||
| 1629 | |||||
| 1630 | p->fd = fifo_address_create( | ||||
| 1631 | p->path, | ||||
| 1632 | s->directory_mode, | ||||
| 1633 | s->socket_mode); | ||||
| 1634 | if (p->fd < 0) { | ||||
| 1635 | r = p->fd; | ||||
| 1636 | goto rollback; | ||||
| 1637 | } | ||||
| 1638 | |||||
| 1639 | socket_apply_fifo_options(s, p->fd); | ||||
| 1640 | socket_symlink(s); | ||||
| 1641 | break; | ||||
| 1642 | |||||
| 1643 | case SOCKET_MQUEUE: | ||||
| 1644 | |||||
| 1645 | p->fd = mq_address_create( | ||||
| 1646 | p->path, | ||||
| 1647 | s->socket_mode, | ||||
| 1648 | s->mq_maxmsg, | ||||
| 1649 | s->mq_msgsize); | ||||
| 1650 | if (p->fd < 0) { | ||||
| 1651 | r = p->fd; | ||||
| 1652 | goto rollback; | ||||
| 1653 | } | ||||
| 1654 | break; | ||||
| 1655 | |||||
| 1656 | case SOCKET_USB_FUNCTION: { | ||||
| 1657 | _cleanup_free___attribute__((cleanup(freep))) char *ep = NULL((void*)0); | ||||
| 1658 | |||||
| 1659 | ep = path_make_absolute("ep0", p->path); | ||||
| 1660 | |||||
| 1661 | p->fd = usbffs_address_create(ep); | ||||
| 1662 | if (p->fd < 0) { | ||||
| 1663 | r = p->fd; | ||||
| 1664 | goto rollback; | ||||
| 1665 | } | ||||
| 1666 | |||||
| 1667 | r = usbffs_write_descs(p->fd, SERVICE(UNIT_DEREF(s->service)((s->service).target))); | ||||
| 1668 | if (r < 0) | ||||
| 1669 | goto rollback; | ||||
| 1670 | |||||
| 1671 | r = usbffs_dispatch_eps(p); | ||||
| 1672 | if (r < 0) | ||||
| 1673 | goto rollback; | ||||
| 1674 | |||||
| 1675 | break; | ||||
| 1676 | } | ||||
| 1677 | default: | ||||
| 1678 | assert_not_reached("Unknown port type")do { log_assert_failed_unreachable_realm(LOG_REALM_SYSTEMD, ( "Unknown port type"), "../src/core/socket.c", 1678, __PRETTY_FUNCTION__ ); } while (0); | ||||
| 1679 | } | ||||
| 1680 | } | ||||
| 1681 | |||||
| 1682 | return 0; | ||||
| 1683 | |||||
| 1684 | rollback: | ||||
| 1685 | socket_close_fds(s); | ||||
| 1686 | return r; | ||||
| 1687 | } | ||||
| 1688 | |||||
| 1689 | static void socket_unwatch_fds(Socket *s) { | ||||
| 1690 | SocketPort *p; | ||||
| 1691 | int r; | ||||
| 1692 | |||||
| 1693 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/socket.c", 1693, __PRETTY_FUNCTION__ ); } while (0); | ||||
| 1694 | |||||
| 1695 | LIST_FOREACH(port, p, s->ports)for ((p) = (s->ports); (p); (p) = (p)->port_next) { | ||||
| 1696 | if (p->fd < 0) | ||||
| 1697 | continue; | ||||
| 1698 | |||||
| 1699 | if (!p->event_source) | ||||
| 1700 | continue; | ||||
| 1701 | |||||
| 1702 | r = sd_event_source_set_enabled(p->event_source, SD_EVENT_OFF); | ||||
| 1703 | if (r < 0) | ||||
| 1704 | log_unit_debug_errno(UNIT(s), r, "Failed to disable event source: %m")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (7, r, "../src/core/socket.c", 1704, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Failed to disable event source: %m" ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((7 ))), r, "../src/core/socket.c", 1704, __func__, "Failed to disable event source: %m" ); }); | ||||
| 1705 | } | ||||
| 1706 | } | ||||
| 1707 | |||||
| 1708 | static int socket_watch_fds(Socket *s) { | ||||
| 1709 | SocketPort *p; | ||||
| 1710 | int r; | ||||
| 1711 | |||||
| 1712 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/socket.c", 1712, __PRETTY_FUNCTION__ ); } while (0); | ||||
| 1713 | |||||
| 1714 | LIST_FOREACH(port, p, s->ports)for ((p) = (s->ports); (p); (p) = (p)->port_next) { | ||||
| 1715 | if (p->fd < 0) | ||||
| 1716 | continue; | ||||
| 1717 | |||||
| 1718 | if (p->event_source) { | ||||
| 1719 | r = sd_event_source_set_enabled(p->event_source, SD_EVENT_ON); | ||||
| 1720 | if (r < 0) | ||||
| 1721 | goto fail; | ||||
| 1722 | } else { | ||||
| 1723 | r = sd_event_add_io(UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })->manager->event, &p->event_source, p->fd, EPOLLINEPOLLIN, socket_dispatch_io, p); | ||||
| 1724 | if (r < 0) | ||||
| 1725 | goto fail; | ||||
| 1726 | |||||
| 1727 | (void) sd_event_source_set_description(p->event_source, "socket-port-io"); | ||||
| 1728 | } | ||||
| 1729 | } | ||||
| 1730 | |||||
| 1731 | return 0; | ||||
| 1732 | |||||
| 1733 | fail: | ||||
| 1734 | log_unit_warning_errno(UNIT(s), r, "Failed to watch listening fds: %m")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, r, "../src/core/socket.c", 1734, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Failed to watch listening fds: %m" ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((4 ))), r, "../src/core/socket.c", 1734, __func__, "Failed to watch listening fds: %m" ); }); | ||||
| 1735 | socket_unwatch_fds(s); | ||||
| 1736 | return r; | ||||
| 1737 | } | ||||
| 1738 | |||||
| 1739 | enum { | ||||
| 1740 | SOCKET_OPEN_NONE, | ||||
| 1741 | SOCKET_OPEN_SOME, | ||||
| 1742 | SOCKET_OPEN_ALL, | ||||
| 1743 | }; | ||||
| 1744 | |||||
| 1745 | static int socket_check_open(Socket *s) { | ||||
| 1746 | bool_Bool have_open = false0, have_closed = false0; | ||||
| 1747 | SocketPort *p; | ||||
| 1748 | |||||
| 1749 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/socket.c", 1749, __PRETTY_FUNCTION__ ); } while (0); | ||||
| 1750 | |||||
| 1751 | LIST_FOREACH(port, p, s->ports)for ((p) = (s->ports); (p); (p) = (p)->port_next) { | ||||
| 1752 | if (p->fd < 0) | ||||
| 1753 | have_closed = true1; | ||||
| 1754 | else | ||||
| 1755 | have_open = true1; | ||||
| 1756 | |||||
| 1757 | if (have_open && have_closed) | ||||
| 1758 | return SOCKET_OPEN_SOME; | ||||
| 1759 | } | ||||
| 1760 | |||||
| 1761 | if (have_open) | ||||
| 1762 | return SOCKET_OPEN_ALL; | ||||
| 1763 | |||||
| 1764 | return SOCKET_OPEN_NONE; | ||||
| 1765 | } | ||||
| 1766 | |||||
| 1767 | static void socket_set_state(Socket *s, SocketState state) { | ||||
| 1768 | SocketState old_state; | ||||
| 1769 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/socket.c", 1769, __PRETTY_FUNCTION__ ); } while (0); | ||||
| 1770 | |||||
| 1771 | old_state = s->state; | ||||
| 1772 | s->state = state; | ||||
| 1773 | |||||
| 1774 | if (!IN_SET(state,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){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 })/sizeof(int)]; switch(state) { case SOCKET_START_PRE: case SOCKET_START_CHOWN : case SOCKET_START_POST: case SOCKET_STOP_PRE: case SOCKET_STOP_PRE_SIGTERM : case SOCKET_STOP_PRE_SIGKILL: case SOCKET_STOP_POST: case SOCKET_FINAL_SIGTERM : case SOCKET_FINAL_SIGKILL: _found = 1; break; default: break ; } _found; }) | ||||
| 1775 | SOCKET_START_PRE,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){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 })/sizeof(int)]; switch(state) { case SOCKET_START_PRE: case SOCKET_START_CHOWN : case SOCKET_START_POST: case SOCKET_STOP_PRE: case SOCKET_STOP_PRE_SIGTERM : case SOCKET_STOP_PRE_SIGKILL: case SOCKET_STOP_POST: case SOCKET_FINAL_SIGTERM : case SOCKET_FINAL_SIGKILL: _found = 1; break; default: break ; } _found; }) | ||||
| 1776 | SOCKET_START_CHOWN,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){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 })/sizeof(int)]; switch(state) { case SOCKET_START_PRE: case SOCKET_START_CHOWN : case SOCKET_START_POST: case SOCKET_STOP_PRE: case SOCKET_STOP_PRE_SIGTERM : case SOCKET_STOP_PRE_SIGKILL: case SOCKET_STOP_POST: case SOCKET_FINAL_SIGTERM : case SOCKET_FINAL_SIGKILL: _found = 1; break; default: break ; } _found; }) | ||||
| 1777 | SOCKET_START_POST,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){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 })/sizeof(int)]; switch(state) { case SOCKET_START_PRE: case SOCKET_START_CHOWN : case SOCKET_START_POST: case SOCKET_STOP_PRE: case SOCKET_STOP_PRE_SIGTERM : case SOCKET_STOP_PRE_SIGKILL: case SOCKET_STOP_POST: case SOCKET_FINAL_SIGTERM : case SOCKET_FINAL_SIGKILL: _found = 1; break; default: break ; } _found; }) | ||||
| 1778 | SOCKET_STOP_PRE,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){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 })/sizeof(int)]; switch(state) { case SOCKET_START_PRE: case SOCKET_START_CHOWN : case SOCKET_START_POST: case SOCKET_STOP_PRE: case SOCKET_STOP_PRE_SIGTERM : case SOCKET_STOP_PRE_SIGKILL: case SOCKET_STOP_POST: case SOCKET_FINAL_SIGTERM : case SOCKET_FINAL_SIGKILL: _found = 1; break; default: break ; } _found; }) | ||||
| 1779 | SOCKET_STOP_PRE_SIGTERM,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){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 })/sizeof(int)]; switch(state) { case SOCKET_START_PRE: case SOCKET_START_CHOWN : case SOCKET_START_POST: case SOCKET_STOP_PRE: case SOCKET_STOP_PRE_SIGTERM : case SOCKET_STOP_PRE_SIGKILL: case SOCKET_STOP_POST: case SOCKET_FINAL_SIGTERM : case SOCKET_FINAL_SIGKILL: _found = 1; break; default: break ; } _found; }) | ||||
| 1780 | SOCKET_STOP_PRE_SIGKILL,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){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 })/sizeof(int)]; switch(state) { case SOCKET_START_PRE: case SOCKET_START_CHOWN : case SOCKET_START_POST: case SOCKET_STOP_PRE: case SOCKET_STOP_PRE_SIGTERM : case SOCKET_STOP_PRE_SIGKILL: case SOCKET_STOP_POST: case SOCKET_FINAL_SIGTERM : case SOCKET_FINAL_SIGKILL: _found = 1; break; default: break ; } _found; }) | ||||
| 1781 | SOCKET_STOP_POST,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){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 })/sizeof(int)]; switch(state) { case SOCKET_START_PRE: case SOCKET_START_CHOWN : case SOCKET_START_POST: case SOCKET_STOP_PRE: case SOCKET_STOP_PRE_SIGTERM : case SOCKET_STOP_PRE_SIGKILL: case SOCKET_STOP_POST: case SOCKET_FINAL_SIGTERM : case SOCKET_FINAL_SIGKILL: _found = 1; break; default: break ; } _found; }) | ||||
| 1782 | SOCKET_FINAL_SIGTERM,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){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 })/sizeof(int)]; switch(state) { case SOCKET_START_PRE: case SOCKET_START_CHOWN : case SOCKET_START_POST: case SOCKET_STOP_PRE: case SOCKET_STOP_PRE_SIGTERM : case SOCKET_STOP_PRE_SIGKILL: case SOCKET_STOP_POST: case SOCKET_FINAL_SIGTERM : case SOCKET_FINAL_SIGKILL: _found = 1; break; default: break ; } _found; }) | ||||
| 1783 | SOCKET_FINAL_SIGKILL)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){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 })/sizeof(int)]; switch(state) { case SOCKET_START_PRE: case SOCKET_START_CHOWN : case SOCKET_START_POST: case SOCKET_STOP_PRE: case SOCKET_STOP_PRE_SIGTERM : case SOCKET_STOP_PRE_SIGKILL: case SOCKET_STOP_POST: case SOCKET_FINAL_SIGTERM : case SOCKET_FINAL_SIGKILL: _found = 1; break; default: break ; } _found; })) { | ||||
| 1784 | |||||
| 1785 | s->timer_event_source = sd_event_source_unref(s->timer_event_source); | ||||
| 1786 | socket_unwatch_control_pid(s); | ||||
| 1787 | s->control_command = NULL((void*)0); | ||||
| 1788 | s->control_command_id = _SOCKET_EXEC_COMMAND_INVALID; | ||||
| 1789 | } | ||||
| 1790 | |||||
| 1791 | if (state != SOCKET_LISTENING) | ||||
| 1792 | socket_unwatch_fds(s); | ||||
| 1793 | |||||
| 1794 | if (!IN_SET(state,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SOCKET_START_CHOWN, SOCKET_START_POST, SOCKET_LISTENING , SOCKET_RUNNING, SOCKET_STOP_PRE, SOCKET_STOP_PRE_SIGTERM, SOCKET_STOP_PRE_SIGKILL })/sizeof(int)]; switch(state) { case SOCKET_START_CHOWN: case SOCKET_START_POST: case SOCKET_LISTENING: case SOCKET_RUNNING : case SOCKET_STOP_PRE: case SOCKET_STOP_PRE_SIGTERM: case SOCKET_STOP_PRE_SIGKILL : _found = 1; break; default: break; } _found; }) | ||||
| 1795 | SOCKET_START_CHOWN,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SOCKET_START_CHOWN, SOCKET_START_POST, SOCKET_LISTENING , SOCKET_RUNNING, SOCKET_STOP_PRE, SOCKET_STOP_PRE_SIGTERM, SOCKET_STOP_PRE_SIGKILL })/sizeof(int)]; switch(state) { case SOCKET_START_CHOWN: case SOCKET_START_POST: case SOCKET_LISTENING: case SOCKET_RUNNING : case SOCKET_STOP_PRE: case SOCKET_STOP_PRE_SIGTERM: case SOCKET_STOP_PRE_SIGKILL : _found = 1; break; default: break; } _found; }) | ||||
| 1796 | SOCKET_START_POST,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SOCKET_START_CHOWN, SOCKET_START_POST, SOCKET_LISTENING , SOCKET_RUNNING, SOCKET_STOP_PRE, SOCKET_STOP_PRE_SIGTERM, SOCKET_STOP_PRE_SIGKILL })/sizeof(int)]; switch(state) { case SOCKET_START_CHOWN: case SOCKET_START_POST: case SOCKET_LISTENING: case SOCKET_RUNNING : case SOCKET_STOP_PRE: case SOCKET_STOP_PRE_SIGTERM: case SOCKET_STOP_PRE_SIGKILL : _found = 1; break; default: break; } _found; }) | ||||
| 1797 | SOCKET_LISTENING,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SOCKET_START_CHOWN, SOCKET_START_POST, SOCKET_LISTENING , SOCKET_RUNNING, SOCKET_STOP_PRE, SOCKET_STOP_PRE_SIGTERM, SOCKET_STOP_PRE_SIGKILL })/sizeof(int)]; switch(state) { case SOCKET_START_CHOWN: case SOCKET_START_POST: case SOCKET_LISTENING: case SOCKET_RUNNING : case SOCKET_STOP_PRE: case SOCKET_STOP_PRE_SIGTERM: case SOCKET_STOP_PRE_SIGKILL : _found = 1; break; default: break; } _found; }) | ||||
| 1798 | SOCKET_RUNNING,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SOCKET_START_CHOWN, SOCKET_START_POST, SOCKET_LISTENING , SOCKET_RUNNING, SOCKET_STOP_PRE, SOCKET_STOP_PRE_SIGTERM, SOCKET_STOP_PRE_SIGKILL })/sizeof(int)]; switch(state) { case SOCKET_START_CHOWN: case SOCKET_START_POST: case SOCKET_LISTENING: case SOCKET_RUNNING : case SOCKET_STOP_PRE: case SOCKET_STOP_PRE_SIGTERM: case SOCKET_STOP_PRE_SIGKILL : _found = 1; break; default: break; } _found; }) | ||||
| 1799 | SOCKET_STOP_PRE,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SOCKET_START_CHOWN, SOCKET_START_POST, SOCKET_LISTENING , SOCKET_RUNNING, SOCKET_STOP_PRE, SOCKET_STOP_PRE_SIGTERM, SOCKET_STOP_PRE_SIGKILL })/sizeof(int)]; switch(state) { case SOCKET_START_CHOWN: case SOCKET_START_POST: case SOCKET_LISTENING: case SOCKET_RUNNING : case SOCKET_STOP_PRE: case SOCKET_STOP_PRE_SIGTERM: case SOCKET_STOP_PRE_SIGKILL : _found = 1; break; default: break; } _found; }) | ||||
| 1800 | SOCKET_STOP_PRE_SIGTERM,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SOCKET_START_CHOWN, SOCKET_START_POST, SOCKET_LISTENING , SOCKET_RUNNING, SOCKET_STOP_PRE, SOCKET_STOP_PRE_SIGTERM, SOCKET_STOP_PRE_SIGKILL })/sizeof(int)]; switch(state) { case SOCKET_START_CHOWN: case SOCKET_START_POST: case SOCKET_LISTENING: case SOCKET_RUNNING : case SOCKET_STOP_PRE: case SOCKET_STOP_PRE_SIGTERM: case SOCKET_STOP_PRE_SIGKILL : _found = 1; break; default: break; } _found; }) | ||||
| 1801 | SOCKET_STOP_PRE_SIGKILL)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SOCKET_START_CHOWN, SOCKET_START_POST, SOCKET_LISTENING , SOCKET_RUNNING, SOCKET_STOP_PRE, SOCKET_STOP_PRE_SIGTERM, SOCKET_STOP_PRE_SIGKILL })/sizeof(int)]; switch(state) { case SOCKET_START_CHOWN: case SOCKET_START_POST: case SOCKET_LISTENING: case SOCKET_RUNNING : case SOCKET_STOP_PRE: case SOCKET_STOP_PRE_SIGTERM: case SOCKET_STOP_PRE_SIGKILL : _found = 1; break; default: break; } _found; })) | ||||
| 1802 | socket_close_fds(s); | ||||
| 1803 | |||||
| 1804 | if (state != old_state) | ||||
| 1805 | log_unit_debug(UNIT(s), "Changed %s -> %s", socket_state_to_string(old_state), socket_state_to_string(state))({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (7, 0, "../src/core/socket.c", 1805, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Changed %s -> %s", socket_state_to_string (old_state), socket_state_to_string(state)) : log_internal_realm (((LOG_REALM_SYSTEMD) << 10 | ((7))), 0, "../src/core/socket.c" , 1805, __func__, "Changed %s -> %s", socket_state_to_string (old_state), socket_state_to_string(state)); }); | ||||
| 1806 | |||||
| 1807 | unit_notify(UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; }), state_translation_table[old_state], state_translation_table[state], 0); | ||||
| 1808 | } | ||||
| 1809 | |||||
| 1810 | static int socket_coldplug(Unit *u) { | ||||
| 1811 | Socket *s = SOCKET(u); | ||||
| 1812 | int r; | ||||
| 1813 | |||||
| 1814 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/socket.c", 1814, __PRETTY_FUNCTION__ ); } while (0); | ||||
| 1815 | assert(s->state == SOCKET_DEAD)do { if ((__builtin_expect(!!(!(s->state == SOCKET_DEAD)), 0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("s->state == SOCKET_DEAD" ), "../src/core/socket.c", 1815, __PRETTY_FUNCTION__); } while (0); | ||||
| 1816 | |||||
| 1817 | if (s->deserialized_state == s->state) | ||||
| 1818 | return 0; | ||||
| 1819 | |||||
| 1820 | if (s->control_pid > 0 && | ||||
| 1821 | pid_is_unwaited(s->control_pid) && | ||||
| 1822 | IN_SET(s->deserialized_state,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){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 })/sizeof(int)]; switch(s->deserialized_state) { case SOCKET_START_PRE : case SOCKET_START_CHOWN: case SOCKET_START_POST: case SOCKET_STOP_PRE : case SOCKET_STOP_PRE_SIGTERM: case SOCKET_STOP_PRE_SIGKILL: case SOCKET_STOP_POST: case SOCKET_FINAL_SIGTERM: case SOCKET_FINAL_SIGKILL : _found = 1; break; default: break; } _found; }) | ||||
| 1823 | SOCKET_START_PRE,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){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 })/sizeof(int)]; switch(s->deserialized_state) { case SOCKET_START_PRE : case SOCKET_START_CHOWN: case SOCKET_START_POST: case SOCKET_STOP_PRE : case SOCKET_STOP_PRE_SIGTERM: case SOCKET_STOP_PRE_SIGKILL: case SOCKET_STOP_POST: case SOCKET_FINAL_SIGTERM: case SOCKET_FINAL_SIGKILL : _found = 1; break; default: break; } _found; }) | ||||
| 1824 | SOCKET_START_CHOWN,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){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 })/sizeof(int)]; switch(s->deserialized_state) { case SOCKET_START_PRE : case SOCKET_START_CHOWN: case SOCKET_START_POST: case SOCKET_STOP_PRE : case SOCKET_STOP_PRE_SIGTERM: case SOCKET_STOP_PRE_SIGKILL: case SOCKET_STOP_POST: case SOCKET_FINAL_SIGTERM: case SOCKET_FINAL_SIGKILL : _found = 1; break; default: break; } _found; }) | ||||
| 1825 | SOCKET_START_POST,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){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 })/sizeof(int)]; switch(s->deserialized_state) { case SOCKET_START_PRE : case SOCKET_START_CHOWN: case SOCKET_START_POST: case SOCKET_STOP_PRE : case SOCKET_STOP_PRE_SIGTERM: case SOCKET_STOP_PRE_SIGKILL: case SOCKET_STOP_POST: case SOCKET_FINAL_SIGTERM: case SOCKET_FINAL_SIGKILL : _found = 1; break; default: break; } _found; }) | ||||
| 1826 | SOCKET_STOP_PRE,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){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 })/sizeof(int)]; switch(s->deserialized_state) { case SOCKET_START_PRE : case SOCKET_START_CHOWN: case SOCKET_START_POST: case SOCKET_STOP_PRE : case SOCKET_STOP_PRE_SIGTERM: case SOCKET_STOP_PRE_SIGKILL: case SOCKET_STOP_POST: case SOCKET_FINAL_SIGTERM: case SOCKET_FINAL_SIGKILL : _found = 1; break; default: break; } _found; }) | ||||
| 1827 | SOCKET_STOP_PRE_SIGTERM,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){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 })/sizeof(int)]; switch(s->deserialized_state) { case SOCKET_START_PRE : case SOCKET_START_CHOWN: case SOCKET_START_POST: case SOCKET_STOP_PRE : case SOCKET_STOP_PRE_SIGTERM: case SOCKET_STOP_PRE_SIGKILL: case SOCKET_STOP_POST: case SOCKET_FINAL_SIGTERM: case SOCKET_FINAL_SIGKILL : _found = 1; break; default: break; } _found; }) | ||||
| 1828 | SOCKET_STOP_PRE_SIGKILL,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){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 })/sizeof(int)]; switch(s->deserialized_state) { case SOCKET_START_PRE : case SOCKET_START_CHOWN: case SOCKET_START_POST: case SOCKET_STOP_PRE : case SOCKET_STOP_PRE_SIGTERM: case SOCKET_STOP_PRE_SIGKILL: case SOCKET_STOP_POST: case SOCKET_FINAL_SIGTERM: case SOCKET_FINAL_SIGKILL : _found = 1; break; default: break; } _found; }) | ||||
| 1829 | SOCKET_STOP_POST,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){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 })/sizeof(int)]; switch(s->deserialized_state) { case SOCKET_START_PRE : case SOCKET_START_CHOWN: case SOCKET_START_POST: case SOCKET_STOP_PRE : case SOCKET_STOP_PRE_SIGTERM: case SOCKET_STOP_PRE_SIGKILL: case SOCKET_STOP_POST: case SOCKET_FINAL_SIGTERM: case SOCKET_FINAL_SIGKILL : _found = 1; break; default: break; } _found; }) | ||||
| 1830 | SOCKET_FINAL_SIGTERM,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){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 })/sizeof(int)]; switch(s->deserialized_state) { case SOCKET_START_PRE : case SOCKET_START_CHOWN: case SOCKET_START_POST: case SOCKET_STOP_PRE : case SOCKET_STOP_PRE_SIGTERM: case SOCKET_STOP_PRE_SIGKILL: case SOCKET_STOP_POST: case SOCKET_FINAL_SIGTERM: case SOCKET_FINAL_SIGKILL : _found = 1; break; default: break; } _found; }) | ||||
| 1831 | SOCKET_FINAL_SIGKILL)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){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 })/sizeof(int)]; switch(s->deserialized_state) { case SOCKET_START_PRE : case SOCKET_START_CHOWN: case SOCKET_START_POST: case SOCKET_STOP_PRE : case SOCKET_STOP_PRE_SIGTERM: case SOCKET_STOP_PRE_SIGKILL: case SOCKET_STOP_POST: case SOCKET_FINAL_SIGTERM: case SOCKET_FINAL_SIGKILL : _found = 1; break; default: break; } _found; })) { | ||||
| 1832 | |||||
| 1833 | r = unit_watch_pid(UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; }), s->control_pid, false0); | ||||
| 1834 | if (r < 0) | ||||
| 1835 | return r; | ||||
| 1836 | |||||
| 1837 | r = socket_arm_timer(s, usec_add(u->state_change_timestamp.monotonic, s->timeout_usec)); | ||||
| 1838 | if (r < 0) | ||||
| 1839 | return r; | ||||
| 1840 | } | ||||
| 1841 | |||||
| 1842 | if (IN_SET(s->deserialized_state,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SOCKET_START_CHOWN, SOCKET_START_POST, SOCKET_LISTENING , SOCKET_RUNNING})/sizeof(int)]; switch(s->deserialized_state ) { case SOCKET_START_CHOWN: case SOCKET_START_POST: case SOCKET_LISTENING : case SOCKET_RUNNING: _found = 1; break; default: break; } _found ; }) | ||||
| 1843 | SOCKET_START_CHOWN,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SOCKET_START_CHOWN, SOCKET_START_POST, SOCKET_LISTENING , SOCKET_RUNNING})/sizeof(int)]; switch(s->deserialized_state ) { case SOCKET_START_CHOWN: case SOCKET_START_POST: case SOCKET_LISTENING : case SOCKET_RUNNING: _found = 1; break; default: break; } _found ; }) | ||||
| 1844 | SOCKET_START_POST,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SOCKET_START_CHOWN, SOCKET_START_POST, SOCKET_LISTENING , SOCKET_RUNNING})/sizeof(int)]; switch(s->deserialized_state ) { case SOCKET_START_CHOWN: case SOCKET_START_POST: case SOCKET_LISTENING : case SOCKET_RUNNING: _found = 1; break; default: break; } _found ; }) | ||||
| 1845 | SOCKET_LISTENING,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SOCKET_START_CHOWN, SOCKET_START_POST, SOCKET_LISTENING , SOCKET_RUNNING})/sizeof(int)]; switch(s->deserialized_state ) { case SOCKET_START_CHOWN: case SOCKET_START_POST: case SOCKET_LISTENING : case SOCKET_RUNNING: _found = 1; break; default: break; } _found ; }) | ||||
| 1846 | SOCKET_RUNNING)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SOCKET_START_CHOWN, SOCKET_START_POST, SOCKET_LISTENING , SOCKET_RUNNING})/sizeof(int)]; switch(s->deserialized_state ) { case SOCKET_START_CHOWN: case SOCKET_START_POST: case SOCKET_LISTENING : case SOCKET_RUNNING: _found = 1; break; default: break; } _found ; })) { | ||||
| 1847 | |||||
| 1848 | /* Originally, we used to simply reopen all sockets here that we didn't have file descriptors | ||||
| 1849 | * for. However, this is problematic, as we won't traverse throught the SOCKET_START_CHOWN state for | ||||
| 1850 | * them, and thus the UID/GID wouldn't be right. Hence, instead simply check if we have all fds open, | ||||
| 1851 | * and if there's a mismatch, warn loudly. */ | ||||
| 1852 | |||||
| 1853 | r = socket_check_open(s); | ||||
| 1854 | if (r == SOCKET_OPEN_NONE) | ||||
| 1855 | log_unit_warning(UNIT(s),({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, 0, "../src/core/socket.c", 1858, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Socket unit configuration has changed while unit has been running, " "no open socket file descriptor left. " "The socket unit is not functional until restarted." ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((4 ))), 0, "../src/core/socket.c", 1858, __func__, "Socket unit configuration has changed while unit has been running, " "no open socket file descriptor left. " "The socket unit is not functional until restarted." ); }) | ||||
| 1856 | "Socket unit configuration has changed while unit has been running, "({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, 0, "../src/core/socket.c", 1858, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Socket unit configuration has changed while unit has been running, " "no open socket file descriptor left. " "The socket unit is not functional until restarted." ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((4 ))), 0, "../src/core/socket.c", 1858, __func__, "Socket unit configuration has changed while unit has been running, " "no open socket file descriptor left. " "The socket unit is not functional until restarted." ); }) | ||||
| 1857 | "no open socket file descriptor left. "({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, 0, "../src/core/socket.c", 1858, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Socket unit configuration has changed while unit has been running, " "no open socket file descriptor left. " "The socket unit is not functional until restarted." ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((4 ))), 0, "../src/core/socket.c", 1858, __func__, "Socket unit configuration has changed while unit has been running, " "no open socket file descriptor left. " "The socket unit is not functional until restarted." ); }) | ||||
| 1858 | "The socket unit is not functional until restarted.")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, 0, "../src/core/socket.c", 1858, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Socket unit configuration has changed while unit has been running, " "no open socket file descriptor left. " "The socket unit is not functional until restarted." ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((4 ))), 0, "../src/core/socket.c", 1858, __func__, "Socket unit configuration has changed while unit has been running, " "no open socket file descriptor left. " "The socket unit is not functional until restarted." ); }); | ||||
| 1859 | else if (r == SOCKET_OPEN_SOME) | ||||
| 1860 | log_unit_warning(UNIT(s),({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, 0, "../src/core/socket.c", 1863, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Socket unit configuration has changed while unit has been running, " "and some socket file descriptors have not been opened yet. " "The socket unit is not fully functional until restarted.") : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((4))) , 0, "../src/core/socket.c", 1863, __func__, "Socket unit configuration has changed while unit has been running, " "and some socket file descriptors have not been opened yet. " "The socket unit is not fully functional until restarted."); }) | ||||
| 1861 | "Socket unit configuration has changed while unit has been running, "({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, 0, "../src/core/socket.c", 1863, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Socket unit configuration has changed while unit has been running, " "and some socket file descriptors have not been opened yet. " "The socket unit is not fully functional until restarted.") : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((4))) , 0, "../src/core/socket.c", 1863, __func__, "Socket unit configuration has changed while unit has been running, " "and some socket file descriptors have not been opened yet. " "The socket unit is not fully functional until restarted."); }) | ||||
| 1862 | "and some socket file descriptors have not been opened yet. "({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, 0, "../src/core/socket.c", 1863, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Socket unit configuration has changed while unit has been running, " "and some socket file descriptors have not been opened yet. " "The socket unit is not fully functional until restarted.") : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((4))) , 0, "../src/core/socket.c", 1863, __func__, "Socket unit configuration has changed while unit has been running, " "and some socket file descriptors have not been opened yet. " "The socket unit is not fully functional until restarted."); }) | ||||
| 1863 | "The socket unit is not fully functional until restarted.")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, 0, "../src/core/socket.c", 1863, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Socket unit configuration has changed while unit has been running, " "and some socket file descriptors have not been opened yet. " "The socket unit is not fully functional until restarted.") : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((4))) , 0, "../src/core/socket.c", 1863, __func__, "Socket unit configuration has changed while unit has been running, " "and some socket file descriptors have not been opened yet. " "The socket unit is not fully functional until restarted."); }); | ||||
| 1864 | } | ||||
| 1865 | |||||
| 1866 | if (s->deserialized_state == SOCKET_LISTENING) { | ||||
| 1867 | r = socket_watch_fds(s); | ||||
| 1868 | if (r < 0) | ||||
| 1869 | return r; | ||||
| 1870 | } | ||||
| 1871 | |||||
| 1872 | if (!IN_SET(s->deserialized_state, SOCKET_DEAD, SOCKET_FAILED)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SOCKET_DEAD, SOCKET_FAILED})/sizeof(int) ]; switch(s->deserialized_state) { case SOCKET_DEAD: case SOCKET_FAILED : _found = 1; break; default: break; } _found; })) { | ||||
| 1873 | (void) unit_setup_dynamic_creds(u); | ||||
| 1874 | (void) unit_setup_exec_runtime(u); | ||||
| 1875 | } | ||||
| 1876 | |||||
| 1877 | socket_set_state(s, s->deserialized_state); | ||||
| 1878 | return 0; | ||||
| 1879 | } | ||||
| 1880 | |||||
| 1881 | static int socket_spawn(Socket *s, ExecCommand *c, pid_t *_pid) { | ||||
| 1882 | |||||
| 1883 | ExecParameters exec_params = { | ||||
| 1884 | .flags = EXEC_APPLY_SANDBOXING|EXEC_APPLY_CHROOT|EXEC_APPLY_TTY_STDIN, | ||||
| 1885 | .stdin_fd = -1, | ||||
| 1886 | .stdout_fd = -1, | ||||
| 1887 | .stderr_fd = -1, | ||||
| 1888 | .exec_fd = -1, | ||||
| 1889 | }; | ||||
| 1890 | pid_t pid; | ||||
| 1891 | int r; | ||||
| 1892 | |||||
| 1893 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/socket.c", 1893, __PRETTY_FUNCTION__ ); } while (0); | ||||
| 1894 | assert(c)do { if ((__builtin_expect(!!(!(c)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("c"), "../src/core/socket.c", 1894, __PRETTY_FUNCTION__ ); } while (0); | ||||
| 1895 | assert(_pid)do { if ((__builtin_expect(!!(!(_pid)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("_pid"), "../src/core/socket.c", 1895, __PRETTY_FUNCTION__ ); } while (0); | ||||
| 1896 | |||||
| 1897 | r = unit_prepare_exec(UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); | ||||
| 1898 | if (r < 0) | ||||
| 1899 | return r; | ||||
| 1900 | |||||
| 1901 | r = socket_arm_timer(s, usec_add(now(CLOCK_MONOTONIC1), s->timeout_usec)); | ||||
| 1902 | if (r < 0) | ||||
| 1903 | return r; | ||||
| 1904 | |||||
| 1905 | unit_set_exec_params(UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; }), &exec_params); | ||||
| 1906 | |||||
| 1907 | exec_params.argv = c->argv; | ||||
| 1908 | |||||
| 1909 | r = exec_spawn(UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; }), | ||||
| 1910 | c, | ||||
| 1911 | &s->exec_context, | ||||
| 1912 | &exec_params, | ||||
| 1913 | s->exec_runtime, | ||||
| 1914 | &s->dynamic_creds, | ||||
| 1915 | &pid); | ||||
| 1916 | if (r < 0) | ||||
| 1917 | return r; | ||||
| 1918 | |||||
| 1919 | r = unit_watch_pid(UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; }), pid, true1); | ||||
| 1920 | if (r < 0) | ||||
| 1921 | return r; | ||||
| 1922 | |||||
| 1923 | *_pid = pid; | ||||
| 1924 | |||||
| 1925 | return 0; | ||||
| 1926 | } | ||||
| 1927 | |||||
| 1928 | static int socket_chown(Socket *s, pid_t *_pid) { | ||||
| 1929 | pid_t pid; | ||||
| 1930 | int r; | ||||
| 1931 | |||||
| 1932 | r = socket_arm_timer(s, usec_add(now(CLOCK_MONOTONIC1), s->timeout_usec)); | ||||
| 1933 | if (r < 0) | ||||
| 1934 | goto fail; | ||||
| 1935 | |||||
| 1936 | /* We have to resolve the user names out-of-process, hence | ||||
| 1937 | * let's fork here. It's messy, but well, what can we do? */ | ||||
| 1938 | |||||
| 1939 | r = unit_fork_helper_process(UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; }), "(sd-chown)", &pid); | ||||
| 1940 | if (r < 0) | ||||
| 1941 | return r; | ||||
| 1942 | if (r == 0) { | ||||
| 1943 | uid_t uid = UID_INVALID((uid_t) -1); | ||||
| 1944 | gid_t gid = GID_INVALID((gid_t) -1); | ||||
| 1945 | SocketPort *p; | ||||
| 1946 | |||||
| 1947 | /* Child */ | ||||
| 1948 | |||||
| 1949 | if (!isempty(s->user)) { | ||||
| 1950 | const char *user = s->user; | ||||
| 1951 | |||||
| 1952 | r = get_user_creds(&user, &uid, &gid, NULL((void*)0), NULL((void*)0)); | ||||
| 1953 | if (r < 0) { | ||||
| 1954 | log_unit_error_errno(UNIT(s), r, "Failed to resolve user %s: %m", user)({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (3, r, "../src/core/socket.c", 1954, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Failed to resolve user %s: %m" , user) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3))), r, "../src/core/socket.c", 1954, __func__, "Failed to resolve user %s: %m" , user); }); | ||||
| 1955 | _exit(EXIT_USER); | ||||
| 1956 | } | ||||
| 1957 | } | ||||
| 1958 | |||||
| 1959 | if (!isempty(s->group)) { | ||||
| 1960 | const char *group = s->group; | ||||
| 1961 | |||||
| 1962 | r = get_group_creds(&group, &gid); | ||||
| 1963 | if (r < 0) { | ||||
| 1964 | log_unit_error_errno(UNIT(s), r, "Failed to resolve group %s: %m", group)({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (3, r, "../src/core/socket.c", 1964, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Failed to resolve group %s: %m" , group) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3))), r, "../src/core/socket.c", 1964, __func__, "Failed to resolve group %s: %m" , group); }); | ||||
| 1965 | _exit(EXIT_GROUP); | ||||
| 1966 | } | ||||
| 1967 | } | ||||
| 1968 | |||||
| 1969 | LIST_FOREACH(port, p, s->ports)for ((p) = (s->ports); (p); (p) = (p)->port_next) { | ||||
| 1970 | const char *path = NULL((void*)0); | ||||
| 1971 | |||||
| 1972 | if (p->type == SOCKET_SOCKET) | ||||
| 1973 | path = socket_address_get_path(&p->address); | ||||
| 1974 | else if (p->type == SOCKET_FIFO) | ||||
| 1975 | path = p->path; | ||||
| 1976 | |||||
| 1977 | if (!path) | ||||
| 1978 | continue; | ||||
| 1979 | |||||
| 1980 | if (chown(path, uid, gid) < 0) { | ||||
| 1981 | log_unit_error_errno(UNIT(s), errno, "Failed to chown(): %m")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (3, (*__errno_location ()), "../src/core/socket.c", 1981, __func__ , _u->manager->unit_log_field, _u->id, _u->manager ->invocation_log_field, _u->invocation_id_string, "Failed to chown(): %m" ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3 ))), (*__errno_location ()), "../src/core/socket.c", 1981, __func__ , "Failed to chown(): %m"); }); | ||||
| 1982 | _exit(EXIT_CHOWN); | ||||
| 1983 | } | ||||
| 1984 | } | ||||
| 1985 | |||||
| 1986 | _exit(EXIT_SUCCESS0); | ||||
| 1987 | } | ||||
| 1988 | |||||
| 1989 | r = unit_watch_pid(UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; }), pid, true1); | ||||
| 1990 | if (r < 0) | ||||
| 1991 | goto fail; | ||||
| 1992 | |||||
| 1993 | *_pid = pid; | ||||
| 1994 | return 0; | ||||
| 1995 | |||||
| 1996 | fail: | ||||
| 1997 | s->timer_event_source = sd_event_source_unref(s->timer_event_source); | ||||
| 1998 | return r; | ||||
| 1999 | } | ||||
| 2000 | |||||
| 2001 | static void socket_enter_dead(Socket *s, SocketResult f) { | ||||
| 2002 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/socket.c", 2002, __PRETTY_FUNCTION__ ); } while (0); | ||||
| 2003 | |||||
| 2004 | if (s->result == SOCKET_SUCCESS) | ||||
| 2005 | s->result = f; | ||||
| 2006 | |||||
| 2007 | if (s->result == SOCKET_SUCCESS) | ||||
| 2008 | unit_log_success(UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); | ||||
| 2009 | else | ||||
| 2010 | unit_log_failure(UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; }), socket_result_to_string(s->result)); | ||||
| 2011 | |||||
| 2012 | socket_set_state(s, s->result != SOCKET_SUCCESS ? SOCKET_FAILED : SOCKET_DEAD); | ||||
| 2013 | |||||
| 2014 | s->exec_runtime = exec_runtime_unref(s->exec_runtime, true1); | ||||
| 2015 | |||||
| 2016 | exec_context_destroy_runtime_directory(&s->exec_context, UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })->manager->prefix[EXEC_DIRECTORY_RUNTIME]); | ||||
| 2017 | |||||
| 2018 | unit_unref_uid_gid(UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; }), true1); | ||||
| 2019 | |||||
| 2020 | dynamic_creds_destroy(&s->dynamic_creds); | ||||
| 2021 | } | ||||
| 2022 | |||||
| 2023 | static void socket_enter_signal(Socket *s, SocketState state, SocketResult f); | ||||
| 2024 | |||||
| 2025 | static void socket_enter_stop_post(Socket *s, SocketResult f) { | ||||
| 2026 | int r; | ||||
| 2027 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/socket.c", 2027, __PRETTY_FUNCTION__ ); } while (0); | ||||
| 2028 | |||||
| 2029 | if (s->result == SOCKET_SUCCESS) | ||||
| 2030 | s->result = f; | ||||
| 2031 | |||||
| 2032 | socket_unwatch_control_pid(s); | ||||
| 2033 | s->control_command_id = SOCKET_EXEC_STOP_POST; | ||||
| 2034 | s->control_command = s->exec_command[SOCKET_EXEC_STOP_POST]; | ||||
| 2035 | |||||
| 2036 | if (s->control_command) { | ||||
| 2037 | r = socket_spawn(s, s->control_command, &s->control_pid); | ||||
| 2038 | if (r < 0) | ||||
| 2039 | goto fail; | ||||
| 2040 | |||||
| 2041 | socket_set_state(s, SOCKET_STOP_POST); | ||||
| 2042 | } else | ||||
| 2043 | socket_enter_signal(s, SOCKET_FINAL_SIGTERM, SOCKET_SUCCESS); | ||||
| 2044 | |||||
| 2045 | return; | ||||
| 2046 | |||||
| 2047 | fail: | ||||
| 2048 | log_unit_warning_errno(UNIT(s), r, "Failed to run 'stop-post' task: %m")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, r, "../src/core/socket.c", 2048, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Failed to run 'stop-post' task: %m" ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((4 ))), r, "../src/core/socket.c", 2048, __func__, "Failed to run 'stop-post' task: %m" ); }); | ||||
| 2049 | socket_enter_signal(s, SOCKET_FINAL_SIGTERM, SOCKET_FAILURE_RESOURCES); | ||||
| 2050 | } | ||||
| 2051 | |||||
| 2052 | static void socket_enter_signal(Socket *s, SocketState state, SocketResult f) { | ||||
| 2053 | int r; | ||||
| 2054 | |||||
| 2055 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/socket.c", 2055, __PRETTY_FUNCTION__ ); } while (0); | ||||
| 2056 | |||||
| 2057 | if (s->result == SOCKET_SUCCESS) | ||||
| 2058 | s->result = f; | ||||
| 2059 | |||||
| 2060 | r = unit_kill_context( | ||||
| 2061 | UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; }), | ||||
| 2062 | &s->kill_context, | ||||
| 2063 | !IN_SET(state, SOCKET_STOP_PRE_SIGTERM, SOCKET_FINAL_SIGTERM)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SOCKET_STOP_PRE_SIGTERM, SOCKET_FINAL_SIGTERM })/sizeof(int)]; switch(state) { case SOCKET_STOP_PRE_SIGTERM : case SOCKET_FINAL_SIGTERM: _found = 1; break; default: break ; } _found; }) ? | ||||
| 2064 | KILL_KILL : KILL_TERMINATE, | ||||
| 2065 | -1, | ||||
| 2066 | s->control_pid, | ||||
| 2067 | false0); | ||||
| 2068 | if (r < 0) | ||||
| 2069 | goto fail; | ||||
| 2070 | |||||
| 2071 | if (r > 0) { | ||||
| 2072 | r = socket_arm_timer(s, usec_add(now(CLOCK_MONOTONIC1), s->timeout_usec)); | ||||
| 2073 | if (r < 0) | ||||
| 2074 | goto fail; | ||||
| 2075 | |||||
| 2076 | socket_set_state(s, state); | ||||
| 2077 | } else if (state == SOCKET_STOP_PRE_SIGTERM) | ||||
| 2078 | socket_enter_signal(s, SOCKET_STOP_PRE_SIGKILL, SOCKET_SUCCESS); | ||||
| 2079 | else if (state == SOCKET_STOP_PRE_SIGKILL) | ||||
| 2080 | socket_enter_stop_post(s, SOCKET_SUCCESS); | ||||
| 2081 | else if (state == SOCKET_FINAL_SIGTERM) | ||||
| 2082 | socket_enter_signal(s, SOCKET_FINAL_SIGKILL, SOCKET_SUCCESS); | ||||
| 2083 | else | ||||
| 2084 | socket_enter_dead(s, SOCKET_SUCCESS); | ||||
| 2085 | |||||
| 2086 | return; | ||||
| 2087 | |||||
| 2088 | fail: | ||||
| 2089 | log_unit_warning_errno(UNIT(s), r, "Failed to kill processes: %m")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, r, "../src/core/socket.c", 2089, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Failed to kill processes: %m" ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((4 ))), r, "../src/core/socket.c", 2089, __func__, "Failed to kill processes: %m" ); }); | ||||
| 2090 | |||||
| 2091 | if (IN_SET(state, SOCKET_STOP_PRE_SIGTERM, SOCKET_STOP_PRE_SIGKILL)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SOCKET_STOP_PRE_SIGTERM, SOCKET_STOP_PRE_SIGKILL })/sizeof(int)]; switch(state) { case SOCKET_STOP_PRE_SIGTERM : case SOCKET_STOP_PRE_SIGKILL: _found = 1; break; default: break ; } _found; })) | ||||
| 2092 | socket_enter_stop_post(s, SOCKET_FAILURE_RESOURCES); | ||||
| 2093 | else | ||||
| 2094 | socket_enter_dead(s, SOCKET_FAILURE_RESOURCES); | ||||
| 2095 | } | ||||
| 2096 | |||||
| 2097 | static void socket_enter_stop_pre(Socket *s, SocketResult f) { | ||||
| 2098 | int r; | ||||
| 2099 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/socket.c", 2099, __PRETTY_FUNCTION__ ); } while (0); | ||||
| 2100 | |||||
| 2101 | if (s->result == SOCKET_SUCCESS) | ||||
| 2102 | s->result = f; | ||||
| 2103 | |||||
| 2104 | socket_unwatch_control_pid(s); | ||||
| 2105 | s->control_command_id = SOCKET_EXEC_STOP_PRE; | ||||
| 2106 | s->control_command = s->exec_command[SOCKET_EXEC_STOP_PRE]; | ||||
| 2107 | |||||
| 2108 | if (s->control_command) { | ||||
| 2109 | r = socket_spawn(s, s->control_command, &s->control_pid); | ||||
| 2110 | if (r < 0) | ||||
| 2111 | goto fail; | ||||
| 2112 | |||||
| 2113 | socket_set_state(s, SOCKET_STOP_PRE); | ||||
| 2114 | } else | ||||
| 2115 | socket_enter_stop_post(s, SOCKET_SUCCESS); | ||||
| 2116 | |||||
| 2117 | return; | ||||
| 2118 | |||||
| 2119 | fail: | ||||
| 2120 | log_unit_warning_errno(UNIT(s), r, "Failed to run 'stop-pre' task: %m")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, r, "../src/core/socket.c", 2120, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Failed to run 'stop-pre' task: %m" ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((4 ))), r, "../src/core/socket.c", 2120, __func__, "Failed to run 'stop-pre' task: %m" ); }); | ||||
| 2121 | socket_enter_stop_post(s, SOCKET_FAILURE_RESOURCES); | ||||
| 2122 | } | ||||
| 2123 | |||||
| 2124 | static void socket_enter_listening(Socket *s) { | ||||
| 2125 | int r; | ||||
| 2126 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/socket.c", 2126, __PRETTY_FUNCTION__ ); } while (0); | ||||
| 2127 | |||||
| 2128 | if (!s->accept && s->flush_pending) { | ||||
| 2129 | log_unit_debug(UNIT(s), "Flushing socket before listening.")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (7, 0, "../src/core/socket.c", 2129, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Flushing socket before listening." ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((7 ))), 0, "../src/core/socket.c", 2129, __func__, "Flushing socket before listening." ); }); | ||||
| 2130 | flush_ports(s); | ||||
| 2131 | } | ||||
| 2132 | |||||
| 2133 | r = socket_watch_fds(s); | ||||
| 2134 | if (r < 0) { | ||||
| 2135 | log_unit_warning_errno(UNIT(s), r, "Failed to watch sockets: %m")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, r, "../src/core/socket.c", 2135, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Failed to watch sockets: %m") : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((4) )), r, "../src/core/socket.c", 2135, __func__, "Failed to watch sockets: %m" ); }); | ||||
| 2136 | goto fail; | ||||
| 2137 | } | ||||
| 2138 | |||||
| 2139 | socket_set_state(s, SOCKET_LISTENING); | ||||
| 2140 | return; | ||||
| 2141 | |||||
| 2142 | fail: | ||||
| 2143 | socket_enter_stop_pre(s, SOCKET_FAILURE_RESOURCES); | ||||
| 2144 | } | ||||
| 2145 | |||||
| 2146 | static void socket_enter_start_post(Socket *s) { | ||||
| 2147 | int r; | ||||
| 2148 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/socket.c", 2148, __PRETTY_FUNCTION__ ); } while (0); | ||||
| 2149 | |||||
| 2150 | socket_unwatch_control_pid(s); | ||||
| 2151 | s->control_command_id = SOCKET_EXEC_START_POST; | ||||
| 2152 | s->control_command = s->exec_command[SOCKET_EXEC_START_POST]; | ||||
| 2153 | |||||
| 2154 | if (s->control_command) { | ||||
| 2155 | r = socket_spawn(s, s->control_command, &s->control_pid); | ||||
| 2156 | if (r < 0) { | ||||
| 2157 | log_unit_warning_errno(UNIT(s), r, "Failed to run 'start-post' task: %m")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, r, "../src/core/socket.c", 2157, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Failed to run 'start-post' task: %m" ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((4 ))), r, "../src/core/socket.c", 2157, __func__, "Failed to run 'start-post' task: %m" ); }); | ||||
| 2158 | goto fail; | ||||
| 2159 | } | ||||
| 2160 | |||||
| 2161 | socket_set_state(s, SOCKET_START_POST); | ||||
| 2162 | } else | ||||
| 2163 | socket_enter_listening(s); | ||||
| 2164 | |||||
| 2165 | return; | ||||
| 2166 | |||||
| 2167 | fail: | ||||
| 2168 | socket_enter_stop_pre(s, SOCKET_FAILURE_RESOURCES); | ||||
| 2169 | } | ||||
| 2170 | |||||
| 2171 | static void socket_enter_start_chown(Socket *s) { | ||||
| 2172 | int r; | ||||
| 2173 | |||||
| 2174 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/socket.c", 2174, __PRETTY_FUNCTION__ ); } while (0); | ||||
| 2175 | |||||
| 2176 | r = socket_open_fds(s); | ||||
| 2177 | if (r < 0) { | ||||
| 2178 | log_unit_warning_errno(UNIT(s), r, "Failed to listen on sockets: %m")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, r, "../src/core/socket.c", 2178, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Failed to listen on sockets: %m" ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((4 ))), r, "../src/core/socket.c", 2178, __func__, "Failed to listen on sockets: %m" ); }); | ||||
| 2179 | goto fail; | ||||
| 2180 | } | ||||
| 2181 | |||||
| 2182 | if (!isempty(s->user) || !isempty(s->group)) { | ||||
| 2183 | |||||
| 2184 | socket_unwatch_control_pid(s); | ||||
| 2185 | s->control_command_id = SOCKET_EXEC_START_CHOWN; | ||||
| 2186 | s->control_command = NULL((void*)0); | ||||
| 2187 | |||||
| 2188 | r = socket_chown(s, &s->control_pid); | ||||
| 2189 | if (r < 0) { | ||||
| 2190 | log_unit_warning_errno(UNIT(s), r, "Failed to fork 'start-chown' task: %m")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, r, "../src/core/socket.c", 2190, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Failed to fork 'start-chown' task: %m" ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((4 ))), r, "../src/core/socket.c", 2190, __func__, "Failed to fork 'start-chown' task: %m" ); }); | ||||
| 2191 | goto fail; | ||||
| 2192 | } | ||||
| 2193 | |||||
| 2194 | socket_set_state(s, SOCKET_START_CHOWN); | ||||
| 2195 | } else | ||||
| 2196 | socket_enter_start_post(s); | ||||
| 2197 | |||||
| 2198 | return; | ||||
| 2199 | |||||
| 2200 | fail: | ||||
| 2201 | socket_enter_stop_pre(s, SOCKET_FAILURE_RESOURCES); | ||||
| 2202 | } | ||||
| 2203 | |||||
| 2204 | static void socket_enter_start_pre(Socket *s) { | ||||
| 2205 | int r; | ||||
| 2206 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/socket.c", 2206, __PRETTY_FUNCTION__ ); } while (0); | ||||
| 2207 | |||||
| 2208 | socket_unwatch_control_pid(s); | ||||
| 2209 | |||||
| 2210 | unit_warn_leftover_processes(UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); | ||||
| 2211 | |||||
| 2212 | s->control_command_id = SOCKET_EXEC_START_PRE; | ||||
| 2213 | s->control_command = s->exec_command[SOCKET_EXEC_START_PRE]; | ||||
| 2214 | |||||
| 2215 | if (s->control_command) { | ||||
| 2216 | r = socket_spawn(s, s->control_command, &s->control_pid); | ||||
| 2217 | if (r < 0) { | ||||
| 2218 | log_unit_warning_errno(UNIT(s), r, "Failed to run 'start-pre' task: %m")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, r, "../src/core/socket.c", 2218, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Failed to run 'start-pre' task: %m" ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((4 ))), r, "../src/core/socket.c", 2218, __func__, "Failed to run 'start-pre' task: %m" ); }); | ||||
| 2219 | goto fail; | ||||
| 2220 | } | ||||
| 2221 | |||||
| 2222 | socket_set_state(s, SOCKET_START_PRE); | ||||
| 2223 | } else | ||||
| 2224 | socket_enter_start_chown(s); | ||||
| 2225 | |||||
| 2226 | return; | ||||
| 2227 | |||||
| 2228 | fail: | ||||
| 2229 | socket_enter_dead(s, SOCKET_FAILURE_RESOURCES); | ||||
| 2230 | } | ||||
| 2231 | |||||
| 2232 | static void flush_ports(Socket *s) { | ||||
| 2233 | SocketPort *p; | ||||
| 2234 | |||||
| 2235 | /* Flush all incoming traffic, regardless if actual bytes or new connections, so that this socket isn't busy | ||||
| 2236 | * anymore */ | ||||
| 2237 | |||||
| 2238 | LIST_FOREACH(port, p, s->ports)for ((p) = (s->ports); (p); (p) = (p)->port_next) { | ||||
| 2239 | if (p->fd < 0) | ||||
| 2240 | continue; | ||||
| 2241 | |||||
| 2242 | (void) flush_accept(p->fd); | ||||
| 2243 | (void) flush_fd(p->fd); | ||||
| 2244 | } | ||||
| 2245 | } | ||||
| 2246 | |||||
| 2247 | static void socket_enter_running(Socket *s, int cfd) { | ||||
| 2248 | _cleanup_(sd_bus_error_free)__attribute__((cleanup(sd_bus_error_free))) sd_bus_error error = SD_BUS_ERROR_NULL((const sd_bus_error) {(((void*)0)), (((void*)0)), 0}); | ||||
| 2249 | int r; | ||||
| 2250 | |||||
| 2251 | /* Note that this call takes possession of the connection fd passed. It either has to assign it somewhere or | ||||
| 2252 | * close it. */ | ||||
| 2253 | |||||
| 2254 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/socket.c", 2254, __PRETTY_FUNCTION__ ); } while (0); | ||||
| |||||
| 2255 | |||||
| 2256 | /* We don't take connections anymore if we are supposed to shut down anyway */ | ||||
| 2257 | if (unit_stop_pending(UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; }))) { | ||||
| 2258 | |||||
| 2259 | log_unit_debug(UNIT(s), "Suppressing connection request since unit stop is scheduled.")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (7, 0, "../src/core/socket.c", 2259, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Suppressing connection request since unit stop is scheduled." ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((7 ))), 0, "../src/core/socket.c", 2259, __func__, "Suppressing connection request since unit stop is scheduled." ); }); | ||||
| 2260 | |||||
| 2261 | if (cfd >= 0) | ||||
| 2262 | goto refuse; | ||||
| 2263 | else | ||||
| 2264 | flush_ports(s); | ||||
| 2265 | |||||
| 2266 | return; | ||||
| 2267 | } | ||||
| 2268 | |||||
| 2269 | if (!ratelimit_below(&s->trigger_limit)) { | ||||
| 2270 | log_unit_warning(UNIT(s), "Trigger limit hit, refusing further activation.")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, 0, "../src/core/socket.c", 2270, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Trigger limit hit, refusing further activation." ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((4 ))), 0, "../src/core/socket.c", 2270, __func__, "Trigger limit hit, refusing further activation." ); }); | ||||
| 2271 | socket_enter_stop_pre(s, SOCKET_FAILURE_TRIGGER_LIMIT_HIT); | ||||
| 2272 | goto refuse; | ||||
| 2273 | } | ||||
| 2274 | |||||
| 2275 | if (cfd < 0) { | ||||
| 2276 | bool_Bool pending = false0; | ||||
| 2277 | Unit *other; | ||||
| 2278 | Iterator i; | ||||
| 2279 | void *v; | ||||
| 2280 | |||||
| 2281 | /* If there's already a start pending don't bother to | ||||
| 2282 | * do anything */ | ||||
| 2283 | HASHMAP_FOREACH_KEY(v, other, UNIT(s)->dependencies[UNIT_TRIGGERS], i)for ((i) = ((Iterator) { .idx = ((2147483647 *2U +1U) - 1), . next_key = ((void*)0) }); hashmap_iterate((({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_ ; })->dependencies[UNIT_TRIGGERS]), &(i), (void**)& (v), (const void**) &(other)); ) | ||||
| 2284 | if (unit_active_or_pending(other)) { | ||||
| 2285 | pending = true1; | ||||
| 2286 | break; | ||||
| 2287 | } | ||||
| 2288 | |||||
| 2289 | if (!pending) { | ||||
| 2290 | if (!UNIT_ISSET(s->service)(!!(s->service).target)) { | ||||
| 2291 | log_unit_error(UNIT(s), "Service to activate vanished, refusing activation.")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (3, 0, "../src/core/socket.c", 2291, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Service to activate vanished, refusing activation." ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3 ))), 0, "../src/core/socket.c", 2291, __func__, "Service to activate vanished, refusing activation." ); }); | ||||
| 2292 | r = -ENOENT2; | ||||
| 2293 | goto fail; | ||||
| 2294 | } | ||||
| 2295 | |||||
| 2296 | r = manager_add_job(UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })->manager, JOB_START, UNIT_DEREF(s->service)((s->service).target), JOB_REPLACE, NULL((void*)0), &error, NULL((void*)0)); | ||||
| 2297 | if (r < 0) | ||||
| 2298 | goto fail; | ||||
| 2299 | } | ||||
| 2300 | |||||
| 2301 | socket_set_state(s, SOCKET_RUNNING); | ||||
| 2302 | } else { | ||||
| 2303 | _cleanup_free___attribute__((cleanup(freep))) char *prefix = NULL((void*)0), *instance = NULL((void*)0), *name = NULL((void*)0); | ||||
| 2304 | _cleanup_(socket_peer_unrefp)__attribute__((cleanup(socket_peer_unrefp))) SocketPeer *p = NULL((void*)0); | ||||
| 2305 | Service *service; | ||||
| 2306 | |||||
| 2307 | if (s->n_connections >= s->max_connections) { | ||||
| 2308 | log_unit_warning(UNIT(s), "Too many incoming connections (%u), dropping connection.",({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, 0, "../src/core/socket.c", 2309, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Too many incoming connections (%u), dropping connection." , s->n_connections) : log_internal_realm(((LOG_REALM_SYSTEMD ) << 10 | ((4))), 0, "../src/core/socket.c", 2309, __func__ , "Too many incoming connections (%u), dropping connection.", s->n_connections); }) | ||||
| 2309 | s->n_connections)({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, 0, "../src/core/socket.c", 2309, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Too many incoming connections (%u), dropping connection." , s->n_connections) : log_internal_realm(((LOG_REALM_SYSTEMD ) << 10 | ((4))), 0, "../src/core/socket.c", 2309, __func__ , "Too many incoming connections (%u), dropping connection.", s->n_connections); }); | ||||
| 2310 | goto refuse; | ||||
| 2311 | } | ||||
| 2312 | |||||
| 2313 | if (s->max_connections_per_source > 0) { | ||||
| 2314 | r = socket_acquire_peer(s, cfd, &p); | ||||
| 2315 | if (r
| ||||
| 2316 | goto refuse; | ||||
| 2317 | } else if (r
| ||||
| 2318 | _cleanup_free___attribute__((cleanup(freep))) char *t = NULL((void*)0); | ||||
| 2319 | |||||
| 2320 | (void) sockaddr_pretty(&p->peer.sa, p->peer_salen, true1, false0, &t); | ||||
| 2321 | |||||
| 2322 | log_unit_warning(UNIT(s),({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, 0, "../src/core/socket.c", 2324, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Too many incoming connections (%u) from source %s, dropping connection." , p->n_ref, strnull(t)) : log_internal_realm(((LOG_REALM_SYSTEMD ) << 10 | ((4))), 0, "../src/core/socket.c", 2324, __func__ , "Too many incoming connections (%u) from source %s, dropping connection." , p->n_ref, strnull(t)); }) | ||||
| 2323 | "Too many incoming connections (%u) from source %s, dropping connection.",({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, 0, "../src/core/socket.c", 2324, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Too many incoming connections (%u) from source %s, dropping connection." , p->n_ref, strnull(t)) : log_internal_realm(((LOG_REALM_SYSTEMD ) << 10 | ((4))), 0, "../src/core/socket.c", 2324, __func__ , "Too many incoming connections (%u) from source %s, dropping connection." , p->n_ref, strnull(t)); }) | ||||
| 2324 | p->n_ref, strnull(t))({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, 0, "../src/core/socket.c", 2324, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Too many incoming connections (%u) from source %s, dropping connection." , p->n_ref, strnull(t)) : log_internal_realm(((LOG_REALM_SYSTEMD ) << 10 | ((4))), 0, "../src/core/socket.c", 2324, __func__ , "Too many incoming connections (%u) from source %s, dropping connection." , p->n_ref, strnull(t)); }); | ||||
| 2325 | goto refuse; | ||||
| 2326 | } | ||||
| 2327 | } | ||||
| 2328 | |||||
| 2329 | r = socket_instantiate_service(s); | ||||
| 2330 | if (r < 0) | ||||
| 2331 | goto fail; | ||||
| 2332 | |||||
| 2333 | r = instance_from_socket(cfd, s->n_accepted, &instance); | ||||
| 2334 | if (r < 0) { | ||||
| 2335 | if (r != -ENOTCONN107) | ||||
| 2336 | goto fail; | ||||
| 2337 | |||||
| 2338 | /* ENOTCONN is legitimate if TCP RST was received. | ||||
| 2339 | * This connection is over, but the socket unit lives on. */ | ||||
| 2340 | log_unit_debug(UNIT(s), "Got ENOTCONN on incoming socket, assuming aborted connection attempt, ignoring.")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (7, 0, "../src/core/socket.c", 2340, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Got ENOTCONN on incoming socket, assuming aborted connection attempt, ignoring." ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((7 ))), 0, "../src/core/socket.c", 2340, __func__, "Got ENOTCONN on incoming socket, assuming aborted connection attempt, ignoring." ); }); | ||||
| 2341 | goto refuse; | ||||
| 2342 | } | ||||
| 2343 | |||||
| 2344 | r = unit_name_to_prefix(UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })->id, &prefix); | ||||
| 2345 | if (r < 0) | ||||
| 2346 | goto fail; | ||||
| 2347 | |||||
| 2348 | r = unit_name_build(prefix, instance, ".service", &name); | ||||
| 2349 | if (r < 0) | ||||
| 2350 | goto fail; | ||||
| 2351 | |||||
| 2352 | r = unit_add_name(UNIT_DEREF(s->service)((s->service).target), name); | ||||
| 2353 | if (r < 0) | ||||
| 2354 | goto fail; | ||||
| 2355 | |||||
| 2356 | service = SERVICE(UNIT_DEREF(s->service)((s->service).target)); | ||||
| 2357 | unit_ref_unset(&s->service); | ||||
| 2358 | |||||
| 2359 | s->n_accepted++; | ||||
| 2360 | unit_choose_id(UNIT(service)({ typeof(service) _u_ = (service); Unit *_w_ = _u_ ? &(_u_ )->meta : ((void*)0); _w_; }), name); | ||||
| 2361 | |||||
| 2362 | r = service_set_socket_fd(service, cfd, s, s->selinux_context_from_net); | ||||
| 2363 | if (r < 0) | ||||
| 2364 | goto fail; | ||||
| 2365 | |||||
| 2366 | cfd = -1; /* We passed ownership of the fd to the service now. Forget it here. */ | ||||
| 2367 | s->n_connections++; | ||||
| 2368 | |||||
| 2369 | service->peer = TAKE_PTR(p)({ typeof(p) _ptr_ = (p); (p) = ((void*)0); _ptr_; }); /* Pass ownership of the peer reference */ | ||||
| 2370 | |||||
| 2371 | r = manager_add_job(UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })->manager, JOB_START, UNIT(service)({ typeof(service) _u_ = (service); Unit *_w_ = _u_ ? &(_u_ )->meta : ((void*)0); _w_; }), JOB_REPLACE, NULL((void*)0), &error, NULL((void*)0)); | ||||
| 2372 | if (r < 0) { | ||||
| 2373 | /* We failed to activate the new service, but it still exists. Let's make sure the service | ||||
| 2374 | * closes and forgets the connection fd again, immediately. */ | ||||
| 2375 | service_close_socket_fd(service); | ||||
| 2376 | goto fail; | ||||
| 2377 | } | ||||
| 2378 | |||||
| 2379 | /* Notify clients about changed counters */ | ||||
| 2380 | unit_add_to_dbus_queue(UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); | ||||
| 2381 | } | ||||
| 2382 | |||||
| 2383 | return; | ||||
| 2384 | |||||
| 2385 | refuse: | ||||
| 2386 | s->n_refused++; | ||||
| 2387 | safe_close(cfd); | ||||
| 2388 | return; | ||||
| 2389 | |||||
| 2390 | fail: | ||||
| 2391 | log_unit_warning(UNIT(s), "Failed to queue service startup job (Maybe the service file is missing or not a %s unit?): %s",({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, 0, "../src/core/socket.c", 2393, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "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_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((4))), 0, "../src/core/socket.c", 2393, __func__, "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)); }) | ||||
| |||||
| 2392 | cfd >= 0 ? "template" : "non-template",({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, 0, "../src/core/socket.c", 2393, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "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_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((4))), 0, "../src/core/socket.c", 2393, __func__, "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)); }) | ||||
| 2393 | bus_error_message(&error, r))({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, 0, "../src/core/socket.c", 2393, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "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_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((4))), 0, "../src/core/socket.c", 2393, __func__, "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)); }); | ||||
| 2394 | |||||
| 2395 | socket_enter_stop_pre(s, SOCKET_FAILURE_RESOURCES); | ||||
| 2396 | safe_close(cfd); | ||||
| 2397 | } | ||||
| 2398 | |||||
| 2399 | static void socket_run_next(Socket *s) { | ||||
| 2400 | int r; | ||||
| 2401 | |||||
| 2402 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/socket.c", 2402, __PRETTY_FUNCTION__ ); } while (0); | ||||
| 2403 | assert(s->control_command)do { if ((__builtin_expect(!!(!(s->control_command)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s->control_command"), "../src/core/socket.c" , 2403, __PRETTY_FUNCTION__); } while (0); | ||||
| 2404 | assert(s->control_command->command_next)do { if ((__builtin_expect(!!(!(s->control_command->command_next )),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("s->control_command->command_next" ), "../src/core/socket.c", 2404, __PRETTY_FUNCTION__); } while (0); | ||||
| 2405 | |||||
| 2406 | socket_unwatch_control_pid(s); | ||||
| 2407 | |||||
| 2408 | s->control_command = s->control_command->command_next; | ||||
| 2409 | |||||
| 2410 | r = socket_spawn(s, s->control_command, &s->control_pid); | ||||
| 2411 | if (r < 0) | ||||
| 2412 | goto fail; | ||||
| 2413 | |||||
| 2414 | return; | ||||
| 2415 | |||||
| 2416 | fail: | ||||
| 2417 | log_unit_warning_errno(UNIT(s), r, "Failed to run next task: %m")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, r, "../src/core/socket.c", 2417, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Failed to run next task: %m") : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((4) )), r, "../src/core/socket.c", 2417, __func__, "Failed to run next task: %m" ); }); | ||||
| 2418 | |||||
| 2419 | if (s->state == SOCKET_START_POST) | ||||
| 2420 | socket_enter_stop_pre(s, SOCKET_FAILURE_RESOURCES); | ||||
| 2421 | else if (s->state == SOCKET_STOP_POST) | ||||
| 2422 | socket_enter_dead(s, SOCKET_FAILURE_RESOURCES); | ||||
| 2423 | else | ||||
| 2424 | socket_enter_signal(s, SOCKET_FINAL_SIGTERM, SOCKET_FAILURE_RESOURCES); | ||||
| 2425 | } | ||||
| 2426 | |||||
| 2427 | static int socket_start(Unit *u) { | ||||
| 2428 | Socket *s = SOCKET(u); | ||||
| 2429 | int r; | ||||
| 2430 | |||||
| 2431 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/socket.c", 2431, __PRETTY_FUNCTION__ ); } while (0); | ||||
| 2432 | |||||
| 2433 | /* We cannot fulfill this request right now, try again later | ||||
| 2434 | * please! */ | ||||
| 2435 | if (IN_SET(s->state,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SOCKET_STOP_PRE, SOCKET_STOP_PRE_SIGKILL , SOCKET_STOP_PRE_SIGTERM, SOCKET_STOP_POST, SOCKET_FINAL_SIGTERM , SOCKET_FINAL_SIGKILL})/sizeof(int)]; switch(s->state) { case SOCKET_STOP_PRE: case SOCKET_STOP_PRE_SIGKILL: case SOCKET_STOP_PRE_SIGTERM : case SOCKET_STOP_POST: case SOCKET_FINAL_SIGTERM: case SOCKET_FINAL_SIGKILL : _found = 1; break; default: break; } _found; }) | ||||
| 2436 | SOCKET_STOP_PRE,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SOCKET_STOP_PRE, SOCKET_STOP_PRE_SIGKILL , SOCKET_STOP_PRE_SIGTERM, SOCKET_STOP_POST, SOCKET_FINAL_SIGTERM , SOCKET_FINAL_SIGKILL})/sizeof(int)]; switch(s->state) { case SOCKET_STOP_PRE: case SOCKET_STOP_PRE_SIGKILL: case SOCKET_STOP_PRE_SIGTERM : case SOCKET_STOP_POST: case SOCKET_FINAL_SIGTERM: case SOCKET_FINAL_SIGKILL : _found = 1; break; default: break; } _found; }) | ||||
| 2437 | SOCKET_STOP_PRE_SIGKILL,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SOCKET_STOP_PRE, SOCKET_STOP_PRE_SIGKILL , SOCKET_STOP_PRE_SIGTERM, SOCKET_STOP_POST, SOCKET_FINAL_SIGTERM , SOCKET_FINAL_SIGKILL})/sizeof(int)]; switch(s->state) { case SOCKET_STOP_PRE: case SOCKET_STOP_PRE_SIGKILL: case SOCKET_STOP_PRE_SIGTERM : case SOCKET_STOP_POST: case SOCKET_FINAL_SIGTERM: case SOCKET_FINAL_SIGKILL : _found = 1; break; default: break; } _found; }) | ||||
| 2438 | SOCKET_STOP_PRE_SIGTERM,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SOCKET_STOP_PRE, SOCKET_STOP_PRE_SIGKILL , SOCKET_STOP_PRE_SIGTERM, SOCKET_STOP_POST, SOCKET_FINAL_SIGTERM , SOCKET_FINAL_SIGKILL})/sizeof(int)]; switch(s->state) { case SOCKET_STOP_PRE: case SOCKET_STOP_PRE_SIGKILL: case SOCKET_STOP_PRE_SIGTERM : case SOCKET_STOP_POST: case SOCKET_FINAL_SIGTERM: case SOCKET_FINAL_SIGKILL : _found = 1; break; default: break; } _found; }) | ||||
| 2439 | SOCKET_STOP_POST,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SOCKET_STOP_PRE, SOCKET_STOP_PRE_SIGKILL , SOCKET_STOP_PRE_SIGTERM, SOCKET_STOP_POST, SOCKET_FINAL_SIGTERM , SOCKET_FINAL_SIGKILL})/sizeof(int)]; switch(s->state) { case SOCKET_STOP_PRE: case SOCKET_STOP_PRE_SIGKILL: case SOCKET_STOP_PRE_SIGTERM : case SOCKET_STOP_POST: case SOCKET_FINAL_SIGTERM: case SOCKET_FINAL_SIGKILL : _found = 1; break; default: break; } _found; }) | ||||
| 2440 | SOCKET_FINAL_SIGTERM,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SOCKET_STOP_PRE, SOCKET_STOP_PRE_SIGKILL , SOCKET_STOP_PRE_SIGTERM, SOCKET_STOP_POST, SOCKET_FINAL_SIGTERM , SOCKET_FINAL_SIGKILL})/sizeof(int)]; switch(s->state) { case SOCKET_STOP_PRE: case SOCKET_STOP_PRE_SIGKILL: case SOCKET_STOP_PRE_SIGTERM : case SOCKET_STOP_POST: case SOCKET_FINAL_SIGTERM: case SOCKET_FINAL_SIGKILL : _found = 1; break; default: break; } _found; }) | ||||
| 2441 | SOCKET_FINAL_SIGKILL)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SOCKET_STOP_PRE, SOCKET_STOP_PRE_SIGKILL , SOCKET_STOP_PRE_SIGTERM, SOCKET_STOP_POST, SOCKET_FINAL_SIGTERM , SOCKET_FINAL_SIGKILL})/sizeof(int)]; switch(s->state) { case SOCKET_STOP_PRE: case SOCKET_STOP_PRE_SIGKILL: case SOCKET_STOP_PRE_SIGTERM : case SOCKET_STOP_POST: case SOCKET_FINAL_SIGTERM: case SOCKET_FINAL_SIGKILL : _found = 1; break; default: break; } _found; })) | ||||
| 2442 | return -EAGAIN11; | ||||
| 2443 | |||||
| 2444 | /* Already on it! */ | ||||
| 2445 | if (IN_SET(s->state,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SOCKET_START_PRE, SOCKET_START_CHOWN, SOCKET_START_POST })/sizeof(int)]; switch(s->state) { case SOCKET_START_PRE: case SOCKET_START_CHOWN: case SOCKET_START_POST: _found = 1; break; default: break; } _found; }) | ||||
| 2446 | SOCKET_START_PRE,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SOCKET_START_PRE, SOCKET_START_CHOWN, SOCKET_START_POST })/sizeof(int)]; switch(s->state) { case SOCKET_START_PRE: case SOCKET_START_CHOWN: case SOCKET_START_POST: _found = 1; break; default: break; } _found; }) | ||||
| 2447 | SOCKET_START_CHOWN,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SOCKET_START_PRE, SOCKET_START_CHOWN, SOCKET_START_POST })/sizeof(int)]; switch(s->state) { case SOCKET_START_PRE: case SOCKET_START_CHOWN: case SOCKET_START_POST: _found = 1; break; default: break; } _found; }) | ||||
| 2448 | SOCKET_START_POST)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SOCKET_START_PRE, SOCKET_START_CHOWN, SOCKET_START_POST })/sizeof(int)]; switch(s->state) { case SOCKET_START_PRE: case SOCKET_START_CHOWN: case SOCKET_START_POST: _found = 1; break; default: break; } _found; })) | ||||
| 2449 | return 0; | ||||
| 2450 | |||||
| 2451 | /* Cannot run this without the service being around */ | ||||
| 2452 | if (UNIT_ISSET(s->service)(!!(s->service).target)) { | ||||
| 2453 | Service *service; | ||||
| 2454 | |||||
| 2455 | service = SERVICE(UNIT_DEREF(s->service)((s->service).target)); | ||||
| 2456 | |||||
| 2457 | if (UNIT(service)({ typeof(service) _u_ = (service); Unit *_w_ = _u_ ? &(_u_ )->meta : ((void*)0); _w_; })->load_state != UNIT_LOADED) { | ||||
| 2458 | log_unit_error(u, "Socket service %s not loaded, refusing.", UNIT(service)->id)({ const Unit *_u = (u); _u ? log_object_internal(3, 0, "../src/core/socket.c" , 2458, __func__, _u->manager->unit_log_field, _u->id , _u->manager->invocation_log_field, _u->invocation_id_string , "Socket service %s not loaded, refusing.", ({ typeof(service ) _u_ = (service); Unit *_w_ = _u_ ? &(_u_)->meta : (( void*)0); _w_; })->id) : log_internal_realm(((LOG_REALM_SYSTEMD ) << 10 | ((3))), 0, "../src/core/socket.c", 2458, __func__ , "Socket service %s not loaded, refusing.", ({ typeof(service ) _u_ = (service); Unit *_w_ = _u_ ? &(_u_)->meta : (( void*)0); _w_; })->id); }); | ||||
| 2459 | return -ENOENT2; | ||||
| 2460 | } | ||||
| 2461 | |||||
| 2462 | /* If the service is already active we cannot start the | ||||
| 2463 | * socket */ | ||||
| 2464 | if (!IN_SET(service->state, SERVICE_DEAD, SERVICE_FAILED, SERVICE_AUTO_RESTART)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SERVICE_DEAD, SERVICE_FAILED, SERVICE_AUTO_RESTART })/sizeof(int)]; switch(service->state) { case SERVICE_DEAD : case SERVICE_FAILED: case SERVICE_AUTO_RESTART: _found = 1; break; default: break; } _found; })) { | ||||
| 2465 | log_unit_error(u, "Socket service %s already active, refusing.", UNIT(service)->id)({ const Unit *_u = (u); _u ? log_object_internal(3, 0, "../src/core/socket.c" , 2465, __func__, _u->manager->unit_log_field, _u->id , _u->manager->invocation_log_field, _u->invocation_id_string , "Socket service %s already active, refusing.", ({ typeof(service ) _u_ = (service); Unit *_w_ = _u_ ? &(_u_)->meta : (( void*)0); _w_; })->id) : log_internal_realm(((LOG_REALM_SYSTEMD ) << 10 | ((3))), 0, "../src/core/socket.c", 2465, __func__ , "Socket service %s already active, refusing.", ({ typeof(service ) _u_ = (service); Unit *_w_ = _u_ ? &(_u_)->meta : (( void*)0); _w_; })->id); }); | ||||
| 2466 | return -EBUSY16; | ||||
| 2467 | } | ||||
| 2468 | } | ||||
| 2469 | |||||
| 2470 | assert(IN_SET(s->state, SOCKET_DEAD, SOCKET_FAILED))do { if ((__builtin_expect(!!(!(({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended[20 - sizeof((int[]){SOCKET_DEAD, SOCKET_FAILED})/sizeof(int)]; switch (s->state) { case SOCKET_DEAD: case SOCKET_FAILED: _found = 1; break; default: break; } _found; }))),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("IN_SET(s->state, SOCKET_DEAD, SOCKET_FAILED)" ), "../src/core/socket.c", 2470, __PRETTY_FUNCTION__); } while (0); | ||||
| 2471 | |||||
| 2472 | r = unit_start_limit_test(u); | ||||
| 2473 | if (r < 0) { | ||||
| 2474 | socket_enter_dead(s, SOCKET_FAILURE_START_LIMIT_HIT); | ||||
| 2475 | return r; | ||||
| 2476 | } | ||||
| 2477 | |||||
| 2478 | r = unit_acquire_invocation_id(u); | ||||
| 2479 | if (r < 0) | ||||
| 2480 | return r; | ||||
| 2481 | |||||
| 2482 | s->result = SOCKET_SUCCESS; | ||||
| 2483 | |||||
| 2484 | u->reset_accounting = true1; | ||||
| 2485 | |||||
| 2486 | socket_enter_start_pre(s); | ||||
| 2487 | return 1; | ||||
| 2488 | } | ||||
| 2489 | |||||
| 2490 | static int socket_stop(Unit *u) { | ||||
| 2491 | Socket *s = SOCKET(u); | ||||
| 2492 | |||||
| 2493 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/socket.c", 2493, __PRETTY_FUNCTION__ ); } while (0); | ||||
| 2494 | |||||
| 2495 | /* Already on it */ | ||||
| 2496 | if (IN_SET(s->state,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SOCKET_STOP_PRE, SOCKET_STOP_PRE_SIGTERM , SOCKET_STOP_PRE_SIGKILL, SOCKET_STOP_POST, SOCKET_FINAL_SIGTERM , SOCKET_FINAL_SIGKILL})/sizeof(int)]; switch(s->state) { case SOCKET_STOP_PRE: case SOCKET_STOP_PRE_SIGTERM: case SOCKET_STOP_PRE_SIGKILL : case SOCKET_STOP_POST: case SOCKET_FINAL_SIGTERM: case SOCKET_FINAL_SIGKILL : _found = 1; break; default: break; } _found; }) | ||||
| 2497 | SOCKET_STOP_PRE,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SOCKET_STOP_PRE, SOCKET_STOP_PRE_SIGTERM , SOCKET_STOP_PRE_SIGKILL, SOCKET_STOP_POST, SOCKET_FINAL_SIGTERM , SOCKET_FINAL_SIGKILL})/sizeof(int)]; switch(s->state) { case SOCKET_STOP_PRE: case SOCKET_STOP_PRE_SIGTERM: case SOCKET_STOP_PRE_SIGKILL : case SOCKET_STOP_POST: case SOCKET_FINAL_SIGTERM: case SOCKET_FINAL_SIGKILL : _found = 1; break; default: break; } _found; }) | ||||
| 2498 | SOCKET_STOP_PRE_SIGTERM,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SOCKET_STOP_PRE, SOCKET_STOP_PRE_SIGTERM , SOCKET_STOP_PRE_SIGKILL, SOCKET_STOP_POST, SOCKET_FINAL_SIGTERM , SOCKET_FINAL_SIGKILL})/sizeof(int)]; switch(s->state) { case SOCKET_STOP_PRE: case SOCKET_STOP_PRE_SIGTERM: case SOCKET_STOP_PRE_SIGKILL : case SOCKET_STOP_POST: case SOCKET_FINAL_SIGTERM: case SOCKET_FINAL_SIGKILL : _found = 1; break; default: break; } _found; }) | ||||
| 2499 | SOCKET_STOP_PRE_SIGKILL,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SOCKET_STOP_PRE, SOCKET_STOP_PRE_SIGTERM , SOCKET_STOP_PRE_SIGKILL, SOCKET_STOP_POST, SOCKET_FINAL_SIGTERM , SOCKET_FINAL_SIGKILL})/sizeof(int)]; switch(s->state) { case SOCKET_STOP_PRE: case SOCKET_STOP_PRE_SIGTERM: case SOCKET_STOP_PRE_SIGKILL : case SOCKET_STOP_POST: case SOCKET_FINAL_SIGTERM: case SOCKET_FINAL_SIGKILL : _found = 1; break; default: break; } _found; }) | ||||
| 2500 | SOCKET_STOP_POST,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SOCKET_STOP_PRE, SOCKET_STOP_PRE_SIGTERM , SOCKET_STOP_PRE_SIGKILL, SOCKET_STOP_POST, SOCKET_FINAL_SIGTERM , SOCKET_FINAL_SIGKILL})/sizeof(int)]; switch(s->state) { case SOCKET_STOP_PRE: case SOCKET_STOP_PRE_SIGTERM: case SOCKET_STOP_PRE_SIGKILL : case SOCKET_STOP_POST: case SOCKET_FINAL_SIGTERM: case SOCKET_FINAL_SIGKILL : _found = 1; break; default: break; } _found; }) | ||||
| 2501 | SOCKET_FINAL_SIGTERM,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SOCKET_STOP_PRE, SOCKET_STOP_PRE_SIGTERM , SOCKET_STOP_PRE_SIGKILL, SOCKET_STOP_POST, SOCKET_FINAL_SIGTERM , SOCKET_FINAL_SIGKILL})/sizeof(int)]; switch(s->state) { case SOCKET_STOP_PRE: case SOCKET_STOP_PRE_SIGTERM: case SOCKET_STOP_PRE_SIGKILL : case SOCKET_STOP_POST: case SOCKET_FINAL_SIGTERM: case SOCKET_FINAL_SIGKILL : _found = 1; break; default: break; } _found; }) | ||||
| 2502 | SOCKET_FINAL_SIGKILL)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SOCKET_STOP_PRE, SOCKET_STOP_PRE_SIGTERM , SOCKET_STOP_PRE_SIGKILL, SOCKET_STOP_POST, SOCKET_FINAL_SIGTERM , SOCKET_FINAL_SIGKILL})/sizeof(int)]; switch(s->state) { case SOCKET_STOP_PRE: case SOCKET_STOP_PRE_SIGTERM: case SOCKET_STOP_PRE_SIGKILL : case SOCKET_STOP_POST: case SOCKET_FINAL_SIGTERM: case SOCKET_FINAL_SIGKILL : _found = 1; break; default: break; } _found; })) | ||||
| 2503 | return 0; | ||||
| 2504 | |||||
| 2505 | /* If there's already something running we go directly into | ||||
| 2506 | * kill mode. */ | ||||
| 2507 | if (IN_SET(s->state,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SOCKET_START_PRE, SOCKET_START_CHOWN, SOCKET_START_POST })/sizeof(int)]; switch(s->state) { case SOCKET_START_PRE: case SOCKET_START_CHOWN: case SOCKET_START_POST: _found = 1; break; default: break; } _found; }) | ||||
| 2508 | SOCKET_START_PRE,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SOCKET_START_PRE, SOCKET_START_CHOWN, SOCKET_START_POST })/sizeof(int)]; switch(s->state) { case SOCKET_START_PRE: case SOCKET_START_CHOWN: case SOCKET_START_POST: _found = 1; break; default: break; } _found; }) | ||||
| 2509 | SOCKET_START_CHOWN,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SOCKET_START_PRE, SOCKET_START_CHOWN, SOCKET_START_POST })/sizeof(int)]; switch(s->state) { case SOCKET_START_PRE: case SOCKET_START_CHOWN: case SOCKET_START_POST: _found = 1; break; default: break; } _found; }) | ||||
| 2510 | SOCKET_START_POST)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SOCKET_START_PRE, SOCKET_START_CHOWN, SOCKET_START_POST })/sizeof(int)]; switch(s->state) { case SOCKET_START_PRE: case SOCKET_START_CHOWN: case SOCKET_START_POST: _found = 1; break; default: break; } _found; })) { | ||||
| 2511 | socket_enter_signal(s, SOCKET_STOP_PRE_SIGTERM, SOCKET_SUCCESS); | ||||
| 2512 | return -EAGAIN11; | ||||
| 2513 | } | ||||
| 2514 | |||||
| 2515 | assert(IN_SET(s->state, SOCKET_LISTENING, SOCKET_RUNNING))do { if ((__builtin_expect(!!(!(({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended[20 - sizeof((int[]){SOCKET_LISTENING, SOCKET_RUNNING})/sizeof(int )]; switch(s->state) { case SOCKET_LISTENING: case SOCKET_RUNNING : _found = 1; break; default: break; } _found; }))),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("IN_SET(s->state, SOCKET_LISTENING, SOCKET_RUNNING)" ), "../src/core/socket.c", 2515, __PRETTY_FUNCTION__); } while (0); | ||||
| 2516 | |||||
| 2517 | socket_enter_stop_pre(s, SOCKET_SUCCESS); | ||||
| 2518 | return 1; | ||||
| 2519 | } | ||||
| 2520 | |||||
| 2521 | static int socket_serialize(Unit *u, FILE *f, FDSet *fds) { | ||||
| 2522 | Socket *s = SOCKET(u); | ||||
| 2523 | SocketPort *p; | ||||
| 2524 | int r; | ||||
| 2525 | |||||
| 2526 | assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("u"), "../src/core/socket.c", 2526, __PRETTY_FUNCTION__ ); } while (0); | ||||
| 2527 | assert(f)do { if ((__builtin_expect(!!(!(f)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("f"), "../src/core/socket.c", 2527, __PRETTY_FUNCTION__ ); } while (0); | ||||
| 2528 | assert(fds)do { if ((__builtin_expect(!!(!(fds)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("fds"), "../src/core/socket.c", 2528, __PRETTY_FUNCTION__ ); } while (0); | ||||
| 2529 | |||||
| 2530 | unit_serialize_item(u, f, "state", socket_state_to_string(s->state)); | ||||
| 2531 | unit_serialize_item(u, f, "result", socket_result_to_string(s->result)); | ||||
| 2532 | unit_serialize_item_format(u, f, "n-accepted", "%u", s->n_accepted); | ||||
| 2533 | unit_serialize_item_format(u, f, "n-refused", "%u", s->n_refused); | ||||
| 2534 | |||||
| 2535 | if (s->control_pid > 0) | ||||
| 2536 | unit_serialize_item_format(u, f, "control-pid", PID_FMT"%" "i", s->control_pid); | ||||
| 2537 | |||||
| 2538 | if (s->control_command_id >= 0) | ||||
| 2539 | unit_serialize_item(u, f, "control-command", socket_exec_command_to_string(s->control_command_id)); | ||||
| 2540 | |||||
| 2541 | LIST_FOREACH(port, p, s->ports)for ((p) = (s->ports); (p); (p) = (p)->port_next) { | ||||
| 2542 | int copy; | ||||
| 2543 | |||||
| 2544 | if (p->fd < 0) | ||||
| 2545 | continue; | ||||
| 2546 | |||||
| 2547 | copy = fdset_put_dup(fds, p->fd); | ||||
| 2548 | if (copy < 0) | ||||
| 2549 | return copy; | ||||
| 2550 | |||||
| 2551 | if (p->type == SOCKET_SOCKET) { | ||||
| 2552 | _cleanup_free___attribute__((cleanup(freep))) char *t = NULL((void*)0); | ||||
| 2553 | |||||
| 2554 | r = socket_address_print(&p->address, &t); | ||||
| 2555 | if (r < 0) | ||||
| 2556 | return r; | ||||
| 2557 | |||||
| 2558 | if (socket_address_family(&p->address)((&p->address)->sockaddr.sa.sa_family) == AF_NETLINK16) | ||||
| 2559 | unit_serialize_item_format(u, f, "netlink", "%i %s", copy, t); | ||||
| 2560 | else | ||||
| 2561 | unit_serialize_item_format(u, f, "socket", "%i %i %s", copy, p->address.type, t); | ||||
| 2562 | |||||
| 2563 | } else if (p->type == SOCKET_SPECIAL) | ||||
| 2564 | unit_serialize_item_format(u, f, "special", "%i %s", copy, p->path); | ||||
| 2565 | else if (p->type == SOCKET_MQUEUE) | ||||
| 2566 | unit_serialize_item_format(u, f, "mqueue", "%i %s", copy, p->path); | ||||
| 2567 | else if (p->type == SOCKET_USB_FUNCTION) | ||||
| 2568 | unit_serialize_item_format(u, f, "ffs", "%i %s", copy, p->path); | ||||
| 2569 | else { | ||||
| 2570 | assert(p->type == SOCKET_FIFO)do { if ((__builtin_expect(!!(!(p->type == SOCKET_FIFO)),0 ))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("p->type == SOCKET_FIFO" ), "../src/core/socket.c", 2570, __PRETTY_FUNCTION__); } while (0); | ||||
| 2571 | unit_serialize_item_format(u, f, "fifo", "%i %s", copy, p->path); | ||||
| 2572 | } | ||||
| 2573 | } | ||||
| 2574 | |||||
| 2575 | return 0; | ||||
| 2576 | } | ||||
| 2577 | |||||
| 2578 | static void socket_port_take_fd(SocketPort *p, FDSet *fds, int fd) { | ||||
| 2579 | safe_close(p->fd); | ||||
| 2580 | p->fd = fdset_remove(fds, fd); | ||||
| 2581 | } | ||||
| 2582 | |||||
| 2583 | static int socket_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) { | ||||
| 2584 | Socket *s = SOCKET(u); | ||||
| 2585 | |||||
| 2586 | assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("u"), "../src/core/socket.c", 2586, __PRETTY_FUNCTION__ ); } while (0); | ||||
| 2587 | assert(key)do { if ((__builtin_expect(!!(!(key)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("key"), "../src/core/socket.c", 2587, __PRETTY_FUNCTION__ ); } while (0); | ||||
| 2588 | assert(value)do { if ((__builtin_expect(!!(!(value)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("value"), "../src/core/socket.c", 2588, __PRETTY_FUNCTION__ ); } while (0); | ||||
| 2589 | |||||
| 2590 | if (streq(key, "state")(strcmp((key),("state")) == 0)) { | ||||
| 2591 | SocketState state; | ||||
| 2592 | |||||
| 2593 | state = socket_state_from_string(value); | ||||
| 2594 | if (state < 0) | ||||
| 2595 | log_unit_debug(u, "Failed to parse state value: %s", value)({ const Unit *_u = (u); _u ? log_object_internal(7, 0, "../src/core/socket.c" , 2595, __func__, _u->manager->unit_log_field, _u->id , _u->manager->invocation_log_field, _u->invocation_id_string , "Failed to parse state value: %s", value) : log_internal_realm (((LOG_REALM_SYSTEMD) << 10 | ((7))), 0, "../src/core/socket.c" , 2595, __func__, "Failed to parse state value: %s", value); } ); | ||||
| 2596 | else | ||||
| 2597 | s->deserialized_state = state; | ||||
| 2598 | } else if (streq(key, "result")(strcmp((key),("result")) == 0)) { | ||||
| 2599 | SocketResult f; | ||||
| 2600 | |||||
| 2601 | f = socket_result_from_string(value); | ||||
| 2602 | if (f < 0) | ||||
| 2603 | log_unit_debug(u, "Failed to parse result value: %s", value)({ const Unit *_u = (u); _u ? log_object_internal(7, 0, "../src/core/socket.c" , 2603, __func__, _u->manager->unit_log_field, _u->id , _u->manager->invocation_log_field, _u->invocation_id_string , "Failed to parse result value: %s", value) : log_internal_realm (((LOG_REALM_SYSTEMD) << 10 | ((7))), 0, "../src/core/socket.c" , 2603, __func__, "Failed to parse result value: %s", value); }); | ||||
| 2604 | else if (f != SOCKET_SUCCESS) | ||||
| 2605 | s->result = f; | ||||
| 2606 | |||||
| 2607 | } else if (streq(key, "n-accepted")(strcmp((key),("n-accepted")) == 0)) { | ||||
| 2608 | unsigned k; | ||||
| 2609 | |||||
| 2610 | if (safe_atou(value, &k) < 0) | ||||
| 2611 | log_unit_debug(u, "Failed to parse n-accepted value: %s", value)({ const Unit *_u = (u); _u ? log_object_internal(7, 0, "../src/core/socket.c" , 2611, __func__, _u->manager->unit_log_field, _u->id , _u->manager->invocation_log_field, _u->invocation_id_string , "Failed to parse n-accepted value: %s", value) : log_internal_realm (((LOG_REALM_SYSTEMD) << 10 | ((7))), 0, "../src/core/socket.c" , 2611, __func__, "Failed to parse n-accepted value: %s", value ); }); | ||||
| 2612 | else | ||||
| 2613 | s->n_accepted += k; | ||||
| 2614 | } else if (streq(key, "n-refused")(strcmp((key),("n-refused")) == 0)) { | ||||
| 2615 | unsigned k; | ||||
| 2616 | |||||
| 2617 | if (safe_atou(value, &k) < 0) | ||||
| 2618 | log_unit_debug(u, "Failed to parse n-refused value: %s", value)({ const Unit *_u = (u); _u ? log_object_internal(7, 0, "../src/core/socket.c" , 2618, __func__, _u->manager->unit_log_field, _u->id , _u->manager->invocation_log_field, _u->invocation_id_string , "Failed to parse n-refused value: %s", value) : log_internal_realm (((LOG_REALM_SYSTEMD) << 10 | ((7))), 0, "../src/core/socket.c" , 2618, __func__, "Failed to parse n-refused value: %s", value ); }); | ||||
| 2619 | else | ||||
| 2620 | s->n_refused += k; | ||||
| 2621 | } else if (streq(key, "control-pid")(strcmp((key),("control-pid")) == 0)) { | ||||
| 2622 | pid_t pid; | ||||
| 2623 | |||||
| 2624 | if (parse_pid(value, &pid) < 0) | ||||
| 2625 | log_unit_debug(u, "Failed to parse control-pid value: %s", value)({ const Unit *_u = (u); _u ? log_object_internal(7, 0, "../src/core/socket.c" , 2625, __func__, _u->manager->unit_log_field, _u->id , _u->manager->invocation_log_field, _u->invocation_id_string , "Failed to parse control-pid value: %s", value) : log_internal_realm (((LOG_REALM_SYSTEMD) << 10 | ((7))), 0, "../src/core/socket.c" , 2625, __func__, "Failed to parse control-pid value: %s", value ); }); | ||||
| 2626 | else | ||||
| 2627 | s->control_pid = pid; | ||||
| 2628 | } else if (streq(key, "control-command")(strcmp((key),("control-command")) == 0)) { | ||||
| 2629 | SocketExecCommand id; | ||||
| 2630 | |||||
| 2631 | id = socket_exec_command_from_string(value); | ||||
| 2632 | if (id < 0) | ||||
| 2633 | log_unit_debug(u, "Failed to parse exec-command value: %s", value)({ const Unit *_u = (u); _u ? log_object_internal(7, 0, "../src/core/socket.c" , 2633, __func__, _u->manager->unit_log_field, _u->id , _u->manager->invocation_log_field, _u->invocation_id_string , "Failed to parse exec-command value: %s", value) : log_internal_realm (((LOG_REALM_SYSTEMD) << 10 | ((7))), 0, "../src/core/socket.c" , 2633, __func__, "Failed to parse exec-command value: %s", value ); }); | ||||
| 2634 | else { | ||||
| 2635 | s->control_command_id = id; | ||||
| 2636 | s->control_command = s->exec_command[id]; | ||||
| 2637 | } | ||||
| 2638 | } else if (streq(key, "fifo")(strcmp((key),("fifo")) == 0)) { | ||||
| 2639 | int fd, skip = 0; | ||||
| 2640 | SocketPort *p; | ||||
| 2641 | |||||
| 2642 | if (sscanf(value, "%i %n", &fd, &skip) < 1 || fd < 0 || !fdset_contains(fds, fd)) | ||||
| 2643 | log_unit_debug(u, "Failed to parse fifo value: %s", value)({ const Unit *_u = (u); _u ? log_object_internal(7, 0, "../src/core/socket.c" , 2643, __func__, _u->manager->unit_log_field, _u->id , _u->manager->invocation_log_field, _u->invocation_id_string , "Failed to parse fifo value: %s", value) : log_internal_realm (((LOG_REALM_SYSTEMD) << 10 | ((7))), 0, "../src/core/socket.c" , 2643, __func__, "Failed to parse fifo value: %s", value); } ); | ||||
| 2644 | else | ||||
| 2645 | LIST_FOREACH(port, p, s->ports)for ((p) = (s->ports); (p); (p) = (p)->port_next) | ||||
| 2646 | if (p->type == SOCKET_FIFO && | ||||
| 2647 | path_equal_or_files_same(p->path, value+skip, 0)) { | ||||
| 2648 | socket_port_take_fd(p, fds, fd); | ||||
| 2649 | break; | ||||
| 2650 | } | ||||
| 2651 | |||||
| 2652 | } else if (streq(key, "special")(strcmp((key),("special")) == 0)) { | ||||
| 2653 | int fd, skip = 0; | ||||
| 2654 | SocketPort *p; | ||||
| 2655 | |||||
| 2656 | if (sscanf(value, "%i %n", &fd, &skip) < 1 || fd < 0 || !fdset_contains(fds, fd)) | ||||
| 2657 | log_unit_debug(u, "Failed to parse special value: %s", value)({ const Unit *_u = (u); _u ? log_object_internal(7, 0, "../src/core/socket.c" , 2657, __func__, _u->manager->unit_log_field, _u->id , _u->manager->invocation_log_field, _u->invocation_id_string , "Failed to parse special value: %s", value) : log_internal_realm (((LOG_REALM_SYSTEMD) << 10 | ((7))), 0, "../src/core/socket.c" , 2657, __func__, "Failed to parse special value: %s", value) ; }); | ||||
| 2658 | else | ||||
| 2659 | LIST_FOREACH(port, p, s->ports)for ((p) = (s->ports); (p); (p) = (p)->port_next) | ||||
| 2660 | if (p->type == SOCKET_SPECIAL && | ||||
| 2661 | path_equal_or_files_same(p->path, value+skip, 0)) { | ||||
| 2662 | socket_port_take_fd(p, fds, fd); | ||||
| 2663 | break; | ||||
| 2664 | } | ||||
| 2665 | |||||
| 2666 | } else if (streq(key, "mqueue")(strcmp((key),("mqueue")) == 0)) { | ||||
| 2667 | int fd, skip = 0; | ||||
| 2668 | SocketPort *p; | ||||
| 2669 | |||||
| 2670 | if (sscanf(value, "%i %n", &fd, &skip) < 1 || fd < 0 || !fdset_contains(fds, fd)) | ||||
| 2671 | log_unit_debug(u, "Failed to parse mqueue value: %s", value)({ const Unit *_u = (u); _u ? log_object_internal(7, 0, "../src/core/socket.c" , 2671, __func__, _u->manager->unit_log_field, _u->id , _u->manager->invocation_log_field, _u->invocation_id_string , "Failed to parse mqueue value: %s", value) : log_internal_realm (((LOG_REALM_SYSTEMD) << 10 | ((7))), 0, "../src/core/socket.c" , 2671, __func__, "Failed to parse mqueue value: %s", value); }); | ||||
| 2672 | else | ||||
| 2673 | LIST_FOREACH(port, p, s->ports)for ((p) = (s->ports); (p); (p) = (p)->port_next) | ||||
| 2674 | if (p->type == SOCKET_MQUEUE && | ||||
| 2675 | streq(p->path, value+skip)(strcmp((p->path),(value+skip)) == 0)) { | ||||
| 2676 | socket_port_take_fd(p, fds, fd); | ||||
| 2677 | break; | ||||
| 2678 | } | ||||
| 2679 | |||||
| 2680 | } else if (streq(key, "socket")(strcmp((key),("socket")) == 0)) { | ||||
| 2681 | int fd, type, skip = 0; | ||||
| 2682 | SocketPort *p; | ||||
| 2683 | |||||
| 2684 | if (sscanf(value, "%i %i %n", &fd, &type, &skip) < 2 || fd < 0 || type < 0 || !fdset_contains(fds, fd)) | ||||
| 2685 | log_unit_debug(u, "Failed to parse socket value: %s", value)({ const Unit *_u = (u); _u ? log_object_internal(7, 0, "../src/core/socket.c" , 2685, __func__, _u->manager->unit_log_field, _u->id , _u->manager->invocation_log_field, _u->invocation_id_string , "Failed to parse socket value: %s", value) : log_internal_realm (((LOG_REALM_SYSTEMD) << 10 | ((7))), 0, "../src/core/socket.c" , 2685, __func__, "Failed to parse socket value: %s", value); }); | ||||
| 2686 | else | ||||
| 2687 | LIST_FOREACH(port, p, s->ports)for ((p) = (s->ports); (p); (p) = (p)->port_next) | ||||
| 2688 | if (socket_address_is(&p->address, value+skip, type)) { | ||||
| 2689 | socket_port_take_fd(p, fds, fd); | ||||
| 2690 | break; | ||||
| 2691 | } | ||||
| 2692 | |||||
| 2693 | } else if (streq(key, "netlink")(strcmp((key),("netlink")) == 0)) { | ||||
| 2694 | int fd, skip = 0; | ||||
| 2695 | SocketPort *p; | ||||
| 2696 | |||||
| 2697 | if (sscanf(value, "%i %n", &fd, &skip) < 1 || fd < 0 || !fdset_contains(fds, fd)) | ||||
| 2698 | log_unit_debug(u, "Failed to parse socket value: %s", value)({ const Unit *_u = (u); _u ? log_object_internal(7, 0, "../src/core/socket.c" , 2698, __func__, _u->manager->unit_log_field, _u->id , _u->manager->invocation_log_field, _u->invocation_id_string , "Failed to parse socket value: %s", value) : log_internal_realm (((LOG_REALM_SYSTEMD) << 10 | ((7))), 0, "../src/core/socket.c" , 2698, __func__, "Failed to parse socket value: %s", value); }); | ||||
| 2699 | else | ||||
| 2700 | LIST_FOREACH(port, p, s->ports)for ((p) = (s->ports); (p); (p) = (p)->port_next) | ||||
| 2701 | if (socket_address_is_netlink(&p->address, value+skip)) { | ||||
| 2702 | socket_port_take_fd(p, fds, fd); | ||||
| 2703 | break; | ||||
| 2704 | } | ||||
| 2705 | |||||
| 2706 | } else if (streq(key, "ffs")(strcmp((key),("ffs")) == 0)) { | ||||
| 2707 | int fd, skip = 0; | ||||
| 2708 | SocketPort *p; | ||||
| 2709 | |||||
| 2710 | if (sscanf(value, "%i %n", &fd, &skip) < 1 || fd < 0 || !fdset_contains(fds, fd)) | ||||
| 2711 | log_unit_debug(u, "Failed to parse ffs value: %s", value)({ const Unit *_u = (u); _u ? log_object_internal(7, 0, "../src/core/socket.c" , 2711, __func__, _u->manager->unit_log_field, _u->id , _u->manager->invocation_log_field, _u->invocation_id_string , "Failed to parse ffs value: %s", value) : log_internal_realm (((LOG_REALM_SYSTEMD) << 10 | ((7))), 0, "../src/core/socket.c" , 2711, __func__, "Failed to parse ffs value: %s", value); }); | ||||
| 2712 | else | ||||
| 2713 | LIST_FOREACH(port, p, s->ports)for ((p) = (s->ports); (p); (p) = (p)->port_next) | ||||
| 2714 | if (p->type == SOCKET_USB_FUNCTION && | ||||
| 2715 | path_equal_or_files_same(p->path, value+skip, 0)) { | ||||
| 2716 | socket_port_take_fd(p, fds, fd); | ||||
| 2717 | break; | ||||
| 2718 | } | ||||
| 2719 | |||||
| 2720 | } else | ||||
| 2721 | log_unit_debug(UNIT(s), "Unknown serialization key: %s", key)({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (7, 0, "../src/core/socket.c", 2721, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Unknown serialization key: %s" , key) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((7))), 0, "../src/core/socket.c", 2721, __func__, "Unknown serialization key: %s" , key); }); | ||||
| 2722 | |||||
| 2723 | return 0; | ||||
| 2724 | } | ||||
| 2725 | |||||
| 2726 | static void socket_distribute_fds(Unit *u, FDSet *fds) { | ||||
| 2727 | Socket *s = SOCKET(u); | ||||
| 2728 | SocketPort *p; | ||||
| 2729 | |||||
| 2730 | assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("u"), "../src/core/socket.c", 2730, __PRETTY_FUNCTION__ ); } while (0); | ||||
| 2731 | |||||
| 2732 | LIST_FOREACH(port, p, s->ports)for ((p) = (s->ports); (p); (p) = (p)->port_next) { | ||||
| 2733 | Iterator i; | ||||
| 2734 | int fd; | ||||
| 2735 | |||||
| 2736 | if (p->type != SOCKET_SOCKET) | ||||
| 2737 | continue; | ||||
| 2738 | |||||
| 2739 | if (p->fd >= 0) | ||||
| 2740 | continue; | ||||
| 2741 | |||||
| 2742 | FDSET_FOREACH(fd, fds, i)for ((i) = ((Iterator) { .idx = ((2147483647 *2U +1U) - 1), . next_key = ((void*)0) }), (fd) = fdset_iterate((fds), &(i )); (fd) >= 0; (fd) = fdset_iterate((fds), &(i))) { | ||||
| 2743 | if (socket_address_matches_fd(&p->address, fd)) { | ||||
| 2744 | p->fd = fdset_remove(fds, fd); | ||||
| 2745 | s->deserialized_state = SOCKET_LISTENING; | ||||
| 2746 | break; | ||||
| 2747 | } | ||||
| 2748 | } | ||||
| 2749 | } | ||||
| 2750 | } | ||||
| 2751 | |||||
| 2752 | _pure___attribute__ ((pure)) static UnitActiveState socket_active_state(Unit *u) { | ||||
| 2753 | assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("u"), "../src/core/socket.c", 2753, __PRETTY_FUNCTION__ ); } while (0); | ||||
| 2754 | |||||
| 2755 | return state_translation_table[SOCKET(u)->state]; | ||||
| 2756 | } | ||||
| 2757 | |||||
| 2758 | _pure___attribute__ ((pure)) static const char *socket_sub_state_to_string(Unit *u) { | ||||
| 2759 | assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("u"), "../src/core/socket.c", 2759, __PRETTY_FUNCTION__ ); } while (0); | ||||
| 2760 | |||||
| 2761 | return socket_state_to_string(SOCKET(u)->state); | ||||
| 2762 | } | ||||
| 2763 | |||||
| 2764 | const char* socket_port_type_to_string(SocketPort *p) { | ||||
| 2765 | |||||
| 2766 | assert(p)do { if ((__builtin_expect(!!(!(p)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("p"), "../src/core/socket.c", 2766, __PRETTY_FUNCTION__ ); } while (0); | ||||
| 2767 | |||||
| 2768 | switch (p->type) { | ||||
| 2769 | |||||
| 2770 | case SOCKET_SOCKET: | ||||
| 2771 | |||||
| 2772 | switch (p->address.type) { | ||||
| 2773 | |||||
| 2774 | case SOCK_STREAMSOCK_STREAM: | ||||
| 2775 | return "Stream"; | ||||
| 2776 | |||||
| 2777 | case SOCK_DGRAMSOCK_DGRAM: | ||||
| 2778 | return "Datagram"; | ||||
| 2779 | |||||
| 2780 | case SOCK_SEQPACKETSOCK_SEQPACKET: | ||||
| 2781 | return "SequentialPacket"; | ||||
| 2782 | |||||
| 2783 | case SOCK_RAWSOCK_RAW: | ||||
| 2784 | if (socket_address_family(&p->address)((&p->address)->sockaddr.sa.sa_family) == AF_NETLINK16) | ||||
| 2785 | return "Netlink"; | ||||
| 2786 | |||||
| 2787 | _fallthrough_; | ||||
| 2788 | default: | ||||
| 2789 | return NULL((void*)0); | ||||
| 2790 | } | ||||
| 2791 | |||||
| 2792 | case SOCKET_SPECIAL: | ||||
| 2793 | return "Special"; | ||||
| 2794 | |||||
| 2795 | case SOCKET_MQUEUE: | ||||
| 2796 | return "MessageQueue"; | ||||
| 2797 | |||||
| 2798 | case SOCKET_FIFO: | ||||
| 2799 | return "FIFO"; | ||||
| 2800 | |||||
| 2801 | case SOCKET_USB_FUNCTION: | ||||
| 2802 | return "USBFunction"; | ||||
| 2803 | |||||
| 2804 | default: | ||||
| 2805 | return NULL((void*)0); | ||||
| 2806 | } | ||||
| 2807 | } | ||||
| 2808 | |||||
| 2809 | SocketType socket_port_type_from_string(const char *s) { | ||||
| 2810 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/socket.c", 2810, __PRETTY_FUNCTION__ ); } while (0); | ||||
| 2811 | |||||
| 2812 | if (STR_IN_SET(s, "Stream", "Datagram", "SequentialPacket", "Netlink")(!!strv_find((((char**) ((const char*[]) { "Stream", "Datagram" , "SequentialPacket", "Netlink", ((void*)0) }))), (s)))) | ||||
| 2813 | return SOCKET_SOCKET; | ||||
| 2814 | else if (streq(s, "Special")(strcmp((s),("Special")) == 0)) | ||||
| 2815 | return SOCKET_SPECIAL; | ||||
| 2816 | else if (streq(s, "MessageQueue")(strcmp((s),("MessageQueue")) == 0)) | ||||
| 2817 | return SOCKET_MQUEUE; | ||||
| 2818 | else if (streq(s, "FIFO")(strcmp((s),("FIFO")) == 0)) | ||||
| 2819 | return SOCKET_FIFO; | ||||
| 2820 | else if (streq(s, "USBFunction")(strcmp((s),("USBFunction")) == 0)) | ||||
| 2821 | return SOCKET_USB_FUNCTION; | ||||
| 2822 | else | ||||
| 2823 | return _SOCKET_TYPE_INVALID; | ||||
| 2824 | } | ||||
| 2825 | |||||
| 2826 | _pure___attribute__ ((pure)) static bool_Bool socket_may_gc(Unit *u) { | ||||
| 2827 | Socket *s = SOCKET(u); | ||||
| 2828 | |||||
| 2829 | assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("u"), "../src/core/socket.c", 2829, __PRETTY_FUNCTION__ ); } while (0); | ||||
| 2830 | |||||
| 2831 | return s->n_connections == 0; | ||||
| 2832 | } | ||||
| 2833 | |||||
| 2834 | static int socket_accept_do(Socket *s, int fd) { | ||||
| 2835 | int cfd; | ||||
| 2836 | |||||
| 2837 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/socket.c", 2837, __PRETTY_FUNCTION__ ); } while (0); | ||||
| 2838 | assert(fd >= 0)do { if ((__builtin_expect(!!(!(fd >= 0)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("fd >= 0"), "../src/core/socket.c", 2838 , __PRETTY_FUNCTION__); } while (0); | ||||
| 2839 | |||||
| 2840 | for (;;) { | ||||
| 2841 | cfd = accept4(fd, NULL((void*)0), NULL((void*)0), SOCK_NONBLOCKSOCK_NONBLOCK); | ||||
| 2842 | if (cfd < 0) { | ||||
| 2843 | if (errno(*__errno_location ()) == EINTR4) | ||||
| 2844 | continue; | ||||
| 2845 | |||||
| 2846 | return -errno(*__errno_location ()); | ||||
| 2847 | } | ||||
| 2848 | |||||
| 2849 | break; | ||||
| 2850 | } | ||||
| 2851 | |||||
| 2852 | return cfd; | ||||
| 2853 | } | ||||
| 2854 | |||||
| 2855 | static int socket_accept_in_cgroup(Socket *s, SocketPort *p, int fd) { | ||||
| 2856 | _cleanup_close_pair___attribute__((cleanup(close_pairp))) int pair[2] = { -1, -1 }; | ||||
| 2857 | int cfd, r; | ||||
| 2858 | pid_t pid; | ||||
| 2859 | |||||
| 2860 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/socket.c", 2860, __PRETTY_FUNCTION__ ); } while (0); | ||||
| 2861 | assert(p)do { if ((__builtin_expect(!!(!(p)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("p"), "../src/core/socket.c", 2861, __PRETTY_FUNCTION__ ); } while (0); | ||||
| 2862 | assert(fd >= 0)do { if ((__builtin_expect(!!(!(fd >= 0)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("fd >= 0"), "../src/core/socket.c", 2862 , __PRETTY_FUNCTION__); } while (0); | ||||
| 2863 | |||||
| 2864 | /* Similar to socket_address_listen_in_cgroup(), but for accept() rathern than socket(): make sure that any | ||||
| 2865 | * connection socket is also properly associated with the cgroup. */ | ||||
| 2866 | |||||
| 2867 | if (!IN_SET(p->address.sockaddr.sa.sa_family, AF_INET, AF_INET6)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){2, 10})/sizeof(int)]; switch(p->address .sockaddr.sa.sa_family) { case 2: case 10: _found = 1; break; default: break; } _found; })) | ||||
| 2868 | goto shortcut; | ||||
| 2869 | |||||
| 2870 | r = bpf_firewall_supported(); | ||||
| 2871 | if (r < 0) | ||||
| 2872 | return r; | ||||
| 2873 | if (r == BPF_FIREWALL_UNSUPPORTED) | ||||
| 2874 | goto shortcut; | ||||
| 2875 | |||||
| 2876 | if (socketpair(AF_UNIX1, SOCK_SEQPACKETSOCK_SEQPACKET|SOCK_CLOEXECSOCK_CLOEXEC, 0, pair) < 0) | ||||
| 2877 | return log_unit_error_errno(UNIT(s), errno, "Failed to create communication channel: %m")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (3, (*__errno_location ()), "../src/core/socket.c", 2877, __func__ , _u->manager->unit_log_field, _u->id, _u->manager ->invocation_log_field, _u->invocation_id_string, "Failed to create communication channel: %m" ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3 ))), (*__errno_location ()), "../src/core/socket.c", 2877, __func__ , "Failed to create communication channel: %m"); }); | ||||
| 2878 | |||||
| 2879 | r = unit_fork_helper_process(UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; }), "(sd-accept)", &pid); | ||||
| 2880 | if (r < 0) | ||||
| 2881 | return log_unit_error_errno(UNIT(s), r, "Failed to fork off accept stub process: %m")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (3, r, "../src/core/socket.c", 2881, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Failed to fork off accept stub process: %m" ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3 ))), r, "../src/core/socket.c", 2881, __func__, "Failed to fork off accept stub process: %m" ); }); | ||||
| 2882 | if (r == 0) { | ||||
| 2883 | /* Child */ | ||||
| 2884 | |||||
| 2885 | pair[0] = safe_close(pair[0]); | ||||
| 2886 | |||||
| 2887 | cfd = socket_accept_do(s, fd); | ||||
| 2888 | if (cfd < 0) { | ||||
| 2889 | log_unit_error_errno(UNIT(s), cfd, "Failed to accept connection socket: %m")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (3, cfd, "../src/core/socket.c", 2889, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Failed to accept connection socket: %m" ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3 ))), cfd, "../src/core/socket.c", 2889, __func__, "Failed to accept connection socket: %m" ); }); | ||||
| 2890 | _exit(EXIT_FAILURE1); | ||||
| 2891 | } | ||||
| 2892 | |||||
| 2893 | r = send_one_fd(pair[1], cfd, 0)send_one_fd_iov_sa(pair[1], cfd, ((void*)0), 0, ((void*)0), 0 , 0); | ||||
| 2894 | if (r < 0) { | ||||
| 2895 | log_unit_error_errno(UNIT(s), r, "Failed to send connection socket to parent: %m")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (3, r, "../src/core/socket.c", 2895, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Failed to send connection socket to parent: %m" ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3 ))), r, "../src/core/socket.c", 2895, __func__, "Failed to send connection socket to parent: %m" ); }); | ||||
| 2896 | _exit(EXIT_FAILURE1); | ||||
| 2897 | } | ||||
| 2898 | |||||
| 2899 | _exit(EXIT_SUCCESS0); | ||||
| 2900 | } | ||||
| 2901 | |||||
| 2902 | pair[1] = safe_close(pair[1]); | ||||
| 2903 | cfd = receive_one_fd(pair[0], 0); | ||||
| 2904 | |||||
| 2905 | /* We synchronously wait for the helper, as it shouldn't be slow */ | ||||
| 2906 | r = wait_for_terminate_and_check("(sd-accept)", pid, WAIT_LOG_ABNORMAL); | ||||
| 2907 | if (r < 0) { | ||||
| 2908 | safe_close(cfd); | ||||
| 2909 | return r; | ||||
| 2910 | } | ||||
| 2911 | |||||
| 2912 | if (cfd < 0) | ||||
| 2913 | return log_unit_error_errno(UNIT(s), cfd, "Failed to receive connection socket: %m")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (3, cfd, "../src/core/socket.c", 2913, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Failed to receive connection socket: %m" ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3 ))), cfd, "../src/core/socket.c", 2913, __func__, "Failed to receive connection socket: %m" ); }); | ||||
| 2914 | |||||
| 2915 | return cfd; | ||||
| 2916 | |||||
| 2917 | shortcut: | ||||
| 2918 | cfd = socket_accept_do(s, fd); | ||||
| 2919 | if (cfd < 0) | ||||
| 2920 | return log_unit_error_errno(UNIT(s), cfd, "Failed to accept connection socket: %m")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (3, cfd, "../src/core/socket.c", 2920, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Failed to accept connection socket: %m" ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3 ))), cfd, "../src/core/socket.c", 2920, __func__, "Failed to accept connection socket: %m" ); }); | ||||
| 2921 | |||||
| 2922 | return cfd; | ||||
| 2923 | } | ||||
| 2924 | |||||
| 2925 | static int socket_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata) { | ||||
| 2926 | SocketPort *p = userdata; | ||||
| 2927 | int cfd = -1; | ||||
| 2928 | |||||
| 2929 | assert(p)do { if ((__builtin_expect(!!(!(p)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("p"), "../src/core/socket.c", 2929, __PRETTY_FUNCTION__ ); } while (0); | ||||
| 2930 | assert(fd >= 0)do { if ((__builtin_expect(!!(!(fd >= 0)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("fd >= 0"), "../src/core/socket.c", 2930 , __PRETTY_FUNCTION__); } while (0); | ||||
| 2931 | |||||
| 2932 | if (p->socket->state != SOCKET_LISTENING) | ||||
| 2933 | return 0; | ||||
| 2934 | |||||
| 2935 | log_unit_debug(UNIT(p->socket), "Incoming traffic")({ const Unit *_u = (({ typeof(p->socket) _u_ = (p->socket ); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; } )); _u ? log_object_internal(7, 0, "../src/core/socket.c", 2935 , __func__, _u->manager->unit_log_field, _u->id, _u-> manager->invocation_log_field, _u->invocation_id_string , "Incoming traffic") : log_internal_realm(((LOG_REALM_SYSTEMD ) << 10 | ((7))), 0, "../src/core/socket.c", 2935, __func__ , "Incoming traffic"); }); | ||||
| 2936 | |||||
| 2937 | if (revents != EPOLLINEPOLLIN) { | ||||
| 2938 | |||||
| 2939 | if (revents & EPOLLHUPEPOLLHUP) | ||||
| 2940 | log_unit_error(UNIT(p->socket), "Got POLLHUP on a listening socket. The service probably invoked shutdown() on it, and should better not do that.")({ const Unit *_u = (({ typeof(p->socket) _u_ = (p->socket ); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; } )); _u ? log_object_internal(3, 0, "../src/core/socket.c", 2940 , __func__, _u->manager->unit_log_field, _u->id, _u-> manager->invocation_log_field, _u->invocation_id_string , "Got POLLHUP on a listening socket. The service probably invoked shutdown() on it, and should better not do that." ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3 ))), 0, "../src/core/socket.c", 2940, __func__, "Got POLLHUP on a listening socket. The service probably invoked shutdown() on it, and should better not do that." ); }); | ||||
| 2941 | else | ||||
| 2942 | log_unit_error(UNIT(p->socket), "Got unexpected poll event (0x%x) on socket.", revents)({ const Unit *_u = (({ typeof(p->socket) _u_ = (p->socket ); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; } )); _u ? log_object_internal(3, 0, "../src/core/socket.c", 2942 , __func__, _u->manager->unit_log_field, _u->id, _u-> manager->invocation_log_field, _u->invocation_id_string , "Got unexpected poll event (0x%x) on socket.", revents) : log_internal_realm (((LOG_REALM_SYSTEMD) << 10 | ((3))), 0, "../src/core/socket.c" , 2942, __func__, "Got unexpected poll event (0x%x) on socket." , revents); }); | ||||
| 2943 | goto fail; | ||||
| 2944 | } | ||||
| 2945 | |||||
| 2946 | if (p->socket->accept && | ||||
| 2947 | p->type == SOCKET_SOCKET && | ||||
| 2948 | socket_address_can_accept(&p->address)) { | ||||
| 2949 | |||||
| 2950 | cfd = socket_accept_in_cgroup(p->socket, p, fd); | ||||
| 2951 | if (cfd < 0) | ||||
| 2952 | goto fail; | ||||
| 2953 | |||||
| 2954 | socket_apply_socket_options(p->socket, cfd); | ||||
| 2955 | } | ||||
| 2956 | |||||
| 2957 | socket_enter_running(p->socket, cfd); | ||||
| 2958 | return 0; | ||||
| 2959 | |||||
| 2960 | fail: | ||||
| 2961 | socket_enter_stop_pre(p->socket, SOCKET_FAILURE_RESOURCES); | ||||
| 2962 | return 0; | ||||
| 2963 | } | ||||
| 2964 | |||||
| 2965 | static void socket_sigchld_event(Unit *u, pid_t pid, int code, int status) { | ||||
| 2966 | Socket *s = SOCKET(u); | ||||
| 2967 | SocketResult f; | ||||
| 2968 | |||||
| 2969 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/socket.c", 2969, __PRETTY_FUNCTION__ ); } while (0); | ||||
| 2970 | assert(pid >= 0)do { if ((__builtin_expect(!!(!(pid >= 0)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("pid >= 0"), "../src/core/socket.c", 2970 , __PRETTY_FUNCTION__); } while (0); | ||||
| 2971 | |||||
| 2972 | if (pid != s->control_pid) | ||||
| 2973 | return; | ||||
| 2974 | |||||
| 2975 | s->control_pid = 0; | ||||
| 2976 | |||||
| 2977 | if (is_clean_exit(code, status, EXIT_CLEAN_COMMAND, NULL((void*)0))) | ||||
| 2978 | f = SOCKET_SUCCESS; | ||||
| 2979 | else if (code == CLD_EXITEDCLD_EXITED) | ||||
| 2980 | f = SOCKET_FAILURE_EXIT_CODE; | ||||
| 2981 | else if (code == CLD_KILLEDCLD_KILLED) | ||||
| 2982 | f = SOCKET_FAILURE_SIGNAL; | ||||
| 2983 | else if (code == CLD_DUMPEDCLD_DUMPED) | ||||
| 2984 | f = SOCKET_FAILURE_CORE_DUMP; | ||||
| 2985 | else | ||||
| 2986 | assert_not_reached("Unknown sigchld code")do { log_assert_failed_unreachable_realm(LOG_REALM_SYSTEMD, ( "Unknown sigchld code"), "../src/core/socket.c", 2986, __PRETTY_FUNCTION__ ); } while (0); | ||||
| 2987 | |||||
| 2988 | if (s->control_command) { | ||||
| 2989 | exec_status_exit(&s->control_command->exec_status, &s->exec_context, pid, code, status); | ||||
| 2990 | |||||
| 2991 | if (s->control_command->flags & EXEC_COMMAND_IGNORE_FAILURE) | ||||
| 2992 | f = SOCKET_SUCCESS; | ||||
| 2993 | } | ||||
| 2994 | |||||
| 2995 | log_unit_full(u, f == SOCKET_SUCCESS ? LOG_DEBUG : LOG_NOTICE, 0,({ const Unit *_u = (u); _u ? log_object_internal(f == SOCKET_SUCCESS ? 7 : 5, 0, "../src/core/socket.c", 2997, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Control process exited, code=%s status=%i" , sigchld_code_to_string(code), status) : log_internal_realm( ((LOG_REALM_SYSTEMD) << 10 | ((f == SOCKET_SUCCESS ? 7 : 5))), 0, "../src/core/socket.c", 2997, __func__, "Control process exited, code=%s status=%i" , sigchld_code_to_string(code), status); }) | ||||
| 2996 | "Control process exited, code=%s status=%i",({ const Unit *_u = (u); _u ? log_object_internal(f == SOCKET_SUCCESS ? 7 : 5, 0, "../src/core/socket.c", 2997, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Control process exited, code=%s status=%i" , sigchld_code_to_string(code), status) : log_internal_realm( ((LOG_REALM_SYSTEMD) << 10 | ((f == SOCKET_SUCCESS ? 7 : 5))), 0, "../src/core/socket.c", 2997, __func__, "Control process exited, code=%s status=%i" , sigchld_code_to_string(code), status); }) | ||||
| 2997 | sigchld_code_to_string(code), status)({ const Unit *_u = (u); _u ? log_object_internal(f == SOCKET_SUCCESS ? 7 : 5, 0, "../src/core/socket.c", 2997, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Control process exited, code=%s status=%i" , sigchld_code_to_string(code), status) : log_internal_realm( ((LOG_REALM_SYSTEMD) << 10 | ((f == SOCKET_SUCCESS ? 7 : 5))), 0, "../src/core/socket.c", 2997, __func__, "Control process exited, code=%s status=%i" , sigchld_code_to_string(code), status); }); | ||||
| 2998 | |||||
| 2999 | if (s->result == SOCKET_SUCCESS) | ||||
| 3000 | s->result = f; | ||||
| 3001 | |||||
| 3002 | if (s->control_command && | ||||
| 3003 | s->control_command->command_next && | ||||
| 3004 | f == SOCKET_SUCCESS) { | ||||
| 3005 | |||||
| 3006 | log_unit_debug(u, "Running next command for state %s", socket_state_to_string(s->state))({ const Unit *_u = (u); _u ? log_object_internal(7, 0, "../src/core/socket.c" , 3006, __func__, _u->manager->unit_log_field, _u->id , _u->manager->invocation_log_field, _u->invocation_id_string , "Running next command for state %s", socket_state_to_string (s->state)) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((7))), 0, "../src/core/socket.c", 3006, __func__, "Running next command for state %s" , socket_state_to_string(s->state)); }); | ||||
| 3007 | socket_run_next(s); | ||||
| 3008 | } else { | ||||
| 3009 | s->control_command = NULL((void*)0); | ||||
| 3010 | s->control_command_id = _SOCKET_EXEC_COMMAND_INVALID; | ||||
| 3011 | |||||
| 3012 | /* No further commands for this step, so let's figure | ||||
| 3013 | * out what to do next */ | ||||
| 3014 | |||||
| 3015 | log_unit_debug(u, "Got final SIGCHLD for state %s", socket_state_to_string(s->state))({ const Unit *_u = (u); _u ? log_object_internal(7, 0, "../src/core/socket.c" , 3015, __func__, _u->manager->unit_log_field, _u->id , _u->manager->invocation_log_field, _u->invocation_id_string , "Got final SIGCHLD for state %s", socket_state_to_string(s-> state)) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((7))), 0, "../src/core/socket.c", 3015, __func__, "Got final SIGCHLD for state %s" , socket_state_to_string(s->state)); }); | ||||
| 3016 | |||||
| 3017 | switch (s->state) { | ||||
| 3018 | |||||
| 3019 | case SOCKET_START_PRE: | ||||
| 3020 | if (f == SOCKET_SUCCESS) | ||||
| 3021 | socket_enter_start_chown(s); | ||||
| 3022 | else | ||||
| 3023 | socket_enter_signal(s, SOCKET_FINAL_SIGTERM, f); | ||||
| 3024 | break; | ||||
| 3025 | |||||
| 3026 | case SOCKET_START_CHOWN: | ||||
| 3027 | if (f == SOCKET_SUCCESS) | ||||
| 3028 | socket_enter_start_post(s); | ||||
| 3029 | else | ||||
| 3030 | socket_enter_stop_pre(s, f); | ||||
| 3031 | break; | ||||
| 3032 | |||||
| 3033 | case SOCKET_START_POST: | ||||
| 3034 | if (f == SOCKET_SUCCESS) | ||||
| 3035 | socket_enter_listening(s); | ||||
| 3036 | else | ||||
| 3037 | socket_enter_stop_pre(s, f); | ||||
| 3038 | break; | ||||
| 3039 | |||||
| 3040 | case SOCKET_STOP_PRE: | ||||
| 3041 | case SOCKET_STOP_PRE_SIGTERM: | ||||
| 3042 | case SOCKET_STOP_PRE_SIGKILL: | ||||
| 3043 | socket_enter_stop_post(s, f); | ||||
| 3044 | break; | ||||
| 3045 | |||||
| 3046 | case SOCKET_STOP_POST: | ||||
| 3047 | case SOCKET_FINAL_SIGTERM: | ||||
| 3048 | case SOCKET_FINAL_SIGKILL: | ||||
| 3049 | socket_enter_dead(s, f); | ||||
| 3050 | break; | ||||
| 3051 | |||||
| 3052 | default: | ||||
| 3053 | assert_not_reached("Uh, control process died at wrong time.")do { log_assert_failed_unreachable_realm(LOG_REALM_SYSTEMD, ( "Uh, control process died at wrong time."), "../src/core/socket.c" , 3053, __PRETTY_FUNCTION__); } while (0); | ||||
| 3054 | } | ||||
| 3055 | } | ||||
| 3056 | |||||
| 3057 | /* Notify clients about changed exit status */ | ||||
| 3058 | unit_add_to_dbus_queue(u); | ||||
| 3059 | } | ||||
| 3060 | |||||
| 3061 | static int socket_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata) { | ||||
| 3062 | Socket *s = SOCKET(userdata); | ||||
| 3063 | |||||
| 3064 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/socket.c", 3064, __PRETTY_FUNCTION__ ); } while (0); | ||||
| 3065 | assert(s->timer_event_source == source)do { if ((__builtin_expect(!!(!(s->timer_event_source == source )),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("s->timer_event_source == source" ), "../src/core/socket.c", 3065, __PRETTY_FUNCTION__); } while (0); | ||||
| 3066 | |||||
| 3067 | switch (s->state) { | ||||
| 3068 | |||||
| 3069 | case SOCKET_START_PRE: | ||||
| 3070 | log_unit_warning(UNIT(s), "Starting timed out. Terminating.")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, 0, "../src/core/socket.c", 3070, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Starting timed out. Terminating." ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((4 ))), 0, "../src/core/socket.c", 3070, __func__, "Starting timed out. Terminating." ); }); | ||||
| 3071 | socket_enter_signal(s, SOCKET_FINAL_SIGTERM, SOCKET_FAILURE_TIMEOUT); | ||||
| 3072 | break; | ||||
| 3073 | |||||
| 3074 | case SOCKET_START_CHOWN: | ||||
| 3075 | case SOCKET_START_POST: | ||||
| 3076 | log_unit_warning(UNIT(s), "Starting timed out. Stopping.")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, 0, "../src/core/socket.c", 3076, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Starting timed out. Stopping." ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((4 ))), 0, "../src/core/socket.c", 3076, __func__, "Starting timed out. Stopping." ); }); | ||||
| 3077 | socket_enter_stop_pre(s, SOCKET_FAILURE_TIMEOUT); | ||||
| 3078 | break; | ||||
| 3079 | |||||
| 3080 | case SOCKET_STOP_PRE: | ||||
| 3081 | log_unit_warning(UNIT(s), "Stopping timed out. Terminating.")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, 0, "../src/core/socket.c", 3081, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Stopping timed out. Terminating." ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((4 ))), 0, "../src/core/socket.c", 3081, __func__, "Stopping timed out. Terminating." ); }); | ||||
| 3082 | socket_enter_signal(s, SOCKET_STOP_PRE_SIGTERM, SOCKET_FAILURE_TIMEOUT); | ||||
| 3083 | break; | ||||
| 3084 | |||||
| 3085 | case SOCKET_STOP_PRE_SIGTERM: | ||||
| 3086 | if (s->kill_context.send_sigkill) { | ||||
| 3087 | log_unit_warning(UNIT(s), "Stopping timed out. Killing.")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, 0, "../src/core/socket.c", 3087, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Stopping timed out. Killing." ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((4 ))), 0, "../src/core/socket.c", 3087, __func__, "Stopping timed out. Killing." ); }); | ||||
| 3088 | socket_enter_signal(s, SOCKET_STOP_PRE_SIGKILL, SOCKET_FAILURE_TIMEOUT); | ||||
| 3089 | } else { | ||||
| 3090 | log_unit_warning(UNIT(s), "Stopping timed out. Skipping SIGKILL. Ignoring.")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, 0, "../src/core/socket.c", 3090, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Stopping timed out. Skipping SIGKILL. Ignoring." ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((4 ))), 0, "../src/core/socket.c", 3090, __func__, "Stopping timed out. Skipping SIGKILL. Ignoring." ); }); | ||||
| 3091 | socket_enter_stop_post(s, SOCKET_FAILURE_TIMEOUT); | ||||
| 3092 | } | ||||
| 3093 | break; | ||||
| 3094 | |||||
| 3095 | case SOCKET_STOP_PRE_SIGKILL: | ||||
| 3096 | log_unit_warning(UNIT(s), "Processes still around after SIGKILL. Ignoring.")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, 0, "../src/core/socket.c", 3096, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Processes still around after SIGKILL. Ignoring." ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((4 ))), 0, "../src/core/socket.c", 3096, __func__, "Processes still around after SIGKILL. Ignoring." ); }); | ||||
| 3097 | socket_enter_stop_post(s, SOCKET_FAILURE_TIMEOUT); | ||||
| 3098 | break; | ||||
| 3099 | |||||
| 3100 | case SOCKET_STOP_POST: | ||||
| 3101 | log_unit_warning(UNIT(s), "Stopping timed out (2). Terminating.")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, 0, "../src/core/socket.c", 3101, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Stopping timed out (2). Terminating." ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((4 ))), 0, "../src/core/socket.c", 3101, __func__, "Stopping timed out (2). Terminating." ); }); | ||||
| 3102 | socket_enter_signal(s, SOCKET_FINAL_SIGTERM, SOCKET_FAILURE_TIMEOUT); | ||||
| 3103 | break; | ||||
| 3104 | |||||
| 3105 | case SOCKET_FINAL_SIGTERM: | ||||
| 3106 | if (s->kill_context.send_sigkill) { | ||||
| 3107 | log_unit_warning(UNIT(s), "Stopping timed out (2). Killing.")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, 0, "../src/core/socket.c", 3107, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Stopping timed out (2). Killing." ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((4 ))), 0, "../src/core/socket.c", 3107, __func__, "Stopping timed out (2). Killing." ); }); | ||||
| 3108 | socket_enter_signal(s, SOCKET_FINAL_SIGKILL, SOCKET_FAILURE_TIMEOUT); | ||||
| 3109 | } else { | ||||
| 3110 | log_unit_warning(UNIT(s), "Stopping timed out (2). Skipping SIGKILL. Ignoring.")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, 0, "../src/core/socket.c", 3110, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Stopping timed out (2). Skipping SIGKILL. Ignoring." ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((4 ))), 0, "../src/core/socket.c", 3110, __func__, "Stopping timed out (2). Skipping SIGKILL. Ignoring." ); }); | ||||
| 3111 | socket_enter_dead(s, SOCKET_FAILURE_TIMEOUT); | ||||
| 3112 | } | ||||
| 3113 | break; | ||||
| 3114 | |||||
| 3115 | case SOCKET_FINAL_SIGKILL: | ||||
| 3116 | log_unit_warning(UNIT(s), "Still around after SIGKILL (2). Entering failed mode.")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, 0, "../src/core/socket.c", 3116, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Still around after SIGKILL (2). Entering failed mode." ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((4 ))), 0, "../src/core/socket.c", 3116, __func__, "Still around after SIGKILL (2). Entering failed mode." ); }); | ||||
| 3117 | socket_enter_dead(s, SOCKET_FAILURE_TIMEOUT); | ||||
| 3118 | break; | ||||
| 3119 | |||||
| 3120 | default: | ||||
| 3121 | assert_not_reached("Timeout at wrong time.")do { log_assert_failed_unreachable_realm(LOG_REALM_SYSTEMD, ( "Timeout at wrong time."), "../src/core/socket.c", 3121, __PRETTY_FUNCTION__ ); } while (0); | ||||
| 3122 | } | ||||
| 3123 | |||||
| 3124 | return 0; | ||||
| 3125 | } | ||||
| 3126 | |||||
| 3127 | int socket_collect_fds(Socket *s, int **fds) { | ||||
| 3128 | size_t k = 0, n = 0; | ||||
| 3129 | SocketPort *p; | ||||
| 3130 | int *rfds; | ||||
| 3131 | |||||
| 3132 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/socket.c", 3132, __PRETTY_FUNCTION__ ); } while (0); | ||||
| 3133 | assert(fds)do { if ((__builtin_expect(!!(!(fds)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("fds"), "../src/core/socket.c", 3133, __PRETTY_FUNCTION__ ); } while (0); | ||||
| 3134 | |||||
| 3135 | /* Called from the service code for requesting our fds */ | ||||
| 3136 | |||||
| 3137 | LIST_FOREACH(port, p, s->ports)for ((p) = (s->ports); (p); (p) = (p)->port_next) { | ||||
| 3138 | if (p->fd >= 0) | ||||
| 3139 | n++; | ||||
| 3140 | n += p->n_auxiliary_fds; | ||||
| 3141 | } | ||||
| 3142 | |||||
| 3143 | if (n <= 0) { | ||||
| 3144 | *fds = NULL((void*)0); | ||||
| 3145 | return 0; | ||||
| 3146 | } | ||||
| 3147 | |||||
| 3148 | rfds = new(int, n)((int*) malloc_multiply(sizeof(int), (n))); | ||||
| 3149 | if (!rfds) | ||||
| 3150 | return -ENOMEM12; | ||||
| 3151 | |||||
| 3152 | LIST_FOREACH(port, p, s->ports)for ((p) = (s->ports); (p); (p) = (p)->port_next) { | ||||
| 3153 | size_t i; | ||||
| 3154 | |||||
| 3155 | if (p->fd >= 0) | ||||
| 3156 | rfds[k++] = p->fd; | ||||
| 3157 | for (i = 0; i < p->n_auxiliary_fds; ++i) | ||||
| 3158 | rfds[k++] = p->auxiliary_fds[i]; | ||||
| 3159 | } | ||||
| 3160 | |||||
| 3161 | assert(k == n)do { if ((__builtin_expect(!!(!(k == n)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("k == n"), "../src/core/socket.c", 3161, __PRETTY_FUNCTION__); } while (0); | ||||
| 3162 | |||||
| 3163 | *fds = rfds; | ||||
| 3164 | return (int) n; | ||||
| 3165 | } | ||||
| 3166 | |||||
| 3167 | static void socket_reset_failed(Unit *u) { | ||||
| 3168 | Socket *s = SOCKET(u); | ||||
| 3169 | |||||
| 3170 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/socket.c", 3170, __PRETTY_FUNCTION__ ); } while (0); | ||||
| 3171 | |||||
| 3172 | if (s->state == SOCKET_FAILED) | ||||
| 3173 | socket_set_state(s, SOCKET_DEAD); | ||||
| 3174 | |||||
| 3175 | s->result = SOCKET_SUCCESS; | ||||
| 3176 | } | ||||
| 3177 | |||||
| 3178 | void socket_connection_unref(Socket *s) { | ||||
| 3179 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/socket.c", 3179, __PRETTY_FUNCTION__ ); } while (0); | ||||
| 3180 | |||||
| 3181 | /* The service is dead. Yay! | ||||
| 3182 | * | ||||
| 3183 | * This is strictly for one-instance-per-connection | ||||
| 3184 | * services. */ | ||||
| 3185 | |||||
| 3186 | assert(s->n_connections > 0)do { if ((__builtin_expect(!!(!(s->n_connections > 0)), 0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("s->n_connections > 0" ), "../src/core/socket.c", 3186, __PRETTY_FUNCTION__); } while (0); | ||||
| 3187 | s->n_connections--; | ||||
| 3188 | |||||
| 3189 | log_unit_debug(UNIT(s), "One connection closed, %u left.", s->n_connections)({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (7, 0, "../src/core/socket.c", 3189, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "One connection closed, %u left." , s->n_connections) : log_internal_realm(((LOG_REALM_SYSTEMD ) << 10 | ((7))), 0, "../src/core/socket.c", 3189, __func__ , "One connection closed, %u left.", s->n_connections); }); | ||||
| 3190 | } | ||||
| 3191 | |||||
| 3192 | static void socket_trigger_notify(Unit *u, Unit *other) { | ||||
| 3193 | Socket *s = SOCKET(u); | ||||
| 3194 | |||||
| 3195 | assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("u"), "../src/core/socket.c", 3195, __PRETTY_FUNCTION__ ); } while (0); | ||||
| 3196 | assert(other)do { if ((__builtin_expect(!!(!(other)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("other"), "../src/core/socket.c", 3196, __PRETTY_FUNCTION__ ); } while (0); | ||||
| 3197 | |||||
| 3198 | /* Filter out invocations with bogus state */ | ||||
| 3199 | if (other->load_state != UNIT_LOADED || other->type != UNIT_SERVICE) | ||||
| 3200 | return; | ||||
| 3201 | |||||
| 3202 | /* Don't propagate state changes from the service if we are already down */ | ||||
| 3203 | if (!IN_SET(s->state, SOCKET_RUNNING, SOCKET_LISTENING)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SOCKET_RUNNING, SOCKET_LISTENING})/sizeof (int)]; switch(s->state) { case SOCKET_RUNNING: case SOCKET_LISTENING : _found = 1; break; default: break; } _found; })) | ||||
| 3204 | return; | ||||
| 3205 | |||||
| 3206 | /* We don't care for the service state if we are in Accept=yes mode */ | ||||
| 3207 | if (s->accept) | ||||
| 3208 | return; | ||||
| 3209 | |||||
| 3210 | /* Propagate start limit hit state */ | ||||
| 3211 | if (other->start_limit_hit) { | ||||
| 3212 | socket_enter_stop_pre(s, SOCKET_FAILURE_SERVICE_START_LIMIT_HIT); | ||||
| 3213 | return; | ||||
| 3214 | } | ||||
| 3215 | |||||
| 3216 | /* Don't propagate anything if there's still a job queued */ | ||||
| 3217 | if (other->job) | ||||
| 3218 | return; | ||||
| 3219 | |||||
| 3220 | if (IN_SET(SERVICE(other)->state,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SERVICE_DEAD, SERVICE_FAILED, SERVICE_FINAL_SIGTERM , SERVICE_FINAL_SIGKILL, SERVICE_AUTO_RESTART})/sizeof(int)]; switch(SERVICE(other)->state) { case SERVICE_DEAD: case SERVICE_FAILED : case SERVICE_FINAL_SIGTERM: case SERVICE_FINAL_SIGKILL: case SERVICE_AUTO_RESTART: _found = 1; break; default: break; } _found ; }) | ||||
| 3221 | SERVICE_DEAD, SERVICE_FAILED,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SERVICE_DEAD, SERVICE_FAILED, SERVICE_FINAL_SIGTERM , SERVICE_FINAL_SIGKILL, SERVICE_AUTO_RESTART})/sizeof(int)]; switch(SERVICE(other)->state) { case SERVICE_DEAD: case SERVICE_FAILED : case SERVICE_FINAL_SIGTERM: case SERVICE_FINAL_SIGKILL: case SERVICE_AUTO_RESTART: _found = 1; break; default: break; } _found ; }) | ||||
| 3222 | SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SERVICE_DEAD, SERVICE_FAILED, SERVICE_FINAL_SIGTERM , SERVICE_FINAL_SIGKILL, SERVICE_AUTO_RESTART})/sizeof(int)]; switch(SERVICE(other)->state) { case SERVICE_DEAD: case SERVICE_FAILED : case SERVICE_FINAL_SIGTERM: case SERVICE_FINAL_SIGKILL: case SERVICE_AUTO_RESTART: _found = 1; break; default: break; } _found ; }) | ||||
| 3223 | SERVICE_AUTO_RESTART)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SERVICE_DEAD, SERVICE_FAILED, SERVICE_FINAL_SIGTERM , SERVICE_FINAL_SIGKILL, SERVICE_AUTO_RESTART})/sizeof(int)]; switch(SERVICE(other)->state) { case SERVICE_DEAD: case SERVICE_FAILED : case SERVICE_FINAL_SIGTERM: case SERVICE_FINAL_SIGKILL: case SERVICE_AUTO_RESTART: _found = 1; break; default: break; } _found ; })) | ||||
| 3224 | socket_enter_listening(s); | ||||
| 3225 | |||||
| 3226 | if (SERVICE(other)->state == SERVICE_RUNNING) | ||||
| 3227 | socket_set_state(s, SOCKET_RUNNING); | ||||
| 3228 | } | ||||
| 3229 | |||||
| 3230 | static int socket_kill(Unit *u, KillWho who, int signo, sd_bus_error *error) { | ||||
| 3231 | return unit_kill_common(u, who, signo, -1, SOCKET(u)->control_pid, error); | ||||
| 3232 | } | ||||
| 3233 | |||||
| 3234 | static int socket_get_timeout(Unit *u, usec_t *timeout) { | ||||
| 3235 | Socket *s = SOCKET(u); | ||||
| 3236 | usec_t t; | ||||
| 3237 | int r; | ||||
| 3238 | |||||
| 3239 | if (!s->timer_event_source) | ||||
| 3240 | return 0; | ||||
| 3241 | |||||
| 3242 | r = sd_event_source_get_time(s->timer_event_source, &t); | ||||
| 3243 | if (r < 0) | ||||
| 3244 | return r; | ||||
| 3245 | if (t == USEC_INFINITY((usec_t) -1)) | ||||
| 3246 | return 0; | ||||
| 3247 | |||||
| 3248 | *timeout = t; | ||||
| 3249 | return 1; | ||||
| 3250 | } | ||||
| 3251 | |||||
| 3252 | char *socket_fdname(Socket *s) { | ||||
| 3253 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/socket.c", 3253, __PRETTY_FUNCTION__ ); } while (0); | ||||
| 3254 | |||||
| 3255 | /* Returns the name to use for $LISTEN_NAMES. If the user | ||||
| 3256 | * didn't specify anything specifically, use the socket unit's | ||||
| 3257 | * name as fallback. */ | ||||
| 3258 | |||||
| 3259 | return s->fdname ?: UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })->id; | ||||
| 3260 | } | ||||
| 3261 | |||||
| 3262 | static int socket_control_pid(Unit *u) { | ||||
| 3263 | Socket *s = SOCKET(u); | ||||
| 3264 | |||||
| 3265 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/socket.c", 3265, __PRETTY_FUNCTION__ ); } while (0); | ||||
| 3266 | |||||
| 3267 | return s->control_pid; | ||||
| 3268 | } | ||||
| 3269 | |||||
| 3270 | static const char* const socket_exec_command_table[_SOCKET_EXEC_COMMAND_MAX] = { | ||||
| 3271 | [SOCKET_EXEC_START_PRE] = "ExecStartPre", | ||||
| 3272 | [SOCKET_EXEC_START_CHOWN] = "ExecStartChown", | ||||
| 3273 | [SOCKET_EXEC_START_POST] = "ExecStartPost", | ||||
| 3274 | [SOCKET_EXEC_STOP_PRE] = "ExecStopPre", | ||||
| 3275 | [SOCKET_EXEC_STOP_POST] = "ExecStopPost" | ||||
| 3276 | }; | ||||
| 3277 | |||||
| 3278 | DEFINE_STRING_TABLE_LOOKUP(socket_exec_command, SocketExecCommand)const char *socket_exec_command_to_string(SocketExecCommand i ) { if (i < 0 || i >= (SocketExecCommand) __extension__ (__builtin_choose_expr( !__builtin_types_compatible_p(typeof (socket_exec_command_table), typeof(&*(socket_exec_command_table ))), sizeof(socket_exec_command_table)/sizeof((socket_exec_command_table )[0]), ((void)0)))) return ((void*)0); return socket_exec_command_table [i]; } SocketExecCommand socket_exec_command_from_string(const char *s) { return (SocketExecCommand) string_table_lookup(socket_exec_command_table , __extension__ (__builtin_choose_expr( !__builtin_types_compatible_p (typeof(socket_exec_command_table), typeof(&*(socket_exec_command_table ))), sizeof(socket_exec_command_table)/sizeof((socket_exec_command_table )[0]), ((void)0))), s); }; | ||||
| 3279 | |||||
| 3280 | static const char* const socket_result_table[_SOCKET_RESULT_MAX] = { | ||||
| 3281 | [SOCKET_SUCCESS] = "success", | ||||
| 3282 | [SOCKET_FAILURE_RESOURCES] = "resources", | ||||
| 3283 | [SOCKET_FAILURE_TIMEOUT] = "timeout", | ||||
| 3284 | [SOCKET_FAILURE_EXIT_CODE] = "exit-code", | ||||
| 3285 | [SOCKET_FAILURE_SIGNAL] = "signal", | ||||
| 3286 | [SOCKET_FAILURE_CORE_DUMP] = "core-dump", | ||||
| 3287 | [SOCKET_FAILURE_START_LIMIT_HIT] = "start-limit-hit", | ||||
| 3288 | [SOCKET_FAILURE_TRIGGER_LIMIT_HIT] = "trigger-limit-hit", | ||||
| 3289 | [SOCKET_FAILURE_SERVICE_START_LIMIT_HIT] = "service-start-limit-hit" | ||||
| 3290 | }; | ||||
| 3291 | |||||
| 3292 | DEFINE_STRING_TABLE_LOOKUP(socket_result, SocketResult)const char *socket_result_to_string(SocketResult i) { if (i < 0 || i >= (SocketResult) __extension__ (__builtin_choose_expr ( !__builtin_types_compatible_p(typeof(socket_result_table), typeof (&*(socket_result_table))), sizeof(socket_result_table)/sizeof ((socket_result_table)[0]), ((void)0)))) return ((void*)0); return socket_result_table[i]; } SocketResult socket_result_from_string (const char *s) { return (SocketResult) string_table_lookup(socket_result_table , __extension__ (__builtin_choose_expr( !__builtin_types_compatible_p (typeof(socket_result_table), typeof(&*(socket_result_table ))), sizeof(socket_result_table)/sizeof((socket_result_table) [0]), ((void)0))), s); }; | ||||
| 3293 | |||||
| 3294 | const UnitVTable socket_vtable = { | ||||
| 3295 | .object_size = sizeof(Socket), | ||||
| 3296 | .exec_context_offset = offsetof(Socket, exec_context)__builtin_offsetof(Socket, exec_context), | ||||
| 3297 | .cgroup_context_offset = offsetof(Socket, cgroup_context)__builtin_offsetof(Socket, cgroup_context), | ||||
| 3298 | .kill_context_offset = offsetof(Socket, kill_context)__builtin_offsetof(Socket, kill_context), | ||||
| 3299 | .exec_runtime_offset = offsetof(Socket, exec_runtime)__builtin_offsetof(Socket, exec_runtime), | ||||
| 3300 | .dynamic_creds_offset = offsetof(Socket, dynamic_creds)__builtin_offsetof(Socket, dynamic_creds), | ||||
| 3301 | |||||
| 3302 | .sections = | ||||
| 3303 | "Unit\0" | ||||
| 3304 | "Socket\0" | ||||
| 3305 | "Install\0", | ||||
| 3306 | .private_section = "Socket", | ||||
| 3307 | |||||
| 3308 | .can_transient = true1, | ||||
| 3309 | |||||
| 3310 | .init = socket_init, | ||||
| 3311 | .done = socket_done, | ||||
| 3312 | .load = socket_load, | ||||
| 3313 | |||||
| 3314 | .coldplug = socket_coldplug, | ||||
| 3315 | |||||
| 3316 | .dump = socket_dump, | ||||
| 3317 | |||||
| 3318 | .start = socket_start, | ||||
| 3319 | .stop = socket_stop, | ||||
| 3320 | |||||
| 3321 | .kill = socket_kill, | ||||
| 3322 | |||||
| 3323 | .get_timeout = socket_get_timeout, | ||||
| 3324 | |||||
| 3325 | .serialize = socket_serialize, | ||||
| 3326 | .deserialize_item = socket_deserialize_item, | ||||
| 3327 | .distribute_fds = socket_distribute_fds, | ||||
| 3328 | |||||
| 3329 | .active_state = socket_active_state, | ||||
| 3330 | .sub_state_to_string = socket_sub_state_to_string, | ||||
| 3331 | |||||
| 3332 | .may_gc = socket_may_gc, | ||||
| 3333 | |||||
| 3334 | .sigchld_event = socket_sigchld_event, | ||||
| 3335 | |||||
| 3336 | .trigger_notify = socket_trigger_notify, | ||||
| 3337 | |||||
| 3338 | .reset_failed = socket_reset_failed, | ||||
| 3339 | |||||
| 3340 | .control_pid = socket_control_pid, | ||||
| 3341 | |||||
| 3342 | .bus_vtable = bus_socket_vtable, | ||||
| 3343 | .bus_set_property = bus_socket_set_property, | ||||
| 3344 | .bus_commit_properties = bus_socket_commit_properties, | ||||
| 3345 | |||||
| 3346 | .status_message_formats = { | ||||
| 3347 | /*.starting_stopping = { | ||||
| 3348 | [0] = "Starting socket %s...", | ||||
| 3349 | [1] = "Stopping socket %s...", | ||||
| 3350 | },*/ | ||||
| 3351 | .finished_start_job = { | ||||
| 3352 | [JOB_DONE] = "Listening on %s.", | ||||
| 3353 | [JOB_FAILED] = "Failed to listen on %s.", | ||||
| 3354 | [JOB_TIMEOUT] = "Timed out starting %s.", | ||||
| 3355 | }, | ||||
| 3356 | .finished_stop_job = { | ||||
| 3357 | [JOB_DONE] = "Closed %s.", | ||||
| 3358 | [JOB_FAILED] = "Failed stopping %s.", | ||||
| 3359 | [JOB_TIMEOUT] = "Timed out stopping %s.", | ||||
| 3360 | }, | ||||
| 3361 | }, | ||||
| 3362 | }; |