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