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