hare

The Hare programming language
git clone https://git.torresjrjr.com/hare.git
Log | Files | Refs | README | LICENSE

commit c3610791a32991d46814afa36c19a9c2521424ec
parent f882bb8727c7b012e6aa030eb6165553dae29331
Author: Drew DeVault <sir@cmpwn.com>
Date:   Wed, 23 Jun 2021 16:17:43 -0400

net::dns: send requests to all nameservers at once

Signed-off-by: Drew DeVault <sir@cmpwn.com>

Diffstat:
Mnet/dns/query.ha | 36++++++++++++++++++++++++++----------
1 file changed, 26 insertions(+), 10 deletions(-)

diff --git a/net/dns/query.ha b/net/dns/query.ha @@ -6,9 +6,13 @@ use unix::resolvconf; // free the return value with [[message_free]]. // // If no DNS servers are provided, the system default servers (if any) are used. -export fn query(query: *message, addr: ip::addr...) (*message | error) = { - if (len(addr) == 0) { - addr = resolvconf::load(); +export fn query(query: *message, servers: ip::addr...) (*message | error) = { + if (len(servers) == 0) { + servers = resolvconf::load(); + }; + if (len(servers) == 0) { + // Fall back to localhost + servers = [[127, 0, 0, 1]: ip::addr4]; }; let socket = udp::listen(ip::ANY_V4, 0)?; @@ -17,8 +21,12 @@ export fn query(query: *message, addr: ip::addr...) (*message | error) = { // TODO: Use TCP for messages >512 bytes let sendbuf: [512]u8 = [0...]; let z = encode(sendbuf, query)?; - // TODO: Query multiple servers - udp::sendto(socket, sendbuf[..z], addr[0], 53)?; + + // We send requests in parallel to all configured servers and take the + // first one which sends us a reasonable answer. + for (let i = 0z; i < len(servers); i += 1) { + udp::sendto(socket, sendbuf[..z], servers[i], 53)?; + }; let header = header { ... }; let recvbuf: [512]u8 = [0...]; @@ -26,19 +34,27 @@ export fn query(query: *message, addr: ip::addr...) (*message | error) = { // TODO: Add timeout let src: ip::addr = ip::ANY_V4; z = udp::recvfrom(socket, recvbuf, &src, null)?; - if (!ip::equal(src, addr[0])) { + + let expected = false; + for (let i = 0z; i < len(servers); i += 1) { + if (ip::equal(src, servers[i])) { + expected = true; + break; + }; + }; + if (!expected) { continue; }; let dec = decoder_init(recvbuf[..z]); decode_header(&dec, &header)?; - if (header.id != query.header.id || header.op.qr != qr::RESPONSE) { - continue; + if (header.id == query.header.id && header.op.qr == qr::RESPONSE) { + break; }; - - break; }; + assert(!header.op.tc, "TODO: Retry with TCP for truncated DNS response"); + check_rcode(header.op.rcode)?; return decode(recvbuf[..z])?; };