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