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