const is_debug = builtin.mode == .Debug; const help = \\-h, --help Display this help and exit. \\-r, --relay A relay message to send. \\-d, --dest An IPv4 or <= 4 ASCII byte string. \\-c, --connect A connection message to send. \\ ; const Option = enum { help, relay, dest, connect }; const to_option: StaticStringMap(Option) = .initComptime(.{ .{ "-h", .help }, .{ "--help", .help }, .{ "-r", .relay }, .{ "--relay", .relay }, .{ "-d", .dest }, .{ "--dest", .dest }, .{ "-c", .connect }, .{ "--connect", .connect }, }); pub fn main(init: std.process.Init) !void { // CLI parsing adapted from the example here // https://codeberg.org/ziglang/zig/pulls/30644 const args = try init.minimal.args.toSlice(init.arena.allocator()); if (args.len == 1) { std.debug.print("{s}", .{help}); return; } var flags: struct { relay: ?[]const u8 = null, dest: ?[]const u8 = null, connect: ?[]const u8 = null, } = .{}; { var i: usize = 1; while (i < args.len) : (i += 1) { if (to_option.get(args[i])) |opt| { switch (opt) { .help => { std.debug.print("{s}\n", .{help}); return; }, .relay => { i += 1; if (i < args.len) { flags.relay = args[i]; } else { std.debug.print("-r/--relay requires a string\n", .{}); return error.InvalidArguments; } }, .dest => { i += 1; if (i < args.len) { flags.dest = args[i]; } else { std.debug.print("-d/--dest requires a string\n", .{}); return error.InvalidArguments; } }, .connect => { i += 1; if (i < args.len) { flags.connect = args[i]; } else { std.debug.print("-c/--connect requires a string\n", .{}); return error.InvalidArguments; } }, } } else { std.debug.print("Unknown argument: {s}\n", .{args[i]}); return error.InvalidArguments; } } } if (flags.connect != null and (flags.relay != null or flags.dest != null)) { std.debug.print("Incompatible arguments.\nCannot use --connect/-c with dest or relay.\n", .{}); return error.InvalidArguments; } std.debug.print("relay: {s}\n", .{flags.relay orelse ""}); std.debug.print("dest: {s}\n", .{flags.dest orelse ""}); std.debug.print("connect: {s}\n", .{flags.connect orelse ""}); // const net_interface: std.Io.net.Interface = .{ .index = 1 }; // std.debug.print("Interface: {s}\n", .{(try net_interface.name(init.io)).toSlice()}); const linux_socket = blk: { const linux_socket = std.os.linux.socket(AF.PACKET, SOCK.RAW, 0); const errno = std.os.linux.errno(linux_socket); if (errno != .SUCCESS) { std.debug.log("Failed to open socket: {t}\n", .{errno}); return error.Error; // TODO: better error } break :blk linux_socket; }; const socket_fd = blk: { const socket_fd = std.os.linux.bind(linux_socket, @bitCast(std.os.linux.sockaddr.ll{ .protocol = , .ifindex = 1, .hatype = , .pkttype = , .halen = , .addr = @splat(0), }), @sizeOf(std.os.linux.sockaddr.ll)); }; const ip: std.Io.net.IpAddress = .{ .ip4 = .unspecified(0) }; const socket = try ip.bind(init.io, .{ .mode = .raw, .protocol = .raw }); defer socket.close(init.io); try socket.send(init.io, &.{ .ip4 = try .parse("255.255.255.255", 8888) }, "foo"); // var sock_buffer: [1500]u8 = undefined; // var raw_socket_writer: RawSocketWriter = try .init("enp7s0", &sock_buffer); // /proc/net/dev // 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(); // if (res.args.relay) |r| { // const dest = parseDest(res.args.dest); // 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 { if (in) |dest| { if (dest.len <= 4) { var res: [4]u8 = @splat(0); @memcpy(res[0..dest.len], dest); return res; } const addr = std.Io.net.Ip4Address.parse(dest, 0) catch return "FAIL".*; return addr.bytes; } return "zap\x00".*; } const builtin = @import("builtin"); const std = @import("std"); const ArrayList = std.ArrayList; const StaticStringMap = std.StaticStringMap; const zaprus = @import("zaprus"); const SaprusClient = zaprus.Client; const SaprusMessage = zaprus.Message; const RawSocketWriter = zaprus.RawSocketWriter; const AF = std.os.linux.AF; const SOCK = std.os.linux.SOCK; // const NetWriter = zaprus.NetWriter;