authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-10-02 19:12:25-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-10-02 19:57:23-07:00
logb08f1d0e2a6e4df051a5bce9aeab5b31a1af4746
tree2745cf309ac265b2118a8357032e2851d020c41c
parenta5d8dcc025cc17466627c48bd3645b466b7ba0a5

std.Io.net.HostName: implement DNS reply parsing


1 files changed, 39 insertions(+), 8 deletions(-)

lib/std/Io/net/HostName.zig+39-8
......@@ -363,17 +363,19 @@ fn lookupDns(io: Io, lookup_canon_name: []const u8, rc: *const ResolvConf, optio
363363 continue;
364364 }) |record| switch (record.rr) {
365365 std.posix.RR.A => {
366 if (record.data.len != 4) return error.InvalidDnsARecord;
366 const data = record.packet[record.data_off..][0..record.data_len];
367 if (data.len != 4) return error.InvalidDnsARecord;
367368 options.addresses_buffer[addresses_len] = .{ .ip4 = .{
368 .bytes = record.data[0..4].*,
369 .bytes = data[0..4].*,
369370 .port = options.port,
370371 } };
371372 addresses_len += 1;
372373 },
373374 std.posix.RR.AAAA => {
374 if (record.data.len != 16) return error.InvalidDnsAAAARecord;
375 const data = record.packet[record.data_off..][0..record.data_len];
376 if (data.len != 16) return error.InvalidDnsAAAARecord;
375377 options.addresses_buffer[addresses_len] = .{ .ip6 = .{
376 .bytes = record.data[0..16].*,
378 .bytes = data[0..16].*,
377379 .port = options.port,
378380 } };
379381 addresses_len += 1;
......@@ -575,23 +577,52 @@ pub fn expandDomainName(
575577
576578pub const DnsResponse = struct {
577579 bytes: []const u8,
580 bytes_index: u32,
581 answers_remaining: u16,
578582
579583 pub const Answer = struct {
580584 rr: u8,
581 data: []const u8,
582585 packet: []const u8,
586 data_off: u32,
587 data_len: u16,
583588 };
584589
585590 pub const Error = error{InvalidDnsPacket};
586591
587592 pub fn init(r: []const u8) Error!DnsResponse {
588593 if (r.len < 12) return error.InvalidDnsPacket;
589 return .{ .bytes = r };
594 if ((r[3] & 15) != 0) return .{ .bytes = r, .bytes_index = 3, .answers_remaining = 0 };
595 var i: u32 = 12;
596 var query_count = std.mem.readInt(u16, r[4..6], .big);
597 while (query_count != 0) : (query_count -= 1) {
598 while (i < r.len and r[i] -% 1 < 127) i += 1;
599 if (r.len - i < 6) return error.InvalidDnsPacket;
600 i = i + 5 + @intFromBool(r[i] != 0);
601 }
602 return .{
603 .bytes = r,
604 .bytes_index = i,
605 .answers_remaining = std.mem.readInt(u16, r[6..8], .big),
606 };
590607 }
591608
592609 pub fn next(dr: *DnsResponse) Error!?Answer {
593 _ = dr;
594 @panic("TODO");
610 if (dr.answers_remaining == 0) return null;
611 dr.answers_remaining -= 1;
612 const r = dr.bytes;
613 var i = dr.bytes_index;
614 while (i < r.len and r[i] -% 1 < 127) i += 1;
615 if (r.len - i < 12) return error.InvalidDnsPacket;
616 i = i + 1 + @intFromBool(r[i] != 0);
617 const len = std.mem.readInt(u16, r[i + 8 ..][0..2], .big);
618 if (i + 10 + len > r.len) return error.InvalidDnsPacket;
619 defer dr.bytes_index = i + 10 + len;
620 return .{
621 .rr = r[i + 1],
622 .packet = r,
623 .data_off = i + 10,
624 .data_len = len,
625 };
595626 }
596627};
597628