mirror of
https://git.robbyzambito.me/zaprus
synced 2026-02-04 08:24:52 +00:00
Detect interface and use real mac
This commit is contained in:
102
src/main.zig
102
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,
|
||||
|
||||
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,
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user