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