]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd-bus/bus-message.c
bus: also check for NULL when appending trivial types
[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>
bc7fd8cd 24#include <sys/mman.h>
de1c301e
LP
25
26#include "util.h"
9a17484d 27#include "utf8.h"
89ffcd2a 28#include "strv.h"
6629161f 29#include "time-util.h"
d8d3d8a7 30#include "cgroup-util.h"
de1c301e 31
de1c301e 32#include "sd-bus.h"
9a17484d 33#include "bus-message.h"
de1c301e
LP
34#include "bus-internal.h"
35#include "bus-type.h"
36#include "bus-signature.h"
37
80a46c73 38static int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored);
de1c301e 39
bc7fd8cd
LP
40static void *adjust_pointer(const void *p, void *old_base, size_t sz, void *new_base) {
41
42 if (p == NULL)
43 return NULL;
44
45 if (old_base == new_base)
46 return (void*) p;
47
48 if ((uint8_t*) p < (uint8_t*) old_base)
49 return (void*) p;
50
51 if ((uint8_t*) p >= (uint8_t*) old_base + sz)
52 return (void*) p;
53
54 return (uint8_t*) new_base + ((uint8_t*) p - (uint8_t*) old_base);
55}
56
57static void message_free_part(sd_bus_message *m, struct bus_body_part *part) {
58 assert(m);
59 assert(part);
60
61 if (part->memfd >= 0) {
66b26c5c
LP
62 /* If we can reuse the memfd, try that. For that it
63 * can't be sealed yet. */
bc7fd8cd
LP
64
65 if (!part->sealed)
66 bus_kernel_push_memfd(m->bus, part->memfd, part->data, part->mapped);
67 else {
89b4fc46
LP
68 if (part->mapped > 0)
69 assert_se(munmap(part->data, part->mapped) == 0);
bc7fd8cd
LP
70
71 close_nointr_nofail(part->memfd);
72 }
73
453a0c29
LP
74 } else if (part->munmap_this)
75 munmap(part->data, part->mapped);
76 else if (part->free_this)
bc7fd8cd
LP
77 free(part->data);
78
79 if (part != &m->body)
80 free(part);
81}
82
83static void message_reset_parts(sd_bus_message *m) {
84 struct bus_body_part *part;
85
86 assert(m);
87
88 part = &m->body;
89 while (m->n_body_parts > 0) {
90 struct bus_body_part *next = part->next;
91 message_free_part(m, part);
92 part = next;
93 m->n_body_parts--;
94 }
95
96 m->body_end = NULL;
97
98 m->cached_rindex_part = NULL;
99 m->cached_rindex_part_begin = 0;
100}
101
102static void message_reset_containers(sd_bus_message *m) {
9a17484d
LP
103 unsigned i;
104
105 assert(m);
106
107 for (i = 0; i < m->n_containers; i++)
108 free(m->containers[i].signature);
109
110 free(m->containers);
111 m->containers = NULL;
112
113 m->n_containers = 0;
114 m->root_container.index = 0;
115}
116
de1c301e 117static void message_free(sd_bus_message *m) {
de1c301e
LP
118 assert(m);
119
120 if (m->free_header)
121 free(m->header);
122
bc7fd8cd 123 message_reset_parts(m);
de1c301e 124
6629161f
LP
125 if (m->free_kdbus)
126 free(m->kdbus);
127
62b3e928
KS
128 if (m->release_kdbus) {
129 uint64_t off;
130
131 off = (uint8_t *)m->kdbus - (uint8_t *)m->bus->kdbus_buffer;
132 ioctl(m->bus->input_fd, KDBUS_CMD_MSG_RELEASE, &off);
133 }
fd8d62d9 134
f54514f3
LP
135 if (m->bus)
136 sd_bus_unref(m->bus);
137
2c93b4ef
LP
138 if (m->free_fds) {
139 close_many(m->fds, m->n_fds);
140 free(m->fds);
141 }
de1c301e 142
bc7fd8cd
LP
143 if (m->iovec != m->iovec_fixed)
144 free(m->iovec);
145
77930f11
LP
146 free(m->cmdline_array);
147
bc7fd8cd 148 message_reset_containers(m);
9a17484d 149 free(m->root_container.signature);
de1c301e 150
9a17484d 151 free(m->peeked_signature);
d8d3d8a7
LP
152
153 free(m->unit);
154 free(m->user_unit);
155 free(m->session);
de1c301e
LP
156 free(m);
157}
158
c91cb83c
LP
159static void *message_extend_fields(sd_bus_message *m, size_t align, size_t sz) {
160 void *op, *np;
161 size_t old_size, new_size, start;
de1c301e 162
c91cb83c 163 assert(m);
de1c301e 164
c91cb83c 165 if (m->poisoned)
de1c301e
LP
166 return NULL;
167
c91cb83c
LP
168 old_size = sizeof(struct bus_header) + m->header->fields_size;
169 start = ALIGN_TO(old_size, align);
170 new_size = start + sz;
de1c301e 171
c91cb83c
LP
172 if (old_size == new_size)
173 return (uint8_t*) m->header + old_size;
de1c301e 174
c91cb83c
LP
175 if (new_size > (size_t) ((uint32_t) -1))
176 goto poison;
de1c301e 177
c91cb83c
LP
178 if (m->free_header) {
179 np = realloc(m->header, ALIGN8(new_size));
180 if (!np)
181 goto poison;
182 } else {
183 /* Initially, the header is allocated as part of of
184 * the sd_bus_message itself, let's replace it by
185 * dynamic data */
de1c301e 186
c91cb83c
LP
187 np = malloc(ALIGN8(new_size));
188 if (!np)
189 goto poison;
de1c301e 190
c91cb83c
LP
191 memcpy(np, m->header, sizeof(struct bus_header));
192 }
de1c301e 193
c91cb83c
LP
194 /* Zero out padding */
195 if (start > old_size)
196 memset((uint8_t*) np + old_size, 0, start - old_size);
bc7fd8cd 197
c91cb83c
LP
198 op = m->header;
199 m->header = np;
200 m->header->fields_size = new_size - sizeof(struct bus_header);
de1c301e 201
bc7fd8cd 202 /* Adjust quick access pointers */
c91cb83c
LP
203 m->path = adjust_pointer(m->path, op, old_size, m->header);
204 m->interface = adjust_pointer(m->interface, op, old_size, m->header);
205 m->member = adjust_pointer(m->member, op, old_size, m->header);
206 m->destination = adjust_pointer(m->destination, op, old_size, m->header);
207 m->sender = adjust_pointer(m->sender, op, old_size, m->header);
208 m->error.name = adjust_pointer(m->error.name, op, old_size, m->header);
bc7fd8cd 209
c91cb83c 210 m->free_header = true;
de1c301e 211
c91cb83c
LP
212 return (uint8_t*) np + start;
213
214poison:
215 m->poisoned = true;
216 return NULL;
de1c301e
LP
217}
218
219static int message_append_field_string(
220 sd_bus_message *m,
221 uint8_t h,
222 char type,
223 const char *s,
224 const char **ret) {
225
226 size_t l;
227 uint8_t *p;
228
229 assert(m);
230
231 l = strlen(s);
232 if (l > (size_t) (uint32_t) -1)
233 return -EINVAL;
234
235 /* field id byte + signature length + signature 's' + NUL + string length + string + NUL */
236 p = message_extend_fields(m, 8, 4 + 4 + l + 1);
237 if (!p)
238 return -ENOMEM;
239
240 p[0] = h;
241 p[1] = 1;
242 p[2] = type;
243 p[3] = 0;
244
245 ((uint32_t*) p)[1] = l;
246 memcpy(p + 8, s, l + 1);
247
248 if (ret)
bc7fd8cd 249 *ret = (char*) p + 8;
de1c301e
LP
250
251 return 0;
252}
253
254static int message_append_field_signature(
255 sd_bus_message *m,
256 uint8_t h,
257 const char *s,
258 const char **ret) {
259
260 size_t l;
261 uint8_t *p;
262
263 assert(m);
264
265 l = strlen(s);
266 if (l > 255)
267 return -EINVAL;
268
269 /* field id byte + signature length + signature 'g' + NUL + string length + string + NUL */
270 p = message_extend_fields(m, 8, 4 + 1 + l + 1);
271 if (!p)
272 return -ENOMEM;
273
274 p[0] = h;
275 p[1] = 1;
276 p[2] = SD_BUS_TYPE_SIGNATURE;
277 p[3] = 0;
278 p[4] = l;
279 memcpy(p + 5, s, l + 1);
280
281 if (ret)
282 *ret = (const char*) p + 5;
283
284 return 0;
285}
286
287static int message_append_field_uint32(sd_bus_message *m, uint8_t h, uint32_t x) {
288 uint8_t *p;
289
290 assert(m);
291
292 /* field id byte + signature length + signature 'u' + NUL + value */
293 p = message_extend_fields(m, 8, 4 + 4);
294 if (!p)
295 return -ENOMEM;
296
297 p[0] = h;
298 p[1] = 1;
299 p[2] = SD_BUS_TYPE_UINT32;
300 p[3] = 0;
301
302 ((uint32_t*) p)[1] = x;
303
304 return 0;
305}
306
6629161f 307int bus_message_from_header(
2571ead1
LP
308 void *buffer,
309 size_t length,
2c93b4ef
LP
310 int *fds,
311 unsigned n_fds,
312 const struct ucred *ucred,
2571ead1 313 const char *label,
6629161f 314 size_t extra,
2571ead1
LP
315 sd_bus_message **ret) {
316
80a46c73
LP
317 sd_bus_message *m;
318 struct bus_header *h;
6629161f 319 size_t a, label_sz;
80a46c73
LP
320
321 assert(buffer || length <= 0);
2c93b4ef 322 assert(fds || n_fds <= 0);
80a46c73
LP
323 assert(ret);
324
325 if (length < sizeof(struct bus_header))
326 return -EBADMSG;
327
328 h = buffer;
329 if (h->version != 1)
330 return -EBADMSG;
331
332 if (h->serial == 0)
333 return -EBADMSG;
334
335 if (h->type == _SD_BUS_MESSAGE_TYPE_INVALID)
336 return -EBADMSG;
337
6629161f
LP
338 if (h->endian != SD_BUS_LITTLE_ENDIAN &&
339 h->endian != SD_BUS_BIG_ENDIAN)
80a46c73
LP
340 return -EBADMSG;
341
6629161f 342 a = ALIGN(sizeof(sd_bus_message)) + ALIGN(extra);
80a46c73 343
2571ead1
LP
344 if (label) {
345 label_sz = strlen(label);
6629161f
LP
346 a += label_sz + 1;
347 }
2571ead1
LP
348
349 m = malloc0(a);
80a46c73
LP
350 if (!m)
351 return -ENOMEM;
352
353 m->n_ref = 1;
2c93b4ef 354 m->sealed = true;
80a46c73 355 m->header = h;
2c93b4ef
LP
356 m->fds = fds;
357 m->n_fds = n_fds;
80a46c73 358
2571ead1
LP
359 if (ucred) {
360 m->uid = ucred->uid;
361 m->pid = ucred->pid;
362 m->gid = ucred->gid;
363 m->uid_valid = m->gid_valid = true;
364 }
365
366 if (label) {
6629161f 367 m->label = (char*) m + ALIGN(sizeof(sd_bus_message)) + ALIGN(extra);
2571ead1
LP
368 memcpy(m->label, label, label_sz + 1);
369 }
370
6629161f
LP
371 *ret = m;
372 return 0;
373}
374
375int bus_message_from_malloc(
376 void *buffer,
377 size_t length,
378 int *fds,
379 unsigned n_fds,
380 const struct ucred *ucred,
381 const char *label,
382 sd_bus_message **ret) {
383
384 sd_bus_message *m;
385 int r;
386
387 r = bus_message_from_header(buffer, length, fds, n_fds, ucred, label, 0, &m);
388 if (r < 0)
389 return r;
390
391 if (length != BUS_MESSAGE_SIZE(m)) {
392 r = -EBADMSG;
393 goto fail;
394 }
395
bc7fd8cd
LP
396 m->n_body_parts = 1;
397 m->body.data = (uint8_t*) buffer + sizeof(struct bus_header) + ALIGN8(BUS_MESSAGE_FIELDS_SIZE(m));
398 m->body.size = length - sizeof(struct bus_header) - ALIGN8(BUS_MESSAGE_FIELDS_SIZE(m));
399 m->body.sealed = true;
400 m->body.memfd = -1;
6629161f 401
80a46c73 402 m->n_iovec = 1;
bc7fd8cd 403 m->iovec = m->iovec_fixed;
80a46c73
LP
404 m->iovec[0].iov_base = buffer;
405 m->iovec[0].iov_len = length;
406
6629161f 407 r = bus_message_parse_fields(m);
2c93b4ef
LP
408 if (r < 0)
409 goto fail;
410
411 /* We take possession of the memory and fds now */
412 m->free_header = true;
413 m->free_fds = true;
80a46c73
LP
414
415 *ret = m;
416 return 0;
2c93b4ef
LP
417
418fail:
419 message_free(m);
420 return r;
80a46c73
LP
421}
422
de1c301e
LP
423static sd_bus_message *message_new(sd_bus *bus, uint8_t type) {
424 sd_bus_message *m;
425
80a46c73 426 m = malloc0(ALIGN(sizeof(sd_bus_message)) + sizeof(struct bus_header));
de1c301e
LP
427 if (!m)
428 return NULL;
429
430 m->n_ref = 1;
431 m->header = (struct bus_header*) ((uint8_t*) m + ALIGN(sizeof(struct sd_bus_message)));
80a46c73 432 m->header->endian = SD_BUS_NATIVE_ENDIAN;
de1c301e
LP
433 m->header->type = type;
434 m->header->version = bus ? bus->message_version : 1;
021a1e78 435 m->allow_fds = !bus || bus->can_fds || (bus->state != BUS_HELLO && bus->state != BUS_RUNNING);
de1c301e 436
9b05bc48
LP
437 if (bus)
438 m->bus = sd_bus_ref(bus);
439
de1c301e
LP
440 return m;
441}
442
d9f644e2 443_public_ int sd_bus_message_new_signal(
de1c301e
LP
444 sd_bus *bus,
445 const char *path,
446 const char *interface,
447 const char *member,
448 sd_bus_message **m) {
449
450 sd_bus_message *t;
451 int r;
452
9d6c7c82
LP
453 assert_return(!bus || bus->state != BUS_UNSET, -ENOTCONN);
454 assert_return(object_path_is_valid(path), -EINVAL);
455 assert_return(interface_name_is_valid(interface), -EINVAL);
456 assert_return(member_name_is_valid(member), -EINVAL);
457 assert_return(m, -EINVAL);
de1c301e 458
40ca29a1 459 t = message_new(bus, SD_BUS_MESSAGE_SIGNAL);
de1c301e
LP
460 if (!t)
461 return -ENOMEM;
462
89ffcd2a
LP
463 t->header->flags |= SD_BUS_MESSAGE_NO_REPLY_EXPECTED;
464
de1c301e
LP
465 r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
466 if (r < 0)
467 goto fail;
468 r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
469 if (r < 0)
470 goto fail;
471 r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
472 if (r < 0)
473 goto fail;
474
475 *m = t;
476 return 0;
477
478fail:
479 sd_bus_message_unref(t);
480 return r;
481}
482
d9f644e2 483_public_ int sd_bus_message_new_method_call(
de1c301e
LP
484 sd_bus *bus,
485 const char *destination,
486 const char *path,
487 const char *interface,
488 const char *member,
489 sd_bus_message **m) {
490
491 sd_bus_message *t;
492 int r;
493
9d6c7c82
LP
494 assert_return(!bus || bus->state != BUS_UNSET, -ENOTCONN);
495 assert_return(!destination || service_name_is_valid(destination), -EINVAL);
496 assert_return(object_path_is_valid(path), -EINVAL);
497 assert_return(!interface || interface_name_is_valid(interface), -EINVAL);
498 assert_return(member_name_is_valid(member), -EINVAL);
499 assert_return(m, -EINVAL);
de1c301e 500
40ca29a1 501 t = message_new(bus, SD_BUS_MESSAGE_METHOD_CALL);
de1c301e
LP
502 if (!t)
503 return -ENOMEM;
504
505 r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
506 if (r < 0)
507 goto fail;
508 r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
509 if (r < 0)
510 goto fail;
511
512 if (interface) {
513 r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
514 if (r < 0)
515 goto fail;
516 }
517
518 if (destination) {
519 r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &t->destination);
520 if (r < 0)
521 goto fail;
522 }
523
524 *m = t;
525 return 0;
526
527fail:
528 message_free(t);
529 return r;
530}
531
5407f2de 532static int message_new_reply(
de1c301e
LP
533 sd_bus *bus,
534 sd_bus_message *call,
5407f2de 535 uint8_t type,
de1c301e
LP
536 sd_bus_message **m) {
537
538 sd_bus_message *t;
539 int r;
540
9d6c7c82
LP
541 assert_return(!bus || bus->state != BUS_UNSET, -ENOTCONN);
542 assert_return(call, -EINVAL);
543 assert_return(call->sealed, -EPERM);
544 assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL);
545 assert_return(m, -EINVAL);
de1c301e 546
5407f2de 547 t = message_new(bus, type);
de1c301e
LP
548 if (!t)
549 return -ENOMEM;
550
89ffcd2a 551 t->header->flags |= SD_BUS_MESSAGE_NO_REPLY_EXPECTED;
de1c301e 552 t->reply_serial = BUS_MESSAGE_SERIAL(call);
5407f2de 553
de1c301e
LP
554 r = message_append_field_uint32(t, SD_BUS_MESSAGE_HEADER_REPLY_SERIAL, t->reply_serial);
555 if (r < 0)
556 goto fail;
557
558 if (call->sender) {
8f155917 559 r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, call->sender, &t->destination);
de1c301e
LP
560 if (r < 0)
561 goto fail;
562 }
563
5407f2de
LP
564 t->dont_send = !!(call->header->flags & SD_BUS_MESSAGE_NO_REPLY_EXPECTED);
565
de1c301e 566 *m = t;
89ffcd2a 567 return 0;
de1c301e
LP
568
569fail:
570 message_free(t);
571 return r;
572}
573
d9f644e2 574_public_ int sd_bus_message_new_method_return(
5407f2de
LP
575 sd_bus *bus,
576 sd_bus_message *call,
577 sd_bus_message **m) {
578
40ca29a1 579 return message_new_reply(bus, call, SD_BUS_MESSAGE_METHOD_RETURN, m);
5407f2de
LP
580}
581
d9f644e2 582_public_ int sd_bus_message_new_method_error(
de1c301e
LP
583 sd_bus *bus,
584 sd_bus_message *call,
585 const sd_bus_error *e,
586 sd_bus_message **m) {
587
588 sd_bus_message *t;
589 int r;
590
9d6c7c82
LP
591 assert_return(sd_bus_error_is_set(e), -EINVAL);
592 assert_return(m, -EINVAL);
de1c301e 593
40ca29a1 594 r = message_new_reply(bus, call, SD_BUS_MESSAGE_METHOD_ERROR, &t);
de1c301e 595 if (r < 0)
5407f2de 596 return r;
de1c301e
LP
597
598 r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
599 if (r < 0)
600 goto fail;
601
602 if (e->message) {
603 r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
604 if (r < 0)
605 goto fail;
606 }
607
608 *m = t;
609 return 0;
610
611fail:
612 message_free(t);
613 return r;
614}
615
d9f644e2 616_public_ int sd_bus_message_new_method_errorf(
29ddb38f
LP
617 sd_bus *bus,
618 sd_bus_message *call,
619 sd_bus_message **m,
620 const char *name,
621 const char *format,
622 ...) {
623
40ca29a1 624 _cleanup_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
29ddb38f
LP
625 va_list ap;
626 int r;
627
40ca29a1
LP
628 assert_return(name, -EINVAL);
629 assert_return(m, -EINVAL);
630
631 va_start(ap, format);
632 r = bus_error_setfv(&error, name, format, ap);
633 va_end(ap);
29ddb38f 634
29ddb38f
LP
635 if (r < 0)
636 return r;
637
40ca29a1
LP
638 return sd_bus_message_new_method_error(bus, call, &error, m);
639}
29ddb38f 640
d9f644e2 641_public_ int sd_bus_message_new_method_errno(
40ca29a1
LP
642 sd_bus *bus,
643 sd_bus_message *call,
644 int error,
645 const sd_bus_error *p,
646 sd_bus_message **m) {
29ddb38f 647
40ca29a1 648 _cleanup_free_ sd_bus_error berror = SD_BUS_ERROR_NULL;
29ddb38f 649
40ca29a1
LP
650 if (sd_bus_error_is_set(p))
651 return sd_bus_message_new_method_error(bus, call, p, m);
29ddb38f 652
40ca29a1 653 sd_bus_error_set_errno(&berror, error);
29ddb38f 654
40ca29a1
LP
655 return sd_bus_message_new_method_error(bus, call, &berror, m);
656}
29ddb38f 657
d9f644e2 658_public_ int sd_bus_message_new_method_errnof(
40ca29a1
LP
659 sd_bus *bus,
660 sd_bus_message *call,
661 sd_bus_message **m,
662 int error,
663 const char *format,
664 ...) {
665
666 _cleanup_free_ sd_bus_error berror = SD_BUS_ERROR_NULL;
667 va_list ap;
668 int r;
669
670 va_start(ap, format);
671 r = bus_error_set_errnofv(&berror, error, format, ap);
672 va_end(ap);
673
674 if (r < 0)
675 return r;
676
677 return sd_bus_message_new_method_error(bus, call, &berror, m);
29ddb38f
LP
678}
679
eb01ba5d
LP
680int bus_message_new_synthetic_error(
681 sd_bus *bus,
682 uint64_t serial,
683 const sd_bus_error *e,
684 sd_bus_message **m) {
685
686 sd_bus_message *t;
687 int r;
688
689 assert(sd_bus_error_is_set(e));
690 assert(m);
691
40ca29a1 692 t = message_new(bus, SD_BUS_MESSAGE_METHOD_ERROR);
eb01ba5d
LP
693 if (!t)
694 return -ENOMEM;
695
696 t->header->flags |= SD_BUS_MESSAGE_NO_REPLY_EXPECTED;
697 t->reply_serial = serial;
698
699 r = message_append_field_uint32(t, SD_BUS_MESSAGE_HEADER_REPLY_SERIAL, t->reply_serial);
700 if (r < 0)
701 goto fail;
702
703 if (bus && bus->unique_name) {
704 r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, bus->unique_name, &t->destination);
705 if (r < 0)
706 goto fail;
707 }
708
3a7d4f1b
LP
709 r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
710 if (r < 0)
711 goto fail;
712
713 if (e->message) {
714 r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
715 if (r < 0)
716 goto fail;
717 }
718
eb01ba5d
LP
719 *m = t;
720 return 0;
721
722fail:
723 message_free(t);
724 return r;
725}
726
d9f644e2 727_public_ sd_bus_message* sd_bus_message_ref(sd_bus_message *m) {
9d6c7c82 728 assert_return(m, NULL);
de1c301e
LP
729
730 assert(m->n_ref > 0);
731 m->n_ref++;
732
733 return m;
734}
735
d9f644e2 736_public_ sd_bus_message* sd_bus_message_unref(sd_bus_message *m) {
9d6c7c82 737 assert_return(m, NULL);
de1c301e
LP
738
739 assert(m->n_ref > 0);
740 m->n_ref--;
741
742 if (m->n_ref <= 0)
743 message_free(m);
744
745 return NULL;
746}
747
d9f644e2 748_public_ int sd_bus_message_get_type(sd_bus_message *m, uint8_t *type) {
9d6c7c82
LP
749 assert_return(m, -EINVAL);
750 assert_return(type, -EINVAL);
de1c301e
LP
751
752 *type = m->header->type;
753 return 0;
754}
755
d9f644e2 756_public_ int sd_bus_message_get_serial(sd_bus_message *m, uint64_t *serial) {
9d6c7c82
LP
757 assert_return(m, -EINVAL);
758 assert_return(serial, -EINVAL);
759 assert_return(m->header->serial != 0, -ENOENT);
de1c301e
LP
760
761 *serial = BUS_MESSAGE_SERIAL(m);
762 return 0;
763}
764
d9f644e2 765_public_ int sd_bus_message_get_reply_serial(sd_bus_message *m, uint64_t *serial) {
9d6c7c82
LP
766 assert_return(m, -EINVAL);
767 assert_return(serial, -EINVAL);
768 assert_return(m->reply_serial != 0, -ENOENT);
de1c301e
LP
769
770 *serial = m->reply_serial;
771 return 0;
772}
773
d9f644e2 774_public_ int sd_bus_message_get_no_reply(sd_bus_message *m) {
9d6c7c82 775 assert_return(m, -EINVAL);
de1c301e 776
40ca29a1 777 return m->header->type == SD_BUS_MESSAGE_METHOD_CALL ? !!(m->header->flags & SD_BUS_MESSAGE_NO_REPLY_EXPECTED) : 0;
de1c301e
LP
778}
779
d9f644e2 780_public_ const char *sd_bus_message_get_path(sd_bus_message *m) {
9d6c7c82 781 assert_return(m, NULL);
de1c301e
LP
782
783 return m->path;
784}
785
d9f644e2 786_public_ const char *sd_bus_message_get_interface(sd_bus_message *m) {
9d6c7c82 787 assert_return(m, NULL);
de1c301e
LP
788
789 return m->interface;
790}
791
d9f644e2 792_public_ const char *sd_bus_message_get_member(sd_bus_message *m) {
9d6c7c82 793 assert_return(m, NULL);
de1c301e
LP
794
795 return m->member;
796}
d9f644e2
ZJS
797
798_public_ const char *sd_bus_message_get_destination(sd_bus_message *m) {
9d6c7c82 799 assert_return(m, NULL);
de1c301e
LP
800
801 return m->destination;
802}
803
d9f644e2 804_public_ const char *sd_bus_message_get_sender(sd_bus_message *m) {
9d6c7c82 805 assert_return(m, NULL);
de1c301e
LP
806
807 return m->sender;
808}
809
d9f644e2 810_public_ const sd_bus_error *sd_bus_message_get_error(sd_bus_message *m) {
9d6c7c82
LP
811 assert_return(m, NULL);
812 assert_return(sd_bus_error_is_set(&m->error), NULL);
de1c301e
LP
813
814 return &m->error;
815}
816
d9f644e2 817_public_ int sd_bus_message_get_uid(sd_bus_message *m, uid_t *uid) {
9d6c7c82
LP
818 assert_return(m, -EINVAL);
819 assert_return(uid, -EINVAL);
820 assert_return(m->uid_valid, -ESRCH);
de1c301e
LP
821
822 *uid = m->uid;
823 return 0;
824}
825
d9f644e2 826_public_ int sd_bus_message_get_gid(sd_bus_message *m, gid_t *gid) {
9d6c7c82
LP
827 assert_return(m, -EINVAL);
828 assert_return(gid, -EINVAL);
829 assert_return(m->gid_valid, -ESRCH);
de1c301e
LP
830
831 *gid = m->gid;
832 return 0;
833}
834
d9f644e2 835_public_ int sd_bus_message_get_pid(sd_bus_message *m, pid_t *pid) {
9d6c7c82
LP
836 assert_return(m, -EINVAL);
837 assert_return(pid, -EINVAL);
838 assert_return(m->pid > 0, -ESRCH);
de1c301e
LP
839
840 *pid = m->pid;
841 return 0;
842}
843
d9f644e2 844_public_ int sd_bus_message_get_tid(sd_bus_message *m, pid_t *tid) {
9d6c7c82
LP
845 assert_return(m, -EINVAL);
846 assert_return(tid, -EINVAL);
847 assert_return(m->tid > 0, -ESRCH);
de1c301e
LP
848
849 *tid = m->tid;
850 return 0;
851}
852
d9f644e2 853_public_ int sd_bus_message_get_pid_starttime(sd_bus_message *m, uint64_t *usec) {
9d6c7c82
LP
854 assert_return(m, -EINVAL);
855 assert_return(usec, -EINVAL);
856 assert_return(m->pid_starttime > 0, -ESRCH);
8323bc1f
LP
857
858 *usec = m->pid_starttime;
859 return 0;
860}
861
d9f644e2 862_public_ int sd_bus_message_get_selinux_context(sd_bus_message *m, const char **ret) {
9d6c7c82
LP
863 assert_return(m, -EINVAL);
864 assert_return(m->label, -ESRCH);
2571ead1 865
4a875b61
LP
866 *ret = m->label;
867 return 0;
2571ead1
LP
868}
869
d9f644e2 870_public_ int sd_bus_message_get_monotonic_timestamp(sd_bus_message *m, uint64_t *usec) {
9d6c7c82
LP
871 assert_return(m, -EINVAL);
872 assert_return(usec, -EINVAL);
873 assert_return(m->monotonic > 0, -ESRCH);
acb5a3cb 874
69aec65c 875 *usec = m->monotonic;
acb5a3cb
LP
876 return 0;
877}
878
d9f644e2 879_public_ int sd_bus_message_get_realtime_timestamp(sd_bus_message *m, uint64_t *usec) {
9d6c7c82
LP
880 assert_return(m, -EINVAL);
881 assert_return(usec, -EINVAL);
882 assert_return(m->realtime > 0, -ESRCH);
69aec65c
LP
883
884 *usec = m->realtime;
885 return 0;
886}
887
d9f644e2 888_public_ int sd_bus_message_get_comm(sd_bus_message *m, const char **ret) {
9d6c7c82
LP
889 assert_return(m, -EINVAL);
890 assert_return(ret, -EINVAL);
891 assert_return(m->comm, -ESRCH);
69aec65c 892
4a875b61
LP
893 *ret = m->comm;
894 return 0;
69aec65c
LP
895}
896
d9f644e2 897_public_ int sd_bus_message_get_tid_comm(sd_bus_message *m, const char **ret) {
9d6c7c82
LP
898 assert_return(m, -EINVAL);
899 assert_return(ret, -EINVAL);
900 assert_return(m->tid_comm, -ESRCH);
69aec65c 901
4a875b61
LP
902 *ret = m->tid_comm;
903 return 0;
69aec65c
LP
904}
905
d9f644e2 906_public_ int sd_bus_message_get_exe(sd_bus_message *m, const char **ret) {
9d6c7c82
LP
907 assert_return(m, -EINVAL);
908 assert_return(ret, -EINVAL);
909 assert_return(m->exe, -ESRCH);
69aec65c 910
4a875b61
LP
911 *ret = m->exe;
912 return 0;
913}
914
d9f644e2 915_public_ int sd_bus_message_get_cgroup(sd_bus_message *m, const char **ret) {
9d6c7c82
LP
916 assert_return(m, -EINVAL);
917 assert_return(ret, -EINVAL);
918 assert_return(m->cgroup, -ESRCH);
4a875b61
LP
919
920 *ret = m->cgroup;
921 return 0;
69aec65c
LP
922}
923
d9f644e2 924_public_ int sd_bus_message_get_unit(sd_bus_message *m, const char **ret) {
d8d3d8a7
LP
925 int r;
926
9d6c7c82
LP
927 assert_return(m, -EINVAL);
928 assert_return(ret, -EINVAL);
929 assert_return(m->cgroup, -ESRCH);
d8d3d8a7
LP
930
931 if (!m->unit) {
932 r = cg_path_get_unit(m->cgroup, &m->unit);
933 if (r < 0)
934 return r;
935 }
936
937 *ret = m->unit;
938 return 0;
939}
940
d9f644e2 941_public_ int sd_bus_message_get_user_unit(sd_bus_message *m, const char **ret) {
d8d3d8a7
LP
942 int r;
943
9d6c7c82
LP
944 assert_return(m, -EINVAL);
945 assert_return(ret, -EINVAL);
946 assert_return(m->cgroup, -ESRCH);
d8d3d8a7
LP
947
948 if (!m->user_unit) {
949 r = cg_path_get_user_unit(m->cgroup, &m->user_unit);
950 if (r < 0)
951 return r;
952 }
953
954 *ret = m->user_unit;
955 return 0;
956}
957
d9f644e2 958_public_ int sd_bus_message_get_session(sd_bus_message *m, const char **ret) {
d8d3d8a7
LP
959 int r;
960
9d6c7c82
LP
961 assert_return(m, -EINVAL);
962 assert_return(ret, -EINVAL);
963 assert_return(m->cgroup, -ESRCH);
d8d3d8a7
LP
964
965 if (!m->session) {
966 r = cg_path_get_session(m->cgroup, &m->session);
967 if (r < 0)
968 return r;
969 }
970
971 *ret = m->session;
972 return 0;
973}
974
d9f644e2 975_public_ int sd_bus_message_get_owner_uid(sd_bus_message *m, uid_t *uid) {
9d6c7c82
LP
976 assert_return(m, -EINVAL);
977 assert_return(uid, -EINVAL);
978 assert_return(m->cgroup, -ESRCH);
bc7f3beb
LP
979
980 return cg_path_get_owner_uid(m->cgroup, uid);
981}
982
d9f644e2 983_public_ int sd_bus_message_get_cmdline(sd_bus_message *m, char ***cmdline) {
77930f11
LP
984 size_t n, i;
985 const char *p;
986 bool first;
987
9d6c7c82
LP
988 assert_return(m, -EINVAL);
989 assert_return(m->cmdline, -ESRCH);
77930f11
LP
990
991 for (p = m->cmdline, n = 0; p < m->cmdline + m->cmdline_length; p++)
992 if (*p == 0)
993 n++;
994
995 m->cmdline_array = new(char*, n + 1);
996 if (!m->cmdline_array)
997 return -ENOMEM;
998
999 for (p = m->cmdline, i = 0, first = true; p < m->cmdline + m->cmdline_length; p++) {
1000 if (first)
1001 m->cmdline_array[i++] = (char*) p;
1002
1003 first = *p == 0;
1004 }
1005
1006 m->cmdline_array[i] = NULL;
1007 *cmdline = m->cmdline_array;
1008
1009 return 0;
1010}
1011
d9f644e2 1012_public_ int sd_bus_message_get_audit_sessionid(sd_bus_message *m, uint32_t *sessionid) {
9d6c7c82
LP
1013 assert_return(m, -EINVAL);
1014 assert_return(sessionid, -EINVAL);
1015 assert_return(m->audit, -ESRCH);
120f919e
LP
1016
1017 *sessionid = m->audit->sessionid;
1018 return 0;
1019}
1020
d9f644e2 1021_public_ int sd_bus_message_get_audit_loginuid(sd_bus_message *m, uid_t *uid) {
9d6c7c82
LP
1022 assert_return(m, -EINVAL);
1023 assert_return(uid, -EINVAL);
1024 assert_return(m->audit, -ESRCH);
120f919e
LP
1025
1026 *uid = m->audit->loginuid;
1027 return 0;
1028}
1029
d9f644e2 1030_public_ int sd_bus_message_has_effective_cap(sd_bus_message *m, int capability) {
102ea8e4
LP
1031 unsigned sz;
1032
9d6c7c82
LP
1033 assert_return(m, -EINVAL);
1034 assert_return(capability < 0, -EINVAL);
1035 assert_return(!m->capability, -ESRCH);
102ea8e4
LP
1036
1037 sz = m->capability_size / 4;
1038 if ((unsigned) capability >= sz*8)
1039 return 0;
1040
1041 return !!(m->capability[2 * sz + (capability / 8)] & (1 << (capability % 8)));
1042}
1043
d9f644e2
ZJS
1044_public_ int sd_bus_message_is_signal(sd_bus_message *m,
1045 const char *interface,
1046 const char *member) {
9d6c7c82 1047 assert_return(m, -EINVAL);
de1c301e 1048
40ca29a1 1049 if (m->header->type != SD_BUS_MESSAGE_SIGNAL)
de1c301e
LP
1050 return 0;
1051
1052 if (interface && (!m->interface || !streq(m->interface, interface)))
1053 return 0;
1054
1055 if (member && (!m->member || !streq(m->member, member)))
1056 return 0;
1057
1058 return 1;
1059}
1060
d9f644e2
ZJS
1061_public_ int sd_bus_message_is_method_call(sd_bus_message *m,
1062 const char *interface,
1063 const char *member) {
9d6c7c82 1064 assert_return(m, -EINVAL);
de1c301e 1065
40ca29a1 1066 if (m->header->type != SD_BUS_MESSAGE_METHOD_CALL)
de1c301e
LP
1067 return 0;
1068
1069 if (interface && (!m->interface || !streq(m->interface, interface)))
1070 return 0;
1071
1072 if (member && (!m->member || !streq(m->member, member)))
1073 return 0;
1074
1075 return 1;
1076}
1077
d9f644e2 1078_public_ int sd_bus_message_is_method_error(sd_bus_message *m, const char *name) {
9d6c7c82 1079 assert_return(m, -EINVAL);
de1c301e 1080
40ca29a1 1081 if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
de1c301e
LP
1082 return 0;
1083
1084 if (name && (!m->error.name || !streq(m->error.name, name)))
1085 return 0;
1086
1087 return 1;
1088}
1089
d9f644e2 1090_public_ int sd_bus_message_set_no_reply(sd_bus_message *m, int b) {
9d6c7c82
LP
1091 assert_return(m, -EINVAL);
1092 assert_return(!m->sealed, -EPERM);
1093 assert_return(m->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EPERM);
de1c301e
LP
1094
1095 if (b)
1096 m->header->flags |= SD_BUS_MESSAGE_NO_REPLY_EXPECTED;
1097 else
1098 m->header->flags &= ~SD_BUS_MESSAGE_NO_REPLY_EXPECTED;
1099
1100 return 0;
1101}
1102
1103static struct bus_container *message_get_container(sd_bus_message *m) {
1104 assert(m);
1105
1106 if (m->n_containers == 0)
1107 return &m->root_container;
1108
9a17484d
LP
1109 assert(m->containers);
1110 return m->containers + m->n_containers - 1;
de1c301e
LP
1111}
1112
bc7fd8cd
LP
1113struct bus_body_part *message_append_part(sd_bus_message *m) {
1114 struct bus_body_part *part;
1115
1116 assert(m);
1117
1118 if (m->poisoned)
1119 return NULL;
1120
1121 if (m->n_body_parts <= 0) {
1122 part = &m->body;
1123 zero(*part);
1124 } else {
1125 assert(m->body_end);
1126
1127 part = new0(struct bus_body_part, 1);
1128 if (!part) {
1129 m->poisoned = true;
1130 return NULL;
1131 }
1132
1133 m->body_end->next = part;
1134 }
1135
1136 part->memfd = -1;
1137 m->body_end = part;
1138 m->n_body_parts ++;
1139
1140 return part;
1141}
1142
1143static void part_zero(struct bus_body_part *part, size_t sz) {
1144 assert(part);
1145 assert(sz > 0);
1146 assert(sz < 8);
1147
453a0c29
LP
1148 /* All other fields can be left in their defaults */
1149 assert(!part->data);
1150 assert(part->memfd < 0);
1151
bc7fd8cd 1152 part->size = sz;
453a0c29
LP
1153 part->is_zero = true;
1154 part->sealed = true;
bc7fd8cd
LP
1155}
1156
1157static int part_make_space(
1158 struct sd_bus_message *m,
1159 struct bus_body_part *part,
1160 size_t sz,
1161 void **q) {
1162
1163 void *n;
1164 int r;
1165
1166 assert(m);
1167 assert(part);
1168 assert(!part->sealed);
1169
1170 if (m->poisoned)
1171 return -ENOMEM;
1172
1173 if (!part->data && part->memfd < 0)
1174 part->memfd = bus_kernel_pop_memfd(m->bus, &part->data, &part->mapped);
1175
1176 if (part->memfd >= 0) {
1177 uint64_t u = sz;
1178
1179 r = ioctl(part->memfd, KDBUS_CMD_MEMFD_SIZE_SET, &u);
1180 if (r < 0) {
1181 m->poisoned = true;
1182 return -errno;
1183 }
1184
453a0c29
LP
1185 if (!part->data || sz > part->mapped) {
1186 size_t psz = PAGE_ALIGN(sz > 0 ? sz : 1);
bc7fd8cd
LP
1187
1188 if (part->mapped <= 0)
1189 n = mmap(NULL, psz, PROT_READ|PROT_WRITE, MAP_SHARED, part->memfd, 0);
1190 else
1191 n = mremap(part->data, part->mapped, psz, MREMAP_MAYMOVE);
1192
1193 if (n == MAP_FAILED) {
1194 m->poisoned = true;
1195 return -errno;
1196 }
1197
1198 part->mapped = psz;
1199 part->data = n;
1200 }
bf30e48f
KS
1201
1202 part->munmap_this = true;
bc7fd8cd 1203 } else {
23c6f770 1204 n = realloc(part->data, MAX(sz, 1u));
bc7fd8cd
LP
1205 if (!n) {
1206 m->poisoned = true;
1207 return -ENOMEM;
1208 }
1209
1210 part->data = n;
1211 part->free_this = true;
1212 }
1213
1214 if (q)
1215 *q = part->data ? (uint8_t*) part->data + part->size : NULL;
1216
1217 part->size = sz;
1218 return 0;
1219}
1220
453a0c29 1221static void message_extend_containers(sd_bus_message *m, size_t expand) {
de1c301e 1222 struct bus_container *c;
453a0c29
LP
1223
1224 assert(m);
1225
1226 if (expand <= 0)
1227 return;
1228
1229 /* Update counters */
1230 for (c = m->containers; c < m->containers + m->n_containers; c++)
1231 if (c->array_size)
1232 *c->array_size += expand;
453a0c29
LP
1233}
1234
1235static void *message_extend_body(sd_bus_message *m, size_t align, size_t sz) {
bc7fd8cd
LP
1236 struct bus_body_part *part = NULL;
1237 size_t start_body, end_body, padding, start_part, end_part, added;
1238 bool add_new_part;
1239 void *p;
1240 int r;
de1c301e
LP
1241
1242 assert(m);
9a17484d 1243 assert(align > 0);
bc7fd8cd 1244 assert(!m->sealed);
de1c301e 1245
bc7fd8cd
LP
1246 if (m->poisoned)
1247 return NULL;
de1c301e 1248
bc7fd8cd
LP
1249 start_body = ALIGN_TO((size_t) m->header->body_size, align);
1250 end_body = start_body + sz;
1251
1252 padding = start_body - m->header->body_size;
1253 added = padding + sz;
1254
1255 /* Check for 32bit overflows */
1256 if (end_body > (size_t) ((uint32_t) -1)) {
1257 m->poisoned = true;
de1c301e 1258 return NULL;
bc7fd8cd 1259 }
de1c301e 1260
bc7fd8cd
LP
1261 add_new_part =
1262 m->n_body_parts <= 0 ||
1263 m->body_end->sealed ||
1264 padding != ALIGN_TO(m->body_end->size, align) - m->body_end->size;
de1c301e 1265
bc7fd8cd
LP
1266 if (add_new_part) {
1267 if (padding > 0) {
1268 part = message_append_part(m);
1269 if (!part)
1270 return NULL;
1271
1272 part_zero(part, padding);
1273 }
1274
1275 part = message_append_part(m);
1276 if (!part)
1277 return NULL;
1278
1279 r = part_make_space(m, part, sz, &p);
1280 if (r < 0)
1281 return NULL;
1282 } else {
453a0c29 1283 struct bus_container *c;
bc7fd8cd
LP
1284 void *op;
1285 size_t os;
1286
1287 part = m->body_end;
1288 op = part->data;
1289 os = part->size;
1290
1291 start_part = ALIGN_TO(part->size, align);
1292 end_part = start_part + sz;
1293
1294 r = part_make_space(m, part, end_part, &p);
1295 if (r < 0)
1296 return NULL;
1297
1298 if (padding > 0) {
1299 memset(p, 0, padding);
1300 p = (uint8_t*) p + padding;
de1c301e
LP
1301 }
1302
bc7fd8cd
LP
1303 /* Readjust pointers */
1304 for (c = m->containers; c < m->containers + m->n_containers; c++)
1305 c->array_size = adjust_pointer(c->array_size, op, os, part->data);
1306
1307 m->error.message = (const char*) adjust_pointer(m->error.message, op, os, part->data);
de1c301e
LP
1308 }
1309
bc7fd8cd 1310 m->header->body_size = end_body;
453a0c29 1311 message_extend_containers(m, added);
de1c301e
LP
1312
1313 return p;
1314}
1315
1316int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored) {
1317 struct bus_container *c;
27f6e5c7 1318 ssize_t align, sz;
de1c301e
LP
1319 uint32_t k;
1320 void *a;
2c93b4ef 1321 int fd = -1;
62cfa9da 1322 uint32_t fdi = 0;
2c93b4ef 1323 int r;
de1c301e 1324
9d6c7c82 1325 assert_return(m, -EINVAL);
9d6c7c82
LP
1326 assert_return(!m->sealed, -EPERM);
1327 assert_return(bus_type_is_basic(type), -EINVAL);
1328 assert_return(!m->poisoned, -ESTALE);
de1c301e
LP
1329
1330 c = message_get_container(m);
1331
1332 if (c->signature && c->signature[c->index]) {
1333 /* Container signature is already set */
1334
1335 if (c->signature[c->index] != type)
9a17484d 1336 return -ENXIO;
de1c301e 1337 } else {
5cbe7492
LP
1338 char *e;
1339
de1c301e
LP
1340 /* Maybe we can append to the signature? But only if this is the top-level container*/
1341 if (c->enclosing != 0)
9a17484d 1342 return -ENXIO;
de1c301e
LP
1343
1344 e = strextend(&c->signature, CHAR_TO_STR(type), NULL);
bc7fd8cd
LP
1345 if (!e) {
1346 m->poisoned = true;
de1c301e 1347 return -ENOMEM;
bc7fd8cd 1348 }
de1c301e
LP
1349 }
1350
de1c301e
LP
1351 switch (type) {
1352
1353 case SD_BUS_TYPE_STRING:
cd6f997f
LP
1354 /* To make things easy we'll serialize a NULL string
1355 * into the empty string */
1356 p = strempty(p);
1357
1358 /* Fall through... */
de1c301e 1359 case SD_BUS_TYPE_OBJECT_PATH:
b8beb278 1360
cd6f997f
LP
1361 if (!p) {
1362 r = -EINVAL;
1363 goto fail;
1364 }
1365
de1c301e
LP
1366 align = 4;
1367 sz = 4 + strlen(p) + 1;
1368 break;
1369
1370 case SD_BUS_TYPE_SIGNATURE:
b8beb278 1371
cd6f997f
LP
1372 if (!p) {
1373 r = -EINVAL;
1374 goto fail;
1375 }
1376
de1c301e
LP
1377 align = 1;
1378 sz = 1 + strlen(p) + 1;
1379 break;
1380
1381 case SD_BUS_TYPE_BOOLEAN:
b3273daf 1382
15912917
KS
1383 if (!p) {
1384 r = -EINVAL;
1385 goto fail;
1386 }
1387
de1c301e
LP
1388 align = sz = 4;
1389
1390 assert_cc(sizeof(int) == sizeof(uint32_t));
1391 memcpy(&k, p, 4);
1392 k = !!k;
1393 p = &k;
1394 break;
1395
2c93b4ef
LP
1396 case SD_BUS_TYPE_UNIX_FD: {
1397 int z, *f;
1398
15912917
KS
1399 if (!p) {
1400 r = -EINVAL;
1401 goto fail;
1402 }
1403
2c93b4ef
LP
1404 if (!m->allow_fds) {
1405 r = -ENOTSUP;
1406 goto fail;
1407 }
1408
1409 align = sz = 4;
1410
1411 z = *(int*) p;
1412 if (z < 0) {
1413 r = -EINVAL;
1414 goto fail;
1415 }
1416
1417 fd = fcntl(z, F_DUPFD_CLOEXEC, 3);
1418 if (fd < 0) {
1419 r = -errno;
1420 goto fail;
1421 }
1422
1423 f = realloc(m->fds, sizeof(int) * (m->n_fds + 1));
1424 if (!f) {
bc7fd8cd 1425 m->poisoned = true;
2c93b4ef
LP
1426 r = -ENOMEM;
1427 goto fail;
1428 }
1429
1430 fdi = m->n_fds;
1431 f[fdi] = fd;
1432 m->fds = f;
1433 m->free_fds = true;
1434 break;
1435 }
1436
de1c301e 1437 default:
b3273daf
LP
1438 if (!p) {
1439 r = -EINVAL;
1440 goto fail;
1441 }
1442
de1c301e
LP
1443 align = bus_type_get_alignment(type);
1444 sz = bus_type_get_size(type);
1445 break;
1446 }
1447
1448 assert(align > 0);
1449 assert(sz > 0);
1450
1451 a = message_extend_body(m, align, sz);
1452 if (!a) {
2c93b4ef
LP
1453 r = -ENOMEM;
1454 goto fail;
de1c301e
LP
1455 }
1456
1457 if (type == SD_BUS_TYPE_STRING || type == SD_BUS_TYPE_OBJECT_PATH) {
1458 *(uint32_t*) a = sz - 5;
1459 memcpy((uint8_t*) a + 4, p, sz - 4);
1460
1461 if (stored)
1462 *stored = (const uint8_t*) a + 4;
1463
1464 } else if (type == SD_BUS_TYPE_SIGNATURE) {
1465 *(uint8_t*) a = sz - 1;
1466 memcpy((uint8_t*) a + 1, p, sz - 1);
1467
1468 if (stored)
1469 *stored = (const uint8_t*) a + 1;
2c93b4ef
LP
1470 } else if (type == SD_BUS_TYPE_UNIX_FD) {
1471 *(uint32_t*) a = fdi;
1472
1473 if (stored)
1474 *stored = a;
1475
1476 m->n_fds ++;
de1c301e
LP
1477
1478 } else {
1479 memcpy(a, p, sz);
1480
1481 if (stored)
1482 *stored = a;
1483 }
1484
1485 if (c->enclosing != SD_BUS_TYPE_ARRAY)
9a17484d 1486 c->index++;
de1c301e
LP
1487
1488 return 0;
2c93b4ef
LP
1489
1490fail:
2c93b4ef
LP
1491 if (fd >= 0)
1492 close_nointr_nofail(fd);
1493
1494 return r;
de1c301e
LP
1495}
1496
d9f644e2 1497_public_ int sd_bus_message_append_basic(sd_bus_message *m, char type, const void *p) {
de1c301e
LP
1498 return message_append_basic(m, type, p, NULL);
1499}
1500
d9f644e2 1501_public_ int sd_bus_message_append_string_space(sd_bus_message *m, size_t size, char **s) {
f8e013f8 1502 struct bus_container *c;
f8e013f8 1503 void *a;
f8e013f8 1504
9d6c7c82
LP
1505 assert_return(m, -EINVAL);
1506 assert_return(s, -EINVAL);
1507 assert_return(!m->sealed, -EPERM);
1508 assert_return(!m->poisoned, -ESTALE);
f8e013f8
LP
1509
1510 c = message_get_container(m);
1511
1512 if (c->signature && c->signature[c->index]) {
1513 /* Container signature is already set */
1514
1515 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
1516 return -ENXIO;
1517 } else {
5cbe7492
LP
1518 char *e;
1519
f8e013f8
LP
1520 /* Maybe we can append to the signature? But only if this is the top-level container*/
1521 if (c->enclosing != 0)
1522 return -ENXIO;
1523
1524 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
bc7fd8cd
LP
1525 if (!e) {
1526 m->poisoned = true;
f8e013f8 1527 return -ENOMEM;
bc7fd8cd 1528 }
f8e013f8
LP
1529 }
1530
f8e013f8 1531 a = message_extend_body(m, 4, 4 + size + 1);
bc7fd8cd
LP
1532 if (!a)
1533 return -ENOMEM;
f8e013f8
LP
1534
1535 *(uint32_t*) a = size;
1536 *s = (char*) a + 4;
1537
1538 (*s)[size] = 0;
1539
1540 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1541 c->index++;
1542
1543 return 0;
f8e013f8
LP
1544}
1545
de1c301e
LP
1546static int bus_message_open_array(
1547 sd_bus_message *m,
1548 struct bus_container *c,
1549 const char *contents,
1550 uint32_t **array_size) {
1551
9a17484d 1552 unsigned nindex;
bc7fd8cd 1553 void *a, *op;
de1c301e 1554 int alignment;
bc7fd8cd
LP
1555 size_t os;
1556 struct bus_body_part *o;
de1c301e
LP
1557
1558 assert(m);
1559 assert(c);
1560 assert(contents);
1561 assert(array_size);
1562
29ddb38f 1563 if (!signature_is_single(contents, true))
de1c301e
LP
1564 return -EINVAL;
1565
1566 alignment = bus_type_get_alignment(contents[0]);
1567 if (alignment < 0)
1568 return alignment;
1569
1570 if (c->signature && c->signature[c->index]) {
1571
1572 /* Verify the existing signature */
1573
1574 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
9a17484d 1575 return -ENXIO;
de1c301e
LP
1576
1577 if (!startswith(c->signature + c->index + 1, contents))
9a17484d 1578 return -ENXIO;
de1c301e
LP
1579
1580 nindex = c->index + 1 + strlen(contents);
1581 } else {
5cbe7492
LP
1582 char *e;
1583
de1c301e 1584 if (c->enclosing != 0)
9a17484d 1585 return -ENXIO;
de1c301e
LP
1586
1587 /* Extend the existing signature */
1588
1589 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_ARRAY), contents, NULL);
bc7fd8cd
LP
1590 if (!e) {
1591 m->poisoned = true;
de1c301e 1592 return -ENOMEM;
bc7fd8cd 1593 }
de1c301e
LP
1594
1595 nindex = e - c->signature;
1596 }
1597
de1c301e 1598 a = message_extend_body(m, 4, 4);
bc7fd8cd 1599 if (!a)
de1c301e 1600 return -ENOMEM;
de1c301e 1601
bc7fd8cd
LP
1602 o = m->body_end;
1603 op = m->body_end->data;
1604 os = m->body_end->size;
de1c301e 1605
bc7fd8cd
LP
1606 /* Add alignment between size and first element */
1607 if (!message_extend_body(m, alignment, 0))
de1c301e 1608 return -ENOMEM;
de1c301e
LP
1609
1610 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1611 c->index = nindex;
1612
bc7fd8cd
LP
1613 /* location of array size might have changed so let's readjust a */
1614 if (o == m->body_end)
1615 a = adjust_pointer(a, op, os, m->body_end->data);
de1c301e 1616
bc7fd8cd 1617 *(uint32_t*) a = 0;
de1c301e
LP
1618 *array_size = a;
1619 return 0;
1620}
1621
1622static int bus_message_open_variant(
1623 sd_bus_message *m,
1624 struct bus_container *c,
1625 const char *contents) {
1626
9a17484d 1627 size_t l;
de1c301e
LP
1628 void *a;
1629
1630 assert(m);
1631 assert(c);
1632 assert(contents);
1633
29ddb38f 1634 if (!signature_is_single(contents, false))
de1c301e
LP
1635 return -EINVAL;
1636
1637 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
1638 return -EINVAL;
1639
1640 if (c->signature && c->signature[c->index]) {
1641
1642 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
9a17484d 1643 return -ENXIO;
de1c301e
LP
1644
1645 } else {
5cbe7492
LP
1646 char *e;
1647
de1c301e 1648 if (c->enclosing != 0)
9a17484d 1649 return -ENXIO;
de1c301e
LP
1650
1651 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_VARIANT), NULL);
bc7fd8cd
LP
1652 if (!e) {
1653 m->poisoned = true;
de1c301e 1654 return -ENOMEM;
bc7fd8cd 1655 }
de1c301e
LP
1656 }
1657
de1c301e
LP
1658 l = strlen(contents);
1659 a = message_extend_body(m, 1, 1 + l + 1);
bc7fd8cd 1660 if (!a)
de1c301e 1661 return -ENOMEM;
de1c301e
LP
1662
1663 *(uint8_t*) a = l;
1664 memcpy((uint8_t*) a + 1, contents, l + 1);
1665
1666 if (c->enclosing != SD_BUS_TYPE_ARRAY)
9a17484d 1667 c->index++;
de1c301e
LP
1668
1669 return 0;
1670}
1671
1672static int bus_message_open_struct(
1673 sd_bus_message *m,
1674 struct bus_container *c,
1675 const char *contents) {
1676
1677 size_t nindex;
de1c301e
LP
1678
1679 assert(m);
1680 assert(c);
1681 assert(contents);
1682
1683 if (!signature_is_valid(contents, false))
1684 return -EINVAL;
1685
1686 if (c->signature && c->signature[c->index]) {
1687 size_t l;
1688
1689 l = strlen(contents);
1690
1691 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
1692 !startswith(c->signature + c->index + 1, contents) ||
1693 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
9a17484d 1694 return -ENXIO;
de1c301e
LP
1695
1696 nindex = c->index + 1 + l + 1;
1697 } else {
5cbe7492
LP
1698 char *e;
1699
de1c301e 1700 if (c->enclosing != 0)
9a17484d 1701 return -ENXIO;
de1c301e
LP
1702
1703 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_BEGIN), contents, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_END), NULL);
bc7fd8cd
LP
1704 if (!e) {
1705 m->poisoned = true;
de1c301e 1706 return -ENOMEM;
bc7fd8cd 1707 }
de1c301e
LP
1708
1709 nindex = e - c->signature;
1710 }
1711
1712 /* Align contents to 8 byte boundary */
bc7fd8cd 1713 if (!message_extend_body(m, 8, 0))
de1c301e 1714 return -ENOMEM;
de1c301e
LP
1715
1716 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1717 c->index = nindex;
1718
1719 return 0;
1720}
1721
1722static int bus_message_open_dict_entry(
1723 sd_bus_message *m,
1724 struct bus_container *c,
1725 const char *contents) {
1726
1727 size_t nindex;
1728
1729 assert(m);
1730 assert(c);
1731 assert(contents);
1732
1733 if (!signature_is_pair(contents))
1734 return -EINVAL;
1735
1736 if (c->enclosing != SD_BUS_TYPE_ARRAY)
9a17484d 1737 return -ENXIO;
de1c301e
LP
1738
1739 if (c->signature && c->signature[c->index]) {
1740 size_t l;
1741
1742 l = strlen(contents);
1743
1744 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
1745 !startswith(c->signature + c->index + 1, contents) ||
1746 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
9a17484d 1747 return -ENXIO;
de1c301e
LP
1748
1749 nindex = c->index + 1 + l + 1;
1750 } else
9a17484d 1751 return -ENXIO;
de1c301e
LP
1752
1753 /* Align contents to 8 byte boundary */
1754 if (!message_extend_body(m, 8, 0))
1755 return -ENOMEM;
1756
1757 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1758 c->index = nindex;
1759
1760 return 0;
1761}
1762
d9f644e2 1763_public_ int sd_bus_message_open_container(
de1c301e
LP
1764 sd_bus_message *m,
1765 char type,
1766 const char *contents) {
1767
9a17484d 1768 struct bus_container *c, *w;
de1c301e 1769 uint32_t *array_size = NULL;
9a17484d 1770 char *signature;
b3af9646 1771 size_t before;
de1c301e
LP
1772 int r;
1773
9d6c7c82
LP
1774 assert_return(m, -EINVAL);
1775 assert_return(!m->sealed, -EPERM);
1776 assert_return(contents, -EINVAL);
1777 assert_return(!m->poisoned, -ESTALE);
de1c301e
LP
1778
1779 /* Make sure we have space for one more container */
9a17484d 1780 w = realloc(m->containers, sizeof(struct bus_container) * (m->n_containers + 1));
bc7fd8cd
LP
1781 if (!w) {
1782 m->poisoned = true;
de1c301e 1783 return -ENOMEM;
bc7fd8cd
LP
1784 }
1785
9a17484d 1786 m->containers = w;
de1c301e
LP
1787
1788 c = message_get_container(m);
1789
1790 signature = strdup(contents);
bc7fd8cd
LP
1791 if (!signature) {
1792 m->poisoned = true;
de1c301e 1793 return -ENOMEM;
bc7fd8cd 1794 }
de1c301e 1795
b3af9646
LP
1796 /* Save old index in the parent container, in case we have to
1797 * abort this container */
1798 c->saved_index = c->index;
1799 before = m->header->body_size;
1800
de1c301e
LP
1801 if (type == SD_BUS_TYPE_ARRAY)
1802 r = bus_message_open_array(m, c, contents, &array_size);
1803 else if (type == SD_BUS_TYPE_VARIANT)
1804 r = bus_message_open_variant(m, c, contents);
1805 else if (type == SD_BUS_TYPE_STRUCT)
1806 r = bus_message_open_struct(m, c, contents);
1807 else if (type == SD_BUS_TYPE_DICT_ENTRY)
1808 r = bus_message_open_dict_entry(m, c, contents);
1809 else
1810 r = -EINVAL;
1811
1812 if (r < 0) {
1813 free(signature);
1814 return r;
1815 }
1816
1817 /* OK, let's fill it in */
9a17484d
LP
1818 w += m->n_containers++;
1819 w->enclosing = type;
1820 w->signature = signature;
1821 w->index = 0;
1822 w->array_size = array_size;
b3af9646
LP
1823 w->before = before;
1824 w->begin = m->rindex;
de1c301e
LP
1825
1826 return 0;
1827}
1828
d9f644e2 1829_public_ int sd_bus_message_close_container(sd_bus_message *m) {
de1c301e
LP
1830 struct bus_container *c;
1831
9d6c7c82
LP
1832 assert_return(m, -EINVAL);
1833 assert_return(!m->sealed, -EPERM);
1834 assert_return(m->n_containers > 0, -EINVAL);
1835 assert_return(!m->poisoned, -ESTALE);
de1c301e
LP
1836
1837 c = message_get_container(m);
de1c301e 1838 if (c->enclosing != SD_BUS_TYPE_ARRAY)
9a17484d 1839 if (c->signature && c->signature[c->index] != 0)
de1c301e
LP
1840 return -EINVAL;
1841
1842 free(c->signature);
1843 m->n_containers--;
1844
1845 return 0;
1846}
1847
1b492614
LP
1848typedef struct {
1849 const char *types;
1850 unsigned n_struct;
1851 unsigned n_array;
1852} TypeStack;
1853
1854static int type_stack_push(TypeStack *stack, unsigned max, unsigned *i, const char *types, unsigned n_struct, unsigned n_array) {
1855 assert(stack);
1856 assert(max > 0);
1857
1858 if (*i >= max)
1859 return -EINVAL;
1860
1861 stack[*i].types = types;
1862 stack[*i].n_struct = n_struct;
1863 stack[*i].n_array = n_array;
1864 (*i)++;
1865
1866 return 0;
1867}
1868
1869static int type_stack_pop(TypeStack *stack, unsigned max, unsigned *i, const char **types, unsigned *n_struct, unsigned *n_array) {
1870 assert(stack);
1871 assert(max > 0);
1872 assert(types);
1873 assert(n_struct);
1874 assert(n_array);
1875
1876 if (*i <= 0)
1877 return 0;
1878
1879 (*i)--;
1880 *types = stack[*i].types;
1881 *n_struct = stack[*i].n_struct;
1882 *n_array = stack[*i].n_array;
1883
1884 return 1;
1885}
1886
917b5dc7 1887int bus_message_append_ap(
de1c301e
LP
1888 sd_bus_message *m,
1889 const char *types,
1890 va_list ap) {
1891
1b492614
LP
1892 unsigned n_array, n_struct;
1893 TypeStack stack[BUS_CONTAINER_DEPTH];
1894 unsigned stack_ptr = 0;
de1c301e
LP
1895 int r;
1896
1897 assert(m);
88d331d5
LP
1898
1899 if (!types)
1900 return 0;
de1c301e 1901
1b492614
LP
1902 n_array = (unsigned) -1;
1903 n_struct = strlen(types);
1904
1905 for (;;) {
1906 const char *t;
1907
1908 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
1909 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
1910 if (r < 0)
1911 return r;
1912 if (r == 0)
1913 break;
1914
1915 r = sd_bus_message_close_container(m);
1916 if (r < 0)
1917 return r;
1918
1919 continue;
1920 }
1921
1922 t = types;
1923 if (n_array != (unsigned) -1)
1924 n_array --;
1925 else {
1926 types ++;
1927 n_struct--;
1928 }
1929
de1c301e
LP
1930 switch (*t) {
1931
1932 case SD_BUS_TYPE_BYTE: {
1933 uint8_t x;
1934
1935 x = (uint8_t) va_arg(ap, int);
1936 r = sd_bus_message_append_basic(m, *t, &x);
1937 break;
1938 }
1939
1940 case SD_BUS_TYPE_BOOLEAN:
1941 case SD_BUS_TYPE_INT32:
9a17484d
LP
1942 case SD_BUS_TYPE_UINT32:
1943 case SD_BUS_TYPE_UNIX_FD: {
de1c301e
LP
1944 uint32_t x;
1945
9a17484d
LP
1946 /* We assume a boolean is the same as int32_t */
1947 assert_cc(sizeof(int32_t) == sizeof(int));
1948
de1c301e
LP
1949 x = va_arg(ap, uint32_t);
1950 r = sd_bus_message_append_basic(m, *t, &x);
1951 break;
1952 }
1953
1954 case SD_BUS_TYPE_INT16:
1955 case SD_BUS_TYPE_UINT16: {
1956 uint16_t x;
1957
1958 x = (uint16_t) va_arg(ap, int);
1959 r = sd_bus_message_append_basic(m, *t, &x);
1960 break;
1961 }
1962
1963 case SD_BUS_TYPE_INT64:
1964 case SD_BUS_TYPE_UINT64:
1965 case SD_BUS_TYPE_DOUBLE: {
1966 uint64_t x;
1967
1968 x = va_arg(ap, uint64_t);
1969 r = sd_bus_message_append_basic(m, *t, &x);
1970 break;
1971 }
1972
1973 case SD_BUS_TYPE_STRING:
1974 case SD_BUS_TYPE_OBJECT_PATH:
1975 case SD_BUS_TYPE_SIGNATURE: {
1976 const char *x;
1977
1978 x = va_arg(ap, const char*);
1979 r = sd_bus_message_append_basic(m, *t, x);
1980 break;
1981 }
1982
de1c301e 1983 case SD_BUS_TYPE_ARRAY: {
de1c301e
LP
1984 size_t k;
1985
1986 r = signature_element_length(t + 1, &k);
1987 if (r < 0)
1988 return r;
1989
1990 {
1991 char s[k + 1];
de1c301e
LP
1992 memcpy(s, t + 1, k);
1993 s[k] = 0;
de1c301e
LP
1994
1995 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, s);
1996 if (r < 0)
1997 return r;
1b492614 1998 }
de1c301e 1999
1b492614
LP
2000 if (n_array == (unsigned) -1) {
2001 types += k;
2002 n_struct -= k;
de1c301e
LP
2003 }
2004
1b492614
LP
2005 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2006 if (r < 0)
2007 return r;
2008
2009 types = t + 1;
2010 n_struct = k;
2011 n_array = va_arg(ap, unsigned);
2012
de1c301e
LP
2013 break;
2014 }
2015
2016 case SD_BUS_TYPE_VARIANT: {
2017 const char *s;
2018
2019 s = va_arg(ap, const char*);
2020 if (!s)
2021 return -EINVAL;
2022
2023 r = sd_bus_message_open_container(m, SD_BUS_TYPE_VARIANT, s);
2024 if (r < 0)
2025 return r;
2026
1b492614 2027 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
de1c301e
LP
2028 if (r < 0)
2029 return r;
2030
1b492614
LP
2031 types = s;
2032 n_struct = strlen(s);
2033 n_array = (unsigned) -1;
2034
de1c301e
LP
2035 break;
2036 }
2037
2038 case SD_BUS_TYPE_STRUCT_BEGIN:
2039 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
2040 size_t k;
2041
2042 r = signature_element_length(t, &k);
2043 if (r < 0)
2044 return r;
2045
2046 {
2047 char s[k - 1];
2048
2049 memcpy(s, t + 1, k - 2);
2050 s[k - 2] = 0;
2051
2052 r = sd_bus_message_open_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
2053 if (r < 0)
2054 return r;
1b492614 2055 }
de1c301e 2056
1b492614
LP
2057 if (n_array == (unsigned) -1) {
2058 types += k - 1;
2059 n_struct -= k - 1;
2060 }
de1c301e 2061
1b492614
LP
2062 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2063 if (r < 0)
2064 return r;
de1c301e 2065
1b492614
LP
2066 types = t + 1;
2067 n_struct = k - 2;
2068 n_array = (unsigned) -1;
de1c301e
LP
2069
2070 break;
2071 }
2072
2073 default:
2074 r = -EINVAL;
2075 }
2076
2077 if (r < 0)
2078 return r;
2079 }
2080
2081 return 0;
2082}
2083
d9f644e2 2084_public_ int sd_bus_message_append(sd_bus_message *m, const char *types, ...) {
de1c301e
LP
2085 va_list ap;
2086 int r;
2087
9d6c7c82
LP
2088 assert_return(m, -EINVAL);
2089 assert_return(types, -EINVAL);
2090 assert_return(!m->sealed, -EPERM);
2091 assert_return(!m->poisoned, -ESTALE);
de1c301e
LP
2092
2093 va_start(ap, types);
917b5dc7 2094 r = bus_message_append_ap(m, types, ap);
de1c301e
LP
2095 va_end(ap);
2096
2097 return r;
2098}
2099
d9f644e2
ZJS
2100_public_ int sd_bus_message_append_array_space(sd_bus_message *m,
2101 char type,
2102 size_t size,
2103 void **ptr) {
b3af9646
LP
2104 ssize_t align, sz;
2105 void *a;
2106 int r;
2107
9d6c7c82
LP
2108 assert_return(m, -EINVAL);
2109 assert_return(!m->sealed, -EPERM);
2110 assert_return(bus_type_is_trivial(type), -EINVAL);
2111 assert_return(ptr || size == 0, -EINVAL);
2112 assert_return(!m->poisoned, -ESTALE);
b3af9646
LP
2113
2114 align = bus_type_get_alignment(type);
2115 sz = bus_type_get_size(type);
2116
2117 assert_se(align > 0);
2118 assert_se(sz > 0);
2119
2120 if (size % sz != 0)
2121 return -EINVAL;
2122
2123 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2124 if (r < 0)
2125 return r;
2126
2127 a = message_extend_body(m, align, size);
bc7fd8cd
LP
2128 if (!a)
2129 return -ENOMEM;
b3af9646
LP
2130
2131 r = sd_bus_message_close_container(m);
2132 if (r < 0)
bc7fd8cd 2133 return r;
b3af9646
LP
2134
2135 *ptr = a;
2136 return 0;
b3af9646
LP
2137}
2138
d9f644e2
ZJS
2139_public_ int sd_bus_message_append_array(sd_bus_message *m,
2140 char type,
2141 const void *ptr,
2142 size_t size) {
b3af9646
LP
2143 int r;
2144 void *p;
2145
9d6c7c82
LP
2146 assert_return(m, -EINVAL);
2147 assert_return(!m->sealed, -EPERM);
2148 assert_return(bus_type_is_trivial(type), -EINVAL);
2149 assert_return(ptr || size == 0, -EINVAL);
2150 assert_return(!m->poisoned, -ESTALE);
b3af9646 2151
f8e013f8 2152 r = sd_bus_message_append_array_space(m, type, size, &p);
b3af9646
LP
2153 if (r < 0)
2154 return r;
2155
2156 if (size > 0)
2157 memcpy(p, ptr, size);
2158
2159 return 0;
2160}
2161
d9f644e2
ZJS
2162_public_ int sd_bus_message_append_array_memfd(sd_bus_message *m,
2163 char type,
2164 sd_memfd *memfd) {
453a0c29
LP
2165 _cleanup_close_ int copy_fd = -1;
2166 struct bus_body_part *part;
2167 ssize_t align, sz;
2168 uint64_t size;
2169 void *a;
2170 int r;
2171
2172 if (!m)
2173 return -EINVAL;
2174 if (!memfd)
2175 return -EINVAL;
2176 if (m->sealed)
2177 return -EPERM;
2178 if (!bus_type_is_trivial(type))
2179 return -EINVAL;
2180 if (m->poisoned)
2181 return -ESTALE;
2182
2183 r = sd_memfd_set_sealed(memfd, true);
2184 if (r < 0)
2185 return r;
2186
2187 copy_fd = sd_memfd_dup_fd(memfd);
2188 if (copy_fd < 0)
2189 return copy_fd;
2190
2191 r = sd_memfd_get_size(memfd, &size);
2192 if (r < 0)
2193 return r;
2194
2195 align = bus_type_get_alignment(type);
2196 sz = bus_type_get_size(type);
2197
2198 assert_se(align > 0);
2199 assert_se(sz > 0);
2200
2201 if (size % sz != 0)
2202 return -EINVAL;
2203
5cbe7492 2204 if (size > (uint64_t) (uint32_t) -1)
453a0c29
LP
2205 return -EINVAL;
2206
2207 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2208 if (r < 0)
2209 return r;
2210
2211 a = message_extend_body(m, align, 0);
2212 if (!a)
2213 return -ENOMEM;
2214
2215 part = message_append_part(m);
2216 if (!part)
2217 return -ENOMEM;
2218
2219 part->memfd = copy_fd;
2220 part->sealed = true;
2221 part->size = size;
2222 copy_fd = -1;
2223
2224 message_extend_containers(m, size);
2225 m->header->body_size += size;
2226
2227 return sd_bus_message_close_container(m);
2228}
2229
d9f644e2 2230_public_ int sd_bus_message_append_string_memfd(sd_bus_message *m, sd_memfd *memfd) {
5cbe7492
LP
2231 _cleanup_close_ int copy_fd = -1;
2232 struct bus_body_part *part;
2233 struct bus_container *c;
2234 uint64_t size;
2235 void *a;
2236 int r;
2237
55736ed0
LP
2238 assert_return(m, -EINVAL);
2239 assert_return(memfd, -EINVAL);
2240 assert_return(!m->sealed, -EPERM);
2241 assert_return(!m->poisoned, -ESTALE);
5cbe7492
LP
2242
2243 r = sd_memfd_set_sealed(memfd, true);
2244 if (r < 0)
2245 return r;
2246
2247 copy_fd = sd_memfd_dup_fd(memfd);
2248 if (copy_fd < 0)
2249 return copy_fd;
2250
2251 r = sd_memfd_get_size(memfd, &size);
2252 if (r < 0)
2253 return r;
2254
2255 /* We require this to be NUL terminated */
2256 if (size == 0)
2257 return -EINVAL;
2258
2259 if (size > (uint64_t) (uint32_t) -1)
2260 return -EINVAL;
2261
2262 c = message_get_container(m);
2263 if (c->signature && c->signature[c->index]) {
2264 /* Container signature is already set */
2265
2266 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
2267 return -ENXIO;
2268 } else {
2269 char *e;
2270
2271 /* Maybe we can append to the signature? But only if this is the top-level container*/
2272 if (c->enclosing != 0)
2273 return -ENXIO;
2274
2275 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
2276 if (!e) {
2277 m->poisoned = true;
2278 return -ENOMEM;
2279 }
2280 }
2281
2282 a = message_extend_body(m, 4, 4);
2283 if (!a)
2284 return -ENOMEM;
2285
2286 *(uint32_t*) a = size - 1;
2287
2288 part = message_append_part(m);
2289 if (!part)
2290 return -ENOMEM;
2291
2292 part->memfd = copy_fd;
2293 part->sealed = true;
2294 part->size = size;
2295 copy_fd = -1;
2296
2297 message_extend_containers(m, size);
2298 m->header->body_size += size;
2299
2300 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2301 c->index++;
2302
2303 return 0;
2304}
2305
d9f644e2 2306_public_ int sd_bus_message_append_strv(sd_bus_message *m, char **l) {
55736ed0
LP
2307 char **i;
2308 int r;
2309
2310 assert_return(m, -EINVAL);
2311 assert_return(!m->sealed, -EPERM);
2312 assert_return(!m->poisoned, -ESTALE);
2313
2314 r = sd_bus_message_open_container(m, 'a', "s");
2315 if (r < 0)
2316 return r;
2317
2318 STRV_FOREACH(i, l) {
2319 r = sd_bus_message_append_basic(m, 's', *i);
2320 if (r < 0)
2321 return r;
2322 }
2323
2324 return sd_bus_message_close_container(m);
2325}
2326
a392d361 2327int bus_body_part_map(struct bus_body_part *part) {
453a0c29
LP
2328 void *p;
2329 size_t psz;
2330
2331 assert_se(part);
2332
2333 if (part->data)
2334 return 0;
2335
2336 if (part->size <= 0)
2337 return 0;
2338
1307c3ff
LP
2339 /* For smaller zero parts (as used for padding) we don't need to map anything... */
2340 if (part->memfd < 0 && part->is_zero && part->size < 8) {
2341 static const uint8_t zeroes[7] = { };
2342 part->data = (void*) zeroes;
2343 return 0;
2344 }
2345
453a0c29
LP
2346 psz = PAGE_ALIGN(part->size);
2347
2348 if (part->memfd >= 0)
2349 p = mmap(NULL, psz, PROT_READ, MAP_SHARED, part->memfd, 0);
2350 else if (part->is_zero)
2351 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
2352 else
2353 return -EINVAL;
2354
2355 if (p == MAP_FAILED)
2356 return -errno;
2357
2358 part->mapped = psz;
2359 part->data = p;
a392d361
LP
2360 part->munmap_this = true;
2361
453a0c29
LP
2362 return 0;
2363}
2364
a392d361
LP
2365void bus_body_part_unmap(struct bus_body_part *part) {
2366
2367 assert_se(part);
2368
2369 if (part->memfd < 0)
2370 return;
2371
a392d361
LP
2372 if (!part->data)
2373 return;
2374
bf30e48f
KS
2375 if (!part->munmap_this)
2376 return;
a392d361
LP
2377
2378 assert_se(munmap(part->data, part->mapped) == 0);
2379
2380 part->data = NULL;
2381 part->mapped = 0;
2382 part->munmap_this = false;
2383
2384 return;
2385}
2386
9a17484d 2387static int buffer_peek(const void *p, uint32_t sz, size_t *rindex, size_t align, size_t nbytes, void **r) {
bc7fd8cd 2388 size_t k, start, end;
de1c301e 2389
9a17484d
LP
2390 assert(rindex);
2391 assert(align > 0);
de1c301e 2392
9a17484d 2393 start = ALIGN_TO((size_t) *rindex, align);
bc7fd8cd 2394 end = start + nbytes;
9a17484d 2395
bc7fd8cd 2396 if (end > sz)
9a17484d
LP
2397 return -EBADMSG;
2398
2399 /* Verify that padding is 0 */
2400 for (k = *rindex; k < start; k++)
2401 if (((const uint8_t*) p)[k] != 0)
2402 return -EBADMSG;
2403
2404 if (r)
2405 *r = (uint8_t*) p + start;
2406
bc7fd8cd 2407 *rindex = end;
9a17484d
LP
2408
2409 return 1;
de1c301e
LP
2410}
2411
7b058942
LP
2412static bool message_end_of_signature(sd_bus_message *m) {
2413 struct bus_container *c;
2414
2415 assert(m);
2416
2417 c = message_get_container(m);
2418 return !c->signature || c->signature[c->index] == 0;
2419}
2420
9a17484d
LP
2421static bool message_end_of_array(sd_bus_message *m, size_t index) {
2422 struct bus_container *c;
de1c301e 2423
9a17484d 2424 assert(m);
de1c301e 2425
9a17484d
LP
2426 c = message_get_container(m);
2427 if (!c->array_size)
2428 return false;
de1c301e 2429
9a17484d 2430 return index >= c->begin + BUS_MESSAGE_BSWAP32(m, *c->array_size);
de1c301e
LP
2431}
2432
7b058942
LP
2433int sd_bus_message_at_end(sd_bus_message *m, int complete) {
2434 assert_return(m, -EINVAL);
2435 assert_return(m->sealed, -EPERM);
2436
2437 if (complete && m->n_containers > 0)
2438 return false;
2439
2440 if (message_end_of_signature(m))
2441 return true;
2442
2443 if (message_end_of_array(m, m->rindex))
2444 return true;
2445
2446 return false;
2447}
2448
bc7fd8cd
LP
2449static struct bus_body_part* find_part(sd_bus_message *m, size_t index, size_t sz, void **p) {
2450 struct bus_body_part *part;
2451 size_t begin;
453a0c29
LP
2452 int r;
2453
bc7fd8cd
LP
2454 assert(m);
2455
2456 if (m->cached_rindex_part && index >= m->cached_rindex_part_begin) {
2457 part = m->cached_rindex_part;
2458 begin = m->cached_rindex_part_begin;
2459 } else {
2460 part = &m->body;
2461 begin = 0;
2462 }
2463
2464 while (part) {
2465 if (index < begin)
2466 return NULL;
2467
2468 if (index + sz <= begin + part->size) {
453a0c29 2469
a392d361 2470 r = bus_body_part_map(part);
453a0c29
LP
2471 if (r < 0)
2472 return NULL;
2473
bc7fd8cd 2474 if (p)
453a0c29 2475 *p = (uint8_t*) part->data + index - begin;
bc7fd8cd
LP
2476
2477 m->cached_rindex_part = part;
2478 m->cached_rindex_part_begin = begin;
2479
2480 return part;
2481 }
2482
453a0c29 2483 begin += part->size;
bc7fd8cd
LP
2484 part = part->next;
2485 }
2486
2487 return NULL;
2488}
2489
2490static int message_peek_body(
2491 sd_bus_message *m,
2492 size_t *rindex,
2493 size_t align,
2494 size_t nbytes,
2495 void **ret) {
2496
2497 size_t k, start, end, padding;
2498 struct bus_body_part *part;
2499 uint8_t *q;
2500
de1c301e 2501 assert(m);
9a17484d
LP
2502 assert(rindex);
2503 assert(align > 0);
de1c301e 2504
9a17484d
LP
2505 if (message_end_of_array(m, *rindex))
2506 return 0;
de1c301e 2507
bc7fd8cd
LP
2508 start = ALIGN_TO((size_t) *rindex, align);
2509 padding = start - *rindex;
2510 end = start + nbytes;
2511
2512 if (end > BUS_MESSAGE_BODY_SIZE(m))
2513 return -EBADMSG;
2514
2515 part = find_part(m, *rindex, padding, (void**) &q);
2516 if (!part)
2517 return -EBADMSG;
2518
2519 if (q) {
2520 /* Verify padding */
2521 for (k = 0; k < padding; k++)
2522 if (q[k] != 0)
2523 return -EBADMSG;
2524 }
2525
2526 part = find_part(m, start, nbytes, (void**) &q);
2527 if (!part || !q)
2528 return -EBADMSG;
2529
2530 *rindex = end;
2531
2532 if (ret)
2533 *ret = q;
2534
2535 return 1;
9a17484d 2536}
de1c301e 2537
ac89bf1d 2538static bool validate_nul(const char *s, size_t l) {
de1c301e 2539
9a17484d
LP
2540 /* Check for NUL chars in the string */
2541 if (memchr(s, 0, l))
2542 return false;
de1c301e 2543
9a17484d
LP
2544 /* Check for NUL termination */
2545 if (s[l] != 0)
2546 return false;
de1c301e 2547
ac89bf1d
LP
2548 return true;
2549}
2550
2551static bool validate_string(const char *s, size_t l) {
2552
2553 if (!validate_nul(s, l))
2554 return false;
2555
9a17484d
LP
2556 /* Check if valid UTF8 */
2557 if (!utf8_is_valid(s))
2558 return false;
2559
2560 return true;
de1c301e
LP
2561}
2562
9a17484d 2563static bool validate_signature(const char *s, size_t l) {
de1c301e 2564
ac89bf1d 2565 if (!validate_nul(s, l))
9a17484d 2566 return false;
de1c301e 2567
9a17484d
LP
2568 /* Check if valid signature */
2569 if (!signature_is_valid(s, true))
2570 return false;
2571
2572 return true;
2573}
2574
ac89bf1d
LP
2575static bool validate_object_path(const char *s, size_t l) {
2576
2577 if (!validate_nul(s, l))
2578 return false;
2579
2580 if (!object_path_is_valid(s))
2581 return false;
2582
2583 return true;
2584}
2585
d9f644e2 2586_public_ int sd_bus_message_read_basic(sd_bus_message *m, char type, void *p) {
9a17484d 2587 struct bus_container *c;
9a17484d 2588 void *q;
0dcd14b9 2589 int r;
9a17484d 2590
9d6c7c82
LP
2591 assert_return(m, -EINVAL);
2592 assert_return(m->sealed, -EPERM);
2593 assert_return(bus_type_is_basic(type), -EINVAL);
de1c301e 2594
7b058942 2595 if (message_end_of_signature(m))
430fb8fa 2596 return -ENXIO;
9a17484d 2597
1daf8121
LP
2598 if (message_end_of_array(m, m->rindex))
2599 return 0;
2600
7b058942 2601 c = message_get_container(m);
9a17484d
LP
2602 if (c->signature[c->index] != type)
2603 return -ENXIO;
2604
2605 switch (type) {
2606
2607 case SD_BUS_TYPE_STRING:
2608 case SD_BUS_TYPE_OBJECT_PATH: {
2609 uint32_t l;
2610 size_t rindex;
2611
2612 rindex = m->rindex;
2613 r = message_peek_body(m, &rindex, 4, 4, &q);
2614 if (r <= 0)
2615 return r;
2616
2617 l = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
2618 r = message_peek_body(m, &rindex, 1, l+1, &q);
de1c301e
LP
2619 if (r < 0)
2620 return r;
9a17484d
LP
2621 if (r == 0)
2622 return -EBADMSG;
2623
ac89bf1d
LP
2624 if (type == SD_BUS_TYPE_OBJECT_PATH) {
2625 if (!validate_object_path(q, l))
2626 return -EBADMSG;
2627 } else {
2628 if (!validate_string(q, l))
2629 return -EBADMSG;
2630 }
9a17484d
LP
2631
2632 m->rindex = rindex;
0dcd14b9
LP
2633 if (p)
2634 *(const char**) p = q;
2635
9a17484d 2636 break;
de1c301e
LP
2637 }
2638
9a17484d
LP
2639 case SD_BUS_TYPE_SIGNATURE: {
2640 uint8_t l;
2641 size_t rindex;
2642
2643 rindex = m->rindex;
2644 r = message_peek_body(m, &rindex, 1, 1, &q);
2645 if (r <= 0)
2646 return r;
2647
2648 l = *(uint8_t*) q;
2649 r = message_peek_body(m, &rindex, 1, l+1, &q);
de1c301e
LP
2650 if (r < 0)
2651 return r;
9a17484d
LP
2652 if (r == 0)
2653 return -EBADMSG;
2654
2655 if (!validate_signature(q, l))
2656 return -EBADMSG;
2657
2658 m->rindex = rindex;
0dcd14b9
LP
2659
2660 if (p)
2661 *(const char**) p = q;
9a17484d 2662 break;
de1c301e
LP
2663 }
2664
9a17484d 2665 default: {
27f6e5c7
ZJS
2666 ssize_t sz, align;
2667 size_t rindex;
de1c301e 2668
9a17484d
LP
2669 align = bus_type_get_alignment(type);
2670 sz = bus_type_get_size(type);
27f6e5c7 2671 assert(align > 0 && sz > 0);
de1c301e 2672
2c93b4ef
LP
2673 rindex = m->rindex;
2674 r = message_peek_body(m, &rindex, align, sz, &q);
9a17484d
LP
2675 if (r <= 0)
2676 return r;
2677
2678 switch (type) {
2679
2680 case SD_BUS_TYPE_BYTE:
0dcd14b9
LP
2681 if (p)
2682 *(uint8_t*) p = *(uint8_t*) q;
9a17484d
LP
2683 break;
2684
2685 case SD_BUS_TYPE_BOOLEAN:
0dcd14b9 2686 if (p)
102d8f81 2687 *(int*) p = !!*(uint32_t*) q;
9a17484d
LP
2688 break;
2689
2690 case SD_BUS_TYPE_INT16:
2691 case SD_BUS_TYPE_UINT16:
0dcd14b9
LP
2692 if (p)
2693 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
9a17484d
LP
2694 break;
2695
2696 case SD_BUS_TYPE_INT32:
2697 case SD_BUS_TYPE_UINT32:
0dcd14b9
LP
2698 if (p)
2699 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
9a17484d
LP
2700 break;
2701
2702 case SD_BUS_TYPE_INT64:
2703 case SD_BUS_TYPE_UINT64:
2704 case SD_BUS_TYPE_DOUBLE:
0dcd14b9
LP
2705 if (p)
2706 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
9a17484d
LP
2707 break;
2708
2c93b4ef 2709 case SD_BUS_TYPE_UNIX_FD: {
2c93b4ef
LP
2710 uint32_t j;
2711
2712 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
2713 if (j >= m->n_fds)
2714 return -EBADMSG;
2715
0dcd14b9
LP
2716 if (p)
2717 *(int*) p = m->fds[j];
2c93b4ef
LP
2718 break;
2719 }
2720
9a17484d
LP
2721 default:
2722 assert_not_reached("Unknown basic type...");
2723 }
2724
b3af9646 2725 m->rindex = rindex;
2c93b4ef 2726
9a17484d
LP
2727 break;
2728 }
2729 }
2730
2731 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2732 c->index++;
2733
2734 return 1;
de1c301e
LP
2735}
2736
9a17484d
LP
2737static int bus_message_enter_array(
2738 sd_bus_message *m,
2739 struct bus_container *c,
2740 const char *contents,
2741 uint32_t **array_size) {
2742
2743 size_t rindex;
2744 void *q;
2745 int r, alignment;
2746
2747 assert(m);
2748 assert(c);
2749 assert(contents);
2750 assert(array_size);
2751
29ddb38f 2752 if (!signature_is_single(contents, true))
de1c301e 2753 return -EINVAL;
9a17484d
LP
2754
2755 alignment = bus_type_get_alignment(contents[0]);
2756 if (alignment < 0)
2757 return alignment;
2758
2759 if (!c->signature || c->signature[c->index] == 0)
2760 return 0;
2761
2762 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
2763 return -ENXIO;
2764
2765 if (!startswith(c->signature + c->index + 1, contents))
2766 return -ENXIO;
2767
2768 rindex = m->rindex;
2769 r = message_peek_body(m, &rindex, 4, 4, &q);
2770 if (r <= 0)
2771 return r;
2772
ac89bf1d 2773 if (BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q) > BUS_ARRAY_MAX_SIZE)
80a46c73 2774 return -EBADMSG;
9a17484d
LP
2775
2776 r = message_peek_body(m, &rindex, alignment, 0, NULL);
2777 if (r < 0)
2778 return r;
2779 if (r == 0)
2780 return -EBADMSG;
2781
2782 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2783 c->index += 1 + strlen(contents);
2784
2785 m->rindex = rindex;
2786
2787 *array_size = (uint32_t*) q;
2788
2789 return 1;
2790}
2791
2792static int bus_message_enter_variant(
2793 sd_bus_message *m,
2794 struct bus_container *c,
2795 const char *contents) {
2796
2797 size_t rindex;
2798 uint8_t l;
2799 void *q;
2800 int r;
2801
2802 assert(m);
2803 assert(c);
2804 assert(contents);
2805
29ddb38f 2806 if (!signature_is_single(contents, false))
de1c301e 2807 return -EINVAL;
de1c301e 2808
9a17484d
LP
2809 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
2810 return -EINVAL;
2811
2812 if (!c->signature || c->signature[c->index] == 0)
2813 return 0;
2814
2815 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
2816 return -ENXIO;
2817
2818 rindex = m->rindex;
2819 r = message_peek_body(m, &rindex, 1, 1, &q);
2820 if (r <= 0)
2821 return r;
2822
2823 l = *(uint8_t*) q;
2824 r = message_peek_body(m, &rindex, 1, l+1, &q);
2825 if (r < 0)
2826 return r;
2827 if (r == 0)
2828 return -EBADMSG;
2829
2830 if (!validate_signature(q, l))
2831 return -EBADMSG;
2832
2833 if (!streq(q, contents))
2834 return -ENXIO;
2835
2836 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2837 c->index++;
2838
2839 m->rindex = rindex;
2840
2841 return 1;
de1c301e
LP
2842}
2843
9a17484d
LP
2844static int bus_message_enter_struct(
2845 sd_bus_message *m,
2846 struct bus_container *c,
2847 const char *contents) {
2848
2849 size_t l;
2850 int r;
2851
2852 assert(m);
2853 assert(c);
2854 assert(contents);
2855
2856 if (!signature_is_valid(contents, false))
2857 return -EINVAL;
2858
2859 if (!c->signature || c->signature[c->index] == 0)
2860 return 0;
2861
2862 l = strlen(contents);
2863
2864 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
2865 !startswith(c->signature + c->index + 1, contents) ||
2866 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
2867 return -ENXIO;
2868
2869 r = message_peek_body(m, &m->rindex, 8, 0, NULL);
2870 if (r <= 0)
2871 return r;
2872
2873 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2874 c->index += 1 + l + 1;
2875
2876 return 1;
2877}
2878
2879static int bus_message_enter_dict_entry(
2880 sd_bus_message *m,
2881 struct bus_container *c,
2882 const char *contents) {
2883
2884 size_t l;
2885 int r;
2886
2887 assert(m);
2888 assert(c);
2889 assert(contents);
2890
2891 if (!signature_is_pair(contents))
2892 return -EINVAL;
2893
2894 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2895 return -ENXIO;
2896
2897 if (!c->signature || c->signature[c->index] == 0)
2898 return 0;
2899
2900 l = strlen(contents);
2901
2902 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
2903 !startswith(c->signature + c->index + 1, contents) ||
2904 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
2905 return -ENXIO;
2906
2907 r = message_peek_body(m, &m->rindex, 8, 0, NULL);
2908 if (r <= 0)
2909 return r;
2910
2911 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2912 c->index += 1 + l + 1;
2913
2914 return 1;
2915}
2916
d9f644e2
ZJS
2917_public_ int sd_bus_message_enter_container(sd_bus_message *m,
2918 char type,
2919 const char *contents) {
9a17484d
LP
2920 struct bus_container *c, *w;
2921 uint32_t *array_size = NULL;
2922 char *signature;
b3af9646 2923 size_t before;
9a17484d
LP
2924 int r;
2925
275b39fe
LP
2926 assert_return(m, -EINVAL);
2927 assert_return(m->sealed, -EPERM);
2928 assert_return(type != 0 || !contents, -EINVAL);
2929
2930 if (type == 0 || !contents) {
2931 const char *cc;
2932 char tt;
2933
2934 /* Allow entering into anonymous containers */
2935 r = sd_bus_message_peek_type(m, &tt, &cc);
2936 if (r <= 0)
2937 return r;
2938
2939 if (type != 0 && type != tt)
2940 return -ENXIO;
2941
2942 if (contents && !streq(contents, cc))
2943 return -ENXIO;
2944
2945 type = tt;
2946 contents = cc;
2947 }
9a17484d 2948
ed205a6b
LP
2949 /*
2950 * We enforce a global limit on container depth, that is much
2951 * higher than the 32 structs and 32 arrays the specification
2952 * mandates. This is simpler to implement for us, and we need
2953 * this only to ensure our container array doesn't grow
2954 * without bounds. We are happy to return any data from a
2955 * message as long as the data itself is valid, even if the
2956 * overall message might be not.
2957 *
2958 * Note that the message signature is validated when
2959 * parsing the headers, and that validation does check the
2960 * 32/32 limit.
2961 *
2962 * Note that the specification defines no limits on the depth
2963 * of stacked variants, but we do.
2964 */
2965 if (m->n_containers >= BUS_CONTAINER_DEPTH)
2966 return -EBADMSG;
2967
9a17484d
LP
2968 w = realloc(m->containers, sizeof(struct bus_container) * (m->n_containers + 1));
2969 if (!w)
2970 return -ENOMEM;
2971 m->containers = w;
2972
7b058942 2973 if (message_end_of_signature(m))
430fb8fa 2974 return -ENXIO;
9a17484d 2975
1daf8121
LP
2976 if (message_end_of_array(m, m->rindex))
2977 return 0;
2978
7b058942
LP
2979 c = message_get_container(m);
2980
9a17484d
LP
2981 signature = strdup(contents);
2982 if (!signature)
2983 return -ENOMEM;
2984
b3af9646
LP
2985 c->saved_index = c->index;
2986 before = m->rindex;
2987
9a17484d
LP
2988 if (type == SD_BUS_TYPE_ARRAY)
2989 r = bus_message_enter_array(m, c, contents, &array_size);
2990 else if (type == SD_BUS_TYPE_VARIANT)
2991 r = bus_message_enter_variant(m, c, contents);
2992 else if (type == SD_BUS_TYPE_STRUCT)
2993 r = bus_message_enter_struct(m, c, contents);
2994 else if (type == SD_BUS_TYPE_DICT_ENTRY)
2995 r = bus_message_enter_dict_entry(m, c, contents);
2996 else
2997 r = -EINVAL;
2998
2999 if (r <= 0) {
3000 free(signature);
3001 return r;
3002 }
3003
3004 /* OK, let's fill it in */
3005 w += m->n_containers++;
3006 w->enclosing = type;
3007 w->signature = signature;
3008 w->index = 0;
3009 w->array_size = array_size;
b3af9646 3010 w->before = before;
9a17484d
LP
3011 w->begin = m->rindex;
3012
3013 return 1;
3014}
3015
d9f644e2 3016_public_ int sd_bus_message_exit_container(sd_bus_message *m) {
9a17484d
LP
3017 struct bus_container *c;
3018
9d6c7c82
LP
3019 assert_return(m, -EINVAL);
3020 assert_return(m->sealed, -EPERM);
3021 assert_return(m->n_containers > 0, -EINVAL);
9a17484d
LP
3022
3023 c = message_get_container(m);
3024 if (c->enclosing == SD_BUS_TYPE_ARRAY) {
3025 uint32_t l;
3026
3027 l = BUS_MESSAGE_BSWAP32(m, *c->array_size);
3028 if (c->begin + l != m->rindex)
3029 return -EBUSY;
3030
3031 } else {
3032 if (c->signature && c->signature[c->index] != 0)
3033 return -EINVAL;
3034 }
3035
3036 free(c->signature);
3037 m->n_containers--;
3038
3039 return 1;
3040}
3041
b3af9646
LP
3042static void message_quit_container(sd_bus_message *m) {
3043 struct bus_container *c;
3044
3045 assert(m);
3046 assert(m->sealed);
3047 assert(m->n_containers > 0);
3048
3049 c = message_get_container(m);
3050
3051 /* Undo seeks */
3052 assert(m->rindex >= c->before);
3053 m->rindex = c->before;
3054
3055 /* Free container */
3056 free(c->signature);
3057 m->n_containers--;
3058
3059 /* Correct index of new top-level container */
3060 c = message_get_container(m);
3061 c->index = c->saved_index;
3062}
3063
d9f644e2 3064_public_ int sd_bus_message_peek_type(sd_bus_message *m, char *type, const char **contents) {
9a17484d
LP
3065 struct bus_container *c;
3066 int r;
3067
c430fee6
LP
3068 assert_return(m, -EINVAL);
3069 assert_return(m->sealed, -EPERM);
9a17484d 3070
7b058942 3071 if (message_end_of_signature(m))
9a17484d
LP
3072 goto eof;
3073
3074 if (message_end_of_array(m, m->rindex))
3075 goto eof;
3076
7b058942
LP
3077 c = message_get_container(m);
3078
9a17484d
LP
3079 if (bus_type_is_basic(c->signature[c->index])) {
3080 if (contents)
3081 *contents = NULL;
3082 if (type)
3083 *type = c->signature[c->index];
3084 return 1;
3085 }
3086
3087 if (c->signature[c->index] == SD_BUS_TYPE_ARRAY) {
3088
3089 if (contents) {
3090 size_t l;
3091 char *sig;
3092
3093 r = signature_element_length(c->signature+c->index+1, &l);
3094 if (r < 0)
3095 return r;
3096
80a46c73
LP
3097 assert(l >= 1);
3098
9a17484d
LP
3099 sig = strndup(c->signature + c->index + 1, l);
3100 if (!sig)
3101 return -ENOMEM;
3102
3103 free(m->peeked_signature);
3104 m->peeked_signature = sig;
3105
3106 *contents = sig;
3107 }
3108
3109 if (type)
3110 *type = SD_BUS_TYPE_ARRAY;
3111
3112 return 1;
3113 }
3114
3115 if (c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ||
3116 c->signature[c->index] == SD_BUS_TYPE_DICT_ENTRY_BEGIN) {
3117
3118 if (contents) {
3119 size_t l;
3120 char *sig;
3121
3122 r = signature_element_length(c->signature+c->index, &l);
3123 if (r < 0)
3124 return r;
3125
3126 assert(l >= 2);
3127 sig = strndup(c->signature + c->index + 1, l - 2);
3128 if (!sig)
3129 return -ENOMEM;
3130
3131 free(m->peeked_signature);
3132 m->peeked_signature = sig;
3133
3134 *contents = sig;
3135 }
3136
3137 if (type)
3138 *type = c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY;
3139
3140 return 1;
3141 }
3142
3143 if (c->signature[c->index] == SD_BUS_TYPE_VARIANT) {
3144 if (contents) {
3145 size_t rindex, l;
3146 void *q;
3147
3148 rindex = m->rindex;
3149 r = message_peek_body(m, &rindex, 1, 1, &q);
3150 if (r < 0)
3151 return r;
3152 if (r == 0)
3153 goto eof;
3154
3155 l = *(uint8_t*) q;
3156 r = message_peek_body(m, &rindex, 1, l+1, &q);
3157 if (r < 0)
3158 return r;
3159 if (r == 0)
3160 return -EBADMSG;
3161
3162 if (!validate_signature(q, l))
3163 return -EBADMSG;
3164
3165 *contents = q;
3166 }
3167
3168 if (type)
3169 *type = SD_BUS_TYPE_VARIANT;
3170
3171 return 1;
3172 }
3173
3174 return -EINVAL;
3175
3176eof:
3177 if (type)
7b058942 3178 *type = 0;
9a17484d
LP
3179 if (contents)
3180 *contents = NULL;
3181 return 0;
3182}
3183
d9f644e2 3184_public_ int sd_bus_message_rewind(sd_bus_message *m, int complete) {
9a17484d
LP
3185 struct bus_container *c;
3186
9d6c7c82
LP
3187 assert_return(m, -EINVAL);
3188 assert_return(m->sealed, -EPERM);
9a17484d
LP
3189
3190 if (complete) {
bc7fd8cd 3191 message_reset_containers(m);
9a17484d
LP
3192 m->rindex = 0;
3193 m->root_container.index = 0;
3194
3195 c = message_get_container(m);
3196 } else {
3197 c = message_get_container(m);
3198
3199 c->index = 0;
3200 m->rindex = c->begin;
3201 }
3202
3203 return !isempty(c->signature);
3204}
1b492614
LP
3205static int message_read_ap(
3206 sd_bus_message *m,
3207 const char *types,
3208 va_list ap) {
9a17484d 3209
fe1d424d
LP
3210 unsigned n_array, n_struct;
3211 TypeStack stack[BUS_CONTAINER_DEPTH];
3212 unsigned stack_ptr = 0;
430fb8fa 3213 unsigned n_loop = 0;
9a17484d
LP
3214 int r;
3215
3216 assert(m);
1b492614 3217
430fb8fa 3218 if (isempty(types))
1b492614 3219 return 0;
9a17484d 3220
fe1d424d
LP
3221 /* Ideally, we'd just call ourselves recursively on every
3222 * complex type. However, the state of a va_list that is
3223 * passed to a function is undefined after that function
3224 * returns. This means we need to docode the va_list linearly
3225 * in a single stackframe. We hence implement our own
3226 * home-grown stack in an array. */
3227
430fb8fa
LP
3228 n_array = (unsigned) -1; /* lenght of current array entries */
3229 n_struct = strlen(types); /* length of current struct contents signature */
fe1d424d
LP
3230
3231 for (;;) {
3232 const char *t;
3233
430fb8fa
LP
3234 n_loop++;
3235
1b492614 3236 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
fe1d424d
LP
3237 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
3238 if (r < 0)
3239 return r;
3240 if (r == 0)
3241 break;
3242
3243 r = sd_bus_message_exit_container(m);
3244 if (r < 0)
3245 return r;
3246
3247 continue;
3248 }
3249
3250 t = types;
3251 if (n_array != (unsigned) -1)
3252 n_array --;
3253 else {
3254 types ++;
3255 n_struct--;
3256 }
3257
9a17484d
LP
3258 switch (*t) {
3259
3260 case SD_BUS_TYPE_BYTE:
3261 case SD_BUS_TYPE_BOOLEAN:
3262 case SD_BUS_TYPE_INT16:
3263 case SD_BUS_TYPE_UINT16:
3264 case SD_BUS_TYPE_INT32:
3265 case SD_BUS_TYPE_UINT32:
3266 case SD_BUS_TYPE_INT64:
3267 case SD_BUS_TYPE_UINT64:
3268 case SD_BUS_TYPE_DOUBLE:
3269 case SD_BUS_TYPE_STRING:
3270 case SD_BUS_TYPE_OBJECT_PATH:
2c93b4ef
LP
3271 case SD_BUS_TYPE_SIGNATURE:
3272 case SD_BUS_TYPE_UNIX_FD: {
9a17484d
LP
3273 void *p;
3274
3275 p = va_arg(ap, void*);
3276 r = sd_bus_message_read_basic(m, *t, p);
fe1d424d
LP
3277 if (r < 0)
3278 return r;
430fb8fa
LP
3279 if (r == 0) {
3280 if (n_loop <= 1)
3281 return 0;
3282
fe1d424d 3283 return -ENXIO;
430fb8fa 3284 }
fe1d424d 3285
9a17484d
LP
3286 break;
3287 }
3288
3289 case SD_BUS_TYPE_ARRAY: {
3290 size_t k;
3291
3292 r = signature_element_length(t + 1, &k);
3293 if (r < 0)
3294 return r;
3295
3296 {
9a17484d 3297 char s[k + 1];
9a17484d
LP
3298 memcpy(s, t + 1, k);
3299 s[k] = 0;
9a17484d
LP
3300
3301 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
3302 if (r < 0)
3303 return r;
430fb8fa
LP
3304 if (r == 0) {
3305 if (n_loop <= 1)
3306 return 0;
3307
9a17484d 3308 return -ENXIO;
430fb8fa 3309 }
fe1d424d 3310 }
9a17484d 3311
fe1d424d
LP
3312 if (n_array == (unsigned) -1) {
3313 types += k;
3314 n_struct -= k;
9a17484d
LP
3315 }
3316
fe1d424d
LP
3317 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
3318 if (r < 0)
3319 return r;
3320
3321 types = t + 1;
3322 n_struct = k;
3323 n_array = va_arg(ap, unsigned);
3324
9a17484d
LP
3325 break;
3326 }
3327
3328 case SD_BUS_TYPE_VARIANT: {
3329 const char *s;
3330
3331 s = va_arg(ap, const char *);
3332 if (!s)
3333 return -EINVAL;
3334
3335 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, s);
3336 if (r < 0)
3337 return r;
430fb8fa
LP
3338 if (r == 0) {
3339 if (n_loop <= 1)
3340 return 0;
3341
9a17484d 3342 return -ENXIO;
430fb8fa 3343 }
9a17484d 3344
fe1d424d 3345 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
9a17484d
LP
3346 if (r < 0)
3347 return r;
9a17484d 3348
fe1d424d
LP
3349 types = s;
3350 n_struct = strlen(s);
3351 n_array = (unsigned) -1;
3352
9a17484d
LP
3353 break;
3354 }
3355
3356 case SD_BUS_TYPE_STRUCT_BEGIN:
3357 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
3358 size_t k;
3359
3360 r = signature_element_length(t, &k);
3361 if (r < 0)
3362 return r;
3363
3364 {
3365 char s[k - 1];
3366 memcpy(s, t + 1, k - 2);
3367 s[k - 2] = 0;
3368
3369 r = sd_bus_message_enter_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
3370 if (r < 0)
3371 return r;
430fb8fa
LP
3372 if (r == 0) {
3373 if (n_loop <= 1)
3374 return 0;
9a17484d 3375 return -ENXIO;
430fb8fa 3376 }
fe1d424d 3377 }
9a17484d 3378
fe1d424d
LP
3379 if (n_array == (unsigned) -1) {
3380 types += k - 1;
3381 n_struct -= k - 1;
3382 }
9a17484d 3383
fe1d424d
LP
3384 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
3385 if (r < 0)
3386 return r;
9a17484d 3387
fe1d424d
LP
3388 types = t + 1;
3389 n_struct = k - 2;
3390 n_array = (unsigned) -1;
9a17484d
LP
3391
3392 break;
3393 }
3394
3395 default:
fe1d424d 3396 return -EINVAL;
9a17484d 3397 }
9a17484d
LP
3398 }
3399
3400 return 1;
3401}
3402
d9f644e2 3403_public_ int sd_bus_message_read(sd_bus_message *m, const char *types, ...) {
9a17484d
LP
3404 va_list ap;
3405 int r;
3406
9b07511d
LP
3407 assert_return(m, -EINVAL);
3408 assert_return(m->sealed, -EPERM);
3409 assert_return(types, -EINVAL);
9a17484d
LP
3410
3411 va_start(ap, types);
3412 r = message_read_ap(m, types, ap);
3413 va_end(ap);
3414
3415 return r;
3416}
3417
d9f644e2 3418_public_ int sd_bus_message_skip(sd_bus_message *m, const char *types) {
9b07511d
LP
3419 int r;
3420
3421 assert_return(m, -EINVAL);
3422 assert_return(m->sealed, -EPERM);
3423 assert_return(types, -EINVAL);
3424
3425 if (isempty(types))
3426 return 0;
3427
3428 switch (*types) {
3429
3430 case SD_BUS_TYPE_BYTE:
3431 case SD_BUS_TYPE_BOOLEAN:
3432 case SD_BUS_TYPE_INT16:
3433 case SD_BUS_TYPE_UINT16:
3434 case SD_BUS_TYPE_INT32:
3435 case SD_BUS_TYPE_UINT32:
3436 case SD_BUS_TYPE_INT64:
3437 case SD_BUS_TYPE_UINT64:
3438 case SD_BUS_TYPE_DOUBLE:
3439 case SD_BUS_TYPE_STRING:
3440 case SD_BUS_TYPE_OBJECT_PATH:
3441 case SD_BUS_TYPE_SIGNATURE:
3442 case SD_BUS_TYPE_UNIX_FD:
3443
3444 r = sd_bus_message_read_basic(m, *types, NULL);
3445 if (r <= 0)
3446 return r;
3447
3448 r = sd_bus_message_skip(m, types + 1);
3449 if (r < 0)
3450 return r;
3451
3452 return 1;
3453
3454 case SD_BUS_TYPE_ARRAY: {
3455 size_t k;
3456
3457 r = signature_element_length(types + 1, &k);
3458 if (r < 0)
3459 return r;
3460
3461 {
3462 char s[k+1];
3463 memcpy(s, types+1, k);
3464 s[k] = 0;
3465
3466 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
3467 if (r <= 0)
3468 return r;
3469
3470 for (;;) {
3471 r = sd_bus_message_skip(m, s);
3472 if (r < 0)
3473 return r;
3474 if (r == 0)
3475 break;
3476 }
3477
3478 r = sd_bus_message_exit_container(m);
3479 if (r < 0)
3480 return r;
3481 }
3482
3483 r = sd_bus_message_skip(m, types + 1 + k);
3484 if (r < 0)
3485 return r;
3486
3487 return 1;
3488 }
3489
3490 case SD_BUS_TYPE_VARIANT: {
3491 const char *contents;
3492 char x;
3493
3494 r = sd_bus_message_peek_type(m, &x, &contents);
3495 if (r <= 0)
3496 return r;
3497
3498 if (x != SD_BUS_TYPE_VARIANT)
3499 return -ENXIO;
3500
3501 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
3502 if (r <= 0)
3503 return r;
3504
3505 r = sd_bus_message_skip(m, contents);
3506 if (r < 0)
3507 return r;
3508 assert(r != 0);
3509
3510 r = sd_bus_message_exit_container(m);
3511 if (r < 0)
3512 return r;
3513
3514 r = sd_bus_message_skip(m, types + 1);
3515 if (r < 0)
3516 return r;
3517
3518 return 1;
3519 }
3520
3521 case SD_BUS_TYPE_STRUCT_BEGIN:
3522 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
3523 size_t k;
3524
3525 r = signature_element_length(types, &k);
3526 if (r < 0)
3527 return r;
3528
3529 {
3530 char s[k-1];
3531 memcpy(s, types+1, k-2);
3532 s[k-2] = 0;
3533
3534 r = sd_bus_message_enter_container(m, *types == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
3535 if (r <= 0)
3536 return r;
3537
3538 r = sd_bus_message_skip(m, s);
3539 if (r < 0)
3540 return r;
3541 assert(r != 0);
3542
3543 r = sd_bus_message_exit_container(m);
3544 if (r < 0)
3545 return r;
3546 }
3547
3548 r = sd_bus_message_skip(m, types + k);
3549 if (r < 0)
3550 return r;
3551
3552 return 1;
3553 }
3554
3555 default:
3556 return -EINVAL;
3557 }
3558}
3559
d9f644e2
ZJS
3560_public_ int sd_bus_message_read_array(sd_bus_message *m,
3561 char type,
3562 const void **ptr,
3563 size_t *size) {
b3af9646
LP
3564 struct bus_container *c;
3565 void *p;
3566 size_t sz;
3567 ssize_t align;
3568 int r;
3569
9d6c7c82
LP
3570 assert_return(m, -EINVAL);
3571 assert_return(m->sealed, -EPERM);
3572 assert_return(bus_type_is_trivial(type), -EINVAL);
3573 assert_return(ptr, -EINVAL);
3574 assert_return(size, -EINVAL);
3575 assert_return(!BUS_MESSAGE_NEED_BSWAP(m), -ENOTSUP);
b3af9646
LP
3576
3577 align = bus_type_get_alignment(type);
3578 if (align < 0)
3579 return align;
3580
3581 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
66b26c5c 3582 if (r <= 0)
b3af9646
LP
3583 return r;
3584
3585 c = message_get_container(m);
3586 sz = BUS_MESSAGE_BSWAP32(m, *c->array_size);
3587
3588 r = message_peek_body(m, &m->rindex, align, sz, &p);
3589 if (r < 0)
3590 goto fail;
3591 if (r == 0) {
3592 r = -EBADMSG;
3593 goto fail;
3594 }
3595
3596 r = sd_bus_message_exit_container(m);
3597 if (r < 0)
3598 goto fail;
3599
3600 *ptr = (const void*) p;
3601 *size = sz;
3602
3603 return 1;
3604
3605fail:
3606 message_quit_container(m);
3607 return r;
3608}
3609
80a46c73
LP
3610static int message_peek_fields(
3611 sd_bus_message *m,
3612 size_t *rindex,
3613 size_t align,
3614 size_t nbytes,
3615 void **ret) {
3616
3617 assert(m);
3618 assert(rindex);
3619 assert(align > 0);
3620
c91cb83c 3621 return buffer_peek(BUS_MESSAGE_FIELDS(m), BUS_MESSAGE_FIELDS_SIZE(m), rindex, align, nbytes, ret);
80a46c73
LP
3622}
3623
9f26c90c
LP
3624static int message_peek_field_uint32(
3625 sd_bus_message *m,
3626 size_t *ri,
3627 uint32_t *ret) {
3628
3629 int r;
3630 void *q;
3631
3632 assert(m);
3633 assert(ri);
3634
3635 r = message_peek_fields(m, ri, 4, 4, &q);
3636 if (r < 0)
3637 return r;
3638
3639 if (ret)
3640 *ret = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3641
3642 return 0;
3643}
3644
80a46c73
LP
3645static int message_peek_field_string(
3646 sd_bus_message *m,
6693860f 3647 bool (*validate)(const char *p),
80a46c73
LP
3648 size_t *ri,
3649 const char **ret) {
3650
9f26c90c 3651 uint32_t l;
80a46c73
LP
3652 int r;
3653 void *q;
3654
9a17484d 3655 assert(m);
80a46c73
LP
3656 assert(ri);
3657
9f26c90c 3658 r = message_peek_field_uint32(m, ri, &l);
80a46c73
LP
3659 if (r < 0)
3660 return r;
3661
80a46c73
LP
3662 r = message_peek_fields(m, ri, 1, l+1, &q);
3663 if (r < 0)
3664 return r;
9a17484d 3665
6693860f
LP
3666 if (validate) {
3667 if (!validate_nul(q, l))
3668 return -EBADMSG;
3669
3670 if (!validate(q))
ac89bf1d
LP
3671 return -EBADMSG;
3672 } else {
3673 if (!validate_string(q, l))
3674 return -EBADMSG;
3675 }
80a46c73
LP
3676
3677 if (ret)
3678 *ret = q;
3679
3680 return 0;
3681}
3682
3683static int message_peek_field_signature(
3684 sd_bus_message *m,
3685 size_t *ri,
3686 const char **ret) {
3687
3688 size_t l;
3689 int r;
3690 void *q;
3691
3692 assert(m);
3693 assert(ri);
3694
3695 r = message_peek_fields(m, ri, 1, 1, &q);
3696 if (r < 0)
3697 return r;
3698
3699 l = *(uint8_t*) q;
3700 r = message_peek_fields(m, ri, 1, l+1, &q);
3701 if (r < 0)
3702 return r;
3703
3704 if (!validate_signature(q, l))
3705 return -EBADMSG;
3706
3707 if (ret)
3708 *ret = q;
3709
3710 return 0;
3711}
3712
80a46c73
LP
3713static int message_skip_fields(
3714 sd_bus_message *m,
3715 size_t *ri,
3716 uint32_t array_size,
3717 const char **signature) {
3718
3719 size_t original_index;
3720 int r;
3721
3722 assert(m);
3723 assert(ri);
3724 assert(signature);
3725
3726 original_index = *ri;
3727
3728 for (;;) {
3729 char t;
80a46c73
LP
3730 size_t l;
3731
3732 if (array_size != (uint32_t) -1 &&
3733 array_size <= *ri - original_index)
3734 return 0;
3735
3736 t = **signature;
3737 if (!t)
3738 return 0;
3739
6693860f
LP
3740 if (t == SD_BUS_TYPE_STRING) {
3741
3742 r = message_peek_field_string(m, NULL, ri, NULL);
3743 if (r < 0)
3744 return r;
3745
3746 (*signature)++;
3747
3748 } else if (t == SD_BUS_TYPE_OBJECT_PATH) {
80a46c73 3749
6693860f 3750 r = message_peek_field_string(m, object_path_is_valid, ri, NULL);
80a46c73
LP
3751 if (r < 0)
3752 return r;
3753
3754 (*signature)++;
3755
3756 } else if (t == SD_BUS_TYPE_SIGNATURE) {
3757
3758 r = message_peek_field_signature(m, ri, NULL);
3759 if (r < 0)
3760 return r;
3761
3762 (*signature)++;
3763
3764 } else if (bus_type_is_basic(t)) {
27f6e5c7 3765 ssize_t align, k;
80a46c73 3766
c66a2e0c
TG
3767 align = bus_type_get_alignment(t);
3768 k = bus_type_get_size(t);
27f6e5c7 3769 assert(align > 0 && k > 0);
80a46c73
LP
3770
3771 r = message_peek_fields(m, ri, align, k, NULL);
3772 if (r < 0)
3773 return r;
9a17484d 3774
80a46c73
LP
3775 (*signature)++;
3776
3777 } else if (t == SD_BUS_TYPE_ARRAY) {
3778
3779 r = signature_element_length(*signature+1, &l);
3780 if (r < 0)
3781 return r;
3782
3783 assert(l >= 1);
3784 {
3785 char sig[l-1], *s;
9f26c90c 3786 uint32_t nas;
80a46c73
LP
3787 int alignment;
3788
3789 strncpy(sig, *signature + 1, l-1);
3790 s = sig;
3791
3792 alignment = bus_type_get_alignment(sig[0]);
3793 if (alignment < 0)
3794 return alignment;
3795
9f26c90c 3796 r = message_peek_field_uint32(m, ri, &nas);
80a46c73
LP
3797 if (r < 0)
3798 return r;
ac89bf1d 3799 if (nas > BUS_ARRAY_MAX_SIZE)
80a46c73
LP
3800 return -EBADMSG;
3801
3802 r = message_peek_fields(m, ri, alignment, 0, NULL);
3803 if (r < 0)
3804 return r;
3805
3806 r = message_skip_fields(m, ri, nas, (const char**) &s);
3807 if (r < 0)
3808 return r;
3809 }
3810
3811 (*signature) += 1 + l;
3812
3813 } else if (t == SD_BUS_TYPE_VARIANT) {
3814 const char *s;
3815
3816 r = message_peek_field_signature(m, ri, &s);
3817 if (r < 0)
3818 return r;
3819
3820 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
3821 if (r < 0)
3822 return r;
3823
3824 (*signature)++;
3825
3826 } else if (t == SD_BUS_TYPE_STRUCT ||
3827 t == SD_BUS_TYPE_DICT_ENTRY) {
3828
3829 r = signature_element_length(*signature, &l);
3830 if (r < 0)
3831 return r;
3832
3833 assert(l >= 2);
3834 {
3835 char sig[l-1], *s;
3836 strncpy(sig, *signature + 1, l-1);
3837 s = sig;
3838
3839 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
3840 if (r < 0)
3841 return r;
3842 }
3843
3844 *signature += l;
3845 } else
3846 return -EINVAL;
3847 }
3848}
3849
6629161f 3850int bus_message_parse_fields(sd_bus_message *m) {
80a46c73
LP
3851 size_t ri;
3852 int r;
2c93b4ef 3853 uint32_t unix_fds = 0;
80a46c73
LP
3854
3855 assert(m);
3856
3857 for (ri = 0; ri < BUS_MESSAGE_FIELDS_SIZE(m); ) {
3858 const char *signature;
3859 uint8_t *header;
3860
3861 r = message_peek_fields(m, &ri, 8, 1, (void**) &header);
3862 if (r < 0)
3863 return r;
3864
3865 r = message_peek_field_signature(m, &ri, &signature);
3866 if (r < 0)
3867 return r;
3868
3869 switch (*header) {
3870 case _SD_BUS_MESSAGE_HEADER_INVALID:
3871 return -EBADMSG;
3872
3873 case SD_BUS_MESSAGE_HEADER_PATH:
2c93b4ef
LP
3874
3875 if (m->path)
3876 return -EBADMSG;
3877
80a46c73
LP
3878 if (!streq(signature, "o"))
3879 return -EBADMSG;
3880
6693860f 3881 r = message_peek_field_string(m, object_path_is_valid, &ri, &m->path);
80a46c73
LP
3882 break;
3883
3884 case SD_BUS_MESSAGE_HEADER_INTERFACE:
2c93b4ef
LP
3885
3886 if (m->interface)
3887 return -EBADMSG;
3888
80a46c73
LP
3889 if (!streq(signature, "s"))
3890 return -EBADMSG;
3891
6693860f 3892 r = message_peek_field_string(m, interface_name_is_valid, &ri, &m->interface);
80a46c73
LP
3893 break;
3894
3895 case SD_BUS_MESSAGE_HEADER_MEMBER:
2c93b4ef
LP
3896
3897 if (m->member)
3898 return -EBADMSG;
3899
80a46c73
LP
3900 if (!streq(signature, "s"))
3901 return -EBADMSG;
3902
6693860f 3903 r = message_peek_field_string(m, member_name_is_valid, &ri, &m->member);
80a46c73
LP
3904 break;
3905
3906 case SD_BUS_MESSAGE_HEADER_ERROR_NAME:
2c93b4ef
LP
3907
3908 if (m->error.name)
3909 return -EBADMSG;
3910
80a46c73
LP
3911 if (!streq(signature, "s"))
3912 return -EBADMSG;
3913
6693860f 3914 r = message_peek_field_string(m, error_name_is_valid, &ri, &m->error.name);
80a46c73
LP
3915 break;
3916
3917 case SD_BUS_MESSAGE_HEADER_DESTINATION:
2c93b4ef
LP
3918
3919 if (m->destination)
3920 return -EBADMSG;
3921
80a46c73
LP
3922 if (!streq(signature, "s"))
3923 return -EBADMSG;
3924
6693860f 3925 r = message_peek_field_string(m, service_name_is_valid, &ri, &m->destination);
80a46c73
LP
3926 break;
3927
3928 case SD_BUS_MESSAGE_HEADER_SENDER:
2c93b4ef
LP
3929
3930 if (m->sender)
3931 return -EBADMSG;
3932
80a46c73
LP
3933 if (!streq(signature, "s"))
3934 return -EBADMSG;
3935
6693860f 3936 r = message_peek_field_string(m, service_name_is_valid, &ri, &m->sender);
80a46c73
LP
3937 break;
3938
3939
3940 case SD_BUS_MESSAGE_HEADER_SIGNATURE: {
3941 const char *s;
3942 char *c;
3943
2c93b4ef
LP
3944 if (m->root_container.signature)
3945 return -EBADMSG;
3946
80a46c73
LP
3947 if (!streq(signature, "g"))
3948 return -EBADMSG;
3949
3950 r = message_peek_field_signature(m, &ri, &s);
3951 if (r < 0)
3952 return r;
3953
3954 c = strdup(s);
3955 if (!c)
3956 return -ENOMEM;
3957
3958 free(m->root_container.signature);
3959 m->root_container.signature = c;
80a46c73
LP
3960 break;
3961 }
3962
3963 case SD_BUS_MESSAGE_HEADER_REPLY_SERIAL:
2c93b4ef
LP
3964 if (m->reply_serial != 0)
3965 return -EBADMSG;
3966
80a46c73
LP
3967 if (!streq(signature, "u"))
3968 return -EBADMSG;
3969
3970 r = message_peek_field_uint32(m, &ri, &m->reply_serial);
6693860f
LP
3971 if (r < 0)
3972 return r;
3973
3974 if (m->reply_serial == 0)
3975 return -EBADMSG;
3976
80a46c73
LP
3977 break;
3978
2c93b4ef
LP
3979 case SD_BUS_MESSAGE_HEADER_UNIX_FDS:
3980 if (unix_fds != 0)
3981 return -EBADMSG;
3982
3983 if (!streq(signature, "u"))
3984 return -EBADMSG;
3985
3986 r = message_peek_field_uint32(m, &ri, &unix_fds);
3987 if (r < 0)
3988 return -EBADMSG;
3989
3990 if (unix_fds == 0)
3991 return -EBADMSG;
3992
3993 break;
3994
80a46c73
LP
3995 default:
3996 r = message_skip_fields(m, &ri, (uint32_t) -1, (const char **) &signature);
3997 }
3998
3999 if (r < 0)
4000 return r;
4001 }
4002
2c93b4ef
LP
4003 if (m->n_fds != unix_fds)
4004 return -EBADMSG;
4005
80a46c73
LP
4006 if (isempty(m->root_container.signature) != (BUS_MESSAGE_BODY_SIZE(m) == 0))
4007 return -EBADMSG;
4008
4009 switch (m->header->type) {
4010
40ca29a1 4011 case SD_BUS_MESSAGE_SIGNAL:
80a46c73
LP
4012 if (!m->path || !m->interface || !m->member)
4013 return -EBADMSG;
4014 break;
4015
40ca29a1 4016 case SD_BUS_MESSAGE_METHOD_CALL:
80a46c73
LP
4017
4018 if (!m->path || !m->member)
4019 return -EBADMSG;
4020
4021 break;
4022
40ca29a1 4023 case SD_BUS_MESSAGE_METHOD_RETURN:
80a46c73
LP
4024
4025 if (m->reply_serial == 0)
4026 return -EBADMSG;
4027 break;
4028
40ca29a1 4029 case SD_BUS_MESSAGE_METHOD_ERROR:
80a46c73
LP
4030
4031 if (m->reply_serial == 0 || !m->error.name)
4032 return -EBADMSG;
4033 break;
4034 }
9a17484d 4035
89ffcd2a 4036 /* Try to read the error message, but if we can't it's a non-issue */
40ca29a1 4037 if (m->header->type == SD_BUS_MESSAGE_METHOD_ERROR)
89ffcd2a
LP
4038 sd_bus_message_read(m, "s", &m->error.message);
4039
9a17484d
LP
4040 return 0;
4041}
4042
9a17484d 4043int bus_message_seal(sd_bus_message *m, uint64_t serial) {
47e6ce32 4044 struct bus_body_part *part;
69aec65c 4045 size_t l, a;
47e6ce32
LP
4046 unsigned i;
4047 int r;
9a17484d
LP
4048
4049 assert(m);
4050
4051 if (m->sealed)
4052 return -EPERM;
4053
4054 if (m->n_containers > 0)
4055 return -EBADMSG;
4056
13c299d3
LP
4057 if (m->poisoned)
4058 return -ESTALE;
4059
9a17484d
LP
4060 /* If there's a non-trivial signature set, then add it in here */
4061 if (!isempty(m->root_container.signature)) {
80a46c73 4062 r = message_append_field_signature(m, SD_BUS_MESSAGE_HEADER_SIGNATURE, m->root_container.signature, NULL);
9a17484d
LP
4063 if (r < 0)
4064 return r;
4065 }
4066
4067 if (m->n_fds > 0) {
4068 r = message_append_field_uint32(m, SD_BUS_MESSAGE_HEADER_UNIX_FDS, m->n_fds);
4069 if (r < 0)
4070 return r;
4071 }
4072
66b26c5c
LP
4073 /* Add padding at the end of the fields part, since we know
4074 * the body needs to start at an 8 byte alignment. We made
4075 * sure we allocated enough space for this, so all we need to
4076 * do here is to zero it out. */
69aec65c
LP
4077 l = BUS_MESSAGE_FIELDS_SIZE(m);
4078 a = ALIGN8(l) - l;
c91cb83c
LP
4079 if (a > 0)
4080 memset((uint8_t*) BUS_MESSAGE_FIELDS(m) + l, 0, a);
69aec65c 4081
66b26c5c
LP
4082 /* If this is something we can send as memfd, then let's seal
4083 the memfd now. Note that we can send memfds as payload only
4084 for directed messages, and not for broadcasts. */
8f155917 4085 if (m->destination && m->bus && m->bus->use_memfd) {
66b26c5c 4086 MESSAGE_FOREACH_PART(part, i, m)
8f155917 4087 if (part->memfd >= 0 && !part->sealed && (part->size > MEMFD_MIN_SIZE || m->bus->use_memfd < 0)) {
66b26c5c 4088 bus_body_part_unmap(part);
a392d361 4089
66b26c5c
LP
4090 if (ioctl(part->memfd, KDBUS_CMD_MEMFD_SEAL_SET, 1) >= 0)
4091 part->sealed = true;
4092 }
4093 }
47e6ce32 4094
9a17484d
LP
4095 m->header->serial = serial;
4096 m->sealed = true;
4097
9a17484d
LP
4098 return 0;
4099}
4100
d9f644e2 4101_public_ int sd_bus_message_set_destination(sd_bus_message *m, const char *destination) {
9d6c7c82
LP
4102 assert_return(m, -EINVAL);
4103 assert_return(destination, -EINVAL);
4104 assert_return(!m->sealed, -EPERM);
4105 assert_return(!m->destination, -EEXIST);
9a17484d
LP
4106
4107 return message_append_field_string(m, SD_BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &m->destination);
4108}
4109
c430fee6 4110int bus_message_dump(sd_bus_message *m, FILE *f, bool with_header) {
d8d3d8a7 4111 const char *u = NULL, *uu = NULL, *s = NULL;
77930f11 4112 char **cmdline = NULL;
9a17484d
LP
4113 unsigned level = 1;
4114 int r;
120f919e
LP
4115 uid_t owner, audit_loginuid;
4116 uint32_t audit_sessionid;
9a17484d
LP
4117
4118 assert(m);
4119
c430fee6
LP
4120 if (!f)
4121 f = stdout;
4122
4123 if (with_header) {
4124 fprintf(f,
4125 "Message %p\n"
4126 "\tn_ref=%u\n"
4127 "\tendian=%c\n"
4128 "\ttype=%i\n"
4129 "\tflags=%u\n"
4130 "\tversion=%u\n"
4131 "\tserial=%u\n"
4132 "\tfields_size=%u\n"
4133 "\tbody_size=%u\n"
4134 "\tpath=%s\n"
4135 "\tinterface=%s\n"
4136 "\tmember=%s\n"
4137 "\tdestination=%s\n"
4138 "\tsender=%s\n"
4139 "\tsignature=%s\n"
4140 "\treply_serial=%u\n"
c430fee6
LP
4141 "\tsealed=%s\n"
4142 "\tn_body_parts=%u\n",
4143 m,
4144 m->n_ref,
4145 m->header->endian,
4146 m->header->type,
4147 m->header->flags,
4148 m->header->version,
4149 BUS_MESSAGE_SERIAL(m),
4150 BUS_MESSAGE_FIELDS_SIZE(m),
4151 BUS_MESSAGE_BODY_SIZE(m),
4152 strna(m->path),
4153 strna(m->interface),
4154 strna(m->member),
4155 strna(m->destination),
4156 strna(m->sender),
4157 strna(m->root_container.signature),
4158 m->reply_serial,
c430fee6
LP
4159 yes_no(m->sealed),
4160 m->n_body_parts);
4161
3fc047f4
LP
4162 if (sd_bus_error_is_set(&m->error))
4163 fprintf(f,
4164 "\terror.name=%s\n"
4165 "\terror.message=%s\n",
4166 strna(m->error.name),
4167 strna(m->error.message));
4168
c430fee6
LP
4169 if (m->pid != 0)
4170 fprintf(f, "\tpid=%lu\n", (unsigned long) m->pid);
4171 if (m->tid != 0)
4172 fprintf(f, "\ttid=%lu\n", (unsigned long) m->tid);
4173 if (m->uid_valid)
4174 fprintf(f, "\tuid=%lu\n", (unsigned long) m->uid);
4175 if (m->gid_valid)
4176 fprintf(f, "\tgid=%lu\n", (unsigned long) m->gid);
4177 if (m->pid_starttime != 0)
4178 fprintf(f, "\tpid_starttime=%llu\n", (unsigned long long) m->pid_starttime);
4179 if (m->monotonic != 0)
4180 fprintf(f, "\tmonotonic=%llu\n", (unsigned long long) m->monotonic);
4181 if (m->realtime != 0)
4182 fprintf(f, "\trealtime=%llu\n", (unsigned long long) m->realtime);
4183 if (m->exe)
4184 fprintf(f, "\texe=[%s]\n", m->exe);
4185 if (m->comm)
4186 fprintf(f, "\tcomm=[%s]\n", m->comm);
4187 if (m->tid_comm)
4188 fprintf(f, "\ttid_comm=[%s]\n", m->tid_comm);
4189 if (m->label)
4190 fprintf(f, "\tlabel=[%s]\n", m->label);
4191 if (m->cgroup)
4192 fprintf(f, "\tcgroup=[%s]\n", m->cgroup);
4193
4194 sd_bus_message_get_unit(m, &u);
4195 if (u)
4196 fprintf(f, "\tunit=[%s]\n", u);
4197 sd_bus_message_get_user_unit(m, &uu);
4198 if (uu)
4199 fprintf(f, "\tuser_unit=[%s]\n", uu);
4200 sd_bus_message_get_session(m, &s);
4201 if (s)
4202 fprintf(f, "\tsession=[%s]\n", s);
4203 if (sd_bus_message_get_owner_uid(m, &owner) >= 0)
4204 fprintf(f, "\towner_uid=%lu\n", (unsigned long) owner);
4205 if (sd_bus_message_get_audit_loginuid(m, &audit_loginuid) >= 0)
4206 fprintf(f, "\taudit_loginuid=%lu\n", (unsigned long) audit_loginuid);
4207 if (sd_bus_message_get_audit_sessionid(m, &audit_sessionid) >= 0)
4208 fprintf(f, "\taudit_sessionid=%lu\n", (unsigned long) audit_sessionid);
4209
3fc047f4
LP
4210 r = sd_bus_message_has_effective_cap(m, 5);
4211 if (r >= 0)
4212 fprintf(f, "\tCAP_KILL=%s\n", yes_no(r));
c430fee6
LP
4213
4214 if (sd_bus_message_get_cmdline(m, &cmdline) >= 0) {
4215 char **c;
4216
4217 fputs("\tcmdline=[", f);
4218 STRV_FOREACH(c, cmdline) {
4219 if (c != cmdline)
4220 fputc(' ', f);
4221
4222 fputs(*c, f);
4223 }
77930f11 4224
c430fee6
LP
4225 fputs("]\n", f);
4226 }
77930f11
LP
4227 }
4228
9a17484d
LP
4229 r = sd_bus_message_rewind(m, true);
4230 if (r < 0) {
4231 log_error("Failed to rewind: %s", strerror(-r));
4232 return r;
4233 }
4234
c430fee6 4235 fprintf(f, "BEGIN_MESSAGE \"%s\" {\n", strempty(m->root_container.signature));
9a17484d
LP
4236
4237 for(;;) {
4238 _cleanup_free_ char *prefix = NULL;
4239 const char *contents = NULL;
4240 char type;
4241 union {
4242 uint8_t u8;
4243 uint16_t u16;
4244 int16_t s16;
4245 uint32_t u32;
4246 int32_t s32;
4247 uint64_t u64;
4248 int64_t s64;
4249 double d64;
4250 const char *string;
4251 int i;
4252 } basic;
4253
4254 r = sd_bus_message_peek_type(m, &type, &contents);
4255 if (r < 0) {
4256 log_error("Failed to peek type: %s", strerror(-r));
4257 return r;
4258 }
4259 if (r == 0) {
4260 if (level <= 1)
4261 break;
4262
4263 r = sd_bus_message_exit_container(m);
4264 if (r < 0) {
4265 log_error("Failed to exit container: %s", strerror(-r));
4266 return r;
4267 }
4268
4269 level--;
4270
4271 prefix = strrep("\t", level);
4272 if (!prefix)
4273 return log_oom();
4274
4275 if (type == SD_BUS_TYPE_ARRAY)
c430fee6 4276 fprintf(f, "%s} END_ARRAY \n", prefix);
9a17484d 4277 else if (type == SD_BUS_TYPE_VARIANT)
c430fee6 4278 fprintf(f, "%s} END_VARIANT\n", prefix);
9a17484d 4279 else if (type == SD_BUS_TYPE_STRUCT)
c430fee6 4280 fprintf(f, "%s} END_STRUCT\n", prefix);
9a17484d 4281 else if (type == SD_BUS_TYPE_DICT_ENTRY)
c430fee6 4282 fprintf(f, "%s} END_DICT_ENTRY\n", prefix);
9a17484d
LP
4283
4284 continue;
4285 }
4286
4287 prefix = strrep("\t", level);
4288 if (!prefix)
4289 return log_oom();
4290
4291 if (bus_type_is_container(type) > 0) {
4292 r = sd_bus_message_enter_container(m, type, contents);
4293 if (r < 0) {
4294 log_error("Failed to enter container: %s", strerror(-r));
4295 return r;
4296 }
4297
4298 if (type == SD_BUS_TYPE_ARRAY)
c430fee6 4299 fprintf(f, "%sBEGIN_ARRAY \"%s\" {\n", prefix, contents);
9a17484d 4300 else if (type == SD_BUS_TYPE_VARIANT)
c430fee6 4301 fprintf(f, "%sBEGIN_VARIANT \"%s\" {\n", prefix, contents);
9a17484d 4302 else if (type == SD_BUS_TYPE_STRUCT)
c430fee6 4303 fprintf(f, "%sBEGIN_STRUCT \"%s\" {\n", prefix, contents);
9a17484d 4304 else if (type == SD_BUS_TYPE_DICT_ENTRY)
c430fee6 4305 fprintf(f, "%sBEGIN_DICT_ENTRY \"%s\" {\n", prefix, contents);
9a17484d
LP
4306
4307 level ++;
4308
4309 continue;
4310 }
4311
4312 r = sd_bus_message_read_basic(m, type, &basic);
4313 if (r < 0) {
4314 log_error("Failed to get basic: %s", strerror(-r));
4315 return r;
4316 }
4317
c430fee6
LP
4318 assert(r > 0);
4319
9a17484d
LP
4320 switch (type) {
4321
4322 case SD_BUS_TYPE_BYTE:
c430fee6 4323 fprintf(f, "%sBYTE: %u\n", prefix, basic.u8);
9a17484d
LP
4324 break;
4325
4326 case SD_BUS_TYPE_BOOLEAN:
c430fee6 4327 fprintf(f, "%sBOOLEAN: %s\n", prefix, yes_no(basic.i));
9a17484d
LP
4328 break;
4329
4330 case SD_BUS_TYPE_INT16:
c430fee6 4331 fprintf(f, "%sINT16: %i\n", prefix, basic.s16);
9a17484d
LP
4332 break;
4333
4334 case SD_BUS_TYPE_UINT16:
c430fee6 4335 fprintf(f, "%sUINT16: %u\n", prefix, basic.u16);
9a17484d
LP
4336 break;
4337
4338 case SD_BUS_TYPE_INT32:
c430fee6 4339 fprintf(f, "%sINT32: %i\n", prefix, basic.s32);
9a17484d
LP
4340 break;
4341
4342 case SD_BUS_TYPE_UINT32:
c430fee6 4343 fprintf(f, "%sUINT32: %u\n", prefix, basic.u32);
9a17484d
LP
4344 break;
4345
4346 case SD_BUS_TYPE_INT64:
c430fee6 4347 fprintf(f, "%sINT64: %lli\n", prefix, (long long) basic.s64);
9a17484d
LP
4348 break;
4349
4350 case SD_BUS_TYPE_UINT64:
c430fee6 4351 fprintf(f, "%sUINT64: %llu\n", prefix, (unsigned long long) basic.u64);
9a17484d
LP
4352 break;
4353
4354 case SD_BUS_TYPE_DOUBLE:
c430fee6 4355 fprintf(f, "%sDOUBLE: %g\n", prefix, basic.d64);
9a17484d
LP
4356 break;
4357
4358 case SD_BUS_TYPE_STRING:
c430fee6 4359 fprintf(f, "%sSTRING: \"%s\"\n", prefix, basic.string);
9a17484d
LP
4360 break;
4361
4362 case SD_BUS_TYPE_OBJECT_PATH:
c430fee6 4363 fprintf(f, "%sOBJECT_PATH: \"%s\"\n", prefix, basic.string);
9a17484d
LP
4364 break;
4365
4366 case SD_BUS_TYPE_SIGNATURE:
c430fee6 4367 fprintf(f, "%sSIGNATURE: \"%s\"\n", prefix, basic.string);
9a17484d
LP
4368 break;
4369
4370 case SD_BUS_TYPE_UNIX_FD:
c430fee6 4371 fprintf(f, "%sUNIX_FD: %i\n", prefix, basic.i);
9a17484d
LP
4372 break;
4373
4374 default:
4375 assert_not_reached("Unknown basic type.");
4376 }
4377 }
4378
c430fee6 4379 fprintf(f, "} END_MESSAGE\n");
9a17484d 4380 return 0;
de1c301e
LP
4381}
4382
4383int bus_message_get_blob(sd_bus_message *m, void **buffer, size_t *sz) {
4384 size_t total;
de1c301e 4385 void *p, *e;
bc7fd8cd
LP
4386 unsigned i;
4387 struct bus_body_part *part;
de1c301e
LP
4388
4389 assert(m);
4390 assert(buffer);
4391 assert(sz);
4392
6629161f 4393 total = BUS_MESSAGE_SIZE(m);
de1c301e
LP
4394
4395 p = malloc(total);
4396 if (!p)
4397 return -ENOMEM;
4398
c91cb83c 4399 e = mempcpy(p, m->header, BUS_MESSAGE_BODY_BEGIN(m));
9b29bb68 4400 MESSAGE_FOREACH_PART(part, i, m)
bc7fd8cd 4401 e = mempcpy(e, part->data, part->size);
2100fa10
LP
4402
4403 assert(total == (size_t) ((uint8_t*) e - (uint8_t*) p));
de1c301e
LP
4404
4405 *buffer = p;
4406 *sz = total;
4407
4408 return 0;
4409}
89ffcd2a
LP
4410
4411int bus_message_read_strv_extend(sd_bus_message *m, char ***l) {
4412 int r;
4413
4414 assert(m);
4415 assert(l);
4416
4417 r = sd_bus_message_enter_container(m, 'a', "s");
4686d1b6 4418 if (r <= 0)
89ffcd2a
LP
4419 return r;
4420
4421 for (;;) {
4422 const char *s;
4423
4424 r = sd_bus_message_read_basic(m, 's', &s);
4425 if (r < 0)
4426 return r;
4427 if (r == 0)
4428 break;
4429
4430 r = strv_extend(l, s);
4431 if (r < 0)
4432 return r;
4433 }
4434
4435 r = sd_bus_message_exit_container(m);
4436 if (r < 0)
4437 return r;
4438
4439 return 0;
4440}
392d5b37 4441
ba341e7c 4442_public_ int sd_bus_message_read_strv(sd_bus_message *m, char ***l) {
4686d1b6
MAP
4443 char **strv = NULL;
4444 int r;
4445
4446 assert_return(m, -EINVAL);
4447 assert_return(m->sealed, -EPERM);
4448 assert_return(l, -EINVAL);
4449
4450 r = bus_message_read_strv_extend(m, &strv);
4451 if (r <= 0) {
4452 strv_free(strv);
4453 return r;
4454 }
4455
4456 *l = strv;
4457 return 1;
4458}
4459
392d5b37
LP
4460const char* bus_message_get_arg(sd_bus_message *m, unsigned i) {
4461 int r;
42c5aaf3
LP
4462 const char *t = NULL;
4463 unsigned j;
392d5b37
LP
4464
4465 assert(m);
4466
4467 r = sd_bus_message_rewind(m, true);
4468 if (r < 0)
4469 return NULL;
4470
42c5aaf3
LP
4471 for (j = 0; j <= i; j++) {
4472 char type;
4473
392d5b37
LP
4474 r = sd_bus_message_peek_type(m, &type, NULL);
4475 if (r < 0)
4476 return NULL;
4477
4478 if (type != SD_BUS_TYPE_STRING &&
4479 type != SD_BUS_TYPE_OBJECT_PATH &&
4480 type != SD_BUS_TYPE_SIGNATURE)
4481 return NULL;
4482
4483 r = sd_bus_message_read_basic(m, type, &t);
4484 if (r < 0)
4485 return NULL;
392d5b37
LP
4486 }
4487
392d5b37
LP
4488 return t;
4489}
2100fa10 4490
c91cb83c
LP
4491bool bus_header_is_complete(struct bus_header *h, size_t size) {
4492 size_t full;
4493
4494 assert(h);
4495 assert(size);
4496
4497 if (size < sizeof(struct bus_header))
4498 return false;
4499
4500 full = sizeof(struct bus_header) +
4501 (h->endian == SD_BUS_NATIVE_ENDIAN ? h->fields_size : bswap_32(h->fields_size));
4502
4503 return size >= full;
4504}
4505
4506int bus_header_message_size(struct bus_header *h, size_t *sum) {
6629161f
LP
4507 size_t fs, bs;
4508
4509 assert(h);
4510 assert(sum);
4511
4512 if (h->endian == SD_BUS_NATIVE_ENDIAN) {
4513 fs = h->fields_size;
4514 bs = h->body_size;
4515 } else if (h->endian == SD_BUS_REVERSE_ENDIAN) {
4516 fs = bswap_32(h->fields_size);
4517 bs = bswap_32(h->body_size);
4518 } else
4519 return -EBADMSG;
2100fa10 4520
6629161f
LP
4521 *sum = sizeof(struct bus_header) + ALIGN8(fs) + bs;
4522 return 0;
2100fa10 4523}
eb01ba5d 4524
d9f644e2 4525_public_ int sd_bus_message_get_errno(sd_bus_message *m) {
40ca29a1 4526 assert_return(m, -EINVAL);
eb01ba5d 4527
40ca29a1 4528 if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
eb01ba5d
LP
4529 return 0;
4530
40ca29a1 4531 return sd_bus_error_get_errno(&m->error);
eb01ba5d 4532}
29ddb38f 4533
d9f644e2 4534_public_ const char* sd_bus_message_get_signature(sd_bus_message *m, int complete) {
29ddb38f
LP
4535 struct bus_container *c;
4536
9d6c7c82 4537 assert_return(m, NULL);
29ddb38f
LP
4538
4539 c = complete ? &m->root_container : message_get_container(m);
40ca29a1 4540 return c->signature ?: "";
29ddb38f 4541}
c430fee6 4542
d9f644e2 4543_public_ int sd_bus_message_copy(sd_bus_message *m, sd_bus_message *source, int all) {
c430fee6
LP
4544 bool done_something = false;
4545 int r;
4546
80ba3b84
LP
4547 assert_return(m, -EINVAL);
4548 assert_return(source, -EINVAL);
4549 assert_return(!m->sealed, -EPERM);
4550 assert_return(source->sealed, -EPERM);
4551
c430fee6
LP
4552 do {
4553 const char *contents;
4554 char type;
4555 union {
4556 uint8_t u8;
4557 uint16_t u16;
4558 int16_t s16;
4559 uint32_t u32;
4560 int32_t s32;
4561 uint64_t u64;
4562 int64_t s64;
4563 double d64;
4564 const char *string;
4565 int i;
4566 } basic;
4567
4568 r = sd_bus_message_peek_type(source, &type, &contents);
4569 if (r < 0)
4570 return r;
4571 if (r == 0)
4572 break;
4573
4574 done_something = true;
4575
4576 if (bus_type_is_container(type) > 0) {
4577
4578 r = sd_bus_message_enter_container(source, type, contents);
4579 if (r < 0)
4580 return r;
4581
4582 r = sd_bus_message_open_container(m, type, contents);
4583 if (r < 0)
4584 return r;
4585
4586 r = sd_bus_message_copy(m, source, true);
4587 if (r < 0)
4588 return r;
4589
4590 r = sd_bus_message_close_container(m);
4591 if (r < 0)
4592 return r;
4593
4594 r = sd_bus_message_exit_container(source);
4595 if (r < 0)
4596 return r;
4597
4598 continue;
4599 }
4600
4601 r = sd_bus_message_read_basic(source, type, &basic);
4602 if (r < 0)
4603 return r;
4604
4605 assert(r > 0);
4606
4607 if (type == SD_BUS_TYPE_OBJECT_PATH ||
4608 type == SD_BUS_TYPE_SIGNATURE ||
4609 type == SD_BUS_TYPE_STRING)
4610 r = sd_bus_message_append_basic(m, type, basic.string);
4611 else
4612 r = sd_bus_message_append_basic(m, type, &basic);
4613
4614 if (r < 0)
4615 return r;
4616
4617 } while (all);
4618
4619 return done_something;
4620}
4621
d9f644e2 4622_public_ int sd_bus_message_verify_type(sd_bus_message *m, char type, const char *contents) {
c430fee6
LP
4623 const char *c;
4624 char t;
4625 int r;
4626
4627 assert_return(m, -EINVAL);
4628 assert_return(m->sealed, -EPERM);
4629 assert_return(!type || bus_type_is_valid(type), -EINVAL);
4630 assert_return(!contents || signature_is_valid(contents, true), -EINVAL);
4631 assert_return(type || contents, -EINVAL);
4632 assert_return(!contents || !type || bus_type_is_container(type), -EINVAL);
4633
4634 r = sd_bus_message_peek_type(m, &t, &c);
4635 if (r <= 0)
4636 return r;
4637
4638 if (type != 0 && type != t)
4639 return 0;
4640
4641 if (contents && !streq_ptr(contents, c))
4642 return 0;
4643
4644 return 1;
4645}