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