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