]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd-bus/bus-message.c
update TODO
[thirdparty/systemd.git] / src / libsystemd-bus / bus-message.c
CommitLineData
de1c301e
LP
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>
2c93b4ef 23#include <fcntl.h>
de1c301e
LP
24
25#include "util.h"
9a17484d 26#include "utf8.h"
89ffcd2a 27#include "strv.h"
de1c301e 28
de1c301e 29#include "sd-bus.h"
9a17484d 30#include "bus-message.h"
de1c301e
LP
31#include "bus-internal.h"
32#include "bus-type.h"
33#include "bus-signature.h"
34
80a46c73
LP
35static int message_parse_fields(sd_bus_message *m);
36static int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored);
de1c301e 37
9a17484d
LP
38static void reset_containers(sd_bus_message *m) {
39 unsigned i;
40
41 assert(m);
42
43 for (i = 0; i < m->n_containers; i++)
44 free(m->containers[i].signature);
45
46 free(m->containers);
47 m->containers = NULL;
48
49 m->n_containers = 0;
50 m->root_container.index = 0;
51}
52
de1c301e 53static void message_free(sd_bus_message *m) {
de1c301e
LP
54 assert(m);
55
56 if (m->free_header)
57 free(m->header);
58
59 if (m->free_fields)
60 free(m->fields);
61
62 if (m->free_body)
63 free(m->body);
64
2c93b4ef
LP
65 if (m->free_fds) {
66 close_many(m->fds, m->n_fds);
67 free(m->fds);
68 }
de1c301e 69
9a17484d
LP
70 reset_containers(m);
71 free(m->root_container.signature);
de1c301e 72
9a17484d 73 free(m->peeked_signature);
de1c301e
LP
74 free(m);
75}
76
77static void* buffer_extend(void **p, uint32_t *sz, size_t align, size_t extend) {
78 size_t start, n;
79 void *k;
80
81 assert(p);
82 assert(sz);
83 assert(align > 0);
84
85 start = ALIGN_TO((size_t) *sz, align);
86 n = start + extend;
87
88 if (n == *sz)
89 return (uint8_t*) *p + start;
90
91 if (n > (size_t) ((uint32_t) -1))
92 return NULL;
93
94 k = realloc(*p, n);
95 if (!k)
96 return NULL;
97
98 /* Zero out padding */
99 if (start > *sz)
100 memset((uint8_t*) k + *sz, 0, start - *sz);
101
102 *p = k;
103 *sz = n;
104
105 return (uint8_t*) k + start;
106}
107
108static void *message_extend_fields(sd_bus_message *m, size_t align, size_t sz) {
109 void *p, *o;
110
111 assert(m);
112
113 o = m->fields;
114 p = buffer_extend(&m->fields, &m->header->fields_size, align, sz);
115 if (!p)
116 return NULL;
117
118 if (o != m->fields) {
119 /* Adjust quick access pointers */
120
121 if (m->path)
122 m->path = (const char*) m->fields + (m->path - (const char*) o);
123 if (m->interface)
124 m->interface = (const char*) m->fields + (m->interface - (const char*) o);
125 if (m->member)
126 m->member = (const char*) m->fields + (m->member - (const char*) o);
127 if (m->destination)
128 m->destination = (const char*) m->fields + (m->destination - (const char*) o);
129 if (m->sender)
130 m->sender = (const char*) m->fields + (m->sender - (const char*) o);
de1c301e
LP
131 if (m->error.name)
132 m->error.name = (const char*) m->fields + (m->error.name - (const char*) o);
133 }
134
135 m->free_fields = true;
136
137 return p;
138}
139
140static int message_append_field_string(
141 sd_bus_message *m,
142 uint8_t h,
143 char type,
144 const char *s,
145 const char **ret) {
146
147 size_t l;
148 uint8_t *p;
149
150 assert(m);
151
152 l = strlen(s);
153 if (l > (size_t) (uint32_t) -1)
154 return -EINVAL;
155
156 /* field id byte + signature length + signature 's' + NUL + string length + string + NUL */
157 p = message_extend_fields(m, 8, 4 + 4 + l + 1);
158 if (!p)
159 return -ENOMEM;
160
161 p[0] = h;
162 p[1] = 1;
163 p[2] = type;
164 p[3] = 0;
165
166 ((uint32_t*) p)[1] = l;
167 memcpy(p + 8, s, l + 1);
168
169 if (ret)
170 *ret = (const char*) p + 8;
171
172 return 0;
173}
174
175static int message_append_field_signature(
176 sd_bus_message *m,
177 uint8_t h,
178 const char *s,
179 const char **ret) {
180
181 size_t l;
182 uint8_t *p;
183
184 assert(m);
185
186 l = strlen(s);
187 if (l > 255)
188 return -EINVAL;
189
190 /* field id byte + signature length + signature 'g' + NUL + string length + string + NUL */
191 p = message_extend_fields(m, 8, 4 + 1 + l + 1);
192 if (!p)
193 return -ENOMEM;
194
195 p[0] = h;
196 p[1] = 1;
197 p[2] = SD_BUS_TYPE_SIGNATURE;
198 p[3] = 0;
199 p[4] = l;
200 memcpy(p + 5, s, l + 1);
201
202 if (ret)
203 *ret = (const char*) p + 5;
204
205 return 0;
206}
207
208static int message_append_field_uint32(sd_bus_message *m, uint8_t h, uint32_t x) {
209 uint8_t *p;
210
211 assert(m);
212
213 /* field id byte + signature length + signature 'u' + NUL + value */
214 p = message_extend_fields(m, 8, 4 + 4);
215 if (!p)
216 return -ENOMEM;
217
218 p[0] = h;
219 p[1] = 1;
220 p[2] = SD_BUS_TYPE_UINT32;
221 p[3] = 0;
222
223 ((uint32_t*) p)[1] = x;
224
225 return 0;
226}
227
2571ead1
LP
228int bus_message_from_malloc(
229 void *buffer,
230 size_t length,
2c93b4ef
LP
231 int *fds,
232 unsigned n_fds,
233 const struct ucred *ucred,
2571ead1
LP
234 const char *label,
235 sd_bus_message **ret) {
236
80a46c73
LP
237 sd_bus_message *m;
238 struct bus_header *h;
2571ead1 239 size_t total, fs, bs, label_sz, a;
80a46c73
LP
240 int r;
241
242 assert(buffer || length <= 0);
2c93b4ef 243 assert(fds || n_fds <= 0);
80a46c73
LP
244 assert(ret);
245
246 if (length < sizeof(struct bus_header))
247 return -EBADMSG;
248
249 h = buffer;
250 if (h->version != 1)
251 return -EBADMSG;
252
253 if (h->serial == 0)
254 return -EBADMSG;
255
256 if (h->type == _SD_BUS_MESSAGE_TYPE_INVALID)
257 return -EBADMSG;
258
259 if (h->endian == SD_BUS_NATIVE_ENDIAN) {
260 fs = h->fields_size;
261 bs = h->body_size;
262 } else if (h->endian == SD_BUS_REVERSE_ENDIAN) {
263 fs = bswap_32(h->fields_size);
264 bs = bswap_32(h->body_size);
265 } else
266 return -EBADMSG;
267
9be9c7cf 268 total = sizeof(struct bus_header) + ALIGN8(fs) + bs;
80a46c73
LP
269 if (length != total)
270 return -EBADMSG;
271
2571ead1
LP
272 if (label) {
273 label_sz = strlen(label);
274 a = ALIGN(sizeof(sd_bus_message)) + label_sz + 1;
275 } else
276 a = sizeof(sd_bus_message);
277
278 m = malloc0(a);
80a46c73
LP
279 if (!m)
280 return -ENOMEM;
281
282 m->n_ref = 1;
2c93b4ef 283 m->sealed = true;
80a46c73 284 m->header = h;
80a46c73 285 m->fields = (uint8_t*) buffer + sizeof(struct bus_header);
9be9c7cf 286 m->body = (uint8_t*) buffer + sizeof(struct bus_header) + ALIGN8(fs);
2c93b4ef
LP
287 m->fds = fds;
288 m->n_fds = n_fds;
80a46c73 289
2571ead1
LP
290 if (ucred) {
291 m->uid = ucred->uid;
292 m->pid = ucred->pid;
293 m->gid = ucred->gid;
294 m->uid_valid = m->gid_valid = true;
295 }
296
297 if (label) {
298 m->label = (char*) m + ALIGN(sizeof(sd_bus_message));
299 memcpy(m->label, label, label_sz + 1);
300 }
301
80a46c73
LP
302 m->n_iovec = 1;
303 m->iovec[0].iov_base = buffer;
304 m->iovec[0].iov_len = length;
305
306 r = message_parse_fields(m);
2c93b4ef
LP
307 if (r < 0)
308 goto fail;
309
310 /* We take possession of the memory and fds now */
311 m->free_header = true;
312 m->free_fds = true;
80a46c73
LP
313
314 *ret = m;
315 return 0;
2c93b4ef
LP
316
317fail:
318 message_free(m);
319 return r;
80a46c73
LP
320}
321
de1c301e
LP
322static sd_bus_message *message_new(sd_bus *bus, uint8_t type) {
323 sd_bus_message *m;
324
80a46c73 325 m = malloc0(ALIGN(sizeof(sd_bus_message)) + sizeof(struct bus_header));
de1c301e
LP
326 if (!m)
327 return NULL;
328
329 m->n_ref = 1;
330 m->header = (struct bus_header*) ((uint8_t*) m + ALIGN(sizeof(struct sd_bus_message)));
80a46c73 331 m->header->endian = SD_BUS_NATIVE_ENDIAN;
de1c301e
LP
332 m->header->type = type;
333 m->header->version = bus ? bus->message_version : 1;
021a1e78 334 m->allow_fds = !bus || bus->can_fds || (bus->state != BUS_HELLO && bus->state != BUS_RUNNING);
de1c301e
LP
335
336 return m;
337}
338
339int sd_bus_message_new_signal(
340 sd_bus *bus,
341 const char *path,
342 const char *interface,
343 const char *member,
344 sd_bus_message **m) {
345
346 sd_bus_message *t;
347 int r;
348
349 if (!path)
350 return -EINVAL;
351 if (!interface)
352 return -EINVAL;
353 if (!member)
354 return -EINVAL;
5407f2de
LP
355 if (!m)
356 return -EINVAL;
021a1e78
LP
357 if (bus && bus->state == BUS_UNSET)
358 return -ENOTCONN;
de1c301e
LP
359
360 t = message_new(bus, SD_BUS_MESSAGE_TYPE_SIGNAL);
361 if (!t)
362 return -ENOMEM;
363
89ffcd2a
LP
364 t->header->flags |= SD_BUS_MESSAGE_NO_REPLY_EXPECTED;
365
de1c301e
LP
366 r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
367 if (r < 0)
368 goto fail;
369 r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
370 if (r < 0)
371 goto fail;
372 r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
373 if (r < 0)
374 goto fail;
375
376 *m = t;
377 return 0;
378
379fail:
380 sd_bus_message_unref(t);
381 return r;
382}
383
384int sd_bus_message_new_method_call(
385 sd_bus *bus,
386 const char *destination,
387 const char *path,
388 const char *interface,
389 const char *member,
390 sd_bus_message **m) {
391
392 sd_bus_message *t;
393 int r;
394
395 if (!path)
396 return -EINVAL;
397 if (!member)
398 return -EINVAL;
5407f2de
LP
399 if (!m)
400 return -EINVAL;
021a1e78
LP
401 if (bus && bus->state == BUS_UNSET)
402 return -ENOTCONN;
de1c301e
LP
403
404 t = message_new(bus, SD_BUS_MESSAGE_TYPE_METHOD_CALL);
405 if (!t)
406 return -ENOMEM;
407
408 r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
409 if (r < 0)
410 goto fail;
411 r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
412 if (r < 0)
413 goto fail;
414
415 if (interface) {
416 r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
417 if (r < 0)
418 goto fail;
419 }
420
421 if (destination) {
422 r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &t->destination);
423 if (r < 0)
424 goto fail;
425 }
426
427 *m = t;
428 return 0;
429
430fail:
431 message_free(t);
432 return r;
433}
434
5407f2de 435static int message_new_reply(
de1c301e
LP
436 sd_bus *bus,
437 sd_bus_message *call,
5407f2de 438 uint8_t type,
de1c301e
LP
439 sd_bus_message **m) {
440
441 sd_bus_message *t;
442 int r;
443
444 if (!call)
445 return -EINVAL;
e3017af9
LP
446 if (!call->sealed)
447 return -EPERM;
de1c301e
LP
448 if (call->header->type != SD_BUS_MESSAGE_TYPE_METHOD_CALL)
449 return -EINVAL;
5407f2de
LP
450 if (!m)
451 return -EINVAL;
021a1e78
LP
452 if (bus && bus->state == BUS_UNSET)
453 return -ENOTCONN;
de1c301e 454
5407f2de 455 t = message_new(bus, type);
de1c301e
LP
456 if (!t)
457 return -ENOMEM;
458
89ffcd2a 459 t->header->flags |= SD_BUS_MESSAGE_NO_REPLY_EXPECTED;
de1c301e 460 t->reply_serial = BUS_MESSAGE_SERIAL(call);
5407f2de 461
de1c301e
LP
462 r = message_append_field_uint32(t, SD_BUS_MESSAGE_HEADER_REPLY_SERIAL, t->reply_serial);
463 if (r < 0)
464 goto fail;
465
466 if (call->sender) {
467 r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, call->sender, &t->sender);
468 if (r < 0)
469 goto fail;
470 }
471
5407f2de
LP
472 t->dont_send = !!(call->header->flags & SD_BUS_MESSAGE_NO_REPLY_EXPECTED);
473
de1c301e 474 *m = t;
89ffcd2a 475 return 0;
de1c301e
LP
476
477fail:
478 message_free(t);
479 return r;
480}
481
5407f2de
LP
482int sd_bus_message_new_method_return(
483 sd_bus *bus,
484 sd_bus_message *call,
485 sd_bus_message **m) {
486
487 return message_new_reply(bus, call, SD_BUS_MESSAGE_TYPE_METHOD_RETURN, m);
488}
489
de1c301e
LP
490int sd_bus_message_new_method_error(
491 sd_bus *bus,
492 sd_bus_message *call,
493 const sd_bus_error *e,
494 sd_bus_message **m) {
495
496 sd_bus_message *t;
497 int r;
498
fbfa72b0 499 if (!sd_bus_error_is_set(e))
de1c301e 500 return -EINVAL;
5407f2de
LP
501 if (!m)
502 return -EINVAL;
de1c301e 503
5407f2de 504 r = message_new_reply(bus, call, SD_BUS_MESSAGE_TYPE_METHOD_ERROR, &t);
de1c301e 505 if (r < 0)
5407f2de 506 return r;
de1c301e
LP
507
508 r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
509 if (r < 0)
510 goto fail;
511
512 if (e->message) {
513 r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
514 if (r < 0)
515 goto fail;
516 }
517
518 *m = t;
519 return 0;
520
521fail:
522 message_free(t);
523 return r;
524}
525
526sd_bus_message* sd_bus_message_ref(sd_bus_message *m) {
527 if (!m)
528 return NULL;
529
530 assert(m->n_ref > 0);
531 m->n_ref++;
532
533 return m;
534}
535
536sd_bus_message* sd_bus_message_unref(sd_bus_message *m) {
537 if (!m)
538 return NULL;
539
540 assert(m->n_ref > 0);
541 m->n_ref--;
542
543 if (m->n_ref <= 0)
544 message_free(m);
545
546 return NULL;
547}
548
549int sd_bus_message_get_type(sd_bus_message *m, uint8_t *type) {
550 if (!m)
551 return -EINVAL;
552 if (!type)
553 return -EINVAL;
554
555 *type = m->header->type;
556 return 0;
557}
558
559int sd_bus_message_get_serial(sd_bus_message *m, uint64_t *serial) {
560 if (!m)
561 return -EINVAL;
562 if (!serial)
563 return -EINVAL;
564 if (m->header->serial == 0)
565 return -ENOENT;
566
567 *serial = BUS_MESSAGE_SERIAL(m);
568 return 0;
569}
570
571int sd_bus_message_get_reply_serial(sd_bus_message *m, uint64_t *serial) {
572 if (!m)
573 return -EINVAL;
574 if (!serial)
575 return -EINVAL;
576 if (m->reply_serial == 0)
577 return -ENOENT;
578
579 *serial = m->reply_serial;
580 return 0;
581}
582
583int sd_bus_message_get_no_reply(sd_bus_message *m) {
584 if (!m)
585 return -EINVAL;
586
587 return m->header->type == SD_BUS_MESSAGE_TYPE_METHOD_CALL ? !!(m->header->flags & SD_BUS_MESSAGE_NO_REPLY_EXPECTED) : 0;
588}
589
590const char *sd_bus_message_get_path(sd_bus_message *m) {
591 if (!m)
592 return NULL;
593
594 return m->path;
595}
596
597const char *sd_bus_message_get_interface(sd_bus_message *m) {
598 if (!m)
599 return NULL;
600
601 return m->interface;
602}
603
604const char *sd_bus_message_get_member(sd_bus_message *m) {
605 if (!m)
606 return NULL;
607
608 return m->member;
609}
610const char *sd_bus_message_get_destination(sd_bus_message *m) {
611 if (!m)
612 return NULL;
613
614 return m->destination;
615}
616
617const char *sd_bus_message_get_sender(sd_bus_message *m) {
618 if (!m)
619 return NULL;
620
621 return m->sender;
622}
623
624const sd_bus_error *sd_bus_message_get_error(sd_bus_message *m) {
625 if (!m)
626 return NULL;
627
628 if (!sd_bus_error_is_set(&m->error))
629 return NULL;
630
631 return &m->error;
632}
633
634int sd_bus_message_get_uid(sd_bus_message *m, uid_t *uid) {
635 if (!m)
636 return -EINVAL;
637 if (!m->uid_valid)
638 return -ENOENT;
639
640 *uid = m->uid;
641 return 0;
642}
643
644int sd_bus_message_get_gid(sd_bus_message *m, gid_t *gid) {
645 if (!m)
646 return -EINVAL;
647 if (!m->gid_valid)
648 return -ENOENT;
649
650 *gid = m->gid;
651 return 0;
652}
653
654int sd_bus_message_get_pid(sd_bus_message *m, pid_t *pid) {
655 if (!m)
656 return -EINVAL;
657 if (m->pid <= 0)
658 return -ENOENT;
659
660 *pid = m->pid;
661 return 0;
662}
663
664int sd_bus_message_get_tid(sd_bus_message *m, pid_t *tid) {
665 if (!m)
666 return -EINVAL;
667 if (m->tid <= 0)
668 return -ENOENT;
669
670 *tid = m->tid;
671 return 0;
672}
673
2571ead1
LP
674const char *sd_bus_message_get_label(sd_bus_message *m) {
675 if (!m)
676 return NULL;
677
678 return m->label;
679}
680
de1c301e
LP
681int sd_bus_message_is_signal(sd_bus_message *m, const char *interface, const char *member) {
682 if (!m)
683 return -EINVAL;
684
685 if (m->header->type != SD_BUS_MESSAGE_TYPE_SIGNAL)
686 return 0;
687
688 if (interface && (!m->interface || !streq(m->interface, interface)))
689 return 0;
690
691 if (member && (!m->member || !streq(m->member, member)))
692 return 0;
693
694 return 1;
695}
696
697int sd_bus_message_is_method_call(sd_bus_message *m, const char *interface, const char *member) {
698 if (!m)
699 return -EINVAL;
700
701 if (m->header->type != SD_BUS_MESSAGE_TYPE_METHOD_CALL)
702 return 0;
703
704 if (interface && (!m->interface || !streq(m->interface, interface)))
705 return 0;
706
707 if (member && (!m->member || !streq(m->member, member)))
708 return 0;
709
710 return 1;
711}
712
713int sd_bus_message_is_method_error(sd_bus_message *m, const char *name) {
714 if (!m)
715 return -EINVAL;
716
717 if (m->header->type != SD_BUS_MESSAGE_TYPE_METHOD_ERROR)
718 return 0;
719
720 if (name && (!m->error.name || !streq(m->error.name, name)))
721 return 0;
722
723 return 1;
724}
725
726int sd_bus_message_set_no_reply(sd_bus_message *m, int b) {
727 if (!m)
728 return -EINVAL;
729 if (m->sealed)
730 return -EPERM;
731 if (m->header->type != SD_BUS_MESSAGE_TYPE_METHOD_CALL)
732 return -EPERM;
733
734 if (b)
735 m->header->flags |= SD_BUS_MESSAGE_NO_REPLY_EXPECTED;
736 else
737 m->header->flags &= ~SD_BUS_MESSAGE_NO_REPLY_EXPECTED;
738
739 return 0;
740}
741
742static struct bus_container *message_get_container(sd_bus_message *m) {
743 assert(m);
744
745 if (m->n_containers == 0)
746 return &m->root_container;
747
9a17484d
LP
748 assert(m->containers);
749 return m->containers + m->n_containers - 1;
de1c301e
LP
750}
751
752static void *message_extend_body(sd_bus_message *m, size_t align, size_t sz) {
753 void *p, *o;
754 size_t added;
755 struct bus_container *c;
756
757 assert(m);
9a17484d 758 assert(align > 0);
de1c301e
LP
759
760 o = m->body;
761 added = m->header->body_size;
762
763 p = buffer_extend(&m->body, &m->header->body_size, align, sz);
764 if (!p)
765 return NULL;
766
767 added = m->header->body_size - added;
768
9a17484d 769 for (c = m->containers; c < m->containers + m->n_containers; c++)
de1c301e
LP
770 if (c->array_size) {
771 c->array_size = (uint32_t*) ((uint8_t*) m->body + ((uint8_t*) c->array_size - (uint8_t*) o));
772 *c->array_size += added;
773 }
774
775 if (o != m->body) {
776 if (m->error.message)
777 m->error.message = (const char*) m->body + (m->error.message - (const char*) o);
778 }
779
780 m->free_body = true;
781
782 return p;
783}
784
785int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored) {
786 struct bus_container *c;
27f6e5c7 787 ssize_t align, sz;
de1c301e
LP
788 uint32_t k;
789 void *a;
790 char *e = NULL;
2c93b4ef 791 int fd = -1;
62cfa9da 792 uint32_t fdi = 0;
2c93b4ef 793 int r;
de1c301e
LP
794
795 if (!m)
796 return -EINVAL;
2c93b4ef
LP
797 if (!p)
798 return -EINVAL;
de1c301e
LP
799 if (m->sealed)
800 return -EPERM;
801 if (!bus_type_is_basic(type))
802 return -EINVAL;
803
804 c = message_get_container(m);
805
806 if (c->signature && c->signature[c->index]) {
807 /* Container signature is already set */
808
809 if (c->signature[c->index] != type)
9a17484d 810 return -ENXIO;
de1c301e
LP
811 } else {
812 /* Maybe we can append to the signature? But only if this is the top-level container*/
813 if (c->enclosing != 0)
9a17484d 814 return -ENXIO;
de1c301e
LP
815
816 e = strextend(&c->signature, CHAR_TO_STR(type), NULL);
817 if (!e)
818 return -ENOMEM;
819 }
820
de1c301e
LP
821 switch (type) {
822
823 case SD_BUS_TYPE_STRING:
824 case SD_BUS_TYPE_OBJECT_PATH:
b8beb278 825
de1c301e
LP
826 align = 4;
827 sz = 4 + strlen(p) + 1;
828 break;
829
830 case SD_BUS_TYPE_SIGNATURE:
b8beb278 831
de1c301e
LP
832 align = 1;
833 sz = 1 + strlen(p) + 1;
834 break;
835
836 case SD_BUS_TYPE_BOOLEAN:
837 align = sz = 4;
838
839 assert_cc(sizeof(int) == sizeof(uint32_t));
840 memcpy(&k, p, 4);
841 k = !!k;
842 p = &k;
843 break;
844
2c93b4ef
LP
845 case SD_BUS_TYPE_UNIX_FD: {
846 int z, *f;
847
848 if (!m->allow_fds) {
849 r = -ENOTSUP;
850 goto fail;
851 }
852
853 align = sz = 4;
854
855 z = *(int*) p;
856 if (z < 0) {
857 r = -EINVAL;
858 goto fail;
859 }
860
861 fd = fcntl(z, F_DUPFD_CLOEXEC, 3);
862 if (fd < 0) {
863 r = -errno;
864 goto fail;
865 }
866
867 f = realloc(m->fds, sizeof(int) * (m->n_fds + 1));
868 if (!f) {
869 r = -ENOMEM;
870 goto fail;
871 }
872
873 fdi = m->n_fds;
874 f[fdi] = fd;
875 m->fds = f;
876 m->free_fds = true;
877 break;
878 }
879
de1c301e
LP
880 default:
881 align = bus_type_get_alignment(type);
882 sz = bus_type_get_size(type);
883 break;
884 }
885
886 assert(align > 0);
887 assert(sz > 0);
888
889 a = message_extend_body(m, align, sz);
890 if (!a) {
2c93b4ef
LP
891 r = -ENOMEM;
892 goto fail;
de1c301e
LP
893 }
894
895 if (type == SD_BUS_TYPE_STRING || type == SD_BUS_TYPE_OBJECT_PATH) {
896 *(uint32_t*) a = sz - 5;
897 memcpy((uint8_t*) a + 4, p, sz - 4);
898
899 if (stored)
900 *stored = (const uint8_t*) a + 4;
901
902 } else if (type == SD_BUS_TYPE_SIGNATURE) {
903 *(uint8_t*) a = sz - 1;
904 memcpy((uint8_t*) a + 1, p, sz - 1);
905
906 if (stored)
907 *stored = (const uint8_t*) a + 1;
2c93b4ef
LP
908 } else if (type == SD_BUS_TYPE_UNIX_FD) {
909 *(uint32_t*) a = fdi;
910
911 if (stored)
912 *stored = a;
913
914 m->n_fds ++;
de1c301e
LP
915
916 } else {
917 memcpy(a, p, sz);
918
919 if (stored)
920 *stored = a;
921 }
922
923 if (c->enclosing != SD_BUS_TYPE_ARRAY)
9a17484d 924 c->index++;
de1c301e
LP
925
926 return 0;
2c93b4ef
LP
927
928fail:
929 /* Truncate extended signature again */
930 if (e)
931 c->signature[c->index] = 0;
932
933 if (fd >= 0)
934 close_nointr_nofail(fd);
935
936 return r;
de1c301e
LP
937}
938
939int sd_bus_message_append_basic(sd_bus_message *m, char type, const void *p) {
940 return message_append_basic(m, type, p, NULL);
941}
942
943static int bus_message_open_array(
944 sd_bus_message *m,
945 struct bus_container *c,
946 const char *contents,
947 uint32_t **array_size) {
948
9a17484d 949 unsigned nindex;
de1c301e 950 char *e = NULL;
de1c301e
LP
951 void *a, *b;
952 int alignment;
953 size_t saved;
954
955 assert(m);
956 assert(c);
957 assert(contents);
958 assert(array_size);
959
960 if (!signature_is_single(contents))
961 return -EINVAL;
962
963 alignment = bus_type_get_alignment(contents[0]);
964 if (alignment < 0)
965 return alignment;
966
967 if (c->signature && c->signature[c->index]) {
968
969 /* Verify the existing signature */
970
971 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
9a17484d 972 return -ENXIO;
de1c301e
LP
973
974 if (!startswith(c->signature + c->index + 1, contents))
9a17484d 975 return -ENXIO;
de1c301e
LP
976
977 nindex = c->index + 1 + strlen(contents);
978 } else {
979 if (c->enclosing != 0)
9a17484d 980 return -ENXIO;
de1c301e
LP
981
982 /* Extend the existing signature */
983
984 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_ARRAY), contents, NULL);
985 if (!e)
986 return -ENOMEM;
987
988 nindex = e - c->signature;
989 }
990
991 saved = m->header->body_size;
992 a = message_extend_body(m, 4, 4);
993 if (!a) {
994 /* Truncate extended signature again */
995 if (e)
996 c->signature[c->index] = 0;
997
998 return -ENOMEM;
999 }
1000 b = m->body;
1001
1002 if (!message_extend_body(m, alignment, 0)) {
1003 /* Add alignment between size and first element */
1004 if (e)
1005 c->signature[c->index] = 0;
1006
1007 m->header->body_size = saved;
1008 return -ENOMEM;
1009 }
1010
1011 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1012 c->index = nindex;
1013
1014 /* m->body might have changed so let's readjust a */
1015 a = (uint8_t*) m->body + ((uint8_t*) a - (uint8_t*) b);
1016 *(uint32_t*) a = 0;
1017
1018 *array_size = a;
1019 return 0;
1020}
1021
1022static int bus_message_open_variant(
1023 sd_bus_message *m,
1024 struct bus_container *c,
1025 const char *contents) {
1026
1027 char *e = NULL;
9a17484d 1028 size_t l;
de1c301e
LP
1029 void *a;
1030
1031 assert(m);
1032 assert(c);
1033 assert(contents);
1034
1035 if (!signature_is_single(contents))
1036 return -EINVAL;
1037
1038 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
1039 return -EINVAL;
1040
1041 if (c->signature && c->signature[c->index]) {
1042
1043 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
9a17484d 1044 return -ENXIO;
de1c301e
LP
1045
1046 } else {
1047 if (c->enclosing != 0)
9a17484d 1048 return -ENXIO;
de1c301e
LP
1049
1050 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_VARIANT), NULL);
1051 if (!e)
1052 return -ENOMEM;
1053 }
1054
de1c301e
LP
1055 l = strlen(contents);
1056 a = message_extend_body(m, 1, 1 + l + 1);
1057 if (!a) {
1058 /* Truncate extended signature again */
1059 if (e)
1060 c->signature[c->index] = 0;
1061
1062 return -ENOMEM;
1063 }
1064
1065 *(uint8_t*) a = l;
1066 memcpy((uint8_t*) a + 1, contents, l + 1);
1067
1068 if (c->enclosing != SD_BUS_TYPE_ARRAY)
9a17484d 1069 c->index++;
de1c301e
LP
1070
1071 return 0;
1072}
1073
1074static int bus_message_open_struct(
1075 sd_bus_message *m,
1076 struct bus_container *c,
1077 const char *contents) {
1078
1079 size_t nindex;
1080 char *e = NULL;
1081
1082 assert(m);
1083 assert(c);
1084 assert(contents);
1085
1086 if (!signature_is_valid(contents, false))
1087 return -EINVAL;
1088
1089 if (c->signature && c->signature[c->index]) {
1090 size_t l;
1091
1092 l = strlen(contents);
1093
1094 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
1095 !startswith(c->signature + c->index + 1, contents) ||
1096 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
9a17484d 1097 return -ENXIO;
de1c301e
LP
1098
1099 nindex = c->index + 1 + l + 1;
1100 } else {
1101 if (c->enclosing != 0)
9a17484d 1102 return -ENXIO;
de1c301e
LP
1103
1104 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_BEGIN), contents, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_END), NULL);
1105 if (!e)
1106 return -ENOMEM;
1107
1108 nindex = e - c->signature;
1109 }
1110
1111 /* Align contents to 8 byte boundary */
1112 if (!message_extend_body(m, 8, 0)) {
1113 if (e)
1114 c->signature[c->index] = 0;
1115
1116 return -ENOMEM;
1117 }
1118
1119 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1120 c->index = nindex;
1121
1122 return 0;
1123}
1124
1125static int bus_message_open_dict_entry(
1126 sd_bus_message *m,
1127 struct bus_container *c,
1128 const char *contents) {
1129
1130 size_t nindex;
1131
1132 assert(m);
1133 assert(c);
1134 assert(contents);
1135
1136 if (!signature_is_pair(contents))
1137 return -EINVAL;
1138
1139 if (c->enclosing != SD_BUS_TYPE_ARRAY)
9a17484d 1140 return -ENXIO;
de1c301e
LP
1141
1142 if (c->signature && c->signature[c->index]) {
1143 size_t l;
1144
1145 l = strlen(contents);
1146
1147 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
1148 !startswith(c->signature + c->index + 1, contents) ||
1149 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
9a17484d 1150 return -ENXIO;
de1c301e
LP
1151
1152 nindex = c->index + 1 + l + 1;
1153 } else
9a17484d 1154 return -ENXIO;
de1c301e
LP
1155
1156 /* Align contents to 8 byte boundary */
1157 if (!message_extend_body(m, 8, 0))
1158 return -ENOMEM;
1159
1160 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1161 c->index = nindex;
1162
1163 return 0;
1164}
1165
1166int sd_bus_message_open_container(
1167 sd_bus_message *m,
1168 char type,
1169 const char *contents) {
1170
9a17484d 1171 struct bus_container *c, *w;
de1c301e 1172 uint32_t *array_size = NULL;
9a17484d 1173 char *signature;
de1c301e
LP
1174 int r;
1175
1176 if (!m)
1177 return -EINVAL;
1178 if (m->sealed)
1179 return -EPERM;
1180 if (!contents)
1181 return -EINVAL;
1182
1183 /* Make sure we have space for one more container */
9a17484d
LP
1184 w = realloc(m->containers, sizeof(struct bus_container) * (m->n_containers + 1));
1185 if (!w)
de1c301e 1186 return -ENOMEM;
9a17484d 1187 m->containers = w;
de1c301e
LP
1188
1189 c = message_get_container(m);
1190
1191 signature = strdup(contents);
1192 if (!signature)
1193 return -ENOMEM;
1194
1195 if (type == SD_BUS_TYPE_ARRAY)
1196 r = bus_message_open_array(m, c, contents, &array_size);
1197 else if (type == SD_BUS_TYPE_VARIANT)
1198 r = bus_message_open_variant(m, c, contents);
1199 else if (type == SD_BUS_TYPE_STRUCT)
1200 r = bus_message_open_struct(m, c, contents);
1201 else if (type == SD_BUS_TYPE_DICT_ENTRY)
1202 r = bus_message_open_dict_entry(m, c, contents);
1203 else
1204 r = -EINVAL;
1205
1206 if (r < 0) {
1207 free(signature);
1208 return r;
1209 }
1210
1211 /* OK, let's fill it in */
9a17484d
LP
1212 w += m->n_containers++;
1213 w->enclosing = type;
1214 w->signature = signature;
1215 w->index = 0;
1216 w->array_size = array_size;
1217 w->begin = 0;
de1c301e
LP
1218
1219 return 0;
1220}
1221
1222int sd_bus_message_close_container(sd_bus_message *m) {
1223 struct bus_container *c;
1224
1225 if (!m)
1226 return -EINVAL;
1227 if (m->sealed)
1228 return -EPERM;
1229 if (m->n_containers <= 0)
1230 return -EINVAL;
1231
1232 c = message_get_container(m);
de1c301e 1233 if (c->enclosing != SD_BUS_TYPE_ARRAY)
9a17484d 1234 if (c->signature && c->signature[c->index] != 0)
de1c301e
LP
1235 return -EINVAL;
1236
1237 free(c->signature);
1238 m->n_containers--;
1239
1240 return 0;
1241}
1242
1b492614
LP
1243
1244typedef struct {
1245 const char *types;
1246 unsigned n_struct;
1247 unsigned n_array;
1248} TypeStack;
1249
1250static int type_stack_push(TypeStack *stack, unsigned max, unsigned *i, const char *types, unsigned n_struct, unsigned n_array) {
1251 assert(stack);
1252 assert(max > 0);
1253
1254 if (*i >= max)
1255 return -EINVAL;
1256
1257 stack[*i].types = types;
1258 stack[*i].n_struct = n_struct;
1259 stack[*i].n_array = n_array;
1260 (*i)++;
1261
1262 return 0;
1263}
1264
1265static int type_stack_pop(TypeStack *stack, unsigned max, unsigned *i, const char **types, unsigned *n_struct, unsigned *n_array) {
1266 assert(stack);
1267 assert(max > 0);
1268 assert(types);
1269 assert(n_struct);
1270 assert(n_array);
1271
1272 if (*i <= 0)
1273 return 0;
1274
1275 (*i)--;
1276 *types = stack[*i].types;
1277 *n_struct = stack[*i].n_struct;
1278 *n_array = stack[*i].n_array;
1279
1280 return 1;
1281}
1282
917b5dc7 1283int bus_message_append_ap(
de1c301e
LP
1284 sd_bus_message *m,
1285 const char *types,
1286 va_list ap) {
1287
1b492614
LP
1288 unsigned n_array, n_struct;
1289 TypeStack stack[BUS_CONTAINER_DEPTH];
1290 unsigned stack_ptr = 0;
de1c301e
LP
1291 int r;
1292
1293 assert(m);
88d331d5
LP
1294
1295 if (!types)
1296 return 0;
de1c301e 1297
1b492614
LP
1298 n_array = (unsigned) -1;
1299 n_struct = strlen(types);
1300
1301 for (;;) {
1302 const char *t;
1303
1304 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
1305 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
1306 if (r < 0)
1307 return r;
1308 if (r == 0)
1309 break;
1310
1311 r = sd_bus_message_close_container(m);
1312 if (r < 0)
1313 return r;
1314
1315 continue;
1316 }
1317
1318 t = types;
1319 if (n_array != (unsigned) -1)
1320 n_array --;
1321 else {
1322 types ++;
1323 n_struct--;
1324 }
1325
de1c301e
LP
1326 switch (*t) {
1327
1328 case SD_BUS_TYPE_BYTE: {
1329 uint8_t x;
1330
1331 x = (uint8_t) va_arg(ap, int);
1332 r = sd_bus_message_append_basic(m, *t, &x);
1333 break;
1334 }
1335
1336 case SD_BUS_TYPE_BOOLEAN:
1337 case SD_BUS_TYPE_INT32:
9a17484d
LP
1338 case SD_BUS_TYPE_UINT32:
1339 case SD_BUS_TYPE_UNIX_FD: {
de1c301e
LP
1340 uint32_t x;
1341
9a17484d
LP
1342 /* We assume a boolean is the same as int32_t */
1343 assert_cc(sizeof(int32_t) == sizeof(int));
1344
de1c301e
LP
1345 x = va_arg(ap, uint32_t);
1346 r = sd_bus_message_append_basic(m, *t, &x);
1347 break;
1348 }
1349
1350 case SD_BUS_TYPE_INT16:
1351 case SD_BUS_TYPE_UINT16: {
1352 uint16_t x;
1353
1354 x = (uint16_t) va_arg(ap, int);
1355 r = sd_bus_message_append_basic(m, *t, &x);
1356 break;
1357 }
1358
1359 case SD_BUS_TYPE_INT64:
1360 case SD_BUS_TYPE_UINT64:
1361 case SD_BUS_TYPE_DOUBLE: {
1362 uint64_t x;
1363
1364 x = va_arg(ap, uint64_t);
1365 r = sd_bus_message_append_basic(m, *t, &x);
1366 break;
1367 }
1368
1369 case SD_BUS_TYPE_STRING:
1370 case SD_BUS_TYPE_OBJECT_PATH:
1371 case SD_BUS_TYPE_SIGNATURE: {
1372 const char *x;
1373
1374 x = va_arg(ap, const char*);
1375 r = sd_bus_message_append_basic(m, *t, x);
1376 break;
1377 }
1378
de1c301e 1379 case SD_BUS_TYPE_ARRAY: {
de1c301e
LP
1380 size_t k;
1381
1382 r = signature_element_length(t + 1, &k);
1383 if (r < 0)
1384 return r;
1385
1386 {
1387 char s[k + 1];
de1c301e
LP
1388 memcpy(s, t + 1, k);
1389 s[k] = 0;
de1c301e
LP
1390
1391 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, s);
1392 if (r < 0)
1393 return r;
1b492614 1394 }
de1c301e 1395
1b492614
LP
1396 if (n_array == (unsigned) -1) {
1397 types += k;
1398 n_struct -= k;
de1c301e
LP
1399 }
1400
1b492614
LP
1401 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
1402 if (r < 0)
1403 return r;
1404
1405 types = t + 1;
1406 n_struct = k;
1407 n_array = va_arg(ap, unsigned);
1408
de1c301e
LP
1409 break;
1410 }
1411
1412 case SD_BUS_TYPE_VARIANT: {
1413 const char *s;
1414
1415 s = va_arg(ap, const char*);
1416 if (!s)
1417 return -EINVAL;
1418
1419 r = sd_bus_message_open_container(m, SD_BUS_TYPE_VARIANT, s);
1420 if (r < 0)
1421 return r;
1422
1b492614 1423 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
de1c301e
LP
1424 if (r < 0)
1425 return r;
1426
1b492614
LP
1427 types = s;
1428 n_struct = strlen(s);
1429 n_array = (unsigned) -1;
1430
de1c301e
LP
1431 break;
1432 }
1433
1434 case SD_BUS_TYPE_STRUCT_BEGIN:
1435 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
1436 size_t k;
1437
1438 r = signature_element_length(t, &k);
1439 if (r < 0)
1440 return r;
1441
1442 {
1443 char s[k - 1];
1444
1445 memcpy(s, t + 1, k - 2);
1446 s[k - 2] = 0;
1447
1448 r = sd_bus_message_open_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
1449 if (r < 0)
1450 return r;
1b492614 1451 }
de1c301e 1452
1b492614
LP
1453 if (n_array == (unsigned) -1) {
1454 types += k - 1;
1455 n_struct -= k - 1;
1456 }
de1c301e 1457
1b492614
LP
1458 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
1459 if (r < 0)
1460 return r;
de1c301e 1461
1b492614
LP
1462 types = t + 1;
1463 n_struct = k - 2;
1464 n_array = (unsigned) -1;
de1c301e
LP
1465
1466 break;
1467 }
1468
1469 default:
1470 r = -EINVAL;
1471 }
1472
1473 if (r < 0)
1474 return r;
1475 }
1476
1477 return 0;
1478}
1479
1480int sd_bus_message_append(sd_bus_message *m, const char *types, ...) {
1481 va_list ap;
1482 int r;
1483
1484 if (!m)
1485 return -EINVAL;
1486 if (m->sealed)
1487 return -EPERM;
1488 if (!types)
917b5dc7 1489 return 0;
de1c301e
LP
1490
1491 va_start(ap, types);
917b5dc7 1492 r = bus_message_append_ap(m, types, ap);
de1c301e
LP
1493 va_end(ap);
1494
1495 return r;
1496}
1497
9a17484d
LP
1498static int buffer_peek(const void *p, uint32_t sz, size_t *rindex, size_t align, size_t nbytes, void **r) {
1499 size_t k, start, n;
de1c301e 1500
9a17484d
LP
1501 assert(rindex);
1502 assert(align > 0);
de1c301e 1503
9a17484d
LP
1504 start = ALIGN_TO((size_t) *rindex, align);
1505 n = start + nbytes;
1506
1507 if (n > sz)
1508 return -EBADMSG;
1509
1510 /* Verify that padding is 0 */
1511 for (k = *rindex; k < start; k++)
1512 if (((const uint8_t*) p)[k] != 0)
1513 return -EBADMSG;
1514
1515 if (r)
1516 *r = (uint8_t*) p + start;
1517
1518 *rindex = n;
1519
1520 return 1;
de1c301e
LP
1521}
1522
9a17484d
LP
1523static bool message_end_of_array(sd_bus_message *m, size_t index) {
1524 struct bus_container *c;
de1c301e 1525
9a17484d 1526 assert(m);
de1c301e 1527
9a17484d
LP
1528 c = message_get_container(m);
1529 if (!c->array_size)
1530 return false;
de1c301e 1531
9a17484d 1532 return index >= c->begin + BUS_MESSAGE_BSWAP32(m, *c->array_size);
de1c301e
LP
1533}
1534
9a17484d 1535static int message_peek_body(sd_bus_message *m, size_t *rindex, size_t align, size_t nbytes, void **ret) {
de1c301e 1536 assert(m);
9a17484d
LP
1537 assert(rindex);
1538 assert(align > 0);
de1c301e 1539
9a17484d
LP
1540 if (message_end_of_array(m, *rindex))
1541 return 0;
de1c301e 1542
9a17484d
LP
1543 return buffer_peek(m->body, BUS_MESSAGE_BODY_SIZE(m), rindex, align, nbytes, ret);
1544}
de1c301e 1545
ac89bf1d 1546static bool validate_nul(const char *s, size_t l) {
de1c301e 1547
9a17484d
LP
1548 /* Check for NUL chars in the string */
1549 if (memchr(s, 0, l))
1550 return false;
de1c301e 1551
9a17484d
LP
1552 /* Check for NUL termination */
1553 if (s[l] != 0)
1554 return false;
de1c301e 1555
ac89bf1d
LP
1556 return true;
1557}
1558
1559static bool validate_string(const char *s, size_t l) {
1560
1561 if (!validate_nul(s, l))
1562 return false;
1563
9a17484d
LP
1564 /* Check if valid UTF8 */
1565 if (!utf8_is_valid(s))
1566 return false;
1567
1568 return true;
de1c301e
LP
1569}
1570
9a17484d 1571static bool validate_signature(const char *s, size_t l) {
de1c301e 1572
ac89bf1d 1573 if (!validate_nul(s, l))
9a17484d 1574 return false;
de1c301e 1575
9a17484d
LP
1576 /* Check if valid signature */
1577 if (!signature_is_valid(s, true))
1578 return false;
1579
1580 return true;
1581}
1582
ac89bf1d
LP
1583static bool validate_object_path(const char *s, size_t l) {
1584
1585 if (!validate_nul(s, l))
1586 return false;
1587
1588 if (!object_path_is_valid(s))
1589 return false;
1590
1591 return true;
1592}
1593
9a17484d
LP
1594int sd_bus_message_read_basic(sd_bus_message *m, char type, void *p) {
1595 struct bus_container *c;
1596 int r;
1597 void *q;
1598
1599 if (!m)
1600 return -EINVAL;
1601 if (!m->sealed)
de1c301e 1602 return -EPERM;
9a17484d
LP
1603 if (!bus_type_is_basic(type))
1604 return -EINVAL;
2c93b4ef
LP
1605 if (!p)
1606 return -EINVAL;
de1c301e 1607
9a17484d 1608 c = message_get_container(m);
de1c301e 1609
9a17484d
LP
1610 if (!c->signature || c->signature[c->index] == 0)
1611 return 0;
1612
1613 if (c->signature[c->index] != type)
1614 return -ENXIO;
1615
1616 switch (type) {
1617
1618 case SD_BUS_TYPE_STRING:
1619 case SD_BUS_TYPE_OBJECT_PATH: {
1620 uint32_t l;
1621 size_t rindex;
1622
1623 rindex = m->rindex;
1624 r = message_peek_body(m, &rindex, 4, 4, &q);
1625 if (r <= 0)
1626 return r;
1627
1628 l = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
1629 r = message_peek_body(m, &rindex, 1, l+1, &q);
de1c301e
LP
1630 if (r < 0)
1631 return r;
9a17484d
LP
1632 if (r == 0)
1633 return -EBADMSG;
1634
ac89bf1d
LP
1635 if (type == SD_BUS_TYPE_OBJECT_PATH) {
1636 if (!validate_object_path(q, l))
1637 return -EBADMSG;
1638 } else {
1639 if (!validate_string(q, l))
1640 return -EBADMSG;
1641 }
9a17484d
LP
1642
1643 m->rindex = rindex;
1644 *(const char**) p = q;
1645 break;
de1c301e
LP
1646 }
1647
9a17484d
LP
1648 case SD_BUS_TYPE_SIGNATURE: {
1649 uint8_t l;
1650 size_t rindex;
1651
1652 rindex = m->rindex;
1653 r = message_peek_body(m, &rindex, 1, 1, &q);
1654 if (r <= 0)
1655 return r;
1656
1657 l = *(uint8_t*) q;
1658 r = message_peek_body(m, &rindex, 1, l+1, &q);
de1c301e
LP
1659 if (r < 0)
1660 return r;
9a17484d
LP
1661 if (r == 0)
1662 return -EBADMSG;
1663
1664 if (!validate_signature(q, l))
1665 return -EBADMSG;
1666
1667 m->rindex = rindex;
1668 *(const char**) p = q;
1669 break;
de1c301e
LP
1670 }
1671
9a17484d 1672 default: {
27f6e5c7
ZJS
1673 ssize_t sz, align;
1674 size_t rindex;
de1c301e 1675
9a17484d
LP
1676 align = bus_type_get_alignment(type);
1677 sz = bus_type_get_size(type);
27f6e5c7 1678 assert(align > 0 && sz > 0);
de1c301e 1679
2c93b4ef
LP
1680 rindex = m->rindex;
1681 r = message_peek_body(m, &rindex, align, sz, &q);
9a17484d
LP
1682 if (r <= 0)
1683 return r;
1684
1685 switch (type) {
1686
1687 case SD_BUS_TYPE_BYTE:
1688 *(uint8_t*) p = *(uint8_t*) q;
1689 break;
1690
1691 case SD_BUS_TYPE_BOOLEAN:
1692 *(int*) p = !!*(uint32_t*) q;
1693 break;
1694
1695 case SD_BUS_TYPE_INT16:
1696 case SD_BUS_TYPE_UINT16:
1697 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
1698 break;
1699
1700 case SD_BUS_TYPE_INT32:
1701 case SD_BUS_TYPE_UINT32:
1702 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
1703 break;
1704
1705 case SD_BUS_TYPE_INT64:
1706 case SD_BUS_TYPE_UINT64:
1707 case SD_BUS_TYPE_DOUBLE:
1708 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
1709 break;
1710
2c93b4ef 1711 case SD_BUS_TYPE_UNIX_FD: {
2c93b4ef
LP
1712 uint32_t j;
1713
1714 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
1715 if (j >= m->n_fds)
1716 return -EBADMSG;
1717
1ef2af5a 1718 *(int*) p = m->fds[j];
2c93b4ef
LP
1719 break;
1720 }
1721
9a17484d
LP
1722 default:
1723 assert_not_reached("Unknown basic type...");
1724 }
1725
2c93b4ef
LP
1726 m->rindex = rindex;
1727
9a17484d
LP
1728 break;
1729 }
1730 }
1731
1732 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1733 c->index++;
1734
1735 return 1;
de1c301e
LP
1736}
1737
9a17484d
LP
1738static int bus_message_enter_array(
1739 sd_bus_message *m,
1740 struct bus_container *c,
1741 const char *contents,
1742 uint32_t **array_size) {
1743
1744 size_t rindex;
1745 void *q;
1746 int r, alignment;
1747
1748 assert(m);
1749 assert(c);
1750 assert(contents);
1751 assert(array_size);
1752
1753 if (!signature_is_single(contents))
de1c301e 1754 return -EINVAL;
9a17484d
LP
1755
1756 alignment = bus_type_get_alignment(contents[0]);
1757 if (alignment < 0)
1758 return alignment;
1759
1760 if (!c->signature || c->signature[c->index] == 0)
1761 return 0;
1762
1763 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
1764 return -ENXIO;
1765
1766 if (!startswith(c->signature + c->index + 1, contents))
1767 return -ENXIO;
1768
1769 rindex = m->rindex;
1770 r = message_peek_body(m, &rindex, 4, 4, &q);
1771 if (r <= 0)
1772 return r;
1773
ac89bf1d 1774 if (BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q) > BUS_ARRAY_MAX_SIZE)
80a46c73 1775 return -EBADMSG;
9a17484d
LP
1776
1777 r = message_peek_body(m, &rindex, alignment, 0, NULL);
1778 if (r < 0)
1779 return r;
1780 if (r == 0)
1781 return -EBADMSG;
1782
1783 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1784 c->index += 1 + strlen(contents);
1785
1786 m->rindex = rindex;
1787
1788 *array_size = (uint32_t*) q;
1789
1790 return 1;
1791}
1792
1793static int bus_message_enter_variant(
1794 sd_bus_message *m,
1795 struct bus_container *c,
1796 const char *contents) {
1797
1798 size_t rindex;
1799 uint8_t l;
1800 void *q;
1801 int r;
1802
1803 assert(m);
1804 assert(c);
1805 assert(contents);
1806
1807 if (!signature_is_single(contents))
de1c301e 1808 return -EINVAL;
de1c301e 1809
9a17484d
LP
1810 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
1811 return -EINVAL;
1812
1813 if (!c->signature || c->signature[c->index] == 0)
1814 return 0;
1815
1816 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
1817 return -ENXIO;
1818
1819 rindex = m->rindex;
1820 r = message_peek_body(m, &rindex, 1, 1, &q);
1821 if (r <= 0)
1822 return r;
1823
1824 l = *(uint8_t*) q;
1825 r = message_peek_body(m, &rindex, 1, l+1, &q);
1826 if (r < 0)
1827 return r;
1828 if (r == 0)
1829 return -EBADMSG;
1830
1831 if (!validate_signature(q, l))
1832 return -EBADMSG;
1833
1834 if (!streq(q, contents))
1835 return -ENXIO;
1836
1837 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1838 c->index++;
1839
1840 m->rindex = rindex;
1841
1842 return 1;
de1c301e
LP
1843}
1844
9a17484d
LP
1845static int bus_message_enter_struct(
1846 sd_bus_message *m,
1847 struct bus_container *c,
1848 const char *contents) {
1849
1850 size_t l;
1851 int r;
1852
1853 assert(m);
1854 assert(c);
1855 assert(contents);
1856
1857 if (!signature_is_valid(contents, false))
1858 return -EINVAL;
1859
1860 if (!c->signature || c->signature[c->index] == 0)
1861 return 0;
1862
1863 l = strlen(contents);
1864
1865 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
1866 !startswith(c->signature + c->index + 1, contents) ||
1867 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
1868 return -ENXIO;
1869
1870 r = message_peek_body(m, &m->rindex, 8, 0, NULL);
1871 if (r <= 0)
1872 return r;
1873
1874 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1875 c->index += 1 + l + 1;
1876
1877 return 1;
1878}
1879
1880static int bus_message_enter_dict_entry(
1881 sd_bus_message *m,
1882 struct bus_container *c,
1883 const char *contents) {
1884
1885 size_t l;
1886 int r;
1887
1888 assert(m);
1889 assert(c);
1890 assert(contents);
1891
1892 if (!signature_is_pair(contents))
1893 return -EINVAL;
1894
1895 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1896 return -ENXIO;
1897
1898 if (!c->signature || c->signature[c->index] == 0)
1899 return 0;
1900
1901 l = strlen(contents);
1902
1903 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
1904 !startswith(c->signature + c->index + 1, contents) ||
1905 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
1906 return -ENXIO;
1907
1908 r = message_peek_body(m, &m->rindex, 8, 0, NULL);
1909 if (r <= 0)
1910 return r;
1911
1912 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1913 c->index += 1 + l + 1;
1914
1915 return 1;
1916}
1917
1918int sd_bus_message_enter_container(sd_bus_message *m, char type, const char *contents) {
1919 struct bus_container *c, *w;
1920 uint32_t *array_size = NULL;
1921 char *signature;
1922 int r;
1923
1924 if (!m)
1925 return -EINVAL;
1926 if (!m->sealed)
1927 return -EPERM;
1928 if (!contents)
1929 return -EINVAL;
1930
ed205a6b
LP
1931 /*
1932 * We enforce a global limit on container depth, that is much
1933 * higher than the 32 structs and 32 arrays the specification
1934 * mandates. This is simpler to implement for us, and we need
1935 * this only to ensure our container array doesn't grow
1936 * without bounds. We are happy to return any data from a
1937 * message as long as the data itself is valid, even if the
1938 * overall message might be not.
1939 *
1940 * Note that the message signature is validated when
1941 * parsing the headers, and that validation does check the
1942 * 32/32 limit.
1943 *
1944 * Note that the specification defines no limits on the depth
1945 * of stacked variants, but we do.
1946 */
1947 if (m->n_containers >= BUS_CONTAINER_DEPTH)
1948 return -EBADMSG;
1949
9a17484d
LP
1950 w = realloc(m->containers, sizeof(struct bus_container) * (m->n_containers + 1));
1951 if (!w)
1952 return -ENOMEM;
1953 m->containers = w;
1954
1955 c = message_get_container(m);
1956
1957 if (!c->signature || c->signature[c->index] == 0)
1958 return 0;
1959
1960 signature = strdup(contents);
1961 if (!signature)
1962 return -ENOMEM;
1963
1964 if (type == SD_BUS_TYPE_ARRAY)
1965 r = bus_message_enter_array(m, c, contents, &array_size);
1966 else if (type == SD_BUS_TYPE_VARIANT)
1967 r = bus_message_enter_variant(m, c, contents);
1968 else if (type == SD_BUS_TYPE_STRUCT)
1969 r = bus_message_enter_struct(m, c, contents);
1970 else if (type == SD_BUS_TYPE_DICT_ENTRY)
1971 r = bus_message_enter_dict_entry(m, c, contents);
1972 else
1973 r = -EINVAL;
1974
1975 if (r <= 0) {
1976 free(signature);
1977 return r;
1978 }
1979
1980 /* OK, let's fill it in */
1981 w += m->n_containers++;
1982 w->enclosing = type;
1983 w->signature = signature;
1984 w->index = 0;
1985 w->array_size = array_size;
1986 w->begin = m->rindex;
1987
1988 return 1;
1989}
1990
1991int sd_bus_message_exit_container(sd_bus_message *m) {
1992 struct bus_container *c;
1993
1994 if (!m)
1995 return -EINVAL;
1996 if (!m->sealed)
1997 return -EPERM;
1998 if (m->n_containers <= 0)
1999 return -EINVAL;
2000
2001 c = message_get_container(m);
2002 if (c->enclosing == SD_BUS_TYPE_ARRAY) {
2003 uint32_t l;
2004
2005 l = BUS_MESSAGE_BSWAP32(m, *c->array_size);
2006 if (c->begin + l != m->rindex)
2007 return -EBUSY;
2008
2009 } else {
2010 if (c->signature && c->signature[c->index] != 0)
2011 return -EINVAL;
2012 }
2013
2014 free(c->signature);
2015 m->n_containers--;
2016
2017 return 1;
2018}
2019
2020int sd_bus_message_peek_type(sd_bus_message *m, char *type, const char **contents) {
2021 struct bus_container *c;
2022 int r;
2023
2024 if (!m)
2025 return -EINVAL;
2026 if (!m->sealed)
2027 return -EPERM;
2028
2029 c = message_get_container(m);
2030
2031 if (!c->signature || c->signature[c->index] == 0)
2032 goto eof;
2033
2034 if (message_end_of_array(m, m->rindex))
2035 goto eof;
2036
2037 if (bus_type_is_basic(c->signature[c->index])) {
2038 if (contents)
2039 *contents = NULL;
2040 if (type)
2041 *type = c->signature[c->index];
2042 return 1;
2043 }
2044
2045 if (c->signature[c->index] == SD_BUS_TYPE_ARRAY) {
2046
2047 if (contents) {
2048 size_t l;
2049 char *sig;
2050
2051 r = signature_element_length(c->signature+c->index+1, &l);
2052 if (r < 0)
2053 return r;
2054
80a46c73
LP
2055 assert(l >= 1);
2056
9a17484d
LP
2057 sig = strndup(c->signature + c->index + 1, l);
2058 if (!sig)
2059 return -ENOMEM;
2060
2061 free(m->peeked_signature);
2062 m->peeked_signature = sig;
2063
2064 *contents = sig;
2065 }
2066
2067 if (type)
2068 *type = SD_BUS_TYPE_ARRAY;
2069
2070 return 1;
2071 }
2072
2073 if (c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ||
2074 c->signature[c->index] == SD_BUS_TYPE_DICT_ENTRY_BEGIN) {
2075
2076 if (contents) {
2077 size_t l;
2078 char *sig;
2079
2080 r = signature_element_length(c->signature+c->index, &l);
2081 if (r < 0)
2082 return r;
2083
2084 assert(l >= 2);
2085 sig = strndup(c->signature + c->index + 1, l - 2);
2086 if (!sig)
2087 return -ENOMEM;
2088
2089 free(m->peeked_signature);
2090 m->peeked_signature = sig;
2091
2092 *contents = sig;
2093 }
2094
2095 if (type)
2096 *type = c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY;
2097
2098 return 1;
2099 }
2100
2101 if (c->signature[c->index] == SD_BUS_TYPE_VARIANT) {
2102 if (contents) {
2103 size_t rindex, l;
2104 void *q;
2105
2106 rindex = m->rindex;
2107 r = message_peek_body(m, &rindex, 1, 1, &q);
2108 if (r < 0)
2109 return r;
2110 if (r == 0)
2111 goto eof;
2112
2113 l = *(uint8_t*) q;
2114 r = message_peek_body(m, &rindex, 1, l+1, &q);
2115 if (r < 0)
2116 return r;
2117 if (r == 0)
2118 return -EBADMSG;
2119
2120 if (!validate_signature(q, l))
2121 return -EBADMSG;
2122
2123 *contents = q;
2124 }
2125
2126 if (type)
2127 *type = SD_BUS_TYPE_VARIANT;
2128
2129 return 1;
2130 }
2131
2132 return -EINVAL;
2133
2134eof:
2135 if (type)
2136 *type = c->enclosing;
2137 if (contents)
2138 *contents = NULL;
2139 return 0;
2140}
2141
89ffcd2a 2142int sd_bus_message_rewind(sd_bus_message *m, int complete) {
9a17484d
LP
2143 struct bus_container *c;
2144
2145 if (!m)
2146 return -EINVAL;
2147 if (!m->sealed)
2148 return -EPERM;
2149
2150 if (complete) {
2151 reset_containers(m);
2152 m->rindex = 0;
2153 m->root_container.index = 0;
2154
2155 c = message_get_container(m);
2156 } else {
2157 c = message_get_container(m);
2158
2159 c->index = 0;
2160 m->rindex = c->begin;
2161 }
2162
2163 return !isempty(c->signature);
2164}
1b492614
LP
2165static int message_read_ap(
2166 sd_bus_message *m,
2167 const char *types,
2168 va_list ap) {
9a17484d 2169
fe1d424d
LP
2170 unsigned n_array, n_struct;
2171 TypeStack stack[BUS_CONTAINER_DEPTH];
2172 unsigned stack_ptr = 0;
9a17484d
LP
2173 int r;
2174
2175 assert(m);
1b492614
LP
2176
2177 if (!types)
2178 return 0;
9a17484d 2179
fe1d424d
LP
2180 /* Ideally, we'd just call ourselves recursively on every
2181 * complex type. However, the state of a va_list that is
2182 * passed to a function is undefined after that function
2183 * returns. This means we need to docode the va_list linearly
2184 * in a single stackframe. We hence implement our own
2185 * home-grown stack in an array. */
2186
2187 n_array = (unsigned) -1;
2188 n_struct = strlen(types);
2189
2190 for (;;) {
2191 const char *t;
2192
1b492614 2193 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
fe1d424d
LP
2194 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
2195 if (r < 0)
2196 return r;
2197 if (r == 0)
2198 break;
2199
2200 r = sd_bus_message_exit_container(m);
2201 if (r < 0)
2202 return r;
2203
2204 continue;
2205 }
2206
2207 t = types;
2208 if (n_array != (unsigned) -1)
2209 n_array --;
2210 else {
2211 types ++;
2212 n_struct--;
2213 }
2214
9a17484d
LP
2215 switch (*t) {
2216
2217 case SD_BUS_TYPE_BYTE:
2218 case SD_BUS_TYPE_BOOLEAN:
2219 case SD_BUS_TYPE_INT16:
2220 case SD_BUS_TYPE_UINT16:
2221 case SD_BUS_TYPE_INT32:
2222 case SD_BUS_TYPE_UINT32:
2223 case SD_BUS_TYPE_INT64:
2224 case SD_BUS_TYPE_UINT64:
2225 case SD_BUS_TYPE_DOUBLE:
2226 case SD_BUS_TYPE_STRING:
2227 case SD_BUS_TYPE_OBJECT_PATH:
2c93b4ef
LP
2228 case SD_BUS_TYPE_SIGNATURE:
2229 case SD_BUS_TYPE_UNIX_FD: {
9a17484d
LP
2230 void *p;
2231
2232 p = va_arg(ap, void*);
2233 r = sd_bus_message_read_basic(m, *t, p);
fe1d424d
LP
2234 if (r < 0)
2235 return r;
2236 if (r == 0)
2237 return -ENXIO;
2238
9a17484d
LP
2239 break;
2240 }
2241
2242 case SD_BUS_TYPE_ARRAY: {
2243 size_t k;
2244
2245 r = signature_element_length(t + 1, &k);
2246 if (r < 0)
2247 return r;
2248
2249 {
9a17484d 2250 char s[k + 1];
9a17484d
LP
2251 memcpy(s, t + 1, k);
2252 s[k] = 0;
9a17484d
LP
2253
2254 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
2255 if (r < 0)
2256 return r;
2257 if (r == 0)
2258 return -ENXIO;
fe1d424d 2259 }
9a17484d 2260
fe1d424d
LP
2261 if (n_array == (unsigned) -1) {
2262 types += k;
2263 n_struct -= k;
9a17484d
LP
2264 }
2265
fe1d424d
LP
2266 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2267 if (r < 0)
2268 return r;
2269
2270 types = t + 1;
2271 n_struct = k;
2272 n_array = va_arg(ap, unsigned);
2273
9a17484d
LP
2274 break;
2275 }
2276
2277 case SD_BUS_TYPE_VARIANT: {
2278 const char *s;
2279
2280 s = va_arg(ap, const char *);
2281 if (!s)
2282 return -EINVAL;
2283
2284 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, s);
2285 if (r < 0)
2286 return r;
2287 if (r == 0)
2288 return -ENXIO;
2289
fe1d424d 2290 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
9a17484d
LP
2291 if (r < 0)
2292 return r;
9a17484d 2293
fe1d424d
LP
2294 types = s;
2295 n_struct = strlen(s);
2296 n_array = (unsigned) -1;
2297
9a17484d
LP
2298 break;
2299 }
2300
2301 case SD_BUS_TYPE_STRUCT_BEGIN:
2302 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
2303 size_t k;
2304
2305 r = signature_element_length(t, &k);
2306 if (r < 0)
2307 return r;
2308
2309 {
2310 char s[k - 1];
2311 memcpy(s, t + 1, k - 2);
2312 s[k - 2] = 0;
2313
2314 r = sd_bus_message_enter_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
2315 if (r < 0)
2316 return r;
2317 if (r == 0)
2318 return -ENXIO;
fe1d424d 2319 }
9a17484d 2320
fe1d424d
LP
2321 if (n_array == (unsigned) -1) {
2322 types += k - 1;
2323 n_struct -= k - 1;
2324 }
9a17484d 2325
fe1d424d
LP
2326 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2327 if (r < 0)
2328 return r;
9a17484d 2329
fe1d424d
LP
2330 types = t + 1;
2331 n_struct = k - 2;
2332 n_array = (unsigned) -1;
9a17484d
LP
2333
2334 break;
2335 }
2336
2337 default:
fe1d424d 2338 return -EINVAL;
9a17484d 2339 }
9a17484d
LP
2340 }
2341
2342 return 1;
2343}
2344
2345int sd_bus_message_read(sd_bus_message *m, const char *types, ...) {
2346 va_list ap;
2347 int r;
2348
2349 if (!m)
2350 return -EINVAL;
2351 if (!m->sealed)
2352 return -EPERM;
2353 if (!types)
2354 return -EINVAL;
2355
2356 va_start(ap, types);
2357 r = message_read_ap(m, types, ap);
2358 va_end(ap);
2359
2360 return r;
2361}
2362
80a46c73
LP
2363static int message_peek_fields(
2364 sd_bus_message *m,
2365 size_t *rindex,
2366 size_t align,
2367 size_t nbytes,
2368 void **ret) {
2369
2370 assert(m);
2371 assert(rindex);
2372 assert(align > 0);
2373
2374 return buffer_peek(m->fields, BUS_MESSAGE_FIELDS_SIZE(m), rindex, align, nbytes, ret);
2375}
2376
9f26c90c
LP
2377static int message_peek_field_uint32(
2378 sd_bus_message *m,
2379 size_t *ri,
2380 uint32_t *ret) {
2381
2382 int r;
2383 void *q;
2384
2385 assert(m);
2386 assert(ri);
2387
2388 r = message_peek_fields(m, ri, 4, 4, &q);
2389 if (r < 0)
2390 return r;
2391
2392 if (ret)
2393 *ret = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
2394
2395 return 0;
2396}
2397
80a46c73
LP
2398static int message_peek_field_string(
2399 sd_bus_message *m,
6693860f 2400 bool (*validate)(const char *p),
80a46c73
LP
2401 size_t *ri,
2402 const char **ret) {
2403
9f26c90c 2404 uint32_t l;
80a46c73
LP
2405 int r;
2406 void *q;
2407
9a17484d 2408 assert(m);
80a46c73
LP
2409 assert(ri);
2410
9f26c90c 2411 r = message_peek_field_uint32(m, ri, &l);
80a46c73
LP
2412 if (r < 0)
2413 return r;
2414
80a46c73
LP
2415 r = message_peek_fields(m, ri, 1, l+1, &q);
2416 if (r < 0)
2417 return r;
9a17484d 2418
6693860f
LP
2419 if (validate) {
2420 if (!validate_nul(q, l))
2421 return -EBADMSG;
2422
2423 if (!validate(q))
ac89bf1d
LP
2424 return -EBADMSG;
2425 } else {
2426 if (!validate_string(q, l))
2427 return -EBADMSG;
2428 }
80a46c73
LP
2429
2430 if (ret)
2431 *ret = q;
2432
2433 return 0;
2434}
2435
2436static int message_peek_field_signature(
2437 sd_bus_message *m,
2438 size_t *ri,
2439 const char **ret) {
2440
2441 size_t l;
2442 int r;
2443 void *q;
2444
2445 assert(m);
2446 assert(ri);
2447
2448 r = message_peek_fields(m, ri, 1, 1, &q);
2449 if (r < 0)
2450 return r;
2451
2452 l = *(uint8_t*) q;
2453 r = message_peek_fields(m, ri, 1, l+1, &q);
2454 if (r < 0)
2455 return r;
2456
2457 if (!validate_signature(q, l))
2458 return -EBADMSG;
2459
2460 if (ret)
2461 *ret = q;
2462
2463 return 0;
2464}
2465
80a46c73
LP
2466static int message_skip_fields(
2467 sd_bus_message *m,
2468 size_t *ri,
2469 uint32_t array_size,
2470 const char **signature) {
2471
2472 size_t original_index;
2473 int r;
2474
2475 assert(m);
2476 assert(ri);
2477 assert(signature);
2478
2479 original_index = *ri;
2480
2481 for (;;) {
2482 char t;
80a46c73
LP
2483 size_t l;
2484
2485 if (array_size != (uint32_t) -1 &&
2486 array_size <= *ri - original_index)
2487 return 0;
2488
2489 t = **signature;
2490 if (!t)
2491 return 0;
2492
6693860f
LP
2493 if (t == SD_BUS_TYPE_STRING) {
2494
2495 r = message_peek_field_string(m, NULL, ri, NULL);
2496 if (r < 0)
2497 return r;
2498
2499 (*signature)++;
2500
2501 } else if (t == SD_BUS_TYPE_OBJECT_PATH) {
80a46c73 2502
6693860f 2503 r = message_peek_field_string(m, object_path_is_valid, ri, NULL);
80a46c73
LP
2504 if (r < 0)
2505 return r;
2506
2507 (*signature)++;
2508
2509 } else if (t == SD_BUS_TYPE_SIGNATURE) {
2510
2511 r = message_peek_field_signature(m, ri, NULL);
2512 if (r < 0)
2513 return r;
2514
2515 (*signature)++;
2516
2517 } else if (bus_type_is_basic(t)) {
27f6e5c7 2518 ssize_t align, k;
80a46c73 2519
c66a2e0c
TG
2520 align = bus_type_get_alignment(t);
2521 k = bus_type_get_size(t);
27f6e5c7 2522 assert(align > 0 && k > 0);
80a46c73
LP
2523
2524 r = message_peek_fields(m, ri, align, k, NULL);
2525 if (r < 0)
2526 return r;
9a17484d 2527
80a46c73
LP
2528 (*signature)++;
2529
2530 } else if (t == SD_BUS_TYPE_ARRAY) {
2531
2532 r = signature_element_length(*signature+1, &l);
2533 if (r < 0)
2534 return r;
2535
2536 assert(l >= 1);
2537 {
2538 char sig[l-1], *s;
9f26c90c 2539 uint32_t nas;
80a46c73
LP
2540 int alignment;
2541
2542 strncpy(sig, *signature + 1, l-1);
2543 s = sig;
2544
2545 alignment = bus_type_get_alignment(sig[0]);
2546 if (alignment < 0)
2547 return alignment;
2548
9f26c90c 2549 r = message_peek_field_uint32(m, ri, &nas);
80a46c73
LP
2550 if (r < 0)
2551 return r;
ac89bf1d 2552 if (nas > BUS_ARRAY_MAX_SIZE)
80a46c73
LP
2553 return -EBADMSG;
2554
2555 r = message_peek_fields(m, ri, alignment, 0, NULL);
2556 if (r < 0)
2557 return r;
2558
2559 r = message_skip_fields(m, ri, nas, (const char**) &s);
2560 if (r < 0)
2561 return r;
2562 }
2563
2564 (*signature) += 1 + l;
2565
2566 } else if (t == SD_BUS_TYPE_VARIANT) {
2567 const char *s;
2568
2569 r = message_peek_field_signature(m, ri, &s);
2570 if (r < 0)
2571 return r;
2572
2573 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
2574 if (r < 0)
2575 return r;
2576
2577 (*signature)++;
2578
2579 } else if (t == SD_BUS_TYPE_STRUCT ||
2580 t == SD_BUS_TYPE_DICT_ENTRY) {
2581
2582 r = signature_element_length(*signature, &l);
2583 if (r < 0)
2584 return r;
2585
2586 assert(l >= 2);
2587 {
2588 char sig[l-1], *s;
2589 strncpy(sig, *signature + 1, l-1);
2590 s = sig;
2591
2592 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
2593 if (r < 0)
2594 return r;
2595 }
2596
2597 *signature += l;
2598 } else
2599 return -EINVAL;
2600 }
2601}
2602
2603static int message_parse_fields(sd_bus_message *m) {
2604 size_t ri;
2605 int r;
2c93b4ef 2606 uint32_t unix_fds = 0;
80a46c73
LP
2607
2608 assert(m);
2609
2610 for (ri = 0; ri < BUS_MESSAGE_FIELDS_SIZE(m); ) {
2611 const char *signature;
2612 uint8_t *header;
2613
2614 r = message_peek_fields(m, &ri, 8, 1, (void**) &header);
2615 if (r < 0)
2616 return r;
2617
2618 r = message_peek_field_signature(m, &ri, &signature);
2619 if (r < 0)
2620 return r;
2621
2622 switch (*header) {
2623 case _SD_BUS_MESSAGE_HEADER_INVALID:
2624 return -EBADMSG;
2625
2626 case SD_BUS_MESSAGE_HEADER_PATH:
2c93b4ef
LP
2627
2628 if (m->path)
2629 return -EBADMSG;
2630
80a46c73
LP
2631 if (!streq(signature, "o"))
2632 return -EBADMSG;
2633
6693860f 2634 r = message_peek_field_string(m, object_path_is_valid, &ri, &m->path);
80a46c73
LP
2635 break;
2636
2637 case SD_BUS_MESSAGE_HEADER_INTERFACE:
2c93b4ef
LP
2638
2639 if (m->interface)
2640 return -EBADMSG;
2641
80a46c73
LP
2642 if (!streq(signature, "s"))
2643 return -EBADMSG;
2644
6693860f 2645 r = message_peek_field_string(m, interface_name_is_valid, &ri, &m->interface);
80a46c73
LP
2646 break;
2647
2648 case SD_BUS_MESSAGE_HEADER_MEMBER:
2c93b4ef
LP
2649
2650 if (m->member)
2651 return -EBADMSG;
2652
80a46c73
LP
2653 if (!streq(signature, "s"))
2654 return -EBADMSG;
2655
6693860f 2656 r = message_peek_field_string(m, member_name_is_valid, &ri, &m->member);
80a46c73
LP
2657 break;
2658
2659 case SD_BUS_MESSAGE_HEADER_ERROR_NAME:
2c93b4ef
LP
2660
2661 if (m->error.name)
2662 return -EBADMSG;
2663
80a46c73
LP
2664 if (!streq(signature, "s"))
2665 return -EBADMSG;
2666
6693860f 2667 r = message_peek_field_string(m, error_name_is_valid, &ri, &m->error.name);
80a46c73
LP
2668 break;
2669
2670 case SD_BUS_MESSAGE_HEADER_DESTINATION:
2c93b4ef
LP
2671
2672 if (m->destination)
2673 return -EBADMSG;
2674
80a46c73
LP
2675 if (!streq(signature, "s"))
2676 return -EBADMSG;
2677
6693860f 2678 r = message_peek_field_string(m, service_name_is_valid, &ri, &m->destination);
80a46c73
LP
2679 break;
2680
2681 case SD_BUS_MESSAGE_HEADER_SENDER:
2c93b4ef
LP
2682
2683 if (m->sender)
2684 return -EBADMSG;
2685
80a46c73
LP
2686 if (!streq(signature, "s"))
2687 return -EBADMSG;
2688
6693860f 2689 r = message_peek_field_string(m, service_name_is_valid, &ri, &m->sender);
80a46c73
LP
2690 break;
2691
2692
2693 case SD_BUS_MESSAGE_HEADER_SIGNATURE: {
2694 const char *s;
2695 char *c;
2696
2c93b4ef
LP
2697 if (m->root_container.signature)
2698 return -EBADMSG;
2699
80a46c73
LP
2700 if (!streq(signature, "g"))
2701 return -EBADMSG;
2702
2703 r = message_peek_field_signature(m, &ri, &s);
2704 if (r < 0)
2705 return r;
2706
2707 c = strdup(s);
2708 if (!c)
2709 return -ENOMEM;
2710
2711 free(m->root_container.signature);
2712 m->root_container.signature = c;
80a46c73
LP
2713 break;
2714 }
2715
2716 case SD_BUS_MESSAGE_HEADER_REPLY_SERIAL:
2c93b4ef
LP
2717 if (m->reply_serial != 0)
2718 return -EBADMSG;
2719
80a46c73
LP
2720 if (!streq(signature, "u"))
2721 return -EBADMSG;
2722
2723 r = message_peek_field_uint32(m, &ri, &m->reply_serial);
6693860f
LP
2724 if (r < 0)
2725 return r;
2726
2727 if (m->reply_serial == 0)
2728 return -EBADMSG;
2729
80a46c73
LP
2730 break;
2731
2c93b4ef
LP
2732 case SD_BUS_MESSAGE_HEADER_UNIX_FDS:
2733 if (unix_fds != 0)
2734 return -EBADMSG;
2735
2736 if (!streq(signature, "u"))
2737 return -EBADMSG;
2738
2739 r = message_peek_field_uint32(m, &ri, &unix_fds);
2740 if (r < 0)
2741 return -EBADMSG;
2742
2743 if (unix_fds == 0)
2744 return -EBADMSG;
2745
2746 break;
2747
80a46c73
LP
2748 default:
2749 r = message_skip_fields(m, &ri, (uint32_t) -1, (const char **) &signature);
2750 }
2751
2752 if (r < 0)
2753 return r;
2754 }
2755
2c93b4ef
LP
2756 if (m->n_fds != unix_fds)
2757 return -EBADMSG;
2758
80a46c73
LP
2759 if (isempty(m->root_container.signature) != (BUS_MESSAGE_BODY_SIZE(m) == 0))
2760 return -EBADMSG;
2761
2762 switch (m->header->type) {
2763
2764 case SD_BUS_MESSAGE_TYPE_SIGNAL:
2765 if (!m->path || !m->interface || !m->member)
2766 return -EBADMSG;
2767 break;
2768
2769 case SD_BUS_MESSAGE_TYPE_METHOD_CALL:
2770
2771 if (!m->path || !m->member)
2772 return -EBADMSG;
2773
2774 break;
2775
2776 case SD_BUS_MESSAGE_TYPE_METHOD_RETURN:
2777
2778 if (m->reply_serial == 0)
2779 return -EBADMSG;
2780 break;
2781
2782 case SD_BUS_MESSAGE_TYPE_METHOD_ERROR:
2783
2784 if (m->reply_serial == 0 || !m->error.name)
2785 return -EBADMSG;
2786 break;
2787 }
9a17484d 2788
89ffcd2a
LP
2789 /* Try to read the error message, but if we can't it's a non-issue */
2790 if (m->header->type == SD_BUS_MESSAGE_TYPE_METHOD_ERROR)
2791 sd_bus_message_read(m, "s", &m->error.message);
2792
9a17484d
LP
2793 return 0;
2794}
2795
9a17484d
LP
2796int bus_message_seal(sd_bus_message *m, uint64_t serial) {
2797 int r;
2798
2799 assert(m);
2800
2801 if (m->sealed)
2802 return -EPERM;
2803
2804 if (m->n_containers > 0)
2805 return -EBADMSG;
2806
2807 /* If there's a non-trivial signature set, then add it in here */
2808 if (!isempty(m->root_container.signature)) {
80a46c73 2809 r = message_append_field_signature(m, SD_BUS_MESSAGE_HEADER_SIGNATURE, m->root_container.signature, NULL);
9a17484d
LP
2810 if (r < 0)
2811 return r;
2812 }
2813
2814 if (m->n_fds > 0) {
2815 r = message_append_field_uint32(m, SD_BUS_MESSAGE_HEADER_UNIX_FDS, m->n_fds);
2816 if (r < 0)
2817 return r;
2818 }
2819
2820 m->header->serial = serial;
2821 m->sealed = true;
2822
9a17484d
LP
2823 return 0;
2824}
2825
2826int sd_bus_message_set_destination(sd_bus_message *m, const char *destination) {
2827 if (!m)
2828 return -EINVAL;
2829 if (!destination)
2830 return -EINVAL;
2831 if (m->sealed)
2832 return -EPERM;
2833 if (m->destination)
2834 return -EEXIST;
2835
2836 return message_append_field_string(m, SD_BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &m->destination);
2837}
2838
2839int bus_message_dump(sd_bus_message *m) {
2840 unsigned level = 1;
2841 int r;
2842
2843 assert(m);
2844
2845 printf("Message %p\n"
2846 "\tn_ref=%u\n"
2847 "\tendian=%c\n"
2848 "\ttype=%i\n"
2849 "\tflags=%u\n"
2850 "\tversion=%u\n"
2851 "\tserial=%u\n"
2852 "\tfields_size=%u\n"
2853 "\tbody_size=%u\n"
2854 "\tpath=%s\n"
2855 "\tinterface=%s\n"
2856 "\tmember=%s\n"
2857 "\tdestination=%s\n"
2858 "\tsender=%s\n"
2859 "\tsignature=%s\n"
2860 "\treply_serial=%u\n"
2861 "\terror.name=%s\n"
2862 "\terror.message=%s\n"
2863 "\tsealed=%s\n",
2864 m,
2865 m->n_ref,
2866 m->header->endian,
2867 m->header->type,
2868 m->header->flags,
2869 m->header->version,
2870 BUS_MESSAGE_SERIAL(m),
2871 BUS_MESSAGE_FIELDS_SIZE(m),
2872 BUS_MESSAGE_BODY_SIZE(m),
2873 strna(m->path),
2874 strna(m->interface),
2875 strna(m->member),
2876 strna(m->destination),
2877 strna(m->sender),
80a46c73 2878 strna(m->root_container.signature),
9a17484d
LP
2879 m->reply_serial,
2880 strna(m->error.name),
2881 strna(m->error.message),
2882 yes_no(m->sealed));
2883
2884 r = sd_bus_message_rewind(m, true);
2885 if (r < 0) {
2886 log_error("Failed to rewind: %s", strerror(-r));
2887 return r;
2888 }
2889
80a46c73 2890 printf("BEGIN_MESSAGE \"%s\" {\n", strempty(m->root_container.signature));
9a17484d
LP
2891
2892 for(;;) {
2893 _cleanup_free_ char *prefix = NULL;
2894 const char *contents = NULL;
2895 char type;
2896 union {
2897 uint8_t u8;
2898 uint16_t u16;
2899 int16_t s16;
2900 uint32_t u32;
2901 int32_t s32;
2902 uint64_t u64;
2903 int64_t s64;
2904 double d64;
2905 const char *string;
2906 int i;
2907 } basic;
2908
2909 r = sd_bus_message_peek_type(m, &type, &contents);
2910 if (r < 0) {
2911 log_error("Failed to peek type: %s", strerror(-r));
2912 return r;
2913 }
2914 if (r == 0) {
2915 if (level <= 1)
2916 break;
2917
2918 r = sd_bus_message_exit_container(m);
2919 if (r < 0) {
2920 log_error("Failed to exit container: %s", strerror(-r));
2921 return r;
2922 }
2923
2924 level--;
2925
2926 prefix = strrep("\t", level);
2927 if (!prefix)
2928 return log_oom();
2929
2930 if (type == SD_BUS_TYPE_ARRAY)
2931 printf("%s} END_ARRAY \n", prefix);
2932 else if (type == SD_BUS_TYPE_VARIANT)
2933 printf("%s} END_VARIANT\n", prefix);
2934 else if (type == SD_BUS_TYPE_STRUCT)
2935 printf("%s} END_STRUCT\n", prefix);
2936 else if (type == SD_BUS_TYPE_DICT_ENTRY)
2937 printf("%s} END_DICT_ENTRY\n", prefix);
2938
2939 continue;
2940 }
2941
2942 prefix = strrep("\t", level);
2943 if (!prefix)
2944 return log_oom();
2945
2946 if (bus_type_is_container(type) > 0) {
2947 r = sd_bus_message_enter_container(m, type, contents);
2948 if (r < 0) {
2949 log_error("Failed to enter container: %s", strerror(-r));
2950 return r;
2951 }
2952
2953 if (type == SD_BUS_TYPE_ARRAY)
2954 printf("%sBEGIN_ARRAY \"%s\" {\n", prefix, contents);
2955 else if (type == SD_BUS_TYPE_VARIANT)
2956 printf("%sBEGIN_VARIANT \"%s\" {\n", prefix, contents);
2957 else if (type == SD_BUS_TYPE_STRUCT)
2958 printf("%sBEGIN_STRUCT \"%s\" {\n", prefix, contents);
2959 else if (type == SD_BUS_TYPE_DICT_ENTRY)
2960 printf("%sBEGIN_DICT_ENTRY \"%s\" {\n", prefix, contents);
2961
2962 level ++;
2963
2964 continue;
2965 }
2966
2967 r = sd_bus_message_read_basic(m, type, &basic);
2968 if (r < 0) {
2969 log_error("Failed to get basic: %s", strerror(-r));
2970 return r;
2971 }
2972
2973 switch (type) {
2974
2975 case SD_BUS_TYPE_BYTE:
2976 printf("%sBYTE: %u\n", prefix, basic.u8);
2977 break;
2978
2979 case SD_BUS_TYPE_BOOLEAN:
2980 printf("%sBOOLEAN: %s\n", prefix, yes_no(basic.i));
2981 break;
2982
2983 case SD_BUS_TYPE_INT16:
2984 printf("%sINT16: %i\n", prefix, basic.s16);
2985 break;
2986
2987 case SD_BUS_TYPE_UINT16:
2988 printf("%sUINT16: %u\n", prefix, basic.u16);
2989 break;
2990
2991 case SD_BUS_TYPE_INT32:
2992 printf("%sINT32: %i\n", prefix, basic.s32);
2993 break;
2994
2995 case SD_BUS_TYPE_UINT32:
2996 printf("%sUINT32: %u\n", prefix, basic.u32);
2997 break;
2998
2999 case SD_BUS_TYPE_INT64:
3000 printf("%sINT64: %lli\n", prefix, (long long) basic.s64);
3001 break;
3002
3003 case SD_BUS_TYPE_UINT64:
3004 printf("%sUINT64: %llu\n", prefix, (unsigned long long) basic.u64);
3005 break;
3006
3007 case SD_BUS_TYPE_DOUBLE:
3008 printf("%sDOUBLE: %g\n", prefix, basic.d64);
3009 break;
3010
3011 case SD_BUS_TYPE_STRING:
3012 printf("%sSTRING: \"%s\"\n", prefix, basic.string);
3013 break;
3014
3015 case SD_BUS_TYPE_OBJECT_PATH:
3016 printf("%sOBJECT_PATH: \"%s\"\n", prefix, basic.string);
3017 break;
3018
3019 case SD_BUS_TYPE_SIGNATURE:
3020 printf("%sSIGNATURE: \"%s\"\n", prefix, basic.string);
3021 break;
3022
3023 case SD_BUS_TYPE_UNIX_FD:
3024 printf("%sUNIX_FD: %i\n", prefix, basic.i);
3025 break;
3026
3027 default:
3028 assert_not_reached("Unknown basic type.");
3029 }
3030 }
3031
3032 printf("} END_MESSAGE\n");
3033 return 0;
de1c301e
LP
3034}
3035
3036int bus_message_get_blob(sd_bus_message *m, void **buffer, size_t *sz) {
3037 size_t total;
de1c301e
LP
3038 void *p, *e;
3039
3040 assert(m);
3041 assert(buffer);
3042 assert(sz);
3043
2100fa10 3044 total = bus_message_size(m);
de1c301e
LP
3045
3046 p = malloc(total);
3047 if (!p)
3048 return -ENOMEM;
3049
2100fa10
LP
3050 e = mempcpy(p, m->header, sizeof(*m->header));
3051
3052 if (m->fields) {
3053 e = mempcpy(e, m->fields, m->header->fields_size);
3054
3055 if (m->header->fields_size % 8 != 0)
3056 e = mempset(e, 0, 8 - (m->header->fields_size % 8));
3057 }
3058
3059 if (m->body)
3060 e = mempcpy(e, m->body, m->header->body_size);
3061
3062 assert(total == (size_t) ((uint8_t*) e - (uint8_t*) p));
de1c301e
LP
3063
3064 *buffer = p;
3065 *sz = total;
3066
3067 return 0;
3068}
89ffcd2a
LP
3069
3070int bus_message_read_strv_extend(sd_bus_message *m, char ***l) {
3071 int r;
3072
3073 assert(m);
3074 assert(l);
3075
3076 r = sd_bus_message_enter_container(m, 'a', "s");
3077 if (r < 0)
3078 return r;
3079
3080 for (;;) {
3081 const char *s;
3082
3083 r = sd_bus_message_read_basic(m, 's', &s);
3084 if (r < 0)
3085 return r;
3086 if (r == 0)
3087 break;
3088
3089 r = strv_extend(l, s);
3090 if (r < 0)
3091 return r;
3092 }
3093
3094 r = sd_bus_message_exit_container(m);
3095 if (r < 0)
3096 return r;
3097
3098 return 0;
3099}
392d5b37
LP
3100
3101const char* bus_message_get_arg(sd_bus_message *m, unsigned i) {
3102 int r;
3103 const char *t;
3104 char type;
3105
3106 assert(m);
3107
3108 r = sd_bus_message_rewind(m, true);
3109 if (r < 0)
3110 return NULL;
3111
3112 while (i > 0) {
3113 r = sd_bus_message_peek_type(m, &type, NULL);
3114 if (r < 0)
3115 return NULL;
3116
3117 if (type != SD_BUS_TYPE_STRING &&
3118 type != SD_BUS_TYPE_OBJECT_PATH &&
3119 type != SD_BUS_TYPE_SIGNATURE)
3120 return NULL;
3121
3122 r = sd_bus_message_read_basic(m, type, &t);
3123 if (r < 0)
3124 return NULL;
3125
3126 i--;
3127 }
3128
3129 r = sd_bus_message_rewind(m, true);
3130 if (r < 0)
3131 return NULL;
3132
3133 return t;
3134}
2100fa10
LP
3135
3136size_t bus_message_size(sd_bus_message *m) {
3137 assert(m);
3138 assert(m->sealed);
3139
3140 return
3141 sizeof(*m->header) +
3142 ALIGN8(m->header->fields_size) +
3143 m->header->body_size;
3144}