]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd-bus/bus-message.c
systemctl does not expand %u, so revert back to %I
[thirdparty/systemd.git] / src / libsystemd-bus / bus-message.c
CommitLineData
de1c301e
LP
1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3/***
4 This file is part of systemd.
5
6 Copyright 2013 Lennart Poettering
7
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20***/
21
22#include <errno.h>
2c93b4ef 23#include <fcntl.h>
de1c301e
LP
24
25#include "util.h"
9a17484d 26#include "utf8.h"
89ffcd2a 27#include "strv.h"
6629161f 28#include "time-util.h"
d8d3d8a7 29#include "cgroup-util.h"
de1c301e 30
de1c301e 31#include "sd-bus.h"
9a17484d 32#include "bus-message.h"
de1c301e
LP
33#include "bus-internal.h"
34#include "bus-type.h"
35#include "bus-signature.h"
36
80a46c73 37static int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored);
de1c301e 38
9a17484d
LP
39static void reset_containers(sd_bus_message *m) {
40 unsigned i;
41
42 assert(m);
43
44 for (i = 0; i < m->n_containers; i++)
45 free(m->containers[i].signature);
46
47 free(m->containers);
48 m->containers = NULL;
49
50 m->n_containers = 0;
51 m->root_container.index = 0;
52}
53
de1c301e 54static void message_free(sd_bus_message *m) {
de1c301e
LP
55 assert(m);
56
57 if (m->free_header)
58 free(m->header);
59
60 if (m->free_fields)
61 free(m->fields);
62
63 if (m->free_body)
64 free(m->body);
65
6629161f
LP
66 if (m->free_kdbus)
67 free(m->kdbus);
68
2c93b4ef
LP
69 if (m->free_fds) {
70 close_many(m->fds, m->n_fds);
71 free(m->fds);
72 }
de1c301e 73
77930f11
LP
74 free(m->cmdline_array);
75
9a17484d
LP
76 reset_containers(m);
77 free(m->root_container.signature);
de1c301e 78
9a17484d 79 free(m->peeked_signature);
d8d3d8a7
LP
80
81 free(m->unit);
82 free(m->user_unit);
83 free(m->session);
de1c301e
LP
84 free(m);
85}
86
87static void* buffer_extend(void **p, uint32_t *sz, size_t align, size_t extend) {
88 size_t start, n;
89 void *k;
90
91 assert(p);
92 assert(sz);
93 assert(align > 0);
94
95 start = ALIGN_TO((size_t) *sz, align);
96 n = start + extend;
97
98 if (n == *sz)
99 return (uint8_t*) *p + start;
100
101 if (n > (size_t) ((uint32_t) -1))
102 return NULL;
103
104 k = realloc(*p, n);
105 if (!k)
106 return NULL;
107
108 /* Zero out padding */
109 if (start > *sz)
110 memset((uint8_t*) k + *sz, 0, start - *sz);
111
112 *p = k;
113 *sz = n;
114
115 return (uint8_t*) k + start;
116}
117
118static void *message_extend_fields(sd_bus_message *m, size_t align, size_t sz) {
119 void *p, *o;
120
121 assert(m);
122
123 o = m->fields;
124 p = buffer_extend(&m->fields, &m->header->fields_size, align, sz);
125 if (!p)
126 return NULL;
127
128 if (o != m->fields) {
129 /* Adjust quick access pointers */
130
131 if (m->path)
132 m->path = (const char*) m->fields + (m->path - (const char*) o);
133 if (m->interface)
134 m->interface = (const char*) m->fields + (m->interface - (const char*) o);
135 if (m->member)
136 m->member = (const char*) m->fields + (m->member - (const char*) o);
137 if (m->destination)
138 m->destination = (const char*) m->fields + (m->destination - (const char*) o);
139 if (m->sender)
140 m->sender = (const char*) m->fields + (m->sender - (const char*) o);
de1c301e
LP
141 if (m->error.name)
142 m->error.name = (const char*) m->fields + (m->error.name - (const char*) o);
143 }
144
145 m->free_fields = true;
146
147 return p;
148}
149
150static int message_append_field_string(
151 sd_bus_message *m,
152 uint8_t h,
153 char type,
154 const char *s,
155 const char **ret) {
156
157 size_t l;
158 uint8_t *p;
159
160 assert(m);
161
162 l = strlen(s);
163 if (l > (size_t) (uint32_t) -1)
164 return -EINVAL;
165
166 /* field id byte + signature length + signature 's' + NUL + string length + string + NUL */
167 p = message_extend_fields(m, 8, 4 + 4 + l + 1);
168 if (!p)
169 return -ENOMEM;
170
171 p[0] = h;
172 p[1] = 1;
173 p[2] = type;
174 p[3] = 0;
175
176 ((uint32_t*) p)[1] = l;
177 memcpy(p + 8, s, l + 1);
178
179 if (ret)
180 *ret = (const char*) p + 8;
181
182 return 0;
183}
184
185static int message_append_field_signature(
186 sd_bus_message *m,
187 uint8_t h,
188 const char *s,
189 const char **ret) {
190
191 size_t l;
192 uint8_t *p;
193
194 assert(m);
195
196 l = strlen(s);
197 if (l > 255)
198 return -EINVAL;
199
200 /* field id byte + signature length + signature 'g' + NUL + string length + string + NUL */
201 p = message_extend_fields(m, 8, 4 + 1 + l + 1);
202 if (!p)
203 return -ENOMEM;
204
205 p[0] = h;
206 p[1] = 1;
207 p[2] = SD_BUS_TYPE_SIGNATURE;
208 p[3] = 0;
209 p[4] = l;
210 memcpy(p + 5, s, l + 1);
211
212 if (ret)
213 *ret = (const char*) p + 5;
214
215 return 0;
216}
217
218static int message_append_field_uint32(sd_bus_message *m, uint8_t h, uint32_t x) {
219 uint8_t *p;
220
221 assert(m);
222
223 /* field id byte + signature length + signature 'u' + NUL + value */
224 p = message_extend_fields(m, 8, 4 + 4);
225 if (!p)
226 return -ENOMEM;
227
228 p[0] = h;
229 p[1] = 1;
230 p[2] = SD_BUS_TYPE_UINT32;
231 p[3] = 0;
232
233 ((uint32_t*) p)[1] = x;
234
235 return 0;
236}
237
6629161f 238int bus_message_from_header(
2571ead1
LP
239 void *buffer,
240 size_t length,
2c93b4ef
LP
241 int *fds,
242 unsigned n_fds,
243 const struct ucred *ucred,
2571ead1 244 const char *label,
6629161f 245 size_t extra,
2571ead1
LP
246 sd_bus_message **ret) {
247
80a46c73
LP
248 sd_bus_message *m;
249 struct bus_header *h;
6629161f 250 size_t a, label_sz;
80a46c73
LP
251
252 assert(buffer || length <= 0);
2c93b4ef 253 assert(fds || n_fds <= 0);
80a46c73
LP
254 assert(ret);
255
256 if (length < sizeof(struct bus_header))
257 return -EBADMSG;
258
259 h = buffer;
260 if (h->version != 1)
261 return -EBADMSG;
262
263 if (h->serial == 0)
264 return -EBADMSG;
265
266 if (h->type == _SD_BUS_MESSAGE_TYPE_INVALID)
267 return -EBADMSG;
268
6629161f
LP
269 if (h->endian != SD_BUS_LITTLE_ENDIAN &&
270 h->endian != SD_BUS_BIG_ENDIAN)
80a46c73
LP
271 return -EBADMSG;
272
6629161f 273 a = ALIGN(sizeof(sd_bus_message)) + ALIGN(extra);
80a46c73 274
2571ead1
LP
275 if (label) {
276 label_sz = strlen(label);
6629161f
LP
277 a += label_sz + 1;
278 }
2571ead1
LP
279
280 m = malloc0(a);
80a46c73
LP
281 if (!m)
282 return -ENOMEM;
283
284 m->n_ref = 1;
2c93b4ef 285 m->sealed = true;
80a46c73 286 m->header = h;
2c93b4ef
LP
287 m->fds = fds;
288 m->n_fds = n_fds;
80a46c73 289
2571ead1
LP
290 if (ucred) {
291 m->uid = ucred->uid;
292 m->pid = ucred->pid;
293 m->gid = ucred->gid;
294 m->uid_valid = m->gid_valid = true;
295 }
296
297 if (label) {
6629161f 298 m->label = (char*) m + ALIGN(sizeof(sd_bus_message)) + ALIGN(extra);
2571ead1
LP
299 memcpy(m->label, label, label_sz + 1);
300 }
301
6629161f
LP
302 *ret = m;
303 return 0;
304}
305
306int bus_message_from_malloc(
307 void *buffer,
308 size_t length,
309 int *fds,
310 unsigned n_fds,
311 const struct ucred *ucred,
312 const char *label,
313 sd_bus_message **ret) {
314
315 sd_bus_message *m;
316 int r;
317
318 r = bus_message_from_header(buffer, length, fds, n_fds, ucred, label, 0, &m);
319 if (r < 0)
320 return r;
321
322 if (length != BUS_MESSAGE_SIZE(m)) {
323 r = -EBADMSG;
324 goto fail;
325 }
326
327 m->fields = (uint8_t*) buffer + sizeof(struct bus_header);
328 m->body = (uint8_t*) buffer + sizeof(struct bus_header) + ALIGN8(BUS_MESSAGE_FIELDS_SIZE(m));
329
80a46c73
LP
330 m->n_iovec = 1;
331 m->iovec[0].iov_base = buffer;
332 m->iovec[0].iov_len = length;
333
6629161f 334 r = bus_message_parse_fields(m);
2c93b4ef
LP
335 if (r < 0)
336 goto fail;
337
338 /* We take possession of the memory and fds now */
339 m->free_header = true;
340 m->free_fds = true;
80a46c73
LP
341
342 *ret = m;
343 return 0;
2c93b4ef
LP
344
345fail:
346 message_free(m);
347 return r;
80a46c73
LP
348}
349
de1c301e
LP
350static sd_bus_message *message_new(sd_bus *bus, uint8_t type) {
351 sd_bus_message *m;
352
80a46c73 353 m = malloc0(ALIGN(sizeof(sd_bus_message)) + sizeof(struct bus_header));
de1c301e
LP
354 if (!m)
355 return NULL;
356
357 m->n_ref = 1;
358 m->header = (struct bus_header*) ((uint8_t*) m + ALIGN(sizeof(struct sd_bus_message)));
80a46c73 359 m->header->endian = SD_BUS_NATIVE_ENDIAN;
de1c301e
LP
360 m->header->type = type;
361 m->header->version = bus ? bus->message_version : 1;
021a1e78 362 m->allow_fds = !bus || bus->can_fds || (bus->state != BUS_HELLO && bus->state != BUS_RUNNING);
de1c301e
LP
363
364 return m;
365}
366
367int sd_bus_message_new_signal(
368 sd_bus *bus,
369 const char *path,
370 const char *interface,
371 const char *member,
372 sd_bus_message **m) {
373
374 sd_bus_message *t;
375 int r;
376
377 if (!path)
378 return -EINVAL;
379 if (!interface)
380 return -EINVAL;
381 if (!member)
382 return -EINVAL;
5407f2de
LP
383 if (!m)
384 return -EINVAL;
021a1e78
LP
385 if (bus && bus->state == BUS_UNSET)
386 return -ENOTCONN;
de1c301e
LP
387
388 t = message_new(bus, SD_BUS_MESSAGE_TYPE_SIGNAL);
389 if (!t)
390 return -ENOMEM;
391
89ffcd2a
LP
392 t->header->flags |= SD_BUS_MESSAGE_NO_REPLY_EXPECTED;
393
de1c301e
LP
394 r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
395 if (r < 0)
396 goto fail;
397 r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
398 if (r < 0)
399 goto fail;
400 r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
401 if (r < 0)
402 goto fail;
403
404 *m = t;
405 return 0;
406
407fail:
408 sd_bus_message_unref(t);
409 return r;
410}
411
412int sd_bus_message_new_method_call(
413 sd_bus *bus,
414 const char *destination,
415 const char *path,
416 const char *interface,
417 const char *member,
418 sd_bus_message **m) {
419
420 sd_bus_message *t;
421 int r;
422
423 if (!path)
424 return -EINVAL;
425 if (!member)
426 return -EINVAL;
5407f2de
LP
427 if (!m)
428 return -EINVAL;
021a1e78
LP
429 if (bus && bus->state == BUS_UNSET)
430 return -ENOTCONN;
de1c301e
LP
431
432 t = message_new(bus, SD_BUS_MESSAGE_TYPE_METHOD_CALL);
433 if (!t)
434 return -ENOMEM;
435
436 r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
437 if (r < 0)
438 goto fail;
439 r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
440 if (r < 0)
441 goto fail;
442
443 if (interface) {
444 r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
445 if (r < 0)
446 goto fail;
447 }
448
449 if (destination) {
450 r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &t->destination);
451 if (r < 0)
452 goto fail;
453 }
454
455 *m = t;
456 return 0;
457
458fail:
459 message_free(t);
460 return r;
461}
462
5407f2de 463static int message_new_reply(
de1c301e
LP
464 sd_bus *bus,
465 sd_bus_message *call,
5407f2de 466 uint8_t type,
de1c301e
LP
467 sd_bus_message **m) {
468
469 sd_bus_message *t;
470 int r;
471
472 if (!call)
473 return -EINVAL;
e3017af9
LP
474 if (!call->sealed)
475 return -EPERM;
de1c301e
LP
476 if (call->header->type != SD_BUS_MESSAGE_TYPE_METHOD_CALL)
477 return -EINVAL;
5407f2de
LP
478 if (!m)
479 return -EINVAL;
021a1e78
LP
480 if (bus && bus->state == BUS_UNSET)
481 return -ENOTCONN;
de1c301e 482
5407f2de 483 t = message_new(bus, type);
de1c301e
LP
484 if (!t)
485 return -ENOMEM;
486
89ffcd2a 487 t->header->flags |= SD_BUS_MESSAGE_NO_REPLY_EXPECTED;
de1c301e 488 t->reply_serial = BUS_MESSAGE_SERIAL(call);
5407f2de 489
de1c301e
LP
490 r = message_append_field_uint32(t, SD_BUS_MESSAGE_HEADER_REPLY_SERIAL, t->reply_serial);
491 if (r < 0)
492 goto fail;
493
494 if (call->sender) {
495 r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, call->sender, &t->sender);
496 if (r < 0)
497 goto fail;
498 }
499
5407f2de
LP
500 t->dont_send = !!(call->header->flags & SD_BUS_MESSAGE_NO_REPLY_EXPECTED);
501
de1c301e 502 *m = t;
89ffcd2a 503 return 0;
de1c301e
LP
504
505fail:
506 message_free(t);
507 return r;
508}
509
5407f2de
LP
510int sd_bus_message_new_method_return(
511 sd_bus *bus,
512 sd_bus_message *call,
513 sd_bus_message **m) {
514
515 return message_new_reply(bus, call, SD_BUS_MESSAGE_TYPE_METHOD_RETURN, m);
516}
517
de1c301e
LP
518int sd_bus_message_new_method_error(
519 sd_bus *bus,
520 sd_bus_message *call,
521 const sd_bus_error *e,
522 sd_bus_message **m) {
523
524 sd_bus_message *t;
525 int r;
526
fbfa72b0 527 if (!sd_bus_error_is_set(e))
de1c301e 528 return -EINVAL;
5407f2de
LP
529 if (!m)
530 return -EINVAL;
de1c301e 531
5407f2de 532 r = message_new_reply(bus, call, SD_BUS_MESSAGE_TYPE_METHOD_ERROR, &t);
de1c301e 533 if (r < 0)
5407f2de 534 return r;
de1c301e
LP
535
536 r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
537 if (r < 0)
538 goto fail;
539
540 if (e->message) {
541 r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
542 if (r < 0)
543 goto fail;
544 }
545
546 *m = t;
547 return 0;
548
549fail:
550 message_free(t);
551 return r;
552}
553
554sd_bus_message* sd_bus_message_ref(sd_bus_message *m) {
555 if (!m)
556 return NULL;
557
558 assert(m->n_ref > 0);
559 m->n_ref++;
560
561 return m;
562}
563
564sd_bus_message* sd_bus_message_unref(sd_bus_message *m) {
565 if (!m)
566 return NULL;
567
568 assert(m->n_ref > 0);
569 m->n_ref--;
570
571 if (m->n_ref <= 0)
572 message_free(m);
573
574 return NULL;
575}
576
577int sd_bus_message_get_type(sd_bus_message *m, uint8_t *type) {
578 if (!m)
579 return -EINVAL;
580 if (!type)
581 return -EINVAL;
582
583 *type = m->header->type;
584 return 0;
585}
586
587int sd_bus_message_get_serial(sd_bus_message *m, uint64_t *serial) {
588 if (!m)
589 return -EINVAL;
590 if (!serial)
591 return -EINVAL;
592 if (m->header->serial == 0)
593 return -ENOENT;
594
595 *serial = BUS_MESSAGE_SERIAL(m);
596 return 0;
597}
598
599int sd_bus_message_get_reply_serial(sd_bus_message *m, uint64_t *serial) {
600 if (!m)
601 return -EINVAL;
602 if (!serial)
603 return -EINVAL;
604 if (m->reply_serial == 0)
605 return -ENOENT;
606
607 *serial = m->reply_serial;
608 return 0;
609}
610
611int sd_bus_message_get_no_reply(sd_bus_message *m) {
612 if (!m)
613 return -EINVAL;
614
615 return m->header->type == SD_BUS_MESSAGE_TYPE_METHOD_CALL ? !!(m->header->flags & SD_BUS_MESSAGE_NO_REPLY_EXPECTED) : 0;
616}
617
618const char *sd_bus_message_get_path(sd_bus_message *m) {
619 if (!m)
620 return NULL;
621
622 return m->path;
623}
624
625const char *sd_bus_message_get_interface(sd_bus_message *m) {
626 if (!m)
627 return NULL;
628
629 return m->interface;
630}
631
632const char *sd_bus_message_get_member(sd_bus_message *m) {
633 if (!m)
634 return NULL;
635
636 return m->member;
637}
638const char *sd_bus_message_get_destination(sd_bus_message *m) {
639 if (!m)
640 return NULL;
641
642 return m->destination;
643}
644
645const char *sd_bus_message_get_sender(sd_bus_message *m) {
646 if (!m)
647 return NULL;
648
649 return m->sender;
650}
651
652const sd_bus_error *sd_bus_message_get_error(sd_bus_message *m) {
653 if (!m)
654 return NULL;
655
656 if (!sd_bus_error_is_set(&m->error))
657 return NULL;
658
659 return &m->error;
660}
661
662int sd_bus_message_get_uid(sd_bus_message *m, uid_t *uid) {
663 if (!m)
664 return -EINVAL;
4a875b61
LP
665 if (!uid)
666 return -EINVAL;
de1c301e 667 if (!m->uid_valid)
4a875b61 668 return -ESRCH;
de1c301e
LP
669
670 *uid = m->uid;
671 return 0;
672}
673
674int sd_bus_message_get_gid(sd_bus_message *m, gid_t *gid) {
675 if (!m)
676 return -EINVAL;
4a875b61
LP
677 if (!gid)
678 return -EINVAL;
de1c301e 679 if (!m->gid_valid)
4a875b61 680 return -ESRCH;
de1c301e
LP
681
682 *gid = m->gid;
683 return 0;
684}
685
686int sd_bus_message_get_pid(sd_bus_message *m, pid_t *pid) {
687 if (!m)
688 return -EINVAL;
4a875b61
LP
689 if (!pid)
690 return -EINVAL;
de1c301e 691 if (m->pid <= 0)
4a875b61 692 return -ESRCH;
de1c301e
LP
693
694 *pid = m->pid;
695 return 0;
696}
697
698int sd_bus_message_get_tid(sd_bus_message *m, pid_t *tid) {
699 if (!m)
700 return -EINVAL;
4a875b61
LP
701 if (!tid)
702 return -EINVAL;
de1c301e 703 if (m->tid <= 0)
4a875b61 704 return -ESRCH;
de1c301e
LP
705
706 *tid = m->tid;
707 return 0;
708}
709
8323bc1f
LP
710int sd_bus_message_get_pid_starttime(sd_bus_message *m, uint64_t *usec) {
711 if (!m)
712 return -EINVAL;
4a875b61
LP
713 if (!usec)
714 return -EINVAL;
8323bc1f 715 if (m->pid_starttime <= 0)
4a875b61 716 return -ESRCH;
8323bc1f
LP
717
718 *usec = m->pid_starttime;
719 return 0;
720}
721
4a875b61 722int sd_bus_message_get_selinux_context(sd_bus_message *m, const char **ret) {
2571ead1 723 if (!m)
4a875b61
LP
724 return -EINVAL;
725 if (!m->label)
726 return -ESRCH;
2571ead1 727
4a875b61
LP
728 *ret = m->label;
729 return 0;
2571ead1
LP
730}
731
69aec65c 732int sd_bus_message_get_monotonic_timestamp(sd_bus_message *m, uint64_t *usec) {
acb5a3cb
LP
733 if (!m)
734 return -EINVAL;
4a875b61
LP
735 if (!usec)
736 return -EINVAL;
69aec65c 737 if (m->monotonic <= 0)
4a875b61 738 return -ESRCH;
acb5a3cb 739
69aec65c 740 *usec = m->monotonic;
acb5a3cb
LP
741 return 0;
742}
743
69aec65c
LP
744int sd_bus_message_get_realtime_timestamp(sd_bus_message *m, uint64_t *usec) {
745 if (!m)
746 return -EINVAL;
4a875b61
LP
747 if (!usec)
748 return -EINVAL;
69aec65c 749 if (m->realtime <= 0)
4a875b61 750 return -ESRCH;
69aec65c
LP
751
752 *usec = m->realtime;
753 return 0;
754}
755
4a875b61 756int sd_bus_message_get_comm(sd_bus_message *m, const char **ret) {
69aec65c 757 if (!m)
4a875b61
LP
758 return -EINVAL;
759 if (!ret)
760 return -EINVAL;
761 if (!m->comm)
762 return -ESRCH;
69aec65c 763
4a875b61
LP
764 *ret = m->comm;
765 return 0;
69aec65c
LP
766}
767
4a875b61 768int sd_bus_message_get_tid_comm(sd_bus_message *m, const char **ret) {
69aec65c 769 if (!m)
4a875b61
LP
770 return -EINVAL;
771 if (!ret)
772 return -EINVAL;
773 if (!m->tid_comm)
774 return -ESRCH;
69aec65c 775
4a875b61
LP
776 *ret = m->tid_comm;
777 return 0;
69aec65c
LP
778}
779
4a875b61 780int sd_bus_message_get_exe(sd_bus_message *m, const char **ret) {
69aec65c 781 if (!m)
4a875b61
LP
782 return -EINVAL;
783 if (!ret)
784 return -EINVAL;
785 if (!m->exe)
786 return -ESRCH;
69aec65c 787
4a875b61
LP
788 *ret = m->exe;
789 return 0;
790}
791
792int sd_bus_message_get_cgroup(sd_bus_message *m, const char **ret) {
793 if (!m)
794 return -EINVAL;
795 if (!ret)
796 return -EINVAL;
797 if (!m->cgroup)
798 return -ESRCH;
799
800 *ret = m->cgroup;
801 return 0;
69aec65c
LP
802}
803
d8d3d8a7
LP
804int sd_bus_message_get_unit(sd_bus_message *m, const char **ret) {
805 int r;
806
807 if (!m)
808 return -EINVAL;
809 if (!ret)
810 return -EINVAL;
811 if (!m->cgroup)
812 return -ESRCH;
813
814 if (!m->unit) {
815 r = cg_path_get_unit(m->cgroup, &m->unit);
816 if (r < 0)
817 return r;
818 }
819
820 *ret = m->unit;
821 return 0;
822}
823
824int sd_bus_message_get_user_unit(sd_bus_message *m, const char **ret) {
825 int r;
826
827 if (!m)
828 return -EINVAL;
829 if (!ret)
830 return -EINVAL;
831 if (!m->cgroup)
832 return -ESRCH;
833
834 if (!m->user_unit) {
835 r = cg_path_get_user_unit(m->cgroup, &m->user_unit);
836 if (r < 0)
837 return r;
838 }
839
840 *ret = m->user_unit;
841 return 0;
842}
843
844int sd_bus_message_get_session(sd_bus_message *m, const char **ret) {
845 int r;
846
847 if (!m)
848 return -EINVAL;
849 if (!ret)
850 return -EINVAL;
851 if (!m->cgroup)
852 return -ESRCH;
853
854 if (!m->session) {
855 r = cg_path_get_session(m->cgroup, &m->session);
856 if (r < 0)
857 return r;
858 }
859
860 *ret = m->session;
861 return 0;
862}
863
bc7f3beb
LP
864int sd_bus_message_get_owner_uid(sd_bus_message *m, uid_t *uid) {
865 if (!m)
866 return -EINVAL;
867 if (!uid)
868 return -EINVAL;
869 if (!m->cgroup)
870 return -ESRCH;
871
872 return cg_path_get_owner_uid(m->cgroup, uid);
873}
874
77930f11
LP
875int sd_bus_message_get_cmdline(sd_bus_message *m, char ***cmdline) {
876 size_t n, i;
877 const char *p;
878 bool first;
879
880 if (!m)
881 return -EINVAL;
882
883 if (!m->cmdline)
884 return -ENOENT;
885
886 for (p = m->cmdline, n = 0; p < m->cmdline + m->cmdline_length; p++)
887 if (*p == 0)
888 n++;
889
890 m->cmdline_array = new(char*, n + 1);
891 if (!m->cmdline_array)
892 return -ENOMEM;
893
894 for (p = m->cmdline, i = 0, first = true; p < m->cmdline + m->cmdline_length; p++) {
895 if (first)
896 m->cmdline_array[i++] = (char*) p;
897
898 first = *p == 0;
899 }
900
901 m->cmdline_array[i] = NULL;
902 *cmdline = m->cmdline_array;
903
904 return 0;
905}
906
120f919e
LP
907int sd_bus_message_get_audit_sessionid(sd_bus_message *m, uint32_t *sessionid) {
908 if (!m)
909 return -EINVAL;
910 if (!sessionid)
911 return -EINVAL;
912 if (!m->audit)
913 return -ESRCH;
914
915 *sessionid = m->audit->sessionid;
916 return 0;
917}
918
919int sd_bus_message_get_audit_loginuid(sd_bus_message *m, uid_t *uid) {
920 if (!m)
921 return -EINVAL;
922 if (!uid)
923 return -EINVAL;
924 if (!m->audit)
925 return -ESRCH;
926
927 *uid = m->audit->loginuid;
928 return 0;
929}
930
102ea8e4
LP
931int sd_bus_message_has_effective_cap(sd_bus_message *m, int capability) {
932 unsigned sz;
933
934 if (!m)
935 return -EINVAL;
936 if (capability < 0)
937 return -EINVAL;
938 if (!m->capability)
939 return -ESRCH;
940
941 sz = m->capability_size / 4;
942 if ((unsigned) capability >= sz*8)
943 return 0;
944
945 return !!(m->capability[2 * sz + (capability / 8)] & (1 << (capability % 8)));
946}
947
de1c301e
LP
948int sd_bus_message_is_signal(sd_bus_message *m, const char *interface, const char *member) {
949 if (!m)
950 return -EINVAL;
951
952 if (m->header->type != SD_BUS_MESSAGE_TYPE_SIGNAL)
953 return 0;
954
955 if (interface && (!m->interface || !streq(m->interface, interface)))
956 return 0;
957
958 if (member && (!m->member || !streq(m->member, member)))
959 return 0;
960
961 return 1;
962}
963
964int sd_bus_message_is_method_call(sd_bus_message *m, const char *interface, const char *member) {
965 if (!m)
966 return -EINVAL;
967
968 if (m->header->type != SD_BUS_MESSAGE_TYPE_METHOD_CALL)
969 return 0;
970
971 if (interface && (!m->interface || !streq(m->interface, interface)))
972 return 0;
973
974 if (member && (!m->member || !streq(m->member, member)))
975 return 0;
976
977 return 1;
978}
979
980int sd_bus_message_is_method_error(sd_bus_message *m, const char *name) {
981 if (!m)
982 return -EINVAL;
983
984 if (m->header->type != SD_BUS_MESSAGE_TYPE_METHOD_ERROR)
985 return 0;
986
987 if (name && (!m->error.name || !streq(m->error.name, name)))
988 return 0;
989
990 return 1;
991}
992
993int sd_bus_message_set_no_reply(sd_bus_message *m, int b) {
994 if (!m)
995 return -EINVAL;
996 if (m->sealed)
997 return -EPERM;
998 if (m->header->type != SD_BUS_MESSAGE_TYPE_METHOD_CALL)
999 return -EPERM;
1000
1001 if (b)
1002 m->header->flags |= SD_BUS_MESSAGE_NO_REPLY_EXPECTED;
1003 else
1004 m->header->flags &= ~SD_BUS_MESSAGE_NO_REPLY_EXPECTED;
1005
1006 return 0;
1007}
1008
1009static struct bus_container *message_get_container(sd_bus_message *m) {
1010 assert(m);
1011
1012 if (m->n_containers == 0)
1013 return &m->root_container;
1014
9a17484d
LP
1015 assert(m->containers);
1016 return m->containers + m->n_containers - 1;
de1c301e
LP
1017}
1018
1019static void *message_extend_body(sd_bus_message *m, size_t align, size_t sz) {
1020 void *p, *o;
1021 size_t added;
1022 struct bus_container *c;
1023
1024 assert(m);
9a17484d 1025 assert(align > 0);
de1c301e
LP
1026
1027 o = m->body;
1028 added = m->header->body_size;
1029
1030 p = buffer_extend(&m->body, &m->header->body_size, align, sz);
1031 if (!p)
1032 return NULL;
1033
1034 added = m->header->body_size - added;
1035
9a17484d 1036 for (c = m->containers; c < m->containers + m->n_containers; c++)
de1c301e
LP
1037 if (c->array_size) {
1038 c->array_size = (uint32_t*) ((uint8_t*) m->body + ((uint8_t*) c->array_size - (uint8_t*) o));
1039 *c->array_size += added;
1040 }
1041
1042 if (o != m->body) {
1043 if (m->error.message)
1044 m->error.message = (const char*) m->body + (m->error.message - (const char*) o);
1045 }
1046
1047 m->free_body = true;
1048
1049 return p;
1050}
1051
1052int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored) {
1053 struct bus_container *c;
27f6e5c7 1054 ssize_t align, sz;
de1c301e
LP
1055 uint32_t k;
1056 void *a;
1057 char *e = NULL;
2c93b4ef 1058 int fd = -1;
62cfa9da 1059 uint32_t fdi = 0;
2c93b4ef 1060 int r;
de1c301e
LP
1061
1062 if (!m)
1063 return -EINVAL;
2c93b4ef
LP
1064 if (!p)
1065 return -EINVAL;
de1c301e
LP
1066 if (m->sealed)
1067 return -EPERM;
1068 if (!bus_type_is_basic(type))
1069 return -EINVAL;
1070
1071 c = message_get_container(m);
1072
1073 if (c->signature && c->signature[c->index]) {
1074 /* Container signature is already set */
1075
1076 if (c->signature[c->index] != type)
9a17484d 1077 return -ENXIO;
de1c301e
LP
1078 } else {
1079 /* Maybe we can append to the signature? But only if this is the top-level container*/
1080 if (c->enclosing != 0)
9a17484d 1081 return -ENXIO;
de1c301e
LP
1082
1083 e = strextend(&c->signature, CHAR_TO_STR(type), NULL);
1084 if (!e)
1085 return -ENOMEM;
1086 }
1087
de1c301e
LP
1088 switch (type) {
1089
1090 case SD_BUS_TYPE_STRING:
1091 case SD_BUS_TYPE_OBJECT_PATH:
b8beb278 1092
de1c301e
LP
1093 align = 4;
1094 sz = 4 + strlen(p) + 1;
1095 break;
1096
1097 case SD_BUS_TYPE_SIGNATURE:
b8beb278 1098
de1c301e
LP
1099 align = 1;
1100 sz = 1 + strlen(p) + 1;
1101 break;
1102
1103 case SD_BUS_TYPE_BOOLEAN:
1104 align = sz = 4;
1105
1106 assert_cc(sizeof(int) == sizeof(uint32_t));
1107 memcpy(&k, p, 4);
1108 k = !!k;
1109 p = &k;
1110 break;
1111
2c93b4ef
LP
1112 case SD_BUS_TYPE_UNIX_FD: {
1113 int z, *f;
1114
1115 if (!m->allow_fds) {
1116 r = -ENOTSUP;
1117 goto fail;
1118 }
1119
1120 align = sz = 4;
1121
1122 z = *(int*) p;
1123 if (z < 0) {
1124 r = -EINVAL;
1125 goto fail;
1126 }
1127
1128 fd = fcntl(z, F_DUPFD_CLOEXEC, 3);
1129 if (fd < 0) {
1130 r = -errno;
1131 goto fail;
1132 }
1133
1134 f = realloc(m->fds, sizeof(int) * (m->n_fds + 1));
1135 if (!f) {
1136 r = -ENOMEM;
1137 goto fail;
1138 }
1139
1140 fdi = m->n_fds;
1141 f[fdi] = fd;
1142 m->fds = f;
1143 m->free_fds = true;
1144 break;
1145 }
1146
de1c301e
LP
1147 default:
1148 align = bus_type_get_alignment(type);
1149 sz = bus_type_get_size(type);
1150 break;
1151 }
1152
1153 assert(align > 0);
1154 assert(sz > 0);
1155
1156 a = message_extend_body(m, align, sz);
1157 if (!a) {
2c93b4ef
LP
1158 r = -ENOMEM;
1159 goto fail;
de1c301e
LP
1160 }
1161
1162 if (type == SD_BUS_TYPE_STRING || type == SD_BUS_TYPE_OBJECT_PATH) {
1163 *(uint32_t*) a = sz - 5;
1164 memcpy((uint8_t*) a + 4, p, sz - 4);
1165
1166 if (stored)
1167 *stored = (const uint8_t*) a + 4;
1168
1169 } else if (type == SD_BUS_TYPE_SIGNATURE) {
1170 *(uint8_t*) a = sz - 1;
1171 memcpy((uint8_t*) a + 1, p, sz - 1);
1172
1173 if (stored)
1174 *stored = (const uint8_t*) a + 1;
2c93b4ef
LP
1175 } else if (type == SD_BUS_TYPE_UNIX_FD) {
1176 *(uint32_t*) a = fdi;
1177
1178 if (stored)
1179 *stored = a;
1180
1181 m->n_fds ++;
de1c301e
LP
1182
1183 } else {
1184 memcpy(a, p, sz);
1185
1186 if (stored)
1187 *stored = a;
1188 }
1189
1190 if (c->enclosing != SD_BUS_TYPE_ARRAY)
9a17484d 1191 c->index++;
de1c301e
LP
1192
1193 return 0;
2c93b4ef
LP
1194
1195fail:
1196 /* Truncate extended signature again */
1197 if (e)
1198 c->signature[c->index] = 0;
1199
1200 if (fd >= 0)
1201 close_nointr_nofail(fd);
1202
1203 return r;
de1c301e
LP
1204}
1205
1206int sd_bus_message_append_basic(sd_bus_message *m, char type, const void *p) {
1207 return message_append_basic(m, type, p, NULL);
1208}
1209
1210static int bus_message_open_array(
1211 sd_bus_message *m,
1212 struct bus_container *c,
1213 const char *contents,
1214 uint32_t **array_size) {
1215
9a17484d 1216 unsigned nindex;
de1c301e 1217 char *e = NULL;
de1c301e
LP
1218 void *a, *b;
1219 int alignment;
1220 size_t saved;
1221
1222 assert(m);
1223 assert(c);
1224 assert(contents);
1225 assert(array_size);
1226
1227 if (!signature_is_single(contents))
1228 return -EINVAL;
1229
1230 alignment = bus_type_get_alignment(contents[0]);
1231 if (alignment < 0)
1232 return alignment;
1233
1234 if (c->signature && c->signature[c->index]) {
1235
1236 /* Verify the existing signature */
1237
1238 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
9a17484d 1239 return -ENXIO;
de1c301e
LP
1240
1241 if (!startswith(c->signature + c->index + 1, contents))
9a17484d 1242 return -ENXIO;
de1c301e
LP
1243
1244 nindex = c->index + 1 + strlen(contents);
1245 } else {
1246 if (c->enclosing != 0)
9a17484d 1247 return -ENXIO;
de1c301e
LP
1248
1249 /* Extend the existing signature */
1250
1251 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_ARRAY), contents, NULL);
1252 if (!e)
1253 return -ENOMEM;
1254
1255 nindex = e - c->signature;
1256 }
1257
1258 saved = m->header->body_size;
1259 a = message_extend_body(m, 4, 4);
1260 if (!a) {
1261 /* Truncate extended signature again */
1262 if (e)
1263 c->signature[c->index] = 0;
1264
1265 return -ENOMEM;
1266 }
1267 b = m->body;
1268
1269 if (!message_extend_body(m, alignment, 0)) {
1270 /* Add alignment between size and first element */
1271 if (e)
1272 c->signature[c->index] = 0;
1273
1274 m->header->body_size = saved;
1275 return -ENOMEM;
1276 }
1277
1278 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1279 c->index = nindex;
1280
1281 /* m->body might have changed so let's readjust a */
1282 a = (uint8_t*) m->body + ((uint8_t*) a - (uint8_t*) b);
1283 *(uint32_t*) a = 0;
1284
1285 *array_size = a;
1286 return 0;
1287}
1288
1289static int bus_message_open_variant(
1290 sd_bus_message *m,
1291 struct bus_container *c,
1292 const char *contents) {
1293
1294 char *e = NULL;
9a17484d 1295 size_t l;
de1c301e
LP
1296 void *a;
1297
1298 assert(m);
1299 assert(c);
1300 assert(contents);
1301
1302 if (!signature_is_single(contents))
1303 return -EINVAL;
1304
1305 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
1306 return -EINVAL;
1307
1308 if (c->signature && c->signature[c->index]) {
1309
1310 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
9a17484d 1311 return -ENXIO;
de1c301e
LP
1312
1313 } else {
1314 if (c->enclosing != 0)
9a17484d 1315 return -ENXIO;
de1c301e
LP
1316
1317 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_VARIANT), NULL);
1318 if (!e)
1319 return -ENOMEM;
1320 }
1321
de1c301e
LP
1322 l = strlen(contents);
1323 a = message_extend_body(m, 1, 1 + l + 1);
1324 if (!a) {
1325 /* Truncate extended signature again */
1326 if (e)
1327 c->signature[c->index] = 0;
1328
1329 return -ENOMEM;
1330 }
1331
1332 *(uint8_t*) a = l;
1333 memcpy((uint8_t*) a + 1, contents, l + 1);
1334
1335 if (c->enclosing != SD_BUS_TYPE_ARRAY)
9a17484d 1336 c->index++;
de1c301e
LP
1337
1338 return 0;
1339}
1340
1341static int bus_message_open_struct(
1342 sd_bus_message *m,
1343 struct bus_container *c,
1344 const char *contents) {
1345
1346 size_t nindex;
1347 char *e = NULL;
1348
1349 assert(m);
1350 assert(c);
1351 assert(contents);
1352
1353 if (!signature_is_valid(contents, false))
1354 return -EINVAL;
1355
1356 if (c->signature && c->signature[c->index]) {
1357 size_t l;
1358
1359 l = strlen(contents);
1360
1361 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
1362 !startswith(c->signature + c->index + 1, contents) ||
1363 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
9a17484d 1364 return -ENXIO;
de1c301e
LP
1365
1366 nindex = c->index + 1 + l + 1;
1367 } else {
1368 if (c->enclosing != 0)
9a17484d 1369 return -ENXIO;
de1c301e
LP
1370
1371 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_BEGIN), contents, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_END), NULL);
1372 if (!e)
1373 return -ENOMEM;
1374
1375 nindex = e - c->signature;
1376 }
1377
1378 /* Align contents to 8 byte boundary */
1379 if (!message_extend_body(m, 8, 0)) {
1380 if (e)
1381 c->signature[c->index] = 0;
1382
1383 return -ENOMEM;
1384 }
1385
1386 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1387 c->index = nindex;
1388
1389 return 0;
1390}
1391
1392static int bus_message_open_dict_entry(
1393 sd_bus_message *m,
1394 struct bus_container *c,
1395 const char *contents) {
1396
1397 size_t nindex;
1398
1399 assert(m);
1400 assert(c);
1401 assert(contents);
1402
1403 if (!signature_is_pair(contents))
1404 return -EINVAL;
1405
1406 if (c->enclosing != SD_BUS_TYPE_ARRAY)
9a17484d 1407 return -ENXIO;
de1c301e
LP
1408
1409 if (c->signature && c->signature[c->index]) {
1410 size_t l;
1411
1412 l = strlen(contents);
1413
1414 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
1415 !startswith(c->signature + c->index + 1, contents) ||
1416 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
9a17484d 1417 return -ENXIO;
de1c301e
LP
1418
1419 nindex = c->index + 1 + l + 1;
1420 } else
9a17484d 1421 return -ENXIO;
de1c301e
LP
1422
1423 /* Align contents to 8 byte boundary */
1424 if (!message_extend_body(m, 8, 0))
1425 return -ENOMEM;
1426
1427 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1428 c->index = nindex;
1429
1430 return 0;
1431}
1432
1433int sd_bus_message_open_container(
1434 sd_bus_message *m,
1435 char type,
1436 const char *contents) {
1437
9a17484d 1438 struct bus_container *c, *w;
de1c301e 1439 uint32_t *array_size = NULL;
9a17484d 1440 char *signature;
de1c301e
LP
1441 int r;
1442
1443 if (!m)
1444 return -EINVAL;
1445 if (m->sealed)
1446 return -EPERM;
1447 if (!contents)
1448 return -EINVAL;
1449
1450 /* Make sure we have space for one more container */
9a17484d
LP
1451 w = realloc(m->containers, sizeof(struct bus_container) * (m->n_containers + 1));
1452 if (!w)
de1c301e 1453 return -ENOMEM;
9a17484d 1454 m->containers = w;
de1c301e
LP
1455
1456 c = message_get_container(m);
1457
1458 signature = strdup(contents);
1459 if (!signature)
1460 return -ENOMEM;
1461
1462 if (type == SD_BUS_TYPE_ARRAY)
1463 r = bus_message_open_array(m, c, contents, &array_size);
1464 else if (type == SD_BUS_TYPE_VARIANT)
1465 r = bus_message_open_variant(m, c, contents);
1466 else if (type == SD_BUS_TYPE_STRUCT)
1467 r = bus_message_open_struct(m, c, contents);
1468 else if (type == SD_BUS_TYPE_DICT_ENTRY)
1469 r = bus_message_open_dict_entry(m, c, contents);
1470 else
1471 r = -EINVAL;
1472
1473 if (r < 0) {
1474 free(signature);
1475 return r;
1476 }
1477
1478 /* OK, let's fill it in */
9a17484d
LP
1479 w += m->n_containers++;
1480 w->enclosing = type;
1481 w->signature = signature;
1482 w->index = 0;
1483 w->array_size = array_size;
1484 w->begin = 0;
de1c301e
LP
1485
1486 return 0;
1487}
1488
1489int sd_bus_message_close_container(sd_bus_message *m) {
1490 struct bus_container *c;
1491
1492 if (!m)
1493 return -EINVAL;
1494 if (m->sealed)
1495 return -EPERM;
1496 if (m->n_containers <= 0)
1497 return -EINVAL;
1498
1499 c = message_get_container(m);
de1c301e 1500 if (c->enclosing != SD_BUS_TYPE_ARRAY)
9a17484d 1501 if (c->signature && c->signature[c->index] != 0)
de1c301e
LP
1502 return -EINVAL;
1503
1504 free(c->signature);
1505 m->n_containers--;
1506
1507 return 0;
1508}
1509
1b492614
LP
1510
1511typedef struct {
1512 const char *types;
1513 unsigned n_struct;
1514 unsigned n_array;
1515} TypeStack;
1516
1517static int type_stack_push(TypeStack *stack, unsigned max, unsigned *i, const char *types, unsigned n_struct, unsigned n_array) {
1518 assert(stack);
1519 assert(max > 0);
1520
1521 if (*i >= max)
1522 return -EINVAL;
1523
1524 stack[*i].types = types;
1525 stack[*i].n_struct = n_struct;
1526 stack[*i].n_array = n_array;
1527 (*i)++;
1528
1529 return 0;
1530}
1531
1532static int type_stack_pop(TypeStack *stack, unsigned max, unsigned *i, const char **types, unsigned *n_struct, unsigned *n_array) {
1533 assert(stack);
1534 assert(max > 0);
1535 assert(types);
1536 assert(n_struct);
1537 assert(n_array);
1538
1539 if (*i <= 0)
1540 return 0;
1541
1542 (*i)--;
1543 *types = stack[*i].types;
1544 *n_struct = stack[*i].n_struct;
1545 *n_array = stack[*i].n_array;
1546
1547 return 1;
1548}
1549
917b5dc7 1550int bus_message_append_ap(
de1c301e
LP
1551 sd_bus_message *m,
1552 const char *types,
1553 va_list ap) {
1554
1b492614
LP
1555 unsigned n_array, n_struct;
1556 TypeStack stack[BUS_CONTAINER_DEPTH];
1557 unsigned stack_ptr = 0;
de1c301e
LP
1558 int r;
1559
1560 assert(m);
88d331d5
LP
1561
1562 if (!types)
1563 return 0;
de1c301e 1564
1b492614
LP
1565 n_array = (unsigned) -1;
1566 n_struct = strlen(types);
1567
1568 for (;;) {
1569 const char *t;
1570
1571 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
1572 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
1573 if (r < 0)
1574 return r;
1575 if (r == 0)
1576 break;
1577
1578 r = sd_bus_message_close_container(m);
1579 if (r < 0)
1580 return r;
1581
1582 continue;
1583 }
1584
1585 t = types;
1586 if (n_array != (unsigned) -1)
1587 n_array --;
1588 else {
1589 types ++;
1590 n_struct--;
1591 }
1592
de1c301e
LP
1593 switch (*t) {
1594
1595 case SD_BUS_TYPE_BYTE: {
1596 uint8_t x;
1597
1598 x = (uint8_t) va_arg(ap, int);
1599 r = sd_bus_message_append_basic(m, *t, &x);
1600 break;
1601 }
1602
1603 case SD_BUS_TYPE_BOOLEAN:
1604 case SD_BUS_TYPE_INT32:
9a17484d
LP
1605 case SD_BUS_TYPE_UINT32:
1606 case SD_BUS_TYPE_UNIX_FD: {
de1c301e
LP
1607 uint32_t x;
1608
9a17484d
LP
1609 /* We assume a boolean is the same as int32_t */
1610 assert_cc(sizeof(int32_t) == sizeof(int));
1611
de1c301e
LP
1612 x = va_arg(ap, uint32_t);
1613 r = sd_bus_message_append_basic(m, *t, &x);
1614 break;
1615 }
1616
1617 case SD_BUS_TYPE_INT16:
1618 case SD_BUS_TYPE_UINT16: {
1619 uint16_t x;
1620
1621 x = (uint16_t) va_arg(ap, int);
1622 r = sd_bus_message_append_basic(m, *t, &x);
1623 break;
1624 }
1625
1626 case SD_BUS_TYPE_INT64:
1627 case SD_BUS_TYPE_UINT64:
1628 case SD_BUS_TYPE_DOUBLE: {
1629 uint64_t x;
1630
1631 x = va_arg(ap, uint64_t);
1632 r = sd_bus_message_append_basic(m, *t, &x);
1633 break;
1634 }
1635
1636 case SD_BUS_TYPE_STRING:
1637 case SD_BUS_TYPE_OBJECT_PATH:
1638 case SD_BUS_TYPE_SIGNATURE: {
1639 const char *x;
1640
1641 x = va_arg(ap, const char*);
1642 r = sd_bus_message_append_basic(m, *t, x);
1643 break;
1644 }
1645
de1c301e 1646 case SD_BUS_TYPE_ARRAY: {
de1c301e
LP
1647 size_t k;
1648
1649 r = signature_element_length(t + 1, &k);
1650 if (r < 0)
1651 return r;
1652
1653 {
1654 char s[k + 1];
de1c301e
LP
1655 memcpy(s, t + 1, k);
1656 s[k] = 0;
de1c301e
LP
1657
1658 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, s);
1659 if (r < 0)
1660 return r;
1b492614 1661 }
de1c301e 1662
1b492614
LP
1663 if (n_array == (unsigned) -1) {
1664 types += k;
1665 n_struct -= k;
de1c301e
LP
1666 }
1667
1b492614
LP
1668 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
1669 if (r < 0)
1670 return r;
1671
1672 types = t + 1;
1673 n_struct = k;
1674 n_array = va_arg(ap, unsigned);
1675
de1c301e
LP
1676 break;
1677 }
1678
1679 case SD_BUS_TYPE_VARIANT: {
1680 const char *s;
1681
1682 s = va_arg(ap, const char*);
1683 if (!s)
1684 return -EINVAL;
1685
1686 r = sd_bus_message_open_container(m, SD_BUS_TYPE_VARIANT, s);
1687 if (r < 0)
1688 return r;
1689
1b492614 1690 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
de1c301e
LP
1691 if (r < 0)
1692 return r;
1693
1b492614
LP
1694 types = s;
1695 n_struct = strlen(s);
1696 n_array = (unsigned) -1;
1697
de1c301e
LP
1698 break;
1699 }
1700
1701 case SD_BUS_TYPE_STRUCT_BEGIN:
1702 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
1703 size_t k;
1704
1705 r = signature_element_length(t, &k);
1706 if (r < 0)
1707 return r;
1708
1709 {
1710 char s[k - 1];
1711
1712 memcpy(s, t + 1, k - 2);
1713 s[k - 2] = 0;
1714
1715 r = sd_bus_message_open_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
1716 if (r < 0)
1717 return r;
1b492614 1718 }
de1c301e 1719
1b492614
LP
1720 if (n_array == (unsigned) -1) {
1721 types += k - 1;
1722 n_struct -= k - 1;
1723 }
de1c301e 1724
1b492614
LP
1725 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
1726 if (r < 0)
1727 return r;
de1c301e 1728
1b492614
LP
1729 types = t + 1;
1730 n_struct = k - 2;
1731 n_array = (unsigned) -1;
de1c301e
LP
1732
1733 break;
1734 }
1735
1736 default:
1737 r = -EINVAL;
1738 }
1739
1740 if (r < 0)
1741 return r;
1742 }
1743
1744 return 0;
1745}
1746
1747int sd_bus_message_append(sd_bus_message *m, const char *types, ...) {
1748 va_list ap;
1749 int r;
1750
1751 if (!m)
1752 return -EINVAL;
1753 if (m->sealed)
1754 return -EPERM;
1755 if (!types)
917b5dc7 1756 return 0;
de1c301e
LP
1757
1758 va_start(ap, types);
917b5dc7 1759 r = bus_message_append_ap(m, types, ap);
de1c301e
LP
1760 va_end(ap);
1761
1762 return r;
1763}
1764
9a17484d
LP
1765static int buffer_peek(const void *p, uint32_t sz, size_t *rindex, size_t align, size_t nbytes, void **r) {
1766 size_t k, start, n;
de1c301e 1767
9a17484d
LP
1768 assert(rindex);
1769 assert(align > 0);
de1c301e 1770
9a17484d
LP
1771 start = ALIGN_TO((size_t) *rindex, align);
1772 n = start + nbytes;
1773
1774 if (n > sz)
1775 return -EBADMSG;
1776
1777 /* Verify that padding is 0 */
1778 for (k = *rindex; k < start; k++)
1779 if (((const uint8_t*) p)[k] != 0)
1780 return -EBADMSG;
1781
1782 if (r)
1783 *r = (uint8_t*) p + start;
1784
1785 *rindex = n;
1786
1787 return 1;
de1c301e
LP
1788}
1789
9a17484d
LP
1790static bool message_end_of_array(sd_bus_message *m, size_t index) {
1791 struct bus_container *c;
de1c301e 1792
9a17484d 1793 assert(m);
de1c301e 1794
9a17484d
LP
1795 c = message_get_container(m);
1796 if (!c->array_size)
1797 return false;
de1c301e 1798
9a17484d 1799 return index >= c->begin + BUS_MESSAGE_BSWAP32(m, *c->array_size);
de1c301e
LP
1800}
1801
9a17484d 1802static int message_peek_body(sd_bus_message *m, size_t *rindex, size_t align, size_t nbytes, void **ret) {
de1c301e 1803 assert(m);
9a17484d
LP
1804 assert(rindex);
1805 assert(align > 0);
de1c301e 1806
9a17484d
LP
1807 if (message_end_of_array(m, *rindex))
1808 return 0;
de1c301e 1809
9a17484d
LP
1810 return buffer_peek(m->body, BUS_MESSAGE_BODY_SIZE(m), rindex, align, nbytes, ret);
1811}
de1c301e 1812
ac89bf1d 1813static bool validate_nul(const char *s, size_t l) {
de1c301e 1814
9a17484d
LP
1815 /* Check for NUL chars in the string */
1816 if (memchr(s, 0, l))
1817 return false;
de1c301e 1818
9a17484d
LP
1819 /* Check for NUL termination */
1820 if (s[l] != 0)
1821 return false;
de1c301e 1822
ac89bf1d
LP
1823 return true;
1824}
1825
1826static bool validate_string(const char *s, size_t l) {
1827
1828 if (!validate_nul(s, l))
1829 return false;
1830
9a17484d
LP
1831 /* Check if valid UTF8 */
1832 if (!utf8_is_valid(s))
1833 return false;
1834
1835 return true;
de1c301e
LP
1836}
1837
9a17484d 1838static bool validate_signature(const char *s, size_t l) {
de1c301e 1839
ac89bf1d 1840 if (!validate_nul(s, l))
9a17484d 1841 return false;
de1c301e 1842
9a17484d
LP
1843 /* Check if valid signature */
1844 if (!signature_is_valid(s, true))
1845 return false;
1846
1847 return true;
1848}
1849
ac89bf1d
LP
1850static bool validate_object_path(const char *s, size_t l) {
1851
1852 if (!validate_nul(s, l))
1853 return false;
1854
1855 if (!object_path_is_valid(s))
1856 return false;
1857
1858 return true;
1859}
1860
9a17484d
LP
1861int sd_bus_message_read_basic(sd_bus_message *m, char type, void *p) {
1862 struct bus_container *c;
1863 int r;
1864 void *q;
1865
1866 if (!m)
1867 return -EINVAL;
1868 if (!m->sealed)
de1c301e 1869 return -EPERM;
9a17484d
LP
1870 if (!bus_type_is_basic(type))
1871 return -EINVAL;
2c93b4ef
LP
1872 if (!p)
1873 return -EINVAL;
de1c301e 1874
9a17484d 1875 c = message_get_container(m);
de1c301e 1876
9a17484d
LP
1877 if (!c->signature || c->signature[c->index] == 0)
1878 return 0;
1879
1880 if (c->signature[c->index] != type)
1881 return -ENXIO;
1882
1883 switch (type) {
1884
1885 case SD_BUS_TYPE_STRING:
1886 case SD_BUS_TYPE_OBJECT_PATH: {
1887 uint32_t l;
1888 size_t rindex;
1889
1890 rindex = m->rindex;
1891 r = message_peek_body(m, &rindex, 4, 4, &q);
1892 if (r <= 0)
1893 return r;
1894
1895 l = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
1896 r = message_peek_body(m, &rindex, 1, l+1, &q);
de1c301e
LP
1897 if (r < 0)
1898 return r;
9a17484d
LP
1899 if (r == 0)
1900 return -EBADMSG;
1901
ac89bf1d
LP
1902 if (type == SD_BUS_TYPE_OBJECT_PATH) {
1903 if (!validate_object_path(q, l))
1904 return -EBADMSG;
1905 } else {
1906 if (!validate_string(q, l))
1907 return -EBADMSG;
1908 }
9a17484d
LP
1909
1910 m->rindex = rindex;
1911 *(const char**) p = q;
1912 break;
de1c301e
LP
1913 }
1914
9a17484d
LP
1915 case SD_BUS_TYPE_SIGNATURE: {
1916 uint8_t l;
1917 size_t rindex;
1918
1919 rindex = m->rindex;
1920 r = message_peek_body(m, &rindex, 1, 1, &q);
1921 if (r <= 0)
1922 return r;
1923
1924 l = *(uint8_t*) q;
1925 r = message_peek_body(m, &rindex, 1, l+1, &q);
de1c301e
LP
1926 if (r < 0)
1927 return r;
9a17484d
LP
1928 if (r == 0)
1929 return -EBADMSG;
1930
1931 if (!validate_signature(q, l))
1932 return -EBADMSG;
1933
1934 m->rindex = rindex;
1935 *(const char**) p = q;
1936 break;
de1c301e
LP
1937 }
1938
9a17484d 1939 default: {
27f6e5c7
ZJS
1940 ssize_t sz, align;
1941 size_t rindex;
de1c301e 1942
9a17484d
LP
1943 align = bus_type_get_alignment(type);
1944 sz = bus_type_get_size(type);
27f6e5c7 1945 assert(align > 0 && sz > 0);
de1c301e 1946
2c93b4ef
LP
1947 rindex = m->rindex;
1948 r = message_peek_body(m, &rindex, align, sz, &q);
9a17484d
LP
1949 if (r <= 0)
1950 return r;
1951
1952 switch (type) {
1953
1954 case SD_BUS_TYPE_BYTE:
1955 *(uint8_t*) p = *(uint8_t*) q;
1956 break;
1957
1958 case SD_BUS_TYPE_BOOLEAN:
1959 *(int*) p = !!*(uint32_t*) q;
1960 break;
1961
1962 case SD_BUS_TYPE_INT16:
1963 case SD_BUS_TYPE_UINT16:
1964 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
1965 break;
1966
1967 case SD_BUS_TYPE_INT32:
1968 case SD_BUS_TYPE_UINT32:
1969 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
1970 break;
1971
1972 case SD_BUS_TYPE_INT64:
1973 case SD_BUS_TYPE_UINT64:
1974 case SD_BUS_TYPE_DOUBLE:
1975 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
1976 break;
1977
2c93b4ef 1978 case SD_BUS_TYPE_UNIX_FD: {
2c93b4ef
LP
1979 uint32_t j;
1980
1981 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
1982 if (j >= m->n_fds)
1983 return -EBADMSG;
1984
1ef2af5a 1985 *(int*) p = m->fds[j];
2c93b4ef
LP
1986 break;
1987 }
1988
9a17484d
LP
1989 default:
1990 assert_not_reached("Unknown basic type...");
1991 }
1992
2c93b4ef
LP
1993 m->rindex = rindex;
1994
9a17484d
LP
1995 break;
1996 }
1997 }
1998
1999 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2000 c->index++;
2001
2002 return 1;
de1c301e
LP
2003}
2004
9a17484d
LP
2005static int bus_message_enter_array(
2006 sd_bus_message *m,
2007 struct bus_container *c,
2008 const char *contents,
2009 uint32_t **array_size) {
2010
2011 size_t rindex;
2012 void *q;
2013 int r, alignment;
2014
2015 assert(m);
2016 assert(c);
2017 assert(contents);
2018 assert(array_size);
2019
2020 if (!signature_is_single(contents))
de1c301e 2021 return -EINVAL;
9a17484d
LP
2022
2023 alignment = bus_type_get_alignment(contents[0]);
2024 if (alignment < 0)
2025 return alignment;
2026
2027 if (!c->signature || c->signature[c->index] == 0)
2028 return 0;
2029
2030 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
2031 return -ENXIO;
2032
2033 if (!startswith(c->signature + c->index + 1, contents))
2034 return -ENXIO;
2035
2036 rindex = m->rindex;
2037 r = message_peek_body(m, &rindex, 4, 4, &q);
2038 if (r <= 0)
2039 return r;
2040
ac89bf1d 2041 if (BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q) > BUS_ARRAY_MAX_SIZE)
80a46c73 2042 return -EBADMSG;
9a17484d
LP
2043
2044 r = message_peek_body(m, &rindex, alignment, 0, NULL);
2045 if (r < 0)
2046 return r;
2047 if (r == 0)
2048 return -EBADMSG;
2049
2050 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2051 c->index += 1 + strlen(contents);
2052
2053 m->rindex = rindex;
2054
2055 *array_size = (uint32_t*) q;
2056
2057 return 1;
2058}
2059
2060static int bus_message_enter_variant(
2061 sd_bus_message *m,
2062 struct bus_container *c,
2063 const char *contents) {
2064
2065 size_t rindex;
2066 uint8_t l;
2067 void *q;
2068 int r;
2069
2070 assert(m);
2071 assert(c);
2072 assert(contents);
2073
2074 if (!signature_is_single(contents))
de1c301e 2075 return -EINVAL;
de1c301e 2076
9a17484d
LP
2077 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
2078 return -EINVAL;
2079
2080 if (!c->signature || c->signature[c->index] == 0)
2081 return 0;
2082
2083 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
2084 return -ENXIO;
2085
2086 rindex = m->rindex;
2087 r = message_peek_body(m, &rindex, 1, 1, &q);
2088 if (r <= 0)
2089 return r;
2090
2091 l = *(uint8_t*) q;
2092 r = message_peek_body(m, &rindex, 1, l+1, &q);
2093 if (r < 0)
2094 return r;
2095 if (r == 0)
2096 return -EBADMSG;
2097
2098 if (!validate_signature(q, l))
2099 return -EBADMSG;
2100
2101 if (!streq(q, contents))
2102 return -ENXIO;
2103
2104 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2105 c->index++;
2106
2107 m->rindex = rindex;
2108
2109 return 1;
de1c301e
LP
2110}
2111
9a17484d
LP
2112static int bus_message_enter_struct(
2113 sd_bus_message *m,
2114 struct bus_container *c,
2115 const char *contents) {
2116
2117 size_t l;
2118 int r;
2119
2120 assert(m);
2121 assert(c);
2122 assert(contents);
2123
2124 if (!signature_is_valid(contents, false))
2125 return -EINVAL;
2126
2127 if (!c->signature || c->signature[c->index] == 0)
2128 return 0;
2129
2130 l = strlen(contents);
2131
2132 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
2133 !startswith(c->signature + c->index + 1, contents) ||
2134 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
2135 return -ENXIO;
2136
2137 r = message_peek_body(m, &m->rindex, 8, 0, NULL);
2138 if (r <= 0)
2139 return r;
2140
2141 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2142 c->index += 1 + l + 1;
2143
2144 return 1;
2145}
2146
2147static int bus_message_enter_dict_entry(
2148 sd_bus_message *m,
2149 struct bus_container *c,
2150 const char *contents) {
2151
2152 size_t l;
2153 int r;
2154
2155 assert(m);
2156 assert(c);
2157 assert(contents);
2158
2159 if (!signature_is_pair(contents))
2160 return -EINVAL;
2161
2162 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2163 return -ENXIO;
2164
2165 if (!c->signature || c->signature[c->index] == 0)
2166 return 0;
2167
2168 l = strlen(contents);
2169
2170 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
2171 !startswith(c->signature + c->index + 1, contents) ||
2172 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
2173 return -ENXIO;
2174
2175 r = message_peek_body(m, &m->rindex, 8, 0, NULL);
2176 if (r <= 0)
2177 return r;
2178
2179 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2180 c->index += 1 + l + 1;
2181
2182 return 1;
2183}
2184
2185int sd_bus_message_enter_container(sd_bus_message *m, char type, const char *contents) {
2186 struct bus_container *c, *w;
2187 uint32_t *array_size = NULL;
2188 char *signature;
2189 int r;
2190
2191 if (!m)
2192 return -EINVAL;
2193 if (!m->sealed)
2194 return -EPERM;
2195 if (!contents)
2196 return -EINVAL;
2197
ed205a6b
LP
2198 /*
2199 * We enforce a global limit on container depth, that is much
2200 * higher than the 32 structs and 32 arrays the specification
2201 * mandates. This is simpler to implement for us, and we need
2202 * this only to ensure our container array doesn't grow
2203 * without bounds. We are happy to return any data from a
2204 * message as long as the data itself is valid, even if the
2205 * overall message might be not.
2206 *
2207 * Note that the message signature is validated when
2208 * parsing the headers, and that validation does check the
2209 * 32/32 limit.
2210 *
2211 * Note that the specification defines no limits on the depth
2212 * of stacked variants, but we do.
2213 */
2214 if (m->n_containers >= BUS_CONTAINER_DEPTH)
2215 return -EBADMSG;
2216
9a17484d
LP
2217 w = realloc(m->containers, sizeof(struct bus_container) * (m->n_containers + 1));
2218 if (!w)
2219 return -ENOMEM;
2220 m->containers = w;
2221
2222 c = message_get_container(m);
2223
2224 if (!c->signature || c->signature[c->index] == 0)
2225 return 0;
2226
2227 signature = strdup(contents);
2228 if (!signature)
2229 return -ENOMEM;
2230
2231 if (type == SD_BUS_TYPE_ARRAY)
2232 r = bus_message_enter_array(m, c, contents, &array_size);
2233 else if (type == SD_BUS_TYPE_VARIANT)
2234 r = bus_message_enter_variant(m, c, contents);
2235 else if (type == SD_BUS_TYPE_STRUCT)
2236 r = bus_message_enter_struct(m, c, contents);
2237 else if (type == SD_BUS_TYPE_DICT_ENTRY)
2238 r = bus_message_enter_dict_entry(m, c, contents);
2239 else
2240 r = -EINVAL;
2241
2242 if (r <= 0) {
2243 free(signature);
2244 return r;
2245 }
2246
2247 /* OK, let's fill it in */
2248 w += m->n_containers++;
2249 w->enclosing = type;
2250 w->signature = signature;
2251 w->index = 0;
2252 w->array_size = array_size;
2253 w->begin = m->rindex;
2254
2255 return 1;
2256}
2257
2258int sd_bus_message_exit_container(sd_bus_message *m) {
2259 struct bus_container *c;
2260
2261 if (!m)
2262 return -EINVAL;
2263 if (!m->sealed)
2264 return -EPERM;
2265 if (m->n_containers <= 0)
2266 return -EINVAL;
2267
2268 c = message_get_container(m);
2269 if (c->enclosing == SD_BUS_TYPE_ARRAY) {
2270 uint32_t l;
2271
2272 l = BUS_MESSAGE_BSWAP32(m, *c->array_size);
2273 if (c->begin + l != m->rindex)
2274 return -EBUSY;
2275
2276 } else {
2277 if (c->signature && c->signature[c->index] != 0)
2278 return -EINVAL;
2279 }
2280
2281 free(c->signature);
2282 m->n_containers--;
2283
2284 return 1;
2285}
2286
2287int sd_bus_message_peek_type(sd_bus_message *m, char *type, const char **contents) {
2288 struct bus_container *c;
2289 int r;
2290
2291 if (!m)
2292 return -EINVAL;
2293 if (!m->sealed)
2294 return -EPERM;
2295
2296 c = message_get_container(m);
2297
2298 if (!c->signature || c->signature[c->index] == 0)
2299 goto eof;
2300
2301 if (message_end_of_array(m, m->rindex))
2302 goto eof;
2303
2304 if (bus_type_is_basic(c->signature[c->index])) {
2305 if (contents)
2306 *contents = NULL;
2307 if (type)
2308 *type = c->signature[c->index];
2309 return 1;
2310 }
2311
2312 if (c->signature[c->index] == SD_BUS_TYPE_ARRAY) {
2313
2314 if (contents) {
2315 size_t l;
2316 char *sig;
2317
2318 r = signature_element_length(c->signature+c->index+1, &l);
2319 if (r < 0)
2320 return r;
2321
80a46c73
LP
2322 assert(l >= 1);
2323
9a17484d
LP
2324 sig = strndup(c->signature + c->index + 1, l);
2325 if (!sig)
2326 return -ENOMEM;
2327
2328 free(m->peeked_signature);
2329 m->peeked_signature = sig;
2330
2331 *contents = sig;
2332 }
2333
2334 if (type)
2335 *type = SD_BUS_TYPE_ARRAY;
2336
2337 return 1;
2338 }
2339
2340 if (c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ||
2341 c->signature[c->index] == SD_BUS_TYPE_DICT_ENTRY_BEGIN) {
2342
2343 if (contents) {
2344 size_t l;
2345 char *sig;
2346
2347 r = signature_element_length(c->signature+c->index, &l);
2348 if (r < 0)
2349 return r;
2350
2351 assert(l >= 2);
2352 sig = strndup(c->signature + c->index + 1, l - 2);
2353 if (!sig)
2354 return -ENOMEM;
2355
2356 free(m->peeked_signature);
2357 m->peeked_signature = sig;
2358
2359 *contents = sig;
2360 }
2361
2362 if (type)
2363 *type = c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY;
2364
2365 return 1;
2366 }
2367
2368 if (c->signature[c->index] == SD_BUS_TYPE_VARIANT) {
2369 if (contents) {
2370 size_t rindex, l;
2371 void *q;
2372
2373 rindex = m->rindex;
2374 r = message_peek_body(m, &rindex, 1, 1, &q);
2375 if (r < 0)
2376 return r;
2377 if (r == 0)
2378 goto eof;
2379
2380 l = *(uint8_t*) q;
2381 r = message_peek_body(m, &rindex, 1, l+1, &q);
2382 if (r < 0)
2383 return r;
2384 if (r == 0)
2385 return -EBADMSG;
2386
2387 if (!validate_signature(q, l))
2388 return -EBADMSG;
2389
2390 *contents = q;
2391 }
2392
2393 if (type)
2394 *type = SD_BUS_TYPE_VARIANT;
2395
2396 return 1;
2397 }
2398
2399 return -EINVAL;
2400
2401eof:
2402 if (type)
2403 *type = c->enclosing;
2404 if (contents)
2405 *contents = NULL;
2406 return 0;
2407}
2408
89ffcd2a 2409int sd_bus_message_rewind(sd_bus_message *m, int complete) {
9a17484d
LP
2410 struct bus_container *c;
2411
2412 if (!m)
2413 return -EINVAL;
2414 if (!m->sealed)
2415 return -EPERM;
2416
2417 if (complete) {
2418 reset_containers(m);
2419 m->rindex = 0;
2420 m->root_container.index = 0;
2421
2422 c = message_get_container(m);
2423 } else {
2424 c = message_get_container(m);
2425
2426 c->index = 0;
2427 m->rindex = c->begin;
2428 }
2429
2430 return !isempty(c->signature);
2431}
1b492614
LP
2432static int message_read_ap(
2433 sd_bus_message *m,
2434 const char *types,
2435 va_list ap) {
9a17484d 2436
fe1d424d
LP
2437 unsigned n_array, n_struct;
2438 TypeStack stack[BUS_CONTAINER_DEPTH];
2439 unsigned stack_ptr = 0;
9a17484d
LP
2440 int r;
2441
2442 assert(m);
1b492614
LP
2443
2444 if (!types)
2445 return 0;
9a17484d 2446
fe1d424d
LP
2447 /* Ideally, we'd just call ourselves recursively on every
2448 * complex type. However, the state of a va_list that is
2449 * passed to a function is undefined after that function
2450 * returns. This means we need to docode the va_list linearly
2451 * in a single stackframe. We hence implement our own
2452 * home-grown stack in an array. */
2453
2454 n_array = (unsigned) -1;
2455 n_struct = strlen(types);
2456
2457 for (;;) {
2458 const char *t;
2459
1b492614 2460 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
fe1d424d
LP
2461 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
2462 if (r < 0)
2463 return r;
2464 if (r == 0)
2465 break;
2466
2467 r = sd_bus_message_exit_container(m);
2468 if (r < 0)
2469 return r;
2470
2471 continue;
2472 }
2473
2474 t = types;
2475 if (n_array != (unsigned) -1)
2476 n_array --;
2477 else {
2478 types ++;
2479 n_struct--;
2480 }
2481
9a17484d
LP
2482 switch (*t) {
2483
2484 case SD_BUS_TYPE_BYTE:
2485 case SD_BUS_TYPE_BOOLEAN:
2486 case SD_BUS_TYPE_INT16:
2487 case SD_BUS_TYPE_UINT16:
2488 case SD_BUS_TYPE_INT32:
2489 case SD_BUS_TYPE_UINT32:
2490 case SD_BUS_TYPE_INT64:
2491 case SD_BUS_TYPE_UINT64:
2492 case SD_BUS_TYPE_DOUBLE:
2493 case SD_BUS_TYPE_STRING:
2494 case SD_BUS_TYPE_OBJECT_PATH:
2c93b4ef
LP
2495 case SD_BUS_TYPE_SIGNATURE:
2496 case SD_BUS_TYPE_UNIX_FD: {
9a17484d
LP
2497 void *p;
2498
2499 p = va_arg(ap, void*);
2500 r = sd_bus_message_read_basic(m, *t, p);
fe1d424d
LP
2501 if (r < 0)
2502 return r;
2503 if (r == 0)
2504 return -ENXIO;
2505
9a17484d
LP
2506 break;
2507 }
2508
2509 case SD_BUS_TYPE_ARRAY: {
2510 size_t k;
2511
2512 r = signature_element_length(t + 1, &k);
2513 if (r < 0)
2514 return r;
2515
2516 {
9a17484d 2517 char s[k + 1];
9a17484d
LP
2518 memcpy(s, t + 1, k);
2519 s[k] = 0;
9a17484d
LP
2520
2521 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
2522 if (r < 0)
2523 return r;
2524 if (r == 0)
2525 return -ENXIO;
fe1d424d 2526 }
9a17484d 2527
fe1d424d
LP
2528 if (n_array == (unsigned) -1) {
2529 types += k;
2530 n_struct -= k;
9a17484d
LP
2531 }
2532
fe1d424d
LP
2533 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2534 if (r < 0)
2535 return r;
2536
2537 types = t + 1;
2538 n_struct = k;
2539 n_array = va_arg(ap, unsigned);
2540
9a17484d
LP
2541 break;
2542 }
2543
2544 case SD_BUS_TYPE_VARIANT: {
2545 const char *s;
2546
2547 s = va_arg(ap, const char *);
2548 if (!s)
2549 return -EINVAL;
2550
2551 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, s);
2552 if (r < 0)
2553 return r;
2554 if (r == 0)
2555 return -ENXIO;
2556
fe1d424d 2557 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
9a17484d
LP
2558 if (r < 0)
2559 return r;
9a17484d 2560
fe1d424d
LP
2561 types = s;
2562 n_struct = strlen(s);
2563 n_array = (unsigned) -1;
2564
9a17484d
LP
2565 break;
2566 }
2567
2568 case SD_BUS_TYPE_STRUCT_BEGIN:
2569 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
2570 size_t k;
2571
2572 r = signature_element_length(t, &k);
2573 if (r < 0)
2574 return r;
2575
2576 {
2577 char s[k - 1];
2578 memcpy(s, t + 1, k - 2);
2579 s[k - 2] = 0;
2580
2581 r = sd_bus_message_enter_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
2582 if (r < 0)
2583 return r;
2584 if (r == 0)
2585 return -ENXIO;
fe1d424d 2586 }
9a17484d 2587
fe1d424d
LP
2588 if (n_array == (unsigned) -1) {
2589 types += k - 1;
2590 n_struct -= k - 1;
2591 }
9a17484d 2592
fe1d424d
LP
2593 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2594 if (r < 0)
2595 return r;
9a17484d 2596
fe1d424d
LP
2597 types = t + 1;
2598 n_struct = k - 2;
2599 n_array = (unsigned) -1;
9a17484d
LP
2600
2601 break;
2602 }
2603
2604 default:
fe1d424d 2605 return -EINVAL;
9a17484d 2606 }
9a17484d
LP
2607 }
2608
2609 return 1;
2610}
2611
2612int sd_bus_message_read(sd_bus_message *m, const char *types, ...) {
2613 va_list ap;
2614 int r;
2615
2616 if (!m)
2617 return -EINVAL;
2618 if (!m->sealed)
2619 return -EPERM;
2620 if (!types)
2621 return -EINVAL;
2622
2623 va_start(ap, types);
2624 r = message_read_ap(m, types, ap);
2625 va_end(ap);
2626
2627 return r;
2628}
2629
80a46c73
LP
2630static int message_peek_fields(
2631 sd_bus_message *m,
2632 size_t *rindex,
2633 size_t align,
2634 size_t nbytes,
2635 void **ret) {
2636
2637 assert(m);
2638 assert(rindex);
2639 assert(align > 0);
2640
2641 return buffer_peek(m->fields, BUS_MESSAGE_FIELDS_SIZE(m), rindex, align, nbytes, ret);
2642}
2643
9f26c90c
LP
2644static int message_peek_field_uint32(
2645 sd_bus_message *m,
2646 size_t *ri,
2647 uint32_t *ret) {
2648
2649 int r;
2650 void *q;
2651
2652 assert(m);
2653 assert(ri);
2654
2655 r = message_peek_fields(m, ri, 4, 4, &q);
2656 if (r < 0)
2657 return r;
2658
2659 if (ret)
2660 *ret = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
2661
2662 return 0;
2663}
2664
80a46c73
LP
2665static int message_peek_field_string(
2666 sd_bus_message *m,
6693860f 2667 bool (*validate)(const char *p),
80a46c73
LP
2668 size_t *ri,
2669 const char **ret) {
2670
9f26c90c 2671 uint32_t l;
80a46c73
LP
2672 int r;
2673 void *q;
2674
9a17484d 2675 assert(m);
80a46c73
LP
2676 assert(ri);
2677
9f26c90c 2678 r = message_peek_field_uint32(m, ri, &l);
80a46c73
LP
2679 if (r < 0)
2680 return r;
2681
80a46c73
LP
2682 r = message_peek_fields(m, ri, 1, l+1, &q);
2683 if (r < 0)
2684 return r;
9a17484d 2685
6693860f
LP
2686 if (validate) {
2687 if (!validate_nul(q, l))
2688 return -EBADMSG;
2689
2690 if (!validate(q))
ac89bf1d
LP
2691 return -EBADMSG;
2692 } else {
2693 if (!validate_string(q, l))
2694 return -EBADMSG;
2695 }
80a46c73
LP
2696
2697 if (ret)
2698 *ret = q;
2699
2700 return 0;
2701}
2702
2703static int message_peek_field_signature(
2704 sd_bus_message *m,
2705 size_t *ri,
2706 const char **ret) {
2707
2708 size_t l;
2709 int r;
2710 void *q;
2711
2712 assert(m);
2713 assert(ri);
2714
2715 r = message_peek_fields(m, ri, 1, 1, &q);
2716 if (r < 0)
2717 return r;
2718
2719 l = *(uint8_t*) q;
2720 r = message_peek_fields(m, ri, 1, l+1, &q);
2721 if (r < 0)
2722 return r;
2723
2724 if (!validate_signature(q, l))
2725 return -EBADMSG;
2726
2727 if (ret)
2728 *ret = q;
2729
2730 return 0;
2731}
2732
80a46c73
LP
2733static int message_skip_fields(
2734 sd_bus_message *m,
2735 size_t *ri,
2736 uint32_t array_size,
2737 const char **signature) {
2738
2739 size_t original_index;
2740 int r;
2741
2742 assert(m);
2743 assert(ri);
2744 assert(signature);
2745
2746 original_index = *ri;
2747
2748 for (;;) {
2749 char t;
80a46c73
LP
2750 size_t l;
2751
2752 if (array_size != (uint32_t) -1 &&
2753 array_size <= *ri - original_index)
2754 return 0;
2755
2756 t = **signature;
2757 if (!t)
2758 return 0;
2759
6693860f
LP
2760 if (t == SD_BUS_TYPE_STRING) {
2761
2762 r = message_peek_field_string(m, NULL, ri, NULL);
2763 if (r < 0)
2764 return r;
2765
2766 (*signature)++;
2767
2768 } else if (t == SD_BUS_TYPE_OBJECT_PATH) {
80a46c73 2769
6693860f 2770 r = message_peek_field_string(m, object_path_is_valid, ri, NULL);
80a46c73
LP
2771 if (r < 0)
2772 return r;
2773
2774 (*signature)++;
2775
2776 } else if (t == SD_BUS_TYPE_SIGNATURE) {
2777
2778 r = message_peek_field_signature(m, ri, NULL);
2779 if (r < 0)
2780 return r;
2781
2782 (*signature)++;
2783
2784 } else if (bus_type_is_basic(t)) {
27f6e5c7 2785 ssize_t align, k;
80a46c73 2786
c66a2e0c
TG
2787 align = bus_type_get_alignment(t);
2788 k = bus_type_get_size(t);
27f6e5c7 2789 assert(align > 0 && k > 0);
80a46c73
LP
2790
2791 r = message_peek_fields(m, ri, align, k, NULL);
2792 if (r < 0)
2793 return r;
9a17484d 2794
80a46c73
LP
2795 (*signature)++;
2796
2797 } else if (t == SD_BUS_TYPE_ARRAY) {
2798
2799 r = signature_element_length(*signature+1, &l);
2800 if (r < 0)
2801 return r;
2802
2803 assert(l >= 1);
2804 {
2805 char sig[l-1], *s;
9f26c90c 2806 uint32_t nas;
80a46c73
LP
2807 int alignment;
2808
2809 strncpy(sig, *signature + 1, l-1);
2810 s = sig;
2811
2812 alignment = bus_type_get_alignment(sig[0]);
2813 if (alignment < 0)
2814 return alignment;
2815
9f26c90c 2816 r = message_peek_field_uint32(m, ri, &nas);
80a46c73
LP
2817 if (r < 0)
2818 return r;
ac89bf1d 2819 if (nas > BUS_ARRAY_MAX_SIZE)
80a46c73
LP
2820 return -EBADMSG;
2821
2822 r = message_peek_fields(m, ri, alignment, 0, NULL);
2823 if (r < 0)
2824 return r;
2825
2826 r = message_skip_fields(m, ri, nas, (const char**) &s);
2827 if (r < 0)
2828 return r;
2829 }
2830
2831 (*signature) += 1 + l;
2832
2833 } else if (t == SD_BUS_TYPE_VARIANT) {
2834 const char *s;
2835
2836 r = message_peek_field_signature(m, ri, &s);
2837 if (r < 0)
2838 return r;
2839
2840 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
2841 if (r < 0)
2842 return r;
2843
2844 (*signature)++;
2845
2846 } else if (t == SD_BUS_TYPE_STRUCT ||
2847 t == SD_BUS_TYPE_DICT_ENTRY) {
2848
2849 r = signature_element_length(*signature, &l);
2850 if (r < 0)
2851 return r;
2852
2853 assert(l >= 2);
2854 {
2855 char sig[l-1], *s;
2856 strncpy(sig, *signature + 1, l-1);
2857 s = sig;
2858
2859 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
2860 if (r < 0)
2861 return r;
2862 }
2863
2864 *signature += l;
2865 } else
2866 return -EINVAL;
2867 }
2868}
2869
6629161f 2870int bus_message_parse_fields(sd_bus_message *m) {
80a46c73
LP
2871 size_t ri;
2872 int r;
2c93b4ef 2873 uint32_t unix_fds = 0;
80a46c73
LP
2874
2875 assert(m);
2876
2877 for (ri = 0; ri < BUS_MESSAGE_FIELDS_SIZE(m); ) {
2878 const char *signature;
2879 uint8_t *header;
2880
2881 r = message_peek_fields(m, &ri, 8, 1, (void**) &header);
2882 if (r < 0)
2883 return r;
2884
2885 r = message_peek_field_signature(m, &ri, &signature);
2886 if (r < 0)
2887 return r;
2888
2889 switch (*header) {
2890 case _SD_BUS_MESSAGE_HEADER_INVALID:
2891 return -EBADMSG;
2892
2893 case SD_BUS_MESSAGE_HEADER_PATH:
2c93b4ef
LP
2894
2895 if (m->path)
2896 return -EBADMSG;
2897
80a46c73
LP
2898 if (!streq(signature, "o"))
2899 return -EBADMSG;
2900
6693860f 2901 r = message_peek_field_string(m, object_path_is_valid, &ri, &m->path);
80a46c73
LP
2902 break;
2903
2904 case SD_BUS_MESSAGE_HEADER_INTERFACE:
2c93b4ef
LP
2905
2906 if (m->interface)
2907 return -EBADMSG;
2908
80a46c73
LP
2909 if (!streq(signature, "s"))
2910 return -EBADMSG;
2911
6693860f 2912 r = message_peek_field_string(m, interface_name_is_valid, &ri, &m->interface);
80a46c73
LP
2913 break;
2914
2915 case SD_BUS_MESSAGE_HEADER_MEMBER:
2c93b4ef
LP
2916
2917 if (m->member)
2918 return -EBADMSG;
2919
80a46c73
LP
2920 if (!streq(signature, "s"))
2921 return -EBADMSG;
2922
6693860f 2923 r = message_peek_field_string(m, member_name_is_valid, &ri, &m->member);
80a46c73
LP
2924 break;
2925
2926 case SD_BUS_MESSAGE_HEADER_ERROR_NAME:
2c93b4ef
LP
2927
2928 if (m->error.name)
2929 return -EBADMSG;
2930
80a46c73
LP
2931 if (!streq(signature, "s"))
2932 return -EBADMSG;
2933
6693860f 2934 r = message_peek_field_string(m, error_name_is_valid, &ri, &m->error.name);
80a46c73
LP
2935 break;
2936
2937 case SD_BUS_MESSAGE_HEADER_DESTINATION:
2c93b4ef
LP
2938
2939 if (m->destination)
2940 return -EBADMSG;
2941
80a46c73
LP
2942 if (!streq(signature, "s"))
2943 return -EBADMSG;
2944
6693860f 2945 r = message_peek_field_string(m, service_name_is_valid, &ri, &m->destination);
80a46c73
LP
2946 break;
2947
2948 case SD_BUS_MESSAGE_HEADER_SENDER:
2c93b4ef
LP
2949
2950 if (m->sender)
2951 return -EBADMSG;
2952
80a46c73
LP
2953 if (!streq(signature, "s"))
2954 return -EBADMSG;
2955
6693860f 2956 r = message_peek_field_string(m, service_name_is_valid, &ri, &m->sender);
80a46c73
LP
2957 break;
2958
2959
2960 case SD_BUS_MESSAGE_HEADER_SIGNATURE: {
2961 const char *s;
2962 char *c;
2963
2c93b4ef
LP
2964 if (m->root_container.signature)
2965 return -EBADMSG;
2966
80a46c73
LP
2967 if (!streq(signature, "g"))
2968 return -EBADMSG;
2969
2970 r = message_peek_field_signature(m, &ri, &s);
2971 if (r < 0)
2972 return r;
2973
2974 c = strdup(s);
2975 if (!c)
2976 return -ENOMEM;
2977
2978 free(m->root_container.signature);
2979 m->root_container.signature = c;
80a46c73
LP
2980 break;
2981 }
2982
2983 case SD_BUS_MESSAGE_HEADER_REPLY_SERIAL:
2c93b4ef
LP
2984 if (m->reply_serial != 0)
2985 return -EBADMSG;
2986
80a46c73
LP
2987 if (!streq(signature, "u"))
2988 return -EBADMSG;
2989
2990 r = message_peek_field_uint32(m, &ri, &m->reply_serial);
6693860f
LP
2991 if (r < 0)
2992 return r;
2993
2994 if (m->reply_serial == 0)
2995 return -EBADMSG;
2996
80a46c73
LP
2997 break;
2998
2c93b4ef
LP
2999 case SD_BUS_MESSAGE_HEADER_UNIX_FDS:
3000 if (unix_fds != 0)
3001 return -EBADMSG;
3002
3003 if (!streq(signature, "u"))
3004 return -EBADMSG;
3005
3006 r = message_peek_field_uint32(m, &ri, &unix_fds);
3007 if (r < 0)
3008 return -EBADMSG;
3009
3010 if (unix_fds == 0)
3011 return -EBADMSG;
3012
3013 break;
3014
80a46c73
LP
3015 default:
3016 r = message_skip_fields(m, &ri, (uint32_t) -1, (const char **) &signature);
3017 }
3018
3019 if (r < 0)
3020 return r;
3021 }
3022
2c93b4ef
LP
3023 if (m->n_fds != unix_fds)
3024 return -EBADMSG;
3025
80a46c73
LP
3026 if (isempty(m->root_container.signature) != (BUS_MESSAGE_BODY_SIZE(m) == 0))
3027 return -EBADMSG;
3028
3029 switch (m->header->type) {
3030
3031 case SD_BUS_MESSAGE_TYPE_SIGNAL:
3032 if (!m->path || !m->interface || !m->member)
3033 return -EBADMSG;
3034 break;
3035
3036 case SD_BUS_MESSAGE_TYPE_METHOD_CALL:
3037
3038 if (!m->path || !m->member)
3039 return -EBADMSG;
3040
3041 break;
3042
3043 case SD_BUS_MESSAGE_TYPE_METHOD_RETURN:
3044
3045 if (m->reply_serial == 0)
3046 return -EBADMSG;
3047 break;
3048
3049 case SD_BUS_MESSAGE_TYPE_METHOD_ERROR:
3050
3051 if (m->reply_serial == 0 || !m->error.name)
3052 return -EBADMSG;
3053 break;
3054 }
9a17484d 3055
89ffcd2a
LP
3056 /* Try to read the error message, but if we can't it's a non-issue */
3057 if (m->header->type == SD_BUS_MESSAGE_TYPE_METHOD_ERROR)
3058 sd_bus_message_read(m, "s", &m->error.message);
3059
9a17484d
LP
3060 return 0;
3061}
3062
9a17484d
LP
3063int bus_message_seal(sd_bus_message *m, uint64_t serial) {
3064 int r;
69aec65c 3065 size_t l, a;
9a17484d
LP
3066
3067 assert(m);
3068
3069 if (m->sealed)
3070 return -EPERM;
3071
3072 if (m->n_containers > 0)
3073 return -EBADMSG;
3074
3075 /* If there's a non-trivial signature set, then add it in here */
3076 if (!isempty(m->root_container.signature)) {
80a46c73 3077 r = message_append_field_signature(m, SD_BUS_MESSAGE_HEADER_SIGNATURE, m->root_container.signature, NULL);
9a17484d
LP
3078 if (r < 0)
3079 return r;
3080 }
3081
3082 if (m->n_fds > 0) {
3083 r = message_append_field_uint32(m, SD_BUS_MESSAGE_HEADER_UNIX_FDS, m->n_fds);
3084 if (r < 0)
3085 return r;
3086 }
3087
69aec65c
LP
3088 l = BUS_MESSAGE_FIELDS_SIZE(m);
3089 a = ALIGN8(l) - l;
3090
3091 if (a > 0) {
3092 /* Add padding at the end, since we know the body
3093 * needs to start at an 8 byte alignment. */
3094 void *p;
3095
3096 p = message_extend_fields(m, 1, a);
3097 if (!p)
3098 return -ENOMEM;
3099
3100 memset(p, 0, a);
3101 m->header->fields_size -= a;
3102 }
3103
9a17484d
LP
3104 m->header->serial = serial;
3105 m->sealed = true;
3106
9a17484d
LP
3107 return 0;
3108}
3109
3110int sd_bus_message_set_destination(sd_bus_message *m, const char *destination) {
3111 if (!m)
3112 return -EINVAL;
3113 if (!destination)
3114 return -EINVAL;
3115 if (m->sealed)
3116 return -EPERM;
3117 if (m->destination)
3118 return -EEXIST;
3119
3120 return message_append_field_string(m, SD_BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &m->destination);
3121}
3122
3123int bus_message_dump(sd_bus_message *m) {
d8d3d8a7 3124 const char *u = NULL, *uu = NULL, *s = NULL;
77930f11 3125 char **cmdline = NULL;
9a17484d
LP
3126 unsigned level = 1;
3127 int r;
120f919e
LP
3128 uid_t owner, audit_loginuid;
3129 uint32_t audit_sessionid;
9a17484d
LP
3130
3131 assert(m);
3132
3133 printf("Message %p\n"
3134 "\tn_ref=%u\n"
3135 "\tendian=%c\n"
3136 "\ttype=%i\n"
3137 "\tflags=%u\n"
3138 "\tversion=%u\n"
3139 "\tserial=%u\n"
3140 "\tfields_size=%u\n"
3141 "\tbody_size=%u\n"
3142 "\tpath=%s\n"
3143 "\tinterface=%s\n"
3144 "\tmember=%s\n"
3145 "\tdestination=%s\n"
3146 "\tsender=%s\n"
3147 "\tsignature=%s\n"
3148 "\treply_serial=%u\n"
3149 "\terror.name=%s\n"
3150 "\terror.message=%s\n"
3151 "\tsealed=%s\n",
3152 m,
3153 m->n_ref,
3154 m->header->endian,
3155 m->header->type,
3156 m->header->flags,
3157 m->header->version,
3158 BUS_MESSAGE_SERIAL(m),
3159 BUS_MESSAGE_FIELDS_SIZE(m),
3160 BUS_MESSAGE_BODY_SIZE(m),
3161 strna(m->path),
3162 strna(m->interface),
3163 strna(m->member),
3164 strna(m->destination),
3165 strna(m->sender),
80a46c73 3166 strna(m->root_container.signature),
9a17484d
LP
3167 m->reply_serial,
3168 strna(m->error.name),
3169 strna(m->error.message),
3170 yes_no(m->sealed));
3171
f9be01f3
LP
3172 if (m->pid != 0)
3173 printf("\tpid=%lu\n", (unsigned long) m->pid);
3174 if (m->tid != 0)
3175 printf("\ttid=%lu\n", (unsigned long) m->tid);
3176 if (m->uid_valid)
3177 printf("\tuid=%lu\n", (unsigned long) m->uid);
3178 if (m->gid_valid)
3179 printf("\tgid=%lu\n", (unsigned long) m->gid);
8323bc1f
LP
3180 if (m->pid_starttime != 0)
3181 printf("\tpid_starttime=%llu\n", (unsigned long long) m->pid_starttime);
69aec65c
LP
3182 if (m->monotonic != 0)
3183 printf("\tmonotonic=%llu\n", (unsigned long long) m->monotonic);
3184 if (m->realtime != 0)
3185 printf("\trealtime=%llu\n", (unsigned long long) m->realtime);
3186 if (m->exe)
3187 printf("\texe=[%s]\n", m->exe);
3188 if (m->comm)
3189 printf("\tcomm=[%s]\n", m->comm);
3190 if (m->tid_comm)
3191 printf("\ttid_comm=[%s]\n", m->tid_comm);
3192 if (m->label)
3193 printf("\tlabel=[%s]\n", m->label);
4a875b61
LP
3194 if (m->cgroup)
3195 printf("\tcgroup=[%s]\n", m->cgroup);
f9be01f3 3196
d8d3d8a7
LP
3197 sd_bus_message_get_unit(m, &u);
3198 if (u)
3199 printf("\tunit=[%s]\n", u);
3200 sd_bus_message_get_user_unit(m, &uu);
3201 if (uu)
3202 printf("\tuser_unit=[%s]\n", uu);
3203 sd_bus_message_get_session(m, &s);
3204 if (s)
3205 printf("\tsession=[%s]\n", s);
bc7f3beb
LP
3206 if (sd_bus_message_get_owner_uid(m, &owner) >= 0)
3207 printf("\towner_uid=%lu\n", (unsigned long) owner);
120f919e
LP
3208 if (sd_bus_message_get_audit_loginuid(m, &audit_loginuid) >= 0)
3209 printf("\taudit_loginuid=%lu\n", (unsigned long) audit_loginuid);
3210 if (sd_bus_message_get_audit_sessionid(m, &audit_sessionid) >= 0)
3211 printf("\taudit_sessionid=%lu\n", (unsigned long) audit_sessionid);
d8d3d8a7 3212
102ea8e4
LP
3213 printf("\tCAP_KILL=%i\n", sd_bus_message_has_effective_cap(m, 5));
3214
77930f11
LP
3215 if (sd_bus_message_get_cmdline(m, &cmdline) >= 0) {
3216 char **c;
3217
3218 fputs("\tcmdline=[", stdout);
3219 STRV_FOREACH(c, cmdline) {
3220 if (c != cmdline)
3221 putchar(' ');
3222
3223 fputs(*c, stdout);
3224 }
3225
3226 fputs("]\n", stdout);
3227 }
3228
9a17484d
LP
3229 r = sd_bus_message_rewind(m, true);
3230 if (r < 0) {
3231 log_error("Failed to rewind: %s", strerror(-r));
3232 return r;
3233 }
3234
80a46c73 3235 printf("BEGIN_MESSAGE \"%s\" {\n", strempty(m->root_container.signature));
9a17484d
LP
3236
3237 for(;;) {
3238 _cleanup_free_ char *prefix = NULL;
3239 const char *contents = NULL;
3240 char type;
3241 union {
3242 uint8_t u8;
3243 uint16_t u16;
3244 int16_t s16;
3245 uint32_t u32;
3246 int32_t s32;
3247 uint64_t u64;
3248 int64_t s64;
3249 double d64;
3250 const char *string;
3251 int i;
3252 } basic;
3253
3254 r = sd_bus_message_peek_type(m, &type, &contents);
3255 if (r < 0) {
3256 log_error("Failed to peek type: %s", strerror(-r));
3257 return r;
3258 }
3259 if (r == 0) {
3260 if (level <= 1)
3261 break;
3262
3263 r = sd_bus_message_exit_container(m);
3264 if (r < 0) {
3265 log_error("Failed to exit container: %s", strerror(-r));
3266 return r;
3267 }
3268
3269 level--;
3270
3271 prefix = strrep("\t", level);
3272 if (!prefix)
3273 return log_oom();
3274
3275 if (type == SD_BUS_TYPE_ARRAY)
3276 printf("%s} END_ARRAY \n", prefix);
3277 else if (type == SD_BUS_TYPE_VARIANT)
3278 printf("%s} END_VARIANT\n", prefix);
3279 else if (type == SD_BUS_TYPE_STRUCT)
3280 printf("%s} END_STRUCT\n", prefix);
3281 else if (type == SD_BUS_TYPE_DICT_ENTRY)
3282 printf("%s} END_DICT_ENTRY\n", prefix);
3283
3284 continue;
3285 }
3286
3287 prefix = strrep("\t", level);
3288 if (!prefix)
3289 return log_oom();
3290
3291 if (bus_type_is_container(type) > 0) {
3292 r = sd_bus_message_enter_container(m, type, contents);
3293 if (r < 0) {
3294 log_error("Failed to enter container: %s", strerror(-r));
3295 return r;
3296 }
3297
3298 if (type == SD_BUS_TYPE_ARRAY)
3299 printf("%sBEGIN_ARRAY \"%s\" {\n", prefix, contents);
3300 else if (type == SD_BUS_TYPE_VARIANT)
3301 printf("%sBEGIN_VARIANT \"%s\" {\n", prefix, contents);
3302 else if (type == SD_BUS_TYPE_STRUCT)
3303 printf("%sBEGIN_STRUCT \"%s\" {\n", prefix, contents);
3304 else if (type == SD_BUS_TYPE_DICT_ENTRY)
3305 printf("%sBEGIN_DICT_ENTRY \"%s\" {\n", prefix, contents);
3306
3307 level ++;
3308
3309 continue;
3310 }
3311
3312 r = sd_bus_message_read_basic(m, type, &basic);
3313 if (r < 0) {
3314 log_error("Failed to get basic: %s", strerror(-r));
3315 return r;
3316 }
3317
3318 switch (type) {
3319
3320 case SD_BUS_TYPE_BYTE:
3321 printf("%sBYTE: %u\n", prefix, basic.u8);
3322 break;
3323
3324 case SD_BUS_TYPE_BOOLEAN:
3325 printf("%sBOOLEAN: %s\n", prefix, yes_no(basic.i));
3326 break;
3327
3328 case SD_BUS_TYPE_INT16:
3329 printf("%sINT16: %i\n", prefix, basic.s16);
3330 break;
3331
3332 case SD_BUS_TYPE_UINT16:
3333 printf("%sUINT16: %u\n", prefix, basic.u16);
3334 break;
3335
3336 case SD_BUS_TYPE_INT32:
3337 printf("%sINT32: %i\n", prefix, basic.s32);
3338 break;
3339
3340 case SD_BUS_TYPE_UINT32:
3341 printf("%sUINT32: %u\n", prefix, basic.u32);
3342 break;
3343
3344 case SD_BUS_TYPE_INT64:
3345 printf("%sINT64: %lli\n", prefix, (long long) basic.s64);
3346 break;
3347
3348 case SD_BUS_TYPE_UINT64:
3349 printf("%sUINT64: %llu\n", prefix, (unsigned long long) basic.u64);
3350 break;
3351
3352 case SD_BUS_TYPE_DOUBLE:
3353 printf("%sDOUBLE: %g\n", prefix, basic.d64);
3354 break;
3355
3356 case SD_BUS_TYPE_STRING:
3357 printf("%sSTRING: \"%s\"\n", prefix, basic.string);
3358 break;
3359
3360 case SD_BUS_TYPE_OBJECT_PATH:
3361 printf("%sOBJECT_PATH: \"%s\"\n", prefix, basic.string);
3362 break;
3363
3364 case SD_BUS_TYPE_SIGNATURE:
3365 printf("%sSIGNATURE: \"%s\"\n", prefix, basic.string);
3366 break;
3367
3368 case SD_BUS_TYPE_UNIX_FD:
3369 printf("%sUNIX_FD: %i\n", prefix, basic.i);
3370 break;
3371
3372 default:
3373 assert_not_reached("Unknown basic type.");
3374 }
3375 }
3376
3377 printf("} END_MESSAGE\n");
3378 return 0;
de1c301e
LP
3379}
3380
3381int bus_message_get_blob(sd_bus_message *m, void **buffer, size_t *sz) {
3382 size_t total;
de1c301e
LP
3383 void *p, *e;
3384
3385 assert(m);
3386 assert(buffer);
3387 assert(sz);
3388
6629161f 3389 total = BUS_MESSAGE_SIZE(m);
de1c301e
LP
3390
3391 p = malloc(total);
3392 if (!p)
3393 return -ENOMEM;
3394
2100fa10
LP
3395 e = mempcpy(p, m->header, sizeof(*m->header));
3396
3397 if (m->fields) {
3398 e = mempcpy(e, m->fields, m->header->fields_size);
3399
3400 if (m->header->fields_size % 8 != 0)
3401 e = mempset(e, 0, 8 - (m->header->fields_size % 8));
3402 }
3403
3404 if (m->body)
3405 e = mempcpy(e, m->body, m->header->body_size);
3406
3407 assert(total == (size_t) ((uint8_t*) e - (uint8_t*) p));
de1c301e
LP
3408
3409 *buffer = p;
3410 *sz = total;
3411
3412 return 0;
3413}
89ffcd2a
LP
3414
3415int bus_message_read_strv_extend(sd_bus_message *m, char ***l) {
3416 int r;
3417
3418 assert(m);
3419 assert(l);
3420
3421 r = sd_bus_message_enter_container(m, 'a', "s");
3422 if (r < 0)
3423 return r;
3424
3425 for (;;) {
3426 const char *s;
3427
3428 r = sd_bus_message_read_basic(m, 's', &s);
3429 if (r < 0)
3430 return r;
3431 if (r == 0)
3432 break;
3433
3434 r = strv_extend(l, s);
3435 if (r < 0)
3436 return r;
3437 }
3438
3439 r = sd_bus_message_exit_container(m);
3440 if (r < 0)
3441 return r;
3442
3443 return 0;
3444}
392d5b37
LP
3445
3446const char* bus_message_get_arg(sd_bus_message *m, unsigned i) {
3447 int r;
42c5aaf3
LP
3448 const char *t = NULL;
3449 unsigned j;
392d5b37
LP
3450
3451 assert(m);
3452
3453 r = sd_bus_message_rewind(m, true);
3454 if (r < 0)
3455 return NULL;
3456
42c5aaf3
LP
3457 for (j = 0; j <= i; j++) {
3458 char type;
3459
392d5b37
LP
3460 r = sd_bus_message_peek_type(m, &type, NULL);
3461 if (r < 0)
3462 return NULL;
3463
3464 if (type != SD_BUS_TYPE_STRING &&
3465 type != SD_BUS_TYPE_OBJECT_PATH &&
3466 type != SD_BUS_TYPE_SIGNATURE)
3467 return NULL;
3468
3469 r = sd_bus_message_read_basic(m, type, &t);
3470 if (r < 0)
3471 return NULL;
392d5b37
LP
3472 }
3473
392d5b37
LP
3474 return t;
3475}
2100fa10 3476
6629161f
LP
3477int bus_header_size(struct bus_header *h, size_t *sum) {
3478 size_t fs, bs;
3479
3480 assert(h);
3481 assert(sum);
3482
3483 if (h->endian == SD_BUS_NATIVE_ENDIAN) {
3484 fs = h->fields_size;
3485 bs = h->body_size;
3486 } else if (h->endian == SD_BUS_REVERSE_ENDIAN) {
3487 fs = bswap_32(h->fields_size);
3488 bs = bswap_32(h->body_size);
3489 } else
3490 return -EBADMSG;
2100fa10 3491
6629161f
LP
3492 *sum = sizeof(struct bus_header) + ALIGN8(fs) + bs;
3493 return 0;
2100fa10 3494}