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