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