diff options
| author | Robby Zambito <contact@robbyzambito.me> | 2026-01-14 18:58:13 -0500 |
|---|---|---|
| committer | Robby Zambito <contact@robbyzambito.me> | 2026-01-14 19:34:35 -0500 |
| commit | 0d9c0c33fa7c7e73e2e8448ca2e8071584bfaf39 (patch) | |
| tree | ae002275aea17b02d9769f30c51f496bb1215221 /src/NetWriter.zig | |
| parent | b3f1b00510a6be9a4f792b6fbf7fd61797603eaa (diff) | |
Diffstat (limited to 'src/NetWriter.zig')
| -rw-r--r-- | src/NetWriter.zig | 238 |
1 files changed, 0 insertions, 238 deletions
diff --git a/src/NetWriter.zig b/src/NetWriter.zig deleted file mode 100644 index f0f617d..0000000 --- a/src/NetWriter.zig +++ /dev/null @@ -1,238 +0,0 @@ -//! Wraps a writer with UDP headers. -//! This is useful for wrapping RawSocket Writer with appropriate headers. - -rand: Random, -wrapped: *Writer, -interface: Writer, - -pub fn init(w: *Writer, buffer: []u8) !NetWriter { - std.debug.assert(buffer.len > @sizeOf(EthernetHeaders) + @sizeOf(IpHeaders) + @sizeOf(UdpHeaders)); - - var prng = Random.DefaultPrng.init(blk: { - var seed: u64 = undefined; - try posix.getrandom(mem.asBytes(&seed)); - break :blk seed; - }); - - return .{ - .rand = prng.random(), - .wrapped = w, - .interface = .{ - .vtable = &.{ - .drain = drain, - // .flush = flush, - }, - .buffer = buffer, - }, - }; -} - -fn drain(io_w: *Writer, data: []const []const u8, splat: usize) Writer.Error!usize { - const w: *NetWriter = @alignCast(@fieldParentPtr("interface", io_w)); - const headers_byte_len = comptime (EthernetHeaders.byte_len + (@bitSizeOf(IpHeaders) / 8) + @sizeOf(UdpHeaders)); - const headers: [headers_byte_len]u8 = blk: { - const ether_headers: EthernetHeaders = .{ - .dest_mac = .{ 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff }, - .src_mac = src_blk: { - var output_bytes: [6]u8 = undefined; - output_bytes[0] = 0xee; - w.rand.bytes(output_bytes[1..]); - break :src_blk output_bytes; - }, - .ether_type = 0x0800, - }; - - const total_len = Writer.countSplat(data, splat) + w.interface.end; - - const ip_headers: IpHeaders = .{ - // length of the packet minus eth header - .total_length = @intCast(headers_byte_len + total_len - EthernetHeaders.byte_len), //@intCast(total_len), - .ttl = 64, - .protocol = 0x11, - .src_ip = .{ 0xff, 0x02, 0x03, 0x04 }, - .dest_ip = .{ 0xff, 0xff, 0xff, 0xff }, - }; - - const udp_headers: UdpHeaders = .{ - .src_port = 0xbbbb, - .dest_port = 8888, - .length = @intCast(total_len + @sizeOf(UdpHeaders)), - }; - - var buf: [headers_byte_len]u8 = undefined; - var buf_w = Writer.fixed(&buf); - - _ = try ether_headers.write(&buf_w); - try ip_headers.write(&buf_w); - try buf_w.writeStruct(udp_headers, .big); - - break :blk buf; - }; - - _ = try w.wrapped.write(&headers); - const total_len = try w.wrapped.writeSplatHeader(w.interface.buffered(), data, splat); - - try w.wrapped.flush(); - return total_len - w.interface.consumeAll(); -} - -const EthernetHeaders = struct { - dest_mac: @Vector(6, u8), - - src_mac: @Vector(6, u8), - - ether_type: u16, - - fn write(hdr: EthernetHeaders, writer: *std.Io.Writer) Writer.Error!usize { - try writer.writeInt(u48, @bitCast(hdr.dest_mac), .big); - try writer.writeInt(u48, @bitCast(hdr.src_mac), .big); - try writer.writeInt(u16, hdr.ether_type, .big); - return byte_len; - } - - const byte_len = blk: { - var res: usize = 0; - res += @bitSizeOf(u48) / 8; - res += @bitSizeOf(u48) / 8; - res += @bitSizeOf(u16) / 8; - break :blk res; - }; - - fn bytes(hdr: EthernetHeaders) [byte_len]u8 { - var res: [byte_len]u8 = undefined; - hdr.write(Writer.fixed(&res)) catch unreachable; - } -}; - -const IpHeaders = extern struct { - dest_ip: @Vector(4, u8) align(1), - src_ip: @Vector(4, u8) align(1), - header_checksum: @Vector(2, u8) align(1) = .{ 0, 0 }, - protocol: u8 align(1) = 0, - ttl: u8 align(1) = 0, - fragment_and_flags: packed struct(u16) { - fragment_offset: u13 = 0, - ethernet_flags: u3 = 0, - } = .{}, - // fragment_offset: u13 = 0, - // ethernet_flags: u3 = 0, - identification: u16 align(1) = 0, - total_length: u16 align(1) = 0x04, - type_of_service: u8 align(1) = 0, - header_and_version: packed struct(u8) { - header_length: u4 = 5, - ip_version: u4 = 4, - } = .{}, - // header_length: u4 = 5, - // ip_version: u4 = 4, - - fn write(hdr: IpHeaders, writer: *std.Io.Writer) Writer.Error!void { - try writer.writeInt(u8, 0x45, .big); // ip version and header length - try writer.writeByte(hdr.type_of_service); - try writer.writeInt(u16, hdr.total_length, .big); - try writer.writeInt(u16, hdr.identification, .big); - try writer.writeInt(u16, 0x00, .big); // ethernet flags and fragment offset - try writer.writeByte(hdr.ttl); - try writer.writeByte(hdr.protocol); - try writer.writeInt(u16, @bitCast(hdr.header_checksum), .big); - try writer.writeInt(u32, @bitCast(hdr.src_ip), .big); - try writer.writeInt(u32, @bitCast(hdr.dest_ip), .big); - } - - fn bytes(hdr: IpHeaders) [@bitSizeOf(IpHeaders) / 8]u8 { - var res: [@bitSizeOf(IpHeaders) / 8]u8 = undefined; - var w = Writer.fixed(&res); - _ = hdr.write(&w) catch unreachable; - return res; - } -}; - -test IpHeaders { - var a: IpHeaders = .{ - .dest_ip = .{ 1, 2, 3, 4 }, - .src_ip = .{ 5, 6, 7, 8 }, - // .header_checksum = .{ 0x1, 0x1 }, - // .protocol = 0, - // .ttl = 0x64, - // .identification = 3, - // .type_of_service = 7, - }; - // a.dest_ip = .{ 1, 2, 3, 4 }; - // a.src_ip = .{ 5, 6, 7, 8 }; - std.debug.print("ip struct: {}\n", .{a}); - std.debug.print("dest ip: {}\n", .{a.dest_ip}); - std.debug.print("src ip: {}\n", .{a.src_ip}); - - std.debug.print("raw b : {x}\n", .{@as([@bitSizeOf(IpHeaders) / 8]u8, @bitCast(a))}); - - std.debug.print("ip bytes: {x}\n", .{a.bytes()}); - var a_struct: [@bitSizeOf(IpHeaders) / 8]u8 = undefined; - var a_struct_w = Writer.fixed(&a_struct); - _ = a_struct_w.writeStruct(a, .big) catch unreachable; - std.debug.print("ip struct: {x}\n", .{a_struct}); - try std.testing.expectEqual(a, a); -} - -const UdpHeaders = packed struct { - checksum: @Vector(2, u8) = .{ 0, 0 }, - length: u16, - dest_port: u16, - src_port: u16, - - fn write(hdr: UdpHeaders, writer: *std.Io.Writer) Writer.Error!void { - try writer.writeStruct(hdr, .big); - } - - fn bytes(hdr: UdpHeaders) [@sizeOf(UdpHeaders)]u8 { - var res: [@sizeOf(UdpHeaders)]u8 = undefined; - var w = Writer.fixed(&res); - _ = hdr.write(&w) catch unreachable; - return res; - } -}; - -test UdpHeaders { - const a: UdpHeaders = .{ - .src_port = 1, - .dest_port = 2, - .length = 3, - .checksum = .{ 0x04, 0x05 }, - }; - var a_struct: [@sizeOf(UdpHeaders)]u8 = undefined; - var a_struct_w = Writer.fixed(&a_struct); - _ = a_struct_w.writeStruct(a, .big) catch unreachable; - try std.testing.expectEqual(a.bytes(), a_struct); -} - -const std = @import("std"); -const Random = std.Random; -const posix = std.posix; -const Writer = std.Io.Writer; -const mem = std.mem; - -const NetWriter = @This(); - -const saprusOptions: std.Io.net.BindOptions = .{ - .mode = .raw, - .protocol = 0, -}; - -fn netSaprusBindIpPosix( - userdata: ?*anyopaque, - address: *const IpAddress, - options: IpAddress.BindOptions, -) IpAddress.BindError!net.Socket { - if (!have_networking) return error.NetworkDown; - const t: *Threaded = @ptrCast(@alignCast(userdata)); - const family = std.os.linux.PF.PACKET; - const socket_fd = try openSocketPosix(t, family, options); - errdefer posix.close(socket_fd); - var storage: PosixAddress = undefined; - var addr_len = addressToPosix(address, &storage); - try posixBind(t, socket_fd, &storage.any, addr_len); - try posixGetSockName(t, socket_fd, &storage.any, &addr_len); - return .{ - .handle = socket_fd, - .address = addressFromPosix(&storage), - }; -} |
