Compare commits

...

2 commits

2 changed files with 30 additions and 53 deletions

View file

@ -12,19 +12,17 @@ const MDNSError = error{
SocketSetTimeoutFail, SocketSetTimeoutFail,
}; };
pub fn get_mdns(domain: util.Domain, ip_info: util.IPInfo) !util.IP { pub fn get_mdns(domain: util.Domain, ip_info: util.IP_VER) !util.IP {
if (ip_info.version != .Both) { if (ip_info != .Both) {
const sock = try send_query(domain, ip_info); const sock = try send_query(domain, ip_info);
return receive_response(sock, ip_info); return receive_response(sock, ip_info);
} }
const ip_info4 = util.IPInfo{ .version = .IPv4, .interface = ip_info.interface }; var sock = try send_query(domain, .IPv4);
var sock = try send_query(domain, ip_info4); const addr_v4 = try receive_response(sock, .IPv4);
const addr_v4 = try receive_response(sock, ip_info4);
const ip_info6 = util.IPInfo{ .version = .IPv6, .interface = ip_info.interface }; sock = try send_query(domain, .IPv4);
sock = try send_query(domain, ip_info6); const addr_v6 = try receive_response(sock, .IPv6);
const addr_v6 = try receive_response(sock, ip_info6);
return util.merge_addrs(addr_v4, addr_v6); return util.merge_addrs(addr_v4, addr_v6);
} }
@ -32,10 +30,10 @@ pub fn get_mdns(domain: util.Domain, ip_info: util.IPInfo) !util.IP {
const socket = c_int; const socket = c_int;
const MSG_BUFF_SIZE = util.consts.MSG_BUFF_SIZE; const MSG_BUFF_SIZE = util.consts.MSG_BUFF_SIZE;
fn get_mdns_socket(ip_info: util.IPInfo) !socket { fn get_mdns_socket(ip_info: util.IP_VER) !socket {
const sock = std.c.socket(switch (ip_info.version) { const sock = std.c.socket(switch (ip_info) {
util.IP_VER_ENUM.IPv4 => std.c.AF.INET, .IPv4 => std.c.AF.INET,
util.IP_VER_ENUM.IPv6 => std.c.AF.INET6, .IPv6 => std.c.AF.INET6,
else => unreachable, else => unreachable,
}, std.c.SOCK.DGRAM, std.c.IPPROTO.UDP); }, std.c.SOCK.DGRAM, std.c.IPPROTO.UDP);
if (sock == -1) { if (sock == -1) {
@ -48,7 +46,7 @@ fn get_mdns_socket(ip_info: util.IPInfo) !socket {
return sock; return sock;
} }
fn construct_mdns_query(domain: util.Domain, ip_info: util.IPInfo, buff: []u8) !usize { fn construct_mdns_query(domain: util.Domain, ip_info: util.IP_VER, buff: []u8) !usize {
var n: usize = 0; var n: usize = 0;
var buff_writer = std.io.fixedBufferStream(buff); var buff_writer = std.io.fixedBufferStream(buff);
@ -68,9 +66,9 @@ fn construct_mdns_query(domain: util.Domain, ip_info: util.IPInfo, buff: []u8) !
n += try buff_writer.write(&[_]u8{0x00}); // End null byte n += try buff_writer.write(&[_]u8{0x00}); // End null byte
const question_footer = const question_footer =
[_]u8{ 0x00, switch (ip_info.version) { [_]u8{ 0x00, switch (ip_info) {
util.IP_VER_ENUM.IPv4 => 0x01, .IPv4 => 0x01,
util.IP_VER_ENUM.IPv6 => 0x1c, .IPv6 => 0x1c,
else => unreachable, else => unreachable,
} } ++ // A or AAAA record } } ++ // A or AAAA record
[_]u8{ 0x00, 0x01 } // IN query [_]u8{ 0x00, 0x01 } // IN query
@ -80,22 +78,16 @@ fn construct_mdns_query(domain: util.Domain, ip_info: util.IPInfo, buff: []u8) !
return n; return n;
} }
fn get_target_address(ip_info: util.IPInfo) !std.net.Address { fn get_target_address(ip_info: util.IP_VER) !std.net.Address {
const target_addr: []const u8 = switch (ip_info.version) { const target_addr: []const u8 = switch (ip_info) {
util.IP_VER_ENUM.IPv4 => "224.0.0.251", .IPv4 => "224.0.0.251",
util.IP_VER_ENUM.IPv6 => blk: { .IPv6 => "ff02::fb",
var buf: [50]u8 = undefined;
var byte_buf = std.io.fixedBufferStream(&buf);
const writer = byte_buf.writer();
try std.fmt.format(writer, "ff02::fb%{s}", .{ip_info.interface.?});
break :blk buf[0..writer.context.pos];
},
else => unreachable, else => unreachable,
}; };
return std.net.Address.resolveIp(target_addr, 5353); return std.net.Address.resolveIp(target_addr, 5353);
} }
fn send_query(domain: util.Domain, ip_info: util.IPInfo) !socket { fn send_query(domain: util.Domain, ip_info: util.IP_VER) !socket {
const sock = try get_mdns_socket(ip_info); const sock = try get_mdns_socket(ip_info);
errdefer _ = std.c.close(sock); errdefer _ = std.c.close(sock);
@ -110,7 +102,7 @@ fn send_query(domain: util.Domain, ip_info: util.IPInfo) !socket {
return sock; return sock;
} }
fn receive_response(sock: socket, ip_info: util.IPInfo) !util.IP { fn receive_response(sock: socket, ip_info: util.IP_VER) !util.IP {
defer _ = std.c.close(sock); defer _ = std.c.close(sock);
var buff: [MSG_BUFF_SIZE]u8 = undefined; var buff: [MSG_BUFF_SIZE]u8 = undefined;
@ -141,7 +133,7 @@ inline fn read_u16(bytes: []u8) u16 {
return std.mem.nativeToBig(u16, std.mem.bytesToValue(u16, bytes)); return std.mem.nativeToBig(u16, std.mem.bytesToValue(u16, bytes));
} }
fn parse_mdns_response(response: []u8, ip_info: util.IPInfo) !util.IP { fn parse_mdns_response(response: []u8, ip_info: util.IP_VER) !util.IP {
var pos: usize = 0; var pos: usize = 0;
if (response[2] & 0x80 == 0) { // check packet is response if (response[2] & 0x80 == 0) { // check packet is response
@ -164,9 +156,9 @@ fn parse_mdns_response(response: []u8, ip_info: util.IPInfo) !util.IP {
const ip_bytes = response[pos .. pos + ip_len]; const ip_bytes = response[pos .. pos + ip_len];
pos += ip_len; pos += ip_len;
if (switch (ip_info.version) { if (switch (ip_info) {
util.IP_VER_ENUM.IPv4 => ip_len != 4, .IPv4 => ip_len != 4,
util.IP_VER_ENUM.IPv6 => ip_len != 16, .IPv6 => ip_len != 16,
else => unreachable, else => unreachable,
}) { }) {
continue; continue;
@ -181,14 +173,14 @@ fn parse_mdns_response(response: []u8, ip_info: util.IPInfo) !util.IP {
if (ip_bytes[0] == 0xfd) { if (ip_bytes[0] == 0xfd) {
var addr_buff: [16]u8 = undefined; var addr_buff: [16]u8 = undefined;
@memcpy(&addr_buff, ip_bytes); @memcpy(&addr_buff, ip_bytes);
addr = std.net.Address.initIp6(addr_buff, 0, 0, @intCast(std.c.if_nametoindex(ip_info.interface.?))); addr = std.net.Address.initIp6(addr_buff, 0, 0, 0);
} }
} }
} }
if (addr == null) { if (addr == null) {
return MDNSError.NoMatchingAddress; return MDNSError.NoMatchingAddress;
} }
return switch (ip_info.version) { return switch (ip_info) {
.IPv4 => util.IP{ .v4 = addr }, .IPv4 => util.IP{ .v4 = addr },
.IPv6 => util.IP{ .v6 = addr }, .IPv6 => util.IP{ .v6 = addr },
else => unreachable, else => unreachable,

View file

@ -6,13 +6,11 @@ const ArgError = error{
NotEnoughArgs, NotEnoughArgs,
BadDomain, BadDomain,
InvalidAddressVer, InvalidAddressVer,
InterfaceRequired,
InvalidInterface,
EnvVarNotSet, EnvVarNotSet,
InvalidOldHostsPath, InvalidOldHostsPath,
}; };
pub const IP_VER_ENUM = enum(u3) { pub const IP_VER = enum(u3) {
Both = 0, Both = 0,
IPv4 = 4, IPv4 = 4,
IPv6 = 6, IPv6 = 6,
@ -30,11 +28,6 @@ pub fn merge_addrs(v4: IP, v6: IP) IP {
}; };
} }
pub const IPInfo = struct {
version: IP_VER_ENUM,
interface: ?[:0]const u8,
};
pub const Domain = struct { pub const Domain = struct {
name: [:0]const u8, name: [:0]const u8,
labels: [5][]const u8, labels: [5][]const u8,
@ -53,7 +46,7 @@ pub const cwd = std.fs.cwd();
pub fn get_input() !struct { pub fn get_input() !struct {
Domain, Domain,
IPInfo, IP_VER,
} { } {
var args = std.process.args(); var args = std.process.args();
_ = args.next(); // consume calling binary arg _ = args.next(); // consume calling binary arg
@ -62,17 +55,9 @@ pub fn get_input() !struct {
const domain = try check_domain(domain_str); const domain = try check_domain(domain_str);
const ip_ver_str = args.next() orelse return ArgError.NotEnoughArgs; const ip_ver_str = args.next() orelse return ArgError.NotEnoughArgs;
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; const ip_ver = std.meta.intToEnum(IP_VER, std.fmt.parseInt(u3, ip_ver_str, 10) catch return ArgError.InvalidAddressVer) catch return ArgError.InvalidAddressVer;
var iface: ?[:0]const u8 = null; return .{ domain, ip_ver };
if (ip_ver != IP_VER_ENUM.IPv4) {
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 } };
} }
fn check_domain(domain_str: [:0]const u8) !Domain { fn check_domain(domain_str: [:0]const u8) !Domain {