local-etc-hosts-updater/src/util.zig

81 lines
2 KiB
Zig
Raw Normal View History

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,
InvalidAddressVer,
2024-05-11 15:14:32 +05:00
InterfaceRequired,
InvalidInterface,
};
pub const IP_VER_ENUM = enum(u3) {
IPv4 = 4,
IPv6 = 6,
2024-05-10 14:23:57 +05:00
};
2024-05-10 12:49:51 +05:00
pub const IPs = struct {
2024-05-10 20:33:00 +05:00
v4: []const u8,
v6: []const u8,
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-10 13:13:59 +05:00
pub fn check_perms() !void {
var f = try std.fs.openFileAbsolute("/etc/hosts", .{ .mode = .write_only });
f.close();
}
2024-05-10 12:49:51 +05:00
pub fn get_input() !struct {
Domain,
2024-05-11 15:14:32 +05:00
IPInfo,
} {
2024-05-10 14:23:57 +05:00
var args = std.process.args();
_ = 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-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
};
var labels = std.mem.split(u8, domain_str, ".");
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
}