aboutsummaryrefslogtreecommitdiff
path: root/src/ancillary-data.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/ancillary-data.zig')
-rw-r--r--src/ancillary-data.zig65
1 files changed, 65 insertions, 0 deletions
diff --git a/src/ancillary-data.zig b/src/ancillary-data.zig
new file mode 100644
index 0000000..0754720
--- /dev/null
+++ b/src/ancillary-data.zig
@@ -0,0 +1,65 @@
+const std = @import("std");
+
+const ControlMessage = extern struct {
+ const Level = enum(u32) {
+ socket = std.posix.SOL.SOCKET,
+ };
+
+ // WARNING: this kind enum might be wrong for non-linux posix systems.
+ const Kind = enum(u32) {
+ rights = 1,
+ credentials = 2,
+ };
+
+ const Header = extern struct {
+ length: usize,
+ level: Level,
+ kind: Kind,
+ };
+
+ header: Header,
+ payload: union {
+ fd: [255]std.posix.fd_t,
+ },
+
+ pub fn alignment(length: usize) usize {
+ return (length + @sizeOf(usize) - 1) & ~(@sizeOf(usize) - 1);
+ }
+
+ pub fn space(self: @This()) usize {
+ return self.alignment(self.length) + self.alignment(@sizeOf(Header));
+ }
+
+ pub fn from_fds(fds: []std.posix.fd_t) @This() {
+ var self: @This() = .{
+ };
+
+ self.level = .socket;
+ self.kind = .rights;
+ self.length = self.alignment(@sizeOf(Header)) + (fds.len * @sizeOf(std.posix.fd_t));
+
+ @memcpy(self.payload, fds);
+ }
+};
+
+pub fn send_fds(socket: std.posix.socket_t, fds: []std.posix.fd_t) !void {
+ var iobuf: [1]u8 = std.mem.zeroes([1]u8);
+
+ const io = std.posix.iovec {
+ .base = &iobuf,
+ .len = iobuf.len,
+ };
+
+ var cmsg: ControlMessage = .from_fds(fds);
+
+ const msghdr = std.posix.msghdr_const {
+ .name = null,
+ .namelen = 0,
+ .iov = &io,
+ .iolen = 1,
+ .control = &cmsg,
+ .controllen = cmsg.control_length(),
+ };
+
+ _ = try std.posix.sendmsg(socket, &msghdr, 0);
+}