diff options
| -rw-r--r-- | src/main.zig | 106 |
1 files changed, 74 insertions, 32 deletions
diff --git a/src/main.zig b/src/main.zig index 24b24fa..3d58f66 100644 --- a/src/main.zig +++ b/src/main.zig @@ -147,13 +147,16 @@ pub fn main(init: std.process.Init) !void { } fn setPayloadLen(self: *@This(), len: usize) void { - self.ip.len = @intCast(len + @sizeOf(@TypeOf(self.udp)) + @sizeOf(@TypeOf(self.ip))); - self.udp.len = @intCast(len + @sizeOf(@TypeOf(self.udp))); + self.ip.len = @intCast(len + (@bitSizeOf(@TypeOf(self.udp)) / 8) + (@bitSizeOf(@TypeOf(self.ip)) / 8)); + self.udp.len = @intCast(len + (@bitSizeOf(@TypeOf(self.udp)) / 8)); } }; + var socket: RawSocket = try .init(); + defer socket.deinit(); + var headers: EthIpUdp = .{ - .src_mac = undefined, // TODO: REAL MAC + .src_mac = socket.mac, .ip = .{ .id = 0, .src_addr = rand.int(u32), @@ -191,8 +194,6 @@ pub fn main(init: std.process.Init) !void { std.debug.print("full message = {any}\n", .{full_msg}); - var socket: RawSocket = try .init("enp7s0"); - defer socket.deinit(); try socket.send(full_msg); return; } @@ -229,8 +230,6 @@ pub fn main(init: std.process.Init) !void { std.debug.print("full message = {any}\n", .{full_msg}); - var socket: RawSocket = try .init("enp7s0"); - defer socket.deinit(); try socket.send(full_msg); return; } @@ -268,47 +267,90 @@ const SOCK = std.os.linux.SOCK; const RawSocket = struct { fd: i32, sockaddr_ll: std.posix.sockaddr.ll, + mac: [6]u8, + + const IFF_LOOPBACK = 0x8; + + const ifconf = extern struct { + ifc_len: i32, + ifc_ifcu: extern union { + ifcu_buf: ?[*]u8, + ifcu_req: ?[*]std.os.linux.ifreq, + }, + }; + + fn init() !RawSocket { + const socket: i32 = @intCast(std.os.linux.socket(std.posix.AF.PACKET, std.posix.SOCK.RAW, 0)); + if (socket < 0) return error.SocketError; - fn init(ifname: []const u8) !RawSocket { - const socket: i32 = @intCast(std.os.linux.socket(AF.PACKET, SOCK.RAW, 0)); + // 1. Enumerate interfaces + var ifreq_storage: [16]std.os.linux.ifreq = undefined; + var ifc = ifconf{ + .ifc_len = @sizeOf(@TypeOf(ifreq_storage)), + .ifc_ifcu = .{ .ifcu_req = &ifreq_storage }, + }; + + if (std.os.linux.ioctl(socket, std.os.linux.SIOCGIFCONF, @intFromPtr(&ifc)) != 0) { + return error.NicError; + } - var ifr: std.posix.ifreq = std.mem.zeroInit(std.posix.ifreq, .{}); - @memcpy(ifr.ifrn.name[0..ifname.len], ifname); - ifr.ifrn.name[ifname.len] = 0; - try std.posix.ioctl_SIOCGIFINDEX(socket, &ifr); + const count = @divExact(ifc.ifc_len, @sizeOf(std.os.linux.ifreq)); + var target_ifr: ?std.os.linux.ifreq = null; + + for (ifreq_storage[0..@intCast(count)]) |ifr| { + var temp_ifr = ifr; + if (std.os.linux.ioctl(socket, std.os.linux.SIOCGIFFLAGS, @intFromPtr(&temp_ifr)) == 0) { + // Cast the packed flags to u16 to match the kernel's ifr_flags size + const flags: u16 = @bitCast(temp_ifr.ifru.flags); + if (flags & IFF_LOOPBACK != 0) continue; + + target_ifr = ifr; + break; + } + } + + var ifr = target_ifr orelse return error.NoInterfaceFound; + + // 2. Get Interface Index + if (std.os.linux.ioctl(socket, std.os.linux.SIOCGIFINDEX, @intFromPtr(&ifr)) != 0) { + return error.NicError; + } const ifindex: i32 = ifr.ifru.ivalue; - var rval = std.posix.errno(std.os.linux.ioctl(socket, std.os.linux.SIOCGIFFLAGS, @intFromPtr(&ifr))); - switch (rval) { - .SUCCESS => {}, - else => { - return error.NicError; - }, + // 3. Get Real MAC Address + if (std.os.linux.ioctl(socket, std.os.linux.SIOCGIFHWADDR, @intFromPtr(&ifr)) != 0) { + return error.NicError; + } + var mac: [6]u8 = ifr.ifru.hwaddr.data[0..6].*; + std.mem.reverse(u8, &mac); + + // 4. Set Flags (Promiscuous/Broadcast) + if (std.os.linux.ioctl(socket, std.os.linux.SIOCGIFFLAGS, @intFromPtr(&ifr)) != 0) { + return error.NicError; } ifr.ifru.flags.BROADCAST = true; ifr.ifru.flags.PROMISC = true; - rval = std.posix.errno(std.os.linux.ioctl(socket, std.os.linux.SIOCSIFFLAGS, @intFromPtr(&ifr))); - switch (rval) { - .SUCCESS => {}, - else => { - return error.NicError; - }, + if (std.os.linux.ioctl(socket, std.os.linux.SIOCSIFFLAGS, @intFromPtr(&ifr)) != 0) { + return error.NicError; } - std.debug.print("ifindex: {}\n", .{ifindex}); + const sockaddr_ll = std.posix.sockaddr.ll{ .family = std.posix.AF.PACKET, .ifindex = ifindex, .protocol = std.mem.nativeToBig(u16, @as(u16, std.os.linux.ETH.P.IP)), - .halen = 0, //not used - .addr = .{ 0, 0, 0, 0, 0, 0, 0, 0 }, //not used - .pkttype = 0, //not used - .hatype = 0, //not used + .halen = 0, + .addr = .{ 0, 0, 0, 0, 0, 0, 0, 0 }, + .pkttype = 0, + .hatype = 0, }; - _ = std.os.linux.bind(socket, @ptrCast(&sockaddr_ll), @sizeOf(@TypeOf(sockaddr_ll))); + + const bind_ret = std.os.linux.bind(socket, @ptrCast(&sockaddr_ll), @sizeOf(@TypeOf(sockaddr_ll))); + if (bind_ret != 0) return error.BindError; return .{ .fd = socket, .sockaddr_ll = sockaddr_ll, + .mac = mac, }; } @@ -333,7 +375,7 @@ const RawSocket = struct { self.fd, buf.ptr, buf.len, - 0, // flags + 0, null, null, ); |
