2024-05-10 13:13:59 +05:00
|
|
|
const std = @import("std");
|
|
|
|
|
2024-05-10 14:23:57 +05:00
|
|
|
const ArgError = error{
|
|
|
|
NotEnoughArgs,
|
|
|
|
BadDomain,
|
2024-05-10 15:05:57 +05:00
|
|
|
InvalidAddressVer,
|
2024-05-11 15:14:32 +05:00
|
|
|
InterfaceRequired,
|
|
|
|
InvalidInterface,
|
2024-05-12 18:52:13 +05:00
|
|
|
EnvVarNotSet,
|
2024-05-10 15:05:57 +05:00
|
|
|
};
|
|
|
|
|
|
|
|
pub const IP_VER_ENUM = enum(u3) {
|
|
|
|
IPv4 = 4,
|
|
|
|
IPv6 = 6,
|
2024-05-10 14:23:57 +05:00
|
|
|
};
|
|
|
|
|
2024-05-12 18:52:13 +05:00
|
|
|
pub const IP = ?std.net.Address;
|
2024-05-10 12:49:51 +05:00
|
|
|
|
2024-05-11 15:14:32 +05:00
|
|
|
pub const IPInfo = struct {
|
|
|
|
version: IP_VER_ENUM,
|
|
|
|
interface: ?[:0]const u8,
|
|
|
|
};
|
|
|
|
|
2024-05-10 14:23:57 +05:00
|
|
|
pub const Domain = struct {
|
|
|
|
name: [:0]const u8,
|
2024-05-10 20:33:00 +05:00
|
|
|
labels: [5][]const u8,
|
2024-05-10 14:23:57 +05:00
|
|
|
};
|
|
|
|
|
2024-05-12 18:52:13 +05:00
|
|
|
pub fn getenv(key: [*:0]const u8) ![*:0]const u8 {
|
|
|
|
return (std.c.getenv(key) orelse ArgError.EnvVarNotSet);
|
|
|
|
}
|
|
|
|
|
2024-05-10 13:13:59 +05:00
|
|
|
pub fn check_perms() !void {
|
2024-05-12 18:52:13 +05:00
|
|
|
var f = try std.fs.openFileAbsoluteZ(try getenv("OLD_HOSTS_PATH"), .{ .mode = .write_only });
|
2024-05-10 13:13:59 +05:00
|
|
|
f.close();
|
|
|
|
}
|
2024-05-10 12:49:51 +05:00
|
|
|
|
2024-05-10 15:05:57 +05:00
|
|
|
pub fn get_input() !struct {
|
|
|
|
Domain,
|
2024-05-11 15:14:32 +05:00
|
|
|
IPInfo,
|
2024-05-10 15:05:57 +05:00
|
|
|
} {
|
2024-05-10 14:23:57 +05:00
|
|
|
var args = std.process.args();
|
2024-05-10 15:05:57 +05:00
|
|
|
_ = args.next(); // consume calling binary arg
|
|
|
|
|
|
|
|
const domain_str = args.next() orelse return ArgError.NotEnoughArgs;
|
|
|
|
const domain = try check_domain(domain_str);
|
|
|
|
|
|
|
|
const ip_ver_str = args.next() orelse return ArgError.NotEnoughArgs;
|
2024-05-10 20:33:00 +05:00
|
|
|
const ip_ver = std.meta.intToEnum(IP_VER_ENUM, std.fmt.parseInt(u3, ip_ver_str, 10) catch return ArgError.InvalidAddressVer) catch return ArgError.InvalidAddressVer;
|
2024-05-10 15:05:57 +05:00
|
|
|
|
2024-05-11 15:14:32 +05:00
|
|
|
var iface: ?[:0]const u8 = null;
|
|
|
|
if (ip_ver == IP_VER_ENUM.IPv6) {
|
|
|
|
iface = args.next() orelse return ArgError.InterfaceRequired;
|
|
|
|
if (std.c.if_nametoindex(iface.?) == 0) {
|
|
|
|
return ArgError.InvalidInterface;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return .{ domain, IPInfo{ .version = ip_ver, .interface = iface } };
|
2024-05-10 14:23:57 +05:00
|
|
|
}
|
|
|
|
|
|
|
|
fn check_domain(domain_str: [:0]const u8) !Domain {
|
|
|
|
var domain = Domain{
|
|
|
|
.name = domain_str,
|
2024-05-10 20:33:00 +05:00
|
|
|
.labels = [_][]const u8{&[_]u8{}} ** 5,
|
2024-05-10 14:23:57 +05:00
|
|
|
};
|
2024-05-13 00:28:18 +05:00
|
|
|
var labels = std.mem.splitScalar(u8, domain_str, '.');
|
2024-05-10 14:23:57 +05:00
|
|
|
var last: []const u8 = "";
|
2024-05-10 20:33:00 +05:00
|
|
|
var i: usize = 0;
|
2024-05-10 14:23:57 +05:00
|
|
|
while (labels.next()) |segment| {
|
2024-05-10 20:33:00 +05:00
|
|
|
if (i >= 5) {
|
|
|
|
return ArgError.BadDomain;
|
|
|
|
}
|
2024-05-10 14:23:57 +05:00
|
|
|
last = segment;
|
2024-05-10 20:33:00 +05:00
|
|
|
domain.labels[i] = segment;
|
|
|
|
i += 1;
|
2024-05-10 14:23:57 +05:00
|
|
|
}
|
2024-05-10 20:33:00 +05:00
|
|
|
if (domain.labels.len <= 1 or !std.mem.eql(u8, last, "local")) {
|
2024-05-10 14:23:57 +05:00
|
|
|
return ArgError.BadDomain;
|
|
|
|
}
|
|
|
|
return domain;
|
2024-05-10 12:49:51 +05:00
|
|
|
}
|