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