diff --git a/src/helpers.zig b/src/helpers.zig index f4a99f8..fdc5fd7 100644 --- a/src/helpers.zig +++ b/src/helpers.zig @@ -215,6 +215,10 @@ const AddressList = struct { } }; +/// A very simple getAddressList that sets up the DNS connection and extracts +/// the A records. +/// +/// This function does not implement the "happy eyeballs" algorithm. pub fn getAddressList(incoming_name: []const u8, allocator: std.mem.Allocator) !AddressList { var name_buffer: [128][]const u8 = undefined; const name = try dns.Name.fromString(incoming_name, &name_buffer); @@ -250,8 +254,17 @@ pub fn getAddressList(incoming_name: []const u8, allocator: std.mem.Allocator) ! const reply_packet = reply.packet; - std.debug.assert(packet.header.id == reply_packet.header.id); - std.debug.assert(reply_packet.header.is_response); + if (packet.header.id != reply_packet.header.id) return error.InvalidReply; + if (!reply_packet.header.is_response) return error.InvalidResponse; + + switch (reply_packet.header.response_code) { + .NoError => {}, + .FormatError => return error.ServerFormatError, // bug in implementation caught by server? + .ServerFailure => return error.ServerFailure, + .NameError => return error.ServerNameError, + .NotImplemented => return error.ServerNotImplemented, + .Refused => return error.ServerRefused, + } var list = std.ArrayList(std.net.Address).init(allocator); defer list.deinit(); diff --git a/src/lib.zig b/src/lib.zig index 520205d..cf1ee40 100644 --- a/src/lib.zig +++ b/src/lib.zig @@ -3,6 +3,8 @@ pub const ResourceClass = @import("enums.zig").ResourceClass; pub const Name = @import("name.zig").Name; const pkt = @import("packet.zig"); pub const Packet = pkt.Packet; +pub const ResponseCode = pkt.ResponseCode; +pub const OpCode = pkt.OpCode; pub const IncomingPacket = pkt.IncomingPacket; pub const Question = pkt.Question; pub const Resource = pkt.Resource; diff --git a/src/packet.zig b/src/packet.zig index 4ae3a0e..5405c8e 100644 --- a/src/packet.zig +++ b/src/packet.zig @@ -9,14 +9,32 @@ const logger = std.log.scoped(.dns_packet); pub const ResponseCode = enum(u4) { NoError = 0, + + /// Format error - The name server was unable to interpret the query. FormatError = 1, + + /// Server failure - The name server was unable to process this query + /// due to a problem with the name server. ServerFailure = 2, + + /// Name Error - Meaningful only for responses from an authoritative name + /// server, this code signifies that the domain name referenced in + /// the query does not exist. NameError = 3, + + /// Not Implemented - The name server does not support the requested + /// kind of query. NotImplemented = 4, + + /// Refused - The name server refuses to perform the specified + /// operation for policy reasons. For example, a name server may not + /// wish to provide the information to the particular requester, + /// or a name server may not wish to perform a particular operation + /// (e.g., zone transfer) for particular data. Refused = 5, }; -const OpCode = enum(u4) { +pub const OpCode = enum(u4) { Query = 0, InverseQuery = 1, ServerStatusRequest = 2,