mirror of
https://git.robbyzambito.me/zaprus
synced 2026-02-04 00:14:52 +00:00
Arrange bytes for relay
This commit is contained in:
211
src/main.zig
211
src/main.zig
@@ -90,79 +90,81 @@ pub fn main(init: std.process.Init) !void {
|
|||||||
std.debug.print("dest: {s}\n", .{flags.dest orelse "<null>"});
|
std.debug.print("dest: {s}\n", .{flags.dest orelse "<null>"});
|
||||||
std.debug.print("connect: {s}\n", .{flags.connect orelse "<null>"});
|
std.debug.print("connect: {s}\n", .{flags.connect orelse "<null>"});
|
||||||
|
|
||||||
|
// const rand = blk: {
|
||||||
|
// const io_source: std.Random.IoSource = .{ .io = init.io };
|
||||||
|
// break :blk io_source.interface();
|
||||||
|
// };
|
||||||
|
|
||||||
// const net_interface: std.Io.net.Interface = .{ .index = 1 };
|
// const net_interface: std.Io.net.Interface = .{ .index = 1 };
|
||||||
// std.debug.print("Interface: {s}\n", .{(try net_interface.name(init.io)).toSlice()});
|
// std.debug.print("Interface: {s}\n", .{(try net_interface.name(init.io)).toSlice()});
|
||||||
|
const EthIpUdp = packed struct(u336) { // 42 bytes * 8 bits = 336
|
||||||
|
// --- UDP (Last in memory, defined first for LSB->MSB) ---
|
||||||
|
checksum: u16 = 0,
|
||||||
|
udp_len: u16,
|
||||||
|
dst_port: u16,
|
||||||
|
src_port: u16,
|
||||||
|
|
||||||
const linux_socket = blk: {
|
// --- IP ---
|
||||||
const linux_socket = std.os.linux.socket(AF.PACKET, SOCK.RAW, 0);
|
dst_addr: u32,
|
||||||
const errno = std.os.linux.errno(linux_socket);
|
src_addr: u32,
|
||||||
if (errno != .SUCCESS) {
|
header_checksum: u16 = 0,
|
||||||
std.debug.print("Failed to open socket: {t}\n", .{errno});
|
protocol: u8 = 17, // udp
|
||||||
return error.Error; // TODO: better error
|
ttl: u8 = 0x40,
|
||||||
}
|
|
||||||
break :blk linux_socket;
|
|
||||||
};
|
|
||||||
const socket_fd = blk: {
|
|
||||||
const socket_fd = std.os.linux.bind(@intCast(linux_socket), @bitCast(std.os.linux.sockaddr.ll{
|
|
||||||
// https://codeberg.org/jeffective/gatorcat/src/commit/1da40c85c2d063368e2e5c130e654cb32b6bff0e/src/module/nic.zig#L137
|
|
||||||
.protocol = std.mem.nativeToBig(u16, @as(u16, std.os.linux.ETH.P.ALL)),
|
|
||||||
.ifindex = 1,
|
|
||||||
.hatype = 0,
|
|
||||||
.pkttype = 0,
|
|
||||||
.halen = 0,
|
|
||||||
.addr = @splat(0),
|
|
||||||
}), @sizeOf(std.os.linux.sockaddr.ll));
|
|
||||||
|
|
||||||
const errno = std.os.linux.errno(socket_fd);
|
// fragment_offset (13 bits) + flags (3 bits) = 16 bits
|
||||||
|
// In Big Endian, flags are the high bits of the first byte.
|
||||||
|
// To have flags appear first in the stream, define them last here.
|
||||||
|
fragment_offset: u13 = 0,
|
||||||
|
flags: packed struct(u3) {
|
||||||
|
reserved: u1 = 0,
|
||||||
|
dont_fragment: u1 = 0,
|
||||||
|
more_fragments: u1 = 0,
|
||||||
|
} = .{},
|
||||||
|
|
||||||
if (errno != .SUCCESS) {
|
id: u16,
|
||||||
std.debug.print("Failed to create link layer socket: {t}\n", .{errno});
|
total_length: u16,
|
||||||
return error.Error; // TODO: better error
|
tos: u8 = undefined,
|
||||||
}
|
|
||||||
break :blk socket_fd;
|
|
||||||
};
|
|
||||||
|
|
||||||
const EthIpUdp = struct {
|
// ip_version (4 bits) + ihl (4 bits) = 8 bits
|
||||||
// eth
|
// To have version appear first (high nibble), define it last.
|
||||||
dst_mac: [6]u8 = @splat(0xff),
|
ihl: u4 = 5,
|
||||||
src_mac: [6]u8,
|
|
||||||
eth_type: u16 = std.os.linux.ETH.P.IP,
|
|
||||||
// ip
|
|
||||||
ip_version: u4 = 4,
|
ip_version: u4 = 4,
|
||||||
|
|
||||||
|
// --- Ethernet ---
|
||||||
|
eth_type: u16 = std.os.linux.ETH.P.IP,
|
||||||
|
src_mac: @Vector(6, u8),
|
||||||
|
dst_mac: @Vector(6, u8) = @splat(0xff),
|
||||||
|
|
||||||
|
fn toBytes(self: @This()) [336 / 8]u8 {
|
||||||
|
var res: [336 / 8]u8 = undefined;
|
||||||
|
var w: Writer = .fixed(&res);
|
||||||
|
w.writeStruct(self, .big) catch unreachable;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// const ip: std.Io.net.IpAddress = .{ .ip4 = .unspecified(0) };
|
const headers: EthIpUdp = .{
|
||||||
// const socket = try ip.bind(init.io, .{ .mode = .rdm, .protocol = .raw });
|
.src_mac = @splat(0x0e),
|
||||||
// defer socket.close(init.io);
|
.id = 0,
|
||||||
|
.src_addr = 0,
|
||||||
|
.dst_addr = @bitCast([_]u8{ 255, 255, 255, 255 }),
|
||||||
|
.src_port = undefined, // TODO: change this?
|
||||||
|
.dst_port = 8888,
|
||||||
|
|
||||||
// try socket.send(init.io, &.{ .ip4 = .{ .bytes = @splat(255), .port = 8888 } }, "foo");
|
.total_length = undefined,
|
||||||
|
.udp_len = undefined,
|
||||||
|
};
|
||||||
|
std.debug.print("headers: {any}\n", .{&headers.toBytes()});
|
||||||
|
|
||||||
// var sock_buffer: [1500]u8 = undefined;
|
const relay: SaprusMessage = .{
|
||||||
// var raw_socket_writer: RawSocketWriter = try .init("enp7s0", &sock_buffer); // /proc/net/dev
|
.relay = .{
|
||||||
// var net_buffer: [1500]u8 = undefined;
|
.dest = .fromBytes(&parseDest(flags.dest)),
|
||||||
// var net_writer: NetWriter = try .init(&raw_socket_writer.interface, &net_buffer);
|
.payload = flags.relay.?,
|
||||||
// var client = try SaprusClient.init(&net_writer.interface);
|
},
|
||||||
// defer client.deinit();
|
};
|
||||||
|
|
||||||
// if (res.args.relay) |r| {
|
var relay_bytes: [2048]u8 = undefined;
|
||||||
// const dest = parseDest(res.args.dest);
|
std.debug.print("payload: {any}\n", .{relay.toBytes(&relay_bytes)});
|
||||||
// try client.sendRelay(
|
|
||||||
// if (r.len > 0) r else "Hello darkness my old friend",
|
|
||||||
// dest,
|
|
||||||
// );
|
|
||||||
// return;
|
|
||||||
// } else if (res.args.connect) |c| {
|
|
||||||
// if (false) {
|
|
||||||
// _ = client.connect(if (c.len > 0) c else "Hello darkness my old friend") catch |err| switch (err) {
|
|
||||||
// error.WouldBlock => null,
|
|
||||||
// else => return err,
|
|
||||||
// };
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
// @panic("Not implemented");
|
|
||||||
// }
|
|
||||||
|
|
||||||
// return clap.helpToFile(.stderr(), clap.Help, ¶ms, .{});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parseDest(in: ?[]const u8) [4]u8 {
|
fn parseDest(in: ?[]const u8) [4]u8 {
|
||||||
@@ -189,16 +191,81 @@ const SaprusClient = zaprus.Client;
|
|||||||
const SaprusMessage = zaprus.Message;
|
const SaprusMessage = zaprus.Message;
|
||||||
const RawSocketWriter = zaprus.RawSocketWriter;
|
const RawSocketWriter = zaprus.RawSocketWriter;
|
||||||
|
|
||||||
// Import C headers for network constants and structs
|
|
||||||
const c = @cImport({
|
|
||||||
@cInclude("sys/socket.h");
|
|
||||||
@cInclude("linux/if_packet.h");
|
|
||||||
@cInclude("net/ethernet.h");
|
|
||||||
@cInclude("sys/ioctl.h");
|
|
||||||
@cInclude("net/if.h");
|
|
||||||
@cInclude("arpa/inet.h");
|
|
||||||
});
|
|
||||||
|
|
||||||
const AF = std.os.linux.AF;
|
const AF = std.os.linux.AF;
|
||||||
const SOCK = std.os.linux.SOCK;
|
const SOCK = std.os.linux.SOCK;
|
||||||
// const NetWriter = zaprus.NetWriter;
|
|
||||||
|
const RawSocket = struct {
|
||||||
|
fd: i32,
|
||||||
|
sockaddr_ll: std.posix.sockaddr.ll,
|
||||||
|
|
||||||
|
fn init(ifname: []const u8) RawSocket {
|
||||||
|
const socket: i32 = @intCast(std.os.linux.socket(AF.PACKET, SOCK.RAW, 0));
|
||||||
|
|
||||||
|
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 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;
|
||||||
|
},
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
},
|
||||||
|
}
|
||||||
|
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
|
||||||
|
};
|
||||||
|
_ = std.os.linux.bind(socket, @ptrCast(&sockaddr_ll), @sizeOf(@TypeOf(sockaddr_ll)));
|
||||||
|
|
||||||
|
return .{
|
||||||
|
.fd = socket,
|
||||||
|
.sockaddr_ll = sockaddr_ll,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deinit() void {}
|
||||||
|
|
||||||
|
fn send(self: RawSocket, payload: []const u8) !void {
|
||||||
|
const sent_bytes = std.os.linux.sendto(
|
||||||
|
self.fd,
|
||||||
|
payload.ptr,
|
||||||
|
payload.len,
|
||||||
|
0,
|
||||||
|
@ptrCast(&self.sockaddr_ll),
|
||||||
|
@sizeOf(@TypeOf(self.sockaddr_ll)),
|
||||||
|
);
|
||||||
|
std.debug.assert(sent_bytes == payload.len);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn receive(self: RawSocket, buf: []u8) ![]u8 {
|
||||||
|
const len = std.os.linux.recvfrom(
|
||||||
|
self.fd,
|
||||||
|
buf.ptr,
|
||||||
|
buf.len,
|
||||||
|
0, // flags
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
);
|
||||||
|
return buf[0..len];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const Writer = std.Io.Writer;
|
||||||
|
|||||||
@@ -22,6 +22,12 @@ pub const Message = union(PacketType) {
|
|||||||
|
|
||||||
pub const Relay = message.Relay;
|
pub const Relay = message.Relay;
|
||||||
pub const Connection = message.Connection;
|
pub const Connection = message.Connection;
|
||||||
|
|
||||||
|
pub fn toBytes(self: message.Message, buf: []u8) []u8 {
|
||||||
|
return switch (self) {
|
||||||
|
inline else => |m| m.toBytes(buf),
|
||||||
|
};
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const relay_dest_len = 4;
|
pub const relay_dest_len = 4;
|
||||||
|
|||||||
Reference in New Issue
Block a user