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