[systemd-commits] 24 commits - Makefile.am TODO src/core src/libsystemd-bus src/libudev src/login src/machine src/shared src/systemctl src/systemd src/test

Lennart Poettering lennart at kemper.freedesktop.org
Wed Nov 20 11:58:36 PST 2013


 Makefile.am                              |   71 
 TODO                                     |   47 
 src/core/automount.c                     |   53 
 src/core/automount.h                     |    2 
 src/core/bus-errors.h                    |   43 
 src/core/dbus-automount.c                |   62 
 src/core/dbus-automount.h                |   10 
 src/core/dbus-cgroup.c                   |  347 +--
 src/core/dbus-cgroup.h                   |   24 
 src/core/dbus-client-track.c             |  250 ++
 src/core/dbus-client-track.h             |   42 
 src/core/dbus-device.c                   |   52 
 src/core/dbus-device.h                   |    9 
 src/core/dbus-execute.c                  |  596 +++---
 src/core/dbus-execute.h                  |   93 -
 src/core/dbus-job.c                      |  394 +---
 src/core/dbus-job.h                      |    9 
 src/core/dbus-kill.c                     |   55 
 src/core/dbus-kill.h                     |   17 
 src/core/dbus-manager.c                  | 2816 ++++++++++++++-----------------
 src/core/dbus-manager.h                  |   10 
 src/core/dbus-mount.c                    |  188 --
 src/core/dbus-mount.h                    |   11 
 src/core/dbus-path.c                     |  135 -
 src/core/dbus-path.h                     |   10 
 src/core/dbus-scope.c                    |  127 -
 src/core/dbus-scope.h                    |   10 
 src/core/dbus-service.c                  |  266 --
 src/core/dbus-service.h                  |   11 
 src/core/dbus-slice.c                    |   58 
 src/core/dbus-slice.h                    |    9 
 src/core/dbus-snapshot.c                 |   73 
 src/core/dbus-snapshot.h                 |    8 
 src/core/dbus-socket.c                   |  252 --
 src/core/dbus-socket.h                   |   11 
 src/core/dbus-swap.c                     |  140 -
 src/core/dbus-swap.h                     |   11 
 src/core/dbus-target.c                   |   40 
 src/core/dbus-target.h                   |    8 
 src/core/dbus-timer.c                    |  223 +-
 src/core/dbus-timer.h                    |   10 
 src/core/dbus-unit.c                     | 1308 ++++++--------
 src/core/dbus-unit.h                     |  134 -
 src/core/dbus.c                          | 1896 +++++++-------------
 src/core/dbus.h                          |   26 
 src/core/device.c                        |  148 -
 src/core/device.h                        |    2 
 src/core/job.c                           |  195 --
 src/core/job.h                           |   17 
 src/core/load-fragment-gperf.gperf.m4    |    2 
 src/core/load-fragment.c                 |   19 
 src/core/main.c                          |   50 
 src/core/manager.c                       |  655 ++-----
 src/core/manager.h                       |   93 -
 src/core/mount.c                         |  141 -
 src/core/mount.h                         |    2 
 src/core/path.c                          |   71 
 src/core/path.h                          |    8 
 src/core/scope.c                         |   70 
 src/core/scope.h                         |    2 
 src/core/selinux-access.c                |  225 +-
 src/core/selinux-access.h                |   38 
 src/core/service.c                       |  257 +-
 src/core/service.h                       |    4 
 src/core/slice.c                         |    8 
 src/core/snapshot.c                      |   24 
 src/core/snapshot.h                      |    2 
 src/core/socket.c                        |  256 +-
 src/core/socket.h                        |    8 
 src/core/swap.c                          |  113 -
 src/core/swap.h                          |    5 
 src/core/target.c                        |    3 
 src/core/timer.c                         |   78 
 src/core/timer.h                         |    4 
 src/core/transaction.c                   |   82 
 src/core/transaction.h                   |    4 
 src/core/unit.c                          |  154 -
 src/core/unit.h                          |   41 
 src/libsystemd-bus/bus-dump.c            |   42 
 src/libsystemd-bus/bus-error.c           |   15 
 src/libsystemd-bus/bus-error.h           |    2 
 src/libsystemd-bus/bus-internal.h        |    4 
 src/libsystemd-bus/bus-introspect.c      |    6 
 src/libsystemd-bus/bus-introspect.h      |    2 
 src/libsystemd-bus/bus-message.c         |    1 
 src/libsystemd-bus/bus-objects.c         |  360 ++-
 src/libsystemd-bus/bus-signature.c       |   15 
 src/libsystemd-bus/bus-util.c            |   42 
 src/libsystemd-bus/bus-util.h            |   68 
 src/libsystemd-bus/busctl.c              |   13 
 src/libsystemd-bus/libsystemd-bus.sym    |    4 
 src/libsystemd-bus/sd-bus.c              |  268 ++
 src/libsystemd-bus/sd-event.c            |   75 
 src/libsystemd-bus/test-bus-introspect.c |    4 
 src/libsystemd-bus/test-bus-marshal.c    |    2 
 src/libudev/libudev-device.c             |   12 
 src/libudev/libudev-enumerate.c          |    4 
 src/libudev/libudev-hwdb.c               |    4 
 src/libudev/libudev-monitor.c            |   16 
 src/libudev/libudev-queue.c              |    4 
 src/login/logind-dbus.c                  |    3 
 src/login/logind-inhibit.c               |    2 
 src/login/logind-seat-dbus.c             |    1 
 src/login/logind-session-dbus.c          |    1 
 src/login/logind-session.c               |    2 
 src/login/logind.c                       |    2 
 src/machine/machined-dbus.c              |    1 
 src/shared/bus-errors.h                  |   57 
 src/shared/calendarspec.c                |   17 
 src/shared/dbus-common.c                 | 1430 ---------------
 src/shared/dbus-common.h                 |  246 --
 src/shared/hashmap.c                     |    9 
 src/shared/hwclock.c                     |   18 
 src/shared/install.c                     |   28 
 src/shared/install.h                     |    2 
 src/shared/macro.h                       |   16 
 src/shared/prioq.c                       |    2 
 src/systemctl/systemctl.c                |  142 +
 src/systemd/_sd-common.h                 |    4 
 src/systemd/sd-bus.h                     |    6 
 src/systemd/sd-event.h                   |   34 
 src/test/test-sched-prio.c               |    2 
 src/test/test-unit-name.c                |    2 
 123 files changed, 6352 insertions(+), 9386 deletions(-)

New commits:
commit 1b5995b0395fda2c495579a21b73698d1099c487
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Nov 20 18:20:23 2013 +0100

    event: make sure to possibly disarm the timerfds before we reenter epoll_wait

diff --git a/src/libsystemd-bus/sd-event.c b/src/libsystemd-bus/sd-event.c
index 90cdeda..2dc3672 100644
--- a/src/libsystemd-bus/sd-event.c
+++ b/src/libsystemd-bus/sd-event.c
@@ -1756,18 +1756,16 @@ _public_ int sd_event_run(sd_event *e, uint64_t timeout) {
         if (r < 0)
                 goto finish;
 
-        if (event_next_pending(e) || e->need_process_child)
-                timeout = 0;
+        r = event_arm_timer(e, e->monotonic_fd, e->monotonic_earliest, e->monotonic_latest, &e->monotonic_next);
+        if (r < 0)
+                goto finish;
 
-        if (timeout > 0) {
-                r = event_arm_timer(e, e->monotonic_fd, e->monotonic_earliest, e->monotonic_latest, &e->monotonic_next);
-                if (r < 0)
-                        goto finish;
+        r = event_arm_timer(e, e->realtime_fd, e->realtime_earliest, e->realtime_latest, &e->realtime_next);
+        if (r < 0)
+                goto finish;
 
-                r = event_arm_timer(e, e->realtime_fd, e->realtime_earliest, e->realtime_latest, &e->realtime_next);
-                if (r < 0)
-                        goto finish;
-        }
+        if (event_next_pending(e) || e->need_process_child)
+                timeout = 0;
 
         m = epoll_wait(e->epoll_fd, ev_queue, EPOLL_QUEUE_MAX,
                        timeout == (uint64_t) -1 ? -1 : (int) ((timeout + USEC_PER_MSEC - 1) / USEC_PER_MSEC));

commit c57b5ca30199cbedaf45a0346c38977387359842
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Nov 20 18:19:05 2013 +0100

    event: don't disarm invalid timerfd

diff --git a/src/libsystemd-bus/sd-event.c b/src/libsystemd-bus/sd-event.c
index ec18af4..90cdeda 100644
--- a/src/libsystemd-bus/sd-event.c
+++ b/src/libsystemd-bus/sd-event.c
@@ -1412,6 +1412,9 @@ static int event_arm_timer(
         a = prioq_peek(earliest);
         if (!a || a->enabled == SD_EVENT_OFF) {
 
+                if (timer_fd < 0)
+                        return 0;
+
                 if (*next == (usec_t) -1)
                         return 0;
 

commit 86befb4098e12688605a08bf602532de9a0ec863
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Nov 20 18:18:09 2013 +0100

    bus: make sure an additional ref to a busevent source doesn't cause the event source to be triggered again

diff --git a/src/libsystemd-bus/sd-bus.c b/src/libsystemd-bus/sd-bus.c
index bc88ac9..72d04d2 100644
--- a/src/libsystemd-bus/sd-bus.c
+++ b/src/libsystemd-bus/sd-bus.c
@@ -2626,17 +2626,25 @@ _public_ int sd_bus_detach_event(sd_bus *bus) {
         assert_return(bus, -EINVAL);
         assert_return(bus->event, -ENXIO);
 
-        if (bus->input_io_event_source)
+        if (bus->input_io_event_source) {
+                sd_event_source_set_enabled(bus->input_io_event_source, SD_EVENT_OFF);
                 bus->input_io_event_source = sd_event_source_unref(bus->input_io_event_source);
+        }
 
-        if (bus->output_io_event_source)
+        if (bus->output_io_event_source) {
+                sd_event_source_set_enabled(bus->output_io_event_source, SD_EVENT_OFF);
                 bus->output_io_event_source = sd_event_source_unref(bus->output_io_event_source);
+        }
 
-        if (bus->time_event_source)
+        if (bus->time_event_source) {
+                sd_event_source_set_enabled(bus->time_event_source, SD_EVENT_OFF);
                 bus->time_event_source = sd_event_source_unref(bus->time_event_source);
+        }
 
-        if (bus->quit_event_source)
+        if (bus->quit_event_source) {
+                sd_event_source_set_enabled(bus->quit_event_source, SD_EVENT_OFF);
                 bus->quit_event_source = sd_event_source_unref(bus->quit_event_source);
+        }
 
         if (bus->event)
                 bus->event = sd_event_unref(bus->event);

commit 2576a19ed25dff1adc7fd2c0b874c74946fb35b4
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Nov 20 18:07:07 2013 +0100

    event: whenever a time source changes pending state reshuffle elapsation prioqs

diff --git a/src/libsystemd-bus/sd-event.c b/src/libsystemd-bus/sd-event.c
index 55a8546..ec18af4 100644
--- a/src/libsystemd-bus/sd-event.c
+++ b/src/libsystemd-bus/sd-event.c
@@ -543,6 +543,14 @@ static int source_set_pending(sd_event_source *s, bool b) {
         } else
                 assert_se(prioq_remove(s->event->pending, s, &s->pending_index));
 
+        if (s->type == SOURCE_REALTIME) {
+                prioq_reshuffle(s->event->realtime_earliest, s, &s->time.earliest_index);
+                prioq_reshuffle(s->event->realtime_latest, s, &s->time.latest_index);
+        } else if (s->type == SOURCE_MONOTONIC) {
+                prioq_reshuffle(s->event->monotonic_earliest, s, &s->time.earliest_index);
+                prioq_reshuffle(s->event->monotonic_latest, s, &s->time.latest_index);
+        }
+
         return 0;
 }
 
@@ -1238,10 +1246,8 @@ _public_ int sd_event_source_set_time(sd_event_source *s, uint64_t usec) {
         assert_return(s->event->state != SD_EVENT_FINISHED, -ESTALE);
         assert_return(!event_pid_changed(s->event), -ECHILD);
 
-        if (s->time.next == usec)
-                return 0;
-
         s->time.next = usec;
+
         source_set_pending(s, false);
 
         if (s->type == SOURCE_REALTIME) {
@@ -1275,11 +1281,10 @@ _public_ int sd_event_source_set_time_accuracy(sd_event_source *s, uint64_t usec
         if (usec == 0)
                 usec = DEFAULT_ACCURACY_USEC;
 
-        if (s->time.accuracy == usec)
-                return 0;
-
         s->time.accuracy = usec;
 
+        source_set_pending(s, false);
+
         if (s->type == SOURCE_REALTIME)
                 prioq_reshuffle(s->event->realtime_latest, s, &s->time.latest_index);
         else

commit 503f39c35e0fd7ba23649ec14044e195594e3347
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Nov 20 16:39:22 2013 +0100

    event: when we change the io events to watch we need to figure out if a an event is pending again

diff --git a/src/libsystemd-bus/sd-event.c b/src/libsystemd-bus/sd-event.c
index eab92bd..55a8546 100644
--- a/src/libsystemd-bus/sd-event.c
+++ b/src/libsystemd-bus/sd-event.c
@@ -1027,6 +1027,7 @@ _public_ int sd_event_source_set_io_events(sd_event_source *s, uint32_t events)
         }
 
         s->io.events = events;
+        source_set_pending(s, false);
 
         return 0;
 }

commit a99badf5ed3b2207a19f5b44c549c5e7584dfd83
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Nov 20 03:58:05 2013 +0100

    sd-event: fix comparison functions

diff --git a/src/libsystemd-bus/sd-event.c b/src/libsystemd-bus/sd-event.c
index 5cb3bcc..eab92bd 100644
--- a/src/libsystemd-bus/sd-event.c
+++ b/src/libsystemd-bus/sd-event.c
@@ -234,7 +234,7 @@ static int earliest_time_prioq_compare(const void *a, const void *b) {
         if (x->time.next < y->time.next)
                 return -1;
         if (x->time.next > y->time.next)
-                return -1;
+                return 1;
 
         /* Stability for the rest */
         if (x < y)
@@ -267,7 +267,7 @@ static int latest_time_prioq_compare(const void *a, const void *b) {
         if (x->time.next + x->time.accuracy < y->time.next + y->time.accuracy)
                 return -1;
         if (x->time.next + x->time.accuracy > y->time.next + y->time.accuracy)
-                return -1;
+                return 1;
 
         /* Stability for the rest */
         if (x < y)

commit 3772995afa7df42c3a332fb085a27cb5d266b893
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Nov 20 03:44:11 2013 +0100

    manager: don't do plymouth in a container
    
    Given that plymouth listens on an abstract namespace socket and if
    CLONE_NEWNET is not used the abstract namespace is shared with the host
    we might actually end up send plymouth data to the host.

diff --git a/src/core/manager.c b/src/core/manager.c
index 86de0e3..dd0d83d 100644
--- a/src/core/manager.c
+++ b/src/core/manager.c
@@ -1806,6 +1806,9 @@ void manager_send_unit_plymouth(Manager *m, Unit *u) {
         if (m->running_as != SYSTEMD_SYSTEM)
                 return;
 
+        if (detect_container(NULL) > 0)
+                return;
+
         if (u->type != UNIT_SERVICE &&
             u->type != UNIT_MOUNT &&
             u->type != UNIT_SWAP)

commit b51f299ae17ebdedecf8f38d98cb94cfee763fa7
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Nov 19 21:37:32 2013 +0100

    busctl: when no match is specified, add default match

diff --git a/src/libsystemd-bus/busctl.c b/src/libsystemd-bus/busctl.c
index b9b3305..4204adb 100644
--- a/src/libsystemd-bus/busctl.c
+++ b/src/libsystemd-bus/busctl.c
@@ -129,6 +129,7 @@ static int list_bus_names(sd_bus *bus, char **argv) {
 }
 
 static int monitor(sd_bus *bus, char *argv[]) {
+        bool added_something = false;
         char **i;
         int r;
 
@@ -149,6 +150,8 @@ static int monitor(sd_bus *bus, char *argv[]) {
                         log_error("Failed to add match: %s", strerror(-r));
                         return r;
                 }
+
+                added_something = true;
         }
 
         STRV_FOREACH(i, arg_matches) {
@@ -157,6 +160,16 @@ static int monitor(sd_bus *bus, char *argv[]) {
                         log_error("Failed to add match: %s", strerror(-r));
                         return r;
                 }
+
+                added_something = true;
+        }
+
+        if (!added_something) {
+                r = sd_bus_add_match(bus, "", NULL, NULL);
+                if (r < 0) {
+                        log_error("Failed to add match: %s", strerror(-r));
+                        return r;
+                }
         }
 
         for (;;) {

commit f8cfb5f5f341e35bb8c8fc76680a95941cdef927
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Nov 19 21:35:31 2013 +0100

    bus: add color and indentation to bus_message_dump()

diff --git a/src/libsystemd-bus/bus-dump.c b/src/libsystemd-bus/bus-dump.c
index 8c44326..8231cfa 100644
--- a/src/libsystemd-bus/bus-dump.c
+++ b/src/libsystemd-bus/bus-dump.c
@@ -30,6 +30,20 @@
 #include "bus-type.h"
 #include "bus-dump.h"
 
+static char *indent(unsigned level) {
+        char *p;
+
+        p = new(char, 2 + level + 1);
+        if (!p)
+                return NULL;
+
+        p[0] = p[1] = ' ';
+        memset(p + 2, '\t', level);
+        p[2 + level] = 0;
+
+        return p;
+}
+
 int bus_message_dump(sd_bus_message *m, FILE *f, bool with_header) {
         const char *u = NULL, *uu = NULL, *s = NULL;
         char **cmdline = NULL;
@@ -37,6 +51,7 @@ int bus_message_dump(sd_bus_message *m, FILE *f, bool with_header) {
         int r;
         uid_t owner, audit_loginuid;
         uint32_t audit_sessionid;
+        bool audit_sessionid_is_set = false, audit_loginuid_is_set = false;
 
         assert(m);
 
@@ -45,10 +60,12 @@ int bus_message_dump(sd_bus_message *m, FILE *f, bool with_header) {
 
         if (with_header) {
                 fprintf(f,
-                        "%sEndian=%c  Type=%s%s%s  Flags=%u  Version=%u  Serial=%u ",
-                        draw_special_char(DRAW_TRIANGULAR_BULLET),
-                        m->header->endian,
+                        "%s%s%sType=%s%s%s  Endian=%c  Flags=%u  Version=%u  Serial=%u ",
+                        m->header->type == SD_BUS_MESSAGE_METHOD_ERROR ? ansi_highlight_red() :
+                        m->header->type == SD_BUS_MESSAGE_METHOD_RETURN ? ansi_highlight_green() :
+                        m->header->type != SD_BUS_MESSAGE_SIGNAL ? ansi_highlight() : "", draw_special_char(DRAW_TRIANGULAR_BULLET), ansi_highlight_off(),
                         ansi_highlight(), bus_message_type_to_string(m->header->type), ansi_highlight_off(),
+                        m->header->endian,
                         m->header->flags,
                         m->header->version,
                         BUS_MESSAGE_SERIAL(m));
@@ -142,12 +159,16 @@ int bus_message_dump(sd_bus_message *m, FILE *f, bool with_header) {
                 sd_bus_message_get_session(m, &s);
                 if (s)
                         fprintf(f, "  Session=%s", s);
-                if (sd_bus_message_get_audit_loginuid(m, &audit_loginuid) >= 0)
+                if (sd_bus_message_get_audit_loginuid(m, &audit_loginuid) >= 0) {
+                        audit_loginuid_is_set = true;
                         fprintf(f, "  AuditLoginUID=%lu", (unsigned long) audit_loginuid);
-                if (sd_bus_message_get_audit_sessionid(m, &audit_sessionid) >= 0)
+                }
+                if (sd_bus_message_get_audit_sessionid(m, &audit_sessionid) >= 0) {
+                        audit_sessionid_is_set = true;
                         fprintf(f, "  AuditSessionID=%lu", (unsigned long) audit_sessionid);
+                }
 
-                if (u || uu || s || audit_loginuid || audit_sessionid)
+                if (u || uu || s || audit_loginuid_is_set || audit_sessionid_is_set)
                         fputs("\n", f);
 
                 r = sd_bus_message_has_effective_cap(m, 0);
@@ -162,6 +183,7 @@ int bus_message_dump(sd_bus_message *m, FILE *f, bool with_header) {
                                 if (r > 0)
                                         fprintf(f, "|%s", cap_to_name(c));
                         }
+                        fputs("\n", f);
                 }
         }
 
@@ -171,7 +193,7 @@ int bus_message_dump(sd_bus_message *m, FILE *f, bool with_header) {
                 return r;
         }
 
-        fprintf(f, "MESSAGE \"%s\" {\n", strempty(m->root_container.signature));
+        fprintf(f, "  MESSAGE \"%s\" {\n", strempty(m->root_container.signature));
 
         for(;;) {
                 _cleanup_free_ char *prefix = NULL;
@@ -208,7 +230,7 @@ int bus_message_dump(sd_bus_message *m, FILE *f, bool with_header) {
 
                         level--;
 
-                        prefix = strrep("\t", level);
+                        prefix = indent(level);
                         if (!prefix)
                                 return log_oom();
 
@@ -216,7 +238,7 @@ int bus_message_dump(sd_bus_message *m, FILE *f, bool with_header) {
                         continue;
                 }
 
-                prefix = strrep("\t", level);
+                prefix = indent(level);
                 if (!prefix)
                         return log_oom();
 
@@ -308,6 +330,6 @@ int bus_message_dump(sd_bus_message *m, FILE *f, bool with_header) {
                 }
         }
 
-        fprintf(f, "};\n");
+        fprintf(f, "  };\n\n");
         return 0;
 }

commit 718db96199eb307751264e4163555662c9a389fa
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Nov 19 21:12:59 2013 +0100

    core: convert PID 1 to libsystemd-bus
    
    This patch converts PID 1 to libsystemd-bus and thus drops the
    dependency on libdbus. The only remaining code using libdbus is a test
    case that validates our bus marshalling against libdbus' marshalling,
    and this dependency can be turned off.
    
    This patch also adds a couple of things to libsystem-bus, that are
    necessary to make the port work:
    
    - Synthesizing of "Disconnected" messages when bus connections are
      severed.
    
    - Support for attaching multiple vtables for the same interface on the
      same path.
    
    This patch also fixes the SetDefaultTarget() and GetDefaultTarget() bus
    calls which used an inappropriate signature.
    
    As a side effect we will now generate PropertiesChanged messages which
    carry property contents, rather than just invalidation information.

diff --git a/Makefile.am b/Makefile.am
index 82e46a9..f7fe96c 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -662,16 +662,19 @@ libsystemd_shared_la_SOURCES = \
 	src/shared/linux/fanotify.h \
 	src/shared/linux/seccomp.h \
 	src/shared/linux/seccomp-bpf.h \
+	src/shared/ioprio.h \
 	src/shared/missing.h \
 	src/shared/list.h \
 	src/shared/macro.h \
 	src/shared/def.h \
+	src/shared/sparse-endian.h \
+	src/shared/refcnt.h \
+	src/shared/udev-util.h \
+	src/shared/bus-errors.h \
 	src/shared/device-nodes.c \
 	src/shared/device-nodes.h \
-	src/shared/sparse-endian.h \
 	src/shared/util.c \
 	src/shared/util.h \
-	src/shared/udev-util.h \
 	src/shared/virt.c \
 	src/shared/virt.h \
 	src/shared/efivars.c \
@@ -712,7 +715,6 @@ libsystemd_shared_la_SOURCES = \
 	src/shared/gunicode.h \
 	src/shared/pager.c \
 	src/shared/pager.h \
-	src/shared/ioprio.h \
 	src/shared/socket-util.c \
 	src/shared/socket-util.h \
 	src/shared/conf-files.c \
@@ -748,7 +750,6 @@ libsystemd_shared_la_SOURCES = \
 	src/shared/acpi-fpdt.c \
 	src/shared/boot-timestamps.h \
 	src/shared/boot-timestamps.c \
-	src/shared/refcnt.h \
 	src/shared/mkdir.c \
 	src/shared/mkdir.h \
 	src/shared/smack-util.c \
@@ -762,21 +763,6 @@ libsystemd_shared_la_SOURCES = \
 	src/shared/net-util.c \
 	src/shared/net-util.h
 
-#-------------------------------------------------------------------------------
-noinst_LTLIBRARIES += \
-	libsystemd-dbus.la
-
-libsystemd_dbus_la_SOURCES = \
-	src/shared/dbus-common.c \
-	src/shared/dbus-common.h
-
-libsystemd_dbus_la_CFLAGS = \
-	$(AM_CFLAGS) \
-	$(DBUS_CFLAGS)
-
-libsystemd_dbus_la_LIBADD = \
-	$(DBUS_LIBS)
-
 # ------------------------------------------------------------------------------
 noinst_LTLIBRARIES += \
 	libsystemd-units.la
@@ -792,8 +778,7 @@ libsystemd_units_la_SOURCES = \
 	src/shared/specifier.h
 
 libsystemd_units_la_CFLAGS = \
-	$(AM_CFLAGS) \
-	$(DBUS_CFLAGS)
+	$(AM_CFLAGS)
 
 # ------------------------------------------------------------------------------
 noinst_LTLIBRARIES += \
@@ -953,6 +938,8 @@ libsystemd_core_la_SOURCES = \
 	src/core/dbus-kill.h \
 	src/core/dbus-cgroup.c \
 	src/core/dbus-cgroup.h \
+	src/core/dbus-client-track.c \
+	src/core/dbus-client-track.h \
 	src/core/cgroup.c \
 	src/core/cgroup.h \
 	src/core/selinux-access.c \
@@ -982,7 +969,6 @@ libsystemd_core_la_SOURCES = \
 	src/core/securebits.h \
 	src/core/initreq.h \
 	src/core/special.h \
-	src/core/bus-errors.h \
 	src/core/build.h \
 	src/core/sysfs-show.h \
 	src/core/switch-root.h \
@@ -1010,7 +996,6 @@ nodist_libsystemd_core_la_SOURCES = \
 
 libsystemd_core_la_CFLAGS = \
 	$(AM_CFLAGS) \
-	$(DBUS_CFLAGS) \
 	$(LIBWRAP_CFLAGS) \
 	$(PAM_CFLAGS) \
 	$(AUDIT_CFLAGS) \
@@ -1021,13 +1006,13 @@ libsystemd_core_la_LIBADD = \
 	libsystemd-capability.la \
 	libsystemd-units.la \
 	libsystemd-label.la \
-	libsystemd-dbus.la \
 	libsystemd-audit.la \
 	libsystemd-id128-internal.la \
 	libsystemd-daemon-internal.la \
 	libudev-internal.la \
 	libsystemd-shared.la \
 	libsystemd-rtnl.la \
+	libsystemd-bus-internal.la \
 	$(LIBWRAP_LIBS) \
 	$(PAM_LIBS) \
 	$(AUDIT_LIBS) \
@@ -1072,10 +1057,6 @@ src/core/syscall-to-name.h: src/core/syscall-list.txt Makefile
 systemd_SOURCES = \
 	src/core/main.c
 
-systemd_CFLAGS = \
-	$(AM_CFLAGS) \
-	$(DBUS_CFLAGS)
-
 systemd_LDADD = \
 	libsystemd-core.la \
 	$(RT_LIBS)
@@ -1166,10 +1147,6 @@ test_device_nodes_LDADD = \
 test_engine_SOURCES = \
 	src/test/test-engine.c
 
-test_engine_CFLAGS = \
-	$(AM_CFLAGS) \
-	$(DBUS_CFLAGS)
-
 test_engine_LDADD = \
 	libsystemd-core.la \
 	$(RT_LIBS)
@@ -1177,10 +1154,6 @@ test_engine_LDADD = \
 test_job_type_SOURCES = \
 	src/test/test-job-type.c
 
-test_job_type_CFLAGS = \
-	$(AM_CFLAGS) \
-	$(DBUS_CFLAGS)
-
 test_job_type_LDADD = \
 	libsystemd-core.la \
 	$(RT_LIBS)
@@ -1191,10 +1164,6 @@ test_ns_SOURCES = \
 test_ns_LDADD = \
 	libsystemd-core.la
 
-test_ns_CFLAGS = \
-	$(AM_CFLAGS) \
-	$(DBUS_CFLAGS)
-
 test_loopback_SOURCES = \
 	src/test/test-loopback.c
 
@@ -1221,10 +1190,6 @@ endif
 test_unit_name_SOURCES = \
 	src/test/test-unit-name.c
 
-test_unit_name_CFLAGS = \
-	$(AM_CFLAGS) \
-	$(DBUS_CFLAGS)
-
 test_unit_name_LDADD = \
 	libsystemd-core.la \
 	$(RT_LIBS)
@@ -1232,10 +1197,6 @@ test_unit_name_LDADD = \
 test_unit_file_SOURCES = \
 	src/test/test-unit-file.c
 
-test_unit_file_CFLAGS = \
-	$(AM_CFLAGS) \
-	$(DBUS_CFLAGS)
-
 test_unit_file_LDADD = \
 	libsystemd-core.la \
 	$(RT_LIBS)
@@ -1274,10 +1235,6 @@ test_tables_SOURCES = \
 	src/test/test-tables.c \
 	src/shared/test-tables.h
 
-test_tables_CFLAGS = \
-	$(AM_CFLAGS) \
-	$(DBUS_CFLAGS)
-
 test_tables_LDADD = \
 	libsystemd-logs.la \
 	libsystemd-journal-internal.la \
@@ -1401,10 +1358,6 @@ test_strxcpyx_LDADD = \
 test_install_SOURCES = \
 	src/test/test-install.c
 
-test_install_CFLAGS = \
-	$(AM_CFLAGS) \
-	$(DBUS_CFLAGS)
-
 test_install_LDADD = \
 	libsystemd-units.la \
 	libsystemd-label.la \
@@ -1422,7 +1375,6 @@ test_sched_prio_SOURCES = \
 
 test_sched_prio_CFLAGS = \
 	$(AM_CFLAGS) \
-	$(DBUS_CFLAGS) \
 	-D"STR(s)=\#s" -D"TEST_DIR=STR($(abs_top_srcdir)/test/)"
 
 test_sched_prio_LDADD = \
@@ -2800,9 +2752,6 @@ mtd_probe_SOURCES =  \
 	src/udev/mtd_probe/mtd_probe.h \
 	src/udev/mtd_probe/probe_smartmedia.c
 
-mtd_probe_CPPFLAGS = \
-	$(AM_CPPFLAGS)
-
 dist_udevrules_DATA += \
 	rules/75-probe_mtd.rules
 
@@ -3893,7 +3842,6 @@ systemd_logind_LDADD = \
 
 libsystemd_logind_core_la_SOURCES = \
 	src/login/logind-core.c \
-	src/login/logind-dbus.c \
 	src/login/logind-device.c \
 	src/login/logind-device.h \
 	src/login/logind-button.c \
@@ -3910,6 +3858,7 @@ libsystemd_logind_core_la_SOURCES = \
 	src/login/logind-user.h \
 	src/login/logind-inhibit.c \
 	src/login/logind-inhibit.h \
+	src/login/logind-dbus.c \
 	src/login/logind-session-dbus.c \
 	src/login/logind-seat-dbus.c \
 	src/login/logind-user-dbus.c \
diff --git a/TODO b/TODO
index efc7e2a..e387486 100644
--- a/TODO
+++ b/TODO
@@ -43,6 +43,53 @@ CGroup Rework Completion:
 
 Features:
 
+* sd-event: allow multiple signal handlers per signal
+
+* timer: expose accuracy as unit setting
+
+* sd-event: do per-minute coalescing of timer events too
+
+* when we detect low battery and no AC on boot, show pretty splash and refuse boot
+
+* move libasyncns into systemd as libsystemd-asyncns
+
+* calendarspec: support value ranges with ".." notation. Example: 2013-4..8-1
+
+* pid1 porting:
+  - restore selinux access control on properties
+
+* sd-bus: when triggering property change events, allow a NULL strv indicate that all properties listed as such are send out as changed
+
+* sd-bus: enforce signatures on response messages
+
+* sd-bus: make message handlers take an sd_bus_error and generate error replies automatically if they are set
+
+* sd-bus: when replying to a bus message we should not need to specify the bus again
+
+* sd-bus: see if we can drop more message validation on the sending side
+
+* sd-bus: introduce sd_bus_creds object and attach it to messages as well as allow querying it for names
+
+* sd-bus: support "const" properties as flag
+
+* sd-bus: add api call to escape bus path components
+
+* sd-event: when a handler returns an error, just turn off its event
+  source, but do not return anything up to the event loop
+  caller. Instead add parameter to sd_event_request_quit() to take
+  retval. This way errors rippling upwards are the option, not the
+  default
+
+* sd-event: child pid handling: first invoke waitid(WNOHANG) and call event handler, only afterwards reap the process
+
+* sd-event: native support for watchdog stuff
+
+* machined, localed: when we try to kill an empty cgroup, generate an ESRCH call over the bus
+
+* sd-bus: SD_BUS_COMMENT() macro for inclusion in vtables, syntax inspired by gdbus
+
+* libsystemd-journal, libsystemd-login, libudev: add calls to easily attach these objects to sd-event event loops
+
 * be more careful what we export on the bus as (usec_t) 0 and (usec_t) -1
 
 * check :no-sender logic after PID 1 conversion
diff --git a/src/core/automount.c b/src/core/automount.c
index d1379e0..49a64b1 100644
--- a/src/core/automount.c
+++ b/src/core/automount.c
@@ -35,13 +35,13 @@
 #include "load-fragment.h"
 #include "load-dropin.h"
 #include "unit-name.h"
-#include "dbus-automount.h"
-#include "bus-errors.h"
 #include "special.h"
 #include "label.h"
 #include "mkdir.h"
 #include "path-util.h"
-#include "dbus-common.h"
+#include "dbus-automount.h"
+#include "bus-util.h"
+#include "bus-error.h"
 
 static const UnitActiveState state_translation_table[_AUTOMOUNT_STATE_MAX] = {
         [AUTOMOUNT_DEAD] = UNIT_INACTIVE,
@@ -51,6 +51,7 @@ static const UnitActiveState state_translation_table[_AUTOMOUNT_STATE_MAX] = {
 };
 
 static int open_dev_autofs(Manager *m);
+static int automount_dispatch_io(sd_event_source *s, int fd, uint32_t events, void *userdata);
 
 static void automount_init(Unit *u) {
         Automount *a = AUTOMOUNT(u);
@@ -58,11 +59,8 @@ static void automount_init(Unit *u) {
         assert(u);
         assert(u->load_state == UNIT_STUB);
 
-        a->pipe_watch.fd = a->pipe_fd = -1;
-        a->pipe_watch.type = WATCH_INVALID;
-
+        a->pipe_fd = -1;
         a->directory_mode = 0755;
-
         UNIT(a)->ignore_on_isolate = true;
 }
 
@@ -91,7 +89,8 @@ static void unmount_autofs(Automount *a) {
 
         automount_send_ready(a, -EHOSTDOWN);
 
-        unit_unwatch_fd(UNIT(a), &a->pipe_watch);
+        a->pipe_event_source = sd_event_source_unref(a->pipe_event_source);
+
         close_nointr_nofail(a->pipe_fd);
         a->pipe_fd = -1;
 
@@ -257,7 +256,7 @@ static int automount_coldplug(Unit *u) {
 
                         assert(a->pipe_fd >= 0);
 
-                        r = unit_watch_fd(UNIT(a), a->pipe_fd, EPOLLIN, &a->pipe_watch);
+                        r = sd_event_add_io(u->manager->event, a->pipe_fd, EPOLLIN, automount_dispatch_io, u, &a->pipe_event_source);
                         if (r < 0)
                                 return r;
                 }
@@ -532,7 +531,7 @@ static void automount_enter_waiting(Automount *a) {
         close_nointr_nofail(ioctl_fd);
         ioctl_fd = -1;
 
-        r = unit_watch_fd(UNIT(a), p[0], EPOLLIN, &a->pipe_watch);
+        r = sd_event_add_io(UNIT(a)->manager->event, p[0], EPOLLIN, automount_dispatch_io, a, &a->pipe_event_source);
         if (r < 0)
                 goto fail;
 
@@ -558,14 +557,12 @@ fail:
 }
 
 static void automount_enter_runnning(Automount *a) {
-        _cleanup_dbus_error_free_ DBusError error;
+        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
         struct stat st;
         int r;
 
         assert(a);
 
-        dbus_error_init(&error);
-
         /* We don't take mount requests anymore if we are supposed to
          * shut down anyway */
         if (unit_stop_pending(UNIT(a))) {
@@ -593,7 +590,7 @@ static void automount_enter_runnning(Automount *a) {
                 if (r < 0) {
                         log_warning_unit(UNIT(a)->id,
                                          "%s failed to queue mount startup job: %s",
-                                         UNIT(a)->id, bus_error(&error, r));
+                                         UNIT(a)->id, bus_error_message(&error, r));
                         goto fail;
                 }
         }
@@ -748,9 +745,9 @@ static bool automount_check_gc(Unit *u) {
         return UNIT_VTABLE(UNIT_TRIGGER(u))->check_gc(UNIT_TRIGGER(u));
 }
 
-static void automount_fd_event(Unit *u, int fd, uint32_t events, Watch *w) {
-        Automount *a = AUTOMOUNT(u);
+static int automount_dispatch_io(sd_event_source *s, int fd, uint32_t events, void *userdata) {
         union autofs_v5_packet_union packet;
+        Automount *a = AUTOMOUNT(userdata);
         ssize_t l;
         int r;
 
@@ -758,13 +755,13 @@ static void automount_fd_event(Unit *u, int fd, uint32_t events, Watch *w) {
         assert(fd == a->pipe_fd);
 
         if (events != EPOLLIN) {
-                log_error_unit(u->id, "Got invalid poll event on pipe.");
+                log_error_unit(UNIT(a)->id, "Got invalid poll event on pipe.");
                 goto fail;
         }
 
         l = loop_read(a->pipe_fd, &packet, sizeof(packet), true);
         if (l != sizeof(packet)) {
-                log_error_unit(u->id, "Invalid read from pipe: %s", l < 0 ? strerror(-l) : "short read");
+                log_error_unit(UNIT(a)->id, "Invalid read from pipe: %s", l < 0 ? strerror(-l) : "short read");
                 goto fail;
         }
 
@@ -776,21 +773,21 @@ static void automount_fd_event(Unit *u, int fd, uint32_t events, Watch *w) {
                         _cleanup_free_ char *p = NULL;
 
                         get_process_comm(packet.v5_packet.pid, &p);
-                        log_debug_unit(u->id,
+                        log_debug_unit(UNIT(a)->id,
                                        "Got direct mount request on %s, triggered by %lu (%s)",
                                        a->where, (unsigned long) packet.v5_packet.pid, strna(p));
                 } else
-                        log_debug_unit(u->id, "Got direct mount request on %s", a->where);
+                        log_debug_unit(UNIT(a)->id, "Got direct mount request on %s", a->where);
 
                 r = set_ensure_allocated(&a->tokens, trivial_hash_func, trivial_compare_func);
                 if (r < 0) {
-                        log_error_unit(u->id, "Failed to allocate token set.");
+                        log_error_unit(UNIT(a)->id, "Failed to allocate token set.");
                         goto fail;
                 }
 
                 r = set_put(a->tokens, UINT_TO_PTR(packet.v5_packet.wait_queue_token));
                 if (r < 0) {
-                        log_error_unit(u->id, "Failed to remember token: %s", strerror(-r));
+                        log_error_unit(UNIT(a)->id, "Failed to remember token: %s", strerror(-r));
                         goto fail;
                 }
 
@@ -798,14 +795,15 @@ static void automount_fd_event(Unit *u, int fd, uint32_t events, Watch *w) {
                 break;
 
         default:
-                log_error_unit(u->id, "Received unknown automount request %i", packet.hdr.type);
+                log_error_unit(UNIT(a)->id, "Received unknown automount request %i", packet.hdr.type);
                 break;
         }
 
-        return;
+        return 0;
 
 fail:
         automount_enter_dead(a, AUTOMOUNT_FAILURE_RESOURCES);
+        return 0;
 }
 
 static void automount_shutdown(Manager *m) {
@@ -844,6 +842,7 @@ DEFINE_STRING_TABLE_LOOKUP(automount_result, AutomountResult);
 
 const UnitVTable automount_vtable = {
         .object_size = sizeof(Automount),
+
         .sections =
                 "Unit\0"
                 "Automount\0"
@@ -871,13 +870,11 @@ const UnitVTable automount_vtable = {
 
         .check_gc = automount_check_gc,
 
-        .fd_event = automount_fd_event,
-
         .reset_failed = automount_reset_failed,
 
         .bus_interface = "org.freedesktop.systemd1.Automount",
-        .bus_message_handler = bus_automount_message_handler,
-        .bus_invalidating_properties = bus_automount_invalidating_properties,
+        .bus_vtable = bus_automount_vtable,
+        .bus_changing_properties = bus_automount_changing_properties,
 
         .shutdown = automount_shutdown,
 
diff --git a/src/core/automount.h b/src/core/automount.h
index a7a25d3..60f5522 100644
--- a/src/core/automount.h
+++ b/src/core/automount.h
@@ -49,8 +49,8 @@ struct Automount {
         char *where;
 
         int pipe_fd;
+        sd_event_source *pipe_event_source;
         mode_t directory_mode;
-        Watch pipe_watch;
         dev_t dev_id;
 
         Set *tokens;
diff --git a/src/core/dbus-automount.c b/src/core/dbus-automount.c
index 720f9ba..420cfaa 100644
--- a/src/core/dbus-automount.c
+++ b/src/core/dbus-automount.c
@@ -19,57 +19,23 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <errno.h>
-
+#include "unit.h"
+#include "automount.h"
 #include "dbus-unit.h"
 #include "dbus-automount.h"
-#include "dbus-common.h"
-#include "selinux-access.h"
-
-#define BUS_AUTOMOUNT_INTERFACE                                      \
-        " <interface name=\"org.freedesktop.systemd1.Automount\">\n" \
-        "  <property name=\"Where\" type=\"s\" access=\"read\"/>\n"  \
-        "  <property name=\"DirectoryMode\" type=\"u\" access=\"read\"/>\n" \
-        "  <property name=\"Result\" type=\"s\" access=\"read\"/>\n"    \
-        " </interface>\n"
-
-#define INTROSPECTION                                                \
-        DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE                    \
-        "<node>\n"                                                   \
-        BUS_UNIT_INTERFACE                                           \
-        BUS_AUTOMOUNT_INTERFACE                                      \
-        BUS_PROPERTIES_INTERFACE                                     \
-        BUS_PEER_INTERFACE                                           \
-        BUS_INTROSPECTABLE_INTERFACE                                 \
-        "</node>\n"
-
-#define INTERFACES_LIST                              \
-        BUS_UNIT_INTERFACES_LIST                     \
-        "org.freedesktop.systemd1.Automount\0"
-
-const char bus_automount_interface[] = BUS_AUTOMOUNT_INTERFACE;
+#include "bus-util.h"
 
-const char bus_automount_invalidating_properties[] =
-        "Result\0";
+static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_result, automount_result, AutomountResult);
 
-static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_automount_append_automount_result, automount_result, AutomountResult);
-
-static const BusProperty bus_automount_properties[] = {
-        { "Where",         bus_property_append_string, "s", offsetof(Automount, where),    true },
-        { "DirectoryMode", bus_property_append_mode,   "u", offsetof(Automount, directory_mode) },
-        { "Result",        bus_automount_append_automount_result, "s", offsetof(Automount, result) },
-        { NULL, }
+const sd_bus_vtable bus_automount_vtable[] = {
+        SD_BUS_VTABLE_START(0),
+        SD_BUS_PROPERTY("Where", "s", NULL, offsetof(Automount, where), 0),
+        SD_BUS_PROPERTY("DirectoryMode", "u", bus_property_get_mode, offsetof(Automount, directory_mode), 0),
+        SD_BUS_PROPERTY("Result", "s", property_get_result, offsetof(Automount, result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+        SD_BUS_VTABLE_END
 };
 
-DBusHandlerResult bus_automount_message_handler(Unit *u, DBusConnection *c, DBusMessage *message) {
-        Automount *am = AUTOMOUNT(u);
-        const BusBoundProperties bps[] = {
-                { "org.freedesktop.systemd1.Unit",      bus_unit_properties,      u  },
-                { "org.freedesktop.systemd1.Automount", bus_automount_properties, am },
-                { NULL, }
-        };
-
-        SELINUX_UNIT_ACCESS_CHECK(u, c, message, "status");
-
-        return bus_default_message_handler(c, message, INTROSPECTION, INTERFACES_LIST, bps);
-}
+const char* const bus_automount_changing_properties[] = {
+        "Result",
+        NULL
+};
diff --git a/src/core/dbus-automount.h b/src/core/dbus-automount.h
index b338e25..0b96183 100644
--- a/src/core/dbus-automount.h
+++ b/src/core/dbus-automount.h
@@ -21,11 +21,7 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <dbus/dbus.h>
+#include "sd-bus.h"
 
-#include "unit.h"
-
-DBusHandlerResult bus_automount_message_handler(Unit *u, DBusConnection *c, DBusMessage *message);
-
-extern const char bus_automount_interface[];
-extern const char bus_automount_invalidating_properties[];
+extern const sd_bus_vtable bus_automount_vtable[];
+extern const char* const bus_automount_changing_properties[];
diff --git a/src/core/dbus-cgroup.c b/src/core/dbus-cgroup.c
index f198357..4dbb83a 100644
--- a/src/core/dbus-cgroup.c
+++ b/src/core/dbus-cgroup.c
@@ -19,147 +19,159 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <dbus/dbus.h>
-
+#include "bus-util.h"
 #include "path-util.h"
+#include "cgroup-util.h"
+#include "cgroup.h"
 #include "dbus-cgroup.h"
 
-static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_cgroup_append_device_policy, cgroup_device_policy, CGroupDevicePolicy);
+static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_cgroup_device_policy, cgroup_device_policy, CGroupDevicePolicy);
+
+static int property_get_blockio_device_weight(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
 
-static int bus_cgroup_append_device_weights(DBusMessageIter *i, const char *property, void *data) {
-        DBusMessageIter sub, sub2;
-        CGroupContext *c = data;
+        CGroupContext *c = userdata;
         CGroupBlockIODeviceWeight *w;
+        int r;
 
-        assert(i);
-        assert(property);
+        assert(bus);
+        assert(reply);
         assert(c);
 
-        if (!dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, "(st)", &sub))
-                return -ENOMEM;
+        r = sd_bus_message_open_container(reply, 'a', "(st)");
+        if (r < 0)
+                return r;
 
         LIST_FOREACH(device_weights, w, c->blockio_device_weights) {
-
-                if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
-                    !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &w->path) ||
-                    !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT64, &w->weight) ||
-                    !dbus_message_iter_close_container(&sub, &sub2))
-                        return -ENOMEM;
+                r = sd_bus_message_append(reply, "(st)", w->path, w->weight);
+                if (r < 0)
+                        return r;
         }
 
-        if (!dbus_message_iter_close_container(i, &sub))
-                return -ENOMEM;
-
-        return 0;
+        return sd_bus_message_close_container(reply);
 }
 
-static int bus_cgroup_append_device_bandwidths(DBusMessageIter *i, const char *property, void *data) {
-        DBusMessageIter sub, sub2;
-        CGroupContext *c = data;
+static int property_get_blockio_device_bandwidths(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
+
+        CGroupContext *c = userdata;
         CGroupBlockIODeviceBandwidth *b;
+        int r;
 
-        assert(i);
-        assert(property);
+        assert(bus);
+        assert(reply);
         assert(c);
 
-        if (!dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, "(st)", &sub))
-                return -ENOMEM;
+        r = sd_bus_message_open_container(reply, 'a', "(st)");
+        if (r < 0)
+                return r;
 
         LIST_FOREACH(device_bandwidths, b, c->blockio_device_bandwidths) {
 
                 if (streq(property, "BlockIOReadBandwidth") != b->read)
                         continue;
 
-                if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
-                    !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &b->path) ||
-                    !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT64, &b->bandwidth) ||
-                    !dbus_message_iter_close_container(&sub, &sub2))
-                        return -ENOMEM;
+                r = sd_bus_message_append(reply, "(st)", b->path, b->bandwidth);
+                if (r < 0)
+                        return r;
         }
 
-        if (!dbus_message_iter_close_container(i, &sub))
-                return -ENOMEM;
-
-        return 0;
+        return sd_bus_message_close_container(reply);
 }
 
-static int bus_cgroup_append_device_allow(DBusMessageIter *i, const char *property, void *data) {
-        DBusMessageIter sub, sub2;
-        CGroupContext *c = data;
+static int property_get_device_allow(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
+
+        CGroupContext *c = userdata;
         CGroupDeviceAllow *a;
+        int r;
 
-        assert(i);
-        assert(property);
+        assert(bus);
+        assert(reply);
         assert(c);
 
-        if (!dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, "(ss)", &sub))
-                return -ENOMEM;
+        r = sd_bus_message_open_container(reply, 'a', "(ss)");
+        if (r < 0)
+                return r;
 
         LIST_FOREACH(device_allow, a, c->device_allow) {
-                const char *rwm;
-                char buf[4];
                 unsigned k = 0;
+                char rwm[4];
 
                 if (a->r)
-                        buf[k++] = 'r';
+                        rwm[k++] = 'r';
                 if (a->w)
-                        buf[k++] = 'w';
+                        rwm[k++] = 'w';
                 if (a->m)
-                        buf[k++] = 'm';
+                        rwm[k++] = 'm';
 
-                buf[k] = 0;
-                rwm = buf;
+                rwm[k] = 0;
 
-                if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
-                    !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &a->path) ||
-                    !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &rwm) ||
-                    !dbus_message_iter_close_container(&sub, &sub2))
-                        return -ENOMEM;
+                r = sd_bus_message_append(reply, "(ss)", a->path, rwm);
+                if (r < 0)
+                        return r;
         }
 
-        if (!dbus_message_iter_close_container(i, &sub))
-                return -ENOMEM;
-
-        return 0;
+        return sd_bus_message_close_container(reply);
 }
 
-const BusProperty bus_cgroup_context_properties[] = {
-        { "CPUAccounting",           bus_property_append_bool,            "b",     offsetof(CGroupContext, cpu_accounting)     },
-        { "CPUShares",               bus_property_append_ul,              "t",     offsetof(CGroupContext, cpu_shares)         },
-        { "BlockIOAccounting",       bus_property_append_bool,            "b",     offsetof(CGroupContext, blockio_accounting) },
-        { "BlockIOWeight",           bus_property_append_ul,              "t",     offsetof(CGroupContext, blockio_weight)     },
-        { "BlockIODeviceWeight",     bus_cgroup_append_device_weights,    "a(st)", 0                                           },
-        { "BlockIOReadBandwidth",    bus_cgroup_append_device_bandwidths, "a(st)", 0                                           },
-        { "BlockIOWriteBandwidth",   bus_cgroup_append_device_bandwidths, "a(st)", 0                                           },
-        { "MemoryAccounting",        bus_property_append_bool,            "b",     offsetof(CGroupContext, memory_accounting)  },
-        { "MemoryLimit",             bus_property_append_uint64,          "t",     offsetof(CGroupContext, memory_limit)       },
-        { "DevicePolicy",            bus_cgroup_append_device_policy,     "s",     offsetof(CGroupContext, device_policy)      },
-        { "DeviceAllow",             bus_cgroup_append_device_allow,      "a(ss)", 0                                           },
-        {}
+const sd_bus_vtable bus_cgroup_vtable[] = {
+        SD_BUS_VTABLE_START(0),
+        SD_BUS_PROPERTY("CPUAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, cpu_accounting), 0),
+        SD_BUS_PROPERTY("CPUShares", "t", bus_property_get_ulong, offsetof(CGroupContext, cpu_shares), 0),
+        SD_BUS_PROPERTY("BlockIOAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, blockio_accounting), 0),
+        SD_BUS_PROPERTY("BlockIOWeight", "t", bus_property_get_ulong, offsetof(CGroupContext, blockio_weight), 0),
+        SD_BUS_PROPERTY("BlockIODeviceWeight", "a(st)", property_get_blockio_device_weight, 0, 0),
+        SD_BUS_PROPERTY("BlockIOReadBandwidth", "a(st)", property_get_blockio_device_bandwidths, 0, 0),
+        SD_BUS_PROPERTY("BlockIOWriteBandwidth", "a(st)", property_get_blockio_device_bandwidths, 0, 0),
+        SD_BUS_PROPERTY("MemoryAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, memory_accounting), 0),
+        SD_BUS_PROPERTY("MemoryLimit", "t", NULL, offsetof(CGroupContext, memory_limit), 0),
+        SD_BUS_PROPERTY("DevicePolicy", "s", property_get_cgroup_device_policy, offsetof(CGroupContext, device_policy), 0),
+        SD_BUS_PROPERTY("DeviceAllow", "a(ss)", property_get_device_allow, 0, 0),
+        SD_BUS_VTABLE_END
 };
 
 int bus_cgroup_set_property(
                 Unit *u,
                 CGroupContext *c,
                 const char *name,
-                DBusMessageIter *i,
+                sd_bus_message *message,
                 UnitSetPropertiesMode mode,
-                DBusError *error) {
+                sd_bus_error *error) {
+
+        int r;
 
-        assert(name);
         assert(u);
         assert(c);
-        assert(i);
+        assert(name);
+        assert(message);
 
         if (streq(name, "CPUAccounting")) {
+                int b;
 
-                if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_BOOLEAN)
-                        return -EINVAL;
+                r = sd_bus_message_read(message, "b", &b);
+                if (r < 0)
+                        return r;
 
                 if (mode != UNIT_CHECK) {
-                        dbus_bool_t b;
-                        dbus_message_iter_get_basic(i, &b);
-
                         c->cpu_accounting = b;
                         unit_write_drop_in_private(u, mode, name, b ? "CPUAccounting=yes" : "CPUAccounting=no");
                 }
@@ -170,14 +182,13 @@ int bus_cgroup_set_property(
                 uint64_t u64;
                 unsigned long ul;
 
-                if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_UINT64)
-                        return -EINVAL;
+                r = sd_bus_message_read(message, "t", &u64);
+                if (r < 0)
+                        return r;
 
-                dbus_message_iter_get_basic(i, &u64);
                 ul = (unsigned long) u64;
-
-                if (u64 <= 0 || u64 != (uint64_t) ul)
-                        return -EINVAL;
+                if (ul <= 0 || (uint64_t) ul != u64)
+                        return sd_bus_error_set_errnof(error, EINVAL, "CPUShares value out of range");
 
                 if (mode != UNIT_CHECK) {
                         c->cpu_shares = ul;
@@ -187,14 +198,13 @@ int bus_cgroup_set_property(
                 return 1;
 
         } else if (streq(name, "BlockIOAccounting")) {
+                int b;
 
-                if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_BOOLEAN)
-                        return -EINVAL;
+                r = sd_bus_message_read(message, "b", &b);
+                if (r < 0)
+                        return r;
 
                 if (mode != UNIT_CHECK) {
-                        dbus_bool_t b;
-                        dbus_message_iter_get_basic(i, &b);
-
                         c->blockio_accounting = b;
                         unit_write_drop_in_private(u, mode, name, b ? "BlockIOAccounting=yes" : "BlockIOAccounting=no");
                 }
@@ -205,14 +215,13 @@ int bus_cgroup_set_property(
                 uint64_t u64;
                 unsigned long ul;
 
-                if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_UINT64)
-                        return -EINVAL;
+                r = sd_bus_message_read(message, "t", &u64);
+                if (r < 0)
+                        return r;
 
-                dbus_message_iter_get_basic(i, &u64);
                 ul = (unsigned long) u64;
-
-                if (u64 < 10 || u64 > 1000)
-                        return -EINVAL;
+                if (ul < 10 || ul > 1000)
+                        return sd_bus_error_set_errnof(error, EINVAL, "BlockIOWeight value out of range");
 
                 if (mode != UNIT_CHECK) {
                         c->blockio_weight = ul;
@@ -222,42 +231,31 @@ int bus_cgroup_set_property(
                 return 1;
 
         } else if (streq(name, "BlockIOReadBandwidth") || streq(name, "BlockIOWriteBandwidth")) {
-                DBusMessageIter sub;
-                unsigned n = 0;
+                const char *path;
                 bool read = true;
+                unsigned n = 0;
+                uint64_t u64;
 
                 if (streq(name, "BlockIOWriteBandwidth"))
                         read = false;
 
-                if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_ARRAY ||
-                    dbus_message_iter_get_element_type(i) != DBUS_TYPE_STRUCT)
-                         return -EINVAL;
-
-                dbus_message_iter_recurse(i, &sub);
-                while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
-                        DBusMessageIter sub2;
-                        const char *path;
-                        uint64_t u64;
+                r = sd_bus_message_enter_container(message, 'a', "(st)");
+                if (r < 0)
+                        return r;
 
-                        dbus_message_iter_recurse(&sub, &sub2);
-                        if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0 ||
-                            bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &u64, false) < 0)
-                                return -EINVAL;
+                while ((r = sd_bus_message_read(message, "(st)", &path, &u64)) > 0) {
 
                         if (mode != UNIT_CHECK) {
-                                CGroupBlockIODeviceBandwidth *a = NULL;
-                                CGroupBlockIODeviceBandwidth *b;
-                                bool exist = false;
+                                CGroupBlockIODeviceBandwidth *a = NULL, *b;
 
                                 LIST_FOREACH(device_bandwidths, b, c->blockio_device_bandwidths) {
                                         if (path_equal(path, b->path) && read == b->read) {
                                                 a = b;
-                                                exist = true;
                                                 break;
                                         }
                                 }
 
-                                if (!exist) {
+                                if (!a) {
                                         a = new0(CGroupBlockIODeviceBandwidth, 1);
                                         if (!a)
                                                 return -ENOMEM;
@@ -268,23 +266,22 @@ int bus_cgroup_set_property(
                                                 free(a);
                                                 return -ENOMEM;
                                         }
+
+                                        LIST_PREPEND(device_bandwidths, c->blockio_device_bandwidths, a);
                                 }
 
                                 a->bandwidth = u64;
-
-                                if (!exist)
-                                        LIST_PREPEND(device_bandwidths, c->blockio_device_bandwidths, a);
                         }
 
                         n++;
-                        dbus_message_iter_next(&sub);
                 }
+                if (r < 0)
+                        return r;
 
                 if (mode != UNIT_CHECK) {
+                        CGroupBlockIODeviceBandwidth *a, *next;
                         _cleanup_free_ char *buf = NULL;
                         _cleanup_fclose_ FILE *f = NULL;
-                        CGroupBlockIODeviceBandwidth *a;
-                        CGroupBlockIODeviceBandwidth *next;
                         size_t size = 0;
 
                         if (n == 0) {
@@ -316,44 +313,32 @@ int bus_cgroup_set_property(
                 return 1;
 
         } else if (streq(name, "BlockIODeviceWeight")) {
-                DBusMessageIter sub;
+                const char *path;
+                uint64_t u64;
                 unsigned n = 0;
 
-                if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_ARRAY ||
-                    dbus_message_iter_get_element_type(i) != DBUS_TYPE_STRUCT)
-                        return -EINVAL;
+                r = sd_bus_message_enter_container(message, 'a', "(st)");
+                if (r < 0)
+                        return r;
 
-                dbus_message_iter_recurse(i, &sub);
-                while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
-                        DBusMessageIter sub2;
-                        const char *path;
-                        uint64_t u64;
+                while (( r = sd_bus_message_read(message, "(st)", &path, &u64)) > 0) {
                         unsigned long ul;
 
-                        dbus_message_iter_recurse(&sub, &sub2);
-
-                        if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0 ||
-                            bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &u64, false) < 0)
-                                return -EINVAL;
-
                         ul = (unsigned long) u64;
                         if (ul < 10 || ul > 1000)
-                                return -EINVAL;
+                                return sd_bus_error_set_errnof(error, EINVAL, "BlockIODeviceWeight out of range");
 
                         if (mode != UNIT_CHECK) {
-                                CGroupBlockIODeviceWeight *a = NULL;
-                                CGroupBlockIODeviceWeight *b;
-                                bool exist = false;
+                                CGroupBlockIODeviceWeight *a = NULL, *b;
 
                                 LIST_FOREACH(device_weights, b, c->blockio_device_weights) {
                                         if (path_equal(b->path, path)) {
                                                 a = b;
-                                                exist = true;
                                                 break;
                                         }
                                 }
 
-                                if (!exist) {
+                                if (!a) {
                                         a = new0(CGroupBlockIODeviceWeight, 1);
                                         if (!a)
                                                 return -ENOMEM;
@@ -363,16 +348,13 @@ int bus_cgroup_set_property(
                                                 free(a);
                                                 return -ENOMEM;
                                         }
+                                        LIST_PREPEND(device_weights,c->blockio_device_weights, a);
                                 }
 
                                 a->weight = ul;
-
-                                if (!exist)
-                                        LIST_PREPEND(device_weights,c->blockio_device_weights, a);
                         }
 
                         n++;
-                        dbus_message_iter_next(&sub);
                 }
 
                 if (mode != UNIT_CHECK) {
@@ -401,14 +383,13 @@ int bus_cgroup_set_property(
                 return 1;
 
         } else if (streq(name, "MemoryAccounting")) {
+                int b;
 
-                if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_BOOLEAN)
-                        return -EINVAL;
+                r = sd_bus_message_read(message, "b", &b);
+                if (r < 0)
+                        return r;
 
                 if (mode != UNIT_CHECK) {
-                        dbus_bool_t b;
-                        dbus_message_iter_get_basic(i, &b);
-
                         c->memory_accounting = b;
                         unit_write_drop_in_private(u, mode, name, b ? "MemoryAccounting=yes" : "MemoryAccounting=no");
                 }
@@ -416,14 +397,13 @@ int bus_cgroup_set_property(
                 return 1;
 
         } else if (streq(name, "MemoryLimit")) {
+                uint64_t limit;
 
-                if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_UINT64)
-                        return -EINVAL;
+                r = sd_bus_message_read(message, "t", &limit);
+                if (r < 0)
+                        return r;
 
                 if (mode != UNIT_CHECK) {
-                        uint64_t limit;
-                        dbus_message_iter_get_basic(i, &limit);
-
                         c->memory_limit = limit;
                         unit_write_drop_in_private_format(u, mode, name, "%s=%" PRIu64, name, limit);
                 }
@@ -434,10 +414,10 @@ int bus_cgroup_set_property(
                 const char *policy;
                 CGroupDevicePolicy p;
 
-                if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_STRING)
-                        return -EINVAL;
+                r = sd_bus_message_read(message, "s", &policy);
+                if (r < 0)
+                        return r;
 
-                dbus_message_iter_get_basic(i, &policy);
                 p = cgroup_device_policy_from_string(policy);
                 if (p < 0)
                         return -EINVAL;
@@ -454,51 +434,35 @@ int bus_cgroup_set_property(
                 return 1;
 
         } else if (streq(name, "DeviceAllow")) {
-                DBusMessageIter sub;
+                const char *path, *rwm;
                 unsigned n = 0;
 
-                if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_ARRAY ||
-                    dbus_message_iter_get_element_type(i) != DBUS_TYPE_STRUCT)
-                        return -EINVAL;
-
-                dbus_message_iter_recurse(i, &sub);
-                while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
-                        DBusMessageIter sub2;
-                        const char *path, *rwm;
+                r = sd_bus_message_enter_container(message, 'a', "(ss)");
+                if (r < 0)
+                        return r;
 
-                        dbus_message_iter_recurse(&sub, &sub2);
+                while ((r = sd_bus_message_read(message, "(ss)", &path, &rwm)) > 0) {
 
-                        if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0 ||
-                            bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &rwm, false) < 0)
-                                return -EINVAL;
-
-                        if (!path_startswith(path, "/dev")) {
-                                dbus_set_error(error, DBUS_ERROR_INVALID_ARGS, "DeviceAllow= requires device node");
-                                return -EINVAL;
-                        }
+                        if (!path_startswith(path, "/dev"))
+                                return sd_bus_error_set_errnof(error, EINVAL, "DeviceAllow= requires device node");
 
                         if (isempty(rwm))
                                 rwm = "rwm";
 
-                        if (!in_charset(rwm, "rwm")) {
-                                dbus_set_error(error, DBUS_ERROR_INVALID_ARGS, "DeviceAllow= requires combination of rwm flags");
-                                return -EINVAL;
-                        }
+                        if (!in_charset(rwm, "rwm"))
+                                return sd_bus_error_set_errnof(error, EINVAL, "DeviceAllow= requires combination of rwm flags");
 
                         if (mode != UNIT_CHECK) {
-                                CGroupDeviceAllow *a = NULL;
-                                CGroupDeviceAllow *b;
-                                bool exist = false;
+                                CGroupDeviceAllow *a = NULL, *b;
 
                                 LIST_FOREACH(device_allow, b, c->device_allow) {
                                         if (path_equal(b->path, path)) {
                                                 a = b;
-                                                exist = true;
                                                 break;
                                         }
                                 }
 
-                                if (!exist) {
+                                if (!a) {
                                         a = new0(CGroupDeviceAllow, 1);
                                         if (!a)
                                                 return -ENOMEM;
@@ -508,18 +472,17 @@ int bus_cgroup_set_property(
                                                 free(a);
                                                 return -ENOMEM;
                                         }
+
+                                        LIST_PREPEND(device_allow, c->device_allow, a);
                                 }
 
                                 a->r = !!strchr(rwm, 'r');
                                 a->w = !!strchr(rwm, 'w');
                                 a->m = !!strchr(rwm, 'm');
 
-                                if (!exist)
-                                        LIST_PREPEND(device_allow, c->device_allow, a);
                         }
 
                         n++;
-                        dbus_message_iter_next(&sub);
                 }
 
                 if (mode != UNIT_CHECK) {
diff --git a/src/core/dbus-cgroup.h b/src/core/dbus-cgroup.h
index e5ac4c3..c2a3910 100644
--- a/src/core/dbus-cgroup.h
+++ b/src/core/dbus-cgroup.h
@@ -21,25 +21,9 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <dbus/dbus.h>
-
-#include "manager.h"
-#include "dbus-common.h"
+#include "sd-bus.h"
 #include "cgroup.h"
 
-#define BUS_CGROUP_CONTEXT_INTERFACE                                    \
-        "  <property name=\"CPUAccounting\" type=\"b\" access=\"read\"/>\n" \
-        "  <property name=\"CPUShares\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"BlockIOAccounting\" type=\"b\" access=\"read\"/>\n" \
-        "  <property name=\"BlockIOWeight\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"BlockIODeviceWeight\" type=\"a(st)\" access=\"read\"/>\n" \
-        "  <property name=\"BlockIOReadBandwidth=\" type=\"a(st)\" access=\"read\"/>\n" \
-        "  <property name=\"BlockIOWriteBandwidth=\" type=\"a(st)\" access=\"read\"/>\n" \
-        "  <property name=\"MemoryAccounting\" type=\"b\" access=\"read\"/>\n" \
-        "  <property name=\"MemoryLimit\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"DevicePolicy\" type=\"s\" access=\"read\"/>\n" \
-        "  <property name=\"DeviceAllow\" type=\"a(ss)\" access=\"read\"/>\n"
-
-extern const BusProperty bus_cgroup_context_properties[];
-
-int bus_cgroup_set_property(Unit *u, CGroupContext *c, const char *name, DBusMessageIter *i, UnitSetPropertiesMode mode, DBusError *error);
+extern const sd_bus_vtable bus_cgroup_vtable[];
+
+int bus_cgroup_set_property(Unit *u, CGroupContext *c, const char *name, sd_bus_message *message, UnitSetPropertiesMode mode, sd_bus_error *error);
diff --git a/src/core/dbus-client-track.c b/src/core/dbus-client-track.c
new file mode 100644
index 0000000..ce514b5
--- /dev/null
+++ b/src/core/dbus-client-track.c
@@ -0,0 +1,250 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+  This file is part of systemd.
+
+  Copyright 2013 Lennart Poettering
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include "dbus-client-track.h"
+
+static unsigned tracked_client_hash(const void *a) {
+        const BusTrackedClient *x = a;
+
+        return string_hash_func(x->name) ^ PTR_TO_UINT(x->bus);
+}
+
+static int tracked_client_compare(const void *a, const void *b) {
+        const BusTrackedClient *x = a, *y = b;
+        int r;
+
+        r = strcmp(x->name, y->name);
+        if (r != 0)
+                return r;
+
+        if (x->bus < y->bus)
+                return -1;
+        if (x->bus > y->bus)
+                return 1;
+
+        return 0;
+}
+
+static int on_name_owner_changed(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        BusTrackedClient *c = userdata;
+        const char *name, *old, *new;
+        int r;
+
+        assert(bus);
+        assert(message);
+
+        r = sd_bus_message_read(message, "sss", &name, &old, &new);
+        if (r < 0) {
+                log_debug("Failed to parse NameOwnerChanged message.");
+                return 0;
+        }
+
+        bus_client_untrack(c->set, bus, name);
+        return 0;
+}
+
+static char *build_match(const char *name) {
+
+        return strjoin("type='signal',"
+                       "sender='org.freedesktop.DBus',"
+                       "path='/org/freedesktop/DBus',"
+                       "interface='org.freedesktop.DBus',"
+                       "member='NameOwnerChanged',"
+                       "arg0='", name, "'", NULL);
+}
+
+int bus_client_track(Set **s, sd_bus *bus, const char *name) {
+        BusTrackedClient *c, *found;
+        size_t l;
+        int r;
+
+        assert(s);
+        assert(bus);
+
+        r = set_ensure_allocated(s, tracked_client_hash, tracked_client_compare);
+        if (r < 0)
+                return r;
+
+        name = strempty(name);
+
+        l = strlen(name);
+
+        c = alloca(offsetof(BusTrackedClient, name) + l + 1);
+        c->set = *s;
+        c->bus = bus;
+        strcpy(c->name, name);
+
+        found = set_get(*s, c);
+        if (found)
+                return 0;
+
+        c = memdup(c, offsetof(BusTrackedClient, name) + l + 1);
+        if (!c)
+                return -ENOMEM;
+
+        r = set_put(*s, c);
+        if (r < 0) {
+                free(c);
+                return r;
+        }
+
+        if (!isempty(name)) {
+                _cleanup_free_ char *match = NULL;
+
+                match = build_match(name);
+                if (!match) {
+                        set_remove(*s, c);
+                        free(c);
+                        return -ENOMEM;
+                }
+
+                r = sd_bus_add_match(bus, match, on_name_owner_changed, c);
+                if (r < 0) {
+                        set_remove(*s, c);
+                        free(c);
+                        return r;
+                }
+        }
+
+        sd_bus_ref(c->bus);
+        return 1;
+}
+
+static void bus_client_free_one(Set *s, BusTrackedClient *c) {
+        assert(s);
+        assert(c);
+
+        if (!isempty(c->name)) {
+                _cleanup_free_ char *match = NULL;
+
+                match = build_match(c->name);
+                if (match)
+                        sd_bus_remove_match(c->bus, match, on_name_owner_changed, c);
+        }
+
+        sd_bus_unref(c->bus);
+        set_remove(s, c);
+        free(c);
+}
+
+int bus_client_untrack(Set *s, sd_bus *bus, const char *name) {
+        BusTrackedClient *c, *found;
+        size_t l;
+
+        assert(bus);
+        assert(s);
+        assert(name);
+
+        name = strempty(name);
+
+        l = strlen(name);
+
+        c = alloca(offsetof(BusTrackedClient, name) + l + 1);
+        c->bus = bus;
+        strcpy(c->name, name);
+
+        found = set_get(s, c);
+        if (!found)
+                return 0;
+
+        bus_client_free_one(s, found);
+        return 1;
+}
+
+void bus_client_track_free(Set *s) {
+        BusTrackedClient *c;
+
+        while ((c = set_first(s)))
+                bus_client_free_one(s, c);
+
+        set_free(s);
+}
+
+int bus_client_untrack_bus(Set *s, sd_bus *bus) {
+        BusTrackedClient *c;
+        Iterator i;
+        int r = 0;
+
+        SET_FOREACH(c, s, i)
+                if (c->bus == bus) {
+                        bus_client_free_one(s, c);
+                        r++;
+                }
+
+        return r;
+}
+
+void bus_client_track_serialize(Manager *m, FILE *f, Set *s) {
+        BusTrackedClient *c;
+        Iterator i;
+
+        assert(m);
+        assert(f);
+
+        SET_FOREACH(c, s, i) {
+                if (c->bus == m->api_bus)
+                        fprintf(f, "subscribed=%s", isempty(c->name) ? "*" : c->name);
+                else
+                        fprintf(f, "subscribed=%p %s", c->bus, isempty(c->name) ? "*" : c->name);
+        }
+}
+
+int bus_client_track_deserialize_item(Manager *m, Set **s, const char *line) {
+        const char *e, *q, *name;
+        sd_bus *bus;
+        void *p;
+        int r;
+
+        e = startswith(line, "subscribed=");
+        if (!e)
+                return 0;
+
+        q = strpbrk(e, WHITESPACE);
+        if (!q) {
+                if (m->api_bus) {
+                        bus = m->api_bus;
+                        name = e;
+                        goto finish;
+                }
+
+                return 1;
+        }
+
+        if (sscanf(e, "%p", &p) != 1) {
+                log_debug("Failed to parse subscription pointer.");
+                return -EINVAL;
+        }
+
+        bus = set_get(m->private_buses, p);
+        if (!bus)
+                return 1;
+
+        name = q + strspn(q, WHITESPACE);
+
+finish:
+        r = bus_client_track(s, bus, streq(name, "*") ? NULL : name);
+        if (r < 0) {
+                log_debug("Failed to deserialize client subscription: %s", strerror(-r));
+                return r;
+        }
+
+        return 1;
+}
diff --git a/src/core/dbus-client-track.h b/src/core/dbus-client-track.h
new file mode 100644
index 0000000..0167647
--- /dev/null
+++ b/src/core/dbus-client-track.h
@@ -0,0 +1,42 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+#pragma once
+
+/***
+  This file is part of systemd.
+
+  Copyright 2013 Lennart Poettering
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include "sd-bus.h"
+#include "set.h"
+#include "manager.h"
+
+typedef struct BusTrackedClient {
+        Set *set;
+        sd_bus *bus;
+        char name[0];
+} BusTrackedClient;
+
+int bus_client_track(Set **s, sd_bus *bus, const char *name);
+
+int bus_client_untrack(Set *s, sd_bus *bus, const char *name);
+int bus_client_untrack_bus(Set *s, sd_bus *bus);
+
+void bus_client_track_free(Set *s);
+
+void bus_client_track_serialize(Manager *m, FILE *f, Set *s);
+int bus_client_track_deserialize_item(Manager *m, Set **s, const char *line);
diff --git a/src/core/dbus-device.c b/src/core/dbus-device.c
index ef484a8..621bab0 100644
--- a/src/core/dbus-device.c
+++ b/src/core/dbus-device.c
@@ -19,50 +19,18 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include "unit.h"
+#include "device.h"
 #include "dbus-unit.h"
 #include "dbus-device.h"
-#include "dbus-common.h"
-#include "selinux-access.h"
 
-#define BUS_DEVICE_INTERFACE                                            \
-        " <interface name=\"org.freedesktop.systemd1.Device\">\n"       \
-        "  <property name=\"SysFSPath\" type=\"s\" access=\"read\"/>\n" \
-        " </interface>\n"
-
-#define INTROSPECTION                                                   \
-        DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE                       \
-        "<node>\n"                                                      \
-        BUS_UNIT_INTERFACE                                              \
-        BUS_DEVICE_INTERFACE                                            \
-        BUS_PROPERTIES_INTERFACE                                        \
-        BUS_PEER_INTERFACE                                              \
-        BUS_INTROSPECTABLE_INTERFACE                                    \
-        "</node>\n"
-
-#define INTERFACES_LIST                              \
-        BUS_UNIT_INTERFACES_LIST                     \
-        "org.freedesktop.systemd1.Device\0"
-
-const char bus_device_interface[] = BUS_DEVICE_INTERFACE;
-
-const char bus_device_invalidating_properties[] =
-        "SysFSPath\0";
-
-static const BusProperty bus_device_properties[] = {
-        { "SysFSPath", bus_property_append_string, "s", offsetof(Device, sysfs), true },
-        { NULL, }
+const sd_bus_vtable bus_device_vtable[] = {
+        SD_BUS_VTABLE_START(0),
+        SD_BUS_PROPERTY("SysFSPath", "s", NULL, offsetof(Device, sysfs), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+        SD_BUS_VTABLE_END
 };
 
-
-DBusHandlerResult bus_device_message_handler(Unit *u, DBusConnection *c, DBusMessage *message) {
-        Device *d = DEVICE(u);
-        const BusBoundProperties bps[] = {
-                { "org.freedesktop.systemd1.Unit",   bus_unit_properties,   u },
-                { "org.freedesktop.systemd1.Device", bus_device_properties, d },
-                { NULL, }
-        };
-
-        SELINUX_UNIT_ACCESS_CHECK(u, c, message, "status");
-
-        return bus_default_message_handler(c, message, INTROSPECTION, INTERFACES_LIST, bps);
-}
+const char* const bus_device_changing_properties[] = {
+        "SysFSPath",
+        NULL
+};
diff --git a/src/core/dbus-device.h b/src/core/dbus-device.h
index 311e068..f248c28 100644
--- a/src/core/dbus-device.h
+++ b/src/core/dbus-device.h
@@ -21,11 +21,8 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <dbus/dbus.h>
-
+#include "sd-bus.h"
 #include "unit.h"
 
-DBusHandlerResult bus_device_message_handler(Unit *u, DBusConnection *c, DBusMessage *message);
-
-extern const char bus_device_interface[];
-extern const char bus_device_invalidating_properties[];
+extern const sd_bus_vtable bus_device_vtable[];
+extern const char* const bus_device_changing_properties[];
diff --git a/src/core/dbus-execute.c b/src/core/dbus-execute.c
index 2402e8c..ca7ee5c 100644
--- a/src/core/dbus-execute.c
+++ b/src/core/dbus-execute.c
@@ -19,59 +19,102 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <errno.h>
-#include <dbus/dbus.h>
 #include <sys/prctl.h>
 
-#include "dbus-execute.h"
+#include "bus-util.h"
 #include "missing.h"
 #include "ioprio.h"
 #include "strv.h"
-#include "dbus-common.h"
 #include "syscall-list.h"
 #include "fileio.h"
+#include "execute.h"
+#include "dbus-execute.h"
 
-static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_execute_append_input, exec_input, ExecInput);
-static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_execute_append_output, exec_output, ExecOutput);
+BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_exec_output, exec_output, ExecOutput);
 
-static int bus_execute_append_env_files(DBusMessageIter *i, const char *property, void *data) {
-        char **env_files = data, **j;
-        DBusMessageIter sub, sub2;
+static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_exec_input, exec_input, ExecInput);
 
-        assert(i);
-        assert(property);
+static int property_get_environment_files(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
 
-        if (!dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, "(sb)", &sub))
-                return -ENOMEM;
+        ExecContext *c = userdata;
+        char **j;
+        int r;
 
-        STRV_FOREACH(j, env_files) {
-                dbus_bool_t b = false;
-                char *fn = *j;
+        assert(bus);
+        assert(reply);
+        assert(c);
+
+        r = sd_bus_message_open_container(reply, 'a', "(sb)");
+        if (r < 0)
+                return r;
 
-                if (fn[0] == '-') {
-                        b = true;
-                        fn++;
-                }
+        STRV_FOREACH(j, c->environment_files) {
+                const char *fn = *j;
 
-                if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
-                    !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &fn) ||
-                    !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_BOOLEAN, &b) ||
-                    !dbus_message_iter_close_container(&sub, &sub2))
-                        return -ENOMEM;
+                r = sd_bus_message_append(reply, "(sb)", fn[0] == '-' ? fn + 1 : fn, fn[0] == '-');
+                if (r < 0)
+                        return r;
         }
 
-        if (!dbus_message_iter_close_container(i, &sub))
-                return -ENOMEM;
+        return sd_bus_message_close_container(reply);
+}
+
+static int property_get_rlimit(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
+
+        struct rlimit *rl;
+        uint64_t u;
+
+        assert(bus);
+        assert(reply);
+        assert(userdata);
 
-        return 0;
+        rl = *(struct rlimit**) userdata;
+        if (rl)
+                u = (uint64_t) rl->rlim_max;
+        else {
+                struct rlimit buf = {};
+                int z;
+
+                z = rlimit_from_string(property);
+                assert(z >= 0);
+
+                getrlimit(z, &buf);
+
+                u = (uint64_t) buf.rlim_max;
+        }
+
+        return sd_bus_message_append(reply, "t", u);
 }
 
-static int bus_execute_append_oom_score_adjust(DBusMessageIter *i, const char *property, void *data) {
-        ExecContext *c = data;
+static int property_get_oom_score_adjust(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
+
+
+        ExecContext *c = userdata;
         int32_t n;
 
-        assert(i);
-        assert(property);
+        assert(bus);
+        assert(reply);
         assert(c);
 
         if (c->oom_score_adjust_set)
@@ -80,80 +123,111 @@ static int bus_execute_append_oom_score_adjust(DBusMessageIter *i, const char *p
                 _cleanup_free_ char *t = NULL;
 
                 n = 0;
-                if (read_one_line_file("/proc/self/oom_score_adj", &t) >= 0) {
+                if (read_one_line_file("/proc/self/oom_score_adj", &t) >= 0)
                         safe_atoi(t, &n);
-                }
         }
 
-        if (!dbus_message_iter_append_basic(i, DBUS_TYPE_INT32, &n))
-                return -ENOMEM;
-
-        return 0;
+        return sd_bus_message_append(reply, "i", n);
 }
 
-static int bus_execute_append_nice(DBusMessageIter *i, const char *property, void *data) {
-        ExecContext *c = data;
+static int property_get_nice(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
+
+
+        ExecContext *c = userdata;
         int32_t n;
 
-        assert(i);
-        assert(property);
+        assert(bus);
+        assert(reply);
         assert(c);
 
         if (c->nice_set)
                 n = c->nice;
-        else
+        else {
+                errno = 0;
                 n = getpriority(PRIO_PROCESS, 0);
+                if (errno != 0)
+                        n = 0;
+        }
 
-        if (!dbus_message_iter_append_basic(i, DBUS_TYPE_INT32, &n))
-                return -ENOMEM;
-
-        return 0;
+        return sd_bus_message_append(reply, "i", n);
 }
 
-static int bus_execute_append_ioprio(DBusMessageIter *i, const char *property, void *data) {
-        ExecContext *c = data;
+static int property_get_ioprio(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
+
+
+        ExecContext *c = userdata;
         int32_t n;
 
-        assert(i);
-        assert(property);
+        assert(bus);
+        assert(reply);
         assert(c);
 
         if (c->ioprio_set)
                 n = c->ioprio;
-        else
+        else {
                 n = ioprio_get(IOPRIO_WHO_PROCESS, 0);
+                if (n < 0)
+                        n = IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE, 4);
+        }
 
-        if (!dbus_message_iter_append_basic(i, DBUS_TYPE_INT32, &n))
-                return -ENOMEM;
-
-        return 0;
+        return sd_bus_message_append(reply, "i", n);
 }
 
-static int bus_execute_append_cpu_sched_policy(DBusMessageIter *i, const char *property, void *data) {
-        ExecContext *c = data;
+static int property_get_cpu_sched_policy(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
+
+        ExecContext *c = userdata;
         int32_t n;
 
-        assert(i);
-        assert(property);
+        assert(bus);
+        assert(reply);
         assert(c);
 
         if (c->cpu_sched_set)
                 n = c->cpu_sched_policy;
-        else
+        else {
                 n = sched_getscheduler(0);
+                if (n < 0)
+                        n = SCHED_OTHER;
+        }
 
-        if (!dbus_message_iter_append_basic(i, DBUS_TYPE_INT32, &n))
-                return -ENOMEM;
-
-        return 0;
+        return sd_bus_message_append(reply, "i", n);
 }
 
-static int bus_execute_append_cpu_sched_priority(DBusMessageIter *i, const char *property, void *data) {
-        ExecContext *c = data;
+static int property_get_cpu_sched_priority(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
+
+        ExecContext *c = userdata;
         int32_t n;
 
-        assert(i);
-        assert(property);
+        assert(bus);
+        assert(reply);
         assert(c);
 
         if (c->cpu_sched_set)
@@ -167,44 +241,44 @@ static int bus_execute_append_cpu_sched_priority(DBusMessageIter *i, const char
                         n = 0;
         }
 
-        if (!dbus_message_iter_append_basic(i, DBUS_TYPE_INT32, &n))
-                return -ENOMEM;
-
-        return 0;
+        return sd_bus_message_append(reply, "i", n);
 }
 
-static int bus_execute_append_affinity(DBusMessageIter *i, const char *property, void *data) {
-        ExecContext *c = data;
-        dbus_bool_t b;
-        DBusMessageIter sub;
+static int property_get_cpu_affinity(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
 
-        assert(i);
-        assert(property);
-        assert(c);
+        ExecContext *c = userdata;
 
-        if (!dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, "y", &sub))
-                return -ENOMEM;
+        assert(bus);
+        assert(reply);
+        assert(c);
 
         if (c->cpuset)
-                b = dbus_message_iter_append_fixed_array(&sub, DBUS_TYPE_BYTE, &c->cpuset, CPU_ALLOC_SIZE(c->cpuset_ncpus));
+                return sd_bus_message_append_array(reply, 'y', c->cpuset, CPU_ALLOC_SIZE(c->cpuset_ncpus));
         else
-                b = dbus_message_iter_append_fixed_array(&sub, DBUS_TYPE_BYTE, &c->cpuset, 0);
-
-        if (!b)
-                return -ENOMEM;
-
-        if (!dbus_message_iter_close_container(i, &sub))
-                return -ENOMEM;
-
-        return 0;
+                return sd_bus_message_append_array(reply, 'y', NULL, 0);
 }
 
-static int bus_execute_append_timer_slack_nsec(DBusMessageIter *i, const char *property, void *data) {
-        ExecContext *c = data;
+static int property_get_timer_slack_nsec(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
+
+        ExecContext *c = userdata;
         uint64_t u;
 
-        assert(i);
-        assert(property);
+        assert(bus);
+        assert(reply);
         assert(c);
 
         if (c->timer_slack_nsec != (nsec_t) -1)
@@ -212,37 +286,45 @@ static int bus_execute_append_timer_slack_nsec(DBusMessageIter *i, const char *p
         else
                 u = (uint64_t) prctl(PR_GET_TIMERSLACK);
 
-        if (!dbus_message_iter_append_basic(i, DBUS_TYPE_UINT64, &u))
-                return -ENOMEM;
-
-        return 0;
+        return sd_bus_message_append(reply, "t", u);
 }
 
-static int bus_execute_append_capability_bs(DBusMessageIter *i, const char *property, void *data) {
-        ExecContext *c = data;
-        uint64_t normal, inverted;
+static int property_get_capability_bounding_set(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
 
-        assert(i);
-        assert(property);
+        ExecContext *c = userdata;
+
+        assert(bus);
+        assert(reply);
         assert(c);
 
         /* We store this negated internally, to match the kernel, but
          * we expose it normalized. */
-
-        normal = *(uint64_t*) data;
-        inverted = ~normal;
-
-        return bus_property_append_uint64(i, property, &inverted);
+        return sd_bus_message_append(reply, "t", ~c->capability_bounding_set_drop);
 }
 
-static int bus_execute_append_capabilities(DBusMessageIter *i, const char *property, void *data) {
-        ExecContext *c = data;
+static int property_get_capabilities(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
+
+        ExecContext *c = userdata;
         char *t = NULL;
         const char *s;
-        dbus_bool_t b;
+        int r;
 
-        assert(i);
-        assert(property);
+        assert(bus);
+        assert(reply);
         assert(c);
 
         if (c->capabilities)
@@ -253,184 +335,150 @@ static int bus_execute_append_capabilities(DBusMessageIter *i, const char *prope
         if (!s)
                 return -ENOMEM;
 
-        b = dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &s);
+        r = sd_bus_message_append(reply, "s", s);
 
         if (t)
                 cap_free(t);
 
-        if (!b)
-                return -ENOMEM;
-
-        return 0;
+        return r;
 }
 
-static int bus_execute_append_rlimits(DBusMessageIter *i, const char *property, void *data) {
-        ExecContext *c = data;
-        int r;
-        uint64_t u;
-
-        assert(i);
-        assert(property);
-        assert(c);
-
-        assert_se((r = rlimit_from_string(property)) >= 0);
+static int property_get_syscall_filter(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
 
-        if (c->rlimit[r])
-                u = (uint64_t) c->rlimit[r]->rlim_max;
-        else {
-                struct rlimit rl = {};
+        ExecContext *c = userdata;
 
-                getrlimit(r, &rl);
+        assert(bus);
+        assert(reply);
+        assert(c);
 
-                u = (uint64_t) rl.rlim_max;
-        }
+        if (c->syscall_filter)
+                return sd_bus_message_append_array(reply, 'u', c->syscall_filter, (syscall_max() + 31) >> 4);
+        else
+                return sd_bus_message_append_array(reply, 'u', NULL, 0);
+}
 
-        if (!dbus_message_iter_append_basic(i, DBUS_TYPE_UINT64, &u))
-                return -ENOMEM;
+const sd_bus_vtable bus_exec_vtable[] = {
+        SD_BUS_VTABLE_START(0),
+        SD_BUS_PROPERTY("Environment", "as", NULL, offsetof(ExecContext, environment), 0),
+        SD_BUS_PROPERTY("EnvironmentFiles", "a(sb)", property_get_environment_files, 0, 0),
+        SD_BUS_PROPERTY("UMask", "u", bus_property_get_mode, offsetof(ExecContext, umask), 0),
+        SD_BUS_PROPERTY("LimitCPU", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_CPU]), 0),
+        SD_BUS_PROPERTY("LimitFSIZE", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_FSIZE]), 0),
+        SD_BUS_PROPERTY("LimitDATA", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_DATA]), 0),
+        SD_BUS_PROPERTY("LimitSTACK", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_STACK]), 0),
+        SD_BUS_PROPERTY("LimitCORE", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_CORE]), 0),
+        SD_BUS_PROPERTY("LimitRSS", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RSS]), 0),
+        SD_BUS_PROPERTY("LimitNOFILE", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NOFILE]), 0),
+        SD_BUS_PROPERTY("LimitAS", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_AS]), 0),
+        SD_BUS_PROPERTY("LimitNPROC", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NPROC]), 0),
+        SD_BUS_PROPERTY("LimitMEMLOCK", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_MEMLOCK]), 0),
+        SD_BUS_PROPERTY("LimitLOCKS", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_LOCKS]), 0),
+        SD_BUS_PROPERTY("LimitSIGPENDING", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_SIGPENDING]), 0),
+        SD_BUS_PROPERTY("LimitMSGQUEUE", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_MSGQUEUE]), 0),
+        SD_BUS_PROPERTY("LimitNICE", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NICE]), 0),
+        SD_BUS_PROPERTY("LimitRTPRIO", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RTPRIO]), 0),
+        SD_BUS_PROPERTY("LimitRTTIME", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RTTIME]), 0),
+        SD_BUS_PROPERTY("WorkingDirectory", "s", NULL, offsetof(ExecContext, working_directory), 0),
+        SD_BUS_PROPERTY("RootDirectory", "s", NULL, offsetof(ExecContext, root_directory), 0),
+        SD_BUS_PROPERTY("OOMScoreAdjust", "i", property_get_oom_score_adjust, 0, 0),
+        SD_BUS_PROPERTY("Nice", "i", property_get_nice, 0, 0),
+        SD_BUS_PROPERTY("IOScheduling", "i", property_get_ioprio, 0, 0),
+        SD_BUS_PROPERTY("CPUSchedulingPolicy", "i", property_get_cpu_sched_policy, 0, 0),
+        SD_BUS_PROPERTY("CPUSchedulingPriority", "i", property_get_cpu_sched_priority, 0, 0),
+        SD_BUS_PROPERTY("CPUAffinity", "ay", property_get_cpu_affinity, 0, 0),
+        SD_BUS_PROPERTY("TimerSlackNSec", "t", property_get_timer_slack_nsec, 0, 0),
+        SD_BUS_PROPERTY("CPUSchedulingResetOnFork", "b", bus_property_get_bool, offsetof(ExecContext, cpu_sched_reset_on_fork), 0),
+        SD_BUS_PROPERTY("NonBlocking", "b", bus_property_get_bool, offsetof(ExecContext, non_blocking), 0),
+        SD_BUS_PROPERTY("StandardInput", "s", property_get_exec_input, offsetof(ExecContext, std_input), 0),
+        SD_BUS_PROPERTY("StandardOutput", "s", bus_property_get_exec_output, offsetof(ExecContext, std_output), 0),
+        SD_BUS_PROPERTY("StandardError", "s", bus_property_get_exec_output, offsetof(ExecContext, std_error), 0),
+        SD_BUS_PROPERTY("TTYPath", "s", NULL, offsetof(ExecContext, tty_path), 0),
+        SD_BUS_PROPERTY("TTYReset", "b", bus_property_get_bool, offsetof(ExecContext, tty_reset), 0),
+        SD_BUS_PROPERTY("TTYVHangup", "b", bus_property_get_bool, offsetof(ExecContext, tty_vhangup), 0),
+        SD_BUS_PROPERTY("TTYVTDisallocate", "b", bus_property_get_bool, offsetof(ExecContext, tty_vt_disallocate), 0),
+        SD_BUS_PROPERTY("SyslogPriority", "i", bus_property_get_int, offsetof(ExecContext, syslog_priority), 0),
+        SD_BUS_PROPERTY("SyslogIdentifier", "s", NULL, offsetof(ExecContext, syslog_identifier), 0),
+        SD_BUS_PROPERTY("SyslogLevelPrefix", "b", bus_property_get_bool, offsetof(ExecContext, syslog_level_prefix), 0),
+        SD_BUS_PROPERTY("Capabilities", "s", property_get_capabilities, 0, 0),
+        SD_BUS_PROPERTY("SecureBits", "i", bus_property_get_int, offsetof(ExecContext, secure_bits), 0),
+        SD_BUS_PROPERTY("CapabilityBoundingSet", "t", property_get_capability_bounding_set, 0, 0),
+        SD_BUS_PROPERTY("User", "s", NULL, offsetof(ExecContext, user), 0),
+        SD_BUS_PROPERTY("Group", "s", NULL, offsetof(ExecContext, group), 0),
+        SD_BUS_PROPERTY("SupplementaryGroups", "as", NULL, offsetof(ExecContext, supplementary_groups), 0),
+        SD_BUS_PROPERTY("TCPWrapName", "s", NULL, offsetof(ExecContext, tcpwrap_name), 0),
+        SD_BUS_PROPERTY("PAMName", "s", NULL, offsetof(ExecContext, pam_name), 0),
+        SD_BUS_PROPERTY("ReadWriteDirectories", "as", NULL, offsetof(ExecContext, read_write_dirs), 0),
+        SD_BUS_PROPERTY("ReadOnlyDirectories", "as", NULL, offsetof(ExecContext, read_only_dirs), 0),
+        SD_BUS_PROPERTY("InaccessibleDirectories", "as", NULL, offsetof(ExecContext, inaccessible_dirs), 0),
+        SD_BUS_PROPERTY("MountFlags", "t", bus_property_get_ulong, offsetof(ExecContext, mount_flags), 0),
+        SD_BUS_PROPERTY("PrivateTmp", "b", bus_property_get_bool, offsetof(ExecContext, private_tmp), 0),
+        SD_BUS_PROPERTY("PrivateNetwork", "b", bus_property_get_bool, offsetof(ExecContext, private_network), 0),
+        SD_BUS_PROPERTY("SameProcessGroup", "b", bus_property_get_bool, offsetof(ExecContext, same_pgrp), 0),
+        SD_BUS_PROPERTY("UtmpIdentifier", "s", NULL, offsetof(ExecContext, utmp_id), 0),
+        SD_BUS_PROPERTY("IgnoreSIGPIPE", "b", bus_property_get_bool, offsetof(ExecContext, ignore_sigpipe), 0),
+        SD_BUS_PROPERTY("NoNewPrivileges", "b", bus_property_get_bool, offsetof(ExecContext, no_new_privileges), 0),
+        SD_BUS_PROPERTY("SystemCallFilter", "au", property_get_syscall_filter, 0, 0),
+        SD_BUS_VTABLE_END
+};
 
-        return 0;
-}
+int bus_property_get_exec_command(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
 
-int bus_execute_append_command(DBusMessageIter *i, const char *property, void *data) {
-        ExecCommand *c = data;
-        DBusMessageIter sub, sub2, sub3;
+        ExecCommand *c = *(ExecCommand**) userdata;
+        int r;
 
-        assert(i);
-        assert(property);
+        assert(bus);
+        assert(reply);
 
-        if (!dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, "(sasbttttuii)", &sub))
-                return -ENOMEM;
+        r = sd_bus_message_open_container(reply, 'a', "(sasbttttuii)");
+        if (r < 0)
+                return r;
 
         LIST_FOREACH(command, c, c) {
-                char **l;
-                uint32_t pid;
-                int32_t code, status;
-                dbus_bool_t b;
-
                 if (!c->path)
                         continue;
 
-                if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
-                    !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &c->path) ||
-                    !dbus_message_iter_open_container(&sub2, DBUS_TYPE_ARRAY, "s", &sub3))
-                        return -ENOMEM;
-
-                STRV_FOREACH(l, c->argv)
-                        if (!dbus_message_iter_append_basic(&sub3, DBUS_TYPE_STRING, l))
-                                return -ENOMEM;
-
-                pid = (uint32_t) c->exec_status.pid;
-                code = (int32_t) c->exec_status.code;
-                status = (int32_t) c->exec_status.status;
-
-                b = !!c->ignore;
-
-                if (!dbus_message_iter_close_container(&sub2, &sub3) ||
-                    !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_BOOLEAN, &b) ||
-                    !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT64, &c->exec_status.start_timestamp.realtime) ||
-                    !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT64, &c->exec_status.start_timestamp.monotonic) ||
-                    !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT64, &c->exec_status.exit_timestamp.realtime) ||
-                    !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT64, &c->exec_status.exit_timestamp.monotonic) ||
-                    !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT32, &pid) ||
-                    !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_INT32, &code) ||
-                    !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_INT32, &status))
-                        return -ENOMEM;
-
-                if (!dbus_message_iter_close_container(&sub, &sub2))
-                        return -ENOMEM;
+                r = sd_bus_message_open_container(reply, 'r', "sasbttttuii");
+                if (r < 0)
+                        return r;
+
+                r = sd_bus_message_append(reply, "s", c->path);
+                if (r < 0)
+                        return r;
+
+                r = sd_bus_message_append_strv(reply, c->argv);
+                if (r < 0)
+                        return r;
+
+                r = sd_bus_message_append(reply, "bttttuii",
+                                          c->ignore,
+                                          c->exec_status.start_timestamp.realtime,
+                                          c->exec_status.start_timestamp.monotonic,
+                                          c->exec_status.exit_timestamp.realtime,
+                                          c->exec_status.exit_timestamp.monotonic,
+                                          (uint32_t) c->exec_status.pid,
+                                          (int32_t) c->exec_status.code,
+                                          (int32_t) c->exec_status.status);
+                if (r < 0)
+                        return r;
+
+                r = sd_bus_message_close_container(reply);
+                if (r < 0)
+                        return r;
         }
 
-        if (!dbus_message_iter_close_container(i, &sub))
-                return -ENOMEM;
-
-        return 0;
-}
-
-static int bus_execute_append_syscall_filter(DBusMessageIter *i, const char *property, void *data) {
-        ExecContext *c = data;
-        dbus_bool_t b;
-        DBusMessageIter sub;
-
-        assert(i);
-        assert(property);
-        assert(c);
-
-        if (!dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, "u", &sub))
-                return -ENOMEM;
-
-        if (c->syscall_filter)
-                b = dbus_message_iter_append_fixed_array(&sub, DBUS_TYPE_UINT32, &c->syscall_filter, (syscall_max() + 31) >> 4);
-        else
-                b = dbus_message_iter_append_fixed_array(&sub, DBUS_TYPE_UINT32, &c->syscall_filter, 0);
-
-        if (!b)
-                return -ENOMEM;
-
-        if (!dbus_message_iter_close_container(i, &sub))
-                return -ENOMEM;
-
-        return 0;
+        return sd_bus_message_close_container(reply);
 }
-
-const BusProperty bus_exec_context_properties[] = {
-        { "Environment",              bus_property_append_strv,             "as", offsetof(ExecContext, environment),            true },
-        { "EnvironmentFiles",         bus_execute_append_env_files,      "a(sb)", offsetof(ExecContext, environment_files),      true },
-        { "UMask",                    bus_property_append_mode,              "u", offsetof(ExecContext, umask)                        },
-        { "LimitCPU",                 bus_execute_append_rlimits,            "t", 0 },
-        { "LimitFSIZE",               bus_execute_append_rlimits,            "t", 0 },
-        { "LimitDATA",                bus_execute_append_rlimits,            "t", 0 },
-        { "LimitSTACK",               bus_execute_append_rlimits,            "t", 0 },
-        { "LimitCORE",                bus_execute_append_rlimits,            "t", 0 },
-        { "LimitRSS",                 bus_execute_append_rlimits,            "t", 0 },
-        { "LimitNOFILE",              bus_execute_append_rlimits,            "t", 0 },
-        { "LimitAS",                  bus_execute_append_rlimits,            "t", 0 },
-        { "LimitNPROC",               bus_execute_append_rlimits,            "t", 0 },
-        { "LimitMEMLOCK",             bus_execute_append_rlimits,            "t", 0 },
-        { "LimitLOCKS",               bus_execute_append_rlimits,            "t", 0 },
-        { "LimitSIGPENDING",          bus_execute_append_rlimits,            "t", 0 },
-        { "LimitMSGQUEUE",            bus_execute_append_rlimits,            "t", 0 },
-        { "LimitNICE",                bus_execute_append_rlimits,            "t", 0 },
-        { "LimitRTPRIO",              bus_execute_append_rlimits,            "t", 0 },
-        { "LimitRTTIME",              bus_execute_append_rlimits,            "t", 0 },
-        { "WorkingDirectory",         bus_property_append_string,            "s", offsetof(ExecContext, working_directory),      true },
-        { "RootDirectory",            bus_property_append_string,            "s", offsetof(ExecContext, root_directory),         true },
-        { "OOMScoreAdjust",           bus_execute_append_oom_score_adjust,   "i", 0 },
-        { "Nice",                     bus_execute_append_nice,               "i", 0 },
-        { "IOScheduling",             bus_execute_append_ioprio,             "i", 0 },
-        { "CPUSchedulingPolicy",      bus_execute_append_cpu_sched_policy,   "i", 0 },
-        { "CPUSchedulingPriority",    bus_execute_append_cpu_sched_priority, "i", 0 },
-        { "CPUAffinity",              bus_execute_append_affinity,          "ay", 0 },
-        { "TimerSlackNSec",           bus_execute_append_timer_slack_nsec,   "t", 0 },
-        { "CPUSchedulingResetOnFork", bus_property_append_bool,              "b", offsetof(ExecContext, cpu_sched_reset_on_fork)      },
-        { "NonBlocking",              bus_property_append_bool,              "b", offsetof(ExecContext, non_blocking)                 },
-        { "StandardInput",            bus_execute_append_input,              "s", offsetof(ExecContext, std_input)                    },
-        { "StandardOutput",           bus_execute_append_output,             "s", offsetof(ExecContext, std_output)                   },
-        { "StandardError",            bus_execute_append_output,             "s", offsetof(ExecContext, std_error)                    },
-        { "TTYPath",                  bus_property_append_string,            "s", offsetof(ExecContext, tty_path),               true },
-        { "TTYReset",                 bus_property_append_bool,              "b", offsetof(ExecContext, tty_reset)                    },
-        { "TTYVHangup",               bus_property_append_bool,              "b", offsetof(ExecContext, tty_vhangup)                  },
-        { "TTYVTDisallocate",         bus_property_append_bool,              "b", offsetof(ExecContext, tty_vt_disallocate)           },
-        { "SyslogPriority",           bus_property_append_int,               "i", offsetof(ExecContext, syslog_priority)              },
-        { "SyslogIdentifier",         bus_property_append_string,            "s", offsetof(ExecContext, syslog_identifier),      true },
-        { "SyslogLevelPrefix",        bus_property_append_bool,              "b", offsetof(ExecContext, syslog_level_prefix)          },
-        { "Capabilities",             bus_execute_append_capabilities,       "s", 0 },
-        { "SecureBits",               bus_property_append_int,               "i", offsetof(ExecContext, secure_bits)                  },
-        { "CapabilityBoundingSet",    bus_execute_append_capability_bs,      "t", offsetof(ExecContext, capability_bounding_set_drop) },
-        { "User",                     bus_property_append_string,            "s", offsetof(ExecContext, user),                   true },
-        { "Group",                    bus_property_append_string,            "s", offsetof(ExecContext, group),                  true },
-        { "SupplementaryGroups",      bus_property_append_strv,             "as", offsetof(ExecContext, supplementary_groups),   true },
-        { "TCPWrapName",              bus_property_append_string,            "s", offsetof(ExecContext, tcpwrap_name),           true },
-        { "PAMName",                  bus_property_append_string,            "s", offsetof(ExecContext, pam_name),               true },
-        { "ReadWriteDirectories",     bus_property_append_strv,             "as", offsetof(ExecContext, read_write_dirs),        true },
-        { "ReadOnlyDirectories",      bus_property_append_strv,             "as", offsetof(ExecContext, read_only_dirs),         true },
-        { "InaccessibleDirectories",  bus_property_append_strv,             "as", offsetof(ExecContext, inaccessible_dirs),      true },
-        { "MountFlags",               bus_property_append_ul,                "t", offsetof(ExecContext, mount_flags)                  },
-        { "PrivateTmp",               bus_property_append_bool,              "b", offsetof(ExecContext, private_tmp)                  },
-        { "PrivateNetwork",           bus_property_append_bool,              "b", offsetof(ExecContext, private_network)              },
-        { "SameProcessGroup",         bus_property_append_bool,              "b", offsetof(ExecContext, same_pgrp)                    },
-        { "UtmpIdentifier",           bus_property_append_string,            "s", offsetof(ExecContext, utmp_id),                true },
-        { "IgnoreSIGPIPE",            bus_property_append_bool,              "b", offsetof(ExecContext, ignore_sigpipe)               },
-        { "NoNewPrivileges",          bus_property_append_bool,              "b", offsetof(ExecContext, no_new_privileges)            },
-        { "SystemCallFilter",         bus_execute_append_syscall_filter,    "au", 0                                                   },
-        {}
-};
diff --git a/src/core/dbus-execute.h b/src/core/dbus-execute.h
index 79bf308..957742b 100644
--- a/src/core/dbus-execute.h
+++ b/src/core/dbus-execute.h
@@ -21,87 +21,20 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <dbus/dbus.h>
+#include "sd-bus.h"
+#include "execute.h"
 
-#include "manager.h"
-#include "dbus-common.h"
+#define BUS_EXEC_STATUS_VTABLE(prefix, offset, flags)                   \
+        BUS_PROPERTY_DUAL_TIMESTAMP(prefix "StartTimestamp", (offset) + offsetof(ExecStatus, start_timestamp), flags), \
+        BUS_PROPERTY_DUAL_TIMESTAMP(prefix "ExitTimestamp", (offset) + offsetof(ExecStatus, exit_timestamp), flags), \
+        SD_BUS_PROPERTY(prefix "PID", "u", bus_property_get_pid, (offset) + offsetof(ExecStatus, pid), flags), \
+        SD_BUS_PROPERTY(prefix "Code", "i", bus_property_get_int, (offset) + offsetof(ExecStatus, code), flags), \
+        SD_BUS_PROPERTY(prefix "Status", "i", bus_property_get_int, (offset) + offsetof(ExecStatus, status), flags)
 
-#define BUS_EXEC_STATUS_INTERFACE(prefix)                               \
-        "  <property name=\"" prefix "StartTimestamp\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"" prefix "StartTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"" prefix "ExitTimestamp\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"" prefix "ExitTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"" prefix "PID\" type=\"u\" access=\"read\"/>\n" \
-        "  <property name=\"" prefix "Code\" type=\"i\" access=\"read\"/>\n" \
-        "  <property name=\"" prefix "Status\" type=\"i\" access=\"read\"/>\n"
+#define BUS_EXEC_COMMAND_VTABLE(name, offset, flags)                    \
+        SD_BUS_PROPERTY(name, "a(sasbttttuii)", bus_property_get_exec_command, offset, flags)
 
-#define BUS_EXEC_CONTEXT_INTERFACE                                      \
-        "  <property name=\"Environment\" type=\"as\" access=\"read\"/>\n" \
-        "  <property name=\"EnvironmentFiles\" type=\"a(sb)\" access=\"read\"/>\n" \
-        "  <property name=\"UMask\" type=\"u\" access=\"read\"/>\n"     \
-        "  <property name=\"LimitCPU\" type=\"t\" access=\"read\"/>\n"  \
-        "  <property name=\"LimitFSIZE\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"LimitDATA\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"LimitSTACK\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"LimitCORE\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"LimitRSS\" type=\"t\" access=\"read\"/>\n"  \
-        "  <property name=\"LimitNOFILE\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"LimitAS\" type=\"t\" access=\"read\"/>\n"   \
-        "  <property name=\"LimitNPROC\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"LimitMEMLOCK\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"LimitLOCKS\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"LimitSIGPENDING\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"LimitMSGQUEUE\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"LimitNICE\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"LimitRTPRIO\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"LimitRTTIME\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"WorkingDirectory\" type=\"s\" access=\"read\"/>\n" \
-        "  <property name=\"RootDirectory\" type=\"s\" access=\"read\"/>\n" \
-        "  <property name=\"OOMScoreAdjust\" type=\"i\" access=\"read\"/>\n" \
-        "  <property name=\"Nice\" type=\"i\" access=\"read\"/>\n" \
-        "  <property name=\"IOScheduling\" type=\"i\" access=\"read\"/>\n" \
-        "  <property name=\"CPUSchedulingPolicy\" type=\"i\" access=\"read\"/>\n" \
-        "  <property name=\"CPUSchedulingPriority\" type=\"i\" access=\"read\"/>\n" \
-        "  <property name=\"CPUAffinity\" type=\"ay\" access=\"read\"/>\n" \
-        "  <property name=\"TimerSlackNSec\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"CPUSchedulingResetOnFork\" type=\"b\" access=\"read\"/>\n" \
-        "  <property name=\"NonBlocking\" type=\"b\" access=\"read\"/>\n" \
-        "  <property name=\"StandardInput\" type=\"s\" access=\"read\"/>\n" \
-        "  <property name=\"StandardOutput\" type=\"s\" access=\"read\"/>\n" \
-        "  <property name=\"StandardError\" type=\"s\" access=\"read\"/>\n" \
-        "  <property name=\"TTYPath\" type=\"s\" access=\"read\"/>\n"   \
-        "  <property name=\"TTYReset\" type=\"b\" access=\"read\"/>\n"   \
-        "  <property name=\"TTYVHangup\" type=\"b\" access=\"read\"/>\n"   \
-        "  <property name=\"TTYVTDisallocate\" type=\"b\" access=\"read\"/>\n"   \
-        "  <property name=\"SyslogPriority\" type=\"i\" access=\"read\"/>\n" \
-        "  <property name=\"SyslogIdentifier\" type=\"s\" access=\"read\"/>\n" \
-        "  <property name=\"SyslogLevelPrefix\" type=\"b\" access=\"read\"/>\n" \
-        "  <property name=\"Capabilities\" type=\"s\" access=\"read\"/>\n" \
-        "  <property name=\"SecureBits\" type=\"i\" access=\"read\"/>\n" \
-        "  <property name=\"CapabilityBoundingSet\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"User\" type=\"s\" access=\"read\"/>\n"      \
-        "  <property name=\"Group\" type=\"s\" access=\"read\"/>\n"     \
-        "  <property name=\"SupplementaryGroups\" type=\"as\" access=\"read\"/>\n" \
-        "  <property name=\"TCPWrapName\" type=\"s\" access=\"read\"/>\n" \
-        "  <property name=\"PAMName\" type=\"s\" access=\"read\"/>\n"   \
-        "  <property name=\"ReadWriteDirectories\" type=\"as\" access=\"read\"/>\n" \
-        "  <property name=\"ReadOnlyDirectories\" type=\"as\" access=\"read\"/>\n" \
-        "  <property name=\"InaccessibleDirectories\" type=\"as\" access=\"read\"/>\n" \
-        "  <property name=\"MountFlags\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"PrivateTmp\" type=\"b\" access=\"read\"/>\n" \
-        "  <property name=\"PrivateNetwork\" type=\"b\" access=\"read\"/>\n" \
-        "  <property name=\"SameProcessGroup\" type=\"b\" access=\"read\"/>\n" \
-        "  <property name=\"UtmpIdentifier\" type=\"s\" access=\"read\"/>\n" \
-        "  <property name=\"IgnoreSIGPIPE\" type=\"b\" access=\"read\"/>\n" \
-        "  <property name=\"NoNewPrivileges\" type=\"b\" access=\"read\"/>\n" \
-        "  <property name=\"SystemCallFilter\" type=\"au\" access=\"read\"/>\n"
+extern const sd_bus_vtable bus_exec_vtable[];
 
-#define BUS_EXEC_COMMAND_INTERFACE(name)                             \
-        "  <property name=\"" name "\" type=\"a(sasbttuii)\" access=\"read\"/>\n"
-
-extern const BusProperty bus_exec_context_properties[];
-
-#define BUS_EXEC_COMMAND_PROPERTY(name, command, indirect)             \
-        { name, bus_execute_append_command, "a(sasbttttuii)", (command), (indirect), NULL }
-
-int bus_execute_append_command(DBusMessageIter *u, const char *property, void *data);
+int bus_property_get_exec_output(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, sd_bus_error *error, void *userdata);
+int bus_property_get_exec_command(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, sd_bus_error *error, void *userdata);
diff --git a/src/core/dbus-job.c b/src/core/dbus-job.c
index e1d7504..e774383 100644
--- a/src/core/dbus-job.c
+++ b/src/core/dbus-job.c
@@ -19,303 +19,145 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <errno.h>
-
-#include "dbus.h"
 #include "log.h"
-#include "dbus-job.h"
-#include "dbus-common.h"
+#include "sd-bus.h"
 #include "selinux-access.h"
+#include "job.h"
+#include "dbus-job.h"
+#include "dbus-client-track.h"
+
+static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_type, job_type, JobType);
+static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_state, job_state, JobState);
+
+static int property_get_unit(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
 
-#define BUS_JOB_INTERFACE                                             \
-        " <interface name=\"org.freedesktop.systemd1.Job\">\n"        \
-        "  <method name=\"Cancel\"/>\n"                               \
-        "  <property name=\"Id\" type=\"u\" access=\"read\"/>\n"      \
-        "  <property name=\"Unit\" type=\"(so)\" access=\"read\"/>\n" \
-        "  <property name=\"JobType\" type=\"s\" access=\"read\"/>\n" \
-        "  <property name=\"State\" type=\"s\" access=\"read\"/>\n"   \
-        " </interface>\n"
-
-#define INTROSPECTION                                                 \
-        DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE                     \
-        "<node>\n"                                                    \
-        BUS_JOB_INTERFACE                                             \
-        BUS_PROPERTIES_INTERFACE                                      \
-        BUS_PEER_INTERFACE                                            \
-        BUS_INTROSPECTABLE_INTERFACE                                  \
-        "</node>\n"
-
-const char bus_job_interface[] = BUS_JOB_INTERFACE;
-
-#define INTERFACES_LIST                              \
-        BUS_GENERIC_INTERFACES_LIST                  \
-        "org.freedesktop.systemd1.Job\0"
-
-#define INVALIDATING_PROPERTIES                 \
-        "State\0"
-
-static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_job_append_state, job_state, JobState);
-static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_job_append_type, job_type, JobType);
-
-static int bus_job_append_unit(DBusMessageIter *i, const char *property, void *data) {
-        Job *j = data;
-        DBusMessageIter sub;
         _cleanup_free_ char *p = NULL;
+        Job *j = userdata;
 
-        assert(i);
-        assert(property);
+        assert(bus);
+        assert(reply);
         assert(j);
 
-        if (!dbus_message_iter_open_container(i, DBUS_TYPE_STRUCT, NULL, &sub))
-                return -ENOMEM;
-
         p = unit_dbus_path(j->unit);
         if (!p)
                 return -ENOMEM;
 
-        if (!dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &j->unit->id) ||
-            !dbus_message_iter_append_basic(&sub, DBUS_TYPE_OBJECT_PATH, &p)) {
-                return -ENOMEM;
-        }
-
-        if (!dbus_message_iter_close_container(i, &sub))
-                return -ENOMEM;
-
-        return 0;
+        return sd_bus_message_append(reply, "(so)", j->unit->id, p);
 }
 
-static const BusProperty bus_job_properties[] = {
-        { "Id",      bus_property_append_uint32, "u", offsetof(Job, id)    },
-        { "State",   bus_job_append_state,       "s", offsetof(Job, state) },
-        { "JobType", bus_job_append_type,        "s", offsetof(Job, type)  },
-        { "Unit",    bus_job_append_unit,     "(so)", 0 },
-        { NULL, }
-};
-
-static DBusHandlerResult bus_job_message_dispatch(Job *j, DBusConnection *connection, DBusMessage *message) {
-        _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
-
-        if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Job", "Cancel")) {
-
-                SELINUX_UNIT_ACCESS_CHECK(j->unit, connection, message, "stop");
-                job_finish_and_invalidate(j, JOB_CANCELED, true);
-
-                reply = dbus_message_new_method_return(message);
-                if (!reply)
-                        return DBUS_HANDLER_RESULT_NEED_MEMORY;
-        } else {
-                const BusBoundProperties bps[] = {
-                        { "org.freedesktop.systemd1.Job", bus_job_properties, j },
-                        { NULL, }
-                };
-
-                SELINUX_UNIT_ACCESS_CHECK(j->unit, connection, message, "status");
-                return bus_default_message_handler(connection, message, INTROSPECTION, INTERFACES_LIST, bps);
-        }
-
-        if (!bus_maybe_send_reply(connection, message, reply))
-                return DBUS_HANDLER_RESULT_NEED_MEMORY;
-
-        return DBUS_HANDLER_RESULT_HANDLED;
-}
-
-static DBusHandlerResult bus_job_message_handler(DBusConnection *connection, DBusMessage  *message, void *data) {
-        Manager *m = data;
-        Job *j;
-        int r;
-        _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
+static int method_cancel(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        Job *j = userdata;
 
-        assert(connection);
+        assert(bus);
         assert(message);
-        assert(m);
-
-        if (streq(dbus_message_get_path(message), "/org/freedesktop/systemd1/job")) {
-                /* Be nice to gdbus and return introspection data for our mid-level paths */
-
-                if (dbus_message_is_method_call(message, "org.freedesktop.DBus.Introspectable", "Introspect")) {
-                        _cleanup_free_ char *introspection = NULL;
-                        FILE *f;
-                        Iterator i;
-                        size_t size;
-
-                        SELINUX_ACCESS_CHECK(connection, message, "status");
-
-                        reply = dbus_message_new_method_return(message);
-                        if (!reply)
-                                goto oom;
-
-                        /* We roll our own introspection code here, instead of
-                         * relying on bus_default_message_handler() because we
-                         * need to generate our introspection string
-                         * dynamically. */
-
-                        f = open_memstream(&introspection, &size);
-                        if (!f)
-                                goto oom;
-
-                        fputs(DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE
-                              "<node>\n", f);
-
-                        fputs(BUS_INTROSPECTABLE_INTERFACE, f);
-                        fputs(BUS_PEER_INTERFACE, f);
-
-                        HASHMAP_FOREACH(j, m->jobs, i)
-                                fprintf(f, "<node name=\"job/%lu\"/>", (unsigned long) j->id);
-
-                        fputs("</node>\n", f);
-
-                        if (ferror(f)) {
-                                fclose(f);
-                                goto oom;
-                        }
-
-                        fclose(f);
-
-                        if (!introspection)
-                                goto oom;
-
-                        if (!dbus_message_append_args(reply, DBUS_TYPE_STRING, &introspection, DBUS_TYPE_INVALID)) {
-                                goto oom;
-                        }
-
-                        if (!bus_maybe_send_reply(connection, message, reply))
-                                goto oom;
-
-                        return DBUS_HANDLER_RESULT_HANDLED;
-                }
-
-                return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-        }
-
-        r = manager_get_job_from_dbus_path(m, dbus_message_get_path(message), &j);
-        if (r == -ENOMEM)
-                goto oom;
-        if (r == -ENOENT) {
-                DBusError e;
-
-                dbus_error_init(&e);
-                dbus_set_error_const(&e, DBUS_ERROR_UNKNOWN_OBJECT, "Unknown job");
-                return bus_send_error_reply(connection, message, &e, r);
-        }
-        if (r < 0)
-                return bus_send_error_reply(connection, message, NULL, r);
+        assert(j);
 
-        return bus_job_message_dispatch(j, connection, message);
+        SELINUX_UNIT_ACCESS_CHECK(j->unit, bus, message, "stop");
+        job_finish_and_invalidate(j, JOB_CANCELED, true);
 
-oom:
-        return DBUS_HANDLER_RESULT_NEED_MEMORY;
+        return sd_bus_reply_method_return(bus, message, NULL);
 }
 
-const DBusObjectPathVTable bus_job_vtable = {
-        .message_function = bus_job_message_handler
+const sd_bus_vtable bus_job_vtable[] = {
+        SD_BUS_VTABLE_START(0),
+        SD_BUS_METHOD("Cancel", NULL, NULL, method_cancel, 0),
+        SD_BUS_PROPERTY("Id", "u", NULL, offsetof(Job, id), 0),
+        SD_BUS_PROPERTY("Unit", "(so)", property_get_unit, 0, 0),
+        SD_BUS_PROPERTY("JobType", "s", property_get_type, offsetof(Job, type), 0),
+        SD_BUS_PROPERTY("State", "s", property_get_state, offsetof(Job, state), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+        SD_BUS_VTABLE_END
 };
 
-static int job_send_message(Job *j, DBusMessage* (*new_message)(Job *j)) {
-        _cleanup_dbus_message_unref_ DBusMessage *m = NULL;
+static int foreach_client(Job *j, int (*send_message)(sd_bus *bus, const char *name, Job *j)) {
+        BusTrackedClient *one_destination = NULL;
+        Iterator i;
+        sd_bus *b;
+        unsigned n, m;
         int r;
 
         assert(j);
-        assert(new_message);
+        assert(send_message);
 
-        if (bus_has_subscriber(j->manager) || j->forgot_bus_clients) {
-                m = new_message(j);
-                if (!m)
-                        return -ENOMEM;
+        n = set_size(j->manager->subscribed);
+        m = set_size(j->subscribed);
 
-                r = bus_broadcast(j->manager, m);
-                if (r < 0)
-                        return r;
-
-        } else {
-                /* If nobody is subscribed, we just send the message
-                 * to the client(s) which created the job */
-                JobBusClient *cl;
-                assert(j->bus_client_list);
-
-                LIST_FOREACH(client, cl, j->bus_client_list) {
-                        assert(cl->bus);
+        if (n <= 0 && m <= 0)
+                return 0;
 
-                        m = new_message(j);
-                        if (!m)
-                                return -ENOMEM;
+        if (n == 1 && m == 0)
+                one_destination = set_first(j->manager->subscribed);
+        else if (n == 0 && m == 1)
+                one_destination = set_first(j->subscribed);
+        else
+                one_destination = NULL;
 
-                        if (!dbus_message_set_destination(m, cl->name))
-                                return -ENOMEM;
+        if (one_destination)
+                return send_message(one_destination->bus, isempty(one_destination->name) ? NULL : one_destination->name, j);
 
-                        if (!dbus_connection_send(cl->bus, m, NULL))
-                                return -ENOMEM;
-
-                        dbus_message_unref(m);
-                        m = NULL;
-                }
+        /* Send to everybody */
+        SET_FOREACH(b, j->manager->private_buses, i) {
+                r = send_message(b, NULL, j);
+                if (r < 0)
+                        return r;
         }
 
+        if (j->manager->api_bus)
+                return send_message(j->manager->api_bus, NULL, j);
+
         return 0;
 }
 
-static DBusMessage* new_change_signal_message(Job *j) {
+static int send_new_signal(sd_bus *bus, const char *destination, Job *j) {
+        _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
         _cleanup_free_ char *p = NULL;
-        DBusMessage *m;
+        int r;
+
+        assert(bus);
+        assert(j);
 
         p = job_dbus_path(j);
         if (!p)
-                return NULL;
-
-        if (j->sent_dbus_new_signal) {
-                /* Send a properties changed signal */
-                m = bus_properties_changed_new(p, "org.freedesktop.systemd1.Job", INVALIDATING_PROPERTIES);
-                if (!m)
-                        return NULL;
-
-        } else {
-                /* Send a new signal */
-
-                m = dbus_message_new_signal("/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "JobNew");
-                if (!m)
-                        return NULL;
-
-                if (!dbus_message_append_args(m,
-                                              DBUS_TYPE_UINT32, &j->id,
-                                              DBUS_TYPE_OBJECT_PATH, &p,
-                                              DBUS_TYPE_STRING, &j->unit->id,
-                                              DBUS_TYPE_INVALID)) {
-                        dbus_message_unref(m);
-                        return NULL;
-                }
-        }
+                return -ENOMEM;
 
-        return m;
+        r = sd_bus_message_new_signal(
+                        bus,
+                        "/org/freedesktop/systemd1",
+                        "org.freedesktop.systemd1.Manager",
+                        "JobNew",
+                        &m);
+        if (r < 0)
+                return r;
+
+        r = sd_bus_message_append(m, "uos", j->id, p, j->unit->id);
+        if (r < 0)
+                return r;
+
+        return sd_bus_send_to(bus, m, destination, NULL);
 }
 
-static DBusMessage* new_removed_signal_message(Job *j) {
+static int send_changed_signal(sd_bus *bus, const char *destination, Job *j) {
         _cleanup_free_ char *p = NULL;
-        DBusMessage *m;
-        const char *r;
+
+        assert(bus);
+        assert(j);
 
         p = job_dbus_path(j);
         if (!p)
-                return NULL;
-
-        m = dbus_message_new_signal("/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "JobRemoved");
-        if (!m)
-                return NULL;
-
-        r = job_result_to_string(j->result);
-
-        if (!dbus_message_append_args(m,
-                                      DBUS_TYPE_UINT32, &j->id,
-                                      DBUS_TYPE_OBJECT_PATH, &p,
-                                      DBUS_TYPE_STRING, &j->unit->id,
-                                      DBUS_TYPE_STRING, &r,
-                                      DBUS_TYPE_INVALID)) {
-                dbus_message_unref(m);
-                return NULL;
-        }
+                return -ENOMEM;
 
-        return m;
+        return sd_bus_emit_properties_changed(bus, p, "org.freedesktop.systemd1.Job", "State", NULL);
 }
 
 void bus_job_send_change_signal(Job *j) {
+        int r;
+
         assert(j);
 
         if (j->in_dbus_queue) {
@@ -323,36 +165,52 @@ void bus_job_send_change_signal(Job *j) {
                 j->in_dbus_queue = false;
         }
 
-        if (!bus_has_subscriber(j->manager) && !j->bus_client_list && !j->forgot_bus_clients) {
-                j->sent_dbus_new_signal = true;
-                return;
-        }
-
-        if (job_send_message(j, new_change_signal_message) < 0)
-                goto oom;
+        r = foreach_client(j, j->sent_dbus_new_signal ? send_changed_signal : send_new_signal);
+        if (r < 0)
+                log_warning("Failed to send job change signal for %u/%s: %s", j->id, j->unit->id, strerror(-r));
 
         j->sent_dbus_new_signal = true;
+}
+
+static int send_removed_signal(sd_bus *bus, const char *destination, Job *j) {
+        _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+        _cleanup_free_ char *p = NULL;
+        int r;
+
+        assert(bus);
+        assert(j);
+
+        p = job_dbus_path(j);
+        if (!p)
+                return -ENOMEM;
 
-        return;
 
-oom:
-        log_error("Failed to allocate job change signal.");
+        r = sd_bus_message_new_signal(
+                        bus,
+                        "/org/freedesktop/systemd1",
+                        "org.freedesktop.systemd1.Manager",
+                        "JobRemoved",
+                        &m);
+        if (r < 0)
+                return r;
+
+        r = sd_bus_message_append(m, "uoss", j->id, p, j->unit->id, job_result_to_string(j->result));
+        if (r < 0)
+                return r;
+
+        return sd_bus_send_to(bus, m, destination, NULL);
 }
 
 void bus_job_send_removed_signal(Job *j) {
-        assert(j);
+        int r;
 
-        if (!bus_has_subscriber(j->manager) && !j->bus_client_list && !j->forgot_bus_clients)
-                return;
+        assert(j);
 
         if (!j->sent_dbus_new_signal)
                 bus_job_send_change_signal(j);
 
-        if (job_send_message(j, new_removed_signal_message) < 0)
-                goto oom;
-
-        return;
-
-oom:
-        log_error("Failed to allocate job remove signal.");
+        r = foreach_client(j, send_removed_signal);
+        if (r < 0)
+                log_warning("Failed to send job removal signal for %u/%s: %s", j->id, j->unit->id, strerror(-r));
+                return;
 }
diff --git a/src/core/dbus-job.h b/src/core/dbus-job.h
index a1b928f..d1d0f6d 100644
--- a/src/core/dbus-job.h
+++ b/src/core/dbus-job.h
@@ -21,13 +21,10 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <dbus/dbus.h>
-
+#include "sd-bus.h"
 #include "job.h"
 
+extern const sd_bus_vtable bus_job_vtable[];
+
 void bus_job_send_change_signal(Job *j);
 void bus_job_send_removed_signal(Job *j);
-
-extern const DBusObjectPathVTable bus_job_vtable;
-
-extern const char bus_job_interface[];
diff --git a/src/core/dbus-kill.c b/src/core/dbus-kill.c
index 811adb1..42488b1 100644
--- a/src/core/dbus-kill.c
+++ b/src/core/dbus-kill.c
@@ -19,43 +19,44 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <errno.h>
-#include <dbus/dbus.h>
-
+#include "bus-util.h"
+#include "kill.h"
 #include "dbus-kill.h"
-#include "dbus-common.h"
+#include "bus-util.h"
 
-static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_kill_append_mode, kill_mode, KillMode);
+static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_kill_mode, kill_mode, KillMode);
 
-const BusProperty bus_kill_context_properties[] = {
-        { "KillMode",    bus_kill_append_mode,     "s", offsetof(KillContext, kill_mode)    },
-        { "KillSignal",  bus_property_append_int,  "i", offsetof(KillContext, kill_signal)  },
-        { "SendSIGKILL", bus_property_append_bool, "b", offsetof(KillContext, send_sigkill) },
-        { "SendSIGHUP",  bus_property_append_bool, "b", offsetof(KillContext, send_sighup)  },
-        {}
+const sd_bus_vtable bus_kill_vtable[] = {
+        SD_BUS_VTABLE_START(0),
+        SD_BUS_PROPERTY("KillMode", "s", property_get_kill_mode, offsetof(KillContext, kill_mode), 0),
+        SD_BUS_PROPERTY("KillSignal", "i", bus_property_get_int, offsetof(KillContext, kill_signal), 0),
+        SD_BUS_PROPERTY("SendSIGKILL", "b", bus_property_get_bool, offsetof(KillContext, send_sigkill), 0),
+        SD_BUS_PROPERTY("SendSIGHUP", "b", bus_property_get_bool,  offsetof(KillContext, send_sighup), 0),
+        SD_BUS_VTABLE_END
 };
 
 int bus_kill_context_set_transient_property(
                 Unit *u,
                 KillContext *c,
                 const char *name,
-                DBusMessageIter *i,
+                sd_bus_message *message,
                 UnitSetPropertiesMode mode,
-                DBusError *error) {
+                sd_bus_error *error) {
+
+        int r;
 
         assert(u);
         assert(c);
         assert(name);
-        assert(i);
+        assert(message);
 
         if (streq(name, "KillMode")) {
                 const char *m;
                 KillMode k;
 
-                if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_STRING)
-                        return -EINVAL;
-
-                dbus_message_iter_get_basic(i, &m);
+                r = sd_bus_message_read(message, "s", &m);
+                if (r < 0)
+                        return r;
 
                 k = kill_mode_from_string(m);
                 if (k < 0)
@@ -70,14 +71,13 @@ int bus_kill_context_set_transient_property(
                 return 1;
 
         } else if (streq(name, "SendSIGHUP")) {
+                int b;
 
-                if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_BOOLEAN)
-                        return -EINVAL;
+                r = sd_bus_message_read(message, "b", &b);
+                if (r < 0)
+                        return r;
 
                 if (mode != UNIT_CHECK) {
-                        dbus_bool_t b;
-
-                        dbus_message_iter_get_basic(i, &b);
                         c->send_sighup = b;
 
                         unit_write_drop_in_private_format(u, mode, name, "SendSIGHUP=%s\n", yes_no(b));
@@ -86,14 +86,13 @@ int bus_kill_context_set_transient_property(
                 return 1;
 
         } else if (streq(name, "SendSIGKILL")) {
+                int b;
 
-                if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_BOOLEAN)
-                        return -EINVAL;
+                r = sd_bus_message_read(message, "b", &b);
+                if (r < 0)
+                        return r;
 
                 if (mode != UNIT_CHECK) {
-                        dbus_bool_t b;
-
-                        dbus_message_iter_get_basic(i, &b);
                         c->send_sigkill = b;
 
                         unit_write_drop_in_private_format(u, mode, name, "SendSIGKILL=%s\n", yes_no(b));
diff --git a/src/core/dbus-kill.h b/src/core/dbus-kill.h
index 7676d98..7c15f3a 100644
--- a/src/core/dbus-kill.h
+++ b/src/core/dbus-kill.h
@@ -21,17 +21,10 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <dbus/dbus.h>
+#include "sd-bus.h"
+#include "unit.h"
+#include "kill.h"
 
-#include "manager.h"
-#include "dbus-common.h"
+extern const sd_bus_vtable bus_kill_vtable[];
 
-#define BUS_KILL_CONTEXT_INTERFACE                                      \
-        "  <property name=\"KillMode\" type=\"s\" access=\"read\"/>\n"  \
-        "  <property name=\"KillSignal\" type=\"i\" access=\"read\"/>\n" \
-        "  <property name=\"SendSIGKILL\" type=\"b\" access=\"read\"/>\n" \
-        "  <property name=\"SendSIGHUP\" type=\"b\" access=\"read\"/>\n"
-
-extern const BusProperty bus_kill_context_properties[];
-
-int bus_kill_context_set_transient_property(Unit *u, KillContext *c, const char *name, DBusMessageIter *i, UnitSetPropertiesMode mode, DBusError *error);
+int bus_kill_context_set_transient_property(Unit *u, KillContext *c, const char *name, sd_bus_message *message, UnitSetPropertiesMode mode, sd_bus_error *error);
diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c
index 747bcfc..2e4de2e 100644
--- a/src/core/dbus-manager.c
+++ b/src/core/dbus-manager.c
@@ -22,320 +22,88 @@
 #include <errno.h>
 #include <unistd.h>
 
-#include "dbus.h"
 #include "log.h"
-#include "dbus-manager.h"
 #include "strv.h"
-#include "bus-errors.h"
 #include "build.h"
-#include "dbus-common.h"
 #include "install.h"
 #include "selinux-access.h"
 #include "watchdog.h"
 #include "hwclock.h"
 #include "path-util.h"
-#include "dbus-unit.h"
 #include "virt.h"
 #include "env-util.h"
+#include "dbus.h"
+#include "dbus-manager.h"
+#include "dbus-unit.h"
+#include "dbus-snapshot.h"
+#include "dbus-client-track.h"
+#include "dbus-execute.h"
+#include "bus-errors.h"
 
-#define BUS_MANAGER_INTERFACE_BEGIN                                     \
-        " <interface name=\"org.freedesktop.systemd1.Manager\">\n"
-
-#define BUS_MANAGER_INTERFACE_METHODS                                   \
-        "  <method name=\"GetUnit\">\n"                                 \
-        "   <arg name=\"name\" type=\"s\" direction=\"in\"/>\n"         \
-        "   <arg name=\"unit\" type=\"o\" direction=\"out\"/>\n"        \
-        "  </method>\n"                                                 \
-        "  <method name=\"GetUnitByPID\">\n"                            \
-        "   <arg name=\"pid\" type=\"u\" direction=\"in\"/>\n"          \
-        "   <arg name=\"unit\" type=\"o\" direction=\"out\"/>\n"        \
-        "  </method>\n"                                                 \
-        "  <method name=\"LoadUnit\">\n"                                \
-        "   <arg name=\"name\" type=\"s\" direction=\"in\"/>\n"         \
-        "   <arg name=\"unit\" type=\"o\" direction=\"out\"/>\n"        \
-        "  </method>\n"                                                 \
-        "  <method name=\"StartUnit\">\n"                               \
-        "   <arg name=\"name\" type=\"s\" direction=\"in\"/>\n"         \
-        "   <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n"         \
-        "   <arg name=\"job\" type=\"o\" direction=\"out\"/>\n"         \
-        "  </method>\n"                                                 \
-        "  <method name=\"StartUnitReplace\">\n"                        \
-        "   <arg name=\"old_unit\" type=\"s\" direction=\"in\"/>\n"     \
-        "   <arg name=\"new_unit\" type=\"s\" direction=\"in\"/>\n"     \
-        "   <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n"         \
-        "   <arg name=\"job\" type=\"o\" direction=\"out\"/>\n"         \
-        "  </method>\n"                                                 \
-        "  <method name=\"StopUnit\">\n"                                \
-        "   <arg name=\"name\" type=\"s\" direction=\"in\"/>\n"         \
-        "   <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n"         \
-        "   <arg name=\"job\" type=\"o\" direction=\"out\"/>\n"         \
-        "  </method>\n"                                                 \
-        "  <method name=\"ReloadUnit\">\n"                              \
-        "   <arg name=\"name\" type=\"s\" direction=\"in\"/>\n"         \
-        "   <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n"         \
-        "   <arg name=\"job\" type=\"o\" direction=\"out\"/>\n"         \
-        "  </method>\n"                                                 \
-        "  <method name=\"RestartUnit\">\n"                             \
-        "   <arg name=\"name\" type=\"s\" direction=\"in\"/>\n"         \
-        "   <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n"         \
-        "   <arg name=\"job\" type=\"o\" direction=\"out\"/>\n"         \
-        "  </method>\n"                                                 \
-        "  <method name=\"TryRestartUnit\">\n"                          \
-        "   <arg name=\"name\" type=\"s\" direction=\"in\"/>\n"         \
-        "   <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n"         \
-        "   <arg name=\"job\" type=\"o\" direction=\"out\"/>\n"         \
-        "  </method>\n"                                                 \
-        "  <method name=\"ReloadOrRestartUnit\">\n"                     \
-        "   <arg name=\"name\" type=\"s\" direction=\"in\"/>\n"         \
-        "   <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n"         \
-        "   <arg name=\"job\" type=\"o\" direction=\"out\"/>\n"         \
-        "  </method>\n"                                                 \
-        "  <method name=\"ReloadOrTryRestartUnit\">\n"                  \
-        "   <arg name=\"name\" type=\"s\" direction=\"in\"/>\n"         \
-        "   <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n"         \
-        "   <arg name=\"job\" type=\"o\" direction=\"out\"/>\n"         \
-        "  </method>\n"                                                 \
-        "  <method name=\"KillUnit\">\n"                                \
-        "   <arg name=\"name\" type=\"s\" direction=\"in\"/>\n"         \
-        "   <arg name=\"who\" type=\"s\" direction=\"in\"/>\n"          \
-        "   <arg name=\"signal\" type=\"i\" direction=\"in\"/>\n"       \
-        "  </method>\n"                                                 \
-        "  <method name=\"ResetFailedUnit\">\n"                         \
-        "   <arg name=\"name\" type=\"s\" direction=\"in\"/>\n"         \
-        "  </method>\n"                                                 \
-        "  <method name=\"GetJob\">\n"                                  \
-        "   <arg name=\"id\" type=\"u\" direction=\"in\"/>\n"           \
-        "   <arg name=\"job\" type=\"o\" direction=\"out\"/>\n"         \
-        "  </method>\n"                                                 \
-        "  <method name=\"CancelJob\">\n"                               \
-        "   <arg name=\"id\" type=\"u\" direction=\"in\"/>\n"           \
-        "  </method>\n"                                                 \
-        "  <method name=\"ClearJobs\"/>\n"                              \
-        "  <method name=\"ResetFailed\"/>\n"                            \
-        "  <method name=\"ListUnits\">\n"                               \
-        "   <arg name=\"units\" type=\"a(ssssssouso)\" direction=\"out\"/>\n" \
-        "  </method>\n"                                                 \
-        "  <method name=\"ListJobs\">\n"                                \
-        "   <arg name=\"jobs\" type=\"a(usssoo)\" direction=\"out\"/>\n" \
-        "  </method>\n"                                                 \
-        "  <method name=\"Subscribe\"/>\n"                              \
-        "  <method name=\"Unsubscribe\"/>\n"                            \
-        "  <method name=\"Dump\">\n"                                    \
-        "   <arg name=\"dump\" type=\"s\" direction=\"out\"/>\n"        \
-        "  </method>\n"                                                 \
-        "  <method name=\"CreateSnapshot\">\n"                          \
-        "   <arg name=\"name\" type=\"s\" direction=\"in\"/>\n"         \
-        "   <arg name=\"cleanup\" type=\"b\" direction=\"in\"/>\n"      \
-        "   <arg name=\"unit\" type=\"o\" direction=\"out\"/>\n"        \
-        "  </method>\n"                                                 \
-        "  <method name=\"RemoveSnapshot\">\n"                          \
-        "   <arg name=\"name\" type=\"s\" direction=\"in\"/>\n"         \
-        "  </method>\n"                                                 \
-        "  <method name=\"Reload\"/>\n"                                 \
-        "  <method name=\"Reexecute\"/>\n"                              \
-        "  <method name=\"Exit\"/>\n"                                   \
-        "  <method name=\"Reboot\"/>\n"                                 \
-        "  <method name=\"PowerOff\"/>\n"                               \
-        "  <method name=\"Halt\"/>\n"                                   \
-        "  <method name=\"KExec\"/>\n"                                  \
-        "  <method name=\"SwitchRoot\">\n"                              \
-        "   <arg name=\"new_root\" type=\"s\" direction=\"in\"/>\n"     \
-        "   <arg name=\"init\" type=\"s\" direction=\"in\"/>\n"         \
-        "  </method>\n"                                                 \
-        "  <method name=\"SetEnvironment\">\n"                          \
-        "   <arg name=\"names\" type=\"as\" direction=\"in\"/>\n"       \
-        "  </method>\n"                                                 \
-        "  <method name=\"UnsetEnvironment\">\n"                        \
-        "   <arg name=\"names\" type=\"as\" direction=\"in\"/>\n"       \
-        "  </method>\n"                                                 \
-        "  <method name=\"UnsetAndSetEnvironment\">\n"                  \
-        "   <arg name=\"unset\" type=\"as\" direction=\"in\"/>\n"       \
-        "   <arg name=\"set\" type=\"as\" direction=\"in\"/>\n"         \
-        "  </method>\n"                                                 \
-        "  <method name=\"ListUnitFiles\">\n"                           \
-        "   <arg name=\"files\" type=\"a(ss)\" direction=\"out\"/>\n"   \
-        "  </method>\n"                                                 \
-        "  <method name=\"GetUnitFileState\">\n"                        \
-        "   <arg name=\"file\" type=\"s\" direction=\"in\"/>\n"         \
-        "   <arg name=\"state\" type=\"s\" direction=\"out\"/>\n"       \
-        "  </method>\n"                                                 \
-        "  <method name=\"EnableUnitFiles\">\n"                         \
-        "   <arg name=\"files\" type=\"as\" direction=\"in\"/>\n"       \
-        "   <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n"      \
-        "   <arg name=\"force\" type=\"b\" direction=\"in\"/>\n"        \
-        "   <arg name=\"carries_install_info\" type=\"b\" direction=\"out\"/>\n" \
-        "   <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
-        "  </method>\n"                                                 \
-        "  <method name=\"DisableUnitFiles\">\n"                        \
-        "   <arg name=\"files\" type=\"as\" direction=\"in\"/>\n"       \
-        "   <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n"      \
-        "   <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
-        "  </method>\n"                                                 \
-        "  <method name=\"ReenableUnitFiles\">\n"                       \
-        "   <arg name=\"files\" type=\"as\" direction=\"in\"/>\n"       \
-        "   <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n"      \
-        "   <arg name=\"force\" type=\"b\" direction=\"in\"/>\n"        \
-        "   <arg name=\"carries_install_info\" type=\"b\" direction=\"out\"/>\n" \
-        "   <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
-        "  </method>\n"                                                 \
-        "  <method name=\"LinkUnitFiles\">\n"                           \
-        "   <arg name=\"files\" type=\"as\" direction=\"in\"/>\n"       \
-        "   <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n"      \
-        "   <arg name=\"force\" type=\"b\" direction=\"in\"/>\n"        \
-        "   <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
-        "  </method>\n"                                                 \
-        "  <method name=\"PresetUnitFiles\">\n"                         \
-        "   <arg name=\"files\" type=\"as\" direction=\"in\"/>\n"       \
-        "   <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n"      \
-        "   <arg name=\"force\" type=\"b\" direction=\"in\"/>\n"        \
-        "   <arg name=\"carries_install_info\" type=\"b\" direction=\"out\"/>\n" \
-        "   <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
-        "  </method>\n"                                                 \
-        "  <method name=\"MaskUnitFiles\">\n"                           \
-        "   <arg name=\"files\" type=\"as\" direction=\"in\"/>\n"       \
-        "   <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n"      \
-        "   <arg name=\"force\" type=\"b\" direction=\"in\"/>\n"        \
-        "   <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
-        "  </method>\n"                                                 \
-        "  <method name=\"UnmaskUnitFiles\">\n"                         \
-        "   <arg name=\"files\" type=\"as\" direction=\"in\"/>\n"       \
-        "   <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n"      \
-        "   <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
-        "  </method>\n"                                                 \
-        "  <method name=\"SetDefaultTarget\">\n"                        \
-        "   <arg name=\"files\" type=\"as\" direction=\"in\"/>\n"       \
-        "   <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
-        "  </method>\n"                                                 \
-        "  <method name=\"GetDefaultTarget\">\n"                        \
-        "   <arg name=\"name\" type=\"s\" direction=\"out\"/>\n"        \
-        "  </method>\n"                                                 \
-        "  <method name=\"SetUnitProperties\">\n"                       \
-        "   <arg name=\"name\" type=\"s\" direction=\"in\"/>\n"         \
-        "   <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n"      \
-        "   <arg name=\"properties\" type=\"a(sv)\" direction=\"in\"/>\n" \
-        "  </method>\n"                                                 \
-        "  <method name=\"StartTransientUnit\">\n"                      \
-        "   <arg name=\"name\" type=\"s\" direction=\"in\"/>\n"         \
-        "   <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n"         \
-        "   <arg name=\"properties\" type=\"a(sv)\" direction=\"in\"/>\n" \
-        "   <arg name=\"aux\" type=\"a(sa(sv))\" direction=\"in\"/>\n"  \
-        "   <arg name=\"job\" type=\"o\" direction=\"out\"/>\n"         \
-        "  </method>\n"
-
-#define BUS_MANAGER_INTERFACE_SIGNALS                                   \
-        "  <signal name=\"UnitNew\">\n"                                 \
-        "   <arg name=\"id\" type=\"s\"/>\n"                            \
-        "   <arg name=\"unit\" type=\"o\"/>\n"                          \
-        "  </signal>\n"                                                 \
-        "  <signal name=\"UnitRemoved\">\n"                             \
-        "   <arg name=\"id\" type=\"s\"/>\n"                            \
-        "   <arg name=\"unit\" type=\"o\"/>\n"                          \
-        "  </signal>\n"                                                 \
-        "  <signal name=\"JobNew\">\n"                                  \
-        "   <arg name=\"id\" type=\"u\"/>\n"                            \
-        "   <arg name=\"job\" type=\"o\"/>\n"                           \
-        "   <arg name=\"unit\" type=\"s\"/>\n"                          \
-        "  </signal>\n"                                                 \
-        "  <signal name=\"JobRemoved\">\n"                              \
-        "   <arg name=\"id\" type=\"u\"/>\n"                            \
-        "   <arg name=\"job\" type=\"o\"/>\n"                           \
-        "   <arg name=\"unit\" type=\"s\"/>\n"                          \
-        "   <arg name=\"result\" type=\"s\"/>\n"                        \
-        "  </signal>"                                                   \
-        "  <signal name=\"StartupFinished\">\n"                         \
-        "   <arg name=\"firmware\" type=\"t\"/>\n"                      \
-        "   <arg name=\"loader\" type=\"t\"/>\n"                        \
-        "   <arg name=\"kernel\" type=\"t\"/>\n"                        \
-        "   <arg name=\"initrd\" type=\"t\"/>\n"                        \
-        "   <arg name=\"userspace\" type=\"t\"/>\n"                     \
-        "   <arg name=\"total\" type=\"t\"/>\n"                         \
-        "  </signal>"                                                   \
-        "  <signal name=\"UnitFilesChanged\"/>\n"                       \
-        "  <signal name=\"Reloading\">\n"                               \
-        "   <arg name=\"active\" type=\"b\"/>\n"                        \
-        "  </signal>"
-
-#define BUS_MANAGER_INTERFACE_PROPERTIES_GENERAL                        \
-        "  <property name=\"Version\" type=\"s\" access=\"read\"/>\n"   \
-        "  <property name=\"Features\" type=\"s\" access=\"read\"/>\n"  \
-        "  <property name=\"Tainted\" type=\"s\" access=\"read\"/>\n"   \
-        "  <property name=\"FirmwareTimestamp\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"FirmwareTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"LoaderTimestamp\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"LoaderTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"KernelTimestamp\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"KernelTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"InitRDTimestamp\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"InitRDTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"UserspaceTimestamp\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"UserspaceTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"FinishTimestamp\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"FinishTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"SecurityStartTimestamp\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"SecurityStartTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"SecurityFinishTimestamp\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"SecurityFinishTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"GeneratorsStartTimestamp\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"GeneratorsStartTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"GeneratorsFinishTimestamp\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"GeneratorsFinishTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"UnitsLoadStartTimestamp\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"UnitsLoadStartTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"UnitsLoadFinishTimestamp\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"UnitsLoadFinishTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"LogLevel\" type=\"s\" access=\"readwrite\"/>\n"  \
-        "  <property name=\"LogTarget\" type=\"s\" access=\"readwrite\"/>\n" \
-        "  <property name=\"NNames\" type=\"u\" access=\"read\"/>\n"    \
-        "  <property name=\"NJobs\" type=\"u\" access=\"read\"/>\n"     \
-        "  <property name=\"NInstalledJobs\" type=\"u\" access=\"read\"/>\n" \
-        "  <property name=\"NFailedJobs\" type=\"u\" access=\"read\"/>\n" \
-        "  <property name=\"Progress\" type=\"d\" access=\"read\"/>\n"  \
-        "  <property name=\"Environment\" type=\"as\" access=\"read\"/>\n" \
-        "  <property name=\"ConfirmSpawn\" type=\"b\" access=\"read\"/>\n" \
-        "  <property name=\"ShowStatus\" type=\"b\" access=\"read\"/>\n" \
-        "  <property name=\"UnitPath\" type=\"as\" access=\"read\"/>\n" \
-        "  <property name=\"DefaultStandardOutput\" type=\"s\" access=\"read\"/>\n" \
-        "  <property name=\"DefaultStandardError\" type=\"s\" access=\"read\"/>\n" \
-        "  <property name=\"RuntimeWatchdogUSec\" type=\"t\" access=\"readwrite\"/>\n" \
-        "  <property name=\"ShutdownWatchdogUSec\" type=\"t\" access=\"readwrite\"/>\n" \
-        "  <property name=\"Virtualization\" type=\"s\" access=\"read\"/>\n"
-
-#define BUS_MANAGER_INTERFACE_END                                       \
-        " </interface>\n"
-
-#define BUS_MANAGER_INTERFACE                                           \
-        BUS_MANAGER_INTERFACE_BEGIN                                     \
-        BUS_MANAGER_INTERFACE_METHODS                                   \
-        BUS_MANAGER_INTERFACE_SIGNALS                                   \
-        BUS_MANAGER_INTERFACE_PROPERTIES_GENERAL                        \
-        BUS_MANAGER_INTERFACE_END
-
-#define INTROSPECTION_BEGIN                                             \
-        DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE                       \
-        "<node>\n"                                                      \
-        BUS_MANAGER_INTERFACE                                           \
-        BUS_PROPERTIES_INTERFACE                                        \
-        BUS_PEER_INTERFACE                                              \
-        BUS_INTROSPECTABLE_INTERFACE
-
-#define INTROSPECTION_END                                               \
-        "</node>\n"
-
-#define INTERFACES_LIST                              \
-        BUS_GENERIC_INTERFACES_LIST                  \
-        "org.freedesktop.systemd1.Manager\0"
-
-const char bus_manager_interface[] = BUS_MANAGER_INTERFACE;
-
-static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_manager_append_exec_output, exec_output, ExecOutput);
-
-static int bus_manager_append_tainted(DBusMessageIter *i, const char *property, void *data) {
-        const char *t;
-        Manager *m = data;
-        char buf[LINE_MAX] = "", *e = buf, *p = NULL;
+static int property_get_version(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
+
+        assert(bus);
+        assert(reply);
+
+        return sd_bus_message_append(reply, "s", PACKAGE_VERSION);
+}
 
-        assert(i);
-        assert(property);
+static int property_get_features(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
+
+        assert(bus);
+        assert(reply);
+
+        return sd_bus_message_append(reply, "s", SYSTEMD_FEATURES);
+}
+
+static int property_get_virtualization(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
+
+        const char *id = NULL;
+
+        assert(bus);
+        assert(reply);
+
+        detect_virtualization(&id);
+
+        return sd_bus_message_append(reply, "s", id);
+}
+
+static int property_get_tainted(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
+
+        char buf[LINE_MAX] = "", *e = buf;
+        _cleanup_free_ char *p = NULL;
+        Manager *m = userdata;
+
+        assert(bus);
+        assert(reply);
         assert(m);
 
         if (m->taint_usr)
@@ -343,8 +111,6 @@ static int bus_manager_append_tainted(DBusMessageIter *i, const char *property,
 
         if (readlink_malloc("/etc/mtab", &p) < 0)
                 e = stpcpy(e, "mtab-not-symlink:");
-        else
-                free(p);
 
         if (access("/proc/cgroups", F_OK) < 0)
                 e = stpcpy(e, "cgroups-missing:");
@@ -356,105 +122,140 @@ static int bus_manager_append_tainted(DBusMessageIter *i, const char *property,
         if (e != buf)
                 e[-1] = 0;
 
-        t = buf;
-
-        if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &t))
-                return -ENOMEM;
-
-        return 0;
+        return sd_bus_message_append(reply, "s", buf);
 }
 
-static int bus_manager_append_log_target(DBusMessageIter *i, const char *property, void *data) {
-        const char *t;
-
-        assert(i);
-        assert(property);
-
-        t = log_target_to_string(log_get_target());
+static int property_get_log_target(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
 
-        if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &t))
-                return -ENOMEM;
+        assert(bus);
+        assert(reply);
 
-        return 0;
+        return sd_bus_message_append(reply, "s", log_target_to_string(log_get_target()));
 }
 
-static int bus_manager_set_log_target(DBusMessageIter *i, const char *property, void *data) {
+static int property_set_log_target(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *value,
+                sd_bus_error *error,
+                void *userdata) {
+
         const char *t;
+        int r;
 
-        assert(i);
-        assert(property);
+        assert(bus);
+        assert(value);
 
-        dbus_message_iter_get_basic(i, &t);
+        r = sd_bus_message_read(value, "s", &t);
+        if (r < 0)
+                return r;
 
         return log_set_target_from_string(t);
 }
 
-static int bus_manager_append_log_level(DBusMessageIter *i, const char *property, void *data) {
+static int property_get_log_level(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
+
         _cleanup_free_ char *t = NULL;
         int r;
 
-        assert(i);
-        assert(property);
+        assert(bus);
+        assert(reply);
 
         r = log_level_to_string_alloc(log_get_max_level(), &t);
         if (r < 0)
                 return r;
 
-        if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &t))
-                r = -ENOMEM;
-
-        return r;
+        return sd_bus_message_append(reply, "s", t);
 }
 
-static int bus_manager_set_log_level(DBusMessageIter *i, const char *property, void *data) {
+static int property_set_log_level(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *value,
+                sd_bus_error *error,
+                void *userdata) {
+
         const char *t;
+        int r;
 
-        assert(i);
-        assert(property);
+        assert(bus);
+        assert(value);
 
-        dbus_message_iter_get_basic(i, &t);
+        r = sd_bus_message_read(value, "s", &t);
+        if (r < 0)
+                return r;
 
         return log_set_max_level_from_string(t);
 }
 
-static int bus_manager_append_n_names(DBusMessageIter *i, const char *property, void *data) {
-        Manager *m = data;
-        uint32_t u;
+static int property_get_n_names(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
 
-        assert(i);
-        assert(property);
-        assert(m);
+        Manager *m = userdata;
 
-        u = hashmap_size(m->units);
-
-        if (!dbus_message_iter_append_basic(i, DBUS_TYPE_UINT32, &u))
-                return -ENOMEM;
+        assert(bus);
+        assert(reply);
+        assert(m);
 
-        return 0;
+        return sd_bus_message_append(reply, "u", (uint32_t) hashmap_size(m->units));
 }
 
-static int bus_manager_append_n_jobs(DBusMessageIter *i, const char *property, void *data) {
-        Manager *m = data;
-        uint32_t u;
+static int property_get_n_jobs(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
 
-        assert(i);
-        assert(property);
-        assert(m);
+        Manager *m = userdata;
 
-        u = hashmap_size(m->jobs);
-
-        if (!dbus_message_iter_append_basic(i, DBUS_TYPE_UINT32, &u))
-                return -ENOMEM;
+        assert(bus);
+        assert(reply);
+        assert(m);
 
-        return 0;
+        return sd_bus_message_append(reply, "u", (uint32_t) hashmap_size(m->jobs));
 }
 
-static int bus_manager_append_progress(DBusMessageIter *i, const char *property, void *data) {
+static int property_get_progress(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
+
+        Manager *m = userdata;
         double d;
-        Manager *m = data;
 
-        assert(i);
-        assert(property);
+        assert(bus);
+        assert(reply);
         assert(m);
 
         if (dual_timestamp_is_set(&m->finish_timestamp))
@@ -462,1416 +263,1375 @@ static int bus_manager_append_progress(DBusMessageIter *i, const char *property,
         else
                 d = 1.0 - ((double) hashmap_size(m->jobs) / (double) m->n_installed_jobs);
 
-        if (!dbus_message_iter_append_basic(i, DBUS_TYPE_DOUBLE, &d))
-                return -ENOMEM;
+        return sd_bus_message_append(reply, "d", d);
+}
+
+static int property_set_runtime_watchdog(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *value,
+                sd_bus_error *error,
+                void *userdata) {
 
-        return 0;
+        usec_t *t = userdata;
+        int r;
+
+        assert(bus);
+        assert(value);
+
+        assert_cc(sizeof(usec_t) == sizeof(uint64_t));
+
+        r = sd_bus_message_read(value, "t", t);
+        if (r < 0)
+                return r;
+
+        return watchdog_set_timeout(t);
 }
 
-static int bus_manager_append_virt(DBusMessageIter *i, const char *property, void *data) {
-        Manager *m = data;
-        const char *id = NULL;
+static int method_get_unit(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        _cleanup_free_ char *path = NULL;
+        Manager *m = userdata;
+        const char *name;
+        Unit *u;
+        int r;
 
-        assert(i);
-        assert(property);
+        assert(bus);
+        assert(message);
         assert(m);
 
-        detect_virtualization(&id);
+        r = sd_bus_message_read(message, "s", &name);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
 
-        if (!id)
-                id = "";
-        if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &id))
-                return -ENOMEM;
+        u = manager_get_unit(m, name);
+        if (!u)
+                return sd_bus_reply_method_errorf(bus, message, BUS_ERROR_NO_SUCH_UNIT, "Unit %s not loaded.", name);
 
-        return 0;
-}
+        SELINUX_UNIT_ACCESS_CHECK(u, bus, message, "status");
 
-static DBusMessage *message_from_file_changes(
-                DBusMessage *m,
-                UnitFileChange *changes,
-                unsigned n_changes,
-                int carries_install_info) {
+        path = unit_dbus_path(u);
+        if (!path)
+                return sd_bus_reply_method_errno(bus, message, ENOMEM, NULL);
 
-        DBusMessageIter iter, sub, sub2;
-        DBusMessage *reply;
-        unsigned i;
+        return sd_bus_reply_method_return(bus, message, "o", path);
+}
 
-        reply = dbus_message_new_method_return(m);
-        if (!reply)
-                return NULL;
+static int method_get_unit_by_pid(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        _cleanup_free_ char *path = NULL;
+        Manager *m = userdata;
+        pid_t pid;
+        Unit *u;
+        int r;
 
-        dbus_message_iter_init_append(reply, &iter);
+        assert(bus);
+        assert(message);
+        assert(m);
 
-        if (carries_install_info >= 0) {
-                dbus_bool_t b;
+        assert_cc(sizeof(pid_t) == sizeof(uint32_t));
 
-                b = !!carries_install_info;
-                if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b))
-                        goto oom;
+        r = sd_bus_message_read(message, "u", &pid);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
+
+        if (pid == 0) {
+                r = sd_bus_get_owner_pid(bus, sd_bus_message_get_sender(message), &pid);
+                if (r < 0)
+                        return sd_bus_reply_method_errno(bus, message, r, NULL);
         }
 
-        if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(sss)", &sub))
-                goto oom;
+        u = manager_get_unit_by_pid(m, pid);
+        if (!u)
+                return sd_bus_reply_method_errorf(bus, message, BUS_ERROR_NO_UNIT_FOR_PID, "PID %u does not belong to any loaded unit.", pid);
 
-        for (i = 0; i < n_changes; i++) {
-                const char *type, *path, *source;
-
-                type = unit_file_change_type_to_string(changes[i].type);
-                path = strempty(changes[i].path);
-                source = strempty(changes[i].source);
-
-                if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
-                    !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &type) ||
-                    !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &path) ||
-                    !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &source) ||
-                    !dbus_message_iter_close_container(&sub, &sub2))
-                        goto oom;
-        }
+        SELINUX_UNIT_ACCESS_CHECK(u, bus, message, "status");
+
+        path = unit_dbus_path(u);
+        if (!path)
+                return sd_bus_reply_method_errno(bus, message, ENOMEM, NULL);
+
+        return sd_bus_reply_method_return(bus, message, "o", path);
+}
+
+static int method_load_unit(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_free_ char *path = NULL;
+        Manager *m = userdata;
+        const char *name;
+        Unit *u;
+        int r;
 
-        if (!dbus_message_iter_close_container(&iter, &sub))
-                goto oom;
+        assert(bus);
+        assert(message);
+        assert(m);
+
+        r = sd_bus_message_read(message, "s", &name);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
 
-        return reply;
+        r = manager_load_unit(m, name, NULL, &error, &u);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, &error);
+
+        SELINUX_UNIT_ACCESS_CHECK(u, bus, message, "status");
 
-oom:
-        dbus_message_unref(reply);
-        return NULL;
+        path = unit_dbus_path(u);
+        if (!path)
+                return sd_bus_reply_method_errno(bus, message, ENOMEM, NULL);
+
+        return sd_bus_reply_method_return(bus, message, "o", path);
 }
 
-static int bus_manager_send_unit_files_changed(Manager *m) {
-        DBusMessage *s;
+static int method_start_unit_generic(sd_bus *bus, sd_bus_message *message, Manager *m, JobType job_type, bool reload_if_possible) {
+        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        const char *name;
+        Unit *u;
         int r;
 
-        s = dbus_message_new_signal("/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "UnitFilesChanged");
-        if (!s)
-                return -ENOMEM;
+        assert(bus);
+        assert(message);
+        assert(m);
 
-        r = bus_broadcast(m, s);
-        dbus_message_unref(s);
+        r = sd_bus_message_read(message, "s", &name);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
 
-        return r;
+        r = manager_load_unit(m, name, NULL, &error, &u);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, &error);
+
+        return bus_unit_method_start_generic(bus, message, u, job_type, reload_if_possible);
 }
 
-static int bus_manager_set_runtime_watchdog_usec(DBusMessageIter *i, const char *property, void *data) {
-        uint64_t *t = data;
+static int method_start_unit(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        return method_start_unit_generic(bus, message, userdata, JOB_START, false);
+}
 
-        assert(i);
-        assert(property);
+static int method_stop_unit(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        return method_start_unit_generic(bus, message, userdata, JOB_STOP, false);
+}
 
-        dbus_message_iter_get_basic(i, t);
+static int method_reload_unit(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        return method_start_unit_generic(bus, message, userdata, JOB_RELOAD, false);
+}
 
-        return watchdog_set_timeout(t);
+static int method_restart_unit(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        return method_start_unit_generic(bus, message, userdata, JOB_RESTART, false);
 }
 
-static const char systemd_property_string[] =
-        PACKAGE_STRING "\0"
-        SYSTEMD_FEATURES;
+static int method_try_restart_unit(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        return method_start_unit_generic(bus, message, userdata, JOB_TRY_RESTART, false);
+}
 
-static const BusProperty bus_systemd_properties[] = {
-        { "Version",       bus_property_append_string,    "s",  0                      },
-        { "Features",      bus_property_append_string,    "s",  sizeof(PACKAGE_STRING) },
-        { NULL, }
-};
+static int method_reload_or_restart_unit(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        return method_start_unit_generic(bus, message, userdata, JOB_RESTART, true);
+}
 
-static const BusProperty bus_manager_properties[] = {
-        { "Tainted",                     bus_manager_append_tainted,     "s",  0                                                },
-        { "FirmwareTimestamp",           bus_property_append_uint64,     "t",  offsetof(Manager, firmware_timestamp.realtime)   },
-        { "FirmwareTimestampMonotonic",  bus_property_append_uint64,     "t",  offsetof(Manager, firmware_timestamp.monotonic)  },
-        { "LoaderTimestamp",             bus_property_append_uint64,     "t",  offsetof(Manager, loader_timestamp.realtime)     },
-        { "LoaderTimestampMonotonic",    bus_property_append_uint64,     "t",  offsetof(Manager, loader_timestamp.monotonic)    },
-        { "KernelTimestamp",             bus_property_append_uint64,     "t",  offsetof(Manager, kernel_timestamp.realtime)     },
-        { "KernelTimestampMonotonic",    bus_property_append_uint64,     "t",  offsetof(Manager, kernel_timestamp.monotonic)    },
-        { "InitRDTimestamp",             bus_property_append_uint64,     "t",  offsetof(Manager, initrd_timestamp.realtime)     },
-        { "InitRDTimestampMonotonic",    bus_property_append_uint64,     "t",  offsetof(Manager, initrd_timestamp.monotonic)    },
-        { "UserspaceTimestamp",          bus_property_append_uint64,     "t",  offsetof(Manager, userspace_timestamp.realtime)  },
-        { "UserspaceTimestampMonotonic", bus_property_append_uint64,     "t",  offsetof(Manager, userspace_timestamp.monotonic) },
-        { "FinishTimestamp",             bus_property_append_uint64,     "t",  offsetof(Manager, finish_timestamp.realtime)     },
-        { "FinishTimestampMonotonic",    bus_property_append_uint64,     "t",  offsetof(Manager, finish_timestamp.monotonic)    },
-        { "SecurityStartTimestamp",             bus_property_append_uint64,     "t",  offsetof(Manager, security_start_timestamp.realtime)     },
-        { "SecurityStartTimestampMonotonic",    bus_property_append_uint64,     "t",  offsetof(Manager, security_start_timestamp.monotonic)    },
-        { "SecurityFinishTimestamp",            bus_property_append_uint64,     "t",  offsetof(Manager, security_finish_timestamp.realtime)    },
-        { "SecurityFinishTimestampMonotonic",   bus_property_append_uint64,     "t",  offsetof(Manager, security_finish_timestamp.monotonic)   },
-        { "GeneratorsStartTimestamp",           bus_property_append_uint64,     "t",  offsetof(Manager, generators_start_timestamp.realtime)   },
-        { "GeneratorsStartTimestampMonotonic",  bus_property_append_uint64,     "t",  offsetof(Manager, generators_start_timestamp.monotonic)  },
-        { "GeneratorsFinishTimestamp",          bus_property_append_uint64,     "t",  offsetof(Manager, generators_finish_timestamp.realtime)  },
-        { "GeneratorsFinishTimestampMonotonic", bus_property_append_uint64,     "t",  offsetof(Manager, generators_finish_timestamp.monotonic) },
-        { "UnitsLoadStartTimestamp",            bus_property_append_uint64,     "t",  offsetof(Manager, unitsload_start_timestamp.realtime)    },
-        { "UnitsLoadStartTimestampMonotonic",   bus_property_append_uint64,     "t",  offsetof(Manager, unitsload_start_timestamp.monotonic)   },
-        { "UnitsLoadFinishTimestamp",           bus_property_append_uint64,     "t",  offsetof(Manager, unitsload_finish_timestamp.realtime)   },
-        { "UnitsLoadFinishTimestampMonotonic",  bus_property_append_uint64,     "t",  offsetof(Manager, unitsload_finish_timestamp.monotonic)  },
-        { "LogLevel",                    bus_manager_append_log_level,   "s",  0,                                               false, bus_manager_set_log_level },
-        { "LogTarget",                   bus_manager_append_log_target,  "s",  0,                                               false, bus_manager_set_log_target },
-        { "NNames",                      bus_manager_append_n_names,     "u",  0                                                },
-        { "NJobs",                       bus_manager_append_n_jobs,      "u",  0                                                },
-        { "NInstalledJobs",              bus_property_append_uint32,     "u",  offsetof(Manager, n_installed_jobs)              },
-        { "NFailedJobs",                 bus_property_append_uint32,     "u",  offsetof(Manager, n_failed_jobs)                 },
-        { "Progress",                    bus_manager_append_progress,    "d",  0                                                },
-        { "Environment",                 bus_property_append_strv,       "as", offsetof(Manager, environment),                  true },
-        { "ConfirmSpawn",                bus_property_append_bool,       "b",  offsetof(Manager, confirm_spawn)                 },
-        { "ShowStatus",                  bus_property_append_bool,       "b",  offsetof(Manager, show_status)                   },
-        { "UnitPath",                    bus_property_append_strv,       "as", offsetof(Manager, lookup_paths.unit_path),       true },
-        { "DefaultStandardOutput",       bus_manager_append_exec_output, "s",  offsetof(Manager, default_std_output)            },
-        { "DefaultStandardError",        bus_manager_append_exec_output, "s",  offsetof(Manager, default_std_error)             },
-        { "RuntimeWatchdogUSec",         bus_property_append_usec,       "t",  offsetof(Manager, runtime_watchdog),             false, bus_manager_set_runtime_watchdog_usec },
-        { "ShutdownWatchdogUSec",        bus_property_append_usec,       "t",  offsetof(Manager, shutdown_watchdog),            false, bus_property_set_usec },
-        { "Virtualization",              bus_manager_append_virt,        "s",  0,                                               },
-        { NULL, }
-};
+static int method_reload_or_try_restart_unit(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        return method_start_unit_generic(bus, message, userdata, JOB_TRY_RESTART, true);
+}
 
-static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection, DBusMessage *message, void *data) {
-        _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
-        _cleanup_free_ char * path = NULL;
-        Manager *m = data;
+static int method_start_unit_replace(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        Manager *m = userdata;
+        const char *old_name;
+        Unit *u;
         int r;
-        DBusError error;
-        JobType job_type = _JOB_TYPE_INVALID;
-        bool reload_if_possible = false;
-        const char *member;
 
-        assert(connection);
+        assert(bus);
         assert(message);
         assert(m);
 
-        dbus_error_init(&error);
+        r = sd_bus_message_read(message, "s", &old_name);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
 
-        member = dbus_message_get_member(message);
+        u = manager_get_unit(m, old_name);
+        if (!u || !u->job || u->job->type != JOB_START)
+                return sd_bus_reply_method_errorf(bus, message, BUS_ERROR_NO_SUCH_JOB, "No job queued for unit %s", old_name);
 
-        if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetUnit")) {
-                const char *name;
-                Unit *u;
+        return method_start_unit_generic(bus, message, m, JOB_START, false);
+}
 
-                if (!dbus_message_get_args(
-                                    message,
-                                    &error,
-                                    DBUS_TYPE_STRING, &name,
-                                    DBUS_TYPE_INVALID))
-                        return bus_send_error_reply(connection, message, &error, -EINVAL);
+static int method_kill_unit(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        Manager *m = userdata;
+        const char *name;
+        Unit *u;
+        int r;
 
-                u = manager_get_unit(m, name);
-                if (!u) {
-                        dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
-                        return bus_send_error_reply(connection, message, &error, -ENOENT);
-                }
+        assert(bus);
+        assert(message);
+        assert(m);
 
-                SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "status");
-
-                reply = dbus_message_new_method_return(message);
-                if (!reply)
-                        goto oom;
-
-                path = unit_dbus_path(u);
-                if (!path)
-                        goto oom;
-
-                if (!dbus_message_append_args(
-                                    reply,
-                                    DBUS_TYPE_OBJECT_PATH, &path,
-                                    DBUS_TYPE_INVALID))
-                        goto oom;
-        } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetUnitByPID")) {
-                Unit *u;
-                uint32_t pid;
-
-                if (!dbus_message_get_args(
-                                    message,
-                                    &error,
-                                    DBUS_TYPE_UINT32, &pid,
-                                    DBUS_TYPE_INVALID))
-                        return bus_send_error_reply(connection, message, &error, -EINVAL);
-
-                u = manager_get_unit_by_pid(m, (pid_t) pid);
-                if (!u) {
-                        dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "No unit for PID %lu is loaded.", (unsigned long) pid);
-                        return bus_send_error_reply(connection, message, &error, -ENOENT);
-                }
+        r = sd_bus_message_read(message, "s", &name);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
 
-                SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "status");
-
-                reply = dbus_message_new_method_return(message);
-                if (!reply)
-                        goto oom;
-
-                path = unit_dbus_path(u);
-                if (!path)
-                        goto oom;
-
-                if (!dbus_message_append_args(
-                                    reply,
-                                    DBUS_TYPE_OBJECT_PATH, &path,
-                                    DBUS_TYPE_INVALID))
-                        goto oom;
-        } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "LoadUnit")) {
-                const char *name;
-                Unit *u;
-
-                if (!dbus_message_get_args(
-                                    message,
-                                    &error,
-                                    DBUS_TYPE_STRING, &name,
-                                    DBUS_TYPE_INVALID))
-                        return bus_send_error_reply(connection, message, &error, -EINVAL);
-
-                r = manager_load_unit(m, name, NULL, &error, &u);
-                if (r < 0)
-                        return bus_send_error_reply(connection, message, &error, r);
-
-                SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "status");
-
-                reply = dbus_message_new_method_return(message);
-                if (!reply)
-                        goto oom;
-
-                path = unit_dbus_path(u);
-                if (!path)
-                        goto oom;
-
-                if (!dbus_message_append_args(
-                                    reply,
-                                    DBUS_TYPE_OBJECT_PATH, &path,
-                                    DBUS_TYPE_INVALID))
-                        goto oom;
-
-        } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "StartUnit"))
-                job_type = JOB_START;
-        else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "StartUnitReplace"))
-                job_type = JOB_START;
-        else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "StopUnit"))
-                job_type = JOB_STOP;
-        else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ReloadUnit"))
-                job_type = JOB_RELOAD;
-        else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "RestartUnit"))
-                job_type = JOB_RESTART;
-        else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "TryRestartUnit"))
-                job_type = JOB_TRY_RESTART;
-        else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ReloadOrRestartUnit")) {
-                reload_if_possible = true;
-                job_type = JOB_RESTART;
-        } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ReloadOrTryRestartUnit")) {
-                reload_if_possible = true;
-                job_type = JOB_TRY_RESTART;
-        } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "KillUnit")) {
-                const char *name, *swho;
-                int32_t signo;
-                Unit *u;
-                KillWho who;
-
-                if (!dbus_message_get_args(
-                                    message,
-                                    &error,
-                                    DBUS_TYPE_STRING, &name,
-                                    DBUS_TYPE_STRING, &swho,
-                                    DBUS_TYPE_INT32, &signo,
-                                    DBUS_TYPE_INVALID))
-                        return bus_send_error_reply(connection, message, &error, -EINVAL);
-
-                if (isempty(swho))
-                        who = KILL_ALL;
-                else {
-                        who = kill_who_from_string(swho);
-                        if (who < 0)
-                                return bus_send_error_reply(connection, message, &error, -EINVAL);
-                }
+        u = manager_get_unit(m, name);
+        if (!u)
+                return sd_bus_reply_method_errorf(bus, message, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
 
-                if (signo <= 0 || signo >= _NSIG)
-                        return bus_send_error_reply(connection, message, &error, -EINVAL);
+        return bus_unit_method_kill(bus, message, u);
+}
 
-                u = manager_get_unit(m, name);
-                if (!u) {
-                        dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
-                        return bus_send_error_reply(connection, message, &error, -ENOENT);
-                }
+static int method_reset_failed_unit(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        Manager *m = userdata;
+        const char *name;
+        Unit *u;
+        int r;
 
-                SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "stop");
+        assert(bus);
+        assert(message);
+        assert(m);
 
-                r = unit_kill(u, who, signo, &error);
-                if (r < 0)
-                        return bus_send_error_reply(connection, message, &error, r);
-
-                reply = dbus_message_new_method_return(message);
-                if (!reply)
-                        goto oom;
-
-        } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetJob")) {
-                uint32_t id;
-                Job *j;
-
-                if (!dbus_message_get_args(
-                                    message,
-                                    &error,
-                                    DBUS_TYPE_UINT32, &id,
-                                    DBUS_TYPE_INVALID))
-                        return bus_send_error_reply(connection, message, &error, -EINVAL);
-
-                j = manager_get_job(m, id);
-                if (!j) {
-                        dbus_set_error(&error, BUS_ERROR_NO_SUCH_JOB, "Job %u does not exist.", (unsigned) id);
-                        return bus_send_error_reply(connection, message, &error, -ENOENT);
-                }
+        r = sd_bus_message_read(message, "s", &name);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
 
-                SELINUX_UNIT_ACCESS_CHECK(j->unit, connection, message, "status");
-
-                reply = dbus_message_new_method_return(message);
-                if (!reply)
-                        goto oom;
-
-                path = job_dbus_path(j);
-                if (!path)
-                        goto oom;
-
-                if (!dbus_message_append_args(
-                                    reply,
-                                    DBUS_TYPE_OBJECT_PATH, &path,
-                                    DBUS_TYPE_INVALID))
-                        goto oom;
-
-        } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "CancelJob")) {
-                uint32_t id;
-                Job *j;
-
-                if (!dbus_message_get_args(
-                                    message,
-                                    &error,
-                                    DBUS_TYPE_UINT32, &id,
-                                    DBUS_TYPE_INVALID))
-                        return bus_send_error_reply(connection, message, &error, -EINVAL);
-
-                j = manager_get_job(m, id);
-                if (!j) {
-                        dbus_set_error(&error, BUS_ERROR_NO_SUCH_JOB, "Job %u does not exist.", (unsigned) id);
-                        return bus_send_error_reply(connection, message, &error, -ENOENT);
-                }
+        u = manager_get_unit(m, name);
+        if (!u)
+                return sd_bus_reply_method_errorf(bus, message, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
 
-                SELINUX_UNIT_ACCESS_CHECK(j->unit, connection, message, "stop");
-                job_finish_and_invalidate(j, JOB_CANCELED, true);
+        return bus_unit_method_reset_failed(bus, message, u);
+}
 
-                reply = dbus_message_new_method_return(message);
-                if (!reply)
-                        goto oom;
+static int method_set_unit_properties(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        Manager *m = userdata;
+        const char *name;
+        Unit *u;
+        int r;
 
-        } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ClearJobs")) {
+        assert(bus);
+        assert(message);
+        assert(m);
+
+        r = sd_bus_message_read(message, "s", &name);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
+
+        u = manager_get_unit(m, name);
+        if (!u)
+                return sd_bus_reply_method_errorf(bus, message, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
 
-                SELINUX_ACCESS_CHECK(connection, message, "reboot");
-                manager_clear_jobs(m);
+        return bus_unit_method_set_properties(bus, message, u);
+}
+
+static int method_start_transient_unit(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        const char *name, *smode;
+        Manager *m = userdata;
+        JobMode mode;
+        UnitType t;
+        Unit *u;
+        int r;
 
-                reply = dbus_message_new_method_return(message);
-                if (!reply)
-                        goto oom;
+        assert(bus);
+        assert(message);
+        assert(m);
 
-        } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ResetFailed")) {
+        r = sd_bus_message_read(message, "ss", &name, &smode);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
 
-                SELINUX_ACCESS_CHECK(connection, message, "reload");
+        t = unit_name_to_type(name);
+        if (t < 0)
+                return sd_bus_reply_method_errorf(bus, message, SD_BUS_ERROR_INVALID_ARGS, "Invalid unit type.");
 
-                manager_reset_failed(m);
+        if (!unit_vtable[t]->can_transient)
+                return sd_bus_reply_method_errorf(bus, message, SD_BUS_ERROR_INVALID_ARGS, "Unit type %s does not support transient units.");
 
-                reply = dbus_message_new_method_return(message);
-                if (!reply)
-                        goto oom;
+        mode = job_mode_from_string(smode);
+        if (mode < 0)
+                return sd_bus_reply_method_errorf(bus, message, SD_BUS_ERROR_INVALID_ARGS, "Job mode %s is invalid.", smode);
 
-        } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ResetFailedUnit")) {
-                const char *name;
-                Unit *u;
+        r = manager_load_unit(m, name, NULL, &error, &u);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, &error);
 
-                if (!dbus_message_get_args(
-                                    message,
-                                    &error,
-                                    DBUS_TYPE_STRING, &name,
-                                    DBUS_TYPE_INVALID))
-                        return bus_send_error_reply(connection, message, &error, -EINVAL);
+        SELINUX_UNIT_ACCESS_CHECK(u, bus, message, "start");
 
-                u = manager_get_unit(m, name);
-                if (!u) {
-                        dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
-                        return bus_send_error_reply(connection, message, &error, -ENOENT);
-                }
+        if (u->load_state != UNIT_NOT_FOUND || set_size(u->dependencies[UNIT_REFERENCED_BY]) > 0)
+                return sd_bus_reply_method_errorf(bus, message, BUS_ERROR_UNIT_EXISTS, "Unit %s already exists.", name);
 
-                SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "reload");
-
-                unit_reset_failed(u);
-
-                reply = dbus_message_new_method_return(message);
-                if (!reply)
-                        goto oom;
-
-        } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ListUnits")) {
-                DBusMessageIter iter, sub;
-                Iterator i;
-                Unit *u;
-                const char *k;
-
-                SELINUX_ACCESS_CHECK(connection, message, "status");
-
-                reply = dbus_message_new_method_return(message);
-                if (!reply)
-                        goto oom;
-
-                dbus_message_iter_init_append(reply, &iter);
-
-                if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(ssssssouso)", &sub))
-                        goto oom;
-
-                HASHMAP_FOREACH_KEY(u, k, m->units, i) {
-                        char *u_path, *j_path;
-                        const char *description, *load_state, *active_state, *sub_state, *sjob_type, *following;
-                        DBusMessageIter sub2;
-                        uint32_t job_id;
-                        Unit *f;
-
-                        if (k != u->id)
-                                continue;
-
-                        if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2))
-                                goto oom;
-
-                        description = unit_description(u);
-                        load_state = unit_load_state_to_string(u->load_state);
-                        active_state = unit_active_state_to_string(unit_active_state(u));
-                        sub_state = unit_sub_state_to_string(u);
-
-                        f = unit_following(u);
-                        following = f ? f->id : "";
-
-                        u_path = unit_dbus_path(u);
-                        if (!u_path)
-                                goto oom;
-
-                        if (u->job) {
-                                job_id = (uint32_t) u->job->id;
-
-                                if (!(j_path = job_dbus_path(u->job))) {
-                                        free(u_path);
-                                        goto oom;
-                                }
-
-                                sjob_type = job_type_to_string(u->job->type);
-                        } else {
-                                job_id = 0;
-                                j_path = u_path;
-                                sjob_type = "";
-                        }
-
-                        if (!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &u->id) ||
-                            !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &description) ||
-                            !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &load_state) ||
-                            !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &active_state) ||
-                            !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &sub_state) ||
-                            !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &following) ||
-                            !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &u_path) ||
-                            !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT32, &job_id) ||
-                            !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &sjob_type) ||
-                            !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &j_path)) {
-                                free(u_path);
-                                if (u->job)
-                                        free(j_path);
-                                goto oom;
-                        }
-
-                        free(u_path);
-                        if (u->job)
-                                free(j_path);
-
-                        if (!dbus_message_iter_close_container(&sub, &sub2))
-                                goto oom;
-                }
+        /* OK, the unit failed to load and is unreferenced, now let's
+         * fill in the transient data instead */
+        r = unit_make_transient(u);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
 
-                if (!dbus_message_iter_close_container(&iter, &sub))
-                        goto oom;
+        /* Set our properties */
+        r = bus_unit_set_properties(u, message, UNIT_RUNTIME, false, &error);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, &error);
 
-        } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ListJobs")) {
-                DBusMessageIter iter, sub;
-                Iterator i;
-                Job *j;
+        /* And load this stub fully */
+        r = unit_load(u);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, &error);
 
-                SELINUX_ACCESS_CHECK(connection, message, "status");
+        manager_dispatch_load_queue(m);
 
-                reply = dbus_message_new_method_return(message);
-                if (!reply)
-                        goto oom;
+        /* Finally, start it */
+        return bus_unit_queue_job(bus, message, u, JOB_START, mode, false);
+}
 
-                dbus_message_iter_init_append(reply, &iter);
+static int method_get_job(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        _cleanup_free_ char *path = NULL;
+        Manager *m = userdata;
+        uint32_t id;
+        Job *j;
+        int r;
 
-                if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(usssoo)", &sub))
-                        goto oom;
+        assert(bus);
+        assert(message);
+        assert(m);
 
-                HASHMAP_FOREACH(j, m->jobs, i) {
-                        char *u_path, *j_path;
-                        const char *state, *type;
-                        uint32_t id;
-                        DBusMessageIter sub2;
+        r = sd_bus_message_read(message, "u", &id);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
 
-                        if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2))
-                                goto oom;
+        j = manager_get_job(m, id);
+        if (!j)
+                return sd_bus_reply_method_errorf(bus, message, BUS_ERROR_NO_SUCH_JOB, "Job %u does not exist.", (unsigned) id);
 
-                        id = (uint32_t) j->id;
-                        state = job_state_to_string(j->state);
-                        type = job_type_to_string(j->type);
+        SELINUX_UNIT_ACCESS_CHECK(j->unit, bus, message, "status");
 
-                        j_path = job_dbus_path(j);
-                        if (!j_path)
-                                goto oom;
+        path = job_dbus_path(j);
+        if (!path)
+                return sd_bus_reply_method_errno(bus, message, ENOMEM, NULL);
 
-                        u_path = unit_dbus_path(j->unit);
-                        if (!u_path) {
-                                free(j_path);
-                                goto oom;
-                        }
+        return sd_bus_reply_method_return(bus, message, "o", path);
+}
 
-                        if (!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT32, &id) ||
-                            !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &j->unit->id) ||
-                            !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &type) ||
-                            !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &state) ||
-                            !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &j_path) ||
-                            !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &u_path)) {
-                                free(j_path);
-                                free(u_path);
-                                goto oom;
-                        }
+static int method_cancel_job(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        Manager *m = userdata;
+        uint32_t id;
+        Job *j;
+        int r;
 
-                        free(j_path);
-                        free(u_path);
+        assert(bus);
+        assert(message);
+        assert(m);
 
-                        if (!dbus_message_iter_close_container(&sub, &sub2))
-                                goto oom;
-                }
+        r = sd_bus_message_read(message, "u", &id);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
 
-                if (!dbus_message_iter_close_container(&iter, &sub))
-                        goto oom;
+        j = manager_get_job(m, id);
+        if (!j)
+                return sd_bus_reply_method_errorf(bus, message, BUS_ERROR_NO_SUCH_JOB, "Job %u does not exist.", (unsigned) id);
 
-        } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Subscribe")) {
-                char *client;
-                Set *s;
+        SELINUX_UNIT_ACCESS_CHECK(j->unit, bus, message, "stop");
 
-                SELINUX_ACCESS_CHECK(connection, message, "status");
+        job_finish_and_invalidate(j, JOB_CANCELED, true);
 
-                s = bus_acquire_subscribed(m, connection);
-                if (!s)
-                        goto oom;
+        return sd_bus_reply_method_return(bus, message, NULL);
+}
 
-                client = strdup(bus_message_get_sender_with_fallback(message));
-                if (!client)
-                        goto oom;
+static int method_clear_jobs(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        Manager *m = userdata;
 
-                r = set_consume(s, client);
-                if (r < 0)
-                        return bus_send_error_reply(connection, message, NULL, r);
+        assert(bus);
+        assert(message);
+        assert(m);
 
-                reply = dbus_message_new_method_return(message);
-                if (!reply)
-                        goto oom;
+        SELINUX_ACCESS_CHECK(bus, message, "reboot");
+        manager_clear_jobs(m);
 
-        } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Unsubscribe")) {
-                char *client;
+        return sd_bus_reply_method_return(bus, message, NULL);
+}
 
-                SELINUX_ACCESS_CHECK(connection, message, "status");
+static int method_reset_failed(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        Manager *m = userdata;
 
-                client = set_remove(BUS_CONNECTION_SUBSCRIBED(m, connection), (char*) bus_message_get_sender_with_fallback(message));
-                if (!client) {
-                        dbus_set_error(&error, BUS_ERROR_NOT_SUBSCRIBED, "Client is not subscribed.");
-                        return bus_send_error_reply(connection, message, &error, -ENOENT);
-                }
+        assert(bus);
+        assert(message);
+        assert(m);
+
+        SELINUX_ACCESS_CHECK(bus, message, "reload");
+        manager_reset_failed(m);
 
-                free(client);
+        return sd_bus_reply_method_return(bus, message, NULL);
+}
 
-                reply = dbus_message_new_method_return(message);
-                if (!reply)
-                        goto oom;
+static int method_list_units(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+        Manager *m = userdata;
+        const char *k;
+        Iterator i;
+        Unit *u;
+        int r;
 
-        } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Dump")) {
-                FILE *f;
-                char *dump = NULL;
-                size_t size;
+        assert(bus);
+        assert(message);
+        assert(m);
 
-                SELINUX_ACCESS_CHECK(connection, message, "status");
+        SELINUX_ACCESS_CHECK(bus, message, "status");
 
-                reply = dbus_message_new_method_return(message);
-                if (!reply)
-                        goto oom;
+        r = sd_bus_message_new_method_return(bus, message, &reply);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
 
-                f = open_memstream(&dump, &size);
-                if (!f)
-                        goto oom;
+        r = sd_bus_message_open_container(reply, 'a', "(ssssssouso)");
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
 
-                manager_dump_units(m, f, NULL);
-                manager_dump_jobs(m, f, NULL);
+        HASHMAP_FOREACH_KEY(u, k, m->units, i) {
+                _cleanup_free_ char *unit_path = NULL, *job_path = NULL;
+                Unit *following;
 
-                if (ferror(f)) {
-                        fclose(f);
-                        free(dump);
-                        goto oom;
-                }
+                if (k != u->id)
+                        continue;
 
-                fclose(f);
+                following = unit_following(u);
 
-                if (!dbus_message_append_args(reply, DBUS_TYPE_STRING, &dump, DBUS_TYPE_INVALID)) {
-                        free(dump);
-                        goto oom;
+                unit_path = unit_dbus_path(u);
+                if (!unit_path)
+                        return sd_bus_reply_method_errno(bus, message, ENOMEM, NULL);
+
+                if (u->job) {
+                        job_path = job_dbus_path(u->job);
+                        if (!job_path)
+                                return sd_bus_reply_method_errno(bus, message, ENOMEM, NULL);
                 }
 
-                free(dump);
-        } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "CreateSnapshot")) {
-                const char *name;
-                dbus_bool_t cleanup;
-                Snapshot *s;
+                r = sd_bus_message_append(
+                                reply, "(ssssssouso)",
+                                u->id,
+                                unit_description(u),
+                                unit_load_state_to_string(u->load_state),
+                                unit_active_state_to_string(unit_active_state(u)),
+                                unit_sub_state_to_string(u),
+                                following ? following->id : "",
+                                unit_path,
+                                u->job ? u->job->id : 0,
+                                u->job ? job_type_to_string(u->job->type) : "",
+                                job_path ? job_path : "/");
+                if (r < 0)
+                        return sd_bus_reply_method_errno(bus, message, r, NULL);
+        }
 
-                SELINUX_ACCESS_CHECK(connection, message, "start");
+        r = sd_bus_message_close_container(reply);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
 
-                if (!dbus_message_get_args(
-                                    message,
-                                    &error,
-                                    DBUS_TYPE_STRING, &name,
-                                    DBUS_TYPE_BOOLEAN, &cleanup,
-                                    DBUS_TYPE_INVALID))
-                        return bus_send_error_reply(connection, message, &error, -EINVAL);
+        return sd_bus_send(bus, reply, NULL);
+}
 
-                if (isempty(name))
-                        name = NULL;
+static int method_list_jobs(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+        Manager *m = userdata;
+        Iterator i;
+        Job *j;
+        int r;
 
-                r = snapshot_create(m, name, cleanup, &error, &s);
+        assert(bus);
+        assert(message);
+        assert(m);
+
+        SELINUX_ACCESS_CHECK(bus, message, "status");
+
+        r = sd_bus_message_new_method_return(bus, message, &reply);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
+
+        r = sd_bus_message_open_container(reply, 'a', "(usssoo)");
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
+
+        HASHMAP_FOREACH(j, m->jobs, i) {
+                _cleanup_free_ char *unit_path = NULL, *job_path = NULL;
+
+                job_path = job_dbus_path(j);
+                if (!job_path)
+                        return sd_bus_reply_method_errno(bus, message, ENOMEM, NULL);
+
+                unit_path = unit_dbus_path(j->unit);
+                if (!unit_path)
+                        return sd_bus_reply_method_errno(bus, message, ENOMEM, NULL);
+
+                r = sd_bus_message_append(
+                                reply, "(usssoo)",
+                                j->id,
+                                job_state_to_string(j->state),
+                                job_type_to_string(j->type),
+                                job_path,
+                                unit_path);
                 if (r < 0)
-                        return bus_send_error_reply(connection, message, &error, r);
-
-                reply = dbus_message_new_method_return(message);
-                if (!reply)
-                        goto oom;
-
-                path = unit_dbus_path(UNIT(s));
-                if (!path)
-                        goto oom;
-
-                if (!dbus_message_append_args(
-                                    reply,
-                                    DBUS_TYPE_OBJECT_PATH, &path,
-                                    DBUS_TYPE_INVALID))
-                        goto oom;
-
-        } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "RemoveSnapshot")) {
-                const char *name;
-                Unit *u;
-
-                if (!dbus_message_get_args(
-                                    message,
-                                    &error,
-                                    DBUS_TYPE_STRING, &name,
-                                    DBUS_TYPE_INVALID))
-                        return bus_send_error_reply(connection, message, &error, -EINVAL);
-
-                u = manager_get_unit(m, name);
-                if (!u) {
-                        dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s does not exist.", name);
-                        return bus_send_error_reply(connection, message, &error, -ENOENT);
-                }
+                        return sd_bus_reply_method_errno(bus, message, r, NULL);
+        }
 
-                if (u->type != UNIT_SNAPSHOT) {
-                        dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not a snapshot.", name);
-                        return bus_send_error_reply(connection, message, &error, -ENOENT);
-                }
+        r = sd_bus_message_close_container(reply);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
 
-                SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "stop");
-                snapshot_remove(SNAPSHOT(u));
+        return sd_bus_send(bus, reply, NULL);
+}
 
-                reply = dbus_message_new_method_return(message);
-                if (!reply)
-                        goto oom;
+static int method_subscribe(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        Manager *m = userdata;
+        int r;
 
-        } else if (dbus_message_is_method_call(message, "org.freedesktop.DBus.Introspectable", "Introspect")) {
-                _cleanup_free_ char *introspection = NULL;
-                FILE *f;
-                Iterator i;
-                Unit *u;
-                Job *j;
-                const char *k;
-                size_t size;
+        assert(bus);
+        assert(message);
+        assert(m);
 
-                SELINUX_ACCESS_CHECK(connection, message, "status");
+        SELINUX_ACCESS_CHECK(bus, message, "status");
 
-                reply = dbus_message_new_method_return(message);
-                if (!reply)
-                        goto oom;
+        r = bus_client_track(&m->subscribed, bus, sd_bus_message_get_sender(message));
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
+        if (r == 0)
+                return sd_bus_reply_method_errorf(bus, message, BUS_ERROR_ALREADY_SUBSCRIBED, "Client is already subscribed.");
 
-                /* We roll our own introspection code here, instead of
-                 * relying on bus_default_message_handler() because we
-                 * need to generate our introspection string
-                 * dynamically. */
+        return sd_bus_reply_method_return(bus, message, NULL);
+}
 
-                f = open_memstream(&introspection, &size);
-                if (!f)
-                        goto oom;
+static int method_unsubscribe(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        Manager *m = userdata;
+        int r;
 
-                fputs(INTROSPECTION_BEGIN, f);
+        assert(bus);
+        assert(message);
+        assert(m);
 
-                HASHMAP_FOREACH_KEY(u, k, m->units, i) {
-                        _cleanup_free_ char *p = NULL;
+        SELINUX_ACCESS_CHECK(bus, message, "status");
 
-                        if (k != u->id)
-                                continue;
+        r = bus_client_untrack(m->subscribed, bus, sd_bus_message_get_sender(message));
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
+        if (r == 0)
+                return sd_bus_reply_method_errorf(bus, message, BUS_ERROR_NOT_SUBSCRIBED, "Client is not subscribed.");
 
-                        p = bus_path_escape(k);
-                        if (!p) {
-                                fclose(f);
-                                goto oom;
-                        }
+        return sd_bus_reply_method_return(bus, message, NULL);
+}
 
-                        fprintf(f, "<node name=\"unit/%s\"/>", p);
-                }
+static int method_dump(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        _cleanup_free_ char *dump = NULL;
+        _cleanup_fclose_ FILE *f = NULL;
+        Manager *m = userdata;
+        size_t size;
 
-                HASHMAP_FOREACH(j, m->jobs, i)
-                        fprintf(f, "<node name=\"job/%lu\"/>", (unsigned long) j->id);
+        assert(bus);
+        assert(message);
+        assert(m);
 
-                fputs(INTROSPECTION_END, f);
+        SELINUX_ACCESS_CHECK(bus, message, "status");
 
-                if (ferror(f)) {
-                        fclose(f);
-                        goto oom;
-                }
+        f = open_memstream(&dump, &size);
+        if (!f)
+                return sd_bus_reply_method_errno(bus, message, ENOMEM, NULL);
 
-                fclose(f);
+        manager_dump_units(m, f, NULL);
+        manager_dump_jobs(m, f, NULL);
 
-                if (!introspection)
-                        goto oom;
+        fflush(f);
 
-                if (!dbus_message_append_args(reply, DBUS_TYPE_STRING, &introspection, DBUS_TYPE_INVALID)) {
-                        goto oom;
-                }
-        } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Reload")) {
+        if (ferror(f))
+                return sd_bus_reply_method_errno(bus, message, ENOMEM, NULL);
 
-                SELINUX_ACCESS_CHECK(connection, message, "reload");
+        return sd_bus_reply_method_return(bus, message, "s", dump);
+}
 
-                assert(!m->queued_message);
+static int method_create_snapshot(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_free_ char *path = NULL;
+        Manager *m = userdata;
+        const char *name;
+        int cleanup;
+        Snapshot *s;
+        int r;
 
-                /* Instead of sending the reply back right away, we
-                 * just remember that we need to and then send it
-                 * after the reload is finished. That way the caller
-                 * knows when the reload finished. */
+        assert(bus);
+        assert(message);
+        assert(m);
 
-                m->queued_message = dbus_message_new_method_return(message);
-                if (!m->queued_message)
-                        goto oom;
+        SELINUX_ACCESS_CHECK(bus, message, "start");
 
-                m->queued_message_connection = connection;
-                m->exit_code = MANAGER_RELOAD;
+        r = sd_bus_message_read(message, "sb", &name, &cleanup);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
 
-        } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Reexecute")) {
+        if (isempty(name))
+                name = NULL;
 
-                SELINUX_ACCESS_CHECK(connection, message, "reload");
+        r = snapshot_create(m, name, cleanup, &error, &s);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, &error);
 
-                /* We don't send a reply back here, the client should
-                 * just wait for us disconnecting. */
+        path = unit_dbus_path(UNIT(s));
+        if (!path)
+                return sd_bus_reply_method_errno(bus, message, ENOMEM, NULL);
 
-                m->exit_code = MANAGER_REEXECUTE;
+        return sd_bus_reply_method_return(bus, message, "o", path);
+}
 
-        } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Exit")) {
+static int method_remove_snapshot(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        Manager *m = userdata;
+        const char *name;
+        Unit *u;
+        int r;
 
-                SELINUX_ACCESS_CHECK(connection, message, "halt");
+        assert(bus);
+        assert(message);
+        assert(m);
 
-                if (m->running_as == SYSTEMD_SYSTEM) {
-                        dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Exit is only supported for user service managers.");
-                        return bus_send_error_reply(connection, message, &error, -ENOTSUP);
-                }
+        SELINUX_ACCESS_CHECK(bus, message, "start");
 
-                reply = dbus_message_new_method_return(message);
-                if (!reply)
-                        goto oom;
+        r = sd_bus_message_read(message, "s", &name);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
 
-                m->exit_code = MANAGER_EXIT;
+        u = manager_get_unit(m, name);
+        if (!u)
+                return sd_bus_reply_method_errorf(bus, message, BUS_ERROR_NO_SUCH_UNIT, "Unit %s does not exist.", name);
 
-        } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Reboot")) {
+        if (u->type != UNIT_SNAPSHOT)
+                return sd_bus_reply_method_errorf(bus, message, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not a snapshot", name);
 
-                SELINUX_ACCESS_CHECK(connection, message, "reboot");
+        return bus_snapshot_method_remove(bus, message, u);
+}
 
-                if (m->running_as != SYSTEMD_SYSTEM) {
-                        dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Reboot is only supported for system managers.");
-                        return bus_send_error_reply(connection, message, &error, -ENOTSUP);
-                }
+static int method_reload(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        Manager *m = userdata;
+        int r;
 
-                reply = dbus_message_new_method_return(message);
-                if (!reply)
-                        goto oom;
+        assert(bus);
+        assert(message);
+        assert(m);
 
-                m->exit_code = MANAGER_REBOOT;
+        SELINUX_ACCESS_CHECK(bus, message, "reload");
 
-        } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "PowerOff")) {
+        /* Instead of sending the reply back right away, we just
+         * remember that we need to and then send it after the reload
+         * is finished. That way the caller knows when the reload
+         * finished. */
 
-                SELINUX_ACCESS_CHECK(connection, message, "halt");
+        assert(!m->queued_message);
+        r = sd_bus_message_new_method_return(bus, message, &m->queued_message);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
 
-                if (m->running_as != SYSTEMD_SYSTEM) {
-                        dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Powering off is only supported for system managers.");
-                        return bus_send_error_reply(connection, message, &error, -ENOTSUP);
-                }
+        m->queued_message_bus = sd_bus_ref(bus);
+        m->exit_code = MANAGER_RELOAD;
 
-                reply = dbus_message_new_method_return(message);
-                if (!reply)
-                        goto oom;
+        return 1;
+}
 
-                m->exit_code = MANAGER_POWEROFF;
+static int method_reexecute(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        Manager *m = userdata;
 
-        } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Halt")) {
+        assert(bus);
+        assert(message);
+        assert(m);
 
-                SELINUX_ACCESS_CHECK(connection, message, "halt");
+        SELINUX_ACCESS_CHECK(bus, message, "reload");
 
-                if (m->running_as != SYSTEMD_SYSTEM) {
-                        dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Halting is only supported for system managers.");
-                        return bus_send_error_reply(connection, message, &error, -ENOTSUP);
-                }
+        /* We don't send a reply back here, the client should
+         * just wait for us disconnecting. */
 
-                reply = dbus_message_new_method_return(message);
-                if (!reply)
-                        goto oom;
+        m->exit_code = MANAGER_REEXECUTE;
+        return 1;
+}
 
-                m->exit_code = MANAGER_HALT;
+static int method_exit(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        Manager *m = userdata;
 
-        } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "KExec")) {
+        assert(bus);
+        assert(message);
+        assert(m);
 
-                SELINUX_ACCESS_CHECK(connection, message, "reboot");
+        SELINUX_ACCESS_CHECK(bus, message, "halt");
 
-                if (m->running_as != SYSTEMD_SYSTEM) {
-                        dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "kexec is only supported for system managers.");
-                        return bus_send_error_reply(connection, message, &error, -ENOTSUP);
-                }
+        if (m->running_as == SYSTEMD_SYSTEM)
+                return sd_bus_reply_method_errorf(bus, message, SD_BUS_ERROR_NOT_SUPPORTED, "Exit is only supported for user service managers.");
 
-                reply = dbus_message_new_method_return(message);
-                if (!reply)
-                        goto oom;
+        m->exit_code = MANAGER_EXIT;
 
-                m->exit_code = MANAGER_KEXEC;
+        return sd_bus_reply_method_return(bus, message, NULL);
+}
 
-        } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "SwitchRoot")) {
-                const char *switch_root, *switch_root_init;
-                char *u, *v;
-                bool good;
+static int method_reboot(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        Manager *m = userdata;
 
-                SELINUX_ACCESS_CHECK(connection, message, "reboot");
+        assert(bus);
+        assert(message);
+        assert(m);
 
-                if (!dbus_message_get_args(
-                                    message,
-                                    &error,
-                                    DBUS_TYPE_STRING, &switch_root,
-                                    DBUS_TYPE_STRING, &switch_root_init,
-                                    DBUS_TYPE_INVALID))
-                        return bus_send_error_reply(connection, message, &error, -EINVAL);
+        SELINUX_ACCESS_CHECK(bus, message, "reboot");
 
-                if (path_equal(switch_root, "/") || !path_is_absolute(switch_root))
-                        return bus_send_error_reply(connection, message, NULL, -EINVAL);
+        if (m->running_as != SYSTEMD_SYSTEM)
+                return sd_bus_reply_method_errorf(bus, message, SD_BUS_ERROR_NOT_SUPPORTED, "Reboot is only supported for system managers.");
 
-                if (!isempty(switch_root_init) && !path_is_absolute(switch_root_init))
-                        return bus_send_error_reply(connection, message, NULL, -EINVAL);
+        m->exit_code = MANAGER_REBOOT;
 
-                if (m->running_as != SYSTEMD_SYSTEM) {
-                        dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Switching root is only supported for system managers.");
-                        return bus_send_error_reply(connection, message, &error, -ENOTSUP);
-                }
+        return sd_bus_reply_method_return(bus, message, NULL);
+}
 
-                /* Safety check */
-                if (isempty(switch_root_init)) {
-                        good = path_is_os_tree(switch_root);
-                        if (!good)
-                                log_error("Not switching root: %s does not seem to be an OS tree. /etc/os-release is missing.", switch_root);
-                }
-                else {
-                        _cleanup_free_ char *p = NULL;
 
-                        p = strjoin(switch_root, "/", switch_root_init, NULL);
-                        if (!p)
-                                goto oom;
+static int method_poweroff(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        Manager *m = userdata;
 
-                        good = access(p, X_OK) >= 0;
-                        if (!good)
-                                log_error("Not switching root: cannot execute new init %s", p);
-                }
-                if (!good)
-                        return bus_send_error_reply(connection, message, NULL, -EINVAL);
-
-                u = strdup(switch_root);
-                if (!u)
-                        goto oom;
-
-                if (!isempty(switch_root_init)) {
-                        v = strdup(switch_root_init);
-                        if (!v) {
-                                free(u);
-                                goto oom;
-                        }
-                } else
-                        v = NULL;
-
-                free(m->switch_root);
-                free(m->switch_root_init);
-                m->switch_root = u;
-                m->switch_root_init = v;
-
-                reply = dbus_message_new_method_return(message);
-                if (!reply)
-                        goto oom;
-
-                m->exit_code = MANAGER_SWITCH_ROOT;
-
-        } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "SetEnvironment")) {
-                _cleanup_strv_free_ char **l = NULL;
-                char **e = NULL;
-
-                SELINUX_ACCESS_CHECK(connection, message, "reload");
-
-                r = bus_parse_strv(message, &l);
-                if (r == -ENOMEM)
-                        goto oom;
-                if (r < 0)
-                        return bus_send_error_reply(connection, message, NULL, r);
-                if (!strv_env_is_valid(l))
-                        return bus_send_error_reply(connection, message, NULL, -EINVAL);
-
-                e = strv_env_merge(2, m->environment, l);
-                if (!e)
-                        goto oom;
-
-                reply = dbus_message_new_method_return(message);
-                if (!reply) {
-                        strv_free(e);
-                        goto oom;
-                }
+        assert(bus);
+        assert(message);
+        assert(m);
 
-                strv_free(m->environment);
-                m->environment = e;
+        SELINUX_ACCESS_CHECK(bus, message, "halt");
 
-        } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "UnsetEnvironment")) {
-                _cleanup_strv_free_ char **l = NULL;
-                char **e = NULL;
+        if (m->running_as != SYSTEMD_SYSTEM)
+                return sd_bus_reply_method_errorf(bus, message, SD_BUS_ERROR_NOT_SUPPORTED, "Powering off is only supported for system managers.");
 
-                SELINUX_ACCESS_CHECK(connection, message, "reload");
+        m->exit_code = MANAGER_POWEROFF;
 
-                r = bus_parse_strv(message, &l);
-                if (r == -ENOMEM)
-                        goto oom;
-                if (r < 0)
-                        return bus_send_error_reply(connection, message, NULL, r);
-                if (!strv_env_name_or_assignment_is_valid(l))
-                        return bus_send_error_reply(connection, message, NULL, -EINVAL);
-
-                e = strv_env_delete(m->environment, 1, l);
-                if (!e)
-                        goto oom;
-
-                reply = dbus_message_new_method_return(message);
-                if (!reply) {
-                        strv_free(e);
-                        goto oom;
-                }
+        return sd_bus_reply_method_return(bus, message, NULL);
+}
 
-                strv_free(m->environment);
-                m->environment = e;
+static int method_halt(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        Manager *m = userdata;
 
-        } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "UnsetAndSetEnvironment")) {
-                _cleanup_strv_free_ char **l_set = NULL, **l_unset = NULL, **e = NULL;
-                char **f = NULL;
-                DBusMessageIter iter;
+        assert(bus);
+        assert(message);
+        assert(m);
 
-                SELINUX_ACCESS_CHECK(connection, message, "reload");
+        SELINUX_ACCESS_CHECK(bus, message, "halt");
 
-                if (!dbus_message_iter_init(message, &iter))
-                        goto oom;
+        if (m->running_as != SYSTEMD_SYSTEM)
+                return sd_bus_reply_method_errorf(bus, message, SD_BUS_ERROR_NOT_SUPPORTED, "Halt is only supported for system managers.");
 
-                r = bus_parse_strv_iter(&iter, &l_unset);
-                if (r == -ENOMEM)
-                        goto oom;
-                if (r < 0)
-                        return bus_send_error_reply(connection, message, NULL, r);
-                if (!strv_env_name_or_assignment_is_valid(l_unset))
-                        return bus_send_error_reply(connection, message, NULL, -EINVAL);
+        m->exit_code = MANAGER_HALT;
 
-                if (!dbus_message_iter_next(&iter))
-                        return bus_send_error_reply(connection, message, NULL, -EINVAL);
+        return sd_bus_reply_method_return(bus, message, NULL);
+}
 
-                r = bus_parse_strv_iter(&iter, &l_set);
-                if (r == -ENOMEM)
-                        goto oom;
-                if (r < 0)
-                        return bus_send_error_reply(connection, message, NULL, r);
-                if (!strv_env_is_valid(l_set))
-                        return bus_send_error_reply(connection, message, NULL, -EINVAL);
-
-                e = strv_env_delete(m->environment, 1, l_unset);
-                if (!e)
-                        goto oom;
-
-                f = strv_env_merge(2, e, l_set);
-                if (!f)
-                        goto oom;
-
-                reply = dbus_message_new_method_return(message);
-                if (!reply) {
-                        strv_free(f);
-                        goto oom;
-                }
+static int method_kexec(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        Manager *m = userdata;
 
-                strv_free(m->environment);
-                m->environment = f;
-        } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ListUnitFiles")) {
-                DBusMessageIter iter, sub, sub2;
-                Hashmap *h;
-                Iterator i;
-                UnitFileList *item;
+        assert(bus);
+        assert(message);
+        assert(m);
 
-                SELINUX_ACCESS_CHECK(connection, message, "status");
+        SELINUX_ACCESS_CHECK(bus, message, "reboot");
 
-                reply = dbus_message_new_method_return(message);
-                if (!reply)
-                        goto oom;
+        if (m->running_as != SYSTEMD_SYSTEM)
+                return sd_bus_reply_method_errorf(bus, message, SD_BUS_ERROR_NOT_SUPPORTED, "KExec is only supported for system managers.");
 
-                h = hashmap_new(string_hash_func, string_compare_func);
-                if (!h)
-                        goto oom;
+        m->exit_code = MANAGER_KEXEC;
 
-                r = unit_file_get_list(m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER, NULL, h);
-                if (r < 0) {
-                        unit_file_list_free(h);
-                        return bus_send_error_reply(connection, message, NULL, r);
-                }
+        return sd_bus_reply_method_return(bus, message, NULL);
+}
 
-                dbus_message_iter_init_append(reply, &iter);
+static int method_switch_root(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        char *ri = NULL, *rt = NULL;
+        const char *root, *init;
+        Manager *m = userdata;
+        int r;
 
-                if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(ss)", &sub)) {
-                        unit_file_list_free(h);
-                        goto oom;
-                }
+        assert(bus);
+        assert(message);
+        assert(m);
 
-                HASHMAP_FOREACH(item, h, i) {
-                        const char *state;
+        SELINUX_ACCESS_CHECK(bus, message, "reboot");
 
-                        state = unit_file_state_to_string(item->state);
-                        assert(state);
+        if (m->running_as != SYSTEMD_SYSTEM)
+                return sd_bus_reply_method_errorf(bus, message, SD_BUS_ERROR_NOT_SUPPORTED, "KExec is only supported for system managers.");
 
-                        if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
-                            !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &item->path) ||
-                            !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &state) ||
-                            !dbus_message_iter_close_container(&sub, &sub2)) {
-                                unit_file_list_free(h);
-                                goto oom;
-                        }
-                }
+        r = sd_bus_message_read(message, "ss", &root, &init);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
 
-                unit_file_list_free(h);
-
-                if (!dbus_message_iter_close_container(&iter, &sub))
-                        goto oom;
-
-        } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetUnitFileState")) {
-                const char *name;
-                UnitFileState state;
-                const char *s;
-
-                SELINUX_ACCESS_CHECK(connection, message, "status");
-
-                if (!dbus_message_get_args(
-                                    message,
-                                    &error,
-                                    DBUS_TYPE_STRING, &name,
-                                    DBUS_TYPE_INVALID))
-                        return bus_send_error_reply(connection, message, &error, -EINVAL);
-
-                state = unit_file_get_state(m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER, NULL, name);
-                if (state < 0)
-                        return bus_send_error_reply(connection, message, NULL, state);
-
-                s = unit_file_state_to_string(state);
-                assert(s);
-
-                reply = dbus_message_new_method_return(message);
-                if (!reply)
-                        goto oom;
-
-                if (!dbus_message_append_args(
-                                    reply,
-                                    DBUS_TYPE_STRING, &s,
-                                    DBUS_TYPE_INVALID))
-                        goto oom;
-        } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "EnableUnitFiles") ||
-                   dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ReenableUnitFiles") ||
-                   dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "LinkUnitFiles") ||
-                   dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "PresetUnitFiles") ||
-                   dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "MaskUnitFiles") ||
-                   dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "SetDefaultTarget")) {
-
-                char **l = NULL;
-                DBusMessageIter iter;
-                UnitFileScope scope = m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
-                UnitFileChange *changes = NULL;
-                unsigned n_changes = 0;
-                dbus_bool_t runtime, force;
-                int carries_install_info = -1;
-
-                SELINUX_ACCESS_CHECK(connection, message, streq(member, "MaskUnitFiles") ? "disable" : "enable");
-
-                if (!dbus_message_iter_init(message, &iter))
-                        goto oom;
-
-                r = bus_parse_strv_iter(&iter, &l);
-                if (r < 0) {
-                        if (r == -ENOMEM)
-                                goto oom;
+        if (path_equal(root, "/") || !path_is_absolute(root))
+                return sd_bus_reply_method_errorf(bus, message, SD_BUS_ERROR_INVALID_ARGS, "Invalid switch root path %s", root);
 
-                        return bus_send_error_reply(connection, message, NULL, r);
-                }
+        /* Safety check */
+        if (isempty(init)) {
+                if (! path_is_os_tree(root))
+                        return sd_bus_reply_method_errorf(bus, message, SD_BUS_ERROR_INVALID_ARGS, "Specified switch root path %s does not seem to be an OS tree. /etc/os-release is missing.", root);
+        } else {
+                _cleanup_free_ char *p = NULL;
 
-                if (!dbus_message_iter_next(&iter) ||
-                    bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &runtime, true) < 0 ||
-                    bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &force, false) < 0) {
-                        strv_free(l);
-                        return bus_send_error_reply(connection, message, NULL, -EIO);
-                }
+                if (!path_is_absolute(init))
+                        return sd_bus_reply_method_errorf(bus, message, SD_BUS_ERROR_INVALID_ARGS, "Invalid init path %s", init);
 
-                if (streq(member, "EnableUnitFiles")) {
-                        r = unit_file_enable(scope, runtime, NULL, l, force, &changes, &n_changes);
-                        carries_install_info = r;
-                } else if (streq(member, "ReenableUnitFiles")) {
-                        r = unit_file_reenable(scope, runtime, NULL, l, force, &changes, &n_changes);
-                        carries_install_info = r;
-                } else if (streq(member, "LinkUnitFiles"))
-                        r = unit_file_link(scope, runtime, NULL, l, force, &changes, &n_changes);
-                else if (streq(member, "PresetUnitFiles")) {
-                        r = unit_file_preset(scope, runtime, NULL, l, force, &changes, &n_changes);
-                        carries_install_info = r;
-                } else if (streq(member, "MaskUnitFiles"))
-                        r = unit_file_mask(scope, runtime, NULL, l, force, &changes, &n_changes);
-                else if (streq(member, "SetDefaultTarget"))
-                        r = unit_file_set_default(scope, NULL, l[0], &changes, &n_changes);
-                else
-                        assert_not_reached("Uh? Wrong method");
-
-                strv_free(l);
-                bus_manager_send_unit_files_changed(m);
+                p = strappend(root, init);
+                if (!p)
+                        return sd_bus_reply_method_errno(bus, message, ENOMEM, NULL);
 
-                if (r < 0) {
-                        unit_file_changes_free(changes, n_changes);
-                        return bus_send_error_reply(connection, message, NULL, r);
+                if (access(p, X_OK) < 0)
+                        return sd_bus_reply_method_errorf(bus, message, SD_BUS_ERROR_INVALID_ARGS, "Specified init binary %s does not exist.", p);
+        }
+
+        rt = strdup(root);
+        if (!rt)
+                return sd_bus_reply_method_errno(bus, message, ENOMEM, NULL);
+
+        if (!isempty(init)) {
+                ri = strdup(init);
+                if (!ri) {
+                        free(ri);
+                        return sd_bus_reply_method_errno(bus, message, ENOMEM, NULL);
                 }
+        }
 
-                reply = message_from_file_changes(message, changes, n_changes, carries_install_info);
-                unit_file_changes_free(changes, n_changes);
+        free(m->switch_root);
+        m->switch_root = rt;
 
-                if (!reply)
-                        goto oom;
+        free(m->switch_root_init);
+        m->switch_root_init = ri;
 
-        } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "DisableUnitFiles") ||
-                   dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "UnmaskUnitFiles")) {
+        return sd_bus_reply_method_return(bus, message, NULL);
+}
 
-                char **l = NULL;
-                DBusMessageIter iter;
-                UnitFileScope scope = m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
-                UnitFileChange *changes = NULL;
-                unsigned n_changes = 0;
-                dbus_bool_t runtime;
+static int method_set_environment(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        _cleanup_strv_free_ char **plus = NULL;
+        Manager *m = userdata;
+        int r;
 
-                SELINUX_ACCESS_CHECK(connection, message, streq(member, "UnmaskUnitFiles") ? "enable" : "disable");
+        assert(bus);
+        assert(message);
+        assert(m);
 
-                if (!dbus_message_iter_init(message, &iter))
-                        goto oom;
+        SELINUX_ACCESS_CHECK(bus, message, "reload");
 
-                r = bus_parse_strv_iter(&iter, &l);
-                if (r < 0) {
-                        if (r == -ENOMEM)
-                                goto oom;
+        r = sd_bus_message_read_strv(message, &plus);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
+        if (!strv_env_is_valid(plus))
+                return sd_bus_reply_method_errorf(bus, message, SD_BUS_ERROR_INVALID_ARGS, "Invalid environment assignments");
 
-                        return bus_send_error_reply(connection, message, NULL, r);
-                }
+        r = manager_environment_add(m, NULL, plus);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
 
-                if (!dbus_message_iter_next(&iter) ||
-                    bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &runtime, false) < 0) {
-                        strv_free(l);
-                        return bus_send_error_reply(connection, message, NULL, -EIO);
-                }
+        return sd_bus_reply_method_return(bus, message, NULL);
+}
+
+static int method_unset_environment(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        _cleanup_strv_free_ char **minus = NULL;
+        Manager *m = userdata;
+        int r;
+
+        assert(bus);
+        assert(message);
+        assert(m);
+
+        SELINUX_ACCESS_CHECK(bus, message, "reload");
 
-                if (streq(member, "DisableUnitFiles"))
-                        r = unit_file_disable(scope, runtime, NULL, l, &changes, &n_changes);
-                else if (streq(member, "UnmaskUnitFiles"))
-                        r = unit_file_unmask(scope, runtime, NULL, l, &changes, &n_changes);
-                else
-                        assert_not_reached("Uh? Wrong method");
+        r = sd_bus_message_read_strv(message, &minus);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
+
+        if (!strv_env_name_or_assignment_is_valid(minus))
+                return sd_bus_reply_method_errorf(bus, message, SD_BUS_ERROR_INVALID_ARGS, "Invalid environment variable names or assignments");
+
+        r = manager_environment_add(m, minus, NULL);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
+
+        return sd_bus_reply_method_return(bus, message, NULL);
+}
+
+static int method_unset_and_set_environment(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        _cleanup_strv_free_ char **minus = NULL, **plus = NULL;
+        Manager *m = userdata;
+        int r;
+
+        assert(bus);
+        assert(message);
+        assert(m);
+
+        SELINUX_ACCESS_CHECK(bus, message, "reload");
+
+        r = sd_bus_message_read_strv(message, &plus);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
+
+        r = sd_bus_message_read_strv(message, &minus);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
+
+        if (!strv_env_is_valid(plus))
+                return sd_bus_reply_method_errorf(bus, message, SD_BUS_ERROR_INVALID_ARGS, "Invalid environment assignments");
+        if (!strv_env_name_or_assignment_is_valid(minus))
+                return sd_bus_reply_method_errorf(bus, message, SD_BUS_ERROR_INVALID_ARGS, "Invalid environment variable names or assignments");
+
+        r = manager_environment_add(m, minus, plus);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
+
+        return sd_bus_reply_method_return(bus, message, NULL);
+}
+
+static int method_list_unit_files(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+        Manager *m = userdata;
+        UnitFileList *item;
+        Hashmap *h;
+        Iterator i;
+        int r;
+
+        assert(bus);
+        assert(message);
+        assert(m);
+
+        SELINUX_ACCESS_CHECK(bus, message, "status");
+
+        r = sd_bus_message_new_method_return(bus, message, &reply);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
 
-                strv_free(l);
-                bus_manager_send_unit_files_changed(m);
+        h = hashmap_new(string_hash_func, string_compare_func);
+        if (!h)
+                return sd_bus_reply_method_errno(bus, message, ENOMEM, NULL);
 
+        r = unit_file_get_list(m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER, NULL, h);
+        if (r < 0) {
+                r = sd_bus_reply_method_errno(bus, message, r, NULL);
+                goto fail;
+        }
+
+        r = sd_bus_message_open_container(reply, 'a', "(ss)");
+        if (r < 0) {
+                r = sd_bus_reply_method_errno(bus, message, r, NULL);
+                goto fail;
+        }
+
+        HASHMAP_FOREACH(item, h, i) {
+
+                r = sd_bus_message_append(reply, "(ss)", item->path, unit_file_state_to_string(item->state));
                 if (r < 0) {
-                        unit_file_changes_free(changes, n_changes);
-                        return bus_send_error_reply(connection, message, NULL, r);
+                        r = sd_bus_reply_method_errno(bus, message, r, NULL);
+                        goto fail;
                 }
+        }
 
-                reply = message_from_file_changes(message, changes, n_changes, -1);
-                unit_file_changes_free(changes, n_changes);
+        unit_file_list_free(h);
 
-                if (!reply)
-                        goto oom;
+        r = sd_bus_message_close_container(reply);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
 
-        } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetDefaultTarget")) {
-                UnitFileScope scope = m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
-                _cleanup_free_ char *default_target = NULL;
+        return sd_bus_send(bus, reply, NULL);
 
-                reply = dbus_message_new_method_return(message);
-                if (!reply)
-                        goto oom;
+fail:
+        unit_file_list_free(h);
+        return r;
+}
 
-                r = unit_file_get_default(scope, NULL, &default_target);
-                if (r < 0)
-                        return bus_send_error_reply(connection, message, NULL, r);
+static int method_get_unit_file_state(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        Manager *m = userdata;
+        const char *name;
+        UnitFileState state;
+        UnitFileScope scope;
+        int r;
 
-                if (!dbus_message_append_args(reply, DBUS_TYPE_STRING, &default_target, DBUS_TYPE_INVALID)) {
-                        goto oom;
-                }
+        assert(bus);
+        assert(message);
+        assert(m);
 
-        } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "SetUnitProperties")) {
-                DBusMessageIter iter;
-                dbus_bool_t runtime;
-                const char *name;
-                Unit *u;
+        SELINUX_ACCESS_CHECK(bus, message, "status");
 
-                if (!dbus_message_iter_init(message, &iter))
-                        goto oom;
+        r = sd_bus_message_read(message, "s", &name);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
 
-                if (bus_iter_get_basic_and_next(&iter, DBUS_TYPE_STRING, &name, true) < 0 ||
-                    bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &runtime, true) < 0)
-                        return bus_send_error_reply(connection, message, NULL, -EINVAL);
+        scope = m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
 
-                u = manager_get_unit(m, name);
-                if (!u) {
-                        dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
-                        return bus_send_error_reply(connection, message, &error, -ENOENT);
-                }
+        state = unit_file_get_state(scope, NULL, name);
+        if (state < 0)
+                return sd_bus_reply_method_errno(bus, message, state, NULL);
 
-                SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "start");
+        return sd_bus_reply_method_return(bus, message, "s", unit_file_state_to_string(state));
+}
 
-                r = bus_unit_set_properties(u, &iter, runtime ? UNIT_RUNTIME : UNIT_PERSISTENT, true, &error);
-                if (r < 0)
-                        return bus_send_error_reply(connection, message, &error, r);
-
-                reply = dbus_message_new_method_return(message);
-                if (!reply)
-                        goto oom;
-
-        } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "StartTransientUnit")) {
-                const char *name, *smode;
-                DBusMessageIter iter;
-                JobMode mode;
-                UnitType t;
-                Unit *u;
-
-                if (!dbus_message_iter_init(message, &iter))
-                        goto oom;
-
-                if (bus_iter_get_basic_and_next(&iter, DBUS_TYPE_STRING, &name, true) < 0 ||
-                    bus_iter_get_basic_and_next(&iter, DBUS_TYPE_STRING, &smode, true) < 0)
-                        return bus_send_error_reply(connection, message, NULL, -EINVAL);
-
-                t = unit_name_to_type(name);
-                if (t < 0)
-                        return bus_send_error_reply(connection, message, NULL, -EINVAL);
-                if (!unit_vtable[t]->can_transient) {
-                        dbus_set_error(&error, DBUS_ERROR_INVALID_ARGS, "Unit type %s does not support transient units.", unit_type_to_string(t));
-                        return bus_send_error_reply(connection, message, &error, -EINVAL);
-                }
+static int method_get_default_target(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        _cleanup_free_ char *default_target = NULL;
+        Manager *m = userdata;
+        UnitFileScope scope;
+        int r;
 
-                mode = job_mode_from_string(smode);
-                if (mode < 0) {
-                        dbus_set_error(&error, BUS_ERROR_INVALID_JOB_MODE, "Job mode %s is invalid.", smode);
-                        return bus_send_error_reply(connection, message, &error, -EINVAL);
-                }
+        assert(bus);
+        assert(message);
+        assert(m);
 
-                r = manager_load_unit(m, name, NULL, NULL, &u);
-                if (r < 0)
-                        return bus_send_error_reply(connection, message, &error, r);
+        SELINUX_ACCESS_CHECK(bus, message, "status");
 
-                SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "start");
+        scope = m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
 
-                if (u->load_state != UNIT_NOT_FOUND || set_size(u->dependencies[UNIT_REFERENCED_BY]) > 0) {
-                        dbus_set_error(&error, BUS_ERROR_UNIT_EXISTS, "Unit %s already exists.", name);
-                        return bus_send_error_reply(connection, message, &error, -EEXIST);
-                }
+        r = unit_file_get_default(scope, NULL, &default_target);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
 
-                /* OK, the unit failed to load and is unreferenced,
-                 * now let's fill in the transient data instead */
-                r = unit_make_transient(u);
-                if (r < 0)
-                        return bus_send_error_reply(connection, message, &error, r);
+        return sd_bus_reply_method_return(bus, message, "s", default_target);
+}
 
-                /* Set our properties */
-                r = bus_unit_set_properties(u, &iter, UNIT_RUNTIME, false, &error);
+static int send_unit_files_changed(sd_bus *bus, const char *destination, void *userdata) {
+        _cleanup_bus_message_unref_ sd_bus_message *message = NULL;
+        int r;
+
+        assert(bus);
+
+        r = sd_bus_message_new_signal(bus, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "UnitFilesChanged", &message);
+        if (r < 0)
+                return r;
+
+        return sd_bus_send_to(bus, message, destination, NULL);
+}
+
+static int reply_unit_file_changes_and_free(
+                Manager *m,
+                sd_bus *bus,
+                sd_bus_message *message,
+                int carries_install_info,
+                UnitFileChange *changes,
+                unsigned n_changes) {
+
+        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+        unsigned i;
+        int r;
+
+        if (n_changes > 0)
+                bus_manager_foreach_client(m, send_unit_files_changed, NULL);
+
+        r = sd_bus_message_new_method_return(bus, message, &reply);
+        if (r < 0)
+                goto fail;
+
+        if (carries_install_info >= 0) {
+                r = sd_bus_message_append(reply, "b", carries_install_info);
                 if (r < 0)
-                        return bus_send_error_reply(connection, message, &error, r);
+                        goto fail;
+        }
+
+        r = sd_bus_message_open_container(reply, 'a', "(sss)");
+        if (r < 0)
+                goto fail;
 
-                /* And load this stub fully */
-                r = unit_load(u);
+        for (i = 0; i < n_changes; i++) {
+                r = sd_bus_message_append(
+                                message, "(sss)",
+                                unit_file_change_type_to_string(changes[i].type),
+                                changes[i].path,
+                                changes[i].source);
                 if (r < 0)
-                        return bus_send_error_reply(connection, message, &error, r);
+                        goto fail;
+        }
 
-                manager_dispatch_load_queue(m);
+        r = sd_bus_message_close_container(reply);
+        if (r < 0)
+                goto fail;
 
-                /* Finally, start it */
-                return bus_unit_queue_job(connection, message, u, JOB_START, mode, false);
+        return sd_bus_send(bus, message, NULL);
 
-        } else {
-                const BusBoundProperties bps[] = {
-                        { "org.freedesktop.systemd1.Manager", bus_systemd_properties, systemd_property_string },
-                        { "org.freedesktop.systemd1.Manager", bus_manager_properties, m },
-                        { NULL, }
-                };
+fail:
+        unit_file_changes_free(changes, n_changes);
+        return sd_bus_reply_method_errno(bus, message, r, NULL);
+}
 
-                SELINUX_ACCESS_CHECK(connection, message, "status");
+static int method_enable_unit_files_generic(
+                sd_bus *bus,
+                sd_bus_message *message,
+                Manager *m, const
+                char *verb,
+                int (*call)(UnitFileScope scope, bool runtime, const char *root_dir, char *files[], bool force, UnitFileChange **changes, unsigned *n_changes),
+                bool carries_install_info) {
+
+        _cleanup_strv_free_ char **l = NULL;
+        UnitFileChange *changes = NULL;
+        unsigned n_changes = 0;
+        UnitFileScope scope;
+        int runtime, force, r;
+
+        assert(bus);
+        assert(message);
+        assert(m);
 
-                return bus_default_message_handler(connection, message, NULL, INTERFACES_LIST, bps);
-        }
+        SELINUX_ACCESS_CHECK(bus, message, verb);
 
-        if (job_type != _JOB_TYPE_INVALID) {
-                const char *name, *smode, *old_name = NULL;
-                JobMode mode;
-                Unit *u;
-                dbus_bool_t b;
-
-                if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "StartUnitReplace"))
-                        b = dbus_message_get_args(
-                                        message,
-                                        &error,
-                                        DBUS_TYPE_STRING, &old_name,
-                                        DBUS_TYPE_STRING, &name,
-                                        DBUS_TYPE_STRING, &smode,
-                                        DBUS_TYPE_INVALID);
-                else
-                        b = dbus_message_get_args(
-                                        message,
-                                        &error,
-                                        DBUS_TYPE_STRING, &name,
-                                        DBUS_TYPE_STRING, &smode,
-                                        DBUS_TYPE_INVALID);
-                if (!b)
-                        return bus_send_error_reply(connection, message, &error, -EINVAL);
-
-                if (old_name) {
-                        u = manager_get_unit(m, old_name);
-                        if (!u || !u->job || u->job->type != JOB_START) {
-                                dbus_set_error(&error, BUS_ERROR_NO_SUCH_JOB, "No job queued for unit %s", old_name);
-                                return bus_send_error_reply(connection, message, &error, -ENOENT);
-                        }
-                }
+        r = sd_bus_message_read_strv(message, &l);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
 
-                mode = job_mode_from_string(smode);
-                if (mode < 0) {
-                        dbus_set_error(&error, BUS_ERROR_INVALID_JOB_MODE, "Job mode %s is invalid.", smode);
-                        return bus_send_error_reply(connection, message, &error, -EINVAL);
-                }
+        r = sd_bus_message_read(message, "bb", &runtime, &force);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
 
-                r = manager_load_unit(m, name, NULL, &error, &u);
-                if (r < 0)
-                        return bus_send_error_reply(connection, message, &error, r);
+        scope = m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
 
-                return bus_unit_queue_job(connection, message, u, job_type, mode, reload_if_possible);
-        }
+        r = call(scope, runtime, NULL, l, force, &changes, &n_changes);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
+
+        return reply_unit_file_changes_and_free(m, bus, message, carries_install_info ? r : -1, changes, n_changes);
+}
 
-        if (reply)
-                if (!bus_maybe_send_reply(connection, message, reply))
-                        goto oom;
+static int method_enable_unit_files(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        return method_enable_unit_files_generic(bus, message, userdata, "enable", unit_file_enable, true);
+}
 
-        return DBUS_HANDLER_RESULT_HANDLED;
+static int method_reenable_unit_files(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        return method_enable_unit_files_generic(bus, message, userdata, "enable", unit_file_reenable, true);
+}
+
+static int method_link_unit_files(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        return method_enable_unit_files_generic(bus, message, userdata, "enable", unit_file_link, false);
+}
+
+static int method_preset_unit_files(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        return method_enable_unit_files_generic(bus, message, userdata, "enable", unit_file_preset, true);
+}
+
+static int method_mask_unit_files(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        return method_enable_unit_files_generic(bus, message, userdata, "disable", unit_file_mask, false);
+}
 
-oom:
-        dbus_error_free(&error);
+static int method_disable_unit_files_generic(
+                sd_bus *bus,
+                sd_bus_message *message,
+                Manager *m, const
+                char *verb,
+                int (*call)(UnitFileScope scope, bool runtime, const char *root_dir, char *files[], UnitFileChange **changes, unsigned *n_changes)) {
+
+        _cleanup_strv_free_ char **l = NULL;
+        UnitFileChange *changes = NULL;
+        unsigned n_changes = 0;
+        UnitFileScope scope;
+        int r, runtime;
+
+        assert(bus);
+        assert(message);
+        assert(m);
+
+        SELINUX_ACCESS_CHECK(bus, message, verb);
+
+        r = sd_bus_message_read_strv(message, &l);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
+
+        r = sd_bus_message_read(message, "b", &runtime);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
+
+        scope = m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
+
+        r = call(scope, runtime, NULL, l, &changes, &n_changes);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
+
+        return reply_unit_file_changes_and_free(m, bus, message, -1, changes, n_changes);
+}
 
-        return DBUS_HANDLER_RESULT_NEED_MEMORY;
+static int method_disable_unit_files(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        return method_disable_unit_files_generic(bus, message, userdata, "disable", unit_file_disable);
 }
 
-const DBusObjectPathVTable bus_manager_vtable = {
-        .message_function = bus_manager_message_handler
+static int method_unmask_unit_files(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        return method_disable_unit_files_generic(bus, message, userdata, "enable", unit_file_unmask);
+}
+
+static int method_set_default_target(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        UnitFileChange *changes = NULL;
+        unsigned n_changes = 0;
+        Manager *m = userdata;
+        UnitFileScope scope;
+        const char *name;
+        int force, r;
+
+        assert(bus);
+        assert(message);
+        assert(m);
+
+        SELINUX_ACCESS_CHECK(bus, message, "enable");
+
+        r = sd_bus_message_read(message, "sb", &name, &force);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
+
+        scope = m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
+
+        r = unit_file_set_default(scope, NULL, name, force, &changes, &n_changes);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
+
+        return reply_unit_file_changes_and_free(m, bus, message, -1, changes, n_changes);
+}
+
+const sd_bus_vtable bus_manager_vtable[] = {
+        SD_BUS_VTABLE_START(0),
+
+        SD_BUS_PROPERTY("Version", "s", property_get_version, 0, 0),
+        SD_BUS_PROPERTY("Features", "s", property_get_features, 0, 0),
+        SD_BUS_PROPERTY("Virtualization", "s", property_get_virtualization, 0, 0),
+        SD_BUS_PROPERTY("Tainted", "s", property_get_tainted, 0, 0),
+        BUS_PROPERTY_DUAL_TIMESTAMP("FirmwareTimestamp", offsetof(Manager, firmware_timestamp), 0),
+        BUS_PROPERTY_DUAL_TIMESTAMP("LoaderTimestamp", offsetof(Manager, loader_timestamp), 0),
+        BUS_PROPERTY_DUAL_TIMESTAMP("KernelTimestamp", offsetof(Manager, firmware_timestamp), 0),
+        BUS_PROPERTY_DUAL_TIMESTAMP("InitRDTimestamp", offsetof(Manager, initrd_timestamp), 0),
+        BUS_PROPERTY_DUAL_TIMESTAMP("UserspaceTimestamp", offsetof(Manager, userspace_timestamp), 0),
+        BUS_PROPERTY_DUAL_TIMESTAMP("FinishTimestamp", offsetof(Manager, finish_timestamp), 0),
+        BUS_PROPERTY_DUAL_TIMESTAMP("SecurityStartTimestamp", offsetof(Manager, security_start_timestamp), 0),
+        BUS_PROPERTY_DUAL_TIMESTAMP("SecurityFinishTimestamp", offsetof(Manager, security_finish_timestamp), 0),
+        BUS_PROPERTY_DUAL_TIMESTAMP("GeneratorsStartTimestamp", offsetof(Manager, generators_start_timestamp), 0),
+        BUS_PROPERTY_DUAL_TIMESTAMP("GeneratorsFinishTimestamp", offsetof(Manager, generators_finish_timestamp), 0),
+        BUS_PROPERTY_DUAL_TIMESTAMP("UnitsLoadStartTimestamp", offsetof(Manager, units_load_start_timestamp), 0),
+        BUS_PROPERTY_DUAL_TIMESTAMP("UnitsLoadFinishTimestamp", offsetof(Manager, units_load_finish_timestamp), 0),
+        SD_BUS_WRITABLE_PROPERTY("LogLevel", "s", property_get_log_level, property_set_log_level, 0, 0),
+        SD_BUS_WRITABLE_PROPERTY("LogTarget", "s", property_get_log_target, property_set_log_target, 0, 0),
+        SD_BUS_PROPERTY("NNames", "u", property_get_n_names, 0, 0),
+        SD_BUS_PROPERTY("NJobs", "u", property_get_n_jobs, 0, 0),
+        SD_BUS_PROPERTY("NInstalledJobs", "u", bus_property_get_unsigned, offsetof(Manager, n_installed_jobs), 0),
+        SD_BUS_PROPERTY("NFailedJobs", "u", bus_property_get_unsigned, offsetof(Manager, n_failed_jobs), 0),
+        SD_BUS_PROPERTY("Progress", "d", property_get_progress, 0, 0),
+        SD_BUS_PROPERTY("Environment", "as", NULL, offsetof(Manager, environment), 0),
+        SD_BUS_PROPERTY("ConfirmSpawn", "b", bus_property_get_bool, offsetof(Manager, confirm_spawn), 0),
+        SD_BUS_PROPERTY("ShowStatus", "b", bus_property_get_bool, offsetof(Manager, show_status), 0),
+        SD_BUS_PROPERTY("UnitPath", "as", NULL, offsetof(Manager, lookup_paths.unit_path), 0),
+        SD_BUS_PROPERTY("DefaultStandardOutput", "s", bus_property_get_exec_output, offsetof(Manager, default_std_output), 0),
+        SD_BUS_PROPERTY("DefaultStandardError", "s", bus_property_get_exec_output, offsetof(Manager, default_std_output), 0),
+        SD_BUS_WRITABLE_PROPERTY("RuntimeWatchdogUSec", "t", bus_property_get_usec, property_set_runtime_watchdog, offsetof(Manager, runtime_watchdog), 0),
+        SD_BUS_WRITABLE_PROPERTY("ShutdownWatchdogUSec", "t", bus_property_get_usec, bus_property_set_usec, offsetof(Manager, shutdown_watchdog), 0),
+
+        SD_BUS_METHOD("GetUnit", "s", "o", method_get_unit, 0),
+        SD_BUS_METHOD("GetUnitByPID", "u", "o", method_get_unit_by_pid, 0),
+        SD_BUS_METHOD("LoadUnit", "s", "o", method_load_unit, 0),
+        SD_BUS_METHOD("StartUnit", "ss", "o", method_start_unit, 0),
+        SD_BUS_METHOD("StartUnitReplace", "sss", "o", method_start_unit_replace, 0),
+        SD_BUS_METHOD("StopUnit", "ss", "o", method_stop_unit, 0),
+        SD_BUS_METHOD("ReloadUnit", "ss", "o", method_reload_unit, 0),
+        SD_BUS_METHOD("RestartUnit", "ss", "o", method_restart_unit, 0),
+        SD_BUS_METHOD("TryRestartUnit", "ss", "o", method_try_restart_unit, 0),
+        SD_BUS_METHOD("ReloadOrRestartUnit", "ss", "o", method_reload_or_restart_unit, 0),
+        SD_BUS_METHOD("ReloadOrTryRestartUnit", "ss", "o", method_reload_or_try_restart_unit, 0),
+        SD_BUS_METHOD("KillUnit", "ssi", NULL, method_kill_unit, 0),
+        SD_BUS_METHOD("ResetFailedUnit", "s", NULL, method_reset_failed_unit, 0),
+        SD_BUS_METHOD("SetUnitProperties", "sb", "a(sv)", method_set_unit_properties, 0),
+        SD_BUS_METHOD("StartTransientUnit", "ssa(sv)a(sa(sv))", "o", method_start_transient_unit, 0),
+        SD_BUS_METHOD("GetJob", "u", "o", method_get_job, 0),
+        SD_BUS_METHOD("CancelJob", "u", NULL, method_cancel_job, 0),
+        SD_BUS_METHOD("ClearJobs", NULL, NULL, method_clear_jobs, 0),
+        SD_BUS_METHOD("ResetFailed", NULL, NULL, method_reset_failed, 0),
+        SD_BUS_METHOD("ListUnits", NULL, "a(ssssssouso)", method_list_units, 0),
+        SD_BUS_METHOD("ListJobs", NULL, "a(usssoo)", method_list_jobs, 0),
+        SD_BUS_METHOD("Subscribe", NULL, NULL, method_subscribe, 0),
+        SD_BUS_METHOD("Unsubscribe", NULL, NULL, method_unsubscribe, 0),
+        SD_BUS_METHOD("Dump", NULL, "s", method_dump, 0),
+        SD_BUS_METHOD("CreateSnapshot", "sb", "o", method_create_snapshot, 0),
+        SD_BUS_METHOD("RemoveSnapshot", "s", NULL, method_remove_snapshot, 0),
+        SD_BUS_METHOD("Reload", NULL, NULL, method_reload, 0),
+        SD_BUS_METHOD("Reexecute", NULL, NULL, method_reexecute, 0),
+        SD_BUS_METHOD("Exit", NULL, NULL, method_exit, 0),
+        SD_BUS_METHOD("Reboot", NULL, NULL, method_reboot, 0),
+        SD_BUS_METHOD("PowerOff", NULL, NULL, method_poweroff, 0),
+        SD_BUS_METHOD("Halt", NULL, NULL, method_halt, 0),
+        SD_BUS_METHOD("KExec", NULL, NULL, method_kexec, 0),
+        SD_BUS_METHOD("SwitchRoot", "ss", NULL, method_switch_root, 0),
+        SD_BUS_METHOD("SetEnvironment", "as", NULL, method_set_environment, 0),
+        SD_BUS_METHOD("UnsetEnvironment", "as", NULL, method_unset_environment, 0),
+        SD_BUS_METHOD("UnsetAndSetEnvironment", "asas", NULL, method_unset_and_set_environment, 0),
+        SD_BUS_METHOD("ListUnitFiles", NULL, "a(ss)", method_list_unit_files, 0),
+        SD_BUS_METHOD("GetUnitFileState", "s", "s", method_get_unit_file_state, 0),
+        SD_BUS_METHOD("EnableUnitFiles", "asbb", "ba(sss)", method_enable_unit_files, 0),
+        SD_BUS_METHOD("DisableUnitFiles", "asb", "a(sss)", method_disable_unit_files, 0),
+        SD_BUS_METHOD("ReenableUnitFiles", "asbb", "ba(sss)", method_reenable_unit_files, 0),
+        SD_BUS_METHOD("LinkUnitFiles", "asbb", "a(sss)", method_link_unit_files, 0),
+        SD_BUS_METHOD("PresetUnitFiles", "asbb", "ba(sss)", method_preset_unit_files, 0),
+        SD_BUS_METHOD("MaskUnitFiles", "asbb", "a(sss)", method_mask_unit_files, 0),
+        SD_BUS_METHOD("UnmaskUnitFiles", "asb", "a(sss)", method_unmask_unit_files, 0),
+        SD_BUS_METHOD("SetDefaultTarget", "sb", "a(sss)", method_set_default_target, 0),
+        SD_BUS_METHOD("GetDefaultTarget", NULL, "s", method_get_default_target, 0),
+
+        SD_BUS_SIGNAL("UnitNew", "so", 0),
+        SD_BUS_SIGNAL("UnitRemoved", "so", 0),
+        SD_BUS_SIGNAL("JobNew", "uos", 0),
+        SD_BUS_SIGNAL("JobRemoved", "uoss", 0),
+        SD_BUS_SIGNAL("StartupFinished", "tttttt", 0),
+        SD_BUS_SIGNAL("UnitFilesChanged", NULL, 0),
+        SD_BUS_SIGNAL("Reloading", "b", 0),
+
+        SD_BUS_VTABLE_END
 };
+
+int bus_manager_foreach_client(Manager *m, int (*send_message)(sd_bus *bus, const char *destination, void *userdata), void *userdata) {
+        Iterator i;
+        sd_bus *b;
+        unsigned n;
+        int r;
+
+        n = set_size(m->subscribed);
+        if (n <= 0)
+                return 0;
+        if (n == 1) {
+                BusTrackedClient *d;
+
+                assert_se(d = set_first(m->subscribed));
+                return send_message(d->bus, isempty(d->name) ? NULL : d->name, userdata);
+        }
+
+        /* Send to everybody */
+        SET_FOREACH(b, m->private_buses, i) {
+                r = send_message(b, NULL, userdata);
+                if (r < 0)
+                        return r;
+        }
+
+        if (m->api_bus)
+                return send_message(m->api_bus, NULL, userdata);
+
+        return 0;
+}
+
+static int send_finished(sd_bus *bus, const char *destination, void *userdata) {
+        _cleanup_bus_message_unref_ sd_bus_message *message = NULL;
+        usec_t *times = userdata;
+        int r;
+
+        assert(bus);
+        assert(times);
+
+        r = sd_bus_message_new_signal(bus, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "StartupFinished", &message);
+        if (r < 0)
+                return r;
+
+        r = sd_bus_message_append(message, "tttttt", times[0], times[1], times[2], times[3], times[4], times[5]);
+        if (r < 0)
+                return r;
+
+        return sd_bus_send_to(bus, message, destination, NULL);
+}
+
+int bus_manager_send_finished(
+                Manager *m,
+                usec_t firmware_usec,
+                usec_t loader_usec,
+                usec_t kernel_usec,
+                usec_t initrd_usec,
+                usec_t userspace_usec,
+                usec_t total_usec) {
+
+        assert(m);
+
+        return bus_manager_foreach_client(m, send_finished,
+                        (usec_t[6]) { firmware_usec, loader_usec, kernel_usec, initrd_usec, userspace_usec, total_usec });
+}
+
+static int send_reloading(sd_bus *bus, const char *destination, void *userdata) {
+        _cleanup_bus_message_unref_ sd_bus_message *message = NULL;
+        int r;
+
+        assert(bus);
+
+        r = sd_bus_message_new_signal(bus, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "Reloading", &message);
+        if (r < 0)
+                return r;
+
+        r = sd_bus_message_append(message, "b", PTR_TO_INT(userdata));
+        if (r < 0)
+                return r;
+
+        return sd_bus_send_to(bus, message, destination, NULL);
+}
+
+int bus_manager_send_reloading(Manager *m, bool active) {
+        assert(m);
+
+        return bus_manager_foreach_client(m, send_reloading, INT_TO_PTR(active));
+}
diff --git a/src/core/dbus-manager.h b/src/core/dbus-manager.h
index f0dce5a..ad451eb 100644
--- a/src/core/dbus-manager.h
+++ b/src/core/dbus-manager.h
@@ -21,8 +21,12 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <dbus/dbus.h>
+#include "sd-bus.h"
+#include "manager.h"
 
-extern const DBusObjectPathVTable bus_manager_vtable;
+extern const sd_bus_vtable bus_manager_vtable[];
 
-extern const char bus_manager_interface[];
+int bus_manager_foreach_client(Manager *m, int (*send_message)(sd_bus *bus, const char *destination, void *userdata), void *userdata);
+
+int bus_manager_send_finished(Manager *m, usec_t firmware_usec, usec_t loader_usec, usec_t kernel_usec, usec_t initrd_usec, usec_t userspace_usec, usec_t total_usec);
+int bus_manager_send_reloading(Manager *m, bool active);
diff --git a/src/core/dbus-mount.c b/src/core/dbus-mount.c
index 70b2d48..2056eab 100644
--- a/src/core/dbus-mount.c
+++ b/src/core/dbus-mount.c
@@ -19,67 +19,29 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <errno.h>
-
+#include "unit.h"
+#include "mount.h"
 #include "dbus-unit.h"
 #include "dbus-execute.h"
 #include "dbus-kill.h"
 #include "dbus-cgroup.h"
-#include "dbus-common.h"
-#include "selinux-access.h"
 #include "dbus-mount.h"
-
-#define BUS_MOUNT_INTERFACE                                             \
-        " <interface name=\"org.freedesktop.systemd1.Mount\">\n"        \
-        "  <property name=\"Where\" type=\"s\" access=\"read\"/>\n"     \
-        "  <property name=\"What\" type=\"s\" access=\"read\"/>\n"      \
-        "  <property name=\"Options\" type=\"s\" access=\"read\"/>\n"   \
-        "  <property name=\"Type\" type=\"s\" access=\"read\"/>\n"      \
-        "  <property name=\"TimeoutUSec\" type=\"t\" access=\"read\"/>\n" \
-        BUS_UNIT_CGROUP_INTERFACE                                       \
-        BUS_EXEC_COMMAND_INTERFACE("ExecMount")                         \
-        BUS_EXEC_COMMAND_INTERFACE("ExecUnmount")                       \
-        BUS_EXEC_COMMAND_INTERFACE("ExecRemount")                       \
-        BUS_EXEC_CONTEXT_INTERFACE                                      \
-        BUS_KILL_CONTEXT_INTERFACE                                      \
-        BUS_CGROUP_CONTEXT_INTERFACE                                    \
-        "  <property name=\"ControlPID\" type=\"u\" access=\"read\"/>\n" \
-        "  <property name=\"DirectoryMode\" type=\"u\" access=\"read\"/>\n" \
-        "  <property name=\"Result\" type=\"s\" access=\"read\"/>\n"    \
-        " </interface>\n"
-
-#define INTROSPECTION                                                   \
-        DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE                       \
-        "<node>\n"                                                      \
-        BUS_UNIT_INTERFACE                                              \
-        BUS_MOUNT_INTERFACE                                             \
-        BUS_PROPERTIES_INTERFACE                                        \
-        BUS_PEER_INTERFACE                                              \
-        BUS_INTROSPECTABLE_INTERFACE                                    \
-        "</node>\n"
-
-#define INTERFACES_LIST                              \
-        BUS_UNIT_INTERFACES_LIST                     \
-        "org.freedesktop.systemd1.Mount\0"
-
-const char bus_mount_interface[] = BUS_MOUNT_INTERFACE;
-
-const char bus_mount_invalidating_properties[] =
-        "What\0"
-        "Options\0"
-        "Type\0"
-        "ExecMount\0"
-        "ExecUnmount\0"
-        "ExecRemount\0"
-        "ControlPID\0"
-        "Result\0";
-
-static int bus_mount_append_what(DBusMessageIter *i, const char *property, void *data) {
-        Mount *m = data;
+#include "bus-util.h"
+
+static int property_get_what(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
+
+        Mount *m = userdata;
         const char *d;
 
-        assert(i);
-        assert(property);
+        assert(bus);
+        assert(reply);
         assert(m);
 
         if (m->from_proc_self_mountinfo && m->parameters_proc_self_mountinfo.what)
@@ -89,18 +51,23 @@ static int bus_mount_append_what(DBusMessageIter *i, const char *property, void
         else
                 d = "";
 
-        if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &d))
-                return -ENOMEM;
-
-        return 0;
+        return sd_bus_message_append(reply, "s", d);
 }
 
-static int bus_mount_append_options(DBusMessageIter *i, const char *property, void *data) {
-        Mount *m = data;
+static int property_get_options(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
+
+        Mount *m = userdata;
         const char *d;
 
-        assert(i);
-        assert(property);
+        assert(bus);
+        assert(reply);
         assert(m);
 
         if (m->from_proc_self_mountinfo && m->parameters_proc_self_mountinfo.options)
@@ -110,18 +77,23 @@ static int bus_mount_append_options(DBusMessageIter *i, const char *property, vo
         else
                 d = "";
 
-        if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &d))
-                return -ENOMEM;
-
-        return 0;
+        return sd_bus_message_append(reply, "s", d);
 }
 
-static int bus_mount_append_type(DBusMessageIter *i, const char *property, void *data) {
-        Mount *m = data;
+static int property_get_type(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
+
+        Mount *m = userdata;
         const char *d;
 
-        assert(i);
-        assert(property);
+        assert(bus);
+        assert(reply);
         assert(m);
 
         if (m->from_proc_self_mountinfo && m->parameters_proc_self_mountinfo.fstype)
@@ -131,66 +103,50 @@ static int bus_mount_append_type(DBusMessageIter *i, const char *property, void
         else
                 d = "";
 
-        if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &d))
-                return -ENOMEM;
-
-        return 0;
+        return sd_bus_message_append(reply, "s", d);
 }
 
-static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_mount_append_mount_result, mount_result, MountResult);
-
-static const BusProperty bus_mount_properties[] = {
-        { "Where",         bus_property_append_string, "s", offsetof(Mount, where),    true },
-        { "What",          bus_mount_append_what,      "s", 0 },
-        { "Options",       bus_mount_append_options,   "s", 0 },
-        { "Type",          bus_mount_append_type,      "s", 0 },
-        { "TimeoutUSec",   bus_property_append_usec,   "t", offsetof(Mount, timeout_usec)   },
-        BUS_EXEC_COMMAND_PROPERTY("ExecMount",   offsetof(Mount, exec_command[MOUNT_EXEC_MOUNT]),   false),
-        BUS_EXEC_COMMAND_PROPERTY("ExecUnmount", offsetof(Mount, exec_command[MOUNT_EXEC_UNMOUNT]), false),
-        BUS_EXEC_COMMAND_PROPERTY("ExecRemount", offsetof(Mount, exec_command[MOUNT_EXEC_REMOUNT]), false),
-        { "ControlPID",    bus_property_append_pid,    "u", offsetof(Mount, control_pid)    },
-        { "DirectoryMode", bus_property_append_mode,   "u", offsetof(Mount, directory_mode) },
-        { "Result",        bus_mount_append_mount_result, "s", offsetof(Mount, result)      },
-        { NULL, }
+static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_result, mount_result, MountResult);
+
+const sd_bus_vtable bus_mount_vtable[] = {
+        SD_BUS_VTABLE_START(0),
+        SD_BUS_PROPERTY("Where", "s", NULL, offsetof(Mount, where), 0),
+        SD_BUS_PROPERTY("What", "s", property_get_what, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+        SD_BUS_PROPERTY("Options","s", property_get_options, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+        SD_BUS_PROPERTY("Type", "s", property_get_type, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+        SD_BUS_PROPERTY("TimeoutUSec", "t", bus_property_get_usec, offsetof(Mount, timeout_usec), 0),
+        SD_BUS_PROPERTY("ControlPID", "u", bus_property_get_pid, offsetof(Mount, control_pid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+        SD_BUS_PROPERTY("DirectoryMode", "u", bus_property_get_mode, offsetof(Mount, directory_mode), 0),
+        SD_BUS_PROPERTY("Result", "s", property_get_result, offsetof(Mount, result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+        BUS_EXEC_COMMAND_VTABLE("ExecMount", offsetof(Mount, exec_command[MOUNT_EXEC_MOUNT]), 0),
+        BUS_EXEC_COMMAND_VTABLE("ExecUnmount", offsetof(Mount, exec_command[MOUNT_EXEC_UNMOUNT]), 0),
+        BUS_EXEC_COMMAND_VTABLE("ExecRemount", offsetof(Mount, exec_command[MOUNT_EXEC_REMOUNT]), 0),
+        SD_BUS_VTABLE_END
 };
 
-DBusHandlerResult bus_mount_message_handler(Unit *u, DBusConnection *c, DBusMessage *message) {
-        Mount *m = MOUNT(u);
-
-        const BusBoundProperties bps[] = {
-                { "org.freedesktop.systemd1.Unit",  bus_unit_properties,           u },
-                { "org.freedesktop.systemd1.Mount", bus_unit_cgroup_properties,    u },
-                { "org.freedesktop.systemd1.Mount", bus_mount_properties,          m },
-                { "org.freedesktop.systemd1.Mount", bus_exec_context_properties,   &m->exec_context },
-                { "org.freedesktop.systemd1.Mount", bus_kill_context_properties,   &m->kill_context },
-                { "org.freedesktop.systemd1.Mount", bus_cgroup_context_properties, &m->cgroup_context },
-                { NULL, }
-        };
-
-        SELINUX_UNIT_ACCESS_CHECK(u, c, message, "status");
-
-        return bus_default_message_handler(c, message, INTROSPECTION, INTERFACES_LIST, bps );
-}
+const char * const bus_mount_changing_properties[] = {
+        "What",
+        "Options",
+        "Type",
+        "ControlPID",
+        "Result",
+        NULL
+};
 
 int bus_mount_set_property(
                 Unit *u,
                 const char *name,
-                DBusMessageIter *i,
+                sd_bus_message *message,
                 UnitSetPropertiesMode mode,
-                DBusError *error) {
+                sd_bus_error *error) {
 
         Mount *m = MOUNT(u);
-        int r;
 
+        assert(m);
         assert(name);
-        assert(u);
-        assert(i);
+        assert(message);
 
-        r = bus_cgroup_set_property(u, &m->cgroup_context, name, i, mode, error);
-        if (r != 0)
-                return r;
-
-        return 0;
+        return bus_cgroup_set_property(u, &m->cgroup_context, name, message, mode, error);
 }
 
 int bus_mount_commit_properties(Unit *u) {
diff --git a/src/core/dbus-mount.h b/src/core/dbus-mount.h
index f4ec8b1..4bb5d2d 100644
--- a/src/core/dbus-mount.h
+++ b/src/core/dbus-mount.h
@@ -21,14 +21,11 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <dbus/dbus.h>
-
+#include "sd-bus.h"
 #include "unit.h"
 
-DBusHandlerResult bus_mount_message_handler(Unit *u, DBusConnection *c, DBusMessage *message);
+extern const sd_bus_vtable bus_mount_vtable[];
+extern const char * const bus_mount_changing_properties[];
 
-int bus_mount_set_property(Unit *u, const char *name, DBusMessageIter *i, UnitSetPropertiesMode mode, DBusError *error);
+int bus_mount_set_property(Unit *u, const char *name, sd_bus_message *message, UnitSetPropertiesMode mode, sd_bus_error *error);
 int bus_mount_commit_properties(Unit *u);
-
-extern const char bus_mount_interface[];
-extern const char bus_mount_invalidating_properties[];
diff --git a/src/core/dbus-path.c b/src/core/dbus-path.c
index a523b81..a206f49 100644
--- a/src/core/dbus-path.c
+++ b/src/core/dbus-path.c
@@ -19,104 +19,75 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <errno.h>
-
+#include "unit.h"
+#include "path.h"
 #include "dbus-unit.h"
 #include "dbus-path.h"
-#include "dbus-execute.h"
-#include "dbus-common.h"
-#include "selinux-access.h"
-
-#define BUS_PATH_INTERFACE                                              \
-        " <interface name=\"org.freedesktop.systemd1.Path\">\n"         \
-        "  <property name=\"Unit\" type=\"s\" access=\"read\"/>\n"      \
-        "  <property name=\"Paths\" type=\"a(ss)\" access=\"read\"/>\n" \
-        "  <property name=\"MakeDirectory\" type=\"b\" access=\"read\"/>\n" \
-        "  <property name=\"DirectoryMode\" type=\"u\" access=\"read\"/>\n" \
-        "  <property name=\"Result\" type=\"s\" access=\"read\"/>\n"    \
-        " </interface>\n"
-
-#define INTROSPECTION                                                   \
-        DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE                       \
-        "<node>\n"                                                      \
-        BUS_UNIT_INTERFACE                                              \
-        BUS_PATH_INTERFACE                                              \
-        BUS_PROPERTIES_INTERFACE                                        \
-        BUS_PEER_INTERFACE                                              \
-        BUS_INTROSPECTABLE_INTERFACE                                    \
-        "</node>\n"
-
-#define INTERFACES_LIST                              \
-        BUS_UNIT_INTERFACES_LIST                     \
-        "org.freedesktop.systemd1.Path\0"
-
-const char bus_path_interface[] = BUS_PATH_INTERFACE;
-
-const char bus_path_invalidating_properties[] =
-        "Result\0";
-
-static int bus_path_append_paths(DBusMessageIter *i, const char *property, void *data) {
-        Path *p = data;
-        DBusMessageIter sub, sub2;
+#include "bus-util.h"
+
+static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_result, path_result, PathResult);
+
+static int property_get_paths(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
+
+        Path *p = userdata;
         PathSpec *k;
+        int r;
 
-        assert(i);
-        assert(property);
+        assert(bus);
+        assert(reply);
         assert(p);
 
-        if (!dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, "(ss)", &sub))
-                return -ENOMEM;
+        r = sd_bus_message_open_container(reply, 'a', "(ss)");
+        if (r < 0)
+                return r;
 
         LIST_FOREACH(spec, k, p->specs) {
-                const char *t = path_type_to_string(k->type);
-
-                if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
-                    !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &t) ||
-                    !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &k->path) ||
-                    !dbus_message_iter_close_container(&sub, &sub2))
-                        return -ENOMEM;
+                r = sd_bus_message_append(reply, "(ss)", path_type_to_string(k->type), k->path);
+                if (r < 0)
+                        return r;
         }
 
-        if (!dbus_message_iter_close_container(i, &sub))
-                return -ENOMEM;
-
-        return 0;
+        return sd_bus_message_close_container(reply);
 }
 
-static int bus_path_append_unit(DBusMessageIter *i, const char *property, void *data) {
-        Unit *u = data, *trigger;
-        const char *t;
+static int property_get_unit(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
 
-        assert(i);
-        assert(property);
-        assert(u);
+        Unit *p = userdata, *trigger;
 
-        trigger = UNIT_TRIGGER(u);
-        t = trigger ? trigger->id : "";
+        assert(bus);
+        assert(reply);
+        assert(p);
 
-        return dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &t) ? 0 : -ENOMEM;
-}
+        trigger = UNIT_TRIGGER(p);
 
-static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_path_append_path_result, path_result, PathResult);
+        return sd_bus_message_append(reply, "s", trigger ? trigger->id : "");
+}
 
-static const BusProperty bus_path_properties[] = {
-        { "Unit",          bus_path_append_unit,      "s", 0 },
-        { "Paths",         bus_path_append_paths, "a(ss)", 0 },
-        { "MakeDirectory", bus_property_append_bool,  "b", offsetof(Path, make_directory) },
-        { "DirectoryMode", bus_property_append_mode,  "u", offsetof(Path, directory_mode) },
-        { "Result",        bus_path_append_path_result, "s", offsetof(Path, result) },
-        { NULL, }
+const sd_bus_vtable bus_path_vtable[] = {
+        SD_BUS_VTABLE_START(0),
+        SD_BUS_PROPERTY("Unit", "s", property_get_unit, 0, 0),
+        SD_BUS_PROPERTY("Paths", "a(ss)", property_get_paths, 0, 0),
+        SD_BUS_PROPERTY("MakeDirectory", "b", bus_property_get_bool, offsetof(Path, make_directory), 0),
+        SD_BUS_PROPERTY("DirectoryMode", "u", bus_property_get_mode, offsetof(Path, directory_mode), 0),
+        SD_BUS_PROPERTY("Result", "s", property_get_result, offsetof(Path, result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+        SD_BUS_VTABLE_END
 };
 
-DBusHandlerResult bus_path_message_handler(Unit *u, DBusConnection *c, DBusMessage *message) {
-        Path *p = PATH(u);
-        const BusBoundProperties bps[] = {
-                { "org.freedesktop.systemd1.Unit", bus_unit_properties, u },
-                { "org.freedesktop.systemd1.Path", bus_path_properties, p },
-                { NULL, }
-        };
-
-        SELINUX_UNIT_ACCESS_CHECK(u, c, message, "status");
-
-        return bus_default_message_handler(c, message, INTROSPECTION, INTERFACES_LIST, bps);
-}
+const char* const bus_path_changing_properties[] = {
+        "Result",
+        NULL
+};
diff --git a/src/core/dbus-path.h b/src/core/dbus-path.h
index c945f7d..e9558f8 100644
--- a/src/core/dbus-path.h
+++ b/src/core/dbus-path.h
@@ -21,12 +21,8 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <dbus/dbus.h>
 
-#include "unit.h"
+#include "sd-bus.h"
 
-DBusHandlerResult bus_path_message_handler(Unit *u, DBusConnection *c, DBusMessage *message);
-
-extern const char bus_path_interface[];
-
-extern const char bus_path_invalidating_properties[];
+extern const sd_bus_vtable bus_path_vtable[];
+extern const char* const bus_path_changing_properties[];
diff --git a/src/core/dbus-scope.c b/src/core/dbus-scope.c
index c790d26..13ff49d 100644
--- a/src/core/dbus-scope.c
+++ b/src/core/dbus-scope.c
@@ -19,95 +19,54 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <errno.h>
-
+#include "unit.h"
+#include "scope.h"
 #include "dbus-unit.h"
-#include "dbus-common.h"
 #include "dbus-cgroup.h"
 #include "dbus-kill.h"
-#include "selinux-access.h"
 #include "dbus-scope.h"
+#include "bus-util.h"
 
-#define BUS_SCOPE_INTERFACE                                             \
-        " <interface name=\"org.freedesktop.systemd1.Scope\">\n"        \
-        BUS_UNIT_CGROUP_INTERFACE                                       \
-        "  <property name=\"TimeoutStopUSec\" type=\"t\" access=\"read\"/>\n" \
-        BUS_KILL_CONTEXT_INTERFACE                                      \
-        BUS_CGROUP_CONTEXT_INTERFACE                                    \
-        "  <property name=\"Result\" type=\"s\" access=\"read\"/>\n"    \
-        " </interface>\n"
-
-#define INTROSPECTION                                                   \
-        DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE                       \
-        "<node>\n"                                                      \
-        BUS_UNIT_INTERFACE                                              \
-        BUS_SCOPE_INTERFACE                                             \
-        BUS_PROPERTIES_INTERFACE                                        \
-        BUS_PEER_INTERFACE                                              \
-        BUS_INTROSPECTABLE_INTERFACE                                    \
-        "</node>\n"
-
-#define INTERFACES_LIST                              \
-        BUS_UNIT_INTERFACES_LIST                     \
-        "org.freedesktop.systemd1.Scope\0"
-
-const char bus_scope_interface[] = BUS_SCOPE_INTERFACE;
-
-static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_scope_append_scope_result, scope_result, ScopeResult);
-
-static const BusProperty bus_scope_properties[] = {
-        { "TimeoutStopUSec",        bus_property_append_usec,      "t", offsetof(Scope, timeout_stop_usec) },
-        { "Result",                 bus_scope_append_scope_result, "s", offsetof(Scope, result)            },
-        {}
-};
-
-DBusHandlerResult bus_scope_message_handler(Unit *u, DBusConnection *c, DBusMessage *message) {
-        Scope *s = SCOPE(u);
+static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_result, scope_result, ScopeResult);
 
-        const BusBoundProperties bps[] = {
-                { "org.freedesktop.systemd1.Unit",  bus_unit_properties,           u },
-                { "org.freedesktop.systemd1.Scope", bus_unit_cgroup_properties,    u },
-                { "org.freedesktop.systemd1.Scope", bus_scope_properties,          s },
-                { "org.freedesktop.systemd1.Scope", bus_cgroup_context_properties, &s->cgroup_context },
-                { "org.freedesktop.systemd1.Scope", bus_kill_context_properties,   &s->kill_context   },
-                {}
-        };
-
-        SELINUX_UNIT_ACCESS_CHECK(u, c, message, "status");
+const sd_bus_vtable bus_scope_vtable[] = {
+        SD_BUS_VTABLE_START(0),
+        SD_BUS_PROPERTY("TimeoutStopUSec", "t", bus_property_get_usec, offsetof(Scope, timeout_stop_usec), 0),
+        SD_BUS_PROPERTY("Result", "s", property_get_result, offsetof(Scope, result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+        SD_BUS_VTABLE_END
+};
 
-        return bus_default_message_handler(c, message, INTROSPECTION, INTERFACES_LIST, bps);
-}
+const char* const bus_scope_changing_properties[] = {
+        "Result",
+        NULL
+};
 
 static int bus_scope_set_transient_property(
                 Scope *s,
                 const char *name,
-                DBusMessageIter *i,
+                sd_bus_message *message,
                 UnitSetPropertiesMode mode,
-                DBusError *error) {
+                sd_bus_error *error) {
 
         int r;
 
-        assert(name);
         assert(s);
-        assert(i);
+        assert(name);
+        assert(message);
 
         if (streq(name, "PIDs")) {
-                DBusMessageIter sub;
                 unsigned n = 0;
-
-                if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_ARRAY ||
-                    dbus_message_iter_get_element_type(i) != DBUS_TYPE_UINT32)
-                        return -EINVAL;
+                uint32_t pid;
 
                 r = set_ensure_allocated(&s->pids, trivial_hash_func, trivial_compare_func);
                 if (r < 0)
                         return r;
 
-                dbus_message_iter_recurse(i, &sub);
-                while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_UINT32) {
-                        uint32_t pid;
+                r = sd_bus_message_enter_container(message, 'a', "u");
+                if (r < 0)
+                        return r;
 
-                        dbus_message_iter_get_basic(&sub, &pid);
+                while ((r = sd_bus_message_read(message, "u", &pid)) > 0) {
 
                         if (pid <= 1)
                                 return -EINVAL;
@@ -118,9 +77,14 @@ static int bus_scope_set_transient_property(
                                         return r;
                         }
 
-                        dbus_message_iter_next(&sub);
                         n++;
                 }
+                if (r < 0)
+                        return r;
+
+                r = sd_bus_message_exit_container(message);
+                if (r < 0)
+                        return r;
 
                 if (n <= 0)
                         return -EINVAL;
@@ -129,17 +93,16 @@ static int bus_scope_set_transient_property(
 
         } else if (streq(name, "TimeoutStopUSec")) {
 
-                if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_UINT64)
-                        return -EINVAL;
-
                 if (mode != UNIT_CHECK) {
-                        uint64_t t;
-
-                        dbus_message_iter_get_basic(i, &t);
-
-                        s->timeout_stop_usec = t;
-
-                        unit_write_drop_in_format(UNIT(s), mode, name, "[Scope]\nTimeoutStopSec=%lluus\n", (unsigned long long) t);
+                        r = sd_bus_message_read(message, "t", &s->timeout_stop_usec);
+                        if (r < 0)
+                                return r;
+
+                        unit_write_drop_in_format(UNIT(s), mode, name, "[Scope]\nTimeoutStopSec=%lluus\n", (unsigned long long) s->timeout_stop_usec);
+                } else {
+                        r = sd_bus_message_skip(message, "t");
+                        if (r < 0)
+                                return r;
                 }
 
                 return 1;
@@ -151,29 +114,29 @@ static int bus_scope_set_transient_property(
 int bus_scope_set_property(
                 Unit *u,
                 const char *name,
-                DBusMessageIter *i,
+                sd_bus_message *message,
                 UnitSetPropertiesMode mode,
-                DBusError *error) {
+                sd_bus_error *error) {
 
         Scope *s = SCOPE(u);
         int r;
 
+        assert(s);
         assert(name);
-        assert(u);
-        assert(i);
+        assert(message);
 
-        r = bus_cgroup_set_property(u, &s->cgroup_context, name, i, mode, error);
+        r = bus_cgroup_set_property(u, &s->cgroup_context, name, message, mode, error);
         if (r != 0)
                 return r;
 
         if (u->load_state == UNIT_STUB) {
                 /* While we are created we still accept PIDs */
 
-                r = bus_scope_set_transient_property(s, name, i, mode, error);
+                r = bus_scope_set_transient_property(s, name, message, mode, error);
                 if (r != 0)
                         return r;
 
-                r = bus_kill_context_set_transient_property(u, &s->kill_context, name, i, mode, error);
+                r = bus_kill_context_set_transient_property(u, &s->kill_context, name, message, mode, error);
                 if (r != 0)
                         return r;
         }
diff --git a/src/core/dbus-scope.h b/src/core/dbus-scope.h
index e6836f1..30c5e1e 100644
--- a/src/core/dbus-scope.h
+++ b/src/core/dbus-scope.h
@@ -21,13 +21,11 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <dbus/dbus.h>
-
+#include "sd-bus.h"
 #include "unit.h"
 
-DBusHandlerResult bus_scope_message_handler(Unit *u, DBusConnection *c, DBusMessage *message);
+extern const sd_bus_vtable bus_scope_vtable[];
+extern const char* const bus_scope_changing_properties[];
 
-int bus_scope_set_property(Unit *u, const char *name, DBusMessageIter *i, UnitSetPropertiesMode mode, DBusError *error);
+int bus_scope_set_property(Unit *u, const char *name, sd_bus_message *i, UnitSetPropertiesMode mode, sd_bus_error *error);
 int bus_scope_commit_properties(Unit *u);
-
-extern const char bus_scope_interface[];
diff --git a/src/core/dbus-service.c b/src/core/dbus-service.c
index c888570..c4bfa2c 100644
--- a/src/core/dbus-service.c
+++ b/src/core/dbus-service.c
@@ -19,176 +19,92 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <errno.h>
-
 #include "strv.h"
 #include "path-util.h"
+#include "unit.h"
+#include "service.h"
 #include "dbus-unit.h"
 #include "dbus-execute.h"
 #include "dbus-kill.h"
 #include "dbus-cgroup.h"
-#include "dbus-common.h"
-#include "selinux-access.h"
 #include "dbus-service.h"
-
-#define BUS_SERVICE_INTERFACE                                           \
-        " <interface name=\"org.freedesktop.systemd1.Service\">\n"      \
-        "  <property name=\"Type\" type=\"s\" access=\"read\"/>\n"      \
-        "  <property name=\"Restart\" type=\"s\" access=\"read\"/>\n"   \
-        "  <property name=\"PIDFile\" type=\"s\" access=\"read\"/>\n"   \
-        "  <property name=\"NotifyAccess\" type=\"s\" access=\"read\"/>\n" \
-        "  <property name=\"RestartUSec\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"TimeoutStartUSec\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"TimeoutStopUSec\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"WatchdogUSec\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"WatchdogTimestamp\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"WatchdogTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"StartLimitInterval\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"StartLimitBurst\" type=\"u\" access=\"read\"/>\n" \
-        "  <property name=\"StartLimitAction\" type=\"s\" access=\"readwrite\"/>\n" \
-        BUS_UNIT_CGROUP_INTERFACE                                       \
-        BUS_EXEC_COMMAND_INTERFACE("ExecStartPre")                      \
-        BUS_EXEC_COMMAND_INTERFACE("ExecStart")                         \
-        BUS_EXEC_COMMAND_INTERFACE("ExecStartPost")                     \
-        BUS_EXEC_COMMAND_INTERFACE("ExecReload")                        \
-        BUS_EXEC_COMMAND_INTERFACE("ExecStop")                          \
-        BUS_EXEC_COMMAND_INTERFACE("ExecStopPost")                      \
-        BUS_EXEC_CONTEXT_INTERFACE                                      \
-        BUS_KILL_CONTEXT_INTERFACE                                      \
-        BUS_CGROUP_CONTEXT_INTERFACE                                    \
-        "  <property name=\"PermissionsStartOnly\" type=\"b\" access=\"read\"/>\n" \
-        "  <property name=\"RootDirectoryStartOnly\" type=\"b\" access=\"read\"/>\n" \
-        "  <property name=\"RemainAfterExit\" type=\"b\" access=\"read\"/>\n" \
-        BUS_EXEC_STATUS_INTERFACE("ExecMain")                           \
-        "  <property name=\"MainPID\" type=\"u\" access=\"read\"/>\n"   \
-        "  <property name=\"ControlPID\" type=\"u\" access=\"read\"/>\n" \
-        "  <property name=\"BusName\" type=\"s\" access=\"read\"/>\n"   \
-        "  <property name=\"StatusText\" type=\"s\" access=\"read\"/>\n" \
-        "  <property name=\"Result\" type=\"s\" access=\"read\"/>\n"    \
-       " </interface>\n"
-
-#define INTROSPECTION                                                   \
-        DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE                       \
-        "<node>\n"                                                      \
-        BUS_UNIT_INTERFACE                                              \
-        BUS_SERVICE_INTERFACE                                           \
-        BUS_PROPERTIES_INTERFACE                                        \
-        BUS_PEER_INTERFACE                                              \
-        BUS_INTROSPECTABLE_INTERFACE                                    \
-        "</node>\n"
-
-#define INTERFACES_LIST                              \
-        BUS_UNIT_INTERFACES_LIST                     \
-        "org.freedesktop.systemd1.Service\0"
-
-const char bus_service_interface[] = BUS_SERVICE_INTERFACE;
-
-const char bus_service_invalidating_properties[] =
-        "ExecStartPre\0"
-        "ExecStart\0"
-        "ExecStartPost\0"
-        "ExecReload\0"
-        "ExecStop\0"
-        "ExecStopPost\0"
-        "ExecMain\0"
-        "WatchdogTimestamp\0"
-        "WatchdogTimestampMonotonic\0"
-        "MainPID\0"
-        "ControlPID\0"
-        "StatusText\0"
-        "Result\0";
-
-static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_service_append_type, service_type, ServiceType);
-static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_service_append_restart, service_restart, ServiceRestart);
-static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_service_append_notify_access, notify_access, NotifyAccess);
-static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_service_append_service_result, service_result, ServiceResult);
-static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_service_append_start_limit_action, start_limit_action, StartLimitAction);
-static DEFINE_BUS_PROPERTY_SET_ENUM(bus_service_set_start_limit_action, start_limit_action, StartLimitAction);
-
-static const BusProperty bus_exec_main_status_properties[] = {
-        { "ExecMainStartTimestamp",         bus_property_append_usec, "t", offsetof(ExecStatus, start_timestamp.realtime)  },
-        { "ExecMainStartTimestampMonotonic",bus_property_append_usec, "t", offsetof(ExecStatus, start_timestamp.monotonic) },
-        { "ExecMainExitTimestamp",          bus_property_append_usec, "t", offsetof(ExecStatus, exit_timestamp.realtime)   },
-        { "ExecMainExitTimestampMonotonic", bus_property_append_usec, "t", offsetof(ExecStatus, exit_timestamp.monotonic)  },
-        { "ExecMainPID",                    bus_property_append_pid,  "u", offsetof(ExecStatus, pid)                       },
-        { "ExecMainCode",                   bus_property_append_int,  "i", offsetof(ExecStatus, code)                      },
-        { "ExecMainStatus",                 bus_property_append_int,  "i", offsetof(ExecStatus, status)                    },
-        {}
+#include "bus-util.h"
+
+static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_type, service_type, ServiceType);
+static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_result, service_result, ServiceResult);
+static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_restart, service_restart, ServiceRestart);
+static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_notify_access, notify_access, NotifyAccess);
+static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_start_limit_action, start_limit_action, StartLimitAction);
+
+const sd_bus_vtable bus_service_vtable[] = {
+        SD_BUS_VTABLE_START(0),
+        SD_BUS_PROPERTY("Type", "s", property_get_type, offsetof(Service, type), 0),
+        SD_BUS_PROPERTY("Restart", "s", property_get_restart, offsetof(Service, restart), 0),
+        SD_BUS_PROPERTY("PIDFile", "s", NULL, offsetof(Service, pid_file), 0),
+        SD_BUS_PROPERTY("NotifyAccess", "s", property_get_notify_access, offsetof(Service, notify_access), 0),
+        SD_BUS_PROPERTY("RestartUSec", "t", bus_property_get_usec, offsetof(Service, restart_usec), 0),
+        SD_BUS_PROPERTY("TimeoutStartUSec", "t", bus_property_get_usec, offsetof(Service, timeout_start_usec), 0),
+        SD_BUS_PROPERTY("TimeoutStopUSec", "t", bus_property_get_usec, offsetof(Service, timeout_stop_usec), 0),
+        SD_BUS_PROPERTY("WatchdogUSec", "t", bus_property_get_usec, offsetof(Service, watchdog_usec), 0),
+        BUS_PROPERTY_DUAL_TIMESTAMP("WatchdogTimestamp", offsetof(Service, watchdog_timestamp), 0),
+        SD_BUS_PROPERTY("StartLimitInterval", "t", bus_property_get_usec, offsetof(Service, start_limit.interval), 0),
+        SD_BUS_PROPERTY("StartLimitBurst", "u", bus_property_get_unsigned, offsetof(Service, start_limit.burst), 0),
+        SD_BUS_PROPERTY("StartLimitAction", "s", property_get_start_limit_action, offsetof(Service, start_limit_action), 0),
+        SD_BUS_PROPERTY("PermissionsStartOnly", "b", bus_property_get_bool, offsetof(Service, permissions_start_only), 0),
+        SD_BUS_PROPERTY("RootDirectoryStartOnly", "b", bus_property_get_bool, offsetof(Service, root_directory_start_only), 0),
+        SD_BUS_PROPERTY("RemainAfterExit", "b", bus_property_get_bool, offsetof(Service, remain_after_exit), 0),
+        SD_BUS_PROPERTY("GuessMainPID", "b", bus_property_get_bool, offsetof(Service, guess_main_pid), 0),
+        SD_BUS_PROPERTY("MainPID", "u", bus_property_get_pid, offsetof(Service, main_pid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+        SD_BUS_PROPERTY("ControlPID", "u", bus_property_get_pid, offsetof(Service, control_pid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+        SD_BUS_PROPERTY("BusName", "s", NULL, offsetof(Service, bus_name), 0),
+        SD_BUS_PROPERTY("StatusText", "s", NULL, offsetof(Service, status_text), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+        SD_BUS_PROPERTY("Result", "s", property_get_result, offsetof(Service, result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+        BUS_EXEC_STATUS_VTABLE("ExecMain", offsetof(Service, main_exec_status), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+        BUS_EXEC_COMMAND_VTABLE("ExecStartPre", offsetof(Service, exec_command[SERVICE_EXEC_START_PRE]), 0),
+        BUS_EXEC_COMMAND_VTABLE("ExecStart", offsetof(Service, exec_command[SERVICE_EXEC_START]), 0),
+        BUS_EXEC_COMMAND_VTABLE("ExecStartPost", offsetof(Service, exec_command[SERVICE_EXEC_START_POST]), 0),
+        BUS_EXEC_COMMAND_VTABLE("ExecReload", offsetof(Service, exec_command[SERVICE_EXEC_RELOAD]), 0),
+        BUS_EXEC_COMMAND_VTABLE("ExecStop", offsetof(Service, exec_command[SERVICE_EXEC_STOP]), 0),
+        BUS_EXEC_COMMAND_VTABLE("ExecStopPost", offsetof(Service, exec_command[SERVICE_EXEC_STOP_POST]), 0),
+        SD_BUS_VTABLE_END
 };
 
-static const BusProperty bus_service_properties[] = {
-        { "Type",                   bus_service_append_type,          "s", offsetof(Service, type)                         },
-        { "Restart",                bus_service_append_restart,       "s", offsetof(Service, restart)                      },
-        { "PIDFile",                bus_property_append_string,       "s", offsetof(Service, pid_file),               true },
-        { "NotifyAccess",           bus_service_append_notify_access, "s", offsetof(Service, notify_access)                },
-        { "RestartUSec",            bus_property_append_usec,         "t", offsetof(Service, restart_usec)                 },
-        { "TimeoutStartUSec",       bus_property_append_usec,         "t", offsetof(Service, timeout_start_usec)           },
-        { "TimeoutStopUSec",        bus_property_append_usec,         "t", offsetof(Service, timeout_stop_usec)            },
-        { "WatchdogUSec",           bus_property_append_usec,         "t", offsetof(Service, watchdog_usec)                },
-        { "WatchdogTimestamp",      bus_property_append_usec,         "t", offsetof(Service, watchdog_timestamp.realtime)  },
-        { "WatchdogTimestampMonotonic",bus_property_append_usec,      "t", offsetof(Service, watchdog_timestamp.monotonic) },
-        { "StartLimitInterval",     bus_property_append_usec,         "t", offsetof(Service, start_limit.interval)         },
-        { "StartLimitBurst",        bus_property_append_uint32,       "u", offsetof(Service, start_limit.burst)            },
-        { "StartLimitAction",       bus_service_append_start_limit_action,"s", offsetof(Service, start_limit_action), false, bus_service_set_start_limit_action},
-        BUS_EXEC_COMMAND_PROPERTY("ExecStartPre",  offsetof(Service, exec_command[SERVICE_EXEC_START_PRE]),  true ),
-        BUS_EXEC_COMMAND_PROPERTY("ExecStart",     offsetof(Service, exec_command[SERVICE_EXEC_START]),      true ),
-        BUS_EXEC_COMMAND_PROPERTY("ExecStartPost", offsetof(Service, exec_command[SERVICE_EXEC_START_POST]), true ),
-        BUS_EXEC_COMMAND_PROPERTY("ExecReload",    offsetof(Service, exec_command[SERVICE_EXEC_RELOAD]),     true ),
-        BUS_EXEC_COMMAND_PROPERTY("ExecStop",      offsetof(Service, exec_command[SERVICE_EXEC_STOP]),       true ),
-        BUS_EXEC_COMMAND_PROPERTY("ExecStopPost",  offsetof(Service, exec_command[SERVICE_EXEC_STOP_POST]),  true ),
-        { "PermissionsStartOnly",   bus_property_append_bool,         "b", offsetof(Service, permissions_start_only)       },
-        { "RootDirectoryStartOnly", bus_property_append_bool,         "b", offsetof(Service, root_directory_start_only)    },
-        { "RemainAfterExit",        bus_property_append_bool,         "b", offsetof(Service, remain_after_exit)            },
-        { "GuessMainPID",           bus_property_append_bool,         "b", offsetof(Service, guess_main_pid)               },
-        { "MainPID",                bus_property_append_pid,          "u", offsetof(Service, main_pid)                     },
-        { "ControlPID",             bus_property_append_pid,          "u", offsetof(Service, control_pid)                  },
-        { "BusName",                bus_property_append_string,       "s", offsetof(Service, bus_name),               true },
-        { "StatusText",             bus_property_append_string,       "s", offsetof(Service, status_text),            true },
-        { "Result",                 bus_service_append_service_result,"s", offsetof(Service, result)                       },
-        {}
+const char* const bus_service_changing_properties[] = {
+        "ExecMainStartTimestamp",
+        "ExecMainStartTimestampMonotonic",
+        "ExecMainExitTimestamp",
+        "ExecMainExitTimestampMonotonic",
+        "ExecMainPID",
+        "ExecMainCode",
+        "ExecMainStatus",
+        "MainPID",
+        "ControlPID",
+        "StatusText",
+        "Result",
+        NULL
 };
 
-DBusHandlerResult bus_service_message_handler(Unit *u, DBusConnection *connection, DBusMessage *message) {
-        Service *s = SERVICE(u);
-
-        const BusBoundProperties bps[] = {
-                { "org.freedesktop.systemd1.Unit",    bus_unit_properties,             u },
-                { "org.freedesktop.systemd1.Service", bus_unit_cgroup_properties,      u },
-                { "org.freedesktop.systemd1.Service", bus_service_properties,          s },
-                { "org.freedesktop.systemd1.Service", bus_exec_context_properties,     &s->exec_context },
-                { "org.freedesktop.systemd1.Service", bus_kill_context_properties,     &s->kill_context },
-                { "org.freedesktop.systemd1.Service", bus_cgroup_context_properties,   &s->cgroup_context },
-                { "org.freedesktop.systemd1.Service", bus_exec_main_status_properties, &s->main_exec_status },
-                {}
-        };
-
-        SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "status");
-
-        return bus_default_message_handler(connection, message, INTROSPECTION, INTERFACES_LIST, bps);
-}
-
 static int bus_service_set_transient_property(
                 Service *s,
                 const char *name,
-                DBusMessageIter *i,
+                sd_bus_message *message,
                 UnitSetPropertiesMode mode,
-                DBusError *error) {
+                sd_bus_error *error) {
 
         int r;
 
-        assert(name);
         assert(s);
-        assert(i);
+        assert(name);
+        assert(message);
 
         if (streq(name, "RemainAfterExit")) {
-                if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_BOOLEAN)
-                        return -EINVAL;
+                int b;
 
-                if (mode != UNIT_CHECK) {
-                        dbus_bool_t b;
-
-                        dbus_message_iter_get_basic(i, &b);
+                r = sd_bus_message_read(message, "b", &b);
+                if (r < 0)
+                        return r;
 
+                if (mode != UNIT_CHECK) {
                         s->remain_after_exit = b;
                         unit_write_drop_in_private_format(UNIT(s), mode, name, "RemainAfterExit=%s\n", yes_no(b));
                 }
@@ -196,38 +112,35 @@ static int bus_service_set_transient_property(
                 return 1;
 
         } else if (streq(name, "ExecStart")) {
-                DBusMessageIter sub;
                 unsigned n = 0;
 
-                if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_ARRAY ||
-                    dbus_message_iter_get_element_type(i) != DBUS_TYPE_STRUCT)
-                        return -EINVAL;
+                r = sd_bus_message_enter_container(message, 'a', "(sasb)");
+                if (r < 0)
+                        return r;
 
-                dbus_message_iter_recurse(i, &sub);
-                while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
+                while ((r = sd_bus_message_enter_container(message, 'r', "sasb")) > 0) {
                         _cleanup_strv_free_ char **argv = NULL;
-                        DBusMessageIter sub2;
-                        dbus_bool_t ignore;
                         const char *path;
+                        int b;
 
-                        dbus_message_iter_recurse(&sub, &sub2);
-
-                        if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0)
-                                return -EINVAL;
+                        r = sd_bus_message_read(message, "s", &path);
+                        if (r < 0)
+                                return r;
 
-                        if (!path_is_absolute(path)) {
-                                dbus_set_error(error, DBUS_ERROR_INVALID_ARGS, "Path %s is not absolute.", path);
-                                return -EINVAL;
-                        }
+                        if (!path_is_absolute(path))
+                                return sd_bus_error_set_errnof(error, EINVAL, "Path %s is not absolute.", path);
 
-                        r = bus_parse_strv_iter(&sub2, &argv);
+                        r = sd_bus_message_read_strv(message, &argv);
                         if (r < 0)
                                 return r;
 
-                        dbus_message_iter_next(&sub2);
+                        r = sd_bus_message_read(message, "b", &b);
+                        if (r < 0)
+                                return r;
 
-                        if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, false) < 0)
-                                return -EINVAL;
+                        r = sd_bus_message_exit_container(message);
+                        if (r < 0)
+                                return r;
 
                         if (mode != UNIT_CHECK) {
                                 ExecCommand *c;
@@ -245,15 +158,16 @@ static int bus_service_set_transient_property(
                                 c->argv = argv;
                                 argv = NULL;
 
-                                c->ignore = ignore;
+                                c->ignore = b;
 
                                 path_kill_slashes(c->path);
                                 exec_command_append_list(&s->exec_command[SERVICE_EXEC_START], c);
                         }
 
                         n++;
-                        dbus_message_iter_next(&sub);
                 }
+                if (r < 0)
+                        return r;
 
                 if (mode != UNIT_CHECK) {
                         _cleanup_free_ char *buf = NULL;
@@ -298,29 +212,29 @@ static int bus_service_set_transient_property(
 int bus_service_set_property(
                 Unit *u,
                 const char *name,
-                DBusMessageIter *i,
+                sd_bus_message *message,
                 UnitSetPropertiesMode mode,
-                DBusError *error) {
+                sd_bus_error *error) {
 
         Service *s = SERVICE(u);
         int r;
 
+        assert(s);
         assert(name);
-        assert(u);
-        assert(i);
+        assert(message);
 
-        r = bus_cgroup_set_property(u, &s->cgroup_context, name, i, mode, error);
+        r = bus_cgroup_set_property(u, &s->cgroup_context, name, message, mode, error);
         if (r != 0)
                 return r;
 
         if (u->transient && u->load_state == UNIT_STUB) {
                 /* This is a transient unit, let's load a little more */
 
-                r = bus_service_set_transient_property(s, name, i, mode, error);
+                r = bus_service_set_transient_property(s, name, message, mode, error);
                 if (r != 0)
                         return r;
 
-                r = bus_kill_context_set_transient_property(u, &s->kill_context, name, i, mode, error);
+                r = bus_kill_context_set_transient_property(u, &s->kill_context, name, message, mode, error);
                 if (r != 0)
                         return r;
         }
diff --git a/src/core/dbus-service.h b/src/core/dbus-service.h
index 9b9f137..5fa9b2f 100644
--- a/src/core/dbus-service.h
+++ b/src/core/dbus-service.h
@@ -21,14 +21,11 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <dbus/dbus.h>
-
+#include "sd-bus.h"
 #include "unit.h"
 
-DBusHandlerResult bus_service_message_handler(Unit *u, DBusConnection *c, DBusMessage *message);
+extern const sd_bus_vtable bus_service_vtable[];
+extern const char* const bus_service_changing_properties[];
 
-int bus_service_set_property(Unit *u, const char *name, DBusMessageIter *i, UnitSetPropertiesMode mode, DBusError *error);
+int bus_service_set_property(Unit *u, const char *name, sd_bus_message *i, UnitSetPropertiesMode mode, sd_bus_error *error);
 int bus_service_commit_properties(Unit *u);
-
-extern const char bus_service_interface[];
-extern const char bus_service_invalidating_properties[];
diff --git a/src/core/dbus-slice.c b/src/core/dbus-slice.c
index eeefcdb..2a48ea4 100644
--- a/src/core/dbus-slice.c
+++ b/src/core/dbus-slice.c
@@ -19,70 +19,30 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <errno.h>
-
+#include "unit.h"
+#include "slice.h"
 #include "dbus-unit.h"
-#include "dbus-common.h"
 #include "dbus-cgroup.h"
-#include "selinux-access.h"
 #include "dbus-slice.h"
 
-#define BUS_SLICE_INTERFACE                                             \
-        " <interface name=\"org.freedesktop.systemd1.Slice\">\n"        \
-        BUS_UNIT_CGROUP_INTERFACE                                       \
-        BUS_CGROUP_CONTEXT_INTERFACE                                    \
-        " </interface>\n"
-
-#define INTROSPECTION                                                   \
-        DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE                       \
-        "<node>\n"                                                      \
-        BUS_UNIT_INTERFACE                                              \
-        BUS_SLICE_INTERFACE                                             \
-        BUS_PROPERTIES_INTERFACE                                        \
-        BUS_PEER_INTERFACE                                              \
-        BUS_INTROSPECTABLE_INTERFACE                                    \
-        "</node>\n"
-
-#define INTERFACES_LIST                              \
-        BUS_UNIT_INTERFACES_LIST                     \
-        "org.freedesktop.systemd1.Slice\0"
-
-const char bus_slice_interface[] = BUS_SLICE_INTERFACE;
-
-DBusHandlerResult bus_slice_message_handler(Unit *u, DBusConnection *c, DBusMessage *message) {
-        Slice *s = SLICE(u);
-
-        const BusBoundProperties bps[] = {
-                { "org.freedesktop.systemd1.Unit",  bus_unit_properties,           u },
-                { "org.freedesktop.systemd1.Slice", bus_unit_cgroup_properties,    u },
-                { "org.freedesktop.systemd1.Slice", bus_cgroup_context_properties, &s->cgroup_context },
-                {}
-        };
-
-        SELINUX_UNIT_ACCESS_CHECK(u, c, message, "status");
-
-        return bus_default_message_handler(c, message, INTROSPECTION, INTERFACES_LIST, bps);
-}
+const sd_bus_vtable bus_slice_vtable[] = {
+        SD_BUS_VTABLE_START(0),
+        SD_BUS_VTABLE_END
+};
 
 int bus_slice_set_property(
                 Unit *u,
                 const char *name,
-                DBusMessageIter *i,
+                sd_bus_message *message,
                 UnitSetPropertiesMode mode,
-                DBusError *error) {
+                sd_bus_error *error) {
 
         Slice *s = SLICE(u);
-        int r;
 
         assert(name);
         assert(u);
-        assert(i);
-
-        r = bus_cgroup_set_property(u, &s->cgroup_context, name, i, mode, error);
-        if (r != 0)
-                return r;
 
-        return 0;
+        return bus_cgroup_set_property(u, &s->cgroup_context, name, message, mode, error);
 }
 
 int bus_slice_commit_properties(Unit *u) {
diff --git a/src/core/dbus-slice.h b/src/core/dbus-slice.h
index c5ac473..eadc3b1 100644
--- a/src/core/dbus-slice.h
+++ b/src/core/dbus-slice.h
@@ -21,13 +21,10 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <dbus/dbus.h>
-
+#include "sd-bus.h"
 #include "unit.h"
 
-DBusHandlerResult bus_slice_message_handler(Unit *u, DBusConnection *c, DBusMessage *message);
+extern const sd_bus_vtable bus_slice_vtable[];
 
-int bus_slice_set_property(Unit *u, const char *name, DBusMessageIter *i, UnitSetPropertiesMode mode, DBusError *error);
+int bus_slice_set_property(Unit *u, const char *name, sd_bus_message *message, UnitSetPropertiesMode mode, sd_bus_error *error);
 int bus_slice_commit_properties(Unit *u);
-
-extern const char bus_slice_interface[];
diff --git a/src/core/dbus-snapshot.c b/src/core/dbus-snapshot.c
index 9978df6..a4ba588 100644
--- a/src/core/dbus-snapshot.c
+++ b/src/core/dbus-snapshot.c
@@ -19,66 +19,29 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include "selinux-access.h"
+#include "unit.h"
+#include "snapshot.h"
 #include "dbus-unit.h"
 #include "dbus-snapshot.h"
-#include "dbus-common.h"
-#include "selinux-access.h"
-
-#define BUS_SNAPSHOT_INTERFACE                                          \
-        " <interface name=\"org.freedesktop.systemd1.Snapshot\">\n"     \
-        "  <method name=\"Remove\"/>\n"                                 \
-        "  <property name=\"Cleanup\" type=\"b\" access=\"read\"/>\n"   \
-        " </interface>\n"
-
-#define INTROSPECTION                                                   \
-        DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE                       \
-        "<node>\n"                                                      \
-        BUS_UNIT_INTERFACE                                              \
-        BUS_SNAPSHOT_INTERFACE                                          \
-        BUS_PROPERTIES_INTERFACE                                        \
-        BUS_PEER_INTERFACE                                              \
-        BUS_INTROSPECTABLE_INTERFACE                                    \
-        "</node>\n"
-
-#define INTERFACES_LIST                              \
-        BUS_UNIT_INTERFACES_LIST                     \
-        "org.freedesktop.systemd1.Snapshot\0"
-
-const char bus_snapshot_interface[] = BUS_SNAPSHOT_INTERFACE;
-
-static const BusProperty bus_snapshot_properties[] = {
-        { "Cleanup", bus_property_append_bool, "b", offsetof(Snapshot, cleanup) },
-        { NULL, }
-};
 
-DBusHandlerResult bus_snapshot_message_handler(Unit *u, DBusConnection *c, DBusMessage *message) {
-        Snapshot *s = SNAPSHOT(u);
-        _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
+int bus_snapshot_method_remove(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        Snapshot *s = userdata;
 
-        if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Snapshot", "Remove")) {
+        assert(bus);
+        assert(message);
+        assert(s);
 
-                SELINUX_UNIT_ACCESS_CHECK(u, c, message, "stop");
+        SELINUX_UNIT_ACCESS_CHECK(UNIT(s), bus, message, "stop");
 
-                reply = dbus_message_new_method_return(message);
-                if (!reply)
-                        return DBUS_HANDLER_RESULT_NEED_MEMORY;
+        snapshot_remove(s);
 
-                snapshot_remove(SNAPSHOT(u));
-
-        } else {
-                const BusBoundProperties bps[] = {
-                        { "org.freedesktop.systemd1.Unit",     bus_unit_properties,     u },
-                        { "org.freedesktop.systemd1.Snapshot", bus_snapshot_properties, s },
-                        { NULL, }
-                };
-
-                SELINUX_UNIT_ACCESS_CHECK(u, c, message, "status");
-
-                return bus_default_message_handler(c, message, INTROSPECTION, INTERFACES_LIST, bps);
-        }
-
-        if (!bus_maybe_send_reply(c, message, reply))
-                return DBUS_HANDLER_RESULT_NEED_MEMORY;
-
-        return DBUS_HANDLER_RESULT_HANDLED;
+        return sd_bus_reply_method_return(bus, message, NULL);
 }
+
+const sd_bus_vtable bus_snapshot_vtable[] = {
+        SD_BUS_VTABLE_START(0),
+        SD_BUS_METHOD("Remove", NULL, NULL, bus_snapshot_method_remove, 0),
+        SD_BUS_PROPERTY("Cleanup", "b", bus_property_get_bool, offsetof(Snapshot, cleanup), 0),
+        SD_BUS_VTABLE_END
+};
diff --git a/src/core/dbus-snapshot.h b/src/core/dbus-snapshot.h
index 1208aaf..f6f4322 100644
--- a/src/core/dbus-snapshot.h
+++ b/src/core/dbus-snapshot.h
@@ -21,10 +21,8 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <dbus/dbus.h>
+#include "sd-bus.h"
 
-#include "unit.h"
+extern const sd_bus_vtable bus_snapshot_vtable[];
 
-DBusHandlerResult bus_snapshot_message_handler(Unit *u, DBusConnection *c, DBusMessage *message);
-
-extern const char bus_snapshot_interface[];
+int bus_snapshot_method_remove(sd_bus *bus, sd_bus_message *message, void *userdata);
diff --git a/src/core/dbus-socket.c b/src/core/dbus-socket.c
index 60a8d05..e9fa24d 100644
--- a/src/core/dbus-socket.c
+++ b/src/core/dbus-socket.c
@@ -19,122 +19,50 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <errno.h>
-
+#include "unit.h"
+#include "socket.h"
 #include "dbus-unit.h"
 #include "dbus-execute.h"
 #include "dbus-kill.h"
 #include "dbus-cgroup.h"
-#include "dbus-common.h"
-#include "selinux-access.h"
 #include "dbus-socket.h"
+#include "bus-util.h"
+
+static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_result, socket_result, SocketResult);
+static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_bind_ipv6_only, socket_address_bind_ipv6_only, SocketAddressBindIPv6Only);
+
+static int property_get_listen(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
 
-#define BUS_SOCKET_INTERFACE                                            \
-        " <interface name=\"org.freedesktop.systemd1.Socket\">\n"       \
-        "  <property name=\"BindIPv6Only\" type=\"b\" access=\"read\"/>\n" \
-        "  <property name=\"Backlog\" type=\"u\" access=\"read\"/>\n"   \
-        "  <property name=\"TimeoutUSec\" type=\"t\" access=\"read\"/>\n" \
-        BUS_UNIT_CGROUP_INTERFACE                                       \
-        BUS_EXEC_COMMAND_INTERFACE("ExecStartPre")                      \
-        BUS_EXEC_COMMAND_INTERFACE("ExecStartPost")                     \
-        BUS_EXEC_COMMAND_INTERFACE("ExecStopPre")                       \
-        BUS_EXEC_COMMAND_INTERFACE("ExecStopPost")                      \
-        BUS_EXEC_CONTEXT_INTERFACE                                      \
-        BUS_KILL_CONTEXT_INTERFACE                                      \
-        BUS_CGROUP_CONTEXT_INTERFACE                                    \
-        "  <property name=\"ControlPID\" type=\"u\" access=\"read\"/>\n" \
-        "  <property name=\"BindToDevice\" type=\"s\" access=\"read\"/>\n" \
-        "  <property name=\"DirectoryMode\" type=\"u\" access=\"read\"/>\n" \
-        "  <property name=\"SocketMode\" type=\"u\" access=\"read\"/>\n" \
-        "  <property name=\"Accept\" type=\"b\" access=\"read\"/>\n"    \
-        "  <property name=\"KeepAlive\" type=\"b\" access=\"read\"/>\n" \
-        "  <property name=\"Priority\" type=\"i\" access=\"read\"/>\n"  \
-        "  <property name=\"ReceiveBuffer\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"SendBuffer\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"IPTOS\" type=\"i\" access=\"read\"/>\n"     \
-        "  <property name=\"IPTTL\" type=\"i\" access=\"read\"/>\n"     \
-        "  <property name=\"PipeSize\" type=\"t\" access=\"read\"/>\n"  \
-        "  <property name=\"FreeBind\" type=\"b\" access=\"read\"/>\n"  \
-        "  <property name=\"Transparent\" type=\"b\" access=\"read\"/>\n" \
-        "  <property name=\"Broadcast\" type=\"b\" access=\"read\"/>\n" \
-        "  <property name=\"PassCredentials\" type=\"b\" access=\"read\"/>\n" \
-        "  <property name=\"PassSecurity\" type=\"b\" access=\"read\"/>\n" \
-        "  <property name=\"Mark\" type=\"i\" access=\"read\"/>\n"      \
-        "  <property name=\"MaxConnections\" type=\"u\" access=\"read\"/>\n" \
-        "  <property name=\"NAccepted\" type=\"u\" access=\"read\"/>\n" \
-        "  <property name=\"NConnections\" type=\"u\" access=\"read\"/>\n" \
-        "  <property name=\"MessageQueueMaxMessages\" type=\"x\" access=\"read\"/>\n" \
-        "  <property name=\"MessageQueueMessageSize\" type=\"x\" access=\"read\"/>\n" \
-        "  <property name=\"Listen\" type=\"a(ss)\" access=\"read\"/>\n"    \
-        "  <property name=\"Result\" type=\"s\" access=\"read\"/>\n"    \
-        "  <property name=\"ReusePort\" type=\"b\" access=\"read\"/>\n" \
-        "  <property name=\"SmackLabel\" type=\"s\" access=\"read\"/>\n" \
-        "  <property name=\"SmackLabelIPIn\" type=\"s\" access=\"read\"/>\n" \
-        "  <property name=\"SmackLabelIPOut\" type=\"s\" access=\"read\"/>\n" \
-        " </interface>\n"                                               \
-
-#define INTROSPECTION                                                   \
-        DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE                       \
-        "<node>\n"                                                      \
-        BUS_UNIT_INTERFACE                                              \
-        BUS_SOCKET_INTERFACE                                            \
-        BUS_PROPERTIES_INTERFACE                                        \
-        BUS_PEER_INTERFACE                                              \
-        BUS_INTROSPECTABLE_INTERFACE                                    \
-        "</node>\n"
-
-#define INTERFACES_LIST                              \
-        BUS_UNIT_INTERFACES_LIST                     \
-        "org.freedesktop.systemd1.Socket\0"
-
-const char bus_socket_interface[] = BUS_SOCKET_INTERFACE;
-
-const char bus_socket_invalidating_properties[] =
-        "ExecStartPre\0"
-        "ExecStartPost\0"
-        "ExecStopPre\0"
-        "ExecStopPost\0"
-        "ControlPID\0"
-        "NAccepted\0"
-        "NConnections\0"
-        "Result\0";
-
-static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_socket_append_bind_ipv6_only, socket_address_bind_ipv6_only, SocketAddressBindIPv6Only);
-static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_socket_append_socket_result, socket_result, SocketResult);
-
-static int bus_socket_append_listen(DBusMessageIter *i, const char *property, void *data) {
-
-        Socket *s = SOCKET(data);
+
+        Socket *s = SOCKET(userdata);
         SocketPort *p;
-        DBusMessageIter array, stru;
+        int r;
 
-        assert(data);
-        assert(property);
+        assert(bus);
+        assert(reply);
         assert(s);
 
-        if (!dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, "(ss)", &array))
-                return log_oom();
+        r = sd_bus_message_open_container(reply, 'a', "(ss)");
+        if (r < 0)
+                return r;
 
         LIST_FOREACH(port, p, s->ports) {
-                const char *type = socket_port_type_to_string(p);
                 _cleanup_free_ char *address = NULL;
                 const char *a;
 
-                if (!dbus_message_iter_open_container(&array, DBUS_TYPE_STRUCT, NULL, &stru))
-                        return log_oom();
-
-                if (!dbus_message_iter_append_basic(&stru, DBUS_TYPE_STRING, &type))
-                        return log_oom();
-
                 switch (p->type) {
                         case SOCKET_SOCKET: {
-                                int r;
-
                                 r = socket_address_print(&p->address, &address);
-                                if (r) {
-                                        log_error("socket_address_print failed: %s", strerror(-r));
+                                if (r)
                                         return r;
-                                }
+
                                 a = address;
                                 break;
                         }
@@ -146,98 +74,80 @@ static int bus_socket_append_listen(DBusMessageIter *i, const char *property, vo
                                 break;
 
                         default:
-                                a = type;
+                                assert_not_reached("Unknown socket type");
                 }
 
-                if (!dbus_message_iter_append_basic(&stru, DBUS_TYPE_STRING, &a))
-                        return -ENOMEM;
-
-                if (!dbus_message_iter_close_container(&array, &stru))
-                        return -ENOMEM;
+                r = sd_bus_message_append(reply, "(ss)", socket_port_type_to_string(p), a);
+                if (r < 0)
+                        return r;
         }
 
-        if (!dbus_message_iter_close_container(i, &array))
-                return -ENOMEM;
-
-        return 0;
+        return sd_bus_message_close_container(reply);
 }
 
-static const BusProperty bus_socket_properties[] = {
-        { "BindIPv6Only",   bus_socket_append_bind_ipv6_only,  "s", offsetof(Socket, bind_ipv6_only)  },
-        { "Backlog",        bus_property_append_unsigned,      "u", offsetof(Socket, backlog)         },
-        { "TimeoutUSec",    bus_property_append_usec,          "t", offsetof(Socket, timeout_usec)    },
-        BUS_EXEC_COMMAND_PROPERTY("ExecStartPre",  offsetof(Socket, exec_command[SOCKET_EXEC_START_PRE]),  true ),
-        BUS_EXEC_COMMAND_PROPERTY("ExecStartPost", offsetof(Socket, exec_command[SOCKET_EXEC_START_POST]), true ),
-        BUS_EXEC_COMMAND_PROPERTY("ExecStopPre",   offsetof(Socket, exec_command[SOCKET_EXEC_STOP_PRE]),   true ),
-        BUS_EXEC_COMMAND_PROPERTY("ExecStopPost",  offsetof(Socket, exec_command[SOCKET_EXEC_STOP_POST]),  true ),
-        { "ControlPID",     bus_property_append_pid,           "u", offsetof(Socket, control_pid)     },
-        { "BindToDevice",   bus_property_append_string,        "s", offsetof(Socket, bind_to_device), true },
-        { "DirectoryMode",  bus_property_append_mode,          "u", offsetof(Socket, directory_mode)  },
-        { "SocketMode",     bus_property_append_mode,          "u", offsetof(Socket, socket_mode)     },
-        { "Accept",         bus_property_append_bool,          "b", offsetof(Socket, accept)          },
-        { "KeepAlive",      bus_property_append_bool,          "b", offsetof(Socket, keep_alive)      },
-        { "Priority",       bus_property_append_int,           "i", offsetof(Socket, priority)        },
-        { "ReceiveBuffer",  bus_property_append_size,          "t", offsetof(Socket, receive_buffer)  },
-        { "SendBuffer",     bus_property_append_size,          "t", offsetof(Socket, send_buffer)     },
-        { "IPTOS",          bus_property_append_int,           "i", offsetof(Socket, ip_tos)          },
-        { "IPTTL",          bus_property_append_int,           "i", offsetof(Socket, ip_ttl)          },
-        { "PipeSize",       bus_property_append_size,          "t", offsetof(Socket, pipe_size)       },
-        { "FreeBind",       bus_property_append_bool,          "b", offsetof(Socket, free_bind)       },
-        { "Transparent",    bus_property_append_bool,          "b", offsetof(Socket, transparent)     },
-        { "Broadcast",      bus_property_append_bool,          "b", offsetof(Socket, broadcast)       },
-        { "PassCredentials",bus_property_append_bool,          "b", offsetof(Socket, pass_cred)       },
-        { "PassSecurity",   bus_property_append_bool,          "b", offsetof(Socket, pass_sec)        },
-        { "Listen",         bus_socket_append_listen,      "a(ss)", 0,                                },
-        { "Mark",           bus_property_append_int,           "i", offsetof(Socket, mark)            },
-        { "MaxConnections", bus_property_append_unsigned,      "u", offsetof(Socket, max_connections) },
-        { "NConnections",   bus_property_append_unsigned,      "u", offsetof(Socket, n_connections)   },
-        { "NAccepted",      bus_property_append_unsigned,      "u", offsetof(Socket, n_accepted)      },
-        { "MessageQueueMaxMessages", bus_property_append_long, "x", offsetof(Socket, mq_maxmsg)       },
-        { "MessageQueueMessageSize", bus_property_append_long, "x", offsetof(Socket, mq_msgsize)      },
-        { "Result",         bus_socket_append_socket_result,   "s", offsetof(Socket, result)          },
-        { "ReusePort",      bus_property_append_bool,          "b", offsetof(Socket, reuseport)       },
-        { "SmackLabel",     bus_property_append_string,        "s", offsetof(Socket, smack),          true },
-        { "SmackLabelIPIn", bus_property_append_string,        "s", offsetof(Socket, smack_ip_in),    true },
-        { "SmackLabelIPOut",bus_property_append_string,        "s", offsetof(Socket, smack_ip_out),   true },
-        {}
+const sd_bus_vtable bus_socket_vtable[] = {
+        SD_BUS_VTABLE_START(0),
+        SD_BUS_PROPERTY("BindIPv6Only", "s", property_get_bind_ipv6_only, offsetof(Socket, bind_ipv6_only), 0),
+        SD_BUS_PROPERTY("Backlog", "u", bus_property_get_unsigned, offsetof(Socket, backlog), 0),
+        SD_BUS_PROPERTY("TimeoutUSec", "t", bus_property_get_usec, offsetof(Socket, timeout_usec), 0),
+        SD_BUS_PROPERTY("ControlPID", "u", bus_property_get_pid, offsetof(Socket, control_pid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+        SD_BUS_PROPERTY("BindToDevice", "s", NULL, offsetof(Socket, bind_to_device), 0),
+        SD_BUS_PROPERTY("DirectoryMode", "u", bus_property_get_mode, offsetof(Socket, directory_mode), 0),
+        SD_BUS_PROPERTY("SocketMode", "u", bus_property_get_mode, offsetof(Socket, socket_mode), 0),
+        SD_BUS_PROPERTY("Accept", "b", bus_property_get_bool, offsetof(Socket, accept), 0),
+        SD_BUS_PROPERTY("KeepAlive", "b", bus_property_get_bool, offsetof(Socket, keep_alive), 0),
+        SD_BUS_PROPERTY("Priority", "i", bus_property_get_int, offsetof(Socket, priority), 0),
+        SD_BUS_PROPERTY("ReceiveBuffer", "t", bus_property_get_size, offsetof(Socket, receive_buffer), 0),
+        SD_BUS_PROPERTY("SendBuffer", "t", bus_property_get_size, offsetof(Socket, send_buffer), 0),
+        SD_BUS_PROPERTY("IPTOS", "i", bus_property_get_int, offsetof(Socket, ip_tos), 0),
+        SD_BUS_PROPERTY("IPTTL", "i", bus_property_get_int, offsetof(Socket, ip_ttl), 0),
+        SD_BUS_PROPERTY("PipeSize", "t", bus_property_get_size, offsetof(Socket, pipe_size), 0),
+        SD_BUS_PROPERTY("FreeBind", "b", bus_property_get_bool, offsetof(Socket, free_bind), 0),
+        SD_BUS_PROPERTY("Transparent", "b", bus_property_get_bool, offsetof(Socket, transparent), 0),
+        SD_BUS_PROPERTY("Broadcast", "b", bus_property_get_bool, offsetof(Socket, broadcast), 0),
+        SD_BUS_PROPERTY("PassCredentials", "b", bus_property_get_bool, offsetof(Socket, pass_cred), 0),
+        SD_BUS_PROPERTY("PassSecurity", "b", bus_property_get_bool, offsetof(Socket, pass_sec), 0),
+        SD_BUS_PROPERTY("Listen", "a(ss)", property_get_listen, 0, 0),
+        SD_BUS_PROPERTY("Mark", "i", bus_property_get_int, offsetof(Socket, mark), 0),
+        SD_BUS_PROPERTY("MaxConnections", "u", bus_property_get_unsigned, offsetof(Socket, max_connections), 0),
+        SD_BUS_PROPERTY("NConnections", "u", bus_property_get_unsigned, offsetof(Socket, n_connections), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+        SD_BUS_PROPERTY("NAccepted", "u", bus_property_get_unsigned, offsetof(Socket, n_accepted), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+        SD_BUS_PROPERTY("MessageQueueMaxMessages", "x", bus_property_get_long, offsetof(Socket, mq_maxmsg), 0),
+        SD_BUS_PROPERTY("MessageQueueMessageSize", "x", bus_property_get_long, offsetof(Socket, mq_msgsize), 0),
+        SD_BUS_PROPERTY("Result", "s", property_get_result, offsetof(Socket, result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+        SD_BUS_PROPERTY("ReusePort", "b",  bus_property_get_bool, offsetof(Socket, reuse_port), 0),
+        SD_BUS_PROPERTY("SmackLabel", "s", NULL, offsetof(Socket, smack), 0),
+        SD_BUS_PROPERTY("SmackLabelIPIn", "s", NULL, offsetof(Socket, smack_ip_in), 0),
+        SD_BUS_PROPERTY("SmackLabelIPOut", "s", NULL, offsetof(Socket, smack_ip_out), 0),
+        BUS_EXEC_COMMAND_VTABLE("ExecStartPre", offsetof(Socket, exec_command[SOCKET_EXEC_START_PRE]), 0),
+        BUS_EXEC_COMMAND_VTABLE("ExecStartPost", offsetof(Socket, exec_command[SOCKET_EXEC_START_POST]), 0),
+        BUS_EXEC_COMMAND_VTABLE("ExecStopPre", offsetof(Socket, exec_command[SOCKET_EXEC_STOP_PRE]), 0),
+        BUS_EXEC_COMMAND_VTABLE("ExecStopPost", offsetof(Socket, exec_command[SOCKET_EXEC_STOP_POST]), 0),
+        SD_BUS_VTABLE_END
 };
 
-DBusHandlerResult bus_socket_message_handler(Unit *u, DBusConnection *c, DBusMessage *message) {
-        Socket *s = SOCKET(u);
-        const BusBoundProperties bps[] = {
-                { "org.freedesktop.systemd1.Unit",   bus_unit_properties,           u },
-                { "org.freedesktop.systemd1.Socket", bus_unit_cgroup_properties,    u },
-                { "org.freedesktop.systemd1.Socket", bus_socket_properties,         s },
-                { "org.freedesktop.systemd1.Socket", bus_exec_context_properties,   &s->exec_context },
-                { "org.freedesktop.systemd1.Socket", bus_kill_context_properties,   &s->kill_context },
-                { "org.freedesktop.systemd1.Socket", bus_cgroup_context_properties, &s->cgroup_context },
-                {}
-        };
-
-        SELINUX_UNIT_ACCESS_CHECK(u, c, message, "status");
-
-        return bus_default_message_handler(c, message, INTROSPECTION, INTERFACES_LIST, bps);
-}
+const char* const bus_socket_changing_properties[] = {
+        "ControlPID",
+        "NAccepted",
+        "NConnections",
+        "Result",
+        NULL
+};
 
 int bus_socket_set_property(
                 Unit *u,
                 const char *name,
-                DBusMessageIter *i,
+                sd_bus_message *message,
                 UnitSetPropertiesMode mode,
-                DBusError *error) {
+                sd_bus_error *error) {
 
         Socket *s = SOCKET(u);
-        int r;
 
+        assert(s);
         assert(name);
-        assert(u);
-        assert(i);
+        assert(message);
 
-        r = bus_cgroup_set_property(u, &s->cgroup_context, name, i, mode, error);
-        if (r != 0)
-                return r;
-
-        return 0;
+        return bus_cgroup_set_property(u, &s->cgroup_context, name, message, mode, error);
 }
 
 int bus_socket_commit_properties(Unit *u) {
diff --git a/src/core/dbus-socket.h b/src/core/dbus-socket.h
index eb035c1..8808fa2 100644
--- a/src/core/dbus-socket.h
+++ b/src/core/dbus-socket.h
@@ -21,14 +21,11 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <dbus/dbus.h>
-
+#include "sd-bus.h"
 #include "unit.h"
 
-DBusHandlerResult bus_socket_message_handler(Unit *u, DBusConnection *c, DBusMessage *message);
+extern const sd_bus_vtable bus_socket_vtable[];
+extern const char* const bus_socket_changing_properties[];
 
-int bus_socket_set_property(Unit *u, const char *name, DBusMessageIter *i, UnitSetPropertiesMode mode, DBusError *error);
+int bus_socket_set_property(Unit *u, const char *name, sd_bus_message *message, UnitSetPropertiesMode mode, sd_bus_error *error);
 int bus_socket_commit_properties(Unit *u);
-
-extern const char bus_socket_interface[];
-extern const char bus_socket_invalidating_properties[];
diff --git a/src/core/dbus-swap.c b/src/core/dbus-swap.c
index 0da86bd..15292cd 100644
--- a/src/core/dbus-swap.c
+++ b/src/core/dbus-swap.c
@@ -20,125 +20,77 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <errno.h>
-
+#include "unit.h"
+#include "swap.h"
 #include "dbus-unit.h"
 #include "dbus-execute.h"
 #include "dbus-kill.h"
 #include "dbus-cgroup.h"
-#include "dbus-common.h"
-#include "selinux-access.h"
 #include "dbus-swap.h"
-
-#define BUS_SWAP_INTERFACE                                              \
-        " <interface name=\"org.freedesktop.systemd1.Swap\">\n"         \
-        "  <property name=\"What\" type=\"s\" access=\"read\"/>\n"      \
-        "  <property name=\"Priority\" type=\"i\" access=\"read\"/>\n"  \
-        "  <property name=\"TimeoutUSec\" type=\"t\" access=\"read\"/>\n" \
-        BUS_UNIT_CGROUP_INTERFACE                                       \
-        BUS_EXEC_COMMAND_INTERFACE("ExecActivate")                      \
-        BUS_EXEC_COMMAND_INTERFACE("ExecDeactivate")                    \
-        BUS_EXEC_CONTEXT_INTERFACE                                      \
-        BUS_KILL_CONTEXT_INTERFACE                                      \
-        BUS_CGROUP_CONTEXT_INTERFACE                                    \
-        "  <property name=\"ControlPID\" type=\"u\" access=\"read\"/>\n" \
-        "  <property name=\"Result\" type=\"s\" access=\"read\"/>\n"    \
-        " </interface>\n"
-
-#define INTROSPECTION                                                   \
-        DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE                       \
-        "<node>\n"                                                      \
-        BUS_UNIT_INTERFACE                                              \
-        BUS_SWAP_INTERFACE                                              \
-        BUS_PROPERTIES_INTERFACE                                        \
-        BUS_PEER_INTERFACE                                              \
-        BUS_INTROSPECTABLE_INTERFACE                                    \
-        "</node>\n"
-
-#define INTERFACES_LIST                              \
-        BUS_UNIT_INTERFACES_LIST                     \
-        "org.freedesktop.systemd1.Swap\0"
-
-const char bus_swap_interface[] = BUS_SWAP_INTERFACE;
-
-const char bus_swap_invalidating_properties[] =
-        "What\0"
-        "Priority\0"
-        "ExecActivate\0"
-        "ExecDeactivate\0"
-        "ControlPID\0"
-        "Result\0";
-
-static int bus_swap_append_priority(DBusMessageIter *i, const char *property, void *data) {
-        Swap *s = data;
-        dbus_int32_t j;
-
-        assert(i);
-        assert(property);
+#include "bus-util.h"
+
+static int property_get_priority(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
+
+        Swap *s = SWAP(userdata);
+        int p;
+
+        assert(bus);
+        assert(reply);
         assert(s);
 
         if (s->from_proc_swaps)
-                j = s->parameters_proc_swaps.priority;
+                p = s->parameters_proc_swaps.priority;
         else if (s->from_fragment)
-                j = s->parameters_fragment.priority;
+                p = s->parameters_fragment.priority;
         else
-                j = -1;
-
-        if (!dbus_message_iter_append_basic(i, DBUS_TYPE_INT32, &j))
-                return -ENOMEM;
+                p = -1;
 
-        return 0;
+        return sd_bus_message_append(reply, "i", p);
 }
 
-static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_swap_append_swap_result, swap_result, SwapResult);
-
-static const BusProperty bus_swap_properties[] = {
-        { "What",       bus_property_append_string, "s", offsetof(Swap, what),  true },
-        { "Priority",   bus_swap_append_priority,   "i", 0 },
-        { "TimeoutUSec",bus_property_append_usec,   "t", offsetof(Swap, timeout_usec)},
-        BUS_EXEC_COMMAND_PROPERTY("ExecActivate",   offsetof(Swap, exec_command[SWAP_EXEC_ACTIVATE]),   false),
-        BUS_EXEC_COMMAND_PROPERTY("ExecDeactivate", offsetof(Swap, exec_command[SWAP_EXEC_DEACTIVATE]), false),
-        { "ControlPID", bus_property_append_pid,    "u", offsetof(Swap, control_pid) },
-        { "Result",     bus_swap_append_swap_result,"s", offsetof(Swap, result)      },
-        { NULL, }
+static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_result, swap_result, SwapResult);
+
+const sd_bus_vtable bus_swap_vtable[] = {
+        SD_BUS_VTABLE_START(0),
+        SD_BUS_PROPERTY("What", "s", NULL, offsetof(Swap, what), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+        SD_BUS_PROPERTY("Priority", "i", property_get_priority, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+        SD_BUS_PROPERTY("TimeoutUSec", "t", bus_property_get_usec, offsetof(Swap, timeout_usec), 0),
+        SD_BUS_PROPERTY("ControlPID", "u", bus_property_get_pid, offsetof(Swap, control_pid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+        SD_BUS_PROPERTY("Result", "s", property_get_result, offsetof(Swap, result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+        BUS_EXEC_COMMAND_VTABLE("ExecActivate", offsetof(Swap, exec_command[SWAP_EXEC_ACTIVATE]), 0),
+        BUS_EXEC_COMMAND_VTABLE("ExecDeactivate", offsetof(Swap, exec_command[SWAP_EXEC_DEACTIVATE]), 0),
+        SD_BUS_VTABLE_END
 };
 
-DBusHandlerResult bus_swap_message_handler(Unit *u, DBusConnection *c, DBusMessage *message) {
-        Swap *s = SWAP(u);
-        const BusBoundProperties bps[] = {
-                { "org.freedesktop.systemd1.Unit", bus_unit_properties,           u },
-                { "org.freedesktop.systemd1.Swap", bus_unit_cgroup_properties,    u },
-                { "org.freedesktop.systemd1.Swap", bus_swap_properties,           s },
-                { "org.freedesktop.systemd1.Swap", bus_exec_context_properties,   &s->exec_context },
-                { "org.freedesktop.systemd1.Swap", bus_kill_context_properties,   &s->kill_context },
-                { "org.freedesktop.systemd1.Swap", bus_cgroup_context_properties, &s->cgroup_context },
-                { NULL, }
-        };
-
-        SELINUX_UNIT_ACCESS_CHECK(u, c, message, "status");
-
-        return bus_default_message_handler(c, message, INTROSPECTION, INTERFACES_LIST, bps);
-}
+const char* const bus_swap_changing_properties[] = {
+        "What",
+        "Priority",
+        "ControlPID",
+        "Result",
+        NULL
+};
 
 int bus_swap_set_property(
                 Unit *u,
                 const char *name,
-                DBusMessageIter *i,
+                sd_bus_message *message,
                 UnitSetPropertiesMode mode,
-                DBusError *error) {
+                sd_bus_error *error) {
 
         Swap *s = SWAP(u);
-        int r;
 
+        assert(s);
         assert(name);
-        assert(u);
-        assert(i);
+        assert(message);
 
-        r = bus_cgroup_set_property(u, &s->cgroup_context, name, i, mode, error);
-        if (r != 0)
-                return r;
-
-        return 0;
+        return bus_cgroup_set_property(u, &s->cgroup_context, name, message, mode, error);
 }
 
 int bus_swap_commit_properties(Unit *u) {
diff --git a/src/core/dbus-swap.h b/src/core/dbus-swap.h
index 9b586a1..5d35737 100644
--- a/src/core/dbus-swap.h
+++ b/src/core/dbus-swap.h
@@ -22,14 +22,11 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <dbus/dbus.h>
-
+#include "sd-bus.h"
 #include "unit.h"
 
-DBusHandlerResult bus_swap_message_handler(Unit *u, DBusConnection *c, DBusMessage *message);
+extern const sd_bus_vtable bus_swap_vtable[];
+extern const char* const bus_swap_changing_properties[];
 
-int bus_swap_set_property(Unit *u, const char *name, DBusMessageIter *i, UnitSetPropertiesMode mode, DBusError *error);
+int bus_swap_set_property(Unit *u, const char *name, sd_bus_message *message, UnitSetPropertiesMode mode, sd_bus_error *error);
 int bus_swap_commit_properties(Unit *u);
-
-extern const char bus_swap_interface[];
-extern const char bus_swap_invalidating_properties[];
diff --git a/src/core/dbus-target.c b/src/core/dbus-target.c
index f143d89..205d1c4 100644
--- a/src/core/dbus-target.c
+++ b/src/core/dbus-target.c
@@ -19,40 +19,12 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <errno.h>
-
+#include "unit.h"
+#include "target.h"
 #include "dbus-unit.h"
 #include "dbus-target.h"
-#include "dbus-common.h"
-#include "selinux-access.h"
-
-#define BUS_TARGET_INTERFACE                                            \
-        " <interface name=\"org.freedesktop.systemd1.Target\">\n"       \
-        " </interface>\n"
-
-#define INTROSPECTION                                                   \
-        DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE                       \
-        "<node>\n"                                                      \
-        BUS_UNIT_INTERFACE                                              \
-        BUS_TARGET_INTERFACE                                            \
-        BUS_PROPERTIES_INTERFACE                                        \
-        BUS_PEER_INTERFACE                                              \
-        BUS_INTROSPECTABLE_INTERFACE                                    \
-        "</node>\n"
-
-#define INTERFACES_LIST                              \
-        BUS_UNIT_INTERFACES_LIST                     \
-        "org.freedesktop.systemd1.Target\0"
-
-const char bus_target_interface[] = BUS_TARGET_INTERFACE;
-
-DBusHandlerResult bus_target_message_handler(Unit *u, DBusConnection *c, DBusMessage *message) {
-        const BusBoundProperties bps[] = {
-                { "org.freedesktop.systemd1.Unit", bus_unit_properties, u },
-                { NULL, }
-        };
-
-        SELINUX_UNIT_ACCESS_CHECK(u, c, message, "status");
 
-        return bus_default_message_handler(c, message, INTROSPECTION, INTERFACES_LIST, bps);
-}
+const sd_bus_vtable bus_target_vtable[] = {
+        SD_BUS_VTABLE_START(0),
+        SD_BUS_VTABLE_END
+};
diff --git a/src/core/dbus-target.h b/src/core/dbus-target.h
index a8a0304..6be9c9f 100644
--- a/src/core/dbus-target.h
+++ b/src/core/dbus-target.h
@@ -21,10 +21,6 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <dbus/dbus.h>
+#include "sd-bus.h"
 
-#include "unit.h"
-
-DBusHandlerResult bus_target_message_handler(Unit *u, DBusConnection *c, DBusMessage *message);
-
-extern const char bus_target_interface[];
+extern const sd_bus_vtable bus_target_vtable[];
diff --git a/src/core/dbus-timer.c b/src/core/dbus-timer.c
index c6f1dd9..113c63f 100644
--- a/src/core/dbus-timer.c
+++ b/src/core/dbus-timer.c
@@ -19,173 +19,136 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <errno.h>
-
+#include "unit.h"
+#include "timer.h"
 #include "dbus-unit.h"
 #include "dbus-timer.h"
-#include "dbus-execute.h"
-#include "dbus-common.h"
-#include "selinux-access.h"
-
-#define BUS_TIMER_INTERFACE                                             \
-        " <interface name=\"org.freedesktop.systemd1.Timer\">\n"        \
-        "  <property name=\"Unit\" type=\"s\" access=\"read\"/>\n"      \
-        "  <property name=\"TimersMonotonic\" type=\"a(stt)\" access=\"read\"/>\n" \
-        "  <property name=\"TimersCalendar\" type=\"a(sst)\" access=\"read\"/>\n" \
-        "  <property name=\"NextElapseUSecRealtime\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"NextElapseUSecMonotonic\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"Result\" type=\"s\" access=\"read\"/>\n"    \
-        " </interface>\n"
-
-#define INTROSPECTION                                                   \
-        DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE                       \
-        "<node>\n"                                                      \
-        BUS_UNIT_INTERFACE                                              \
-        BUS_TIMER_INTERFACE                                             \
-        BUS_PROPERTIES_INTERFACE                                        \
-        BUS_PEER_INTERFACE                                              \
-        BUS_INTROSPECTABLE_INTERFACE                                    \
-        "</node>\n"
-
-#define INTERFACES_LIST                              \
-        BUS_UNIT_INTERFACES_LIST                     \
-        "org.freedesktop.systemd1.Timer\0"
-
-const char bus_timer_interface[] = BUS_TIMER_INTERFACE;
-
-const char bus_timer_invalidating_properties[] =
-        "TimersMonotonic\0"
-        "TimersRealtime\0"
-        "NextElapseUSecRealtime\0"
-        "NextElapseUSecMonotonic\0"
-        "Result\0";
-
-static int bus_timer_append_monotonic_timers(DBusMessageIter *i, const char *property, void *data) {
-        Timer *p = data;
-        DBusMessageIter sub, sub2;
-        TimerValue *k;
-
-        assert(i);
-        assert(property);
-        assert(p);
-
-        if (!dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, "(stt)", &sub))
-                return -ENOMEM;
-
-        LIST_FOREACH(value, k, p->values) {
+#include "bus-util.h"
+
+static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_result, timer_result, TimerResult);
+
+static int property_get_monotonic_timers(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
+
+        Timer *t = userdata;
+        TimerValue *v;
+        int r;
+
+        assert(bus);
+        assert(reply);
+        assert(t);
+
+        r = sd_bus_message_open_container(reply, 'a', "(stt)");
+        if (r < 0)
+                return r;
+
+        LIST_FOREACH(value, v, t->values) {
                 _cleanup_free_ char *buf = NULL;
-                const char *t;
+                const char *s;
                 size_t l;
-                bool b;
 
-                if (k->base == TIMER_CALENDAR)
+                if (v->base == TIMER_CALENDAR)
                         continue;
 
-                t = timer_base_to_string(k->base);
-                assert(endswith(t, "Sec"));
+                s = timer_base_to_string(v->base);
+                assert(endswith(s, "Sec"));
 
                 /* s/Sec/USec/ */
-                l = strlen(t);
+                l = strlen(s);
                 buf = new(char, l+2);
                 if (!buf)
                         return -ENOMEM;
 
-                memcpy(buf, t, l-3);
+                memcpy(buf, s, l-3);
                 memcpy(buf+l-3, "USec", 5);
 
-                b = dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) &&
-                        dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &buf) &&
-                        dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT64, &k->value) &&
-                        dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT64, &k->next_elapse) &&
-                        dbus_message_iter_close_container(&sub, &sub2);
-
-                if (!b)
-                        return -ENOMEM;
+                r = sd_bus_message_append(reply, "(stt)", buf, v->value, v->next_elapse);
+                if (r < 0)
+                        return r;
         }
 
-        if (!dbus_message_iter_close_container(i, &sub))
-                return -ENOMEM;
-
-        return 0;
+        return sd_bus_message_close_container(reply);
 }
 
-static int bus_timer_append_calendar_timers(DBusMessageIter *i, const char *property, void *data) {
-        Timer *p = data;
-        DBusMessageIter sub, sub2;
-        TimerValue *k;
+static int property_get_calendar_timers(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
 
-        assert(i);
-        assert(property);
-        assert(p);
+        Timer *t = userdata;
+        TimerValue *v;
+        int r;
 
-        if (!dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, "(sst)", &sub))
-                return -ENOMEM;
+        assert(bus);
+        assert(reply);
+        assert(t);
 
-        LIST_FOREACH(value, k, p->values) {
+        r = sd_bus_message_open_container(reply, 'a', "(sst)");
+        if (r < 0)
+                return r;
+
+        LIST_FOREACH(value, v, t->values) {
                 _cleanup_free_ char *buf = NULL;
-                const char *t;
-                bool b;
-                int j;
 
-                if (k->base != TIMER_CALENDAR)
+                if (v->base != TIMER_CALENDAR)
                         continue;
 
-                t = timer_base_to_string(k->base);
-                j = calendar_spec_to_string(k->calendar_spec, &buf);
-                if (j < 0)
-                        return j;
-
-                b = dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) &&
-                        dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &t) &&
-                        dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &buf) &&
-                        dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT64, &k->next_elapse) &&
-                        dbus_message_iter_close_container(&sub, &sub2);
+                r = calendar_spec_to_string(v->calendar_spec, &buf);
+                if (r < 0)
+                        return r;
 
-                if (!b)
-                        return -ENOMEM;
+                r = sd_bus_message_append(reply, "(sst)", timer_base_to_string(v->base), buf, v->next_elapse);
+                if (r < 0)
+                        return r;
         }
 
-        if (!dbus_message_iter_close_container(i, &sub))
-                return -ENOMEM;
-
-        return 0;
+        return sd_bus_message_close_container(reply);
 }
 
-static int bus_timer_append_unit(DBusMessageIter *i, const char *property, void *data) {
-        Unit *u = data, *trigger;
-        const char *t;
+static int property_get_unit(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
+
+        Unit *u = userdata, *trigger;
 
-        assert(i);
-        assert(property);
+        assert(bus);
+        assert(reply);
         assert(u);
 
         trigger = UNIT_TRIGGER(u);
-        t = trigger ? trigger->id : "";
 
-        return dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &t) ? 0 : -ENOMEM;
+        return sd_bus_message_append(reply, "s", trigger ? trigger->id : "");
 }
 
-static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_timer_append_timer_result, timer_result, TimerResult);
-
-static const BusProperty bus_timer_properties[] = {
-        { "Unit",                    bus_timer_append_unit,             "s",      0 },
-        { "TimersMonotonic",         bus_timer_append_monotonic_timers, "a(stt)", 0 },
-        { "TimersCalendar",          bus_timer_append_calendar_timers,  "a(sst)", 0 },
-        { "NextElapseUSecMonotonic", bus_property_append_usec,          "t",      offsetof(Timer, next_elapse_monotonic) },
-        { "NextElapseUSecRealtime",  bus_property_append_usec,          "t",      offsetof(Timer, next_elapse_realtime) },
-        { "Result",                  bus_timer_append_timer_result,     "s",      offsetof(Timer, result) },
-        { NULL, }
+const sd_bus_vtable bus_timer_vtable[] = {
+        SD_BUS_VTABLE_START(0),
+        SD_BUS_PROPERTY("Unit", "s", property_get_unit, 0, 0),
+        SD_BUS_PROPERTY("TimersMonotonic", "a(stt)", property_get_monotonic_timers, 0, 0),
+        SD_BUS_PROPERTY("TimersCalendar", "a(sst)", property_get_calendar_timers, 0, 0),
+        SD_BUS_PROPERTY("NextElapseUSecRealtime", "t", bus_property_get_usec, offsetof(Timer, next_elapse_monotonic), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+        SD_BUS_PROPERTY("NextElapseUSecMonotonic", "t", bus_property_get_usec, offsetof(Timer, next_elapse_realtime), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+        SD_BUS_PROPERTY("Result", "s", property_get_result, offsetof(Timer, result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+        SD_BUS_VTABLE_END
 };
 
-DBusHandlerResult bus_timer_message_handler(Unit *u, DBusConnection *c, DBusMessage *message) {
-        Timer *t = TIMER(u);
-        const BusBoundProperties bps[] = {
-                { "org.freedesktop.systemd1.Unit",  bus_unit_properties,  u },
-                { "org.freedesktop.systemd1.Timer", bus_timer_properties, t },
-                { NULL, }
-        };
-
-        SELINUX_UNIT_ACCESS_CHECK(u, c, message, "status");
-
-        return bus_default_message_handler(c, message, INTROSPECTION, INTERFACES_LIST, bps);
-}
+const char* const bus_timer_changing_properties[] = {
+        "NextElapseUSecRealtime",
+        "NextElapseUSecMonotonic",
+        "Result",
+        NULL
+};
diff --git a/src/core/dbus-timer.h b/src/core/dbus-timer.h
index 9ac3050..ddd311c 100644
--- a/src/core/dbus-timer.h
+++ b/src/core/dbus-timer.h
@@ -21,11 +21,7 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <dbus/dbus.h>
+#include "sd-bus.h"
 
-#include "unit.h"
-
-DBusHandlerResult bus_timer_message_handler(Unit *u, DBusConnection *c, DBusMessage *message);
-
-extern const char bus_timer_interface[];
-extern const char bus_timer_invalidating_properties[];
+extern const sd_bus_vtable bus_timer_vtable[];
+extern const char* const bus_timer_changing_properties[];
diff --git a/src/core/dbus-unit.c b/src/core/dbus-unit.c
index 032915d..4905478 100644
--- a/src/core/dbus-unit.c
+++ b/src/core/dbus-unit.c
@@ -19,609 +19,645 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <errno.h>
-
-#include "dbus.h"
+#include "sd-bus.h"
 #include "log.h"
-#include "dbus-unit.h"
-#include "bus-errors.h"
-#include "dbus-common.h"
 #include "selinux-access.h"
 #include "cgroup-util.h"
 #include "strv.h"
 #include "path-util.h"
 #include "fileio.h"
+#include "dbus-unit.h"
+#include "dbus-manager.h"
+#include "bus-errors.h"
+#include "dbus-client-track.h"
+
+static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_load_state, unit_load_state, UnitLoadState);
+
+static int property_get_names(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
+
+        Unit *u = userdata;
+        Iterator i;
+        const char *t;
+        int r;
 
-const char bus_unit_interface[] = BUS_UNIT_INTERFACE;
-
-#define INVALIDATING_PROPERTIES                 \
-        "LoadState\0"                           \
-        "ActiveState\0"                         \
-        "SubState\0"                            \
-        "InactiveExitTimestamp\0"               \
-        "ActiveEnterTimestamp\0"                \
-        "ActiveExitTimestamp\0"                 \
-        "InactiveEnterTimestamp\0"              \
-        "Job\0"                                 \
-        "NeedDaemonReload\0"
-
-static int bus_unit_append_names(DBusMessageIter *i, const char *property, void *data) {
-        char *t;
-        Iterator j;
-        DBusMessageIter sub;
-        Unit *u = data;
-
-        if (!dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, "s", &sub))
-                return -ENOMEM;
+        assert(bus);
+        assert(reply);
+        assert(u);
 
-        SET_FOREACH(t, u->names, j)
-                if (!dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &t))
-                        return -ENOMEM;
+        r = sd_bus_message_open_container(reply, 'a', "s");
+        if (r < 0)
+                return r;
 
-        if (!dbus_message_iter_close_container(i, &sub))
-                return -ENOMEM;
+        SET_FOREACH(t, u->names, i) {
+                r = sd_bus_message_append(reply, "s", t);
+                if (r < 0)
+                        return r;
+        }
 
-        return 0;
+        return sd_bus_message_close_container(reply);
 }
 
-static int bus_unit_append_following(DBusMessageIter *i, const char *property, void *data) {
-        Unit *u = data, *f;
-        const char *d;
+static int property_get_following(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
+
+        Unit *u = userdata, *f;
 
-        assert(i);
-        assert(property);
+        assert(bus);
+        assert(reply);
         assert(u);
 
         f = unit_following(u);
-        d = f ? f->id : "";
-
-        if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &d))
-                return -ENOMEM;
-
-        return 0;
+        return sd_bus_message_append(reply, "s", f ? f->id : "");
 }
 
-static int bus_unit_append_slice(DBusMessageIter *i, const char *property, void *data) {
-        Unit *u = data;
-        const char *d;
-
-        assert(i);
-        assert(property);
-        assert(u);
-
-        d = strempty(unit_slice_name(u));
-
-        if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &d))
-                return -ENOMEM;
+static int property_get_dependencies(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
 
-        return 0;
-}
-
-static int bus_unit_append_dependencies(DBusMessageIter *i, const char *property, void *data) {
-        Unit *u;
+        Set *s = *(Set**) userdata;
         Iterator j;
-        DBusMessageIter sub;
-        Set *s = data;
+        Unit *u;
+        int r;
 
-        if (!dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, "s", &sub))
-                return -ENOMEM;
+        assert(bus);
+        assert(reply);
 
-        SET_FOREACH(u, s, j)
-                if (!dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &u->id))
-                        return -ENOMEM;
+        r = sd_bus_message_open_container(reply, 'a', "s");
+        if (r < 0)
+                return r;
 
-        if (!dbus_message_iter_close_container(i, &sub))
-                return -ENOMEM;
+        SET_FOREACH(u, s, j) {
+                r = sd_bus_message_append(reply, "s", u->id);
+                if (r < 0)
+                        return r;
+        }
 
-        return 0;
+        return sd_bus_message_close_container(reply);
 }
 
-static int bus_unit_append_description(DBusMessageIter *i, const char *property, void *data) {
-        Unit *u = data;
-        const char *d;
+static int property_get_description(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
 
-        assert(i);
-        assert(property);
-        assert(u);
-
-        d = unit_description(u);
+        Unit *u = userdata;
 
-        if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &d))
-                return -ENOMEM;
+        assert(bus);
+        assert(reply);
+        assert(u);
 
-        return 0;
+        return sd_bus_message_append(reply, "s", unit_description(u));
 }
 
-static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_unit_append_load_state, unit_load_state, UnitLoadState);
+static int property_get_active_state(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
 
-static int bus_unit_append_active_state(DBusMessageIter *i, const char *property, void *data) {
-        Unit *u = data;
-        const char *state;
+        Unit *u = userdata;
 
-        assert(i);
-        assert(property);
+        assert(bus);
+        assert(reply);
         assert(u);
 
-        state = unit_active_state_to_string(unit_active_state(u));
-
-        if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &state))
-                return -ENOMEM;
-
-        return 0;
+        return sd_bus_message_append(reply, "s", unit_active_state_to_string(unit_active_state(u)));
 }
 
-static int bus_unit_append_sub_state(DBusMessageIter *i, const char *property, void *data) {
-        Unit *u = data;
-        const char *state;
-
-        assert(i);
-        assert(property);
-        assert(u);
+static int property_get_sub_state(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
 
-        state = unit_sub_state_to_string(u);
+        Unit *u = userdata;
 
-        if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &state))
-                return -ENOMEM;
+        assert(bus);
+        assert(reply);
+        assert(u);
 
-        return 0;
+        return sd_bus_message_append(reply, "s", unit_sub_state_to_string(u));
 }
 
-static int bus_unit_append_file_state(DBusMessageIter *i, const char *property, void *data) {
-        Unit *u = data;
-        const char *state;
+static int property_get_unit_file_state(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
 
-        assert(i);
-        assert(property);
-        assert(u);
+        Unit *u = userdata;
 
-        state = strempty(unit_file_state_to_string(unit_get_unit_file_state(u)));
-
-        if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &state))
-                return -ENOMEM;
+        assert(bus);
+        assert(reply);
+        assert(u);
 
-        return 0;
+        return sd_bus_message_append(reply, "s", unit_file_state_to_string(unit_get_unit_file_state(u)));
 }
 
-static int bus_unit_append_can_start(DBusMessageIter *i, const char *property, void *data) {
-        Unit *u = data;
-        dbus_bool_t b;
-
-        assert(i);
-        assert(property);
-        assert(u);
+static int property_get_can_start(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
 
-        b = unit_can_start(u) &&
-                !u->refuse_manual_start;
+        Unit *u = userdata;
 
-        if (!dbus_message_iter_append_basic(i, DBUS_TYPE_BOOLEAN, &b))
-                return -ENOMEM;
+        assert(bus);
+        assert(reply);
+        assert(u);
 
-        return 0;
+        return sd_bus_message_append(reply, "b", unit_can_start(u) && !u->refuse_manual_start);
 }
 
-static int bus_unit_append_can_stop(DBusMessageIter *i, const char *property, void *data) {
-        Unit *u = data;
-        dbus_bool_t b;
+static int property_get_can_stop(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
+
+        Unit *u = userdata;
 
-        assert(i);
-        assert(property);
+        assert(bus);
+        assert(reply);
         assert(u);
 
         /* On the lower levels we assume that every unit we can start
          * we can also stop */
 
-        b = unit_can_start(u) &&
-                !u->refuse_manual_stop;
-
-        if (!dbus_message_iter_append_basic(i, DBUS_TYPE_BOOLEAN, &b))
-                return -ENOMEM;
-
-        return 0;
+        return sd_bus_message_append(reply, "b", unit_can_start(u) && !u->refuse_manual_stop);
 }
 
-static int bus_unit_append_can_reload(DBusMessageIter *i, const char *property, void *data) {
-        Unit *u = data;
-        dbus_bool_t b;
+static int property_get_can_reload(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
 
-        assert(i);
-        assert(property);
-        assert(u);
-
-        b = unit_can_reload(u);
+        Unit *u = userdata;
 
-        if (!dbus_message_iter_append_basic(i, DBUS_TYPE_BOOLEAN, &b))
-                return -ENOMEM;
+        assert(bus);
+        assert(reply);
+        assert(u);
 
-        return 0;
+        return sd_bus_message_append(reply, "b", unit_can_reload(u));
 }
 
-static int bus_unit_append_can_isolate(DBusMessageIter *i, const char *property, void *data) {
-        Unit *u = data;
-        dbus_bool_t b;
+static int property_get_can_isolate(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
 
-        assert(i);
-        assert(property);
-        assert(u);
-
-        b = unit_can_isolate(u) &&
-                !u->refuse_manual_start;
+        Unit *u = userdata;
 
-        if (!dbus_message_iter_append_basic(i, DBUS_TYPE_BOOLEAN, &b))
-                return -ENOMEM;
+        assert(bus);
+        assert(reply);
+        assert(u);
 
-        return 0;
+        return sd_bus_message_append(reply, "b", unit_can_isolate(u) && !u->refuse_manual_start);
 }
 
-static int bus_unit_append_job(DBusMessageIter *i, const char *property, void *data) {
-        Unit *u = data;
-        DBusMessageIter sub;
+static int property_get_job(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
+
         _cleanup_free_ char *p = NULL;
+        Unit *u = userdata;
 
-        assert(i);
-        assert(property);
+        assert(bus);
+        assert(reply);
         assert(u);
 
-        if (!dbus_message_iter_open_container(i, DBUS_TYPE_STRUCT, NULL, &sub))
-                return -ENOMEM;
-
-        if (u->job) {
+        if (!u->job)
+                return sd_bus_message_append(reply, "(uo)", 0, "/");
 
-                p = job_dbus_path(u->job);
-                if (!p)
-                        return -ENOMEM;
-
-                if (!dbus_message_iter_append_basic(&sub, DBUS_TYPE_UINT32, &u->job->id) ||
-                    !dbus_message_iter_append_basic(&sub, DBUS_TYPE_OBJECT_PATH, &p))
-                        return -ENOMEM;
-        } else {
-                uint32_t id = 0;
+        p = job_dbus_path(u->job);
+        if (!p)
+                return -ENOMEM;
 
-                /* No job, so let's fill in some placeholder
-                 * data. Since we need to fill in a valid path we
-                 * simple point to ourselves. */
+        return sd_bus_message_append(reply, "(uo)", u->job->id, p);
+}
 
-                p = unit_dbus_path(u);
-                if (!p)
-                        return -ENOMEM;
+static int property_get_need_daemon_reload(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
 
-                if (!dbus_message_iter_append_basic(&sub, DBUS_TYPE_UINT32, &id) ||
-                    !dbus_message_iter_append_basic(&sub, DBUS_TYPE_OBJECT_PATH, &p))
-                        return -ENOMEM;
-        }
+        Unit *u = userdata;
 
-        if (!dbus_message_iter_close_container(i, &sub))
-                return -ENOMEM;
+        assert(bus);
+        assert(reply);
+        assert(u);
 
-        return 0;
+        return sd_bus_message_append(reply, "b", unit_need_daemon_reload(u));
 }
 
-static int bus_unit_append_need_daemon_reload(DBusMessageIter *i, const char *property, void *data) {
-        Unit *u = data;
-        dbus_bool_t b;
+static int property_get_conditions(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
 
-        assert(i);
-        assert(property);
-        assert(u);
+        Unit *u = userdata;
+        Condition *c;
+        int r;
 
-        b = unit_need_daemon_reload(u);
+        assert(bus);
+        assert(reply);
+        assert(u);
 
-        if (!dbus_message_iter_append_basic(i, DBUS_TYPE_BOOLEAN, &b))
-                return -ENOMEM;
+        r = sd_bus_message_open_container(reply, 'a', "(sbbsi)");
+        if (r < 0)
+                return r;
 
-        return 0;
-}
+        LIST_FOREACH(conditions, c, u->conditions) {
+                r = sd_bus_message_append(reply, "sbbsi", condition_type_to_string(c->type), c->trigger, c->negate, c->parameter, c->state);
+                if (r < 0)
+                        return r;
 
-static int bus_property_append_condition(DBusMessageIter *i, const char *property, void *data) {
-        Condition **cp = data;
-        Condition *c;
-        const char *name, *param;
-        dbus_bool_t trigger, negate;
-        dbus_int32_t state;
-        DBusMessageIter sub;
-
-        assert(i);
-        assert(property);
-        assert(cp);
-
-        c = *cp;
-        assert(c);
-
-        name = condition_type_to_string(c->type);
-        param = c->parameter;
-        trigger = c->trigger;
-        negate = c->negate;
-        state = c->state;
-
-        if (!dbus_message_iter_open_container(i, DBUS_TYPE_STRUCT, NULL, &sub) ||
-            !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &name) ||
-            !dbus_message_iter_append_basic(&sub, DBUS_TYPE_BOOLEAN, &trigger) ||
-            !dbus_message_iter_append_basic(&sub, DBUS_TYPE_BOOLEAN, &negate) ||
-            !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &param) ||
-            !dbus_message_iter_append_basic(&sub, DBUS_TYPE_INT32, &state) ||
-            !dbus_message_iter_close_container(i, &sub))
-                return -ENOMEM;
+        }
 
-        return 0;
+        return sd_bus_message_close_container(reply);
 }
 
-static int bus_property_append_condition_list(DBusMessageIter *i, const char *property, void *data) {
-        Condition **first = data, *c;
-        DBusMessageIter sub;
-
-        assert(i);
-        assert(data);
+static int property_get_load_error(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
 
-        if (!dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, "(sbbsi)", &sub))
-                return -ENOMEM;
+        _cleanup_bus_error_free_ sd_bus_error e = SD_BUS_ERROR_NULL;
+        Unit *u = userdata;
 
-        LIST_FOREACH(conditions, c, *first)
-                bus_property_append_condition(&sub, property, &c);
+        assert(bus);
+        assert(reply);
+        assert(u);
 
-        if (!dbus_message_iter_close_container(i, &sub))
-                return -ENOMEM;
+        if (u->load_error != 0)
+                sd_bus_error_set_errno(&e, u->load_error);
 
-        return 0;
+        return sd_bus_message_append(reply, "(ss)", e.name, e.message);
 }
 
-static int bus_unit_append_load_error(DBusMessageIter *i, const char *property, void *data) {
-        Unit *u = data;
-        const char *name, *message;
-        DBusMessageIter sub;
+int bus_unit_method_start_generic(sd_bus *bus, sd_bus_message *message, Unit *u, JobType job_type, bool reload_if_possible) {
+        const char *smode;
+        JobMode mode;
+        int r;
 
-        assert(i);
-        assert(property);
+        assert(bus);
+        assert(message);
         assert(u);
+        assert(job_type >= 0 && job_type < _JOB_TYPE_MAX);
 
-        if (u->load_error != 0) {
-                name = bus_errno_to_dbus(u->load_error);
-                message = strempty(strerror(-u->load_error));
-        } else
-                name = message = "";
+        r = sd_bus_message_read(message, "s", &smode);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
 
-        if (!dbus_message_iter_open_container(i, DBUS_TYPE_STRUCT, NULL, &sub) ||
-            !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &name) ||
-            !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &message) ||
-            !dbus_message_iter_close_container(i, &sub))
-                return -ENOMEM;
+        mode = job_mode_from_string(smode);
+        if (mode < 0)
+                return sd_bus_reply_method_errorf(bus, message, SD_BUS_ERROR_INVALID_ARGS, "Job mode %s invalid", smode);
 
-        return 0;
+        return bus_unit_queue_job(bus, message, u, job_type, mode, reload_if_possible);
 }
 
-static DBusHandlerResult bus_unit_message_dispatch(Unit *u, DBusConnection *connection, DBusMessage *message) {
-        _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
-        DBusError error;
-        JobType job_type = _JOB_TYPE_INVALID;
-        bool reload_if_possible = false;
-        int r;
+static int method_start(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        return bus_unit_method_start_generic(bus, message, userdata, JOB_START, false);
+}
 
-        dbus_error_init(&error);
-
-        if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Unit", "Start"))
-                job_type = JOB_START;
-        else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Unit", "Stop"))
-                job_type = JOB_STOP;
-        else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Unit", "Reload"))
-                job_type = JOB_RELOAD;
-        else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Unit", "Restart"))
-                job_type = JOB_RESTART;
-        else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Unit", "TryRestart"))
-                job_type = JOB_TRY_RESTART;
-        else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Unit", "ReloadOrRestart")) {
-                reload_if_possible = true;
-                job_type = JOB_RESTART;
-        } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Unit", "ReloadOrTryRestart")) {
-                reload_if_possible = true;
-                job_type = JOB_TRY_RESTART;
-        } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Unit", "Kill")) {
-                const char *swho;
-                int32_t signo;
-                KillWho who;
-
-                if (!dbus_message_get_args(
-                                    message,
-                                    &error,
-                                    DBUS_TYPE_STRING, &swho,
-                                    DBUS_TYPE_INT32, &signo,
-                                    DBUS_TYPE_INVALID))
-                        return bus_send_error_reply(connection, message, &error, -EINVAL);
-
-                if (isempty(swho))
-                        who = KILL_ALL;
-                else {
-                        who = kill_who_from_string(swho);
-                        if (who < 0)
-                                return bus_send_error_reply(connection, message, &error, -EINVAL);
-                }
+static int method_stop(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        return bus_unit_method_start_generic(bus, message, userdata, JOB_STOP, false);
+}
+
+static int method_reload(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        return bus_unit_method_start_generic(bus, message, userdata, JOB_RELOAD, false);
+}
 
-                if (signo <= 0 || signo >= _NSIG)
-                        return bus_send_error_reply(connection, message, &error, -EINVAL);
+static int method_restart(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        return bus_unit_method_start_generic(bus, message, userdata, JOB_RESTART, false);
+}
 
-                SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "stop");
+static int method_try_restart(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        return bus_unit_method_start_generic(bus, message, userdata, JOB_TRY_RESTART, false);
+}
 
-                r = unit_kill(u, who, signo, &error);
-                if (r < 0)
-                        return bus_send_error_reply(connection, message, &error, r);
+static int method_reload_or_restart(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        return bus_unit_method_start_generic(bus, message, userdata, JOB_RESTART, true);
+}
 
-                reply = dbus_message_new_method_return(message);
-                if (!reply)
-                        goto oom;
+static int method_reload_or_try_restart(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        return bus_unit_method_start_generic(bus, message, userdata, JOB_TRY_RESTART, true);
+}
 
-        } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Unit", "ResetFailed")) {
+int bus_unit_method_kill(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        Unit *u = userdata;
+        const char *swho;
+        int32_t signo;
+        KillWho who;
+        int r;
 
-                SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "reload");
+        assert(bus);
+        assert(message);
+        assert(u);
 
-                unit_reset_failed(u);
+        r = sd_bus_message_read(message, "si", &swho, &signo);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
+
+        if (isempty(swho))
+                who = KILL_ALL;
+        else {
+                who = kill_who_from_string(swho);
+                if (who < 0)
+                        return sd_bus_reply_method_errorf(bus, message, SD_BUS_ERROR_INVALID_ARGS, "Invalid who argument %s", swho);
+        }
 
-                reply = dbus_message_new_method_return(message);
-                if (!reply)
-                        goto oom;
-        } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Unit", "SetProperties")) {
-                DBusMessageIter iter;
-                dbus_bool_t runtime;
+        if (signo <= 0 || signo >= _NSIG)
+                return sd_bus_reply_method_errorf(bus, message, SD_BUS_ERROR_INVALID_ARGS, "Signal number out of range.");
 
-                if (!dbus_message_iter_init(message, &iter))
-                        goto oom;
+        SELINUX_UNIT_ACCESS_CHECK(u, bus, message, "stop");
 
-                if (bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &runtime, true) < 0)
-                        return bus_send_error_reply(connection, message, NULL, -EINVAL);
+        r = unit_kill(u, who, signo, &error);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, &error);
 
-                SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "start");
+        return sd_bus_reply_method_return(bus, message, NULL);
+}
 
-                r = bus_unit_set_properties(u, &iter, runtime ? UNIT_RUNTIME : UNIT_PERSISTENT, true, &error);
-                if (r < 0)
-                        return bus_send_error_reply(connection, message, &error, r);
-
-                reply = dbus_message_new_method_return(message);
-                if (!reply)
-                        goto oom;
-
-        } else if (UNIT_VTABLE(u)->bus_message_handler)
-                return UNIT_VTABLE(u)->bus_message_handler(u, connection, message);
-        else
-                return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-
-        if (job_type != _JOB_TYPE_INVALID) {
-                const char *smode;
-                JobMode mode;
-
-                if (!dbus_message_get_args(
-                                    message,
-                                    &error,
-                                    DBUS_TYPE_STRING, &smode,
-                                    DBUS_TYPE_INVALID))
-                        return bus_send_error_reply(connection, message, &error, -EINVAL);
-
-                mode = job_mode_from_string(smode);
-                if (mode < 0) {
-                        dbus_set_error(&error, BUS_ERROR_INVALID_JOB_MODE, "Job mode %s is invalid.", smode);
-                        return bus_send_error_reply(connection, message, &error, -EINVAL);
-                }
+int bus_unit_method_reset_failed(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        Unit *u = userdata;
 
-                return bus_unit_queue_job(connection, message, u, job_type, mode, reload_if_possible);
-        }
+        assert(bus);
+        assert(message);
+        assert(u);
 
-        if (reply)
-                if (!bus_maybe_send_reply(connection, message, reply))
-                        goto oom;
+        SELINUX_UNIT_ACCESS_CHECK(u, bus, message, "reload");
 
-        return DBUS_HANDLER_RESULT_HANDLED;
+        unit_reset_failed(u);
 
-oom:
-        dbus_error_free(&error);
-        return DBUS_HANDLER_RESULT_NEED_MEMORY;
+        return sd_bus_reply_method_return(bus, message, NULL);
 }
 
-static DBusHandlerResult bus_unit_message_handler(DBusConnection *connection, DBusMessage  *message, void *data) {
-        Manager *m = data;
-        Unit *u;
-        int r;
-        _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
-        DBusError error;
+int bus_unit_method_set_properties(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        Unit *u = userdata;
+        int runtime, r;
 
-        assert(connection);
+        assert(bus);
         assert(message);
-        assert(m);
-
-        dbus_error_init(&error);
+        assert(u);
 
-        if (streq(dbus_message_get_path(message), "/org/freedesktop/systemd1/unit")) {
-                /* Be nice to gdbus and return introspection data for our mid-level paths */
+        r = sd_bus_message_read(message, "b", &runtime);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
 
-                SELINUX_ACCESS_CHECK(connection, message, "status");
+        SELINUX_UNIT_ACCESS_CHECK(u, bus, message, "start");
 
-                if (dbus_message_is_method_call(message, "org.freedesktop.DBus.Introspectable", "Introspect")) {
-                        char *introspection = NULL;
-                        FILE *f;
-                        Iterator i;
-                        const char *k;
-                        size_t size;
+        r = sd_bus_message_enter_container(message, 'a', "(sv)");
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
 
-                        reply = dbus_message_new_method_return(message);
-                        if (!reply)
-                                goto oom;
+        r = bus_unit_set_properties(u, message, runtime ? UNIT_RUNTIME : UNIT_PERSISTENT, true, &error);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, &error);
 
-                        /* We roll our own introspection code here, instead of
-                         * relying on bus_default_message_handler() because we
-                         * need to generate our introspection string
-                         * dynamically. */
+        r = sd_bus_message_exit_container(message);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
 
-                        f = open_memstream(&introspection, &size);
-                        if (!f)
-                                goto oom;
+        return sd_bus_reply_method_return(bus, message, NULL);
+}
 
-                        fputs(DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE
-                              "<node>\n", f);
+const sd_bus_vtable bus_unit_vtable[] = {
+        SD_BUS_VTABLE_START(0),
+
+        SD_BUS_PROPERTY("Id", "s", NULL, offsetof(Unit, id), 0),
+        SD_BUS_PROPERTY("Names", "as", property_get_names, 0, 0),
+        SD_BUS_PROPERTY("Following", "s", property_get_following, 0, 0),
+        SD_BUS_PROPERTY("Requires", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_REQUIRES]), 0),
+        SD_BUS_PROPERTY("RequiresOverridable", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_REQUIRES_OVERRIDABLE]), 0),
+        SD_BUS_PROPERTY("Requisite", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_REQUISITE]), 0),
+        SD_BUS_PROPERTY("RequisiteOverridable", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_REQUISITE_OVERRIDABLE]), 0),
+        SD_BUS_PROPERTY("Wants", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_WANTS]), 0),
+        SD_BUS_PROPERTY("BindsTo", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_BINDS_TO]), 0),
+        SD_BUS_PROPERTY("PartOf", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_PART_OF]), 0),
+        SD_BUS_PROPERTY("RequiredBy", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_REQUIRED_BY]), 0),
+        SD_BUS_PROPERTY("RequiredByOverridable", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_REQUIRED_BY_OVERRIDABLE]), 0),
+        SD_BUS_PROPERTY("WantedBy", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_WANTED_BY]), 0),
+        SD_BUS_PROPERTY("BoundBy", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_BOUND_BY]), 0),
+        SD_BUS_PROPERTY("ConsistsOf", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_CONSISTS_OF]), 0),
+        SD_BUS_PROPERTY("Conflicts", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_CONFLICTS]), 0),
+        SD_BUS_PROPERTY("ConflictedBy", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_CONFLICTED_BY]), 0),
+        SD_BUS_PROPERTY("Before", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_BEFORE]), 0),
+        SD_BUS_PROPERTY("After", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_AFTER]), 0),
+        SD_BUS_PROPERTY("OnFailure", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_ON_FAILURE]), 0),
+        SD_BUS_PROPERTY("Triggers", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_TRIGGERS]), 0),
+        SD_BUS_PROPERTY("TriggeredBy", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_TRIGGERED_BY]), 0),
+        SD_BUS_PROPERTY("PropagatesReloadTo", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_PROPAGATES_RELOAD_TO]), 0),
+        SD_BUS_PROPERTY("ReloadPropagatedFrom", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_RELOAD_PROPAGATED_FROM]), 0),
+        SD_BUS_PROPERTY("RequiresMountsFor", "as", NULL, offsetof(Unit, requires_mounts_for), 0),
+        SD_BUS_PROPERTY("Documentation", "as", NULL, offsetof(Unit, documentation), 0),
+        SD_BUS_PROPERTY("Description", "s", property_get_description, 0, 0),
+        SD_BUS_PROPERTY("LoadState", "s", property_get_load_state, offsetof(Unit, load_state), 0),
+        SD_BUS_PROPERTY("ActiveState", "s", property_get_active_state, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+        SD_BUS_PROPERTY("SubState", "s", property_get_sub_state, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+        SD_BUS_PROPERTY("FragmentPath", "s", NULL, offsetof(Unit, fragment_path), 0),
+        SD_BUS_PROPERTY("SourcePath", "s", NULL, offsetof(Unit, source_path), 0),
+        SD_BUS_PROPERTY("DropInPaths", "as", NULL, offsetof(Unit, dropin_paths), 0),
+        SD_BUS_PROPERTY("UnitFileState", "s", property_get_unit_file_state, 0, 0),
+        BUS_PROPERTY_DUAL_TIMESTAMP("InactiveExitTimestamp", offsetof(Unit, inactive_exit_timestamp), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+        BUS_PROPERTY_DUAL_TIMESTAMP("ActiveEnterTimestamp", offsetof(Unit, active_enter_timestamp), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+        BUS_PROPERTY_DUAL_TIMESTAMP("ActiveExitTimestamp", offsetof(Unit, active_exit_timestamp), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+        BUS_PROPERTY_DUAL_TIMESTAMP("InactiveEnterTimestamp", offsetof(Unit, inactive_enter_timestamp), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+        SD_BUS_PROPERTY("CanStart", "b", property_get_can_start, 0, 0),
+        SD_BUS_PROPERTY("CanStop", "b", property_get_can_stop, 0, 0),
+        SD_BUS_PROPERTY("CanReload", "b", property_get_can_reload, 0, 0),
+        SD_BUS_PROPERTY("CanIsolate", "b", property_get_can_isolate, 0, 0),
+        SD_BUS_PROPERTY("Job", "(uo)", property_get_job, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+        SD_BUS_PROPERTY("StopWhenUnneeded", "b", bus_property_get_bool, offsetof(Unit, stop_when_unneeded), 0),
+        SD_BUS_PROPERTY("RefuseManualStart", "b", bus_property_get_bool, offsetof(Unit, refuse_manual_start), 0),
+        SD_BUS_PROPERTY("RefuseManualStop", "b", bus_property_get_bool, offsetof(Unit, refuse_manual_stop), 0),
+        SD_BUS_PROPERTY("AllowIsolate", "b", bus_property_get_bool, offsetof(Unit, allow_isolate), 0),
+        SD_BUS_PROPERTY("DefaultDependencies", "b", bus_property_get_bool, offsetof(Unit, default_dependencies), 0),
+        SD_BUS_PROPERTY("OnFailureIsolate", "b", bus_property_get_bool, offsetof(Unit, on_failure_isolate), 0),
+        SD_BUS_PROPERTY("IgnoreOnIsolate", "b", bus_property_get_bool, offsetof(Unit, ignore_on_isolate), 0),
+        SD_BUS_PROPERTY("IgnoreOnSnapshot", "b", bus_property_get_bool, offsetof(Unit, ignore_on_snapshot), 0),
+        SD_BUS_PROPERTY("NeedDaemonReload", "b", property_get_need_daemon_reload, 0, 0),
+        SD_BUS_PROPERTY("JobTimeoutUSec", "t", bus_property_get_usec, offsetof(Unit, job_timeout), 0),
+        SD_BUS_PROPERTY("ConditionResult", "b", bus_property_get_bool, offsetof(Unit, condition_result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+        BUS_PROPERTY_DUAL_TIMESTAMP("ConditionTimestamp", offsetof(Unit, condition_timestamp), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+        SD_BUS_PROPERTY("Conditions", "a(sbbsi)", property_get_conditions, 0, 0),
+        SD_BUS_PROPERTY("LoadError", "(ss)", property_get_load_error, 0, 0),
+        SD_BUS_PROPERTY("Transient", "b", bus_property_get_bool, offsetof(Unit, transient), 0),
+
+        SD_BUS_METHOD("Start", "s", "o", method_start, 0),
+        SD_BUS_METHOD("Stop", "s", "o", method_stop, 0),
+        SD_BUS_METHOD("Reload", "s", "o", method_reload, 0),
+        SD_BUS_METHOD("Restart", "s", "o", method_restart, 0),
+        SD_BUS_METHOD("TryRestart", "s", "o", method_try_restart, 0),
+        SD_BUS_METHOD("ReloadOrRestart", "s", "o", method_reload_or_restart, 0),
+        SD_BUS_METHOD("ReloadOrTryRestart", "s", "o", method_reload_or_try_restart, 0),
+        SD_BUS_METHOD("Kill", "si", NULL, bus_unit_method_kill, 0),
+        SD_BUS_METHOD("ResetFailed", NULL, NULL, bus_unit_method_reset_failed, 0),
+        SD_BUS_METHOD("SetProperties", "ba(sv)", NULL, bus_unit_method_set_properties, 0),
+
+        SD_BUS_VTABLE_END
+};
 
-                        fputs(BUS_INTROSPECTABLE_INTERFACE, f);
-                        fputs(BUS_PEER_INTERFACE, f);
+static int property_get_slice(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
 
-                        HASHMAP_FOREACH_KEY(u, k, m->units, i) {
-                                char *p;
+        Unit *u = userdata;
 
-                                if (k != u->id)
-                                        continue;
+        assert(bus);
+        assert(reply);
+        assert(u);
 
-                                p = bus_path_escape(k);
-                                if (!p) {
-                                        fclose(f);
-                                        free(introspection);
-                                        goto oom;
-                                }
+        return sd_bus_message_append(reply, "s", unit_slice_name(u));
+}
 
-                                fprintf(f, "<node name=\"%s\"/>", p);
-                                free(p);
-                        }
+const sd_bus_vtable bus_unit_cgroup_vtable[] = {
+        SD_BUS_VTABLE_START(0),
+        SD_BUS_PROPERTY("Slice", "s", property_get_slice, 0, 0),
+        SD_BUS_PROPERTY("ControlGroup", "s", NULL, offsetof(Unit, cgroup_path), 0),
+        SD_BUS_VTABLE_END
+};
 
-                        fputs("</node>\n", f);
+static int send_new_signal(sd_bus *bus, const char *destination, void *userdata) {
+        _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+        _cleanup_free_ char *p = NULL;
+        Unit *u = userdata;
+        int r;
 
-                        if (ferror(f)) {
-                                fclose(f);
-                                free(introspection);
-                                goto oom;
-                        }
+        assert(bus);
+        assert(u);
 
-                        fclose(f);
+        p = unit_dbus_path(u);
+        if (!u)
+                return -ENOMEM;
 
-                        if (!introspection)
-                                goto oom;
+        r = sd_bus_message_new_signal(
+                        bus,
+                        "/org/freedesktop/systemd1",
+                        "org.freedesktop.systemd1.Manager",
+                        "UnitNew",
+                        &m);
+        if (r < 0)
+                return r;
 
-                        if (!dbus_message_append_args(reply, DBUS_TYPE_STRING, &introspection, DBUS_TYPE_INVALID)) {
-                                free(introspection);
-                                goto oom;
-                        }
+        r = sd_bus_message_append(m, "so", u->id, p);
+        if (r < 0)
+                return r;
 
-                        free(introspection);
+        return sd_bus_send_to(bus, m, destination, NULL);
+}
 
-                        if (!bus_maybe_send_reply(connection, message, reply))
-                                goto oom;
+static int send_changed_signal(sd_bus *bus, const char *destination, void *userdata) {
+        _cleanup_free_ char *p = NULL;
+        Unit *u = userdata;
+        int r;
 
-                        return DBUS_HANDLER_RESULT_HANDLED;
-                }
+        assert(bus);
+        assert(u);
 
-                return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-        }
+        p = unit_dbus_path(u);
+        if (!u)
+                return -ENOMEM;
 
-        r = manager_load_unit_from_dbus_path(m, dbus_message_get_path(message), &error, &u);
-        if (r == -ENOMEM)
-                goto oom;
-        if (r < 0)
-                return bus_send_error_reply(connection, message, &error, r);
+        /* Send a properties changed signal. First for the specific
+         * type, then for the generic unit. The clients may rely on
+         * this order to get atomic behavior if needed. */
 
-        return bus_unit_message_dispatch(u, connection, message);
+        if (UNIT_VTABLE(u)->bus_changing_properties) {
 
-oom:
-        dbus_error_free(&error);
+                r = sd_bus_emit_properties_changed_strv(
+                                bus, p,
+                                UNIT_VTABLE(u)->bus_interface,
+                                (char**) UNIT_VTABLE(u)->bus_changing_properties);
+                if (r < 0)
+                        return r;
+        }
 
-        return DBUS_HANDLER_RESULT_NEED_MEMORY;
+        return sd_bus_emit_properties_changed(
+                        bus, p,
+                        "org.freedesktop.systemd1.Unit",
+                        "ActiveState",
+                        "SubState",
+                        "InactiveExitTimestamp",
+                        "ActiveEnterTimestamp",
+                        "ActiveExitTimestamp",
+                        "InactiveEnterTimestamp",
+                        "Job",
+                        "ConditionResult",
+                        "ConditionTimestamp",
+                        NULL);
 }
 
-const DBusObjectPathVTable bus_unit_vtable = {
-        .message_function = bus_unit_message_handler
-};
-
 void bus_unit_send_change_signal(Unit *u) {
-        _cleanup_dbus_message_unref_ DBusMessage *m = NULL;
-        _cleanup_free_ char *p = NULL;
         int r;
 
         assert(u);
@@ -634,141 +670,77 @@ void bus_unit_send_change_signal(Unit *u) {
         if (!u->id)
                 return;
 
-        if (!bus_has_subscriber(u->manager)) {
-                u->sent_dbus_new_signal = true;
-                return;
-        }
-
-        p = unit_dbus_path(u);
-        if (!p) {
-                log_oom();
-                return;
-        }
-
-        if (u->sent_dbus_new_signal) {
-                /* Send a properties changed signal. First for the
-                 * specific type, then for the generic unit. The
-                 * clients may rely on this order to get atomic
-                 * behavior if needed. */
-
-                if (UNIT_VTABLE(u)->bus_invalidating_properties) {
-
-                        m = bus_properties_changed_new(p,
-                                                       UNIT_VTABLE(u)->bus_interface,
-                                                       UNIT_VTABLE(u)->bus_invalidating_properties);
-                        if (!m) {
-                                log_oom();
-                                return;
-                        }
-
-                        r = bus_broadcast(u->manager, m);
-                        if (r < 0) {
-                                log_error("Failed to broadcast change message: %s", strerror(-r));
-                                return;
-                        }
+        r = bus_manager_foreach_client(u->manager, u->sent_dbus_new_signal ? send_changed_signal : send_new_signal, u);
+        if (r < 0)
+                log_warning("Failed to send unit change signal for %s: %s", u->id, strerror(-r));
 
-                        dbus_message_unref(m);
-                }
+        u->sent_dbus_new_signal = true;
+}
 
-                m = bus_properties_changed_new(p, "org.freedesktop.systemd1.Unit",
-                                               INVALIDATING_PROPERTIES);
-                if (!m) {
-                        log_oom();
-                        return;
-                }
+static int send_removed_signal(sd_bus *bus, const char *destination, void *userdata) {
+        _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+        _cleanup_free_ char *p = NULL;
+        Unit *u = userdata;
+        int r;
 
-        } else {
-                /* Send a new signal */
+        assert(bus);
+        assert(u);
 
-                m = dbus_message_new_signal("/org/freedesktop/systemd1",
-                                            "org.freedesktop.systemd1.Manager",
-                                            "UnitNew");
-                if (!m) {
-                        log_oom();
-                        return;
-                }
+        p = unit_dbus_path(u);
+        if (!u)
+                return -ENOMEM;
 
-                if (!dbus_message_append_args(m,
-                                              DBUS_TYPE_STRING, &u->id,
-                                              DBUS_TYPE_OBJECT_PATH, &p,
-                                              DBUS_TYPE_INVALID)) {
-                        log_oom();
-                        return;
-                }
-        }
+        r = sd_bus_message_new_signal(
+                        bus,
+                        "/org/freedesktop/systemd1",
+                        "org.freedesktop.systemd1.Manager",
+                        "UnitRemoved",
+                        &m);
+        if (r < 0)
+                return r;
 
-        r = bus_broadcast(u->manager, m);
-        if (r < 0) {
-                log_error("Failed to broadcast UnitNew/PropertiesChanged message.");
-                return;
-        }
+        r = sd_bus_message_append(m, "so", u->id, p);
+        if (r < 0)
+                return r;
 
-        u->sent_dbus_new_signal = true;
+        return sd_bus_send_to(bus, m, destination, NULL);
 }
 
 void bus_unit_send_removed_signal(Unit *u) {
-        _cleanup_free_ char *p = NULL;
-        _cleanup_dbus_message_unref_ DBusMessage *m = NULL;
+        int r;
 
         assert(u);
 
-        if (!bus_has_subscriber(u->manager))
-                return;
-
         if (!u->sent_dbus_new_signal)
                 bus_unit_send_change_signal(u);
 
         if (!u->id)
                 return;
 
-        p = unit_dbus_path(u);
-        if (!p)
-                goto oom;
-
-        m = dbus_message_new_signal("/org/freedesktop/systemd1",
-                                    "org.freedesktop.systemd1.Manager",
-                                    "UnitRemoved");
-        if (!m)
-                goto oom;
-
-        if (!dbus_message_append_args(m,
-                                      DBUS_TYPE_STRING, &u->id,
-                                      DBUS_TYPE_OBJECT_PATH, &p,
-                                      DBUS_TYPE_INVALID))
-                goto oom;
-
-        if (bus_broadcast(u->manager, m) < 0)
-                goto oom;
-
-        return;
-
-oom:
-        log_oom();
+        r = bus_manager_foreach_client(u->manager, send_removed_signal, u);
+        if (r < 0)
+                log_warning("Failed to send unit change signal for %s: %s", u->id, strerror(-r));
 }
 
-DBusHandlerResult bus_unit_queue_job(
-                DBusConnection *connection,
-                DBusMessage *message,
+int bus_unit_queue_job(
+                sd_bus *bus,
+                sd_bus_message *message,
                 Unit *u,
                 JobType type,
                 JobMode mode,
                 bool reload_if_possible) {
 
-        _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
+        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
         _cleanup_free_ char *path = NULL;
         Job *j;
-        JobBusClient *cl;
-        DBusError error;
         int r;
 
-        assert(connection);
+        assert(bus);
         assert(message);
         assert(u);
         assert(type >= 0 && type < _JOB_TYPE_MAX);
         assert(mode >= 0 && mode < _JOB_MODE_MAX);
 
-        dbus_error_init(&error);
-
         if (reload_if_possible && unit_can_reload(u)) {
                 if (type == JOB_RESTART)
                         type = JOB_RELOAD_OR_START;
@@ -776,85 +748,61 @@ DBusHandlerResult bus_unit_queue_job(
                         type = JOB_RELOAD;
         }
 
-        SELINUX_UNIT_ACCESS_CHECK(u, connection, message,
+        SELINUX_UNIT_ACCESS_CHECK(u, bus, message,
                                   (type == JOB_START || type == JOB_RESTART || type == JOB_TRY_RESTART) ? "start" :
                                   type == JOB_STOP ? "stop" : "reload");
 
-        if (type == JOB_STOP && (u->load_state == UNIT_NOT_FOUND || u->load_state == UNIT_ERROR) && unit_active_state(u) == UNIT_INACTIVE) {
-                dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s not loaded.", u->id);
-                return bus_send_error_reply(connection, message, &error, -EPERM);
-        }
+        if (type == JOB_STOP &&
+            (u->load_state == UNIT_NOT_FOUND || u->load_state == UNIT_ERROR) &&
+            unit_active_state(u) == UNIT_INACTIVE)
+                return sd_bus_reply_method_errorf(bus, message, BUS_ERROR_NO_SUCH_UNIT, "Unit %s not loaded.", u->id);
 
         if ((type == JOB_START && u->refuse_manual_start) ||
             (type == JOB_STOP && u->refuse_manual_stop) ||
-            ((type == JOB_RESTART || type == JOB_TRY_RESTART) && (u->refuse_manual_start || u->refuse_manual_stop))) {
-                dbus_set_error(&error, BUS_ERROR_ONLY_BY_DEPENDENCY,
-                               "Operation refused, unit %s may be requested by dependency only.", u->id);
-                return bus_send_error_reply(connection, message, &error, -EPERM);
-        }
+            ((type == JOB_RESTART || type == JOB_TRY_RESTART) && (u->refuse_manual_start || u->refuse_manual_stop)))
+                return sd_bus_reply_method_errorf(bus, message, BUS_ERROR_ONLY_BY_DEPENDENCY, "Operation refused, unit %s may be requested by dependency only.", u->id);
 
         r = manager_add_job(u->manager, type, u, mode, true, &error, &j);
         if (r < 0)
-                return bus_send_error_reply(connection, message, &error, r);
-
-        cl = job_bus_client_new(connection, bus_message_get_sender_with_fallback(message));
-        if (!cl)
-                goto oom;
-
-        LIST_PREPEND(client, j->bus_client_list, cl);
+                return sd_bus_reply_method_errno(bus, message, r, &error);
 
-        reply = dbus_message_new_method_return(message);
-        if (!reply)
-                goto oom;
+        r = bus_client_track(&j->subscribed, bus, sd_bus_message_get_sender(message));
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
 
         path = job_dbus_path(j);
         if (!path)
-                goto oom;
-
-        if (!dbus_message_append_args(
-                            reply,
-                            DBUS_TYPE_OBJECT_PATH, &path,
-                            DBUS_TYPE_INVALID))
-                goto oom;
-
-        if (!bus_maybe_send_reply(connection, message, reply))
-                goto oom;
-
-        return DBUS_HANDLER_RESULT_HANDLED;
-
-oom:
-        dbus_error_free(&error);
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
 
-        return DBUS_HANDLER_RESULT_NEED_MEMORY;
+        return sd_bus_reply_method_return(bus, message, "o", path);
 }
 
 static int bus_unit_set_transient_property(
                 Unit *u,
                 const char *name,
-                DBusMessageIter *i,
+                sd_bus_message *message,
                 UnitSetPropertiesMode mode,
-                DBusError *error) {
+                sd_bus_error *error) {
 
         int r;
 
         assert(u);
         assert(name);
-        assert(i);
+        assert(message);
 
         if (streq(name, "Description")) {
-                if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_STRING)
-                        return -EINVAL;
-
-                if (mode != UNIT_CHECK) {
-                        const char *description;
+                const char *d;
 
-                        dbus_message_iter_get_basic(i, &description);
+                r = sd_bus_message_read(message, "s", &d);
+                if (r < 0)
+                        return r;
 
-                        r = unit_set_description(u, description);
+                if (mode != UNIT_CHECK) {
+                        r = unit_set_description(u, d);
                         if (r < 0)
                                 return r;
 
-                        unit_write_drop_in_format(u, mode, name, "[Unit]\nDescription=%s\n", description);
+                        unit_write_drop_in_format(u, mode, name, "[Unit]\nDescription=%s\n", d);
                 }
 
                 return 1;
@@ -862,10 +810,12 @@ static int bus_unit_set_transient_property(
         } else if (streq(name, "Slice") && unit_get_cgroup_context(u)) {
                 const char *s;
 
-                if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_STRING)
-                        return -EINVAL;
+                r = sd_bus_message_read(message, "s", &s);
+                if (r < 0)
+                        return r;
 
-                dbus_message_iter_get_basic(i, &s);
+                if (!unit_name_is_valid(s, false) || !endswith(s, ".slice"))
+                        return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid slice name %s", s);
 
                 if (isempty(s)) {
                         if (mode != UNIT_CHECK) {
@@ -905,24 +855,19 @@ static int bus_unit_set_transient_property(
                    streq(name, "PartOf")) {
 
                 UnitDependency d;
-                DBusMessageIter sub;
+                const char *other;
 
                 d = unit_dependency_from_string(name);
                 if (d < 0)
                         return -EINVAL;
 
-                if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_ARRAY ||
-                    dbus_message_iter_get_element_type(i) != DBUS_TYPE_STRING)
-                        return -EINVAL;
-
-                dbus_message_iter_recurse(i, &sub);
-                while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING) {
-                        const char *other;
-
-                        dbus_message_iter_get_basic(&sub, &other);
+                r = sd_bus_message_enter_container(message, 'a', "s");
+                if (r < 0)
+                        return r;
 
+                while ((r = sd_bus_message_read(message, "s", &other)) > 0) {
                         if (!unit_name_is_valid(other, false))
-                                return -EINVAL;
+                                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid unit name %s", other);
 
                         if (mode != UNIT_CHECK) {
                                 _cleanup_free_ char *label = NULL;
@@ -938,8 +883,9 @@ static int bus_unit_set_transient_property(
                                 unit_write_drop_in_format(u, mode, label, "[Unit]\n%s=%s\n", name, other);
                         }
 
-                        dbus_message_iter_next(&sub);
                 }
+                if (r < 0)
+                        return r;
 
                 return 1;
         }
@@ -949,18 +895,17 @@ static int bus_unit_set_transient_property(
 
 int bus_unit_set_properties(
                 Unit *u,
-                DBusMessageIter *iter,
+                sd_bus_message *message,
                 UnitSetPropertiesMode mode,
                 bool commit,
-                DBusError *error) {
+                sd_bus_error *error) {
 
         bool for_real = false;
-        DBusMessageIter sub;
         unsigned n = 0;
         int r;
 
         assert(u);
-        assert(iter);
+        assert(message);
 
         if (u->transient)
                 mode &= UNIT_RUNTIME;
@@ -970,52 +915,54 @@ int bus_unit_set_properties(
          * it. This is to implement transaction-like behaviour without
          * actually providing full transactions. */
 
-        if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY ||
-            dbus_message_iter_get_element_type(iter) != DBUS_TYPE_STRUCT)
-                return -EINVAL;
+        r = sd_bus_message_enter_container(message, 'a', "(sv)");
+        if (r < 0)
+                return r;
 
-        dbus_message_iter_recurse(iter, &sub);
         for (;;) {
-                DBusMessageIter sub2, sub3;
                 const char *name;
 
-                if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_INVALID) {
-
+                r = sd_bus_message_enter_container(message, 'r', "sv");
+                if (r < 0)
+                        return r;
+                if (r == 0) {
                         if (for_real || mode == UNIT_CHECK)
                                 break;
 
                         /* Reached EOF. Let's try again, and this time for realz... */
-                        dbus_message_iter_recurse(iter, &sub);
+                        r = sd_bus_message_rewind(message, false);
+                        if (r < 0)
+                                return r;
                         for_real = true;
                         continue;
                 }
 
-                if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT)
-                        return -EINVAL;
-
-                dbus_message_iter_recurse(&sub, &sub2);
+                r = sd_bus_message_read(message, "s", &name);
+                if (r < 0)
+                        return r;
 
-                if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0 ||
-                    dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT)
-                        return -EINVAL;
+                if (!UNIT_VTABLE(u)->bus_set_property)
+                        return sd_bus_error_setf(error, SD_BUS_ERROR_PROPERTY_READ_ONLY, "Objects of this type do not support setting properties.");
 
-                if (!UNIT_VTABLE(u)->bus_set_property) {
-                        dbus_set_error(error, DBUS_ERROR_PROPERTY_READ_ONLY, "Objects of this type do not support setting properties.");
-                        return -ENOENT;
-                }
+                r = sd_bus_message_enter_container(message, 'v', NULL);
+                if (r < 0)
+                        return r;
 
-                dbus_message_iter_recurse(&sub2, &sub3);
-                r = UNIT_VTABLE(u)->bus_set_property(u, name, &sub3, for_real ? mode : UNIT_CHECK, error);
+                r = UNIT_VTABLE(u)->bus_set_property(u, name, message, for_real ? mode : UNIT_CHECK, error);
                 if (r == 0 && u->transient && u->load_state == UNIT_STUB)
-                        r = bus_unit_set_transient_property(u, name, &sub3, for_real ? mode : UNIT_CHECK, error);
+                        r = bus_unit_set_transient_property(u, name, message, for_real ? mode : UNIT_CHECK, error);
+                if (r < 0)
+                        return r;
+                if (r == 0)
+                        return sd_bus_error_setf(error, SD_BUS_ERROR_PROPERTY_READ_ONLY, "Cannot set property %s, or unknown property.", name);
+
+                r = sd_bus_message_exit_container(message);
                 if (r < 0)
                         return r;
-                if (r == 0) {
-                        dbus_set_error(error, DBUS_ERROR_PROPERTY_READ_ONLY, "Cannot set property %s, or unknown property.", name);
-                        return -ENOENT;
-                }
 
-                dbus_message_iter_next(&sub);
+                r = sd_bus_message_exit_container(message);
+                if (r < 0)
+                        return r;
 
                 n += for_real;
         }
@@ -1025,76 +972,3 @@ int bus_unit_set_properties(
 
         return n;
 }
-
-const BusProperty bus_unit_properties[] = {
-        { "Id",                              bus_property_append_string,                "s", offsetof(Unit, id),                                         true },
-        { "Names",                           bus_unit_append_names,                    "as", 0                                                                },
-        { "Following",                       bus_unit_append_following,                 "s", 0                                                                },
-        { "Requires",                        bus_unit_append_dependencies,             "as", offsetof(Unit, dependencies[UNIT_REQUIRES]),                true },
-        { "RequiresOverridable",             bus_unit_append_dependencies,             "as", offsetof(Unit, dependencies[UNIT_REQUIRES_OVERRIDABLE]),    true },
-        { "Requisite",                       bus_unit_append_dependencies,             "as", offsetof(Unit, dependencies[UNIT_REQUISITE]),               true },
-        { "RequisiteOverridable",            bus_unit_append_dependencies,             "as", offsetof(Unit, dependencies[UNIT_REQUISITE_OVERRIDABLE]),   true },
-        { "Wants",                           bus_unit_append_dependencies,             "as", offsetof(Unit, dependencies[UNIT_WANTS]),                   true },
-        { "BindsTo",                         bus_unit_append_dependencies,             "as", offsetof(Unit, dependencies[UNIT_BINDS_TO]),                true },
-        { "PartOf",                          bus_unit_append_dependencies,             "as", offsetof(Unit, dependencies[UNIT_PART_OF]),                 true },
-        { "RequiredBy",                      bus_unit_append_dependencies,             "as", offsetof(Unit, dependencies[UNIT_REQUIRED_BY]),             true },
-        { "RequiredByOverridable",           bus_unit_append_dependencies,             "as", offsetof(Unit, dependencies[UNIT_REQUIRED_BY_OVERRIDABLE]), true },
-        { "WantedBy",                        bus_unit_append_dependencies,             "as", offsetof(Unit, dependencies[UNIT_WANTED_BY]),               true },
-        { "BoundBy",                         bus_unit_append_dependencies,             "as", offsetof(Unit, dependencies[UNIT_BOUND_BY]),                true },
-        { "ConsistsOf",                      bus_unit_append_dependencies,             "as", offsetof(Unit, dependencies[UNIT_CONSISTS_OF]),             true },
-        { "Conflicts",                       bus_unit_append_dependencies,             "as", offsetof(Unit, dependencies[UNIT_CONFLICTS]),               true },
-        { "ConflictedBy",                    bus_unit_append_dependencies,             "as", offsetof(Unit, dependencies[UNIT_CONFLICTED_BY]),           true },
-        { "Before",                          bus_unit_append_dependencies,             "as", offsetof(Unit, dependencies[UNIT_BEFORE]),                  true },
-        { "After",                           bus_unit_append_dependencies,             "as", offsetof(Unit, dependencies[UNIT_AFTER]),                   true },
-        { "OnFailure",                       bus_unit_append_dependencies,             "as", offsetof(Unit, dependencies[UNIT_ON_FAILURE]),              true },
-        { "Triggers",                        bus_unit_append_dependencies,             "as", offsetof(Unit, dependencies[UNIT_TRIGGERS]),                true },
-        { "TriggeredBy",                     bus_unit_append_dependencies,             "as", offsetof(Unit, dependencies[UNIT_TRIGGERED_BY]),            true },
-        { "PropagatesReloadTo",              bus_unit_append_dependencies,             "as", offsetof(Unit, dependencies[UNIT_PROPAGATES_RELOAD_TO]),    true },
-        { "ReloadPropagatedFrom",            bus_unit_append_dependencies,             "as", offsetof(Unit, dependencies[UNIT_RELOAD_PROPAGATED_FROM]),  true },
-        { "RequiresMountsFor",               bus_property_append_strv,                 "as", offsetof(Unit, requires_mounts_for),                        true },
-        { "Documentation",                   bus_property_append_strv,                 "as", offsetof(Unit, documentation),                              true },
-        { "Description",                     bus_unit_append_description,               "s", 0                                                                },
-        { "LoadState",                       bus_unit_append_load_state,                "s", offsetof(Unit, load_state)                                       },
-        { "ActiveState",                     bus_unit_append_active_state,              "s", 0                                                                },
-        { "SubState",                        bus_unit_append_sub_state,                 "s", 0                                                                },
-        { "FragmentPath",                    bus_property_append_string,                "s", offsetof(Unit, fragment_path),                              true },
-        { "SourcePath",                      bus_property_append_string,                "s", offsetof(Unit, source_path),                                true },
-        { "DropInPaths",                     bus_property_append_strv,                 "as", offsetof(Unit, dropin_paths),                               true },
-        { "UnitFileState",                   bus_unit_append_file_state,                "s", 0                                                                },
-        { "InactiveExitTimestamp",           bus_property_append_usec,                  "t", offsetof(Unit, inactive_exit_timestamp.realtime)                 },
-        { "InactiveExitTimestampMonotonic",  bus_property_append_usec,                  "t", offsetof(Unit, inactive_exit_timestamp.monotonic)                },
-        { "ActiveEnterTimestamp",            bus_property_append_usec,                  "t", offsetof(Unit, active_enter_timestamp.realtime)                  },
-        { "ActiveEnterTimestampMonotonic",   bus_property_append_usec,                  "t", offsetof(Unit, active_enter_timestamp.monotonic)                 },
-        { "ActiveExitTimestamp",             bus_property_append_usec,                  "t", offsetof(Unit, active_exit_timestamp.realtime)                   },
-        { "ActiveExitTimestampMonotonic",    bus_property_append_usec,                  "t", offsetof(Unit, active_exit_timestamp.monotonic)                  },
-        { "InactiveEnterTimestamp",          bus_property_append_usec,                  "t", offsetof(Unit, inactive_enter_timestamp.realtime)                },
-        { "InactiveEnterTimestampMonotonic", bus_property_append_usec,                  "t", offsetof(Unit, inactive_enter_timestamp.monotonic)               },
-        { "CanStart",                        bus_unit_append_can_start,                 "b", 0                                                                },
-        { "CanStop",                         bus_unit_append_can_stop,                  "b", 0                                                                },
-        { "CanReload",                       bus_unit_append_can_reload,                "b", 0                                                                },
-        { "CanIsolate",                      bus_unit_append_can_isolate,               "b", 0                                                                },
-        { "Job",                             bus_unit_append_job,                    "(uo)", 0                                                                },
-        { "StopWhenUnneeded",                bus_property_append_bool,                  "b", offsetof(Unit, stop_when_unneeded)                               },
-        { "RefuseManualStart",               bus_property_append_bool,                  "b", offsetof(Unit, refuse_manual_start)                              },
-        { "RefuseManualStop",                bus_property_append_bool,                  "b", offsetof(Unit, refuse_manual_stop)                               },
-        { "AllowIsolate",                    bus_property_append_bool,                  "b", offsetof(Unit, allow_isolate)                                    },
-        { "DefaultDependencies",             bus_property_append_bool,                  "b", offsetof(Unit, default_dependencies)                             },
-        { "OnFailureIsolate",                bus_property_append_bool,                  "b", offsetof(Unit, on_failure_isolate)                               },
-        { "IgnoreOnIsolate",                 bus_property_append_bool,                  "b", offsetof(Unit, ignore_on_isolate)                                },
-        { "IgnoreOnSnapshot",                bus_property_append_bool,                  "b", offsetof(Unit, ignore_on_snapshot)                               },
-        { "NeedDaemonReload",                bus_unit_append_need_daemon_reload,        "b", 0                                                                },
-        { "JobTimeoutUSec",                  bus_property_append_usec,                  "t", offsetof(Unit, job_timeout)                                      },
-        { "ConditionTimestamp",              bus_property_append_usec,                  "t", offsetof(Unit, condition_timestamp.realtime)                     },
-        { "ConditionTimestampMonotonic",     bus_property_append_usec,                  "t", offsetof(Unit, condition_timestamp.monotonic)                    },
-        { "ConditionResult",                 bus_property_append_bool,                  "b", offsetof(Unit, condition_result)                                 },
-        { "Conditions",                      bus_property_append_condition_list, "a(sbbsi)", offsetof(Unit, conditions)                                       },
-        { "LoadError",                       bus_unit_append_load_error,             "(ss)", 0                                                                },
-        { "Transient",                       bus_property_append_bool,                  "b", offsetof(Unit, transient)                                        },
-        {}
-};
-
-const BusProperty bus_unit_cgroup_properties[] = {
-        { "Slice",                bus_unit_append_slice,              "s", 0 },
-        { "ControlGroup",         bus_property_append_string,         "s", offsetof(Unit, cgroup_path),                                true },
-        {}
-};
diff --git a/src/core/dbus-unit.h b/src/core/dbus-unit.h
index 3064cd5..859de10 100644
--- a/src/core/dbus-unit.h
+++ b/src/core/dbus-unit.h
@@ -21,133 +21,19 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <dbus/dbus.h>
+#include "sd-bus.h"
+#include "unit.h"
 
-#include "manager.h"
-#include "dbus-common.h"
-
-#define BUS_UNIT_INTERFACE \
-        " <interface name=\"org.freedesktop.systemd1.Unit\">\n"         \
-        "  <method name=\"Start\">\n"                                   \
-        "   <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n"         \
-        "   <arg name=\"job\" type=\"o\" direction=\"out\"/>\n"         \
-        "  </method>\n"                                                 \
-        "  <method name=\"Stop\">\n"                                    \
-        "   <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n"         \
-        "   <arg name=\"job\" type=\"o\" direction=\"out\"/>\n"         \
-        "  </method>\n"                                                 \
-        "  <method name=\"Reload\">\n"                                  \
-        "   <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n"         \
-        "   <arg name=\"job\" type=\"o\" direction=\"out\"/>\n"         \
-        "  </method>\n"                                                 \
-        "  <method name=\"Restart\">\n"                                 \
-        "   <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n"         \
-        "   <arg name=\"job\" type=\"o\" direction=\"out\"/>\n"         \
-        "  </method>\n"                                                 \
-        "  <method name=\"TryRestart\">\n"                              \
-        "   <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n"         \
-        "   <arg name=\"job\" type=\"o\" direction=\"out\"/>\n"         \
-        "  </method>\n"                                                 \
-        "  <method name=\"ReloadOrRestart\">\n"                         \
-        "   <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n"         \
-        "   <arg name=\"job\" type=\"o\" direction=\"out\"/>\n"         \
-        "  </method>\n"                                                 \
-        "  <method name=\"ReloadOrTryRestart\">\n"                      \
-        "   <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n"         \
-        "   <arg name=\"job\" type=\"o\" direction=\"out\"/>\n"         \
-        "  </method>\n"                                                 \
-        "  <method name=\"Kill\">\n"                                    \
-        "   <arg name=\"who\" type=\"s\" direction=\"in\"/>\n"          \
-        "   <arg name=\"signal\" type=\"i\" direction=\"in\"/>\n"       \
-        "  </method>\n"                                                 \
-        "  <method name=\"ResetFailed\"/>\n"                            \
-        "  <method name=\"SetProperties\">\n"                           \
-        "   <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n"      \
-        "   <arg name=\"properties\" type=\"a(sv)\" direction=\"in\"/>\n" \
-        "  </method>\n"                                                 \
-        "  <property name=\"Id\" type=\"s\" access=\"read\"/>\n"        \
-        "  <property name=\"Names\" type=\"as\" access=\"read\"/>\n"    \
-        "  <property name=\"Following\" type=\"s\" access=\"read\"/>\n" \
-        "  <property name=\"Requires\" type=\"as\" access=\"read\"/>\n" \
-        "  <property name=\"RequiresOverridable\" type=\"as\" access=\"read\"/>\n" \
-        "  <property name=\"Requisite\" type=\"as\" access=\"read\"/>\n" \
-        "  <property name=\"RequisiteOverridable\" type=\"as\" access=\"read\"/>\n" \
-        "  <property name=\"Wants\" type=\"as\" access=\"read\"/>\n"    \
-        "  <property name=\"BindsTo\" type=\"as\" access=\"read\"/>\n"  \
-        "  <property name=\"PartOf\" type=\"as\" access=\"read\"/>\n"   \
-        "  <property name=\"RequiredBy\" type=\"as\" access=\"read\"/>\n" \
-        "  <property name=\"RequiredByOverridable\" type=\"as\" access=\"read\"/>\n" \
-        "  <property name=\"WantedBy\" type=\"as\" access=\"read\"/>\n" \
-        "  <property name=\"BoundBy\" type=\"as\" access=\"read\"/>\n" \
-        "  <property name=\"ConsistsOf\" type=\"as\" access=\"read\"/>\n" \
-        "  <property name=\"Conflicts\" type=\"as\" access=\"read\"/>\n" \
-        "  <property name=\"ConflictedBy\" type=\"as\" access=\"read\"/>\n" \
-        "  <property name=\"Before\" type=\"as\" access=\"read\"/>\n"   \
-        "  <property name=\"After\" type=\"as\" access=\"read\"/>\n"    \
-        "  <property name=\"OnFailure\" type=\"as\" access=\"read\"/>\n"    \
-        "  <property name=\"Triggers\" type=\"as\" access=\"read\"/>\n"    \
-        "  <property name=\"TriggeredBy\" type=\"as\" access=\"read\"/>\n"    \
-        "  <property name=\"PropagatesReloadTo\" type=\"as\" access=\"read\"/>\n" \
-        "  <property name=\"ReloadPropagatedFrom\" type=\"as\" access=\"read\"/>\n" \
-        "  <property name=\"RequiresMountsFor\" type=\"as\" access=\"read\"/>\n" \
-        "  <property name=\"Description\" type=\"s\" access=\"read\"/>\n" \
-        "  <property name=\"SourcePath\" type=\"s\" access=\"read\"/>\n" \
-        "  <property name=\"DropInPaths\" type=\"as\" access=\"read\"/>\n" \
-        "  <property name=\"Documentation\" type=\"as\" access=\"read\"/>\n" \
-        "  <property name=\"LoadState\" type=\"s\" access=\"read\"/>\n" \
-        "  <property name=\"ActiveState\" type=\"s\" access=\"read\"/>\n" \
-        "  <property name=\"SubState\" type=\"s\" access=\"read\"/>\n"  \
-        "  <property name=\"FragmentPath\" type=\"s\" access=\"read\"/>\n" \
-        "  <property name=\"UnitFileState\" type=\"s\" access=\"read\"/>\n" \
-        "  <property name=\"InactiveExitTimestamp\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"InactiveExitTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"ActiveEnterTimestamp\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"ActiveEnterTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"ActiveExitTimestamp\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"ActiveExitTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"InactiveEnterTimestamp\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"InactiveEnterTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"CanStart\" type=\"b\" access=\"read\"/>\n"  \
-        "  <property name=\"CanStop\" type=\"b\" access=\"read\"/>\n"   \
-        "  <property name=\"CanReload\" type=\"b\" access=\"read\"/>\n" \
-        "  <property name=\"CanIsolate\" type=\"b\" access=\"read\"/>\n" \
-        "  <property name=\"Job\" type=\"(uo)\" access=\"read\"/>\n"    \
-        "  <property name=\"StopWhenUnneeded\" type=\"b\" access=\"read\"/>\n" \
-        "  <property name=\"RefuseManualStart\" type=\"b\" access=\"read\"/>\n" \
-        "  <property name=\"RefuseManualStop\" type=\"b\" access=\"read\"/>\n" \
-        "  <property name=\"AllowIsolate\" type=\"b\" access=\"read\"/>\n" \
-        "  <property name=\"DefaultDependencies\" type=\"b\" access=\"read\"/>\n" \
-        "  <property name=\"OnFailureIsolate\" type=\"b\" access=\"read\"/>\n" \
-        "  <property name=\"IgnoreOnIsolate\" type=\"b\" access=\"read\"/>\n" \
-        "  <property name=\"IgnoreOnSnapshot\" type=\"b\" access=\"read\"/>\n" \
-        "  <property name=\"NeedDaemonReload\" type=\"b\" access=\"read\"/>\n" \
-        "  <property name=\"JobTimeoutUSec\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"ConditionTimestamp\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"ConditionTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"ConditionResult\" type=\"b\" access=\"read\"/>\n" \
-        "  <property name=\"Conditions\" type=\"a(sbbsi)\" access=\"read\"/>\n" \
-        "  <property name=\"LoadError\" type=\"(ss)\" access=\"read\"/>\n" \
-        "  <property name=\"Transient\" type=\"b\" access=\"read\"/>\n" \
-        " </interface>\n"
-
-#define BUS_UNIT_CGROUP_INTERFACE                                       \
-        "  <property name=\"Slice\" type=\"s\" access=\"read\"/>\n"     \
-        "  <property name=\"ControlGroup\" type=\"s\" access=\"read\"/>\n"
-
-#define BUS_UNIT_INTERFACES_LIST                \
-        BUS_GENERIC_INTERFACES_LIST             \
-        "org.freedesktop.systemd1.Unit\0"
-
-extern const BusProperty bus_unit_properties[];
-extern const BusProperty bus_unit_cgroup_properties[];
+extern const sd_bus_vtable bus_unit_vtable[];
+extern const sd_bus_vtable bus_unit_cgroup_vtable[];
 
 void bus_unit_send_change_signal(Unit *u);
 void bus_unit_send_removed_signal(Unit *u);
 
-DBusHandlerResult bus_unit_queue_job(DBusConnection *connection, DBusMessage *message, Unit *u, JobType type, JobMode mode, bool reload_if_possible);
-
-int bus_unit_set_properties(Unit *u, DBusMessageIter *i, UnitSetPropertiesMode mode, bool commit, DBusError *error);
-
-extern const DBusObjectPathVTable bus_unit_vtable;
+int bus_unit_method_start_generic(sd_bus *bus, sd_bus_message *message, Unit *u, JobType job_type, bool reload_if_possible);
+int bus_unit_method_kill(sd_bus *bus, sd_bus_message *message, void *userdata);
+int bus_unit_method_reset_failed(sd_bus *bus, sd_bus_message *message, void *userdata);
 
-extern const char bus_unit_interface[];
+int bus_unit_queue_job(sd_bus *bus, sd_bus_message *message, Unit *u, JobType type, JobMode mode, bool reload_if_possible);
+int bus_unit_set_properties(Unit *u, sd_bus_message *message, UnitSetPropertiesMode mode, bool commit, sd_bus_error *error);
+int bus_unit_method_set_properties(sd_bus *bus, sd_bus_message *message, void *userdata);
diff --git a/src/core/dbus.c b/src/core/dbus.c
index b0ae3e1..35d185a 100644
--- a/src/core/dbus.c
+++ b/src/core/dbus.c
@@ -23,9 +23,8 @@
 #include <sys/timerfd.h>
 #include <errno.h>
 #include <unistd.h>
-#include <dbus/dbus.h>
 
-#include "dbus.h"
+#include "sd-bus.h"
 #include "log.h"
 #include "strv.h"
 #include "mkdir.h"
@@ -33,1034 +32,851 @@
 #include "dbus-unit.h"
 #include "dbus-job.h"
 #include "dbus-manager.h"
-#include "dbus-service.h"
-#include "dbus-socket.h"
-#include "dbus-target.h"
-#include "dbus-device.h"
-#include "dbus-mount.h"
-#include "dbus-automount.h"
-#include "dbus-snapshot.h"
-#include "dbus-swap.h"
-#include "dbus-timer.h"
-#include "dbus-path.h"
-#include "bus-errors.h"
+#include "dbus-execute.h"
+#include "dbus-kill.h"
+#include "dbus-cgroup.h"
 #include "special.h"
-#include "dbus-common.h"
+#include "dbus.h"
+#include "bus-util.h"
+#include "bus-error.h"
+#include "bus-errors.h"
+#include "strxcpyx.h"
+#include "dbus-client-track.h"
 
 #define CONNECTIONS_MAX 512
 
-/* Well-known address (http://dbus.freedesktop.org/doc/dbus-specification.html#message-bus-types) */
-#define DBUS_SYSTEM_BUS_DEFAULT_ADDRESS "unix:path=/var/run/dbus/system_bus_socket"
-/* Only used as a fallback */
-#define DBUS_SESSION_BUS_DEFAULT_ADDRESS "autolaunch:"
-
-static const char bus_properties_interface[] = BUS_PROPERTIES_INTERFACE;
-static const char bus_introspectable_interface[] = BUS_INTROSPECTABLE_INTERFACE;
-
-const char *const bus_interface_table[] = {
-        "org.freedesktop.DBus.Properties",     bus_properties_interface,
-        "org.freedesktop.DBus.Introspectable", bus_introspectable_interface,
-        "org.freedesktop.systemd1.Manager",    bus_manager_interface,
-        "org.freedesktop.systemd1.Job",        bus_job_interface,
-        "org.freedesktop.systemd1.Unit",       bus_unit_interface,
-        "org.freedesktop.systemd1.Service",    bus_service_interface,
-        "org.freedesktop.systemd1.Socket",     bus_socket_interface,
-        "org.freedesktop.systemd1.Target",     bus_target_interface,
-        "org.freedesktop.systemd1.Device",     bus_device_interface,
-        "org.freedesktop.systemd1.Mount",      bus_mount_interface,
-        "org.freedesktop.systemd1.Automount",  bus_automount_interface,
-        "org.freedesktop.systemd1.Snapshot",   bus_snapshot_interface,
-        "org.freedesktop.systemd1.Swap",       bus_swap_interface,
-        "org.freedesktop.systemd1.Timer",      bus_timer_interface,
-        "org.freedesktop.systemd1.Path",       bus_path_interface,
-        NULL
-};
-
-static void bus_done_api(Manager *m);
-static void bus_done_system(Manager *m);
-static void bus_done_private(Manager *m);
-static void shutdown_connection(Manager *m, DBusConnection *c);
-
-static void bus_dispatch_status(DBusConnection *bus, DBusDispatchStatus status, void *data)  {
-        Manager *m = data;
+static void destroy_bus(Manager *m, sd_bus **bus);
+
+int bus_send_queued_message(Manager *m) {
+        int r;
 
-        assert(bus);
         assert(m);
 
-        /* We maintain two sets, one for those connections where we
-         * requested a dispatch, and another where we didn't. And then,
-         * we move the connections between the two sets. */
+        if (!m->queued_message)
+                return 0;
 
-        if (status == DBUS_DISPATCH_COMPLETE)
-                set_move_one(m->bus_connections, m->bus_connections_for_dispatch, bus);
-        else
-                set_move_one(m->bus_connections_for_dispatch, m->bus_connections, bus);
-}
+        assert(m->queued_message_bus);
 
-void bus_watch_event(Manager *m, Watch *w, int events) {
-        assert(m);
-        assert(w);
+        /* If we cannot get rid of this message we won't dispatch any
+         * D-Bus messages, so that we won't end up wanting to queue
+         * another message. */
 
-        /* This is called by the event loop whenever there is
-         * something happening on D-Bus' file handles. */
+        r = sd_bus_send(m->queued_message_bus, m->queued_message, NULL);
+        if (r < 0)
+                log_warning("Failed to send queued message: %s", strerror(-r));
 
-        if (!dbus_watch_get_enabled(w->data.bus_watch))
-                return;
+        m->queued_message = sd_bus_message_unref(m->queued_message);
+        m->queued_message_bus = sd_bus_unref(m->queued_message_bus);
 
-        dbus_watch_handle(w->data.bus_watch, bus_events_to_flags(events));
+        return 0;
 }
 
-static dbus_bool_t bus_add_watch(DBusWatch *bus_watch, void *data) {
-        Manager *m = data;
-        Watch *w;
-        struct epoll_event ev;
+static int signal_agent_released(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        Manager *m = userdata;
+        const char *cgroup;
+        int r;
 
-        assert(bus_watch);
+        assert(bus);
+        assert(message);
         assert(m);
 
-        if (!(w = new0(Watch, 1)))
-                return FALSE;
-
-        w->fd = dbus_watch_get_unix_fd(bus_watch);
-        w->type = WATCH_DBUS_WATCH;
-        w->data.bus_watch = bus_watch;
+        r = sd_bus_message_read(message, "s", &cgroup);
+        if (r < 0) {
+                bus_log_parse_error(r);
+                return 0;
+        }
 
-        zero(ev);
-        ev.events = bus_flags_to_events(bus_watch);
-        ev.data.ptr = w;
+        manager_notify_cgroup_empty(m, cgroup);
 
-        if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, w->fd, &ev) < 0) {
+        if (m->running_as == SYSTEMD_SYSTEM && m->system_bus) {
+                /* If we are running as system manager, forward the
+                 * message to the system bus */
 
-                if (errno != EEXIST) {
-                        free(w);
-                        return FALSE;
-                }
+                r = sd_bus_send(m->system_bus, message, NULL);
+                if (r < 0)
+                        log_warning("Failed to forward Released message: %s", strerror(-r));
+        }
 
-                /* Hmm, bloody D-Bus creates multiple watches on the
-                 * same fd. epoll() does not like that. As a dirty
-                 * hack we simply dup() the fd and hence get a second
-                 * one we can safely add to the epoll(). */
+        return 0;
+}
 
-                if ((w->fd = dup(w->fd)) < 0) {
-                        free(w);
-                        return FALSE;
-                }
+static int signal_disconnected(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        Manager *m = userdata;
 
-                if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, w->fd, &ev) < 0) {
-                        close_nointr_nofail(w->fd);
-                        free(w);
-                        return FALSE;
-                }
+        assert(bus);
+        assert(message);
+        assert(m);
 
-                w->fd_is_dupped = true;
+        if (bus == m->api_bus)
+                destroy_bus(m, &m->api_bus);
+        if (bus == m->system_bus)
+                destroy_bus(m, &m->system_bus);
+        if (set_remove(m->private_buses, bus)) {
+                log_debug("Got disconnect on private connection.");
+                destroy_bus(m, &bus);
         }
 
-        dbus_watch_set_data(bus_watch, w, NULL);
-
-        return TRUE;
+        return 0;
 }
 
-static void bus_remove_watch(DBusWatch *bus_watch, void *data) {
-        Manager *m = data;
-        Watch *w;
+static int signal_name_owner_changed(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        const char *name, *old_owner, *new_owner;
+        Manager *m = userdata;
+        int r;
 
-        assert(bus_watch);
+        assert(bus);
+        assert(message);
         assert(m);
 
-        w = dbus_watch_get_data(bus_watch);
-        if (!w)
-                return;
-
-        assert(w->type == WATCH_DBUS_WATCH);
-        assert_se(epoll_ctl(m->epoll_fd, EPOLL_CTL_DEL, w->fd, NULL) >= 0);
+        r = sd_bus_message_read(message, "sss", &name, &old_owner, &new_owner);
+        if (r < 0) {
+                bus_log_parse_error(r);
+                return 0;
+        }
 
-        if (w->fd_is_dupped)
-                close_nointr_nofail(w->fd);
+        manager_dispatch_bus_name_owner_changed(
+                        m, name,
+                        isempty(old_owner) ? NULL : old_owner,
+                        isempty(new_owner) ? NULL : new_owner);
 
-        free(w);
+        return 0;
 }
 
-static void bus_toggle_watch(DBusWatch *bus_watch, void *data) {
-        Manager *m = data;
-        Watch *w;
-        struct epoll_event ev;
+static int signal_activation_request(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+        Manager *m = userdata;
+        const char *name;
+        Unit *u;
+        int r;
 
-        assert(bus_watch);
+        assert(bus);
+        assert(message);
         assert(m);
 
-        w = dbus_watch_get_data(bus_watch);
-        if (!w)
-                return;
-
-        assert(w->type == WATCH_DBUS_WATCH);
-
-        zero(ev);
-        ev.events = bus_flags_to_events(bus_watch);
-        ev.data.ptr = w;
-
-        assert_se(epoll_ctl(m->epoll_fd, EPOLL_CTL_MOD, w->fd, &ev) == 0);
-}
+        r = sd_bus_message_read(message, "s", &name);
+        if (r < 0) {
+                bus_log_parse_error(r);
+                return 0;
+        }
 
-static int bus_timeout_arm(Manager *m, Watch *w) {
-        struct itimerspec its = {};
+        if (manager_unit_inactive_or_pending(m, SPECIAL_DBUS_SERVICE) ||
+            manager_unit_inactive_or_pending(m, SPECIAL_DBUS_SOCKET)) {
+                r = sd_bus_error_setf(&error, BUS_ERROR_SHUTTING_DOWN, "Refusing activation, D-Bus is shutting down.");
+                goto failed;
+        }
 
-        assert(m);
-        assert(w);
+        r = manager_load_unit(m, name, NULL, &error, &u);
+        if (r < 0)
+                goto failed;
 
-        if (dbus_timeout_get_enabled(w->data.bus_timeout)) {
-                timespec_store(&its.it_value, dbus_timeout_get_interval(w->data.bus_timeout) * USEC_PER_MSEC);
-                its.it_interval = its.it_value;
+        if (u->refuse_manual_start) {
+                r = sd_bus_error_setf(&error, BUS_ERROR_ONLY_BY_DEPENDENCY, "Operation refused, %u may be requested by dependency only.", u->id);
+                goto failed;
         }
 
-        if (timerfd_settime(w->fd, 0, &its, NULL) < 0)
-                return -errno;
+        r = manager_add_job(m, JOB_START, u, JOB_REPLACE, true, &error, NULL);
+        if (r < 0)
+                goto failed;
 
+        /* Successfully queued, that's it for us */
         return 0;
-}
 
-void bus_timeout_event(Manager *m, Watch *w, int events) {
-        assert(m);
-        assert(w);
+failed:
+        if (!sd_bus_error_is_set(&error))
+                sd_bus_error_set_errno(&error, r);
 
-        /* This is called by the event loop whenever there is
-         * something happening on D-Bus' file handles. */
+        log_debug("D-Bus activation failed for %s: %s", name, bus_error_message(&error, r));
 
-        if (!(dbus_timeout_get_enabled(w->data.bus_timeout)))
-                return;
+        r = sd_bus_message_new_signal(bus, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Activator", "ActivationFailure", &reply);
+        if (r < 0) {
+                bus_log_create_error(r);
+                return 0;
+        }
+
+        r = sd_bus_message_append(reply, "sss", error.name, error.message);
+        if (r < 0) {
+                bus_log_create_error(r);
+                return 0;
+        }
+
+        r = sd_bus_send_to(bus, reply, "org.freedesktop.DBus", NULL);
+        if (r < 0) {
+                log_error("Failed to respond with to bus activation request: %s", strerror(-r));
+                return r;
+        }
 
-        dbus_timeout_handle(w->data.bus_timeout);
+        return 0;
 }
 
-static dbus_bool_t bus_add_timeout(DBusTimeout *timeout, void *data) {
-        Manager *m = data;
-        Watch *w;
-        struct epoll_event ev;
+static int bus_job_find(sd_bus *bus, const char *path, const char *interface, void **found, void *userdata) {
+        Manager *m = userdata;
+        Job *j;
+        int r;
 
-        assert(timeout);
+        assert(bus);
+        assert(path);
+        assert(interface);
+        assert(found);
         assert(m);
 
-        if (!(w = new0(Watch, 1)))
-                return FALSE;
-
-        if ((w->fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK|TFD_CLOEXEC)) < 0)
-                goto fail;
+        r = manager_get_job_from_dbus_path(m, path, &j);
+        if (r < 0)
+                return 0;
 
-        w->type = WATCH_DBUS_TIMEOUT;
-        w->data.bus_timeout = timeout;
+        *found = j;
+        return 1;
+}
 
-        if (bus_timeout_arm(m, w) < 0)
-                goto fail;
+static Unit *find_unit(Manager *m, sd_bus *bus, const char *path) {
+        Unit *u;
+        int r;
 
-        zero(ev);
-        ev.events = EPOLLIN;
-        ev.data.ptr = w;
+        assert(m);
+        assert(bus);
+        assert(path);
 
-        if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, w->fd, &ev) < 0)
-                goto fail;
+        if (streq_ptr(path, "/org/freedesktop/systemd1/unit/self")) {
+                sd_bus_message *message;
+                pid_t pid;
 
-        dbus_timeout_set_data(timeout, w, NULL);
+                message = sd_bus_get_current(bus);
+                if (!message)
+                        return NULL;
 
-        return TRUE;
+                r = sd_bus_get_owner_pid(bus, sd_bus_message_get_sender(message), &pid);
+                if (r < 0)
+                        return NULL;
 
-fail:
-        if (w->fd >= 0)
-                close_nointr_nofail(w->fd);
+                u = manager_get_unit_by_pid(m, pid);
+        } else {
+                r = manager_load_unit_from_dbus_path(m, path, NULL, &u);
+                if (r < 0)
+                        return NULL;
+        }
 
-        free(w);
-        return FALSE;
+        return u;
 }
 
-static void bus_remove_timeout(DBusTimeout *timeout, void *data) {
-        Manager *m = data;
-        Watch *w;
+static int bus_unit_find(sd_bus *bus, const char *path, const char *interface, void **found, void *userdata) {
+        Manager *m = userdata;
+        Unit *u;
 
-        assert(timeout);
+        assert(bus);
+        assert(path);
+        assert(interface);
+        assert(found);
         assert(m);
 
-        w = dbus_timeout_get_data(timeout);
-        if (!w)
-                return;
-
-        assert(w->type == WATCH_DBUS_TIMEOUT);
+        u = find_unit(m, bus, path);
+        if (!u)
+                return 0;
 
-        assert_se(epoll_ctl(m->epoll_fd, EPOLL_CTL_DEL, w->fd, NULL) >= 0);
-        close_nointr_nofail(w->fd);
-        free(w);
+        *found = u;
+        return 1;
 }
 
-static void bus_toggle_timeout(DBusTimeout *timeout, void *data) {
-        Manager *m = data;
-        Watch *w;
-        int r;
+static int bus_unit_interface_find(sd_bus *bus, const char *path, const char *interface, void **found, void *userdata) {
+        Manager *m = userdata;
+        Unit *u;
 
-        assert(timeout);
+        assert(bus);
+        assert(path);
+        assert(interface);
+        assert(found);
         assert(m);
 
-        w = dbus_timeout_get_data(timeout);
-        if (!w)
-                return;
+        u = find_unit(m, bus, path);
+        if (!u)
+                return 0;
 
-        assert(w->type == WATCH_DBUS_TIMEOUT);
+        if (!streq_ptr(interface, UNIT_VTABLE(u)->bus_interface))
+                return 0;
 
-        if ((r = bus_timeout_arm(m, w)) < 0)
-                log_error("Failed to rearm timer: %s", strerror(-r));
+        *found = u;
+        return 1;
 }
 
-static DBusHandlerResult api_bus_message_filter(DBusConnection *connection, DBusMessage *message, void *data) {
-        Manager *m = data;
-        DBusError error;
-        DBusMessage *reply = NULL;
+static int bus_unit_cgroup_find(sd_bus *bus, const char *path, const char *interface, void **found, void *userdata) {
+        Manager *m = userdata;
+        Unit *u;
 
-        assert(connection);
-        assert(message);
+        assert(bus);
+        assert(path);
+        assert(interface);
+        assert(found);
         assert(m);
 
-        dbus_error_init(&error);
-
-        if (dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_METHOD_CALL ||
-            dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_SIGNAL)
-                log_debug("Got D-Bus request: %s.%s() on %s",
-                          dbus_message_get_interface(message),
-                          dbus_message_get_member(message),
-                          dbus_message_get_path(message));
-
-        if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected")) {
-                log_debug("API D-Bus connection terminated.");
-                bus_done_api(m);
-
-        } else if (dbus_message_is_signal(message, DBUS_INTERFACE_DBUS, "NameOwnerChanged")) {
-                const char *name, *old_owner, *new_owner;
-
-                if (!dbus_message_get_args(message, &error,
-                                           DBUS_TYPE_STRING, &name,
-                                           DBUS_TYPE_STRING, &old_owner,
-                                           DBUS_TYPE_STRING, &new_owner,
-                                           DBUS_TYPE_INVALID))
-                        log_error("Failed to parse NameOwnerChanged message: %s", bus_error_message(&error));
-                else  {
-                        if (set_remove(BUS_CONNECTION_SUBSCRIBED(m, connection), (char*) name))
-                                log_debug("Subscription client vanished: %s (left: %u)", name, set_size(BUS_CONNECTION_SUBSCRIBED(m, connection)));
-
-                        if (old_owner[0] == 0)
-                                old_owner = NULL;
+        u = find_unit(m, bus, path);
+        if (!u)
+                return 0;
 
-                        if (new_owner[0] == 0)
-                                new_owner = NULL;
+        if (!streq_ptr(interface, UNIT_VTABLE(u)->bus_interface))
+                return 0;
 
-                        manager_dispatch_bus_name_owner_changed(m, name, old_owner, new_owner);
-                }
-        } else if (dbus_message_is_signal(message, "org.freedesktop.systemd1.Activator", "ActivationRequest")) {
-                const char *name;
-
-                if (!dbus_message_get_args(message, &error,
-                                           DBUS_TYPE_STRING, &name,
-                                           DBUS_TYPE_INVALID))
-                        log_error("Failed to parse ActivationRequest message: %s", bus_error_message(&error));
-                else  {
-                        int r;
-                        Unit *u;
-
-                        log_debug("Got D-Bus activation request for %s", name);
-
-                        if (manager_unit_inactive_or_pending(m, SPECIAL_DBUS_SERVICE) ||
-                            manager_unit_inactive_or_pending(m, SPECIAL_DBUS_SOCKET)) {
-                                r = -EADDRNOTAVAIL;
-                                dbus_set_error(&error, BUS_ERROR_SHUTTING_DOWN, "Refusing activation, D-Bus is shutting down.");
-                        } else {
-                                r = manager_load_unit(m, name, NULL, &error, &u);
-
-                                if (r >= 0 && u->refuse_manual_start)
-                                        r = -EPERM;
-
-                                if (r >= 0)
-                                        r = manager_add_job(m, JOB_START, u, JOB_REPLACE, true, &error, NULL);
-                        }
+        if (!unit_get_cgroup_context(u))
+                return 0;
 
-                        if (r < 0) {
-                                const char *id, *text;
+        *found = u;
+        return 1;
+}
 
-                                log_debug("D-Bus activation failed for %s: %s", name, strerror(-r));
+static int bus_cgroup_context_find(sd_bus *bus, const char *path, const char *interface, void **found, void *userdata) {
+        Manager *m = userdata;
+        CGroupContext *c;
+        Unit *u;
 
-                                if (!(reply = dbus_message_new_signal("/org/freedesktop/systemd1", "org.freedesktop.systemd1.Activator", "ActivationFailure")))
-                                        goto oom;
+        assert(bus);
+        assert(path);
+        assert(interface);
+        assert(found);
+        assert(m);
 
-                                id = error.name ? error.name : bus_errno_to_dbus(r);
-                                text = bus_error(&error, r);
+        u = find_unit(m, bus, path);
+        if (!u)
+                return 0;
 
-                                if (!dbus_message_set_destination(reply, DBUS_SERVICE_DBUS) ||
-                                    !dbus_message_append_args(reply,
-                                                              DBUS_TYPE_STRING, &name,
-                                                              DBUS_TYPE_STRING, &id,
-                                                              DBUS_TYPE_STRING, &text,
-                                                              DBUS_TYPE_INVALID))
-                                        goto oom;
-                        }
+        if (!streq_ptr(interface, UNIT_VTABLE(u)->bus_interface))
+                return 0;
 
-                        /* On success we don't do anything, the service will be spawned now */
-                }
-        }
+        c = unit_get_cgroup_context(u);
+        if (!c)
+                return 0;
 
-        dbus_error_free(&error);
+        *found = c;
+        return 1;
+}
 
-        if (reply) {
-                if (!bus_maybe_send_reply(connection, message, reply))
-                        goto oom;
+static int bus_exec_context_find(sd_bus *bus, const char *path, const char *interface, void **found, void *userdata) {
+        Manager *m = userdata;
+        ExecContext *c;
+        Unit *u;
 
-                dbus_message_unref(reply);
-        }
+        assert(bus);
+        assert(path);
+        assert(interface);
+        assert(found);
+        assert(m);
 
-        return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+        u = find_unit(m, bus, path);
+        if (!u)
+                return 0;
 
-oom:
-        if (reply)
-                dbus_message_unref(reply);
+        if (!streq_ptr(interface, UNIT_VTABLE(u)->bus_interface))
+                return 0;
 
-        dbus_error_free(&error);
+        c = unit_get_exec_context(u);
+        if (!c)
+                return 0;
 
-        return DBUS_HANDLER_RESULT_NEED_MEMORY;
+        *found = c;
+        return 1;
 }
 
-static DBusHandlerResult system_bus_message_filter(DBusConnection *connection, DBusMessage *message, void *data) {
-        Manager *m = data;
-        DBusError error;
+static int bus_kill_context_find(sd_bus *bus, const char *path, const char *interface, void **found, void *userdata) {
+        Manager *m = userdata;
+        KillContext *c;
+        Unit *u;
 
-        assert(connection);
-        assert(message);
+        assert(bus);
+        assert(path);
+        assert(interface);
+        assert(found);
         assert(m);
 
-        dbus_error_init(&error);
-
-        if (m->api_bus != m->system_bus &&
-            (dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_METHOD_CALL ||
-             dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_SIGNAL))
-                log_debug("Got D-Bus request on system bus: %s.%s() on %s",
-                          dbus_message_get_interface(message),
-                          dbus_message_get_member(message),
-                          dbus_message_get_path(message));
+        u = find_unit(m, bus, path);
+        if (!u)
+                return 0;
 
-        if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected")) {
-                log_debug("System D-Bus connection terminated.");
-                bus_done_system(m);
+        if (!streq_ptr(interface, UNIT_VTABLE(u)->bus_interface))
+                return 0;
 
-        } else if (m->running_as != SYSTEMD_SYSTEM &&
-                   dbus_message_is_signal(message, "org.freedesktop.systemd1.Agent", "Released")) {
+        c = unit_get_kill_context(u);
+        if (!c)
+                return 0;
 
-                const char *cgroup;
+        *found = c;
+        return 1;
+}
 
-                if (!dbus_message_get_args(message, &error,
-                                           DBUS_TYPE_STRING, &cgroup,
-                                           DBUS_TYPE_INVALID))
-                        log_error("Failed to parse Released message: %s", bus_error_message(&error));
-                else
-                        manager_notify_cgroup_empty(m, cgroup);
-        }
+static int bus_job_enumerate(sd_bus *bus, const char *path, char ***nodes, void *userdata) {
+        _cleanup_free_ char **l = NULL;
+        Manager *m = userdata;
+        unsigned k = 0;
+        Iterator i;
+        Job *j;
 
-        dbus_error_free(&error);
-        return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-}
+        l = new0(char*, hashmap_size(m->jobs)+1);
+        if (!l)
+                return -ENOMEM;
 
-static DBusHandlerResult private_bus_message_filter(DBusConnection *connection, DBusMessage *message, void *data) {
-        Manager *m = data;
-        DBusError error;
+        HASHMAP_FOREACH(j, m->jobs, i) {
+                l[k] = job_dbus_path(j);
+                if (!l[k])
+                        return -ENOMEM;
 
-        assert(connection);
-        assert(message);
-        assert(m);
+                k++;
+        }
 
-        dbus_error_init(&error);
+        assert(hashmap_size(m->jobs) == k);
 
-        if (dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_METHOD_CALL ||
-            dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_SIGNAL)
-                log_debug("Got D-Bus request: %s.%s() on %s",
-                          dbus_message_get_interface(message),
-                          dbus_message_get_member(message),
-                          dbus_message_get_path(message));
+        *nodes = l;
+        l = NULL;
 
-        if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected"))
-                shutdown_connection(m, connection);
-        else if (m->running_as == SYSTEMD_SYSTEM &&
-                 dbus_message_is_signal(message, "org.freedesktop.systemd1.Agent", "Released")) {
+        return k;
+}
 
-                const char *cgroup;
+static int bus_unit_enumerate(sd_bus *bus, const char *path, char ***nodes, void *userdata) {
+        _cleanup_free_ char **l = NULL;
+        Manager *m = userdata;
+        unsigned k = 0;
+        Iterator i;
+        Unit *u;
 
-                if (!dbus_message_get_args(message, &error,
-                                           DBUS_TYPE_STRING, &cgroup,
-                                           DBUS_TYPE_INVALID))
-                        log_error("Failed to parse Released message: %s", bus_error_message(&error));
-                else
-                        manager_notify_cgroup_empty(m, cgroup);
+        l = new0(char*, hashmap_size(m->units)+1);
+        if (!l)
+                return -ENOMEM;
 
-                /* Forward the message to the system bus, so that user
-                 * instances are notified as well */
+        HASHMAP_FOREACH(u, m->units, i) {
+                l[k] = unit_dbus_path(u);
+                if (!l[k])
+                        return -ENOMEM;
 
-                if (m->system_bus)
-                        dbus_connection_send(m->system_bus, message, NULL);
+                k++;
         }
 
-        dbus_error_free(&error);
+        *nodes = l;
+        l = NULL;
 
-        return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+        return k;
 }
 
-unsigned bus_dispatch(Manager *m) {
-        DBusConnection *c;
+static int bus_setup_api_vtables(Manager *m, sd_bus *bus) {
+        UnitType t;
+        int r;
 
         assert(m);
+        assert(bus);
 
-        if (m->queued_message) {
-                /* If we cannot get rid of this message we won't
-                 * dispatch any D-Bus messages, so that we won't end
-                 * up wanting to queue another message. */
-
-                if (m->queued_message_connection)
-                        if (!dbus_connection_send(m->queued_message_connection, m->queued_message, NULL))
-                                return 0;
-
-                dbus_message_unref(m->queued_message);
-                m->queued_message = NULL;
-                m->queued_message_connection = NULL;
+        r = sd_bus_add_object_vtable(bus, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", bus_manager_vtable, m);
+        if (r < 0) {
+                log_error("Failed to register Manager vtable: %s", strerror(-r));
+                return r;
         }
 
-        if ((c = set_first(m->bus_connections_for_dispatch))) {
-                if (dbus_connection_dispatch(c) == DBUS_DISPATCH_COMPLETE)
-                        set_move_one(m->bus_connections, m->bus_connections_for_dispatch, c);
-
-                return 1;
+        r = sd_bus_add_fallback_vtable(bus, "/org/freedesktop/systemd1/job", "org.freedesktop.systemd1.Job", bus_job_vtable, bus_job_find, m);
+        if (r < 0) {
+                log_error("Failed to register Job vtable: %s", strerror(-r));
+                return r;
         }
 
-        return 0;
-}
-
-static void request_name_pending_cb(DBusPendingCall *pending, void *userdata) {
-        DBusMessage *reply;
-        DBusError error;
-
-        dbus_error_init(&error);
-
-        assert_se(reply = dbus_pending_call_steal_reply(pending));
+        r = sd_bus_add_node_enumerator(bus, "/org/freedesktop/systemd1/job", bus_job_enumerate, m);
+        if (r < 0) {
+                log_error("Failed to add job enumerator: %s", strerror(-r));
+                return r;
+        }
 
-        switch (dbus_message_get_type(reply)) {
+        r = sd_bus_add_fallback_vtable(bus, "/org/freedesktop/systemd1/unit", "org.freedesktop.systemd1.Unit", bus_unit_vtable, bus_unit_find, m);
+        if (r < 0) {
+                log_error("Failed to register Unit vtable: %s", strerror(-r));
+                return r;
+        }
 
-        case DBUS_MESSAGE_TYPE_ERROR:
+        r = sd_bus_add_node_enumerator(bus, "/org/freedesktop/systemd1/unit", bus_unit_enumerate, m);
+        if (r < 0) {
+                log_error("Failed to add job enumerator: %s", strerror(-r));
+                return r;
+        }
 
-                assert_se(dbus_set_error_from_message(&error, reply));
-                log_warning("RequestName() failed: %s", bus_error_message(&error));
-                break;
+        for (t = 0; t < _UNIT_TYPE_MAX; t++) {
+                r = sd_bus_add_fallback_vtable(bus, "/org/freedesktop/systemd1/unit", unit_vtable[t]->bus_interface, unit_vtable[t]->bus_vtable, bus_unit_interface_find, m);
+                if (r < 0)  {
+                        log_error("Failed to register type specific vtable for %s: %s", unit_vtable[t]->bus_interface, strerror(-r));
+                        return r;
+                }
 
-        case DBUS_MESSAGE_TYPE_METHOD_RETURN: {
-                uint32_t r;
+                if (unit_vtable[t]->cgroup_context_offset > 0) {
+                        r = sd_bus_add_fallback_vtable(bus, "/org/freedesktop/systemd1/unit", unit_vtable[t]->bus_interface, bus_unit_cgroup_vtable, bus_unit_cgroup_find, m);
+                        if (r < 0) {
+                                log_error("Failed to register control group unit vtable for %s: %s", unit_vtable[t]->bus_interface, strerror(-r));
+                                return r;
+                        }
 
-                if (!dbus_message_get_args(reply,
-                                           &error,
-                                           DBUS_TYPE_UINT32, &r,
-                                           DBUS_TYPE_INVALID)) {
-                        log_error("Failed to parse RequestName() reply: %s", bus_error_message(&error));
-                        break;
+                        r = sd_bus_add_fallback_vtable(bus, "/org/freedesktop/systemd1/unit", unit_vtable[t]->bus_interface, bus_cgroup_vtable, bus_cgroup_context_find, m);
+                        if (r < 0) {
+                                log_error("Failed to register control group vtable for %s: %s", unit_vtable[t]->bus_interface, strerror(-r));
+                                return r;
+                        }
                 }
 
-                if (r == 1)
-                        log_debug("Successfully acquired name.");
-                else
-                        log_error("Name already owned.");
-
-                break;
-        }
+                if (unit_vtable[t]->exec_context_offset > 0) {
+                        r = sd_bus_add_fallback_vtable(bus, "/org/freedesktop/systemd1/unit", unit_vtable[t]->bus_interface, bus_exec_vtable, bus_exec_context_find, m);
+                        if (r < 0) {
+                                log_error("Failed to register execute vtable for %s: %s", unit_vtable[t]->bus_interface, strerror(-r));
+                                return r;
+                        }
+                }
 
-        default:
-                assert_not_reached("Invalid reply message");
+                if (unit_vtable[t]->kill_context_offset > 0) {
+                        r = sd_bus_add_fallback_vtable(bus, "/org/freedesktop/systemd1/unit", unit_vtable[t]->bus_interface, bus_kill_vtable, bus_kill_context_find, m);
+                        if (r < 0) {
+                                log_error("Failed to register kill vtable for %s: %s", unit_vtable[t]->bus_interface, strerror(-r));
+                                return r;
+                        }
+                }
         }
 
-        dbus_message_unref(reply);
-        dbus_error_free(&error);
+        return 0;
 }
 
-static int request_name(Manager *m) {
-        const char *name = "org.freedesktop.systemd1";
-        /* Allow replacing of our name, to ease implementation of
-         * reexecution, where we keep the old connection open until
-         * after the new connection is set up and the name installed
-         * to allow clients to synchronously wait for reexecution to
-         * finish */
-        uint32_t flags = DBUS_NAME_FLAG_ALLOW_REPLACEMENT|DBUS_NAME_FLAG_REPLACE_EXISTING;
-        DBusMessage *message = NULL;
-        DBusPendingCall *pending = NULL;
-
-        if (!(message = dbus_message_new_method_call(
-                              DBUS_SERVICE_DBUS,
-                              DBUS_PATH_DBUS,
-                              DBUS_INTERFACE_DBUS,
-                              "RequestName")))
-                goto oom;
-
-        if (!dbus_message_append_args(
-                            message,
-                            DBUS_TYPE_STRING, &name,
-                            DBUS_TYPE_UINT32, &flags,
-                            DBUS_TYPE_INVALID))
-                goto oom;
-
-        if (!dbus_connection_send_with_reply(m->api_bus, message, &pending, -1))
-                goto oom;
-
-        if (!dbus_pending_call_set_notify(pending, request_name_pending_cb, m, NULL))
-                goto oom;
-
-        dbus_message_unref(message);
-        dbus_pending_call_unref(pending);
+static int bus_setup_disconnected_match(Manager *m, sd_bus *bus) {
+        int r;
 
-        /* We simple ask for the name and don't wait for it. Sooner or
-         * later we'll have it. */
+        assert(m);
+        assert(bus);
 
-        return 0;
+        r = sd_bus_add_match(
+                        bus,
+                        "type='signal',"
+                        "path='/org/freedesktop/DBus/Local',"
+                        "interface='org.freedesktop.DBus.Local',"
+                        "member='Disconnected'",
+                        signal_disconnected, m);
 
-oom:
-        if (pending) {
-                dbus_pending_call_cancel(pending);
-                dbus_pending_call_unref(pending);
+        if (r < 0) {
+                log_error("Failed to register match for Disconnected message: %s", strerror(-r));
+                return r;
         }
 
-        if (message)
-                dbus_message_unref(message);
-
-        return -ENOMEM;
+        return 0;
 }
 
-static void query_name_list_pending_cb(DBusPendingCall *pending, void *userdata) {
-        DBusMessage *reply;
-        DBusError error;
+static int bus_on_connection(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
+        _cleanup_bus_unref_ sd_bus *bus = NULL;
+        _cleanup_close_ int nfd = -1;
         Manager *m = userdata;
+        sd_id128_t id;
+        int r;
 
+        assert(s);
         assert(m);
 
-        dbus_error_init(&error);
+        nfd = accept4(fd, NULL, NULL, SOCK_NONBLOCK|SOCK_CLOEXEC);
+        if (nfd < 0) {
+                log_warning("Failed to accept private connection, ignoring: %m");
+                return 0;
+        }
 
-        assert_se(reply = dbus_pending_call_steal_reply(pending));
+        if (set_size(m->private_buses) >= CONNECTIONS_MAX) {
+                log_warning("Too many concurrent connections, refusing");
+                return 0;
+        }
 
-        switch (dbus_message_get_type(reply)) {
+        r = set_ensure_allocated(&m->private_buses, trivial_hash_func, trivial_compare_func);
+        if (r < 0) {
+                log_oom();
+                return 0;
+        }
 
-        case DBUS_MESSAGE_TYPE_ERROR:
+        r = sd_bus_new(&bus);
+        if (r < 0) {
+                log_warning("Failed to allocate new private connection bus: %s", strerror(-r));
+                return 0;
+        }
 
-                assert_se(dbus_set_error_from_message(&error, reply));
-                log_warning("ListNames() failed: %s", bus_error_message(&error));
-                break;
+        r = sd_bus_set_fd(bus, nfd, nfd);
+        if (r < 0) {
+                log_warning("Failed to set fd on new connection bus: %s", strerror(-r));
+                return 0;
+        }
 
-        case DBUS_MESSAGE_TYPE_METHOD_RETURN: {
-                int r;
-                char **l;
+        nfd = -1;
 
-                if ((r = bus_parse_strv(reply, &l)) < 0)
-                        log_warning("Failed to parse ListNames() reply: %s", strerror(-r));
-                else {
-                        char **t;
+        r = bus_check_peercred(bus);
+        if (r < 0) {
+                log_warning("Incoming private connection from unprivileged client, refusing: %s", strerror(-r));
+                return 0;
+        }
 
-                        STRV_FOREACH(t, l)
-                                /* This is a bit hacky, we say the
-                                 * owner of the name is the name
-                                 * itself, because we don't want the
-                                 * extra traffic to figure out the
-                                 * real owner. */
-                                manager_dispatch_bus_name_owner_changed(m, *t, NULL, *t);
+        assert_se(sd_id128_randomize(&id) >= 0);
 
-                        strv_free(l);
-                }
+        r = sd_bus_set_server(bus, 1, id);
+        if (r < 0) {
+                log_warning("Failed to enable server support for new connection bus: %s", strerror(-r));
+                return 0;
+        }
 
-                break;
+        r = sd_bus_start(bus);
+        if (r < 0) {
+                log_warning("Failed to start new connection bus: %s", strerror(-r));
+                return 0;
         }
 
-        default:
-                assert_not_reached("Invalid reply message");
+        r = sd_bus_attach_event(bus, m->event, SD_EVENT_PRIORITY_NORMAL);
+        if (r < 0) {
+                log_warning("Failed to attach new connection bus to event loop: %s", strerror(-r));
+                return 0;
         }
 
-        dbus_message_unref(reply);
-        dbus_error_free(&error);
-}
+        if (m->running_as == SYSTEMD_SYSTEM) {
+                /* When we run as system instance we get the Released
+                 * signal via a direct connection */
+
+                r = sd_bus_add_match(
+                                bus,
+                                "type='signal',"
+                                "interface='org.freedesktop.systemd1.Agent',"
+                                "member='Released',"
+                                "path='/org/freedesktop/systemd1/agent'",
+                                signal_agent_released, m);
+
+                if (r < 0) {
+                        log_warning("Failed to register Released match on new connection bus: %s", strerror(-r));
+                        return 0;
+                }
+        }
 
-static int query_name_list(Manager *m) {
-        DBusMessage *message = NULL;
-        DBusPendingCall *pending = NULL;
+        r = bus_setup_disconnected_match(m, bus);
+        if (r < 0)
+                return 0;
 
-        /* Asks for the currently installed bus names */
+        r = bus_setup_api_vtables(m, bus);
+        if (r < 0) {
+                log_warning("Failed to set up API vtables on new connection bus: %s", strerror(-r));
+                return 0;
+        }
 
-        if (!(message = dbus_message_new_method_call(
-                              DBUS_SERVICE_DBUS,
-                              DBUS_PATH_DBUS,
-                              DBUS_INTERFACE_DBUS,
-                              "ListNames")))
-                goto oom;
-
-        if (!dbus_connection_send_with_reply(m->api_bus, message, &pending, -1))
-                goto oom;
-
-        if (!dbus_pending_call_set_notify(pending, query_name_list_pending_cb, m, NULL))
-                goto oom;
-
-        dbus_message_unref(message);
-        dbus_pending_call_unref(pending);
-
-        /* We simple ask for the list and don't wait for it. Sooner or
-         * later we'll get it. */
-
-        return 0;
-
-oom:
-        if (pending) {
-                dbus_pending_call_cancel(pending);
-                dbus_pending_call_unref(pending);
+        r = set_put(m->private_buses, bus);
+        if (r < 0) {
+                log_warning("Failed to add new conenction bus to set: %s", strerror(-r));
+                return 0;
         }
 
-        if (message)
-                dbus_message_unref(message);
+        bus = NULL;
 
-        return -ENOMEM;
-}
+        log_debug("Accepted new private connection.");
 
-static int bus_setup_loop(Manager *m, DBusConnection *bus) {
-        assert(m);
-        assert(bus);
-
-        dbus_connection_set_exit_on_disconnect(bus, FALSE);
-
-        if (!dbus_connection_set_watch_functions(bus, bus_add_watch, bus_remove_watch, bus_toggle_watch, m, NULL) ||
-            !dbus_connection_set_timeout_functions(bus, bus_add_timeout, bus_remove_timeout, bus_toggle_timeout, m, NULL))
-                return log_oom();
-
-        if (set_put(m->bus_connections_for_dispatch, bus) < 0)
-                return log_oom();
-
-        dbus_connection_set_dispatch_status_function(bus, bus_dispatch_status, m, NULL);
         return 0;
 }
 
-static dbus_bool_t allow_only_same_user(DBusConnection *connection, unsigned long uid, void *data) {
-        return uid == 0 || uid == geteuid();
-}
-
-static void bus_new_connection(
-                DBusServer *server,
-                DBusConnection *new_connection,
-                void *data) {
-
-        Manager *m = data;
+static int bus_list_names(Manager *m, sd_bus *bus) {
+        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+        const char *name;
+        int r;
 
         assert(m);
+        assert(bus);
 
-        if (set_size(m->bus_connections) >= CONNECTIONS_MAX) {
-                log_error("Too many concurrent connections.");
-                return;
+        r = sd_bus_call_method(
+                        bus,
+                        "org.freedesktop.DBus",
+                        "/org/freedesktop/DBus",
+                        "org.freedesktop.DBus",
+                        "ListNames",
+                        &error, &reply,
+                        NULL);
+        if (r < 0) {
+                log_error("Failed to get initial list of names: %s", bus_error_message(&error, r));
+                return r;
         }
 
-        dbus_connection_set_unix_user_function(new_connection, allow_only_same_user, NULL, NULL);
-
-        if (bus_setup_loop(m, new_connection) < 0)
-                return;
+        r = sd_bus_message_enter_container(reply, 'a', "s");
+        if (r < 0)
+                return bus_log_parse_error(r);
 
-        if (!dbus_connection_register_object_path(new_connection, "/org/freedesktop/systemd1", &bus_manager_vtable, m) ||
-            !dbus_connection_register_fallback(new_connection, "/org/freedesktop/systemd1/unit", &bus_unit_vtable, m) ||
-            !dbus_connection_register_fallback(new_connection, "/org/freedesktop/systemd1/job", &bus_job_vtable, m) ||
-            !dbus_connection_add_filter(new_connection, private_bus_message_filter, m, NULL)) {
-                log_oom();
-                return;
-        }
+        /* This is a bit hacky, we say the owner of the name is the
+         * name itself, because we don't want the extra traffic to
+         * figure out the real owner. */
+        while ((r = sd_bus_message_read(reply, "s", &name)) > 0)
+                manager_dispatch_bus_name_owner_changed(m, name, NULL, name);
+        if (r < 0)
+                return bus_log_parse_error(r);
 
-        log_debug("Accepted connection on private bus.");
+        r = sd_bus_message_exit_container(reply);
+        if (r < 0)
+                return bus_log_parse_error(r);
 
-        dbus_connection_ref(new_connection);
+        return 0;
 }
 
-static int init_registered_system_bus(Manager *m) {
-        char *id = NULL;
+static int bus_setup_api(Manager *m, sd_bus *bus) {
+        int r;
 
-        if (!dbus_connection_add_filter(m->system_bus, system_bus_message_filter, m, NULL))
-                return log_oom();
+        assert(m);
+        assert(bus);
 
-        if (m->running_as != SYSTEMD_SYSTEM) {
-                DBusError error;
+        r = bus_setup_api_vtables(m, bus);
+        if (r < 0)
+                return r;
 
-                dbus_error_init(&error);
+        r = sd_bus_add_match(
+                        bus,
+                        "type='signal',"
+                        "sender='org.freedesktop.DBus',"
+                        "path='/org/freedesktop/DBus',"
+                        "interface='org.freedesktop.DBus',"
+                        "member='NameOwnerChanged'",
+                        signal_name_owner_changed, m);
+        if (r < 0)
+                log_warning("Failed to subscribe to NameOwnerChanged signal: %s", strerror(-r));
+
+        r = sd_bus_add_match(
+                        bus,
+                        "type='signal',"
+                        "sender='org.freedesktop.DBus',"
+                        "path='/org/freedesktop/DBus',"
+                        "interface='org.freedesktop.systemd1.Activator',"
+                        "member='ActivationRequest'",
+                        signal_activation_request, m);
+        if (r < 0)
+                log_warning("Failed to subscribe to activation signal: %s", strerror(-r));
 
-                dbus_bus_add_match(m->system_bus,
-                                   "type='signal',"
-                                   "interface='org.freedesktop.systemd1.Agent',"
-                                   "member='Released',"
-                                   "path='/org/freedesktop/systemd1/agent'",
-                                   &error);
+        /* Allow replacing of our name, to ease implementation of
+         * reexecution, where we keep the old connection open until
+         * after the new connection is set up and the name installed
+         * to allow clients to synchronously wait for reexecution to
+         * finish */
+        r = sd_bus_request_name(bus,"org.freedesktop.systemd1", SD_BUS_NAME_ALLOW_REPLACEMENT|SD_BUS_NAME_REPLACE_EXISTING);
+        if (r < 0) {
+                log_error("Failed to register name: %s", strerror(-r));
+                return r;
+        }
 
-                if (dbus_error_is_set(&error)) {
-                        log_error("Failed to register match: %s", bus_error_message(&error));
-                        dbus_error_free(&error);
-                        return -1;
-                }
+        if (r != SD_BUS_NAME_PRIMARY_OWNER) {
+                log_error("Failed to acquire name.");
+                return -EEXIST;
         }
 
-        log_debug("Successfully connected to system D-Bus bus %s as %s",
-                 strnull((id = dbus_connection_get_server_id(m->system_bus))),
-                 strnull(dbus_bus_get_unique_name(m->system_bus)));
-        dbus_free(id);
+        bus_list_names(m, bus);
 
+        log_debug("Successfully connected to API bus.");
         return 0;
 }
 
-static int init_registered_api_bus(Manager *m) {
+static int bus_init_api(Manager *m) {
+        _cleanup_bus_unref_ sd_bus *bus = NULL;
         int r;
 
-        if (!dbus_connection_register_object_path(m->api_bus, "/org/freedesktop/systemd1", &bus_manager_vtable, m) ||
-            !dbus_connection_register_fallback(m->api_bus, "/org/freedesktop/systemd1/unit", &bus_unit_vtable, m) ||
-            !dbus_connection_register_fallback(m->api_bus, "/org/freedesktop/systemd1/job", &bus_job_vtable, m) ||
-            !dbus_connection_add_filter(m->api_bus, api_bus_message_filter, m, NULL))
-                return log_oom();
-
-        /* Get NameOwnerChange messages */
-        dbus_bus_add_match(m->api_bus,
-                           "type='signal',"
-                           "sender='"DBUS_SERVICE_DBUS"',"
-                           "interface='"DBUS_INTERFACE_DBUS"',"
-                           "member='NameOwnerChanged',"
-                           "path='"DBUS_PATH_DBUS"'",
-                           NULL);
-
-        /* Get activation requests */
-        dbus_bus_add_match(m->api_bus,
-                           "type='signal',"
-                           "sender='"DBUS_SERVICE_DBUS"',"
-                           "interface='org.freedesktop.systemd1.Activator',"
-                           "member='ActivationRequest',"
-                           "path='"DBUS_PATH_DBUS"'",
-                           NULL);
-
-        r = request_name(m);
-        if (r < 0)
-                return r;
-
-        r = query_name_list(m);
-        if (r < 0)
-                return r;
-
-        if (m->running_as == SYSTEMD_USER) {
-                char *id = NULL;
-
-                log_debug("Successfully connected to API D-Bus bus %s as %s",
-                         strnull((id = dbus_connection_get_server_id(m->api_bus))),
-                         strnull(dbus_bus_get_unique_name(m->api_bus)));
-                dbus_free(id);
-        } else
-                log_debug("Successfully initialized API on the system bus");
+        if (m->api_bus)
+                return 0;
 
-        return 0;
-}
+        /* The API and system bus is the same if we are running in system mode */
+        if (m->running_as == SYSTEMD_SYSTEM && m->system_bus)
+                bus = sd_bus_ref(m->system_bus);
+        else {
+                if (m->running_as == SYSTEMD_SYSTEM)
+                        r = sd_bus_open_system(&bus);
+                else
+                        r = sd_bus_open_user(&bus);
 
-static void bus_register_cb(DBusPendingCall *pending, void *userdata) {
-        Manager *m = userdata;
-        DBusConnection **conn;
-        DBusMessage *reply;
-        DBusError error;
-        const char *name;
-        int r = 0;
-
-        dbus_error_init(&error);
-
-        conn = dbus_pending_call_get_data(pending, m->conn_data_slot);
-        assert(conn == &m->system_bus || conn == &m->api_bus);
-
-        reply = dbus_pending_call_steal_reply(pending);
-
-        switch (dbus_message_get_type(reply)) {
-        case DBUS_MESSAGE_TYPE_ERROR:
-                assert_se(dbus_set_error_from_message(&error, reply));
-                log_warning("Failed to register to bus: %s", bus_error_message(&error));
-                r = -1;
-                break;
-        case DBUS_MESSAGE_TYPE_METHOD_RETURN:
-                if (!dbus_message_get_args(reply, &error,
-                                           DBUS_TYPE_STRING, &name,
-                                           DBUS_TYPE_INVALID)) {
-                        log_error("Failed to parse Hello reply: %s", bus_error_message(&error));
-                        r = -1;
-                        break;
+                if (r < 0) {
+                        log_debug("Failed to connect to API bus, retrying later...");
+                        return 0;
                 }
 
-                log_debug("Received name %s in reply to Hello", name);
-                if (!dbus_bus_set_unique_name(*conn, name)) {
-                        log_error("Failed to set unique name");
-                        r = -1;
-                        break;
+                r = sd_bus_attach_event(bus, m->event, SD_EVENT_PRIORITY_NORMAL);
+                if (r < 0) {
+                        log_error("Failed to attach API bus to event loop: %s", strerror(-r));
+                        return 0;
                 }
 
-                if (conn == &m->system_bus) {
-                        r = init_registered_system_bus(m);
-                        if (r == 0 && m->running_as == SYSTEMD_SYSTEM)
-                                r = init_registered_api_bus(m);
-                } else
-                        r = init_registered_api_bus(m);
-
-                break;
-        default:
-                assert_not_reached("Invalid reply message");
+                r = bus_setup_disconnected_match(m, bus);
+                if (r < 0)
+                        return 0;
         }
 
-        dbus_message_unref(reply);
-        dbus_error_free(&error);
-
+        r = bus_setup_api(m, bus);
         if (r < 0) {
-                if (conn == &m->system_bus) {
-                        log_debug("Failed setting up the system bus");
-                        bus_done_system(m);
-                } else {
-                        log_debug("Failed setting up the API bus");
-                        bus_done_api(m);
-                }
+                log_error("Failed to set up API bus: %s", strerror(-r));
+                return 0;
         }
-}
 
-static int manager_bus_async_register(Manager *m, DBusConnection **conn) {
-        DBusMessage *message = NULL;
-        DBusPendingCall *pending = NULL;
-
-        message = dbus_message_new_method_call(DBUS_SERVICE_DBUS,
-                                               DBUS_PATH_DBUS,
-                                               DBUS_INTERFACE_DBUS,
-                                               "Hello");
-        if (!message)
-                goto oom;
-
-        if (!dbus_connection_send_with_reply(*conn, message, &pending, -1))
-                goto oom;
-
-        if (!dbus_pending_call_set_data(pending, m->conn_data_slot, conn, NULL))
-                goto oom;
-
-        if (!dbus_pending_call_set_notify(pending, bus_register_cb, m, NULL))
-                goto oom;
-
-        dbus_message_unref(message);
-        dbus_pending_call_unref(pending);
+        m->api_bus = bus;
+        bus = NULL;
 
         return 0;
-oom:
-        if (pending) {
-                dbus_pending_call_cancel(pending);
-                dbus_pending_call_unref(pending);
-        }
-
-        if (message)
-                dbus_message_unref(message);
-
-        return -ENOMEM;
 }
 
-static DBusConnection* manager_bus_connect_private(Manager *m, DBusBusType type) {
-        const char *address;
-        DBusConnection *connection;
-        DBusError error;
-
-        switch (type) {
-        case DBUS_BUS_SYSTEM:
-                address = secure_getenv("DBUS_SYSTEM_BUS_ADDRESS");
-                if (!address || !address[0])
-                        address = DBUS_SYSTEM_BUS_DEFAULT_ADDRESS;
-                break;
-        case DBUS_BUS_SESSION:
-                address = secure_getenv("DBUS_SESSION_BUS_ADDRESS");
-                if (!address || !address[0])
-                        address = DBUS_SESSION_BUS_DEFAULT_ADDRESS;
-                break;
-        default:
-                assert_not_reached("Invalid bus type");
-        }
+static int bus_setup_system(Manager *m, sd_bus *bus) {
+        int r;
 
-        dbus_error_init(&error);
+        assert(m);
+        assert(bus);
 
-        connection = dbus_connection_open_private(address, &error);
-        if (!connection) {
-                log_warning("Failed to open private bus connection: %s", bus_error_message(&error));
-                goto fail;
-        }
+        if (m->running_as == SYSTEMD_SYSTEM)
+                return 0;
 
-        return connection;
+        /* If we are a user instance we get the Released message via
+         * the system bus */
+        r = sd_bus_add_match(
+                        bus,
+                        "type='signal',"
+                        "interface='org.freedesktop.systemd1.Agent',"
+                        "member='Released',"
+                        "path='/org/freedesktop/systemd1/agent'",
+                        signal_agent_released, m);
 
-fail:
-        dbus_error_free(&error);
-        return NULL;
+        if (r < 0)
+                log_warning("Failed to register Released match on system bus: %s", strerror(-r));
+
+        log_debug("Successfully connected to system bus.");
+        return 0;
 }
 
 static int bus_init_system(Manager *m) {
+        _cleanup_bus_unref_ sd_bus *bus = NULL;
         int r;
 
         if (m->system_bus)
                 return 0;
 
-        m->system_bus = manager_bus_connect_private(m, DBUS_BUS_SYSTEM);
-        if (!m->system_bus) {
-                log_debug("Failed to connect to system D-Bus, retrying later");
-                r = 0;
-                goto fail;
+        /* The API and system bus is the same if we are running in system mode */
+        if (m->running_as == SYSTEMD_SYSTEM && m->api_bus) {
+                m->system_bus = sd_bus_ref(m->api_bus);
+                return 0;
         }
 
-        r = bus_setup_loop(m, m->system_bus);
-        if (r < 0)
-                goto fail;
+        r = sd_bus_open_system(&bus);
+        if (r < 0) {
+                log_debug("Failed to connect to system bus, retrying later...");
+                return 0;
+        }
 
-        r = manager_bus_async_register(m, &m->system_bus);
+        r = bus_setup_disconnected_match(m, bus);
         if (r < 0)
-                goto fail;
-
-        return 0;
-fail:
-        bus_done_system(m);
-
-        return r;
-}
-
-static int bus_init_api(Manager *m) {
-        int r;
-
-        if (m->api_bus)
                 return 0;
 
-        if (m->running_as == SYSTEMD_SYSTEM) {
-                m->api_bus = m->system_bus;
-                /* In this mode there is no distinct connection to the API bus,
-                 * the API is published on the system bus.
-                 * bus_register_cb() is aware of that and will init the API
-                 * when the system bus gets registered.
-                 * No need to setup anything here. */
+        r = sd_bus_attach_event(bus, m->event, SD_EVENT_PRIORITY_NORMAL);
+        if (r < 0) {
+                log_error("Failed to attach system bus to event loop: %s", strerror(-r));
                 return 0;
         }
 
-        m->api_bus = manager_bus_connect_private(m, DBUS_BUS_SESSION);
-        if (!m->api_bus) {
-                log_debug("Failed to connect to API D-Bus, retrying later");
-                r = 0;
-                goto fail;
+        r = bus_setup_system(m, bus);
+        if (r < 0) {
+                log_error("Fauiled to set up system bus: %s", strerror(-r));
+                return 0;
         }
 
-        r = bus_setup_loop(m, m->api_bus);
-        if (r < 0)
-                goto fail;
-
-        r = manager_bus_async_register(m, &m->api_bus);
-        if (r < 0)
-                goto fail;
+        m->system_bus = bus;
+        bus = NULL;
 
         return 0;
-fail:
-        bus_done_api(m);
-
-        return r;
 }
 
 static int bus_init_private(Manager *m) {
-        DBusError error;
-        int r;
-        static const char *const external_only[] = {
-                "EXTERNAL",
-                NULL
+        _cleanup_close_ int fd = -1;
+        union sockaddr_union sa = {
+                .un.sun_family = AF_UNIX
         };
+        sd_event_source *s;
+        socklen_t salen;
+        int r;
 
         assert(m);
 
-        dbus_error_init(&error);
-
-        if (m->private_bus)
+        if (m->private_listen_fd >= 0)
                 return 0;
 
         if (m->running_as == SYSTEMD_SYSTEM) {
@@ -1069,90 +885,72 @@ static int bus_init_private(Manager *m) {
                 if (getpid() != 1)
                         return 0;
 
-                unlink("/run/systemd/private");
-                m->private_bus = dbus_server_listen("unix:path=/run/systemd/private", &error);
+                strcpy(sa.un.sun_path, "/run/systemd/private");
+                salen = offsetof(union sockaddr_union, un.sun_path) + sizeof("/run/systemd/private") - 1;
         } else {
+                size_t left = sizeof(sa.un.sun_path);
+                char *p = sa.un.sun_path;
                 const char *e;
-                char *p;
-                char *escaped;
 
                 e = secure_getenv("XDG_RUNTIME_DIR");
-                if (!e)
-                        return 0;
-
-                if (asprintf(&p, "%s/systemd/private", e) < 0) {
-                        r = log_oom();
-                        goto fail;
+                if (!e) {
+                        log_error("Failed to determine XDG_RUNTIME_DIR");
+                        return -EHOSTDOWN;
                 }
 
-                mkdir_parents_label(p, 0755);
-                unlink(p);
-                free(p);
+                left = strpcpy(&p, left, e);
+                left = strpcpy(&p, left, "/systemd/private");
 
-                escaped = dbus_address_escape_value(e);
-                if (!escaped) {
-                        r = log_oom();
-                        goto fail;
-                }
-                if (asprintf(&p, "unix:path=%s/systemd/private", escaped) < 0) {
-                        dbus_free(escaped);
-                        r = log_oom();
-                        goto fail;
-                }
-                dbus_free(escaped);
+                salen = sizeof(sa.un) - left;
 
-                m->private_bus = dbus_server_listen(p, &error);
-                free(p);
+                mkdir_parents_label(sa.un.sun_path, 0755);
         }
 
-        if (!m->private_bus) {
-                log_error("Failed to create private D-Bus server: %s", bus_error_message(&error));
-                r = -EIO;
-                goto fail;
+        unlink(sa.un.sun_path);
+
+        fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
+        if (fd < 0) {
+                log_error("Failed to allocate private socket: %m");
+                return -errno;
         }
 
-        if (!dbus_server_set_auth_mechanisms(m->private_bus, (const char**) external_only) ||
-            !dbus_server_set_watch_functions(m->private_bus, bus_add_watch, bus_remove_watch, bus_toggle_watch, m, NULL) ||
-            !dbus_server_set_timeout_functions(m->private_bus, bus_add_timeout, bus_remove_timeout, bus_toggle_timeout, m, NULL)) {
-                r = log_oom();
-                goto fail;
+        r = bind(fd, &sa.sa, salen);
+        if (r < 0) {
+                log_error("Failed to bind private socket: %m");
+                return -errno;
         }
 
-        dbus_server_set_new_connection_function(m->private_bus, bus_new_connection, m, NULL);
+        r = listen(fd, SOMAXCONN);
+        if (r < 0) {
+                log_error("Failed to make private socket listening: %m");
+                return -errno;
+        }
 
-        log_debug("Successfully created private D-Bus server.");
+        r = sd_event_add_io(m->event, fd, EPOLLIN, bus_on_connection, m, &s);
+        if (r < 0) {
+                log_error("Failed to allocate event source: %s", strerror(-r));
+                return r;
+        }
 
-        return 0;
+        m->private_listen_fd = fd;
+        m->private_listen_event_source = s;
+        fd = -1;
 
-fail:
-        bus_done_private(m);
-        dbus_error_free(&error);
+        log_debug("Successfully created private D-Bus server.");
 
-        return r;
+        return 0;
 }
 
 int bus_init(Manager *m, bool try_bus_connect) {
         int r;
 
-        if (set_ensure_allocated(&m->bus_connections, trivial_hash_func, trivial_compare_func) < 0 ||
-            set_ensure_allocated(&m->bus_connections_for_dispatch, trivial_hash_func, trivial_compare_func) < 0)
-                return log_oom();
-
-        if (m->name_data_slot < 0)
-                if (!dbus_pending_call_allocate_data_slot(&m->name_data_slot))
-                        return log_oom();
-
-        if (m->conn_data_slot < 0)
-                if (!dbus_pending_call_allocate_data_slot(&m->conn_data_slot))
-                        return log_oom();
-
-        if (m->subscribed_data_slot < 0)
-                if (!dbus_connection_allocate_data_slot(&m->subscribed_data_slot))
-                        return log_oom();
-
         if (try_bus_connect) {
-                if ((r = bus_init_system(m)) < 0 ||
-                    (r = bus_init_api(m)) < 0)
+                r = bus_init_system(m);
+                if (r < 0)
+                        return r;
+
+                r = bus_init_api(m);
+                if (r < 0)
                         return r;
         }
 
@@ -1163,415 +961,113 @@ int bus_init(Manager *m, bool try_bus_connect) {
         return 0;
 }
 
-static void shutdown_connection(Manager *m, DBusConnection *c) {
-        Job *j;
+static void destroy_bus(Manager *m, sd_bus **bus) {
         Iterator i;
+        Job *j;
 
-        HASHMAP_FOREACH(j, m->jobs, i) {
-                JobBusClient *cl, *nextcl;
-                LIST_FOREACH_SAFE(client, cl, nextcl, j->bus_client_list) {
-                        if (cl->bus == c) {
-                                LIST_REMOVE(client, j->bus_client_list, cl);
-                                free(cl);
-                        }
-                }
-        }
-
-        set_remove(m->bus_connections, c);
-        set_remove(m->bus_connections_for_dispatch, c);
-        set_free_free(BUS_CONNECTION_SUBSCRIBED(m, c));
-
-        if (m->queued_message_connection == c) {
-                m->queued_message_connection = NULL;
-
-                if (m->queued_message) {
-                        dbus_message_unref(m->queued_message);
-                        m->queued_message = NULL;
-                }
-        }
-
-        dbus_connection_set_dispatch_status_function(c, NULL, NULL, NULL);
-        /* system manager cannot afford to block on DBus */
-        if (m->running_as != SYSTEMD_SYSTEM)
-                dbus_connection_flush(c);
-        dbus_connection_close(c);
-        dbus_connection_unref(c);
-}
+        assert(m);
+        assert(bus);
 
-static void bus_done_api(Manager *m) {
-        if (!m->api_bus)
+        if (!*bus)
                 return;
 
-        if (m->running_as == SYSTEMD_USER)
-                shutdown_connection(m, m->api_bus);
+        /* Get rid of tracked clients on this bus */
+        bus_client_untrack_bus(m->subscribed, *bus);
+        HASHMAP_FOREACH(j, m->jobs, i)
+                bus_client_untrack_bus(j->subscribed, *bus);
 
-        m->api_bus = NULL;
+        /* Get rid of queued message on this bus */
+        if (m->queued_message_bus == *bus) {
+                m->queued_message_bus = sd_bus_unref(m->queued_message_bus);
 
-        if (m->queued_message) {
-                dbus_message_unref(m->queued_message);
-                m->queued_message = NULL;
+                if (m->queued_message)
+                        m->queued_message = sd_bus_message_unref(m->queued_message);
         }
-}
-
-static void bus_done_system(Manager *m) {
-        if (!m->system_bus)
-                return;
-
-        if (m->running_as == SYSTEMD_SYSTEM)
-                bus_done_api(m);
 
-        shutdown_connection(m, m->system_bus);
-        m->system_bus = NULL;
-}
-
-static void bus_done_private(Manager *m) {
-        if (!m->private_bus)
-                return;
+        /* Possibly flush unwritten data, but only if we are
+         * unprivileged, since we don't want to sync here */
+        if (m->running_as != SYSTEMD_SYSTEM)
+                sd_bus_flush(*bus);
 
-        dbus_server_disconnect(m->private_bus);
-        dbus_server_unref(m->private_bus);
-        m->private_bus = NULL;
+        /* And destroy the object */
+        sd_bus_close(*bus);
+        *bus = sd_bus_unref(*bus);
 }
 
 void bus_done(Manager *m) {
-        DBusConnection *c;
-
-        bus_done_api(m);
-        bus_done_system(m);
-        bus_done_private(m);
-
-        while ((c = set_steal_first(m->bus_connections)))
-                shutdown_connection(m, c);
-
-        while ((c = set_steal_first(m->bus_connections_for_dispatch)))
-                shutdown_connection(m, c);
-
-        set_free(m->bus_connections);
-        set_free(m->bus_connections_for_dispatch);
-
-        if (m->name_data_slot >= 0)
-                dbus_pending_call_free_data_slot(&m->name_data_slot);
-
-        if (m->conn_data_slot >= 0)
-                dbus_pending_call_free_data_slot(&m->conn_data_slot);
-
-        if (m->subscribed_data_slot >= 0)
-                dbus_connection_free_data_slot(&m->subscribed_data_slot);
-}
-
-static void query_pid_pending_cb(DBusPendingCall *pending, void *userdata) {
-        Manager *m = userdata;
-        DBusMessage *reply;
-        DBusError error;
-        const char *name;
-
-        dbus_error_init(&error);
-
-        assert_se(name = BUS_PENDING_CALL_NAME(m, pending));
-        assert_se(reply = dbus_pending_call_steal_reply(pending));
-
-        switch (dbus_message_get_type(reply)) {
-
-        case DBUS_MESSAGE_TYPE_ERROR:
-
-                assert_se(dbus_set_error_from_message(&error, reply));
-                log_warning("GetConnectionUnixProcessID() failed: %s", bus_error_message(&error));
-                break;
-
-        case DBUS_MESSAGE_TYPE_METHOD_RETURN: {
-                uint32_t r;
-
-                if (!dbus_message_get_args(reply,
-                                           &error,
-                                           DBUS_TYPE_UINT32, &r,
-                                           DBUS_TYPE_INVALID)) {
-                        log_error("Failed to parse GetConnectionUnixProcessID() reply: %s", bus_error_message(&error));
-                        break;
-                }
-
-                manager_dispatch_bus_query_pid_done(m, name, (pid_t) r);
-                break;
-        }
-
-        default:
-                assert_not_reached("Invalid reply message");
-        }
-
-        dbus_message_unref(reply);
-        dbus_error_free(&error);
-}
-
-int bus_query_pid(Manager *m, const char *name) {
-        DBusMessage *message = NULL;
-        DBusPendingCall *pending = NULL;
-        char *n = NULL;
+        sd_bus *b;
 
         assert(m);
-        assert(name);
-
-        if (!(message = dbus_message_new_method_call(
-                              DBUS_SERVICE_DBUS,
-                              DBUS_PATH_DBUS,
-                              DBUS_INTERFACE_DBUS,
-                              "GetConnectionUnixProcessID")))
-                goto oom;
 
-        if (!(dbus_message_append_args(
-                              message,
-                              DBUS_TYPE_STRING, &name,
-                              DBUS_TYPE_INVALID)))
-                goto oom;
-
-        if (!dbus_connection_send_with_reply(m->api_bus, message, &pending, -1))
-                goto oom;
-
-        if (!(n = strdup(name)))
-                goto oom;
-
-        if (!dbus_pending_call_set_data(pending, m->name_data_slot, n, free))
-                goto oom;
-
-        n = NULL;
-
-        if (!dbus_pending_call_set_notify(pending, query_pid_pending_cb, m, NULL))
-                goto oom;
-
-        dbus_message_unref(message);
-        dbus_pending_call_unref(pending);
+        if (m->api_bus)
+                destroy_bus(m, &m->api_bus);
+        if (m->system_bus)
+                destroy_bus(m, &m->system_bus);
+        while ((b = set_steal_first(m->private_buses)))
+                destroy_bus(m, &b);
 
-        return 0;
+        set_free(m->private_buses);
+        set_free(m->subscribed);
 
-oom:
-        free(n);
+        if (m->private_listen_event_source)
+                m->private_listen_event_source = sd_event_source_unref(m->private_listen_event_source);
 
-        if (pending) {
-                dbus_pending_call_cancel(pending);
-                dbus_pending_call_unref(pending);
+        if (m->private_listen_fd >= 0) {
+                close_nointr_nofail(m->private_listen_fd);
+                m->private_listen_fd = -1;
         }
-
-        if (message)
-                dbus_message_unref(message);
-
-        return -ENOMEM;
-}
-
-int bus_broadcast(Manager *m, DBusMessage *message) {
-        bool oom = false;
-        Iterator i;
-        DBusConnection *c;
-
-        assert(m);
-        assert(message);
-
-        SET_FOREACH(c, m->bus_connections_for_dispatch, i)
-                if (c != m->system_bus || m->running_as == SYSTEMD_SYSTEM)
-                        oom = !dbus_connection_send(c, message, NULL);
-
-        SET_FOREACH(c, m->bus_connections, i)
-                if (c != m->system_bus || m->running_as == SYSTEMD_SYSTEM)
-                        oom = !dbus_connection_send(c, message, NULL);
-
-        return oom ? -ENOMEM : 0;
-}
-
-bool bus_has_subscriber(Manager *m) {
-        Iterator i;
-        DBusConnection *c;
-
-        assert(m);
-
-        /* If we are reloading then we might not have deserialized the
-           subscribers yet, hence let's assume that there are some */
-
-        if (m->n_reloading > 0)
-                return true;
-
-        SET_FOREACH(c, m->bus_connections_for_dispatch, i)
-                if (bus_connection_has_subscriber(m, c))
-                        return true;
-
-        SET_FOREACH(c, m->bus_connections, i)
-                if (bus_connection_has_subscriber(m, c))
-                        return true;
-
-        return false;
-}
-
-bool bus_connection_has_subscriber(Manager *m, DBusConnection *c) {
-        assert(m);
-        assert(c);
-
-        return !set_isempty(BUS_CONNECTION_SUBSCRIBED(m, c));
 }
 
 int bus_fdset_add_all(Manager *m, FDSet *fds) {
         Iterator i;
-        DBusConnection *c;
+        sd_bus *b;
+        int fd;
 
         assert(m);
         assert(fds);
 
         /* When we are about to reexecute we add all D-Bus fds to the
          * set to pass over to the newly executed systemd. They won't
-         * be used there however, except that they are closed at the
+         * be used there however, except thatt they are closed at the
          * very end of deserialization, those making it possible for
          * clients to synchronously wait for systemd to reexec by
          * simply waiting for disconnection */
 
-        SET_FOREACH(c, m->bus_connections_for_dispatch, i) {
-                int fd;
-
-                if (dbus_connection_get_unix_fd(c, &fd)) {
+        if (m->api_bus) {
+                fd = sd_bus_get_fd(m->api_bus);
+                if (fd >= 0) {
                         fd = fdset_put_dup(fds, fd);
-
                         if (fd < 0)
                                 return fd;
                 }
         }
 
-        SET_FOREACH(c, m->bus_connections, i) {
-                int fd;
-
-                if (dbus_connection_get_unix_fd(c, &fd)) {
+        SET_FOREACH(b, m->private_buses, i) {
+                fd = sd_bus_get_fd(b);
+                if (fd >= 0) {
                         fd = fdset_put_dup(fds, fd);
-
                         if (fd < 0)
                                 return fd;
                 }
         }
 
-        return 0;
-}
-
-void bus_broadcast_finished(
-                Manager *m,
-                usec_t firmware_usec,
-                usec_t loader_usec,
-                usec_t kernel_usec,
-                usec_t initrd_usec,
-                usec_t userspace_usec,
-                usec_t total_usec) {
-
-        _cleanup_dbus_message_unref_ DBusMessage *message = NULL;
-
-        assert(m);
-
-        message = dbus_message_new_signal("/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "StartupFinished");
-        if (!message) {
-                log_oom();
-                return;
-        }
-
-        assert_cc(sizeof(usec_t) == sizeof(uint64_t));
-        if (!dbus_message_append_args(message,
-                                      DBUS_TYPE_UINT64, &firmware_usec,
-                                      DBUS_TYPE_UINT64, &loader_usec,
-                                      DBUS_TYPE_UINT64, &kernel_usec,
-                                      DBUS_TYPE_UINT64, &initrd_usec,
-                                      DBUS_TYPE_UINT64, &userspace_usec,
-                                      DBUS_TYPE_UINT64, &total_usec,
-                                      DBUS_TYPE_INVALID)) {
-                log_oom();
-                return;
-        }
-
-
-        if (bus_broadcast(m, message) < 0) {
-                log_oom();
-                return;
-        }
-}
-
-void bus_broadcast_reloading(Manager *m, bool active) {
-
-        _cleanup_dbus_message_unref_ DBusMessage *message = NULL;
-        dbus_bool_t b = active;
-
-        assert(m);
-
-        message = dbus_message_new_signal("/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "Reloading");
-        if (!message) {
-                log_oom();
-                return;
-        }
-
-        assert_cc(sizeof(usec_t) == sizeof(uint64_t));
-        if (!dbus_message_append_args(message,
-                                      DBUS_TYPE_BOOLEAN, &b,
-                                      DBUS_TYPE_INVALID)) {
-                log_oom();
-                return;
-        }
-
-
-        if (bus_broadcast(m, message) < 0) {
-                log_oom();
-                return;
-        }
-}
-
-Set *bus_acquire_subscribed(Manager *m, DBusConnection *c) {
-        Set *s;
-
-        assert(m);
-        assert(c);
-
-        s = BUS_CONNECTION_SUBSCRIBED(m, c);
-        if (s)
-                return s;
-
-        s = set_new(string_hash_func, string_compare_func);
-        if (!s)
-                return NULL;
+        /* We don't offer any APIs on the system bus (well, unless it
+         * is the same as the API bus) hence we don't bother with it
+         * here */
 
-        if (!dbus_connection_set_data(c, m->subscribed_data_slot, s, NULL)) {
-                set_free(s);
-                return NULL;
-        }
-
-        return s;
+        return 0;
 }
 
 void bus_serialize(Manager *m, FILE *f) {
-        char *client;
-        Iterator i;
-        Set *s;
-
         assert(m);
         assert(f);
 
-        if (!m->api_bus)
-                return;
-
-        s = BUS_CONNECTION_SUBSCRIBED(m, m->api_bus);
-        SET_FOREACH(client, s, i)
-                fprintf(f, "subscribed=%s\n", client);
+        bus_client_track_serialize(m, f, m->subscribed);
 }
 
 int bus_deserialize_item(Manager *m, const char *line) {
-        const char *e;
-        char *b;
-        Set *s;
-
         assert(m);
         assert(line);
 
-        if (!m->api_bus)
-                return 0;
-
-        e = startswith(line, "subscribed=");
-        if (!e)
-                return 0;
-
-        s = bus_acquire_subscribed(m, m->api_bus);
-        if (!s)
-                return -ENOMEM;
-
-        b = strdup(e);
-        if (!b)
-                return -ENOMEM;
-
-        set_consume(s, b);
-
-        return 1;
+        return bus_client_track_deserialize_item(m, &m->subscribed, line);
 }
diff --git a/src/core/dbus.h b/src/core/dbus.h
index 6500cd7..a3bef47 100644
--- a/src/core/dbus.h
+++ b/src/core/dbus.h
@@ -21,36 +21,14 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <dbus/dbus.h>
-
 #include "manager.h"
 
+int bus_send_queued_message(Manager *m);
+
 int bus_init(Manager *m, bool try_bus_connect);
 void bus_done(Manager *m);
 
-unsigned bus_dispatch(Manager *m);
-
-void bus_watch_event(Manager *m, Watch *w, int events);
-void bus_timeout_event(Manager *m, Watch *w, int events);
-
-int bus_query_pid(Manager *m, const char *name);
-
-int bus_broadcast(Manager *m, DBusMessage *message);
-
-bool bus_has_subscriber(Manager *m);
-bool bus_connection_has_subscriber(Manager *m, DBusConnection *c);
-
 int bus_fdset_add_all(Manager *m, FDSet *fds);
 
-void bus_broadcast_finished(Manager *m, usec_t firmware_usec, usec_t loader_usec, usec_t kernel_usec, usec_t initrd_usec, usec_t userspace_usec, usec_t total_usec);
-void bus_broadcast_reloading(Manager *m, bool active);
-
-Set *bus_acquire_subscribed(Manager *m, DBusConnection *c);
-
 void bus_serialize(Manager *m, FILE *f);
 int bus_deserialize_item(Manager *m, const char *line);
-
-#define BUS_CONNECTION_SUBSCRIBED(m, c) dbus_connection_get_data((c), (m)->subscribed_data_slot)
-#define BUS_PENDING_CALL_NAME(m, p) dbus_pending_call_get_data((p), (m)->name_data_slot)
-
-extern const char * const bus_interface_table[];
diff --git a/src/core/device.c b/src/core/device.c
index 6fc4c95..91e37e0 100644
--- a/src/core/device.c
+++ b/src/core/device.c
@@ -31,12 +31,15 @@
 #include "dbus-device.h"
 #include "def.h"
 #include "path-util.h"
+#include "udev-util.h"
 
 static const UnitActiveState state_translation_table[_DEVICE_STATE_MAX] = {
         [DEVICE_DEAD] = UNIT_INACTIVE,
         [DEVICE_PLUGGED] = UNIT_ACTIVE
 };
 
+static int device_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata);
+
 static void device_unset_sysfs(Device *d) {
         Device *first;
 
@@ -137,7 +140,7 @@ _pure_ static const char *device_sub_state_to_string(Unit *u) {
 }
 
 static int device_add_escaped_name(Unit *u, const char *dn) {
-        char *e;
+        _cleanup_free_ char *e = NULL;
         int r;
 
         assert(u);
@@ -149,8 +152,6 @@ static int device_add_escaped_name(Unit *u, const char *dn) {
                 return -ENOMEM;
 
         r = unit_add_name(u, e);
-        free(e);
-
         if (r < 0 && r != -EEXIST)
                 return r;
 
@@ -158,7 +159,7 @@ static int device_add_escaped_name(Unit *u, const char *dn) {
 }
 
 static int device_find_escape_name(Manager *m, const char *dn, Unit **_u) {
-        char *e;
+        _cleanup_free_ char *e = NULL;
         Unit *u;
 
         assert(m);
@@ -171,8 +172,6 @@ static int device_find_escape_name(Manager *m, const char *dn, Unit **_u) {
                 return -ENOMEM;
 
         u = manager_get_unit(m, e);
-        free(e);
-
         if (u) {
                 *_u = u;
                 return 1;
@@ -222,16 +221,15 @@ static int device_update_unit(Manager *m, struct udev_device *dev, const char *p
         if (!DEVICE(u)->sysfs) {
                 Device *first;
 
-                if (!(DEVICE(u)->sysfs = strdup(sysfs))) {
+                DEVICE(u)->sysfs = strdup(sysfs);
+                if (!DEVICE(u)->sysfs) {
                         r = -ENOMEM;
                         goto fail;
                 }
 
-                if (!m->devices_by_sysfs)
-                        if (!(m->devices_by_sysfs = hashmap_new(string_hash_func, string_compare_func))) {
-                                r = -ENOMEM;
-                                goto fail;
-                        }
+                r = hashmap_ensure_allocated(&m->devices_by_sysfs, string_hash_func, string_compare_func);
+                if (r < 0)
+                        goto fail;
 
                 first = hashmap_get(m->devices_by_sysfs, sysfs);
                 LIST_PREPEND(same_sysfs, first, DEVICE(u));
@@ -242,15 +240,12 @@ static int device_update_unit(Manager *m, struct udev_device *dev, const char *p
         }
 
         if ((model = udev_device_get_property_value(dev, "ID_MODEL_FROM_DATABASE")) ||
-            (model = udev_device_get_property_value(dev, "ID_MODEL"))) {
+            (model = udev_device_get_property_value(dev, "ID_MODEL")))
                 r = unit_set_description(u, model);
-                if (r < 0)
-                        goto fail;
-        } else {
+        else
                 r = unit_set_description(u, path);
-                if (r < 0)
-                        goto fail;
-        }
+        if (r < 0)
+                goto fail;
 
         if (main) {
                 /* The additional systemd udev properties we only
@@ -278,7 +273,7 @@ static int device_update_unit(Manager *m, struct udev_device *dev, const char *p
                         }
                 }
 
-                wants = udev_device_get_property_value(dev, "SYSTEMD_WANTS");
+                wants = udev_device_get_property_value(dev, m->running_as == SYSTEMD_USER ? "SYSTEMD_USER_WANTS" : "SYSTEMD_WANTS");
                 if (wants) {
                         char *state, *w;
                         size_t l;
@@ -324,7 +319,8 @@ static int device_process_new_device(Manager *m, struct udev_device *dev, bool u
 
         assert(m);
 
-        if (!(sysfs = udev_device_get_syspath(dev)))
+        sysfs = udev_device_get_syspath(dev);
+        if (!sysfs)
                 return -ENOMEM;
 
         /* Add the main unit named after the sysfs path */
@@ -384,7 +380,8 @@ static int device_process_path(Manager *m, const char *path, bool update_state)
         assert(m);
         assert(path);
 
-        if (!(dev = udev_device_new_from_syspath(m->udev, path))) {
+        dev = udev_device_new_from_syspath(m->udev, path);
+        if (!dev) {
                 log_warning("Failed to get udev device object from udev for path %s.", path);
                 return -ENOMEM;
         }
@@ -473,6 +470,8 @@ fail:
 static void device_shutdown(Manager *m) {
         assert(m);
 
+        m->udev_event_source = sd_event_source_unref(m->udev_event_source);
+
         if (m->udev_monitor) {
                 udev_monitor_unref(m->udev_monitor);
                 m->udev_monitor = NULL;
@@ -488,19 +487,19 @@ static void device_shutdown(Manager *m) {
 }
 
 static int device_enumerate(Manager *m) {
-        int r;
-        struct udev_enumerate *e = NULL;
+        _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
         struct udev_list_entry *item = NULL, *first = NULL;
+        int r;
 
         assert(m);
 
         if (!m->udev) {
-                struct epoll_event ev;
-
-                if (!(m->udev = udev_new()))
+                m->udev = udev_new();
+                if (!m->udev)
                         return -ENOMEM;
 
-                if (!(m->udev_monitor = udev_monitor_new_from_netlink(m->udev, "udev"))) {
+                m->udev_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
+                if (!m->udev_monitor) {
                         r = -ENOMEM;
                         goto fail;
                 }
@@ -510,101 +509,88 @@ static int device_enumerate(Manager *m) {
                  * during boot. */
                 udev_monitor_set_receive_buffer_size(m->udev_monitor, 128*1024*1024);
 
-                if (udev_monitor_filter_add_match_tag(m->udev_monitor, "systemd") < 0) {
-                        r = -ENOMEM;
+                r = udev_monitor_filter_add_match_tag(m->udev_monitor, "systemd");
+                if (r < 0)
                         goto fail;
-                }
 
-                if (udev_monitor_enable_receiving(m->udev_monitor) < 0) {
-                        r = -EIO;
+                r = udev_monitor_enable_receiving(m->udev_monitor);
+                if (r < 0)
                         goto fail;
-                }
-
-                m->udev_watch.type = WATCH_UDEV;
-                m->udev_watch.fd = udev_monitor_get_fd(m->udev_monitor);
-
-                zero(ev);
-                ev.events = EPOLLIN;
-                ev.data.ptr = &m->udev_watch;
 
-                if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->udev_watch.fd, &ev) < 0)
-                        return -errno;
+                r = sd_event_add_io(m->event, udev_monitor_get_fd(m->udev_monitor), EPOLLIN, device_dispatch_io, m, &m->udev_event_source);
+                if (r < 0)
+                        goto fail;
         }
 
-        if (!(e = udev_enumerate_new(m->udev))) {
+        e = udev_enumerate_new(m->udev);
+        if (!e) {
                 r = -ENOMEM;
                 goto fail;
         }
-        if (udev_enumerate_add_match_tag(e, "systemd") < 0) {
-                r = -EIO;
+
+        r = udev_enumerate_add_match_tag(e, "systemd");
+        if (r < 0)
                 goto fail;
-        }
 
-        if (udev_enumerate_scan_devices(e) < 0) {
-                r = -EIO;
+        r = udev_enumerate_scan_devices(e);
+        if (r < 0)
                 goto fail;
-        }
 
         first = udev_enumerate_get_list_entry(e);
         udev_list_entry_foreach(item, first)
                 device_process_path(m, udev_list_entry_get_name(item), false);
 
-        udev_enumerate_unref(e);
         return 0;
 
 fail:
-        if (e)
-                udev_enumerate_unref(e);
-
         device_shutdown(m);
         return r;
 }
 
-void device_fd_event(Manager *m, int events) {
-        struct udev_device *dev;
-        int r;
+static int device_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
+        _cleanup_udev_device_unref_ struct udev_device *dev = NULL;
         const char *action, *ready;
+        Manager *m = userdata;
+        int r;
 
         assert(m);
 
-        if (events != EPOLLIN) {
+        if (revents != EPOLLIN) {
                 static RATELIMIT_DEFINE(limit, 10*USEC_PER_SEC, 5);
 
                 if (!ratelimit_test(&limit))
                         log_error("Failed to get udev event: %m");
-                if (!(events & EPOLLIN))
-                        return;
+                if (!(revents & EPOLLIN))
+                        return 0;
         }
 
-        if (!(dev = udev_monitor_receive_device(m->udev_monitor))) {
-                /*
-                 * libudev might filter-out devices which pass the bloom filter,
-                 * so getting NULL here is not necessarily an error
-                 */
-                return;
-        }
+        /*
+         * libudev might filter-out devices which pass the bloom
+         * filter, so getting NULL here is not necessarily an error.
+         */
+        dev = udev_monitor_receive_device(m->udev_monitor);
+        if (!dev)
+                return 0;
 
-        if (!(action = udev_device_get_action(dev))) {
+        action = udev_device_get_action(dev);
+        if (!action) {
                 log_error("Failed to get udev action string.");
-                goto fail;
+                return 0;
         }
 
         ready = udev_device_get_property_value(dev, "SYSTEMD_READY");
 
         if (streq(action, "remove") || (ready && parse_boolean(ready) == 0)) {
-                if ((r = device_process_removed_device(m, dev)) < 0) {
+                r = device_process_removed_device(m, dev);
+                if (r < 0)
                         log_error("Failed to process udev device event: %s", strerror(-r));
-                        goto fail;
-                }
         } else {
-                if ((r = device_process_new_device(m, dev, true)) < 0) {
+                r = device_process_new_device(m, dev, true);
+                if (r < 0)
                         log_error("Failed to process udev device event: %s", strerror(-r));
-                        goto fail;
-                }
         }
 
-fail:
-        udev_device_unref(dev);
+        return 0;
 }
 
 static const char* const device_state_table[_DEVICE_STATE_MAX] = {
@@ -624,9 +610,9 @@ const UnitVTable device_vtable = {
         .no_instances = true,
 
         .init = device_init,
-
-        .load = unit_load_fragment_and_dropin_optional,
         .done = device_done,
+        .load = unit_load_fragment_and_dropin_optional,
+
         .coldplug = device_coldplug,
 
         .dump = device_dump,
@@ -635,8 +621,8 @@ const UnitVTable device_vtable = {
         .sub_state_to_string = device_sub_state_to_string,
 
         .bus_interface = "org.freedesktop.systemd1.Device",
-        .bus_message_handler = bus_device_message_handler,
-        .bus_invalidating_properties =  bus_device_invalidating_properties,
+        .bus_changing_properties = bus_device_changing_properties,
+        .bus_vtable = bus_device_vtable,
 
         .following = device_following,
         .following_set = device_following_set,
diff --git a/src/core/device.h b/src/core/device.h
index 41e8de9..bb7ae07 100644
--- a/src/core/device.h
+++ b/src/core/device.h
@@ -50,7 +50,5 @@ struct Device {
 
 extern const UnitVTable device_vtable;
 
-void device_fd_event(Manager *m, int events);
-
 const char* device_state_to_string(DeviceState i) _const_;
 DeviceState device_state_from_string(const char *s) _pure_;
diff --git a/src/core/job.c b/src/core/job.c
index 0dd161c..f053d57 100644
--- a/src/core/job.c
+++ b/src/core/job.c
@@ -24,8 +24,8 @@
 #include <sys/timerfd.h>
 #include <sys/epoll.h>
 
-#include "systemd/sd-id128.h"
-#include "systemd/sd-messages.h"
+#include "sd-id128.h"
+#include "sd-messages.h"
 #include "set.h"
 #include "unit.h"
 #include "macro.h"
@@ -37,20 +37,7 @@
 #include "special.h"
 #include "async.h"
 #include "virt.h"
-
-JobBusClient* job_bus_client_new(DBusConnection *connection, const char *name) {
-        JobBusClient *cl;
-        size_t name_len;
-
-        name_len = strlen(name);
-        cl = malloc0(sizeof(JobBusClient) + name_len + 1);
-        if (!cl)
-                return NULL;
-
-        cl->bus = connection;
-        memcpy(cl->name, name, name_len + 1);
-        return cl;
-}
+#include "dbus-client-track.h"
 
 Job* job_new_raw(Unit *unit) {
         Job *j;
@@ -66,7 +53,6 @@ Job* job_new_raw(Unit *unit) {
         j->manager = unit->manager;
         j->unit = unit;
         j->type = _JOB_TYPE_INVALID;
-        j->timer_watch.type = WATCH_INVALID;
 
         return j;
 }
@@ -89,8 +75,6 @@ Job* job_new(Unit *unit, JobType type) {
 }
 
 void job_free(Job *j) {
-        JobBusClient *cl;
-
         assert(j);
         assert(!j->installed);
         assert(!j->transaction_prev);
@@ -104,19 +88,10 @@ void job_free(Job *j) {
         if (j->in_dbus_queue)
                 LIST_REMOVE(dbus_queue, j->manager->dbus_job_queue, j);
 
-        if (j->timer_watch.type != WATCH_INVALID) {
-                assert(j->timer_watch.type == WATCH_JOB_TIMER);
-                assert(j->timer_watch.data.job == j);
-                assert(j->timer_watch.fd >= 0);
+        sd_event_source_unref(j->timer_event_source);
 
-                assert_se(epoll_ctl(j->manager->epoll_fd, EPOLL_CTL_DEL, j->timer_watch.fd, NULL) >= 0);
-                close_nointr_nofail(j->timer_watch.fd);
-        }
+        bus_client_track_free(j->subscribed);
 
-        while ((cl = j->bus_client_list)) {
-                LIST_REMOVE(client, j->bus_client_list, cl);
-                free(cl);
-        }
         free(j);
 }
 
@@ -859,48 +834,32 @@ finish:
         return 0;
 }
 
-int job_start_timer(Job *j) {
-        struct itimerspec its = {};
-        struct epoll_event ev = {
-                .data.ptr = &j->timer_watch,
-                .events = EPOLLIN,
-        };
-        int fd, r;
-
-        if (j->unit->job_timeout <= 0 ||
-            j->timer_watch.type == WATCH_JOB_TIMER)
-                return 0;
+static int job_dispatch_timer(sd_event_source *s, uint64_t monotonic, void *userdata) {
+        Job *j = userdata;
 
-        assert(j->timer_watch.type == WATCH_INVALID);
-
-        if ((fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK|TFD_CLOEXEC)) < 0) {
-                r = -errno;
-                goto fail;
-        }
+        assert(j);
+        assert(s == j->timer_event_source);
 
-        timespec_store(&its.it_value, j->unit->job_timeout);
+        log_warning_unit(j->unit->id, "Job %s/%s timed out.",
+                         j->unit->id, job_type_to_string(j->type));
 
-        if (timerfd_settime(fd, 0, &its, NULL) < 0) {
-                r = -errno;
-                goto fail;
-        }
+        job_finish_and_invalidate(j, JOB_TIMEOUT, true);
+        return 0;
+}
 
-        if (epoll_ctl(j->manager->epoll_fd, EPOLL_CTL_ADD, fd, &ev) < 0) {
-                r = -errno;
-                goto fail;
-        }
+int job_start_timer(Job *j) {
+        int r;
 
-        j->timer_watch.type = WATCH_JOB_TIMER;
-        j->timer_watch.fd = fd;
-        j->timer_watch.data.job = j;
+        if (j->unit->job_timeout <= 0 || j->timer_event_source)
+                return 0;
 
-        return 0;
+        j->begin_usec = now(CLOCK_MONOTONIC);
 
-fail:
-        if (fd >= 0)
-                close_nointr_nofail(fd);
+        r = sd_event_add_monotonic(j->manager->event, j->begin_usec + j->unit->job_timeout, 0, job_dispatch_timer, j, &j->timer_event_source);
+        if (r < 0)
+                return r;
 
-        return r;
+        return 0;
 }
 
 void job_add_to_run_queue(Job *j) {
@@ -940,15 +899,6 @@ char *job_dbus_path(Job *j) {
         return p;
 }
 
-void job_timer_event(Job *j, uint64_t n_elapsed, Watch *w) {
-        assert(j);
-        assert(w == &j->timer_watch);
-
-        log_warning_unit(j->unit->id, "Job %s/%s timed out.",
-                         j->unit->id, job_type_to_string(j->type));
-        job_finish_and_invalidate(j, JOB_TIMEOUT, true);
-}
-
 int job_serialize(Job *j, FILE *f, FDSet *fds) {
         fprintf(f, "job-id=%u\n", j->id);
         fprintf(f, "job-type=%s\n", job_type_to_string(j->type));
@@ -957,16 +907,11 @@ int job_serialize(Job *j, FILE *f, FDSet *fds) {
         fprintf(f, "job-irreversible=%s\n", yes_no(j->irreversible));
         fprintf(f, "job-sent-dbus-new-signal=%s\n", yes_no(j->sent_dbus_new_signal));
         fprintf(f, "job-ignore-order=%s\n", yes_no(j->ignore_order));
-        /* Cannot save bus clients. Just note the fact that we're losing
-         * them. job_send_message() will fallback to broadcasting. */
-        fprintf(f, "job-forgot-bus-clients=%s\n",
-                yes_no(j->forgot_bus_clients || j->bus_client_list));
-        if (j->timer_watch.type == WATCH_JOB_TIMER) {
-                int copy = fdset_put_dup(fds, j->timer_watch.fd);
-                if (copy < 0)
-                        return copy;
-                fprintf(f, "job-timer-watch-fd=%d\n", copy);
-        }
+
+        if (j->begin_usec > 0)
+                fprintf(f, "job-begin=%llu", (unsigned long long) j->begin_usec);
+
+        bus_client_track_serialize(j->manager, f, j->subscribed);
 
         /* End marker */
         fputc('\n', f);
@@ -974,6 +919,8 @@ int job_serialize(Job *j, FILE *f, FDSet *fds) {
 }
 
 int job_deserialize(Job *j, FILE *f, FDSet *fds) {
+        assert(j);
+
         for (;;) {
                 char line[LINE_MAX], *l, *v;
                 size_t k;
@@ -1000,81 +947,101 @@ int job_deserialize(Job *j, FILE *f, FDSet *fds) {
                         v = l+k;
 
                 if (streq(l, "job-id")) {
+
                         if (safe_atou32(v, &j->id) < 0)
                                 log_debug("Failed to parse job id value %s", v);
+
                 } else if (streq(l, "job-type")) {
-                        JobType t = job_type_from_string(v);
+                        JobType t;
+
+                        t = job_type_from_string(v);
                         if (t < 0)
                                 log_debug("Failed to parse job type %s", v);
                         else if (t >= _JOB_TYPE_MAX_IN_TRANSACTION)
                                 log_debug("Cannot deserialize job of type %s", v);
                         else
                                 j->type = t;
+
                 } else if (streq(l, "job-state")) {
-                        JobState s = job_state_from_string(v);
+                        JobState s;
+
+                        s = job_state_from_string(v);
                         if (s < 0)
                                 log_debug("Failed to parse job state %s", v);
                         else
                                 j->state = s;
+
                 } else if (streq(l, "job-override")) {
-                        int b = parse_boolean(v);
+                        int b;
+
+                        b = parse_boolean(v);
                         if (b < 0)
                                 log_debug("Failed to parse job override flag %s", v);
                         else
                                 j->override = j->override || b;
+
                 } else if (streq(l, "job-irreversible")) {
-                        int b = parse_boolean(v);
+                        int b;
+
+                        b = parse_boolean(v);
                         if (b < 0)
                                 log_debug("Failed to parse job irreversible flag %s", v);
                         else
                                 j->irreversible = j->irreversible || b;
+
                 } else if (streq(l, "job-sent-dbus-new-signal")) {
-                        int b = parse_boolean(v);
+                        int b;
+
+                        b = parse_boolean(v);
                         if (b < 0)
                                 log_debug("Failed to parse job sent_dbus_new_signal flag %s", v);
                         else
                                 j->sent_dbus_new_signal = j->sent_dbus_new_signal || b;
+
                 } else if (streq(l, "job-ignore-order")) {
-                        int b = parse_boolean(v);
+                        int b;
+
+                        b = parse_boolean(v);
                         if (b < 0)
                                 log_debug("Failed to parse job ignore_order flag %s", v);
                         else
                                 j->ignore_order = j->ignore_order || b;
-                } else if (streq(l, "job-forgot-bus-clients")) {
-                        int b = parse_boolean(v);
-                        if (b < 0)
-                                log_debug("Failed to parse job forgot_bus_clients flag %s", v);
+
+                } else if (streq(l, "job-begin")) {
+                        unsigned long long ull;
+
+                        if (sscanf(v, "%llu", &ull) != 1)
+                                log_debug("Failed to parse job-begin value %s", v);
                         else
-                                j->forgot_bus_clients = j->forgot_bus_clients || b;
-                } else if (streq(l, "job-timer-watch-fd")) {
-                        int fd;
-                        if (safe_atoi(v, &fd) < 0 || fd < 0 || !fdset_contains(fds, fd))
-                                log_debug("Failed to parse job-timer-watch-fd value %s", v);
-                        else {
-                                if (j->timer_watch.type == WATCH_JOB_TIMER)
-                                        close_nointr_nofail(j->timer_watch.fd);
-
-                                j->timer_watch.type = WATCH_JOB_TIMER;
-                                j->timer_watch.fd = fdset_remove(fds, fd);
-                                j->timer_watch.data.job = j;
-                        }
+                                j->begin_usec = ull;
+
+                } else {
+                        char t[strlen(l) + 1 + strlen(v) + 1];
+
+                        strcpy(stpcpy(stpcpy(t, l), "="), v);
+
+                        if (bus_client_track_deserialize_item(j->manager, &j->subscribed, t) == 0)
+                                log_debug("Unknown deserialization key '%s'", l);
                 }
         }
 }
 
 int job_coldplug(Job *j) {
-        struct epoll_event ev = {
-                .data.ptr = &j->timer_watch,
-                .events = EPOLLIN,
-        };
+        int r;
+
+        assert(j);
 
-        if (j->timer_watch.type != WATCH_JOB_TIMER)
+        if (j->begin_usec <= 0)
                 return 0;
 
-        if (epoll_ctl(j->manager->epoll_fd, EPOLL_CTL_ADD, j->timer_watch.fd, &ev) < 0)
-                return -errno;
+        if (j->timer_event_source)
+                j->timer_event_source = sd_event_source_unref(j->timer_event_source);
 
-        return 0;
+        r = sd_event_add_monotonic(j->manager->event, j->begin_usec + j->unit->job_timeout, 0, job_dispatch_timer, j, &j->timer_event_source);
+        if (r < 0)
+                log_debug("Failed to restart timeout for job: %s", strerror(-r));
+
+        return r;
 }
 
 void job_shutdown_magic(Job *j) {
diff --git a/src/core/job.h b/src/core/job.h
index be9d278..60bb87d 100644
--- a/src/core/job.h
+++ b/src/core/job.h
@@ -27,7 +27,6 @@
 
 typedef struct Job Job;
 typedef struct JobDependency JobDependency;
-typedef struct JobBusClient JobBusClient;
 typedef enum JobType JobType;
 typedef enum JobState JobState;
 typedef enum JobMode JobMode;
@@ -102,6 +101,7 @@ enum JobResult {
         _JOB_RESULT_INVALID = -1
 };
 
+#include "sd-event.h"
 #include "manager.h"
 #include "unit.h"
 #include "hashmap.h"
@@ -120,13 +120,6 @@ struct JobDependency {
         bool conflicts;
 };
 
-struct JobBusClient {
-        LIST_FIELDS(JobBusClient, client);
-        /* Note that this bus object is not ref counted here. */
-        DBusConnection *bus;
-        char name[0];
-};
-
 struct Job {
         Manager *manager;
         Unit *unit;
@@ -147,10 +140,11 @@ struct Job {
         JobType type;
         JobState state;
 
-        Watch timer_watch;
+        sd_event_source *timer_event_source;
+        usec_t begin_usec;
 
         /* There can be more than one client, because of job merging. */
-        LIST_HEAD(JobBusClient, bus_client_list);
+        Set *subscribed;
 
         JobResult result;
 
@@ -165,8 +159,6 @@ struct Job {
         bool irreversible:1;
 };
 
-JobBusClient* job_bus_client_new(DBusConnection *connection, const char *name);
-
 Job* job_new(Unit *unit, JobType type);
 Job* job_new_raw(Unit *unit);
 void job_free(Job *job);
@@ -210,7 +202,6 @@ void job_add_to_run_queue(Job *j);
 void job_add_to_dbus_queue(Job *j);
 
 int job_start_timer(Job *j);
-void job_timer_event(Job *j, uint64_t n_elapsed, Watch *w);
 
 int job_run_and_invalidate(Job *j);
 int job_finish_and_invalidate(Job *j, JobResult result, bool recursive);
diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4
index b64fdc9..22dc536 100644
--- a/src/core/load-fragment-gperf.gperf.m4
+++ b/src/core/load-fragment-gperf.gperf.m4
@@ -210,7 +210,7 @@ Socket.Broadcast,                config_parse_bool,                  0,
 Socket.PassCredentials,          config_parse_bool,                  0,                             offsetof(Socket, pass_cred)
 Socket.PassSecurity,             config_parse_bool,                  0,                             offsetof(Socket, pass_sec)
 Socket.TCPCongestion,            config_parse_string,                0,                             offsetof(Socket, tcp_congestion)
-Socket.ReusePort,                config_parse_bool,                  0,                             offsetof(Socket, reuseport)
+Socket.ReusePort,                config_parse_bool,                  0,                             offsetof(Socket, reuse_port)
 Socket.MessageQueueMaxMessages,  config_parse_long,                  0,                             offsetof(Socket, mq_maxmsg)
 Socket.MessageQueueMessageSize,  config_parse_long,                  0,                             offsetof(Socket, mq_msgsize)
 Socket.Service,                  config_parse_socket_service,        0,                             0
diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c
index 72c4637..de612f0 100644
--- a/src/core/load-fragment.c
+++ b/src/core/load-fragment.c
@@ -45,12 +45,13 @@
 #include "missing.h"
 #include "unit-name.h"
 #include "unit-printf.h"
-#include "dbus-common.h"
 #include "utf8.h"
 #include "path-util.h"
 #include "syscall-list.h"
 #include "env-util.h"
 #include "cgroup.h"
+#include "bus-util.h"
+#include "bus-error.h"
 
 #ifndef HAVE_SYSV_COMPAT
 int config_parse_warn_compat(const char *unit,
@@ -1288,6 +1289,7 @@ int config_parse_path_spec(const char *unit,
         if (!s)
                 return log_oom();
 
+        s->unit = UNIT(p);
         s->path = path_kill_slashes(k);
         k = NULL;
         s->type = b;
@@ -1308,9 +1310,9 @@ int config_parse_socket_service(const char *unit,
                                 void *data,
                                 void *userdata) {
 
+        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
         Socket *s = data;
         int r;
-        DBusError error;
         Unit *x;
         _cleanup_free_ char *p = NULL;
 
@@ -1319,25 +1321,18 @@ int config_parse_socket_service(const char *unit,
         assert(rvalue);
         assert(data);
 
-        dbus_error_init(&error);
-
         r = unit_name_printf(UNIT(s), rvalue, &p);
         if (r < 0)
-                log_syntax(unit, LOG_ERR, filename, line, -r,
-                           "Failed to resolve specifiers, ignoring: %s", rvalue);
+                log_syntax(unit, LOG_ERR, filename, line, -r, "Failed to resolve specifiers, ignoring: %s", rvalue);
 
         if (!endswith(p ?: rvalue, ".service")) {
-                log_syntax(unit, LOG_ERR, filename, line, EINVAL,
-                           "Unit must be of type service, ignoring: %s", rvalue);
+                log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Unit must be of type service, ignoring: %s", rvalue);
                 return 0;
         }
 
         r = manager_load_unit(UNIT(s)->manager, p ?: rvalue, NULL, &error, &x);
         if (r < 0) {
-                log_syntax(unit, LOG_ERR, filename, line, r,
-                           "Failed to load unit %s, ignoring: %s",
-                           rvalue, bus_error(&error, r));
-                dbus_error_free(&error);
+                log_syntax(unit, LOG_ERR, filename, line, r, "Failed to load unit %s, ignoring: %s", rvalue, bus_error_message(&error, r));
                 return 0;
         }
 
diff --git a/src/core/main.c b/src/core/main.c
index c89c123..f342cdd 100644
--- a/src/core/main.c
+++ b/src/core/main.c
@@ -19,8 +19,6 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <dbus/dbus.h>
-
 #include <stdio.h>
 #include <errno.h>
 #include <string.h>
@@ -34,13 +32,15 @@
 #include <sys/prctl.h>
 #include <sys/mount.h>
 
+#include "sd-daemon.h"
+#include "sd-messages.h"
+#include "sd-bus.h"
 #include "manager.h"
 #include "log.h"
 #include "load-fragment.h"
 #include "fdset.h"
 #include "special.h"
 #include "conf-parser.h"
-#include "dbus-common.h"
 #include "missing.h"
 #include "label.h"
 #include "build.h"
@@ -54,20 +54,21 @@
 #include "killall.h"
 #include "env-util.h"
 #include "hwclock.h"
-#include "sd-daemon.h"
-#include "sd-messages.h"
+#include "fileio.h"
+#include "dbus-manager.h"
+#include "bus-error.h"
+#include "bus-util.h"
 
 #include "mount-setup.h"
 #include "loopback-setup.h"
-#ifdef HAVE_KMOD
-#include "kmod-setup.h"
-#endif
 #include "hostname-setup.h"
 #include "machine-id-setup.h"
 #include "selinux-setup.h"
 #include "ima-setup.h"
-#include "fileio.h"
 #include "smack-setup.h"
+#ifdef HAVE_KMOD
+#include "kmod-setup.h"
+#endif
 
 static enum {
         ACTION_RUN,
@@ -1039,7 +1040,7 @@ static int prepare_reexecute(Manager *m, FILE **_f, FDSet **_fds, bool switching
 
         /* Make sure nothing is really destructed when we shut down */
         m->n_reloading ++;
-        bus_broadcast_reloading(m, true);
+        bus_manager_send_reloading(m, true);
 
         fds = fdset_new();
         if (!fds) {
@@ -1442,9 +1443,6 @@ int main(int argc, char *argv[]) {
         /* Move out of the way, so that we won't block unmounts */
         assert_se(chdir("/")  == 0);
 
-        /* Make sure D-Bus doesn't fiddle with the SIGPIPE handlers */
-        dbus_connection_set_change_sigpipe(FALSE);
-
         /* Reset the console, but only if this is really init and we
          * are freshly booted */
         if (arg_running_as == SYSTEMD_SYSTEM && arg_action == ACTION_RUN)
@@ -1551,7 +1549,7 @@ int main(int argc, char *argv[]) {
         manager_set_default_rlimits(m, arg_default_rlimit);
 
         if (arg_default_environment)
-                manager_environment_add(m, arg_default_environment);
+                manager_environment_add(m, NULL, arg_default_environment);
 
         manager_set_show_status(m, arg_show_status);
 
@@ -1575,19 +1573,16 @@ int main(int argc, char *argv[]) {
         }
 
         if (queue_default_job) {
-                DBusError error;
+                _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
                 Unit *target = NULL;
                 Job *default_unit_job;
 
-                dbus_error_init(&error);
-
                 log_debug("Activating default unit: %s", arg_default_unit);
 
                 r = manager_load_unit(m, arg_default_unit, NULL, &error, &target);
-                if (r < 0) {
-                        log_error("Failed to load default target: %s", bus_error(&error, r));
-                        dbus_error_free(&error);
-                } else if (target->load_state == UNIT_ERROR || target->load_state == UNIT_NOT_FOUND)
+                if (r < 0)
+                        log_error("Failed to load default target: %s", bus_error_message(&error, r));
+                else if (target->load_state == UNIT_ERROR || target->load_state == UNIT_NOT_FOUND)
                         log_error("Failed to load default target: %s", strerror(-target->load_error));
                 else if (target->load_state == UNIT_MASKED)
                         log_error("Default target masked.");
@@ -1597,8 +1592,7 @@ int main(int argc, char *argv[]) {
 
                         r = manager_load_unit(m, SPECIAL_RESCUE_TARGET, NULL, &error, &target);
                         if (r < 0) {
-                                log_error("Failed to load rescue target: %s", bus_error(&error, r));
-                                dbus_error_free(&error);
+                                log_error("Failed to load rescue target: %s", bus_error_message(&error, r));
                                 goto finish;
                         } else if (target->load_state == UNIT_ERROR || target->load_state == UNIT_NOT_FOUND) {
                                 log_error("Failed to load rescue target: %s", strerror(-target->load_error));
@@ -1618,18 +1612,15 @@ int main(int argc, char *argv[]) {
 
                 r = manager_add_job(m, JOB_START, target, JOB_ISOLATE, false, &error, &default_unit_job);
                 if (r == -EPERM) {
-                        log_debug("Default target could not be isolated, starting instead: %s", bus_error(&error, r));
-                        dbus_error_free(&error);
+                        log_debug("Default target could not be isolated, starting instead: %s", bus_error_message(&error, r));
 
                         r = manager_add_job(m, JOB_START, target, JOB_REPLACE, false, &error, &default_unit_job);
                         if (r < 0) {
-                                log_error("Failed to start default target: %s", bus_error(&error, r));
-                                dbus_error_free(&error);
+                                log_error("Failed to start default target: %s", bus_error_message(&error, r));
                                 goto finish;
                         }
                 } else if (r < 0) {
-                        log_error("Failed to isolate default target: %s", bus_error(&error, r));
-                        dbus_error_free(&error);
+                        log_error("Failed to isolate default target: %s", bus_error_message(&error, r));
                         goto finish;
                 }
 
@@ -1725,7 +1716,6 @@ finish:
         free(arg_default_unit);
         free_join_controllers();
 
-        dbus_shutdown();
         label_finish();
 
         if (reexecute) {
diff --git a/src/core/manager.c b/src/core/manager.c
index c99a022..86de0e3 100644
--- a/src/core/manager.c
+++ b/src/core/manager.c
@@ -42,9 +42,9 @@
 #include <libaudit.h>
 #endif
 
-#include "systemd/sd-daemon.h"
-#include "systemd/sd-id128.h"
-#include "systemd/sd-messages.h"
+#include "sd-daemon.h"
+#include "sd-id128.h"
+#include "sd-messages.h"
 
 #include "manager.h"
 #include "transaction.h"
@@ -58,12 +58,9 @@
 #include "locale-setup.h"
 #include "mount-setup.h"
 #include "unit-name.h"
-#include "dbus-unit.h"
-#include "dbus-job.h"
 #include "missing.h"
 #include "path-lookup.h"
 #include "special.h"
-#include "bus-errors.h"
 #include "exit-status.h"
 #include "virt.h"
 #include "watchdog.h"
@@ -72,6 +69,13 @@
 #include "audit-fd.h"
 #include "boot-timestamps.h"
 #include "env-util.h"
+#include "bus-errors.h"
+#include "bus-error.h"
+#include "bus-util.h"
+#include "dbus.h"
+#include "dbus-unit.h"
+#include "dbus-job.h"
+#include "dbus-manager.h"
 
 /* As soon as 5s passed since a unit was added to our GC queue, make sure to run a gc sweep */
 #define GC_QUEUE_USEC_MAX (10*USEC_PER_SEC)
@@ -86,6 +90,12 @@
 
 #define TIME_T_MAX (time_t)((1UL << ((sizeof(time_t) << 3) - 1)) - 1)
 
+static int manager_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata);
+static int manager_dispatch_signal_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata);
+static int manager_dispatch_time_change_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata);
+static int manager_dispatch_idle_pipe_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata);
+static int manager_dispatch_jobs_in_progress(sd_event_source *source, usec_t usec, void *userdata);
+
 static int manager_setup_notify(Manager *m) {
         union {
                 struct sockaddr sa;
@@ -93,15 +103,10 @@ static int manager_setup_notify(Manager *m) {
         } sa = {
                 .sa.sa_family = AF_UNIX,
         };
-        struct epoll_event ev = {
-                .events = EPOLLIN,
-                .data.ptr = &m->notify_watch,
-        };
         int one = 1, r;
 
-        m->notify_watch.type = WATCH_NOTIFY;
-        m->notify_watch.fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
-        if (m->notify_watch.fd < 0) {
+        m->notify_fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
+        if (m->notify_fd < 0) {
                 log_error("Failed to allocate notification socket: %m");
                 return -errno;
         }
@@ -110,25 +115,23 @@ static int manager_setup_notify(Manager *m) {
                 snprintf(sa.un.sun_path, sizeof(sa.un.sun_path), NOTIFY_SOCKET "/%llu", random_ull());
         else
                 strncpy(sa.un.sun_path, NOTIFY_SOCKET, sizeof(sa.un.sun_path));
-
         sa.un.sun_path[0] = 0;
 
-        r = bind(m->notify_watch.fd, &sa.sa,
-                 offsetof(struct sockaddr_un, sun_path) + 1 + strlen(sa.un.sun_path+1));
+        r = bind(m->notify_fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + 1 + strlen(sa.un.sun_path+1));
         if (r < 0) {
                 log_error("bind() failed: %m");
                 return -errno;
         }
 
-        r = setsockopt(m->notify_watch.fd, SOL_SOCKET, SO_PASSCRED, &one, sizeof(one));
+        r = setsockopt(m->notify_fd, SOL_SOCKET, SO_PASSCRED, &one, sizeof(one));
         if (r < 0) {
                 log_error("SO_PASSCRED failed: %m");
                 return -errno;
         }
 
-        r = epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->notify_watch.fd, &ev);
+        r = sd_event_add_io(m->event, m->notify_fd, EPOLLIN, manager_dispatch_notify_fd, m, &m->notify_event_source);
         if (r < 0) {
-                log_error("Failed to add notification socket fd to epoll: %m");
+                log_error("Failed to allocate notify event source: %s", strerror(-r));
                 return -errno;
         }
 
@@ -142,75 +145,17 @@ static int manager_setup_notify(Manager *m) {
         return 0;
 }
 
-static int manager_jobs_in_progress_mod_timer(Manager *m) {
-        struct itimerspec its = {
-                .it_value.tv_sec = JOBS_IN_PROGRESS_WAIT_SEC,
-                .it_interval.tv_sec = JOBS_IN_PROGRESS_PERIOD_SEC,
-        };
-
-        if (m->jobs_in_progress_watch.type != WATCH_JOBS_IN_PROGRESS)
-                return 0;
-
-        if (timerfd_settime(m->jobs_in_progress_watch.fd, 0, &its, NULL) < 0)
-                return -errno;
-
-        return 0;
-}
-
 static int manager_watch_jobs_in_progress(Manager *m) {
-        struct epoll_event ev = {
-                .events = EPOLLIN,
-                .data.ptr = &m->jobs_in_progress_watch,
-        };
-        int r;
+        assert(m);
 
-        if (m->jobs_in_progress_watch.type != WATCH_INVALID)
+        if (m->jobs_in_progress_event_source)
                 return 0;
 
-        m->jobs_in_progress_watch.type = WATCH_JOBS_IN_PROGRESS;
-        m->jobs_in_progress_watch.fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK|TFD_CLOEXEC);
-        if (m->jobs_in_progress_watch.fd < 0) {
-                log_error("Failed to create timerfd: %m");
-                r = -errno;
-                goto err;
-        }
-
-        r = manager_jobs_in_progress_mod_timer(m);
-        if (r < 0) {
-                log_error("Failed to set up timer for jobs progress watch: %s", strerror(-r));
-                goto err;
-        }
-
-        if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->jobs_in_progress_watch.fd, &ev) < 0) {
-                log_error("Failed to add jobs progress timer fd to epoll: %m");
-                r = -errno;
-                goto err;
-        }
-
-        log_debug("Set up jobs progress timerfd.");
-
-        return 0;
-
-err:
-        if (m->jobs_in_progress_watch.fd >= 0)
-                close_nointr_nofail(m->jobs_in_progress_watch.fd);
-        watch_init(&m->jobs_in_progress_watch);
-        return r;
+        return sd_event_add_monotonic(m->event, JOBS_IN_PROGRESS_WAIT_SEC, 0, manager_dispatch_jobs_in_progress, m, &m->jobs_in_progress_event_source);
 }
 
-static void manager_unwatch_jobs_in_progress(Manager *m) {
-        if (m->jobs_in_progress_watch.type != WATCH_JOBS_IN_PROGRESS)
-                return;
-
-        assert_se(epoll_ctl(m->epoll_fd, EPOLL_CTL_DEL, m->jobs_in_progress_watch.fd, NULL) >= 0);
-        close_nointr_nofail(m->jobs_in_progress_watch.fd);
-        watch_init(&m->jobs_in_progress_watch);
-        m->jobs_in_progress_iteration = 0;
-
-        log_debug("Closed jobs progress timerfd.");
-}
+#define CYLON_BUFFER_EXTRA (2*(sizeof(ANSI_RED_ON)-1) + sizeof(ANSI_HIGHLIGHT_RED_ON)-1 + 2*(sizeof(ANSI_HIGHLIGHT_OFF)-1))
 
-#define CYLON_BUFFER_EXTRA (2*strlen(ANSI_RED_ON) + strlen(ANSI_HIGHLIGHT_RED_ON) + 2*strlen(ANSI_HIGHLIGHT_OFF))
 static void draw_cylon(char buffer[], size_t buflen, unsigned width, unsigned pos) {
         char *p = buffer;
 
@@ -241,13 +186,15 @@ static void draw_cylon(char buffer[], size_t buflen, unsigned width, unsigned po
 }
 
 static void manager_print_jobs_in_progress(Manager *m) {
+        _cleanup_free_ char *job_of_n = NULL;
         Iterator i;
         Job *j;
-        char *job_of_n = NULL;
         unsigned counter = 0, print_nr;
         char cylon[6 + CYLON_BUFFER_EXTRA + 1];
         unsigned cylon_pos;
 
+        assert(m);
+
         print_nr = (m->jobs_in_progress_iteration / JOBS_IN_PROGRESS_PERIOD_DIVISOR) % m->n_running_jobs;
 
         HASHMAP_FOREACH(j, m->jobs, i)
@@ -270,94 +217,69 @@ static void manager_print_jobs_in_progress(Manager *m) {
 
         manager_status_printf(m, true, cylon, "%sA %s job is running for %s",
                               strempty(job_of_n), job_type_to_string(j->type), unit_description(j->unit));
-        free(job_of_n);
 
         m->jobs_in_progress_iteration++;
 }
 
 static int manager_watch_idle_pipe(Manager *m) {
-        struct epoll_event ev = {
-                .events = EPOLLIN,
-                .data.ptr = &m->idle_pipe_watch,
-        };
         int r;
 
-        if (m->idle_pipe_watch.type != WATCH_INVALID)
+        assert(m);
+
+        if (m->idle_pipe_event_source)
                 return 0;
 
         if (m->idle_pipe[2] < 0)
                 return 0;
 
-        m->idle_pipe_watch.type = WATCH_IDLE_PIPE;
-        m->idle_pipe_watch.fd = m->idle_pipe[2];
-        if (m->idle_pipe_watch.fd < 0) {
-                log_error("Failed to create timerfd: %m");
-                r = -errno;
-                goto err;
-        }
-
-        if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->idle_pipe_watch.fd, &ev) < 0) {
-                log_error("Failed to add idle_pipe fd to epoll: %m");
-                r = -errno;
-                goto err;
+        r = sd_event_add_io(m->event, m->idle_pipe[2], EPOLLIN, manager_dispatch_idle_pipe_fd, m, &m->idle_pipe_event_source);
+        if (r < 0) {
+                log_error("Failed to watch idle pipe: %s", strerror(-r));
+                return r;
         }
 
-        log_debug("Set up idle_pipe watch.");
-
         return 0;
-
-err:
-        if (m->idle_pipe_watch.fd >= 0)
-                close_nointr_nofail(m->idle_pipe_watch.fd);
-        watch_init(&m->idle_pipe_watch);
-        return r;
 }
 
-static void manager_unwatch_idle_pipe(Manager *m) {
-        if (m->idle_pipe_watch.type != WATCH_IDLE_PIPE)
-                return;
-
-        assert_se(epoll_ctl(m->epoll_fd, EPOLL_CTL_DEL, m->idle_pipe_watch.fd, NULL) >= 0);
-        watch_init(&m->idle_pipe_watch);
+static void manager_close_idle_pipe(Manager *m) {
+        assert(m);
 
-        log_debug("Closed idle_pipe watch.");
+        close_pipe(m->idle_pipe);
+        close_pipe(m->idle_pipe + 2);
 }
 
 static int manager_setup_time_change(Manager *m) {
-        struct epoll_event ev = {
-                .events = EPOLLIN,
-                .data.ptr = &m->time_change_watch,
-        };
+        int r;
 
         /* We only care for the cancellation event, hence we set the
          * timeout to the latest possible value. */
         struct itimerspec its = {
                 .it_value.tv_sec = TIME_T_MAX,
         };
-        assert_cc(sizeof(time_t) == sizeof(TIME_T_MAX));
 
-        assert(m->time_change_watch.type == WATCH_INVALID);
+        assert(m);
+        assert_cc(sizeof(time_t) == sizeof(TIME_T_MAX));
 
         /* Uses TFD_TIMER_CANCEL_ON_SET to get notifications whenever
          * CLOCK_REALTIME makes a jump relative to CLOCK_MONOTONIC */
 
-        m->time_change_watch.type = WATCH_TIME_CHANGE;
-        m->time_change_watch.fd = timerfd_create(CLOCK_REALTIME, TFD_NONBLOCK|TFD_CLOEXEC);
-        if (m->time_change_watch.fd < 0) {
+        m->time_change_fd = timerfd_create(CLOCK_REALTIME, TFD_NONBLOCK|TFD_CLOEXEC);
+        if (m->time_change_fd < 0) {
                 log_error("Failed to create timerfd: %m");
                 return -errno;
         }
 
-        if (timerfd_settime(m->time_change_watch.fd, TFD_TIMER_ABSTIME|TFD_TIMER_CANCEL_ON_SET, &its, NULL) < 0) {
+        if (timerfd_settime(m->time_change_fd, TFD_TIMER_ABSTIME|TFD_TIMER_CANCEL_ON_SET, &its, NULL) < 0) {
                 log_debug("Failed to set up TFD_TIMER_CANCEL_ON_SET, ignoring: %m");
-                close_nointr_nofail(m->time_change_watch.fd);
-                watch_init(&m->time_change_watch);
+                close_nointr_nofail(m->time_change_fd);
+                m->time_change_fd = -1;
                 return 0;
         }
 
-        if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->time_change_watch.fd, &ev) < 0) {
-                log_error("Failed to add timer change fd to epoll: %m");
-                return -errno;
+        r = sd_event_add_io(m->event, m->time_change_fd, EPOLLIN, manager_dispatch_time_change_fd, m, &m->time_change_event_source);
+        if (r < 0) {
+                log_error("Failed to create time change event source: %s", strerror(-r));
+                return r;
         }
 
         log_debug("Set up TFD_TIMER_CANCEL_ON_SET timerfd.");
@@ -366,7 +288,7 @@ static int manager_setup_time_change(Manager *m) {
 }
 
 static int enable_special_signals(Manager *m) {
-        int fd;
+        _cleanup_close_ int fd = -1;
 
         assert(m);
 
@@ -385,23 +307,18 @@ static int enable_special_signals(Manager *m) {
                 /* Enable that we get SIGWINCH on kbrequest */
                 if (ioctl(fd, KDSIGACCEPT, SIGWINCH) < 0)
                         log_warning("Failed to enable kbrequest handling: %s", strerror(errno));
-
-                close_nointr_nofail(fd);
         }
 
         return 0;
 }
 
 static int manager_setup_signals(Manager *m) {
-        sigset_t mask;
-        struct epoll_event ev = {
-                .events = EPOLLIN,
-                .data.ptr = &m->signal_watch,
-        };
         struct sigaction sa = {
                 .sa_handler = SIG_DFL,
                 .sa_flags = SA_NOCLDSTOP|SA_RESTART,
         };
+        sigset_t mask;
+        int r;
 
         assert(m);
 
@@ -442,13 +359,13 @@ static int manager_setup_signals(Manager *m) {
                         -1);
         assert_se(sigprocmask(SIG_SETMASK, &mask, NULL) == 0);
 
-        m->signal_watch.type = WATCH_SIGNAL;
-        m->signal_watch.fd = signalfd(-1, &mask, SFD_NONBLOCK|SFD_CLOEXEC);
-        if (m->signal_watch.fd < 0)
+        m->signal_fd = signalfd(-1, &mask, SFD_NONBLOCK|SFD_CLOEXEC);
+        if (m->signal_fd < 0)
                 return -errno;
 
-        if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->signal_watch.fd, &ev) < 0)
-                return -errno;
+        r = sd_event_add_io(m->event, m->signal_fd, EPOLLIN, manager_dispatch_signal_fd, m, &m->signal_event_source);
+        if (r < 0)
+                return r;
 
         if (m->running_as == SYSTEMD_SYSTEM)
                 return enable_special_signals(m);
@@ -502,44 +419,39 @@ int manager_new(SystemdRunningAs running_as, bool reexecuting, Manager **_m) {
 #endif
 
         m->running_as = running_as;
-        m->name_data_slot = m->conn_data_slot = m->subscribed_data_slot = -1;
         m->exit_code = _MANAGER_EXIT_CODE_INVALID;
-        m->pin_cgroupfs_fd = -1;
-        m->idle_pipe[0] = m->idle_pipe[1] = m->idle_pipe[2] = m->idle_pipe[3] = -1;
 
-        watch_init(&m->signal_watch);
-        watch_init(&m->mount_watch);
-        watch_init(&m->swap_watch);
-        watch_init(&m->udev_watch);
-        watch_init(&m->time_change_watch);
-        watch_init(&m->jobs_in_progress_watch);
+        m->idle_pipe[0] = m->idle_pipe[1] = m->idle_pipe[2] = m->idle_pipe[3] = -1;
 
-        m->epoll_fd = m->dev_autofs_fd = -1;
+        m->pin_cgroupfs_fd = m->notify_fd = m->signal_fd = m->time_change_fd = m->dev_autofs_fd = m->private_listen_fd = -1;
         m->current_job_id = 1; /* start as id #1, so that we can leave #0 around as "null-like" value */
 
         r = manager_default_environment(m);
         if (r < 0)
                 goto fail;
 
-        if (!(m->units = hashmap_new(string_hash_func, string_compare_func)))
+        r = hashmap_ensure_allocated(&m->units, string_hash_func, string_compare_func);
+        if (r < 0)
                 goto fail;
 
-        if (!(m->jobs = hashmap_new(trivial_hash_func, trivial_compare_func)))
+        r = hashmap_ensure_allocated(&m->jobs, trivial_hash_func, trivial_compare_func);
+        if (r < 0)
                 goto fail;
 
-        if (!(m->watch_pids = hashmap_new(trivial_hash_func, trivial_compare_func)))
+        r = hashmap_ensure_allocated(&m->cgroup_unit, string_hash_func, string_compare_func);
+        if (r < 0)
                 goto fail;
 
-        m->cgroup_unit = hashmap_new(string_hash_func, string_compare_func);
-        if (!m->cgroup_unit)
+        r = hashmap_ensure_allocated(&m->watch_pids, trivial_hash_func, trivial_compare_func);
+        if (r < 0)
                 goto fail;
 
-        m->watch_bus = hashmap_new(string_hash_func, string_compare_func);
-        if (!m->watch_bus)
+        r = hashmap_ensure_allocated(&m->watch_bus, string_hash_func, string_compare_func);
+        if (r < 0)
                 goto fail;
 
-        m->epoll_fd = epoll_create1(EPOLL_CLOEXEC);
-        if (m->epoll_fd < 0)
+        r = sd_event_default(&m->event);
+        if (r < 0)
                 goto fail;
 
         r = manager_setup_signals(m);
@@ -718,11 +630,6 @@ static void manager_clear_jobs_and_units(Manager *m) {
         m->n_running_jobs = 0;
 }
 
-static void close_idle_pipe(Manager *m) {
-        close_pipe(m->idle_pipe);
-        close_pipe(m->idle_pipe + 2);
-}
-
 void manager_free(Manager *m) {
         UnitType c;
         int i;
@@ -748,16 +655,22 @@ void manager_free(Manager *m) {
         hashmap_free(m->watch_pids);
         hashmap_free(m->watch_bus);
 
-        if (m->epoll_fd >= 0)
-                close_nointr_nofail(m->epoll_fd);
-        if (m->signal_watch.fd >= 0)
-                close_nointr_nofail(m->signal_watch.fd);
-        if (m->notify_watch.fd >= 0)
-                close_nointr_nofail(m->notify_watch.fd);
-        if (m->time_change_watch.fd >= 0)
-                close_nointr_nofail(m->time_change_watch.fd);
-        if (m->jobs_in_progress_watch.fd >= 0)
-                close_nointr_nofail(m->jobs_in_progress_watch.fd);
+        sd_event_source_unref(m->signal_event_source);
+        sd_event_source_unref(m->notify_event_source);
+        sd_event_source_unref(m->time_change_event_source);
+        sd_event_source_unref(m->jobs_in_progress_event_source);
+        sd_event_source_unref(m->idle_pipe_event_source);
+
+        if (m->signal_fd >= 0)
+                close_nointr_nofail(m->signal_fd);
+        if (m->notify_fd >= 0)
+                close_nointr_nofail(m->notify_fd);
+        if (m->time_change_fd >= 0)
+                close_nointr_nofail(m->time_change_fd);
+
+        manager_close_idle_pipe(m);
+
+        sd_event_unref(m->event);
 
         free(m->notify_socket);
 
@@ -767,8 +680,6 @@ void manager_free(Manager *m) {
         hashmap_free(m->cgroup_unit);
         set_free_free(m->unit_path_cache);
 
-        close_idle_pipe(m);
-
         free(m->switch_root);
         free(m->switch_root_init);
 
@@ -929,9 +840,9 @@ int manager_startup(Manager *m, FILE *serialization, FDSet *fds) {
                 m->n_reloading ++;
 
         /* First, enumerate what we can from all config files */
-        dual_timestamp_get(&m->unitsload_start_timestamp);
+        dual_timestamp_get(&m->units_load_start_timestamp);
         r = manager_enumerate(m);
-        dual_timestamp_get(&m->unitsload_finish_timestamp);
+        dual_timestamp_get(&m->units_load_finish_timestamp);
 
         /* Second, deserialize if there is something to deserialize */
         if (serialization) {
@@ -968,7 +879,7 @@ int manager_startup(Manager *m, FILE *serialization, FDSet *fds) {
         return r;
 }
 
-int manager_add_job(Manager *m, JobType type, Unit *unit, JobMode mode, bool override, DBusError *e, Job **_ret) {
+int manager_add_job(Manager *m, JobType type, Unit *unit, JobMode mode, bool override, sd_bus_error *e, Job **_ret) {
         int r;
         Transaction *tr;
 
@@ -978,12 +889,12 @@ int manager_add_job(Manager *m, JobType type, Unit *unit, JobMode mode, bool ove
         assert(mode < _JOB_MODE_MAX);
 
         if (mode == JOB_ISOLATE && type != JOB_START) {
-                dbus_set_error(e, BUS_ERROR_INVALID_JOB_MODE, "Isolate is only valid for start.");
+                sd_bus_error_setf(e, SD_BUS_ERROR_INVALID_ARGS, "Isolate is only valid for start.");
                 return -EINVAL;
         }
 
         if (mode == JOB_ISOLATE && !unit->allow_isolate) {
-                dbus_set_error(e, BUS_ERROR_NO_ISOLATION, "Operation refused, unit may not be isolated.");
+                sd_bus_error_setf(e, BUS_ERROR_NO_ISOLATION, "Operation refused, unit may not be isolated.");
                 return -EPERM;
         }
 
@@ -1029,7 +940,7 @@ tr_abort:
         return r;
 }
 
-int manager_add_job_by_name(Manager *m, JobType type, const char *name, JobMode mode, bool override, DBusError *e, Job **_ret) {
+int manager_add_job_by_name(Manager *m, JobType type, const char *name, JobMode mode, bool override, sd_bus_error *e, Job **_ret) {
         Unit *unit;
         int r;
 
@@ -1088,7 +999,7 @@ int manager_load_unit_prepare(
                 Manager *m,
                 const char *name,
                 const char *path,
-                DBusError *e,
+                sd_bus_error *e,
                 Unit **_ret) {
 
         Unit *ret;
@@ -1101,20 +1012,16 @@ int manager_load_unit_prepare(
         /* This will prepare the unit for loading, but not actually
          * load anything from disk. */
 
-        if (path && !is_path(path)) {
-                dbus_set_error(e, BUS_ERROR_INVALID_PATH, "Path %s is not absolute.", path);
-                return -EINVAL;
-        }
+        if (path && !is_path(path))
+                return sd_bus_error_setf(e, SD_BUS_ERROR_INVALID_ARGS, "Path %s is not absolute.", path);
 
         if (!name)
                 name = path_get_file_name(path);
 
         t = unit_name_to_type(name);
 
-        if (t == _UNIT_TYPE_INVALID || !unit_name_is_valid(name, false)) {
-                dbus_set_error(e, BUS_ERROR_INVALID_NAME, "Unit name %s is not valid.", name);
-                return -EINVAL;
-        }
+        if (t == _UNIT_TYPE_INVALID || !unit_name_is_valid(name, false))
+                return sd_bus_error_setf(e, SD_BUS_ERROR_INVALID_ARGS, "Unit name %s is not valid.", name);
 
         ret = manager_get_unit(m, name);
         if (ret) {
@@ -1154,7 +1061,7 @@ int manager_load_unit(
                 Manager *m,
                 const char *name,
                 const char *path,
-                DBusError *e,
+                sd_bus_error *e,
                 Unit **_ret) {
 
         int r;
@@ -1269,16 +1176,26 @@ static unsigned manager_dispatch_dbus_queue(Manager *m) {
         if (m->send_reloading_done) {
                 m->send_reloading_done = false;
 
-                bus_broadcast_reloading(m, false);
+                bus_manager_send_reloading(m, false);
         }
 
+        if (m->queued_message)
+                bus_send_queued_message(m);
+
         return n;
 }
 
-static int manager_process_notify_fd(Manager *m) {
+static int manager_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
+        Manager *m = userdata;
         ssize_t n;
 
         assert(m);
+        assert(m->notify_fd == fd);
+
+        if (revents != EPOLLIN) {
+                log_warning("Got unexpected poll event for notify fd.");
+                return 0;
+        }
 
         for (;;) {
                 char buf[4096];
@@ -1302,7 +1219,7 @@ static int manager_process_notify_fd(Manager *m) {
                 Unit *u;
                 _cleanup_strv_free_ char **tags = NULL;
 
-                n = recvmsg(m->notify_watch.fd, &msghdr, MSG_DONTWAIT);
+                n = recvmsg(m->notify_fd, &msghdr, MSG_DONTWAIT);
                 if (n <= 0) {
                         if (n == 0)
                                 return -EIO;
@@ -1383,7 +1300,7 @@ static int manager_dispatch_sigchld(Manager *m) {
                  * have queued for us. This ensures that the process
                  * still exists in /proc so that we can figure out
                  * which cgroup and hence unit it belongs to. */
-                r = manager_process_notify_fd(m);
+                r = manager_dispatch_notify_fd(m->notify_event_source, m->notify_fd, EPOLLIN, m);
                 if (r < 0)
                         return r;
 
@@ -1425,32 +1342,34 @@ static int manager_dispatch_sigchld(Manager *m) {
 }
 
 static int manager_start_target(Manager *m, const char *name, JobMode mode) {
+        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
         int r;
-        DBusError error;
-
-        dbus_error_init(&error);
 
         log_debug_unit(name, "Activating special unit %s", name);
 
         r = manager_add_job_by_name(m, JOB_START, name, mode, true, &error, NULL);
         if (r < 0)
-                log_error_unit(name,
-                               "Failed to enqueue %s job: %s", name, bus_error(&error, r));
-
-        dbus_error_free(&error);
+                log_error_unit(name, "Failed to enqueue %s job: %s", name, bus_error_message(&error, r));
 
         return r;
 }
 
-static int manager_process_signal_fd(Manager *m) {
+static int manager_dispatch_signal_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
+        Manager *m = userdata;
         ssize_t n;
         struct signalfd_siginfo sfsi;
         bool sigchld = false;
 
         assert(m);
+        assert(m->signal_fd == fd);
+
+        if (revents != EPOLLIN) {
+                log_warning("Got unexpected events from signal file descriptor.");
+                return 0;
+        }
 
         for (;;) {
-                n = read(m->signal_watch.fd, &sfsi, sizeof(sfsi));
+                n = read(m->signal_fd, &sfsi, sizeof(sfsi));
                 if (n != sizeof(sfsi)) {
 
                         if (n >= 0)
@@ -1537,11 +1456,12 @@ static int manager_process_signal_fd(Manager *m) {
                 }
 
                 case SIGUSR2: {
-                        FILE *f;
-                        char *dump = NULL;
+                        _cleanup_free_ char *dump = NULL;
+                        _cleanup_fclose_ FILE *f = NULL;
                         size_t size;
 
-                        if (!(f = open_memstream(&dump, &size))) {
+                        f = open_memstream(&dump, &size);
+                        if (!f) {
                                 log_warning("Failed to allocate memory stream.");
                                 break;
                         }
@@ -1550,16 +1470,11 @@ static int manager_process_signal_fd(Manager *m) {
                         manager_dump_jobs(m, f, "\t");
 
                         if (ferror(f)) {
-                                fclose(f);
-                                free(dump);
                                 log_warning("Failed to write status stream");
                                 break;
                         }
 
-                        fclose(f);
                         log_dump(LOG_INFO, dump);
-                        free(dump);
-
                         break;
                 }
 
@@ -1666,141 +1581,54 @@ static int manager_process_signal_fd(Manager *m) {
         return 0;
 }
 
-static int process_event(Manager *m, struct epoll_event *ev) {
-        int r;
-        Watch *w;
+static int manager_dispatch_time_change_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
+        Manager *m = userdata;
+        Iterator i;
+        Unit *u;
 
         assert(m);
-        assert(ev);
-
-        assert_se(w = ev->data.ptr);
-
-        if (w->type == WATCH_INVALID)
-                return 0;
-
-        switch (w->type) {
-
-        case WATCH_SIGNAL:
-
-                /* An incoming signal? */
-                if (ev->events != EPOLLIN)
-                        return -EINVAL;
-
-                if ((r = manager_process_signal_fd(m)) < 0)
-                        return r;
-
-                break;
-
-        case WATCH_NOTIFY:
-
-                /* An incoming daemon notification event? */
-                if (ev->events != EPOLLIN)
-                        return -EINVAL;
-
-                if ((r = manager_process_notify_fd(m)) < 0)
-                        return r;
-
-                break;
-
-        case WATCH_FD:
-
-                /* Some fd event, to be dispatched to the units */
-                UNIT_VTABLE(w->data.unit)->fd_event(w->data.unit, w->fd, ev->events, w);
-                break;
-
-        case WATCH_UNIT_TIMER:
-        case WATCH_JOB_TIMER: {
-                uint64_t v;
-                ssize_t k;
-
-                /* Some timer event, to be dispatched to the units */
-                k = read(w->fd, &v, sizeof(v));
-                if (k != sizeof(v)) {
+        assert(m->time_change_fd == fd);
 
-                        if (k < 0 && (errno == EINTR || errno == EAGAIN))
-                                break;
-
-                        log_error("Failed to read timer event counter: %s", k < 0 ? strerror(-k) : "Short read");
-                        return k < 0 ? -errno : -EIO;
-                }
+        log_struct(LOG_INFO,
+                   MESSAGE_ID(SD_MESSAGE_TIME_CHANGE),
+                   "MESSAGE=Time has been changed",
+                   NULL);
 
-                if (w->type == WATCH_UNIT_TIMER)
-                        UNIT_VTABLE(w->data.unit)->timer_event(w->data.unit, v, w);
-                else
-                        job_timer_event(w->data.job, v, w);
-                break;
-        }
+        /* Restart the watch */
+        m->time_change_event_source = sd_event_source_unref(m->time_change_event_source);
 
-        case WATCH_MOUNT:
-                /* Some mount table change, intended for the mount subsystem */
-                mount_fd_event(m, ev->events);
-                break;
+        close_nointr_nofail(m->time_change_fd);
+        m->time_change_fd = -1;
 
-        case WATCH_SWAP:
-                /* Some swap table change, intended for the swap subsystem */
-                swap_fd_event(m, ev->events);
-                break;
+        manager_setup_time_change(m);
 
-        case WATCH_UDEV:
-                /* Some notification from udev, intended for the device subsystem */
-                device_fd_event(m, ev->events);
-                break;
-
-        case WATCH_DBUS_WATCH:
-                bus_watch_event(m, w, ev->events);
-                break;
+        HASHMAP_FOREACH(u, m->units, i)
+                if (UNIT_VTABLE(u)->time_change)
+                        UNIT_VTABLE(u)->time_change(u);
 
-        case WATCH_DBUS_TIMEOUT:
-                bus_timeout_event(m, w, ev->events);
-                break;
+        return 0;
+}
 
-        case WATCH_TIME_CHANGE: {
-                Unit *u;
-                Iterator i;
-
-                log_struct(LOG_INFO,
-                           MESSAGE_ID(SD_MESSAGE_TIME_CHANGE),
-                           "MESSAGE=Time has been changed",
-                           NULL);
-
-                /* Restart the watch */
-                epoll_ctl(m->epoll_fd, EPOLL_CTL_DEL, m->time_change_watch.fd,
-                          NULL);
-                close_nointr_nofail(m->time_change_watch.fd);
-                watch_init(&m->time_change_watch);
-                manager_setup_time_change(m);
-
-                HASHMAP_FOREACH(u, m->units, i) {
-                        if (UNIT_VTABLE(u)->time_change)
-                                UNIT_VTABLE(u)->time_change(u);
-                }
+static int manager_dispatch_idle_pipe_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
+        Manager *m = userdata;
 
-                break;
-        }
+        assert(m);
+        assert(m->idle_pipe[2] == fd);
 
-        case WATCH_JOBS_IN_PROGRESS: {
-                uint64_t v;
+        m->no_console_output = m->n_on_console > 0;
 
-                /* not interested in the data */
-                read(w->fd, &v, sizeof(v));
+        m->idle_pipe_event_source = sd_event_source_unref(m->idle_pipe_event_source);
+        manager_close_idle_pipe(m);
 
-                manager_print_jobs_in_progress(m);
-                break;
-        }
-
-        case WATCH_IDLE_PIPE: {
-                m->no_console_output = m->n_on_console > 0;
+        return 0;
+}
 
-                manager_unwatch_idle_pipe(m);
-                close_idle_pipe(m);
-                break;
-        }
+static int manager_dispatch_jobs_in_progress(sd_event_source *source, usec_t usec, void *userdata) {
+        Manager *m = userdata;
 
-        default:
-                log_error("event type=%i", w->type);
-                assert_not_reached("Unknown epoll event type.");
-        }
+        assert(m);
 
+        manager_print_jobs_in_progress(m);
         return 0;
 }
 
@@ -1825,9 +1653,7 @@ int manager_loop(Manager *m) {
                 return r;
 
         while (m->exit_code == MANAGER_RUNNING) {
-                struct epoll_event event;
-                int n;
-                int wait_msec = -1;
+                usec_t wait_usec;
 
                 if (m->runtime_watchdog > 0 && m->running_as == SYSTEMD_SYSTEM)
                         watchdog_ping();
@@ -1854,44 +1680,28 @@ int manager_loop(Manager *m) {
                 if (manager_dispatch_run_queue(m) > 0)
                         continue;
 
-                if (bus_dispatch(m) > 0)
-                        continue;
-
                 if (manager_dispatch_dbus_queue(m) > 0)
                         continue;
 
-                if (swap_dispatch_reload(m) > 0)
-                        continue;
-
                 /* Sleep for half the watchdog time */
                 if (m->runtime_watchdog > 0 && m->running_as == SYSTEMD_SYSTEM) {
-                        wait_msec = (int) (m->runtime_watchdog / 2 / USEC_PER_MSEC);
-                        if (wait_msec <= 0)
-                                wait_msec = 1;
+                        wait_usec = m->runtime_watchdog / 2;
+                        if (wait_usec <= 0)
+                                wait_usec = 1;
                 } else
-                        wait_msec = -1;
-
-                n = epoll_wait(m->epoll_fd, &event, 1, wait_msec);
-                if (n < 0) {
+                        wait_usec = (usec_t) -1;
 
-                        if (errno == EINTR)
-                                continue;
-
-                        return -errno;
-                } else if (n == 0)
-                        continue;
-
-                assert(n == 1);
-
-                r = process_event(m, &event);
-                if (r < 0)
+                r = sd_event_run(m->event, wait_usec);
+                if (r < 0) {
+                        log_error("Failed to run event loop: %s", strerror(-r));
                         return r;
+                }
         }
 
         return m->exit_code;
 }
 
-int manager_load_unit_from_dbus_path(Manager *m, const char *s, DBusError *e, Unit **_u) {
+int manager_load_unit_from_dbus_path(Manager *m, const char *s, sd_bus_error *e, Unit **_u) {
         _cleanup_free_ char *n = NULL;
         Unit *u;
         int r;
@@ -1914,18 +1724,20 @@ int manager_load_unit_from_dbus_path(Manager *m, const char *s, DBusError *e, Un
 }
 
 int manager_get_job_from_dbus_path(Manager *m, const char *s, Job **_j) {
-        Job *j;
+        const char *p;
         unsigned id;
+        Job *j;
         int r;
 
         assert(m);
         assert(s);
         assert(_j);
 
-        if (!startswith(s, "/org/freedesktop/systemd1/job/"))
+        p = startswith(s, "/org/freedesktop/systemd1/job/");
+        if (!p)
                 return -EINVAL;
 
-        r = safe_atou(s + 30, &id);
+        r = safe_atou(p, &id);
         if (r < 0)
                 return r;
 
@@ -2060,29 +1872,13 @@ void manager_dispatch_bus_name_owner_changed(
         assert(m);
         assert(name);
 
-        if (!(u = hashmap_get(m->watch_bus, name)))
+        u = hashmap_get(m->watch_bus, name);
+        if (!u)
                 return;
 
         UNIT_VTABLE(u)->bus_name_owner_change(u, name, old_owner, new_owner);
 }
 
-void manager_dispatch_bus_query_pid_done(
-                Manager *m,
-                const char *name,
-                pid_t pid) {
-
-        Unit *u;
-
-        assert(m);
-        assert(name);
-        assert(pid >= 1);
-
-        if (!(u = hashmap_get(m->watch_bus, name)))
-                return;
-
-        UNIT_VTABLE(u)->bus_query_pid_done(u, name, pid);
-}
-
 int manager_open_serialization(Manager *m, FILE **_f) {
         char *path = NULL;
         int fd = -1;
@@ -2140,13 +1936,19 @@ int manager_serialize(Manager *m, FILE *f, FDSet *fds, bool switching_root) {
         fprintf(f, "n-failed-jobs=%u\n", m->n_failed_jobs);
 
         dual_timestamp_serialize(f, "firmware-timestamp", &m->firmware_timestamp);
-        dual_timestamp_serialize(f, "kernel-timestamp", &m->kernel_timestamp);
         dual_timestamp_serialize(f, "loader-timestamp", &m->loader_timestamp);
+        dual_timestamp_serialize(f, "kernel-timestamp", &m->kernel_timestamp);
         dual_timestamp_serialize(f, "initrd-timestamp", &m->initrd_timestamp);
 
         if (!in_initrd()) {
                 dual_timestamp_serialize(f, "userspace-timestamp", &m->userspace_timestamp);
                 dual_timestamp_serialize(f, "finish-timestamp", &m->finish_timestamp);
+                dual_timestamp_serialize(f, "security-start-timestamp", &m->security_start_timestamp);
+                dual_timestamp_serialize(f, "security-finish-timestamp", &m->security_finish_timestamp);
+                dual_timestamp_serialize(f, "generators-start-timestamp", &m->generators_start_timestamp);
+                dual_timestamp_serialize(f, "generators-finish-timestamp", &m->generators_finish_timestamp);
+                dual_timestamp_serialize(f, "units-load-start-timestamp", &m->units_load_start_timestamp);
+                dual_timestamp_serialize(f, "units-load-finish-timestamp", &m->units_load_finish_timestamp);
         }
 
         if (!switching_root) {
@@ -2229,6 +2031,7 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) {
                                 log_debug("Failed to parse current job id value %s", l+15);
                         else
                                 m->current_job_id = MAX(m->current_job_id, id);
+
                 } else if (startswith(l, "n-installed-jobs=")) {
                         uint32_t n;
 
@@ -2236,6 +2039,7 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) {
                                 log_debug("Failed to parse installed jobs counter %s", l+17);
                         else
                                 m->n_installed_jobs += n;
+
                 } else if (startswith(l, "n-failed-jobs=")) {
                         uint32_t n;
 
@@ -2243,6 +2047,7 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) {
                                 log_debug("Failed to parse failed jobs counter %s", l+14);
                         else
                                 m->n_failed_jobs += n;
+
                 } else if (startswith(l, "taint-usr=")) {
                         int b;
 
@@ -2250,6 +2055,7 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) {
                                 log_debug("Failed to parse taint /usr flag %s", l+10);
                         else
                                 m->taint_usr = m->taint_usr || b;
+
                 } else if (startswith(l, "firmware-timestamp="))
                         dual_timestamp_deserialize(l+19, &m->firmware_timestamp);
                 else if (startswith(l, "loader-timestamp="))
@@ -2262,6 +2068,18 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) {
                         dual_timestamp_deserialize(l+20, &m->userspace_timestamp);
                 else if (startswith(l, "finish-timestamp="))
                         dual_timestamp_deserialize(l+17, &m->finish_timestamp);
+                else if (startswith(l, "security-start-timestamp="))
+                        dual_timestamp_deserialize(l+25, &m->security_start_timestamp);
+                else if (startswith(l, "security-finish-timestamp="))
+                        dual_timestamp_deserialize(l+26, &m->security_finish_timestamp);
+                else if (startswith(l, "generators-start-timestamp="))
+                        dual_timestamp_deserialize(l+27, &m->generators_start_timestamp);
+                else if (startswith(l, "generators-finish-timestamp="))
+                        dual_timestamp_deserialize(l+28, &m->generators_finish_timestamp);
+                else if (startswith(l, "units-load-start-timestamp="))
+                        dual_timestamp_deserialize(l+27, &m->units_load_start_timestamp);
+                else if (startswith(l, "units-load-finish-timestamp="))
+                        dual_timestamp_deserialize(l+28, &m->units_load_finish_timestamp);
                 else if (startswith(l, "env=")) {
                         _cleanup_free_ char *uce = NULL;
                         char **e;
@@ -2333,7 +2151,7 @@ int manager_reload(Manager *m) {
                 return r;
 
         m->n_reloading ++;
-        bus_broadcast_reloading(m, true);
+        bus_manager_send_reloading(m, true);
 
         fds = fdset_new();
         if (!fds) {
@@ -2450,16 +2268,16 @@ void manager_check_finished(Manager *m) {
         assert(m);
 
         if (m->n_running_jobs == 0)
-                manager_unwatch_jobs_in_progress(m);
+                m->jobs_in_progress_event_source = sd_event_source_unref(m->jobs_in_progress_event_source);
 
-        if (hashmap_size(m->jobs) > 0) {
-                manager_jobs_in_progress_mod_timer(m);
+        if (hashmap_size(m->jobs) > 0 && m->jobs_in_progress_event_source) {
+                sd_event_source_set_time(m->jobs_in_progress_event_source, JOBS_IN_PROGRESS_PERIOD_SEC);
                 return;
         }
 
         /* Notify Type=idle units that we are done now */
-        manager_unwatch_idle_pipe(m);
-        close_idle_pipe(m);
+        m->idle_pipe_event_source = sd_event_source_unref(m->idle_pipe_event_source);
+        manager_close_idle_pipe(m);
 
         /* Turn off confirm spawn now */
         m->confirm_spawn = false;
@@ -2526,7 +2344,7 @@ void manager_check_finished(Manager *m) {
                                    NULL);
         }
 
-        bus_broadcast_finished(m, firmware_usec, loader_usec, kernel_usec, initrd_usec, userspace_usec, total_usec);
+        bus_manager_send_finished(m, firmware_usec, loader_usec, kernel_usec, initrd_usec, userspace_usec, total_usec);
 
         sd_notifyf(false,
                    "READY=1\nSTATUS=Startup finished in %s.",
@@ -2590,7 +2408,7 @@ static void trim_generator_dir(Manager *m, char **generator) {
 }
 
 void manager_run_generators(Manager *m) {
-        DIR *d = NULL;
+        _cleanup_closedir_ DIR *d = NULL;
         const char *generator_path;
         const char *argv[5];
         int r;
@@ -2626,17 +2444,13 @@ void manager_run_generators(Manager *m) {
         argv[3] = m->generator_unit_path_late;
         argv[4] = NULL;
 
-        RUN_WITH_UMASK(0022) {
+        RUN_WITH_UMASK(0022)
                 execute_directory(generator_path, d, (char**) argv);
-        }
 
+finish:
         trim_generator_dir(m, &m->generator_unit_path);
         trim_generator_dir(m, &m->generator_unit_path_early);
         trim_generator_dir(m, &m->generator_unit_path_late);
-
-finish:
-        if (d)
-                closedir(d);
 }
 
 static void remove_generator_dir(Manager *m, char **generator) {
@@ -2661,17 +2475,36 @@ void manager_undo_generators(Manager *m) {
         remove_generator_dir(m, &m->generator_unit_path_late);
 }
 
-int manager_environment_add(Manager *m, char **environment) {
-        char **e = NULL;
+int manager_environment_add(Manager *m, char **minus, char **plus) {
+        char **a = NULL, **b = NULL, **l;
         assert(m);
 
-        e = strv_env_merge(2, m->environment, environment);
-        if (!e)
-                return -ENOMEM;
+        l = m->environment;
 
-        strv_free(m->environment);
-        m->environment = e;
+        if (!strv_isempty(minus)) {
+                a = strv_env_delete(l, 1, minus);
+                if (!a)
+                        return -ENOMEM;
+
+                l = a;
+        }
+
+        if (!strv_isempty(plus)) {
+                b = strv_env_merge(2, l, plus);
+                if (!b)
+                        return -ENOMEM;
 
+                l = b;
+        }
+
+        if (m->environment != l)
+                strv_free(m->environment);
+        if (a != l)
+                strv_free(a);
+        if (b != l)
+                strv_free(b);
+
+        m->environment = l;
         return 0;
 }
 
@@ -2802,10 +2635,3 @@ Set *manager_get_units_requiring_mounts_for(Manager *m, const char *path) {
 
         return hashmap_get(m->units_requiring_mounts_for, streq(p, "/") ? "" : p);
 }
-
-void watch_init(Watch *w) {
-        assert(w);
-
-        w->type = WATCH_INVALID;
-        w->fd = -1;
-}
diff --git a/src/core/manager.h b/src/core/manager.h
index b043970..9eddef2 100644
--- a/src/core/manager.h
+++ b/src/core/manager.h
@@ -24,8 +24,9 @@
 #include <stdbool.h>
 #include <inttypes.h>
 #include <stdio.h>
-#include <dbus/dbus.h>
 
+#include "sd-bus.h"
+#include "sd-event.h"
 #include "fdset.h"
 #include "cgroup-util.h"
 
@@ -33,8 +34,6 @@
 #define MANAGER_MAX_NAMES 131072 /* 128K */
 
 typedef struct Manager Manager;
-typedef enum WatchType WatchType;
-typedef struct Watch Watch;
 
 typedef enum ManagerExitCode {
         MANAGER_RUNNING,
@@ -50,42 +49,11 @@ typedef enum ManagerExitCode {
         _MANAGER_EXIT_CODE_INVALID = -1
 } ManagerExitCode;
 
-enum WatchType {
-        WATCH_INVALID,
-        WATCH_SIGNAL,
-        WATCH_NOTIFY,
-        WATCH_FD,
-        WATCH_UNIT_TIMER,
-        WATCH_JOB_TIMER,
-        WATCH_MOUNT,
-        WATCH_SWAP,
-        WATCH_UDEV,
-        WATCH_DBUS_WATCH,
-        WATCH_DBUS_TIMEOUT,
-        WATCH_TIME_CHANGE,
-        WATCH_JOBS_IN_PROGRESS,
-        WATCH_IDLE_PIPE,
-};
-
-struct Watch {
-        int fd;
-        WatchType type;
-        union {
-                struct Unit *unit;
-                struct Job *job;
-                DBusWatch *bus_watch;
-                DBusTimeout *bus_timeout;
-        } data;
-        bool fd_is_dupped:1;
-        bool socket_accept:1;
-};
-
 #include "unit.h"
 #include "job.h"
 #include "hashmap.h"
 #include "list.h"
 #include "set.h"
-#include "dbus.h"
 #include "path-lookup.h"
 #include "execute.h"
 #include "unit-name.h"
@@ -125,17 +93,21 @@ struct Manager {
         /* Units that should be realized */
         LIST_HEAD(Unit, cgroup_queue);
 
+        sd_event *event;
+
         Hashmap *watch_pids;  /* pid => Unit object n:1 */
 
         char *notify_socket;
+        int notify_fd;
+        sd_event_source *notify_event_source;
+
+        int signal_fd;
+        sd_event_source *signal_event_source;
 
-        Watch notify_watch;
-        Watch signal_watch;
-        Watch time_change_watch;
-        Watch jobs_in_progress_watch;
-        Watch idle_pipe_watch;
+        int time_change_fd;
+        sd_event_source *time_change_event_source;
 
-        int epoll_fd;
+        sd_event_source *jobs_in_progress_event_source;
 
         unsigned n_snapshots;
 
@@ -157,8 +129,8 @@ struct Manager {
         dual_timestamp security_finish_timestamp;
         dual_timestamp generators_start_timestamp;
         dual_timestamp generators_finish_timestamp;
-        dual_timestamp unitsload_start_timestamp;
-        dual_timestamp unitsload_finish_timestamp;
+        dual_timestamp units_load_start_timestamp;
+        dual_timestamp units_load_finish_timestamp;
 
         char *generator_unit_path;
         char *generator_unit_path_early;
@@ -167,34 +139,33 @@ struct Manager {
         /* Data specific to the device subsystem */
         struct udev* udev;
         struct udev_monitor* udev_monitor;
-        Watch udev_watch;
+        sd_event_source *udev_event_source;
         Hashmap *devices_by_sysfs;
 
         /* Data specific to the mount subsystem */
         FILE *proc_self_mountinfo;
-        Watch mount_watch;
+        sd_event_source *mount_event_source;
 
         /* Data specific to the swap filesystem */
         FILE *proc_swaps;
+        sd_event_source *swap_event_source;
         Hashmap *swaps_by_proc_swaps;
         bool request_reload;
-        Watch swap_watch;
 
         /* Data specific to the D-Bus subsystem */
-        DBusConnection *api_bus, *system_bus;
-        DBusServer *private_bus;
-        Set *bus_connections, *bus_connections_for_dispatch;
+        sd_bus *api_bus, *system_bus;
+        Set *private_buses;
+        int private_listen_fd;
+        sd_event_source *private_listen_event_source;
+        Set *subscribed;
 
-        DBusMessage *queued_message; /* This is used during reloading:
+        sd_bus_message *queued_message; /* This is used during reloading:
                                       * before the reload we queue the
                                       * reply message here, and
                                       * afterwards we send it */
-        DBusConnection *queued_message_connection; /* The connection to send the queued message on */
+        sd_bus *queued_message_bus; /* The connection to send the queued message on */
 
         Hashmap *watch_bus;  /* D-Bus names => Unit object n:1 */
-        int32_t name_data_slot;
-        int32_t conn_data_slot;
-        int32_t subscribed_data_slot;
 
         bool send_reloading_done;
 
@@ -253,6 +224,7 @@ struct Manager {
 
         /* Type=idle pipes */
         int idle_pipe[4];
+        sd_event_source *idle_pipe_event_source;
 
         char *switch_root;
         char *switch_root_init;
@@ -276,12 +248,12 @@ int manager_get_unit_by_path(Manager *m, const char *path, const char *suffix, U
 
 int manager_get_job_from_dbus_path(Manager *m, const char *s, Job **_j);
 
-int manager_load_unit_prepare(Manager *m, const char *name, const char *path, DBusError *e, Unit **_ret);
-int manager_load_unit(Manager *m, const char *name, const char *path, DBusError *e, Unit **_ret);
-int manager_load_unit_from_dbus_path(Manager *m, const char *s, DBusError *e, Unit **_u);
+int manager_load_unit_prepare(Manager *m, const char *name, const char *path, sd_bus_error *e, Unit **_ret);
+int manager_load_unit(Manager *m, const char *name, const char *path, sd_bus_error *e, Unit **_ret);
+int manager_load_unit_from_dbus_path(Manager *m, const char *s, sd_bus_error *e, Unit **_u);
 
-int manager_add_job(Manager *m, JobType type, Unit *unit, JobMode mode, bool force, DBusError *e, Job **_ret);
-int manager_add_job_by_name(Manager *m, JobType type, const char *name, JobMode mode, bool force, DBusError *e, Job **_ret);
+int manager_add_job(Manager *m, JobType type, Unit *unit, JobMode mode, bool force, sd_bus_error *e, Job **_ret);
+int manager_add_job_by_name(Manager *m, JobType type, const char *name, JobMode mode, bool force, sd_bus_error *e, Job **_ret);
 
 void manager_dump_units(Manager *s, FILE *f, const char *prefix);
 void manager_dump_jobs(Manager *s, FILE *f, const char *prefix);
@@ -290,13 +262,12 @@ void manager_clear_jobs(Manager *m);
 
 unsigned manager_dispatch_load_queue(Manager *m);
 
-int manager_environment_add(Manager *m, char **environment);
+int manager_environment_add(Manager *m, char **minus, char **plus);
 int manager_set_default_rlimits(Manager *m, struct rlimit **default_rlimit);
 
 int manager_loop(Manager *m);
 
 void manager_dispatch_bus_name_owner_changed(Manager *m, const char *name, const char* old_owner, const char *new_owner);
-void manager_dispatch_bus_query_pid_done(Manager *m, const char *name, pid_t pid);
 
 int manager_open_serialization(Manager *m, FILE **_f);
 
@@ -325,5 +296,3 @@ void manager_set_show_status(Manager *m, bool b);
 void manager_status_printf(Manager *m, bool ephemeral, const char *status, const char *format, ...) _printf_(4,5);
 
 Set *manager_get_units_requiring_mounts_for(Manager *m, const char *path);
-
-void watch_init(Watch *w);
diff --git a/src/core/mount.c b/src/core/mount.c
index 0c15b99..99e7ced 100644
--- a/src/core/mount.c
+++ b/src/core/mount.c
@@ -59,6 +59,9 @@ static const UnitActiveState state_translation_table[_MOUNT_STATE_MAX] = {
         [MOUNT_FAILED] = UNIT_FAILED
 };
 
+static int mount_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata);
+static int mount_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata);
+
 static char* mount_test_option(const char *haystack, const char *needle) {
         struct mntent me = { .mnt_opts = (char*) haystack };
 
@@ -156,13 +159,32 @@ static void mount_init(Unit *u) {
          * already trying to comply its last one. */
         m->exec_context.same_pgrp = true;
 
-        m->timer_watch.type = WATCH_INVALID;
-
         m->control_command_id = _MOUNT_EXEC_COMMAND_INVALID;
 
         UNIT(m)->ignore_on_isolate = true;
 }
 
+static int mount_arm_timer(Mount *m) {
+        int r;
+
+        assert(m);
+
+        if (m->timeout_usec <= 0) {
+                m->timer_event_source = sd_event_source_unref(m->timer_event_source);
+                return 0;
+        }
+
+        if (m->timer_event_source) {
+                r = sd_event_source_set_time(m->timer_event_source, now(CLOCK_MONOTONIC) + m->timeout_usec);
+                if (r < 0)
+                        return r;
+
+                return sd_event_source_set_enabled(m->timer_event_source, SD_EVENT_ONESHOT);
+        }
+
+        return sd_event_add_monotonic(UNIT(m)->manager->event, now(CLOCK_MONOTONIC) + m->timeout_usec, 0, mount_dispatch_timer, m, &m->timer_event_source);
+}
+
 static void mount_unwatch_control_pid(Mount *m) {
         assert(m);
 
@@ -201,7 +223,7 @@ static void mount_done(Unit *u) {
 
         mount_unwatch_control_pid(m);
 
-        unit_unwatch_timer(u, &m->timer_watch);
+        m->timer_event_source = sd_event_source_unref(m->timer_event_source);
 }
 
 _pure_ static MountParameters* get_mount_parameters_fragment(Mount *m) {
@@ -626,7 +648,7 @@ static void mount_set_state(Mount *m, MountState state) {
             state != MOUNT_UNMOUNTING_SIGKILL &&
             state != MOUNT_REMOUNTING_SIGTERM &&
             state != MOUNT_REMOUNTING_SIGKILL) {
-                unit_unwatch_timer(UNIT(m), &m->timer_watch);
+                m->timer_event_source = sd_event_source_unref(m->timer_event_source);
                 mount_unwatch_control_pid(m);
                 m->control_command = NULL;
                 m->control_command_id = _MOUNT_EXEC_COMMAND_INVALID;
@@ -692,7 +714,7 @@ static int mount_coldplug(Unit *u) {
                         if (r < 0)
                                 return r;
 
-                        r = unit_watch_timer(UNIT(m), CLOCK_MONOTONIC, true, m->timeout_usec, &m->timer_watch);
+                        r = mount_arm_timer(m);
                         if (r < 0)
                                 return r;
                 }
@@ -751,7 +773,7 @@ static int mount_spawn(Mount *m, ExecCommand *c, pid_t *_pid) {
 
         unit_realize_cgroup(UNIT(m));
 
-        r = unit_watch_timer(UNIT(m), CLOCK_MONOTONIC, true, m->timeout_usec, &m->timer_watch);
+        r = mount_arm_timer(m);
         if (r < 0)
                 goto fail;
 
@@ -782,7 +804,7 @@ static int mount_spawn(Mount *m, ExecCommand *c, pid_t *_pid) {
         return 0;
 
 fail:
-        unit_unwatch_timer(UNIT(m), &m->timer_watch);
+        m->timer_event_source = sd_event_source_unref(m->timer_event_source);
 
         return r;
 }
@@ -825,7 +847,7 @@ static void mount_enter_signal(Mount *m, MountState state, MountResult f) {
                 goto fail;
 
         if (r > 0) {
-                r = unit_watch_timer(UNIT(m), CLOCK_MONOTONIC, true, m->timeout_usec, &m->timer_watch);
+                r = mount_arm_timer(m);
                 if (r < 0)
                         goto fail;
 
@@ -959,17 +981,11 @@ static void mount_enter_remounting(Mount *m) {
         m->control_command = m->exec_command + MOUNT_EXEC_REMOUNT;
 
         if (m->from_fragment) {
-                char *buf = NULL;
                 const char *o;
 
-                if (m->parameters_fragment.options) {
-                        if (!(buf = strappend("remount,", m->parameters_fragment.options))) {
-                                r = -ENOMEM;
-                                goto fail;
-                        }
-
-                        o = buf;
-                } else
+                if (m->parameters_fragment.options)
+                        o = strappenda("remount,", m->parameters_fragment.options);
+                else
                         o = "remount";
 
                 r = exec_command_set(
@@ -980,8 +996,6 @@ static void mount_enter_remounting(Mount *m) {
                                 "-t", m->parameters_fragment.fstype ? m->parameters_fragment.fstype : "auto",
                                 "-o", o,
                                 NULL);
-
-                free(buf);
         } else
                 r = -ENOENT;
 
@@ -990,7 +1004,8 @@ static void mount_enter_remounting(Mount *m) {
 
         mount_unwatch_control_pid(m);
 
-        if ((r = mount_spawn(m, m->control_command, &m->control_pid)) < 0)
+        r = mount_spawn(m, m->control_command, &m->control_pid);
+        if (r < 0)
                 goto fail;
 
         mount_set_state(m, MOUNT_REMOUNTING);
@@ -1279,44 +1294,43 @@ static void mount_sigchld_event(Unit *u, pid_t pid, int code, int status) {
         unit_add_to_dbus_queue(u);
 }
 
-static void mount_timer_event(Unit *u, uint64_t elapsed, Watch *w) {
-        Mount *m = MOUNT(u);
+static int mount_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata) {
+        Mount *m = MOUNT(userdata);
 
         assert(m);
-        assert(elapsed == 1);
-        assert(w == &m->timer_watch);
+        assert(m->timer_event_source == source);
 
         switch (m->state) {
 
         case MOUNT_MOUNTING:
         case MOUNT_MOUNTING_DONE:
-                log_warning_unit(u->id,
-                                 "%s mounting timed out. Stopping.", u->id);
+                log_warning_unit(UNIT(m)->id,
+                                 "%s mounting timed out. Stopping.", UNIT(m)->id);
                 mount_enter_signal(m, MOUNT_MOUNTING_SIGTERM, MOUNT_FAILURE_TIMEOUT);
                 break;
 
         case MOUNT_REMOUNTING:
-                log_warning_unit(u->id,
-                                 "%s remounting timed out. Stopping.", u->id);
+                log_warning_unit(UNIT(m)->id,
+                                 "%s remounting timed out. Stopping.", UNIT(m)->id);
                 m->reload_result = MOUNT_FAILURE_TIMEOUT;
                 mount_enter_mounted(m, MOUNT_SUCCESS);
                 break;
 
         case MOUNT_UNMOUNTING:
-                log_warning_unit(u->id,
-                                 "%s unmounting timed out. Stopping.", u->id);
+                log_warning_unit(UNIT(m)->id,
+                                 "%s unmounting timed out. Stopping.", UNIT(m)->id);
                 mount_enter_signal(m, MOUNT_UNMOUNTING_SIGTERM, MOUNT_FAILURE_TIMEOUT);
                 break;
 
         case MOUNT_MOUNTING_SIGTERM:
                 if (m->kill_context.send_sigkill) {
-                        log_warning_unit(u->id,
-                                         "%s mounting timed out. Killing.", u->id);
+                        log_warning_unit(UNIT(m)->id,
+                                         "%s mounting timed out. Killing.", UNIT(m)->id);
                         mount_enter_signal(m, MOUNT_MOUNTING_SIGKILL, MOUNT_FAILURE_TIMEOUT);
                 } else {
-                        log_warning_unit(u->id,
+                        log_warning_unit(UNIT(m)->id,
                                          "%s mounting timed out. Skipping SIGKILL. Ignoring.",
-                                         u->id);
+                                         UNIT(m)->id);
 
                         if (m->from_proc_self_mountinfo)
                                 mount_enter_mounted(m, MOUNT_FAILURE_TIMEOUT);
@@ -1327,13 +1341,13 @@ static void mount_timer_event(Unit *u, uint64_t elapsed, Watch *w) {
 
         case MOUNT_REMOUNTING_SIGTERM:
                 if (m->kill_context.send_sigkill) {
-                        log_warning_unit(u->id,
-                                         "%s remounting timed out. Killing.", u->id);
+                        log_warning_unit(UNIT(m)->id,
+                                         "%s remounting timed out. Killing.", UNIT(m)->id);
                         mount_enter_signal(m, MOUNT_REMOUNTING_SIGKILL, MOUNT_FAILURE_TIMEOUT);
                 } else {
-                        log_warning_unit(u->id,
+                        log_warning_unit(UNIT(m)->id,
                                          "%s remounting timed out. Skipping SIGKILL. Ignoring.",
-                                         u->id);
+                                         UNIT(m)->id);
 
                         if (m->from_proc_self_mountinfo)
                                 mount_enter_mounted(m, MOUNT_FAILURE_TIMEOUT);
@@ -1344,13 +1358,13 @@ static void mount_timer_event(Unit *u, uint64_t elapsed, Watch *w) {
 
         case MOUNT_UNMOUNTING_SIGTERM:
                 if (m->kill_context.send_sigkill) {
-                        log_warning_unit(u->id,
-                                         "%s unmounting timed out. Killing.", u->id);
+                        log_warning_unit(UNIT(m)->id,
+                                         "%s unmounting timed out. Killing.", UNIT(m)->id);
                         mount_enter_signal(m, MOUNT_UNMOUNTING_SIGKILL, MOUNT_FAILURE_TIMEOUT);
                 } else {
-                        log_warning_unit(u->id,
+                        log_warning_unit(UNIT(m)->id,
                                          "%s unmounting timed out. Skipping SIGKILL. Ignoring.",
-                                         u->id);
+                                         UNIT(m)->id);
 
                         if (m->from_proc_self_mountinfo)
                                 mount_enter_mounted(m, MOUNT_FAILURE_TIMEOUT);
@@ -1362,9 +1376,9 @@ static void mount_timer_event(Unit *u, uint64_t elapsed, Watch *w) {
         case MOUNT_MOUNTING_SIGKILL:
         case MOUNT_REMOUNTING_SIGKILL:
         case MOUNT_UNMOUNTING_SIGKILL:
-                log_warning_unit(u->id,
+                log_warning_unit(UNIT(m)->id,
                                  "%s mount process still around after SIGKILL. Ignoring.",
-                                 u->id);
+                                 UNIT(m)->id);
 
                 if (m->from_proc_self_mountinfo)
                         mount_enter_mounted(m, MOUNT_FAILURE_TIMEOUT);
@@ -1375,6 +1389,8 @@ static void mount_timer_event(Unit *u, uint64_t elapsed, Watch *w) {
         default:
                 assert_not_reached("Timeout at wrong time.");
         }
+
+        return 0;
 }
 
 static int mount_add_one(
@@ -1582,6 +1598,8 @@ static int mount_load_proc_self_mountinfo(Manager *m, bool set_flags) {
 static void mount_shutdown(Manager *m) {
         assert(m);
 
+        m->mount_event_source = sd_event_source_unref(m->mount_event_source);
+
         if (m->proc_self_mountinfo) {
                 fclose(m->proc_self_mountinfo);
                 m->proc_self_mountinfo = NULL;
@@ -1593,20 +1611,13 @@ static int mount_enumerate(Manager *m) {
         assert(m);
 
         if (!m->proc_self_mountinfo) {
-                struct epoll_event ev = {
-                        .events = EPOLLPRI,
-                        .data.ptr = &m->mount_watch,
-                };
-
                 m->proc_self_mountinfo = fopen("/proc/self/mountinfo", "re");
                 if (!m->proc_self_mountinfo)
                         return -errno;
 
-                m->mount_watch.type = WATCH_MOUNT;
-                m->mount_watch.fd = fileno(m->proc_self_mountinfo);
-
-                if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->mount_watch.fd, &ev) < 0)
-                        return -errno;
+                r = sd_event_add_io(m->event, fileno(m->proc_self_mountinfo), EPOLLPRI, mount_dispatch_io, m, &m->mount_event_source);
+                if (r < 0)
+                        goto fail;
         }
 
         r = mount_load_proc_self_mountinfo(m, false);
@@ -1620,12 +1631,13 @@ fail:
         return r;
 }
 
-void mount_fd_event(Manager *m, int events) {
+static int mount_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
+        Manager *m = userdata;
         Unit *u;
         int r;
 
         assert(m);
-        assert(events & EPOLLPRI);
+        assert(revents & EPOLLPRI);
 
         /* The manager calls this for every fd event happening on the
          * /proc/self/mountinfo file, which informs us about mounting
@@ -1642,7 +1654,7 @@ void mount_fd_event(Manager *m, int events) {
                         mount->is_mounted = mount->just_mounted = mount->just_changed = false;
                 }
 
-                return;
+                return 0;
         }
 
         manager_dispatch_load_queue(m);
@@ -1696,6 +1708,8 @@ void mount_fd_event(Manager *m, int events) {
                 /* Reset the flags for later calls */
                 mount->is_mounted = mount->just_mounted = mount->just_changed = false;
         }
+
+        return 0;
 }
 
 static void mount_reset_failed(Unit *u) {
@@ -1710,7 +1724,7 @@ static void mount_reset_failed(Unit *u) {
         m->reload_result = MOUNT_SUCCESS;
 }
 
-static int mount_kill(Unit *u, KillWho who, int signo, DBusError *error) {
+static int mount_kill(Unit *u, KillWho who, int signo, sd_bus_error *error) {
         return unit_kill_common(u, who, signo, -1, MOUNT(u)->control_pid, error);
 }
 
@@ -1753,15 +1767,15 @@ DEFINE_STRING_TABLE_LOOKUP(mount_result, MountResult);
 
 const UnitVTable mount_vtable = {
         .object_size = sizeof(Mount),
+        .exec_context_offset = offsetof(Mount, exec_context),
+        .cgroup_context_offset = offsetof(Mount, cgroup_context),
+        .kill_context_offset = offsetof(Mount, kill_context),
 
         .sections =
                 "Unit\0"
                 "Mount\0"
                 "Install\0",
-
         .private_section = "Mount",
-        .exec_context_offset = offsetof(Mount, exec_context),
-        .cgroup_context_offset = offsetof(Mount, cgroup_context),
 
         .no_alias = true,
         .no_instances = true,
@@ -1789,13 +1803,12 @@ const UnitVTable mount_vtable = {
         .check_gc = mount_check_gc,
 
         .sigchld_event = mount_sigchld_event,
-        .timer_event = mount_timer_event,
 
         .reset_failed = mount_reset_failed,
 
         .bus_interface = "org.freedesktop.systemd1.Mount",
-        .bus_message_handler = bus_mount_message_handler,
-        .bus_invalidating_properties =  bus_mount_invalidating_properties,
+        .bus_vtable = bus_mount_vtable,
+        .bus_changing_properties = bus_mount_changing_properties,
         .bus_set_property = bus_mount_set_property,
         .bus_commit_properties = bus_mount_commit_properties,
 
diff --git a/src/core/mount.h b/src/core/mount.h
index a955069..2edb75e 100644
--- a/src/core/mount.h
+++ b/src/core/mount.h
@@ -107,7 +107,7 @@ struct Mount {
         MountExecCommand control_command_id;
         pid_t control_pid;
 
-        Watch timer_watch;
+        sd_event_source *timer_event_source;
 };
 
 extern const UnitVTable mount_vtable;
diff --git a/src/core/path.c b/src/core/path.c
index 10df80f..51e8d1d 100644
--- a/src/core/path.c
+++ b/src/core/path.c
@@ -31,9 +31,10 @@
 #include "mkdir.h"
 #include "dbus-path.h"
 #include "special.h"
-#include "dbus-common.h"
 #include "path-util.h"
 #include "macro.h"
+#include "bus-util.h"
+#include "bus-error.h"
 
 static const UnitActiveState state_translation_table[_PATH_STATE_MAX] = {
         [PATH_DEAD] = UNIT_INACTIVE,
@@ -42,7 +43,9 @@ static const UnitActiveState state_translation_table[_PATH_STATE_MAX] = {
         [PATH_FAILED] = UNIT_FAILED
 };
 
-int path_spec_watch(PathSpec *s, Unit *u) {
+static int path_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata);
+
+int path_spec_watch(PathSpec *s, sd_event_io_handler_t handler) {
 
         static const int flags_table[_PATH_TYPE_MAX] = {
                 [PATH_EXISTS] = IN_DELETE_SELF|IN_MOVE_SELF|IN_ATTRIB,
@@ -56,10 +59,11 @@ int path_spec_watch(PathSpec *s, Unit *u) {
         char *slash, *oldslash = NULL;
         int r;
 
-        assert(u);
         assert(s);
+        assert(s->unit);
+        assert(handler);
 
-        path_spec_unwatch(s, u);
+        path_spec_unwatch(s);
 
         s->inotify_fd = inotify_init1(IN_NONBLOCK|IN_CLOEXEC);
         if (s->inotify_fd < 0) {
@@ -67,7 +71,7 @@ int path_spec_watch(PathSpec *s, Unit *u) {
                 goto fail;
         }
 
-        r = unit_watch_fd(u, s->inotify_fd, EPOLLIN, &s->watch);
+        r = sd_event_add_io(s->unit->manager->event, s->inotify_fd, EPOLLIN, handler, s, &s->event_source);
         if (r < 0)
                 goto fail;
 
@@ -140,29 +144,29 @@ int path_spec_watch(PathSpec *s, Unit *u) {
         return 0;
 
 fail:
-        path_spec_unwatch(s, u);
+        path_spec_unwatch(s);
         return r;
 }
 
-void path_spec_unwatch(PathSpec *s, Unit *u) {
-
-        if (s->inotify_fd < 0)
-                return;
+void path_spec_unwatch(PathSpec *s) {
+        assert(s);
 
-        unit_unwatch_fd(u, &s->watch);
+        s->event_source = sd_event_source_unref(s->event_source);
 
-        close_nointr_nofail(s->inotify_fd);
-        s->inotify_fd = -1;
+        if (s->inotify_fd >= 0) {
+                close_nointr_nofail(s->inotify_fd);
+                s->inotify_fd = -1;
+        }
 }
 
-int path_spec_fd_event(PathSpec *s, uint32_t events) {
+int path_spec_fd_event(PathSpec *s, uint32_t revents) {
         _cleanup_free_ uint8_t *buf = NULL;
         struct inotify_event *e;
         ssize_t k;
         int l;
         int r = 0;
 
-        if (events != EPOLLIN) {
+        if (revents != EPOLLIN) {
                 log_error("Got invalid poll event on inotify.");
                 return -EINVAL;
         }
@@ -282,7 +286,7 @@ void path_free_specs(Path *p) {
         assert(p);
 
         while ((s = p->specs)) {
-                path_spec_unwatch(s, UNIT(p));
+                path_spec_unwatch(s);
                 LIST_REMOVE(spec, p->specs, s);
                 path_spec_done(s);
                 free(s);
@@ -419,7 +423,7 @@ static void path_unwatch(Path *p) {
         assert(p);
 
         LIST_FOREACH(spec, s, p->specs)
-                path_spec_unwatch(s, UNIT(p));
+                path_spec_unwatch(s);
 }
 
 static int path_watch(Path *p) {
@@ -429,7 +433,7 @@ static int path_watch(Path *p) {
         assert(p);
 
         LIST_FOREACH(spec, s, p->specs) {
-                r = path_spec_watch(s, UNIT(p));
+                r = path_spec_watch(s, path_dispatch_io);
                 if (r < 0)
                         return r;
         }
@@ -487,13 +491,11 @@ static void path_enter_dead(Path *p, PathResult f) {
 }
 
 static void path_enter_running(Path *p) {
-        _cleanup_dbus_error_free_ DBusError error;
+        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
         int r;
 
         assert(p);
 
-        dbus_error_init(&error);
-
         /* Don't start job if we are supposed to go down */
         if (unit_stop_pending(UNIT(p)))
                 return;
@@ -514,7 +516,7 @@ static void path_enter_running(Path *p) {
 
 fail:
         log_warning("%s failed to queue unit startup job: %s",
-                    UNIT(p)->id, bus_error(&error, r));
+                    UNIT(p)->id, bus_error_message(&error, r));
         path_enter_dead(p, PATH_FAILURE_RESOURCES);
 }
 
@@ -664,17 +666,20 @@ _pure_ static const char *path_sub_state_to_string(Unit *u) {
         return path_state_to_string(PATH(u)->state);
 }
 
-static void path_fd_event(Unit *u, int fd, uint32_t events, Watch *w) {
-        Path *p = PATH(u);
-        PathSpec *s;
+static int path_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
+        PathSpec *s = userdata;
+        Path *p;
         int changed;
 
-        assert(p);
+        assert(s);
+        assert(s->unit);
         assert(fd >= 0);
 
+        p = PATH(s->unit);
+
         if (p->state != PATH_WAITING &&
             p->state != PATH_RUNNING)
-                return;
+                return 0;
 
         /* log_debug("inotify wakeup on %s.", u->id); */
 
@@ -687,7 +692,7 @@ static void path_fd_event(Unit *u, int fd, uint32_t events, Watch *w) {
                 goto fail;
         }
 
-        changed = path_spec_fd_event(s, events);
+        changed = path_spec_fd_event(s, revents);
         if (changed < 0)
                 goto fail;
 
@@ -701,10 +706,11 @@ static void path_fd_event(Unit *u, int fd, uint32_t events, Watch *w) {
         else
                 path_enter_waiting(p, false, true);
 
-        return;
+        return 0;
 
 fail:
         path_enter_dead(p, PATH_FAILURE_RESOURCES);
+        return 0;
 }
 
 static void path_trigger_notify(Unit *u, Unit *other) {
@@ -771,6 +777,7 @@ DEFINE_STRING_TABLE_LOOKUP(path_result, PathResult);
 
 const UnitVTable path_vtable = {
         .object_size = sizeof(Path),
+
         .sections =
                 "Unit\0"
                 "Path\0"
@@ -793,13 +800,11 @@ const UnitVTable path_vtable = {
         .active_state = path_active_state,
         .sub_state_to_string = path_sub_state_to_string,
 
-        .fd_event = path_fd_event,
-
         .trigger_notify = path_trigger_notify,
 
         .reset_failed = path_reset_failed,
 
         .bus_interface = "org.freedesktop.systemd1.Path",
-        .bus_message_handler = bus_path_message_handler,
-        .bus_invalidating_properties = bus_path_invalidating_properties
+        .bus_vtable = bus_path_vtable,
+        .bus_changing_properties = bus_path_changing_properties
 };
diff --git a/src/core/path.h b/src/core/path.h
index dec3df7..d2e91d7 100644
--- a/src/core/path.h
+++ b/src/core/path.h
@@ -46,9 +46,11 @@ typedef enum PathType {
 } PathType;
 
 typedef struct PathSpec {
+        Unit *unit;
+
         char *path;
 
-        Watch watch;
+        sd_event_source *event_source;
 
         LIST_FIELDS(struct PathSpec, spec);
 
@@ -59,8 +61,8 @@ typedef struct PathSpec {
         bool previous_exists;
 } PathSpec;
 
-int path_spec_watch(PathSpec *s, Unit *u);
-void path_spec_unwatch(PathSpec *s, Unit *u);
+int path_spec_watch(PathSpec *s, sd_event_io_handler_t handler);
+void path_spec_unwatch(PathSpec *s);
 int path_spec_fd_event(PathSpec *s, uint32_t events);
 void path_spec_done(PathSpec *s);
 
diff --git a/src/core/scope.c b/src/core/scope.c
index 41da3b9..a3c9479 100644
--- a/src/core/scope.c
+++ b/src/core/scope.c
@@ -40,6 +40,8 @@ static const UnitActiveState state_translation_table[_SCOPE_STATE_MAX] = {
         [SCOPE_FAILED] = UNIT_FAILED
 };
 
+static int scope_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata);
+
 static void scope_init(Unit *u) {
         Scope *s = SCOPE(u);
 
@@ -48,8 +50,6 @@ static void scope_init(Unit *u) {
 
         s->timeout_stop_usec = u->manager->default_timeout_stop_usec;
 
-        watch_init(&s->timer_watch);
-
         cgroup_context_init(&s->cgroup_context);
         kill_context_init(&s->kill_context);
 
@@ -67,7 +67,28 @@ static void scope_done(Unit *u) {
         set_free(s->pids);
         s->pids = NULL;
 
-        unit_unwatch_timer(u, &s->timer_watch);
+        s->timer_event_source = sd_event_source_unref(s->timer_event_source);
+}
+
+static int scope_arm_timer(Scope *s) {
+        int r;
+
+        assert(s);
+
+        if (s->timeout_stop_usec <= 0) {
+                s->timer_event_source = sd_event_source_unref(s->timer_event_source);
+                return 0;
+        }
+
+        if (s->timer_event_source) {
+                r = sd_event_source_set_time(s->timer_event_source, now(CLOCK_MONOTONIC) + s->timeout_stop_usec);
+                if (r < 0)
+                        return r;
+
+                return sd_event_source_set_enabled(s->timer_event_source, SD_EVENT_ONESHOT);
+        }
+
+        return sd_event_add_monotonic(UNIT(s)->manager->event, now(CLOCK_MONOTONIC) + s->timeout_stop_usec, 0, scope_dispatch_timer, s, &s->timer_event_source);
 }
 
 static void scope_set_state(Scope *s, ScopeState state) {
@@ -79,7 +100,7 @@ static void scope_set_state(Scope *s, ScopeState state) {
 
         if (state != SCOPE_STOP_SIGTERM &&
             state != SCOPE_STOP_SIGKILL)
-                unit_unwatch_timer(UNIT(s), &s->timer_watch);
+                s->timer_event_source = sd_event_source_unref(s->timer_event_source);
 
         if (state != old_state)
                 log_debug("%s changed %s -> %s",
@@ -158,11 +179,9 @@ static int scope_coldplug(Unit *u) {
 
         if (s->deserialized_state != s->state) {
 
-                if ((s->deserialized_state == SCOPE_STOP_SIGKILL || s->deserialized_state == SCOPE_STOP_SIGTERM)
-                    && s->timeout_stop_usec > 0) {
-                        r = unit_watch_timer(UNIT(s), CLOCK_MONOTONIC, true, s->timeout_stop_usec, &s->timer_watch);
+                if (s->deserialized_state == SCOPE_STOP_SIGKILL || s->deserialized_state == SCOPE_STOP_SIGTERM) {
+                        r = scope_arm_timer(s);
                         if (r < 0)
-
                                 return r;
                 }
 
@@ -214,11 +233,9 @@ static void scope_enter_signal(Scope *s, ScopeState state, ScopeResult f) {
                 goto fail;
 
         if (r > 0) {
-                if (s->timeout_stop_usec > 0) {
-                        r = unit_watch_timer(UNIT(s), CLOCK_MONOTONIC, true, s->timeout_stop_usec, &s->timer_watch);
-                        if (r < 0)
-                                goto fail;
-                }
+                r = scope_arm_timer(s);
+                if (r < 0)
+                        goto fail;
 
                 scope_set_state(s, state);
         } else
@@ -297,7 +314,7 @@ static void scope_reset_failed(Unit *u) {
         s->result = SCOPE_SUCCESS;
 }
 
-static int scope_kill(Unit *u, KillWho who, int signo, DBusError *error) {
+static int scope_kill(Unit *u, KillWho who, int signo, sd_bus_error *error) {
         return unit_kill_common(u, who, signo, -1, -1, error);
 }
 
@@ -353,34 +370,35 @@ static bool scope_check_gc(Unit *u) {
         return false;
 }
 
-static void scope_timer_event(Unit *u, uint64_t elapsed, Watch*w) {
-        Scope *s = SCOPE(u);
+static int scope_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata) {
+        Scope *s = SCOPE(userdata);
 
         assert(s);
-        assert(elapsed == 1);
-        assert(w == &s->timer_watch);
+        assert(s->timer_event_source == source);
 
         switch (s->state) {
 
         case SCOPE_STOP_SIGTERM:
                 if (s->kill_context.send_sigkill) {
-                        log_warning_unit(u->id, "%s stopping timed out. Killing.", u->id);
+                        log_warning_unit(UNIT(s)->id, "%s stopping timed out. Killing.", UNIT(s)->id);
                         scope_enter_signal(s, SCOPE_STOP_SIGKILL, SCOPE_FAILURE_TIMEOUT);
                 } else {
-                        log_warning_unit(u->id, "%s stopping timed out. Skipping SIGKILL.", u->id);
+                        log_warning_unit(UNIT(s)->id, "%s stopping timed out. Skipping SIGKILL.", UNIT(s)->id);
                         scope_enter_dead(s, SCOPE_FAILURE_TIMEOUT);
                 }
 
                 break;
 
         case SCOPE_STOP_SIGKILL:
-                log_warning_unit(u->id, "%s still around after SIGKILL. Ignoring.", u->id);
+                log_warning_unit(UNIT(s)->id, "%s still around after SIGKILL. Ignoring.", UNIT(s)->id);
                 scope_enter_dead(s, SCOPE_FAILURE_TIMEOUT);
                 break;
 
         default:
                 assert_not_reached("Timeout at wrong time.");
         }
+
+        return 0;
 }
 
 static void scope_notify_cgroup_empty_event(Unit *u) {
@@ -435,13 +453,14 @@ DEFINE_STRING_TABLE_LOOKUP(scope_result, ScopeResult);
 
 const UnitVTable scope_vtable = {
         .object_size = sizeof(Scope),
+        .cgroup_context_offset = offsetof(Scope, cgroup_context),
+        .kill_context_offset = offsetof(Scope, kill_context),
+
         .sections =
                 "Unit\0"
                 "Scope\0"
                 "Install\0",
-
         .private_section = "Scope",
-        .cgroup_context_offset = offsetof(Scope, cgroup_context),
 
         .no_alias = true,
         .no_instances = true,
@@ -467,14 +486,13 @@ const UnitVTable scope_vtable = {
 
         .check_gc = scope_check_gc,
 
-        .timer_event = scope_timer_event,
-
         .reset_failed = scope_reset_failed,
 
         .notify_cgroup_empty = scope_notify_cgroup_empty_event,
 
         .bus_interface = "org.freedesktop.systemd1.Scope",
-        .bus_message_handler = bus_scope_message_handler,
+        .bus_vtable = bus_scope_vtable,
+        .bus_changing_properties = bus_scope_changing_properties,
         .bus_set_property = bus_scope_set_property,
         .bus_commit_properties = bus_scope_commit_properties,
 
diff --git a/src/core/scope.h b/src/core/scope.h
index 2a3dcb7..4d8a171 100644
--- a/src/core/scope.h
+++ b/src/core/scope.h
@@ -57,7 +57,7 @@ struct Scope {
 
         Set *pids;
 
-        Watch timer_watch;
+        sd_event_source *timer_event_source;
 };
 
 extern const UnitVTable scope_vtable;
diff --git a/src/core/selinux-access.c b/src/core/selinux-access.c
index c7e951c..0ecbdf0 100644
--- a/src/core/selinux-access.c
+++ b/src/core/selinux-access.c
@@ -32,12 +32,11 @@
 #ifdef HAVE_AUDIT
 #include <libaudit.h>
 #endif
-#include <dbus.h>
 
+#include "sd-bus.h"
+#include "bus-util.h"
 #include "util.h"
 #include "log.h"
-#include "bus-errors.h"
-#include "dbus-common.h"
 #include "audit.h"
 #include "selinux-util.h"
 #include "audit-fd.h"
@@ -53,72 +52,59 @@ struct auditstruct {
 };
 
 static int bus_get_selinux_security_context(
-                DBusConnection *connection,
+                sd_bus *bus,
                 const char *name,
-                char **scon,
-                DBusError *error) {
+                sd_bus_error *error,
+                char **ret) {
 
-        _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
-        DBusMessageIter iter, sub;
-        const char *bytes;
+        _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+        const void *p;
+        size_t sz;
         char *b;
-        int nbytes;
-
-        m = dbus_message_new_method_call(
-                        DBUS_SERVICE_DBUS,
-                        DBUS_PATH_DBUS,
-                        DBUS_INTERFACE_DBUS,
-                        "GetConnectionSELinuxSecurityContext");
-        if (!m) {
-                dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, NULL);
-                return -ENOMEM;
-        }
-
-        if (!dbus_message_append_args(
-                            m,
-                            DBUS_TYPE_STRING, &name,
-                            DBUS_TYPE_INVALID)) {
-                dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, NULL);
-                return -ENOMEM;
-        }
-
-        reply = dbus_connection_send_with_reply_and_block(connection, m, -1, error);
-        if (!reply)
-                return -EIO;
-
-        if (dbus_set_error_from_message(error, reply))
-                return -EIO;
-
-        if (!dbus_message_iter_init(reply, &iter))
-                return -EIO;
+        int r;
 
-        if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY)
-                return -EIO;
+        assert(bus);
+        assert(name);
+        assert(ret);
+
+        r = sd_bus_call_method(
+                        bus,
+                        "org.freedesktop.DBus",
+                        "/org/freedesktop/DBus",
+                        "org.freedesktop.DBus",
+                        "GetConnectionSELinuxSecurityContext",
+                        error, &m,
+                        "s", name);
+        if (r < 0)
+                return r;
 
-        dbus_message_iter_recurse(&iter, &sub);
-        dbus_message_iter_get_fixed_array(&sub, &bytes, &nbytes);
+        r = sd_bus_message_read_array(m, 'y', &p, &sz);
+        if (r < 0)
+                return r;
 
-        b = strndup(bytes, nbytes);
+        b = strndup(p, sz);
         if (!b)
                 return -ENOMEM;
 
-        *scon = b;
-
+        *ret = b;
         return 0;
 }
 
 static int bus_get_audit_data(
-                DBusConnection *connection,
+                sd_bus *bus,
                 const char *name,
-                struct auditstruct *audit,
-                DBusError *error) {
+                struct auditstruct *audit) {
 
         pid_t pid;
         int r;
 
-        pid = bus_get_unix_process_id(connection, name, error);
-        if (pid <= 0)
-                return -EIO;
+        assert(bus);
+        assert(name);
+        assert(audit);
+
+        r = sd_bus_get_owner_pid(bus, name, &pid);
+        if (r < 0)
+                return r;
 
         r = audit_loginuid_from_pid(pid, &audit->loginuid);
         if (r < 0)
@@ -207,7 +193,7 @@ _printf_(2, 3) static int log_callback(int type, const char *fmt, ...) {
    If you want to cleanup memory you should need to call selinux_access_finish.
 */
 static int access_init(void) {
-        int r;
+        int r = 0;
 
         if (avc_open(NULL, 0)) {
                 log_error("avc_open() failed: %m");
@@ -217,34 +203,33 @@ static int access_init(void) {
         selinux_set_callback(SELINUX_CB_AUDIT, (union selinux_callback) audit_callback);
         selinux_set_callback(SELINUX_CB_LOG, (union selinux_callback) log_callback);
 
-        if (security_getenforce() >= 0)
-                return 0;
-
-        r = -errno;
-        avc_destroy();
+        if (security_getenforce() < 0){
+                r = -errno;
+                avc_destroy();
+        }
 
         return r;
 }
 
-static int selinux_access_init(DBusError *error) {
+static int selinux_access_init(sd_bus_error *error) {
         int r;
 
         if (initialized)
                 return 0;
 
-        if (use_selinux()) {
-                r = access_init();
-                if (r < 0) {
-                        dbus_set_error(error, DBUS_ERROR_ACCESS_DENIED, "Failed to initialize SELinux.");
-                        return r;
-                }
-        }
+        if (!use_selinux())
+                return 0;
+
+        r = access_init();
+        if (r < 0)
+                return sd_bus_error_set(error, SD_BUS_ERROR_ACCESS_DENIED, "Failed to initialize SELinux.");
 
         initialized = true;
         return 0;
 }
 
 void selinux_access_free(void) {
+
         if (!initialized)
                 return;
 
@@ -253,28 +238,27 @@ void selinux_access_free(void) {
 }
 
 static int get_audit_data(
-                DBusConnection *connection,
-                DBusMessage *message,
-                struct auditstruct *audit,
-                DBusError *error) {
+                sd_bus *bus,
+                sd_bus_message *message,
+                struct auditstruct *audit) {
 
+        struct ucred ucred;
         const char *sender;
+        socklen_t len;
         int r, fd;
-        struct ucred ucred;
-        socklen_t len = sizeof(ucred);
 
-        sender = dbus_message_get_sender(message);
+        sender = sd_bus_message_get_sender(message);
         if (sender)
-                return bus_get_audit_data(connection, sender, audit, error);
+                return bus_get_audit_data(bus, sender, audit);
 
-        if (!dbus_connection_get_unix_fd(connection, &fd))
-                return -EINVAL;
+        fd = sd_bus_get_fd(bus);
+        if (fd < 0)
+                return fd;
 
+        len = sizeof(ucred);
         r = getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &len);
-        if (r < 0) {
-                log_error("Failed to determine peer credentials: %m");
+        if (r < 0)
                 return -errno;
-        }
 
         audit->uid = ucred.uid;
         audit->gid = ucred.gid;
@@ -295,40 +279,30 @@ static int get_audit_data(
    connections.  Whether it is on the bus or a local connection.
 */
 static int get_calling_context(
-                DBusConnection *connection,
-                DBusMessage *message,
-                security_context_t *scon,
-                DBusError *error) {
+                sd_bus *bus,
+                sd_bus_message *message,
+                sd_bus_error *error,
+                security_context_t *ret) {
 
         const char *sender;
-        int r;
-        int fd;
+        int r, fd;
 
         /*
            If sender exists then
            if sender is NULL this indicates a local connection.  Grab the fd
            from dbus and do an getpeercon to peers process context
         */
-        sender = dbus_message_get_sender(message);
-        if (sender) {
-                r = bus_get_selinux_security_context(connection, sender, scon, error);
-                if (r >= 0)
-                        return r;
-
-                log_error("bus_get_selinux_security_context failed: %m");
-                return r;
-        }
+        sender = sd_bus_message_get_sender(message);
+        if (sender)
+                return bus_get_selinux_security_context(bus, sender, error, ret);
 
-        if (!dbus_connection_get_unix_fd(connection, &fd)) {
-                log_error("bus_connection_get_unix_fd failed %m");
-                return -EINVAL;
-        }
+        fd = sd_bus_get_fd(bus);
+        if (fd < 0)
+                return fd;
 
-        r = getpeercon(fd, scon);
-        if (r < 0) {
-                log_error("getpeercon failed %m");
+        r = getpeercon(fd, ret);
+        if (r < 0)
                 return -errno;
-        }
 
         return 0;
 }
@@ -340,18 +314,18 @@ static int get_calling_context(
    still be generated if the access would be denied in enforcing mode.
 */
 int selinux_access_check(
-                DBusConnection *connection,
-                DBusMessage *message,
+                sd_bus *bus,
+                sd_bus_message *message,
                 const char *path,
                 const char *permission,
-                DBusError *error) {
+                sd_bus_error *error) {
 
         security_context_t scon = NULL, fcon = NULL;
-        int r = 0;
         const char *tclass = NULL;
         struct auditstruct audit;
+        int r = 0;
 
-        assert(connection);
+        assert(bus);
         assert(message);
         assert(permission);
         assert(error);
@@ -368,43 +342,36 @@ int selinux_access_check(
         audit.cmdline = NULL;
         audit.path = path;
 
-        r = get_calling_context(connection, message, &scon, error);
-        if (r < 0) {
-                log_error("Failed to get caller's security context on: %m");
+        r = get_calling_context(bus, message, error, &scon);
+        if (r < 0)
                 goto finish;
-        }
 
         if (path) {
-                tclass = "service";
-                /* get the file context of the unit file */
+                /* Get the file context of the unit file */
+
                 r = getfilecon(path, &fcon);
                 if (r < 0) {
-                        dbus_set_error(error, DBUS_ERROR_ACCESS_DENIED, "Failed to get file context on %s.", path);
-                        r = -errno;
-                        log_error("Failed to get security context on %s: %m",path);
+                        r = sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "Failed to get file context on %s.", path);
                         goto finish;
                 }
 
+                tclass = "service";
         } else {
-                tclass = "system";
                 r = getcon(&fcon);
                 if (r < 0) {
-                        dbus_set_error(error, DBUS_ERROR_ACCESS_DENIED, "Failed to get current context.");
-                        r = -errno;
-                        log_error("Failed to get current process context on: %m");
+                        r = sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "Failed to get current context.");
                         goto finish;
                 }
+
+                tclass = "system";
         }
 
-        (void) get_audit_data(connection, message, &audit, error);
+        get_audit_data(bus, message, &audit);
 
         errno = 0;
         r = selinux_check_access(scon, fcon, tclass, permission, &audit);
-        if (r < 0) {
-                dbus_set_error(error, DBUS_ERROR_ACCESS_DENIED, "SELinux policy denies access.");
-                r = -errno;
-                log_error("SELinux policy denies access.");
-        }
+        if (r < 0)
+                r = sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "SELinux policy denies access.");
 
         log_debug("SELinux access check scon=%s tcon=%s tclass=%s perm=%s path=%s cmdline=%s: %i", scon, fcon, tclass, permission, path, audit.cmdline, r);
 
@@ -414,7 +381,7 @@ finish:
         freecon(fcon);
 
         if (r && security_getenforce() != 1) {
-                dbus_error_init(error);
+                sd_bus_error_free(error);
                 r = 0;
         }
 
@@ -424,11 +391,11 @@ finish:
 #else
 
 int selinux_access_check(
-                DBusConnection *connection,
-                DBusMessage *message,
+                sd_bus *bus,
+                sd_bus_message *message,
                 const char *path,
                 const char *permission,
-                DBusError *error) {
+                sd_bus_error *error) {
 
         return 0;
 }
diff --git a/src/core/selinux-access.h b/src/core/selinux-access.h
index 2d7ac64..0926a5e 100644
--- a/src/core/selinux-access.h
+++ b/src/core/selinux-access.h
@@ -21,42 +21,42 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <dbus.h>
+#include "sd-bus.h"
+#include "bus-error.h"
+#include "bus-util.h"
 
 void selinux_access_free(void);
 
-int selinux_access_check(DBusConnection *connection, DBusMessage *message, const char *path, const char *permission, DBusError *error);
+int selinux_access_check(sd_bus *bus, sd_bus_message *message, const char *path, const char *permission, sd_bus_error *error);
 
 #ifdef HAVE_SELINUX
 
-#define SELINUX_ACCESS_CHECK(connection, message, permission) \
+#define SELINUX_ACCESS_CHECK(bus, message, permission)                  \
         do {                                                            \
-                DBusError _error;                                       \
+                _cleanup_bus_error_free_ sd_bus_error _error = SD_BUS_ERROR_NULL; \
+                sd_bus_message *_m = (message);                         \
+                sd_bus *_b = (bus);                                     \
                 int _r;                                                 \
-                DBusConnection *_c = (connection);                      \
-                DBusMessage *_m = (message);                            \
-                dbus_error_init(&_error);                               \
-                _r = selinux_access_check(_c, _m, NULL, (permission), &_error); \
+                _r = selinux_access_check(_b, _m, NULL, (permission), &_error); \
                 if (_r < 0)                                             \
-                        return bus_send_error_reply(_c, _m, &_error, _r); \
+                        return sd_bus_reply_method_errno(_b, _m, _r, &_error); \
         } while (false)
 
-#define SELINUX_UNIT_ACCESS_CHECK(unit, connection, message, permission) \
+#define SELINUX_UNIT_ACCESS_CHECK(unit, bus, message, permission)       \
         do {                                                            \
-                DBusError _error;                                       \
-                int _r;                                                 \
-                DBusConnection *_c = (connection);                      \
-                DBusMessage *_m = (message);                            \
+                _cleanup_bus_error_free_ sd_bus_error _error = SD_BUS_ERROR_NULL; \
+                sd_bus_message *_m = (message);                         \
+                sd_bus *_b = (bus);                                     \
                 Unit *_u = (unit);                                      \
-                dbus_error_init(&_error);                               \
-                _r = selinux_access_check(_c, _m, _u->source_path ?: _u->fragment_path, (permission), &_error); \
+                int _r;                                                 \
+                _r = selinux_access_check(_b, _m, _u->source_path ?: _u->fragment_path, (permission), &_error); \
                 if (_r < 0)                                             \
-                        return bus_send_error_reply(_c, _m, &_error, _r); \
+                        return sd_bus_reply_method_errno(_b, _m, _r, &_error); \
         } while (false)
 
 #else
 
-#define SELINUX_ACCESS_CHECK(connection, message, permission) do { } while (false)
-#define SELINUX_UNIT_ACCESS_CHECK(unit, connection, message, permission) do { } while (false)
+#define SELINUX_ACCESS_CHECK(bus, message, permission) do { } while (false)
+#define SELINUX_UNIT_ACCESS_CHECK(unit, bus, message, permission) do { } while (false)
 
 #endif
diff --git a/src/core/service.c b/src/core/service.c
index c0ee114..d9e525e 100644
--- a/src/core/service.c
+++ b/src/core/service.c
@@ -36,7 +36,6 @@
 #include "unit-printf.h"
 #include "dbus-service.h"
 #include "special.h"
-#include "dbus-common.h"
 #include "exit-status.h"
 #include "def.h"
 #include "path-util.h"
@@ -44,6 +43,8 @@
 #include "utf8.h"
 #include "env-util.h"
 #include "fileio.h"
+#include "bus-error.h"
+#include "bus-util.h"
 
 #ifdef HAVE_SYSV_COMPAT
 
@@ -118,6 +119,10 @@ static const UnitActiveState state_translation_table_idle[_SERVICE_STATE_MAX] =
         [SERVICE_AUTO_RESTART] = UNIT_ACTIVATING
 };
 
+static int service_dispatch_io(sd_event_source *source, int fd, uint32_t events, void *userdata);
+static int service_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata);
+static int service_dispatch_watchdog(sd_event_source *source, usec_t usec, void *userdata);
+
 static void service_init(Unit *u) {
         Service *s = SERVICE(u);
 
@@ -129,9 +134,6 @@ static void service_init(Unit *u) {
         s->restart_usec = u->manager->default_restart_usec;
         s->type = _SERVICE_TYPE_INVALID;
 
-        watch_init(&s->watchdog_watch);
-        watch_init(&s->timer_watch);
-
 #ifdef HAVE_SYSV_COMPAT
         s->sysv_start_priority = -1;
         s->sysv_start_priority_from_rcnd = -1;
@@ -176,7 +178,7 @@ static void service_unwatch_pid_file(Service *s) {
 
         log_debug_unit(UNIT(s)->id, "Stopping watch for %s's PID file %s",
                        UNIT(s)->id, s->pid_file_pathspec->path);
-        path_spec_unwatch(s->pid_file_pathspec, UNIT(s));
+        path_spec_unwatch(s->pid_file_pathspec);
         path_spec_done(s->pid_file_pathspec);
         free(s->pid_file_pathspec);
         s->pid_file_pathspec = NULL;
@@ -239,15 +241,14 @@ static void service_connection_unref(Service *s) {
 static void service_stop_watchdog(Service *s) {
         assert(s);
 
-        unit_unwatch_timer(UNIT(s), &s->watchdog_watch);
-        s->watchdog_timestamp.realtime = 0;
-        s->watchdog_timestamp.monotonic = 0;
+        s->watchdog_event_source = sd_event_source_unref(s->watchdog_event_source);
+        s->watchdog_timestamp = (struct dual_timestamp) { 0, 0 };
 }
 
 static void service_enter_signal(Service *s, ServiceState state, ServiceResult f);
 
 static void service_handle_watchdog(Service *s) {
-        usec_t offset;
+        usec_t nw;
         int r;
 
         assert(s);
@@ -255,14 +256,24 @@ static void service_handle_watchdog(Service *s) {
         if (s->watchdog_usec == 0)
                 return;
 
-        offset = now(CLOCK_MONOTONIC) - s->watchdog_timestamp.monotonic;
-        if (offset >= s->watchdog_usec) {
+        nw = now(CLOCK_MONOTONIC);
+        if (nw >=  s->watchdog_timestamp.monotonic + s->watchdog_usec) {
                 log_error_unit(UNIT(s)->id, "%s watchdog timeout!", UNIT(s)->id);
                 service_enter_signal(s, SERVICE_STOP_SIGKILL, SERVICE_FAILURE_WATCHDOG);
                 return;
         }
 
-        r = unit_watch_timer(UNIT(s), CLOCK_MONOTONIC, true, s->watchdog_usec - offset, &s->watchdog_watch);
+        if (s->watchdog_event_source) {
+                r = sd_event_source_set_time(s->watchdog_event_source, s->watchdog_timestamp.monotonic + s->watchdog_usec);
+                if (r < 0) {
+                        log_warning_unit(UNIT(s)->id, "%s failed to reset watchdog timer: %s", UNIT(s)->id, strerror(-r));
+                        return;
+                }
+
+                r = sd_event_source_set_enabled(s->watchdog_event_source, SD_EVENT_ON);
+        } else
+                r = sd_event_add_monotonic(UNIT(s)->manager->event, s->watchdog_timestamp.monotonic + s->watchdog_usec, 0, service_dispatch_watchdog, s, &s->watchdog_event_source);
+
         if (r < 0)
                 log_warning_unit(UNIT(s)->id,
                                  "%s failed to install watchdog timer: %s",
@@ -327,7 +338,28 @@ static void service_done(Unit *u) {
 
         service_stop_watchdog(s);
 
-        unit_unwatch_timer(u, &s->timer_watch);
+        s->timer_event_source = sd_event_source_unref(s->timer_event_source);
+}
+
+static int service_arm_timer(Service *s, usec_t usec) {
+        int r;
+
+        assert(s);
+
+        if (usec <= 0) {
+                s->timer_event_source = sd_event_source_unref(s->timer_event_source);
+                return 0;
+        }
+
+        if (s->timer_event_source) {
+                r = sd_event_source_set_time(s->timer_event_source, now(CLOCK_MONOTONIC) + usec);
+                if (r < 0)
+                        return r;
+
+                return sd_event_source_set_enabled(s->timer_event_source, SD_EVENT_ONESHOT);
+        }
+
+        return sd_event_add_monotonic(UNIT(s)->manager->event, now(CLOCK_MONOTONIC) + usec, 0, service_dispatch_timer, s, &s->timer_event_source);
 }
 
 #ifdef HAVE_SYSV_COMPAT
@@ -1214,9 +1246,11 @@ static int service_load(Unit *u) {
                         return r;
 #endif
 
-                if (s->bus_name)
-                        if ((r = unit_watch_bus_name(u, s->bus_name)) < 0)
+                if (s->bus_name) {
+                        r = unit_watch_bus_name(u, s->bus_name);
+                        if (r < 0)
                                 return r;
+                }
 
                 if (s->type == SERVICE_NOTIFY && s->notify_access == NOTIFY_NONE)
                         s->notify_access = NOTIFY_MAIN;
@@ -1467,7 +1501,7 @@ static void service_set_state(Service *s, ServiceState state) {
             state != SERVICE_FINAL_SIGTERM &&
             state != SERVICE_FINAL_SIGKILL &&
             state != SERVICE_AUTO_RESTART)
-                unit_unwatch_timer(UNIT(s), &s->timer_watch);
+                s->timer_event_source = sd_event_source_unref(s->timer_event_source);
 
         if (state != SERVICE_START &&
             state != SERVICE_START_POST &&
@@ -1567,11 +1601,12 @@ static int service_coldplug(Unit *u) {
                     s->deserialized_state == SERVICE_AUTO_RESTART) {
 
                         if (s->deserialized_state == SERVICE_AUTO_RESTART || s->timeout_start_usec > 0) {
-                                usec_t k;
 
-                                k = s->deserialized_state == SERVICE_AUTO_RESTART ? s->restart_usec : s->timeout_start_usec;
-
-                                r = unit_watch_timer(UNIT(s), CLOCK_MONOTONIC, true, k, &s->timer_watch);
+                                r = service_arm_timer(s,
+                                                      s->deserialized_state == SERVICE_AUTO_RESTART ? s->restart_usec :
+                                                      s->deserialized_state == SERVICE_START_PRE || s->deserialized_state == SERVICE_START ||
+                                                      s->deserialized_state == SERVICE_START_POST || s->deserialized_state == SERVICE_RELOAD ? s->timeout_start_usec :
+                                                      s->timeout_stop_usec);
                                 if (r < 0)
                                         return r;
                         }
@@ -1728,13 +1763,9 @@ static int service_spawn(
                 }
         }
 
-        if (timeout && s->timeout_start_usec) {
-                r = unit_watch_timer(UNIT(s), CLOCK_MONOTONIC, true,
-                                     s->timeout_start_usec, &s->timer_watch);
-                if (r < 0)
-                        goto fail;
-        } else
-                unit_unwatch_timer(UNIT(s), &s->timer_watch);
+        r = service_arm_timer(s, timeout ? s->timeout_start_usec : 0);
+        if (r < 0)
+                goto fail;
 
         r = unit_full_printf_strv(UNIT(s), c->argv, &argv);
         if (r < 0)
@@ -1810,7 +1841,7 @@ static int service_spawn(
 
 fail:
         if (timeout)
-                unit_unwatch_timer(UNIT(s), &s->timer_watch);
+                s->timer_event_source = sd_event_source_unref(s->timer_event_source);
 
         return r;
 }
@@ -1881,10 +1912,9 @@ static void service_enter_dead(Service *s, ServiceResult f, bool allow_restart)
             (s->result != SERVICE_FAILURE_EXIT_CODE ||
              !set_contains(s->restart_ignore_status.code, INT_TO_PTR(s->main_exec_status.status))) &&
             (s->result != SERVICE_FAILURE_SIGNAL ||
-             !set_contains(s->restart_ignore_status.signal, INT_TO_PTR(s->main_exec_status.status)))
-                ) {
+             !set_contains(s->restart_ignore_status.signal, INT_TO_PTR(s->main_exec_status.status)))) {
 
-                r = unit_watch_timer(UNIT(s), CLOCK_MONOTONIC, true, s->restart_usec, &s->timer_watch);
+                r = service_arm_timer(s, s->restart_usec);
                 if (r < 0)
                         goto fail;
 
@@ -1971,8 +2001,7 @@ static void service_enter_signal(Service *s, ServiceState state, ServiceResult f
 
         if (r > 0) {
                 if (s->timeout_stop_usec > 0) {
-                        r = unit_watch_timer(UNIT(s), CLOCK_MONOTONIC, true,
-                                             s->timeout_stop_usec, &s->timer_watch);
+                        r = service_arm_timer(s, s->timeout_stop_usec);
                         if (r < 0)
                                 goto fail;
                 }
@@ -2225,18 +2254,17 @@ fail:
 }
 
 static void service_enter_restart(Service *s) {
+        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
         int r;
-        DBusError error;
 
         assert(s);
-        dbus_error_init(&error);
 
         if (UNIT(s)->job && UNIT(s)->job->type == JOB_STOP) {
                 /* Don't restart things if we are going down anyway */
                 log_info_unit(UNIT(s)->id,
                               "Stop job pending for unit, delaying automatic restart.");
 
-                r = unit_watch_timer(UNIT(s), CLOCK_MONOTONIC, true, s->restart_usec, &s->timer_watch);
+                r = service_arm_timer(s, s->restart_usec);
                 if (r < 0)
                         goto fail;
 
@@ -2262,10 +2290,8 @@ static void service_enter_restart(Service *s) {
 fail:
         log_warning_unit(UNIT(s)->id,
                          "%s failed to schedule restart job: %s",
-                         UNIT(s)->id, bus_error(&error, -r));
+                         UNIT(s)->id, bus_error_message(&error, -r));
         service_enter_dead(s, SERVICE_FAILURE_RESOURCES, false);
-
-        dbus_error_free(&error);
 }
 
 static void service_enter_reload(Service *s) {
@@ -2402,22 +2428,18 @@ static int service_start_limit_test(Service *s) {
                 break;
 
         case SERVICE_START_LIMIT_REBOOT: {
-                DBusError error;
+                _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
                 int r;
 
-                dbus_error_init(&error);
-
                 log_warning_unit(UNIT(s)->id,
                                  "%s start request repeated too quickly, rebooting.", UNIT(s)->id);
 
                 r = manager_add_job_by_name(UNIT(s)->manager, JOB_START,
                                             SPECIAL_REBOOT_TARGET, JOB_REPLACE,
                                             true, &error, NULL);
-                if (r < 0) {
+                if (r < 0)
                         log_error_unit(UNIT(s)->id,
-                                       "Failed to reboot: %s.", bus_error(&error, r));
-                        dbus_error_free(&error);
-                }
+                                       "Failed to reboot: %s.", bus_error_message(&error, r));
 
                 break;
         }
@@ -2837,7 +2859,7 @@ static int service_watch_pid_file(Service *s) {
         log_debug_unit(UNIT(s)->id,
                        "Setting watch for %s's PID file %s",
                        UNIT(s)->id, s->pid_file_pathspec->path);
-        r = path_spec_watch(s->pid_file_pathspec, UNIT(s));
+        r = path_spec_watch(s->pid_file_pathspec, service_dispatch_io);
         if (r < 0)
                 goto fail;
 
@@ -2866,6 +2888,7 @@ static int service_demand_pid_file(Service *s) {
         if (!ps)
                 return -ENOMEM;
 
+        ps->unit = UNIT(s);
         ps->path = strdup(s->pid_file);
         if (!ps->path) {
                 free(ps);
@@ -2884,8 +2907,8 @@ static int service_demand_pid_file(Service *s) {
         return service_watch_pid_file(s);
 }
 
-static void service_fd_event(Unit *u, int fd, uint32_t events, Watch *w) {
-        Service *s = SERVICE(u);
+static int service_dispatch_io(sd_event_source *source, int fd, uint32_t events, void *userdata) {
+        Service *s = SERVICE(userdata);
 
         assert(s);
         assert(fd >= 0);
@@ -2893,21 +2916,23 @@ static void service_fd_event(Unit *u, int fd, uint32_t events, Watch *w) {
         assert(s->pid_file_pathspec);
         assert(path_spec_owns_inotify_fd(s->pid_file_pathspec, fd));
 
-        log_debug_unit(u->id, "inotify event for %s", u->id);
+        log_debug_unit(UNIT(s)->id, "inotify event for %s", UNIT(s)->id);
 
         if (path_spec_fd_event(s->pid_file_pathspec, events) < 0)
                 goto fail;
 
         if (service_retry_pid_file(s) == 0)
-                return;
+                return 0;
 
         if (service_watch_pid_file(s) < 0)
                 goto fail;
 
-        return;
+        return 0;
+
 fail:
         service_unwatch_pid_file(s);
         service_enter_signal(s, SERVICE_STOP_SIGTERM, SERVICE_FAILURE_RESOURCES);
+        return 0;
 }
 
 static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) {
@@ -3180,55 +3205,48 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) {
         unit_add_to_dbus_queue(u);
 }
 
-static void service_timer_event(Unit *u, uint64_t elapsed, Watch* w) {
-        Service *s = SERVICE(u);
+static int service_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata) {
+        Service *s = SERVICE(userdata);
 
         assert(s);
-        assert(elapsed == 1);
-
-        if (w == &s->watchdog_watch) {
-                service_handle_watchdog(s);
-                return;
-        }
-
-        assert(w == &s->timer_watch);
+        assert(source == s->timer_event_source);
 
         switch (s->state) {
 
         case SERVICE_START_PRE:
         case SERVICE_START:
-                log_warning_unit(u->id,
-                                 "%s operation timed out. Terminating.", u->id);
+                log_warning_unit(UNIT(s)->id,
+                                 "%s operation timed out. Terminating.", UNIT(s)->id);
                 service_enter_signal(s, SERVICE_FINAL_SIGTERM, SERVICE_FAILURE_TIMEOUT);
                 break;
 
         case SERVICE_START_POST:
-                log_warning_unit(u->id,
-                                 "%s operation timed out. Stopping.", u->id);
+                log_warning_unit(UNIT(s)->id,
+                                 "%s operation timed out. Stopping.", UNIT(s)->id);
                 service_enter_stop(s, SERVICE_FAILURE_TIMEOUT);
                 break;
 
         case SERVICE_RELOAD:
-                log_warning_unit(u->id,
-                                 "%s operation timed out. Stopping.", u->id);
+                log_warning_unit(UNIT(s)->id,
+                                 "%s operation timed out. Stopping.", UNIT(s)->id);
                 s->reload_result = SERVICE_FAILURE_TIMEOUT;
                 service_enter_running(s, SERVICE_SUCCESS);
                 break;
 
         case SERVICE_STOP:
-                log_warning_unit(u->id,
-                                 "%s stopping timed out. Terminating.", u->id);
+                log_warning_unit(UNIT(s)->id,
+                                 "%s stopping timed out. Terminating.", UNIT(s)->id);
                 service_enter_signal(s, SERVICE_STOP_SIGTERM, SERVICE_FAILURE_TIMEOUT);
                 break;
 
         case SERVICE_STOP_SIGTERM:
                 if (s->kill_context.send_sigkill) {
-                        log_warning_unit(u->id,
-                                         "%s stopping timed out. Killing.", u->id);
+                        log_warning_unit(UNIT(s)->id,
+                                         "%s stopping timed out. Killing.", UNIT(s)->id);
                         service_enter_signal(s, SERVICE_STOP_SIGKILL, SERVICE_FAILURE_TIMEOUT);
                 } else {
-                        log_warning_unit(u->id,
-                                         "%s stopping timed out. Skipping SIGKILL.", u->id);
+                        log_warning_unit(UNIT(s)->id,
+                                         "%s stopping timed out. Skipping SIGKILL.", UNIT(s)->id);
                         service_enter_stop_post(s, SERVICE_FAILURE_TIMEOUT);
                 }
 
@@ -3239,46 +3257,58 @@ static void service_timer_event(Unit *u, uint64_t elapsed, Watch* w) {
                  * Must be something we cannot kill, so let's just be
                  * weirded out and continue */
 
-                log_warning_unit(u->id,
-                                 "%s still around after SIGKILL. Ignoring.", u->id);
+                log_warning_unit(UNIT(s)->id,
+                                 "%s still around after SIGKILL. Ignoring.", UNIT(s)->id);
                 service_enter_stop_post(s, SERVICE_FAILURE_TIMEOUT);
                 break;
 
         case SERVICE_STOP_POST:
-                log_warning_unit(u->id,
-                                 "%s stopping timed out (2). Terminating.", u->id);
+                log_warning_unit(UNIT(s)->id,
+                                 "%s stopping timed out (2). Terminating.", UNIT(s)->id);
                 service_enter_signal(s, SERVICE_FINAL_SIGTERM, SERVICE_FAILURE_TIMEOUT);
                 break;
 
         case SERVICE_FINAL_SIGTERM:
                 if (s->kill_context.send_sigkill) {
-                        log_warning_unit(u->id,
-                                         "%s stopping timed out (2). Killing.", u->id);
+                        log_warning_unit(UNIT(s)->id,
+                                         "%s stopping timed out (2). Killing.", UNIT(s)->id);
                         service_enter_signal(s, SERVICE_FINAL_SIGKILL, SERVICE_FAILURE_TIMEOUT);
                 } else {
-                        log_warning_unit(u->id,
+                        log_warning_unit(UNIT(s)->id,
                                          "%s stopping timed out (2). Skipping SIGKILL. Entering failed mode.",
-                                         u->id);
+                                         UNIT(s)->id);
                         service_enter_dead(s, SERVICE_FAILURE_TIMEOUT, false);
                 }
 
                 break;
 
         case SERVICE_FINAL_SIGKILL:
-                log_warning_unit(u->id,
-                                 "%s still around after SIGKILL (2). Entering failed mode.", u->id);
+                log_warning_unit(UNIT(s)->id,
+                                 "%s still around after SIGKILL (2). Entering failed mode.", UNIT(s)->id);
                 service_enter_dead(s, SERVICE_FAILURE_TIMEOUT, true);
                 break;
 
         case SERVICE_AUTO_RESTART:
-                log_info_unit(u->id,
-                              "%s holdoff time over, scheduling restart.", u->id);
+                log_info_unit(UNIT(s)->id,
+                              "%s holdoff time over, scheduling restart.", UNIT(s)->id);
                 service_enter_restart(s);
                 break;
 
         default:
                 assert_not_reached("Timeout at wrong time.");
         }
+
+        return 0;
+}
+
+static int service_dispatch_watchdog(sd_event_source *source, usec_t usec, void *userdata) {
+        Service *s = SERVICE(userdata);
+
+        assert(s);
+        assert(source == s->watchdog_event_source);
+
+        service_handle_watchdog(s);
+        return 0;
 }
 
 static void service_notify_cgroup_empty_event(Unit *u) {
@@ -3606,6 +3636,7 @@ static void service_bus_name_owner_change(
                 const char *new_owner) {
 
         Service *s = SERVICE(u);
+        int r;
 
         assert(s);
         assert(name);
@@ -3644,35 +3675,17 @@ static void service_bus_name_owner_change(
                     s->state == SERVICE_RUNNING ||
                     s->state == SERVICE_RELOAD)) {
 
-                /* Try to acquire PID from bus service */
-                log_debug_unit(u->id,
-                               "Trying to acquire PID from D-Bus name...");
-
-                bus_query_pid(u->manager, name);
-        }
-}
-
-static void service_bus_query_pid_done(
-                Unit *u,
-                const char *name,
-                pid_t pid) {
-
-        Service *s = SERVICE(u);
+                pid_t pid;
 
-        assert(s);
-        assert(name);
+                /* Try to acquire PID from bus service */
 
-        log_debug_unit(u->id,
-                       "%s's D-Bus name %s is now owned by process %u",
-                       u->id, name, (unsigned) pid);
+                r = sd_bus_get_owner_pid(u->manager->api_bus, name, &pid);
+                if (r >= 0) {
+                        log_debug_unit(u->id, "%s's D-Bus name %s is now owned by process %u", u->id, name, (unsigned) pid);
 
-        if (s->main_pid <= 0 &&
-            (s->state == SERVICE_START ||
-             s->state == SERVICE_START_POST ||
-             s->state == SERVICE_RUNNING ||
-             s->state == SERVICE_RELOAD)){
-                service_set_main_pid(s, pid);
-                unit_watch_pid(UNIT(s), pid);
+                        service_set_main_pid(s, pid);
+                        unit_watch_pid(UNIT(s), pid);
+                }
         }
 }
 
@@ -3716,7 +3729,7 @@ static void service_reset_failed(Unit *u) {
         RATELIMIT_RESET(s->start_limit);
 }
 
-static int service_kill(Unit *u, KillWho who, int signo, DBusError *error) {
+static int service_kill(Unit *u, KillWho who, int signo, sd_bus_error *error) {
         Service *s = SERVICE(u);
 
         return unit_kill_common(u, who, signo, s->main_pid, s->control_pid, error);
@@ -3806,15 +3819,15 @@ DEFINE_STRING_TABLE_LOOKUP(start_limit_action, StartLimitAction);
 
 const UnitVTable service_vtable = {
         .object_size = sizeof(Service),
+        .exec_context_offset = offsetof(Service, exec_context),
+        .cgroup_context_offset = offsetof(Service, cgroup_context),
+        .kill_context_offset = offsetof(Service, kill_context),
 
         .sections =
                 "Unit\0"
                 "Service\0"
                 "Install\0",
-
         .private_section = "Service",
-        .exec_context_offset = offsetof(Service, exec_context),
-        .cgroup_context_offset = offsetof(Service, cgroup_context),
 
         .init = service_init,
         .done = service_done,
@@ -3842,8 +3855,6 @@ const UnitVTable service_vtable = {
         .check_snapshot = service_check_snapshot,
 
         .sigchld_event = service_sigchld_event,
-        .timer_event = service_timer_event,
-        .fd_event = service_fd_event,
 
         .reset_failed = service_reset_failed,
 
@@ -3851,19 +3862,19 @@ const UnitVTable service_vtable = {
         .notify_message = service_notify_message,
 
         .bus_name_owner_change = service_bus_name_owner_change,
-        .bus_query_pid_done = service_bus_query_pid_done,
 
         .bus_interface = "org.freedesktop.systemd1.Service",
-        .bus_message_handler = bus_service_message_handler,
-        .bus_invalidating_properties =  bus_service_invalidating_properties,
+        .bus_vtable = bus_service_vtable,
+        .bus_changing_properties = bus_service_changing_properties,
         .bus_set_property = bus_service_set_property,
         .bus_commit_properties = bus_service_commit_properties,
 
-        .can_transient = true,
-
 #ifdef HAVE_SYSV_COMPAT
         .enumerate = service_enumerate,
 #endif
+
+        .can_transient = true,
+
         .status_message_formats = {
                 .starting_stopping = {
                         [0] = "Starting %s...",
diff --git a/src/core/service.h b/src/core/service.h
index 37fa6ff..5c53791 100644
--- a/src/core/service.h
+++ b/src/core/service.h
@@ -130,7 +130,7 @@ struct Service {
 
         dual_timestamp watchdog_timestamp;
         usec_t watchdog_usec;
-        Watch watchdog_watch;
+        sd_event_source *watchdog_event_source;
 
         ExecCommand* exec_command[_SERVICE_EXEC_COMMAND_MAX];
 
@@ -191,7 +191,7 @@ struct Service {
 
         UnitRef accept_socket;
 
-        Watch timer_watch;
+        sd_event_source *timer_event_source;
         PathSpec *pid_file_pathspec;
 
         NotifyAccess notify_access;
diff --git a/src/core/slice.c b/src/core/slice.c
index 40d416e..1e42df2 100644
--- a/src/core/slice.c
+++ b/src/core/slice.c
@@ -216,7 +216,7 @@ static int slice_stop(Unit *u) {
         return 0;
 }
 
-static int slice_kill(Unit *u, KillWho who, int signo, DBusError *error) {
+static int slice_kill(Unit *u, KillWho who, int signo, sd_bus_error *error) {
         return unit_kill_common(u, who, signo, -1, -1, error);
 }
 
@@ -275,13 +275,13 @@ DEFINE_STRING_TABLE_LOOKUP(slice_state, SliceState);
 
 const UnitVTable slice_vtable = {
         .object_size = sizeof(Slice),
+        .cgroup_context_offset = offsetof(Slice, cgroup_context),
+
         .sections =
                 "Unit\0"
                 "Slice\0"
                 "Install\0",
-
         .private_section = "Slice",
-        .cgroup_context_offset = offsetof(Slice, cgroup_context),
 
         .no_alias = true,
         .no_instances = true,
@@ -306,7 +306,7 @@ const UnitVTable slice_vtable = {
         .sub_state_to_string = slice_sub_state_to_string,
 
         .bus_interface = "org.freedesktop.systemd1.Slice",
-        .bus_message_handler = bus_slice_message_handler,
+        .bus_vtable = bus_slice_vtable,
         .bus_set_property = bus_slice_set_property,
         .bus_commit_properties = bus_slice_commit_properties,
 
diff --git a/src/core/snapshot.c b/src/core/snapshot.c
index d11239d..21e89ac 100644
--- a/src/core/snapshot.c
+++ b/src/core/snapshot.c
@@ -189,7 +189,7 @@ _pure_ static const char *snapshot_sub_state_to_string(Unit *u) {
         return snapshot_state_to_string(SNAPSHOT(u)->state);
 }
 
-int snapshot_create(Manager *m, const char *name, bool cleanup, DBusError *e, Snapshot **_s) {
+int snapshot_create(Manager *m, const char *name, bool cleanup, sd_bus_error *e, Snapshot **_s) {
         _cleanup_free_ char *n = NULL;
         Unit *other, *u = NULL;
         Iterator i;
@@ -200,20 +200,14 @@ int snapshot_create(Manager *m, const char *name, bool cleanup, DBusError *e, Sn
         assert(_s);
 
         if (name) {
-                if (!unit_name_is_valid(name, false)) {
-                        dbus_set_error(e, BUS_ERROR_INVALID_NAME, "Unit name %s is not valid.", name);
-                        return -EINVAL;
-                }
+                if (!unit_name_is_valid(name, false))
+                        return sd_bus_error_setf(e, SD_BUS_ERROR_INVALID_ARGS, "Unit name %s is not valid.", name);
 
-                if (unit_name_to_type(name) != UNIT_SNAPSHOT) {
-                        dbus_set_error(e, BUS_ERROR_UNIT_TYPE_MISMATCH, "Unit name %s lacks snapshot suffix.", name);
-                        return -EINVAL;
-                }
+                if (unit_name_to_type(name) != UNIT_SNAPSHOT)
+                        return sd_bus_error_setf(e, SD_BUS_ERROR_INVALID_ARGS, "Unit name %s lacks snapshot suffix.", name);
 
-                if (manager_get_unit(m, name)) {
-                        dbus_set_error(e, BUS_ERROR_UNIT_EXISTS, "Snapshot %s exists already.", name);
-                        return -EEXIST;
-                }
+                if (manager_get_unit(m, name))
+                        sd_bus_error_setf(e, BUS_ERROR_UNIT_EXISTS, "Snapshot %s exists already.", name);
 
         } else {
 
@@ -293,8 +287,8 @@ const UnitVTable snapshot_vtable = {
         .no_gc = true,
 
         .init = snapshot_init,
-
         .load = snapshot_load,
+
         .coldplug = snapshot_coldplug,
 
         .dump = snapshot_dump,
@@ -309,5 +303,5 @@ const UnitVTable snapshot_vtable = {
         .sub_state_to_string = snapshot_sub_state_to_string,
 
         .bus_interface = "org.freedesktop.systemd1.Snapshot",
-        .bus_message_handler = bus_snapshot_message_handler
+        .bus_vtable = bus_snapshot_vtable
 };
diff --git a/src/core/snapshot.h b/src/core/snapshot.h
index 2675b1b..e6dc661 100644
--- a/src/core/snapshot.h
+++ b/src/core/snapshot.h
@@ -42,7 +42,7 @@ struct Snapshot {
 
 extern const UnitVTable snapshot_vtable;
 
-int snapshot_create(Manager *m, const char *name, bool cleanup, DBusError *e, Snapshot **s);
+int snapshot_create(Manager *m, const char *name, bool cleanup, sd_bus_error *e, Snapshot **s);
 void snapshot_remove(Snapshot *s);
 
 const char* snapshot_state_to_string(SnapshotState i) _const_;
diff --git a/src/core/socket.c b/src/core/socket.c
index 751f20b..eae9465 100644
--- a/src/core/socket.c
+++ b/src/core/socket.c
@@ -27,14 +27,15 @@
 #include <sys/epoll.h>
 #include <signal.h>
 #include <arpa/inet.h>
+#include <netinet/tcp.h>
 #include <mqueue.h>
 #ifdef HAVE_XATTR
 #include <attr/xattr.h>
 #endif
 
+#include "sd-event.h"
 #include "unit.h"
 #include "socket.h"
-#include "netinet/tcp.h"
 #include "log.h"
 #include "load-dropin.h"
 #include "load-fragment.h"
@@ -46,11 +47,12 @@
 #include "dbus-socket.h"
 #include "missing.h"
 #include "special.h"
-#include "dbus-common.h"
 #include "label.h"
 #include "exit-status.h"
 #include "def.h"
 #include "smack-util.h"
+#include "bus-util.h"
+#include "bus-error.h"
 
 static const UnitActiveState state_translation_table[_SOCKET_STATE_MAX] = {
         [SOCKET_DEAD] = UNIT_INACTIVE,
@@ -67,6 +69,9 @@ static const UnitActiveState state_translation_table[_SOCKET_STATE_MAX] = {
         [SOCKET_FAILED] = UNIT_FAILED
 };
 
+static int socket_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata);
+static int socket_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata);
+
 static void socket_init(Unit *u) {
         Socket *s = SOCKET(u);
 
@@ -112,10 +117,10 @@ void socket_free_ports(Socket *s) {
         while ((p = s->ports)) {
                 LIST_REMOVE(port, s->ports, p);
 
-                if (p->fd >= 0) {
-                        unit_unwatch_fd(UNIT(s), &p->fd_watch);
+                sd_event_source_unref(p->event_source);
+
+                if (p->fd >= 0)
                         close_nointr_nofail(p->fd);
-                }
 
                 free(p->path);
                 free(p);
@@ -149,7 +154,28 @@ static void socket_done(Unit *u) {
         free(s->smack_ip_in);
         free(s->smack_ip_out);
 
-        unit_unwatch_timer(u, &s->timer_watch);
+        s->timer_event_source = sd_event_source_unref(s->timer_event_source);
+}
+
+static int socket_arm_timer(Socket *s) {
+        int r;
+
+        assert(s);
+
+        if (s->timeout_usec <= 0) {
+                s->timer_event_source = sd_event_source_unref(s->timer_event_source);
+                return 0;
+        }
+
+        if (s->timer_event_source) {
+                r = sd_event_source_set_time(s->timer_event_source, now(CLOCK_MONOTONIC) + s->timeout_usec);
+                if (r < 0)
+                        return r;
+
+                return sd_event_source_set_enabled(s->timer_event_source, SD_EVENT_ONESHOT);
+        }
+
+        return sd_event_add_monotonic(UNIT(s)->manager->event, now(CLOCK_MONOTONIC) + s->timeout_usec, 0, socket_dispatch_timer, s, &s->timer_event_source);
 }
 
 static int socket_instantiate_service(Socket *s) {
@@ -508,10 +534,10 @@ static void socket_dump(Unit *u, FILE *f, const char *prefix) {
                         "%sMessageQueueMessageSize: %li\n",
                         prefix, s->mq_msgsize);
 
-        if (s->reuseport)
+        if (s->reuse_port)
                 fprintf(f,
                         "%sReusePort: %s\n",
-                         prefix, yes_no(s->reuseport));
+                         prefix, yes_no(s->reuse_port));
 
         if (s->smack)
                 fprintf(f,
@@ -673,10 +699,12 @@ static void socket_close_fds(Socket *s) {
         assert(s);
 
         LIST_FOREACH(port, p, s->ports) {
+
+                p->event_source = sd_event_source_unref(p->event_source);
+
                 if (p->fd < 0)
                         continue;
 
-                unit_unwatch_fd(UNIT(s), &p->fd_watch);
                 close_nointr_nofail(p->fd);
 
                 /* One little note: we should never delete any sockets
@@ -769,8 +797,8 @@ static void socket_apply_socket_options(Socket *s, int fd) {
                 if (setsockopt(fd, SOL_TCP, TCP_CONGESTION, s->tcp_congestion, strlen(s->tcp_congestion)+1) < 0)
                         log_warning_unit(UNIT(s)->id, "TCP_CONGESTION failed: %m");
 
-        if (s->reuseport) {
-                int b = s->reuseport;
+        if (s->reuse_port) {
+                int b = s->reuse_port;
                 if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &b, sizeof(b)) < 0)
                         log_warning_unit(UNIT(s)->id, "SO_REUSEPORT failed: %m");
         }
@@ -1054,6 +1082,7 @@ rollback:
 
 static void socket_unwatch_fds(Socket *s) {
         SocketPort *p;
+        int r;
 
         assert(s);
 
@@ -1061,7 +1090,11 @@ static void socket_unwatch_fds(Socket *s) {
                 if (p->fd < 0)
                         continue;
 
-                unit_unwatch_fd(UNIT(s), &p->fd_watch);
+                if (p->event_source) {
+                        r = sd_event_source_set_enabled(p->event_source, SD_EVENT_OFF);
+                        if (r < 0)
+                                log_debug_unit(UNIT(s)->id, "Failed to disable event source.");
+                }
         }
 }
 
@@ -1075,13 +1108,15 @@ static int socket_watch_fds(Socket *s) {
                 if (p->fd < 0)
                         continue;
 
-                p->fd_watch.socket_accept =
-                        s->accept &&
-                        p->type == SOCKET_SOCKET &&
-                        socket_address_can_accept(&p->address);
+                if (p->event_source)
+                        r = sd_event_source_set_enabled(p->event_source, SD_EVENT_ON);
+                else
+                        r = sd_event_add_io(UNIT(s)->manager->event, p->fd, EPOLLIN, socket_dispatch_io, p, &p->event_source);
 
-                if ((r = unit_watch_fd(UNIT(s), p->fd, EPOLLIN, &p->fd_watch)) < 0)
+                if (r < 0) {
+                        log_warning_unit(UNIT(s)->id, "Failed to watch listening fds: %s", strerror(-r));
                         goto fail;
+                }
         }
 
         return 0;
@@ -1106,7 +1141,8 @@ static void socket_set_state(Socket *s, SocketState state) {
             state != SOCKET_STOP_POST &&
             state != SOCKET_FINAL_SIGTERM &&
             state != SOCKET_FINAL_SIGKILL) {
-                unit_unwatch_timer(UNIT(s), &s->timer_watch);
+
+                s->timer_event_source = sd_event_source_unref(s->timer_event_source);
                 socket_unwatch_control_pid(s);
                 s->control_command = NULL;
                 s->control_command_id = _SOCKET_EXEC_COMMAND_INVALID;
@@ -1157,7 +1193,7 @@ static int socket_coldplug(Unit *u) {
                         if (r < 0)
                                 return r;
 
-                        r = unit_watch_timer(UNIT(s), CLOCK_MONOTONIC, true, s->timeout_usec, &s->timer_watch);
+                        r = socket_arm_timer(s);
                         if (r < 0)
                                 return r;
                 }
@@ -1167,13 +1203,17 @@ static int socket_coldplug(Unit *u) {
                     s->deserialized_state == SOCKET_RUNNING ||
                     s->deserialized_state == SOCKET_STOP_PRE ||
                     s->deserialized_state == SOCKET_STOP_PRE_SIGTERM ||
-                    s->deserialized_state == SOCKET_STOP_PRE_SIGKILL)
-                        if ((r = socket_open_fds(s)) < 0)
+                    s->deserialized_state == SOCKET_STOP_PRE_SIGKILL) {
+                        r = socket_open_fds(s);
+                        if (r < 0)
                                 return r;
+                }
 
-                if (s->deserialized_state == SOCKET_LISTENING)
-                        if ((r = socket_watch_fds(s)) < 0)
+                if (s->deserialized_state == SOCKET_LISTENING) {
+                        r = socket_watch_fds(s);
+                        if (r < 0)
                                 return r;
+                }
 
                 socket_set_state(s, s->deserialized_state);
         }
@@ -1192,7 +1232,7 @@ static int socket_spawn(Socket *s, ExecCommand *c, pid_t *_pid) {
 
         unit_realize_cgroup(UNIT(s));
 
-        r = unit_watch_timer(UNIT(s), CLOCK_MONOTONIC, true, s->timeout_usec, &s->timer_watch);
+        r = socket_arm_timer(s);
         if (r < 0)
                 goto fail;
 
@@ -1219,7 +1259,8 @@ static int socket_spawn(Socket *s, ExecCommand *c, pid_t *_pid) {
         if (r < 0)
                 goto fail;
 
-        if ((r = unit_watch_pid(UNIT(s), pid)) < 0)
+        r = unit_watch_pid(UNIT(s), pid);
+        if (r < 0)
                 /* FIXME: we need to do something here */
                 goto fail;
 
@@ -1228,7 +1269,7 @@ static int socket_spawn(Socket *s, ExecCommand *c, pid_t *_pid) {
         return 0;
 
 fail:
-        unit_unwatch_timer(UNIT(s), &s->timer_watch);
+        s->timer_event_source = sd_event_source_unref(s->timer_event_source);
 
         return r;
 }
@@ -1292,7 +1333,7 @@ static void socket_enter_signal(Socket *s, SocketState state, SocketResult f) {
                 goto fail;
 
         if (r > 0) {
-                r = unit_watch_timer(UNIT(s), CLOCK_MONOTONIC, true, s->timeout_usec, &s->timer_watch);
+                r = socket_arm_timer(s);
                 if (r < 0)
                         goto fail;
 
@@ -1423,11 +1464,10 @@ fail:
 }
 
 static void socket_enter_running(Socket *s, int cfd) {
+        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
         int r;
-        DBusError error;
 
         assert(s);
-        dbus_error_init(&error);
 
         /* We don't take connections anymore if we are supposed to
          * shut down anyway */
@@ -1548,13 +1588,11 @@ fail:
                          "%s failed to queue service startup job (Maybe the service file is missing or not a %s unit?): %s",
                          UNIT(s)->id,
                          cfd >= 0 ? "template" : "non-template",
-                         bus_error(&error, r));
+                         bus_error_message(&error, r));
         socket_enter_stop_pre(s, SOCKET_FAILURE_RESOURCES);
 
         if (cfd >= 0)
                 close_nointr_nofail(cfd);
-
-        dbus_error_free(&error);
 }
 
 static void socket_run_next(Socket *s) {
@@ -1952,20 +1990,39 @@ const char* socket_port_type_to_string(SocketPort *p) {
         assert(p);
 
         switch (p->type) {
-                case SOCKET_SOCKET:
-                        switch (p->address.type) {
-                                case SOCK_STREAM: return "Stream";
-                                case SOCK_DGRAM: return "Datagram";
-                                case SOCK_SEQPACKET: return "SequentialPacket";
-                                case SOCK_RAW:
-                                        if (socket_address_family(&p->address) == AF_NETLINK)
-                                                return "Netlink";
-                                default: return "Invalid";
-                        }
-                case SOCKET_SPECIAL: return "Special";
-                case SOCKET_MQUEUE: return "MessageQueue";
-                case SOCKET_FIFO: return "FIFO";
-                default: return NULL;
+
+        case SOCKET_SOCKET:
+
+                switch (p->address.type) {
+
+                case SOCK_STREAM:
+                        return "Stream";
+
+                case SOCK_DGRAM:
+                        return "Datagram";
+
+                case SOCK_SEQPACKET:
+                        return "SequentialPacket";
+
+                case SOCK_RAW:
+                        if (socket_address_family(&p->address) == AF_NETLINK)
+                                return "Netlink";
+
+                default:
+                        return NULL;
+                }
+
+        case SOCKET_SPECIAL:
+                return "Special";
+
+        case SOCKET_MQUEUE:
+                return "MessageQueue";
+
+        case SOCKET_FIFO:
+                return "FIFO";
+
+        default:
+                return NULL;
         }
 }
 
@@ -1977,33 +2034,36 @@ _pure_ static bool socket_check_gc(Unit *u) {
         return s->n_connections > 0;
 }
 
-static void socket_fd_event(Unit *u, int fd, uint32_t events, Watch *w) {
-        Socket *s = SOCKET(u);
+static int socket_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
+        SocketPort *p = userdata;
         int cfd = -1;
 
-        assert(s);
+        assert(p);
         assert(fd >= 0);
 
-        if (s->state != SOCKET_LISTENING)
-                return;
+        if (p->socket->state != SOCKET_LISTENING)
+                return 0;
 
-        log_debug_unit(u->id, "Incoming traffic on %s", u->id);
+        log_debug_unit(UNIT(p->socket)->id, "Incoming traffic on %s", UNIT(p->socket)->id);
 
-        if (events != EPOLLIN) {
+        if (revents != EPOLLIN) {
 
-                if (events & EPOLLHUP)
-                        log_error_unit(u->id,
+                if (revents & EPOLLHUP)
+                        log_error_unit(UNIT(p->socket)->id,
                                        "%s: Got POLLHUP on a listening socket. The service probably invoked shutdown() on it, and should better not do that.",
-                                       u->id);
+                                       UNIT(p->socket)->id);
                 else
-                        log_error_unit(u->id,
+                        log_error_unit(UNIT(p->socket)->id,
                                        "%s: Got unexpected poll event (0x%x) on socket.",
-                                       u->id, events);
+                                       UNIT(p->socket)->id, revents);
 
                 goto fail;
         }
 
-        if (w->socket_accept) {
+        if (p->socket->accept &&
+            p->type == SOCKET_SOCKET &&
+            socket_address_can_accept(&p->address)) {
+
                 for (;;) {
 
                         cfd = accept4(fd, NULL, NULL, SOCK_NONBLOCK);
@@ -2012,7 +2072,7 @@ static void socket_fd_event(Unit *u, int fd, uint32_t events, Watch *w) {
                                 if (errno == EINTR)
                                         continue;
 
-                                log_error_unit(u->id,
+                                log_error_unit(UNIT(p->socket)->id,
                                                "Failed to accept socket: %m");
                                 goto fail;
                         }
@@ -2020,14 +2080,15 @@ static void socket_fd_event(Unit *u, int fd, uint32_t events, Watch *w) {
                         break;
                 }
 
-                socket_apply_socket_options(s, cfd);
+                socket_apply_socket_options(p->socket, cfd);
         }
 
-        socket_enter_running(s, cfd);
-        return;
+        socket_enter_running(p->socket, cfd);
+        return 0;
 
 fail:
-        socket_enter_stop_pre(s, SOCKET_FAILURE_RESOURCES);
+        socket_enter_stop_pre(p->socket, SOCKET_FAILURE_RESOURCES);
+        return 0;
 }
 
 static void socket_sigchld_event(Unit *u, pid_t pid, int code, int status) {
@@ -2124,81 +2185,82 @@ static void socket_sigchld_event(Unit *u, pid_t pid, int code, int status) {
         unit_add_to_dbus_queue(u);
 }
 
-static void socket_timer_event(Unit *u, uint64_t elapsed, Watch *w) {
-        Socket *s = SOCKET(u);
+static int socket_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata) {
+        Socket *s = SOCKET(userdata);
 
         assert(s);
-        assert(elapsed == 1);
-        assert(w == &s->timer_watch);
+        assert(s->timer_event_source == source);
 
         switch (s->state) {
 
         case SOCKET_START_PRE:
-                log_warning_unit(u->id,
-                                 "%s starting timed out. Terminating.", u->id);
+                log_warning_unit(UNIT(s)->id,
+                                 "%s starting timed out. Terminating.", UNIT(s)->id);
                 socket_enter_signal(s, SOCKET_FINAL_SIGTERM, SOCKET_FAILURE_TIMEOUT);
                 break;
 
         case SOCKET_START_POST:
-                log_warning_unit(u->id,
-                                 "%s starting timed out. Stopping.", u->id);
+                log_warning_unit(UNIT(s)->id,
+                                 "%s starting timed out. Stopping.", UNIT(s)->id);
                 socket_enter_stop_pre(s, SOCKET_FAILURE_TIMEOUT);
                 break;
 
         case SOCKET_STOP_PRE:
-                log_warning_unit(u->id,
-                                 "%s stopping timed out. Terminating.", u->id);
+                log_warning_unit(UNIT(s)->id,
+                                 "%s stopping timed out. Terminating.", UNIT(s)->id);
                 socket_enter_signal(s, SOCKET_STOP_PRE_SIGTERM, SOCKET_FAILURE_TIMEOUT);
                 break;
 
         case SOCKET_STOP_PRE_SIGTERM:
                 if (s->kill_context.send_sigkill) {
-                        log_warning_unit(u->id,
-                                         "%s stopping timed out. Killing.", u->id);
+                        log_warning_unit(UNIT(s)->id,
+                                         "%s stopping timed out. Killing.", UNIT(s)->id);
                         socket_enter_signal(s, SOCKET_STOP_PRE_SIGKILL, SOCKET_FAILURE_TIMEOUT);
                 } else {
-                        log_warning_unit(u->id,
+                        log_warning_unit(UNIT(s)->id,
                                          "%s stopping timed out. Skipping SIGKILL. Ignoring.",
-                                         u->id);
+                                         UNIT(s)->id);
                         socket_enter_stop_post(s, SOCKET_FAILURE_TIMEOUT);
                 }
                 break;
 
         case SOCKET_STOP_PRE_SIGKILL:
-                log_warning_unit(u->id,
-                                 "%s still around after SIGKILL. Ignoring.", u->id);
+                log_warning_unit(UNIT(s)->id,
+                                 "%s still around after SIGKILL. Ignoring.", UNIT(s)->id);
                 socket_enter_stop_post(s, SOCKET_FAILURE_TIMEOUT);
                 break;
 
         case SOCKET_STOP_POST:
-                log_warning_unit(u->id,
-                                 "%s stopping timed out (2). Terminating.", u->id);
+                log_warning_unit(UNIT(s)->id,
+                                 "%s stopping timed out (2). Terminating.", UNIT(s)->id);
                 socket_enter_signal(s, SOCKET_FINAL_SIGTERM, SOCKET_FAILURE_TIMEOUT);
                 break;
 
         case SOCKET_FINAL_SIGTERM:
                 if (s->kill_context.send_sigkill) {
-                        log_warning_unit(u->id,
-                                         "%s stopping timed out (2). Killing.", u->id);
+                        log_warning_unit(UNIT(s)->id,
+                                         "%s stopping timed out (2). Killing.", UNIT(s)->id);
                         socket_enter_signal(s, SOCKET_FINAL_SIGKILL, SOCKET_FAILURE_TIMEOUT);
                 } else {
-                        log_warning_unit(u->id,
+                        log_warning_unit(UNIT(s)->id,
                                          "%s stopping timed out (2). Skipping SIGKILL. Ignoring.",
-                                         u->id);
+                                         UNIT(s)->id);
                         socket_enter_dead(s, SOCKET_FAILURE_TIMEOUT);
                 }
                 break;
 
         case SOCKET_FINAL_SIGKILL:
-                log_warning_unit(u->id,
+                log_warning_unit(UNIT(s)->id,
                                  "%s still around after SIGKILL (2). Entering failed mode.",
-                                 u->id);
+                                 UNIT(s)->id);
                 socket_enter_dead(s, SOCKET_FAILURE_TIMEOUT);
                 break;
 
         default:
                 assert_not_reached("Timeout at wrong time.");
         }
+
+        return 0;
 }
 
 int socket_collect_fds(Socket *s, int **fds, unsigned *n_fds) {
@@ -2319,7 +2381,7 @@ static void socket_trigger_notify(Unit *u, Unit *other) {
                 socket_set_state(s, SOCKET_RUNNING);
 }
 
-static int socket_kill(Unit *u, KillWho who, int signo, DBusError *error) {
+static int socket_kill(Unit *u, KillWho who, int signo, sd_bus_error *error) {
         return unit_kill_common(u, who, signo, -1, SOCKET(u)->control_pid, error);
 }
 
@@ -2363,22 +2425,20 @@ DEFINE_STRING_TABLE_LOOKUP(socket_result, SocketResult);
 
 const UnitVTable socket_vtable = {
         .object_size = sizeof(Socket),
+        .exec_context_offset = offsetof(Socket, exec_context),
+        .cgroup_context_offset = offsetof(Socket, cgroup_context),
+        .kill_context_offset = offsetof(Socket, kill_context),
 
         .sections =
                 "Unit\0"
                 "Socket\0"
                 "Install\0",
-
         .private_section = "Socket",
-        .exec_context_offset = offsetof(Socket, exec_context),
-        .cgroup_context_offset = offsetof(Socket, cgroup_context),
 
         .init = socket_init,
         .done = socket_done,
         .load = socket_load,
 
-        .kill = socket_kill,
-
         .coldplug = socket_coldplug,
 
         .dump = socket_dump,
@@ -2386,6 +2446,8 @@ const UnitVTable socket_vtable = {
         .start = socket_start,
         .stop = socket_stop,
 
+        .kill = socket_kill,
+
         .serialize = socket_serialize,
         .deserialize_item = socket_deserialize_item,
         .distribute_fds = socket_distribute_fds,
@@ -2395,17 +2457,15 @@ const UnitVTable socket_vtable = {
 
         .check_gc = socket_check_gc,
 
-        .fd_event = socket_fd_event,
         .sigchld_event = socket_sigchld_event,
-        .timer_event = socket_timer_event,
 
         .trigger_notify = socket_trigger_notify,
 
         .reset_failed = socket_reset_failed,
 
         .bus_interface = "org.freedesktop.systemd1.Socket",
-        .bus_message_handler = bus_socket_message_handler,
-        .bus_invalidating_properties =  bus_socket_invalidating_properties,
+        .bus_vtable = bus_socket_vtable,
+        .bus_changing_properties = bus_socket_changing_properties,
         .bus_set_property = bus_socket_set_property,
         .bus_commit_properties = bus_socket_commit_properties,
 
diff --git a/src/core/socket.h b/src/core/socket.h
index 3d7eadc..db0796c 100644
--- a/src/core/socket.h
+++ b/src/core/socket.h
@@ -77,12 +77,14 @@ typedef enum SocketResult {
 } SocketResult;
 
 typedef struct SocketPort {
+        Socket *socket;
+
         SocketType type;
         int fd;
 
         SocketAddress address;
         char *path;
-        Watch fd_watch;
+        sd_event_source *event_source;
 
         LIST_FIELDS(struct SocketPort, port);
 } SocketPort;
@@ -111,7 +113,7 @@ struct Socket {
 
         SocketState state, deserialized_state;
 
-        Watch timer_watch;
+        sd_event_source *timer_event_source;
 
         ExecCommand* control_command;
         SocketExecCommand control_command_id;
@@ -144,7 +146,7 @@ struct Socket {
         size_t pipe_size;
         char *bind_to_device;
         char *tcp_congestion;
-        bool reuseport;
+        bool reuse_port;
         long mq_maxmsg;
         long mq_msgsize;
 
diff --git a/src/core/swap.c b/src/core/swap.c
index c48c0bd..a798eca 100644
--- a/src/core/swap.c
+++ b/src/core/swap.c
@@ -53,6 +53,9 @@ static const UnitActiveState state_translation_table[_SWAP_STATE_MAX] = {
         [SWAP_FAILED] = UNIT_FAILED
 };
 
+static int swap_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata);
+static int swap_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata);
+
 static void swap_unset_proc_swaps(Swap *s) {
         Swap *first;
         Hashmap *swaps;
@@ -96,8 +99,6 @@ static void swap_init(Unit *u) {
 
         s->parameters_proc_swaps.priority = s->parameters_fragment.priority = -1;
 
-        s->timer_watch.type = WATCH_INVALID;
-
         s->control_command_id = _SWAP_EXEC_COMMAND_INVALID;
 
         UNIT(s)->ignore_on_isolate = true;
@@ -134,7 +135,28 @@ static void swap_done(Unit *u) {
 
         swap_unwatch_control_pid(s);
 
-        unit_unwatch_timer(u, &s->timer_watch);
+        s->timer_event_source = sd_event_source_unref(s->timer_event_source);
+}
+
+static int swap_arm_timer(Swap *s) {
+        int r;
+
+        assert(s);
+
+        if (s->timeout_usec <= 0) {
+                s->timer_event_source = sd_event_source_unref(s->timer_event_source);
+                return 0;
+        }
+
+        if (s->timer_event_source) {
+                r = sd_event_source_set_time(s->timer_event_source, now(CLOCK_MONOTONIC) + s->timeout_usec);
+                if (r < 0)
+                        return r;
+
+                return sd_event_source_set_enabled(s->timer_event_source, SD_EVENT_ONESHOT);
+        }
+
+        return sd_event_add_monotonic(UNIT(s)->manager->event, now(CLOCK_MONOTONIC) + s->timeout_usec, 0, swap_dispatch_timer, s, &s->timer_event_source);
 }
 
 static int swap_add_device_links(Swap *s) {
@@ -465,7 +487,7 @@ static void swap_set_state(Swap *s, SwapState state) {
             state != SWAP_DEACTIVATING &&
             state != SWAP_DEACTIVATING_SIGTERM &&
             state != SWAP_DEACTIVATING_SIGKILL) {
-                unit_unwatch_timer(UNIT(s), &s->timer_watch);
+                s->timer_event_source = sd_event_source_unref(s->timer_event_source);
                 swap_unwatch_control_pid(s);
                 s->control_command = NULL;
                 s->control_command_id = _SWAP_EXEC_COMMAND_INVALID;
@@ -511,7 +533,7 @@ static int swap_coldplug(Unit *u) {
                         if (r < 0)
                                 return r;
 
-                        r = unit_watch_timer(UNIT(s), CLOCK_MONOTONIC, true, s->timeout_usec, &s->timer_watch);
+                        r = swap_arm_timer(s);
                         if (r < 0)
                                 return r;
                 }
@@ -576,7 +598,7 @@ static int swap_spawn(Swap *s, ExecCommand *c, pid_t *_pid) {
 
         unit_realize_cgroup(UNIT(s));
 
-        r = unit_watch_timer(UNIT(s), CLOCK_MONOTONIC, true, s->timeout_usec, &s->timer_watch);
+        r = swap_arm_timer(s);
         if (r < 0)
                 goto fail;
 
@@ -607,7 +629,7 @@ static int swap_spawn(Swap *s, ExecCommand *c, pid_t *_pid) {
         return 0;
 
 fail:
-        unit_unwatch_timer(UNIT(s), &s->timer_watch);
+        s->timer_event_source = sd_event_source_unref(s->timer_event_source);
 
         return r;
 }
@@ -650,7 +672,7 @@ static void swap_enter_signal(Swap *s, SwapState state, SwapResult f) {
                 goto fail;
 
         if (r > 0) {
-                r = unit_watch_timer(UNIT(s), CLOCK_MONOTONIC, true, s->timeout_usec, &s->timer_watch);
+                r = swap_arm_timer(s);
                 if (r < 0)
                         goto fail;
 
@@ -977,54 +999,55 @@ static void swap_sigchld_event(Unit *u, pid_t pid, int code, int status) {
         u->manager->request_reload = true;
 }
 
-static void swap_timer_event(Unit *u, uint64_t elapsed, Watch *w) {
-        Swap *s = SWAP(u);
+static int swap_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata) {
+        Swap *s = SWAP(userdata);
 
         assert(s);
-        assert(elapsed == 1);
-        assert(w == &s->timer_watch);
+        assert(s->timer_event_source == source);
 
         switch (s->state) {
 
         case SWAP_ACTIVATING:
-                log_warning_unit(u->id, "%s activation timed out. Stopping.", u->id);
+                log_warning_unit(UNIT(s)->id, "%s activation timed out. Stopping.", UNIT(s)->id);
                 swap_enter_signal(s, SWAP_ACTIVATING_SIGTERM, SWAP_FAILURE_TIMEOUT);
                 break;
 
         case SWAP_DEACTIVATING:
-                log_warning_unit(u->id, "%s deactivation timed out. Stopping.", u->id);
+                log_warning_unit(UNIT(s)->id, "%s deactivation timed out. Stopping.", UNIT(s)->id);
                 swap_enter_signal(s, SWAP_DEACTIVATING_SIGTERM, SWAP_FAILURE_TIMEOUT);
                 break;
 
         case SWAP_ACTIVATING_SIGTERM:
                 if (s->kill_context.send_sigkill) {
-                        log_warning_unit(u->id, "%s activation timed out. Killing.", u->id);
+                        log_warning_unit(UNIT(s)->id, "%s activation timed out. Killing.", UNIT(s)->id);
                         swap_enter_signal(s, SWAP_ACTIVATING_SIGKILL, SWAP_FAILURE_TIMEOUT);
                 } else {
-                        log_warning_unit(u->id, "%s activation timed out. Skipping SIGKILL. Ignoring.", u->id);
+                        log_warning_unit(UNIT(s)->id, "%s activation timed out. Skipping SIGKILL. Ignoring.", UNIT(s)->id);
                         swap_enter_dead(s, SWAP_FAILURE_TIMEOUT);
                 }
                 break;
 
         case SWAP_DEACTIVATING_SIGTERM:
                 if (s->kill_context.send_sigkill) {
-                        log_warning_unit(u->id, "%s deactivation timed out. Killing.", u->id);
+                        log_warning_unit(UNIT(s)->id, "%s deactivation timed out. Killing.", UNIT(s)->id);
                         swap_enter_signal(s, SWAP_DEACTIVATING_SIGKILL, SWAP_FAILURE_TIMEOUT);
                 } else {
-                        log_warning_unit(u->id, "%s deactivation timed out. Skipping SIGKILL. Ignoring.", u->id);
+                        log_warning_unit(UNIT(s)->id, "%s deactivation timed out. Skipping SIGKILL. Ignoring.", UNIT(s)->id);
                         swap_enter_dead(s, SWAP_FAILURE_TIMEOUT);
                 }
                 break;
 
         case SWAP_ACTIVATING_SIGKILL:
         case SWAP_DEACTIVATING_SIGKILL:
-                log_warning_unit(u->id, "%s swap process still around after SIGKILL. Ignoring.", u->id);
+                log_warning_unit(UNIT(s)->id, "%s swap process still around after SIGKILL. Ignoring.", UNIT(s)->id);
                 swap_enter_dead(s, SWAP_FAILURE_TIMEOUT);
                 break;
 
         default:
                 assert_not_reached("Timeout at wrong time.");
         }
+
+        return 0;
 }
 
 static int swap_load_proc_swaps(Manager *m, bool set_flags) {
@@ -1068,23 +1091,13 @@ static int swap_load_proc_swaps(Manager *m, bool set_flags) {
         return r;
 }
 
-int swap_dispatch_reload(Manager *m) {
-        /* This function should go as soon as the kernel properly notifies us */
-
-        if (_likely_(!m->request_reload))
-                return 0;
-
-        m->request_reload = false;
-
-        return swap_fd_event(m, EPOLLPRI);
-}
-
-int swap_fd_event(Manager *m, int events) {
+static int swap_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
+        Manager *m = userdata;
         Unit *u;
         int r;
 
         assert(m);
-        assert(events & EPOLLPRI);
+        assert(revents & EPOLLPRI);
 
         r = swap_load_proc_swaps(m, true);
         if (r < 0) {
@@ -1212,6 +1225,8 @@ fail:
 static void swap_shutdown(Manager *m) {
         assert(m);
 
+        m->swap_event_source = sd_event_source_unref(m->swap_event_source);
+
         if (m->proc_swaps) {
                 fclose(m->proc_swaps);
                 m->proc_swaps = NULL;
@@ -1226,26 +1241,23 @@ static int swap_enumerate(Manager *m) {
         assert(m);
 
         if (!m->proc_swaps) {
-                struct epoll_event ev = {
-                        .events = EPOLLPRI,
-                        .data.ptr = &m->swap_watch,
-                };
-
                 m->proc_swaps = fopen("/proc/swaps", "re");
                 if (!m->proc_swaps)
-                        return (errno == ENOENT) ? 0 : -errno;
-
-                m->swap_watch.type = WATCH_SWAP;
-                m->swap_watch.fd = fileno(m->proc_swaps);
+                        return errno == ENOENT ? 0 : -errno;
 
-                if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->swap_watch.fd, &ev) < 0)
-                        return -errno;
+                r = sd_event_add_io(m->event, fileno(m->proc_swaps), EPOLLPRI, swap_dispatch_io, m, &m->swap_event_source);
+                if (r < 0)
+                        goto fail;
         }
 
         r = swap_load_proc_swaps(m, false);
         if (r < 0)
-                swap_shutdown(m);
+                goto fail;
+
+        return 0;
 
+fail:
+        swap_shutdown(m);
         return r;
 }
 
@@ -1260,7 +1272,7 @@ static void swap_reset_failed(Unit *u) {
         s->result = SWAP_SUCCESS;
 }
 
-static int swap_kill(Unit *u, KillWho who, int signo, DBusError *error) {
+static int swap_kill(Unit *u, KillWho who, int signo, sd_bus_error *error) {
         return unit_kill_common(u, who, signo, -1, SWAP(u)->control_pid, error);
 }
 
@@ -1298,15 +1310,15 @@ DEFINE_STRING_TABLE_LOOKUP(swap_result, SwapResult);
 
 const UnitVTable swap_vtable = {
         .object_size = sizeof(Swap),
+        .exec_context_offset = offsetof(Swap, exec_context),
+        .cgroup_context_offset = offsetof(Swap, cgroup_context),
+        .kill_context_offset = offsetof(Swap, kill_context),
 
         .sections =
                 "Unit\0"
                 "Swap\0"
                 "Install\0",
-
         .private_section = "Swap",
-        .exec_context_offset = offsetof(Swap, exec_context),
-        .cgroup_context_offset = offsetof(Swap, cgroup_context),
 
         .no_alias = true,
         .no_instances = true,
@@ -1333,13 +1345,12 @@ const UnitVTable swap_vtable = {
         .check_gc = swap_check_gc,
 
         .sigchld_event = swap_sigchld_event,
-        .timer_event = swap_timer_event,
 
         .reset_failed = swap_reset_failed,
 
         .bus_interface = "org.freedesktop.systemd1.Swap",
-        .bus_message_handler = bus_swap_message_handler,
-        .bus_invalidating_properties =  bus_swap_invalidating_properties,
+        .bus_vtable = bus_swap_vtable,
+        .bus_changing_properties = bus_swap_changing_properties,
         .bus_set_property = bus_swap_set_property,
         .bus_commit_properties = bus_swap_commit_properties,
 
diff --git a/src/core/swap.h b/src/core/swap.h
index dd89535..c51c55f 100644
--- a/src/core/swap.h
+++ b/src/core/swap.h
@@ -96,7 +96,7 @@ struct Swap {
         SwapExecCommand control_command_id;
         pid_t control_pid;
 
-        Watch timer_watch;
+        sd_event_source *timer_event_source;
 
         /* In order to be able to distinguish dependencies on
         different device nodes we might end up creating multiple
@@ -107,9 +107,6 @@ struct Swap {
 
 extern const UnitVTable swap_vtable;
 
-int swap_dispatch_reload(Manager *m);
-int swap_fd_event(Manager *m, int events);
-
 const char* swap_state_to_string(SwapState i) _const_;
 SwapState swap_state_from_string(const char *s) _pure_;
 
diff --git a/src/core/target.c b/src/core/target.c
index 3fffa0d..68be22b 100644
--- a/src/core/target.c
+++ b/src/core/target.c
@@ -205,6 +205,7 @@ DEFINE_STRING_TABLE_LOOKUP(target_state, TargetState);
 
 const UnitVTable target_vtable = {
         .object_size = sizeof(Target),
+
         .sections =
                 "Unit\0"
                 "Target\0"
@@ -225,7 +226,7 @@ const UnitVTable target_vtable = {
         .sub_state_to_string = target_sub_state_to_string,
 
         .bus_interface = "org.freedesktop.systemd1.Target",
-        .bus_message_handler = bus_target_message_handler,
+        .bus_vtable = bus_target_vtable,
 
         .status_message_formats = {
                 .finished_start_job = {
diff --git a/src/core/timer.c b/src/core/timer.c
index b90c85f..5bc01a2 100644
--- a/src/core/timer.c
+++ b/src/core/timer.c
@@ -26,7 +26,8 @@
 #include "timer.h"
 #include "dbus-timer.h"
 #include "special.h"
-#include "dbus-common.h"
+#include "bus-util.h"
+#include "bus-error.h"
 
 static const UnitActiveState state_translation_table[_TIMER_STATE_MAX] = {
         [TIMER_DEAD] = UNIT_INACTIVE,
@@ -36,6 +37,8 @@ static const UnitActiveState state_translation_table[_TIMER_STATE_MAX] = {
         [TIMER_FAILED] = UNIT_FAILED
 };
 
+static int timer_dispatch(sd_event_source *s, uint64_t usec, void *userdata);
+
 static void timer_init(Unit *u) {
         Timer *t = TIMER(u);
 
@@ -44,8 +47,6 @@ static void timer_init(Unit *u) {
 
         t->next_elapse_monotonic = (usec_t) -1;
         t->next_elapse_realtime = (usec_t) -1;
-        watch_init(&t->monotonic_watch);
-        watch_init(&t->realtime_watch);
 }
 
 void timer_free_values(Timer *t) {
@@ -70,8 +71,8 @@ static void timer_done(Unit *u) {
 
         timer_free_values(t);
 
-        unit_unwatch_timer(u, &t->monotonic_watch);
-        unit_unwatch_timer(u, &t->realtime_watch);
+        t->monotonic_event_source = sd_event_source_unref(t->monotonic_event_source);
+        t->realtime_event_source = sd_event_source_unref(t->realtime_event_source);
 }
 
 static int timer_verify(Timer *t) {
@@ -189,8 +190,8 @@ static void timer_set_state(Timer *t, TimerState state) {
         t->state = state;
 
         if (state != TIMER_WAITING) {
-                unit_unwatch_timer(UNIT(t), &t->monotonic_watch);
-                unit_unwatch_timer(UNIT(t), &t->realtime_watch);
+                t->monotonic_event_source = sd_event_source_unref(t->monotonic_event_source);
+                t->realtime_event_source = sd_event_source_unref(t->realtime_event_source);
         }
 
         if (state != old_state)
@@ -230,6 +231,7 @@ static void timer_enter_dead(Timer *t, TimerResult f) {
         timer_set_state(t, t->result != TIMER_SUCCESS ? TIMER_FAILED : TIMER_DEAD);
 }
 
+
 static void timer_enter_waiting(Timer *t, bool initial) {
         TimerValue *v;
         usec_t base = 0;
@@ -337,11 +339,24 @@ static void timer_enter_waiting(Timer *t, bool initial) {
                                UNIT(t)->id,
                                format_timespan(buf, sizeof(buf), t->next_elapse_monotonic > ts.monotonic ? t->next_elapse_monotonic - ts.monotonic : 0, 0));
 
-                r = unit_watch_timer(UNIT(t), CLOCK_MONOTONIC, false, t->next_elapse_monotonic, &t->monotonic_watch);
+                if (t->monotonic_event_source) {
+                        r = sd_event_source_set_time(t->monotonic_event_source, t->next_elapse_monotonic);
+                        if (r < 0)
+                                goto fail;
+
+                        r = sd_event_source_set_enabled(t->monotonic_event_source, SD_EVENT_ONESHOT);
+                } else
+                        r = sd_event_add_monotonic(UNIT(t)->manager->event, t->next_elapse_monotonic, 0, timer_dispatch, t, &t->monotonic_event_source);
+
                 if (r < 0)
                         goto fail;
-        } else
-                unit_unwatch_timer(UNIT(t), &t->monotonic_watch);
+
+        } else if (t->monotonic_event_source) {
+                r = sd_event_source_set_enabled(t->monotonic_event_source, SD_EVENT_OFF);
+
+                if (r < 0)
+                        goto fail;
+        }
 
         if (found_realtime) {
                 char buf[FORMAT_TIMESTAMP_MAX];
@@ -350,11 +365,24 @@ static void timer_enter_waiting(Timer *t, bool initial) {
                                UNIT(t)->id,
                                format_timestamp(buf, sizeof(buf), t->next_elapse_realtime));
 
-                r = unit_watch_timer(UNIT(t), CLOCK_REALTIME, false, t->next_elapse_realtime, &t->realtime_watch);
+                if (t->realtime_event_source) {
+                        r = sd_event_source_set_time(t->realtime_event_source, t->next_elapse_realtime);
+                        if (r < 0)
+                                goto fail;
+
+                        r = sd_event_source_set_enabled(t->realtime_event_source, SD_EVENT_ONESHOT);
+                } else
+                        r = sd_event_add_realtime(UNIT(t)->manager->event, t->next_elapse_realtime, 0, timer_dispatch, t, &t->realtime_event_source);
+
                 if (r < 0)
                         goto fail;
-        } else
-                unit_unwatch_timer(UNIT(t), &t->realtime_watch);
+
+        } else if (t->realtime_event_source) {
+                r = sd_event_source_set_enabled(t->realtime_event_source, SD_EVENT_OFF);
+
+                if (r < 0)
+                        goto fail;
+        }
 
         timer_set_state(t, TIMER_WAITING);
         return;
@@ -367,11 +395,10 @@ fail:
 }
 
 static void timer_enter_running(Timer *t) {
-        DBusError error;
+        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
         int r;
 
         assert(t);
-        dbus_error_init(&error);
 
         /* Don't start job if we are supposed to go down */
         if (unit_stop_pending(UNIT(t)))
@@ -390,10 +417,8 @@ static void timer_enter_running(Timer *t) {
 fail:
         log_warning_unit(UNIT(t)->id,
                          "%s failed to queue unit startup job: %s",
-                         UNIT(t)->id, bus_error(&error, r));
+                         UNIT(t)->id, bus_error_message(&error, r));
         timer_enter_dead(t, TIMER_FAILURE_RESOURCES);
-
-        dbus_error_free(&error);
 }
 
 static int timer_start(Unit *u) {
@@ -476,17 +501,17 @@ _pure_ static const char *timer_sub_state_to_string(Unit *u) {
         return timer_state_to_string(TIMER(u)->state);
 }
 
-static void timer_timer_event(Unit *u, uint64_t elapsed, Watch *w) {
-        Timer *t = TIMER(u);
+static int timer_dispatch(sd_event_source *s, uint64_t usec, void *userdata) {
+        Timer *t = TIMER(userdata);
 
         assert(t);
-        assert(elapsed == 1);
 
         if (t->state != TIMER_WAITING)
-                return;
+                return 0;
 
-        log_debug_unit(u->id, "Timer elapsed on %s", u->id);
+        log_debug_unit(UNIT(t)->id, "Timer elapsed on %s", UNIT(t)->id);
         timer_enter_running(t);
+        return 0;
 }
 
 static void timer_trigger_notify(Unit *u, Unit *other) {
@@ -587,6 +612,7 @@ DEFINE_STRING_TABLE_LOOKUP(timer_result, TimerResult);
 
 const UnitVTable timer_vtable = {
         .object_size = sizeof(Timer),
+
         .sections =
                 "Unit\0"
                 "Timer\0"
@@ -609,14 +635,12 @@ const UnitVTable timer_vtable = {
         .active_state = timer_active_state,
         .sub_state_to_string = timer_sub_state_to_string,
 
-        .timer_event = timer_timer_event,
-
         .trigger_notify = timer_trigger_notify,
 
         .reset_failed = timer_reset_failed,
         .time_change = timer_time_change,
 
         .bus_interface = "org.freedesktop.systemd1.Timer",
-        .bus_message_handler = bus_timer_message_handler,
-        .bus_invalidating_properties =  bus_timer_invalidating_properties
+        .bus_vtable = bus_timer_vtable,
+        .bus_changing_properties = bus_timer_changing_properties,
 };
diff --git a/src/core/timer.h b/src/core/timer.h
index 4168553..b3722f0 100644
--- a/src/core/timer.h
+++ b/src/core/timer.h
@@ -75,8 +75,8 @@ struct Timer {
 
         TimerState state, deserialized_state;
 
-        Watch monotonic_watch;
-        Watch realtime_watch;
+        sd_event_source *monotonic_event_source;
+        sd_event_source *realtime_event_source;
 
         TimerResult result;
 
diff --git a/src/core/transaction.c b/src/core/transaction.c
index ba7d8d9..e2ff0bd 100644
--- a/src/core/transaction.c
+++ b/src/core/transaction.c
@@ -22,9 +22,10 @@
 #include <unistd.h>
 #include <fcntl.h>
 
-#include "transaction.h"
 #include "bus-errors.h"
-#include "dbus-common.h"
+#include "bus-util.h"
+#include "bus-error.h"
+#include "transaction.h"
 
 static void transaction_unlink_job(Transaction *tr, Job *j, bool delete_dependencies);
 
@@ -231,7 +232,7 @@ static int delete_one_unmergeable_job(Transaction *tr, Job *j) {
         return -EINVAL;
 }
 
-static int transaction_merge_jobs(Transaction *tr, DBusError *e) {
+static int transaction_merge_jobs(Transaction *tr, sd_bus_error *e) {
         Job *j;
         Iterator i;
         int r;
@@ -261,8 +262,9 @@ static int transaction_merge_jobs(Transaction *tr, DBusError *e) {
                                 return -EAGAIN;
 
                         /* We couldn't merge anything. Failure */
-                        dbus_set_error(e, BUS_ERROR_TRANSACTION_JOBS_CONFLICTING, "Transaction contains conflicting jobs '%s' and '%s' for %s. Probably contradicting requirement dependencies configured.",
-                                       job_type_to_string(t), job_type_to_string(k->type), k->unit->id);
+                        sd_bus_error_setf(
+                                        e, BUS_ERROR_TRANSACTION_JOBS_CONFLICTING, "Transaction contains conflicting jobs '%s' and '%s' for %s. Probably contradicting requirement dependencies configured.",
+                                        job_type_to_string(t), job_type_to_string(k->type), k->unit->id);
                         return r;
                 }
         }
@@ -334,7 +336,7 @@ _pure_ static bool unit_matters_to_anchor(Unit *u, Job *j) {
         return false;
 }
 
-static int transaction_verify_order_one(Transaction *tr, Job *j, Job *from, unsigned generation, DBusError *e) {
+static int transaction_verify_order_one(Transaction *tr, Job *j, Job *from, unsigned generation, sd_bus_error *e) {
         Iterator i;
         Unit *u;
         int r;
@@ -405,8 +407,8 @@ static int transaction_verify_order_one(Transaction *tr, Job *j, Job *from, unsi
 
                 log_error("Unable to break cycle");
 
-                dbus_set_error(e, BUS_ERROR_TRANSACTION_ORDER_IS_CYCLIC,
-                               "Transaction order is cyclic. See system logs for details.");
+                sd_bus_error_setf(e, BUS_ERROR_TRANSACTION_ORDER_IS_CYCLIC,
+                                  "Transaction order is cyclic. See system logs for details.");
                 return -ENOEXEC;
         }
 
@@ -445,7 +447,7 @@ static int transaction_verify_order_one(Transaction *tr, Job *j, Job *from, unsi
         return 0;
 }
 
-static int transaction_verify_order(Transaction *tr, unsigned *generation, DBusError *e) {
+static int transaction_verify_order(Transaction *tr, unsigned *generation, sd_bus_error *e) {
         Job *j;
         int r;
         Iterator i;
@@ -490,7 +492,7 @@ rescan:
         }
 }
 
-static int transaction_is_destructive(Transaction *tr, JobMode mode, DBusError *e) {
+static int transaction_is_destructive(Transaction *tr, JobMode mode, sd_bus_error *e) {
         Iterator i;
         Job *j;
 
@@ -508,7 +510,7 @@ static int transaction_is_destructive(Transaction *tr, JobMode mode, DBusError *
                 if (j->unit->job && (mode == JOB_FAIL || j->unit->job->irreversible) &&
                     !job_type_is_superset(j->type, j->unit->job->type)) {
 
-                        dbus_set_error(e, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE, "Transaction is destructive.");
+                        sd_bus_error_setf(e, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE, "Transaction is destructive.");
                         return -EEXIST;
                 }
         }
@@ -635,7 +637,7 @@ rollback:
         return r;
 }
 
-int transaction_activate(Transaction *tr, Manager *m, JobMode mode, DBusError *e) {
+int transaction_activate(Transaction *tr, Manager *m, JobMode mode, sd_bus_error *e) {
         Iterator i;
         Job *j;
         int r;
@@ -677,7 +679,7 @@ int transaction_activate(Transaction *tr, Manager *m, JobMode mode, DBusError *e
                         break;
 
                 if (r != -EAGAIN) {
-                        log_warning("Requested transaction contains an unfixable cyclic ordering dependency: %s", bus_error(e, r));
+                        log_warning("Requested transaction contains an unfixable cyclic ordering dependency: %s", bus_error_message(e, r));
                         return r;
                 }
 
@@ -694,7 +696,7 @@ int transaction_activate(Transaction *tr, Manager *m, JobMode mode, DBusError *e
                         break;
 
                 if (r != -EAGAIN) {
-                        log_warning("Requested transaction contains unmergeable jobs: %s", bus_error(e, r));
+                        log_warning("Requested transaction contains unmergeable jobs: %s", bus_error_message(e, r));
                         return r;
                 }
 
@@ -713,7 +715,7 @@ int transaction_activate(Transaction *tr, Manager *m, JobMode mode, DBusError *e
         /* Ninth step: check whether we can actually apply this */
         r = transaction_is_destructive(tr, mode, e);
         if (r < 0) {
-                log_notice("Requested transaction contradicts existing jobs: %s", bus_error(e, r));
+                log_notice("Requested transaction contradicts existing jobs: %s", bus_error_message(e, r));
                 return r;
         }
 
@@ -835,7 +837,7 @@ int transaction_add_job_and_dependencies(
                 bool conflicts,
                 bool ignore_requirements,
                 bool ignore_order,
-                DBusError *e) {
+                sd_bus_error *e) {
         Job *ret;
         Iterator i;
         Unit *dep;
@@ -856,12 +858,12 @@ int transaction_add_job_and_dependencies(
             unit->load_state != UNIT_ERROR &&
             unit->load_state != UNIT_NOT_FOUND &&
             unit->load_state != UNIT_MASKED) {
-                dbus_set_error(e, BUS_ERROR_LOAD_FAILED, "Unit %s is not loaded properly.", unit->id);
+                sd_bus_error_setf(e, BUS_ERROR_LOAD_FAILED, "Unit %s is not loaded properly.", unit->id);
                 return -EINVAL;
         }
 
         if (type != JOB_STOP && unit->load_state == UNIT_ERROR) {
-                dbus_set_error(e, BUS_ERROR_LOAD_FAILED,
+                sd_bus_error_setf(e, BUS_ERROR_LOAD_FAILED,
                                "Unit %s failed to load: %s. "
                                "See system logs and 'systemctl status %s' for details.",
                                unit->id,
@@ -871,7 +873,7 @@ int transaction_add_job_and_dependencies(
         }
 
         if (type != JOB_STOP && unit->load_state == UNIT_NOT_FOUND) {
-                dbus_set_error(e, BUS_ERROR_LOAD_FAILED,
+                sd_bus_error_setf(e, BUS_ERROR_LOAD_FAILED,
                                "Unit %s failed to load: %s.",
                                unit->id,
                                strerror(-unit->load_error));
@@ -879,12 +881,12 @@ int transaction_add_job_and_dependencies(
         }
 
         if (type != JOB_STOP && unit->load_state == UNIT_MASKED) {
-                dbus_set_error(e, BUS_ERROR_MASKED, "Unit %s is masked.", unit->id);
+                sd_bus_error_setf(e, BUS_ERROR_UNIT_MASKED, "Unit %s is masked.", unit->id);
                 return -EADDRNOTAVAIL;
         }
 
         if (!unit_job_is_applicable(unit, type)) {
-                dbus_set_error(e, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE, "Job type %s is not applicable for unit %s.", job_type_to_string(type), unit->id);
+                sd_bus_error_setf(e, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE, "Job type %s is not applicable for unit %s.", job_type_to_string(type), unit->id);
                 return -EBADR;
         }
 
@@ -916,10 +918,10 @@ int transaction_add_job_and_dependencies(
                                 if (r < 0) {
                                         log_warning_unit(dep->id,
                                                          "Cannot add dependency job for unit %s, ignoring: %s",
-                                                         dep->id, bus_error(e, r));
+                                                         dep->id, bus_error_message(e, r));
 
                                         if (e)
-                                                dbus_error_free(e);
+                                                sd_bus_error_free(e);
                                 }
                         }
 
@@ -935,7 +937,7 @@ int transaction_add_job_and_dependencies(
                                                 goto fail;
 
                                         if (e)
-                                                dbus_error_free(e);
+                                                sd_bus_error_free(e);
                                 }
                         }
 
@@ -946,7 +948,7 @@ int transaction_add_job_and_dependencies(
                                                 goto fail;
 
                                         if (e)
-                                                dbus_error_free(e);
+                                                sd_bus_error_free(e);
                                 }
                         }
 
@@ -955,10 +957,10 @@ int transaction_add_job_and_dependencies(
                                 if (r < 0) {
                                         log_full_unit(r == -EADDRNOTAVAIL ? LOG_DEBUG : LOG_WARNING, dep->id,
                                                       "Cannot add dependency job for unit %s, ignoring: %s",
-                                                      dep->id, bus_error(e, r));
+                                                      dep->id, bus_error_message(e, r));
 
                                         if (e)
-                                                dbus_error_free(e);
+                                                sd_bus_error_free(e);
                                 }
                         }
 
@@ -967,10 +969,10 @@ int transaction_add_job_and_dependencies(
                                 if (r < 0) {
                                         log_full_unit(r == -EADDRNOTAVAIL ? LOG_DEBUG : LOG_WARNING, dep->id,
                                                       "Cannot add dependency job for unit %s, ignoring: %s",
-                                                      dep->id, bus_error(e, r));
+                                                      dep->id, bus_error_message(e, r));
 
                                         if (e)
-                                                dbus_error_free(e);
+                                                sd_bus_error_free(e);
                                 }
                         }
 
@@ -981,7 +983,7 @@ int transaction_add_job_and_dependencies(
                                                 goto fail;
 
                                         if (e)
-                                                dbus_error_free(e);
+                                                sd_bus_error_free(e);
                                 }
                         }
 
@@ -990,10 +992,10 @@ int transaction_add_job_and_dependencies(
                                 if (r < 0) {
                                         log_full_unit(r == -EADDRNOTAVAIL ? LOG_DEBUG : LOG_WARNING, dep->id,
                                                       "Cannot add dependency job for unit %s, ignoring: %s",
-                                                      dep->id, bus_error(e, r));
+                                                      dep->id, bus_error_message(e, r));
 
                                         if (e)
-                                                dbus_error_free(e);
+                                                sd_bus_error_free(e);
                                 }
                         }
 
@@ -1004,7 +1006,7 @@ int transaction_add_job_and_dependencies(
                                                 goto fail;
 
                                         if (e)
-                                                dbus_error_free(e);
+                                                sd_bus_error_free(e);
                                 }
                         }
 
@@ -1013,10 +1015,10 @@ int transaction_add_job_and_dependencies(
                                 if (r < 0) {
                                         log_warning_unit(dep->id,
                                                          "Cannot add dependency job for unit %s, ignoring: %s",
-                                                         dep->id, bus_error(e, r));
+                                                         dep->id, bus_error_message(e, r));
 
                                         if (e)
-                                                dbus_error_free(e);
+                                                sd_bus_error_free(e);
                                 }
                         }
 
@@ -1031,7 +1033,7 @@ int transaction_add_job_and_dependencies(
                                                 goto fail;
 
                                         if (e)
-                                                dbus_error_free(e);
+                                                sd_bus_error_free(e);
                                 }
                         }
 
@@ -1042,7 +1044,7 @@ int transaction_add_job_and_dependencies(
                                                 goto fail;
 
                                         if (e)
-                                                dbus_error_free(e);
+                                                sd_bus_error_free(e);
                                 }
                         }
 
@@ -1053,7 +1055,7 @@ int transaction_add_job_and_dependencies(
                                                 goto fail;
 
                                         if (e)
-                                                dbus_error_free(e);
+                                                sd_bus_error_free(e);
                                 }
                         }
 
@@ -1066,10 +1068,10 @@ int transaction_add_job_and_dependencies(
                                 if (r < 0) {
                                         log_warning_unit(dep->id,
                                                          "Cannot add dependency reload job for unit %s, ignoring: %s",
-                                                         dep->id, bus_error(e, r));
+                                                         dep->id, bus_error_message(e, r));
 
                                         if (e)
-                                                dbus_error_free(e);
+                                                sd_bus_error_free(e);
                                 }
                         }
                 }
diff --git a/src/core/transaction.h b/src/core/transaction.h
index b6ee237..d949b21 100644
--- a/src/core/transaction.h
+++ b/src/core/transaction.h
@@ -48,7 +48,7 @@ int transaction_add_job_and_dependencies(
                 bool conflicts,
                 bool ignore_requirements,
                 bool ignore_order,
-                DBusError *e);
-int transaction_activate(Transaction *tr, Manager *m, JobMode mode, DBusError *e);
+                sd_bus_error *e);
+int transaction_activate(Transaction *tr, Manager *m, JobMode mode, sd_bus_error *e);
 int transaction_add_isolate_jobs(Transaction *tr, Manager *m);
 void transaction_abort(Transaction *tr);
diff --git a/src/core/unit.c b/src/core/unit.c
index 7f463f3..1173f0b 100644
--- a/src/core/unit.c
+++ b/src/core/unit.c
@@ -29,8 +29,8 @@
 #include <unistd.h>
 #include <sys/stat.h>
 
-#include "systemd/sd-id128.h"
-#include "systemd/sd-messages.h"
+#include "sd-id128.h"
+#include "sd-messages.h"
 #include "set.h"
 #include "unit.h"
 #include "macro.h"
@@ -48,6 +48,7 @@
 #include "label.h"
 #include "fileio-label.h"
 #include "bus-errors.h"
+#include "dbus.h"
 
 const UnitVTable * const unit_vtable[_UNIT_TYPE_MAX] = {
         [UNIT_SERVICE] = &service_vtable,
@@ -326,7 +327,7 @@ void unit_add_to_dbus_queue(Unit *u) {
                 return;
 
         /* Shortcut things if nobody cares */
-        if (!bus_has_subscriber(u->manager)) {
+        if (set_isempty(u->manager->subscribed)) {
                 u->sent_dbus_new_signal = true;
                 return;
         }
@@ -1658,46 +1659,6 @@ void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, bool reload_su
         unit_add_to_gc_queue(u);
 }
 
-int unit_watch_fd(Unit *u, int fd, uint32_t events, Watch *w) {
-        struct epoll_event ev = {
-                .data.ptr = w,
-                .events = events,
-        };
-
-        assert(u);
-        assert(fd >= 0);
-        assert(w);
-        assert(w->type == WATCH_INVALID || (w->type == WATCH_FD && w->fd == fd && w->data.unit == u));
-
-        if (epoll_ctl(u->manager->epoll_fd,
-                      w->type == WATCH_INVALID ? EPOLL_CTL_ADD : EPOLL_CTL_MOD,
-                      fd,
-                      &ev) < 0)
-                return -errno;
-
-        w->fd = fd;
-        w->type = WATCH_FD;
-        w->data.unit = u;
-
-        return 0;
-}
-
-void unit_unwatch_fd(Unit *u, Watch *w) {
-        assert(u);
-        assert(w);
-
-        if (w->type == WATCH_INVALID)
-                return;
-
-        assert(w->type == WATCH_FD);
-        assert(w->data.unit == u);
-        assert_se(epoll_ctl(u->manager->epoll_fd, EPOLL_CTL_DEL, w->fd, NULL) >= 0);
-
-        w->fd = -1;
-        w->type = WATCH_INVALID;
-        w->data.unit = NULL;
-}
-
 int unit_watch_pid(Unit *u, pid_t pid) {
         assert(u);
         assert(pid >= 1);
@@ -1715,90 +1676,6 @@ void unit_unwatch_pid(Unit *u, pid_t pid) {
         hashmap_remove_value(u->manager->watch_pids, LONG_TO_PTR(pid), u);
 }
 
-int unit_watch_timer(Unit *u, clockid_t clock_id, bool relative, usec_t usec, Watch *w) {
-        struct itimerspec its = {};
-        int flags, fd;
-        bool ours;
-
-        assert(u);
-        assert(w);
-        assert(w->type == WATCH_INVALID || (w->type == WATCH_UNIT_TIMER && w->data.unit == u));
-
-        /* This will try to reuse the old timer if there is one */
-
-        if (w->type == WATCH_UNIT_TIMER) {
-                assert(w->data.unit == u);
-                assert(w->fd >= 0);
-
-                ours = false;
-                fd = w->fd;
-        } else if (w->type == WATCH_INVALID) {
-
-                ours = true;
-                fd = timerfd_create(clock_id, TFD_NONBLOCK|TFD_CLOEXEC);
-                if (fd < 0)
-                        return -errno;
-        } else
-                assert_not_reached("Invalid watch type");
-
-        if (usec <= 0) {
-                /* Set absolute time in the past, but not 0, since we
-                 * don't want to disarm the timer */
-                its.it_value.tv_sec = 0;
-                its.it_value.tv_nsec = 1;
-
-                flags = TFD_TIMER_ABSTIME;
-        } else {
-                timespec_store(&its.it_value, usec);
-                flags = relative ? 0 : TFD_TIMER_ABSTIME;
-        }
-
-        /* This will also flush the elapse counter */
-        if (timerfd_settime(fd, flags, &its, NULL) < 0)
-                goto fail;
-
-        if (w->type == WATCH_INVALID) {
-                struct epoll_event ev = {
-                        .data.ptr = w,
-                        .events = EPOLLIN,
-                };
-
-                if (epoll_ctl(u->manager->epoll_fd, EPOLL_CTL_ADD, fd, &ev) < 0)
-                        goto fail;
-        }
-
-        w->type = WATCH_UNIT_TIMER;
-        w->fd = fd;
-        w->data.unit = u;
-
-        return 0;
-
-fail:
-        if (ours)
-                close_nointr_nofail(fd);
-
-        return -errno;
-}
-
-void unit_unwatch_timer(Unit *u, Watch *w) {
-        assert(u);
-        assert(w);
-
-        if (w->type == WATCH_INVALID)
-                return;
-
-        assert(w->type == WATCH_UNIT_TIMER);
-        assert(w->data.unit == u);
-        assert(w->fd >= 0);
-
-        assert_se(epoll_ctl(u->manager->epoll_fd, EPOLL_CTL_DEL, w->fd, NULL) >= 0);
-        close_nointr_nofail(w->fd);
-
-        w->fd = -1;
-        w->type = WATCH_INVALID;
-        w->data.unit = NULL;
-}
-
 bool unit_job_is_applicable(Unit *u, JobType j) {
         assert(u);
         assert(j >= 0 && j < _JOB_TYPE_MAX);
@@ -2572,7 +2449,7 @@ bool unit_active_or_pending(Unit *u) {
         return false;
 }
 
-int unit_kill(Unit *u, KillWho w, int signo, DBusError *error) {
+int unit_kill(Unit *u, KillWho w, int signo, sd_bus_error *error) {
         assert(u);
         assert(w >= 0 && w < _KILL_WHO_MAX);
         assert(signo > 0);
@@ -2618,23 +2495,23 @@ int unit_kill_common(
                 int signo,
                 pid_t main_pid,
                 pid_t control_pid,
-                DBusError *error) {
+                sd_bus_error *error) {
 
         int r = 0;
 
         if (who == KILL_MAIN && main_pid <= 0) {
                 if (main_pid < 0)
-                        dbus_set_error(error, BUS_ERROR_NO_SUCH_PROCESS, "%s units have no main processes", unit_type_to_string(u->type));
+                        sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_PROCESS, "%s units have no main processes", unit_type_to_string(u->type));
                 else
-                        dbus_set_error(error, BUS_ERROR_NO_SUCH_PROCESS, "No main process to kill");
+                        sd_bus_error_set_const(error, BUS_ERROR_NO_SUCH_PROCESS, "No main process to kill");
                 return -ESRCH;
         }
 
         if (who == KILL_CONTROL && control_pid <= 0) {
                 if (control_pid < 0)
-                        dbus_set_error(error, BUS_ERROR_NO_SUCH_PROCESS, "%s units have no control processes", unit_type_to_string(u->type));
+                        sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_PROCESS, "%s units have no control processes", unit_type_to_string(u->type));
                 else
-                        dbus_set_error(error, BUS_ERROR_NO_SUCH_PROCESS, "No control process to kill");
+                        sd_bus_error_set_const(error, BUS_ERROR_NO_SUCH_PROCESS, "No control process to kill");
                 return -ESRCH;
         }
 
@@ -2746,6 +2623,17 @@ ExecContext *unit_get_exec_context(Unit *u) {
         return (ExecContext*) ((uint8_t*) u + offset);
 }
 
+KillContext *unit_get_kill_context(Unit *u) {
+        size_t offset;
+        assert(u);
+
+        offset = UNIT_VTABLE(u)->kill_context_offset;
+        if (offset <= 0)
+                return NULL;
+
+        return (KillContext*) ((uint8_t*) u + offset);
+}
+
 CGroupContext *unit_get_cgroup_context(Unit *u) {
         size_t offset;
 
diff --git a/src/core/unit.h b/src/core/unit.h
index 1a55842..c58202b 100644
--- a/src/core/unit.h
+++ b/src/core/unit.h
@@ -32,6 +32,7 @@ typedef enum UnitDependency UnitDependency;
 typedef struct UnitRef UnitRef;
 typedef struct UnitStatusMessageFormats UnitStatusMessageFormats;
 
+#include "sd-event.h"
 #include "set.h"
 #include "util.h"
 #include "list.h"
@@ -295,6 +296,10 @@ struct UnitVTable {
          * CGroupContext is found, if the unit type has that */
         size_t cgroup_context_offset;
 
+        /* If greater than 0, the offset into the object where
+         * KillContext is found, if the unit type has that */
+        size_t kill_context_offset;
+
         /* The name of the configuration file section with the private settings of this unit*/
         const char *private_section;
 
@@ -327,7 +332,7 @@ struct UnitVTable {
         int (*stop)(Unit *u);
         int (*reload)(Unit *u);
 
-        int (*kill)(Unit *u, KillWho w, int signo, DBusError *error);
+        int (*kill)(Unit *u, KillWho w, int signo, sd_bus_error *error);
 
         bool (*can_reload)(Unit *u);
 
@@ -359,9 +364,8 @@ struct UnitVTable {
         /* Return true when this unit is suitable for snapshotting */
         bool (*check_snapshot)(Unit *u);
 
-        void (*fd_event)(Unit *u, int fd, uint32_t events, Watch *w);
+        /* Invoked on every child that died */
         void (*sigchld_event)(Unit *u, pid_t pid, int code, int status);
-        void (*timer_event)(Unit *u, uint64_t n_elapsed, Watch *w);
 
         /* Reset failed state if we are in failed state */
         void (*reset_failed)(Unit *u);
@@ -377,14 +381,8 @@ struct UnitVTable {
          * goes away. */
         void (*bus_name_owner_change)(Unit *u, const char *name, const char *old_owner, const char *new_owner);
 
-        /* Called whenever a bus PID lookup finishes */
-        void (*bus_query_pid_done)(Unit *u, const char *name, pid_t pid);
-
-        /* Called for each message received on the bus */
-        DBusHandlerResult (*bus_message_handler)(Unit *u, DBusConnection *c, DBusMessage *message);
-
         /* Called for each property that is being set */
-        int (*bus_set_property)(Unit *u, const char *name, DBusMessageIter *i, UnitSetPropertiesMode mode, DBusError *error);
+        int (*bus_set_property)(Unit *u, const char *name, sd_bus_message *message, UnitSetPropertiesMode mode, sd_bus_error *error);
 
         /* Called after at least one property got changed to apply the necessary change */
         int (*bus_commit_properties)(Unit *u);
@@ -412,14 +410,16 @@ struct UnitVTable {
         /* Type specific cleanups. */
         void (*shutdown)(Manager *m);
 
-        /* When sending out PropertiesChanged signal, which properties
-         * shall be invalidated? This is a NUL separated list of
-         * strings, to minimize relocations a little. */
-        const char *bus_invalidating_properties;
-
         /* The interface name */
         const char *bus_interface;
 
+        /* The bus vtable */
+        const sd_bus_vtable *bus_vtable;
+
+        /* strv list of changing properties */
+        const char * const * const bus_changing_properties;
+
+        /* The strings to print in status messages */
         UnitStatusMessageFormats status_message_formats;
 
         /* Can units of this type have multiple names? */
@@ -521,20 +521,14 @@ int unit_start(Unit *u);
 int unit_stop(Unit *u);
 int unit_reload(Unit *u);
 
-int unit_kill(Unit *u, KillWho w, int signo, DBusError *error);
-int unit_kill_common(Unit *u, KillWho who, int signo, pid_t main_pid, pid_t control_pid, DBusError *error);
+int unit_kill(Unit *u, KillWho w, int signo, sd_bus_error *error);
+int unit_kill_common(Unit *u, KillWho who, int signo, pid_t main_pid, pid_t control_pid, sd_bus_error *error);
 
 void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, bool reload_success);
 
-int unit_watch_fd(Unit *u, int fd, uint32_t events, Watch *w);
-void unit_unwatch_fd(Unit *u, Watch *w);
-
 int unit_watch_pid(Unit *u, pid_t pid);
 void unit_unwatch_pid(Unit *u, pid_t pid);
 
-int unit_watch_timer(Unit *u, clockid_t, bool relative, usec_t usec, Watch *w);
-void unit_unwatch_timer(Unit *u, Watch *w);
-
 int unit_watch_bus_name(Unit *u, const char *name);
 void unit_unwatch_bus_name(Unit *u, const char *name);
 
@@ -590,6 +584,7 @@ void unit_ref_unset(UnitRef *ref);
 int unit_exec_context_defaults(Unit *u, ExecContext *c);
 
 ExecContext *unit_get_exec_context(Unit *u) _pure_;
+KillContext *unit_get_kill_context(Unit *u) _pure_;
 CGroupContext *unit_get_cgroup_context(Unit *u) _pure_;
 
 int unit_write_drop_in(Unit *u, UnitSetPropertiesMode mode, const char *name, const char *data);
diff --git a/src/libsystemd-bus/bus-error.h b/src/libsystemd-bus/bus-error.h
index 5474c8c..f442e95 100644
--- a/src/libsystemd-bus/bus-error.h
+++ b/src/libsystemd-bus/bus-error.h
@@ -21,6 +21,8 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <stdbool.h>
+
 #include "sd-bus.h"
 
 bool bus_error_is_dirty(sd_bus_error *e);
diff --git a/src/libsystemd-bus/bus-internal.h b/src/libsystemd-bus/bus-internal.h
index faed183..a1d60b1 100644
--- a/src/libsystemd-bus/bus-internal.h
+++ b/src/libsystemd-bus/bus-internal.h
@@ -119,11 +119,12 @@ enum bus_state {
         BUS_AUTHENTICATING,
         BUS_HELLO,
         BUS_RUNNING,
+        BUS_CLOSING,
         BUS_CLOSED
 };
 
 static inline bool BUS_IS_OPEN(enum bus_state state) {
-        return state > BUS_UNSET && state < BUS_CLOSED;
+        return state > BUS_UNSET && state < BUS_CLOSING;
 }
 
 enum bus_auth {
@@ -155,7 +156,6 @@ struct sd_bus {
         bool anonymous_auth:1;
         bool prefer_readv:1;
         bool prefer_writev:1;
-        bool processing:1;
         bool match_callbacks_modified:1;
         bool filter_callbacks_modified:1;
         bool nodes_modified:1;
diff --git a/src/libsystemd-bus/bus-introspect.c b/src/libsystemd-bus/bus-introspect.c
index 9a49e43..4c60317 100644
--- a/src/libsystemd-bus/bus-introspect.c
+++ b/src/libsystemd-bus/bus-introspect.c
@@ -111,13 +111,10 @@ static int introspect_write_arguments(struct introspect *i, const char *signatur
         }
 }
 
-int introspect_write_interface(struct introspect *i, const char *interface, const sd_bus_vtable *v) {
+int introspect_write_interface(struct introspect *i, const sd_bus_vtable *v) {
         assert(i);
-        assert(interface);
         assert(v);
 
-        fprintf(i->f, " <interface name=\"%s\">\n", interface);
-
         for (; v->type != _SD_BUS_VTABLE_END; v++) {
 
                 switch (v->type) {
@@ -155,7 +152,6 @@ int introspect_write_interface(struct introspect *i, const char *interface, cons
 
         }
 
-        fputs(" </interface>\n", i->f);
         return 0;
 }
 
diff --git a/src/libsystemd-bus/bus-introspect.h b/src/libsystemd-bus/bus-introspect.h
index 48c3885..0be12cf 100644
--- a/src/libsystemd-bus/bus-introspect.h
+++ b/src/libsystemd-bus/bus-introspect.h
@@ -36,6 +36,6 @@ struct introspect {
 int introspect_begin(struct introspect *i);
 int introspect_write_default_interfaces(struct introspect *i, bool object_manager);
 int introspect_write_child_nodes(struct introspect *i, Set *s, const char *prefix);
-int introspect_write_interface(struct introspect *i, const char *interface, const sd_bus_vtable *v);
+int introspect_write_interface(struct introspect *i, const sd_bus_vtable *v);
 int introspect_finish(struct introspect *i, sd_bus *bus, sd_bus_message *m, sd_bus_message **reply);
 void introspect_free(struct introspect *i);
diff --git a/src/libsystemd-bus/bus-message.c b/src/libsystemd-bus/bus-message.c
index 4f21db5..666307c 100644
--- a/src/libsystemd-bus/bus-message.c
+++ b/src/libsystemd-bus/bus-message.c
@@ -3294,6 +3294,7 @@ _public_ int sd_bus_message_rewind(sd_bus_message *m, int complete) {
 
         return !isempty(c->signature);
 }
+
 static int message_read_ap(
                 sd_bus_message *m,
                 const char *types,
diff --git a/src/libsystemd-bus/bus-objects.c b/src/libsystemd-bus/bus-objects.c
index 8369068..a6e8b2d 100644
--- a/src/libsystemd-bus/bus-objects.c
+++ b/src/libsystemd-bus/bus-objects.c
@@ -728,6 +728,7 @@ static int process_introspect(
 
         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
         _cleanup_set_free_free_ Set *s = NULL;
+        const char *previous_interface = NULL;
         struct introspect intro;
         struct node_vtable *c;
         bool empty;
@@ -768,11 +769,24 @@ static int process_introspect(
 
                 empty = false;
 
-                r = introspect_write_interface(&intro, c->interface, c->vtable);
+                if (!streq_ptr(previous_interface, c->interface)) {
+
+                        if (previous_interface)
+                                fputs(" </interface>\n", intro.f);
+
+                        fprintf(intro.f, " <interface name=\"%s\">\n", c->interface);
+                }
+
+                r = introspect_write_interface(&intro, c->vtable);
                 if (r < 0)
                         goto finish;
+
+                previous_interface = c->interface;
         }
 
+        if (previous_interface)
+                fputs(" </interface>\n", intro.f);
+
         if (empty) {
                 /* Nothing?, let's see if we exist at all, and if not
                  * refuse to do anything */
@@ -806,51 +820,6 @@ finish:
         return r;
 }
 
-static int object_manager_serialize_vtable(
-                sd_bus *bus,
-                sd_bus_message *reply,
-                const char *path,
-                struct node_vtable *c,
-                sd_bus_error *error,
-                void *userdata) {
-
-        int r;
-
-        assert(bus);
-        assert(reply);
-        assert(path);
-        assert(c);
-        assert(error);
-
-        r = sd_bus_message_open_container(reply, 'e', "sa{sv}");
-        if (r < 0)
-                return r;
-
-        r = sd_bus_message_append(reply, "s", c->interface);
-        if (r < 0)
-                return r;
-
-        r = sd_bus_message_open_container(reply, 'a', "{sv}");
-        if (r < 0)
-                return r;
-
-        r = vtable_append_all_properties(bus, reply, path, c, userdata, error);
-        if (r < 0)
-                return r;
-        if (bus->nodes_modified)
-                return 0;
-
-        r = sd_bus_message_close_container(reply);
-        if (r < 0)
-                return r;
-
-        r = sd_bus_message_close_container(reply);
-        if (r < 0)
-                return r;
-
-        return 0;
-}
-
 static int object_manager_serialize_path(
                 sd_bus *bus,
                 sd_bus_message *reply,
@@ -859,9 +828,10 @@ static int object_manager_serialize_path(
                 bool require_fallback,
                 sd_bus_error *error) {
 
+        const char *previous_interface = NULL;
+        bool found_something = false;
         struct node_vtable *i;
         struct node *n;
-        bool found_something = false;
         int r;
 
         assert(bus);
@@ -889,6 +859,9 @@ static int object_manager_serialize_path(
                         continue;
 
                 if (!found_something) {
+
+                        /* Open the object part */
+
                         r = sd_bus_message_open_container(reply, 'e', "oa{sa{sv}}");
                         if (r < 0)
                                 return r;
@@ -904,13 +877,54 @@ static int object_manager_serialize_path(
                         found_something = true;
                 }
 
-                r = object_manager_serialize_vtable(bus, reply, path, i, error, u);
+                if (!streq_ptr(previous_interface, i->interface)) {
+
+                        /* Maybe close the previous interface part */
+
+                        if (previous_interface) {
+                                r = sd_bus_message_close_container(reply);
+                                if (r < 0)
+                                        return r;
+
+                                r = sd_bus_message_close_container(reply);
+                                if (r < 0)
+                                        return r;
+                        }
+
+                        /* Open the new interface part */
+
+                        r = sd_bus_message_open_container(reply, 'e', "sa{sv}");
+                        if (r < 0)
+                                return r;
+
+                        r = sd_bus_message_append(reply, "s", i->interface);
+                        if (r < 0)
+                                return r;
+
+                        r = sd_bus_message_open_container(reply, 'a', "{sv}");
+                        if (r < 0)
+                                return r;
+                }
+
+                r = vtable_append_all_properties(bus, reply, path, i, u, error);
                 if (r < 0)
                         return r;
                 if (sd_bus_error_is_set(error))
                         return 0;
                 if (bus->nodes_modified)
                         return 0;
+
+                previous_interface = i->interface;
+        }
+
+        if (previous_interface) {
+                r = sd_bus_message_close_container(reply);
+                if (r < 0)
+                        return r;
+
+                r = sd_bus_message_close_container(reply);
+                if (r < 0)
+                        return r;
         }
 
         if (found_something) {
@@ -1503,7 +1517,7 @@ static int add_object_vtable_internal(
                 sd_bus_object_find_t find,
                 void *userdata) {
 
-        struct node_vtable *c = NULL, *i;
+        struct node_vtable *c = NULL, *i, *existing = NULL;
         const sd_bus_vtable *v;
         struct node *n;
         int r;
@@ -1515,6 +1529,10 @@ static int add_object_vtable_internal(
         assert_return(vtable[0].type == _SD_BUS_VTABLE_START, -EINVAL);
         assert_return(vtable[0].x.start.element_size == sizeof(struct sd_bus_vtable), -EINVAL);
         assert_return(!bus_pid_changed(bus), -ECHILD);
+        assert_return(!streq(interface, "org.freedesktop.DBus.Properties") &&
+                      !streq(interface, "org.freedesktop.DBus.Introspectable") &&
+                      !streq(interface, "org.freedesktop.DBus.Peer") &&
+                      !streq(interface, "org.freedesktop.DBus.ObjectManager"), -EINVAL);
 
         r = hashmap_ensure_allocated(&bus->vtable_methods, vtable_member_hash_func, vtable_member_compare_func);
         if (r < 0)
@@ -1529,15 +1547,20 @@ static int add_object_vtable_internal(
                 return -ENOMEM;
 
         LIST_FOREACH(vtables, i, n->vtables) {
-                if (streq(i->interface, interface)) {
-                        r = -EEXIST;
-                        goto fail;
-                }
-
                 if (i->is_fallback != fallback) {
                         r = -EPROTOTYPE;
                         goto fail;
                 }
+
+                if (streq(i->interface, interface)) {
+
+                        if (i->vtable == vtable) {
+                                r = -EEXIST;
+                                goto fail;
+                        }
+
+                        existing = i;
+                }
         }
 
         c = new0(struct node_vtable, 1);
@@ -1654,7 +1677,7 @@ static int add_object_vtable_internal(
                 }
         }
 
-        LIST_PREPEND(vtables, n->vtables, c);
+        LIST_INSERT_AFTER(vtables, n->vtables, existing, c);
         bus->nodes_modified = true;
 
         return 0;
@@ -1671,7 +1694,10 @@ static int remove_object_vtable_internal(
                 sd_bus *bus,
                 const char *path,
                 const char *interface,
-                bool fallback) {
+                const sd_bus_vtable *vtable,
+                bool fallback,
+                sd_bus_object_find_t find,
+                void *userdata) {
 
         struct node_vtable *c;
         struct node *n;
@@ -1686,7 +1712,11 @@ static int remove_object_vtable_internal(
                 return 0;
 
         LIST_FOREACH(vtables, c, n->vtables)
-                if (streq(c->interface, interface) && c->is_fallback == fallback)
+                if (streq(c->interface, interface) &&
+                    c->is_fallback == fallback &&
+                    c->vtable == vtable &&
+                    c->find == find &&
+                    c->userdata == userdata)
                         break;
 
         if (!c)
@@ -1715,9 +1745,11 @@ _public_ int sd_bus_add_object_vtable(
 _public_ int sd_bus_remove_object_vtable(
                 sd_bus *bus,
                 const char *path,
-                const char *interface) {
+                const char *interface,
+                const sd_bus_vtable *vtable,
+                void *userdata) {
 
-        return remove_object_vtable_internal(bus, path, interface, false);
+        return remove_object_vtable_internal(bus, path, interface, vtable, false, NULL, userdata);
 }
 
 _public_ int sd_bus_add_fallback_vtable(
@@ -1734,9 +1766,12 @@ _public_ int sd_bus_add_fallback_vtable(
 _public_ int sd_bus_remove_fallback_vtable(
                 sd_bus *bus,
                 const char *path,
-                const char *interface) {
+                const char *interface,
+                const sd_bus_vtable *vtable,
+                sd_bus_object_find_t find,
+                void *userdata) {
 
-        return remove_object_vtable_internal(bus, path, interface, true);
+        return remove_object_vtable_internal(bus, path, interface, vtable, true, find, userdata);
 }
 
 _public_ int sd_bus_add_node_enumerator(
@@ -1824,8 +1859,8 @@ static int emit_properties_changed_on_interface(
                 char **names) {
 
         _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
-        bool has_invalidating = false;
-        struct vtable_member key;
+        bool has_invalidating = false, has_changing = false;
+        struct vtable_member key = {};
         struct node_vtable *c;
         struct node *n;
         char **property;
@@ -1841,23 +1876,6 @@ static int emit_properties_changed_on_interface(
         if (!n)
                 return 0;
 
-        LIST_FOREACH(vtables, c, n->vtables) {
-                if (require_fallback && !c->is_fallback)
-                        continue;
-
-                if (streq(c->interface, interface))
-                        break;
-        }
-
-        if (!c)
-                return 0;
-
-        r = node_vtable_get_userdata(bus, path, c, &u);
-        if (r <= 0)
-                return r;
-        if (bus->nodes_modified)
-                return 0;
-
         r = sd_bus_message_new_signal(bus, path, "org.freedesktop.DBus.Properties", "PropertiesChanged", &m);
         if (r < 0)
                 return r;
@@ -1873,52 +1891,78 @@ static int emit_properties_changed_on_interface(
         key.path = prefix;
         key.interface = interface;
 
-        STRV_FOREACH(property, names) {
-                _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
-                struct vtable_member *v;
-
-                assert_return(member_name_is_valid(*property), -EINVAL);
-
-                key.member = *property;
-                v = hashmap_get(bus->vtable_properties, &key);
-                if (!v)
-                        return -ENOENT;
-
-                assert(c == v->parent);
-                assert_return(v->vtable->flags & SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE, -EDOM);
+        LIST_FOREACH(vtables, c, n->vtables) {
+                if (require_fallback && !c->is_fallback)
+                        continue;
 
-                if (v->vtable->flags & SD_BUS_VTABLE_PROPERTY_INVALIDATE_ONLY) {
-                        has_invalidating = true;
+                if (!streq(c->interface, interface))
                         continue;
-                }
 
-                r = sd_bus_message_open_container(m, 'e', "sv");
+                r = node_vtable_get_userdata(bus, path, c, &u);
                 if (r < 0)
                         return r;
+                if (bus->nodes_modified)
+                        return 0;
+                if (r == 0)
+                        continue;
 
-                r = sd_bus_message_append(m, "s", *property);
-                if (r < 0)
-                        return r;
+                STRV_FOREACH(property, names) {
+                        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+                        struct vtable_member *v;
 
-                r = sd_bus_message_open_container(m, 'v', v->vtable->x.property.signature);
-                if (r < 0)
-                        return r;
+                        assert_return(member_name_is_valid(*property), -EINVAL);
 
-                r = invoke_property_get(bus, v->vtable, m->path, interface, *property, m, &error, vtable_property_convert_userdata(v->vtable, u));
-                if (r < 0)
-                        return r;
-                if (bus->nodes_modified)
-                        return 0;
+                        key.member = *property;
+                        v = hashmap_get(bus->vtable_properties, &key);
+                        if (!v)
+                                return -ENOENT;
+
+                        /* If there are two vtables for the same
+                         * interface, let's handle this property when
+                         * we come to that vtable. */
+                        if (c != v->parent)
+                                continue;
 
-                r = sd_bus_message_close_container(m);
-                if (r < 0)
-                        return r;
+                        assert_return(v->vtable->flags & SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE, -EDOM);
 
-                r = sd_bus_message_close_container(m);
-                if (r < 0)
-                        return r;
+                        if (v->vtable->flags & SD_BUS_VTABLE_PROPERTY_INVALIDATE_ONLY) {
+                                has_invalidating = true;
+                                continue;
+                        }
+
+                        has_changing = true;
+
+                        r = sd_bus_message_open_container(m, 'e', "sv");
+                        if (r < 0)
+                                return r;
+
+                        r = sd_bus_message_append(m, "s", *property);
+                        if (r < 0)
+                                return r;
+
+                        r = sd_bus_message_open_container(m, 'v', v->vtable->x.property.signature);
+                        if (r < 0)
+                                return r;
+
+                        r = invoke_property_get(bus, v->vtable, m->path, interface, *property, m, &error, vtable_property_convert_userdata(v->vtable, u));
+                        if (r < 0)
+                                return r;
+                        if (bus->nodes_modified)
+                                return 0;
+
+                        r = sd_bus_message_close_container(m);
+                        if (r < 0)
+                                return r;
+
+                        r = sd_bus_message_close_container(m);
+                        if (r < 0)
+                                return r;
+                }
         }
 
+        if (!has_invalidating && !has_changing)
+                return 0;
+
         r = sd_bus_message_close_container(m);
         if (r < 0)
                 return r;
@@ -1928,19 +1972,35 @@ static int emit_properties_changed_on_interface(
                 return r;
 
         if (has_invalidating) {
-                STRV_FOREACH(property, names) {
-                        struct vtable_member *v;
-
-                        key.member = *property;
-                        assert_se(v = hashmap_get(bus->vtable_properties, &key));
-                        assert(c == v->parent);
+                LIST_FOREACH(vtables, c, n->vtables) {
+                        if (require_fallback && !c->is_fallback)
+                                continue;
 
-                        if (!(v->vtable->flags & SD_BUS_VTABLE_PROPERTY_INVALIDATE_ONLY))
+                        if (!streq(c->interface, interface))
                                 continue;
 
-                        r = sd_bus_message_append(m, "s", *property);
+                        r = node_vtable_get_userdata(bus, path, c, &u);
                         if (r < 0)
                                 return r;
+                        if (bus->nodes_modified)
+                                return 0;
+                        if (r == 0)
+                                continue;
+
+                        STRV_FOREACH(property, names) {
+                                struct vtable_member *v;
+
+                                key.member = *property;
+                                assert_se(v = hashmap_get(bus->vtable_properties, &key));
+                                assert(c == v->parent);
+
+                                if (!(v->vtable->flags & SD_BUS_VTABLE_PROPERTY_INVALIDATE_ONLY))
+                                        continue;
+
+                                r = sd_bus_message_append(m, "s", *property);
+                                if (r < 0)
+                                        return r;
+                        }
                 }
         }
 
@@ -2028,6 +2088,7 @@ static int interfaces_added_append_one_prefix(
                 bool require_fallback) {
 
         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        bool found_interface = false;
         struct node_vtable *c;
         struct node *n;
         void *u = NULL;
@@ -2047,38 +2108,43 @@ static int interfaces_added_append_one_prefix(
                 if (require_fallback && !c->is_fallback)
                         continue;
 
-                if (streq(c->interface, interface))
-                        break;
-        }
+                if (!streq(c->interface, interface))
+                        continue;
 
-        if (!c)
-                return 0;
+                r = node_vtable_get_userdata(bus, path, c, &u);
+                if (r < 0)
+                        return r;
+                if (bus->nodes_modified)
+                        return 0;
+                if (r == 0)
+                        continue;
 
-        r = node_vtable_get_userdata(bus, path, c, &u);
-        if (r <= 0)
-                return r;
-        if (bus->nodes_modified)
-                return 0;
+                if (!found_interface) {
+                        r = sd_bus_message_append_basic(m, 's', interface);
+                        if (r < 0)
+                                return r;
 
-        r = sd_bus_message_append_basic(m, 's', interface);
-        if (r < 0)
-                return r;
+                        r = sd_bus_message_open_container(m, 'a', "{sv}");
+                        if (r < 0)
+                                return r;
 
-        r = sd_bus_message_open_container(m, 'a', "{sv}");
-        if (r < 0)
-                return r;
+                        found_interface = true;
+                }
 
-        r = vtable_append_all_properties(bus, m,path, c, u, &error);
-        if (r < 0)
-                return r;
-        if (bus->nodes_modified)
-                return 0;
+                r = vtable_append_all_properties(bus, m, path, c, u, &error);
+                if (r < 0)
+                        return r;
+                if (bus->nodes_modified)
+                        return 0;
+        }
 
-        r = sd_bus_message_close_container(m);
-        if (r < 0)
-                return r;
+        if (found_interface) {
+                r = sd_bus_message_close_container(m);
+                if (r < 0)
+                        return r;
+        }
 
-        return 1;
+        return found_interface;
 }
 
 static int interfaces_added_append_one(
diff --git a/src/libsystemd-bus/bus-signature.c b/src/libsystemd-bus/bus-signature.c
index 35c054b..1e5bf48 100644
--- a/src/libsystemd-bus/bus-signature.c
+++ b/src/libsystemd-bus/bus-signature.c
@@ -33,7 +33,10 @@ static int signature_element_length_internal(
 
         int r;
 
-        assert(s);
+        if (!s)
+                return -EINVAL;
+
+        assert(l);
 
         if (bus_type_is_basic(*s) || *s == SD_BUS_TYPE_VARIANT) {
                 *l = 1;
@@ -114,7 +117,8 @@ bool signature_is_single(const char *s, bool allow_dict_entry) {
         int r;
         size_t t;
 
-        assert(s);
+        if (!s)
+                return false;
 
         r = signature_element_length_internal(s, allow_dict_entry, 0, 0, &t);
         if (r < 0)
@@ -124,7 +128,9 @@ bool signature_is_single(const char *s, bool allow_dict_entry) {
 }
 
 bool signature_is_pair(const char *s) {
-        assert(s);
+
+        if (!s)
+                return false;
 
         if (!bus_type_is_basic(*s))
                 return false;
@@ -136,7 +142,8 @@ bool signature_is_valid(const char *s, bool allow_dict_entry) {
         const char *p;
         int r;
 
-        assert(s);
+        if (!s)
+                return false;
 
         p = s;
         while (*p) {
diff --git a/src/libsystemd-bus/bus-util.c b/src/libsystemd-bus/bus-util.c
index ed6fdc4..65323d0 100644
--- a/src/libsystemd-bus/bus-util.c
+++ b/src/libsystemd-bus/bus-util.c
@@ -383,7 +383,7 @@ void bus_verify_polkit_async_registry_free(sd_bus *bus, Hashmap *registry) {
 #endif
 }
 
-static int bus_check_peercred(sd_bus *c) {
+int bus_check_peercred(sd_bus *c) {
         struct ucred ucred;
         socklen_t l;
         int fd;
@@ -1014,7 +1014,8 @@ int bus_property_get_bool(
         return sd_bus_message_append_basic(reply, 'b', &b);
 }
 
-int bus_property_get_uid(
+#if __SIZEOF_SIZE_T__ != 8
+int bus_property_get_size(
                 sd_bus *bus,
                 const char *path,
                 const char *interface,
@@ -1023,12 +1024,41 @@ int bus_property_get_uid(
                 sd_bus_error *error,
                 void *userdata) {
 
-        assert_cc(sizeof(uint32_t) == sizeof(uid_t));
-        assert_cc(sizeof(uint32_t) == sizeof(gid_t));
-        assert_cc(sizeof(uint32_t) == sizeof(pid_t));
+        uint64_t sz = *(size_t*) userdata;
 
-        return sd_bus_message_append_basic(reply, 'u', userdata);
+        return sd_bus_message_append_basic(reply, 't', &sz);
 }
+#endif
+
+#if __SIZEOF_LONG__ != 8
+int bus_property_get_long(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
+
+        int64_t l = *(long*) userdata;
+
+        return sd_bus_message_append_basic(reply, 'x', &l);
+}
+
+int bus_property_get_ulong(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
+
+        uint64_t ul = *(unsigned long*) userdata;
+
+        return sd_bus_message_append_basic(reply, 't', &ul);
+}
+#endif
 
 int bus_log_parse_error(int r) {
         log_error("Failed to parse message: %s", strerror(-r));
diff --git a/src/libsystemd-bus/bus-util.h b/src/libsystemd-bus/bus-util.h
index 314c2f7..c8d5dd9 100644
--- a/src/libsystemd-bus/bus-util.h
+++ b/src/libsystemd-bus/bus-util.h
@@ -55,7 +55,8 @@ int bus_map_all_properties(sd_bus *bus,
 int bus_async_unregister_and_quit(sd_event *e, sd_bus *bus, const char *name);
 
 int bus_event_loop_with_idle(sd_event *e, sd_bus *bus, const char *name, usec_t timeout);
-int bus_property_get_tristate(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, sd_bus_error *error, void *userdata);
+
+int bus_check_peercred(sd_bus *c);
 
 int bus_verify_polkit(sd_bus *bus, sd_bus_message *m, const char *action, bool interactive, bool *_challenge, sd_bus_error *e);
 
@@ -71,11 +72,48 @@ int bus_open_transport_systemd(BusTransport transport, const char *host, bool us
 int bus_print_property(const char *name, sd_bus_message *property, bool all);
 int bus_print_all_properties(sd_bus *bus, const char *dest, const char *path, char **filter, bool all);
 
+int bus_property_get_tristate(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, sd_bus_error *error, void *userdata);
 int bus_property_get_bool(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, sd_bus_error *error, void *userdata);
-int bus_property_get_uid(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, sd_bus_error *error, void *userdata);
 
-#define bus_property_get_gid bus_property_get_uid
-#define bus_property_get_pid bus_property_get_uid
+#define bus_property_get_usec ((sd_bus_property_get_t) NULL)
+#define bus_property_set_usec ((sd_bus_property_set_t) NULL)
+
+assert_cc(sizeof(int) == sizeof(int32_t));
+#define bus_property_get_int ((sd_bus_property_get_t) NULL)
+
+assert_cc(sizeof(unsigned) == sizeof(unsigned));
+#define bus_property_get_unsigned ((sd_bus_property_get_t) NULL)
+
+/* On 64bit machines we can use the default serializer for size_t and
+ * friends, otherwise we need to cast this manually */
+#if __SIZEOF_SIZE_T__ == 8
+#define bus_property_get_size ((sd_bus_property_get_t) NULL)
+#else
+int bus_property_get_size(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, sd_bus_error *error, void *userdata);
+#endif
+
+#if __SIZEOF_LONG__ == 8
+#define bus_property_get_long ((sd_bus_property_get_t) NULL)
+#define bus_property_get_ulong ((sd_bus_property_get_t) NULL)
+#else
+int bus_property_get_long(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, sd_bus_error *error, void *userdata);
+int bus_property_get_ulong(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, sd_bus_error *error, void *userdata);
+#endif
+
+/* uid_t and friends on Linux 32 bit. This means we can just use the
+ * default serializer for 32bit unsigned, for serializing it, and map
+ * it to NULL here */
+assert_cc(sizeof(uid_t) == sizeof(uint32_t));
+#define bus_property_get_uid ((sd_bus_property_get_t) NULL)
+
+assert_cc(sizeof(gid_t) == sizeof(uint32_t));
+#define bus_property_get_gid ((sd_bus_property_get_t) NULL)
+
+assert_cc(sizeof(pid_t) == sizeof(uint32_t));
+#define bus_property_get_pid ((sd_bus_property_get_t) NULL)
+
+assert_cc(sizeof(mode_t) == sizeof(uint32_t));
+#define bus_property_get_mode ((sd_bus_property_get_t) NULL)
 
 int bus_log_parse_error(int r);
 int bus_log_create_error(int r);
@@ -129,22 +167,6 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(sd_bus_message*, sd_bus_message_unref);
         }                                                               \
         struct __useless_struct_to_allow_trailing_semicolon__
 
-#define BUS_ERROR_NO_SUCH_UNIT "org.freedesktop.systemd1.NoSuchUnit"
-#define BUS_ERROR_LOAD_FAILED "org.freedesktop.systemd1.LoadFailed"
-#define BUS_ERROR_JOB_FAILED "org.freedesktop.systemd1.JobFailed"
-
-#define BUS_ERROR_NO_SUCH_MACHINE "org.freedesktop.machine1.NoSuchMachine"
-#define BUS_ERROR_NO_MACHINE_FOR_PID "org.freedesktop.machine1.NoMachineForPID"
-#define BUS_ERROR_MACHINE_EXISTS "org.freedesktop.machine1.MachineExists"
-
-#define BUS_ERROR_NO_SUCH_SESSION "org.freedesktop.login1.NoSuchSession"
-#define BUS_ERROR_NO_SESSION_FOR_PID "org.freedesktop.login1.NoSessionForPID"
-#define BUS_ERROR_NO_SUCH_USER "org.freedesktop.login1.NoSuchUser"
-#define BUS_ERROR_NO_USER_FOR_PID "org.freedesktop.login1.NoUserForPID"
-#define BUS_ERROR_NO_SUCH_SEAT "org.freedesktop.login1.NoSuchSeat"
-#define BUS_ERROR_SESSION_NOT_ON_SEAT "org.freedesktop.login1.SessionNotOnSeat"
-#define BUS_ERROR_NOT_IN_CONTROL "org.freedesktop.login1.NotInControl"
-#define BUS_ERROR_DEVICE_IS_TAKEN "org.freedesktop.login1.DeviceIsTaken"
-#define BUS_ERROR_DEVICE_NOT_TAKEN "org.freedesktop.login1.DeviceNotTaken"
-#define BUS_ERROR_OPERATION_IN_PROGRESS "org.freedesktop.login1.OperationInProgress"
-#define BUS_ERROR_SLEEP_VERB_NOT_SUPPORTED "org.freedesktop.login1.SleepVerbNotSupported"
+#define BUS_PROPERTY_DUAL_TIMESTAMP(name, offset, flags) \
+        SD_BUS_PROPERTY(name, "t", bus_property_get_usec, offset + offsetof(struct dual_timestamp, realtime), flags), \
+        SD_BUS_PROPERTY(name "Monotonic", "t", bus_property_get_usec, offset + offsetof(struct dual_timestamp, monotonic), flags)
diff --git a/src/libsystemd-bus/sd-bus.c b/src/libsystemd-bus/sd-bus.c
index c8248e1..bc88ac9 100644
--- a/src/libsystemd-bus/sd-bus.c
+++ b/src/libsystemd-bus/sd-bus.c
@@ -1204,6 +1204,18 @@ _public_ void sd_bus_close(sd_bus *bus) {
          * freed. */
 }
 
+static void bus_enter_closing(sd_bus *bus) {
+        assert(bus);
+
+        if (bus->state != BUS_OPENING &&
+            bus->state != BUS_AUTHENTICATING &&
+            bus->state != BUS_HELLO &&
+            bus->state != BUS_RUNNING)
+                return;
+
+        bus->state = BUS_CLOSING;
+}
+
 _public_ sd_bus *sd_bus_ref(sd_bus *bus) {
         assert_return(bus, NULL);
 
@@ -1282,6 +1294,20 @@ static int bus_seal_message(sd_bus *b, sd_bus_message *m) {
         return bus_message_seal(m, ++b->serial);
 }
 
+static int bus_write_message(sd_bus *bus, sd_bus_message *message, size_t *idx) {
+        int r;
+
+        assert(bus);
+        assert(message);
+
+        if (bus->is_kernel)
+                r = bus_kernel_write_message(bus, message);
+        else
+                r = bus_socket_write_message(bus, message, idx);
+
+        return r;
+}
+
 static int dispatch_wqueue(sd_bus *bus) {
         int r, ret = 0;
 
@@ -1290,15 +1316,10 @@ static int dispatch_wqueue(sd_bus *bus) {
 
         while (bus->wqueue_size > 0) {
 
-                if (bus->is_kernel)
-                        r = bus_kernel_write_message(bus, bus->wqueue[0]);
-                else
-                        r = bus_socket_write_message(bus, bus->wqueue[0], &bus->windex);
-
-                if (r < 0) {
-                        sd_bus_close(bus);
+                r = bus_write_message(bus, bus->wqueue[0], &bus->windex);
+                if (r < 0)
                         return r;
-                } else if (r == 0)
+                else if (r == 0)
                         /* Didn't do anything this time */
                         return ret;
                 else if (bus->is_kernel || bus->windex >= BUS_MESSAGE_SIZE(bus->wqueue[0])) {
@@ -1324,6 +1345,20 @@ static int dispatch_wqueue(sd_bus *bus) {
         return ret;
 }
 
+static int bus_read_message(sd_bus *bus, sd_bus_message **m) {
+        int r;
+
+        assert(bus);
+        assert(m);
+
+        if (bus->is_kernel)
+                r = bus_kernel_read_message(bus, m);
+        else
+                r = bus_socket_read_message(bus, m);
+
+        return r;
+}
+
 static int dispatch_rqueue(sd_bus *bus, sd_bus_message **m) {
         sd_bus_message *z = NULL;
         int r, ret = 0;
@@ -1343,15 +1378,9 @@ static int dispatch_rqueue(sd_bus *bus, sd_bus_message **m) {
 
         /* Try to read a new message */
         do {
-                if (bus->is_kernel)
-                        r = bus_kernel_read_message(bus, &z);
-                else
-                        r = bus_socket_read_message(bus, &z);
-
-                if (r < 0) {
-                        sd_bus_close(bus);
+                r = bus_read_message(bus, &z);
+                if (r < 0)
                         return r;
-                }
                 if (r == 0)
                         return ret;
 
@@ -1395,15 +1424,10 @@ _public_ int sd_bus_send(sd_bus *bus, sd_bus_message *m, uint64_t *serial) {
         if ((bus->state == BUS_RUNNING || bus->state == BUS_HELLO) && bus->wqueue_size <= 0) {
                 size_t idx = 0;
 
-                if (bus->is_kernel)
-                        r = bus_kernel_write_message(bus, m);
-                else
-                        r = bus_socket_write_message(bus, m, &idx);
-
-                if (r < 0) {
-                        sd_bus_close(bus);
+                r = bus_write_message(bus, m, &idx);
+                if (r < 0)
                         return r;
-                } else if (!bus->is_kernel && idx < BUS_MESSAGE_SIZE(m))  {
+                else if (!bus->is_kernel && idx < BUS_MESSAGE_SIZE(m))  {
                         /* Wasn't fully written. So let's remember how
                          * much was written. Note that the first entry
                          * of the wqueue array is always allocated so
@@ -1573,7 +1597,7 @@ int bus_ensure_running(sd_bus *bus) {
 
         assert(bus);
 
-        if (bus->state == BUS_UNSET || bus->state == BUS_CLOSED)
+        if (bus->state == BUS_UNSET || bus->state == BUS_CLOSED || bus->state == BUS_CLOSING)
                 return -ENOTCONN;
         if (bus->state == BUS_RUNNING)
                 return 1;
@@ -1644,12 +1668,10 @@ _public_ int sd_bus_call(
                         room = true;
                 }
 
-                if (bus->is_kernel)
-                        r = bus_kernel_read_message(bus, &incoming);
-                else
-                        r = bus_socket_read_message(bus, &incoming);
+                r = bus_read_message(bus, &incoming);
                 if (r < 0)
                         return r;
+
                 if (incoming) {
 
                         if (incoming->reply_serial == serial) {
@@ -1731,7 +1753,6 @@ _public_ int sd_bus_call(
 _public_ int sd_bus_get_fd(sd_bus *bus) {
 
         assert_return(bus, -EINVAL);
-        assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
         assert_return(bus->input_fd == bus->output_fd, -EPERM);
         assert_return(!bus_pid_changed(bus), -ECHILD);
 
@@ -1742,7 +1763,7 @@ _public_ int sd_bus_get_events(sd_bus *bus) {
         int flags = 0;
 
         assert_return(bus, -EINVAL);
-        assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
+        assert_return(BUS_IS_OPEN(bus->state) || bus->state == BUS_CLOSING, -ENOTCONN);
         assert_return(!bus_pid_changed(bus), -ECHILD);
 
         if (bus->state == BUS_OPENING)
@@ -1769,9 +1790,14 @@ _public_ int sd_bus_get_timeout(sd_bus *bus, uint64_t *timeout_usec) {
 
         assert_return(bus, -EINVAL);
         assert_return(timeout_usec, -EINVAL);
-        assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
+        assert_return(BUS_IS_OPEN(bus->state) || bus->state == BUS_CLOSING, -ENOTCONN);
         assert_return(!bus_pid_changed(bus), -ECHILD);
 
+        if (bus->state == BUS_CLOSING) {
+                *timeout_usec = 0;
+                return 1;
+        }
+
         if (bus->state == BUS_AUTHENTICATING) {
                 *timeout_usec = bus->auth_timeout;
                 return 1;
@@ -1821,12 +1847,21 @@ static int process_timeout(sd_bus *bus) {
         if (r < 0)
                 return r;
 
+        r = bus_seal_message(bus, m);
+        if (r < 0)
+                return r;
+
         assert_se(prioq_pop(bus->reply_callbacks_prioq) == c);
         hashmap_remove(bus->reply_callbacks, &c->serial);
 
+        bus->current = m;
+        bus->iteration_counter ++;
+
         r = c->callback(bus, m, c->userdata);
         free(c);
 
+        bus->current = NULL;
+
         return r < 0 ? r : 1;
 }
 
@@ -1877,7 +1912,7 @@ static int process_reply(sd_bus *bus, sd_bus_message *m) {
         r = c->callback(bus, m, c->userdata);
         free(c);
 
-        return r;
+        return r < 0 ? r : 1;
 }
 
 static int process_filter(sd_bus *bus, sd_bus_message *m) {
@@ -2078,6 +2113,85 @@ null_message:
         return r;
 }
 
+static int process_closing(sd_bus *bus, sd_bus_message **ret) {
+        _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+        struct reply_callback *c;
+        int r;
+
+        assert(bus);
+        assert(bus->state == BUS_CLOSING);
+
+        c = hashmap_first(bus->reply_callbacks);
+        if (c) {
+                /* First, fail all outstanding method calls */
+                r = bus_message_new_synthetic_error(
+                                bus,
+                                c->serial,
+                                &SD_BUS_ERROR_MAKE(SD_BUS_ERROR_NO_REPLY, "Connection terminated"),
+                                &m);
+                if (r < 0)
+                        return r;
+
+                r = bus_seal_message(bus, m);
+                if (r < 0)
+                        return r;
+
+                if (c->timeout != 0)
+                        prioq_remove(bus->reply_callbacks_prioq, c, &c->prioq_idx);
+
+                hashmap_remove(bus->reply_callbacks, &c->serial);
+
+                bus->current = m;
+                bus->iteration_counter++;
+
+                r = c->callback(bus, m, c->userdata);
+                free(c);
+
+                if (r >= 0)
+                        r = 1;
+
+                goto finish;
+        }
+
+        /* Then, synthesize a Disconnected message */
+        r = sd_bus_message_new_signal(
+                        bus,
+                        "/org/freedesktop/DBus/Local",
+                        "org.freedesktop.DBus.Local",
+                        "Disconnected",
+                        &m);
+        if (r < 0)
+                return r;
+
+        r = bus_seal_message(bus, m);
+        if (r < 0)
+                return r;
+
+        sd_bus_close(bus);
+
+        bus->current = m;
+        bus->iteration_counter++;
+
+        r = process_filter(bus, m);
+        if (r != 0)
+                goto finish;
+
+        r = process_match(bus, m);
+        if (r != 0)
+                goto finish;
+
+        if (ret) {
+                *ret = m;
+                m = NULL;
+        }
+
+        r = 1;
+
+finish:
+        bus->current = NULL;
+        return r;
+}
+
 _public_ int sd_bus_process(sd_bus *bus, sd_bus_message **ret) {
         BUS_DONT_DESTROY(bus);
         int r;
@@ -2091,7 +2205,7 @@ _public_ int sd_bus_process(sd_bus *bus, sd_bus_message **ret) {
         assert_return(!bus_pid_changed(bus), -ECHILD);
 
         /* We don't allow recursively invoking sd_bus_process(). */
-        assert_return(!bus->processing, -EBUSY);
+        assert_return(!bus->current, -EBUSY);
 
         switch (bus->state) {
 
@@ -2101,29 +2215,43 @@ _public_ int sd_bus_process(sd_bus *bus, sd_bus_message **ret) {
 
         case BUS_OPENING:
                 r = bus_socket_process_opening(bus);
-                if (r < 0)
+                if (r == -ECONNRESET || r == -EPIPE) {
+                        bus_enter_closing(bus);
+                        r = 1;
+                } else if (r < 0)
                         return r;
                 if (ret)
                         *ret = NULL;
                 return r;
 
         case BUS_AUTHENTICATING:
-
                 r = bus_socket_process_authenticating(bus);
-                if (r < 0)
+                if (r == -ECONNRESET || r == -EPIPE) {
+                        bus_enter_closing(bus);
+                        r = 1;
+                } else if (r < 0)
                         return r;
+
                 if (ret)
                         *ret = NULL;
+
                 return r;
 
         case BUS_RUNNING:
         case BUS_HELLO:
-
-                bus->processing = true;
                 r = process_running(bus, ret);
-                bus->processing = false;
+                if (r == -ECONNRESET || r == -EPIPE) {
+                        bus_enter_closing(bus);
+                        r = 1;
+
+                        if (ret)
+                                *ret = NULL;
+                }
 
                 return r;
+
+        case BUS_CLOSING:
+                return process_closing(bus, ret);
         }
 
         assert_not_reached("Unknown state");
@@ -2136,6 +2264,10 @@ static int bus_poll(sd_bus *bus, bool need_more, uint64_t timeout_usec) {
         usec_t m = (usec_t) -1;
 
         assert(bus);
+
+        if (bus->state == BUS_CLOSING)
+                return 1;
+
         assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
 
         e = sd_bus_get_events(bus);
@@ -2186,9 +2318,13 @@ static int bus_poll(sd_bus *bus, bool need_more, uint64_t timeout_usec) {
 _public_ int sd_bus_wait(sd_bus *bus, uint64_t timeout_usec) {
 
         assert_return(bus, -EINVAL);
-        assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
         assert_return(!bus_pid_changed(bus), -ECHILD);
 
+        if (bus->state == BUS_CLOSING)
+                return 0;
+
+        assert_return(BUS_IS_OPEN(bus->state) , -ENOTCONN);
+
         if (bus->rqueue_size > 0)
                 return 0;
 
@@ -2199,9 +2335,13 @@ _public_ int sd_bus_flush(sd_bus *bus) {
         int r;
 
         assert_return(bus, -EINVAL);
-        assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
         assert_return(!bus_pid_changed(bus), -ECHILD);
 
+        if (bus->state == BUS_CLOSING)
+                return 0;
+
+        assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
+
         r = bus_ensure_running(bus);
         if (r < 0)
                 return r;
diff --git a/src/libsystemd-bus/sd-event.c b/src/libsystemd-bus/sd-event.c
index d01e82d..5cb3bcc 100644
--- a/src/libsystemd-bus/sd-event.c
+++ b/src/libsystemd-bus/sd-event.c
@@ -51,7 +51,7 @@ struct sd_event_source {
 
         sd_event *event;
         void *userdata;
-        sd_prepare_handler_t prepare;
+        sd_event_handler_t prepare;
 
         EventSourceType type:4;
         int enabled:3;
@@ -65,34 +65,34 @@ struct sd_event_source {
 
         union {
                 struct {
-                        sd_io_handler_t callback;
+                        sd_event_io_handler_t callback;
                         int fd;
                         uint32_t events;
                         uint32_t revents;
                         bool registered:1;
                 } io;
                 struct {
-                        sd_time_handler_t callback;
+                        sd_event_time_handler_t callback;
                         usec_t next, accuracy;
                         unsigned earliest_index;
                         unsigned latest_index;
                 } time;
                 struct {
-                        sd_signal_handler_t callback;
+                        sd_event_signal_handler_t callback;
                         struct signalfd_siginfo siginfo;
                         int sig;
                 } signal;
                 struct {
-                        sd_child_handler_t callback;
+                        sd_event_child_handler_t callback;
                         siginfo_t siginfo;
                         pid_t pid;
                         int options;
                 } child;
                 struct {
-                        sd_defer_handler_t callback;
+                        sd_event_handler_t callback;
                 } defer;
                 struct {
-                        sd_quit_handler_t callback;
+                        sd_event_handler_t callback;
                         unsigned prioq_index;
                 } quit;
         };
@@ -567,7 +567,7 @@ _public_ int sd_event_add_io(
                 sd_event *e,
                 int fd,
                 uint32_t events,
-                sd_io_handler_t callback,
+                sd_event_io_handler_t callback,
                 void *userdata,
                 sd_event_source **ret) {
 
@@ -655,7 +655,7 @@ static int event_add_time_internal(
                 Prioq **latest,
                 uint64_t usec,
                 uint64_t accuracy,
-                sd_time_handler_t callback,
+                sd_event_time_handler_t callback,
                 void *userdata,
                 sd_event_source **ret) {
 
@@ -722,7 +722,7 @@ fail:
 _public_ int sd_event_add_monotonic(sd_event *e,
                                     uint64_t usec,
                                     uint64_t accuracy,
-                                    sd_time_handler_t callback,
+                                    sd_event_time_handler_t callback,
                                     void *userdata,
                                     sd_event_source **ret) {
 
@@ -732,7 +732,7 @@ _public_ int sd_event_add_monotonic(sd_event *e,
 _public_ int sd_event_add_realtime(sd_event *e,
                                    uint64_t usec,
                                    uint64_t accuracy,
-                                   sd_time_handler_t callback,
+                                   sd_event_time_handler_t callback,
                                    void *userdata,
                                    sd_event_source **ret) {
 
@@ -774,7 +774,7 @@ static int event_update_signal_fd(sd_event *e) {
 _public_ int sd_event_add_signal(
                 sd_event *e,
                 int sig,
-                sd_signal_handler_t callback,
+                sd_event_signal_handler_t callback,
                 void *userdata,
                 sd_event_source **ret) {
 
@@ -824,7 +824,7 @@ _public_ int sd_event_add_child(
                 sd_event *e,
                 pid_t pid,
                 int options,
-                sd_child_handler_t callback,
+                sd_event_child_handler_t callback,
                 void *userdata,
                 sd_event_source **ret) {
 
@@ -883,7 +883,7 @@ _public_ int sd_event_add_child(
 
 _public_ int sd_event_add_defer(
                 sd_event *e,
-                sd_defer_handler_t callback,
+                sd_event_handler_t callback,
                 void *userdata,
                 sd_event_source **ret) {
 
@@ -916,7 +916,7 @@ _public_ int sd_event_add_defer(
 
 _public_ int sd_event_add_quit(
                 sd_event *e,
-                sd_quit_handler_t callback,
+                sd_event_handler_t callback,
                 void *userdata,
                 sd_event_source **ret) {
 
@@ -1297,7 +1297,7 @@ _public_ int sd_event_source_get_child_pid(sd_event_source *s, pid_t *pid) {
         return 0;
 }
 
-_public_ int sd_event_source_set_prepare(sd_event_source *s, sd_prepare_handler_t callback) {
+_public_ int sd_event_source_set_prepare(sd_event_source *s, sd_event_handler_t callback) {
         int r;
 
         assert_return(s, -EINVAL);
diff --git a/src/libsystemd-bus/test-bus-introspect.c b/src/libsystemd-bus/test-bus-introspect.c
index ae41618..b986534 100644
--- a/src/libsystemd-bus/test-bus-introspect.c
+++ b/src/libsystemd-bus/test-bus-introspect.c
@@ -52,7 +52,9 @@ int main(int argc, char *argv[]) {
 
         assert_se(introspect_begin(&intro) >= 0);
 
-        assert_se(introspect_write_interface(&intro, "org.foo", vtable) >= 0);
+        fprintf(intro.f, " <interface name=\"org.foo\">\n");
+        assert_se(introspect_write_interface(&intro, vtable) >= 0);
+        fputs(" </interface>\n", intro.f);
 
         fflush(intro.f);
         fputs(intro.introspection, stdout);
diff --git a/src/libsystemd-bus/test-bus-marshal.c b/src/libsystemd-bus/test-bus-marshal.c
index cbf5e1a..b7606d7 100644
--- a/src/libsystemd-bus/test-bus-marshal.c
+++ b/src/libsystemd-bus/test-bus-marshal.c
@@ -28,7 +28,7 @@
 #endif
 
 #ifdef HAVE_DBUS
-#include <dbus.h>
+#include <dbus/dbus.h>
 #endif
 
 #include "log.h"
diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c
index 0f25e23..7e6f610 100644
--- a/src/login/logind-dbus.c
+++ b/src/login/logind-dbus.c
@@ -40,6 +40,7 @@
 #include "bus-util.h"
 #include "bus-error.h"
 #include "logind.h"
+#include "bus-errors.h"
 
 static int property_get_idle_hint(
                 sd_bus *bus,
@@ -184,7 +185,7 @@ static int method_get_session_by_pid(sd_bus *bus, sd_bus_message *message, void
 
         p = session_bus_path(session);
         if (!p)
-                return sd_bus_reply_method_errno(bus, message, -ENOMEM, NULL);
+                return sd_bus_reply_method_errno(bus, message, ENOMEM, NULL);
 
         return sd_bus_reply_method_return(bus, message, "o", p);
 }
diff --git a/src/login/logind-inhibit.c b/src/login/logind-inhibit.c
index 26cce8d..1b6f136 100644
--- a/src/login/logind-inhibit.c
+++ b/src/login/logind-inhibit.c
@@ -304,7 +304,7 @@ int inhibitor_create_fifo(Inhibitor *i) {
                 if (r < 0)
                         return r;
 
-                r = sd_event_source_set_priority(i->event_source, SD_PRIORITY_IDLE);
+                r = sd_event_source_set_priority(i->event_source, SD_EVENT_PRIORITY_IDLE);
                 if (r < 0)
                         return r;
         }
diff --git a/src/login/logind-seat-dbus.c b/src/login/logind-seat-dbus.c
index c59dfd9..53141a8 100644
--- a/src/login/logind-seat-dbus.c
+++ b/src/login/logind-seat-dbus.c
@@ -25,6 +25,7 @@
 #include "util.h"
 #include "bus-util.h"
 #include "strv.h"
+#include "bus-errors.h"
 #include "logind.h"
 #include "logind-seat.h"
 
diff --git a/src/login/logind-session-dbus.c b/src/login/logind-session-dbus.c
index fa9c003..4995391 100644
--- a/src/login/logind-session-dbus.c
+++ b/src/login/logind-session-dbus.c
@@ -25,6 +25,7 @@
 #include "util.h"
 #include "strv.h"
 #include "bus-util.h"
+#include "bus-errors.h"
 
 #include "logind.h"
 #include "logind-session.h"
diff --git a/src/login/logind-session.c b/src/login/logind-session.c
index 65cc6f3..d343373 100644
--- a/src/login/logind-session.c
+++ b/src/login/logind-session.c
@@ -864,7 +864,7 @@ int session_create_fifo(Session *s) {
                 if (r < 0)
                         return r;
 
-                r = sd_event_source_set_priority(s->fifo_event_source, SD_PRIORITY_IDLE);
+                r = sd_event_source_set_priority(s->fifo_event_source, SD_EVENT_PRIORITY_IDLE);
                 if (r < 0)
                         return r;
         }
diff --git a/src/login/logind.c b/src/login/logind.c
index 1d16eaa..47b306b 100644
--- a/src/login/logind.c
+++ b/src/login/logind.c
@@ -958,7 +958,7 @@ static int manager_dispatch_idle_action(sd_event_source *s, uint64_t t, void *us
                         return r;
                 }
 
-                r = sd_event_source_set_priority(m->idle_action_event_source, SD_PRIORITY_IDLE+10);
+                r = sd_event_source_set_priority(m->idle_action_event_source, SD_EVENT_PRIORITY_IDLE+10);
                 if (r < 0) {
                         log_error("Failed to set idle event source priority: %s", strerror(-r));
                         return r;
diff --git a/src/machine/machined-dbus.c b/src/machine/machined-dbus.c
index 2b25f07..be0dbe0 100644
--- a/src/machine/machined-dbus.c
+++ b/src/machine/machined-dbus.c
@@ -36,6 +36,7 @@
 #include "utf8.h"
 #include "unit-name.h"
 #include "bus-util.h"
+#include "bus-errors.h"
 #include "time-util.h"
 #include "cgroup-util.h"
 #include "machined.h"
diff --git a/src/shared/bus-errors.h b/src/shared/bus-errors.h
new file mode 100644
index 0000000..e9ab731
--- /dev/null
+++ b/src/shared/bus-errors.h
@@ -0,0 +1,57 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+#pragma once
+
+/***
+  This file is part of systemd.
+
+  Copyright 2013 Lennart Poettering
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#define BUS_ERROR_NO_SUCH_UNIT "org.freedesktop.systemd1.NoSuchUnit"
+#define BUS_ERROR_NO_UNIT_FOR_PID "org.freedesktop.systemd1.NoUnitForPID"
+#define BUS_ERROR_UNIT_EXISTS "org.freedesktop.systemd1.UnitExists"
+#define BUS_ERROR_LOAD_FAILED "org.freedesktop.systemd1.LoadFailed"
+#define BUS_ERROR_JOB_FAILED "org.freedesktop.systemd1.JobFailed"
+#define BUS_ERROR_NO_SUCH_JOB "org.freedesktop.systemd1.NoSuchJob"
+#define BUS_ERROR_NOT_SUBSCRIBED "org.freedesktop.systemd1.NotSubscribed"
+#define BUS_ERROR_ALREADY_SUBSCRIBED "org.freedesktop.systemd1.AlreadySubscribed"
+#define BUS_ERROR_ONLY_BY_DEPENDENCY "org.freedesktop.systemd1.OnlyByDependency"
+#define BUS_ERROR_TRANSACTION_JOBS_CONFLICTING "org.freedesktop.systemd1.TransactionJobsConflicting"
+#define BUS_ERROR_TRANSACTION_ORDER_IS_CYCLIC "org.freedesktop.systemd1.TransactionOrderIsCyclic"
+#define BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE "org.freedesktop.systemd1.TransactionIsDestructive"
+#define BUS_ERROR_UNIT_MASKED "org.freedesktop.systemd1.UnitMasked"
+#define BUS_ERROR_JOB_TYPE_NOT_APPLICABLE "org.freedesktop.systemd1.JobTypeNotApplicable"
+#define BUS_ERROR_NO_ISOLATION "org.freedesktop.systemd1.NoIsolation"
+#define BUS_ERROR_SHUTTING_DOWN "org.freedesktop.systemd1.ShuttingDown"
+
+#define BUS_ERROR_NO_SUCH_MACHINE "org.freedesktop.machine1.NoSuchMachine"
+#define BUS_ERROR_NO_MACHINE_FOR_PID "org.freedesktop.machine1.NoMachineForPID"
+#define BUS_ERROR_MACHINE_EXISTS "org.freedesktop.machine1.MachineExists"
+
+#define BUS_ERROR_NO_SUCH_SESSION "org.freedesktop.login1.NoSuchSession"
+#define BUS_ERROR_NO_SESSION_FOR_PID "org.freedesktop.login1.NoSessionForPID"
+#define BUS_ERROR_NO_SUCH_USER "org.freedesktop.login1.NoSuchUser"
+#define BUS_ERROR_NO_USER_FOR_PID "org.freedesktop.login1.NoUserForPID"
+#define BUS_ERROR_NO_SUCH_SEAT "org.freedesktop.login1.NoSuchSeat"
+#define BUS_ERROR_SESSION_NOT_ON_SEAT "org.freedesktop.login1.SessionNotOnSeat"
+#define BUS_ERROR_NOT_IN_CONTROL "org.freedesktop.login1.NotInControl"
+#define BUS_ERROR_DEVICE_IS_TAKEN "org.freedesktop.login1.DeviceIsTaken"
+#define BUS_ERROR_DEVICE_NOT_TAKEN "org.freedesktop.login1.DeviceNotTaken"
+#define BUS_ERROR_OPERATION_IN_PROGRESS "org.freedesktop.login1.OperationInProgress"
+#define BUS_ERROR_SLEEP_VERB_NOT_SUPPORTED "org.freedesktop.login1.SleepVerbNotSupported"
+
+#define BUS_ERROR_NO_SUCH_PROCESS "org.freedesktop.systemd1.NoSuchProcess"
diff --git a/src/shared/dbus-common.c b/src/shared/dbus-common.c
deleted file mode 100644
index 3ba2d87..0000000
--- a/src/shared/dbus-common.c
+++ /dev/null
@@ -1,1430 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
-  This file is part of systemd.
-
-  Copyright 2010 Lennart Poettering
-
-  systemd is free software; you can redistribute it and/or modify it
-  under the terms of the GNU Lesser General Public License as published by
-  the Free Software Foundation; either version 2.1 of the License, or
-  (at your option) any later version.
-
-  systemd is distributed in the hope that it will be useful, but
-  WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-  Lesser General Public License for more details.
-
-  You should have received a copy of the GNU Lesser General Public License
-  along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <assert.h>
-#include <sys/socket.h>
-#include <errno.h>
-#include <unistd.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <dbus/dbus.h>
-#include <string.h>
-#include <sys/epoll.h>
-
-#include "log.h"
-#include "dbus-common.h"
-#include "util.h"
-#include "missing.h"
-#include "def.h"
-#include "strv.h"
-
-int bus_check_peercred(DBusConnection *c) {
-        int fd;
-        struct ucred ucred;
-        socklen_t l;
-
-        assert(c);
-
-        assert_se(dbus_connection_get_unix_fd(c, &fd));
-
-        l = sizeof(struct ucred);
-        if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &l) < 0) {
-                log_error("SO_PEERCRED failed: %m");
-                return -errno;
-        }
-
-        if (l != sizeof(struct ucred)) {
-                log_error("SO_PEERCRED returned wrong size.");
-                return -E2BIG;
-        }
-
-        if (ucred.uid != 0 && ucred.uid != geteuid())
-                return -EPERM;
-
-        return 1;
-}
-
-static int sync_auth(DBusConnection *bus, DBusError *error) {
-        usec_t begin, tstamp;
-
-        assert(bus);
-
-        /* This complexity should probably move into D-Bus itself:
-         *
-         * https://bugs.freedesktop.org/show_bug.cgi?id=35189 */
-
-        begin = tstamp = now(CLOCK_MONOTONIC);
-        for (;;) {
-
-                if (tstamp > begin + DEFAULT_TIMEOUT_USEC)
-                        break;
-
-                if (dbus_connection_get_is_authenticated(bus))
-                        break;
-
-                if (!dbus_connection_read_write_dispatch(bus, ((begin + DEFAULT_TIMEOUT_USEC - tstamp) + USEC_PER_MSEC - 1) / USEC_PER_MSEC))
-                        break;
-
-                tstamp = now(CLOCK_MONOTONIC);
-        }
-
-        if (!dbus_connection_get_is_connected(bus)) {
-                dbus_set_error_const(error, DBUS_ERROR_NO_SERVER, "Connection terminated during authentication.");
-                return -ECONNREFUSED;
-        }
-
-        if (!dbus_connection_get_is_authenticated(bus)) {
-                dbus_set_error_const(error, DBUS_ERROR_TIMEOUT, "Failed to authenticate in time.");
-                return -EACCES;
-        }
-
-        return 0;
-}
-
-int bus_connect(DBusBusType t, DBusConnection **_bus, bool *_private, DBusError *error) {
-        DBusConnection *bus = NULL;
-        int r;
-        bool private = true;
-
-        assert(_bus);
-
-        if (geteuid() == 0 && t == DBUS_BUS_SYSTEM) {
-                /* If we are root, then let's talk directly to the
-                 * system instance, instead of going via the bus */
-
-                bus = dbus_connection_open_private("unix:path=/run/systemd/private", error);
-                if (!bus)
-                        return -EIO;
-
-        } else {
-                if (t == DBUS_BUS_SESSION) {
-                        const char *e;
-
-                        /* If we are supposed to talk to the instance,
-                         * try via XDG_RUNTIME_DIR first, then
-                         * fallback to normal bus access */
-
-                        e = secure_getenv("XDG_RUNTIME_DIR");
-                        if (e) {
-                                char *p;
-
-                                if (asprintf(&p, "unix:path=%s/systemd/private", e) < 0)
-                                        return -ENOMEM;
-
-                                bus = dbus_connection_open_private(p, NULL);
-                                free(p);
-                        }
-                }
-
-                if (!bus) {
-                        bus = dbus_bus_get_private(t, error);
-                        if (!bus)
-                                return -EIO;
-
-                        private = false;
-                }
-        }
-
-        dbus_connection_set_exit_on_disconnect(bus, FALSE);
-
-        if (private) {
-                if (bus_check_peercred(bus) < 0) {
-                        dbus_connection_close(bus);
-                        dbus_connection_unref(bus);
-
-                        dbus_set_error_const(error, DBUS_ERROR_ACCESS_DENIED, "Failed to verify owner of bus.");
-                        return -EACCES;
-                }
-        }
-
-        r = sync_auth(bus, error);
-        if (r < 0) {
-                dbus_connection_close(bus);
-                dbus_connection_unref(bus);
-                return r;
-        }
-
-        if (_private)
-                *_private = private;
-
-        *_bus = bus;
-        return 0;
-}
-
-int bus_connect_system_ssh(const char *user, const char *host, DBusConnection **_bus, DBusError *error) {
-        DBusConnection *bus;
-        char *p = NULL;
-        int r;
-
-        assert(_bus);
-        assert(user || host);
-
-        if (user && host)
-                asprintf(&p, "unixexec:path=ssh,argv1=-xT,argv2=%s%%40%s,argv3=systemd-stdio-bridge", user, host);
-        else if (user)
-                asprintf(&p, "unixexec:path=ssh,argv1=-xT,argv2=%s%%40localhost,argv3=systemd-stdio-bridge", user);
-        else if (host)
-                asprintf(&p, "unixexec:path=ssh,argv1=-xT,argv2=%s,argv3=systemd-stdio-bridge", host);
-
-        if (!p) {
-                dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, NULL);
-                return -ENOMEM;
-        }
-
-        bus = dbus_connection_open_private(p, error);
-        free(p);
-
-        if (!bus)
-                return -EIO;
-
-        dbus_connection_set_exit_on_disconnect(bus, FALSE);
-
-        if ((r = sync_auth(bus, error)) < 0) {
-                dbus_connection_close(bus);
-                dbus_connection_unref(bus);
-                return r;
-        }
-
-        if (!dbus_bus_register(bus, error)) {
-                dbus_connection_close(bus);
-                dbus_connection_unref(bus);
-                return r;
-        }
-
-        *_bus = bus;
-        return 0;
-}
-
-int bus_connect_system_polkit(DBusConnection **_bus, DBusError *error) {
-        DBusConnection *bus;
-        int r;
-
-        assert(_bus);
-
-        /* Don't bother with PolicyKit if we are root */
-        if (geteuid() == 0)
-                return bus_connect(DBUS_BUS_SYSTEM, _bus, NULL, error);
-
-        bus = dbus_connection_open_private("unixexec:path=pkexec,argv1=" SYSTEMD_STDIO_BRIDGE_BINARY_PATH, error);
-        if (!bus)
-                return -EIO;
-
-        dbus_connection_set_exit_on_disconnect(bus, FALSE);
-
-        r = sync_auth(bus, error);
-        if (r < 0) {
-                dbus_connection_close(bus);
-                dbus_connection_unref(bus);
-                return r;
-        }
-
-        if (!dbus_bus_register(bus, error)) {
-                dbus_connection_close(bus);
-                dbus_connection_unref(bus);
-                return r;
-        }
-
-        *_bus = bus;
-        return 0;
-}
-
-const char *bus_error_message(const DBusError *error) {
-        if (!error)
-                return NULL;
-
-        /* Sometimes the D-Bus server is a little bit too verbose with
-         * its error messages, so let's override them here */
-        if (dbus_error_has_name(error, DBUS_ERROR_ACCESS_DENIED))
-                return "Access denied";
-
-        return error->message;
-}
-
-const char *bus_error(const DBusError *error, int err) {
-        if (error && dbus_error_is_set(error))
-                return bus_error_message(error);
-
-        return strerror(err < 0 ? -err : err);
-}
-
-DBusHandlerResult bus_default_message_handler(
-                DBusConnection *c,
-                DBusMessage *message,
-                const char *introspection,
-                const char *interfaces,
-                const BusBoundProperties *bound_properties) {
-
-        DBusError error;
-        _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
-        int r;
-
-        assert(c);
-        assert(message);
-
-        dbus_error_init(&error);
-
-        if (dbus_message_is_method_call(message, "org.freedesktop.DBus.Introspectable", "Introspect") && introspection) {
-
-                reply = dbus_message_new_method_return(message);
-                if (!reply)
-                        goto oom;
-
-                if (!dbus_message_append_args(reply, DBUS_TYPE_STRING, &introspection, DBUS_TYPE_INVALID))
-                        goto oom;
-
-        } else if (dbus_message_is_method_call(message, "org.freedesktop.DBus.Properties", "Get") && bound_properties) {
-                const char *interface, *property;
-                const BusBoundProperties *bp;
-                const BusProperty *p;
-                void *data;
-                DBusMessageIter iter, sub;
-
-                if (!dbus_message_get_args(
-                            message,
-                            &error,
-                            DBUS_TYPE_STRING, &interface,
-                            DBUS_TYPE_STRING, &property,
-                            DBUS_TYPE_INVALID))
-                        return bus_send_error_reply(c, message, &error, -EINVAL);
-
-                for (bp = bound_properties; bp->interface; bp++) {
-                        if (!streq(bp->interface, interface))
-                                continue;
-
-                        for (p = bp->properties; p->property; p++)
-                                if (streq(p->property, property))
-                                        goto get_prop;
-                }
-
-                /* no match */
-                if (!nulstr_contains(interfaces, interface))
-                        dbus_set_error_const(&error, DBUS_ERROR_UNKNOWN_INTERFACE, "Unknown interface");
-                else
-                        dbus_set_error_const(&error, DBUS_ERROR_UNKNOWN_PROPERTY, "Unknown property");
-
-                return bus_send_error_reply(c, message, &error, -EINVAL);
-
-get_prop:
-                reply = dbus_message_new_method_return(message);
-                if (!reply)
-                        goto oom;
-
-                dbus_message_iter_init_append(reply, &iter);
-
-                if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT, p->signature, &sub))
-                        goto oom;
-
-                data = (char*)bp->base + p->offset;
-                if (p->indirect)
-                        data = *(void**)data;
-
-                r = p->append(&sub, property, data);
-                if (r == -ENOMEM)
-                        goto oom;
-                if (r < 0)
-                        return bus_send_error_reply(c, message, NULL, r);
-
-                if (!dbus_message_iter_close_container(&iter, &sub))
-                        goto oom;
-
-        } else if (dbus_message_is_method_call(message, "org.freedesktop.DBus.Properties", "GetAll") && bound_properties) {
-                const char *interface;
-                const BusBoundProperties *bp;
-                const BusProperty *p;
-                DBusMessageIter iter, sub, sub2, sub3;
-
-                if (!dbus_message_get_args(
-                            message,
-                            &error,
-                            DBUS_TYPE_STRING, &interface,
-                            DBUS_TYPE_INVALID))
-                        return bus_send_error_reply(c, message, &error, -EINVAL);
-
-                if (interface[0] && !nulstr_contains(interfaces, interface)) {
-                        dbus_set_error_const(&error, DBUS_ERROR_UNKNOWN_INTERFACE, "Unknown interface");
-                        return bus_send_error_reply(c, message, &error, -EINVAL);
-                }
-
-                reply = dbus_message_new_method_return(message);
-                if (!reply)
-                        goto oom;
-
-                dbus_message_iter_init_append(reply, &iter);
-
-                if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "{sv}", &sub))
-                        goto oom;
-
-                for (bp = bound_properties; bp->interface; bp++) {
-                        if (interface[0] && !streq(bp->interface, interface))
-                                continue;
-
-                        for (p = bp->properties; p->property; p++) {
-                                void *data;
-
-                                if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_DICT_ENTRY, NULL, &sub2) ||
-                                    !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &p->property) ||
-                                    !dbus_message_iter_open_container(&sub2, DBUS_TYPE_VARIANT, p->signature, &sub3))
-                                        goto oom;
-
-                                data = (char*)bp->base + p->offset;
-                                if (p->indirect)
-                                        data = *(void**)data;
-                                r = p->append(&sub3, p->property, data);
-                                if (r == -ENOMEM)
-                                        goto oom;
-                                if (r < 0)
-                                        return bus_send_error_reply(c, message, NULL, r);
-
-                                if (!dbus_message_iter_close_container(&sub2, &sub3) ||
-                                    !dbus_message_iter_close_container(&sub, &sub2))
-                                        goto oom;
-                        }
-                }
-
-                if (!dbus_message_iter_close_container(&iter, &sub))
-                        goto oom;
-
-        } else if (dbus_message_is_method_call(message, "org.freedesktop.DBus.Properties", "Set") && bound_properties) {
-                const char *interface, *property;
-                DBusMessageIter iter;
-                const BusBoundProperties *bp;
-                const BusProperty *p;
-                DBusMessageIter sub;
-                char *sig;
-                void *data;
-                DBusMessage *changed;
-
-                if (!dbus_message_iter_init(message, &iter) ||
-                    dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
-                        return bus_send_error_reply(c, message, NULL, -EINVAL);
-
-                dbus_message_iter_get_basic(&iter, &interface);
-
-                if (!dbus_message_iter_next(&iter) ||
-                    dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
-                        return bus_send_error_reply(c, message, NULL, -EINVAL);
-
-                dbus_message_iter_get_basic(&iter, &property);
-
-                if (!dbus_message_iter_next(&iter) ||
-                    dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT ||
-                    dbus_message_iter_has_next(&iter))
-                        return bus_send_error_reply(c, message, NULL, -EINVAL);
-
-                for (bp = bound_properties; bp->interface; bp++) {
-                        if (!streq(bp->interface, interface))
-                                continue;
-
-                        for (p = bp->properties; p->property; p++)
-                                if (streq(p->property, property))
-                                        goto set_prop;
-                }
-
-                /* no match */
-                if (!nulstr_contains(interfaces, interface))
-                        dbus_set_error_const(&error, DBUS_ERROR_UNKNOWN_INTERFACE, "Unknown interface");
-                else
-                        dbus_set_error_const(&error, DBUS_ERROR_UNKNOWN_PROPERTY, "Unknown property");
-
-                return bus_send_error_reply(c, message, &error, -EINVAL);
-
-set_prop:
-                if (!p->set) {
-                        dbus_set_error_const(&error, DBUS_ERROR_PROPERTY_READ_ONLY, "Property read-only");
-                        return bus_send_error_reply(c, message, &error, -EINVAL);
-                }
-
-                dbus_message_iter_recurse(&iter, &sub);
-
-                sig = dbus_message_iter_get_signature(&sub);
-                if (!sig)
-                        goto oom;
-
-                if (!streq(sig, p->signature)) {
-                        dbus_free(sig);
-                        return bus_send_error_reply(c, message, NULL, -EINVAL);
-                }
-                dbus_free(sig);
-
-                data = (uint8_t*) bp->base + p->offset;
-                if (p->indirect)
-                        data = *(void**)data;
-
-                r = p->set(&sub, property, data);
-                if (r == -ENOMEM)
-                        goto oom;
-                else if (r < 0)
-                        return bus_send_error_reply(c, message, NULL, r);
-
-                reply = dbus_message_new_method_return(message);
-                if (!reply)
-                        goto oom;
-
-                /* Send out a signal about this, but it doesn't really
-                 * matter if this fails, so eat all errors */
-                changed = bus_properties_changed_one_new(
-                                dbus_message_get_path(message),
-                                interface,
-                                property);
-                if (changed) {
-                        dbus_connection_send(c, changed, NULL);
-                        dbus_message_unref(changed);
-                }
-
-
-        } else {
-                const char *interface = dbus_message_get_interface(message);
-
-                if (!interface || !nulstr_contains(interfaces, interface)) {
-                        dbus_set_error_const(&error, DBUS_ERROR_UNKNOWN_INTERFACE, "Unknown interface");
-                        return bus_send_error_reply(c, message, &error, -EINVAL);
-                }
-        }
-
-        if (reply) {
-                if (!bus_maybe_send_reply(c, message, reply))
-                        goto oom;
-
-                return DBUS_HANDLER_RESULT_HANDLED;
-        }
-
-        return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-
-oom:
-        dbus_error_free(&error);
-
-        return DBUS_HANDLER_RESULT_NEED_MEMORY;
-}
-
-int bus_property_append_string(DBusMessageIter *i, const char *property, void *data) {
-        const char *t = data;
-
-        assert(i);
-        assert(property);
-
-        if (!t)
-                t = "";
-
-        if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &t))
-                return -ENOMEM;
-
-        return 0;
-}
-
-int bus_property_append_strv(DBusMessageIter *i, const char *property, void *data) {
-        char **t = data;
-
-        assert(i);
-        assert(property);
-
-        return bus_append_strv_iter(i, t);
-}
-
-int bus_property_append_bool(DBusMessageIter *i, const char *property, void *data) {
-        bool *b = data;
-        dbus_bool_t db;
-
-        assert(i);
-        assert(property);
-        assert(b);
-
-        db = *b;
-
-        if (!dbus_message_iter_append_basic(i, DBUS_TYPE_BOOLEAN, &db))
-                return -ENOMEM;
-
-        return 0;
-}
-
-int bus_property_append_tristate_false(DBusMessageIter *i, const char *property, void *data) {
-        int *b = data;
-        dbus_bool_t db;
-
-        assert(i);
-        assert(property);
-        assert(b);
-
-        db = *b > 0;
-
-        if (!dbus_message_iter_append_basic(i, DBUS_TYPE_BOOLEAN, &db))
-                return -ENOMEM;
-
-        return 0;
-}
-
-int bus_property_append_uint64(DBusMessageIter *i, const char *property, void *data) {
-        assert(i);
-        assert(property);
-        assert(data);
-
-        /* Let's ensure that usec_t is actually 64bit, and hence this
-         * function can be used for usec_t */
-        assert_cc(sizeof(uint64_t) == sizeof(usec_t));
-
-        if (!dbus_message_iter_append_basic(i, DBUS_TYPE_UINT64, data))
-                return -ENOMEM;
-
-        return 0;
-}
-
-int bus_property_append_uint32(DBusMessageIter *i, const char *property, void *data) {
-        assert(i);
-        assert(property);
-        assert(data);
-
-        /* Let's ensure that pid_t, mode_t, uid_t, gid_t are actually
-         * 32bit, and hence this function can be used for
-         * pid_t/mode_t/uid_t/gid_t */
-        assert_cc(sizeof(uint32_t) == sizeof(pid_t));
-        assert_cc(sizeof(uint32_t) == sizeof(mode_t));
-        assert_cc(sizeof(uint32_t) == sizeof(unsigned));
-        assert_cc(sizeof(uint32_t) == sizeof(uid_t));
-        assert_cc(sizeof(uint32_t) == sizeof(gid_t));
-
-        if (!dbus_message_iter_append_basic(i, DBUS_TYPE_UINT32, data))
-                return -ENOMEM;
-
-        return 0;
-}
-
-int bus_property_append_int32(DBusMessageIter *i, const char *property, void *data) {
-        assert(i);
-        assert(property);
-        assert(data);
-
-        assert_cc(sizeof(int32_t) == sizeof(int));
-
-        if (!dbus_message_iter_append_basic(i, DBUS_TYPE_INT32, data))
-                return -ENOMEM;
-
-        return 0;
-}
-
-int bus_property_append_size(DBusMessageIter *i, const char *property, void *data) {
-        uint64_t u;
-
-        assert(i);
-        assert(property);
-        assert(data);
-
-        u = (uint64_t) *(size_t*) data;
-
-        if (!dbus_message_iter_append_basic(i, DBUS_TYPE_UINT64, &u))
-                return -ENOMEM;
-
-        return 0;
-}
-
-int bus_property_append_ul(DBusMessageIter *i, const char *property, void *data) {
-        uint64_t u;
-
-        assert(i);
-        assert(property);
-        assert(data);
-
-        u = (uint64_t) *(unsigned long*) data;
-
-        if (!dbus_message_iter_append_basic(i, DBUS_TYPE_UINT64, &u))
-                return -ENOMEM;
-
-        return 0;
-}
-
-int bus_property_append_long(DBusMessageIter *i, const char *property, void *data) {
-        int64_t l;
-
-        assert(i);
-        assert(property);
-        assert(data);
-
-        l = (int64_t) *(long*) data;
-
-        if (!dbus_message_iter_append_basic(i, DBUS_TYPE_INT64, &l))
-                return -ENOMEM;
-
-        return 0;
-}
-
-int bus_property_set_uint64(DBusMessageIter *i, const char *property, void *data) {
-        uint64_t *t = data;
-
-        assert(i);
-        assert(property);
-
-        dbus_message_iter_get_basic(i, t);
-        return 0;
-}
-
-const char *bus_errno_to_dbus(int error) {
-
-        switch(error) {
-
-        case -EINVAL:
-                return DBUS_ERROR_INVALID_ARGS;
-
-        case -ENOMEM:
-                return DBUS_ERROR_NO_MEMORY;
-
-        case -EPERM:
-        case -EACCES:
-                return DBUS_ERROR_ACCESS_DENIED;
-
-        case -ESRCH:
-                return DBUS_ERROR_UNIX_PROCESS_ID_UNKNOWN;
-
-        case -ENOENT:
-                return DBUS_ERROR_FILE_NOT_FOUND;
-
-        case -EEXIST:
-                return DBUS_ERROR_FILE_EXISTS;
-
-        case -ETIMEDOUT:
-        case -ETIME:
-                return DBUS_ERROR_TIMEOUT;
-
-        case -EIO:
-                return DBUS_ERROR_IO_ERROR;
-
-        case -ENETRESET:
-        case -ECONNABORTED:
-        case -ECONNRESET:
-                return DBUS_ERROR_DISCONNECTED;
-        }
-
-        return DBUS_ERROR_FAILED;
-}
-
-dbus_bool_t bus_maybe_send_reply (DBusConnection   *c,
-                                  DBusMessage *message,
-                                  DBusMessage *reply)
-{
-        /* Some parts of systemd "reply" to signals, which of course
-         * have the no-reply flag set.  We will be defensive here and
-         * still send out a reply if we're passed a signal.
-         */
-        if (dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_METHOD_CALL &&
-            dbus_message_get_no_reply(message))
-                return TRUE;
-        return dbus_connection_send(c, reply, NULL);
-}
-
-DBusHandlerResult bus_send_error_reply(DBusConnection *c, DBusMessage *message, DBusError *berror, int error) {
-        _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
-        const char *name, *text;
-
-        if (berror && dbus_error_is_set(berror)) {
-                name = berror->name;
-                text = berror->message;
-        } else {
-                name = bus_errno_to_dbus(error);
-                text = strerror(-error);
-        }
-
-        reply = dbus_message_new_error(message, name, text);
-        if (!reply)
-                goto oom;
-
-        if (!bus_maybe_send_reply(c, message, reply))
-                goto oom;
-
-        if (berror)
-                dbus_error_free(berror);
-
-        return DBUS_HANDLER_RESULT_HANDLED;
-
-oom:
-        if (reply)
-                dbus_message_unref(reply);
-
-        if (berror)
-                dbus_error_free(berror);
-
-        return DBUS_HANDLER_RESULT_NEED_MEMORY;
-}
-
-DBusMessage* bus_properties_changed_new(const char *path, const char *interface, const char *properties) {
-        DBusMessage *m;
-        DBusMessageIter iter, sub;
-        const char *i;
-
-        assert(interface);
-        assert(properties);
-
-        m = dbus_message_new_signal(path, "org.freedesktop.DBus.Properties", "PropertiesChanged");
-        if (!m)
-                goto oom;
-
-        dbus_message_iter_init_append(m, &iter);
-
-        /* We won't send any property values, since they might be
-         * large and sometimes not cheap to generated */
-
-        if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &interface) ||
-            !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "{sv}", &sub) ||
-            !dbus_message_iter_close_container(&iter, &sub) ||
-            !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub))
-                goto oom;
-
-        NULSTR_FOREACH(i, properties)
-                if (!dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &i))
-                        goto oom;
-
-        if (!dbus_message_iter_close_container(&iter, &sub))
-                goto oom;
-
-        return m;
-
-oom:
-        if (m)
-                dbus_message_unref(m);
-
-        return NULL;
-}
-
-DBusMessage* bus_properties_changed_one_new(const char *path, const char *interface, const char *property) {
-        DBusMessage *m;
-        DBusMessageIter iter, sub;
-
-        assert(interface);
-        assert(property);
-
-        m = dbus_message_new_signal(path, "org.freedesktop.DBus.Properties", "PropertiesChanged");
-        if (!m)
-                goto oom;
-
-        dbus_message_iter_init_append(m, &iter);
-
-        /* We won't send any property values, since they might be
-         * large and sometimes not cheap to generated */
-
-        if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &interface) ||
-            !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "{sv}", &sub) ||
-            !dbus_message_iter_close_container(&iter, &sub) ||
-            !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub))
-                goto oom;
-
-        if (!dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &property))
-                goto oom;
-
-        if (!dbus_message_iter_close_container(&iter, &sub))
-                goto oom;
-
-        return m;
-
-oom:
-        if (m)
-                dbus_message_unref(m);
-
-        return NULL;
-}
-
-uint32_t bus_flags_to_events(DBusWatch *bus_watch) {
-        unsigned flags;
-        uint32_t events = 0;
-
-        assert(bus_watch);
-
-        /* no watch flags for disabled watches */
-        if (!dbus_watch_get_enabled(bus_watch))
-                return 0;
-
-        flags = dbus_watch_get_flags(bus_watch);
-
-        if (flags & DBUS_WATCH_READABLE)
-                events |= EPOLLIN;
-        if (flags & DBUS_WATCH_WRITABLE)
-                events |= EPOLLOUT;
-
-        return events | EPOLLHUP | EPOLLERR;
-}
-
-unsigned bus_events_to_flags(uint32_t events) {
-        unsigned flags = 0;
-
-        if (events & EPOLLIN)
-                flags |= DBUS_WATCH_READABLE;
-        if (events & EPOLLOUT)
-                flags |= DBUS_WATCH_WRITABLE;
-        if (events & EPOLLHUP)
-                flags |= DBUS_WATCH_HANGUP;
-        if (events & EPOLLERR)
-                flags |= DBUS_WATCH_ERROR;
-
-        return flags;
-}
-
-int bus_parse_strv(DBusMessage *m, char ***_l) {
-        DBusMessageIter iter;
-
-        assert(m);
-        assert(_l);
-
-        if (!dbus_message_iter_init(m, &iter))
-                return -EINVAL;
-
-        return bus_parse_strv_iter(&iter, _l);
-}
-
-int bus_parse_strv_iter(DBusMessageIter *iter, char ***_l) {
-        DBusMessageIter sub;
-        unsigned n = 0, i = 0;
-        char **l;
-
-        assert(iter);
-        assert(_l);
-
-        if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY ||
-            dbus_message_iter_get_element_type(iter) != DBUS_TYPE_STRING)
-            return -EINVAL;
-
-        dbus_message_iter_recurse(iter, &sub);
-
-        while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
-                n++;
-                dbus_message_iter_next(&sub);
-        }
-
-        l = new(char*, n+1);
-        if (!l)
-                return -ENOMEM;
-
-        dbus_message_iter_recurse(iter, &sub);
-
-        while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
-                const char *s;
-
-                assert_se(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING);
-                dbus_message_iter_get_basic(&sub, &s);
-
-                if (!(l[i++] = strdup(s))) {
-                        strv_free(l);
-                        return -ENOMEM;
-                }
-
-                dbus_message_iter_next(&sub);
-        }
-
-        assert(i == n);
-        l[i] = NULL;
-
-        if (_l)
-                *_l = l;
-
-        return 0;
-}
-
-int bus_parse_strv_pairs_iter(DBusMessageIter *iter, char ***_l) {
-        DBusMessageIter sub, sub2;
-        unsigned n = 0, i = 0;
-        _cleanup_strv_free_ char **l = NULL;
-
-        assert(iter);
-        assert(_l);
-
-        if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY ||
-            dbus_message_iter_get_element_type(iter) != DBUS_TYPE_STRUCT)
-            return -EINVAL;
-
-        dbus_message_iter_recurse(iter, &sub);
-
-        while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
-                n++;
-                dbus_message_iter_next(&sub);
-        }
-
-        l = new(char*, n*2+1);
-        if (!l)
-                return -ENOMEM;
-        l[0] = NULL; /* make sure that l is properly terminated at all times */
-
-        dbus_message_iter_recurse(iter, &sub);
-
-        while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
-                const char *a, *b;
-
-                assert_se(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT);
-
-                dbus_message_iter_recurse(&sub, &sub2);
-
-                if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &a, true) < 0 ||
-                    bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &b, false) < 0)
-                        return -EINVAL;
-
-                l[i] = strdup(a);
-                if (!l[i])
-                        return -ENOMEM;
-                i++;
-
-                l[i] = strdup(b);
-                if (!l[i])
-                        return -ENOMEM;
-                i++;
-
-                dbus_message_iter_next(&sub);
-        }
-
-        assert(i == n*2);
-        l[i] = NULL;
-
-        if (_l) {
-                *_l = l;
-                l = NULL; /* avoid freeing */
-        }
-
-        return 0;
-}
-
-int bus_parse_unit_info(DBusMessageIter *iter, struct unit_info *u) {
-        DBusMessageIter sub;
-
-        assert(iter);
-        assert(u);
-
-        if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_STRUCT)
-                return -EINVAL;
-
-        dbus_message_iter_recurse(iter, &sub);
-
-        if (bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &u->id, true) < 0 ||
-            bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &u->description, true) < 0 ||
-            bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &u->load_state, true) < 0 ||
-            bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &u->active_state, true) < 0 ||
-            bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &u->sub_state, true) < 0 ||
-            bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &u->following, true) < 0 ||
-            bus_iter_get_basic_and_next(&sub, DBUS_TYPE_OBJECT_PATH, &u->unit_path, true) < 0 ||
-            bus_iter_get_basic_and_next(&sub, DBUS_TYPE_UINT32, &u->job_id, true) < 0 ||
-            bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &u->job_type, true) < 0 ||
-            bus_iter_get_basic_and_next(&sub, DBUS_TYPE_OBJECT_PATH, &u->job_path, false) < 0) {
-                log_error("Failed to parse reply.");
-                return -EIO;
-        }
-
-        return 0;
-}
-
-int bus_append_strv_iter(DBusMessageIter *iter, char **l) {
-        DBusMessageIter sub;
-
-        assert(iter);
-
-        if (!dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY, "s", &sub))
-                return -ENOMEM;
-
-        STRV_FOREACH(l, l)
-                if (!dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, l))
-                        return -ENOMEM;
-
-        if (!dbus_message_iter_close_container(iter, &sub))
-                return -ENOMEM;
-
-        return 0;
-}
-
-int bus_iter_get_basic_and_next(DBusMessageIter *iter, int type, void *data, bool next) {
-
-        assert(iter);
-        assert(data);
-
-        if (dbus_message_iter_get_arg_type(iter) != type)
-                return -EIO;
-
-        dbus_message_iter_get_basic(iter, data);
-
-        if (!dbus_message_iter_next(iter) != !next)
-                return -EIO;
-
-        return 0;
-}
-
-int generic_print_property(const char *name, DBusMessageIter *iter, bool all) {
-        assert(name);
-        assert(iter);
-
-        switch (dbus_message_iter_get_arg_type(iter)) {
-
-        case DBUS_TYPE_STRING: {
-                const char *s;
-                dbus_message_iter_get_basic(iter, &s);
-
-                if (all || !isempty(s))
-                        printf("%s=%s\n", name, s);
-
-                return 1;
-        }
-
-        case DBUS_TYPE_BOOLEAN: {
-                dbus_bool_t b;
-
-                dbus_message_iter_get_basic(iter, &b);
-                printf("%s=%s\n", name, yes_no(b));
-
-                return 1;
-        }
-
-        case DBUS_TYPE_UINT64: {
-                uint64_t u;
-                dbus_message_iter_get_basic(iter, &u);
-
-                /* Yes, heuristics! But we can change this check
-                 * should it turn out to not be sufficient */
-
-                if (endswith(name, "Timestamp")) {
-                        char timestamp[FORMAT_TIMESTAMP_MAX], *t;
-
-                        t = format_timestamp(timestamp, sizeof(timestamp), u);
-                        if (t || all)
-                                printf("%s=%s\n", name, strempty(t));
-
-                } else if (strstr(name, "USec")) {
-                        char timespan[FORMAT_TIMESPAN_MAX];
-
-                        printf("%s=%s\n", name, format_timespan(timespan, sizeof(timespan), u, 0));
-                } else
-                        printf("%s=%llu\n", name, (unsigned long long) u);
-
-                return 1;
-        }
-
-        case DBUS_TYPE_UINT32: {
-                uint32_t u;
-                dbus_message_iter_get_basic(iter, &u);
-
-                if (strstr(name, "UMask") || strstr(name, "Mode"))
-                        printf("%s=%04o\n", name, u);
-                else
-                        printf("%s=%u\n", name, (unsigned) u);
-
-                return 1;
-        }
-
-        case DBUS_TYPE_INT32: {
-                int32_t i;
-                dbus_message_iter_get_basic(iter, &i);
-
-                printf("%s=%i\n", name, (int) i);
-                return 1;
-        }
-
-        case DBUS_TYPE_DOUBLE: {
-                double d;
-                dbus_message_iter_get_basic(iter, &d);
-
-                printf("%s=%g\n", name, d);
-                return 1;
-        }
-
-        case DBUS_TYPE_ARRAY:
-
-                if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING) {
-                        DBusMessageIter sub;
-                        bool space = false;
-
-                        dbus_message_iter_recurse(iter, &sub);
-                        if (all ||
-                            dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
-                                printf("%s=", name);
-
-                                while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
-                                        const char *s;
-
-                                        assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING);
-                                        dbus_message_iter_get_basic(&sub, &s);
-                                        printf("%s%s", space ? " " : "", s);
-
-                                        space = true;
-                                        dbus_message_iter_next(&sub);
-                                }
-
-                                puts("");
-                        }
-
-                        return 1;
-
-                } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_BYTE) {
-                        DBusMessageIter sub;
-
-                        dbus_message_iter_recurse(iter, &sub);
-                        if (all ||
-                            dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
-                                printf("%s=", name);
-
-                                while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
-                                        uint8_t u;
-
-                                        assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_BYTE);
-                                        dbus_message_iter_get_basic(&sub, &u);
-                                        printf("%02x", u);
-
-                                        dbus_message_iter_next(&sub);
-                                }
-
-                                puts("");
-                        }
-
-                        return 1;
-
-                } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_UINT32) {
-                        DBusMessageIter sub;
-
-                        dbus_message_iter_recurse(iter, &sub);
-                        if (all ||
-                            dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
-                                printf("%s=", name);
-
-                                while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
-                                        uint32_t u;
-
-                                        assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_UINT32);
-                                        dbus_message_iter_get_basic(&sub, &u);
-                                        printf("%08x", u);
-
-                                        dbus_message_iter_next(&sub);
-                                }
-
-                                puts("");
-                        }
-
-                        return 1;
-                }
-
-                break;
-        }
-
-        return 0;
-}
-
-static void release_name_pending_cb(DBusPendingCall *pending, void *userdata) {
-        DBusMessage *reply;
-        DBusConnection *bus = userdata;
-
-        assert_se(reply = dbus_pending_call_steal_reply(pending));
-        dbus_message_unref(reply);
-
-        dbus_connection_close(bus);
-}
-
-void bus_async_unregister_and_exit(DBusConnection *bus, const char *name) {
-        _cleanup_dbus_message_unref_ DBusMessage *m = NULL;
-        DBusPendingCall *pending = NULL;
-
-        assert(bus);
-
-        /* We unregister the name here, but we continue to process
-         * requests, until we get the response for it, so that all
-         * requests are guaranteed to be processed. */
-
-        m = dbus_message_new_method_call(
-                        DBUS_SERVICE_DBUS,
-                        DBUS_PATH_DBUS,
-                        DBUS_INTERFACE_DBUS,
-                        "ReleaseName");
-        if (!m)
-                goto oom;
-
-        if (!dbus_message_append_args(
-                            m,
-                            DBUS_TYPE_STRING,
-                            &name,
-                            DBUS_TYPE_INVALID))
-                goto oom;
-
-        if (!dbus_connection_send_with_reply(bus, m, &pending, -1))
-                goto oom;
-
-        if (!dbus_pending_call_set_notify(pending, release_name_pending_cb, bus, NULL))
-                goto oom;
-
-        dbus_pending_call_unref(pending);
-
-        return;
-
-oom:
-        log_oom();
-
-        if (pending) {
-                dbus_pending_call_cancel(pending);
-                dbus_pending_call_unref(pending);
-        }
-}
-
-DBusHandlerResult bus_exit_idle_filter(DBusConnection *bus, DBusMessage *m, void *userdata) {
-        usec_t *remain_until = userdata;
-
-        assert(bus);
-        assert(m);
-        assert(remain_until);
-
-        /* Every time we get a new message we reset out timeout */
-        *remain_until = now(CLOCK_MONOTONIC) + DEFAULT_EXIT_USEC;
-
-        if (dbus_message_is_signal(m, DBUS_INTERFACE_LOCAL, "Disconnected"))
-                dbus_connection_close(bus);
-
-        return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-}
-
-/* This mimics dbus_bus_get_unix_user() */
-pid_t bus_get_unix_process_id(
-                DBusConnection *connection,
-                const char *name,
-                DBusError *error) {
-
-        _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
-        uint32_t pid = 0;
-
-        m = dbus_message_new_method_call(
-                        DBUS_SERVICE_DBUS,
-                        DBUS_PATH_DBUS,
-                        DBUS_INTERFACE_DBUS,
-                        "GetConnectionUnixProcessID");
-        if (!m) {
-                dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, NULL);
-                return 0;
-        }
-
-        if (!dbus_message_append_args(
-                            m,
-                            DBUS_TYPE_STRING, &name,
-                            DBUS_TYPE_INVALID)) {
-                dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, NULL);
-                return 0;
-        }
-
-        reply = dbus_connection_send_with_reply_and_block(connection, m, -1, error);
-        if (!reply)
-                return 0;
-
-        if (dbus_set_error_from_message(error, reply))
-                return 0;
-
-        if (!dbus_message_get_args(
-                            reply, error,
-                            DBUS_TYPE_UINT32, &pid,
-                            DBUS_TYPE_INVALID))
-                return 0;
-
-        return (pid_t) pid;
-}
-
-bool bus_error_is_no_service(const DBusError *error) {
-        assert(error);
-
-        if (!dbus_error_is_set(error))
-                return false;
-
-        if (dbus_error_has_name(error, DBUS_ERROR_NAME_HAS_NO_OWNER))
-                return true;
-
-        if (dbus_error_has_name(error, DBUS_ERROR_SERVICE_UNKNOWN))
-                return true;
-
-        return startswith(error->name, "org.freedesktop.DBus.Error.Spawn.");
-}
-
-int bus_method_call_with_reply(
-                DBusConnection *bus,
-                const char *destination,
-                const char *path,
-                const char *interface,
-                const char *method,
-                DBusMessage **return_reply,
-                DBusError *return_error,
-                int first_arg_type, ...) {
-
-        DBusError error;
-        _cleanup_dbus_message_unref_ DBusMessage *m = NULL;
-        DBusMessage *reply;
-        va_list ap;
-        int r = 0;
-
-        dbus_error_init(&error);
-        assert(bus);
-
-        m = dbus_message_new_method_call(destination, path, interface, method);
-        if (!m) {
-                r = log_oom();
-                goto finish;
-        }
-
-        va_start(ap, first_arg_type);
-        if (!dbus_message_append_args_valist(m, first_arg_type, ap)) {
-                va_end(ap);
-                r = log_oom();
-                goto finish;
-        }
-        va_end(ap);
-
-        reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
-        if (!reply) {
-                if (!return_error)
-                        log_error("Failed to issue method call: %s", bus_error_message(&error));
-
-                if (bus_error_is_no_service(&error))
-                        r = -ENOENT;
-                else if (dbus_error_has_name(&error, DBUS_ERROR_ACCESS_DENIED))
-                        r = -EACCES;
-                else if (dbus_error_has_name(&error, DBUS_ERROR_NO_REPLY))
-                        r = -ETIMEDOUT;
-                else if (dbus_error_has_name(&error, DBUS_ERROR_DISCONNECTED))
-                        r = -ECONNRESET;
-                else
-                        r = -EIO;
-                goto finish;
-        }
-
-        if (return_reply)
-                *return_reply = reply;
-        else
-                dbus_message_unref(reply);
-
-finish:
-        if (return_error)
-                *return_error = error;
-        else
-                dbus_error_free(&error);
-
-        return r;
-}
-
-void bus_message_unrefp(DBusMessage **reply) {
-        if (!reply)
-                return;
-
-        if (!*reply)
-                return;
-
-        dbus_message_unref(*reply);
-}
-
-const char *bus_message_get_sender_with_fallback(DBusMessage *m) {
-        const char *s;
-
-        assert(m);
-
-        s = dbus_message_get_sender(m);
-        if (s)
-                return s;
-
-        /* When the message came in from a direct connection the
-         * message will have no sender. We fix that here. */
-
-        return ":no-sender";
-}
diff --git a/src/shared/dbus-common.h b/src/shared/dbus-common.h
deleted file mode 100644
index 9752f08..0000000
--- a/src/shared/dbus-common.h
+++ /dev/null
@@ -1,246 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#pragma once
-
-/***
-  This file is part of systemd.
-
-  Copyright 2010 Lennart Poettering
-
-  systemd is free software; you can redistribute it and/or modify it
-  under the terms of the GNU Lesser General Public License as published by
-  the Free Software Foundation; either version 2.1 of the License, or
-  (at your option) any later version.
-
-  systemd is distributed in the hope that it will be useful, but
-  WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-  Lesser General Public License for more details.
-
-  You should have received a copy of the GNU Lesser General Public License
-  along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <dbus/dbus.h>
-#include <inttypes.h>
-#include <sys/types.h>
-
-#include "macro.h"
-
-#ifndef DBUS_ERROR_UNKNOWN_OBJECT
-#define DBUS_ERROR_UNKNOWN_OBJECT "org.freedesktop.DBus.Error.UnknownObject"
-#endif
-
-#ifndef DBUS_ERROR_UNKNOWN_INTERFACE
-#define DBUS_ERROR_UNKNOWN_INTERFACE "org.freedesktop.DBus.Error.UnknownInterface"
-#endif
-
-#ifndef DBUS_ERROR_UNKNOWN_PROPERTY
-#define DBUS_ERROR_UNKNOWN_PROPERTY "org.freedesktop.DBus.Error.UnknownProperty"
-#endif
-
-#ifndef DBUS_ERROR_PROPERTY_READ_ONLY
-#define DBUS_ERROR_PROPERTY_READ_ONLY "org.freedesktop.DBus.Error.PropertyReadOnly"
-#endif
-
-#define BUS_PROPERTIES_INTERFACE                                        \
-        " <interface name=\"org.freedesktop.DBus.Properties\">\n"       \
-        "  <method name=\"Get\">\n"                                     \
-        "   <arg name=\"interface\" direction=\"in\" type=\"s\"/>\n"    \
-        "   <arg name=\"property\" direction=\"in\" type=\"s\"/>\n"     \
-        "   <arg name=\"value\" direction=\"out\" type=\"v\"/>\n"       \
-        "  </method>\n"                                                 \
-        "  <method name=\"GetAll\">\n"                                  \
-        "   <arg name=\"interface\" direction=\"in\" type=\"s\"/>\n"    \
-        "   <arg name=\"properties\" direction=\"out\" type=\"a{sv}\"/>\n" \
-        "  </method>\n"                                                 \
-        "  <method name=\"Set\">\n"                                     \
-        "   <arg name=\"interface\" direction=\"in\" type=\"s\"/>\n"    \
-        "   <arg name=\"property\" direction=\"in\" type=\"s\"/>\n"     \
-        "   <arg name=\"value\" direction=\"in\" type=\"v\"/>\n"        \
-        "  </method>\n"                                                 \
-        "  <signal name=\"PropertiesChanged\">\n"                       \
-        "   <arg type=\"s\" name=\"interface\"/>\n"                     \
-        "   <arg type=\"a{sv}\" name=\"changed_properties\"/>\n"        \
-        "   <arg type=\"as\" name=\"invalidated_properties\"/>\n"       \
-        "  </signal>\n"                                                 \
-        " </interface>\n"
-
-#define BUS_INTROSPECTABLE_INTERFACE                                    \
-        " <interface name=\"org.freedesktop.DBus.Introspectable\">\n"   \
-        "  <method name=\"Introspect\">\n"                              \
-        "   <arg name=\"data\" type=\"s\" direction=\"out\"/>\n"        \
-        "  </method>\n"                                                 \
-        " </interface>\n"
-
-#define BUS_PEER_INTERFACE                                              \
-        "<interface name=\"org.freedesktop.DBus.Peer\">\n"              \
-        " <method name=\"Ping\"/>\n"                                    \
-        " <method name=\"GetMachineId\">\n"                             \
-        "  <arg type=\"s\" name=\"machine_uuid\" direction=\"out\"/>\n" \
-        " </method>\n"                                                  \
-        "</interface>\n"
-
-#define BUS_GENERIC_INTERFACES_LIST             \
-        "org.freedesktop.DBus.Properties\0"     \
-        "org.freedesktop.DBus.Introspectable\0" \
-        "org.freedesktop.DBus.Peer\0"
-
-int bus_check_peercred(DBusConnection *c);
-
-int bus_connect(DBusBusType t, DBusConnection **_bus, bool *private_bus, DBusError *error);
-
-int bus_connect_system_ssh(const char *user, const char *host, DBusConnection **_bus, DBusError *error);
-int bus_connect_system_polkit(DBusConnection **_bus, DBusError *error);
-
-const char *bus_error_message(const DBusError *error);
-const char *bus_error(const DBusError *e, int r);
-
-typedef int (*BusPropertyCallback)(DBusMessageIter *iter, const char *property, void *data);
-typedef int (*BusPropertySetCallback)(DBusMessageIter *iter, const char *property, void *data);
-
-typedef struct BusProperty {
-        const char *property;            /* name of the property */
-        BusPropertyCallback append;      /* Function that is called to serialize this property */
-        const char *signature;
-        const uint16_t offset;           /* Offset from BusBoundProperties::base address to the property data.
-                                          * uint16_t is sufficient, because we have no structs too big.
-                                          * -Werror=overflow will catch it if this does not hold. */
-        bool indirect;                   /* data is indirect, ie. not base+offset, but *(base+offset) */
-        BusPropertySetCallback set;      /* Optional: Function that is called to set this property */
-} BusProperty;
-
-typedef struct BusBoundProperties {
-        const char *interface;           /* interface of the properties */
-        const BusProperty *properties;   /* array of properties, ended by a NULL-filled element */
-        const void *const base;          /* base pointer to which the offset must be added to reach data */
-} BusBoundProperties;
-
-dbus_bool_t bus_maybe_send_reply (DBusConnection   *c,
-                                  DBusMessage *message,
-                                  DBusMessage *reply);
-
-DBusHandlerResult bus_send_error_reply(
-                DBusConnection *c,
-                DBusMessage *message,
-                DBusError *bus_error,
-                int error);
-
-DBusHandlerResult bus_default_message_handler(
-                DBusConnection *c,
-                DBusMessage *message,
-                const char *introspection,
-                const char *interfaces,
-                const BusBoundProperties *bound_properties);
-
-int bus_property_append_string(DBusMessageIter *i, const char *property, void *data);
-int bus_property_append_strv(DBusMessageIter *i, const char *property, void *data);
-int bus_property_append_bool(DBusMessageIter *i, const char *property, void *data);
-int bus_property_append_tristate_false(DBusMessageIter *i, const char *property, void *data);
-int bus_property_append_int32(DBusMessageIter *i, const char *property, void *data);
-int bus_property_append_uint32(DBusMessageIter *i, const char *property, void *data);
-int bus_property_append_uint64(DBusMessageIter *i, const char *property, void *data);
-int bus_property_append_size(DBusMessageIter *i, const char *property, void *data);
-int bus_property_append_ul(DBusMessageIter *i, const char *property, void *data);
-int bus_property_append_long(DBusMessageIter *i, const char *property, void *data);
-
-#define bus_property_append_int bus_property_append_int32
-#define bus_property_append_pid bus_property_append_uint32
-#define bus_property_append_uid bus_property_append_uint32
-#define bus_property_append_gid bus_property_append_uint32
-#define bus_property_append_mode bus_property_append_uint32
-#define bus_property_append_unsigned bus_property_append_uint32
-#define bus_property_append_usec bus_property_append_uint64
-
-int bus_property_set_uint64(DBusMessageIter *i, const char *property, void *data);
-#define bus_property_set_usec bus_property_set_uint64
-
-#define DEFINE_BUS_PROPERTY_APPEND_ENUM(function,name,type)             \
-        int function(DBusMessageIter *i, const char *property, void *data) { \
-                const char *value;                                      \
-                type *field = data;                                     \
-                                                                        \
-                assert(i);                                              \
-                assert(property);                                       \
-                                                                        \
-                value = strempty(name##_to_string(*field));             \
-                                                                        \
-                if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &value)) \
-                        return -ENOMEM;                                 \
-                                                                        \
-                return 0;                                               \
-        }
-
-#define DEFINE_BUS_PROPERTY_SET_ENUM(function,name,type)                \
-        int function(DBusMessageIter *i, const char *property, void *data) { \
-                const char *value;                                      \
-                type f, *field = data;                                  \
-                                                                        \
-                assert(i);                                              \
-                assert(property);                                       \
-                                                                        \
-                dbus_message_iter_get_basic(i, &value);                 \
-                                                                        \
-                f = name##_from_string(value);                          \
-                if (f < 0)                                              \
-                        return f;                                       \
-                                                                        \
-                *field = f;                                             \
-                return 0;                                               \
-        }
-
-const char *bus_errno_to_dbus(int error) _const_;
-
-DBusMessage* bus_properties_changed_new(const char *path, const char *interface, const char *properties);
-DBusMessage* bus_properties_changed_one_new(const char *path, const char *interface, const char *property);
-
-uint32_t bus_flags_to_events(DBusWatch *bus_watch) _pure_;
-unsigned bus_events_to_flags(uint32_t events) _const_;
-
-int bus_parse_strv(DBusMessage *m, char ***_l);
-int bus_parse_strv_iter(DBusMessageIter *iter, char ***_l);
-int bus_parse_strv_pairs_iter(DBusMessageIter *iter, char ***_l);
-
-struct unit_info {
-        const char *id;
-        const char *description;
-        const char *load_state;
-        const char *active_state;
-        const char *sub_state;
-        const char *following;
-        const char *unit_path;
-        uint32_t job_id;
-        const char *job_type;
-        const char *job_path;
-};
-
-int bus_parse_unit_info(DBusMessageIter *iter, struct unit_info *u);
-
-int bus_append_strv_iter(DBusMessageIter *iter, char **l);
-
-int bus_iter_get_basic_and_next(DBusMessageIter *iter, int type, void *data, bool next);
-
-int generic_print_property(const char *name, DBusMessageIter *iter, bool all);
-
-void bus_async_unregister_and_exit(DBusConnection *bus, const char *name);
-
-DBusHandlerResult bus_exit_idle_filter(DBusConnection *bus, DBusMessage *m, void *userdata);
-
-pid_t bus_get_unix_process_id(DBusConnection *connection, const char *name, DBusError *error);
-
-bool bus_error_is_no_service(const DBusError *error);
-int bus_method_call_with_reply(DBusConnection *bus,
-                               const char *destination,
-                               const char *path,
-                               const char *interface,
-                               const char *method,
-                               DBusMessage **return_reply,
-                               DBusError *return_error,
-                               int first_arg_type, ...);
-
-const char *bus_message_get_sender_with_fallback(DBusMessage *m);
-
-void bus_message_unrefp(DBusMessage **reply);
-
-#define _cleanup_dbus_message_unref_ __attribute__((cleanup(bus_message_unrefp)))
-#define _cleanup_dbus_error_free_ __attribute__((cleanup(dbus_error_free)))
diff --git a/src/shared/install.c b/src/shared/install.c
index 2c119e2..16504ee 100644
--- a/src/shared/install.c
+++ b/src/shared/install.c
@@ -1562,6 +1562,7 @@ int unit_file_set_default(
                 UnitFileScope scope,
                 const char *root_dir,
                 const char *file,
+                bool force,
                 UnitFileChange **changes,
                 unsigned *n_changes) {
 
@@ -1599,7 +1600,7 @@ int unit_file_set_default(
 
         path = strappenda(config_path, "/" SPECIAL_DEFAULT_TARGET);
 
-        r = create_symlink(i->path, path, true, changes, n_changes);
+        r = create_symlink(i->path, path, force, changes, n_changes);
         if (r < 0)
                 return r;
 
diff --git a/src/shared/install.h b/src/shared/install.h
index 3c2e162..e87c57e 100644
--- a/src/shared/install.h
+++ b/src/shared/install.h
@@ -80,7 +80,7 @@ int unit_file_link(UnitFileScope scope, bool runtime, const char *root_dir, char
 int unit_file_preset(UnitFileScope scope, bool runtime, const char *root_dir, char *files[], bool force, UnitFileChange **changes, unsigned *n_changes);
 int unit_file_mask(UnitFileScope scope, bool runtime, const char *root_dir, char *files[], bool force, UnitFileChange **changes, unsigned *n_changes);
 int unit_file_unmask(UnitFileScope scope, bool runtime, const char *root_dir, char *files[], UnitFileChange **changes, unsigned *n_changes);
-int unit_file_set_default(UnitFileScope scope, const char *root_dir, const char *file, UnitFileChange **changes, unsigned *n_changes);
+int unit_file_set_default(UnitFileScope scope, const char *root_dir, const char *file, bool force, UnitFileChange **changes, unsigned *n_changes);
 int unit_file_get_default(UnitFileScope scope, const char *root_dir, char **name);
 
 UnitFileState unit_file_get_state(UnitFileScope scope, const char *root_dir, const char *filename);
diff --git a/src/shared/prioq.c b/src/shared/prioq.c
index 537befc..8af4c51 100644
--- a/src/shared/prioq.c
+++ b/src/shared/prioq.c
@@ -295,8 +295,8 @@ unsigned prioq_size(Prioq *q) {
                 return 0;
 
         return q->n_items;
-
 }
+
 bool prioq_isempty(Prioq *q) {
 
         if (!q)
diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
index 2e18636..84826a3 100644
--- a/src/systemctl/systemctl.c
+++ b/src/systemctl/systemctl.c
@@ -70,6 +70,7 @@
 #include "bus-util.h"
 #include "bus-message.h"
 #include "bus-error.h"
+#include "bus-errors.h"
 
 static char **arg_types = NULL;
 static char **arg_states = NULL;
@@ -194,7 +195,7 @@ static int translate_bus_error_to_exit_status(int r, const sd_bus_error *error)
                 return EXIT_NOTINSTALLED;
 
         if (sd_bus_error_has_name(error, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE) ||
-            sd_bus_error_has_name(error, BUS_ERROR_NOT_SUPPORTED))
+            sd_bus_error_has_name(error, SD_BUS_ERROR_NOT_SUPPORTED))
                 return EXIT_NOTIMPLEMENTED;
 
         if (sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED))
@@ -1400,6 +1401,100 @@ static int get_default(sd_bus *bus, char **args) {
         return 0;
 }
 
+static void dump_unit_file_changes(const UnitFileChange *changes, unsigned n_changes) {
+        unsigned i;
+
+        assert(changes || n_changes == 0);
+
+        for (i = 0; i < n_changes; i++) {
+                if (changes[i].type == UNIT_FILE_SYMLINK)
+                        log_info("ln -s '%s' '%s'", changes[i].source, changes[i].path);
+                else
+                        log_info("rm '%s'", changes[i].path);
+        }
+}
+
+static int deserialize_and_dump_unit_file_changes(sd_bus_message *m) {
+        const char *type, *path, *source;
+        int r;
+
+        r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sss)");
+        if (r < 0)
+                return bus_log_parse_error(r);
+
+        while ((r = sd_bus_message_read(m, "(sss)", &type, &path, &source)) > 0) {
+                if (!arg_quiet) {
+                        if (streq(type, "symlink"))
+                                log_info("ln -s '%s' '%s'", source, path);
+                        else
+                                log_info("rm '%s'", path);
+                }
+        }
+        if (r < 0)
+                return bus_log_parse_error(r);
+
+        r = sd_bus_message_exit_container(m);
+        if (r < 0)
+                return bus_log_parse_error(r);
+
+        return 0;
+}
+
+static int set_default(sd_bus *bus, char **args) {
+        _cleanup_free_ char *unit = NULL;
+        UnitFileChange *changes = NULL;
+        unsigned n_changes = 0;
+        int r;
+
+        unit = unit_name_mangle_with_suffix(args[1], ".target");
+        if (!unit)
+                return log_oom();
+
+        if (!bus || avoid_bus()) {
+                r = unit_file_set_default(arg_scope, arg_root, unit, arg_force, &changes, &n_changes);
+                if (r < 0) {
+                        log_error("Failed to set default target: %s", strerror(-r));
+                        return r;
+                }
+
+                if (!arg_quiet)
+                        dump_unit_file_changes(changes, n_changes);
+
+                r = 0;
+        } else {
+                _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+                _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+
+                r = sd_bus_call_method(
+                                bus,
+                                "org.freedesktop.systemd1",
+                                "/org/freedesktop/systemd1",
+                                "org.freedesktop.systemd1.Manager",
+                                "SetDefaultTarget",
+                                &error,
+                                &reply,
+                                "sb", unit, arg_force);
+                if (r < 0) {
+                        log_error("Failed to set default target: %s", bus_error_message(&error, -r));
+                        return r;
+                }
+
+                r = deserialize_and_dump_unit_file_changes(reply);
+                if (r < 0)
+                        return r;
+
+                /* Try to reload if enabeld */
+                if (!arg_no_reload)
+                        r = daemon_reload(bus, args);
+                else
+                        r = 0;
+        }
+
+        unit_file_changes_free(changes, n_changes);
+
+        return r;
+}
+
 struct job_info {
         uint32_t id;
         const char *name, *type, *state;
@@ -4331,12 +4426,10 @@ static int mangle_names(char **original_names, char ***mangled_names) {
 }
 
 static int enable_unit(sd_bus *bus, char **args) {
-        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
         _cleanup_strv_free_ char **mangled_names = NULL;
         const char *verb = args[0];
         UnitFileChange *changes = NULL;
-        unsigned n_changes = 0, i;
+        unsigned n_changes = 0;
         int carries_install_info = -1;
         int r;
 
@@ -4369,8 +4462,6 @@ static int enable_unit(sd_bus *bus, char **args) {
                         r = unit_file_mask(arg_scope, arg_runtime, arg_root, mangled_names, arg_force, &changes, &n_changes);
                 else if (streq(verb, "unmask"))
                         r = unit_file_unmask(arg_scope, arg_runtime, arg_root, mangled_names, &changes, &n_changes);
-                else if (streq(verb, "set-default"))
-                        r = unit_file_set_default(arg_scope, arg_root, args[1], &changes, &n_changes);
                 else
                         assert_not_reached("Unknown verb");
 
@@ -4379,20 +4470,16 @@ static int enable_unit(sd_bus *bus, char **args) {
                         goto finish;
                 }
 
-                if (!arg_quiet) {
-                        for (i = 0; i < n_changes; i++) {
-                                if (changes[i].type == UNIT_FILE_SYMLINK)
-                                        log_info("ln -s '%s' '%s'", changes[i].source, changes[i].path);
-                                else
-                                        log_info("rm '%s'", changes[i].path);
-                        }
-                }
+                if (!arg_quiet)
+                        dump_unit_file_changes(changes, n_changes);
 
                 r = 0;
         } else {
-                const char *method, *type, *path, *source;
+                _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
+                _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
                 int expect_carries_install_info = false;
                 bool send_force = true;
+                const char *method;
 
                 if (streq(verb, "enable")) {
                         method = "EnableUnitFiles";
@@ -4413,8 +4500,6 @@ static int enable_unit(sd_bus *bus, char **args) {
                 else if (streq(verb, "unmask")) {
                         method = "UnmaskUnitFiles";
                         send_force = false;
-                } else if (streq(verb, "set-default")) {
-                        method = "SetDefaultTarget";
                 } else
                         assert_not_reached("Unknown verb");
 
@@ -4454,24 +4539,9 @@ static int enable_unit(sd_bus *bus, char **args) {
                                 return bus_log_parse_error(r);
                 }
 
-                r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(sss)");
-                if (r < 0)
-                        return bus_log_parse_error(r);
-
-                while ((r = sd_bus_message_read(reply, "(sss)", &type, &path, &source)) > 0) {
-                        if (!arg_quiet) {
-                                if (streq(type, "symlink"))
-                                        log_info("ln -s '%s' '%s'", source, path);
-                                else
-                                        log_info("rm '%s'", path);
-                        }
-                }
-                if (r < 0)
-                        return bus_log_parse_error(r);
-
-                r = sd_bus_message_exit_container(reply);
+                r = deserialize_and_dump_unit_file_changes(m);
                 if (r < 0)
-                        return bus_log_parse_error(r);
+                        return r;
 
                 /* Try to reload if enabeld */
                 if (!arg_no_reload)
@@ -5649,8 +5719,8 @@ static int systemctl_main(sd_bus *bus, int argc, char *argv[], int bus_error) {
                 { "link",                  MORE,  2, enable_unit       },
                 { "switch-root",           MORE,  2, switch_root       },
                 { "list-dependencies",     LESS,  2, list_dependencies },
-                { "set-default",           EQUAL, 2, enable_unit       },
-                { "get-default",           LESS,  1, get_default       },
+                { "set-default",           EQUAL, 2, set_default       },
+                { "get-default",           EQUAL, 1, get_default       },
                 { "set-property",          MORE,  3, set_property      },
         };
 
diff --git a/src/systemd/sd-bus.h b/src/systemd/sd-bus.h
index 072b54f..a09b39f 100644
--- a/src/systemd/sd-bus.h
+++ b/src/systemd/sd-bus.h
@@ -125,10 +125,10 @@ int sd_bus_add_fallback(sd_bus *bus, const char *prefix, sd_bus_message_handler_
 int sd_bus_remove_fallback(sd_bus *bus, const char *prefix, sd_bus_message_handler_t callback, void *userdata);
 
 int sd_bus_add_object_vtable(sd_bus *bus, const char *path, const char *interface, const sd_bus_vtable *vtable, void *userdata);
-int sd_bus_remove_object_vtable(sd_bus *bus, const char *path, const char *interface);
+int sd_bus_remove_object_vtable(sd_bus *bus, const char *path, const char *interface, const sd_bus_vtable *vtable, void *userdata);
 
 int sd_bus_add_fallback_vtable(sd_bus *bus, const char *path, const char *interface, const sd_bus_vtable *vtable, sd_bus_object_find_t find, void *userdata);
-int sd_bus_remove_fallback_vtable(sd_bus *bus, const char *path, const char *interface);
+int sd_bus_remove_fallback_vtable(sd_bus *bus, const char *path, const char *interface, const sd_bus_vtable *vtable, sd_bus_object_find_t find, void *userdata);
 
 int sd_bus_add_node_enumerator(sd_bus *bus, const char *path, sd_bus_node_enumerator_t callback, void *userdata);
 int sd_bus_remove_node_enumerator(sd_bus *bus, const char *path, sd_bus_node_enumerator_t callback, void *userdata);
diff --git a/src/systemd/sd-event.h b/src/systemd/sd-event.h
index 919b661..e7b6c9e 100644
--- a/src/systemd/sd-event.h
+++ b/src/systemd/sd-event.h
@@ -59,18 +59,16 @@ enum {
 
 enum {
         /* And everything inbetween and outside is good too */
-        SD_PRIORITY_IMPORTANT = -100,
-        SD_PRIORITY_NORMAL = 0,
-        SD_PRIORITY_IDLE = 100
+        SD_EVENT_PRIORITY_IMPORTANT = -100,
+        SD_EVENT_PRIORITY_NORMAL = 0,
+        SD_EVENT_PRIORITY_IDLE = 100
 };
 
-typedef int (*sd_io_handler_t)(sd_event_source *s, int fd, uint32_t revents, void *userdata);
-typedef int (*sd_time_handler_t)(sd_event_source *s, uint64_t usec, void *userdata);
-typedef int (*sd_signal_handler_t)(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata);
-typedef int (*sd_child_handler_t)(sd_event_source *s, const siginfo_t *si, void *userdata);
-typedef int (*sd_defer_handler_t)(sd_event_source *s, void *userdata);
-typedef int (*sd_prepare_handler_t)(sd_event_source *s, void *userdata);
-typedef int (*sd_quit_handler_t)(sd_event_source *s, void *userdata);
+typedef int (*sd_event_handler_t)(sd_event_source *s, void *userdata);
+typedef int (*sd_event_io_handler_t)(sd_event_source *s, int fd, uint32_t revents, void *userdata);
+typedef int (*sd_event_time_handler_t)(sd_event_source *s, uint64_t usec, void *userdata);
+typedef int (*sd_event_signal_handler_t)(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata);
+typedef int (*sd_event_child_handler_t)(sd_event_source *s, const siginfo_t *si, void *userdata);
 
 int sd_event_default(sd_event **e);
 
@@ -78,13 +76,13 @@ int sd_event_new(sd_event **e);
 sd_event* sd_event_ref(sd_event *e);
 sd_event* sd_event_unref(sd_event *e);
 
-int sd_event_add_io(sd_event *e, int fd, uint32_t events, sd_io_handler_t callback, void *userdata, sd_event_source **s);
-int sd_event_add_monotonic(sd_event *e, uint64_t usec, uint64_t accuracy, sd_time_handler_t callback, void *userdata, sd_event_source **s);
-int sd_event_add_realtime(sd_event *e, uint64_t usec, uint64_t accuracy, sd_time_handler_t callback, void *userdata, sd_event_source **s);
-int sd_event_add_signal(sd_event *e, int sig, sd_signal_handler_t callback, void *userdata, sd_event_source **s);
-int sd_event_add_child(sd_event *e, pid_t pid, int options, sd_child_handler_t callback, void *userdata, sd_event_source **s);
-int sd_event_add_defer(sd_event *e, sd_defer_handler_t callback, void *userdata, sd_event_source **s);
-int sd_event_add_quit(sd_event *e, sd_quit_handler_t callback, void *userdata, sd_event_source **s);
+int sd_event_add_io(sd_event *e, int fd, uint32_t events, sd_event_io_handler_t callback, void *userdata, sd_event_source **s);
+int sd_event_add_monotonic(sd_event *e, uint64_t usec, uint64_t accuracy, sd_event_time_handler_t callback, void *userdata, sd_event_source **s);
+int sd_event_add_realtime(sd_event *e, uint64_t usec, uint64_t accuracy, sd_event_time_handler_t callback, void *userdata, sd_event_source **s);
+int sd_event_add_signal(sd_event *e, int sig, sd_event_signal_handler_t callback, void *userdata, sd_event_source **s);
+int sd_event_add_child(sd_event *e, pid_t pid, int options, sd_event_child_handler_t callback, void *userdata, sd_event_source **s);
+int sd_event_add_defer(sd_event *e, sd_event_handler_t callback, void *userdata, sd_event_source **s);
+int sd_event_add_quit(sd_event *e, sd_event_handler_t callback, void *userdata, sd_event_source **s);
 
 int sd_event_run(sd_event *e, uint64_t timeout);
 int sd_event_loop(sd_event *e);
@@ -101,7 +99,7 @@ sd_event_source* sd_event_source_unref(sd_event_source *s);
 
 sd_event *sd_event_get(sd_event_source *s);
 
-int sd_event_source_set_prepare(sd_event_source *s, sd_prepare_handler_t callback);
+int sd_event_source_set_prepare(sd_event_source *s, sd_event_handler_t callback);
 int sd_event_source_get_pending(sd_event_source *s);
 int sd_event_source_get_priority(sd_event_source *s, int *priority);
 int sd_event_source_set_priority(sd_event_source *s, int priority);

commit 3febea3a0b0a968ea281e7959c1654cbaf95c9bf
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Nov 19 21:02:59 2013 +0100

    hashmap: be a bit more conservative with pre-allocating hash tables and items

diff --git a/src/shared/hashmap.c b/src/shared/hashmap.c
index f06fce6..8f5957b 100644
--- a/src/shared/hashmap.c
+++ b/src/shared/hashmap.c
@@ -66,13 +66,14 @@ static void *first_hashmap_tile = NULL;
 static struct pool *first_entry_pool = NULL;
 static void *first_entry_tile = NULL;
 
-static void* allocate_tile(struct pool **first_pool, void **first_tile, size_t tile_size) {
+static void* allocate_tile(struct pool **first_pool, void **first_tile, size_t tile_size, unsigned at_least) {
         unsigned i;
 
         /* When a tile is released we add it to the list and simply
          * place the next pointer at its offset 0. */
 
         assert(tile_size >= sizeof(void*));
+        assert(at_least > 0);
 
         if (*first_tile) {
                 void *r;
@@ -88,7 +89,7 @@ static void* allocate_tile(struct pool **first_pool, void **first_tile, size_t t
                 struct pool *p;
 
                 n = *first_pool ? (*first_pool)->n_tiles : 0;
-                n = MAX(512U, n * 2);
+                n = MAX(at_least, n * 2);
                 size = PAGE_ALIGN(ALIGN(sizeof(struct pool)) + n*tile_size);
                 n = (size - ALIGN(sizeof(struct pool))) / tile_size;
 
@@ -191,7 +192,7 @@ Hashmap *hashmap_new(hash_func_t hash_func, compare_func_t compare_func) {
         size = ALIGN(sizeof(Hashmap)) + INITIAL_N_BUCKETS * sizeof(struct hashmap_entry*);
 
         if (b) {
-                h = allocate_tile(&first_hashmap_pool, &first_hashmap_tile, size);
+                h = allocate_tile(&first_hashmap_pool, &first_hashmap_tile, size, 8);
                 if (!h)
                         return NULL;
 
@@ -476,7 +477,7 @@ int hashmap_put(Hashmap *h, const void *key, void *value) {
                 hash = bucket_hash(h, key);
 
         if (h->from_pool)
-                e = allocate_tile(&first_entry_pool, &first_entry_tile, sizeof(struct hashmap_entry));
+                e = allocate_tile(&first_entry_pool, &first_entry_tile, sizeof(struct hashmap_entry), 64U);
         else
                 e = new(struct hashmap_entry, 1);
 

commit e8372f7e3e3a5aba053b1b5b944cb84d6d525877
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Nov 19 21:02:16 2013 +0100

    install: when determining where default.target points to, accept a file instead of a symlink, too

diff --git a/src/shared/install.c b/src/shared/install.c
index 881f715..2c119e2 100644
--- a/src/shared/install.c
+++ b/src/shared/install.c
@@ -1638,10 +1638,14 @@ int unit_file_get_default(
                 r = readlink_malloc(path, &tmp);
                 if (r == -ENOENT)
                         continue;
-                if (r < 0)
+                else if (r == -EINVAL)
+                        /* not a symlink */
+                        n = strdup(SPECIAL_DEFAULT_TARGET);
+                else if (r < 0)
                         return r;
+                else
+                        n = strdup(path_get_file_name(tmp));
 
-                n = strdup(path_get_file_name(tmp));
                 if (!n)
                         return -ENOMEM;
 

commit a454d241ef8b08e0984c6efbbd6187d70e32145b
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Nov 19 21:01:24 2013 +0100

    test: exit early if we would conflict with running user systemd

diff --git a/src/test/test-sched-prio.c b/src/test/test-sched-prio.c
index 1bbe867..aee75e8 100644
--- a/src/test/test-sched-prio.c
+++ b/src/test/test-sched-prio.c
@@ -35,7 +35,7 @@ int main(int argc, char *argv[]) {
         /* prepare the test */
         assert_se(set_unit_path(TEST_DIR) >= 0);
         r = manager_new(SYSTEMD_USER, false, &m);
-        if (r == -EPERM || r == -EACCES) {
+        if (r == -EPERM || r == -EACCES || r == -EADDRINUSE) {
                 puts("manager_new: Permission denied. Skipping test.");
                 return EXIT_TEST_SKIP;
         }
diff --git a/src/test/test-unit-name.c b/src/test/test-unit-name.c
index 67ccdd4..bde643a 100644
--- a/src/test/test-unit-name.c
+++ b/src/test/test-unit-name.c
@@ -125,7 +125,7 @@ static int test_unit_printf(void) {
         assert_se(asprintf(&root_uid, "%d", (int) root->pw_uid) > 0);
 
         r = manager_new(SYSTEMD_USER, false, &m);
-        if (r == -EPERM || r == -EACCES) {
+        if (r == -EPERM || r == -EACCES || r == -EADDRINUSE) {
                 puts("manager_new: Permission denied. Skipping test.");
                 return EXIT_TEST_SKIP;
         }

commit 911121a7c837040454c5d0422e2a225a8d799eef
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Nov 19 01:23:08 2013 +0100

    bus: add sd_bus_send_to() API call

diff --git a/src/libsystemd-bus/libsystemd-bus.sym b/src/libsystemd-bus/libsystemd-bus.sym
index a1ffc43..8fa2cde 100644
--- a/src/libsystemd-bus/libsystemd-bus.sym
+++ b/src/libsystemd-bus/libsystemd-bus.sym
@@ -43,9 +43,7 @@ global:
         sd_bus_can_send;
         sd_bus_get_server_id;
         sd_bus_send;
-        sd_bus_call;
-        sd_bus_call_async;
-        sd_bus_call_async_cancel;
+        sd_bus_send_to;
         sd_bus_get_fd;
         sd_bus_get_events;
         sd_bus_get_timeout;
diff --git a/src/libsystemd-bus/sd-bus.c b/src/libsystemd-bus/sd-bus.c
index 0be5a29..c8248e1 100644
--- a/src/libsystemd-bus/sd-bus.c
+++ b/src/libsystemd-bus/sd-bus.c
@@ -1435,6 +1435,27 @@ _public_ int sd_bus_send(sd_bus *bus, sd_bus_message *m, uint64_t *serial) {
         return 1;
 }
 
+_public_ int sd_bus_send_to(sd_bus *bus, sd_bus_message *m, const char *destination, uint64_t *serial) {
+        int r;
+
+        assert_return(bus, -EINVAL);
+        assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
+        assert_return(m, -EINVAL);
+        assert_return(!bus_pid_changed(bus), -ECHILD);
+
+        if (!streq_ptr(m->destination, destination)) {
+
+                if (!destination)
+                        return -EEXIST;
+
+                r = sd_bus_message_set_destination(m, destination);
+                if (r < 0)
+                        return r;
+        }
+
+        return sd_bus_send(bus, m, serial);
+}
+
 static usec_t calc_elapse(uint64_t usec) {
         if (usec == (uint64_t) -1)
                 return 0;
diff --git a/src/systemd/sd-bus.h b/src/systemd/sd-bus.h
index d56f8b3..072b54f 100644
--- a/src/systemd/sd-bus.h
+++ b/src/systemd/sd-bus.h
@@ -94,6 +94,7 @@ int sd_bus_can_send(sd_bus *bus, char type);
 int sd_bus_get_server_id(sd_bus *bus, sd_id128_t *peer);
 
 int sd_bus_send(sd_bus *bus, sd_bus_message *m, uint64_t *serial);
+int sd_bus_send_to(sd_bus *bus, sd_bus_message *m, const char *destination, uint64_t *serial);
 int sd_bus_call(sd_bus *bus, sd_bus_message *m, uint64_t usec, sd_bus_error *error, sd_bus_message **reply);
 int sd_bus_call_async(sd_bus *bus, sd_bus_message *m, sd_bus_message_handler_t callback, void *userdata, uint64_t usec, uint64_t *serial);
 int sd_bus_call_async_cancel(sd_bus *bus, uint64_t serial);
@@ -225,6 +226,7 @@ int sd_bus_get_property_trivial(sd_bus *bus, const char *destination, const char
 int sd_bus_get_property_string(sd_bus *bus, const char *destination, const char *path, const char *interface, const char *member, sd_bus_error *error, char **ret); /* free the result! */
 int sd_bus_get_property_strv(sd_bus *bus, const char *destination, const char *path, const char *interface, const char *member, sd_bus_error *error, char ***ret); /* free the result! */
 int sd_bus_set_property(sd_bus *bus, const char *destination, const char *path, const char *interface, const char *member, sd_bus_error *error, const char *type, ...);
+
 int sd_bus_reply_method_return(sd_bus *bus, sd_bus_message *call, const char *types, ...);
 int sd_bus_reply_method_error(sd_bus *bus, sd_bus_message *call, const sd_bus_error *e);
 int sd_bus_reply_method_errorf(sd_bus *bus, sd_bus_message *call, const char *name, const char *format, ...) _sd_printf_(4, 0);

commit aea93debfa1281a7d5f1523225b043955c1c2472
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Nov 19 01:21:27 2013 +0100

    bus: bump serial number counter when sending already sealed messages

diff --git a/src/libsystemd-bus/sd-bus.c b/src/libsystemd-bus/sd-bus.c
index d93138b..0be5a29 100644
--- a/src/libsystemd-bus/sd-bus.c
+++ b/src/libsystemd-bus/sd-bus.c
@@ -1271,8 +1271,13 @@ static int bus_seal_message(sd_bus *b, sd_bus_message *m) {
         if (m->header->version > b->message_version)
                 return -EPERM;
 
-        if (m->sealed)
+        if (m->sealed) {
+                /* If we copy the same message to multiple
+                 * destinations, avoid using the same serial
+                 * numbers. */
+                b->serial = MAX(b->serial, BUS_MESSAGE_SERIAL(m));
                 return 0;
+        }
 
         return bus_message_seal(m, ++b->serial);
 }

commit 80c1974018fef49d74736c6893674e8e6eddd1d4
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Nov 19 01:19:02 2013 +0100

    bus: sd_bus_error_setxyz calls should always return the error as errno style negative int

diff --git a/src/libsystemd-bus/bus-error.c b/src/libsystemd-bus/bus-error.c
index 1a467cf..652d8e2 100644
--- a/src/libsystemd-bus/bus-error.c
+++ b/src/libsystemd-bus/bus-error.c
@@ -74,7 +74,7 @@ _public_ int sd_bus_error_set(sd_bus_error *e, const char *name, const char *mes
         e->message = m;
         e->need_free = true;
 
-        return 0;
+        return sd_bus_error_get_errno(e);
 }
 
 int bus_error_setfv(sd_bus_error *e, const char *name, const char *format, va_list ap) {
@@ -103,7 +103,7 @@ int bus_error_setfv(sd_bus_error *e, const char *name, const char *format, va_li
         e->message = m;
         e->need_free = true;
 
-        return 0;
+        return sd_bus_error_get_errno(e);
 }
 
 _public_ int sd_bus_error_setf(sd_bus_error *e, const char *name, const char *format, ...) {
@@ -147,7 +147,7 @@ _public_ int sd_bus_error_copy(sd_bus_error *dest, const sd_bus_error *e) {
         dest->name = x;
         dest->message = y;
         dest->need_free = true;
-        return 0;
+        return sd_bus_error_get_errno(e);
 }
 
 _public_ int sd_bus_error_set_const(sd_bus_error *e, const char *name, const char *message) {
@@ -158,7 +158,7 @@ _public_ int sd_bus_error_set_const(sd_bus_error *e, const char *name, const cha
         assert_return(name, -EINVAL);
 
         *e = SD_BUS_ERROR_MAKE(name, message);
-        return 0;
+        return sd_bus_error_get_errno(e);
 }
 
 _public_ int sd_bus_error_is_set(const sd_bus_error *e) {
@@ -396,7 +396,7 @@ int bus_error_set_errnofv(sd_bus_error *e, int error, const char *format, va_lis
                 error = -error;
 
         if (!e)
-                return 0;
+                return -error;
 
         assert_return(!bus_error_is_dirty(e), -EINVAL);
 
@@ -428,8 +428,11 @@ fallback:
 _public_ int sd_bus_error_set_errnof(sd_bus_error *e, int error, const char *format, ...) {
         int r;
 
+        if (error < 0)
+                error = -error;
+
         if (!e)
-                return 0;
+                return -error;
 
         assert_return(!bus_error_is_dirty(e), -EINVAL);
 

commit 725d7e6cebcafef3bd4adbf76c8fa73a9b18972e
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Nov 19 01:15:31 2013 +0100

    libudev: always return NULL in _unref() APIs
    
    Returning anything else but NULL would suggest the caller's reference
    might still be valid, but it isn't, because the caller just invoked
    _unref() after all.
    
    This turns the return value into a typesafe shortcut that allows
    unreffing and resetting a reference in one line. In contrast to
    solutions for this which take a pointer to a pointer to accomplish the
    same this solution is just syntactic sugar the developer can make use of
    but doesn't have to, and this is particularly useful when immediately
    unreffing objects returned by function calls.

diff --git a/src/libudev/libudev-device.c b/src/libudev/libudev-device.c
index b5b07fc..059a590 100644
--- a/src/libudev/libudev-device.c
+++ b/src/libudev/libudev-device.c
@@ -1090,7 +1090,7 @@ _public_ struct udev_device *udev_device_ref(struct udev_device *udev_device)
  * Drop a reference of a udev device. If the refcount reaches zero,
  * the resources of the device will be released.
  *
- * Returns: the passed udev device if it has still an active reference, or #NULL otherwise.
+ * Returns: #NULL
  **/
 _public_ struct udev_device *udev_device_unref(struct udev_device *udev_device)
 {
@@ -1098,7 +1098,7 @@ _public_ struct udev_device *udev_device_unref(struct udev_device *udev_device)
                 return NULL;
         udev_device->refcount--;
         if (udev_device->refcount > 0)
-                return udev_device;
+                return NULL;
         if (udev_device->parent_device != NULL)
                 udev_device_unref(udev_device->parent_device);
         free(udev_device->syspath);
diff --git a/src/libudev/libudev-enumerate.c b/src/libudev/libudev-enumerate.c
index e71d766..48ffe83 100644
--- a/src/libudev/libudev-enumerate.c
+++ b/src/libudev/libudev-enumerate.c
@@ -122,7 +122,7 @@ _public_ struct udev_enumerate *udev_enumerate_ref(struct udev_enumerate *udev_e
  * Drop a reference of an enumeration context. If the refcount reaches zero,
  * all resources of the enumeration context will be released.
  *
- * Returns: the passed enumeration context if it has still an active reference, or #NULL otherwise.
+ * Returns: #NULL
  **/
 _public_ struct udev_enumerate *udev_enumerate_unref(struct udev_enumerate *udev_enumerate)
 {
@@ -132,7 +132,7 @@ _public_ struct udev_enumerate *udev_enumerate_unref(struct udev_enumerate *udev
                 return NULL;
         udev_enumerate->refcount--;
         if (udev_enumerate->refcount > 0)
-                return udev_enumerate;
+                return NULL;
         udev_list_cleanup(&udev_enumerate->sysattr_match_list);
         udev_list_cleanup(&udev_enumerate->sysattr_nomatch_list);
         udev_list_cleanup(&udev_enumerate->subsystem_match_list);
diff --git a/src/libudev/libudev-hwdb.c b/src/libudev/libudev-hwdb.c
index de1cb83..b53b35c 100644
--- a/src/libudev/libudev-hwdb.c
+++ b/src/libudev/libudev-hwdb.c
@@ -334,14 +334,14 @@ _public_ struct udev_hwdb *udev_hwdb_ref(struct udev_hwdb *hwdb) {
  * Drop a reference of a hwdb context. If the refcount reaches zero,
  * all resources of the hwdb context will be released.
  *
- * Returns: the passed hwdb context if it has still an active reference, or #NULL otherwise.
+ * Returns: #NULL
  **/
 _public_ struct udev_hwdb *udev_hwdb_unref(struct udev_hwdb *hwdb) {
         if (!hwdb)
                 return NULL;
         hwdb->refcount--;
         if (hwdb->refcount > 0)
-                return hwdb;
+                return NULL;
         if (hwdb->map)
                 munmap((void *)hwdb->map, hwdb->st.st_size);
         if (hwdb->f)
diff --git a/src/libudev/libudev-monitor.c b/src/libudev/libudev-monitor.c
index 24efdc6..56a6c5e 100644
--- a/src/libudev/libudev-monitor.c
+++ b/src/libudev/libudev-monitor.c
@@ -408,7 +408,7 @@ _public_ struct udev_monitor *udev_monitor_ref(struct udev_monitor *udev_monitor
  * the bound socket will be closed, and the resources of the monitor
  * will be released.
  *
- * Returns: the passed udev monitor if it has still an active reference, or #NULL otherwise.
+ * Returns: #NULL
  **/
 _public_ struct udev_monitor *udev_monitor_unref(struct udev_monitor *udev_monitor)
 {
@@ -416,7 +416,7 @@ _public_ struct udev_monitor *udev_monitor_unref(struct udev_monitor *udev_monit
                 return NULL;
         udev_monitor->refcount--;
         if (udev_monitor->refcount > 0)
-                return udev_monitor;
+                return NULL;
         if (udev_monitor->sock >= 0)
                 close(udev_monitor->sock);
         udev_list_cleanup(&udev_monitor->filter_subsystem_list);
diff --git a/src/libudev/libudev-queue.c b/src/libudev/libudev-queue.c
index 0dd2031..f67dba9 100644
--- a/src/libudev/libudev-queue.c
+++ b/src/libudev/libudev-queue.c
@@ -101,7 +101,7 @@ _public_ struct udev_queue *udev_queue_ref(struct udev_queue *udev_queue)
  * Drop a reference of a udev queue context. If the refcount reaches zero,
  * the resources of the queue context will be released.
  *
- * Returns: the passed queue context if it has still an active reference, or #NULL otherwise.
+ * Returns: #NULL
  **/
 _public_ struct udev_queue *udev_queue_unref(struct udev_queue *udev_queue)
 {
@@ -109,7 +109,7 @@ _public_ struct udev_queue *udev_queue_unref(struct udev_queue *udev_queue)
                 return NULL;
         udev_queue->refcount--;
         if (udev_queue->refcount > 0)
-                return udev_queue;
+                return NULL;
         udev_list_cleanup(&udev_queue->queue_list);
         free(udev_queue);
         return NULL;

commit 994e023433e020e2b3f683d5d1f2c974db580447
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Nov 19 01:14:21 2013 +0100

    libudev: always return valid negative error codes on API functions

diff --git a/src/libudev/libudev-device.c b/src/libudev/libudev-device.c
index d7f672f..b5b07fc 100644
--- a/src/libudev/libudev-device.c
+++ b/src/libudev/libudev-device.c
@@ -536,7 +536,7 @@ int udev_device_read_db(struct udev_device *udev_device, const char *dbfile)
         f = fopen(dbfile, "re");
         if (f == NULL) {
                 udev_dbg(udev_device->udev, "no db file to read %s: %m\n", dbfile);
-                return -1;
+                return -errno;
         }
         udev_device->is_initialized = true;
 
@@ -593,7 +593,7 @@ int udev_device_read_uevent_file(struct udev_device *udev_device)
         strscpyl(filename, sizeof(filename), udev_device->syspath, "/uevent", NULL);
         f = fopen(filename, "re");
         if (f == NULL)
-                return -1;
+                return -errno;
         udev_device->uevent_loaded = true;
 
         while (fgets(line, sizeof(line), f)) {
@@ -1521,13 +1521,13 @@ static int udev_device_sysattr_list_read(struct udev_device *udev_device)
         int num = 0;
 
         if (udev_device == NULL)
-                return -1;
+                return -EINVAL;
         if (udev_device->sysattr_list_read)
                 return 0;
 
         dir = opendir(udev_device_get_syspath(udev_device));
         if (!dir)
-                return -1;
+                return -errno;
 
         for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) {
                 char path[UTIL_PATH_SIZE];
diff --git a/src/libudev/libudev-monitor.c b/src/libudev/libudev-monitor.c
index 0212792..24efdc6 100644
--- a/src/libudev/libudev-monitor.c
+++ b/src/libudev/libudev-monitor.c
@@ -288,7 +288,7 @@ _public_ int udev_monitor_filter_update(struct udev_monitor *udev_monitor)
                         bpf_stmt(ins, &i, BPF_RET|BPF_K, 0xffffffff);
 
                         if (i+1 >= ELEMENTSOF(ins))
-                                return -1;
+                                return -E2BIG;
                 }
 
                 /* nothing matched, drop packet */
@@ -303,7 +303,7 @@ _public_ int udev_monitor_filter_update(struct udev_monitor *udev_monitor)
         filter.len = i;
         filter.filter = ins;
         err = setsockopt(udev_monitor->sock, SOL_SOCKET, SO_ATTACH_FILTER, &filter, sizeof(filter));
-        return err;
+        return err < 0 ? -errno : 0;
 }
 
 int udev_monitor_allow_unicast_sender(struct udev_monitor *udev_monitor, struct udev_monitor *sender)
@@ -350,7 +350,7 @@ _public_ int udev_monitor_enable_receiving(struct udev_monitor *udev_monitor)
                         udev_monitor->snl.nl.nl_pid = snl.nl.nl_pid;
         } else {
                 udev_err(udev_monitor->udev, "bind failed: %m\n");
-                return err;
+                return -errno;
         }
 
         /* enable receiving of sender credentials */
@@ -371,7 +371,7 @@ _public_ int udev_monitor_enable_receiving(struct udev_monitor *udev_monitor)
 _public_ int udev_monitor_set_receive_buffer_size(struct udev_monitor *udev_monitor, int size)
 {
         if (udev_monitor == NULL)
-                return -1;
+                return -EINVAL;
         return setsockopt(udev_monitor->sock, SOL_SOCKET, SO_RCVBUFFORCE, &size, sizeof(size));
 }
 
@@ -381,7 +381,7 @@ int udev_monitor_disconnect(struct udev_monitor *udev_monitor)
 
         err = close(udev_monitor->sock);
         udev_monitor->sock = -1;
-        return err;
+        return err < 0 ? -errno : 0;
 }
 
 /**
@@ -451,7 +451,7 @@ _public_ struct udev *udev_monitor_get_udev(struct udev_monitor *udev_monitor)
 _public_ int udev_monitor_get_fd(struct udev_monitor *udev_monitor)
 {
         if (udev_monitor == NULL)
-                return -1;
+                return -EINVAL;
         return udev_monitor->sock;
 }
 

commit 135168183ecb23f642b4f9fb9a50410e6735c628
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Nov 19 01:13:42 2013 +0100

    calendar: support 'yearly' and 'annually' names the same way as cron

diff --git a/src/shared/calendarspec.c b/src/shared/calendarspec.c
index 7979e23..7075159 100644
--- a/src/shared/calendarspec.c
+++ b/src/shared/calendarspec.c
@@ -686,6 +686,23 @@ int calendar_spec_from_string(const char *p, CalendarSpec **spec) {
                 if (r < 0)
                         goto fail;
 
+        } else if (strcaseeq(p, "anually") || strcaseeq(p, "yearly")) {
+                r = const_chain(1, &c->month);
+                if (r < 0)
+                        goto fail;
+                r = const_chain(1, &c->day);
+                if (r < 0)
+                        goto fail;
+                r = const_chain(0, &c->hour);
+                if (r < 0)
+                        goto fail;
+                r = const_chain(0, &c->minute);
+                if (r < 0)
+                        goto fail;
+                r = const_chain(0, &c->second);
+                if (r < 0)
+                        goto fail;
+
         } else if (strcaseeq(p, "weekly")) {
 
                 c->weekdays_bits = 1;

commit 8e64fd110d85de45929cefcbf83aa506d60f8795
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Nov 19 01:12:03 2013 +0100

    hwclock: modernizations

diff --git a/src/shared/hwclock.c b/src/shared/hwclock.c
index 60292a0..7059d9c 100644
--- a/src/shared/hwclock.c
+++ b/src/shared/hwclock.c
@@ -44,8 +44,7 @@
 #include "fileio.h"
 
 int hwclock_get_time(struct tm *tm) {
-        int fd;
-        int err = 0;
+        _cleanup_close_ int fd = -1;
 
         assert(tm);
 
@@ -56,20 +55,17 @@ int hwclock_get_time(struct tm *tm) {
         /* This leaves the timezone fields of struct tm
          * uninitialized! */
         if (ioctl(fd, RTC_RD_TIME, tm) < 0)
-                err = -errno;
+                return -errno;
 
         /* We don't know daylight saving, so we reset this in order not
          * to confuse mktime(). */
         tm->tm_isdst = -1;
 
-        close_nointr_nofail(fd);
-
-        return err;
+        return 0;
 }
 
 int hwclock_set_time(const struct tm *tm) {
-        int fd;
-        int err = 0;
+        _cleanup_close_ int fd = -1;
 
         assert(tm);
 
@@ -78,11 +74,9 @@ int hwclock_set_time(const struct tm *tm) {
                 return -errno;
 
         if (ioctl(fd, RTC_SET_TIME, tm) < 0)
-                err = -errno;
-
-        close_nointr_nofail(fd);
+                return -errno;
 
-        return err;
+        return 0;
 }
 
 int hwclock_is_localtime(void) {

commit d3cfcae9db39b0cd01bd8c3db1dc57d6a04554a4
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Nov 19 01:10:40 2013 +0100

    macro: add _unlikely_() to assert_return()
    
    As the name indicates assert_return() is really just for assertions,
    i.e. where it's a programming error if the assertion does not hold.
    Hence it is safe to add _unlikely_() decorators for the expression to
    check.

diff --git a/src/shared/macro.h b/src/shared/macro.h
index 37cdff1..c22de91 100644
--- a/src/shared/macro.h
+++ b/src/shared/macro.h
@@ -150,7 +150,7 @@ static inline size_t ALIGN_TO(size_t l, size_t ali) {
 
 #define assert_return(expr, r)                    \
         do {                                      \
-                if (!(expr))                      \
+                if (_unlikely_(!(expr)))          \
                         return (r);               \
         } while (false)
 

commit 780dbeef9f9d2c9f416da50a07bf0aacf3cc66c7
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Nov 19 01:10:22 2013 +0100

    macro: change assert_cc() so that it can appear outside of functions

diff --git a/src/shared/macro.h b/src/shared/macro.h
index 9e94495..37cdff1 100644
--- a/src/shared/macro.h
+++ b/src/shared/macro.h
@@ -143,19 +143,9 @@ static inline size_t ALIGN_TO(size_t l, size_t ali) {
         } while (false)
 
 #if defined(static_assert)
-#define assert_cc(expr)                         \
-        do {                                    \
-                static_assert(expr, #expr);     \
-        } while (false)
+#define assert_cc(expr) static_assert(expr, #expr)
 #else
-#define assert_cc(expr)                         \
-        do {                                    \
-                switch (0) {                    \
-                case 0:                         \
-                case !!(expr):                  \
-                        ;                       \
-                }                               \
-        } while (false)
+#define assert_cc(expr) struct _assert_struct_ ## __LINE__ { char x[(expr) ? 0 : -1]; }
 #endif
 
 #define assert_return(expr, r)                    \

commit fd1b903adb6f7b06d263fcb6a4ae01d734b2c8d4
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Nov 19 01:09:48 2013 +0100

    include: make direct includion of _sd-common.h harder

diff --git a/src/systemd/_sd-common.h b/src/systemd/_sd-common.h
index 594ff3d..cc3be93 100644
--- a/src/systemd/_sd-common.h
+++ b/src/systemd/_sd-common.h
@@ -24,6 +24,10 @@
 
 /* This is a private header, never even think of including this directly! */
 
+#if __INCLUDE_LEVEL__ <= 1
+#error "Do not include _sd-common.h directly, it is a private header."
+#endif
+
 #ifndef _sd_printf_
 #  if __GNUC__ >= 4
 #    define _sd_printf_(a,b) __attribute__ ((format (printf, a, b)))

commit 16ed0233a5b7ae38ed4f544d6fcd5827cde695dc
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Nov 19 01:09:12 2013 +0100

    install: use const where we can

diff --git a/src/core/bus-errors.h b/src/core/bus-errors.h
deleted file mode 100644
index 9368d68..0000000
--- a/src/core/bus-errors.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#pragma once
-
-/***
-  This file is part of systemd.
-
-  Copyright 2010 Lennart Poettering
-
-  systemd is free software; you can redistribute it and/or modify it
-  under the terms of the GNU Lesser General Public License as published by
-  the Free Software Foundation; either version 2.1 of the License, or
-  (at your option) any later version.
-
-  systemd is distributed in the hope that it will be useful, but
-  WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-  Lesser General Public License for more details.
-
-  You should have received a copy of the GNU Lesser General Public License
-  along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#define BUS_ERROR_NO_SUCH_UNIT "org.freedesktop.systemd1.NoSuchUnit"
-#define BUS_ERROR_NO_SUCH_JOB "org.freedesktop.systemd1.NoSuchJob"
-#define BUS_ERROR_NOT_SUBSCRIBED "org.freedesktop.systemd1.NotSubscribed"
-#define BUS_ERROR_INVALID_PATH "org.freedesktop.systemd1.InvalidPath"
-#define BUS_ERROR_INVALID_NAME "org.freedesktop.systemd1.InvalidName"
-#define BUS_ERROR_UNIT_TYPE_MISMATCH "org.freedesktop.systemd1.UnitTypeMismatch"
-#define BUS_ERROR_UNIT_EXISTS "org.freedesktop.systemd1.UnitExists"
-#define BUS_ERROR_NOT_SUPPORTED "org.freedesktop.systemd1.NotSupported"
-#define BUS_ERROR_INVALID_JOB_MODE "org.freedesktop.systemd1.InvalidJobMode"
-#define BUS_ERROR_ONLY_BY_DEPENDENCY "org.freedesktop.systemd1.OnlyByDependency"
-#define BUS_ERROR_NO_ISOLATION "org.freedesktop.systemd1.NoIsolation"
-#define BUS_ERROR_LOAD_FAILED "org.freedesktop.systemd1.LoadFailed"
-#define BUS_ERROR_MASKED "org.freedesktop.systemd1.Masked"
-#define BUS_ERROR_JOB_TYPE_NOT_APPLICABLE "org.freedesktop.systemd1.JobTypeNotApplicable"
-#define BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE "org.freedesktop.systemd1.TransactionIsDestructive"
-#define BUS_ERROR_TRANSACTION_JOBS_CONFLICTING "org.freedesktop.systemd1.TransactionJobsConflicting"
-#define BUS_ERROR_TRANSACTION_ORDER_IS_CYCLIC "org.freedesktop.systemd1.TransactionOrderIsCyclic"
-#define BUS_ERROR_SHUTTING_DOWN "org.freedesktop.systemd1.ShuttingDown"
-#define BUS_ERROR_NO_SUCH_PROCESS "org.freedesktop.systemd1.NoSuchProcess"
-#define BUS_ERROR_JOB_FAILED "org.freedesktop.systemd1.JobFailed"
diff --git a/src/shared/install.c b/src/shared/install.c
index cfd4a5a..881f715 100644
--- a/src/shared/install.c
+++ b/src/shared/install.c
@@ -38,6 +38,7 @@
 #include "conf-files.h"
 #include "specifier.h"
 #include "install-printf.h"
+#include "special.h"
 
 typedef struct {
         Hashmap *will_install;
@@ -1560,7 +1561,7 @@ int unit_file_reenable(
 int unit_file_set_default(
                 UnitFileScope scope,
                 const char *root_dir,
-                char *file,
+                const char *file,
                 UnitFileChange **changes,
                 unsigned *n_changes) {
 
@@ -1573,6 +1574,7 @@ int unit_file_set_default(
 
         assert(scope >= 0);
         assert(scope < _UNIT_FILE_SCOPE_MAX);
+        assert(file);
 
         if (unit_name_to_type(file) != UNIT_TARGET)
                 return -EINVAL;
@@ -1589,13 +1591,14 @@ int unit_file_set_default(
         if (r < 0)
                 return r;
 
-        i = (InstallInfo*)hashmap_first(c.will_install);
+        assert_se(i = hashmap_first(c.will_install));
 
         r = unit_file_search(&c, i, &paths, root_dir, false);
         if (r < 0)
                 return r;
 
-        path = strappenda(config_path, "/default.target");
+        path = strappenda(config_path, "/" SPECIAL_DEFAULT_TARGET);
+
         r = create_symlink(i->path, path, true, changes, n_changes);
         if (r < 0)
                 return r;
@@ -1612,6 +1615,10 @@ int unit_file_get_default(
         char **p;
         int r;
 
+        assert(scope >= 0);
+        assert(scope < _UNIT_FILE_SCOPE_MAX);
+        assert(name);
+
         r = lookup_paths_init_from_scope(&paths, scope);
         if (r < 0)
                 return r;
@@ -1621,9 +1628,9 @@ int unit_file_get_default(
                 char *n;
 
                 if (isempty(root_dir))
-                        path = strappend(*p, "/default.target");
+                        path = strappend(*p, "/" SPECIAL_DEFAULT_TARGET);
                 else
-                        path = strjoin(root_dir, "/", *p, "/default.target", NULL);
+                        path = strjoin(root_dir, "/", *p, "/" SPECIAL_DEFAULT_TARGET, NULL);
 
                 if (!path)
                         return -ENOMEM;
diff --git a/src/shared/install.h b/src/shared/install.h
index 5609d1e..3c2e162 100644
--- a/src/shared/install.h
+++ b/src/shared/install.h
@@ -80,7 +80,7 @@ int unit_file_link(UnitFileScope scope, bool runtime, const char *root_dir, char
 int unit_file_preset(UnitFileScope scope, bool runtime, const char *root_dir, char *files[], bool force, UnitFileChange **changes, unsigned *n_changes);
 int unit_file_mask(UnitFileScope scope, bool runtime, const char *root_dir, char *files[], bool force, UnitFileChange **changes, unsigned *n_changes);
 int unit_file_unmask(UnitFileScope scope, bool runtime, const char *root_dir, char *files[], UnitFileChange **changes, unsigned *n_changes);
-int unit_file_set_default(UnitFileScope scope, const char *root_dir, char *file, UnitFileChange **changes, unsigned *n_changes);
+int unit_file_set_default(UnitFileScope scope, const char *root_dir, const char *file, UnitFileChange **changes, unsigned *n_changes);
 int unit_file_get_default(UnitFileScope scope, const char *root_dir, char **name);
 
 UnitFileState unit_file_get_state(UnitFileScope scope, const char *root_dir, const char *filename);



More information about the systemd-commits mailing list