]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/libsystemd/sd-bus/test-bus-server.c
Add SPDX license identifiers to source files under the LGPL
[thirdparty/systemd.git] / src / libsystemd / sd-bus / test-bus-server.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2 /***
3 This file is part of systemd.
4
5 Copyright 2013 Lennart Poettering
6
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
11
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
19 ***/
20
21 #include <pthread.h>
22 #include <stdlib.h>
23
24 #include "sd-bus.h"
25
26 #include "bus-internal.h"
27 #include "bus-util.h"
28 #include "log.h"
29 #include "macro.h"
30 #include "util.h"
31
32 struct context {
33 int fds[2];
34
35 bool client_negotiate_unix_fds;
36 bool server_negotiate_unix_fds;
37
38 bool client_anonymous_auth;
39 bool server_anonymous_auth;
40 };
41
42 static void *server(void *p) {
43 struct context *c = p;
44 sd_bus *bus = NULL;
45 sd_id128_t id;
46 bool quit = false;
47 int r;
48
49 assert_se(sd_id128_randomize(&id) >= 0);
50
51 assert_se(sd_bus_new(&bus) >= 0);
52 assert_se(sd_bus_set_fd(bus, c->fds[0], c->fds[0]) >= 0);
53 assert_se(sd_bus_set_server(bus, 1, id) >= 0);
54 assert_se(sd_bus_set_anonymous(bus, c->server_anonymous_auth) >= 0);
55 assert_se(sd_bus_negotiate_fds(bus, c->server_negotiate_unix_fds) >= 0);
56 assert_se(sd_bus_start(bus) >= 0);
57
58 while (!quit) {
59 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL;
60
61 r = sd_bus_process(bus, &m);
62 if (r < 0) {
63 log_error_errno(r, "Failed to process requests: %m");
64 goto fail;
65 }
66
67 if (r == 0) {
68 r = sd_bus_wait(bus, (uint64_t) -1);
69 if (r < 0) {
70 log_error_errno(r, "Failed to wait: %m");
71 goto fail;
72 }
73
74 continue;
75 }
76
77 if (!m)
78 continue;
79
80 log_info("Got message! member=%s", strna(sd_bus_message_get_member(m)));
81
82 if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "Exit")) {
83
84 assert_se((sd_bus_can_send(bus, 'h') >= 1) == (c->server_negotiate_unix_fds && c->client_negotiate_unix_fds));
85
86 r = sd_bus_message_new_method_return(m, &reply);
87 if (r < 0) {
88 log_error_errno(r, "Failed to allocate return: %m");
89 goto fail;
90 }
91
92 quit = true;
93
94 } else if (sd_bus_message_is_method_call(m, NULL, NULL)) {
95 r = sd_bus_message_new_method_error(
96 m,
97 &reply,
98 &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_UNKNOWN_METHOD, "Unknown method."));
99 if (r < 0) {
100 log_error_errno(r, "Failed to allocate return: %m");
101 goto fail;
102 }
103 }
104
105 if (reply) {
106 r = sd_bus_send(bus, reply, NULL);
107 if (r < 0) {
108 log_error_errno(r, "Failed to send reply: %m");
109 goto fail;
110 }
111 }
112 }
113
114 r = 0;
115
116 fail:
117 if (bus) {
118 sd_bus_flush(bus);
119 sd_bus_unref(bus);
120 }
121
122 return INT_TO_PTR(r);
123 }
124
125 static int client(struct context *c) {
126 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL;
127 _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL;
128 sd_bus_error error = SD_BUS_ERROR_NULL;
129 int r;
130
131 assert_se(sd_bus_new(&bus) >= 0);
132 assert_se(sd_bus_set_fd(bus, c->fds[1], c->fds[1]) >= 0);
133 assert_se(sd_bus_negotiate_fds(bus, c->client_negotiate_unix_fds) >= 0);
134 assert_se(sd_bus_set_anonymous(bus, c->client_anonymous_auth) >= 0);
135 assert_se(sd_bus_start(bus) >= 0);
136
137 r = sd_bus_message_new_method_call(
138 bus,
139 &m,
140 "org.freedesktop.systemd.test",
141 "/",
142 "org.freedesktop.systemd.test",
143 "Exit");
144 if (r < 0)
145 return log_error_errno(r, "Failed to allocate method call: %m");
146
147 r = sd_bus_call(bus, m, 0, &error, &reply);
148 if (r < 0) {
149 log_error("Failed to issue method call: %s", bus_error_message(&error, -r));
150 return r;
151 }
152
153 return 0;
154 }
155
156 static int test_one(bool client_negotiate_unix_fds, bool server_negotiate_unix_fds,
157 bool client_anonymous_auth, bool server_anonymous_auth) {
158
159 struct context c;
160 pthread_t s;
161 void *p;
162 int r, q;
163
164 zero(c);
165
166 assert_se(socketpair(AF_UNIX, SOCK_STREAM, 0, c.fds) >= 0);
167
168 c.client_negotiate_unix_fds = client_negotiate_unix_fds;
169 c.server_negotiate_unix_fds = server_negotiate_unix_fds;
170 c.client_anonymous_auth = client_anonymous_auth;
171 c.server_anonymous_auth = server_anonymous_auth;
172
173 r = pthread_create(&s, NULL, server, &c);
174 if (r != 0)
175 return -r;
176
177 r = client(&c);
178
179 q = pthread_join(s, &p);
180 if (q != 0)
181 return -q;
182
183 if (r < 0)
184 return r;
185
186 if (PTR_TO_INT(p) < 0)
187 return PTR_TO_INT(p);
188
189 return 0;
190 }
191
192 int main(int argc, char *argv[]) {
193 int r;
194
195 r = test_one(true, true, false, false);
196 assert_se(r >= 0);
197
198 r = test_one(true, false, false, false);
199 assert_se(r >= 0);
200
201 r = test_one(false, true, false, false);
202 assert_se(r >= 0);
203
204 r = test_one(false, false, false, false);
205 assert_se(r >= 0);
206
207 r = test_one(true, true, true, true);
208 assert_se(r >= 0);
209
210 r = test_one(true, true, false, true);
211 assert_se(r >= 0);
212
213 r = test_one(true, true, true, false);
214 assert_se(r == -EPERM);
215
216 return EXIT_SUCCESS;
217 }