]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/bus-proxyd/bus-proxyd.c
remove ReadOnlySystem and ProtectedHome from udevd and logind
[thirdparty/systemd.git] / src / bus-proxyd / bus-proxyd.c
CommitLineData
a8f11321
LP
1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3/***
4 This file is part of systemd.
5
6 Copyright 2010 Lennart Poettering
dc780ecf
KS
7 Copyright 2013 Daniel Mack
8 Copyright 2014 Kay Sievers
a8f11321
LP
9
10 systemd is free software; you can redistribute it and/or modify it
5430f7f2
LP
11 under the terms of the GNU Lesser General Public License as published by
12 the Free Software Foundation; either version 2.1 of the License, or
a8f11321
LP
13 (at your option) any later version.
14
15 systemd is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
5430f7f2 18 Lesser General Public License for more details.
a8f11321 19
5430f7f2 20 You should have received a copy of the GNU Lesser General Public License
a8f11321
LP
21 along with systemd; If not, see <http://www.gnu.org/licenses/>.
22***/
23
24#include <sys/socket.h>
25#include <sys/un.h>
26#include <sys/types.h>
27#include <fcntl.h>
28#include <unistd.h>
29#include <string.h>
30#include <errno.h>
d51539b1 31#include <sys/poll.h>
a8f11321 32#include <stddef.h>
71008e18 33#include <getopt.h>
a8f11321
LP
34
35#include "log.h"
36#include "util.h"
37#include "socket-util.h"
d51539b1
LP
38#include "sd-daemon.h"
39#include "sd-bus.h"
40#include "bus-internal.h"
41#include "bus-message.h"
40ca29a1 42#include "bus-util.h"
19befb2d 43#include "bus-internal.h"
71008e18 44#include "build.h"
0721804f 45#include "strv.h"
ab9001a1 46#include "def.h"
71008e18 47
ab9001a1 48static const char *arg_address = DEFAULT_SYSTEM_BUS_PATH;
0721804f
LP
49static char *arg_command_line_buffer = NULL;
50
71008e18
DM
51static int help(void) {
52
53 printf("%s [OPTIONS...]\n\n"
ba768916 54 "Connect STDIO or a socket to a given bus address.\n\n"
71008e18
DM
55 " -h --help Show this help\n"
56 " --version Show package version\n"
cc4e8b6f 57 " --address=ADDRESS Connect to the bus specified by ADDRESS\n"
ab9001a1 58 " (default: " DEFAULT_SYSTEM_BUS_PATH ")\n",
ba768916 59 program_invocation_short_name);
71008e18
DM
60
61 return 0;
62}
63
64static int parse_argv(int argc, char *argv[]) {
65
66 enum {
67 ARG_VERSION = 0x100,
ba768916 68 ARG_ADDRESS,
71008e18
DM
69 };
70
71 static const struct option options[] = {
ba768916
LP
72 { "help", no_argument, NULL, 'h' },
73 { "version", no_argument, NULL, ARG_VERSION },
74 { "address", required_argument, NULL, ARG_ADDRESS },
75 { NULL, 0, NULL, 0 }
71008e18
DM
76 };
77
78 int c;
79
80 assert(argc >= 0);
81 assert(argv);
82
2dc38ed0 83 while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) {
71008e18
DM
84
85 switch (c) {
86
87 case 'h':
88 help();
89 return 0;
90
91 case ARG_VERSION:
92 puts(PACKAGE_STRING);
93 puts(SYSTEMD_FEATURES);
94 return 0;
95
ba768916
LP
96 case ARG_ADDRESS:
97 arg_address = optarg;
98 break;
99
71008e18
DM
100 case '?':
101 return -EINVAL;
102
71008e18 103 default:
ba768916 104 assert_not_reached("Unhandled option");
71008e18
DM
105 }
106 }
107
0721804f
LP
108 /* If the first command line argument is only "x" characters
109 * we'll write who we are talking to into it, so that "ps" is
110 * explanatory */
111 arg_command_line_buffer = argv[optind];
112 if (argc > optind + 1 ||
113 (arg_command_line_buffer && arg_command_line_buffer[strspn(arg_command_line_buffer, "x")] != 0)) {
114 log_error("Too many arguments");
115 return -EINVAL;
116 }
117
71008e18
DM
118 return 1;
119}
a8f11321 120
758bf0c7 121static int rename_service(sd_bus *a, sd_bus *b) {
a7639e37
LP
122 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
123 _cleanup_free_ char *p = NULL, *name = NULL;
124 const char *comm;
125 char **cmdline;
126 uid_t uid;
127 pid_t pid;
128 int r;
129
758bf0c7 130 assert(a);
a7639e37
LP
131 assert(b);
132
133 r = sd_bus_get_peer_creds(b, SD_BUS_CREDS_UID|SD_BUS_CREDS_PID|SD_BUS_CREDS_CMDLINE|SD_BUS_CREDS_COMM, &creds);
134 if (r < 0)
135 return r;
136
137 r = sd_bus_creds_get_uid(creds, &uid);
138 if (r < 0)
139 return r;
140
141 r = sd_bus_creds_get_pid(creds, &pid);
142 if (r < 0)
143 return r;
144
145 r = sd_bus_creds_get_cmdline(creds, &cmdline);
146 if (r < 0)
147 return r;
148
149 r = sd_bus_creds_get_comm(creds, &comm);
150 if (r < 0)
151 return r;
152
153 name = uid_to_name(uid);
154 if (!name)
155 return -ENOMEM;
156
157 p = strv_join(cmdline, " ");
158 if (!p)
159 return -ENOMEM;
160
161 /* The status string gets the full command line ... */
162 sd_notifyf(false,
ccd06097
ZJS
163 "STATUS=Processing requests from client PID "PID_FMT" (%s); UID "UID_FMT" (%s)",
164 pid, p,
165 uid, name);
a7639e37
LP
166
167 /* ... and the argv line only the short comm */
168 if (arg_command_line_buffer) {
169 size_t m, w;
170
171 m = strlen(arg_command_line_buffer);
172 w = snprintf(arg_command_line_buffer, m,
ccd06097
ZJS
173 "[PID "PID_FMT"/%s; UID "UID_FMT"/%s]",
174 pid, comm,
175 uid, name);
a7639e37
LP
176
177 if (m > w)
29804cc1 178 memzero(arg_command_line_buffer + w, m - w);
a7639e37
LP
179 }
180
ccd06097
ZJS
181 log_debug("Running on behalf of PID "PID_FMT" (%s), UID "UID_FMT" (%s), %s",
182 pid, p,
183 uid, name,
758bf0c7
LP
184 a->unique_name);
185 ;
a7639e37
LP
186 return 0;
187}
188
189static int synthesize_name_acquired(sd_bus *a, sd_bus *b, sd_bus_message *m) {
190 _cleanup_bus_message_unref_ sd_bus_message *n = NULL;
191 const char *name, *old_owner, *new_owner;
192 int r;
193
194 assert(a);
195 assert(b);
196 assert(m);
197
198 /* If we get NameOwnerChanged for our own name, we need to
199 * synthesize NameLost/NameAcquired, since socket clients need
200 * that, even though it is obsoleted on kdbus */
201
202 if (!a->is_kernel)
203 return 0;
204
205 if (!sd_bus_message_is_signal(m, "org.freedesktop.DBus", "NameOwnerChanged") ||
206 !streq_ptr(m->path, "/org/freedesktop/DBus") ||
207 !streq_ptr(m->sender, "org.freedesktop.DBus"))
208 return 0;
209
210 r = sd_bus_message_read(m, "sss", &name, &old_owner, &new_owner);
211 if (r < 0)
212 return r;
213
214 r = sd_bus_message_rewind(m, true);
215 if (r < 0)
216 return r;
217
218 if (streq(old_owner, a->unique_name)) {
219
220 r = sd_bus_message_new_signal(
221 b,
151b9b96 222 &n,
a7639e37
LP
223 "/org/freedesktop/DBus",
224 "org.freedesktop.DBus",
151b9b96 225 "NameLost");
a7639e37
LP
226
227 } else if (streq(new_owner, a->unique_name)) {
228
229 r = sd_bus_message_new_signal(
230 b,
151b9b96 231 &n,
a7639e37
LP
232 "/org/freedesktop/DBus",
233 "org.freedesktop.DBus",
151b9b96 234 "NameAcquired");
a7639e37
LP
235 } else
236 return 0;
237
238 if (r < 0)
239 return r;
240
241 r = sd_bus_message_append(n, "s", name);
242 if (r < 0)
243 return r;
244
245 r = bus_message_append_sender(n, "org.freedesktop.DBus");
246 if (r < 0)
247 return r;
248
249 r = bus_seal_synthetic_message(b, n);
250 if (r < 0)
251 return r;
252
253 return sd_bus_send(b, n, NULL);
254}
255
c2595875
LP
256static int process_policy(sd_bus *a, sd_bus *b, sd_bus_message *m) {
257 _cleanup_bus_message_unref_ sd_bus_message *n = NULL;
258 int r;
259
260 assert(a);
261 assert(b);
262 assert(m);
263
264 if (!sd_bus_message_is_method_call(m, "org.freedesktop.DBus.Properties", "GetAll"))
265 return 0;
266
267 if (!streq_ptr(m->path, "/org/gnome/DisplayManager/Slave"))
268 return 0;
269
270 r = sd_bus_message_new_method_errorf(m, &n, SD_BUS_ERROR_ACCESS_DENIED, "gdm, you are stupid");
271 if (r < 0)
272 return r;
273
274 r = bus_message_append_sender(n, "org.freedesktop.DBus");
275 if (r < 0) {
276 log_error("Failed to append sender to gdm reply: %s", strerror(-r));
277 return r;
278 }
279
280 r = bus_seal_synthetic_message(b, n);
281 if (r < 0) {
282 log_error("Failed to seal gdm reply: %s", strerror(-r));
283 return r;
284 }
285
286 r = sd_bus_send(b, n, NULL);
287 if (r < 0) {
288 log_error("Failed to send gdm reply: %s", strerror(-r));
289 return r;
290 }
291
292 return 1;
293}
294
2f1a3d08
LP
295static int synthetic_driver_send(sd_bus *b, sd_bus_message *m) {
296 int r;
297
298 assert(b);
299 assert(m);
300
301 r = bus_message_append_sender(m, "org.freedesktop.DBus");
302 if (r < 0)
303 return r;
304
305 r = bus_seal_synthetic_message(b, m);
306 if (r < 0)
307 return r;
308
309 return sd_bus_send(b, m, NULL);
310}
311
312static int synthetic_reply_method_error(sd_bus_message *call, const sd_bus_error *e) {
313 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
314 int r;
315
316 if (call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED)
317 return 0;
318
319 r = sd_bus_message_new_method_error(call, &m, e);
320 if (r < 0)
321 return r;
322
323 return synthetic_driver_send(call->bus, m);
324}
325
326static int synthetic_reply_method_errno(sd_bus_message *call, int error, const sd_bus_error *p) {
327
328 _cleanup_bus_error_free_ sd_bus_error berror = SD_BUS_ERROR_NULL;
329
330 if (call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED)
331 return 0;
332
333 if (sd_bus_error_is_set(p))
334 return synthetic_reply_method_error(call, p);
335
336 sd_bus_error_set_errno(&berror, error);
337
338 return synthetic_reply_method_error(call, &berror);
339}
340
341static int synthetic_reply_method_return(sd_bus_message *call, const char *types, ...) {
2f1a3d08
LP
342 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
343 int r;
344
345 if (call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED)
346 return 0;
347
348 r = sd_bus_message_new_method_return(call, &m);
349 if (r < 0)
350 return r;
351
352 if (!isempty(types)) {
353 va_list ap;
354
355 va_start(ap, types);
356 r = bus_message_append_ap(m, types, ap);
357 va_end(ap);
358 if (r < 0)
359 return r;
360 }
361
362 return synthetic_driver_send(call->bus, m);
363}
364
dc780ecf
KS
365static int synthetic_reply_return_strv(sd_bus_message *call, char **l) {
366 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
367 int r;
368
369 r = sd_bus_message_new_method_return(call, &m);
370 if (r < 0)
371 return synthetic_reply_method_errno(call, r, NULL);
372
373 r = sd_bus_message_append_strv(m, l);
374 if (r < 0)
375 return synthetic_reply_method_errno(call, r, NULL);
376
377 return synthetic_driver_send(call->bus, m);
378}
379
380static int get_creds_by_name(sd_bus *bus, const char *name, uint64_t mask, sd_bus_creds **_creds, sd_bus_error *error) {
381 _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
382 int r;
383
384 assert(bus);
385 assert(name);
386 assert(_creds);
387
388 assert_return(service_name_is_valid(name), -EINVAL);
389
390 r = sd_bus_get_owner(bus, name, mask, &c);
391 if (r == -ESRCH || r == -ENXIO)
392 return sd_bus_error_setf(error, SD_BUS_ERROR_NAME_HAS_NO_OWNER, "Name %s is currently not owned by anyone.", name);
393 if (r < 0)
394 return r;
395
396 if ((c->mask & mask) != mask)
397 return -ENOTSUP;
398
399 *_creds = c;
400 c = NULL;
401
402 return 0;
403}
404
405static int get_creds_by_message(sd_bus *bus, sd_bus_message *m, uint64_t mask, sd_bus_creds **_creds, sd_bus_error *error) {
406 const char *name;
407 int r;
408
409 assert(bus);
410 assert(m);
411 assert(_creds);
412
413 r = sd_bus_message_read(m, "s", &name);
414 if (r < 0)
415 return r;
416
417 return get_creds_by_name(bus, name, mask, _creds, error);
418}
419
420static int peer_is_privileged(sd_bus *bus, sd_bus_message *m) {
421 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
422 uid_t uid;
423 int r;
424
425 r = get_creds_by_message(bus, m, SD_BUS_CREDS_UID, &creds, NULL);
426 if (r < 0)
427 return r;
428
429 r = sd_bus_creds_get_uid(creds, &uid);
430 if (r < 0)
431 return r;
432
433 r = sd_bus_creds_has_effective_cap(creds, CAP_SYS_ADMIN);
434 if (r > 0)
435 return true;
436
437 if (uid == getuid())
438 return true;
439
440 return false;
441}
442
443
2a0abe5b
LP
444static int process_driver(sd_bus *a, sd_bus *b, sd_bus_message *m) {
445 int r;
446
447 assert(a);
448 assert(b);
449 assert(m);
450
451 if (!streq_ptr(sd_bus_message_get_destination(m), "org.freedesktop.DBus"))
452 return 0;
453
dc780ecf
KS
454 if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus.Introspectable", "Introspect")) {
455 if (0 && !isempty(sd_bus_message_get_signature(m, true))) {
456 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
457
458 r = sd_bus_error_setf(&error, SD_BUS_ERROR_INVALID_ARGS, "Expected no parameters");
459
460 return synthetic_reply_method_errno(m, r, &error);
461 }
462
463 return synthetic_reply_method_return(m, "s",
464 "<!DOCTYPE node PUBLIC \"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN\" "
465 "\"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd\">\n"
466 "<node>\n"
467 " <interface name=\"org.freedesktop.DBus.Introspectable\">\n"
468 " <method name=\"Introspect\">\n"
469 " <arg name=\"data\" type=\"s\" direction=\"out\"/>\n"
470 " </method>\n"
471 " </interface>\n"
472 " <interface name=\"org.freedesktop.DBus\">\n"
473 " <method name=\"AddMatch\">\n"
474 " <arg type=\"s\" direction=\"in\"/>\n"
475 " </method>\n"
476 " <method name=\"RemoveMatch\">\n"
477 " <arg type=\"s\" direction=\"in\"/>\n"
478 " </method>\n"
479 " <method name=\"GetConnectionSELinuxSecurityContext\">\n"
480 " <arg type=\"s\" direction=\"in\"/>\n"
481 " <arg type=\"ay\" direction=\"out\"/>\n"
482 " </method>\n"
483 " <method name=\"GetConnectionUnixProcessID\">\n"
484 " <arg type=\"s\" direction=\"in\"/>\n"
485 " <arg type=\"u\" direction=\"out\"/>\n"
486 " </method>\n"
487 " <method name=\"GetConnectionUnixUser\">\n"
488 " <arg type=\"s\" direction=\"in\"/>\n"
489 " <arg type=\"u\" direction=\"out\"/>\n"
490 " </method>\n"
491 " <method name=\"GetId\">\n"
492 " <arg type=\"s\" direction=\"out\"/>\n"
493 " </method>\n"
494 " <method name=\"GetNameOwner\">\n"
495 " <arg type=\"s\" direction=\"in\"/>\n"
496 " <arg type=\"s\" direction=\"out\"/>\n"
497 " </method>\n"
498 " <method name=\"Hello\">\n"
499 " <arg type=\"s\" direction=\"out\"/>\n"
500 " </method>\n"
501 " <method name=\"ListActivatableNames\">\n"
502 " <arg type=\"as\" direction=\"out\"/>\n"
503 " </method>\n"
504 " <method name=\"ListNames\">\n"
505 " <arg type=\"as\" direction=\"out\"/>\n"
506 " </method>\n"
507 " <method name=\"ListQueuedOwners\">\n"
508 " <arg type=\"s\" direction=\"in\"/>\n"
509 " <arg type=\"as\" direction=\"out\"/>\n"
510 " </method>\n"
511 " <method name=\"NameHasOwner\">\n"
512 " <arg type=\"s\" direction=\"in\"/>\n"
513 " <arg type=\"b\" direction=\"out\"/>\n"
514 " </method>\n"
515 " <method name=\"ReleaseName\">\n"
516 " <arg type=\"s\" direction=\"in\"/>\n"
517 " <arg type=\"u\" direction=\"out\"/>\n"
518 " </method>\n"
519 " <method name=\"ReloadConfig\">\n"
520 " </method>\n"
521 " <method name=\"RequestName\">\n"
522 " <arg type=\"s\" direction=\"in\"/>\n"
523 " <arg type=\"u\" direction=\"in\"/>\n"
524 " <arg type=\"u\" direction=\"out\"/>\n"
525 " </method>\n"
526 " <method name=\"StartServiceByName\">\n"
527 " <arg type=\"s\" direction=\"in\"/>\n"
528 " <arg type=\"u\" direction=\"in\"/>\n"
529 " <arg type=\"u\" direction=\"out\"/>\n"
530 " </method>\n"
531 " <method name=\"UpdateActivationEnvironment\">\n"
532 " <arg type=\"a{ss}\" direction=\"in\"/>\n"
533 " </method>\n"
534 " <signal name=\"NameAcquired\">\n"
535 " <arg type=\"s\"/>\n"
536 " </signal>\n"
537 " <signal name=\"NameLost\">\n"
538 " <arg type=\"s\"/>\n"
539 " </signal>\n"
540 " <signal name=\"NameOwnerChanged\">\n"
541 " <arg type=\"s\"/>\n"
542 " <arg type=\"s\"/>\n"
543 " <arg type=\"s\"/>\n"
544 " </signal>\n"
545 " </interface>\n"
546 "</node>\n");
547
548 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "AddMatch")) {
2a0abe5b
LP
549 const char *match;
550
551 r = sd_bus_message_read(m, "s", &match);
552 if (r < 0)
2f1a3d08 553 return synthetic_reply_method_errno(m, r, NULL);
2a0abe5b 554
19befb2d 555 r = sd_bus_add_match(a, NULL, match, NULL, NULL);
2a0abe5b 556 if (r < 0)
2f1a3d08 557 return synthetic_reply_method_errno(m, r, NULL);
2a0abe5b 558
2f1a3d08 559 return synthetic_reply_method_return(m, NULL);
2a0abe5b
LP
560
561 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "RemoveMatch")) {
562 const char *match;
563
564 r = sd_bus_message_read(m, "s", &match);
565 if (r < 0)
2f1a3d08 566 return synthetic_reply_method_errno(m, r, NULL);
2a0abe5b 567
19befb2d
LP
568 r = bus_remove_match_by_string(a, match, NULL, NULL);
569 if (r == 0)
570 return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_MATCH_RULE_NOT_FOUND, "Match rule not found"));
2a0abe5b 571 if (r < 0)
2f1a3d08 572 return synthetic_reply_method_errno(m, r, NULL);
2a0abe5b 573
2f1a3d08 574 return synthetic_reply_method_return(m, NULL);
2a0abe5b 575
dc780ecf
KS
576 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetConnectionSELinuxSecurityContext")) {
577 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
578
579 r = get_creds_by_message(a, m, SD_BUS_CREDS_SELINUX_CONTEXT, &creds, NULL);
580 if (r < 0)
581 return synthetic_reply_method_errno(m, r, NULL);
582
583 return synthetic_reply_method_return(m, "y", creds->label, strlen(creds->label));
584
585 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetConnectionUnixProcessID")) {
586 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
587
588 r = get_creds_by_message(a, m, SD_BUS_CREDS_PID, &creds, NULL);
589 if (r < 0)
590 return synthetic_reply_method_errno(m, r, NULL);
591
592 return synthetic_reply_method_return(m, "u", (uint32_t) creds->pid);
593
594 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetConnectionUnixUser")) {
595 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
596
597 r = get_creds_by_message(a, m, SD_BUS_CREDS_UID, &creds, NULL);
598 if (r < 0)
599 return synthetic_reply_method_errno(m, r, NULL);
600
601 return synthetic_reply_method_return(m, "u", (uint32_t) creds->uid);
602
603 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetId")) {
604 sd_id128_t server_id;
605 char buf[SD_ID128_STRING_MAX];
606
607 r = sd_bus_get_server_id(a, &server_id);
608 if (r < 0)
609 return synthetic_reply_method_errno(m, r, NULL);
610
611 return synthetic_reply_method_return(m, "s", sd_id128_to_string(server_id, buf));
612
613 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetNameOwner")) {
614 const char *name;
615 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
616 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
617
618 r = sd_bus_message_read(m, "s", &name);
619 if (r < 0)
620 return synthetic_reply_method_errno(m, r, NULL);
621
622 if (streq(name, "org.freedesktop.DBus"))
623 return synthetic_reply_method_return(m, "s", "org.freedesktop.DBus");
624
625 r = get_creds_by_name(a, name, SD_BUS_CREDS_UNIQUE_NAME, &creds, &error);
626 if (r < 0)
627 return synthetic_reply_method_errno(m, r, &error);
628
629 return synthetic_reply_method_return(m, "s", creds->unique_name);
630
631 /* "Hello" is handled in process_hello() */
632
633 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ListActivatableNames")) {
634 _cleanup_strv_free_ char **names = NULL;
635
636 r = sd_bus_list_names(a, NULL, &names);
637 if (r < 0)
638 return synthetic_reply_method_errno(m, r, NULL);
639
640 /* Let's sort the names list to make it stable */
641 strv_sort(names);
642
643 return synthetic_reply_return_strv(m, names);
644
645 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ListNames")) {
646 _cleanup_strv_free_ char **names = NULL;
647
648 r = sd_bus_list_names(a, &names, NULL);
649 if (r < 0)
650 return synthetic_reply_method_errno(m, r, NULL);
651
652 r = strv_extend(&names, "org.freedesktop.DBus");
653 if (r < 0)
654 return synthetic_reply_method_errno(m, r, NULL);
655
656 /* Let's sort the names list to make it stable */
657 strv_sort(names);
658
659 return synthetic_reply_return_strv(m, names);
660
661 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ListQueuedOwners")) {
662 struct kdbus_cmd_name_list cmd = {};
663 struct kdbus_name_list *name_list;
664 struct kdbus_cmd_name *name;
665 _cleanup_strv_free_ char **owners = NULL;
666 char *arg0;
667 int err = 0;
668
669 r = sd_bus_message_read(m, "s", &arg0);
670 if (r < 0)
671 return synthetic_reply_method_errno(m, r, NULL);
672
673 if (service_name_is_valid(arg0) < 0)
674 return synthetic_reply_method_errno(m, -EINVAL, NULL);
675
676 cmd.flags = KDBUS_NAME_LIST_QUEUED;
677 r = ioctl(a->input_fd, KDBUS_CMD_NAME_LIST, &cmd);
678 if (r < 0)
679 return synthetic_reply_method_errno(m, -errno, NULL);
680
681 name_list = (struct kdbus_name_list *) ((uint8_t *) a->kdbus_buffer + cmd.offset);
682
683 KDBUS_ITEM_FOREACH(name, name_list, names) {
684 char *n;
685
686 if (name->size <= sizeof(*name))
687 continue;
688
689 if (!streq(name->name, arg0))
690 continue;
691
692 if (asprintf(&n, ":1.%llu", (unsigned long long) name->owner_id) < 0) {
693 err = -ENOMEM;
694 break;
695 }
696
697 r = strv_consume(&owners, n);
698 if (r < 0) {
699 err = r;
700 break;
701 }
702 }
703
704 r = ioctl(a->input_fd, KDBUS_CMD_FREE, &cmd.offset);
705 if (r < 0)
706 return synthetic_reply_method_errno(m, r, NULL);
707
708 if (err > 0)
709 return synthetic_reply_method_errno(m, err, NULL);
710
711 return synthetic_reply_return_strv(m, owners);
712
713 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "NameHasOwner")) {
714 const char *name;
715
716 r = sd_bus_message_read(m, "s", &name);
717 if (r < 0)
718 return synthetic_reply_method_errno(m, r, NULL);
719
720 if (service_name_is_valid(name) < 0)
721 return synthetic_reply_method_errno(m, -EINVAL, NULL);
722
723 if (streq(name, "org.freedesktop.DBus"))
724 return synthetic_reply_method_return(m, "b", true);
725
726 r = sd_bus_get_owner(a, name, 0, NULL);
727 if (r < 0 && r != -ESRCH && r != -ENXIO)
728 return synthetic_reply_method_errno(m, r, NULL);
729
730 return synthetic_reply_method_return(m, "b", r >= 0);
731
732 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ReleaseName")) {
733 const char *name;
734
735 r = sd_bus_message_read(m, "s", &name);
736 if (r < 0)
737 return synthetic_reply_method_errno(m, r, NULL);
738
739 if (service_name_is_valid(name) < 0)
740 return synthetic_reply_method_errno(m, -EINVAL, NULL);
741
742 r = sd_bus_release_name(a, name);
743 if (r < 0) {
744 if (r == -ESRCH)
19befb2d 745 return synthetic_reply_method_return(m, "u", BUS_NAME_NON_EXISTENT);
dc780ecf 746 if (r == -EADDRINUSE)
19befb2d
LP
747 return synthetic_reply_method_return(m, "u", BUS_NAME_NOT_OWNER);
748
dc780ecf
KS
749 return synthetic_reply_method_errno(m, r, NULL);
750 }
751
752 return synthetic_reply_method_return(m, "u", BUS_NAME_RELEASED);
753
754 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ReloadConfig")) {
755 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
756
757 r = sd_bus_error_setf(&error, SD_BUS_ERROR_NOT_SUPPORTED, "%s() is not supported", sd_bus_message_get_member(m));
758
759 return synthetic_reply_method_errno(m, r, &error);
760
761 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "RequestName")) {
762 const char *name;
763 uint32_t flags;
764
765 r = sd_bus_message_read(m, "su", &name, &flags);
766 if (r < 0)
767 return synthetic_reply_method_errno(m, r, NULL);
768
769 if (service_name_is_valid(name) < 0)
770 return synthetic_reply_method_errno(m, -EINVAL, NULL);
771 if ((flags & ~(BUS_NAME_ALLOW_REPLACEMENT|BUS_NAME_REPLACE_EXISTING|BUS_NAME_DO_NOT_QUEUE)) != 0)
772 return synthetic_reply_method_errno(m, -EINVAL, NULL);
773
774 r = sd_bus_request_name(a, name, flags);
775 if (r < 0) {
776 if (r == -EEXIST)
777 return synthetic_reply_method_return(m, "u", BUS_NAME_EXISTS);
778 if (r == -EALREADY)
779 return synthetic_reply_method_return(m, "u", BUS_NAME_ALREADY_OWNER);
780 return synthetic_reply_method_errno(m, r, NULL);
781 }
782
783 if (r == 0)
784 return synthetic_reply_method_return(m, "u", BUS_NAME_IN_QUEUE);
785
786 return synthetic_reply_method_return(m, "u", BUS_NAME_PRIMARY_OWNER);
787
788 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "StartServiceByName")) {
789 _cleanup_bus_message_unref_ sd_bus_message *msg = NULL;
790 const char *name;
791 uint32_t flags;
792
793 r = sd_bus_message_read(m, "su", &name, &flags);
794 if (r < 0)
795 return synthetic_reply_method_errno(m, r, NULL);
796
797 if (service_name_is_valid(name) < 0)
798 return synthetic_reply_method_errno(m, -EINVAL, NULL);
799 if (flags != 0)
800 return synthetic_reply_method_errno(m, -EINVAL, NULL);
801
802 r = sd_bus_get_owner(a, name, 0, NULL);
803 if (r >= 0 || streq(name, "org.freedesktop.DBus"))
804 return synthetic_reply_method_return(m, "u", BUS_START_REPLY_ALREADY_RUNNING);
805 if (r != -ESRCH)
806 return synthetic_reply_method_errno(m, r, NULL);
807
808 r = sd_bus_message_new_method_call(
809 a,
810 &msg,
811 name,
812 "/",
813 "org.freedesktop.DBus.Peer",
814 "Ping");
815 if (r < 0)
816 return synthetic_reply_method_errno(m, r, NULL);
817
818 r = sd_bus_send(a, msg, NULL);
819 if (r < 0)
820 return synthetic_reply_method_errno(m, r, NULL);
821
822 return synthetic_reply_method_return(m, "u", BUS_START_REPLY_SUCCESS);
823
824 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "UpdateActivationEnvironment")) {
825 _cleanup_bus_message_unref_ sd_bus_message *msg = NULL;
826 _cleanup_strv_free_ char **args = NULL;
827
828 if (!peer_is_privileged(a, m))
829 return synthetic_reply_method_errno(m, -EPERM, NULL);
830
831 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "{ss}");
832 if (r < 0)
833 return synthetic_reply_method_errno(m, r, NULL);
834
835 while ((r = sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY, "ss")) > 0) {
836 _cleanup_free_ char *s = NULL;
837 const char *key;
838 const char *value;
839
840 r = sd_bus_message_read(m, "ss", &key, &value);
841 if (r < 0)
842 return synthetic_reply_method_errno(m, r, NULL);
843
844 s = strjoin(key, "=", value, NULL);
845 if (!s)
846 return synthetic_reply_method_errno(m, -ENOMEM, NULL);
847
848 r = strv_extend(&args, s);
849 if (r < 0)
850 return synthetic_reply_method_errno(m, r, NULL);
851
852 r = sd_bus_message_exit_container(m);
853 if (r < 0)
854 return synthetic_reply_method_errno(m, r, NULL);
855 }
856
857 r = sd_bus_message_exit_container(m);
858 if (r < 0)
859 return synthetic_reply_method_errno(m, r, NULL);
860
861 if (!args)
862 return synthetic_reply_method_errno(m, -EINVAL, NULL);
863
864 r = sd_bus_message_new_method_call(
865 a,
866 &msg,
867 "org.freedesktop.systemd1",
868 "/org/freedesktop/systemd1",
869 "org.freedesktop.systemd1.Manager",
870 "SetEnvironment");
871 if (r < 0)
872 return synthetic_reply_method_errno(m, r, NULL);
873
874 r = sd_bus_message_append_strv(msg, args);
875 if (r < 0)
876 return synthetic_reply_method_errno(m, r, NULL);
877
878 r = sd_bus_call(a, msg, 0, NULL, NULL);
879 if (r < 0)
880 return synthetic_reply_method_errno(m, r, NULL);
881
882 return synthetic_reply_method_return(m, NULL);
883
884 } else {
885 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
886
887 r = sd_bus_error_setf(&error, SD_BUS_ERROR_UNKNOWN_METHOD, "Unknown method '%s'.", m->member);
888
889 return synthetic_reply_method_errno(m, r, &error);
890 }
2a0abe5b
LP
891}
892
a7639e37
LP
893static int process_hello(sd_bus *a, sd_bus *b, sd_bus_message *m, bool *got_hello) {
894 _cleanup_bus_message_unref_ sd_bus_message *n = NULL;
895 bool is_hello;
896 int r;
897
898 assert(a);
899 assert(b);
900 assert(m);
901 assert(got_hello);
902
903 /* As reaction to hello we need to respond with two messages:
904 * the callback reply and the NameAcquired for the unique
905 * name, since hello is otherwise obsolete on kdbus. */
906
907 is_hello =
908 sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "Hello") &&
909 streq_ptr(m->destination, "org.freedesktop.DBus");
910
911 if (!is_hello) {
912
913 if (*got_hello)
914 return 0;
915
916 log_error("First packet isn't hello (it's %s.%s), aborting.", m->interface, m->member);
917 return -EIO;
918 }
919
920 if (*got_hello) {
921 log_error("Got duplicate hello, aborting.");
922 return -EIO;
923 }
924
925 *got_hello = true;
926
927 if (!a->is_kernel)
928 return 0;
929
930 r = sd_bus_message_new_method_return(m, &n);
931 if (r < 0) {
932 log_error("Failed to generate HELLO reply: %s", strerror(-r));
933 return r;
934 }
935
936 r = sd_bus_message_append(n, "s", a->unique_name);
937 if (r < 0) {
938 log_error("Failed to append unique name to HELLO reply: %s", strerror(-r));
939 return r;
940 }
941
942 r = bus_message_append_sender(n, "org.freedesktop.DBus");
943 if (r < 0) {
944 log_error("Failed to append sender to HELLO reply: %s", strerror(-r));
945 return r;
946 }
947
948 r = bus_seal_synthetic_message(b, n);
949 if (r < 0) {
950 log_error("Failed to seal HELLO reply: %s", strerror(-r));
951 return r;
952 }
953
954 r = sd_bus_send(b, n, NULL);
955 if (r < 0) {
956 log_error("Failed to send HELLO reply: %s", strerror(-r));
957 return r;
958 }
959
960 n = sd_bus_message_unref(n);
961 r = sd_bus_message_new_signal(
962 b,
151b9b96 963 &n,
a7639e37
LP
964 "/org/freedesktop/DBus",
965 "org.freedesktop.DBus",
151b9b96 966 "NameAcquired");
a7639e37
LP
967 if (r < 0) {
968 log_error("Failed to allocate initial NameAcquired message: %s", strerror(-r));
969 return r;
970 }
971
972 r = sd_bus_message_append(n, "s", a->unique_name);
973 if (r < 0) {
974 log_error("Failed to append unique name to NameAcquired message: %s", strerror(-r));
975 return r;
976 }
977
978 r = bus_message_append_sender(n, "org.freedesktop.DBus");
979 if (r < 0) {
980 log_error("Failed to append sender to NameAcquired message: %s", strerror(-r));
981 return r;
982 }
983
984 r = bus_seal_synthetic_message(b, n);
985 if (r < 0) {
986 log_error("Failed to seal NameAcquired message: %s", strerror(-r));
987 return r;
988 }
989
990 r = sd_bus_send(b, n, NULL);
991 if (r < 0) {
992 log_error("Failed to send NameAcquired message: %s", strerror(-r));
993 return r;
994 }
995
996 return 1;
997}
998
7b217f41
LP
999static int patch_sender(sd_bus *a, sd_bus_message *m) {
1000 char **well_known = NULL;
1001 sd_bus_creds *c;
1002 int r;
1003
1004 assert(a);
1005 assert(m);
1006
1007 if (!a->is_kernel)
1008 return 0;
1009
1010 /* We will change the sender of messages from the bus driver
1011 * so that they originate from the bus driver. This is a
1012 * speciality originating from dbus1, where the bus driver did
1013 * not have a unique id, but only the well-known name. */
1014
1015 c = sd_bus_message_get_creds(m);
1016 if (!c)
1017 return 0;
1018
1019 r = sd_bus_creds_get_well_known_names(c, &well_known);
1020 if (r < 0)
1021 return r;
1022
1023 if (strv_contains(well_known, "org.freedesktop.DBus"))
1024 m->sender = "org.freedesktop.DBus";
1025
1026 return 0;
1027}
1028
a8f11321 1029int main(int argc, char *argv[]) {
0721804f 1030
d51539b1
LP
1031 _cleanup_bus_unref_ sd_bus *a = NULL, *b = NULL;
1032 sd_id128_t server_id;
71008e18 1033 int r, in_fd, out_fd;
a7639e37 1034 bool got_hello = false;
0721804f 1035 bool is_unix;
8a0e0ed9
LP
1036 struct ucred ucred = {};
1037 _cleanup_free_ char *peersec = NULL;
a8f11321 1038
4cfa2c99 1039 log_set_target(LOG_TARGET_JOURNAL_OR_KMSG);
a8f11321
LP
1040 log_parse_environment();
1041 log_open();
1042
71008e18
DM
1043 r = parse_argv(argc, argv);
1044 if (r <= 0)
1045 goto finish;
1046
1047 r = sd_listen_fds(0);
1048 if (r == 0) {
1049 in_fd = STDIN_FILENO;
1050 out_fd = STDOUT_FILENO;
1051 } else if (r == 1) {
1052 in_fd = SD_LISTEN_FDS_START;
1053 out_fd = SD_LISTEN_FDS_START;
1054 } else {
9f6445e3 1055 log_error("Illegal number of file descriptors passed");
71008e18
DM
1056 goto finish;
1057 }
1058
d51539b1 1059 is_unix =
71008e18
DM
1060 sd_is_socket(in_fd, AF_UNIX, 0, 0) > 0 &&
1061 sd_is_socket(out_fd, AF_UNIX, 0, 0) > 0;
d51539b1 1062
8a0e0ed9 1063 if (is_unix) {
eff05270 1064 getpeercred(in_fd, &ucred);
8a0e0ed9
LP
1065 getpeersec(in_fd, &peersec);
1066 }
1067
d51539b1
LP
1068 r = sd_bus_new(&a);
1069 if (r < 0) {
1070 log_error("Failed to allocate bus: %s", strerror(-r));
a8f11321
LP
1071 goto finish;
1072 }
1073
44b0ed05
LP
1074 r = sd_bus_set_name(a, "sd-proxy");
1075 if (r < 0) {
1076 log_error("Failed to set bus name: %s", strerror(-r));
1077 goto finish;
1078 }
1079
ba768916 1080 r = sd_bus_set_address(a, arg_address);
d51539b1
LP
1081 if (r < 0) {
1082 log_error("Failed to set address to connect to: %s", strerror(-r));
1083 goto finish;
1084 }
a8f11321 1085
264ad849 1086 r = sd_bus_negotiate_fds(a, is_unix);
d51539b1
LP
1087 if (r < 0) {
1088 log_error("Failed to set FD negotiation: %s", strerror(-r));
a8f11321
LP
1089 goto finish;
1090 }
1091
8a0e0ed9
LP
1092 if (ucred.pid > 0) {
1093 a->fake_creds.pid = ucred.pid;
1094 a->fake_creds.uid = ucred.uid;
1095 a->fake_creds.gid = ucred.gid;
1096 a->fake_creds_valid = true;
1097 }
1098
373f1422
LP
1099 if (peersec) {
1100 a->fake_label = peersec;
1101 peersec = NULL;
1102 }
8a0e0ed9 1103
758bf0c7
LP
1104 a->manual_peer_interface = true;
1105
d51539b1
LP
1106 r = sd_bus_start(a);
1107 if (r < 0) {
1108 log_error("Failed to start bus client: %s", strerror(-r));
1109 goto finish;
1110 }
a8f11321 1111
d51539b1
LP
1112 r = sd_bus_get_server_id(a, &server_id);
1113 if (r < 0) {
1114 log_error("Failed to get server ID: %s", strerror(-r));
a8f11321
LP
1115 goto finish;
1116 }
1117
d51539b1
LP
1118 r = sd_bus_new(&b);
1119 if (r < 0) {
1120 log_error("Failed to allocate bus: %s", strerror(-r));
1121 goto finish;
1122 }
a8f11321 1123
71008e18 1124 r = sd_bus_set_fd(b, in_fd, out_fd);
d51539b1
LP
1125 if (r < 0) {
1126 log_error("Failed to set fds: %s", strerror(-r));
1127 goto finish;
1128 }
a8f11321 1129
d51539b1
LP
1130 r = sd_bus_set_server(b, 1, server_id);
1131 if (r < 0) {
1132 log_error("Failed to set server mode: %s", strerror(-r));
1133 goto finish;
1134 }
a8f11321 1135
264ad849 1136 r = sd_bus_negotiate_fds(b, is_unix);
d51539b1
LP
1137 if (r < 0) {
1138 log_error("Failed to set FD negotiation: %s", strerror(-r));
a8f11321
LP
1139 goto finish;
1140 }
1141
d51539b1
LP
1142 r = sd_bus_set_anonymous(b, true);
1143 if (r < 0) {
1144 log_error("Failed to set anonymous authentication: %s", strerror(-r));
1145 goto finish;
1146 }
a8f11321 1147
758bf0c7
LP
1148 b->manual_peer_interface = true;
1149
d51539b1
LP
1150 r = sd_bus_start(b);
1151 if (r < 0) {
1152 log_error("Failed to start bus client: %s", strerror(-r));
1153 goto finish;
1154 }
a8f11321 1155
758bf0c7 1156 r = rename_service(a, b);
a7639e37
LP
1157 if (r < 0)
1158 log_debug("Failed to rename process: %s", strerror(-r));
0721804f 1159
a7639e37 1160 if (a->is_kernel) {
94a6ce5b 1161 _cleanup_free_ char *match = NULL;
a7639e37
LP
1162 const char *unique;
1163
1164 r = sd_bus_get_unique_name(a, &unique);
1165 if (r < 0) {
1166 log_error("Failed to get unique name: %s", strerror(-r));
0721804f
LP
1167 goto finish;
1168 }
1169
a7639e37
LP
1170 match = strjoin("type='signal',"
1171 "sender='org.freedesktop.DBus',"
1172 "path='/org/freedesktop/DBus',"
1173 "interface='org.freedesktop.DBus',"
1174 "member='NameOwnerChanged',"
1175 "arg1='",
1176 unique,
1177 "'",
1178 NULL);
1179 if (!match) {
1180 log_oom();
0721804f
LP
1181 goto finish;
1182 }
1183
19befb2d 1184 r = sd_bus_add_match(a, NULL, match, NULL, NULL);
a7639e37
LP
1185 if (r < 0) {
1186 log_error("Failed to add match for NameLost: %s", strerror(-r));
1187 goto finish;
1188 }
0721804f 1189
a7639e37
LP
1190 free(match);
1191 match = strjoin("type='signal',"
1192 "sender='org.freedesktop.DBus',"
1193 "path='/org/freedesktop/DBus',"
1194 "interface='org.freedesktop.DBus',"
1195 "member='NameOwnerChanged',"
1196 "arg2='",
1197 unique,
1198 "'",
1199 NULL);
1200 if (!match) {
1201 log_oom();
1202 goto finish;
1203 }
0721804f 1204
19befb2d 1205 r = sd_bus_add_match(a, NULL, match, NULL, NULL);
a7639e37
LP
1206 if (r < 0) {
1207 log_error("Failed to add match for NameAcquired: %s", strerror(-r));
1208 goto finish;
0721804f
LP
1209 }
1210 }
1211
d51539b1
LP
1212 for (;;) {
1213 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
f72a3e5b
KS
1214 int events_a, events_b, fd;
1215 uint64_t timeout_a, timeout_b, t;
d51539b1 1216 struct timespec _ts, *ts;
b2bb3469 1217 struct pollfd *pollfd;
f72a3e5b
KS
1218 int k;
1219
a7639e37
LP
1220 if (got_hello) {
1221 r = sd_bus_process(a, &m);
1222 if (r < 0) {
1223 /* treat 'connection reset by peer' as clean exit condition */
1224 if (r == -ECONNRESET)
1225 r = 0;
1226 else
1227 log_error("Failed to process bus a: %s", strerror(-r));
a8f11321 1228
0358b3f9
LP
1229 goto finish;
1230 }
1231
a7639e37
LP
1232 if (m) {
1233 /* We officially got EOF, let's quit */
1234 if (sd_bus_message_is_signal(m, "org.freedesktop.DBus.Local", "Disconnected")) {
1235 r = 0;
1236 goto finish;
1237 }
1238
1239 k = synthesize_name_acquired(a, b, m);
1240 if (k < 0) {
1241 r = k;
1242 log_error("Failed to synthesize message: %s", strerror(-r));
1243 goto finish;
1244 }
1245
7b217f41
LP
1246 patch_sender(a, m);
1247
a7639e37
LP
1248 k = sd_bus_send(b, m, NULL);
1249 if (k < 0) {
441d56a1
LP
1250 if (k == -ECONNRESET)
1251 r = 0;
1252 else {
1253 r = k;
1254 log_error("Failed to send message: %s", strerror(-r));
1255 }
1256
a7639e37
LP
1257 goto finish;
1258 }
d51539b1 1259 }
a8f11321 1260
a7639e37
LP
1261 if (r > 0)
1262 continue;
1263 }
f72a3e5b
KS
1264
1265 r = sd_bus_process(b, &m);
1266 if (r < 0) {
1267 /* treat 'connection reset by peer' as clean exit condition */
1268 if (r == -ECONNRESET)
1269 r = 0;
1270 else
1271 log_error("Failed to process bus b: %s", strerror(-r));
1272
d51539b1
LP
1273 goto finish;
1274 }
a8f11321 1275
f72a3e5b
KS
1276 if (m) {
1277 /* We officially got EOF, let's quit */
1278 if (sd_bus_message_is_signal(m, "org.freedesktop.DBus.Local", "Disconnected")) {
1279 r = 0;
9818fa6d
ZJS
1280 goto finish;
1281 }
a8f11321 1282
a7639e37 1283 k = process_hello(a, b, m, &got_hello);
f72a3e5b
KS
1284 if (k < 0) {
1285 r = k;
920e2957 1286 log_error("Failed to process HELLO: %s", strerror(-r));
9818fa6d
ZJS
1287 goto finish;
1288 }
a7639e37
LP
1289
1290 if (k > 0)
1291 r = k;
1292 else {
c2595875
LP
1293 k = process_policy(a, b, m);
1294 if (k < 0) {
1295 r = k;
920e2957 1296 log_error("Failed to process policy: %s", strerror(-r));
c2595875
LP
1297 goto finish;
1298 }
1299
2a0abe5b 1300 k = process_driver(a, b, m);
a7639e37 1301 if (k < 0) {
2a0abe5b
LP
1302 r = k;
1303 log_error("Failed to process driver calls: %s", strerror(-r));
a7639e37
LP
1304 goto finish;
1305 }
2a0abe5b
LP
1306
1307 if (k > 0)
1308 r = k;
1309 else {
1310 k = sd_bus_send(a, m, NULL);
1311 if (k < 0) {
1312 if (r == -ECONNRESET)
1313 r = 0;
1314 else {
1315 r = k;
1316 log_error("Failed to send message: %s", strerror(-r));
1317 }
1318
1319 goto finish;
1320 }
1321 }
a7639e37 1322 }
d51539b1 1323 }
a8f11321 1324
f72a3e5b
KS
1325 if (r > 0)
1326 continue;
1327
1328 fd = sd_bus_get_fd(a);
1329 if (fd < 0) {
1330 log_error("Failed to get fd: %s", strerror(-r));
1331 goto finish;
1332 }
1333
1334 events_a = sd_bus_get_events(a);
1335 if (events_a < 0) {
1336 log_error("Failed to get events mask: %s", strerror(-r));
1337 goto finish;
1338 }
1339
1340 r = sd_bus_get_timeout(a, &timeout_a);
1341 if (r < 0) {
1342 log_error("Failed to get timeout: %s", strerror(-r));
1343 goto finish;
1344 }
1345
1346 events_b = sd_bus_get_events(b);
1347 if (events_b < 0) {
1348 log_error("Failed to get events mask: %s", strerror(-r));
1349 goto finish;
1350 }
1351
1352 r = sd_bus_get_timeout(b, &timeout_b);
1353 if (r < 0) {
1354 log_error("Failed to get timeout: %s", strerror(-r));
1355 goto finish;
1356 }
1357
1358 t = timeout_a;
1359 if (t == (uint64_t) -1 || (timeout_b != (uint64_t) -1 && timeout_b < timeout_a))
1360 t = timeout_b;
a8f11321 1361
d51539b1
LP
1362 if (t == (uint64_t) -1)
1363 ts = NULL;
1364 else {
1365 usec_t nw;
a8f11321 1366
d51539b1
LP
1367 nw = now(CLOCK_MONOTONIC);
1368 if (t > nw)
1369 t -= nw;
1370 else
1371 t = 0;
a8f11321 1372
d51539b1 1373 ts = timespec_store(&_ts, t);
a8f11321
LP
1374 }
1375
b2bb3469 1376 pollfd = (struct pollfd[3]) {
f72a3e5b
KS
1377 {.fd = fd, .events = events_a, },
1378 {.fd = in_fd, .events = events_b & POLLIN, },
1379 {.fd = out_fd, .events = events_b & POLLOUT, }
b2bb3469 1380 };
d51539b1 1381
b2bb3469 1382 r = ppoll(pollfd, 3, ts, NULL);
d51539b1
LP
1383 if (r < 0) {
1384 log_error("ppoll() failed: %m");
1385 goto finish;
1386 }
1387 }
a8f11321 1388
a8f11321 1389finish:
0358b3f9
LP
1390 sd_bus_flush(a);
1391 sd_bus_flush(b);
1392
d51539b1 1393 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
a8f11321 1394}