chiark / gitweb /
4c5588cf8a6653f8d0f2167daad5ef747d07e3f2
[elogind.git] / src / libsystemd-bus / bus-message.c
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>
23
24 #include "util.h"
25
26 #include "bus-message.h"
27 #include "sd-bus.h"
28 #include "bus-internal.h"
29 #include "bus-type.h"
30 #include "bus-signature.h"
31
32 int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored);
33
34 static void message_free(sd_bus_message *m) {
35         unsigned i;
36
37         assert(m);
38
39         if (m->free_header)
40                 free(m->header);
41
42         if (m->free_fields)
43                 free(m->fields);
44
45         if (m->free_body)
46                 free(m->body);
47
48         for (i = 0; i < m->n_fds; i++)
49                 close_nointr_nofail(m->fds[i]);
50
51         for (i = 0; i < m->n_containers; i++)
52                 free(m->sub_containers[i].signature);
53
54         free(m->sub_containers);
55         free(m);
56 }
57
58 static void* buffer_extend(void **p, uint32_t *sz, size_t align, size_t extend) {
59         size_t start, n;
60         void *k;
61
62         assert(p);
63         assert(sz);
64         assert(align > 0);
65
66         start = ALIGN_TO((size_t) *sz, align);
67         n = start + extend;
68
69         if (n == *sz)
70                 return (uint8_t*) *p + start;
71
72         if (n > (size_t) ((uint32_t) -1))
73                 return NULL;
74
75         k = realloc(*p, n);
76         if (!k)
77                 return NULL;
78
79         /* Zero out padding */
80         if (start > *sz)
81                 memset((uint8_t*) k + *sz, 0, start - *sz);
82
83         *p = k;
84         *sz = n;
85
86         return (uint8_t*) k + start;
87 }
88
89 static void *message_extend_fields(sd_bus_message *m, size_t align, size_t sz) {
90         void *p, *o;
91
92         assert(m);
93
94         o = m->fields;
95         p = buffer_extend(&m->fields, &m->header->fields_size, align, sz);
96         if (!p)
97                 return NULL;
98
99         if (o != m->fields) {
100                 /* Adjust quick access pointers */
101
102                 if (m->path)
103                         m->path = (const char*) m->fields + (m->path - (const char*) o);
104                 if (m->interface)
105                         m->interface = (const char*) m->fields + (m->interface - (const char*) o);
106                 if (m->member)
107                         m->member = (const char*) m->fields + (m->member - (const char*) o);
108                 if (m->destination)
109                         m->destination = (const char*) m->fields + (m->destination - (const char*) o);
110                 if (m->sender)
111                         m->sender = (const char*) m->fields + (m->sender - (const char*) o);
112                 if (m->signature)
113                         m->signature = (const char*) m->fields + (m->signature - (const char*) o);
114                 if (m->error.name)
115                         m->error.name = (const char*) m->fields + (m->error.name - (const char*) o);
116         }
117
118         m->free_fields = true;
119
120         return p;
121 }
122
123 static int message_append_field_string(
124                 sd_bus_message *m,
125                 uint8_t h,
126                 char type,
127                 const char *s,
128                 const char **ret) {
129
130         size_t l;
131         uint8_t *p;
132
133         assert(m);
134
135         l = strlen(s);
136         if (l > (size_t) (uint32_t) -1)
137                 return -EINVAL;
138
139         /* field id byte + signature length + signature 's' + NUL + string length + string + NUL */
140         p = message_extend_fields(m, 8, 4 + 4 + l + 1);
141         if (!p)
142                 return -ENOMEM;
143
144         p[0] = h;
145         p[1] = 1;
146         p[2] = type;
147         p[3] = 0;
148
149         ((uint32_t*) p)[1] = l;
150         memcpy(p + 8, s, l + 1);
151
152         if (ret)
153                 *ret = (const char*) p + 8;
154
155         return 0;
156 }
157
158 static int message_append_field_signature(
159                 sd_bus_message *m,
160                 uint8_t h,
161                 const char *s,
162                 const char **ret) {
163
164         size_t l;
165         uint8_t *p;
166
167         assert(m);
168
169         l = strlen(s);
170         if (l > 255)
171                 return -EINVAL;
172
173         /* field id byte + signature length + signature 'g' + NUL + string length + string + NUL */
174         p = message_extend_fields(m, 8, 4 + 1 + l + 1);
175         if (!p)
176                 return -ENOMEM;
177
178         p[0] = h;
179         p[1] = 1;
180         p[2] = SD_BUS_TYPE_SIGNATURE;
181         p[3] = 0;
182         p[4] = l;
183         memcpy(p + 5, s, l + 1);
184
185         if (ret)
186                 *ret = (const char*) p + 5;
187
188         return 0;
189 }
190
191 static int message_append_field_uint32(sd_bus_message *m, uint8_t h, uint32_t x) {
192         uint8_t *p;
193
194         assert(m);
195
196         /* field id byte + signature length + signature 'u' + NUL + value */
197         p = message_extend_fields(m, 8, 4 + 4);
198         if (!p)
199                 return -ENOMEM;
200
201         p[0] = h;
202         p[1] = 1;
203         p[2] = SD_BUS_TYPE_UINT32;
204         p[3] = 0;
205
206         ((uint32_t*) p)[1] = x;
207
208         return 0;
209 }
210
211 static sd_bus_message *message_new(sd_bus *bus, uint8_t type) {
212         sd_bus_message *m;
213
214         m = malloc0(ALIGN(sizeof(struct sd_bus_message)) + sizeof(struct bus_header));
215         if (!m)
216                 return NULL;
217
218         m->n_ref = 1;
219         m->header = (struct bus_header*) ((uint8_t*) m + ALIGN(sizeof(struct sd_bus_message)));
220
221 #if __BYTE_ORDER == __BIG_ENDIAN
222         m->header->endian = SD_BUS_BIG_ENDIAN;
223 #else
224         m->header->endian = SD_BUS_LITTLE_ENDIAN;
225 #endif
226         m->header->type = type;
227         m->header->version = bus ? bus->message_version : 1;
228
229         return m;
230 }
231
232 int sd_bus_message_new_signal(
233                 sd_bus *bus,
234                 const char *path,
235                 const char *interface,
236                 const char *member,
237                 sd_bus_message **m) {
238
239         sd_bus_message *t;
240         int r;
241
242         if (!path)
243                 return -EINVAL;
244         if (!interface)
245                 return -EINVAL;
246         if (!member)
247                 return -EINVAL;
248
249         t = message_new(bus, SD_BUS_MESSAGE_TYPE_SIGNAL);
250         if (!t)
251                 return -ENOMEM;
252
253         r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
254         if (r < 0)
255                 goto fail;
256         r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
257         if (r < 0)
258                 goto fail;
259         r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
260         if (r < 0)
261                 goto fail;
262
263         *m = t;
264         return 0;
265
266 fail:
267         sd_bus_message_unref(t);
268         return r;
269 }
270
271 int sd_bus_message_new_method_call(
272                 sd_bus *bus,
273                 const char *destination,
274                 const char *path,
275                 const char *interface,
276                 const char *member,
277                 sd_bus_message **m) {
278
279         sd_bus_message *t;
280         int r;
281
282         if (!path)
283                 return -EINVAL;
284         if (!member)
285                 return -EINVAL;
286
287         t = message_new(bus, SD_BUS_MESSAGE_TYPE_METHOD_CALL);
288         if (!t)
289                 return -ENOMEM;
290
291         r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
292         if (r < 0)
293                 goto fail;
294         r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
295         if (r < 0)
296                 goto fail;
297
298         if (interface) {
299                 r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
300                 if (r < 0)
301                         goto fail;
302         }
303
304         if (destination) {
305                 r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &t->destination);
306                 if (r < 0)
307                         goto fail;
308         }
309
310         *m = t;
311         return 0;
312
313 fail:
314         message_free(t);
315         return r;
316 }
317
318 int sd_bus_message_new_method_return(
319                 sd_bus *bus,
320                 sd_bus_message *call,
321                 sd_bus_message **m) {
322
323         sd_bus_message *t;
324         int r;
325
326         if (!call)
327                 return -EINVAL;
328         if (call->header->type != SD_BUS_MESSAGE_TYPE_METHOD_CALL)
329                 return -EINVAL;
330
331         t = message_new(bus, SD_BUS_MESSAGE_TYPE_METHOD_RETURN);
332         if (!t)
333                 return -ENOMEM;
334
335         t->reply_serial = BUS_MESSAGE_SERIAL(call);
336         r = message_append_field_uint32(t, SD_BUS_MESSAGE_HEADER_REPLY_SERIAL, t->reply_serial);
337         if (r < 0)
338                 goto fail;
339
340         if (call->sender) {
341                 r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, call->sender, &t->sender);
342                 if (r < 0)
343                         goto fail;
344         }
345
346         *m = t;
347         return 0;
348
349 fail:
350         message_free(t);
351         return r;
352 }
353
354 int sd_bus_message_new_method_error(
355                 sd_bus *bus,
356                 sd_bus_message *call,
357                 const sd_bus_error *e,
358                 sd_bus_message **m) {
359
360         sd_bus_message *t;
361         int r;
362
363         if (!call)
364                 return -EINVAL;
365         if (call->header->type != SD_BUS_MESSAGE_TYPE_METHOD_CALL)
366                 return -EINVAL;
367         if (!e)
368                 return -EINVAL;
369         if (!e->name)
370                 return -EINVAL;
371
372         t = message_new(bus, SD_BUS_MESSAGE_TYPE_METHOD_ERROR);
373         if (!t)
374                 return -ENOMEM;
375
376         t->reply_serial = BUS_MESSAGE_SERIAL(call);
377         r = message_append_field_uint32(t, SD_BUS_MESSAGE_HEADER_REPLY_SERIAL, t->reply_serial);
378         if (r < 0)
379                 goto fail;
380
381         if (call->sender) {
382                 r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, call->sender, &t->sender);
383                 if (r < 0)
384                         goto fail;
385         }
386
387         r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
388         if (r < 0)
389                 goto fail;
390
391         if (e->message) {
392                 r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
393                 if (r < 0)
394                         goto fail;
395         }
396
397         *m = t;
398         return 0;
399
400 fail:
401         message_free(t);
402         return r;
403 }
404
405 sd_bus_message* sd_bus_message_ref(sd_bus_message *m) {
406         if (!m)
407                 return NULL;
408
409         assert(m->n_ref > 0);
410         m->n_ref++;
411
412         return m;
413 }
414
415 sd_bus_message* sd_bus_message_unref(sd_bus_message *m) {
416         if (!m)
417                 return NULL;
418
419         assert(m->n_ref > 0);
420         m->n_ref--;
421
422         if (m->n_ref <= 0)
423                 message_free(m);
424
425         return NULL;
426 }
427
428 int sd_bus_message_get_type(sd_bus_message *m, uint8_t *type) {
429         if (!m)
430                 return -EINVAL;
431         if (!type)
432                 return -EINVAL;
433
434         *type = m->header->type;
435         return 0;
436 }
437
438 int sd_bus_message_get_serial(sd_bus_message *m, uint64_t *serial) {
439         if (!m)
440                 return -EINVAL;
441         if (!serial)
442                 return -EINVAL;
443         if (m->header->serial == 0)
444                 return -ENOENT;
445
446         *serial = BUS_MESSAGE_SERIAL(m);
447         return 0;
448 }
449
450 int sd_bus_message_get_reply_serial(sd_bus_message *m, uint64_t *serial) {
451         if (!m)
452                 return -EINVAL;
453         if (!serial)
454                 return -EINVAL;
455         if (m->reply_serial == 0)
456                 return -ENOENT;
457
458         *serial = m->reply_serial;
459         return 0;
460 }
461
462 int sd_bus_message_get_no_reply(sd_bus_message *m) {
463         if (!m)
464                 return -EINVAL;
465
466         return m->header->type == SD_BUS_MESSAGE_TYPE_METHOD_CALL ? !!(m->header->flags & SD_BUS_MESSAGE_NO_REPLY_EXPECTED) : 0;
467 }
468
469 const char *sd_bus_message_get_path(sd_bus_message *m) {
470         if (!m)
471                 return NULL;
472
473         return m->path;
474 }
475
476 const char *sd_bus_message_get_interface(sd_bus_message *m) {
477         if (!m)
478                 return NULL;
479
480         return m->interface;
481 }
482
483 const char *sd_bus_message_get_member(sd_bus_message *m) {
484         if (!m)
485                 return NULL;
486
487         return m->member;
488 }
489 const char *sd_bus_message_get_destination(sd_bus_message *m) {
490         if (!m)
491                 return NULL;
492
493         return m->destination;
494 }
495
496 const char *sd_bus_message_get_sender(sd_bus_message *m) {
497         if (!m)
498                 return NULL;
499
500         return m->sender;
501 }
502
503 const sd_bus_error *sd_bus_message_get_error(sd_bus_message *m) {
504         if (!m)
505                 return NULL;
506
507         if (!sd_bus_error_is_set(&m->error))
508                 return NULL;
509
510         return &m->error;
511 }
512
513 int sd_bus_message_get_uid(sd_bus_message *m, uid_t *uid) {
514         if (!m)
515                 return -EINVAL;
516         if (!m->uid_valid)
517                 return -ENOENT;
518
519         *uid = m->uid;
520         return 0;
521 }
522
523 int sd_bus_message_get_gid(sd_bus_message *m, gid_t *gid) {
524         if (!m)
525                 return -EINVAL;
526         if (!m->gid_valid)
527                 return -ENOENT;
528
529         *gid = m->gid;
530         return 0;
531 }
532
533 int sd_bus_message_get_pid(sd_bus_message *m, pid_t *pid) {
534         if (!m)
535                 return -EINVAL;
536         if (m->pid <= 0)
537                 return -ENOENT;
538
539         *pid = m->pid;
540         return 0;
541 }
542
543 int sd_bus_message_get_tid(sd_bus_message *m, pid_t *tid) {
544         if (!m)
545                 return -EINVAL;
546         if (m->tid <= 0)
547                 return -ENOENT;
548
549         *tid = m->tid;
550         return 0;
551 }
552
553 int sd_bus_message_is_signal(sd_bus_message *m, const char *interface, const char *member) {
554         if (!m)
555                 return -EINVAL;
556
557         if (m->header->type != SD_BUS_MESSAGE_TYPE_SIGNAL)
558                 return 0;
559
560         if (interface && (!m->interface || !streq(m->interface, interface)))
561                 return 0;
562
563         if (member &&  (!m->member || !streq(m->member, member)))
564                 return 0;
565
566         return 1;
567 }
568
569 int sd_bus_message_is_method_call(sd_bus_message *m, const char *interface, const char *member) {
570         if (!m)
571                 return -EINVAL;
572
573         if (m->header->type != SD_BUS_MESSAGE_TYPE_METHOD_CALL)
574                 return 0;
575
576         if (interface && (!m->interface || !streq(m->interface, interface)))
577                 return 0;
578
579         if (member &&  (!m->member || !streq(m->member, member)))
580                 return 0;
581
582         return 1;
583 }
584
585 int sd_bus_message_is_method_error(sd_bus_message *m, const char *name) {
586         if (!m)
587                 return -EINVAL;
588
589         if (m->header->type != SD_BUS_MESSAGE_TYPE_METHOD_ERROR)
590                 return 0;
591
592         if (name && (!m->error.name || !streq(m->error.name, name)))
593                 return 0;
594
595         return 1;
596 }
597
598 int sd_bus_message_set_no_reply(sd_bus_message *m, int b) {
599         if (!m)
600                 return -EINVAL;
601         if (m->sealed)
602                 return -EPERM;
603         if (m->header->type != SD_BUS_MESSAGE_TYPE_METHOD_CALL)
604                 return -EPERM;
605
606         if (b)
607                 m->header->flags |= SD_BUS_MESSAGE_NO_REPLY_EXPECTED;
608         else
609                 m->header->flags &= ~SD_BUS_MESSAGE_NO_REPLY_EXPECTED;
610
611         return 0;
612 }
613
614 static struct bus_container *message_get_container(sd_bus_message *m) {
615         assert(m);
616
617         if (m->n_containers == 0)
618                 return &m->root_container;
619
620         assert(m->sub_containers);
621         return m->sub_containers + m->n_containers - 1;
622 }
623
624 static void *message_extend_body(sd_bus_message *m, size_t align, size_t sz) {
625         void *p, *o;
626         size_t added;
627         struct bus_container *c;
628
629         assert(m);
630
631         o = m->body;
632         added = m->header->body_size;
633
634         p = buffer_extend(&m->body, &m->header->body_size, align, sz);
635         if (!p)
636                 return NULL;
637
638         added = m->header->body_size - added;
639
640         for (c = m->sub_containers; c < m->sub_containers + m->n_containers; c++)
641                 if (c->array_size) {
642                         c->array_size = (uint32_t*) ((uint8_t*) m->body + ((uint8_t*) c->array_size - (uint8_t*) o));
643                         *c->array_size += added;
644                 }
645
646         if (o != m->body) {
647                 if (m->error.message)
648                         m->error.message = (const char*) m->body + (m->error.message - (const char*) o);
649         }
650
651         m->free_body = true;
652
653         return p;
654 }
655
656 int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored) {
657         struct bus_container *c;
658         size_t sz, align, nindex;
659         uint32_t k;
660         void *a;
661         char *e = NULL;
662
663         if (!m)
664                 return -EINVAL;
665         if (m->sealed)
666                 return -EPERM;
667         if (!bus_type_is_basic(type))
668                 return -EINVAL;
669
670         c = message_get_container(m);
671
672         if (c->signature && c->signature[c->index]) {
673                 /* Container signature is already set */
674
675                 if (c->signature[c->index] != type)
676                         return -EINVAL;
677         } else {
678                 /* Maybe we can append to the signature? But only if this is the top-level container*/
679                 if (c->enclosing != 0)
680                         return -EINVAL;
681
682                 e = strextend(&c->signature, CHAR_TO_STR(type), NULL);
683                 if (!e)
684                         return -ENOMEM;
685         }
686
687         nindex = c->index + 1;
688
689         switch (type) {
690
691         case SD_BUS_TYPE_STRING:
692         case SD_BUS_TYPE_OBJECT_PATH:
693                 align = 4;
694                 sz = 4 + strlen(p) + 1;
695                 break;
696
697         case SD_BUS_TYPE_SIGNATURE:
698                 align = 1;
699                 sz = 1 + strlen(p) + 1;
700                 break;
701
702         case SD_BUS_TYPE_BOOLEAN:
703                 align = sz = 4;
704
705                 assert_cc(sizeof(int) == sizeof(uint32_t));
706                 memcpy(&k, p, 4);
707                 k = !!k;
708                 p = &k;
709                 break;
710
711         default:
712                 align = bus_type_get_alignment(type);
713                 sz = bus_type_get_size(type);
714                 break;
715         }
716
717         assert(align > 0);
718         assert(sz > 0);
719
720         a = message_extend_body(m, align, sz);
721         if (!a) {
722                 /* Truncate extended signature again */
723                 if (e)
724                         c->signature[c->index] = 0;
725
726                 return -ENOMEM;
727         }
728
729         if (type == SD_BUS_TYPE_STRING || type == SD_BUS_TYPE_OBJECT_PATH) {
730                 *(uint32_t*) a = sz - 5;
731                 memcpy((uint8_t*) a + 4, p, sz - 4);
732
733                 if (stored)
734                         *stored = (const uint8_t*) a + 4;
735
736         } else if (type == SD_BUS_TYPE_SIGNATURE) {
737                 *(uint8_t*) a = sz - 1;
738                 memcpy((uint8_t*) a + 1, p, sz - 1);
739
740                 if (stored)
741                         *stored = (const uint8_t*) a + 1;
742
743         } else {
744                 memcpy(a, p, sz);
745
746                 if (stored)
747                         *stored = a;
748         }
749
750         if (c->enclosing != SD_BUS_TYPE_ARRAY)
751                 c->index = nindex;
752
753         return 0;
754 }
755
756 int sd_bus_message_append_basic(sd_bus_message *m, char type, const void *p) {
757         return message_append_basic(m, type, p, NULL);
758 }
759
760 static int bus_message_open_array(
761                 sd_bus_message *m,
762                 struct bus_container *c,
763                 const char *contents,
764                 uint32_t **array_size) {
765
766         char *e = NULL;
767         size_t nindex;
768         void *a, *b;
769         int alignment;
770         size_t saved;
771
772         assert(m);
773         assert(c);
774         assert(contents);
775         assert(array_size);
776
777         if (!signature_is_single(contents))
778                 return -EINVAL;
779
780         alignment = bus_type_get_alignment(contents[0]);
781         if (alignment < 0)
782                 return alignment;
783
784         if (c->signature && c->signature[c->index]) {
785
786                 /* Verify the existing signature */
787
788                 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
789                         return -EINVAL;
790
791                 if (!startswith(c->signature + c->index + 1, contents))
792                         return -EINVAL;
793
794                 nindex = c->index + 1 + strlen(contents);
795         } else {
796                 if (c->enclosing != 0)
797                         return -EINVAL;
798
799                 /* Extend the existing signature */
800
801                 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_ARRAY), contents, NULL);
802                 if (!e)
803                         return -ENOMEM;
804
805                 nindex = e - c->signature;
806         }
807
808         saved = m->header->body_size;
809         a = message_extend_body(m, 4, 4);
810         if (!a) {
811                 /* Truncate extended signature again */
812                 if (e)
813                         c->signature[c->index] = 0;
814
815                 return -ENOMEM;
816         }
817         b = m->body;
818
819         if (!message_extend_body(m, alignment, 0)) {
820                 /* Add alignment between size and first element */
821                 if (e)
822                         c->signature[c->index] = 0;
823
824                 m->header->body_size = saved;
825                 return -ENOMEM;
826         }
827
828         if (c->enclosing != SD_BUS_TYPE_ARRAY)
829                 c->index = nindex;
830
831         /* m->body might have changed so let's readjust a */
832         a = (uint8_t*) m->body + ((uint8_t*) a - (uint8_t*) b);
833         *(uint32_t*) a = 0;
834
835         *array_size = a;
836         return 0;
837 }
838
839 static int bus_message_open_variant(
840                 sd_bus_message *m,
841                 struct bus_container *c,
842                 const char *contents) {
843
844         char *e = NULL;
845         size_t l, nindex;
846         void *a;
847
848         assert(m);
849         assert(c);
850         assert(contents);
851
852         if (!signature_is_single(contents))
853                 return -EINVAL;
854
855         if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
856                 return -EINVAL;
857
858         if (c->signature && c->signature[c->index]) {
859
860                 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
861                         return -EINVAL;
862
863         } else {
864                 if (c->enclosing != 0)
865                         return -EINVAL;
866
867                 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_VARIANT), NULL);
868                 if (!e)
869                         return -ENOMEM;
870         }
871
872         nindex = c->index + 1;
873
874         l = strlen(contents);
875         a = message_extend_body(m, 1, 1 + l + 1);
876         if (!a) {
877                 /* Truncate extended signature again */
878                 if (e)
879                         c->signature[c->index] = 0;
880
881                 return -ENOMEM;
882         }
883
884         *(uint8_t*) a = l;
885         memcpy((uint8_t*) a + 1, contents, l + 1);
886
887         if (c->enclosing != SD_BUS_TYPE_ARRAY)
888                 c->index = nindex;
889
890         return 0;
891 }
892
893 static int bus_message_open_struct(
894                 sd_bus_message *m,
895                 struct bus_container *c,
896                 const char *contents) {
897
898         size_t nindex;
899         char *e = NULL;
900
901         assert(m);
902         assert(c);
903         assert(contents);
904
905         if (!signature_is_valid(contents, false))
906                 return -EINVAL;
907
908         if (c->signature && c->signature[c->index]) {
909                 size_t l;
910
911                 l = strlen(contents);
912
913                 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
914                     !startswith(c->signature + c->index + 1, contents) ||
915                     c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
916                         return -EINVAL;
917
918                 nindex = c->index + 1 + l + 1;
919         } else {
920                 if (c->enclosing != 0)
921                         return -EINVAL;
922
923                 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_BEGIN), contents, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_END), NULL);
924                 if (!e)
925                         return -ENOMEM;
926
927                 nindex = e - c->signature;
928         }
929
930         /* Align contents to 8 byte boundary */
931         if (!message_extend_body(m, 8, 0)) {
932                 if (e)
933                         c->signature[c->index] = 0;
934
935                 return -ENOMEM;
936         }
937
938         if (c->enclosing != SD_BUS_TYPE_ARRAY)
939                 c->index = nindex;
940
941         return 0;
942 }
943
944 static int bus_message_open_dict_entry(
945                 sd_bus_message *m,
946                 struct bus_container *c,
947                 const char *contents) {
948
949         size_t nindex;
950
951         assert(m);
952         assert(c);
953         assert(contents);
954
955         if (!signature_is_pair(contents))
956                 return -EINVAL;
957
958         if (c->enclosing != SD_BUS_TYPE_ARRAY)
959                 return -EINVAL;
960
961         if (c->signature && c->signature[c->index]) {
962                 size_t l;
963
964                 l = strlen(contents);
965
966                 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
967                     !startswith(c->signature + c->index + 1, contents) ||
968                     c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
969                         return -EINVAL;
970
971                 nindex = c->index + 1 + l + 1;
972         } else
973                 return -EINVAL;
974
975         /* Align contents to 8 byte boundary */
976         if (!message_extend_body(m, 8, 0))
977                 return -ENOMEM;
978
979         if (c->enclosing != SD_BUS_TYPE_ARRAY)
980                 c->index = nindex;
981
982         return 0;
983 }
984
985 int sd_bus_message_open_container(
986                 sd_bus_message *m,
987                 char type,
988                 const char *contents) {
989
990         struct bus_container *c, *sub;
991         char *signature;
992         uint32_t *array_size = NULL;
993         int r;
994
995         if (!m)
996                 return -EINVAL;
997         if (m->sealed)
998                 return -EPERM;
999         if (!contents)
1000                 return -EINVAL;
1001
1002         /* Make sure we have space for one more container */
1003         sub = realloc(m->sub_containers, sizeof(struct bus_container) * (m->n_containers + 1));
1004         if (!sub)
1005                 return -ENOMEM;
1006
1007         m->sub_containers = sub;
1008
1009         c = message_get_container(m);
1010
1011         signature = strdup(contents);
1012         if (!signature)
1013                 return -ENOMEM;
1014
1015         if (type == SD_BUS_TYPE_ARRAY)
1016                 r = bus_message_open_array(m, c, contents, &array_size);
1017         else if (type == SD_BUS_TYPE_VARIANT)
1018                 r = bus_message_open_variant(m, c, contents);
1019         else if (type == SD_BUS_TYPE_STRUCT)
1020                 r = bus_message_open_struct(m, c, contents);
1021         else if (type == SD_BUS_TYPE_DICT_ENTRY)
1022                 r = bus_message_open_dict_entry(m, c, contents);
1023         else
1024                 r = -EINVAL;
1025
1026         if (r < 0) {
1027                 free(signature);
1028                 return r;
1029         }
1030
1031         /* OK, let's fill it in */
1032         sub += m->n_containers++;
1033
1034         sub->enclosing = type;
1035         sub->signature = signature;
1036         sub->index = 0;
1037         sub->array_size = array_size;
1038
1039         return 0;
1040 }
1041
1042 int sd_bus_message_close_container(sd_bus_message *m) {
1043         struct bus_container *c;
1044
1045         if (!m)
1046                 return -EINVAL;
1047         if (m->sealed)
1048                 return -EPERM;
1049         if (m->n_containers <= 0)
1050                 return -EINVAL;
1051
1052         c = message_get_container(m);
1053
1054         if (!c->signature)
1055                 return -EINVAL;
1056
1057         if (c->enclosing != SD_BUS_TYPE_ARRAY)
1058                 if (c->signature[c->index] != 0)
1059                         return -EINVAL;
1060
1061         free(c->signature);
1062         m->n_containers--;
1063
1064         return 0;
1065 }
1066
1067 static int message_append_ap(
1068                 sd_bus_message *m,
1069                 const char *types,
1070                 va_list ap) {
1071
1072         const char *t;
1073         int r;
1074
1075         assert(m);
1076         assert(types);
1077
1078         for (t = types; *t; t++) {
1079                 switch (*t) {
1080
1081                 case SD_BUS_TYPE_BYTE: {
1082                         uint8_t x;
1083
1084                         x = (uint8_t) va_arg(ap, int);
1085                         r = sd_bus_message_append_basic(m, *t, &x);
1086                         break;
1087                 }
1088
1089                 case SD_BUS_TYPE_BOOLEAN:
1090                 case SD_BUS_TYPE_INT32:
1091                 case SD_BUS_TYPE_UINT32: {
1092                         uint32_t x;
1093
1094                         x = va_arg(ap, uint32_t);
1095                         r = sd_bus_message_append_basic(m, *t, &x);
1096                         break;
1097                 }
1098
1099                 case SD_BUS_TYPE_INT16:
1100                 case SD_BUS_TYPE_UINT16: {
1101                         uint16_t x;
1102
1103                         x = (uint16_t) va_arg(ap, int);
1104                         r = sd_bus_message_append_basic(m, *t, &x);
1105                         break;
1106                 }
1107
1108                 case SD_BUS_TYPE_INT64:
1109                 case SD_BUS_TYPE_UINT64:
1110                 case SD_BUS_TYPE_DOUBLE: {
1111                         uint64_t x;
1112
1113                         x = va_arg(ap, uint64_t);
1114                         r = sd_bus_message_append_basic(m, *t, &x);
1115                         break;
1116                 }
1117
1118                 case SD_BUS_TYPE_STRING:
1119                 case SD_BUS_TYPE_OBJECT_PATH:
1120                 case SD_BUS_TYPE_SIGNATURE: {
1121                         const char *x;
1122
1123                         x = va_arg(ap, const char*);
1124                         r = sd_bus_message_append_basic(m, *t, x);
1125                         break;
1126                 }
1127
1128                 case SD_BUS_TYPE_UNIX_FD: {
1129                         int x;
1130
1131                         x = va_arg(ap, int);
1132                         r = sd_bus_message_append_basic(m, *t, &x);
1133                         break;
1134                 }
1135
1136                 case SD_BUS_TYPE_ARRAY: {
1137                         unsigned i, n;
1138                         size_t k;
1139
1140                         r = signature_element_length(t + 1, &k);
1141                         if (r < 0)
1142                                 return r;
1143
1144                         {
1145                                 char s[k + 1];
1146
1147                                 memcpy(s, t + 1, k);
1148                                 s[k] = 0;
1149                                 t += k;
1150
1151                                 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, s);
1152                                 if (r < 0)
1153                                         return r;
1154
1155                                 n = va_arg(ap, unsigned);
1156
1157                                 for (i = 0; i < n; i++) {
1158                                         r = message_append_ap(m, s, ap);
1159                                         if (r < 0)
1160                                                 return r;
1161                                 }
1162
1163                                 r = sd_bus_message_close_container(m);
1164                         }
1165
1166                         break;
1167                 }
1168
1169                 case SD_BUS_TYPE_VARIANT: {
1170                         const char *s;
1171
1172                         s = va_arg(ap, const char*);
1173                         if (!s)
1174                                 return -EINVAL;
1175
1176                         r = sd_bus_message_open_container(m, SD_BUS_TYPE_VARIANT, s);
1177                         if (r < 0)
1178                                 return r;
1179
1180                         r = message_append_ap(m, s, ap);
1181                         if (r < 0)
1182                                 return r;
1183
1184                         r = sd_bus_message_close_container(m);
1185                         break;
1186                 }
1187
1188                 case SD_BUS_TYPE_STRUCT_BEGIN:
1189                 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
1190                         size_t k;
1191
1192                         r = signature_element_length(t, &k);
1193                         if (r < 0)
1194                                 return r;
1195
1196                         {
1197                                 char s[k - 1];
1198
1199                                 memcpy(s, t + 1, k - 2);
1200                                 s[k - 2] = 0;
1201
1202                                 r = sd_bus_message_open_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
1203                                 if (r < 0)
1204                                         return r;
1205
1206                                 t += k - 1;
1207
1208                                 r = message_append_ap(m, s, ap);
1209                                 if (r < 0)
1210                                         return r;
1211
1212                                 r = sd_bus_message_close_container(m);
1213                         }
1214
1215                         break;
1216                 }
1217
1218                 default:
1219                         r = -EINVAL;
1220                 }
1221
1222                 if (r < 0)
1223                         return r;
1224         }
1225
1226         return 0;
1227 }
1228
1229 int sd_bus_message_append(sd_bus_message *m, const char *types, ...) {
1230         va_list ap;
1231         int r;
1232
1233         if (!m)
1234                 return -EINVAL;
1235         if (m->sealed)
1236                 return -EPERM;
1237         if (!types)
1238                 return -EINVAL;
1239
1240         va_start(ap, types);
1241         r = message_append_ap(m, types, ap);
1242         va_end(ap);
1243
1244         return r;
1245 }
1246
1247 int sd_bus_message_read_type(sd_bus_message *m, char *type, char *element, size_t *length) {
1248         return -ENOTSUP;
1249 }
1250
1251 int sd_bus_message_read_basic(sd_bus_message *m, char type, char element, const void **p, size_t *length) {
1252         return -ENOTSUP;
1253 }
1254
1255 int sd_bus_message_read(sd_bus_message *m, const char *types, ...) {
1256         return -ENOTSUP;
1257 }
1258
1259 int message_parse(sd_bus_message *m) {
1260         assert(m);
1261
1262         if (m->header->version != 1)
1263                 return -EIO;
1264
1265         if (m->header->endian != SD_BUS_BIG_ENDIAN &&
1266             m->header->endian != SD_BUS_LITTLE_ENDIAN)
1267                 return -EIO;
1268
1269         return 0;
1270 }
1271
1272 static void setup_iovec(sd_bus_message *m) {
1273         assert(m);
1274         assert(m->sealed);
1275
1276         m->n_iovec = 0;
1277
1278         m->iovec[m->n_iovec].iov_base = m->header;
1279         m->iovec[m->n_iovec].iov_len = sizeof(*m->header);
1280         m->n_iovec++;
1281
1282         if (m->fields) {
1283                 m->iovec[m->n_iovec].iov_base = m->fields;
1284                 m->iovec[m->n_iovec].iov_len = m->header->fields_size;
1285                 m->n_iovec++;
1286
1287                 if (m->header->fields_size % 8 != 0) {
1288                         static const uint8_t padding[7] = { 0, 0, 0, 0, 0, 0, 0 };
1289
1290                         m->iovec[m->n_iovec].iov_base = (void*) padding;
1291                         m->iovec[m->n_iovec].iov_len = 8 - m->header->fields_size % 8;
1292                         m->n_iovec++;
1293                 }
1294         }
1295
1296         if (m->body) {
1297                 m->iovec[m->n_iovec].iov_base = m->body;
1298                 m->iovec[m->n_iovec].iov_len = m->header->body_size;
1299                 m->n_iovec++;
1300         }
1301 }
1302
1303 int message_seal(sd_bus_message *m, uint64_t serial) {
1304         int r;
1305
1306         assert(m);
1307
1308         if (m->sealed)
1309                 return -EPERM;
1310
1311         if (m->n_containers > 0)
1312                 return -EBADMSG;
1313
1314         /* If there's a non-trivial signature set, then add it in here */
1315         if (!isempty(m->root_container.signature)) {
1316                 r = message_append_field_signature(m, SD_BUS_MESSAGE_HEADER_SIGNATURE, m->root_container.signature, &m->signature);
1317                 if (r < 0)
1318                         return r;
1319         }
1320
1321         if (m->n_fds > 0) {
1322                 r = message_append_field_uint32(m, SD_BUS_MESSAGE_HEADER_UNIX_FDS, m->n_fds);
1323                 if (r < 0)
1324                         return r;
1325         }
1326
1327         m->header->serial = serial;
1328         m->sealed = true;
1329
1330         setup_iovec(m);
1331
1332         return 0;
1333 }
1334
1335 int sd_bus_message_set_destination(sd_bus_message *m, const char *destination) {
1336         if (!m)
1337                 return -EINVAL;
1338         if (!destination)
1339                 return -EINVAL;
1340         if (m->sealed)
1341                 return -EPERM;
1342         if (m->destination)
1343                 return -EEXIST;
1344
1345         return message_append_field_string(m, SD_BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &m->destination);
1346 }
1347
1348 void message_dump(sd_bus_message *m) {
1349
1350         log_info("Message %p\n"
1351                  "\tn_ref=%u\n"
1352                  "\tendian=%c\n"
1353                  "\ttype=%i\n"
1354                  "\tflags=%u\n"
1355                  "\tversion=%u\n"
1356                  "\tserial=%u\n"
1357                  "\tfields_size=%u\n"
1358                  "\tbody_size=%u\n"
1359                  "\tpath=%s\n"
1360                  "\tinterface=%s\n"
1361                  "\tmember=%s\n"
1362                  "\tdestination=%s\n"
1363                  "\tsender=%s\n"
1364                  "\tsignature=%s\n"
1365                  "\treply_serial=%u\n"
1366                  "\terror.name=%s\n"
1367                  "\terror.message=%s\n"
1368                  "\tsealed=%s\n",
1369                  m,
1370                  m->n_ref,
1371                  m->header->endian,
1372                  m->header->type,
1373                  m->header->flags,
1374                  m->header->version,
1375                  BUS_MESSAGE_SERIAL(m),
1376                  BUS_MESSAGE_FIELDS_SIZE(m),
1377                  BUS_MESSAGE_BODY_SIZE(m),
1378                  strna(m->path),
1379                  strna(m->interface),
1380                  strna(m->member),
1381                  strna(m->destination),
1382                  strna(m->sender),
1383                  strna(m->signature),
1384                  m->reply_serial,
1385                  strna(m->error.name),
1386                  strna(m->error.message),
1387                  yes_no(m->sealed));
1388 }
1389
1390 int bus_message_get_blob(sd_bus_message *m, void **buffer, size_t *sz) {
1391         size_t total;
1392         unsigned i;
1393         void *p, *e;
1394
1395         assert(m);
1396         assert(buffer);
1397         assert(sz);
1398
1399         for (i = 0, total = 0; i < m->n_iovec; i++)
1400                 total += m->iovec[i].iov_len;
1401
1402         p = malloc(total);
1403         if (!p)
1404                 return -ENOMEM;
1405
1406         for (i = 0, e = p; i < m->n_iovec; i++)
1407                 e = mempcpy(e, m->iovec[i].iov_base, m->iovec[i].iov_len);
1408
1409         *buffer = p;
1410         *sz = total;
1411
1412         return 0;
1413 }