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