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