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