From d6da3cd31b1f4f66aa61ea7a68fa4ab9782fd2c2 Mon Sep 17 00:00:00 2001 From: Robby Zambito Date: Sun, 12 Oct 2025 18:06:55 -0400 Subject: IT'S RIGHT --- src/NetWriter.zig | 135 ++++++++++++++++++++++++------------------------ src/RawSocketWriter.zig | 3 ++ src/main.zig | 5 +- 3 files changed, 73 insertions(+), 70 deletions(-) (limited to 'src') diff --git a/src/NetWriter.zig b/src/NetWriter.zig index b08ccfe..42d3c91 100644 --- a/src/NetWriter.zig +++ b/src/NetWriter.zig @@ -5,8 +5,8 @@ rand: Random, wrapped: *Writer, interface: Writer, -pub fn init(w: *Writer) !NetWriter { - std.debug.assert(w.buffer.len > @sizeOf(EthernetHeaders) + @sizeOf(IpHeaders) + @sizeOf(UdpHeaders)); +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; @@ -20,33 +20,34 @@ pub fn init(w: *Writer) !NetWriter { .interface = .{ .vtable = &.{ .drain = drain, - .flush = flush, + // .flush = flush, }, - .buffer = &.{}, + .buffer = buffer, }, }; } fn drain(io_w: *Writer, data: []const []const u8, splat: usize) Writer.Error!usize { const w: *NetWriter = @alignCast(@fieldParentPtr("interface", io_w)); - - var res: usize = 0; - - if (io_w.end == 0) { + const headers_byte_len = comptime (EthernetHeaders.byte_len + IpHeaders.byte_len + UdpHeaders.byte_len); + const headers: [headers_byte_len]u8 = blk: { const ether_headers: EthernetHeaders = .{ .dest_mac = .{ 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff }, - .src_mac = blk: { + .src_mac = src_blk: { var output_bytes: [6]u8 = undefined; output_bytes[0] = 0xee; w.rand.bytes(output_bytes[1..]); - break :blk output_bytes; + break :src_blk output_bytes; }, .ether_type = 0x0800, }; + const total_len = Writer.countSplat(data, splat) + w.interface.end; + const ip_headers: IpHeaders = .{ - .total_length = @intCast(res - 92), - .ttl = 0x64, + // 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 }, @@ -55,23 +56,35 @@ fn drain(io_w: *Writer, data: []const []const u8, splat: usize) Writer.Error!usi const udp_headers: UdpHeaders = .{ .src_port = 0xbbbb, .dest_port = 8888, - .length = @intCast(res), + .length = @intCast(total_len + UdpHeaders.byte_len), }; - res += try ether_headers.write(w.wrapped); - res += try ip_headers.write(w.wrapped); - res += try udp_headers.write(w.wrapped); - } + var buf: [headers_byte_len]u8 = undefined; + var buf_w = Writer.fixed(&buf); - res += try w.wrapped.writeSplat(data, splat); - return res; -} + _ = try ether_headers.write(&buf_w); + _ = try ip_headers.write(&buf_w); + std.debug.print("after ip: {x}\n", .{buf_w.buffered()}); + _ = try udp_headers.write(&buf_w); + std.debug.print("after udp: {x}\n", .{buf_w.buffered()}); + + break :blk buf; + }; + + _ = try w.wrapped.write(&headers); + const total_len = try w.wrapped.writeSplatHeader(w.interface.buffered(), data, splat); + + std.debug.print("total splat: {}\theaders.len: {}\tsplat: {}\n", .{ total_len, headers.len, splat }); -fn flush(io_w: *Writer) Writer.Error!void { - const w: *NetWriter = @alignCast(@fieldParentPtr("interface", io_w)); try w.wrapped.flush(); + return total_len - w.interface.consumeAll(); } +// fn flush(io_w: *Writer) Writer.Error!void { +// const w: *NetWriter = @alignCast(@fieldParentPtr("interface", io_w)); +// try io_w.defaultFlush(); +// } + const EthernetHeaders = struct { dest_mac: @Vector(6, u8), @@ -80,21 +93,19 @@ const EthernetHeaders = struct { ether_type: u16, fn write(hdr: EthernetHeaders, writer: *std.Io.Writer) Writer.Error!usize { - comptime var res: usize = 0; - - res += @sizeOf(u48); try writer.writeInt(u48, @bitCast(hdr.dest_mac), .big); - - res += @sizeOf(u48); try writer.writeInt(u48, @bitCast(hdr.src_mac), .big); - - res += @sizeOf(u16); try writer.writeInt(u16, hdr.ether_type, .big); - - return res; + return byte_len; } - const byte_len = @bitSizeOf(EthernetHeaders) / 8; + 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; @@ -120,42 +131,33 @@ const IpHeaders = struct { dest_ip: @Vector(4, u8), fn write(hdr: @This(), writer: *std.Io.Writer) Writer.Error!usize { - comptime var res: usize = 0; - - res += @sizeOf(u8); try writer.writeInt(u8, 0x45, .big); // ip version and header length - - res += @sizeOf(u8); try writer.writeByte(hdr.type_of_service); - - res += @sizeOf(u16); try writer.writeInt(u16, hdr.total_length, .big); - - res += @sizeOf(u16); try writer.writeInt(u16, hdr.identification, .big); - - res += @sizeOf(u16); try writer.writeInt(u16, 0x00, .big); // ethernet flags and fragment offset - - res += @sizeOf(u8); try writer.writeByte(hdr.ttl); - - res += @sizeOf(u8); try writer.writeByte(hdr.protocol); - - res += @sizeOf(u16); try writer.writeInt(u16, @bitCast(hdr.header_checksum), .big); - - res += @sizeOf(u32); try writer.writeInt(u32, @bitCast(hdr.src_ip), .big); - - res += @sizeOf(u32); try writer.writeInt(u32, @bitCast(hdr.dest_ip), .big); - - return res; + return byte_len; } - const byte_len = @bitSizeOf(IpHeaders) / 8; + const byte_len = blk: { + var res: usize = 0; + res += @sizeOf(u8); + res += @sizeOf(u8); + res += @sizeOf(u16); + res += @sizeOf(u16); + res += @sizeOf(u16); + res += @sizeOf(u8); + res += @sizeOf(u8); + res += @sizeOf(u16); + res += @sizeOf(u32); + res += @sizeOf(u32); + break :blk res; + }; fn bytes(hdr: IpHeaders) [byte_len]u8 { var res: [byte_len]u8 = undefined; @@ -171,24 +173,21 @@ const UdpHeaders = packed struct { checksum: @Vector(2, u8) = .{ 0, 0 }, fn write(hdr: @This(), writer: *std.Io.Writer) Writer.Error!usize { - comptime var res: usize = 0; - - res += @sizeOf(u16); try writer.writeInt(u16, hdr.src_port, .big); - - res += @sizeOf(u16); try writer.writeInt(u16, hdr.dest_port, .big); - - res += @sizeOf(u16); try writer.writeInt(u16, hdr.length, .big); - - res += @sizeOf(u16); try writer.writeInt(u16, @bitCast(hdr.checksum), .big); - - return res; + return byte_len; } - const byte_len = @bitSizeOf(UdpHeaders) / 8; + const byte_len = blk: { + var res: usize = 0; + res += @sizeOf(u16); + res += @sizeOf(u16); + res += @sizeOf(u16); + res += @sizeOf(u16); + break :blk res; + }; fn bytes(hdr: UdpHeaders) [byte_len]u8 { var res: [byte_len]u8 = undefined; diff --git a/src/RawSocketWriter.zig b/src/RawSocketWriter.zig index a767729..89e5eb4 100644 --- a/src/RawSocketWriter.zig +++ b/src/RawSocketWriter.zig @@ -8,12 +8,14 @@ interface: Writer, socket: gcat.nic.RawSocket, fn drain(io_w: *std.Io.Writer, data: []const []const u8, splat: usize) Writer.Error!usize { + std.debug.print("in drain\n", .{}); const w: *RawSocketWriter = @alignCast(@fieldParentPtr("interface", io_w)); const rem_buf = io_w.unusedCapacitySlice(); var rem_w = Writer.fixed(rem_buf); const res = rem_w.writeSplat(data, splat) catch rem_buf.len; io_w.advance(res); const buffered = io_w.buffered(); + std.debug.print("buffer: {x}\n", .{buffered}); w.socket.linkLayer().send(buffered) catch return error.WriteFailed; _ = io_w.consumeAll(); @@ -21,6 +23,7 @@ fn drain(io_w: *std.Io.Writer, data: []const []const u8, splat: usize) Writer.Er } pub fn init(interface_name: [:0]const u8, buffer: []u8) !RawSocketWriter { + std.debug.assert(buffer.len > 0); return .{ .interface = .{ .vtable = &.{ .drain = drain }, diff --git a/src/main.zig b/src/main.zig index 1266675..bdff529 100644 --- a/src/main.zig +++ b/src/main.zig @@ -46,9 +46,10 @@ pub fn main() !void { return clap.helpToFile(.stderr(), clap.Help, ¶ms, .{}); } - var sock_buffer: [2048]u8 = undefined; + var sock_buffer: [1500]u8 = undefined; var raw_socket_writer: RawSocketWriter = try .init("enp7s0", &sock_buffer); // /proc/net/dev - var net_writer: NetWriter = try .init(&raw_socket_writer.interface); + var net_buffer: [1500]u8 = undefined; + var net_writer: NetWriter = try .init(&raw_socket_writer.interface, &net_buffer); var client = try SaprusClient.init(&net_writer.interface); defer client.deinit(); -- cgit