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 | }; |