File: | build-scan/../src/core/socket.c |
Warning: | line 611, column 24 Potential leak of memory pointed to by 'remote' |
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 < 0) { | |||
2316 | goto refuse; | |||
2317 | } else if (r > 0 && p->n_ref > s->max_connections_per_source) { | |||
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 | }; |