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