| ... | @@ -51,6 +51,7 @@ pub const LookupError = error{ | ... | @@ -51,6 +51,7 @@ pub const LookupError = error{ |
| 51 | ResolvConfParseFailed, | 51 | ResolvConfParseFailed, |
| 52 | InvalidDnsARecord, | 52 | InvalidDnsARecord, |
| 53 | InvalidDnsAAAARecord, | 53 | InvalidDnsAAAARecord, |
| | 54 | InvalidDnsCnameRecord, |
| 54 | NameServerFailure, | 55 | NameServerFailure, |
| 55 | } || Io.Timestamp.Error || IpAddress.BindError || Io.File.OpenError || Io.File.Reader.Error || Io.Cancelable; | 56 | } || Io.Timestamp.Error || IpAddress.BindError || Io.File.OpenError || Io.File.Reader.Error || Io.Cancelable; |
| 56 | | 57 | |
| ... | @@ -381,16 +382,8 @@ fn lookupDns(io: Io, lookup_canon_name: []const u8, rc: *const ResolvConf, optio | ... | @@ -381,16 +382,8 @@ fn lookupDns(io: Io, lookup_canon_name: []const u8, rc: *const ResolvConf, optio |
| 381 | addresses_len += 1; | 382 | addresses_len += 1; |
| 382 | }, | 383 | }, |
| 383 | std.posix.RR.CNAME => { | 384 | std.posix.RR.CNAME => { |
| 384 | _ = &canonical_name; | 385 | _, canonical_name = expand(record.packet, record.data_off, options.canonical_name_buffer) catch |
| 385 | @panic("TODO"); | 386 | return error.InvalidDnsCnameRecord; |
| 386 | //var tmp: [256]u8 = undefined; | | |
| 387 | //// Returns len of compressed name. strlen to get canon name. | | |
| 388 | //_ = try posix.dn_expand(packet, record.data, &tmp); | | |
| 389 | //const canon_name = mem.sliceTo(&tmp, 0); | | |
| 390 | //if (isValidHostName(canon_name)) { | | |
| 391 | // ctx.canon.items.len = 0; | | |
| 392 | // try ctx.canon.appendSlice(gpa, canon_name); | | |
| 393 | //} | | |
| 394 | }, | 387 | }, |
| 395 | else => continue, | 388 | else => continue, |
| 396 | }; | 389 | }; |
| ... | @@ -525,51 +518,50 @@ fn writeResolutionQuery(q: *[280]u8, op: u4, dname: []const u8, class: u8, ty: u | ... | @@ -525,51 +518,50 @@ fn writeResolutionQuery(q: *[280]u8, op: u4, dname: []const u8, class: u8, ty: u |
| 525 | return n; | 518 | return n; |
| 526 | } | 519 | } |
| 527 | | 520 | |
| 528 | pub const ExpandDomainNameError = error{InvalidDnsPacket}; | 521 | pub const ExpandError = error{InvalidDnsPacket} || InitError; |
| 529 | | 522 | |
| 530 | pub fn expandDomainName( | 523 | /// Decompresses a DNS name. |
| 531 | msg: []const u8, | 524 | /// |
| 532 | comp_dn: []const u8, | 525 | /// Returns number of bytes consumed from `packet` starting at `i`, |
| 533 | exp_dn: []u8, | 526 | /// along with the expanded `HostName`. |
| 534 | ) ExpandDomainNameError!usize { | 527 | /// |
| 535 | // This implementation is ported from musl libc. | 528 | /// Asserts `buffer` is has length at least `max_len`. |
| 536 | // A more idiomatic "ziggy" implementation would be welcome. | 529 | pub fn expand(noalias packet: []const u8, start_i: usize, noalias dest_buffer: []u8) ExpandError!struct { usize, HostName } { |
| 537 | var p = comp_dn.ptr; | 530 | const dest = dest_buffer[0..max_len]; |
| 538 | var len: usize = std.math.maxInt(usize); | 531 | |
| 539 | const end = msg.ptr + msg.len; | 532 | var i = start_i; |
| 540 | if (p == end or exp_dn.len == 0) return error.InvalidDnsPacket; | 533 | var dest_i: usize = 0; |
| 541 | var dest = exp_dn.ptr; | 534 | var len: ?usize = null; |
| 542 | const dend = dest + @min(exp_dn.len, 254); | 535 | |
| 543 | // detect reference loop using an iteration counter | 536 | // Detect reference loop using an iteration counter. |
| 544 | var i: usize = 0; | 537 | for (0..packet.len / 2) |_| { |
| 545 | while (i < msg.len) : (i += 2) { | 538 | if (i >= packet.len) return error.InvalidDnsPacket; |
| 546 | // loop invariants: p<end, dest<dend | 539 | |
| 547 | if ((p[0] & 0xc0) != 0) { | 540 | const c = packet[i]; |
| 548 | if (p + 1 == end) return error.InvalidDnsPacket; | 541 | if ((c & 0xc0) != 0) { |
| 549 | const j = @as(usize, p[0] & 0x3f) << 8 | p[1]; | 542 | if (i + 1 >= packet.len) return error.InvalidDnsPacket; |
| 550 | if (len == std.math.maxInt(usize)) len = @intFromPtr(p) + 2 - @intFromPtr(comp_dn.ptr); | 543 | const j: usize = (@as(usize, c & 0x3F) << 8) | packet[i + 1]; |
| 551 | if (j >= msg.len) return error.InvalidDnsPacket; | 544 | if (j >= packet.len) return error.InvalidDnsPacket; |
| 552 | p = msg.ptr + j; | 545 | if (len == null) len = (i + 2) - start_i; |
| 553 | } else if (p[0] != 0) { | 546 | i = j; |
| 554 | if (dest != exp_dn.ptr) { | 547 | } else if (c != 0) { |
| 555 | dest[0] = '.'; | 548 | if (dest_i != 0) { |
| 556 | dest += 1; | 549 | dest[dest_i] = '.'; |
| 557 | } | 550 | dest_i += 1; |
| 558 | var j = p[0]; | | |
| 559 | p += 1; | | |
| 560 | if (j >= @intFromPtr(end) - @intFromPtr(p) or j >= @intFromPtr(dend) - @intFromPtr(dest)) { | | |
| 561 | return error.InvalidDnsPacket; | | |
| 562 | } | | |
| 563 | while (j != 0) { | | |
| 564 | j -= 1; | | |
| 565 | dest[0] = p[0]; | | |
| 566 | dest += 1; | | |
| 567 | p += 1; | | |
| 568 | } | 551 | } |
| | 552 | const label_len: usize = c; |
| | 553 | if (i + 1 + label_len > packet.len) return error.InvalidDnsPacket; |
| | 554 | if (dest_i + label_len + 1 > dest.len) return error.InvalidDnsPacket; |
| | 555 | @memcpy(dest[dest_i..][0..label_len], packet[i + 1 ..][0..label_len]); |
| | 556 | dest_i += label_len; |
| | 557 | i += 1 + label_len; |
| 569 | } else { | 558 | } else { |
| 570 | dest[0] = 0; | 559 | dest[dest_i] = 0; |
| 571 | if (len == std.math.maxInt(usize)) len = @intFromPtr(p) + 1 - @intFromPtr(comp_dn.ptr); | 560 | dest_i += 1; |
| 572 | return len; | 561 | return .{ |
| | 562 | len orelse i - start_i + 1, |
| | 563 | try .init(dest[0..dest_i]), |
| | 564 | }; |
| 573 | } | 565 | } |
| 574 | } | 566 | } |
| 575 | return error.InvalidDnsPacket; | 567 | return error.InvalidDnsPacket; |