/src/systemd/src/shared/varlink-serialize.c
Line | Count | Source |
1 | | /* SPDX-License-Identifier: LGPL-2.1-or-later */ |
2 | | |
3 | | #include "alloc-util.h" |
4 | | #include "extract-word.h" |
5 | | #include "fd-util.h" |
6 | | #include "fdset.h" |
7 | | #include "log.h" |
8 | | #include "serialize.h" |
9 | | #include "socket-util.h" |
10 | | #include "string-util.h" |
11 | | #include "varlink-internal.h" |
12 | | #include "varlink-serialize.h" |
13 | | |
14 | 76.3k | int varlink_server_serialize(sd_varlink_server *s, const char *name, FILE *f, FDSet *fds) { |
15 | 76.3k | assert(f); |
16 | 76.3k | assert(fds); |
17 | | |
18 | 76.3k | if (!s) |
19 | 76.0k | return 0; |
20 | | |
21 | 292 | const char *prefix = name ? strjoina("varlink-server-", name) : "varlink-server"; |
22 | | |
23 | 292 | LIST_FOREACH(sockets, ss, s->sockets) { |
24 | 0 | assert(ss->address); |
25 | 0 | assert(ss->fd >= 0); |
26 | | |
27 | | /* If we fail to serialize the fd, it will be considered an error during deserialization */ |
28 | 0 | int copy = fdset_put_dup(fds, ss->fd); |
29 | 0 | if (copy < 0) |
30 | 0 | return copy; |
31 | | |
32 | 0 | fprintf(f, "%s-socket-address=%s varlink-server-socket-fd=%d\n", prefix, ss->address, copy); |
33 | 0 | } |
34 | | |
35 | 292 | return 0; |
36 | 292 | } |
37 | | |
38 | 2.47k | int varlink_server_deserialize_one(sd_varlink_server *s, const char *value, FDSet *fds) { |
39 | 2.47k | _cleanup_free_ char *address = NULL; |
40 | 2.47k | _cleanup_close_ int fd = -EBADF; |
41 | 2.47k | const char *v; |
42 | 2.47k | int r; |
43 | | |
44 | | /* This function expects a serialization line with "varlink-server(-name)-" prefix stripped! */ |
45 | | |
46 | 2.47k | assert(s); |
47 | 2.47k | assert(value); |
48 | 2.47k | assert(fds); |
49 | | |
50 | 2.47k | v = startswith(value, "socket-address="); |
51 | 2.47k | if (!v) |
52 | 2.47k | return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), |
53 | 1.70k | "Invalid varlink server serialization entry: %s", value); |
54 | | |
55 | 1.70k | r = extract_first_word(&v, &address, " ", /* flags = */ 0); |
56 | 1.70k | if (r <= 0) |
57 | 1.70k | return varlink_server_log_errno(s, r < 0 ? r : SYNTHETIC_ERRNO(ENODATA), |
58 | 1.12k | "Failed to extract socket address from varlink serialization: %s", value); |
59 | 1.12k | if (v) |
60 | 599 | v = startswith(v, "varlink-server-socket-fd="); |
61 | 1.12k | if (!v) |
62 | 1.12k | return varlink_server_log_errno(s, SYNTHETIC_ERRNO(EBADF), |
63 | 391 | "Got varlink serialization without socket fd, refusing."); |
64 | | |
65 | 391 | fd = deserialize_fd(fds, v); |
66 | 391 | if (fd < 0) |
67 | 391 | return varlink_server_log_errno(s, fd, "Failed to deserialize varlink socket fd: %m"); |
68 | | |
69 | | /* NB: varlink_server_socket_free() does not close the fd! */ |
70 | 0 | _cleanup_(varlink_server_socket_freep) VarlinkServerSocket *ss = NULL; |
71 | 0 | ss = new(VarlinkServerSocket, 1); |
72 | 0 | if (!ss) |
73 | 0 | return log_oom_debug(); |
74 | | |
75 | 0 | *ss = (VarlinkServerSocket) { |
76 | 0 | .server = s, |
77 | 0 | .address = TAKE_PTR(address), |
78 | 0 | .fd = fd, |
79 | 0 | }; |
80 | |
|
81 | 0 | r = varlink_server_add_socket_event_source(s, ss); |
82 | 0 | if (r < 0) |
83 | 0 | return varlink_server_log_errno(s, r, "Failed to add VarlinkServerSocket event source to the event loop: %m"); |
84 | | |
85 | 0 | LIST_PREPEND(sockets, s->sockets, TAKE_PTR(ss)); |
86 | 0 | TAKE_FD(fd); /* ownership is now transferred to varlink server */ |
87 | |
|
88 | 0 | return 0; |
89 | 0 | } |
90 | | |
91 | 0 | bool varlink_server_contains_socket(sd_varlink_server *s, const char *address) { |
92 | 0 | int r; |
93 | |
|
94 | 0 | assert(s); |
95 | 0 | assert(address); |
96 | |
|
97 | 0 | LIST_FOREACH(sockets, ss, s->sockets) { |
98 | 0 | r = socket_address_equal_unix(ss->address, address); |
99 | 0 | if (r < 0) |
100 | 0 | log_debug_errno(r, "Failed to compare '%s' and '%s', ignoring: %m", ss->address, address); |
101 | 0 | if (r > 0) |
102 | 0 | return true; |
103 | 0 | } |
104 | | |
105 | 0 | return false; |
106 | 0 | } |