Detect interface and use real mac

This commit is contained in:
2026-01-19 14:15:06 -05:00
parent cc765dc91b
commit f969d097ab

View File

@@ -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,
fn init(ifname: []const u8) !RawSocket {
const socket: i32 = @intCast(std.os.linux.socket(AF.PACKET, SOCK.RAW, 0));
const IFF_LOOPBACK = 0x8;
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 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;
// 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;
}
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 => {
// 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 => {
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,
);