]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd-bus/bus-message.c
pam_systemd: dup the fd received from logind
[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
LP
1325 assert_return(m, -EINVAL);
1326 assert_return(p, -EINVAL);
1327 assert_return(!m->sealed, -EPERM);
1328 assert_return(bus_type_is_basic(type), -EINVAL);
1329 assert_return(!m->poisoned, -ESTALE);
de1c301e
LP
1330
1331 c = message_get_container(m);
1332
1333 if (c->signature && c->signature[c->index]) {
1334 /* Container signature is already set */
1335
1336 if (c->signature[c->index] != type)
9a17484d 1337 return -ENXIO;
de1c301e 1338 } else {
5cbe7492
LP
1339 char *e;
1340
de1c301e
LP
1341 /* Maybe we can append to the signature? But only if this is the top-level container*/
1342 if (c->enclosing != 0)
9a17484d 1343 return -ENXIO;
de1c301e
LP
1344
1345 e = strextend(&c->signature, CHAR_TO_STR(type), NULL);
bc7fd8cd
LP
1346 if (!e) {
1347 m->poisoned = true;
de1c301e 1348 return -ENOMEM;
bc7fd8cd 1349 }
de1c301e
LP
1350 }
1351
de1c301e
LP
1352 switch (type) {
1353
1354 case SD_BUS_TYPE_STRING:
cd6f997f
LP
1355 /* To make things easy we'll serialize a NULL string
1356 * into the empty string */
1357 p = strempty(p);
1358
1359 /* Fall through... */
de1c301e 1360 case SD_BUS_TYPE_OBJECT_PATH:
b8beb278 1361
cd6f997f
LP
1362 if (!p) {
1363 r = -EINVAL;
1364 goto fail;
1365 }
1366
de1c301e
LP
1367 align = 4;
1368 sz = 4 + strlen(p) + 1;
1369 break;
1370
1371 case SD_BUS_TYPE_SIGNATURE:
b8beb278 1372
cd6f997f
LP
1373 if (!p) {
1374 r = -EINVAL;
1375 goto fail;
1376 }
1377
de1c301e
LP
1378 align = 1;
1379 sz = 1 + strlen(p) + 1;
1380 break;
1381
1382 case SD_BUS_TYPE_BOOLEAN:
1383 align = sz = 4;
1384
1385 assert_cc(sizeof(int) == sizeof(uint32_t));
1386 memcpy(&k, p, 4);
1387 k = !!k;
1388 p = &k;
1389 break;
1390
2c93b4ef
LP
1391 case SD_BUS_TYPE_UNIX_FD: {
1392 int z, *f;
1393
1394 if (!m->allow_fds) {
1395 r = -ENOTSUP;
1396 goto fail;
1397 }
1398
1399 align = sz = 4;
1400
1401 z = *(int*) p;
1402 if (z < 0) {
1403 r = -EINVAL;
1404 goto fail;
1405 }
1406
1407 fd = fcntl(z, F_DUPFD_CLOEXEC, 3);
1408 if (fd < 0) {
1409 r = -errno;
1410 goto fail;
1411 }
1412
1413 f = realloc(m->fds, sizeof(int) * (m->n_fds + 1));
1414 if (!f) {
bc7fd8cd 1415 m->poisoned = true;
2c93b4ef
LP
1416 r = -ENOMEM;
1417 goto fail;
1418 }
1419
1420 fdi = m->n_fds;
1421 f[fdi] = fd;
1422 m->fds = f;
1423 m->free_fds = true;
1424 break;
1425 }
1426
de1c301e
LP
1427 default:
1428 align = bus_type_get_alignment(type);
1429 sz = bus_type_get_size(type);
1430 break;
1431 }
1432
1433 assert(align > 0);
1434 assert(sz > 0);
1435
1436 a = message_extend_body(m, align, sz);
1437 if (!a) {
2c93b4ef
LP
1438 r = -ENOMEM;
1439 goto fail;
de1c301e
LP
1440 }
1441
1442 if (type == SD_BUS_TYPE_STRING || type == SD_BUS_TYPE_OBJECT_PATH) {
1443 *(uint32_t*) a = sz - 5;
1444 memcpy((uint8_t*) a + 4, p, sz - 4);
1445
1446 if (stored)
1447 *stored = (const uint8_t*) a + 4;
1448
1449 } else if (type == SD_BUS_TYPE_SIGNATURE) {
1450 *(uint8_t*) a = sz - 1;
1451 memcpy((uint8_t*) a + 1, p, sz - 1);
1452
1453 if (stored)
1454 *stored = (const uint8_t*) a + 1;
2c93b4ef
LP
1455 } else if (type == SD_BUS_TYPE_UNIX_FD) {
1456 *(uint32_t*) a = fdi;
1457
1458 if (stored)
1459 *stored = a;
1460
1461 m->n_fds ++;
de1c301e
LP
1462
1463 } else {
1464 memcpy(a, p, sz);
1465
1466 if (stored)
1467 *stored = a;
1468 }
1469
1470 if (c->enclosing != SD_BUS_TYPE_ARRAY)
9a17484d 1471 c->index++;
de1c301e
LP
1472
1473 return 0;
2c93b4ef
LP
1474
1475fail:
2c93b4ef
LP
1476 if (fd >= 0)
1477 close_nointr_nofail(fd);
1478
1479 return r;
de1c301e
LP
1480}
1481
d9f644e2 1482_public_ int sd_bus_message_append_basic(sd_bus_message *m, char type, const void *p) {
de1c301e
LP
1483 return message_append_basic(m, type, p, NULL);
1484}
1485
d9f644e2 1486_public_ int sd_bus_message_append_string_space(sd_bus_message *m, size_t size, char **s) {
f8e013f8 1487 struct bus_container *c;
f8e013f8 1488 void *a;
f8e013f8 1489
9d6c7c82
LP
1490 assert_return(m, -EINVAL);
1491 assert_return(s, -EINVAL);
1492 assert_return(!m->sealed, -EPERM);
1493 assert_return(!m->poisoned, -ESTALE);
f8e013f8
LP
1494
1495 c = message_get_container(m);
1496
1497 if (c->signature && c->signature[c->index]) {
1498 /* Container signature is already set */
1499
1500 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
1501 return -ENXIO;
1502 } else {
5cbe7492
LP
1503 char *e;
1504
f8e013f8
LP
1505 /* Maybe we can append to the signature? But only if this is the top-level container*/
1506 if (c->enclosing != 0)
1507 return -ENXIO;
1508
1509 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
bc7fd8cd
LP
1510 if (!e) {
1511 m->poisoned = true;
f8e013f8 1512 return -ENOMEM;
bc7fd8cd 1513 }
f8e013f8
LP
1514 }
1515
f8e013f8 1516 a = message_extend_body(m, 4, 4 + size + 1);
bc7fd8cd
LP
1517 if (!a)
1518 return -ENOMEM;
f8e013f8
LP
1519
1520 *(uint32_t*) a = size;
1521 *s = (char*) a + 4;
1522
1523 (*s)[size] = 0;
1524
1525 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1526 c->index++;
1527
1528 return 0;
f8e013f8
LP
1529}
1530
de1c301e
LP
1531static int bus_message_open_array(
1532 sd_bus_message *m,
1533 struct bus_container *c,
1534 const char *contents,
1535 uint32_t **array_size) {
1536
9a17484d 1537 unsigned nindex;
bc7fd8cd 1538 void *a, *op;
de1c301e 1539 int alignment;
bc7fd8cd
LP
1540 size_t os;
1541 struct bus_body_part *o;
de1c301e
LP
1542
1543 assert(m);
1544 assert(c);
1545 assert(contents);
1546 assert(array_size);
1547
29ddb38f 1548 if (!signature_is_single(contents, true))
de1c301e
LP
1549 return -EINVAL;
1550
1551 alignment = bus_type_get_alignment(contents[0]);
1552 if (alignment < 0)
1553 return alignment;
1554
1555 if (c->signature && c->signature[c->index]) {
1556
1557 /* Verify the existing signature */
1558
1559 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
9a17484d 1560 return -ENXIO;
de1c301e
LP
1561
1562 if (!startswith(c->signature + c->index + 1, contents))
9a17484d 1563 return -ENXIO;
de1c301e
LP
1564
1565 nindex = c->index + 1 + strlen(contents);
1566 } else {
5cbe7492
LP
1567 char *e;
1568
de1c301e 1569 if (c->enclosing != 0)
9a17484d 1570 return -ENXIO;
de1c301e
LP
1571
1572 /* Extend the existing signature */
1573
1574 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_ARRAY), contents, NULL);
bc7fd8cd
LP
1575 if (!e) {
1576 m->poisoned = true;
de1c301e 1577 return -ENOMEM;
bc7fd8cd 1578 }
de1c301e
LP
1579
1580 nindex = e - c->signature;
1581 }
1582
de1c301e 1583 a = message_extend_body(m, 4, 4);
bc7fd8cd 1584 if (!a)
de1c301e 1585 return -ENOMEM;
de1c301e 1586
bc7fd8cd
LP
1587 o = m->body_end;
1588 op = m->body_end->data;
1589 os = m->body_end->size;
de1c301e 1590
bc7fd8cd
LP
1591 /* Add alignment between size and first element */
1592 if (!message_extend_body(m, alignment, 0))
de1c301e 1593 return -ENOMEM;
de1c301e
LP
1594
1595 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1596 c->index = nindex;
1597
bc7fd8cd
LP
1598 /* location of array size might have changed so let's readjust a */
1599 if (o == m->body_end)
1600 a = adjust_pointer(a, op, os, m->body_end->data);
de1c301e 1601
bc7fd8cd 1602 *(uint32_t*) a = 0;
de1c301e
LP
1603 *array_size = a;
1604 return 0;
1605}
1606
1607static int bus_message_open_variant(
1608 sd_bus_message *m,
1609 struct bus_container *c,
1610 const char *contents) {
1611
9a17484d 1612 size_t l;
de1c301e
LP
1613 void *a;
1614
1615 assert(m);
1616 assert(c);
1617 assert(contents);
1618
29ddb38f 1619 if (!signature_is_single(contents, false))
de1c301e
LP
1620 return -EINVAL;
1621
1622 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
1623 return -EINVAL;
1624
1625 if (c->signature && c->signature[c->index]) {
1626
1627 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
9a17484d 1628 return -ENXIO;
de1c301e
LP
1629
1630 } else {
5cbe7492
LP
1631 char *e;
1632
de1c301e 1633 if (c->enclosing != 0)
9a17484d 1634 return -ENXIO;
de1c301e
LP
1635
1636 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_VARIANT), NULL);
bc7fd8cd
LP
1637 if (!e) {
1638 m->poisoned = true;
de1c301e 1639 return -ENOMEM;
bc7fd8cd 1640 }
de1c301e
LP
1641 }
1642
de1c301e
LP
1643 l = strlen(contents);
1644 a = message_extend_body(m, 1, 1 + l + 1);
bc7fd8cd 1645 if (!a)
de1c301e 1646 return -ENOMEM;
de1c301e
LP
1647
1648 *(uint8_t*) a = l;
1649 memcpy((uint8_t*) a + 1, contents, l + 1);
1650
1651 if (c->enclosing != SD_BUS_TYPE_ARRAY)
9a17484d 1652 c->index++;
de1c301e
LP
1653
1654 return 0;
1655}
1656
1657static int bus_message_open_struct(
1658 sd_bus_message *m,
1659 struct bus_container *c,
1660 const char *contents) {
1661
1662 size_t nindex;
de1c301e
LP
1663
1664 assert(m);
1665 assert(c);
1666 assert(contents);
1667
1668 if (!signature_is_valid(contents, false))
1669 return -EINVAL;
1670
1671 if (c->signature && c->signature[c->index]) {
1672 size_t l;
1673
1674 l = strlen(contents);
1675
1676 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
1677 !startswith(c->signature + c->index + 1, contents) ||
1678 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
9a17484d 1679 return -ENXIO;
de1c301e
LP
1680
1681 nindex = c->index + 1 + l + 1;
1682 } else {
5cbe7492
LP
1683 char *e;
1684
de1c301e 1685 if (c->enclosing != 0)
9a17484d 1686 return -ENXIO;
de1c301e
LP
1687
1688 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_BEGIN), contents, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_END), NULL);
bc7fd8cd
LP
1689 if (!e) {
1690 m->poisoned = true;
de1c301e 1691 return -ENOMEM;
bc7fd8cd 1692 }
de1c301e
LP
1693
1694 nindex = e - c->signature;
1695 }
1696
1697 /* Align contents to 8 byte boundary */
bc7fd8cd 1698 if (!message_extend_body(m, 8, 0))
de1c301e 1699 return -ENOMEM;
de1c301e
LP
1700
1701 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1702 c->index = nindex;
1703
1704 return 0;
1705}
1706
1707static int bus_message_open_dict_entry(
1708 sd_bus_message *m,
1709 struct bus_container *c,
1710 const char *contents) {
1711
1712 size_t nindex;
1713
1714 assert(m);
1715 assert(c);
1716 assert(contents);
1717
1718 if (!signature_is_pair(contents))
1719 return -EINVAL;
1720
1721 if (c->enclosing != SD_BUS_TYPE_ARRAY)
9a17484d 1722 return -ENXIO;
de1c301e
LP
1723
1724 if (c->signature && c->signature[c->index]) {
1725 size_t l;
1726
1727 l = strlen(contents);
1728
1729 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
1730 !startswith(c->signature + c->index + 1, contents) ||
1731 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
9a17484d 1732 return -ENXIO;
de1c301e
LP
1733
1734 nindex = c->index + 1 + l + 1;
1735 } else
9a17484d 1736 return -ENXIO;
de1c301e
LP
1737
1738 /* Align contents to 8 byte boundary */
1739 if (!message_extend_body(m, 8, 0))
1740 return -ENOMEM;
1741
1742 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1743 c->index = nindex;
1744
1745 return 0;
1746}
1747
d9f644e2 1748_public_ int sd_bus_message_open_container(
de1c301e
LP
1749 sd_bus_message *m,
1750 char type,
1751 const char *contents) {
1752
9a17484d 1753 struct bus_container *c, *w;
de1c301e 1754 uint32_t *array_size = NULL;
9a17484d 1755 char *signature;
b3af9646 1756 size_t before;
de1c301e
LP
1757 int r;
1758
9d6c7c82
LP
1759 assert_return(m, -EINVAL);
1760 assert_return(!m->sealed, -EPERM);
1761 assert_return(contents, -EINVAL);
1762 assert_return(!m->poisoned, -ESTALE);
de1c301e
LP
1763
1764 /* Make sure we have space for one more container */
9a17484d 1765 w = realloc(m->containers, sizeof(struct bus_container) * (m->n_containers + 1));
bc7fd8cd
LP
1766 if (!w) {
1767 m->poisoned = true;
de1c301e 1768 return -ENOMEM;
bc7fd8cd
LP
1769 }
1770
9a17484d 1771 m->containers = w;
de1c301e
LP
1772
1773 c = message_get_container(m);
1774
1775 signature = strdup(contents);
bc7fd8cd
LP
1776 if (!signature) {
1777 m->poisoned = true;
de1c301e 1778 return -ENOMEM;
bc7fd8cd 1779 }
de1c301e 1780
b3af9646
LP
1781 /* Save old index in the parent container, in case we have to
1782 * abort this container */
1783 c->saved_index = c->index;
1784 before = m->header->body_size;
1785
de1c301e
LP
1786 if (type == SD_BUS_TYPE_ARRAY)
1787 r = bus_message_open_array(m, c, contents, &array_size);
1788 else if (type == SD_BUS_TYPE_VARIANT)
1789 r = bus_message_open_variant(m, c, contents);
1790 else if (type == SD_BUS_TYPE_STRUCT)
1791 r = bus_message_open_struct(m, c, contents);
1792 else if (type == SD_BUS_TYPE_DICT_ENTRY)
1793 r = bus_message_open_dict_entry(m, c, contents);
1794 else
1795 r = -EINVAL;
1796
1797 if (r < 0) {
1798 free(signature);
1799 return r;
1800 }
1801
1802 /* OK, let's fill it in */
9a17484d
LP
1803 w += m->n_containers++;
1804 w->enclosing = type;
1805 w->signature = signature;
1806 w->index = 0;
1807 w->array_size = array_size;
b3af9646
LP
1808 w->before = before;
1809 w->begin = m->rindex;
de1c301e
LP
1810
1811 return 0;
1812}
1813
d9f644e2 1814_public_ int sd_bus_message_close_container(sd_bus_message *m) {
de1c301e
LP
1815 struct bus_container *c;
1816
9d6c7c82
LP
1817 assert_return(m, -EINVAL);
1818 assert_return(!m->sealed, -EPERM);
1819 assert_return(m->n_containers > 0, -EINVAL);
1820 assert_return(!m->poisoned, -ESTALE);
de1c301e
LP
1821
1822 c = message_get_container(m);
de1c301e 1823 if (c->enclosing != SD_BUS_TYPE_ARRAY)
9a17484d 1824 if (c->signature && c->signature[c->index] != 0)
de1c301e
LP
1825 return -EINVAL;
1826
1827 free(c->signature);
1828 m->n_containers--;
1829
1830 return 0;
1831}
1832
1b492614
LP
1833typedef struct {
1834 const char *types;
1835 unsigned n_struct;
1836 unsigned n_array;
1837} TypeStack;
1838
1839static int type_stack_push(TypeStack *stack, unsigned max, unsigned *i, const char *types, unsigned n_struct, unsigned n_array) {
1840 assert(stack);
1841 assert(max > 0);
1842
1843 if (*i >= max)
1844 return -EINVAL;
1845
1846 stack[*i].types = types;
1847 stack[*i].n_struct = n_struct;
1848 stack[*i].n_array = n_array;
1849 (*i)++;
1850
1851 return 0;
1852}
1853
1854static int type_stack_pop(TypeStack *stack, unsigned max, unsigned *i, const char **types, unsigned *n_struct, unsigned *n_array) {
1855 assert(stack);
1856 assert(max > 0);
1857 assert(types);
1858 assert(n_struct);
1859 assert(n_array);
1860
1861 if (*i <= 0)
1862 return 0;
1863
1864 (*i)--;
1865 *types = stack[*i].types;
1866 *n_struct = stack[*i].n_struct;
1867 *n_array = stack[*i].n_array;
1868
1869 return 1;
1870}
1871
917b5dc7 1872int bus_message_append_ap(
de1c301e
LP
1873 sd_bus_message *m,
1874 const char *types,
1875 va_list ap) {
1876
1b492614
LP
1877 unsigned n_array, n_struct;
1878 TypeStack stack[BUS_CONTAINER_DEPTH];
1879 unsigned stack_ptr = 0;
de1c301e
LP
1880 int r;
1881
1882 assert(m);
88d331d5
LP
1883
1884 if (!types)
1885 return 0;
de1c301e 1886
1b492614
LP
1887 n_array = (unsigned) -1;
1888 n_struct = strlen(types);
1889
1890 for (;;) {
1891 const char *t;
1892
1893 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
1894 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
1895 if (r < 0)
1896 return r;
1897 if (r == 0)
1898 break;
1899
1900 r = sd_bus_message_close_container(m);
1901 if (r < 0)
1902 return r;
1903
1904 continue;
1905 }
1906
1907 t = types;
1908 if (n_array != (unsigned) -1)
1909 n_array --;
1910 else {
1911 types ++;
1912 n_struct--;
1913 }
1914
de1c301e
LP
1915 switch (*t) {
1916
1917 case SD_BUS_TYPE_BYTE: {
1918 uint8_t x;
1919
1920 x = (uint8_t) va_arg(ap, int);
1921 r = sd_bus_message_append_basic(m, *t, &x);
1922 break;
1923 }
1924
1925 case SD_BUS_TYPE_BOOLEAN:
1926 case SD_BUS_TYPE_INT32:
9a17484d
LP
1927 case SD_BUS_TYPE_UINT32:
1928 case SD_BUS_TYPE_UNIX_FD: {
de1c301e
LP
1929 uint32_t x;
1930
9a17484d
LP
1931 /* We assume a boolean is the same as int32_t */
1932 assert_cc(sizeof(int32_t) == sizeof(int));
1933
de1c301e
LP
1934 x = va_arg(ap, uint32_t);
1935 r = sd_bus_message_append_basic(m, *t, &x);
1936 break;
1937 }
1938
1939 case SD_BUS_TYPE_INT16:
1940 case SD_BUS_TYPE_UINT16: {
1941 uint16_t x;
1942
1943 x = (uint16_t) va_arg(ap, int);
1944 r = sd_bus_message_append_basic(m, *t, &x);
1945 break;
1946 }
1947
1948 case SD_BUS_TYPE_INT64:
1949 case SD_BUS_TYPE_UINT64:
1950 case SD_BUS_TYPE_DOUBLE: {
1951 uint64_t x;
1952
1953 x = va_arg(ap, uint64_t);
1954 r = sd_bus_message_append_basic(m, *t, &x);
1955 break;
1956 }
1957
1958 case SD_BUS_TYPE_STRING:
1959 case SD_BUS_TYPE_OBJECT_PATH:
1960 case SD_BUS_TYPE_SIGNATURE: {
1961 const char *x;
1962
1963 x = va_arg(ap, const char*);
1964 r = sd_bus_message_append_basic(m, *t, x);
1965 break;
1966 }
1967
de1c301e 1968 case SD_BUS_TYPE_ARRAY: {
de1c301e
LP
1969 size_t k;
1970
1971 r = signature_element_length(t + 1, &k);
1972 if (r < 0)
1973 return r;
1974
1975 {
1976 char s[k + 1];
de1c301e
LP
1977 memcpy(s, t + 1, k);
1978 s[k] = 0;
de1c301e
LP
1979
1980 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, s);
1981 if (r < 0)
1982 return r;
1b492614 1983 }
de1c301e 1984
1b492614
LP
1985 if (n_array == (unsigned) -1) {
1986 types += k;
1987 n_struct -= k;
de1c301e
LP
1988 }
1989
1b492614
LP
1990 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
1991 if (r < 0)
1992 return r;
1993
1994 types = t + 1;
1995 n_struct = k;
1996 n_array = va_arg(ap, unsigned);
1997
de1c301e
LP
1998 break;
1999 }
2000
2001 case SD_BUS_TYPE_VARIANT: {
2002 const char *s;
2003
2004 s = va_arg(ap, const char*);
2005 if (!s)
2006 return -EINVAL;
2007
2008 r = sd_bus_message_open_container(m, SD_BUS_TYPE_VARIANT, s);
2009 if (r < 0)
2010 return r;
2011
1b492614 2012 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
de1c301e
LP
2013 if (r < 0)
2014 return r;
2015
1b492614
LP
2016 types = s;
2017 n_struct = strlen(s);
2018 n_array = (unsigned) -1;
2019
de1c301e
LP
2020 break;
2021 }
2022
2023 case SD_BUS_TYPE_STRUCT_BEGIN:
2024 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
2025 size_t k;
2026
2027 r = signature_element_length(t, &k);
2028 if (r < 0)
2029 return r;
2030
2031 {
2032 char s[k - 1];
2033
2034 memcpy(s, t + 1, k - 2);
2035 s[k - 2] = 0;
2036
2037 r = sd_bus_message_open_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
2038 if (r < 0)
2039 return r;
1b492614 2040 }
de1c301e 2041
1b492614
LP
2042 if (n_array == (unsigned) -1) {
2043 types += k - 1;
2044 n_struct -= k - 1;
2045 }
de1c301e 2046
1b492614
LP
2047 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2048 if (r < 0)
2049 return r;
de1c301e 2050
1b492614
LP
2051 types = t + 1;
2052 n_struct = k - 2;
2053 n_array = (unsigned) -1;
de1c301e
LP
2054
2055 break;
2056 }
2057
2058 default:
2059 r = -EINVAL;
2060 }
2061
2062 if (r < 0)
2063 return r;
2064 }
2065
2066 return 0;
2067}
2068
d9f644e2 2069_public_ int sd_bus_message_append(sd_bus_message *m, const char *types, ...) {
de1c301e
LP
2070 va_list ap;
2071 int r;
2072
9d6c7c82
LP
2073 assert_return(m, -EINVAL);
2074 assert_return(types, -EINVAL);
2075 assert_return(!m->sealed, -EPERM);
2076 assert_return(!m->poisoned, -ESTALE);
de1c301e
LP
2077
2078 va_start(ap, types);
917b5dc7 2079 r = bus_message_append_ap(m, types, ap);
de1c301e
LP
2080 va_end(ap);
2081
2082 return r;
2083}
2084
d9f644e2
ZJS
2085_public_ int sd_bus_message_append_array_space(sd_bus_message *m,
2086 char type,
2087 size_t size,
2088 void **ptr) {
b3af9646
LP
2089 ssize_t align, sz;
2090 void *a;
2091 int r;
2092
9d6c7c82
LP
2093 assert_return(m, -EINVAL);
2094 assert_return(!m->sealed, -EPERM);
2095 assert_return(bus_type_is_trivial(type), -EINVAL);
2096 assert_return(ptr || size == 0, -EINVAL);
2097 assert_return(!m->poisoned, -ESTALE);
b3af9646
LP
2098
2099 align = bus_type_get_alignment(type);
2100 sz = bus_type_get_size(type);
2101
2102 assert_se(align > 0);
2103 assert_se(sz > 0);
2104
2105 if (size % sz != 0)
2106 return -EINVAL;
2107
2108 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2109 if (r < 0)
2110 return r;
2111
2112 a = message_extend_body(m, align, size);
bc7fd8cd
LP
2113 if (!a)
2114 return -ENOMEM;
b3af9646
LP
2115
2116 r = sd_bus_message_close_container(m);
2117 if (r < 0)
bc7fd8cd 2118 return r;
b3af9646
LP
2119
2120 *ptr = a;
2121 return 0;
b3af9646
LP
2122}
2123
d9f644e2
ZJS
2124_public_ int sd_bus_message_append_array(sd_bus_message *m,
2125 char type,
2126 const void *ptr,
2127 size_t size) {
b3af9646
LP
2128 int r;
2129 void *p;
2130
9d6c7c82
LP
2131 assert_return(m, -EINVAL);
2132 assert_return(!m->sealed, -EPERM);
2133 assert_return(bus_type_is_trivial(type), -EINVAL);
2134 assert_return(ptr || size == 0, -EINVAL);
2135 assert_return(!m->poisoned, -ESTALE);
b3af9646 2136
f8e013f8 2137 r = sd_bus_message_append_array_space(m, type, size, &p);
b3af9646
LP
2138 if (r < 0)
2139 return r;
2140
2141 if (size > 0)
2142 memcpy(p, ptr, size);
2143
2144 return 0;
2145}
2146
d9f644e2
ZJS
2147_public_ int sd_bus_message_append_array_memfd(sd_bus_message *m,
2148 char type,
2149 sd_memfd *memfd) {
453a0c29
LP
2150 _cleanup_close_ int copy_fd = -1;
2151 struct bus_body_part *part;
2152 ssize_t align, sz;
2153 uint64_t size;
2154 void *a;
2155 int r;
2156
2157 if (!m)
2158 return -EINVAL;
2159 if (!memfd)
2160 return -EINVAL;
2161 if (m->sealed)
2162 return -EPERM;
2163 if (!bus_type_is_trivial(type))
2164 return -EINVAL;
2165 if (m->poisoned)
2166 return -ESTALE;
2167
2168 r = sd_memfd_set_sealed(memfd, true);
2169 if (r < 0)
2170 return r;
2171
2172 copy_fd = sd_memfd_dup_fd(memfd);
2173 if (copy_fd < 0)
2174 return copy_fd;
2175
2176 r = sd_memfd_get_size(memfd, &size);
2177 if (r < 0)
2178 return r;
2179
2180 align = bus_type_get_alignment(type);
2181 sz = bus_type_get_size(type);
2182
2183 assert_se(align > 0);
2184 assert_se(sz > 0);
2185
2186 if (size % sz != 0)
2187 return -EINVAL;
2188
5cbe7492 2189 if (size > (uint64_t) (uint32_t) -1)
453a0c29
LP
2190 return -EINVAL;
2191
2192 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2193 if (r < 0)
2194 return r;
2195
2196 a = message_extend_body(m, align, 0);
2197 if (!a)
2198 return -ENOMEM;
2199
2200 part = message_append_part(m);
2201 if (!part)
2202 return -ENOMEM;
2203
2204 part->memfd = copy_fd;
2205 part->sealed = true;
2206 part->size = size;
2207 copy_fd = -1;
2208
2209 message_extend_containers(m, size);
2210 m->header->body_size += size;
2211
2212 return sd_bus_message_close_container(m);
2213}
2214
d9f644e2 2215_public_ int sd_bus_message_append_string_memfd(sd_bus_message *m, sd_memfd *memfd) {
5cbe7492
LP
2216 _cleanup_close_ int copy_fd = -1;
2217 struct bus_body_part *part;
2218 struct bus_container *c;
2219 uint64_t size;
2220 void *a;
2221 int r;
2222
55736ed0
LP
2223 assert_return(m, -EINVAL);
2224 assert_return(memfd, -EINVAL);
2225 assert_return(!m->sealed, -EPERM);
2226 assert_return(!m->poisoned, -ESTALE);
5cbe7492
LP
2227
2228 r = sd_memfd_set_sealed(memfd, true);
2229 if (r < 0)
2230 return r;
2231
2232 copy_fd = sd_memfd_dup_fd(memfd);
2233 if (copy_fd < 0)
2234 return copy_fd;
2235
2236 r = sd_memfd_get_size(memfd, &size);
2237 if (r < 0)
2238 return r;
2239
2240 /* We require this to be NUL terminated */
2241 if (size == 0)
2242 return -EINVAL;
2243
2244 if (size > (uint64_t) (uint32_t) -1)
2245 return -EINVAL;
2246
2247 c = message_get_container(m);
2248 if (c->signature && c->signature[c->index]) {
2249 /* Container signature is already set */
2250
2251 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
2252 return -ENXIO;
2253 } else {
2254 char *e;
2255
2256 /* Maybe we can append to the signature? But only if this is the top-level container*/
2257 if (c->enclosing != 0)
2258 return -ENXIO;
2259
2260 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
2261 if (!e) {
2262 m->poisoned = true;
2263 return -ENOMEM;
2264 }
2265 }
2266
2267 a = message_extend_body(m, 4, 4);
2268 if (!a)
2269 return -ENOMEM;
2270
2271 *(uint32_t*) a = size - 1;
2272
2273 part = message_append_part(m);
2274 if (!part)
2275 return -ENOMEM;
2276
2277 part->memfd = copy_fd;
2278 part->sealed = true;
2279 part->size = size;
2280 copy_fd = -1;
2281
2282 message_extend_containers(m, size);
2283 m->header->body_size += size;
2284
2285 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2286 c->index++;
2287
2288 return 0;
2289}
2290
d9f644e2 2291_public_ int sd_bus_message_append_strv(sd_bus_message *m, char **l) {
55736ed0
LP
2292 char **i;
2293 int r;
2294
2295 assert_return(m, -EINVAL);
2296 assert_return(!m->sealed, -EPERM);
2297 assert_return(!m->poisoned, -ESTALE);
2298
2299 r = sd_bus_message_open_container(m, 'a', "s");
2300 if (r < 0)
2301 return r;
2302
2303 STRV_FOREACH(i, l) {
2304 r = sd_bus_message_append_basic(m, 's', *i);
2305 if (r < 0)
2306 return r;
2307 }
2308
2309 return sd_bus_message_close_container(m);
2310}
2311
a392d361 2312int bus_body_part_map(struct bus_body_part *part) {
453a0c29
LP
2313 void *p;
2314 size_t psz;
2315
2316 assert_se(part);
2317
2318 if (part->data)
2319 return 0;
2320
2321 if (part->size <= 0)
2322 return 0;
2323
1307c3ff
LP
2324 /* For smaller zero parts (as used for padding) we don't need to map anything... */
2325 if (part->memfd < 0 && part->is_zero && part->size < 8) {
2326 static const uint8_t zeroes[7] = { };
2327 part->data = (void*) zeroes;
2328 return 0;
2329 }
2330
453a0c29
LP
2331 psz = PAGE_ALIGN(part->size);
2332
2333 if (part->memfd >= 0)
2334 p = mmap(NULL, psz, PROT_READ, MAP_SHARED, part->memfd, 0);
2335 else if (part->is_zero)
2336 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
2337 else
2338 return -EINVAL;
2339
2340 if (p == MAP_FAILED)
2341 return -errno;
2342
2343 part->mapped = psz;
2344 part->data = p;
a392d361
LP
2345 part->munmap_this = true;
2346
453a0c29
LP
2347 return 0;
2348}
2349
a392d361
LP
2350void bus_body_part_unmap(struct bus_body_part *part) {
2351
2352 assert_se(part);
2353
2354 if (part->memfd < 0)
2355 return;
2356
a392d361
LP
2357 if (!part->data)
2358 return;
2359
bf30e48f
KS
2360 if (!part->munmap_this)
2361 return;
a392d361
LP
2362
2363 assert_se(munmap(part->data, part->mapped) == 0);
2364
2365 part->data = NULL;
2366 part->mapped = 0;
2367 part->munmap_this = false;
2368
2369 return;
2370}
2371
9a17484d 2372static int buffer_peek(const void *p, uint32_t sz, size_t *rindex, size_t align, size_t nbytes, void **r) {
bc7fd8cd 2373 size_t k, start, end;
de1c301e 2374
9a17484d
LP
2375 assert(rindex);
2376 assert(align > 0);
de1c301e 2377
9a17484d 2378 start = ALIGN_TO((size_t) *rindex, align);
bc7fd8cd 2379 end = start + nbytes;
9a17484d 2380
bc7fd8cd 2381 if (end > sz)
9a17484d
LP
2382 return -EBADMSG;
2383
2384 /* Verify that padding is 0 */
2385 for (k = *rindex; k < start; k++)
2386 if (((const uint8_t*) p)[k] != 0)
2387 return -EBADMSG;
2388
2389 if (r)
2390 *r = (uint8_t*) p + start;
2391
bc7fd8cd 2392 *rindex = end;
9a17484d
LP
2393
2394 return 1;
de1c301e
LP
2395}
2396
7b058942
LP
2397static bool message_end_of_signature(sd_bus_message *m) {
2398 struct bus_container *c;
2399
2400 assert(m);
2401
2402 c = message_get_container(m);
2403 return !c->signature || c->signature[c->index] == 0;
2404}
2405
9a17484d
LP
2406static bool message_end_of_array(sd_bus_message *m, size_t index) {
2407 struct bus_container *c;
de1c301e 2408
9a17484d 2409 assert(m);
de1c301e 2410
9a17484d
LP
2411 c = message_get_container(m);
2412 if (!c->array_size)
2413 return false;
de1c301e 2414
9a17484d 2415 return index >= c->begin + BUS_MESSAGE_BSWAP32(m, *c->array_size);
de1c301e
LP
2416}
2417
7b058942
LP
2418int sd_bus_message_at_end(sd_bus_message *m, int complete) {
2419 assert_return(m, -EINVAL);
2420 assert_return(m->sealed, -EPERM);
2421
2422 if (complete && m->n_containers > 0)
2423 return false;
2424
2425 if (message_end_of_signature(m))
2426 return true;
2427
2428 if (message_end_of_array(m, m->rindex))
2429 return true;
2430
2431 return false;
2432}
2433
bc7fd8cd
LP
2434static struct bus_body_part* find_part(sd_bus_message *m, size_t index, size_t sz, void **p) {
2435 struct bus_body_part *part;
2436 size_t begin;
453a0c29
LP
2437 int r;
2438
bc7fd8cd
LP
2439 assert(m);
2440
2441 if (m->cached_rindex_part && index >= m->cached_rindex_part_begin) {
2442 part = m->cached_rindex_part;
2443 begin = m->cached_rindex_part_begin;
2444 } else {
2445 part = &m->body;
2446 begin = 0;
2447 }
2448
2449 while (part) {
2450 if (index < begin)
2451 return NULL;
2452
2453 if (index + sz <= begin + part->size) {
453a0c29 2454
a392d361 2455 r = bus_body_part_map(part);
453a0c29
LP
2456 if (r < 0)
2457 return NULL;
2458
bc7fd8cd 2459 if (p)
453a0c29 2460 *p = (uint8_t*) part->data + index - begin;
bc7fd8cd
LP
2461
2462 m->cached_rindex_part = part;
2463 m->cached_rindex_part_begin = begin;
2464
2465 return part;
2466 }
2467
453a0c29 2468 begin += part->size;
bc7fd8cd
LP
2469 part = part->next;
2470 }
2471
2472 return NULL;
2473}
2474
2475static int message_peek_body(
2476 sd_bus_message *m,
2477 size_t *rindex,
2478 size_t align,
2479 size_t nbytes,
2480 void **ret) {
2481
2482 size_t k, start, end, padding;
2483 struct bus_body_part *part;
2484 uint8_t *q;
2485
de1c301e 2486 assert(m);
9a17484d
LP
2487 assert(rindex);
2488 assert(align > 0);
de1c301e 2489
9a17484d
LP
2490 if (message_end_of_array(m, *rindex))
2491 return 0;
de1c301e 2492
bc7fd8cd
LP
2493 start = ALIGN_TO((size_t) *rindex, align);
2494 padding = start - *rindex;
2495 end = start + nbytes;
2496
2497 if (end > BUS_MESSAGE_BODY_SIZE(m))
2498 return -EBADMSG;
2499
2500 part = find_part(m, *rindex, padding, (void**) &q);
2501 if (!part)
2502 return -EBADMSG;
2503
2504 if (q) {
2505 /* Verify padding */
2506 for (k = 0; k < padding; k++)
2507 if (q[k] != 0)
2508 return -EBADMSG;
2509 }
2510
2511 part = find_part(m, start, nbytes, (void**) &q);
2512 if (!part || !q)
2513 return -EBADMSG;
2514
2515 *rindex = end;
2516
2517 if (ret)
2518 *ret = q;
2519
2520 return 1;
9a17484d 2521}
de1c301e 2522
ac89bf1d 2523static bool validate_nul(const char *s, size_t l) {
de1c301e 2524
9a17484d
LP
2525 /* Check for NUL chars in the string */
2526 if (memchr(s, 0, l))
2527 return false;
de1c301e 2528
9a17484d
LP
2529 /* Check for NUL termination */
2530 if (s[l] != 0)
2531 return false;
de1c301e 2532
ac89bf1d
LP
2533 return true;
2534}
2535
2536static bool validate_string(const char *s, size_t l) {
2537
2538 if (!validate_nul(s, l))
2539 return false;
2540
9a17484d
LP
2541 /* Check if valid UTF8 */
2542 if (!utf8_is_valid(s))
2543 return false;
2544
2545 return true;
de1c301e
LP
2546}
2547
9a17484d 2548static bool validate_signature(const char *s, size_t l) {
de1c301e 2549
ac89bf1d 2550 if (!validate_nul(s, l))
9a17484d 2551 return false;
de1c301e 2552
9a17484d
LP
2553 /* Check if valid signature */
2554 if (!signature_is_valid(s, true))
2555 return false;
2556
2557 return true;
2558}
2559
ac89bf1d
LP
2560static bool validate_object_path(const char *s, size_t l) {
2561
2562 if (!validate_nul(s, l))
2563 return false;
2564
2565 if (!object_path_is_valid(s))
2566 return false;
2567
2568 return true;
2569}
2570
d9f644e2 2571_public_ int sd_bus_message_read_basic(sd_bus_message *m, char type, void *p) {
9a17484d 2572 struct bus_container *c;
9a17484d 2573 void *q;
0dcd14b9 2574 int r;
9a17484d 2575
9d6c7c82
LP
2576 assert_return(m, -EINVAL);
2577 assert_return(m->sealed, -EPERM);
2578 assert_return(bus_type_is_basic(type), -EINVAL);
de1c301e 2579
7b058942 2580 if (message_end_of_signature(m))
430fb8fa 2581 return -ENXIO;
9a17484d 2582
1daf8121
LP
2583 if (message_end_of_array(m, m->rindex))
2584 return 0;
2585
7b058942 2586 c = message_get_container(m);
9a17484d
LP
2587 if (c->signature[c->index] != type)
2588 return -ENXIO;
2589
2590 switch (type) {
2591
2592 case SD_BUS_TYPE_STRING:
2593 case SD_BUS_TYPE_OBJECT_PATH: {
2594 uint32_t l;
2595 size_t rindex;
2596
2597 rindex = m->rindex;
2598 r = message_peek_body(m, &rindex, 4, 4, &q);
2599 if (r <= 0)
2600 return r;
2601
2602 l = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
2603 r = message_peek_body(m, &rindex, 1, l+1, &q);
de1c301e
LP
2604 if (r < 0)
2605 return r;
9a17484d
LP
2606 if (r == 0)
2607 return -EBADMSG;
2608
ac89bf1d
LP
2609 if (type == SD_BUS_TYPE_OBJECT_PATH) {
2610 if (!validate_object_path(q, l))
2611 return -EBADMSG;
2612 } else {
2613 if (!validate_string(q, l))
2614 return -EBADMSG;
2615 }
9a17484d
LP
2616
2617 m->rindex = rindex;
0dcd14b9
LP
2618 if (p)
2619 *(const char**) p = q;
2620
9a17484d 2621 break;
de1c301e
LP
2622 }
2623
9a17484d
LP
2624 case SD_BUS_TYPE_SIGNATURE: {
2625 uint8_t l;
2626 size_t rindex;
2627
2628 rindex = m->rindex;
2629 r = message_peek_body(m, &rindex, 1, 1, &q);
2630 if (r <= 0)
2631 return r;
2632
2633 l = *(uint8_t*) q;
2634 r = message_peek_body(m, &rindex, 1, l+1, &q);
de1c301e
LP
2635 if (r < 0)
2636 return r;
9a17484d
LP
2637 if (r == 0)
2638 return -EBADMSG;
2639
2640 if (!validate_signature(q, l))
2641 return -EBADMSG;
2642
2643 m->rindex = rindex;
0dcd14b9
LP
2644
2645 if (p)
2646 *(const char**) p = q;
9a17484d 2647 break;
de1c301e
LP
2648 }
2649
9a17484d 2650 default: {
27f6e5c7
ZJS
2651 ssize_t sz, align;
2652 size_t rindex;
de1c301e 2653
9a17484d
LP
2654 align = bus_type_get_alignment(type);
2655 sz = bus_type_get_size(type);
27f6e5c7 2656 assert(align > 0 && sz > 0);
de1c301e 2657
2c93b4ef
LP
2658 rindex = m->rindex;
2659 r = message_peek_body(m, &rindex, align, sz, &q);
9a17484d
LP
2660 if (r <= 0)
2661 return r;
2662
2663 switch (type) {
2664
2665 case SD_BUS_TYPE_BYTE:
0dcd14b9
LP
2666 if (p)
2667 *(uint8_t*) p = *(uint8_t*) q;
9a17484d
LP
2668 break;
2669
2670 case SD_BUS_TYPE_BOOLEAN:
0dcd14b9
LP
2671 if (p)
2672 *(unsigned*) p = !!*(uint32_t*) q;
9a17484d
LP
2673 break;
2674
2675 case SD_BUS_TYPE_INT16:
2676 case SD_BUS_TYPE_UINT16:
0dcd14b9
LP
2677 if (p)
2678 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
9a17484d
LP
2679 break;
2680
2681 case SD_BUS_TYPE_INT32:
2682 case SD_BUS_TYPE_UINT32:
0dcd14b9
LP
2683 if (p)
2684 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
9a17484d
LP
2685 break;
2686
2687 case SD_BUS_TYPE_INT64:
2688 case SD_BUS_TYPE_UINT64:
2689 case SD_BUS_TYPE_DOUBLE:
0dcd14b9
LP
2690 if (p)
2691 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
9a17484d
LP
2692 break;
2693
2c93b4ef 2694 case SD_BUS_TYPE_UNIX_FD: {
2c93b4ef
LP
2695 uint32_t j;
2696
2697 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
2698 if (j >= m->n_fds)
2699 return -EBADMSG;
2700
0dcd14b9
LP
2701 if (p)
2702 *(int*) p = m->fds[j];
2c93b4ef
LP
2703 break;
2704 }
2705
9a17484d
LP
2706 default:
2707 assert_not_reached("Unknown basic type...");
2708 }
2709
b3af9646 2710 m->rindex = rindex;
2c93b4ef 2711
9a17484d
LP
2712 break;
2713 }
2714 }
2715
2716 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2717 c->index++;
2718
2719 return 1;
de1c301e
LP
2720}
2721
9a17484d
LP
2722static int bus_message_enter_array(
2723 sd_bus_message *m,
2724 struct bus_container *c,
2725 const char *contents,
2726 uint32_t **array_size) {
2727
2728 size_t rindex;
2729 void *q;
2730 int r, alignment;
2731
2732 assert(m);
2733 assert(c);
2734 assert(contents);
2735 assert(array_size);
2736
29ddb38f 2737 if (!signature_is_single(contents, true))
de1c301e 2738 return -EINVAL;
9a17484d
LP
2739
2740 alignment = bus_type_get_alignment(contents[0]);
2741 if (alignment < 0)
2742 return alignment;
2743
2744 if (!c->signature || c->signature[c->index] == 0)
2745 return 0;
2746
2747 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
2748 return -ENXIO;
2749
2750 if (!startswith(c->signature + c->index + 1, contents))
2751 return -ENXIO;
2752
2753 rindex = m->rindex;
2754 r = message_peek_body(m, &rindex, 4, 4, &q);
2755 if (r <= 0)
2756 return r;
2757
ac89bf1d 2758 if (BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q) > BUS_ARRAY_MAX_SIZE)
80a46c73 2759 return -EBADMSG;
9a17484d
LP
2760
2761 r = message_peek_body(m, &rindex, alignment, 0, NULL);
2762 if (r < 0)
2763 return r;
2764 if (r == 0)
2765 return -EBADMSG;
2766
2767 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2768 c->index += 1 + strlen(contents);
2769
2770 m->rindex = rindex;
2771
2772 *array_size = (uint32_t*) q;
2773
2774 return 1;
2775}
2776
2777static int bus_message_enter_variant(
2778 sd_bus_message *m,
2779 struct bus_container *c,
2780 const char *contents) {
2781
2782 size_t rindex;
2783 uint8_t l;
2784 void *q;
2785 int r;
2786
2787 assert(m);
2788 assert(c);
2789 assert(contents);
2790
29ddb38f 2791 if (!signature_is_single(contents, false))
de1c301e 2792 return -EINVAL;
de1c301e 2793
9a17484d
LP
2794 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
2795 return -EINVAL;
2796
2797 if (!c->signature || c->signature[c->index] == 0)
2798 return 0;
2799
2800 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
2801 return -ENXIO;
2802
2803 rindex = m->rindex;
2804 r = message_peek_body(m, &rindex, 1, 1, &q);
2805 if (r <= 0)
2806 return r;
2807
2808 l = *(uint8_t*) q;
2809 r = message_peek_body(m, &rindex, 1, l+1, &q);
2810 if (r < 0)
2811 return r;
2812 if (r == 0)
2813 return -EBADMSG;
2814
2815 if (!validate_signature(q, l))
2816 return -EBADMSG;
2817
2818 if (!streq(q, contents))
2819 return -ENXIO;
2820
2821 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2822 c->index++;
2823
2824 m->rindex = rindex;
2825
2826 return 1;
de1c301e
LP
2827}
2828
9a17484d
LP
2829static int bus_message_enter_struct(
2830 sd_bus_message *m,
2831 struct bus_container *c,
2832 const char *contents) {
2833
2834 size_t l;
2835 int r;
2836
2837 assert(m);
2838 assert(c);
2839 assert(contents);
2840
2841 if (!signature_is_valid(contents, false))
2842 return -EINVAL;
2843
2844 if (!c->signature || c->signature[c->index] == 0)
2845 return 0;
2846
2847 l = strlen(contents);
2848
2849 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
2850 !startswith(c->signature + c->index + 1, contents) ||
2851 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
2852 return -ENXIO;
2853
2854 r = message_peek_body(m, &m->rindex, 8, 0, NULL);
2855 if (r <= 0)
2856 return r;
2857
2858 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2859 c->index += 1 + l + 1;
2860
2861 return 1;
2862}
2863
2864static int bus_message_enter_dict_entry(
2865 sd_bus_message *m,
2866 struct bus_container *c,
2867 const char *contents) {
2868
2869 size_t l;
2870 int r;
2871
2872 assert(m);
2873 assert(c);
2874 assert(contents);
2875
2876 if (!signature_is_pair(contents))
2877 return -EINVAL;
2878
2879 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2880 return -ENXIO;
2881
2882 if (!c->signature || c->signature[c->index] == 0)
2883 return 0;
2884
2885 l = strlen(contents);
2886
2887 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
2888 !startswith(c->signature + c->index + 1, contents) ||
2889 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
2890 return -ENXIO;
2891
2892 r = message_peek_body(m, &m->rindex, 8, 0, NULL);
2893 if (r <= 0)
2894 return r;
2895
2896 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2897 c->index += 1 + l + 1;
2898
2899 return 1;
2900}
2901
d9f644e2
ZJS
2902_public_ int sd_bus_message_enter_container(sd_bus_message *m,
2903 char type,
2904 const char *contents) {
9a17484d
LP
2905 struct bus_container *c, *w;
2906 uint32_t *array_size = NULL;
2907 char *signature;
b3af9646 2908 size_t before;
9a17484d
LP
2909 int r;
2910
275b39fe
LP
2911 assert_return(m, -EINVAL);
2912 assert_return(m->sealed, -EPERM);
2913 assert_return(type != 0 || !contents, -EINVAL);
2914
2915 if (type == 0 || !contents) {
2916 const char *cc;
2917 char tt;
2918
2919 /* Allow entering into anonymous containers */
2920 r = sd_bus_message_peek_type(m, &tt, &cc);
2921 if (r <= 0)
2922 return r;
2923
2924 if (type != 0 && type != tt)
2925 return -ENXIO;
2926
2927 if (contents && !streq(contents, cc))
2928 return -ENXIO;
2929
2930 type = tt;
2931 contents = cc;
2932 }
9a17484d 2933
ed205a6b
LP
2934 /*
2935 * We enforce a global limit on container depth, that is much
2936 * higher than the 32 structs and 32 arrays the specification
2937 * mandates. This is simpler to implement for us, and we need
2938 * this only to ensure our container array doesn't grow
2939 * without bounds. We are happy to return any data from a
2940 * message as long as the data itself is valid, even if the
2941 * overall message might be not.
2942 *
2943 * Note that the message signature is validated when
2944 * parsing the headers, and that validation does check the
2945 * 32/32 limit.
2946 *
2947 * Note that the specification defines no limits on the depth
2948 * of stacked variants, but we do.
2949 */
2950 if (m->n_containers >= BUS_CONTAINER_DEPTH)
2951 return -EBADMSG;
2952
9a17484d
LP
2953 w = realloc(m->containers, sizeof(struct bus_container) * (m->n_containers + 1));
2954 if (!w)
2955 return -ENOMEM;
2956 m->containers = w;
2957
7b058942 2958 if (message_end_of_signature(m))
430fb8fa 2959 return -ENXIO;
9a17484d 2960
1daf8121
LP
2961 if (message_end_of_array(m, m->rindex))
2962 return 0;
2963
7b058942
LP
2964 c = message_get_container(m);
2965
9a17484d
LP
2966 signature = strdup(contents);
2967 if (!signature)
2968 return -ENOMEM;
2969
b3af9646
LP
2970 c->saved_index = c->index;
2971 before = m->rindex;
2972
9a17484d
LP
2973 if (type == SD_BUS_TYPE_ARRAY)
2974 r = bus_message_enter_array(m, c, contents, &array_size);
2975 else if (type == SD_BUS_TYPE_VARIANT)
2976 r = bus_message_enter_variant(m, c, contents);
2977 else if (type == SD_BUS_TYPE_STRUCT)
2978 r = bus_message_enter_struct(m, c, contents);
2979 else if (type == SD_BUS_TYPE_DICT_ENTRY)
2980 r = bus_message_enter_dict_entry(m, c, contents);
2981 else
2982 r = -EINVAL;
2983
2984 if (r <= 0) {
2985 free(signature);
2986 return r;
2987 }
2988
2989 /* OK, let's fill it in */
2990 w += m->n_containers++;
2991 w->enclosing = type;
2992 w->signature = signature;
2993 w->index = 0;
2994 w->array_size = array_size;
b3af9646 2995 w->before = before;
9a17484d
LP
2996 w->begin = m->rindex;
2997
2998 return 1;
2999}
3000
d9f644e2 3001_public_ int sd_bus_message_exit_container(sd_bus_message *m) {
9a17484d
LP
3002 struct bus_container *c;
3003
9d6c7c82
LP
3004 assert_return(m, -EINVAL);
3005 assert_return(m->sealed, -EPERM);
3006 assert_return(m->n_containers > 0, -EINVAL);
9a17484d
LP
3007
3008 c = message_get_container(m);
3009 if (c->enclosing == SD_BUS_TYPE_ARRAY) {
3010 uint32_t l;
3011
3012 l = BUS_MESSAGE_BSWAP32(m, *c->array_size);
3013 if (c->begin + l != m->rindex)
3014 return -EBUSY;
3015
3016 } else {
3017 if (c->signature && c->signature[c->index] != 0)
3018 return -EINVAL;
3019 }
3020
3021 free(c->signature);
3022 m->n_containers--;
3023
3024 return 1;
3025}
3026
b3af9646
LP
3027static void message_quit_container(sd_bus_message *m) {
3028 struct bus_container *c;
3029
3030 assert(m);
3031 assert(m->sealed);
3032 assert(m->n_containers > 0);
3033
3034 c = message_get_container(m);
3035
3036 /* Undo seeks */
3037 assert(m->rindex >= c->before);
3038 m->rindex = c->before;
3039
3040 /* Free container */
3041 free(c->signature);
3042 m->n_containers--;
3043
3044 /* Correct index of new top-level container */
3045 c = message_get_container(m);
3046 c->index = c->saved_index;
3047}
3048
d9f644e2 3049_public_ int sd_bus_message_peek_type(sd_bus_message *m, char *type, const char **contents) {
9a17484d
LP
3050 struct bus_container *c;
3051 int r;
3052
c430fee6
LP
3053 assert_return(m, -EINVAL);
3054 assert_return(m->sealed, -EPERM);
9a17484d 3055
7b058942 3056 if (message_end_of_signature(m))
9a17484d
LP
3057 goto eof;
3058
3059 if (message_end_of_array(m, m->rindex))
3060 goto eof;
3061
7b058942
LP
3062 c = message_get_container(m);
3063
9a17484d
LP
3064 if (bus_type_is_basic(c->signature[c->index])) {
3065 if (contents)
3066 *contents = NULL;
3067 if (type)
3068 *type = c->signature[c->index];
3069 return 1;
3070 }
3071
3072 if (c->signature[c->index] == SD_BUS_TYPE_ARRAY) {
3073
3074 if (contents) {
3075 size_t l;
3076 char *sig;
3077
3078 r = signature_element_length(c->signature+c->index+1, &l);
3079 if (r < 0)
3080 return r;
3081
80a46c73
LP
3082 assert(l >= 1);
3083
9a17484d
LP
3084 sig = strndup(c->signature + c->index + 1, l);
3085 if (!sig)
3086 return -ENOMEM;
3087
3088 free(m->peeked_signature);
3089 m->peeked_signature = sig;
3090
3091 *contents = sig;
3092 }
3093
3094 if (type)
3095 *type = SD_BUS_TYPE_ARRAY;
3096
3097 return 1;
3098 }
3099
3100 if (c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ||
3101 c->signature[c->index] == SD_BUS_TYPE_DICT_ENTRY_BEGIN) {
3102
3103 if (contents) {
3104 size_t l;
3105 char *sig;
3106
3107 r = signature_element_length(c->signature+c->index, &l);
3108 if (r < 0)
3109 return r;
3110
3111 assert(l >= 2);
3112 sig = strndup(c->signature + c->index + 1, l - 2);
3113 if (!sig)
3114 return -ENOMEM;
3115
3116 free(m->peeked_signature);
3117 m->peeked_signature = sig;
3118
3119 *contents = sig;
3120 }
3121
3122 if (type)
3123 *type = c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY;
3124
3125 return 1;
3126 }
3127
3128 if (c->signature[c->index] == SD_BUS_TYPE_VARIANT) {
3129 if (contents) {
3130 size_t rindex, l;
3131 void *q;
3132
3133 rindex = m->rindex;
3134 r = message_peek_body(m, &rindex, 1, 1, &q);
3135 if (r < 0)
3136 return r;
3137 if (r == 0)
3138 goto eof;
3139
3140 l = *(uint8_t*) q;
3141 r = message_peek_body(m, &rindex, 1, l+1, &q);
3142 if (r < 0)
3143 return r;
3144 if (r == 0)
3145 return -EBADMSG;
3146
3147 if (!validate_signature(q, l))
3148 return -EBADMSG;
3149
3150 *contents = q;
3151 }
3152
3153 if (type)
3154 *type = SD_BUS_TYPE_VARIANT;
3155
3156 return 1;
3157 }
3158
3159 return -EINVAL;
3160
3161eof:
3162 if (type)
7b058942 3163 *type = 0;
9a17484d
LP
3164 if (contents)
3165 *contents = NULL;
3166 return 0;
3167}
3168
d9f644e2 3169_public_ int sd_bus_message_rewind(sd_bus_message *m, int complete) {
9a17484d
LP
3170 struct bus_container *c;
3171
9d6c7c82
LP
3172 assert_return(m, -EINVAL);
3173 assert_return(m->sealed, -EPERM);
9a17484d
LP
3174
3175 if (complete) {
bc7fd8cd 3176 message_reset_containers(m);
9a17484d
LP
3177 m->rindex = 0;
3178 m->root_container.index = 0;
3179
3180 c = message_get_container(m);
3181 } else {
3182 c = message_get_container(m);
3183
3184 c->index = 0;
3185 m->rindex = c->begin;
3186 }
3187
3188 return !isempty(c->signature);
3189}
1b492614
LP
3190static int message_read_ap(
3191 sd_bus_message *m,
3192 const char *types,
3193 va_list ap) {
9a17484d 3194
fe1d424d
LP
3195 unsigned n_array, n_struct;
3196 TypeStack stack[BUS_CONTAINER_DEPTH];
3197 unsigned stack_ptr = 0;
430fb8fa 3198 unsigned n_loop = 0;
9a17484d
LP
3199 int r;
3200
3201 assert(m);
1b492614 3202
430fb8fa 3203 if (isempty(types))
1b492614 3204 return 0;
9a17484d 3205
fe1d424d
LP
3206 /* Ideally, we'd just call ourselves recursively on every
3207 * complex type. However, the state of a va_list that is
3208 * passed to a function is undefined after that function
3209 * returns. This means we need to docode the va_list linearly
3210 * in a single stackframe. We hence implement our own
3211 * home-grown stack in an array. */
3212
430fb8fa
LP
3213 n_array = (unsigned) -1; /* lenght of current array entries */
3214 n_struct = strlen(types); /* length of current struct contents signature */
fe1d424d
LP
3215
3216 for (;;) {
3217 const char *t;
3218
430fb8fa
LP
3219 n_loop++;
3220
1b492614 3221 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
fe1d424d
LP
3222 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
3223 if (r < 0)
3224 return r;
3225 if (r == 0)
3226 break;
3227
3228 r = sd_bus_message_exit_container(m);
3229 if (r < 0)
3230 return r;
3231
3232 continue;
3233 }
3234
3235 t = types;
3236 if (n_array != (unsigned) -1)
3237 n_array --;
3238 else {
3239 types ++;
3240 n_struct--;
3241 }
3242
9a17484d
LP
3243 switch (*t) {
3244
3245 case SD_BUS_TYPE_BYTE:
3246 case SD_BUS_TYPE_BOOLEAN:
3247 case SD_BUS_TYPE_INT16:
3248 case SD_BUS_TYPE_UINT16:
3249 case SD_BUS_TYPE_INT32:
3250 case SD_BUS_TYPE_UINT32:
3251 case SD_BUS_TYPE_INT64:
3252 case SD_BUS_TYPE_UINT64:
3253 case SD_BUS_TYPE_DOUBLE:
3254 case SD_BUS_TYPE_STRING:
3255 case SD_BUS_TYPE_OBJECT_PATH:
2c93b4ef
LP
3256 case SD_BUS_TYPE_SIGNATURE:
3257 case SD_BUS_TYPE_UNIX_FD: {
9a17484d
LP
3258 void *p;
3259
3260 p = va_arg(ap, void*);
3261 r = sd_bus_message_read_basic(m, *t, p);
fe1d424d
LP
3262 if (r < 0)
3263 return r;
430fb8fa
LP
3264 if (r == 0) {
3265 if (n_loop <= 1)
3266 return 0;
3267
fe1d424d 3268 return -ENXIO;
430fb8fa 3269 }
fe1d424d 3270
9a17484d
LP
3271 break;
3272 }
3273
3274 case SD_BUS_TYPE_ARRAY: {
3275 size_t k;
3276
3277 r = signature_element_length(t + 1, &k);
3278 if (r < 0)
3279 return r;
3280
3281 {
9a17484d 3282 char s[k + 1];
9a17484d
LP
3283 memcpy(s, t + 1, k);
3284 s[k] = 0;
9a17484d
LP
3285
3286 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
3287 if (r < 0)
3288 return r;
430fb8fa
LP
3289 if (r == 0) {
3290 if (n_loop <= 1)
3291 return 0;
3292
9a17484d 3293 return -ENXIO;
430fb8fa 3294 }
fe1d424d 3295 }
9a17484d 3296
fe1d424d
LP
3297 if (n_array == (unsigned) -1) {
3298 types += k;
3299 n_struct -= k;
9a17484d
LP
3300 }
3301
fe1d424d
LP
3302 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
3303 if (r < 0)
3304 return r;
3305
3306 types = t + 1;
3307 n_struct = k;
3308 n_array = va_arg(ap, unsigned);
3309
9a17484d
LP
3310 break;
3311 }
3312
3313 case SD_BUS_TYPE_VARIANT: {
3314 const char *s;
3315
3316 s = va_arg(ap, const char *);
3317 if (!s)
3318 return -EINVAL;
3319
3320 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, s);
3321 if (r < 0)
3322 return r;
430fb8fa
LP
3323 if (r == 0) {
3324 if (n_loop <= 1)
3325 return 0;
3326
9a17484d 3327 return -ENXIO;
430fb8fa 3328 }
9a17484d 3329
fe1d424d 3330 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
9a17484d
LP
3331 if (r < 0)
3332 return r;
9a17484d 3333
fe1d424d
LP
3334 types = s;
3335 n_struct = strlen(s);
3336 n_array = (unsigned) -1;
3337
9a17484d
LP
3338 break;
3339 }
3340
3341 case SD_BUS_TYPE_STRUCT_BEGIN:
3342 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
3343 size_t k;
3344
3345 r = signature_element_length(t, &k);
3346 if (r < 0)
3347 return r;
3348
3349 {
3350 char s[k - 1];
3351 memcpy(s, t + 1, k - 2);
3352 s[k - 2] = 0;
3353
3354 r = sd_bus_message_enter_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
3355 if (r < 0)
3356 return r;
430fb8fa
LP
3357 if (r == 0) {
3358 if (n_loop <= 1)
3359 return 0;
9a17484d 3360 return -ENXIO;
430fb8fa 3361 }
fe1d424d 3362 }
9a17484d 3363
fe1d424d
LP
3364 if (n_array == (unsigned) -1) {
3365 types += k - 1;
3366 n_struct -= k - 1;
3367 }
9a17484d 3368
fe1d424d
LP
3369 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
3370 if (r < 0)
3371 return r;
9a17484d 3372
fe1d424d
LP
3373 types = t + 1;
3374 n_struct = k - 2;
3375 n_array = (unsigned) -1;
9a17484d
LP
3376
3377 break;
3378 }
3379
3380 default:
fe1d424d 3381 return -EINVAL;
9a17484d 3382 }
9a17484d
LP
3383 }
3384
3385 return 1;
3386}
3387
d9f644e2 3388_public_ int sd_bus_message_read(sd_bus_message *m, const char *types, ...) {
9a17484d
LP
3389 va_list ap;
3390 int r;
3391
9b07511d
LP
3392 assert_return(m, -EINVAL);
3393 assert_return(m->sealed, -EPERM);
3394 assert_return(types, -EINVAL);
9a17484d
LP
3395
3396 va_start(ap, types);
3397 r = message_read_ap(m, types, ap);
3398 va_end(ap);
3399
3400 return r;
3401}
3402
d9f644e2 3403_public_ int sd_bus_message_skip(sd_bus_message *m, const char *types) {
9b07511d
LP
3404 int r;
3405
3406 assert_return(m, -EINVAL);
3407 assert_return(m->sealed, -EPERM);
3408 assert_return(types, -EINVAL);
3409
3410 if (isempty(types))
3411 return 0;
3412
3413 switch (*types) {
3414
3415 case SD_BUS_TYPE_BYTE:
3416 case SD_BUS_TYPE_BOOLEAN:
3417 case SD_BUS_TYPE_INT16:
3418 case SD_BUS_TYPE_UINT16:
3419 case SD_BUS_TYPE_INT32:
3420 case SD_BUS_TYPE_UINT32:
3421 case SD_BUS_TYPE_INT64:
3422 case SD_BUS_TYPE_UINT64:
3423 case SD_BUS_TYPE_DOUBLE:
3424 case SD_BUS_TYPE_STRING:
3425 case SD_BUS_TYPE_OBJECT_PATH:
3426 case SD_BUS_TYPE_SIGNATURE:
3427 case SD_BUS_TYPE_UNIX_FD:
3428
3429 r = sd_bus_message_read_basic(m, *types, NULL);
3430 if (r <= 0)
3431 return r;
3432
3433 r = sd_bus_message_skip(m, types + 1);
3434 if (r < 0)
3435 return r;
3436
3437 return 1;
3438
3439 case SD_BUS_TYPE_ARRAY: {
3440 size_t k;
3441
3442 r = signature_element_length(types + 1, &k);
3443 if (r < 0)
3444 return r;
3445
3446 {
3447 char s[k+1];
3448 memcpy(s, types+1, k);
3449 s[k] = 0;
3450
3451 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
3452 if (r <= 0)
3453 return r;
3454
3455 for (;;) {
3456 r = sd_bus_message_skip(m, s);
3457 if (r < 0)
3458 return r;
3459 if (r == 0)
3460 break;
3461 }
3462
3463 r = sd_bus_message_exit_container(m);
3464 if (r < 0)
3465 return r;
3466 }
3467
3468 r = sd_bus_message_skip(m, types + 1 + k);
3469 if (r < 0)
3470 return r;
3471
3472 return 1;
3473 }
3474
3475 case SD_BUS_TYPE_VARIANT: {
3476 const char *contents;
3477 char x;
3478
3479 r = sd_bus_message_peek_type(m, &x, &contents);
3480 if (r <= 0)
3481 return r;
3482
3483 if (x != SD_BUS_TYPE_VARIANT)
3484 return -ENXIO;
3485
3486 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
3487 if (r <= 0)
3488 return r;
3489
3490 r = sd_bus_message_skip(m, contents);
3491 if (r < 0)
3492 return r;
3493 assert(r != 0);
3494
3495 r = sd_bus_message_exit_container(m);
3496 if (r < 0)
3497 return r;
3498
3499 r = sd_bus_message_skip(m, types + 1);
3500 if (r < 0)
3501 return r;
3502
3503 return 1;
3504 }
3505
3506 case SD_BUS_TYPE_STRUCT_BEGIN:
3507 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
3508 size_t k;
3509
3510 r = signature_element_length(types, &k);
3511 if (r < 0)
3512 return r;
3513
3514 {
3515 char s[k-1];
3516 memcpy(s, types+1, k-2);
3517 s[k-2] = 0;
3518
3519 r = sd_bus_message_enter_container(m, *types == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
3520 if (r <= 0)
3521 return r;
3522
3523 r = sd_bus_message_skip(m, s);
3524 if (r < 0)
3525 return r;
3526 assert(r != 0);
3527
3528 r = sd_bus_message_exit_container(m);
3529 if (r < 0)
3530 return r;
3531 }
3532
3533 r = sd_bus_message_skip(m, types + k);
3534 if (r < 0)
3535 return r;
3536
3537 return 1;
3538 }
3539
3540 default:
3541 return -EINVAL;
3542 }
3543}
3544
d9f644e2
ZJS
3545_public_ int sd_bus_message_read_array(sd_bus_message *m,
3546 char type,
3547 const void **ptr,
3548 size_t *size) {
b3af9646
LP
3549 struct bus_container *c;
3550 void *p;
3551 size_t sz;
3552 ssize_t align;
3553 int r;
3554
9d6c7c82
LP
3555 assert_return(m, -EINVAL);
3556 assert_return(m->sealed, -EPERM);
3557 assert_return(bus_type_is_trivial(type), -EINVAL);
3558 assert_return(ptr, -EINVAL);
3559 assert_return(size, -EINVAL);
3560 assert_return(!BUS_MESSAGE_NEED_BSWAP(m), -ENOTSUP);
b3af9646
LP
3561
3562 align = bus_type_get_alignment(type);
3563 if (align < 0)
3564 return align;
3565
3566 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
66b26c5c 3567 if (r <= 0)
b3af9646
LP
3568 return r;
3569
3570 c = message_get_container(m);
3571 sz = BUS_MESSAGE_BSWAP32(m, *c->array_size);
3572
3573 r = message_peek_body(m, &m->rindex, align, sz, &p);
3574 if (r < 0)
3575 goto fail;
3576 if (r == 0) {
3577 r = -EBADMSG;
3578 goto fail;
3579 }
3580
3581 r = sd_bus_message_exit_container(m);
3582 if (r < 0)
3583 goto fail;
3584
3585 *ptr = (const void*) p;
3586 *size = sz;
3587
3588 return 1;
3589
3590fail:
3591 message_quit_container(m);
3592 return r;
3593}
3594
80a46c73
LP
3595static int message_peek_fields(
3596 sd_bus_message *m,
3597 size_t *rindex,
3598 size_t align,
3599 size_t nbytes,
3600 void **ret) {
3601
3602 assert(m);
3603 assert(rindex);
3604 assert(align > 0);
3605
c91cb83c 3606 return buffer_peek(BUS_MESSAGE_FIELDS(m), BUS_MESSAGE_FIELDS_SIZE(m), rindex, align, nbytes, ret);
80a46c73
LP
3607}
3608
9f26c90c
LP
3609static int message_peek_field_uint32(
3610 sd_bus_message *m,
3611 size_t *ri,
3612 uint32_t *ret) {
3613
3614 int r;
3615 void *q;
3616
3617 assert(m);
3618 assert(ri);
3619
3620 r = message_peek_fields(m, ri, 4, 4, &q);
3621 if (r < 0)
3622 return r;
3623
3624 if (ret)
3625 *ret = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3626
3627 return 0;
3628}
3629
80a46c73
LP
3630static int message_peek_field_string(
3631 sd_bus_message *m,
6693860f 3632 bool (*validate)(const char *p),
80a46c73
LP
3633 size_t *ri,
3634 const char **ret) {
3635
9f26c90c 3636 uint32_t l;
80a46c73
LP
3637 int r;
3638 void *q;
3639
9a17484d 3640 assert(m);
80a46c73
LP
3641 assert(ri);
3642
9f26c90c 3643 r = message_peek_field_uint32(m, ri, &l);
80a46c73
LP
3644 if (r < 0)
3645 return r;
3646
80a46c73
LP
3647 r = message_peek_fields(m, ri, 1, l+1, &q);
3648 if (r < 0)
3649 return r;
9a17484d 3650
6693860f
LP
3651 if (validate) {
3652 if (!validate_nul(q, l))
3653 return -EBADMSG;
3654
3655 if (!validate(q))
ac89bf1d
LP
3656 return -EBADMSG;
3657 } else {
3658 if (!validate_string(q, l))
3659 return -EBADMSG;
3660 }
80a46c73
LP
3661
3662 if (ret)
3663 *ret = q;
3664
3665 return 0;
3666}
3667
3668static int message_peek_field_signature(
3669 sd_bus_message *m,
3670 size_t *ri,
3671 const char **ret) {
3672
3673 size_t l;
3674 int r;
3675 void *q;
3676
3677 assert(m);
3678 assert(ri);
3679
3680 r = message_peek_fields(m, ri, 1, 1, &q);
3681 if (r < 0)
3682 return r;
3683
3684 l = *(uint8_t*) q;
3685 r = message_peek_fields(m, ri, 1, l+1, &q);
3686 if (r < 0)
3687 return r;
3688
3689 if (!validate_signature(q, l))
3690 return -EBADMSG;
3691
3692 if (ret)
3693 *ret = q;
3694
3695 return 0;
3696}
3697
80a46c73
LP
3698static int message_skip_fields(
3699 sd_bus_message *m,
3700 size_t *ri,
3701 uint32_t array_size,
3702 const char **signature) {
3703
3704 size_t original_index;
3705 int r;
3706
3707 assert(m);
3708 assert(ri);
3709 assert(signature);
3710
3711 original_index = *ri;
3712
3713 for (;;) {
3714 char t;
80a46c73
LP
3715 size_t l;
3716
3717 if (array_size != (uint32_t) -1 &&
3718 array_size <= *ri - original_index)
3719 return 0;
3720
3721 t = **signature;
3722 if (!t)
3723 return 0;
3724
6693860f
LP
3725 if (t == SD_BUS_TYPE_STRING) {
3726
3727 r = message_peek_field_string(m, NULL, ri, NULL);
3728 if (r < 0)
3729 return r;
3730
3731 (*signature)++;
3732
3733 } else if (t == SD_BUS_TYPE_OBJECT_PATH) {
80a46c73 3734
6693860f 3735 r = message_peek_field_string(m, object_path_is_valid, ri, NULL);
80a46c73
LP
3736 if (r < 0)
3737 return r;
3738
3739 (*signature)++;
3740
3741 } else if (t == SD_BUS_TYPE_SIGNATURE) {
3742
3743 r = message_peek_field_signature(m, ri, NULL);
3744 if (r < 0)
3745 return r;
3746
3747 (*signature)++;
3748
3749 } else if (bus_type_is_basic(t)) {
27f6e5c7 3750 ssize_t align, k;
80a46c73 3751
c66a2e0c
TG
3752 align = bus_type_get_alignment(t);
3753 k = bus_type_get_size(t);
27f6e5c7 3754 assert(align > 0 && k > 0);
80a46c73
LP
3755
3756 r = message_peek_fields(m, ri, align, k, NULL);
3757 if (r < 0)
3758 return r;
9a17484d 3759
80a46c73
LP
3760 (*signature)++;
3761
3762 } else if (t == SD_BUS_TYPE_ARRAY) {
3763
3764 r = signature_element_length(*signature+1, &l);
3765 if (r < 0)
3766 return r;
3767
3768 assert(l >= 1);
3769 {
3770 char sig[l-1], *s;
9f26c90c 3771 uint32_t nas;
80a46c73
LP
3772 int alignment;
3773
3774 strncpy(sig, *signature + 1, l-1);
3775 s = sig;
3776
3777 alignment = bus_type_get_alignment(sig[0]);
3778 if (alignment < 0)
3779 return alignment;
3780
9f26c90c 3781 r = message_peek_field_uint32(m, ri, &nas);
80a46c73
LP
3782 if (r < 0)
3783 return r;
ac89bf1d 3784 if (nas > BUS_ARRAY_MAX_SIZE)
80a46c73
LP
3785 return -EBADMSG;
3786
3787 r = message_peek_fields(m, ri, alignment, 0, NULL);
3788 if (r < 0)
3789 return r;
3790
3791 r = message_skip_fields(m, ri, nas, (const char**) &s);
3792 if (r < 0)
3793 return r;
3794 }
3795
3796 (*signature) += 1 + l;
3797
3798 } else if (t == SD_BUS_TYPE_VARIANT) {
3799 const char *s;
3800
3801 r = message_peek_field_signature(m, ri, &s);
3802 if (r < 0)
3803 return r;
3804
3805 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
3806 if (r < 0)
3807 return r;
3808
3809 (*signature)++;
3810
3811 } else if (t == SD_BUS_TYPE_STRUCT ||
3812 t == SD_BUS_TYPE_DICT_ENTRY) {
3813
3814 r = signature_element_length(*signature, &l);
3815 if (r < 0)
3816 return r;
3817
3818 assert(l >= 2);
3819 {
3820 char sig[l-1], *s;
3821 strncpy(sig, *signature + 1, l-1);
3822 s = sig;
3823
3824 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
3825 if (r < 0)
3826 return r;
3827 }
3828
3829 *signature += l;
3830 } else
3831 return -EINVAL;
3832 }
3833}
3834
6629161f 3835int bus_message_parse_fields(sd_bus_message *m) {
80a46c73
LP
3836 size_t ri;
3837 int r;
2c93b4ef 3838 uint32_t unix_fds = 0;
80a46c73
LP
3839
3840 assert(m);
3841
3842 for (ri = 0; ri < BUS_MESSAGE_FIELDS_SIZE(m); ) {
3843 const char *signature;
3844 uint8_t *header;
3845
3846 r = message_peek_fields(m, &ri, 8, 1, (void**) &header);
3847 if (r < 0)
3848 return r;
3849
3850 r = message_peek_field_signature(m, &ri, &signature);
3851 if (r < 0)
3852 return r;
3853
3854 switch (*header) {
3855 case _SD_BUS_MESSAGE_HEADER_INVALID:
3856 return -EBADMSG;
3857
3858 case SD_BUS_MESSAGE_HEADER_PATH:
2c93b4ef
LP
3859
3860 if (m->path)
3861 return -EBADMSG;
3862
80a46c73
LP
3863 if (!streq(signature, "o"))
3864 return -EBADMSG;
3865
6693860f 3866 r = message_peek_field_string(m, object_path_is_valid, &ri, &m->path);
80a46c73
LP
3867 break;
3868
3869 case SD_BUS_MESSAGE_HEADER_INTERFACE:
2c93b4ef
LP
3870
3871 if (m->interface)
3872 return -EBADMSG;
3873
80a46c73
LP
3874 if (!streq(signature, "s"))
3875 return -EBADMSG;
3876
6693860f 3877 r = message_peek_field_string(m, interface_name_is_valid, &ri, &m->interface);
80a46c73
LP
3878 break;
3879
3880 case SD_BUS_MESSAGE_HEADER_MEMBER:
2c93b4ef
LP
3881
3882 if (m->member)
3883 return -EBADMSG;
3884
80a46c73
LP
3885 if (!streq(signature, "s"))
3886 return -EBADMSG;
3887
6693860f 3888 r = message_peek_field_string(m, member_name_is_valid, &ri, &m->member);
80a46c73
LP
3889 break;
3890
3891 case SD_BUS_MESSAGE_HEADER_ERROR_NAME:
2c93b4ef
LP
3892
3893 if (m->error.name)
3894 return -EBADMSG;
3895
80a46c73
LP
3896 if (!streq(signature, "s"))
3897 return -EBADMSG;
3898
6693860f 3899 r = message_peek_field_string(m, error_name_is_valid, &ri, &m->error.name);
80a46c73
LP
3900 break;
3901
3902 case SD_BUS_MESSAGE_HEADER_DESTINATION:
2c93b4ef
LP
3903
3904 if (m->destination)
3905 return -EBADMSG;
3906
80a46c73
LP
3907 if (!streq(signature, "s"))
3908 return -EBADMSG;
3909
6693860f 3910 r = message_peek_field_string(m, service_name_is_valid, &ri, &m->destination);
80a46c73
LP
3911 break;
3912
3913 case SD_BUS_MESSAGE_HEADER_SENDER:
2c93b4ef
LP
3914
3915 if (m->sender)
3916 return -EBADMSG;
3917
80a46c73
LP
3918 if (!streq(signature, "s"))
3919 return -EBADMSG;
3920
6693860f 3921 r = message_peek_field_string(m, service_name_is_valid, &ri, &m->sender);
80a46c73
LP
3922 break;
3923
3924
3925 case SD_BUS_MESSAGE_HEADER_SIGNATURE: {
3926 const char *s;
3927 char *c;
3928
2c93b4ef
LP
3929 if (m->root_container.signature)
3930 return -EBADMSG;
3931
80a46c73
LP
3932 if (!streq(signature, "g"))
3933 return -EBADMSG;
3934
3935 r = message_peek_field_signature(m, &ri, &s);
3936 if (r < 0)
3937 return r;
3938
3939 c = strdup(s);
3940 if (!c)
3941 return -ENOMEM;
3942
3943 free(m->root_container.signature);
3944 m->root_container.signature = c;
80a46c73
LP
3945 break;
3946 }
3947
3948 case SD_BUS_MESSAGE_HEADER_REPLY_SERIAL:
2c93b4ef
LP
3949 if (m->reply_serial != 0)
3950 return -EBADMSG;
3951
80a46c73
LP
3952 if (!streq(signature, "u"))
3953 return -EBADMSG;
3954
3955 r = message_peek_field_uint32(m, &ri, &m->reply_serial);
6693860f
LP
3956 if (r < 0)
3957 return r;
3958
3959 if (m->reply_serial == 0)
3960 return -EBADMSG;
3961
80a46c73
LP
3962 break;
3963
2c93b4ef
LP
3964 case SD_BUS_MESSAGE_HEADER_UNIX_FDS:
3965 if (unix_fds != 0)
3966 return -EBADMSG;
3967
3968 if (!streq(signature, "u"))
3969 return -EBADMSG;
3970
3971 r = message_peek_field_uint32(m, &ri, &unix_fds);
3972 if (r < 0)
3973 return -EBADMSG;
3974
3975 if (unix_fds == 0)
3976 return -EBADMSG;
3977
3978 break;
3979
80a46c73
LP
3980 default:
3981 r = message_skip_fields(m, &ri, (uint32_t) -1, (const char **) &signature);
3982 }
3983
3984 if (r < 0)
3985 return r;
3986 }
3987
2c93b4ef
LP
3988 if (m->n_fds != unix_fds)
3989 return -EBADMSG;
3990
80a46c73
LP
3991 if (isempty(m->root_container.signature) != (BUS_MESSAGE_BODY_SIZE(m) == 0))
3992 return -EBADMSG;
3993
3994 switch (m->header->type) {
3995
40ca29a1 3996 case SD_BUS_MESSAGE_SIGNAL:
80a46c73
LP
3997 if (!m->path || !m->interface || !m->member)
3998 return -EBADMSG;
3999 break;
4000
40ca29a1 4001 case SD_BUS_MESSAGE_METHOD_CALL:
80a46c73
LP
4002
4003 if (!m->path || !m->member)
4004 return -EBADMSG;
4005
4006 break;
4007
40ca29a1 4008 case SD_BUS_MESSAGE_METHOD_RETURN:
80a46c73
LP
4009
4010 if (m->reply_serial == 0)
4011 return -EBADMSG;
4012 break;
4013
40ca29a1 4014 case SD_BUS_MESSAGE_METHOD_ERROR:
80a46c73
LP
4015
4016 if (m->reply_serial == 0 || !m->error.name)
4017 return -EBADMSG;
4018 break;
4019 }
9a17484d 4020
89ffcd2a 4021 /* Try to read the error message, but if we can't it's a non-issue */
40ca29a1 4022 if (m->header->type == SD_BUS_MESSAGE_METHOD_ERROR)
89ffcd2a
LP
4023 sd_bus_message_read(m, "s", &m->error.message);
4024
9a17484d
LP
4025 return 0;
4026}
4027
9a17484d 4028int bus_message_seal(sd_bus_message *m, uint64_t serial) {
47e6ce32 4029 struct bus_body_part *part;
69aec65c 4030 size_t l, a;
47e6ce32
LP
4031 unsigned i;
4032 int r;
9a17484d
LP
4033
4034 assert(m);
4035
4036 if (m->sealed)
4037 return -EPERM;
4038
4039 if (m->n_containers > 0)
4040 return -EBADMSG;
4041
13c299d3
LP
4042 if (m->poisoned)
4043 return -ESTALE;
4044
9a17484d
LP
4045 /* If there's a non-trivial signature set, then add it in here */
4046 if (!isempty(m->root_container.signature)) {
80a46c73 4047 r = message_append_field_signature(m, SD_BUS_MESSAGE_HEADER_SIGNATURE, m->root_container.signature, NULL);
9a17484d
LP
4048 if (r < 0)
4049 return r;
4050 }
4051
4052 if (m->n_fds > 0) {
4053 r = message_append_field_uint32(m, SD_BUS_MESSAGE_HEADER_UNIX_FDS, m->n_fds);
4054 if (r < 0)
4055 return r;
4056 }
4057
66b26c5c
LP
4058 /* Add padding at the end of the fields part, since we know
4059 * the body needs to start at an 8 byte alignment. We made
4060 * sure we allocated enough space for this, so all we need to
4061 * do here is to zero it out. */
69aec65c
LP
4062 l = BUS_MESSAGE_FIELDS_SIZE(m);
4063 a = ALIGN8(l) - l;
c91cb83c
LP
4064 if (a > 0)
4065 memset((uint8_t*) BUS_MESSAGE_FIELDS(m) + l, 0, a);
69aec65c 4066
66b26c5c
LP
4067 /* If this is something we can send as memfd, then let's seal
4068 the memfd now. Note that we can send memfds as payload only
4069 for directed messages, and not for broadcasts. */
8f155917 4070 if (m->destination && m->bus && m->bus->use_memfd) {
66b26c5c 4071 MESSAGE_FOREACH_PART(part, i, m)
8f155917 4072 if (part->memfd >= 0 && !part->sealed && (part->size > MEMFD_MIN_SIZE || m->bus->use_memfd < 0)) {
66b26c5c 4073 bus_body_part_unmap(part);
a392d361 4074
66b26c5c
LP
4075 if (ioctl(part->memfd, KDBUS_CMD_MEMFD_SEAL_SET, 1) >= 0)
4076 part->sealed = true;
4077 }
4078 }
47e6ce32 4079
9a17484d
LP
4080 m->header->serial = serial;
4081 m->sealed = true;
4082
9a17484d
LP
4083 return 0;
4084}
4085
d9f644e2 4086_public_ int sd_bus_message_set_destination(sd_bus_message *m, const char *destination) {
9d6c7c82
LP
4087 assert_return(m, -EINVAL);
4088 assert_return(destination, -EINVAL);
4089 assert_return(!m->sealed, -EPERM);
4090 assert_return(!m->destination, -EEXIST);
9a17484d
LP
4091
4092 return message_append_field_string(m, SD_BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &m->destination);
4093}
4094
c430fee6 4095int bus_message_dump(sd_bus_message *m, FILE *f, bool with_header) {
d8d3d8a7 4096 const char *u = NULL, *uu = NULL, *s = NULL;
77930f11 4097 char **cmdline = NULL;
9a17484d
LP
4098 unsigned level = 1;
4099 int r;
120f919e
LP
4100 uid_t owner, audit_loginuid;
4101 uint32_t audit_sessionid;
9a17484d
LP
4102
4103 assert(m);
4104
c430fee6
LP
4105 if (!f)
4106 f = stdout;
4107
4108 if (with_header) {
4109 fprintf(f,
4110 "Message %p\n"
4111 "\tn_ref=%u\n"
4112 "\tendian=%c\n"
4113 "\ttype=%i\n"
4114 "\tflags=%u\n"
4115 "\tversion=%u\n"
4116 "\tserial=%u\n"
4117 "\tfields_size=%u\n"
4118 "\tbody_size=%u\n"
4119 "\tpath=%s\n"
4120 "\tinterface=%s\n"
4121 "\tmember=%s\n"
4122 "\tdestination=%s\n"
4123 "\tsender=%s\n"
4124 "\tsignature=%s\n"
4125 "\treply_serial=%u\n"
c430fee6
LP
4126 "\tsealed=%s\n"
4127 "\tn_body_parts=%u\n",
4128 m,
4129 m->n_ref,
4130 m->header->endian,
4131 m->header->type,
4132 m->header->flags,
4133 m->header->version,
4134 BUS_MESSAGE_SERIAL(m),
4135 BUS_MESSAGE_FIELDS_SIZE(m),
4136 BUS_MESSAGE_BODY_SIZE(m),
4137 strna(m->path),
4138 strna(m->interface),
4139 strna(m->member),
4140 strna(m->destination),
4141 strna(m->sender),
4142 strna(m->root_container.signature),
4143 m->reply_serial,
c430fee6
LP
4144 yes_no(m->sealed),
4145 m->n_body_parts);
4146
3fc047f4
LP
4147 if (sd_bus_error_is_set(&m->error))
4148 fprintf(f,
4149 "\terror.name=%s\n"
4150 "\terror.message=%s\n",
4151 strna(m->error.name),
4152 strna(m->error.message));
4153
c430fee6
LP
4154 if (m->pid != 0)
4155 fprintf(f, "\tpid=%lu\n", (unsigned long) m->pid);
4156 if (m->tid != 0)
4157 fprintf(f, "\ttid=%lu\n", (unsigned long) m->tid);
4158 if (m->uid_valid)
4159 fprintf(f, "\tuid=%lu\n", (unsigned long) m->uid);
4160 if (m->gid_valid)
4161 fprintf(f, "\tgid=%lu\n", (unsigned long) m->gid);
4162 if (m->pid_starttime != 0)
4163 fprintf(f, "\tpid_starttime=%llu\n", (unsigned long long) m->pid_starttime);
4164 if (m->monotonic != 0)
4165 fprintf(f, "\tmonotonic=%llu\n", (unsigned long long) m->monotonic);
4166 if (m->realtime != 0)
4167 fprintf(f, "\trealtime=%llu\n", (unsigned long long) m->realtime);
4168 if (m->exe)
4169 fprintf(f, "\texe=[%s]\n", m->exe);
4170 if (m->comm)
4171 fprintf(f, "\tcomm=[%s]\n", m->comm);
4172 if (m->tid_comm)
4173 fprintf(f, "\ttid_comm=[%s]\n", m->tid_comm);
4174 if (m->label)
4175 fprintf(f, "\tlabel=[%s]\n", m->label);
4176 if (m->cgroup)
4177 fprintf(f, "\tcgroup=[%s]\n", m->cgroup);
4178
4179 sd_bus_message_get_unit(m, &u);
4180 if (u)
4181 fprintf(f, "\tunit=[%s]\n", u);
4182 sd_bus_message_get_user_unit(m, &uu);
4183 if (uu)
4184 fprintf(f, "\tuser_unit=[%s]\n", uu);
4185 sd_bus_message_get_session(m, &s);
4186 if (s)
4187 fprintf(f, "\tsession=[%s]\n", s);
4188 if (sd_bus_message_get_owner_uid(m, &owner) >= 0)
4189 fprintf(f, "\towner_uid=%lu\n", (unsigned long) owner);
4190 if (sd_bus_message_get_audit_loginuid(m, &audit_loginuid) >= 0)
4191 fprintf(f, "\taudit_loginuid=%lu\n", (unsigned long) audit_loginuid);
4192 if (sd_bus_message_get_audit_sessionid(m, &audit_sessionid) >= 0)
4193 fprintf(f, "\taudit_sessionid=%lu\n", (unsigned long) audit_sessionid);
4194
3fc047f4
LP
4195 r = sd_bus_message_has_effective_cap(m, 5);
4196 if (r >= 0)
4197 fprintf(f, "\tCAP_KILL=%s\n", yes_no(r));
c430fee6
LP
4198
4199 if (sd_bus_message_get_cmdline(m, &cmdline) >= 0) {
4200 char **c;
4201
4202 fputs("\tcmdline=[", f);
4203 STRV_FOREACH(c, cmdline) {
4204 if (c != cmdline)
4205 fputc(' ', f);
4206
4207 fputs(*c, f);
4208 }
77930f11 4209
c430fee6
LP
4210 fputs("]\n", f);
4211 }
77930f11
LP
4212 }
4213
9a17484d
LP
4214 r = sd_bus_message_rewind(m, true);
4215 if (r < 0) {
4216 log_error("Failed to rewind: %s", strerror(-r));
4217 return r;
4218 }
4219
c430fee6 4220 fprintf(f, "BEGIN_MESSAGE \"%s\" {\n", strempty(m->root_container.signature));
9a17484d
LP
4221
4222 for(;;) {
4223 _cleanup_free_ char *prefix = NULL;
4224 const char *contents = NULL;
4225 char type;
4226 union {
4227 uint8_t u8;
4228 uint16_t u16;
4229 int16_t s16;
4230 uint32_t u32;
4231 int32_t s32;
4232 uint64_t u64;
4233 int64_t s64;
4234 double d64;
4235 const char *string;
4236 int i;
4237 } basic;
4238
4239 r = sd_bus_message_peek_type(m, &type, &contents);
4240 if (r < 0) {
4241 log_error("Failed to peek type: %s", strerror(-r));
4242 return r;
4243 }
4244 if (r == 0) {
4245 if (level <= 1)
4246 break;
4247
4248 r = sd_bus_message_exit_container(m);
4249 if (r < 0) {
4250 log_error("Failed to exit container: %s", strerror(-r));
4251 return r;
4252 }
4253
4254 level--;
4255
4256 prefix = strrep("\t", level);
4257 if (!prefix)
4258 return log_oom();
4259
4260 if (type == SD_BUS_TYPE_ARRAY)
c430fee6 4261 fprintf(f, "%s} END_ARRAY \n", prefix);
9a17484d 4262 else if (type == SD_BUS_TYPE_VARIANT)
c430fee6 4263 fprintf(f, "%s} END_VARIANT\n", prefix);
9a17484d 4264 else if (type == SD_BUS_TYPE_STRUCT)
c430fee6 4265 fprintf(f, "%s} END_STRUCT\n", prefix);
9a17484d 4266 else if (type == SD_BUS_TYPE_DICT_ENTRY)
c430fee6 4267 fprintf(f, "%s} END_DICT_ENTRY\n", prefix);
9a17484d
LP
4268
4269 continue;
4270 }
4271
4272 prefix = strrep("\t", level);
4273 if (!prefix)
4274 return log_oom();
4275
4276 if (bus_type_is_container(type) > 0) {
4277 r = sd_bus_message_enter_container(m, type, contents);
4278 if (r < 0) {
4279 log_error("Failed to enter container: %s", strerror(-r));
4280 return r;
4281 }
4282
4283 if (type == SD_BUS_TYPE_ARRAY)
c430fee6 4284 fprintf(f, "%sBEGIN_ARRAY \"%s\" {\n", prefix, contents);
9a17484d 4285 else if (type == SD_BUS_TYPE_VARIANT)
c430fee6 4286 fprintf(f, "%sBEGIN_VARIANT \"%s\" {\n", prefix, contents);
9a17484d 4287 else if (type == SD_BUS_TYPE_STRUCT)
c430fee6 4288 fprintf(f, "%sBEGIN_STRUCT \"%s\" {\n", prefix, contents);
9a17484d 4289 else if (type == SD_BUS_TYPE_DICT_ENTRY)
c430fee6 4290 fprintf(f, "%sBEGIN_DICT_ENTRY \"%s\" {\n", prefix, contents);
9a17484d
LP
4291
4292 level ++;
4293
4294 continue;
4295 }
4296
4297 r = sd_bus_message_read_basic(m, type, &basic);
4298 if (r < 0) {
4299 log_error("Failed to get basic: %s", strerror(-r));
4300 return r;
4301 }
4302
c430fee6
LP
4303 assert(r > 0);
4304
9a17484d
LP
4305 switch (type) {
4306
4307 case SD_BUS_TYPE_BYTE:
c430fee6 4308 fprintf(f, "%sBYTE: %u\n", prefix, basic.u8);
9a17484d
LP
4309 break;
4310
4311 case SD_BUS_TYPE_BOOLEAN:
c430fee6 4312 fprintf(f, "%sBOOLEAN: %s\n", prefix, yes_no(basic.i));
9a17484d
LP
4313 break;
4314
4315 case SD_BUS_TYPE_INT16:
c430fee6 4316 fprintf(f, "%sINT16: %i\n", prefix, basic.s16);
9a17484d
LP
4317 break;
4318
4319 case SD_BUS_TYPE_UINT16:
c430fee6 4320 fprintf(f, "%sUINT16: %u\n", prefix, basic.u16);
9a17484d
LP
4321 break;
4322
4323 case SD_BUS_TYPE_INT32:
c430fee6 4324 fprintf(f, "%sINT32: %i\n", prefix, basic.s32);
9a17484d
LP
4325 break;
4326
4327 case SD_BUS_TYPE_UINT32:
c430fee6 4328 fprintf(f, "%sUINT32: %u\n", prefix, basic.u32);
9a17484d
LP
4329 break;
4330
4331 case SD_BUS_TYPE_INT64:
c430fee6 4332 fprintf(f, "%sINT64: %lli\n", prefix, (long long) basic.s64);
9a17484d
LP
4333 break;
4334
4335 case SD_BUS_TYPE_UINT64:
c430fee6 4336 fprintf(f, "%sUINT64: %llu\n", prefix, (unsigned long long) basic.u64);
9a17484d
LP
4337 break;
4338
4339 case SD_BUS_TYPE_DOUBLE:
c430fee6 4340 fprintf(f, "%sDOUBLE: %g\n", prefix, basic.d64);
9a17484d
LP
4341 break;
4342
4343 case SD_BUS_TYPE_STRING:
c430fee6 4344 fprintf(f, "%sSTRING: \"%s\"\n", prefix, basic.string);
9a17484d
LP
4345 break;
4346
4347 case SD_BUS_TYPE_OBJECT_PATH:
c430fee6 4348 fprintf(f, "%sOBJECT_PATH: \"%s\"\n", prefix, basic.string);
9a17484d
LP
4349 break;
4350
4351 case SD_BUS_TYPE_SIGNATURE:
c430fee6 4352 fprintf(f, "%sSIGNATURE: \"%s\"\n", prefix, basic.string);
9a17484d
LP
4353 break;
4354
4355 case SD_BUS_TYPE_UNIX_FD:
c430fee6 4356 fprintf(f, "%sUNIX_FD: %i\n", prefix, basic.i);
9a17484d
LP
4357 break;
4358
4359 default:
4360 assert_not_reached("Unknown basic type.");
4361 }
4362 }
4363
c430fee6 4364 fprintf(f, "} END_MESSAGE\n");
9a17484d 4365 return 0;
de1c301e
LP
4366}
4367
4368int bus_message_get_blob(sd_bus_message *m, void **buffer, size_t *sz) {
4369 size_t total;
de1c301e 4370 void *p, *e;
bc7fd8cd
LP
4371 unsigned i;
4372 struct bus_body_part *part;
de1c301e
LP
4373
4374 assert(m);
4375 assert(buffer);
4376 assert(sz);
4377
6629161f 4378 total = BUS_MESSAGE_SIZE(m);
de1c301e
LP
4379
4380 p = malloc(total);
4381 if (!p)
4382 return -ENOMEM;
4383
c91cb83c 4384 e = mempcpy(p, m->header, BUS_MESSAGE_BODY_BEGIN(m));
9b29bb68 4385 MESSAGE_FOREACH_PART(part, i, m)
bc7fd8cd 4386 e = mempcpy(e, part->data, part->size);
2100fa10
LP
4387
4388 assert(total == (size_t) ((uint8_t*) e - (uint8_t*) p));
de1c301e
LP
4389
4390 *buffer = p;
4391 *sz = total;
4392
4393 return 0;
4394}
89ffcd2a
LP
4395
4396int bus_message_read_strv_extend(sd_bus_message *m, char ***l) {
4397 int r;
4398
4399 assert(m);
4400 assert(l);
4401
4402 r = sd_bus_message_enter_container(m, 'a', "s");
4686d1b6 4403 if (r <= 0)
89ffcd2a
LP
4404 return r;
4405
4406 for (;;) {
4407 const char *s;
4408
4409 r = sd_bus_message_read_basic(m, 's', &s);
4410 if (r < 0)
4411 return r;
4412 if (r == 0)
4413 break;
4414
4415 r = strv_extend(l, s);
4416 if (r < 0)
4417 return r;
4418 }
4419
4420 r = sd_bus_message_exit_container(m);
4421 if (r < 0)
4422 return r;
4423
4424 return 0;
4425}
392d5b37 4426
4686d1b6
MAP
4427int sd_bus_message_read_strv(sd_bus_message *m, char ***l) {
4428 char **strv = NULL;
4429 int r;
4430
4431 assert_return(m, -EINVAL);
4432 assert_return(m->sealed, -EPERM);
4433 assert_return(l, -EINVAL);
4434
4435 r = bus_message_read_strv_extend(m, &strv);
4436 if (r <= 0) {
4437 strv_free(strv);
4438 return r;
4439 }
4440
4441 *l = strv;
4442 return 1;
4443}
4444
392d5b37
LP
4445const char* bus_message_get_arg(sd_bus_message *m, unsigned i) {
4446 int r;
42c5aaf3
LP
4447 const char *t = NULL;
4448 unsigned j;
392d5b37
LP
4449
4450 assert(m);
4451
4452 r = sd_bus_message_rewind(m, true);
4453 if (r < 0)
4454 return NULL;
4455
42c5aaf3
LP
4456 for (j = 0; j <= i; j++) {
4457 char type;
4458
392d5b37
LP
4459 r = sd_bus_message_peek_type(m, &type, NULL);
4460 if (r < 0)
4461 return NULL;
4462
4463 if (type != SD_BUS_TYPE_STRING &&
4464 type != SD_BUS_TYPE_OBJECT_PATH &&
4465 type != SD_BUS_TYPE_SIGNATURE)
4466 return NULL;
4467
4468 r = sd_bus_message_read_basic(m, type, &t);
4469 if (r < 0)
4470 return NULL;
392d5b37
LP
4471 }
4472
392d5b37
LP
4473 return t;
4474}
2100fa10 4475
c91cb83c
LP
4476bool bus_header_is_complete(struct bus_header *h, size_t size) {
4477 size_t full;
4478
4479 assert(h);
4480 assert(size);
4481
4482 if (size < sizeof(struct bus_header))
4483 return false;
4484
4485 full = sizeof(struct bus_header) +
4486 (h->endian == SD_BUS_NATIVE_ENDIAN ? h->fields_size : bswap_32(h->fields_size));
4487
4488 return size >= full;
4489}
4490
4491int bus_header_message_size(struct bus_header *h, size_t *sum) {
6629161f
LP
4492 size_t fs, bs;
4493
4494 assert(h);
4495 assert(sum);
4496
4497 if (h->endian == SD_BUS_NATIVE_ENDIAN) {
4498 fs = h->fields_size;
4499 bs = h->body_size;
4500 } else if (h->endian == SD_BUS_REVERSE_ENDIAN) {
4501 fs = bswap_32(h->fields_size);
4502 bs = bswap_32(h->body_size);
4503 } else
4504 return -EBADMSG;
2100fa10 4505
6629161f
LP
4506 *sum = sizeof(struct bus_header) + ALIGN8(fs) + bs;
4507 return 0;
2100fa10 4508}
eb01ba5d 4509
d9f644e2 4510_public_ int sd_bus_message_get_errno(sd_bus_message *m) {
40ca29a1 4511 assert_return(m, -EINVAL);
eb01ba5d 4512
40ca29a1 4513 if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
eb01ba5d
LP
4514 return 0;
4515
40ca29a1 4516 return sd_bus_error_get_errno(&m->error);
eb01ba5d 4517}
29ddb38f 4518
d9f644e2 4519_public_ const char* sd_bus_message_get_signature(sd_bus_message *m, int complete) {
29ddb38f
LP
4520 struct bus_container *c;
4521
9d6c7c82 4522 assert_return(m, NULL);
29ddb38f
LP
4523
4524 c = complete ? &m->root_container : message_get_container(m);
40ca29a1 4525 return c->signature ?: "";
29ddb38f 4526}
c430fee6 4527
d9f644e2 4528_public_ int sd_bus_message_copy(sd_bus_message *m, sd_bus_message *source, int all) {
c430fee6
LP
4529 bool done_something = false;
4530 int r;
4531
80ba3b84
LP
4532 assert_return(m, -EINVAL);
4533 assert_return(source, -EINVAL);
4534 assert_return(!m->sealed, -EPERM);
4535 assert_return(source->sealed, -EPERM);
4536
c430fee6
LP
4537 do {
4538 const char *contents;
4539 char type;
4540 union {
4541 uint8_t u8;
4542 uint16_t u16;
4543 int16_t s16;
4544 uint32_t u32;
4545 int32_t s32;
4546 uint64_t u64;
4547 int64_t s64;
4548 double d64;
4549 const char *string;
4550 int i;
4551 } basic;
4552
4553 r = sd_bus_message_peek_type(source, &type, &contents);
4554 if (r < 0)
4555 return r;
4556 if (r == 0)
4557 break;
4558
4559 done_something = true;
4560
4561 if (bus_type_is_container(type) > 0) {
4562
4563 r = sd_bus_message_enter_container(source, type, contents);
4564 if (r < 0)
4565 return r;
4566
4567 r = sd_bus_message_open_container(m, type, contents);
4568 if (r < 0)
4569 return r;
4570
4571 r = sd_bus_message_copy(m, source, true);
4572 if (r < 0)
4573 return r;
4574
4575 r = sd_bus_message_close_container(m);
4576 if (r < 0)
4577 return r;
4578
4579 r = sd_bus_message_exit_container(source);
4580 if (r < 0)
4581 return r;
4582
4583 continue;
4584 }
4585
4586 r = sd_bus_message_read_basic(source, type, &basic);
4587 if (r < 0)
4588 return r;
4589
4590 assert(r > 0);
4591
4592 if (type == SD_BUS_TYPE_OBJECT_PATH ||
4593 type == SD_BUS_TYPE_SIGNATURE ||
4594 type == SD_BUS_TYPE_STRING)
4595 r = sd_bus_message_append_basic(m, type, basic.string);
4596 else
4597 r = sd_bus_message_append_basic(m, type, &basic);
4598
4599 if (r < 0)
4600 return r;
4601
4602 } while (all);
4603
4604 return done_something;
4605}
4606
d9f644e2 4607_public_ int sd_bus_message_verify_type(sd_bus_message *m, char type, const char *contents) {
c430fee6
LP
4608 const char *c;
4609 char t;
4610 int r;
4611
4612 assert_return(m, -EINVAL);
4613 assert_return(m->sealed, -EPERM);
4614 assert_return(!type || bus_type_is_valid(type), -EINVAL);
4615 assert_return(!contents || signature_is_valid(contents, true), -EINVAL);
4616 assert_return(type || contents, -EINVAL);
4617 assert_return(!contents || !type || bus_type_is_container(type), -EINVAL);
4618
4619 r = sd_bus_message_peek_type(m, &t, &c);
4620 if (r <= 0)
4621 return r;
4622
4623 if (type != 0 && type != t)
4624 return 0;
4625
4626 if (contents && !streq_ptr(contents, c))
4627 return 0;
4628
4629 return 1;
4630}