diff options
Diffstat (limited to 'src/ancillary-data.zig')
| -rw-r--r-- | src/ancillary-data.zig | 65 |
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); +} |