chiark / gitweb /
e3d32ec54857b6bd33b694225fa1d66e9b823cf7
[elogind.git] / src / bus-driverd / bus-driverd.c
1 /***
2   This file is part of systemd.
3
4   Copyright 2013 Daniel Mack
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
20 #include <stdlib.h>
21 #include <stdbool.h>
22 #include <unistd.h>
23 #include <getopt.h>
24 #include <locale.h>
25 #include <string.h>
26 #include <poll.h>
27 #include <netdb.h>
28 #include <sys/socket.h>
29 #include <sys/un.h>
30 #include <sys/timex.h>
31 #include <sys/utsname.h>
32 #include <unistd.h>
33
34 #include "kdbus.h"
35 #include "sd-bus.h"
36 #include "bus-internal.h"
37
38 #include "sd-daemon.h"
39 #include "sd-event.h"
40 #include "event-util.h"
41 #include "bus-util.h"
42 #include "bus-error.h"
43 #include "bus-message.h"
44 #include "bus-kernel.h"
45 #include "socket-util.h"
46 #include "util.h"
47 #include "build.h"
48 #include "strv.h"
49 #include "sd-id128.h"
50 #include "async.h"
51 #include "hashmap.h"
52
53 #define DBUS_PATH       "/org/freedesktop/DBus"
54 #define DBUS_INTERFACE  "org.freedesktop.DBus"
55
56 /*
57  * TODO:
58  *
59  * AddMatch / RemoveMatch
60  * ListActivatableNames
61  * StartServiceByName
62  */
63
64 static sd_bus *driver_bus;
65
66 static int help(void) {
67
68         printf("%s [OPTIONS...] <bus-path>\n\n"
69                "Driver to provide a org.freedesktop.DBus interface on the given kdbus node.\n\n"
70                "  -h --help              Show this help\n"
71                "     --version           Show package version\n",
72                program_invocation_short_name);
73
74         return 0;
75 }
76
77 static int parse_argv(int argc, char *argv[]) {
78
79         enum {
80                 ARG_VERSION = 0x100,
81         };
82
83         static const struct option options[] = {
84                 { "help",            no_argument,       NULL, 'h'     },
85                 { NULL,              0,                 NULL, 0       }
86         };
87
88         int c;
89
90         assert(argc >= 0);
91         assert(argv);
92
93         while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) {
94
95                 switch (c) {
96
97                 case 'h':
98                         help();
99                         return 0;
100
101                 case ARG_VERSION:
102                         puts(PACKAGE_STRING);
103                         puts(SYSTEMD_FEATURES);
104                         return 0;
105
106                 case '?':
107                         return -EINVAL;
108
109                 default:
110                         log_error("Unknown option code %c", c);
111                         return -EINVAL;
112                 }
113         }
114
115         return 1;
116 }
117
118 static int driver_name_info_error(sd_bus *bus, sd_bus_message *m, const char *name, int error_code) {
119
120         if (error_code == -ENXIO || error_code == -ENOENT)
121                 return sd_bus_reply_method_errorf(m, SD_BUS_ERROR_NAME_HAS_NO_OWNER,
122                                                   "Could not get owner of name '%s': no such name",
123                                                   name);
124
125         return sd_bus_reply_method_errno(m, error_code, NULL);
126 }
127
128 static int driver_add_match(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *error) {
129
130         char *arg0, *match;
131         int r;
132
133         r = sd_bus_message_read(m, "s", &arg0);
134         if (r < 0)
135                 return r;
136
137         match = strdup(arg0);
138         if (!match)
139                 return -ENOMEM;
140
141         /* FIXME */
142
143         return sd_bus_reply_method_return(m, NULL);
144 }
145
146 static int driver_remove_match(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *error) {
147
148         char *arg0;
149         int r;
150
151         r = sd_bus_message_read(m, "s", &arg0);
152         if (r < 0)
153                 return r;
154
155         /* FIXME */
156
157         return sd_bus_reply_method_return(m, NULL);
158 }
159
160 static int driver_get_security_ctx(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *error) {
161
162         _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
163         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
164         char *arg0;
165         int r;
166
167         r = sd_bus_message_read(m, "s", &arg0);
168         if (r < 0)
169                 return r;
170
171         r = sd_bus_get_owner(bus, arg0, SD_BUS_CREDS_SELINUX_CONTEXT, &creds);
172         if (r < 0) {
173                 if (r == -ENOENT)
174                         return driver_name_info_error(bus, m, arg0, r);
175                 else
176                         return r;
177         }
178
179         r = sd_bus_message_new_method_return(m, &reply);
180         if (r < 0)
181                 return r;
182
183         r = sd_bus_message_append_array(reply, 'y', creds->label, strlen(creds->label));
184         if (r < 0)
185                 return r;
186
187         return sd_bus_send(bus, reply, NULL);
188 }
189
190 static int driver_get_pid(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *error) {
191
192         _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
193         char *arg0;
194         int r;
195
196         r = sd_bus_message_read(m, "s", &arg0);
197         if (r < 0)
198                 return r;
199
200         r = sd_bus_get_owner(bus, arg0, SD_BUS_CREDS_PID, &creds);
201         if (r < 0)
202                 return r;
203
204         return sd_bus_reply_method_return(m, "u", creds->pid);
205 }
206
207 static int driver_get_user(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *error) {
208
209         _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
210         char *arg0;
211         int r;
212
213         r = sd_bus_message_read(m, "s", &arg0);
214         if (r < 0)
215                 return r;
216
217         r = sd_bus_get_owner(bus, arg0, SD_BUS_CREDS_UID, &creds);
218         if (r < 0) {
219                 if (r == -ENOENT)
220                         return driver_name_info_error(bus, m, arg0, r);
221                 else
222                         return r;
223         }
224
225         return sd_bus_reply_method_return(m, "u", creds->uid);
226 }
227
228 static int driver_get_id(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *error) {
229
230         sd_id128_t server_id;
231         char buf[SD_ID128_STRING_MAX];
232         int r;
233
234         r = sd_bus_get_server_id(bus, &server_id);
235         if (r < 0)
236                 return r;
237
238         return sd_bus_reply_method_return(m, "s", sd_id128_to_string(server_id, buf));
239 }
240
241 static int driver_get_name_owner(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *error) {
242
243         _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
244         _cleanup_free_ char *owner = NULL;
245         char *arg0;
246         int r;
247
248         r = sd_bus_message_read(m, "s", &arg0);
249         if (r < 0)
250                 return r;
251
252         r = sd_bus_get_owner(bus, arg0, 0, &creds);
253         if (r < 0) {
254                 if (r == -ENOENT)
255                         return driver_name_info_error(bus, m, arg0, r);
256                 else
257                         return r;
258         }
259
260         return sd_bus_reply_method_return(m, "s", creds->unique_name);
261 }
262
263 static int driver_hello(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *error) {
264
265         return sd_bus_reply_method_return(m, "s", m->sender);
266 }
267
268 static int driver_list_names(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *error) {
269
270         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
271         _cleanup_strv_free_ char **names = NULL;
272         int r;
273
274         r = sd_bus_list_names(bus, &names, NULL);
275         if (r < 0)
276                 return r;
277
278         r = sd_bus_message_new_method_return(m, &reply);
279         if (r < 0)
280                 return r;
281
282         r = sd_bus_message_append_strv(reply, names);
283         if (r < 0)
284                 return r;
285
286         return sd_bus_send(bus, reply, NULL);
287 }
288
289 static int driver_list_activatable_names(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *error) {
290
291         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
292         _cleanup_strv_free_ char **names = NULL;
293         int r;
294
295         r = sd_bus_list_names(bus, NULL, &names);
296         if (r < 0)
297                 return r;
298
299         r = sd_bus_message_new_method_return(m, &reply);
300         if (r < 0)
301                 return r;
302
303         r = sd_bus_message_append_strv(reply, names);
304         if (r < 0)
305                 return r;
306
307         return sd_bus_send(bus, reply, NULL);
308 }
309
310 static int driver_list_queued_owners(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *error) {
311
312         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
313         struct kdbus_cmd_name_list cmd = {};
314         struct kdbus_name_list *name_list;
315         struct kdbus_cmd_name *name;
316         _cleanup_strv_free_ char **owners = NULL;
317         char *arg0;
318         int r;
319
320         r = sd_bus_message_read(m, "s", &arg0);
321         if (r < 0)
322                 return r;
323
324         cmd.flags = KDBUS_NAME_LIST_QUEUED;
325
326         r = ioctl(bus->input_fd, KDBUS_CMD_NAME_LIST, &cmd);
327         if (r < 0)
328                 return -errno;
329
330         name_list = (struct kdbus_name_list *) ((uint8_t *) bus->kdbus_buffer + cmd.offset);
331
332         KDBUS_ITEM_FOREACH(name, name_list, names) {
333                 if (name->size > sizeof(*name) && !streq(name->name, arg0)) {
334                         char *n;
335
336                         if (asprintf(&n, ":1.%llu", (unsigned long long) name->id) < 0)
337                                 return -ENOMEM;
338
339                         r = strv_push(&owners, n);
340                         if (r < 0) {
341                                 free(n);
342                                 return -ENOMEM;
343                         }
344                 }
345         }
346
347         r = ioctl(sd_bus_get_fd(bus), KDBUS_CMD_FREE, &cmd.offset);
348         if (r < 0)
349                 return -errno;
350
351         r = sd_bus_message_new_method_return(m, &reply);
352         if (r < 0)
353                 return r;
354
355         r = sd_bus_message_append_strv(reply, owners);
356         if (r < 0)
357                 return r;
358
359         return sd_bus_send(bus, reply, NULL);
360 }
361
362 static int driver_name_has_owner(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *error) {
363
364         char *arg0;
365         int r;
366
367         r = sd_bus_message_read(m, "s", &arg0);
368         if (r < 0)
369                 return r;
370
371         r = sd_bus_get_owner(bus, arg0, 0, NULL);
372         if (r < 0 && r != -ENOENT)
373                 return r;
374
375         return sd_bus_reply_method_return(m, "b", r == 0);
376 }
377
378 static int driver_request_name(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *error) {
379
380         struct kdbus_cmd_name *cmd_name;
381         uint32_t flags;
382         size_t size;
383         uint64_t id;
384         char *name;
385         int r;
386
387         r = sd_bus_message_read(m, "su", &name, &flags);
388         if (r < 0)
389                 return r;
390
391         size = sizeof(*cmd_name) + strlen(name) + 1;
392
393         cmd_name = alloca(size);
394         memset(cmd_name, 0, size);
395         strcpy(cmd_name->name, name);
396         cmd_name->size = size;
397         kdbus_translate_request_name_flags(flags, (uint64_t *) &cmd_name->conn_flags);
398
399         /* This function is open-coded because we request the name 'on behalf'
400          * of the requesting connection */
401         r = bus_kernel_parse_unique_name(m->sender, &id);
402         if (r < 0)
403                 return r;
404
405         cmd_name->id = id;
406
407         r = ioctl(sd_bus_get_fd(bus), KDBUS_CMD_NAME_ACQUIRE, cmd_name);
408         if (r < 0)
409                 return r;
410
411         return sd_bus_reply_method_return(m, "u", 0);
412 }
413
414 static int driver_start_service_by_name(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *error) {
415
416         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
417         char *s;
418         int r;
419
420         return sd_bus_reply_method_return(m, "u", 2);
421
422         r = sd_bus_message_read(m, "s", &s);
423         if (r < 0)
424                 return r;
425
426         /* FIXME */
427
428         return sd_bus_send(bus, reply, NULL);
429 }
430
431 static int driver_update_env(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *error) {
432
433         return sd_bus_reply_method_errorf(m, SD_BUS_ERROR_NOT_SUPPORTED,
434                                           "UpdateActivationEnvironment is unsupported");
435 }
436
437 static int driver_reload_config(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *error) {
438
439         return sd_bus_reply_method_errorf(m, SD_BUS_ERROR_NOT_SUPPORTED,
440                                           "ReloadConfig is unsupported");
441 }
442
443 const sd_bus_vtable dbus_vtable[] = {
444         SD_BUS_VTABLE_START(0),
445         SD_BUS_METHOD("AddMatch", "s", NULL, driver_add_match, 0),
446         SD_BUS_METHOD("GetConnectionSELinuxSecurityContext", "s", "ay", driver_get_security_ctx, 0),
447         SD_BUS_METHOD("GetConnectionUnixProcessID", "s", "u", driver_get_pid, 0),
448         SD_BUS_METHOD("GetConnectionUnixUser", "s", "u", driver_get_user, 0),
449         SD_BUS_METHOD("GetId", NULL, "s", driver_get_id, 0),
450         SD_BUS_METHOD("GetNameOwner", "s", "s", driver_get_name_owner, 0),
451         SD_BUS_METHOD("Hello", NULL, "s", driver_hello, 0),
452         SD_BUS_METHOD("ListActivatableNames", NULL, "as", driver_list_activatable_names, 0),
453         SD_BUS_METHOD("ListNames", NULL, "as", driver_list_names, 0),
454         SD_BUS_METHOD("ListQueuedOwners", "s", "as", driver_list_queued_owners, 0),
455         SD_BUS_METHOD("NameHasOwner", "s", "b", driver_name_has_owner, 0),
456         SD_BUS_METHOD("ReloadConfig", NULL, NULL, driver_reload_config, 0),
457         SD_BUS_METHOD("RemoveMatch", "s", NULL, driver_remove_match, 0),
458         SD_BUS_METHOD("RequestName", "su", "u", driver_request_name, 0),
459         SD_BUS_METHOD("StartServiceByName", "su", "u", driver_start_service_by_name, 0),
460         SD_BUS_METHOD("UpdateActivationEnvironment", "a{ss}", NULL, driver_update_env, 0),
461         SD_BUS_SIGNAL("NameAcquired", "s", 0),
462         SD_BUS_SIGNAL("NameLost", "s", 0),
463         SD_BUS_SIGNAL("NameOwnerChanged", "sss", 0),
464         SD_BUS_VTABLE_END
465 };
466
467 static int driver_main(const char *bus_name) {
468
469         _cleanup_event_source_unref_ sd_event_source *w_accept = NULL;
470         _cleanup_event_source_unref_ sd_event_source *w_root_service = NULL;
471         _cleanup_event_unref_ sd_event *e = NULL;
472         int r;
473
474         r = sd_event_new(&e);
475         if (r < 0) {
476                 log_error("Failed to allocate event loop: %s", strerror(-r));
477                 return r;
478         }
479
480         /* set up kernel bus connection */
481         r = sd_bus_new(&driver_bus);
482         if (r < 0) {
483                 log_error("Failed to create bus: %s", strerror(-r));
484                 return r;
485         }
486
487         r = sd_bus_set_address(driver_bus, bus_name);
488         if (r < 0) {
489                 log_error("Failed to create bus: %s", strerror(-r));
490                 return r;
491         }
492
493         r = sd_bus_start(driver_bus);
494         if (r < 0) {
495                 log_error("Failed to start kernel bus: %s", strerror(-r));
496                 return r;
497         }
498
499         r = sd_bus_request_name(driver_bus, DBUS_INTERFACE, 0);
500         if (r < 0) {
501                 log_error("Unable to request name '%s': %s\n", DBUS_INTERFACE, strerror(-r));
502                 return r;
503         }
504
505         r = sd_bus_add_object_vtable(driver_bus, DBUS_PATH, DBUS_INTERFACE, dbus_vtable, NULL);
506         if (r < 0) {
507                 log_error("Failed to add manager object vtable: %s", strerror(-r));
508                 return r;
509         }
510
511         r = sd_bus_attach_event(driver_bus, e, 0);
512         if (r < 0) {
513                 log_error("Error %d while adding bus to even: %s", r, strerror(-r));
514                 return r;
515         }
516
517         log_debug("Entering main loop.");
518
519         return sd_event_loop(e);
520 }
521
522 int main(int argc, char *argv[]) {
523         char *bus_name;
524         int r;
525
526         setlocale(LC_ALL, "");
527         log_parse_environment();
528         log_open();
529
530         r = parse_argv(argc, argv);
531         if (r <= 0)
532                 return r;
533
534         if (argc <= optind) {
535                 help();
536                 return -EINVAL;
537         }
538
539         r = asprintf(&bus_name, "kernel:path=%s", argv[optind]);
540         if (r < 0)
541                 return r;
542
543         return driver_main(bus_name);
544 }