]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/libsystemd/sd-bus/bus-message.c
util-lib: split our string related calls from util.[ch] into its own file string...
[thirdparty/systemd.git] / src / libsystemd / sd-bus / bus-message.c
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>
23 #include <fcntl.h>
24 #include <sys/mman.h>
25
26 #include "sd-bus.h"
27
28 #include "bus-gvariant.h"
29 #include "bus-internal.h"
30 #include "bus-signature.h"
31 #include "bus-type.h"
32 #include "bus-util.h"
33 #include "memfd-util.h"
34 #include "string-util.h"
35 #include "strv.h"
36 #include "time-util.h"
37 #include "utf8.h"
38 #include "util.h"
39 #include "bus-message.h"
40
41 static int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored);
42
43 static void *adjust_pointer(const void *p, void *old_base, size_t sz, void *new_base) {
44
45 if (p == NULL)
46 return NULL;
47
48 if (old_base == new_base)
49 return (void*) p;
50
51 if ((uint8_t*) p < (uint8_t*) old_base)
52 return (void*) p;
53
54 if ((uint8_t*) p >= (uint8_t*) old_base + sz)
55 return (void*) p;
56
57 return (uint8_t*) new_base + ((uint8_t*) p - (uint8_t*) old_base);
58 }
59
60 static void message_free_part(sd_bus_message *m, struct bus_body_part *part) {
61 assert(m);
62 assert(part);
63
64 if (part->memfd >= 0) {
65 /* If we can reuse the memfd, try that. For that it
66 * can't be sealed yet. */
67
68 if (!part->sealed) {
69 assert(part->memfd_offset == 0);
70 assert(part->data == part->mmap_begin);
71 bus_kernel_push_memfd(m->bus, part->memfd, part->data, part->mapped, part->allocated);
72 } else {
73 if (part->mapped > 0)
74 assert_se(munmap(part->mmap_begin, part->mapped) == 0);
75
76 safe_close(part->memfd);
77 }
78
79 } else if (part->munmap_this)
80 munmap(part->mmap_begin, part->mapped);
81 else if (part->free_this)
82 free(part->data);
83
84 if (part != &m->body)
85 free(part);
86 }
87
88 static void message_reset_parts(sd_bus_message *m) {
89 struct bus_body_part *part;
90
91 assert(m);
92
93 part = &m->body;
94 while (m->n_body_parts > 0) {
95 struct bus_body_part *next = part->next;
96 message_free_part(m, part);
97 part = next;
98 m->n_body_parts--;
99 }
100
101 m->body_end = NULL;
102
103 m->cached_rindex_part = NULL;
104 m->cached_rindex_part_begin = 0;
105 }
106
107 static void message_reset_containers(sd_bus_message *m) {
108 unsigned i;
109
110 assert(m);
111
112 for (i = 0; i < m->n_containers; i++) {
113 free(m->containers[i].signature);
114 free(m->containers[i].offsets);
115 }
116
117 m->containers = mfree(m->containers);
118
119 m->n_containers = m->containers_allocated = 0;
120 m->root_container.index = 0;
121 }
122
123 static void message_free(sd_bus_message *m) {
124 assert(m);
125
126 if (m->free_header)
127 free(m->header);
128
129 message_reset_parts(m);
130
131 if (m->release_kdbus)
132 bus_kernel_cmd_free(m->bus, (uint8_t *) m->kdbus - (uint8_t *) m->bus->kdbus_buffer);
133
134 if (m->free_kdbus)
135 free(m->kdbus);
136
137 sd_bus_unref(m->bus);
138
139 if (m->free_fds) {
140 close_many(m->fds, m->n_fds);
141 free(m->fds);
142 }
143
144 if (m->iovec != m->iovec_fixed)
145 free(m->iovec);
146
147 m->destination_ptr = mfree(m->destination_ptr);
148 message_reset_containers(m);
149 free(m->root_container.signature);
150 free(m->root_container.offsets);
151
152 free(m->root_container.peeked_signature);
153
154 bus_creds_done(&m->creds);
155 free(m);
156 }
157
158 static void *message_extend_fields(sd_bus_message *m, size_t align, size_t sz, bool add_offset) {
159 void *op, *np;
160 size_t old_size, new_size, start;
161
162 assert(m);
163
164 if (m->poisoned)
165 return NULL;
166
167 old_size = sizeof(struct bus_header) + m->fields_size;
168 start = ALIGN_TO(old_size, align);
169 new_size = start + sz;
170
171 if (new_size < start ||
172 new_size > (size_t) ((uint32_t) -1))
173 goto poison;
174
175 if (old_size == new_size)
176 return (uint8_t*) m->header + old_size;
177
178 if (m->free_header) {
179 np = realloc(m->header, ALIGN8(new_size));
180 if (!np)
181 goto poison;
182 } else {
183 /* Initially, the header is allocated as part of of
184 * the sd_bus_message itself, let's replace it by
185 * dynamic data */
186
187 np = malloc(ALIGN8(new_size));
188 if (!np)
189 goto poison;
190
191 memcpy(np, m->header, sizeof(struct bus_header));
192 }
193
194 /* Zero out padding */
195 if (start > old_size)
196 memzero((uint8_t*) np + old_size, start - old_size);
197
198 op = m->header;
199 m->header = np;
200 m->fields_size = new_size - sizeof(struct bus_header);
201
202 /* Adjust quick access pointers */
203 m->path = adjust_pointer(m->path, op, old_size, m->header);
204 m->interface = adjust_pointer(m->interface, op, old_size, m->header);
205 m->member = adjust_pointer(m->member, op, old_size, m->header);
206 m->destination = adjust_pointer(m->destination, op, old_size, m->header);
207 m->sender = adjust_pointer(m->sender, op, old_size, m->header);
208 m->error.name = adjust_pointer(m->error.name, op, old_size, m->header);
209
210 m->free_header = true;
211
212 if (add_offset) {
213 if (m->n_header_offsets >= ELEMENTSOF(m->header_offsets))
214 goto poison;
215
216 m->header_offsets[m->n_header_offsets++] = new_size - sizeof(struct bus_header);
217 }
218
219 return (uint8_t*) np + start;
220
221 poison:
222 m->poisoned = true;
223 return NULL;
224 }
225
226 static int message_append_field_string(
227 sd_bus_message *m,
228 uint64_t h,
229 char type,
230 const char *s,
231 const char **ret) {
232
233 size_t l;
234 uint8_t *p;
235
236 assert(m);
237
238 /* dbus1 only allows 8bit header field ids */
239 if (h > 0xFF)
240 return -EINVAL;
241
242 /* dbus1 doesn't allow strings over 32bit, let's enforce this
243 * globally, to not risk convertability */
244 l = strlen(s);
245 if (l > (size_t) (uint32_t) -1)
246 return -EINVAL;
247
248 /* Signature "(yv)" where the variant contains "s" */
249
250 if (BUS_MESSAGE_IS_GVARIANT(m)) {
251
252 /* (field id 64bit, ((string + NUL) + NUL + signature string 's') */
253 p = message_extend_fields(m, 8, 8 + l + 1 + 1 + 1, true);
254 if (!p)
255 return -ENOMEM;
256
257 *((uint64_t*) p) = h;
258 memcpy(p+8, s, l);
259 p[8+l] = 0;
260 p[8+l+1] = 0;
261 p[8+l+2] = type;
262
263 if (ret)
264 *ret = (char*) p + 8;
265
266 } else {
267 /* (field id byte + (signature length + signature 's' + NUL) + (string length + string + NUL)) */
268 p = message_extend_fields(m, 8, 4 + 4 + l + 1, false);
269 if (!p)
270 return -ENOMEM;
271
272 p[0] = (uint8_t) h;
273 p[1] = 1;
274 p[2] = type;
275 p[3] = 0;
276
277 ((uint32_t*) p)[1] = l;
278 memcpy(p + 8, s, l + 1);
279
280 if (ret)
281 *ret = (char*) p + 8;
282 }
283
284 return 0;
285 }
286
287 static int message_append_field_signature(
288 sd_bus_message *m,
289 uint64_t h,
290 const char *s,
291 const char **ret) {
292
293 size_t l;
294 uint8_t *p;
295
296 assert(m);
297
298 /* dbus1 only allows 8bit header field ids */
299 if (h > 0xFF)
300 return -EINVAL;
301
302 /* dbus1 doesn't allow signatures over 8bit, let's enforce
303 * this globally, to not risk convertability */
304 l = strlen(s);
305 if (l > 255)
306 return -EINVAL;
307
308 /* Signature "(yv)" where the variant contains "g" */
309
310 if (BUS_MESSAGE_IS_GVARIANT(m))
311 /* For gvariant the serialization is the same as for normal strings */
312 return message_append_field_string(m, h, 'g', s, ret);
313 else {
314 /* (field id byte + (signature length + signature 'g' + NUL) + (string length + string + NUL)) */
315 p = message_extend_fields(m, 8, 4 + 1 + l + 1, false);
316 if (!p)
317 return -ENOMEM;
318
319 p[0] = (uint8_t) h;
320 p[1] = 1;
321 p[2] = SD_BUS_TYPE_SIGNATURE;
322 p[3] = 0;
323 p[4] = l;
324 memcpy(p + 5, s, l + 1);
325
326 if (ret)
327 *ret = (const char*) p + 5;
328 }
329
330 return 0;
331 }
332
333 static int message_append_field_uint32(sd_bus_message *m, uint64_t h, uint32_t x) {
334 uint8_t *p;
335
336 assert(m);
337
338 /* dbus1 only allows 8bit header field ids */
339 if (h > 0xFF)
340 return -EINVAL;
341
342 if (BUS_MESSAGE_IS_GVARIANT(m)) {
343 /* (field id 64bit + ((value + NUL + signature string 'u') */
344
345 p = message_extend_fields(m, 8, 8 + 4 + 1 + 1, true);
346 if (!p)
347 return -ENOMEM;
348
349 *((uint64_t*) p) = h;
350 *((uint32_t*) (p + 8)) = x;
351 p[12] = 0;
352 p[13] = 'u';
353 } else {
354 /* (field id byte + (signature length + signature 'u' + NUL) + value) */
355 p = message_extend_fields(m, 8, 4 + 4, false);
356 if (!p)
357 return -ENOMEM;
358
359 p[0] = (uint8_t) h;
360 p[1] = 1;
361 p[2] = 'u';
362 p[3] = 0;
363
364 ((uint32_t*) p)[1] = x;
365 }
366
367 return 0;
368 }
369
370 static int message_append_field_uint64(sd_bus_message *m, uint64_t h, uint64_t x) {
371 uint8_t *p;
372
373 assert(m);
374
375 /* dbus1 only allows 8bit header field ids */
376 if (h > 0xFF)
377 return -EINVAL;
378
379 if (BUS_MESSAGE_IS_GVARIANT(m)) {
380 /* (field id 64bit + ((value + NUL + signature string 't') */
381
382 p = message_extend_fields(m, 8, 8 + 8 + 1 + 1, true);
383 if (!p)
384 return -ENOMEM;
385
386 *((uint64_t*) p) = h;
387 *((uint64_t*) (p + 8)) = x;
388 p[16] = 0;
389 p[17] = 't';
390 } else {
391 /* (field id byte + (signature length + signature 't' + NUL) + 4 byte padding + value) */
392 p = message_extend_fields(m, 8, 4 + 4 + 8, false);
393 if (!p)
394 return -ENOMEM;
395
396 p[0] = (uint8_t) h;
397 p[1] = 1;
398 p[2] = 't';
399 p[3] = 0;
400 p[4] = 0;
401 p[5] = 0;
402 p[6] = 0;
403 p[7] = 0;
404
405 ((uint64_t*) p)[1] = x;
406 }
407
408 return 0;
409 }
410
411 static int message_append_reply_cookie(sd_bus_message *m, uint64_t cookie) {
412 assert(m);
413
414 if (BUS_MESSAGE_IS_GVARIANT(m))
415 return message_append_field_uint64(m, BUS_MESSAGE_HEADER_REPLY_SERIAL, cookie);
416 else {
417 /* 64bit cookies are not supported on dbus1 */
418 if (cookie > 0xffffffffUL)
419 return -EOPNOTSUPP;
420
421 return message_append_field_uint32(m, BUS_MESSAGE_HEADER_REPLY_SERIAL, (uint32_t) cookie);
422 }
423 }
424
425 int bus_message_from_header(
426 sd_bus *bus,
427 void *header,
428 size_t header_accessible,
429 void *footer,
430 size_t footer_accessible,
431 size_t message_size,
432 int *fds,
433 unsigned n_fds,
434 const char *label,
435 size_t extra,
436 sd_bus_message **ret) {
437
438 _cleanup_free_ sd_bus_message *m = NULL;
439 struct bus_header *h;
440 size_t a, label_sz;
441
442 assert(bus);
443 assert(header || header_accessible <= 0);
444 assert(footer || footer_accessible <= 0);
445 assert(fds || n_fds <= 0);
446 assert(ret);
447
448 if (header_accessible < sizeof(struct bus_header))
449 return -EBADMSG;
450
451 if (header_accessible > message_size)
452 return -EBADMSG;
453 if (footer_accessible > message_size)
454 return -EBADMSG;
455
456 h = header;
457 if (!IN_SET(h->version, 1, 2))
458 return -EBADMSG;
459
460 if (h->type == _SD_BUS_MESSAGE_TYPE_INVALID)
461 return -EBADMSG;
462
463 if (!IN_SET(h->endian, BUS_LITTLE_ENDIAN, BUS_BIG_ENDIAN))
464 return -EBADMSG;
465
466 /* Note that we are happy with unknown flags in the flags header! */
467
468 a = ALIGN(sizeof(sd_bus_message)) + ALIGN(extra);
469
470 if (label) {
471 label_sz = strlen(label);
472 a += label_sz + 1;
473 }
474
475 m = malloc0(a);
476 if (!m)
477 return -ENOMEM;
478
479 m->n_ref = 1;
480 m->sealed = true;
481 m->header = header;
482 m->header_accessible = header_accessible;
483 m->footer = footer;
484 m->footer_accessible = footer_accessible;
485
486 if (BUS_MESSAGE_IS_GVARIANT(m)) {
487 size_t ws;
488
489 if (h->dbus2.cookie == 0)
490 return -EBADMSG;
491
492 /* dbus2 derives the sizes from the message size and
493 the offset table at the end, since it is formatted as
494 gvariant "yyyyuta{tv}v". Since the message itself is a
495 structure with precisely to variable sized entries,
496 there's only one offset in the table, which marks the
497 end of the fields array. */
498
499 ws = bus_gvariant_determine_word_size(message_size, 0);
500 if (footer_accessible < ws)
501 return -EBADMSG;
502
503 m->fields_size = bus_gvariant_read_word_le((uint8_t*) footer + footer_accessible - ws, ws);
504 if (ALIGN8(m->fields_size) > message_size - ws)
505 return -EBADMSG;
506 if (m->fields_size < sizeof(struct bus_header))
507 return -EBADMSG;
508
509 m->fields_size -= sizeof(struct bus_header);
510 m->body_size = message_size - (sizeof(struct bus_header) + ALIGN8(m->fields_size));
511 } else {
512 if (h->dbus1.serial == 0)
513 return -EBADMSG;
514
515 /* dbus1 has the sizes in the header */
516 m->fields_size = BUS_MESSAGE_BSWAP32(m, h->dbus1.fields_size);
517 m->body_size = BUS_MESSAGE_BSWAP32(m, h->dbus1.body_size);
518
519 if (sizeof(struct bus_header) + ALIGN8(m->fields_size) + m->body_size != message_size)
520 return -EBADMSG;
521 }
522
523 m->fds = fds;
524 m->n_fds = n_fds;
525
526 if (label) {
527 m->creds.label = (char*) m + ALIGN(sizeof(sd_bus_message)) + ALIGN(extra);
528 memcpy(m->creds.label, label, label_sz + 1);
529
530 m->creds.mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
531 }
532
533 m->bus = sd_bus_ref(bus);
534 *ret = m;
535 m = NULL;
536
537 return 0;
538 }
539
540 int bus_message_from_malloc(
541 sd_bus *bus,
542 void *buffer,
543 size_t length,
544 int *fds,
545 unsigned n_fds,
546 const char *label,
547 sd_bus_message **ret) {
548
549 sd_bus_message *m;
550 size_t sz;
551 int r;
552
553 r = bus_message_from_header(
554 bus,
555 buffer, length, /* in this case the initial bytes and the final bytes are the same */
556 buffer, length,
557 length,
558 fds, n_fds,
559 label,
560 0, &m);
561 if (r < 0)
562 return r;
563
564 sz = length - sizeof(struct bus_header) - ALIGN8(m->fields_size);
565 if (sz > 0) {
566 m->n_body_parts = 1;
567 m->body.data = (uint8_t*) buffer + sizeof(struct bus_header) + ALIGN8(m->fields_size);
568 m->body.size = sz;
569 m->body.sealed = true;
570 m->body.memfd = -1;
571 }
572
573 m->n_iovec = 1;
574 m->iovec = m->iovec_fixed;
575 m->iovec[0].iov_base = buffer;
576 m->iovec[0].iov_len = length;
577
578 r = bus_message_parse_fields(m);
579 if (r < 0)
580 goto fail;
581
582 /* We take possession of the memory and fds now */
583 m->free_header = true;
584 m->free_fds = true;
585
586 *ret = m;
587 return 0;
588
589 fail:
590 message_free(m);
591 return r;
592 }
593
594 static sd_bus_message *message_new(sd_bus *bus, uint8_t type) {
595 sd_bus_message *m;
596
597 assert(bus);
598
599 m = malloc0(ALIGN(sizeof(sd_bus_message)) + sizeof(struct bus_header));
600 if (!m)
601 return NULL;
602
603 m->n_ref = 1;
604 m->header = (struct bus_header*) ((uint8_t*) m + ALIGN(sizeof(struct sd_bus_message)));
605 m->header->endian = BUS_NATIVE_ENDIAN;
606 m->header->type = type;
607 m->header->version = bus->message_version;
608 m->allow_fds = bus->can_fds || (bus->state != BUS_HELLO && bus->state != BUS_RUNNING);
609 m->root_container.need_offsets = BUS_MESSAGE_IS_GVARIANT(m);
610 m->bus = sd_bus_ref(bus);
611
612 if (bus->allow_interactive_authorization)
613 m->header->flags |= BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION;
614
615 return m;
616 }
617
618 _public_ int sd_bus_message_new_signal(
619 sd_bus *bus,
620 sd_bus_message **m,
621 const char *path,
622 const char *interface,
623 const char *member) {
624
625 sd_bus_message *t;
626 int r;
627
628 assert_return(bus, -ENOTCONN);
629 assert_return(bus->state != BUS_UNSET, -ENOTCONN);
630 assert_return(object_path_is_valid(path), -EINVAL);
631 assert_return(interface_name_is_valid(interface), -EINVAL);
632 assert_return(member_name_is_valid(member), -EINVAL);
633 assert_return(m, -EINVAL);
634
635 t = message_new(bus, SD_BUS_MESSAGE_SIGNAL);
636 if (!t)
637 return -ENOMEM;
638
639 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
640
641 r = message_append_field_string(t, BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
642 if (r < 0)
643 goto fail;
644 r = message_append_field_string(t, BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
645 if (r < 0)
646 goto fail;
647 r = message_append_field_string(t, BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
648 if (r < 0)
649 goto fail;
650
651 *m = t;
652 return 0;
653
654 fail:
655 sd_bus_message_unref(t);
656 return r;
657 }
658
659 _public_ int sd_bus_message_new_method_call(
660 sd_bus *bus,
661 sd_bus_message **m,
662 const char *destination,
663 const char *path,
664 const char *interface,
665 const char *member) {
666
667 sd_bus_message *t;
668 int r;
669
670 assert_return(bus, -ENOTCONN);
671 assert_return(bus->state != BUS_UNSET, -ENOTCONN);
672 assert_return(!destination || service_name_is_valid(destination), -EINVAL);
673 assert_return(object_path_is_valid(path), -EINVAL);
674 assert_return(!interface || interface_name_is_valid(interface), -EINVAL);
675 assert_return(member_name_is_valid(member), -EINVAL);
676 assert_return(m, -EINVAL);
677
678 t = message_new(bus, SD_BUS_MESSAGE_METHOD_CALL);
679 if (!t)
680 return -ENOMEM;
681
682 r = message_append_field_string(t, BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
683 if (r < 0)
684 goto fail;
685 r = message_append_field_string(t, BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
686 if (r < 0)
687 goto fail;
688
689 if (interface) {
690 r = message_append_field_string(t, BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
691 if (r < 0)
692 goto fail;
693 }
694
695 if (destination) {
696 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &t->destination);
697 if (r < 0)
698 goto fail;
699 }
700
701 *m = t;
702 return 0;
703
704 fail:
705 message_free(t);
706 return r;
707 }
708
709 static int message_new_reply(
710 sd_bus_message *call,
711 uint8_t type,
712 sd_bus_message **m) {
713
714 sd_bus_message *t;
715 int r;
716
717 assert_return(call, -EINVAL);
718 assert_return(call->sealed, -EPERM);
719 assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL);
720 assert_return(call->bus->state != BUS_UNSET, -ENOTCONN);
721 assert_return(m, -EINVAL);
722
723 t = message_new(call->bus, type);
724 if (!t)
725 return -ENOMEM;
726
727 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
728 t->reply_cookie = BUS_MESSAGE_COOKIE(call);
729 if (t->reply_cookie == 0)
730 return -EOPNOTSUPP;
731
732 r = message_append_reply_cookie(t, t->reply_cookie);
733 if (r < 0)
734 goto fail;
735
736 if (call->sender) {
737 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, call->sender, &t->destination);
738 if (r < 0)
739 goto fail;
740 }
741
742 t->dont_send = !!(call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED);
743 t->enforced_reply_signature = call->enforced_reply_signature;
744
745 *m = t;
746 return 0;
747
748 fail:
749 message_free(t);
750 return r;
751 }
752
753 _public_ int sd_bus_message_new_method_return(
754 sd_bus_message *call,
755 sd_bus_message **m) {
756
757 return message_new_reply(call, SD_BUS_MESSAGE_METHOD_RETURN, m);
758 }
759
760 _public_ int sd_bus_message_new_method_error(
761 sd_bus_message *call,
762 sd_bus_message **m,
763 const sd_bus_error *e) {
764
765 sd_bus_message *t;
766 int r;
767
768 assert_return(sd_bus_error_is_set(e), -EINVAL);
769 assert_return(m, -EINVAL);
770
771 r = message_new_reply(call, SD_BUS_MESSAGE_METHOD_ERROR, &t);
772 if (r < 0)
773 return r;
774
775 r = message_append_field_string(t, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
776 if (r < 0)
777 goto fail;
778
779 if (e->message) {
780 r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
781 if (r < 0)
782 goto fail;
783 }
784
785 t->error._need_free = -1;
786
787 *m = t;
788 return 0;
789
790 fail:
791 message_free(t);
792 return r;
793 }
794
795 _public_ int sd_bus_message_new_method_errorf(
796 sd_bus_message *call,
797 sd_bus_message **m,
798 const char *name,
799 const char *format,
800 ...) {
801
802 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
803 va_list ap;
804
805 assert_return(name, -EINVAL);
806 assert_return(m, -EINVAL);
807
808 va_start(ap, format);
809 bus_error_setfv(&error, name, format, ap);
810 va_end(ap);
811
812 return sd_bus_message_new_method_error(call, m, &error);
813 }
814
815 _public_ int sd_bus_message_new_method_errno(
816 sd_bus_message *call,
817 sd_bus_message **m,
818 int error,
819 const sd_bus_error *p) {
820
821 _cleanup_bus_error_free_ sd_bus_error berror = SD_BUS_ERROR_NULL;
822
823 if (sd_bus_error_is_set(p))
824 return sd_bus_message_new_method_error(call, m, p);
825
826 sd_bus_error_set_errno(&berror, error);
827
828 return sd_bus_message_new_method_error(call, m, &berror);
829 }
830
831 _public_ int sd_bus_message_new_method_errnof(
832 sd_bus_message *call,
833 sd_bus_message **m,
834 int error,
835 const char *format,
836 ...) {
837
838 _cleanup_bus_error_free_ sd_bus_error berror = SD_BUS_ERROR_NULL;
839 va_list ap;
840
841 va_start(ap, format);
842 sd_bus_error_set_errnofv(&berror, error, format, ap);
843 va_end(ap);
844
845 return sd_bus_message_new_method_error(call, m, &berror);
846 }
847
848 void bus_message_set_sender_local(sd_bus *bus, sd_bus_message *m) {
849 assert(bus);
850 assert(m);
851
852 m->sender = m->creds.unique_name = (char*) "org.freedesktop.DBus.Local";
853 m->creds.well_known_names_local = true;
854 m->creds.mask |= (SD_BUS_CREDS_UNIQUE_NAME|SD_BUS_CREDS_WELL_KNOWN_NAMES) & bus->creds_mask;
855 }
856
857 void bus_message_set_sender_driver(sd_bus *bus, sd_bus_message *m) {
858 assert(bus);
859 assert(m);
860
861 m->sender = m->creds.unique_name = (char*) "org.freedesktop.DBus";
862 m->creds.well_known_names_driver = true;
863 m->creds.mask |= (SD_BUS_CREDS_UNIQUE_NAME|SD_BUS_CREDS_WELL_KNOWN_NAMES) & bus->creds_mask;
864 }
865
866 int bus_message_new_synthetic_error(
867 sd_bus *bus,
868 uint64_t cookie,
869 const sd_bus_error *e,
870 sd_bus_message **m) {
871
872 sd_bus_message *t;
873 int r;
874
875 assert(bus);
876 assert(sd_bus_error_is_set(e));
877 assert(m);
878
879 t = message_new(bus, SD_BUS_MESSAGE_METHOD_ERROR);
880 if (!t)
881 return -ENOMEM;
882
883 t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
884 t->reply_cookie = cookie;
885
886 r = message_append_reply_cookie(t, t->reply_cookie);
887 if (r < 0)
888 goto fail;
889
890 if (bus && bus->unique_name) {
891 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, bus->unique_name, &t->destination);
892 if (r < 0)
893 goto fail;
894 }
895
896 r = message_append_field_string(t, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
897 if (r < 0)
898 goto fail;
899
900 if (e->message) {
901 r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
902 if (r < 0)
903 goto fail;
904 }
905
906 t->error._need_free = -1;
907
908 bus_message_set_sender_driver(bus, t);
909
910 *m = t;
911 return 0;
912
913 fail:
914 message_free(t);
915 return r;
916 }
917
918 _public_ sd_bus_message* sd_bus_message_ref(sd_bus_message *m) {
919 assert_return(m, NULL);
920
921 assert(m->n_ref > 0);
922 m->n_ref++;
923
924 return m;
925 }
926
927 _public_ sd_bus_message* sd_bus_message_unref(sd_bus_message *m) {
928
929 if (!m)
930 return NULL;
931
932 assert(m->n_ref > 0);
933 m->n_ref--;
934
935 if (m->n_ref > 0)
936 return NULL;
937
938 message_free(m);
939 return NULL;
940 }
941
942 _public_ int sd_bus_message_get_type(sd_bus_message *m, uint8_t *type) {
943 assert_return(m, -EINVAL);
944 assert_return(type, -EINVAL);
945
946 *type = m->header->type;
947 return 0;
948 }
949
950 _public_ int sd_bus_message_get_cookie(sd_bus_message *m, uint64_t *cookie) {
951 uint64_t c;
952
953 assert_return(m, -EINVAL);
954 assert_return(cookie, -EINVAL);
955
956 c = BUS_MESSAGE_COOKIE(m);
957 if (c == 0)
958 return -ENODATA;
959
960 *cookie = BUS_MESSAGE_COOKIE(m);
961 return 0;
962 }
963
964 _public_ int sd_bus_message_get_reply_cookie(sd_bus_message *m, uint64_t *cookie) {
965 assert_return(m, -EINVAL);
966 assert_return(cookie, -EINVAL);
967
968 if (m->reply_cookie == 0)
969 return -ENODATA;
970
971 *cookie = m->reply_cookie;
972 return 0;
973 }
974
975 _public_ int sd_bus_message_get_expect_reply(sd_bus_message *m) {
976 assert_return(m, -EINVAL);
977
978 return m->header->type == SD_BUS_MESSAGE_METHOD_CALL &&
979 !(m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED);
980 }
981
982 _public_ int sd_bus_message_get_auto_start(sd_bus_message *m) {
983 assert_return(m, -EINVAL);
984
985 return !(m->header->flags & BUS_MESSAGE_NO_AUTO_START);
986 }
987
988 _public_ int sd_bus_message_get_allow_interactive_authorization(sd_bus_message *m) {
989 assert_return(m, -EINVAL);
990
991 return m->header->type == SD_BUS_MESSAGE_METHOD_CALL &&
992 (m->header->flags & BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION);
993 }
994
995 _public_ const char *sd_bus_message_get_path(sd_bus_message *m) {
996 assert_return(m, NULL);
997
998 return m->path;
999 }
1000
1001 _public_ const char *sd_bus_message_get_interface(sd_bus_message *m) {
1002 assert_return(m, NULL);
1003
1004 return m->interface;
1005 }
1006
1007 _public_ const char *sd_bus_message_get_member(sd_bus_message *m) {
1008 assert_return(m, NULL);
1009
1010 return m->member;
1011 }
1012
1013 _public_ const char *sd_bus_message_get_destination(sd_bus_message *m) {
1014 assert_return(m, NULL);
1015
1016 return m->destination;
1017 }
1018
1019 _public_ const char *sd_bus_message_get_sender(sd_bus_message *m) {
1020 assert_return(m, NULL);
1021
1022 return m->sender;
1023 }
1024
1025 _public_ const sd_bus_error *sd_bus_message_get_error(sd_bus_message *m) {
1026 assert_return(m, NULL);
1027
1028 if (!sd_bus_error_is_set(&m->error))
1029 return NULL;
1030
1031 return &m->error;
1032 }
1033
1034 _public_ int sd_bus_message_get_monotonic_usec(sd_bus_message *m, uint64_t *usec) {
1035 assert_return(m, -EINVAL);
1036 assert_return(usec, -EINVAL);
1037
1038 if (m->monotonic <= 0)
1039 return -ENODATA;
1040
1041 *usec = m->monotonic;
1042 return 0;
1043 }
1044
1045 _public_ int sd_bus_message_get_realtime_usec(sd_bus_message *m, uint64_t *usec) {
1046 assert_return(m, -EINVAL);
1047 assert_return(usec, -EINVAL);
1048
1049 if (m->realtime <= 0)
1050 return -ENODATA;
1051
1052 *usec = m->realtime;
1053 return 0;
1054 }
1055
1056 _public_ int sd_bus_message_get_seqnum(sd_bus_message *m, uint64_t *seqnum) {
1057 assert_return(m, -EINVAL);
1058 assert_return(seqnum, -EINVAL);
1059
1060 if (m->seqnum <= 0)
1061 return -ENODATA;
1062
1063 *seqnum = m->seqnum;
1064 return 0;
1065 }
1066
1067 _public_ sd_bus_creds *sd_bus_message_get_creds(sd_bus_message *m) {
1068 assert_return(m, NULL);
1069
1070 if (m->creds.mask == 0)
1071 return NULL;
1072
1073 return &m->creds;
1074 }
1075
1076 _public_ int sd_bus_message_is_signal(
1077 sd_bus_message *m,
1078 const char *interface,
1079 const char *member) {
1080
1081 assert_return(m, -EINVAL);
1082
1083 if (m->header->type != SD_BUS_MESSAGE_SIGNAL)
1084 return 0;
1085
1086 if (interface && (!m->interface || !streq(m->interface, interface)))
1087 return 0;
1088
1089 if (member && (!m->member || !streq(m->member, member)))
1090 return 0;
1091
1092 return 1;
1093 }
1094
1095 _public_ int sd_bus_message_is_method_call(
1096 sd_bus_message *m,
1097 const char *interface,
1098 const char *member) {
1099
1100 assert_return(m, -EINVAL);
1101
1102 if (m->header->type != SD_BUS_MESSAGE_METHOD_CALL)
1103 return 0;
1104
1105 if (interface && (!m->interface || !streq(m->interface, interface)))
1106 return 0;
1107
1108 if (member && (!m->member || !streq(m->member, member)))
1109 return 0;
1110
1111 return 1;
1112 }
1113
1114 _public_ int sd_bus_message_is_method_error(sd_bus_message *m, const char *name) {
1115 assert_return(m, -EINVAL);
1116
1117 if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
1118 return 0;
1119
1120 if (name && (!m->error.name || !streq(m->error.name, name)))
1121 return 0;
1122
1123 return 1;
1124 }
1125
1126 _public_ int sd_bus_message_set_expect_reply(sd_bus_message *m, int b) {
1127 assert_return(m, -EINVAL);
1128 assert_return(!m->sealed, -EPERM);
1129 assert_return(m->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EPERM);
1130
1131 if (b)
1132 m->header->flags &= ~BUS_MESSAGE_NO_REPLY_EXPECTED;
1133 else
1134 m->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
1135
1136 return 0;
1137 }
1138
1139 _public_ int sd_bus_message_set_auto_start(sd_bus_message *m, int b) {
1140 assert_return(m, -EINVAL);
1141 assert_return(!m->sealed, -EPERM);
1142
1143 if (b)
1144 m->header->flags &= ~BUS_MESSAGE_NO_AUTO_START;
1145 else
1146 m->header->flags |= BUS_MESSAGE_NO_AUTO_START;
1147
1148 return 0;
1149 }
1150
1151 _public_ int sd_bus_message_set_allow_interactive_authorization(sd_bus_message *m, int b) {
1152 assert_return(m, -EINVAL);
1153 assert_return(!m->sealed, -EPERM);
1154
1155 if (b)
1156 m->header->flags |= BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION;
1157 else
1158 m->header->flags &= ~BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION;
1159
1160 return 0;
1161 }
1162
1163 static struct bus_container *message_get_container(sd_bus_message *m) {
1164 assert(m);
1165
1166 if (m->n_containers == 0)
1167 return &m->root_container;
1168
1169 assert(m->containers);
1170 return m->containers + m->n_containers - 1;
1171 }
1172
1173 struct bus_body_part *message_append_part(sd_bus_message *m) {
1174 struct bus_body_part *part;
1175
1176 assert(m);
1177
1178 if (m->poisoned)
1179 return NULL;
1180
1181 if (m->n_body_parts <= 0) {
1182 part = &m->body;
1183 zero(*part);
1184 } else {
1185 assert(m->body_end);
1186
1187 part = new0(struct bus_body_part, 1);
1188 if (!part) {
1189 m->poisoned = true;
1190 return NULL;
1191 }
1192
1193 m->body_end->next = part;
1194 }
1195
1196 part->memfd = -1;
1197 m->body_end = part;
1198 m->n_body_parts ++;
1199
1200 return part;
1201 }
1202
1203 static void part_zero(struct bus_body_part *part, size_t sz) {
1204 assert(part);
1205 assert(sz > 0);
1206 assert(sz < 8);
1207
1208 /* All other fields can be left in their defaults */
1209 assert(!part->data);
1210 assert(part->memfd < 0);
1211
1212 part->size = sz;
1213 part->is_zero = true;
1214 part->sealed = true;
1215 }
1216
1217 static int part_make_space(
1218 struct sd_bus_message *m,
1219 struct bus_body_part *part,
1220 size_t sz,
1221 void **q) {
1222
1223 void *n;
1224 int r;
1225
1226 assert(m);
1227 assert(part);
1228 assert(!part->sealed);
1229
1230 if (m->poisoned)
1231 return -ENOMEM;
1232
1233 if (!part->data && part->memfd < 0) {
1234 part->memfd = bus_kernel_pop_memfd(m->bus, &part->data, &part->mapped, &part->allocated);
1235 part->mmap_begin = part->data;
1236 }
1237
1238 if (part->memfd >= 0) {
1239
1240 if (part->allocated == 0 || sz > part->allocated) {
1241 uint64_t new_allocated;
1242
1243 new_allocated = PAGE_ALIGN(sz > 0 ? 2 * sz : 1);
1244 r = memfd_set_size(part->memfd, new_allocated);
1245 if (r < 0) {
1246 m->poisoned = true;
1247 return r;
1248 }
1249
1250 part->allocated = new_allocated;
1251 }
1252
1253 if (!part->data || sz > part->mapped) {
1254 size_t psz;
1255
1256 psz = PAGE_ALIGN(sz > 0 ? sz : 1);
1257 if (part->mapped <= 0)
1258 n = mmap(NULL, psz, PROT_READ|PROT_WRITE, MAP_SHARED, part->memfd, 0);
1259 else
1260 n = mremap(part->mmap_begin, part->mapped, psz, MREMAP_MAYMOVE);
1261
1262 if (n == MAP_FAILED) {
1263 m->poisoned = true;
1264 return -errno;
1265 }
1266
1267 part->mmap_begin = part->data = n;
1268 part->mapped = psz;
1269 part->memfd_offset = 0;
1270 }
1271
1272 part->munmap_this = true;
1273 } else {
1274 if (part->allocated == 0 || sz > part->allocated) {
1275 size_t new_allocated;
1276
1277 new_allocated = sz > 0 ? 2 * sz : 64;
1278 n = realloc(part->data, new_allocated);
1279 if (!n) {
1280 m->poisoned = true;
1281 return -ENOMEM;
1282 }
1283
1284 part->data = n;
1285 part->allocated = new_allocated;
1286 part->free_this = true;
1287 }
1288 }
1289
1290 if (q)
1291 *q = part->data ? (uint8_t*) part->data + part->size : NULL;
1292
1293 part->size = sz;
1294 return 0;
1295 }
1296
1297 static int message_add_offset(sd_bus_message *m, size_t offset) {
1298 struct bus_container *c;
1299
1300 assert(m);
1301 assert(BUS_MESSAGE_IS_GVARIANT(m));
1302
1303 /* Add offset to current container, unless this is the first
1304 * item in it, which will have the 0 offset, which we can
1305 * ignore. */
1306 c = message_get_container(m);
1307
1308 if (!c->need_offsets)
1309 return 0;
1310
1311 if (!GREEDY_REALLOC(c->offsets, c->offsets_allocated, c->n_offsets + 1))
1312 return -ENOMEM;
1313
1314 c->offsets[c->n_offsets++] = offset;
1315 return 0;
1316 }
1317
1318 static void message_extend_containers(sd_bus_message *m, size_t expand) {
1319 struct bus_container *c;
1320
1321 assert(m);
1322
1323 if (expand <= 0)
1324 return;
1325
1326 /* Update counters */
1327 for (c = m->containers; c < m->containers + m->n_containers; c++) {
1328
1329 if (c->array_size)
1330 *c->array_size += expand;
1331 }
1332 }
1333
1334 static void *message_extend_body(
1335 sd_bus_message *m,
1336 size_t align,
1337 size_t sz,
1338 bool add_offset,
1339 bool force_inline) {
1340
1341 size_t start_body, end_body, padding, added;
1342 void *p;
1343 int r;
1344
1345 assert(m);
1346 assert(align > 0);
1347 assert(!m->sealed);
1348
1349 if (m->poisoned)
1350 return NULL;
1351
1352 start_body = ALIGN_TO((size_t) m->body_size, align);
1353 end_body = start_body + sz;
1354
1355 padding = start_body - m->body_size;
1356 added = padding + sz;
1357
1358 /* Check for 32bit overflows */
1359 if (end_body > (size_t) ((uint32_t) -1) ||
1360 end_body < start_body) {
1361 m->poisoned = true;
1362 return NULL;
1363 }
1364
1365 if (added > 0) {
1366 struct bus_body_part *part = NULL;
1367 bool add_new_part;
1368
1369 add_new_part =
1370 m->n_body_parts <= 0 ||
1371 m->body_end->sealed ||
1372 (padding != ALIGN_TO(m->body_end->size, align) - m->body_end->size) ||
1373 (force_inline && m->body_end->size > MEMFD_MIN_SIZE); /* if this must be an inlined extension, let's create a new part if the previous part is large enough to be inlined */
1374
1375 if (add_new_part) {
1376 if (padding > 0) {
1377 part = message_append_part(m);
1378 if (!part)
1379 return NULL;
1380
1381 part_zero(part, padding);
1382 }
1383
1384 part = message_append_part(m);
1385 if (!part)
1386 return NULL;
1387
1388 r = part_make_space(m, part, sz, &p);
1389 if (r < 0)
1390 return NULL;
1391 } else {
1392 struct bus_container *c;
1393 void *op;
1394 size_t os, start_part, end_part;
1395
1396 part = m->body_end;
1397 op = part->data;
1398 os = part->size;
1399
1400 start_part = ALIGN_TO(part->size, align);
1401 end_part = start_part + sz;
1402
1403 r = part_make_space(m, part, end_part, &p);
1404 if (r < 0)
1405 return NULL;
1406
1407 if (padding > 0) {
1408 memzero(p, padding);
1409 p = (uint8_t*) p + padding;
1410 }
1411
1412 /* Readjust pointers */
1413 for (c = m->containers; c < m->containers + m->n_containers; c++)
1414 c->array_size = adjust_pointer(c->array_size, op, os, part->data);
1415
1416 m->error.message = (const char*) adjust_pointer(m->error.message, op, os, part->data);
1417 }
1418 } else
1419 /* Return something that is not NULL and is aligned */
1420 p = (uint8_t *) NULL + align;
1421
1422 m->body_size = end_body;
1423 message_extend_containers(m, added);
1424
1425 if (add_offset) {
1426 r = message_add_offset(m, end_body);
1427 if (r < 0) {
1428 m->poisoned = true;
1429 return NULL;
1430 }
1431 }
1432
1433 return p;
1434 }
1435
1436 static int message_push_fd(sd_bus_message *m, int fd) {
1437 int *f, copy;
1438
1439 assert(m);
1440
1441 if (fd < 0)
1442 return -EINVAL;
1443
1444 if (!m->allow_fds)
1445 return -EOPNOTSUPP;
1446
1447 copy = fcntl(fd, F_DUPFD_CLOEXEC, 3);
1448 if (copy < 0)
1449 return -errno;
1450
1451 f = realloc(m->fds, sizeof(int) * (m->n_fds + 1));
1452 if (!f) {
1453 m->poisoned = true;
1454 safe_close(copy);
1455 return -ENOMEM;
1456 }
1457
1458 m->fds = f;
1459 m->fds[m->n_fds] = copy;
1460 m->free_fds = true;
1461
1462 return copy;
1463 }
1464
1465 int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored) {
1466 _cleanup_close_ int fd = -1;
1467 struct bus_container *c;
1468 ssize_t align, sz;
1469 void *a;
1470
1471 assert_return(m, -EINVAL);
1472 assert_return(!m->sealed, -EPERM);
1473 assert_return(bus_type_is_basic(type), -EINVAL);
1474 assert_return(!m->poisoned, -ESTALE);
1475
1476 c = message_get_container(m);
1477
1478 if (c->signature && c->signature[c->index]) {
1479 /* Container signature is already set */
1480
1481 if (c->signature[c->index] != type)
1482 return -ENXIO;
1483 } else {
1484 char *e;
1485
1486 /* Maybe we can append to the signature? But only if this is the top-level container */
1487 if (c->enclosing != 0)
1488 return -ENXIO;
1489
1490 e = strextend(&c->signature, CHAR_TO_STR(type), NULL);
1491 if (!e) {
1492 m->poisoned = true;
1493 return -ENOMEM;
1494 }
1495 }
1496
1497 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1498 uint8_t u8;
1499 uint32_t u32;
1500
1501 switch (type) {
1502
1503 case SD_BUS_TYPE_SIGNATURE:
1504 case SD_BUS_TYPE_STRING:
1505 p = strempty(p);
1506
1507 /* Fall through... */
1508 case SD_BUS_TYPE_OBJECT_PATH:
1509 if (!p)
1510 return -EINVAL;
1511
1512 align = 1;
1513 sz = strlen(p) + 1;
1514 break;
1515
1516 case SD_BUS_TYPE_BOOLEAN:
1517
1518 u8 = p && *(int*) p;
1519 p = &u8;
1520
1521 align = sz = 1;
1522 break;
1523
1524 case SD_BUS_TYPE_UNIX_FD:
1525
1526 if (!p)
1527 return -EINVAL;
1528
1529 fd = message_push_fd(m, *(int*) p);
1530 if (fd < 0)
1531 return fd;
1532
1533 u32 = m->n_fds;
1534 p = &u32;
1535
1536 align = sz = 4;
1537 break;
1538
1539 default:
1540 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
1541 sz = bus_gvariant_get_size(CHAR_TO_STR(type));
1542 break;
1543 }
1544
1545 assert(align > 0);
1546 assert(sz > 0);
1547
1548 a = message_extend_body(m, align, sz, true, false);
1549 if (!a)
1550 return -ENOMEM;
1551
1552 memcpy(a, p, sz);
1553
1554 if (stored)
1555 *stored = (const uint8_t*) a;
1556
1557 } else {
1558 uint32_t u32;
1559
1560 switch (type) {
1561
1562 case SD_BUS_TYPE_STRING:
1563 /* To make things easy we'll serialize a NULL string
1564 * into the empty string */
1565 p = strempty(p);
1566
1567 /* Fall through... */
1568 case SD_BUS_TYPE_OBJECT_PATH:
1569
1570 if (!p)
1571 return -EINVAL;
1572
1573 align = 4;
1574 sz = 4 + strlen(p) + 1;
1575 break;
1576
1577 case SD_BUS_TYPE_SIGNATURE:
1578
1579 p = strempty(p);
1580
1581 align = 1;
1582 sz = 1 + strlen(p) + 1;
1583 break;
1584
1585 case SD_BUS_TYPE_BOOLEAN:
1586
1587 u32 = p && *(int*) p;
1588 p = &u32;
1589
1590 align = sz = 4;
1591 break;
1592
1593 case SD_BUS_TYPE_UNIX_FD:
1594
1595 if (!p)
1596 return -EINVAL;
1597
1598 fd = message_push_fd(m, *(int*) p);
1599 if (fd < 0)
1600 return fd;
1601
1602 u32 = m->n_fds;
1603 p = &u32;
1604
1605 align = sz = 4;
1606 break;
1607
1608 default:
1609 align = bus_type_get_alignment(type);
1610 sz = bus_type_get_size(type);
1611 break;
1612 }
1613
1614 assert(align > 0);
1615 assert(sz > 0);
1616
1617 a = message_extend_body(m, align, sz, false, false);
1618 if (!a)
1619 return -ENOMEM;
1620
1621 if (type == SD_BUS_TYPE_STRING || type == SD_BUS_TYPE_OBJECT_PATH) {
1622 *(uint32_t*) a = sz - 5;
1623 memcpy((uint8_t*) a + 4, p, sz - 4);
1624
1625 if (stored)
1626 *stored = (const uint8_t*) a + 4;
1627
1628 } else if (type == SD_BUS_TYPE_SIGNATURE) {
1629 *(uint8_t*) a = sz - 2;
1630 memcpy((uint8_t*) a + 1, p, sz - 1);
1631
1632 if (stored)
1633 *stored = (const uint8_t*) a + 1;
1634 } else {
1635 memcpy(a, p, sz);
1636
1637 if (stored)
1638 *stored = a;
1639 }
1640 }
1641
1642 if (type == SD_BUS_TYPE_UNIX_FD)
1643 m->n_fds ++;
1644
1645 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1646 c->index++;
1647
1648 fd = -1;
1649 return 0;
1650 }
1651
1652 _public_ int sd_bus_message_append_basic(sd_bus_message *m, char type, const void *p) {
1653 return message_append_basic(m, type, p, NULL);
1654 }
1655
1656 _public_ int sd_bus_message_append_string_space(
1657 sd_bus_message *m,
1658 size_t size,
1659 char **s) {
1660
1661 struct bus_container *c;
1662 void *a;
1663
1664 assert_return(m, -EINVAL);
1665 assert_return(s, -EINVAL);
1666 assert_return(!m->sealed, -EPERM);
1667 assert_return(!m->poisoned, -ESTALE);
1668
1669 c = message_get_container(m);
1670
1671 if (c->signature && c->signature[c->index]) {
1672 /* Container signature is already set */
1673
1674 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
1675 return -ENXIO;
1676 } else {
1677 char *e;
1678
1679 /* Maybe we can append to the signature? But only if this is the top-level container */
1680 if (c->enclosing != 0)
1681 return -ENXIO;
1682
1683 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
1684 if (!e) {
1685 m->poisoned = true;
1686 return -ENOMEM;
1687 }
1688 }
1689
1690 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1691 a = message_extend_body(m, 1, size + 1, true, false);
1692 if (!a)
1693 return -ENOMEM;
1694
1695 *s = a;
1696 } else {
1697 a = message_extend_body(m, 4, 4 + size + 1, false, false);
1698 if (!a)
1699 return -ENOMEM;
1700
1701 *(uint32_t*) a = size;
1702 *s = (char*) a + 4;
1703 }
1704
1705 (*s)[size] = 0;
1706
1707 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1708 c->index++;
1709
1710 return 0;
1711 }
1712
1713 _public_ int sd_bus_message_append_string_iovec(
1714 sd_bus_message *m,
1715 const struct iovec *iov,
1716 unsigned n) {
1717
1718 size_t size;
1719 unsigned i;
1720 char *p;
1721 int r;
1722
1723 assert_return(m, -EINVAL);
1724 assert_return(!m->sealed, -EPERM);
1725 assert_return(iov || n == 0, -EINVAL);
1726 assert_return(!m->poisoned, -ESTALE);
1727
1728 size = IOVEC_TOTAL_SIZE(iov, n);
1729
1730 r = sd_bus_message_append_string_space(m, size, &p);
1731 if (r < 0)
1732 return r;
1733
1734 for (i = 0; i < n; i++) {
1735
1736 if (iov[i].iov_base)
1737 memcpy(p, iov[i].iov_base, iov[i].iov_len);
1738 else
1739 memset(p, ' ', iov[i].iov_len);
1740
1741 p += iov[i].iov_len;
1742 }
1743
1744 return 0;
1745 }
1746
1747 static int bus_message_open_array(
1748 sd_bus_message *m,
1749 struct bus_container *c,
1750 const char *contents,
1751 uint32_t **array_size,
1752 size_t *begin,
1753 bool *need_offsets) {
1754
1755 unsigned nindex;
1756 int alignment, r;
1757
1758 assert(m);
1759 assert(c);
1760 assert(contents);
1761 assert(array_size);
1762 assert(begin);
1763 assert(need_offsets);
1764
1765 if (!signature_is_single(contents, true))
1766 return -EINVAL;
1767
1768 if (c->signature && c->signature[c->index]) {
1769
1770 /* Verify the existing signature */
1771
1772 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
1773 return -ENXIO;
1774
1775 if (!startswith(c->signature + c->index + 1, contents))
1776 return -ENXIO;
1777
1778 nindex = c->index + 1 + strlen(contents);
1779 } else {
1780 char *e;
1781
1782 if (c->enclosing != 0)
1783 return -ENXIO;
1784
1785 /* Extend the existing signature */
1786
1787 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_ARRAY), contents, NULL);
1788 if (!e) {
1789 m->poisoned = true;
1790 return -ENOMEM;
1791 }
1792
1793 nindex = e - c->signature;
1794 }
1795
1796 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1797 alignment = bus_gvariant_get_alignment(contents);
1798 if (alignment < 0)
1799 return alignment;
1800
1801 /* Add alignment padding and add to offset list */
1802 if (!message_extend_body(m, alignment, 0, false, false))
1803 return -ENOMEM;
1804
1805 r = bus_gvariant_is_fixed_size(contents);
1806 if (r < 0)
1807 return r;
1808
1809 *begin = m->body_size;
1810 *need_offsets = r == 0;
1811 } else {
1812 void *a, *op;
1813 size_t os;
1814 struct bus_body_part *o;
1815
1816 alignment = bus_type_get_alignment(contents[0]);
1817 if (alignment < 0)
1818 return alignment;
1819
1820 a = message_extend_body(m, 4, 4, false, false);
1821 if (!a)
1822 return -ENOMEM;
1823
1824 o = m->body_end;
1825 op = m->body_end->data;
1826 os = m->body_end->size;
1827
1828 /* Add alignment between size and first element */
1829 if (!message_extend_body(m, alignment, 0, false, false))
1830 return -ENOMEM;
1831
1832 /* location of array size might have changed so let's readjust a */
1833 if (o == m->body_end)
1834 a = adjust_pointer(a, op, os, m->body_end->data);
1835
1836 *(uint32_t*) a = 0;
1837 *array_size = a;
1838 }
1839
1840 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1841 c->index = nindex;
1842
1843 return 0;
1844 }
1845
1846 static int bus_message_open_variant(
1847 sd_bus_message *m,
1848 struct bus_container *c,
1849 const char *contents) {
1850
1851 assert(m);
1852 assert(c);
1853 assert(contents);
1854
1855 if (!signature_is_single(contents, false))
1856 return -EINVAL;
1857
1858 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
1859 return -EINVAL;
1860
1861 if (c->signature && c->signature[c->index]) {
1862
1863 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
1864 return -ENXIO;
1865
1866 } else {
1867 char *e;
1868
1869 if (c->enclosing != 0)
1870 return -ENXIO;
1871
1872 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_VARIANT), NULL);
1873 if (!e) {
1874 m->poisoned = true;
1875 return -ENOMEM;
1876 }
1877 }
1878
1879 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1880 /* Variants are always aligned to 8 */
1881
1882 if (!message_extend_body(m, 8, 0, false, false))
1883 return -ENOMEM;
1884
1885 } else {
1886 size_t l;
1887 void *a;
1888
1889 l = strlen(contents);
1890 a = message_extend_body(m, 1, 1 + l + 1, false, false);
1891 if (!a)
1892 return -ENOMEM;
1893
1894 *(uint8_t*) a = l;
1895 memcpy((uint8_t*) a + 1, contents, l + 1);
1896 }
1897
1898 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1899 c->index++;
1900
1901 return 0;
1902 }
1903
1904 static int bus_message_open_struct(
1905 sd_bus_message *m,
1906 struct bus_container *c,
1907 const char *contents,
1908 size_t *begin,
1909 bool *need_offsets) {
1910
1911 size_t nindex;
1912 int r;
1913
1914 assert(m);
1915 assert(c);
1916 assert(contents);
1917 assert(begin);
1918 assert(need_offsets);
1919
1920 if (!signature_is_valid(contents, false))
1921 return -EINVAL;
1922
1923 if (c->signature && c->signature[c->index]) {
1924 size_t l;
1925
1926 l = strlen(contents);
1927
1928 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
1929 !startswith(c->signature + c->index + 1, contents) ||
1930 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
1931 return -ENXIO;
1932
1933 nindex = c->index + 1 + l + 1;
1934 } else {
1935 char *e;
1936
1937 if (c->enclosing != 0)
1938 return -ENXIO;
1939
1940 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_BEGIN), contents, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_END), NULL);
1941 if (!e) {
1942 m->poisoned = true;
1943 return -ENOMEM;
1944 }
1945
1946 nindex = e - c->signature;
1947 }
1948
1949 if (BUS_MESSAGE_IS_GVARIANT(m)) {
1950 int alignment;
1951
1952 alignment = bus_gvariant_get_alignment(contents);
1953 if (alignment < 0)
1954 return alignment;
1955
1956 if (!message_extend_body(m, alignment, 0, false, false))
1957 return -ENOMEM;
1958
1959 r = bus_gvariant_is_fixed_size(contents);
1960 if (r < 0)
1961 return r;
1962
1963 *begin = m->body_size;
1964 *need_offsets = r == 0;
1965 } else {
1966 /* Align contents to 8 byte boundary */
1967 if (!message_extend_body(m, 8, 0, false, false))
1968 return -ENOMEM;
1969 }
1970
1971 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1972 c->index = nindex;
1973
1974 return 0;
1975 }
1976
1977 static int bus_message_open_dict_entry(
1978 sd_bus_message *m,
1979 struct bus_container *c,
1980 const char *contents,
1981 size_t *begin,
1982 bool *need_offsets) {
1983
1984 int r;
1985
1986 assert(m);
1987 assert(c);
1988 assert(contents);
1989 assert(begin);
1990 assert(need_offsets);
1991
1992 if (!signature_is_pair(contents))
1993 return -EINVAL;
1994
1995 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1996 return -ENXIO;
1997
1998 if (c->signature && c->signature[c->index]) {
1999 size_t l;
2000
2001 l = strlen(contents);
2002
2003 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
2004 !startswith(c->signature + c->index + 1, contents) ||
2005 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
2006 return -ENXIO;
2007 } else
2008 return -ENXIO;
2009
2010 if (BUS_MESSAGE_IS_GVARIANT(m)) {
2011 int alignment;
2012
2013 alignment = bus_gvariant_get_alignment(contents);
2014 if (alignment < 0)
2015 return alignment;
2016
2017 if (!message_extend_body(m, alignment, 0, false, false))
2018 return -ENOMEM;
2019
2020 r = bus_gvariant_is_fixed_size(contents);
2021 if (r < 0)
2022 return r;
2023
2024 *begin = m->body_size;
2025 *need_offsets = r == 0;
2026 } else {
2027 /* Align contents to 8 byte boundary */
2028 if (!message_extend_body(m, 8, 0, false, false))
2029 return -ENOMEM;
2030 }
2031
2032 return 0;
2033 }
2034
2035 _public_ int sd_bus_message_open_container(
2036 sd_bus_message *m,
2037 char type,
2038 const char *contents) {
2039
2040 struct bus_container *c, *w;
2041 uint32_t *array_size = NULL;
2042 char *signature;
2043 size_t before, begin = 0;
2044 bool need_offsets = false;
2045 int r;
2046
2047 assert_return(m, -EINVAL);
2048 assert_return(!m->sealed, -EPERM);
2049 assert_return(contents, -EINVAL);
2050 assert_return(!m->poisoned, -ESTALE);
2051
2052 /* Make sure we have space for one more container */
2053 if (!GREEDY_REALLOC(m->containers, m->containers_allocated, m->n_containers + 1)) {
2054 m->poisoned = true;
2055 return -ENOMEM;
2056 }
2057
2058 c = message_get_container(m);
2059
2060 signature = strdup(contents);
2061 if (!signature) {
2062 m->poisoned = true;
2063 return -ENOMEM;
2064 }
2065
2066 /* Save old index in the parent container, in case we have to
2067 * abort this container */
2068 c->saved_index = c->index;
2069 before = m->body_size;
2070
2071 if (type == SD_BUS_TYPE_ARRAY)
2072 r = bus_message_open_array(m, c, contents, &array_size, &begin, &need_offsets);
2073 else if (type == SD_BUS_TYPE_VARIANT)
2074 r = bus_message_open_variant(m, c, contents);
2075 else if (type == SD_BUS_TYPE_STRUCT)
2076 r = bus_message_open_struct(m, c, contents, &begin, &need_offsets);
2077 else if (type == SD_BUS_TYPE_DICT_ENTRY)
2078 r = bus_message_open_dict_entry(m, c, contents, &begin, &need_offsets);
2079 else
2080 r = -EINVAL;
2081
2082 if (r < 0) {
2083 free(signature);
2084 return r;
2085 }
2086
2087 /* OK, let's fill it in */
2088 w = m->containers + m->n_containers++;
2089 w->enclosing = type;
2090 w->signature = signature;
2091 w->index = 0;
2092 w->array_size = array_size;
2093 w->before = before;
2094 w->begin = begin;
2095 w->n_offsets = w->offsets_allocated = 0;
2096 w->offsets = NULL;
2097 w->need_offsets = need_offsets;
2098
2099 return 0;
2100 }
2101
2102 static int bus_message_close_array(sd_bus_message *m, struct bus_container *c) {
2103
2104 assert(m);
2105 assert(c);
2106
2107 if (!BUS_MESSAGE_IS_GVARIANT(m))
2108 return 0;
2109
2110 if (c->need_offsets) {
2111 size_t payload, sz, i;
2112 uint8_t *a;
2113
2114 /* Variable-width arrays */
2115
2116 payload = c->n_offsets > 0 ? c->offsets[c->n_offsets-1] - c->begin : 0;
2117 sz = bus_gvariant_determine_word_size(payload, c->n_offsets);
2118
2119 a = message_extend_body(m, 1, sz * c->n_offsets, true, false);
2120 if (!a)
2121 return -ENOMEM;
2122
2123 for (i = 0; i < c->n_offsets; i++)
2124 bus_gvariant_write_word_le(a + sz*i, sz, c->offsets[i] - c->begin);
2125 } else {
2126 void *a;
2127
2128 /* Fixed-width or empty arrays */
2129
2130 a = message_extend_body(m, 1, 0, true, false); /* let's add offset to parent */
2131 if (!a)
2132 return -ENOMEM;
2133 }
2134
2135 return 0;
2136 }
2137
2138 static int bus_message_close_variant(sd_bus_message *m, struct bus_container *c) {
2139 uint8_t *a;
2140 size_t l;
2141
2142 assert(m);
2143 assert(c);
2144 assert(c->signature);
2145
2146 if (!BUS_MESSAGE_IS_GVARIANT(m))
2147 return 0;
2148
2149 l = strlen(c->signature);
2150
2151 a = message_extend_body(m, 1, 1 + l, true, false);
2152 if (!a)
2153 return -ENOMEM;
2154
2155 a[0] = 0;
2156 memcpy(a+1, c->signature, l);
2157
2158 return 0;
2159 }
2160
2161 static int bus_message_close_struct(sd_bus_message *m, struct bus_container *c, bool add_offset) {
2162 bool fixed_size = true;
2163 size_t n_variable = 0;
2164 unsigned i = 0;
2165 const char *p;
2166 uint8_t *a;
2167 int r;
2168
2169 assert(m);
2170 assert(c);
2171
2172 if (!BUS_MESSAGE_IS_GVARIANT(m))
2173 return 0;
2174
2175 p = strempty(c->signature);
2176 while (*p != 0) {
2177 size_t n;
2178
2179 r = signature_element_length(p, &n);
2180 if (r < 0)
2181 return r;
2182 else {
2183 char t[n+1];
2184
2185 memcpy(t, p, n);
2186 t[n] = 0;
2187
2188 r = bus_gvariant_is_fixed_size(t);
2189 if (r < 0)
2190 return r;
2191 }
2192
2193 assert(!c->need_offsets || i <= c->n_offsets);
2194
2195 /* We need to add an offset for each item that has a
2196 * variable size and that is not the last one in the
2197 * list */
2198 if (r == 0)
2199 fixed_size = false;
2200 if (r == 0 && p[n] != 0)
2201 n_variable++;
2202
2203 i++;
2204 p += n;
2205 }
2206
2207 assert(!c->need_offsets || i == c->n_offsets);
2208 assert(c->need_offsets || n_variable == 0);
2209
2210 if (isempty(c->signature)) {
2211 /* The unary type is encoded as fixed 1 byte padding */
2212 a = message_extend_body(m, 1, 1, add_offset, false);
2213 if (!a)
2214 return -ENOMEM;
2215
2216 *a = 0;
2217 } else if (n_variable <= 0) {
2218 int alignment = 1;
2219
2220 /* Structures with fixed-size members only have to be
2221 * fixed-size themselves. But gvariant requires all fixed-size
2222 * elements to be sized a multiple of their alignment. Hence,
2223 * we must *always* add final padding after the last member so
2224 * the overall size of the structure is properly aligned. */
2225 if (fixed_size)
2226 alignment = bus_gvariant_get_alignment(strempty(c->signature));
2227
2228 assert(alignment > 0);
2229
2230 a = message_extend_body(m, alignment, 0, add_offset, false);
2231 if (!a)
2232 return -ENOMEM;
2233 } else {
2234 size_t sz;
2235 unsigned j;
2236
2237 assert(c->offsets[c->n_offsets-1] == m->body_size);
2238
2239 sz = bus_gvariant_determine_word_size(m->body_size - c->begin, n_variable);
2240
2241 a = message_extend_body(m, 1, sz * n_variable, add_offset, false);
2242 if (!a)
2243 return -ENOMEM;
2244
2245 p = strempty(c->signature);
2246 for (i = 0, j = 0; i < c->n_offsets; i++) {
2247 unsigned k;
2248 size_t n;
2249
2250 r = signature_element_length(p, &n);
2251 if (r < 0)
2252 return r;
2253 else {
2254 char t[n+1];
2255
2256 memcpy(t, p, n);
2257 t[n] = 0;
2258
2259 p += n;
2260
2261 r = bus_gvariant_is_fixed_size(t);
2262 if (r < 0)
2263 return r;
2264 if (r > 0 || p[0] == 0)
2265 continue;
2266 }
2267
2268 k = n_variable - 1 - j;
2269
2270 bus_gvariant_write_word_le(a + k * sz, sz, c->offsets[i] - c->begin);
2271
2272 j++;
2273 }
2274 }
2275
2276 return 0;
2277 }
2278
2279 _public_ int sd_bus_message_close_container(sd_bus_message *m) {
2280 struct bus_container *c;
2281 int r;
2282
2283 assert_return(m, -EINVAL);
2284 assert_return(!m->sealed, -EPERM);
2285 assert_return(m->n_containers > 0, -EINVAL);
2286 assert_return(!m->poisoned, -ESTALE);
2287
2288 c = message_get_container(m);
2289
2290 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2291 if (c->signature && c->signature[c->index] != 0)
2292 return -EINVAL;
2293
2294 m->n_containers--;
2295
2296 if (c->enclosing == SD_BUS_TYPE_ARRAY)
2297 r = bus_message_close_array(m, c);
2298 else if (c->enclosing == SD_BUS_TYPE_VARIANT)
2299 r = bus_message_close_variant(m, c);
2300 else if (c->enclosing == SD_BUS_TYPE_STRUCT || c->enclosing == SD_BUS_TYPE_DICT_ENTRY)
2301 r = bus_message_close_struct(m, c, true);
2302 else
2303 assert_not_reached("Unknown container type");
2304
2305 free(c->signature);
2306 free(c->offsets);
2307
2308 return r;
2309 }
2310
2311 typedef struct {
2312 const char *types;
2313 unsigned n_struct;
2314 unsigned n_array;
2315 } TypeStack;
2316
2317 static int type_stack_push(TypeStack *stack, unsigned max, unsigned *i, const char *types, unsigned n_struct, unsigned n_array) {
2318 assert(stack);
2319 assert(max > 0);
2320
2321 if (*i >= max)
2322 return -EINVAL;
2323
2324 stack[*i].types = types;
2325 stack[*i].n_struct = n_struct;
2326 stack[*i].n_array = n_array;
2327 (*i)++;
2328
2329 return 0;
2330 }
2331
2332 static int type_stack_pop(TypeStack *stack, unsigned max, unsigned *i, const char **types, unsigned *n_struct, unsigned *n_array) {
2333 assert(stack);
2334 assert(max > 0);
2335 assert(types);
2336 assert(n_struct);
2337 assert(n_array);
2338
2339 if (*i <= 0)
2340 return 0;
2341
2342 (*i)--;
2343 *types = stack[*i].types;
2344 *n_struct = stack[*i].n_struct;
2345 *n_array = stack[*i].n_array;
2346
2347 return 1;
2348 }
2349
2350 int bus_message_append_ap(
2351 sd_bus_message *m,
2352 const char *types,
2353 va_list ap) {
2354
2355 unsigned n_array, n_struct;
2356 TypeStack stack[BUS_CONTAINER_DEPTH];
2357 unsigned stack_ptr = 0;
2358 int r;
2359
2360 assert(m);
2361
2362 if (!types)
2363 return 0;
2364
2365 n_array = (unsigned) -1;
2366 n_struct = strlen(types);
2367
2368 for (;;) {
2369 const char *t;
2370
2371 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
2372 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
2373 if (r < 0)
2374 return r;
2375 if (r == 0)
2376 break;
2377
2378 r = sd_bus_message_close_container(m);
2379 if (r < 0)
2380 return r;
2381
2382 continue;
2383 }
2384
2385 t = types;
2386 if (n_array != (unsigned) -1)
2387 n_array --;
2388 else {
2389 types ++;
2390 n_struct--;
2391 }
2392
2393 switch (*t) {
2394
2395 case SD_BUS_TYPE_BYTE: {
2396 uint8_t x;
2397
2398 x = (uint8_t) va_arg(ap, int);
2399 r = sd_bus_message_append_basic(m, *t, &x);
2400 break;
2401 }
2402
2403 case SD_BUS_TYPE_BOOLEAN:
2404 case SD_BUS_TYPE_INT32:
2405 case SD_BUS_TYPE_UINT32:
2406 case SD_BUS_TYPE_UNIX_FD: {
2407 uint32_t x;
2408
2409 /* We assume a boolean is the same as int32_t */
2410 assert_cc(sizeof(int32_t) == sizeof(int));
2411
2412 x = va_arg(ap, uint32_t);
2413 r = sd_bus_message_append_basic(m, *t, &x);
2414 break;
2415 }
2416
2417 case SD_BUS_TYPE_INT16:
2418 case SD_BUS_TYPE_UINT16: {
2419 uint16_t x;
2420
2421 x = (uint16_t) va_arg(ap, int);
2422 r = sd_bus_message_append_basic(m, *t, &x);
2423 break;
2424 }
2425
2426 case SD_BUS_TYPE_INT64:
2427 case SD_BUS_TYPE_UINT64: {
2428 uint64_t x;
2429
2430 x = va_arg(ap, uint64_t);
2431 r = sd_bus_message_append_basic(m, *t, &x);
2432 break;
2433 }
2434
2435 case SD_BUS_TYPE_DOUBLE: {
2436 double x;
2437
2438 x = va_arg(ap, double);
2439 r = sd_bus_message_append_basic(m, *t, &x);
2440 break;
2441 }
2442
2443 case SD_BUS_TYPE_STRING:
2444 case SD_BUS_TYPE_OBJECT_PATH:
2445 case SD_BUS_TYPE_SIGNATURE: {
2446 const char *x;
2447
2448 x = va_arg(ap, const char*);
2449 r = sd_bus_message_append_basic(m, *t, x);
2450 break;
2451 }
2452
2453 case SD_BUS_TYPE_ARRAY: {
2454 size_t k;
2455
2456 r = signature_element_length(t + 1, &k);
2457 if (r < 0)
2458 return r;
2459
2460 {
2461 char s[k + 1];
2462 memcpy(s, t + 1, k);
2463 s[k] = 0;
2464
2465 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, s);
2466 if (r < 0)
2467 return r;
2468 }
2469
2470 if (n_array == (unsigned) -1) {
2471 types += k;
2472 n_struct -= k;
2473 }
2474
2475 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2476 if (r < 0)
2477 return r;
2478
2479 types = t + 1;
2480 n_struct = k;
2481 n_array = va_arg(ap, unsigned);
2482
2483 break;
2484 }
2485
2486 case SD_BUS_TYPE_VARIANT: {
2487 const char *s;
2488
2489 s = va_arg(ap, const char*);
2490 if (!s)
2491 return -EINVAL;
2492
2493 r = sd_bus_message_open_container(m, SD_BUS_TYPE_VARIANT, s);
2494 if (r < 0)
2495 return r;
2496
2497 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2498 if (r < 0)
2499 return r;
2500
2501 types = s;
2502 n_struct = strlen(s);
2503 n_array = (unsigned) -1;
2504
2505 break;
2506 }
2507
2508 case SD_BUS_TYPE_STRUCT_BEGIN:
2509 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
2510 size_t k;
2511
2512 r = signature_element_length(t, &k);
2513 if (r < 0)
2514 return r;
2515
2516 {
2517 char s[k - 1];
2518
2519 memcpy(s, t + 1, k - 2);
2520 s[k - 2] = 0;
2521
2522 r = sd_bus_message_open_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
2523 if (r < 0)
2524 return r;
2525 }
2526
2527 if (n_array == (unsigned) -1) {
2528 types += k - 1;
2529 n_struct -= k - 1;
2530 }
2531
2532 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2533 if (r < 0)
2534 return r;
2535
2536 types = t + 1;
2537 n_struct = k - 2;
2538 n_array = (unsigned) -1;
2539
2540 break;
2541 }
2542
2543 default:
2544 r = -EINVAL;
2545 }
2546
2547 if (r < 0)
2548 return r;
2549 }
2550
2551 return 1;
2552 }
2553
2554 _public_ int sd_bus_message_append(sd_bus_message *m, const char *types, ...) {
2555 va_list ap;
2556 int r;
2557
2558 assert_return(m, -EINVAL);
2559 assert_return(types, -EINVAL);
2560 assert_return(!m->sealed, -EPERM);
2561 assert_return(!m->poisoned, -ESTALE);
2562
2563 va_start(ap, types);
2564 r = bus_message_append_ap(m, types, ap);
2565 va_end(ap);
2566
2567 return r;
2568 }
2569
2570 _public_ int sd_bus_message_append_array_space(
2571 sd_bus_message *m,
2572 char type,
2573 size_t size,
2574 void **ptr) {
2575
2576 ssize_t align, sz;
2577 void *a;
2578 int r;
2579
2580 assert_return(m, -EINVAL);
2581 assert_return(!m->sealed, -EPERM);
2582 assert_return(bus_type_is_trivial(type) && type != SD_BUS_TYPE_BOOLEAN, -EINVAL);
2583 assert_return(ptr || size == 0, -EINVAL);
2584 assert_return(!m->poisoned, -ESTALE);
2585
2586 /* alignment and size of the trivial types (except bool) is
2587 * identical for gvariant and dbus1 marshalling */
2588 align = bus_type_get_alignment(type);
2589 sz = bus_type_get_size(type);
2590
2591 assert_se(align > 0);
2592 assert_se(sz > 0);
2593
2594 if (size % sz != 0)
2595 return -EINVAL;
2596
2597 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2598 if (r < 0)
2599 return r;
2600
2601 a = message_extend_body(m, align, size, false, false);
2602 if (!a)
2603 return -ENOMEM;
2604
2605 r = sd_bus_message_close_container(m);
2606 if (r < 0)
2607 return r;
2608
2609 *ptr = a;
2610 return 0;
2611 }
2612
2613 _public_ int sd_bus_message_append_array(
2614 sd_bus_message *m,
2615 char type,
2616 const void *ptr,
2617 size_t size) {
2618 int r;
2619 void *p;
2620
2621 assert_return(m, -EINVAL);
2622 assert_return(!m->sealed, -EPERM);
2623 assert_return(bus_type_is_trivial(type), -EINVAL);
2624 assert_return(ptr || size == 0, -EINVAL);
2625 assert_return(!m->poisoned, -ESTALE);
2626
2627 r = sd_bus_message_append_array_space(m, type, size, &p);
2628 if (r < 0)
2629 return r;
2630
2631 if (size > 0)
2632 memcpy(p, ptr, size);
2633
2634 return 0;
2635 }
2636
2637 _public_ int sd_bus_message_append_array_iovec(
2638 sd_bus_message *m,
2639 char type,
2640 const struct iovec *iov,
2641 unsigned n) {
2642
2643 size_t size;
2644 unsigned i;
2645 void *p;
2646 int r;
2647
2648 assert_return(m, -EINVAL);
2649 assert_return(!m->sealed, -EPERM);
2650 assert_return(bus_type_is_trivial(type), -EINVAL);
2651 assert_return(iov || n == 0, -EINVAL);
2652 assert_return(!m->poisoned, -ESTALE);
2653
2654 size = IOVEC_TOTAL_SIZE(iov, n);
2655
2656 r = sd_bus_message_append_array_space(m, type, size, &p);
2657 if (r < 0)
2658 return r;
2659
2660 for (i = 0; i < n; i++) {
2661
2662 if (iov[i].iov_base)
2663 memcpy(p, iov[i].iov_base, iov[i].iov_len);
2664 else
2665 memzero(p, iov[i].iov_len);
2666
2667 p = (uint8_t*) p + iov[i].iov_len;
2668 }
2669
2670 return 0;
2671 }
2672
2673 _public_ int sd_bus_message_append_array_memfd(
2674 sd_bus_message *m,
2675 char type,
2676 int memfd,
2677 uint64_t offset,
2678 uint64_t size) {
2679
2680 _cleanup_close_ int copy_fd = -1;
2681 struct bus_body_part *part;
2682 ssize_t align, sz;
2683 uint64_t real_size;
2684 void *a;
2685 int r;
2686
2687 assert_return(m, -EINVAL);
2688 assert_return(memfd >= 0, -EBADF);
2689 assert_return(bus_type_is_trivial(type), -EINVAL);
2690 assert_return(size > 0, -EINVAL);
2691 assert_return(!m->sealed, -EPERM);
2692 assert_return(!m->poisoned, -ESTALE);
2693
2694 r = memfd_set_sealed(memfd);
2695 if (r < 0)
2696 return r;
2697
2698 copy_fd = dup(memfd);
2699 if (copy_fd < 0)
2700 return copy_fd;
2701
2702 r = memfd_get_size(memfd, &real_size);
2703 if (r < 0)
2704 return r;
2705
2706 if (offset == 0 && size == (uint64_t) -1)
2707 size = real_size;
2708 else if (offset + size > real_size)
2709 return -EMSGSIZE;
2710
2711 align = bus_type_get_alignment(type);
2712 sz = bus_type_get_size(type);
2713
2714 assert_se(align > 0);
2715 assert_se(sz > 0);
2716
2717 if (offset % align != 0)
2718 return -EINVAL;
2719
2720 if (size % sz != 0)
2721 return -EINVAL;
2722
2723 if (size > (uint64_t) (uint32_t) -1)
2724 return -EINVAL;
2725
2726 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2727 if (r < 0)
2728 return r;
2729
2730 a = message_extend_body(m, align, 0, false, false);
2731 if (!a)
2732 return -ENOMEM;
2733
2734 part = message_append_part(m);
2735 if (!part)
2736 return -ENOMEM;
2737
2738 part->memfd = copy_fd;
2739 part->memfd_offset = offset;
2740 part->sealed = true;
2741 part->size = size;
2742 copy_fd = -1;
2743
2744 m->body_size += size;
2745 message_extend_containers(m, size);
2746
2747 return sd_bus_message_close_container(m);
2748 }
2749
2750 _public_ int sd_bus_message_append_string_memfd(
2751 sd_bus_message *m,
2752 int memfd,
2753 uint64_t offset,
2754 uint64_t size) {
2755
2756 _cleanup_close_ int copy_fd = -1;
2757 struct bus_body_part *part;
2758 struct bus_container *c;
2759 uint64_t real_size;
2760 void *a;
2761 int r;
2762
2763 assert_return(m, -EINVAL);
2764 assert_return(memfd >= 0, -EBADF);
2765 assert_return(size > 0, -EINVAL);
2766 assert_return(!m->sealed, -EPERM);
2767 assert_return(!m->poisoned, -ESTALE);
2768
2769 r = memfd_set_sealed(memfd);
2770 if (r < 0)
2771 return r;
2772
2773 copy_fd = dup(memfd);
2774 if (copy_fd < 0)
2775 return copy_fd;
2776
2777 r = memfd_get_size(memfd, &real_size);
2778 if (r < 0)
2779 return r;
2780
2781 if (offset == 0 && size == (uint64_t) -1)
2782 size = real_size;
2783 else if (offset + size > real_size)
2784 return -EMSGSIZE;
2785
2786 /* We require this to be NUL terminated */
2787 if (size == 0)
2788 return -EINVAL;
2789
2790 if (size > (uint64_t) (uint32_t) -1)
2791 return -EINVAL;
2792
2793 c = message_get_container(m);
2794 if (c->signature && c->signature[c->index]) {
2795 /* Container signature is already set */
2796
2797 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
2798 return -ENXIO;
2799 } else {
2800 char *e;
2801
2802 /* Maybe we can append to the signature? But only if this is the top-level container */
2803 if (c->enclosing != 0)
2804 return -ENXIO;
2805
2806 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
2807 if (!e) {
2808 m->poisoned = true;
2809 return -ENOMEM;
2810 }
2811 }
2812
2813 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
2814 a = message_extend_body(m, 4, 4, false, false);
2815 if (!a)
2816 return -ENOMEM;
2817
2818 *(uint32_t*) a = size - 1;
2819 }
2820
2821 part = message_append_part(m);
2822 if (!part)
2823 return -ENOMEM;
2824
2825 part->memfd = copy_fd;
2826 part->memfd_offset = offset;
2827 part->sealed = true;
2828 part->size = size;
2829 copy_fd = -1;
2830
2831 m->body_size += size;
2832 message_extend_containers(m, size);
2833
2834 if (BUS_MESSAGE_IS_GVARIANT(m)) {
2835 r = message_add_offset(m, m->body_size);
2836 if (r < 0) {
2837 m->poisoned = true;
2838 return -ENOMEM;
2839 }
2840 }
2841
2842 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2843 c->index++;
2844
2845 return 0;
2846 }
2847
2848 _public_ int sd_bus_message_append_strv(sd_bus_message *m, char **l) {
2849 char **i;
2850 int r;
2851
2852 assert_return(m, -EINVAL);
2853 assert_return(!m->sealed, -EPERM);
2854 assert_return(!m->poisoned, -ESTALE);
2855
2856 r = sd_bus_message_open_container(m, 'a', "s");
2857 if (r < 0)
2858 return r;
2859
2860 STRV_FOREACH(i, l) {
2861 r = sd_bus_message_append_basic(m, 's', *i);
2862 if (r < 0)
2863 return r;
2864 }
2865
2866 return sd_bus_message_close_container(m);
2867 }
2868
2869 static int bus_message_close_header(sd_bus_message *m) {
2870
2871 assert(m);
2872
2873 /* The actual user data is finished now, we just complete the
2874 variant and struct now (at least on gvariant). Remember
2875 this position, so that during parsing we know where to to
2876 put the outer container end. */
2877 m->user_body_size = m->body_size;
2878
2879 if (BUS_MESSAGE_IS_GVARIANT(m)) {
2880 const char *signature;
2881 size_t sz, l;
2882 void *d;
2883
2884 /* Add offset table to end of fields array */
2885 if (m->n_header_offsets >= 1) {
2886 uint8_t *a;
2887 unsigned i;
2888
2889 assert(m->fields_size == m->header_offsets[m->n_header_offsets-1]);
2890
2891 sz = bus_gvariant_determine_word_size(m->fields_size, m->n_header_offsets);
2892 a = message_extend_fields(m, 1, sz * m->n_header_offsets, false);
2893 if (!a)
2894 return -ENOMEM;
2895
2896 for (i = 0; i < m->n_header_offsets; i++)
2897 bus_gvariant_write_word_le(a + sz*i, sz, m->header_offsets[i]);
2898 }
2899
2900 /* Add gvariant NUL byte plus signature to the end of
2901 * the body, followed by the final offset pointing to
2902 * the end of the fields array */
2903
2904 signature = strempty(m->root_container.signature);
2905 l = strlen(signature);
2906
2907 sz = bus_gvariant_determine_word_size(sizeof(struct bus_header) + ALIGN8(m->fields_size) + m->body_size + 1 + l + 2, 1);
2908 d = message_extend_body(m, 1, 1 + l + 2 + sz, false, true);
2909 if (!d)
2910 return -ENOMEM;
2911
2912 *(uint8_t*) d = 0;
2913 *((uint8_t*) d + 1) = SD_BUS_TYPE_STRUCT_BEGIN;
2914 memcpy((uint8_t*) d + 2, signature, l);
2915 *((uint8_t*) d + 1 + l + 1) = SD_BUS_TYPE_STRUCT_END;
2916
2917 bus_gvariant_write_word_le((uint8_t*) d + 1 + l + 2, sz, sizeof(struct bus_header) + m->fields_size);
2918
2919 m->footer = d;
2920 m->footer_accessible = 1 + l + 2 + sz;
2921 } else {
2922 m->header->dbus1.fields_size = m->fields_size;
2923 m->header->dbus1.body_size = m->body_size;
2924 }
2925
2926 return 0;
2927 }
2928
2929 int bus_message_seal(sd_bus_message *m, uint64_t cookie, usec_t timeout) {
2930 struct bus_body_part *part;
2931 size_t a;
2932 unsigned i;
2933 int r;
2934
2935 assert(m);
2936
2937 if (m->sealed)
2938 return -EPERM;
2939
2940 if (m->n_containers > 0)
2941 return -EBADMSG;
2942
2943 if (m->poisoned)
2944 return -ESTALE;
2945
2946 if (cookie > 0xffffffffULL &&
2947 !BUS_MESSAGE_IS_GVARIANT(m))
2948 return -EOPNOTSUPP;
2949
2950 /* In vtables the return signature of method calls is listed,
2951 * let's check if they match if this is a response */
2952 if (m->header->type == SD_BUS_MESSAGE_METHOD_RETURN &&
2953 m->enforced_reply_signature &&
2954 !streq(strempty(m->root_container.signature), m->enforced_reply_signature))
2955 return -ENOMSG;
2956
2957 /* If gvariant marshalling is used we need to close the body structure */
2958 r = bus_message_close_struct(m, &m->root_container, false);
2959 if (r < 0)
2960 return r;
2961
2962 /* If there's a non-trivial signature set, then add it in
2963 * here, but only on dbus1 */
2964 if (!isempty(m->root_container.signature) && !BUS_MESSAGE_IS_GVARIANT(m)) {
2965 r = message_append_field_signature(m, BUS_MESSAGE_HEADER_SIGNATURE, m->root_container.signature, NULL);
2966 if (r < 0)
2967 return r;
2968 }
2969
2970 if (m->n_fds > 0) {
2971 r = message_append_field_uint32(m, BUS_MESSAGE_HEADER_UNIX_FDS, m->n_fds);
2972 if (r < 0)
2973 return r;
2974 }
2975
2976 r = bus_message_close_header(m);
2977 if (r < 0)
2978 return r;
2979
2980 if (BUS_MESSAGE_IS_GVARIANT(m))
2981 m->header->dbus2.cookie = cookie;
2982 else
2983 m->header->dbus1.serial = (uint32_t) cookie;
2984
2985 m->timeout = m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED ? 0 : timeout;
2986
2987 /* Add padding at the end of the fields part, since we know
2988 * the body needs to start at an 8 byte alignment. We made
2989 * sure we allocated enough space for this, so all we need to
2990 * do here is to zero it out. */
2991 a = ALIGN8(m->fields_size) - m->fields_size;
2992 if (a > 0)
2993 memzero((uint8_t*) BUS_MESSAGE_FIELDS(m) + m->fields_size, a);
2994
2995 /* If this is something we can send as memfd, then let's seal
2996 the memfd now. Note that we can send memfds as payload only
2997 for directed messages, and not for broadcasts. */
2998 if (m->destination && m->bus->use_memfd) {
2999 MESSAGE_FOREACH_PART(part, i, m)
3000 if (part->memfd >= 0 &&
3001 !part->sealed &&
3002 (part->size > MEMFD_MIN_SIZE || m->bus->use_memfd < 0) &&
3003 part != m->body_end) { /* The last part may never be sent as memfd */
3004 uint64_t sz;
3005
3006 /* Try to seal it if that makes
3007 * sense. First, unmap our own map to
3008 * make sure we don't keep it busy. */
3009 bus_body_part_unmap(part);
3010
3011 /* Then, sync up real memfd size */
3012 sz = part->size;
3013 r = memfd_set_size(part->memfd, sz);
3014 if (r < 0)
3015 return r;
3016
3017 /* Finally, try to seal */
3018 if (memfd_set_sealed(part->memfd) >= 0)
3019 part->sealed = true;
3020 }
3021 }
3022
3023 m->root_container.end = m->user_body_size;
3024 m->root_container.index = 0;
3025 m->root_container.offset_index = 0;
3026 m->root_container.item_size = m->root_container.n_offsets > 0 ? m->root_container.offsets[0] : 0;
3027
3028 m->sealed = true;
3029
3030 return 0;
3031 }
3032
3033 int bus_body_part_map(struct bus_body_part *part) {
3034 void *p;
3035 size_t psz, shift;
3036
3037 assert_se(part);
3038
3039 if (part->data)
3040 return 0;
3041
3042 if (part->size <= 0)
3043 return 0;
3044
3045 /* For smaller zero parts (as used for padding) we don't need to map anything... */
3046 if (part->memfd < 0 && part->is_zero && part->size < 8) {
3047 static const uint8_t zeroes[7] = { };
3048 part->data = (void*) zeroes;
3049 return 0;
3050 }
3051
3052 shift = part->memfd_offset - ((part->memfd_offset / page_size()) * page_size());
3053 psz = PAGE_ALIGN(part->size + shift);
3054
3055 if (part->memfd >= 0)
3056 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE, part->memfd, part->memfd_offset - shift);
3057 else if (part->is_zero)
3058 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
3059 else
3060 return -EINVAL;
3061
3062 if (p == MAP_FAILED)
3063 return -errno;
3064
3065 part->mapped = psz;
3066 part->mmap_begin = p;
3067 part->data = (uint8_t*) p + shift;
3068 part->munmap_this = true;
3069
3070 return 0;
3071 }
3072
3073 void bus_body_part_unmap(struct bus_body_part *part) {
3074
3075 assert_se(part);
3076
3077 if (part->memfd < 0)
3078 return;
3079
3080 if (!part->mmap_begin)
3081 return;
3082
3083 if (!part->munmap_this)
3084 return;
3085
3086 assert_se(munmap(part->mmap_begin, part->mapped) == 0);
3087
3088 part->mmap_begin = NULL;
3089 part->data = NULL;
3090 part->mapped = 0;
3091 part->munmap_this = false;
3092
3093 return;
3094 }
3095
3096 static int buffer_peek(const void *p, uint32_t sz, size_t *rindex, size_t align, size_t nbytes, void **r) {
3097 size_t k, start, end;
3098
3099 assert(rindex);
3100 assert(align > 0);
3101
3102 start = ALIGN_TO((size_t) *rindex, align);
3103 end = start + nbytes;
3104
3105 if (end > sz)
3106 return -EBADMSG;
3107
3108 /* Verify that padding is 0 */
3109 for (k = *rindex; k < start; k++)
3110 if (((const uint8_t*) p)[k] != 0)
3111 return -EBADMSG;
3112
3113 if (r)
3114 *r = (uint8_t*) p + start;
3115
3116 *rindex = end;
3117
3118 return 1;
3119 }
3120
3121 static bool message_end_of_signature(sd_bus_message *m) {
3122 struct bus_container *c;
3123
3124 assert(m);
3125
3126 c = message_get_container(m);
3127 return !c->signature || c->signature[c->index] == 0;
3128 }
3129
3130 static bool message_end_of_array(sd_bus_message *m, size_t index) {
3131 struct bus_container *c;
3132
3133 assert(m);
3134
3135 c = message_get_container(m);
3136 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3137 return false;
3138
3139 if (BUS_MESSAGE_IS_GVARIANT(m))
3140 return index >= c->end;
3141 else {
3142 assert(c->array_size);
3143 return index >= c->begin + BUS_MESSAGE_BSWAP32(m, *c->array_size);
3144 }
3145 }
3146
3147 _public_ int sd_bus_message_at_end(sd_bus_message *m, int complete) {
3148 assert_return(m, -EINVAL);
3149 assert_return(m->sealed, -EPERM);
3150
3151 if (complete && m->n_containers > 0)
3152 return false;
3153
3154 if (message_end_of_signature(m))
3155 return true;
3156
3157 if (message_end_of_array(m, m->rindex))
3158 return true;
3159
3160 return false;
3161 }
3162
3163 static struct bus_body_part* find_part(sd_bus_message *m, size_t index, size_t sz, void **p) {
3164 struct bus_body_part *part;
3165 size_t begin;
3166 int r;
3167
3168 assert(m);
3169
3170 if (m->cached_rindex_part && index >= m->cached_rindex_part_begin) {
3171 part = m->cached_rindex_part;
3172 begin = m->cached_rindex_part_begin;
3173 } else {
3174 part = &m->body;
3175 begin = 0;
3176 }
3177
3178 while (part) {
3179 if (index < begin)
3180 return NULL;
3181
3182 if (index + sz <= begin + part->size) {
3183
3184 r = bus_body_part_map(part);
3185 if (r < 0)
3186 return NULL;
3187
3188 if (p)
3189 *p = (uint8_t*) part->data + index - begin;
3190
3191 m->cached_rindex_part = part;
3192 m->cached_rindex_part_begin = begin;
3193
3194 return part;
3195 }
3196
3197 begin += part->size;
3198 part = part->next;
3199 }
3200
3201 return NULL;
3202 }
3203
3204 static int container_next_item(sd_bus_message *m, struct bus_container *c, size_t *rindex) {
3205 int r;
3206
3207 assert(m);
3208 assert(c);
3209 assert(rindex);
3210
3211 if (!BUS_MESSAGE_IS_GVARIANT(m))
3212 return 0;
3213
3214 if (c->enclosing == SD_BUS_TYPE_ARRAY) {
3215 int sz;
3216
3217 sz = bus_gvariant_get_size(c->signature);
3218 if (sz < 0) {
3219 int alignment;
3220
3221 if (c->offset_index+1 >= c->n_offsets)
3222 goto end;
3223
3224 /* Variable-size array */
3225
3226 alignment = bus_gvariant_get_alignment(c->signature);
3227 assert(alignment > 0);
3228
3229 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3230 c->item_size = c->offsets[c->offset_index+1] - *rindex;
3231 } else {
3232
3233 if (c->offset_index+1 >= (c->end-c->begin)/sz)
3234 goto end;
3235
3236 /* Fixed-size array */
3237 *rindex = c->begin + (c->offset_index+1) * sz;
3238 c->item_size = sz;
3239 }
3240
3241 c->offset_index++;
3242
3243 } else if (c->enclosing == 0 ||
3244 c->enclosing == SD_BUS_TYPE_STRUCT ||
3245 c->enclosing == SD_BUS_TYPE_DICT_ENTRY) {
3246
3247 int alignment;
3248 size_t n, j;
3249
3250 if (c->offset_index+1 >= c->n_offsets)
3251 goto end;
3252
3253 r = signature_element_length(c->signature + c->index, &n);
3254 if (r < 0)
3255 return r;
3256
3257 r = signature_element_length(c->signature + c->index + n, &j);
3258 if (r < 0)
3259 return r;
3260 else {
3261 char t[j+1];
3262 memcpy(t, c->signature + c->index + n, j);
3263 t[j] = 0;
3264
3265 alignment = bus_gvariant_get_alignment(t);
3266 }
3267
3268 assert(alignment > 0);
3269
3270 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3271 c->item_size = c->offsets[c->offset_index+1] - *rindex;
3272
3273 c->offset_index++;
3274
3275 } else if (c->enclosing == SD_BUS_TYPE_VARIANT)
3276 goto end;
3277 else
3278 assert_not_reached("Unknown container type");
3279
3280 return 0;
3281
3282 end:
3283 /* Reached the end */
3284 *rindex = c->end;
3285 c->item_size = 0;
3286 return 0;
3287 }
3288
3289
3290 static int message_peek_body(
3291 sd_bus_message *m,
3292 size_t *rindex,
3293 size_t align,
3294 size_t nbytes,
3295 void **ret) {
3296
3297 size_t k, start, end, padding;
3298 struct bus_body_part *part;
3299 uint8_t *q;
3300
3301 assert(m);
3302 assert(rindex);
3303 assert(align > 0);
3304
3305 start = ALIGN_TO((size_t) *rindex, align);
3306 padding = start - *rindex;
3307 end = start + nbytes;
3308
3309 if (end > m->user_body_size)
3310 return -EBADMSG;
3311
3312 part = find_part(m, *rindex, padding, (void**) &q);
3313 if (!part)
3314 return -EBADMSG;
3315
3316 if (q) {
3317 /* Verify padding */
3318 for (k = 0; k < padding; k++)
3319 if (q[k] != 0)
3320 return -EBADMSG;
3321 }
3322
3323 part = find_part(m, start, nbytes, (void**) &q);
3324 if (!part || (nbytes > 0 && !q))
3325 return -EBADMSG;
3326
3327 *rindex = end;
3328
3329 if (ret)
3330 *ret = q;
3331
3332 return 0;
3333 }
3334
3335 static bool validate_nul(const char *s, size_t l) {
3336
3337 /* Check for NUL chars in the string */
3338 if (memchr(s, 0, l))
3339 return false;
3340
3341 /* Check for NUL termination */
3342 if (s[l] != 0)
3343 return false;
3344
3345 return true;
3346 }
3347
3348 static bool validate_string(const char *s, size_t l) {
3349
3350 if (!validate_nul(s, l))
3351 return false;
3352
3353 /* Check if valid UTF8 */
3354 if (!utf8_is_valid(s))
3355 return false;
3356
3357 return true;
3358 }
3359
3360 static bool validate_signature(const char *s, size_t l) {
3361
3362 if (!validate_nul(s, l))
3363 return false;
3364
3365 /* Check if valid signature */
3366 if (!signature_is_valid(s, true))
3367 return false;
3368
3369 return true;
3370 }
3371
3372 static bool validate_object_path(const char *s, size_t l) {
3373
3374 if (!validate_nul(s, l))
3375 return false;
3376
3377 if (!object_path_is_valid(s))
3378 return false;
3379
3380 return true;
3381 }
3382
3383 _public_ int sd_bus_message_read_basic(sd_bus_message *m, char type, void *p) {
3384 struct bus_container *c;
3385 size_t rindex;
3386 void *q;
3387 int r;
3388
3389 assert_return(m, -EINVAL);
3390 assert_return(m->sealed, -EPERM);
3391 assert_return(bus_type_is_basic(type), -EINVAL);
3392
3393 if (message_end_of_signature(m))
3394 return -ENXIO;
3395
3396 if (message_end_of_array(m, m->rindex))
3397 return 0;
3398
3399 c = message_get_container(m);
3400 if (c->signature[c->index] != type)
3401 return -ENXIO;
3402
3403 rindex = m->rindex;
3404
3405 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3406
3407 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE)) {
3408 bool ok;
3409
3410 r = message_peek_body(m, &rindex, 1, c->item_size, &q);
3411 if (r < 0)
3412 return r;
3413
3414 if (type == SD_BUS_TYPE_STRING)
3415 ok = validate_string(q, c->item_size-1);
3416 else if (type == SD_BUS_TYPE_OBJECT_PATH)
3417 ok = validate_object_path(q, c->item_size-1);
3418 else
3419 ok = validate_signature(q, c->item_size-1);
3420
3421 if (!ok)
3422 return -EBADMSG;
3423
3424 if (p)
3425 *(const char**) p = q;
3426 } else {
3427 int sz, align;
3428
3429 sz = bus_gvariant_get_size(CHAR_TO_STR(type));
3430 assert(sz > 0);
3431 if ((size_t) sz != c->item_size)
3432 return -EBADMSG;
3433
3434 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
3435 assert(align > 0);
3436
3437 r = message_peek_body(m, &rindex, align, c->item_size, &q);
3438 if (r < 0)
3439 return r;
3440
3441 switch (type) {
3442
3443 case SD_BUS_TYPE_BYTE:
3444 if (p)
3445 *(uint8_t*) p = *(uint8_t*) q;
3446 break;
3447
3448 case SD_BUS_TYPE_BOOLEAN:
3449 if (p)
3450 *(int*) p = !!*(uint8_t*) q;
3451 break;
3452
3453 case SD_BUS_TYPE_INT16:
3454 case SD_BUS_TYPE_UINT16:
3455 if (p)
3456 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3457 break;
3458
3459 case SD_BUS_TYPE_INT32:
3460 case SD_BUS_TYPE_UINT32:
3461 if (p)
3462 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3463 break;
3464
3465 case SD_BUS_TYPE_INT64:
3466 case SD_BUS_TYPE_UINT64:
3467 case SD_BUS_TYPE_DOUBLE:
3468 if (p)
3469 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3470 break;
3471
3472 case SD_BUS_TYPE_UNIX_FD: {
3473 uint32_t j;
3474
3475 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3476 if (j >= m->n_fds)
3477 return -EBADMSG;
3478
3479 if (p)
3480 *(int*) p = m->fds[j];
3481
3482 break;
3483 }
3484
3485 default:
3486 assert_not_reached("unexpected type");
3487 }
3488 }
3489
3490 r = container_next_item(m, c, &rindex);
3491 if (r < 0)
3492 return r;
3493 } else {
3494
3495 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH)) {
3496 uint32_t l;
3497 bool ok;
3498
3499 r = message_peek_body(m, &rindex, 4, 4, &q);
3500 if (r < 0)
3501 return r;
3502
3503 l = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3504 r = message_peek_body(m, &rindex, 1, l+1, &q);
3505 if (r < 0)
3506 return r;
3507
3508 if (type == SD_BUS_TYPE_OBJECT_PATH)
3509 ok = validate_object_path(q, l);
3510 else
3511 ok = validate_string(q, l);
3512 if (!ok)
3513 return -EBADMSG;
3514
3515 if (p)
3516 *(const char**) p = q;
3517
3518 } else if (type == SD_BUS_TYPE_SIGNATURE) {
3519 uint8_t l;
3520
3521 r = message_peek_body(m, &rindex, 1, 1, &q);
3522 if (r < 0)
3523 return r;
3524
3525 l = *(uint8_t*) q;
3526 r = message_peek_body(m, &rindex, 1, l+1, &q);
3527 if (r < 0)
3528 return r;
3529
3530 if (!validate_signature(q, l))
3531 return -EBADMSG;
3532
3533 if (p)
3534 *(const char**) p = q;
3535
3536 } else {
3537 ssize_t sz, align;
3538
3539 align = bus_type_get_alignment(type);
3540 assert(align > 0);
3541
3542 sz = bus_type_get_size(type);
3543 assert(sz > 0);
3544
3545 r = message_peek_body(m, &rindex, align, sz, &q);
3546 if (r < 0)
3547 return r;
3548
3549 switch (type) {
3550
3551 case SD_BUS_TYPE_BYTE:
3552 if (p)
3553 *(uint8_t*) p = *(uint8_t*) q;
3554 break;
3555
3556 case SD_BUS_TYPE_BOOLEAN:
3557 if (p)
3558 *(int*) p = !!*(uint32_t*) q;
3559 break;
3560
3561 case SD_BUS_TYPE_INT16:
3562 case SD_BUS_TYPE_UINT16:
3563 if (p)
3564 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3565 break;
3566
3567 case SD_BUS_TYPE_INT32:
3568 case SD_BUS_TYPE_UINT32:
3569 if (p)
3570 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3571 break;
3572
3573 case SD_BUS_TYPE_INT64:
3574 case SD_BUS_TYPE_UINT64:
3575 case SD_BUS_TYPE_DOUBLE:
3576 if (p)
3577 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3578 break;
3579
3580 case SD_BUS_TYPE_UNIX_FD: {
3581 uint32_t j;
3582
3583 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3584 if (j >= m->n_fds)
3585 return -EBADMSG;
3586
3587 if (p)
3588 *(int*) p = m->fds[j];
3589 break;
3590 }
3591
3592 default:
3593 assert_not_reached("Unknown basic type...");
3594 }
3595 }
3596 }
3597
3598 m->rindex = rindex;
3599
3600 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3601 c->index++;
3602
3603 return 1;
3604 }
3605
3606 static int bus_message_enter_array(
3607 sd_bus_message *m,
3608 struct bus_container *c,
3609 const char *contents,
3610 uint32_t **array_size,
3611 size_t *item_size,
3612 size_t **offsets,
3613 size_t *n_offsets) {
3614
3615 size_t rindex;
3616 void *q;
3617 int r, alignment;
3618
3619 assert(m);
3620 assert(c);
3621 assert(contents);
3622 assert(array_size);
3623 assert(item_size);
3624 assert(offsets);
3625 assert(n_offsets);
3626
3627 if (!signature_is_single(contents, true))
3628 return -EINVAL;
3629
3630 if (!c->signature || c->signature[c->index] == 0)
3631 return -ENXIO;
3632
3633 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
3634 return -ENXIO;
3635
3636 if (!startswith(c->signature + c->index + 1, contents))
3637 return -ENXIO;
3638
3639 rindex = m->rindex;
3640
3641 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3642 /* dbus1 */
3643
3644 r = message_peek_body(m, &rindex, 4, 4, &q);
3645 if (r < 0)
3646 return r;
3647
3648 if (BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q) > BUS_ARRAY_MAX_SIZE)
3649 return -EBADMSG;
3650
3651 alignment = bus_type_get_alignment(contents[0]);
3652 if (alignment < 0)
3653 return alignment;
3654
3655 r = message_peek_body(m, &rindex, alignment, 0, NULL);
3656 if (r < 0)
3657 return r;
3658
3659 *array_size = (uint32_t*) q;
3660
3661 } else if (c->item_size <= 0) {
3662
3663 /* gvariant: empty array */
3664 *item_size = 0;
3665 *offsets = NULL;
3666 *n_offsets = 0;
3667
3668 } else if (bus_gvariant_is_fixed_size(contents)) {
3669
3670 /* gvariant: fixed length array */
3671 *item_size = bus_gvariant_get_size(contents);
3672 *offsets = NULL;
3673 *n_offsets = 0;
3674
3675 } else {
3676 size_t where, p = 0, framing, sz;
3677 unsigned i;
3678
3679 /* gvariant: variable length array */
3680 sz = bus_gvariant_determine_word_size(c->item_size, 0);
3681
3682 where = rindex + c->item_size - sz;
3683 r = message_peek_body(m, &where, 1, sz, &q);
3684 if (r < 0)
3685 return r;
3686
3687 framing = bus_gvariant_read_word_le(q, sz);
3688 if (framing > c->item_size - sz)
3689 return -EBADMSG;
3690 if ((c->item_size - framing) % sz != 0)
3691 return -EBADMSG;
3692
3693 *n_offsets = (c->item_size - framing) / sz;
3694
3695 where = rindex + framing;
3696 r = message_peek_body(m, &where, 1, *n_offsets * sz, &q);
3697 if (r < 0)
3698 return r;
3699
3700 *offsets = new(size_t, *n_offsets);
3701 if (!*offsets)
3702 return -ENOMEM;
3703
3704 for (i = 0; i < *n_offsets; i++) {
3705 size_t x;
3706
3707 x = bus_gvariant_read_word_le((uint8_t*) q + i * sz, sz);
3708 if (x > c->item_size - sz)
3709 return -EBADMSG;
3710 if (x < p)
3711 return -EBADMSG;
3712
3713 (*offsets)[i] = rindex + x;
3714 p = x;
3715 }
3716
3717 *item_size = (*offsets)[0] - rindex;
3718 }
3719
3720 m->rindex = rindex;
3721
3722 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3723 c->index += 1 + strlen(contents);
3724
3725 return 1;
3726 }
3727
3728 static int bus_message_enter_variant(
3729 sd_bus_message *m,
3730 struct bus_container *c,
3731 const char *contents,
3732 size_t *item_size) {
3733
3734 size_t rindex;
3735 uint8_t l;
3736 void *q;
3737 int r;
3738
3739 assert(m);
3740 assert(c);
3741 assert(contents);
3742 assert(item_size);
3743
3744 if (!signature_is_single(contents, false))
3745 return -EINVAL;
3746
3747 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
3748 return -EINVAL;
3749
3750 if (!c->signature || c->signature[c->index] == 0)
3751 return -ENXIO;
3752
3753 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
3754 return -ENXIO;
3755
3756 rindex = m->rindex;
3757
3758 if (BUS_MESSAGE_IS_GVARIANT(m)) {
3759 size_t k, where;
3760
3761 k = strlen(contents);
3762 if (1+k > c->item_size)
3763 return -EBADMSG;
3764
3765 where = rindex + c->item_size - (1+k);
3766 r = message_peek_body(m, &where, 1, 1+k, &q);
3767 if (r < 0)
3768 return r;
3769
3770 if (*(char*) q != 0)
3771 return -EBADMSG;
3772
3773 if (memcmp((uint8_t*) q+1, contents, k))
3774 return -ENXIO;
3775
3776 *item_size = c->item_size - (1+k);
3777
3778 } else {
3779 r = message_peek_body(m, &rindex, 1, 1, &q);
3780 if (r < 0)
3781 return r;
3782
3783 l = *(uint8_t*) q;
3784 r = message_peek_body(m, &rindex, 1, l+1, &q);
3785 if (r < 0)
3786 return r;
3787
3788 if (!validate_signature(q, l))
3789 return -EBADMSG;
3790
3791 if (!streq(q, contents))
3792 return -ENXIO;
3793 }
3794
3795 m->rindex = rindex;
3796
3797 if (c->enclosing != SD_BUS_TYPE_ARRAY)
3798 c->index++;
3799
3800 return 1;
3801 }
3802
3803 static int build_struct_offsets(
3804 sd_bus_message *m,
3805 const char *signature,
3806 size_t size,
3807 size_t *item_size,
3808 size_t **offsets,
3809 size_t *n_offsets) {
3810
3811 unsigned n_variable = 0, n_total = 0, v;
3812 size_t previous = 0, where;
3813 const char *p;
3814 size_t sz;
3815 void *q;
3816 int r;
3817
3818 assert(m);
3819 assert(item_size);
3820 assert(offsets);
3821 assert(n_offsets);
3822
3823 if (isempty(signature)) {
3824 /* Unary type is encoded as *fixed* 1 byte padding */
3825 r = message_peek_body(m, &m->rindex, 1, 1, &q);
3826 if (r < 0)
3827 return r;
3828
3829 if (*(uint8_t *) q != 0)
3830 return -EBADMSG;
3831
3832 *item_size = 0;
3833 *offsets = NULL;
3834 *n_offsets = 0;
3835 return 0;
3836 }
3837
3838 sz = bus_gvariant_determine_word_size(size, 0);
3839 if (sz <= 0)
3840 return -EBADMSG;
3841
3842 /* First, loop over signature and count variable elements and
3843 * elements in general. We use this to know how large the
3844 * offset array is at the end of the structure. Note that
3845 * GVariant only stores offsets for all variable size elements
3846 * that are not the last item. */
3847
3848 p = signature;
3849 while (*p != 0) {
3850 size_t n;
3851
3852 r = signature_element_length(p, &n);
3853 if (r < 0)
3854 return r;
3855 else {
3856 char t[n+1];
3857
3858 memcpy(t, p, n);
3859 t[n] = 0;
3860
3861 r = bus_gvariant_is_fixed_size(t);
3862 }
3863
3864 if (r < 0)
3865 return r;
3866 if (r == 0 && p[n] != 0) /* except the last item */
3867 n_variable ++;
3868 n_total++;
3869
3870 p += n;
3871 }
3872
3873 if (size < n_variable * sz)
3874 return -EBADMSG;
3875
3876 where = m->rindex + size - (n_variable * sz);
3877 r = message_peek_body(m, &where, 1, n_variable * sz, &q);
3878 if (r < 0)
3879 return r;
3880
3881 v = n_variable;
3882
3883 *offsets = new(size_t, n_total);
3884 if (!*offsets)
3885 return -ENOMEM;
3886
3887 *n_offsets = 0;
3888
3889 /* Second, loop again and build an offset table */
3890 p = signature;
3891 while (*p != 0) {
3892 size_t n, offset;
3893 int k;
3894
3895 r = signature_element_length(p, &n);
3896 if (r < 0)
3897 return r;
3898 else {
3899 char t[n+1];
3900
3901 memcpy(t, p, n);
3902 t[n] = 0;
3903
3904 k = bus_gvariant_get_size(t);
3905 if (k < 0) {
3906 size_t x;
3907
3908 /* variable size */
3909 if (v > 0) {
3910 v--;
3911
3912 x = bus_gvariant_read_word_le((uint8_t*) q + v*sz, sz);
3913 if (x >= size)
3914 return -EBADMSG;
3915 if (m->rindex + x < previous)
3916 return -EBADMSG;
3917 } else
3918 /* The last item's end
3919 * is determined from
3920 * the start of the
3921 * offset array */
3922 x = size - (n_variable * sz);
3923
3924 offset = m->rindex + x;
3925
3926 } else {
3927 size_t align;
3928
3929 /* fixed size */
3930 align = bus_gvariant_get_alignment(t);
3931 assert(align > 0);
3932
3933 offset = (*n_offsets == 0 ? m->rindex : ALIGN_TO((*offsets)[*n_offsets-1], align)) + k;
3934 }
3935 }
3936
3937 previous = (*offsets)[(*n_offsets)++] = offset;
3938 p += n;
3939 }
3940
3941 assert(v == 0);
3942 assert(*n_offsets == n_total);
3943
3944 *item_size = (*offsets)[0] - m->rindex;
3945 return 0;
3946 }
3947
3948 static int enter_struct_or_dict_entry(
3949 sd_bus_message *m,
3950 struct bus_container *c,
3951 const char *contents,
3952 size_t *item_size,
3953 size_t **offsets,
3954 size_t *n_offsets) {
3955
3956 int r;
3957
3958 assert(m);
3959 assert(c);
3960 assert(contents);
3961 assert(item_size);
3962 assert(offsets);
3963 assert(n_offsets);
3964
3965 if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3966
3967 /* dbus1 */
3968 r = message_peek_body(m, &m->rindex, 8, 0, NULL);
3969 if (r < 0)
3970 return r;
3971
3972 } else
3973 /* gvariant with contents */
3974 return build_struct_offsets(m, contents, c->item_size, item_size, offsets, n_offsets);
3975
3976 return 0;
3977 }
3978
3979 static int bus_message_enter_struct(
3980 sd_bus_message *m,
3981 struct bus_container *c,
3982 const char *contents,
3983 size_t *item_size,
3984 size_t **offsets,
3985 size_t *n_offsets) {
3986
3987 size_t l;
3988 int r;
3989
3990 assert(m);
3991 assert(c);
3992 assert(contents);
3993 assert(item_size);
3994 assert(offsets);
3995 assert(n_offsets);
3996
3997 if (!signature_is_valid(contents, false))
3998 return -EINVAL;
3999
4000 if (!c->signature || c->signature[c->index] == 0)
4001 return -ENXIO;
4002
4003 l = strlen(contents);
4004
4005 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
4006 !startswith(c->signature + c->index + 1, contents) ||
4007 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
4008 return -ENXIO;
4009
4010 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
4011 if (r < 0)
4012 return r;
4013
4014 if (c->enclosing != SD_BUS_TYPE_ARRAY)
4015 c->index += 1 + l + 1;
4016
4017 return 1;
4018 }
4019
4020 static int bus_message_enter_dict_entry(
4021 sd_bus_message *m,
4022 struct bus_container *c,
4023 const char *contents,
4024 size_t *item_size,
4025 size_t **offsets,
4026 size_t *n_offsets) {
4027
4028 size_t l;
4029 int r;
4030
4031 assert(m);
4032 assert(c);
4033 assert(contents);
4034
4035 if (!signature_is_pair(contents))
4036 return -EINVAL;
4037
4038 if (c->enclosing != SD_BUS_TYPE_ARRAY)
4039 return -ENXIO;
4040
4041 if (!c->signature || c->signature[c->index] == 0)
4042 return 0;
4043
4044 l = strlen(contents);
4045
4046 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
4047 !startswith(c->signature + c->index + 1, contents) ||
4048 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
4049 return -ENXIO;
4050
4051 r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
4052 if (r < 0)
4053 return r;
4054
4055 if (c->enclosing != SD_BUS_TYPE_ARRAY)
4056 c->index += 1 + l + 1;
4057
4058 return 1;
4059 }
4060
4061 _public_ int sd_bus_message_enter_container(sd_bus_message *m,
4062 char type,
4063 const char *contents) {
4064 struct bus_container *c, *w;
4065 uint32_t *array_size = NULL;
4066 char *signature;
4067 size_t before;
4068 size_t *offsets = NULL;
4069 size_t n_offsets = 0, item_size = 0;
4070 int r;
4071
4072 assert_return(m, -EINVAL);
4073 assert_return(m->sealed, -EPERM);
4074 assert_return(type != 0 || !contents, -EINVAL);
4075
4076 if (type == 0 || !contents) {
4077 const char *cc;
4078 char tt;
4079
4080 /* Allow entering into anonymous containers */
4081 r = sd_bus_message_peek_type(m, &tt, &cc);
4082 if (r < 0)
4083 return r;
4084
4085 if (type != 0 && type != tt)
4086 return -ENXIO;
4087
4088 if (contents && !streq(contents, cc))
4089 return -ENXIO;
4090
4091 type = tt;
4092 contents = cc;
4093 }
4094
4095 /*
4096 * We enforce a global limit on container depth, that is much
4097 * higher than the 32 structs and 32 arrays the specification
4098 * mandates. This is simpler to implement for us, and we need
4099 * this only to ensure our container array doesn't grow
4100 * without bounds. We are happy to return any data from a
4101 * message as long as the data itself is valid, even if the
4102 * overall message might be not.
4103 *
4104 * Note that the message signature is validated when
4105 * parsing the headers, and that validation does check the
4106 * 32/32 limit.
4107 *
4108 * Note that the specification defines no limits on the depth
4109 * of stacked variants, but we do.
4110 */
4111 if (m->n_containers >= BUS_CONTAINER_DEPTH)
4112 return -EBADMSG;
4113
4114 if (!GREEDY_REALLOC(m->containers, m->containers_allocated, m->n_containers + 1))
4115 return -ENOMEM;
4116
4117 if (message_end_of_signature(m))
4118 return -ENXIO;
4119
4120 if (message_end_of_array(m, m->rindex))
4121 return 0;
4122
4123 c = message_get_container(m);
4124
4125 signature = strdup(contents);
4126 if (!signature)
4127 return -ENOMEM;
4128
4129 c->saved_index = c->index;
4130 before = m->rindex;
4131
4132 if (type == SD_BUS_TYPE_ARRAY)
4133 r = bus_message_enter_array(m, c, contents, &array_size, &item_size, &offsets, &n_offsets);
4134 else if (type == SD_BUS_TYPE_VARIANT)
4135 r = bus_message_enter_variant(m, c, contents, &item_size);
4136 else if (type == SD_BUS_TYPE_STRUCT)
4137 r = bus_message_enter_struct(m, c, contents, &item_size, &offsets, &n_offsets);
4138 else if (type == SD_BUS_TYPE_DICT_ENTRY)
4139 r = bus_message_enter_dict_entry(m, c, contents, &item_size, &offsets, &n_offsets);
4140 else
4141 r = -EINVAL;
4142
4143 if (r <= 0) {
4144 free(signature);
4145 free(offsets);
4146 return r;
4147 }
4148
4149 /* OK, let's fill it in */
4150 w = m->containers + m->n_containers++;
4151 w->enclosing = type;
4152 w->signature = signature;
4153 w->peeked_signature = NULL;
4154 w->index = 0;
4155
4156 w->before = before;
4157 w->begin = m->rindex;
4158
4159 /* Unary type has fixed size of 1, but virtual size of 0 */
4160 if (BUS_MESSAGE_IS_GVARIANT(m) &&
4161 type == SD_BUS_TYPE_STRUCT &&
4162 isempty(signature))
4163 w->end = m->rindex + 0;
4164 else
4165 w->end = m->rindex + c->item_size;
4166
4167 w->array_size = array_size;
4168 w->item_size = item_size;
4169 w->offsets = offsets;
4170 w->n_offsets = n_offsets;
4171 w->offset_index = 0;
4172
4173 return 1;
4174 }
4175
4176 _public_ int sd_bus_message_exit_container(sd_bus_message *m) {
4177 struct bus_container *c;
4178 unsigned saved;
4179 int r;
4180
4181 assert_return(m, -EINVAL);
4182 assert_return(m->sealed, -EPERM);
4183 assert_return(m->n_containers > 0, -ENXIO);
4184
4185 c = message_get_container(m);
4186
4187 if (c->enclosing != SD_BUS_TYPE_ARRAY) {
4188 if (c->signature && c->signature[c->index] != 0)
4189 return -EBUSY;
4190 }
4191
4192 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4193 if (m->rindex < c->end)
4194 return -EBUSY;
4195
4196 } else if (c->enclosing == SD_BUS_TYPE_ARRAY) {
4197 uint32_t l;
4198
4199 l = BUS_MESSAGE_BSWAP32(m, *c->array_size);
4200 if (c->begin + l != m->rindex)
4201 return -EBUSY;
4202 }
4203
4204 free(c->signature);
4205 free(c->peeked_signature);
4206 free(c->offsets);
4207 m->n_containers--;
4208
4209 c = message_get_container(m);
4210
4211 saved = c->index;
4212 c->index = c->saved_index;
4213 r = container_next_item(m, c, &m->rindex);
4214 c->index = saved;
4215 if (r < 0)
4216 return r;
4217
4218 return 1;
4219 }
4220
4221 static void message_quit_container(sd_bus_message *m) {
4222 struct bus_container *c;
4223
4224 assert(m);
4225 assert(m->sealed);
4226 assert(m->n_containers > 0);
4227
4228 c = message_get_container(m);
4229
4230 /* Undo seeks */
4231 assert(m->rindex >= c->before);
4232 m->rindex = c->before;
4233
4234 /* Free container */
4235 free(c->signature);
4236 free(c->offsets);
4237 m->n_containers--;
4238
4239 /* Correct index of new top-level container */
4240 c = message_get_container(m);
4241 c->index = c->saved_index;
4242 }
4243
4244 _public_ int sd_bus_message_peek_type(sd_bus_message *m, char *type, const char **contents) {
4245 struct bus_container *c;
4246 int r;
4247
4248 assert_return(m, -EINVAL);
4249 assert_return(m->sealed, -EPERM);
4250
4251 if (message_end_of_signature(m))
4252 goto eof;
4253
4254 if (message_end_of_array(m, m->rindex))
4255 goto eof;
4256
4257 c = message_get_container(m);
4258
4259 if (bus_type_is_basic(c->signature[c->index])) {
4260 if (contents)
4261 *contents = NULL;
4262 if (type)
4263 *type = c->signature[c->index];
4264 return 1;
4265 }
4266
4267 if (c->signature[c->index] == SD_BUS_TYPE_ARRAY) {
4268
4269 if (contents) {
4270 size_t l;
4271 char *sig;
4272
4273 r = signature_element_length(c->signature+c->index+1, &l);
4274 if (r < 0)
4275 return r;
4276
4277 assert(l >= 1);
4278
4279 sig = strndup(c->signature + c->index + 1, l);
4280 if (!sig)
4281 return -ENOMEM;
4282
4283 free(c->peeked_signature);
4284 *contents = c->peeked_signature = sig;
4285 }
4286
4287 if (type)
4288 *type = SD_BUS_TYPE_ARRAY;
4289
4290 return 1;
4291 }
4292
4293 if (c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ||
4294 c->signature[c->index] == SD_BUS_TYPE_DICT_ENTRY_BEGIN) {
4295
4296 if (contents) {
4297 size_t l;
4298 char *sig;
4299
4300 r = signature_element_length(c->signature+c->index, &l);
4301 if (r < 0)
4302 return r;
4303
4304 assert(l >= 2);
4305 sig = strndup(c->signature + c->index + 1, l - 2);
4306 if (!sig)
4307 return -ENOMEM;
4308
4309 free(c->peeked_signature);
4310 *contents = c->peeked_signature = sig;
4311 }
4312
4313 if (type)
4314 *type = c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY;
4315
4316 return 1;
4317 }
4318
4319 if (c->signature[c->index] == SD_BUS_TYPE_VARIANT) {
4320 if (contents) {
4321 void *q;
4322
4323 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4324 size_t k;
4325
4326 if (c->item_size < 2)
4327 return -EBADMSG;
4328
4329 /* Look for the NUL delimiter that
4330 separates the payload from the
4331 signature. Since the body might be
4332 in a different part that then the
4333 signature we map byte by byte. */
4334
4335 for (k = 2; k <= c->item_size; k++) {
4336 size_t where;
4337
4338 where = m->rindex + c->item_size - k;
4339 r = message_peek_body(m, &where, 1, k, &q);
4340 if (r < 0)
4341 return r;
4342
4343 if (*(char*) q == 0)
4344 break;
4345 }
4346
4347 if (k > c->item_size)
4348 return -EBADMSG;
4349
4350 free(c->peeked_signature);
4351 c->peeked_signature = strndup((char*) q + 1, k - 1);
4352 if (!c->peeked_signature)
4353 return -ENOMEM;
4354
4355 if (!signature_is_valid(c->peeked_signature, true))
4356 return -EBADMSG;
4357
4358 *contents = c->peeked_signature;
4359 } else {
4360 size_t rindex, l;
4361
4362 rindex = m->rindex;
4363 r = message_peek_body(m, &rindex, 1, 1, &q);
4364 if (r < 0)
4365 return r;
4366
4367 l = *(uint8_t*) q;
4368 r = message_peek_body(m, &rindex, 1, l+1, &q);
4369 if (r < 0)
4370 return r;
4371
4372 if (!validate_signature(q, l))
4373 return -EBADMSG;
4374
4375 *contents = q;
4376 }
4377 }
4378
4379 if (type)
4380 *type = SD_BUS_TYPE_VARIANT;
4381
4382 return 1;
4383 }
4384
4385 return -EINVAL;
4386
4387 eof:
4388 if (type)
4389 *type = 0;
4390 if (contents)
4391 *contents = NULL;
4392 return 0;
4393 }
4394
4395 _public_ int sd_bus_message_rewind(sd_bus_message *m, int complete) {
4396 struct bus_container *c;
4397
4398 assert_return(m, -EINVAL);
4399 assert_return(m->sealed, -EPERM);
4400
4401 if (complete) {
4402 message_reset_containers(m);
4403 m->rindex = 0;
4404
4405 c = message_get_container(m);
4406 } else {
4407 c = message_get_container(m);
4408
4409 c->offset_index = 0;
4410 c->index = 0;
4411 m->rindex = c->begin;
4412 }
4413
4414 c->offset_index = 0;
4415 c->item_size = (c->n_offsets > 0 ? c->offsets[0] : c->end) - c->begin;
4416
4417 return !isempty(c->signature);
4418 }
4419
4420 static int message_read_ap(
4421 sd_bus_message *m,
4422 const char *types,
4423 va_list ap) {
4424
4425 unsigned n_array, n_struct;
4426 TypeStack stack[BUS_CONTAINER_DEPTH];
4427 unsigned stack_ptr = 0;
4428 unsigned n_loop = 0;
4429 int r;
4430
4431 assert(m);
4432
4433 if (isempty(types))
4434 return 0;
4435
4436 /* Ideally, we'd just call ourselves recursively on every
4437 * complex type. However, the state of a va_list that is
4438 * passed to a function is undefined after that function
4439 * returns. This means we need to docode the va_list linearly
4440 * in a single stackframe. We hence implement our own
4441 * home-grown stack in an array. */
4442
4443 n_array = (unsigned) -1; /* length of current array entries */
4444 n_struct = strlen(types); /* length of current struct contents signature */
4445
4446 for (;;) {
4447 const char *t;
4448
4449 n_loop++;
4450
4451 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
4452 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
4453 if (r < 0)
4454 return r;
4455 if (r == 0)
4456 break;
4457
4458 r = sd_bus_message_exit_container(m);
4459 if (r < 0)
4460 return r;
4461
4462 continue;
4463 }
4464
4465 t = types;
4466 if (n_array != (unsigned) -1)
4467 n_array --;
4468 else {
4469 types ++;
4470 n_struct--;
4471 }
4472
4473 switch (*t) {
4474
4475 case SD_BUS_TYPE_BYTE:
4476 case SD_BUS_TYPE_BOOLEAN:
4477 case SD_BUS_TYPE_INT16:
4478 case SD_BUS_TYPE_UINT16:
4479 case SD_BUS_TYPE_INT32:
4480 case SD_BUS_TYPE_UINT32:
4481 case SD_BUS_TYPE_INT64:
4482 case SD_BUS_TYPE_UINT64:
4483 case SD_BUS_TYPE_DOUBLE:
4484 case SD_BUS_TYPE_STRING:
4485 case SD_BUS_TYPE_OBJECT_PATH:
4486 case SD_BUS_TYPE_SIGNATURE:
4487 case SD_BUS_TYPE_UNIX_FD: {
4488 void *p;
4489
4490 p = va_arg(ap, void*);
4491 r = sd_bus_message_read_basic(m, *t, p);
4492 if (r < 0)
4493 return r;
4494 if (r == 0) {
4495 if (n_loop <= 1)
4496 return 0;
4497
4498 return -ENXIO;
4499 }
4500
4501 break;
4502 }
4503
4504 case SD_BUS_TYPE_ARRAY: {
4505 size_t k;
4506
4507 r = signature_element_length(t + 1, &k);
4508 if (r < 0)
4509 return r;
4510
4511 {
4512 char s[k + 1];
4513 memcpy(s, t + 1, k);
4514 s[k] = 0;
4515
4516 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4517 if (r < 0)
4518 return r;
4519 if (r == 0) {
4520 if (n_loop <= 1)
4521 return 0;
4522
4523 return -ENXIO;
4524 }
4525 }
4526
4527 if (n_array == (unsigned) -1) {
4528 types += k;
4529 n_struct -= k;
4530 }
4531
4532 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4533 if (r < 0)
4534 return r;
4535
4536 types = t + 1;
4537 n_struct = k;
4538 n_array = va_arg(ap, unsigned);
4539
4540 break;
4541 }
4542
4543 case SD_BUS_TYPE_VARIANT: {
4544 const char *s;
4545
4546 s = va_arg(ap, const char *);
4547 if (!s)
4548 return -EINVAL;
4549
4550 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, s);
4551 if (r < 0)
4552 return r;
4553 if (r == 0) {
4554 if (n_loop <= 1)
4555 return 0;
4556
4557 return -ENXIO;
4558 }
4559
4560 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4561 if (r < 0)
4562 return r;
4563
4564 types = s;
4565 n_struct = strlen(s);
4566 n_array = (unsigned) -1;
4567
4568 break;
4569 }
4570
4571 case SD_BUS_TYPE_STRUCT_BEGIN:
4572 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4573 size_t k;
4574
4575 r = signature_element_length(t, &k);
4576 if (r < 0)
4577 return r;
4578
4579 {
4580 char s[k - 1];
4581 memcpy(s, t + 1, k - 2);
4582 s[k - 2] = 0;
4583
4584 r = sd_bus_message_enter_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4585 if (r < 0)
4586 return r;
4587 if (r == 0) {
4588 if (n_loop <= 1)
4589 return 0;
4590 return -ENXIO;
4591 }
4592 }
4593
4594 if (n_array == (unsigned) -1) {
4595 types += k - 1;
4596 n_struct -= k - 1;
4597 }
4598
4599 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4600 if (r < 0)
4601 return r;
4602
4603 types = t + 1;
4604 n_struct = k - 2;
4605 n_array = (unsigned) -1;
4606
4607 break;
4608 }
4609
4610 default:
4611 return -EINVAL;
4612 }
4613 }
4614
4615 return 1;
4616 }
4617
4618 _public_ int sd_bus_message_read(sd_bus_message *m, const char *types, ...) {
4619 va_list ap;
4620 int r;
4621
4622 assert_return(m, -EINVAL);
4623 assert_return(m->sealed, -EPERM);
4624 assert_return(types, -EINVAL);
4625
4626 va_start(ap, types);
4627 r = message_read_ap(m, types, ap);
4628 va_end(ap);
4629
4630 return r;
4631 }
4632
4633 _public_ int sd_bus_message_skip(sd_bus_message *m, const char *types) {
4634 int r;
4635
4636 assert_return(m, -EINVAL);
4637 assert_return(m->sealed, -EPERM);
4638
4639 /* If types is NULL, read exactly one element */
4640 if (!types) {
4641 struct bus_container *c;
4642 size_t l;
4643
4644 if (message_end_of_signature(m))
4645 return -ENXIO;
4646
4647 if (message_end_of_array(m, m->rindex))
4648 return 0;
4649
4650 c = message_get_container(m);
4651
4652 r = signature_element_length(c->signature + c->index, &l);
4653 if (r < 0)
4654 return r;
4655
4656 types = strndupa(c->signature + c->index, l);
4657 }
4658
4659 switch (*types) {
4660
4661 case 0: /* Nothing to drop */
4662 return 0;
4663
4664 case SD_BUS_TYPE_BYTE:
4665 case SD_BUS_TYPE_BOOLEAN:
4666 case SD_BUS_TYPE_INT16:
4667 case SD_BUS_TYPE_UINT16:
4668 case SD_BUS_TYPE_INT32:
4669 case SD_BUS_TYPE_UINT32:
4670 case SD_BUS_TYPE_INT64:
4671 case SD_BUS_TYPE_UINT64:
4672 case SD_BUS_TYPE_DOUBLE:
4673 case SD_BUS_TYPE_STRING:
4674 case SD_BUS_TYPE_OBJECT_PATH:
4675 case SD_BUS_TYPE_SIGNATURE:
4676 case SD_BUS_TYPE_UNIX_FD:
4677
4678 r = sd_bus_message_read_basic(m, *types, NULL);
4679 if (r <= 0)
4680 return r;
4681
4682 r = sd_bus_message_skip(m, types + 1);
4683 if (r < 0)
4684 return r;
4685
4686 return 1;
4687
4688 case SD_BUS_TYPE_ARRAY: {
4689 size_t k;
4690
4691 r = signature_element_length(types + 1, &k);
4692 if (r < 0)
4693 return r;
4694
4695 {
4696 char s[k+1];
4697 memcpy(s, types+1, k);
4698 s[k] = 0;
4699
4700 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4701 if (r <= 0)
4702 return r;
4703
4704 for (;;) {
4705 r = sd_bus_message_skip(m, s);
4706 if (r < 0)
4707 return r;
4708 if (r == 0)
4709 break;
4710 }
4711
4712 r = sd_bus_message_exit_container(m);
4713 if (r < 0)
4714 return r;
4715 }
4716
4717 r = sd_bus_message_skip(m, types + 1 + k);
4718 if (r < 0)
4719 return r;
4720
4721 return 1;
4722 }
4723
4724 case SD_BUS_TYPE_VARIANT: {
4725 const char *contents;
4726 char x;
4727
4728 r = sd_bus_message_peek_type(m, &x, &contents);
4729 if (r <= 0)
4730 return r;
4731
4732 if (x != SD_BUS_TYPE_VARIANT)
4733 return -ENXIO;
4734
4735 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
4736 if (r <= 0)
4737 return r;
4738
4739 r = sd_bus_message_skip(m, contents);
4740 if (r < 0)
4741 return r;
4742 assert(r != 0);
4743
4744 r = sd_bus_message_exit_container(m);
4745 if (r < 0)
4746 return r;
4747
4748 r = sd_bus_message_skip(m, types + 1);
4749 if (r < 0)
4750 return r;
4751
4752 return 1;
4753 }
4754
4755 case SD_BUS_TYPE_STRUCT_BEGIN:
4756 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4757 size_t k;
4758
4759 r = signature_element_length(types, &k);
4760 if (r < 0)
4761 return r;
4762
4763 {
4764 char s[k-1];
4765 memcpy(s, types+1, k-2);
4766 s[k-2] = 0;
4767
4768 r = sd_bus_message_enter_container(m, *types == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4769 if (r <= 0)
4770 return r;
4771
4772 r = sd_bus_message_skip(m, s);
4773 if (r < 0)
4774 return r;
4775
4776 r = sd_bus_message_exit_container(m);
4777 if (r < 0)
4778 return r;
4779 }
4780
4781 r = sd_bus_message_skip(m, types + k);
4782 if (r < 0)
4783 return r;
4784
4785 return 1;
4786 }
4787
4788 default:
4789 return -EINVAL;
4790 }
4791 }
4792
4793 _public_ int sd_bus_message_read_array(
4794 sd_bus_message *m,
4795 char type,
4796 const void **ptr,
4797 size_t *size) {
4798
4799 struct bus_container *c;
4800 void *p;
4801 size_t sz;
4802 ssize_t align;
4803 int r;
4804
4805 assert_return(m, -EINVAL);
4806 assert_return(m->sealed, -EPERM);
4807 assert_return(bus_type_is_trivial(type), -EINVAL);
4808 assert_return(ptr, -EINVAL);
4809 assert_return(size, -EINVAL);
4810 assert_return(!BUS_MESSAGE_NEED_BSWAP(m), -EOPNOTSUPP);
4811
4812 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
4813 if (r <= 0)
4814 return r;
4815
4816 c = message_get_container(m);
4817
4818 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4819 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
4820 if (align < 0)
4821 return align;
4822
4823 sz = c->end - c->begin;
4824 } else {
4825 align = bus_type_get_alignment(type);
4826 if (align < 0)
4827 return align;
4828
4829 sz = BUS_MESSAGE_BSWAP32(m, *c->array_size);
4830 }
4831
4832 if (sz == 0)
4833 /* Zero length array, let's return some aligned
4834 * pointer that is not NULL */
4835 p = (uint8_t*) NULL + align;
4836 else {
4837 r = message_peek_body(m, &m->rindex, align, sz, &p);
4838 if (r < 0)
4839 goto fail;
4840 }
4841
4842 r = sd_bus_message_exit_container(m);
4843 if (r < 0)
4844 goto fail;
4845
4846 *ptr = (const void*) p;
4847 *size = sz;
4848
4849 return 1;
4850
4851 fail:
4852 message_quit_container(m);
4853 return r;
4854 }
4855
4856 static int message_peek_fields(
4857 sd_bus_message *m,
4858 size_t *rindex,
4859 size_t align,
4860 size_t nbytes,
4861 void **ret) {
4862
4863 assert(m);
4864 assert(rindex);
4865 assert(align > 0);
4866
4867 return buffer_peek(BUS_MESSAGE_FIELDS(m), m->fields_size, rindex, align, nbytes, ret);
4868 }
4869
4870 static int message_peek_field_uint32(
4871 sd_bus_message *m,
4872 size_t *ri,
4873 size_t item_size,
4874 uint32_t *ret) {
4875
4876 int r;
4877 void *q;
4878
4879 assert(m);
4880 assert(ri);
4881
4882 if (BUS_MESSAGE_IS_GVARIANT(m) && item_size != 4)
4883 return -EBADMSG;
4884
4885 /* identical for gvariant and dbus1 */
4886
4887 r = message_peek_fields(m, ri, 4, 4, &q);
4888 if (r < 0)
4889 return r;
4890
4891 if (ret)
4892 *ret = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
4893
4894 return 0;
4895 }
4896
4897 static int message_peek_field_uint64(
4898 sd_bus_message *m,
4899 size_t *ri,
4900 size_t item_size,
4901 uint64_t *ret) {
4902
4903 int r;
4904 void *q;
4905
4906 assert(m);
4907 assert(ri);
4908
4909 if (BUS_MESSAGE_IS_GVARIANT(m) && item_size != 8)
4910 return -EBADMSG;
4911
4912 /* identical for gvariant and dbus1 */
4913
4914 r = message_peek_fields(m, ri, 8, 8, &q);
4915 if (r < 0)
4916 return r;
4917
4918 if (ret)
4919 *ret = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
4920
4921 return 0;
4922 }
4923
4924 static int message_peek_field_string(
4925 sd_bus_message *m,
4926 bool (*validate)(const char *p),
4927 size_t *ri,
4928 size_t item_size,
4929 const char **ret) {
4930
4931 uint32_t l;
4932 int r;
4933 void *q;
4934
4935 assert(m);
4936 assert(ri);
4937
4938 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4939
4940 if (item_size <= 0)
4941 return -EBADMSG;
4942
4943 r = message_peek_fields(m, ri, 1, item_size, &q);
4944 if (r < 0)
4945 return r;
4946
4947 l = item_size - 1;
4948 } else {
4949 r = message_peek_field_uint32(m, ri, 4, &l);
4950 if (r < 0)
4951 return r;
4952
4953 r = message_peek_fields(m, ri, 1, l+1, &q);
4954 if (r < 0)
4955 return r;
4956 }
4957
4958 if (validate) {
4959 if (!validate_nul(q, l))
4960 return -EBADMSG;
4961
4962 if (!validate(q))
4963 return -EBADMSG;
4964 } else {
4965 if (!validate_string(q, l))
4966 return -EBADMSG;
4967 }
4968
4969 if (ret)
4970 *ret = q;
4971
4972 return 0;
4973 }
4974
4975 static int message_peek_field_signature(
4976 sd_bus_message *m,
4977 size_t *ri,
4978 size_t item_size,
4979 const char **ret) {
4980
4981 size_t l;
4982 int r;
4983 void *q;
4984
4985 assert(m);
4986 assert(ri);
4987
4988 if (BUS_MESSAGE_IS_GVARIANT(m)) {
4989
4990 if (item_size <= 0)
4991 return -EBADMSG;
4992
4993 r = message_peek_fields(m, ri, 1, item_size, &q);
4994 if (r < 0)
4995 return r;
4996
4997 l = item_size - 1;
4998 } else {
4999 r = message_peek_fields(m, ri, 1, 1, &q);
5000 if (r < 0)
5001 return r;
5002
5003 l = *(uint8_t*) q;
5004 r = message_peek_fields(m, ri, 1, l+1, &q);
5005 if (r < 0)
5006 return r;
5007 }
5008
5009 if (!validate_signature(q, l))
5010 return -EBADMSG;
5011
5012 if (ret)
5013 *ret = q;
5014
5015 return 0;
5016 }
5017
5018 static int message_skip_fields(
5019 sd_bus_message *m,
5020 size_t *ri,
5021 uint32_t array_size,
5022 const char **signature) {
5023
5024 size_t original_index;
5025 int r;
5026
5027 assert(m);
5028 assert(ri);
5029 assert(signature);
5030 assert(!BUS_MESSAGE_IS_GVARIANT(m));
5031
5032 original_index = *ri;
5033
5034 for (;;) {
5035 char t;
5036 size_t l;
5037
5038 if (array_size != (uint32_t) -1 &&
5039 array_size <= *ri - original_index)
5040 return 0;
5041
5042 t = **signature;
5043 if (!t)
5044 return 0;
5045
5046 if (t == SD_BUS_TYPE_STRING) {
5047
5048 r = message_peek_field_string(m, NULL, ri, 0, NULL);
5049 if (r < 0)
5050 return r;
5051
5052 (*signature)++;
5053
5054 } else if (t == SD_BUS_TYPE_OBJECT_PATH) {
5055
5056 r = message_peek_field_string(m, object_path_is_valid, ri, 0, NULL);
5057 if (r < 0)
5058 return r;
5059
5060 (*signature)++;
5061
5062 } else if (t == SD_BUS_TYPE_SIGNATURE) {
5063
5064 r = message_peek_field_signature(m, ri, 0, NULL);
5065 if (r < 0)
5066 return r;
5067
5068 (*signature)++;
5069
5070 } else if (bus_type_is_basic(t)) {
5071 ssize_t align, k;
5072
5073 align = bus_type_get_alignment(t);
5074 k = bus_type_get_size(t);
5075 assert(align > 0 && k > 0);
5076
5077 r = message_peek_fields(m, ri, align, k, NULL);
5078 if (r < 0)
5079 return r;
5080
5081 (*signature)++;
5082
5083 } else if (t == SD_BUS_TYPE_ARRAY) {
5084
5085 r = signature_element_length(*signature+1, &l);
5086 if (r < 0)
5087 return r;
5088
5089 assert(l >= 1);
5090 {
5091 char sig[l-1], *s;
5092 uint32_t nas;
5093 int alignment;
5094
5095 strncpy(sig, *signature + 1, l-1);
5096 s = sig;
5097
5098 alignment = bus_type_get_alignment(sig[0]);
5099 if (alignment < 0)
5100 return alignment;
5101
5102 r = message_peek_field_uint32(m, ri, 0, &nas);
5103 if (r < 0)
5104 return r;
5105 if (nas > BUS_ARRAY_MAX_SIZE)
5106 return -EBADMSG;
5107
5108 r = message_peek_fields(m, ri, alignment, 0, NULL);
5109 if (r < 0)
5110 return r;
5111
5112 r = message_skip_fields(m, ri, nas, (const char**) &s);
5113 if (r < 0)
5114 return r;
5115 }
5116
5117 (*signature) += 1 + l;
5118
5119 } else if (t == SD_BUS_TYPE_VARIANT) {
5120 const char *s;
5121
5122 r = message_peek_field_signature(m, ri, 0, &s);
5123 if (r < 0)
5124 return r;
5125
5126 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
5127 if (r < 0)
5128 return r;
5129
5130 (*signature)++;
5131
5132 } else if (t == SD_BUS_TYPE_STRUCT ||
5133 t == SD_BUS_TYPE_DICT_ENTRY) {
5134
5135 r = signature_element_length(*signature, &l);
5136 if (r < 0)
5137 return r;
5138
5139 assert(l >= 2);
5140 {
5141 char sig[l-1], *s;
5142 strncpy(sig, *signature + 1, l-1);
5143 s = sig;
5144
5145 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
5146 if (r < 0)
5147 return r;
5148 }
5149
5150 *signature += l;
5151 } else
5152 return -EINVAL;
5153 }
5154 }
5155
5156 int bus_message_parse_fields(sd_bus_message *m) {
5157 size_t ri;
5158 int r;
5159 uint32_t unix_fds = 0;
5160 bool unix_fds_set = false;
5161 void *offsets = NULL;
5162 unsigned n_offsets = 0;
5163 size_t sz = 0;
5164 unsigned i = 0;
5165
5166 assert(m);
5167
5168 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5169 char *p;
5170
5171 /* Read the signature from the end of the body variant first */
5172 sz = bus_gvariant_determine_word_size(BUS_MESSAGE_SIZE(m), 0);
5173 if (m->footer_accessible < 1 + sz)
5174 return -EBADMSG;
5175
5176 p = (char*) m->footer + m->footer_accessible - (1 + sz);
5177 for (;;) {
5178 if (p < (char*) m->footer)
5179 return -EBADMSG;
5180
5181 if (*p == 0) {
5182 size_t l;
5183 char *c;
5184
5185 /* We found the beginning of the signature
5186 * string, yay! We require the body to be a
5187 * structure, so verify it and then strip the
5188 * opening/closing brackets. */
5189
5190 l = ((char*) m->footer + m->footer_accessible) - p - (1 + sz);
5191 if (l < 2 ||
5192 p[1] != SD_BUS_TYPE_STRUCT_BEGIN ||
5193 p[1 + l - 1] != SD_BUS_TYPE_STRUCT_END)
5194 return -EBADMSG;
5195
5196 c = strndup(p + 1 + 1, l - 2);
5197 if (!c)
5198 return -ENOMEM;
5199
5200 free(m->root_container.signature);
5201 m->root_container.signature = c;
5202 break;
5203 }
5204
5205 p--;
5206 }
5207
5208 /* Calculate the actual user body size, by removing
5209 * the trailing variant signature and struct offset
5210 * table */
5211 m->user_body_size = m->body_size - ((char*) m->footer + m->footer_accessible - p);
5212
5213 /* Pull out the offset table for the fields array */
5214 sz = bus_gvariant_determine_word_size(m->fields_size, 0);
5215 if (sz > 0) {
5216 size_t framing;
5217 void *q;
5218
5219 ri = m->fields_size - sz;
5220 r = message_peek_fields(m, &ri, 1, sz, &q);
5221 if (r < 0)
5222 return r;
5223
5224 framing = bus_gvariant_read_word_le(q, sz);
5225 if (framing >= m->fields_size - sz)
5226 return -EBADMSG;
5227 if ((m->fields_size - framing) % sz != 0)
5228 return -EBADMSG;
5229
5230 ri = framing;
5231 r = message_peek_fields(m, &ri, 1, m->fields_size - framing, &offsets);
5232 if (r < 0)
5233 return r;
5234
5235 n_offsets = (m->fields_size - framing) / sz;
5236 }
5237 } else
5238 m->user_body_size = m->body_size;
5239
5240 ri = 0;
5241 while (ri < m->fields_size) {
5242 _cleanup_free_ char *sig = NULL;
5243 const char *signature;
5244 uint64_t field_type;
5245 size_t item_size = (size_t) -1;
5246
5247 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5248 uint64_t *u64;
5249
5250 if (i >= n_offsets)
5251 break;
5252
5253 if (i == 0)
5254 ri = 0;
5255 else
5256 ri = ALIGN_TO(bus_gvariant_read_word_le((uint8_t*) offsets + (i-1)*sz, sz), 8);
5257
5258 r = message_peek_fields(m, &ri, 8, 8, (void**) &u64);
5259 if (r < 0)
5260 return r;
5261
5262 field_type = BUS_MESSAGE_BSWAP64(m, *u64);
5263 } else {
5264 uint8_t *u8;
5265
5266 r = message_peek_fields(m, &ri, 8, 1, (void**) &u8);
5267 if (r < 0)
5268 return r;
5269
5270 field_type = *u8;
5271 }
5272
5273 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5274 size_t where, end;
5275 char *b;
5276 void *q;
5277
5278 end = bus_gvariant_read_word_le((uint8_t*) offsets + i*sz, sz);
5279
5280 if (end < ri)
5281 return -EBADMSG;
5282
5283 where = ri = ALIGN_TO(ri, 8);
5284 item_size = end - ri;
5285 r = message_peek_fields(m, &where, 1, item_size, &q);
5286 if (r < 0)
5287 return r;
5288
5289 b = memrchr(q, 0, item_size);
5290 if (!b)
5291 return -EBADMSG;
5292
5293 sig = strndup(b+1, item_size - (b+1-(char*) q));
5294 if (!sig)
5295 return -ENOMEM;
5296
5297 signature = sig;
5298 item_size = b - (char*) q;
5299 } else {
5300 r = message_peek_field_signature(m, &ri, 0, &signature);
5301 if (r < 0)
5302 return r;
5303 }
5304
5305 switch (field_type) {
5306
5307 case _BUS_MESSAGE_HEADER_INVALID:
5308 return -EBADMSG;
5309
5310 case BUS_MESSAGE_HEADER_PATH:
5311
5312 if (m->path)
5313 return -EBADMSG;
5314
5315 if (!streq(signature, "o"))
5316 return -EBADMSG;
5317
5318 r = message_peek_field_string(m, object_path_is_valid, &ri, item_size, &m->path);
5319 break;
5320
5321 case BUS_MESSAGE_HEADER_INTERFACE:
5322
5323 if (m->interface)
5324 return -EBADMSG;
5325
5326 if (!streq(signature, "s"))
5327 return -EBADMSG;
5328
5329 r = message_peek_field_string(m, interface_name_is_valid, &ri, item_size, &m->interface);
5330 break;
5331
5332 case BUS_MESSAGE_HEADER_MEMBER:
5333
5334 if (m->member)
5335 return -EBADMSG;
5336
5337 if (!streq(signature, "s"))
5338 return -EBADMSG;
5339
5340 r = message_peek_field_string(m, member_name_is_valid, &ri, item_size, &m->member);
5341 break;
5342
5343 case BUS_MESSAGE_HEADER_ERROR_NAME:
5344
5345 if (m->error.name)
5346 return -EBADMSG;
5347
5348 if (!streq(signature, "s"))
5349 return -EBADMSG;
5350
5351 r = message_peek_field_string(m, error_name_is_valid, &ri, item_size, &m->error.name);
5352 if (r >= 0)
5353 m->error._need_free = -1;
5354
5355 break;
5356
5357 case BUS_MESSAGE_HEADER_DESTINATION:
5358
5359 if (m->destination)
5360 return -EBADMSG;
5361
5362 if (!streq(signature, "s"))
5363 return -EBADMSG;
5364
5365 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->destination);
5366 break;
5367
5368 case BUS_MESSAGE_HEADER_SENDER:
5369
5370 if (m->sender)
5371 return -EBADMSG;
5372
5373 if (!streq(signature, "s"))
5374 return -EBADMSG;
5375
5376 r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->sender);
5377
5378 if (r >= 0 && m->sender[0] == ':' && m->bus->bus_client && !m->bus->is_kernel) {
5379 m->creds.unique_name = (char*) m->sender;
5380 m->creds.mask |= SD_BUS_CREDS_UNIQUE_NAME & m->bus->creds_mask;
5381 }
5382
5383 break;
5384
5385
5386 case BUS_MESSAGE_HEADER_SIGNATURE: {
5387 const char *s;
5388 char *c;
5389
5390 if (BUS_MESSAGE_IS_GVARIANT(m)) /* only applies to dbus1 */
5391 return -EBADMSG;
5392
5393 if (m->root_container.signature)
5394 return -EBADMSG;
5395
5396 if (!streq(signature, "g"))
5397 return -EBADMSG;
5398
5399 r = message_peek_field_signature(m, &ri, item_size, &s);
5400 if (r < 0)
5401 return r;
5402
5403 c = strdup(s);
5404 if (!c)
5405 return -ENOMEM;
5406
5407 free(m->root_container.signature);
5408 m->root_container.signature = c;
5409 break;
5410 }
5411
5412 case BUS_MESSAGE_HEADER_REPLY_SERIAL:
5413
5414 if (m->reply_cookie != 0)
5415 return -EBADMSG;
5416
5417 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5418 /* 64bit on dbus2 */
5419
5420 if (!streq(signature, "t"))
5421 return -EBADMSG;
5422
5423 r = message_peek_field_uint64(m, &ri, item_size, &m->reply_cookie);
5424 if (r < 0)
5425 return r;
5426 } else {
5427 /* 32bit on dbus1 */
5428 uint32_t serial;
5429
5430 if (!streq(signature, "u"))
5431 return -EBADMSG;
5432
5433 r = message_peek_field_uint32(m, &ri, item_size, &serial);
5434 if (r < 0)
5435 return r;
5436
5437 m->reply_cookie = serial;
5438 }
5439
5440 if (m->reply_cookie == 0)
5441 return -EBADMSG;
5442
5443 break;
5444
5445 case BUS_MESSAGE_HEADER_UNIX_FDS:
5446 if (unix_fds_set)
5447 return -EBADMSG;
5448
5449 if (!streq(signature, "u"))
5450 return -EBADMSG;
5451
5452 r = message_peek_field_uint32(m, &ri, item_size, &unix_fds);
5453 if (r < 0)
5454 return -EBADMSG;
5455
5456 unix_fds_set = true;
5457 break;
5458
5459 default:
5460 if (!BUS_MESSAGE_IS_GVARIANT(m))
5461 r = message_skip_fields(m, &ri, (uint32_t) -1, (const char **) &signature);
5462 }
5463
5464 if (r < 0)
5465 return r;
5466
5467 i++;
5468 }
5469
5470 if (m->n_fds != unix_fds)
5471 return -EBADMSG;
5472
5473 switch (m->header->type) {
5474
5475 case SD_BUS_MESSAGE_SIGNAL:
5476 if (!m->path || !m->interface || !m->member)
5477 return -EBADMSG;
5478
5479 if (m->reply_cookie != 0)
5480 return -EBADMSG;
5481
5482 break;
5483
5484 case SD_BUS_MESSAGE_METHOD_CALL:
5485
5486 if (!m->path || !m->member)
5487 return -EBADMSG;
5488
5489 if (m->reply_cookie != 0)
5490 return -EBADMSG;
5491
5492 break;
5493
5494 case SD_BUS_MESSAGE_METHOD_RETURN:
5495
5496 if (m->reply_cookie == 0)
5497 return -EBADMSG;
5498 break;
5499
5500 case SD_BUS_MESSAGE_METHOD_ERROR:
5501
5502 if (m->reply_cookie == 0 || !m->error.name)
5503 return -EBADMSG;
5504 break;
5505 }
5506
5507 /* Refuse non-local messages that claim they are local */
5508 if (streq_ptr(m->path, "/org/freedesktop/DBus/Local"))
5509 return -EBADMSG;
5510 if (streq_ptr(m->interface, "org.freedesktop.DBus.Local"))
5511 return -EBADMSG;
5512 if (streq_ptr(m->sender, "org.freedesktop.DBus.Local"))
5513 return -EBADMSG;
5514
5515 m->root_container.end = m->user_body_size;
5516
5517 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5518 r = build_struct_offsets(
5519 m,
5520 m->root_container.signature,
5521 m->user_body_size,
5522 &m->root_container.item_size,
5523 &m->root_container.offsets,
5524 &m->root_container.n_offsets);
5525 if (r < 0)
5526 return r;
5527 }
5528
5529 /* Try to read the error message, but if we can't it's a non-issue */
5530 if (m->header->type == SD_BUS_MESSAGE_METHOD_ERROR)
5531 (void) sd_bus_message_read(m, "s", &m->error.message);
5532
5533 return 0;
5534 }
5535
5536 _public_ int sd_bus_message_set_destination(sd_bus_message *m, const char *destination) {
5537 assert_return(m, -EINVAL);
5538 assert_return(destination, -EINVAL);
5539 assert_return(!m->sealed, -EPERM);
5540 assert_return(!m->destination, -EEXIST);
5541
5542 return message_append_field_string(m, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &m->destination);
5543 }
5544
5545 int bus_message_get_blob(sd_bus_message *m, void **buffer, size_t *sz) {
5546 size_t total;
5547 void *p, *e;
5548 unsigned i;
5549 struct bus_body_part *part;
5550
5551 assert(m);
5552 assert(buffer);
5553 assert(sz);
5554
5555 total = BUS_MESSAGE_SIZE(m);
5556
5557 p = malloc(total);
5558 if (!p)
5559 return -ENOMEM;
5560
5561 e = mempcpy(p, m->header, BUS_MESSAGE_BODY_BEGIN(m));
5562 MESSAGE_FOREACH_PART(part, i, m)
5563 e = mempcpy(e, part->data, part->size);
5564
5565 assert(total == (size_t) ((uint8_t*) e - (uint8_t*) p));
5566
5567 *buffer = p;
5568 *sz = total;
5569
5570 return 0;
5571 }
5572
5573 int bus_message_read_strv_extend(sd_bus_message *m, char ***l) {
5574 const char *s;
5575 int r;
5576
5577 assert(m);
5578 assert(l);
5579
5580 r = sd_bus_message_enter_container(m, 'a', "s");
5581 if (r <= 0)
5582 return r;
5583
5584 while ((r = sd_bus_message_read_basic(m, 's', &s)) > 0) {
5585 r = strv_extend(l, s);
5586 if (r < 0)
5587 return r;
5588 }
5589 if (r < 0)
5590 return r;
5591
5592 r = sd_bus_message_exit_container(m);
5593 if (r < 0)
5594 return r;
5595
5596 return 1;
5597 }
5598
5599 _public_ int sd_bus_message_read_strv(sd_bus_message *m, char ***l) {
5600 char **strv = NULL;
5601 int r;
5602
5603 assert_return(m, -EINVAL);
5604 assert_return(m->sealed, -EPERM);
5605 assert_return(l, -EINVAL);
5606
5607 r = bus_message_read_strv_extend(m, &strv);
5608 if (r <= 0) {
5609 strv_free(strv);
5610 return r;
5611 }
5612
5613 *l = strv;
5614 return 1;
5615 }
5616
5617 static int bus_message_get_arg_skip(
5618 sd_bus_message *m,
5619 unsigned i,
5620 char *_type,
5621 const char **_contents) {
5622
5623 unsigned j;
5624 int r;
5625
5626 r = sd_bus_message_rewind(m, true);
5627 if (r < 0)
5628 return r;
5629
5630 for (j = 0;; j++) {
5631 const char *contents;
5632 char type;
5633
5634 r = sd_bus_message_peek_type(m, &type, &contents);
5635 if (r < 0)
5636 return r;
5637 if (r == 0)
5638 return -ENXIO;
5639
5640 /* Don't match against arguments after the first one we don't understand */
5641 if (!IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE) &&
5642 !(type == SD_BUS_TYPE_ARRAY && STR_IN_SET(contents, "s", "o", "g")))
5643 return -ENXIO;
5644
5645 if (j >= i) {
5646 if (_contents)
5647 *_contents = contents;
5648 if (_type)
5649 *_type = type;
5650 return 0;
5651 }
5652
5653 r = sd_bus_message_skip(m, NULL);
5654 if (r < 0)
5655 return r;
5656 }
5657
5658 }
5659
5660 int bus_message_get_arg(sd_bus_message *m, unsigned i, const char **str) {
5661 char type;
5662 int r;
5663
5664 assert(m);
5665 assert(str);
5666
5667 r = bus_message_get_arg_skip(m, i, &type, NULL);
5668 if (r < 0)
5669 return r;
5670
5671 if (!IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE))
5672 return -ENXIO;
5673
5674 return sd_bus_message_read_basic(m, type, str);
5675 }
5676
5677 int bus_message_get_arg_strv(sd_bus_message *m, unsigned i, char ***strv) {
5678 const char *contents;
5679 char type;
5680 int r;
5681
5682 assert(m);
5683 assert(strv);
5684
5685 r = bus_message_get_arg_skip(m, i, &type, &contents);
5686 if (r < 0)
5687 return r;
5688
5689 if (type != SD_BUS_TYPE_ARRAY)
5690 return -ENXIO;
5691 if (!STR_IN_SET(contents, "s", "o", "g"))
5692 return -ENXIO;
5693
5694 return sd_bus_message_read_strv(m, strv);
5695 }
5696
5697 _public_ int sd_bus_message_get_errno(sd_bus_message *m) {
5698 assert_return(m, EINVAL);
5699
5700 if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
5701 return 0;
5702
5703 return sd_bus_error_get_errno(&m->error);
5704 }
5705
5706 _public_ const char* sd_bus_message_get_signature(sd_bus_message *m, int complete) {
5707 struct bus_container *c;
5708
5709 assert_return(m, NULL);
5710
5711 c = complete ? &m->root_container : message_get_container(m);
5712 return strempty(c->signature);
5713 }
5714
5715 _public_ int sd_bus_message_is_empty(sd_bus_message *m) {
5716 assert_return(m, -EINVAL);
5717
5718 return isempty(m->root_container.signature);
5719 }
5720
5721 _public_ int sd_bus_message_has_signature(sd_bus_message *m, const char *signature) {
5722 assert_return(m, -EINVAL);
5723
5724 return streq(strempty(m->root_container.signature), strempty(signature));
5725 }
5726
5727 _public_ int sd_bus_message_copy(sd_bus_message *m, sd_bus_message *source, int all) {
5728 bool done_something = false;
5729 int r;
5730
5731 assert_return(m, -EINVAL);
5732 assert_return(source, -EINVAL);
5733 assert_return(!m->sealed, -EPERM);
5734 assert_return(source->sealed, -EPERM);
5735
5736 do {
5737 const char *contents;
5738 char type;
5739 union {
5740 uint8_t u8;
5741 uint16_t u16;
5742 int16_t s16;
5743 uint32_t u32;
5744 int32_t s32;
5745 uint64_t u64;
5746 int64_t s64;
5747 double d64;
5748 const char *string;
5749 int i;
5750 } basic;
5751
5752 r = sd_bus_message_peek_type(source, &type, &contents);
5753 if (r < 0)
5754 return r;
5755 if (r == 0)
5756 break;
5757
5758 done_something = true;
5759
5760 if (bus_type_is_container(type) > 0) {
5761
5762 r = sd_bus_message_enter_container(source, type, contents);
5763 if (r < 0)
5764 return r;
5765
5766 r = sd_bus_message_open_container(m, type, contents);
5767 if (r < 0)
5768 return r;
5769
5770 r = sd_bus_message_copy(m, source, true);
5771 if (r < 0)
5772 return r;
5773
5774 r = sd_bus_message_close_container(m);
5775 if (r < 0)
5776 return r;
5777
5778 r = sd_bus_message_exit_container(source);
5779 if (r < 0)
5780 return r;
5781
5782 continue;
5783 }
5784
5785 r = sd_bus_message_read_basic(source, type, &basic);
5786 if (r < 0)
5787 return r;
5788
5789 assert(r > 0);
5790
5791 if (type == SD_BUS_TYPE_OBJECT_PATH ||
5792 type == SD_BUS_TYPE_SIGNATURE ||
5793 type == SD_BUS_TYPE_STRING)
5794 r = sd_bus_message_append_basic(m, type, basic.string);
5795 else
5796 r = sd_bus_message_append_basic(m, type, &basic);
5797
5798 if (r < 0)
5799 return r;
5800
5801 } while (all);
5802
5803 return done_something;
5804 }
5805
5806 _public_ int sd_bus_message_verify_type(sd_bus_message *m, char type, const char *contents) {
5807 const char *c;
5808 char t;
5809 int r;
5810
5811 assert_return(m, -EINVAL);
5812 assert_return(m->sealed, -EPERM);
5813 assert_return(!type || bus_type_is_valid(type), -EINVAL);
5814 assert_return(!contents || signature_is_valid(contents, true), -EINVAL);
5815 assert_return(type || contents, -EINVAL);
5816 assert_return(!contents || !type || bus_type_is_container(type), -EINVAL);
5817
5818 r = sd_bus_message_peek_type(m, &t, &c);
5819 if (r <= 0)
5820 return r;
5821
5822 if (type != 0 && type != t)
5823 return 0;
5824
5825 if (contents && !streq_ptr(contents, c))
5826 return 0;
5827
5828 return 1;
5829 }
5830
5831 _public_ sd_bus *sd_bus_message_get_bus(sd_bus_message *m) {
5832 assert_return(m, NULL);
5833
5834 return m->bus;
5835 }
5836
5837 int bus_message_remarshal(sd_bus *bus, sd_bus_message **m) {
5838 _cleanup_bus_message_unref_ sd_bus_message *n = NULL;
5839 usec_t timeout;
5840 int r;
5841
5842 assert(bus);
5843 assert(m);
5844 assert(*m);
5845
5846 switch ((*m)->header->type) {
5847
5848 case SD_BUS_MESSAGE_SIGNAL:
5849 r = sd_bus_message_new_signal(bus, &n, (*m)->path, (*m)->interface, (*m)->member);
5850 if (r < 0)
5851 return r;
5852
5853 break;
5854
5855 case SD_BUS_MESSAGE_METHOD_CALL:
5856 r = sd_bus_message_new_method_call(bus, &n, (*m)->destination, (*m)->path, (*m)->interface, (*m)->member);
5857 if (r < 0)
5858 return r;
5859
5860 break;
5861
5862 case SD_BUS_MESSAGE_METHOD_RETURN:
5863 case SD_BUS_MESSAGE_METHOD_ERROR:
5864
5865 n = message_new(bus, (*m)->header->type);
5866 if (!n)
5867 return -ENOMEM;
5868
5869 n->reply_cookie = (*m)->reply_cookie;
5870
5871 r = message_append_reply_cookie(n, n->reply_cookie);
5872 if (r < 0)
5873 return r;
5874
5875 if ((*m)->header->type == SD_BUS_MESSAGE_METHOD_ERROR && (*m)->error.name) {
5876 r = message_append_field_string(n, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, (*m)->error.name, &n->error.message);
5877 if (r < 0)
5878 return r;
5879
5880 n->error._need_free = -1;
5881 }
5882
5883 break;
5884
5885 default:
5886 return -EINVAL;
5887 }
5888
5889 if ((*m)->destination && !n->destination) {
5890 r = message_append_field_string(n, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, (*m)->destination, &n->destination);
5891 if (r < 0)
5892 return r;
5893 }
5894
5895 if ((*m)->sender && !n->sender) {
5896 r = message_append_field_string(n, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, (*m)->sender, &n->sender);
5897 if (r < 0)
5898 return r;
5899 }
5900
5901 n->header->flags |= (*m)->header->flags & (BUS_MESSAGE_NO_REPLY_EXPECTED|BUS_MESSAGE_NO_AUTO_START);
5902
5903 r = sd_bus_message_copy(n, *m, true);
5904 if (r < 0)
5905 return r;
5906
5907 timeout = (*m)->timeout;
5908 if (timeout == 0 && !((*m)->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED))
5909 timeout = BUS_DEFAULT_TIMEOUT;
5910
5911 r = bus_message_seal(n, BUS_MESSAGE_COOKIE(*m), timeout);
5912 if (r < 0)
5913 return r;
5914
5915 sd_bus_message_unref(*m);
5916 *m = n;
5917 n = NULL;
5918
5919 return 0;
5920 }
5921
5922 int bus_message_append_sender(sd_bus_message *m, const char *sender) {
5923 assert(m);
5924 assert(sender);
5925
5926 assert_return(!m->sealed, -EPERM);
5927 assert_return(!m->sender, -EPERM);
5928
5929 return message_append_field_string(m, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, sender, &m->sender);
5930 }
5931
5932 _public_ int sd_bus_message_get_priority(sd_bus_message *m, int64_t *priority) {
5933 assert_return(m, -EINVAL);
5934 assert_return(priority, -EINVAL);
5935
5936 *priority = m->priority;
5937 return 0;
5938 }
5939
5940 _public_ int sd_bus_message_set_priority(sd_bus_message *m, int64_t priority) {
5941 assert_return(m, -EINVAL);
5942 assert_return(!m->sealed, -EPERM);
5943
5944 m->priority = priority;
5945 return 0;
5946 }