libink is a small C library implementing the D-Bus wire protocol,
both the server and the client side, without a broker and without any
dependency on libdbus, sd-bus, or GIO. It was born inside Finit to
let PID 1 be a bus of its own: clients connect straight to the listening
socket, authenticate with the standard SASL EXTERNAL handshake, and get
kernel-authenticated credentials via SO_PEERCRED.
For what the bus exposes and how to talk to it, see the User Guide, D-Bus Integration. This file covers the library itself.
libink is an internal implementation detail of Finit: built as a libtool
convenience library, linked statically into finit and initctl,
nothing installed. There is deliberately no ABI promise yet — that
comes if/when libink is extracted into a project of its own. External
D-Bus clients need none of this; the wire protocol is the compatibility
surface, any standard D-Bus library works.
| File | Contents |
|---|---|
server.c |
Listening socket, accept, peer credential capture |
auth.c |
SASL EXTERNAL handshake, uid verification |
connection.c |
Per-peer state machine, message framing |
proto.c |
Wire header parse/build |
marshal.c |
Body (de)marshalling: basic types, arrays, variants |
dispatch.c |
Object tree, vtable registration, method dispatch |
builtin.c |
org.freedesktop.DBus.* stock interfaces |
match.c |
AddMatch/RemoveMatch rule parsing and signal filter |
path.c |
systemd-style _HH object path encoding |
client.c |
Outgoing connections, method calls, reply/signal wait |
io.c |
Shared EINTR-resilient read/write loops |
Public API symbols carry the link_* prefix (link.h), internal ones
__* (internal.h). Method handlers are registered as vtables of
link_method_t/link_property_t; the framework emits variant
signatures from the property table so the declared type is the single
source of truth.
The boundary to Finit is deliberate: nothing under libink/ includes a
Finit header. All glue lives in src/dbus.c — object registration,
signal emission from the service/condition/runlevel hook points, and
the uev event loop bridge. initctl uses the client half of the same
library, so one wire-format implementation serves both ends. If libink
is ever spun out, that file is the cut line.
Privileged methods over the system bus are root-only. Finit learns
the caller's uid from the broker with GetConnectionUnixUser, but that
reply carries no group list, so it cannot honour --with-group
membership there the way it does on the local bus (where the kernel
hands over the group set via SO_PEERGROUPS). Closing the gap means
asking the broker GetConnectionCredentials and reading its
UnixGroupIDs, which is a variant holding an au array — the reader
(marshal.c) only decodes single-character variant signatures today,
so it needs extending first. Finit's own direct users reach it over
the local bus, so this has not been pressing.
The test/dbus-*.sh suite exercises the library end to end against a
live Finit in a namespace, driven by test/src/dbus-auth-client.c.
Wire-format conformance against third-party tools (dbus-send,
dbus-monitor) and fuzzing of the parsers are tracked as pre-merge
work — this is PID 1's attack surface.