Annotate

net/resolvers/service.lua @ 12147:02481502c3dc

util.dependencies: Enable warning about missing lua-unbound Packages exists now.
author Kim Alvefur <zash@zash.se>
date Wed, 05 Jan 2022 04:12:00 +0100
parent 12129:7a68d5828f3b
child 12401:c029ddcad258
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
8531
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
1 local adns = require "net.adns";
9388
a5d11627ce5d net.resolvers.service: net.connect resolver that uses SRV records
Kim Alvefur <zash@zash.se>
parents: 8775
diff changeset
2 local basic = require "net.resolvers.basic";
10440
1ee87b4979c2 net.resolvers.service: Pass IP literals directly to basic resolver
Kim Alvefur <zash@zash.se>
parents: 10401
diff changeset
3 local inet_pton = require "util.net".pton;
10384
94c9c574cd8a net.resolvers: Apply IDNA conversion to ascii for DNS lookups (fixes #1426)
Kim Alvefur <zash@zash.se>
parents: 9397
diff changeset
4 local idna_to_ascii = require "util.encodings".idna.to_ascii;
9691
e11e076f0eb8 various: Don't rely on _G.unpack existing
Kim Alvefur <zash@zash.se>
parents: 9397
diff changeset
5 local unpack = table.unpack or unpack; -- luacheck: ignore 113
8531
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
6
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
7 local methods = {};
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
8 local resolver_mt = { __index = methods };
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
9
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
10 -- Find the next target to connect to, and
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
11 -- pass it to cb()
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
12 function methods:next(cb)
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
13 if self.targets then
10650
324a0c7d1c6a net.resolvers.service: Fix resolving of targets with multiple IPs
Kim Alvefur <zash@zash.se>
parents: 10484
diff changeset
14 if not self.resolver then
324a0c7d1c6a net.resolvers.service: Fix resolving of targets with multiple IPs
Kim Alvefur <zash@zash.se>
parents: 10484
diff changeset
15 if #self.targets == 0 then
324a0c7d1c6a net.resolvers.service: Fix resolving of targets with multiple IPs
Kim Alvefur <zash@zash.se>
parents: 10484
diff changeset
16 cb(nil);
324a0c7d1c6a net.resolvers.service: Fix resolving of targets with multiple IPs
Kim Alvefur <zash@zash.se>
parents: 10484
diff changeset
17 return;
324a0c7d1c6a net.resolvers.service: Fix resolving of targets with multiple IPs
Kim Alvefur <zash@zash.se>
parents: 10484
diff changeset
18 end
324a0c7d1c6a net.resolvers.service: Fix resolving of targets with multiple IPs
Kim Alvefur <zash@zash.se>
parents: 10484
diff changeset
19 local next_target = table.remove(self.targets, 1);
324a0c7d1c6a net.resolvers.service: Fix resolving of targets with multiple IPs
Kim Alvefur <zash@zash.se>
parents: 10484
diff changeset
20 self.resolver = basic.new(unpack(next_target, 1, 4));
8531
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
21 end
9388
a5d11627ce5d net.resolvers.service: net.connect resolver that uses SRV records
Kim Alvefur <zash@zash.se>
parents: 8775
diff changeset
22 self.resolver:next(function (...)
11901
26406ce35e20 net.connect: Propagate last error message from resolvers
Kim Alvefur <zash@zash.se>
parents: 11710
diff changeset
23 if self.resolver then
26406ce35e20 net.connect: Propagate last error message from resolvers
Kim Alvefur <zash@zash.se>
parents: 11710
diff changeset
24 self.last_error = self.resolver.last_error;
26406ce35e20 net.connect: Propagate last error message from resolvers
Kim Alvefur <zash@zash.se>
parents: 11710
diff changeset
25 end
9388
a5d11627ce5d net.resolvers.service: net.connect resolver that uses SRV records
Kim Alvefur <zash@zash.se>
parents: 8775
diff changeset
26 if ... == nil then
10650
324a0c7d1c6a net.resolvers.service: Fix resolving of targets with multiple IPs
Kim Alvefur <zash@zash.se>
parents: 10484
diff changeset
27 self.resolver = nil;
9388
a5d11627ce5d net.resolvers.service: net.connect resolver that uses SRV records
Kim Alvefur <zash@zash.se>
parents: 8775
diff changeset
28 self:next(cb);
a5d11627ce5d net.resolvers.service: net.connect resolver that uses SRV records
Kim Alvefur <zash@zash.se>
parents: 8775
diff changeset
29 else
a5d11627ce5d net.resolvers.service: net.connect resolver that uses SRV records
Kim Alvefur <zash@zash.se>
parents: 8775
diff changeset
30 cb(...);
a5d11627ce5d net.resolvers.service: net.connect resolver that uses SRV records
Kim Alvefur <zash@zash.se>
parents: 8775
diff changeset
31 end
a5d11627ce5d net.resolvers.service: net.connect resolver that uses SRV records
Kim Alvefur <zash@zash.se>
parents: 8775
diff changeset
32 end);
8531
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
33 return;
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
34 end
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
35
10385
62a7042e0771 net.resolvers: Abort on hostnames not passing IDNA validation
Kim Alvefur <zash@zash.se>
parents: 10384
diff changeset
36 if not self.hostname then
12025
6ed7fd28f5e3 net.resolvers: Report when hostname fails IDNA
Kim Alvefur <zash@zash.se>
parents: 11901
diff changeset
37 self.last_error = "hostname failed IDNA";
10385
62a7042e0771 net.resolvers: Abort on hostnames not passing IDNA validation
Kim Alvefur <zash@zash.se>
parents: 10384
diff changeset
38 cb(nil);
10400
4c2d789a106b net.resolvers: Fix traceback from hostname failing IDNA
Kim Alvefur <zash@zash.se>
parents: 10385
diff changeset
39 return;
10385
62a7042e0771 net.resolvers: Abort on hostnames not passing IDNA validation
Kim Alvefur <zash@zash.se>
parents: 10384
diff changeset
40 end
62a7042e0771 net.resolvers: Abort on hostnames not passing IDNA validation
Kim Alvefur <zash@zash.se>
parents: 10384
diff changeset
41
8531
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
42 local targets = {};
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
43 local function ready()
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
44 self.targets = targets;
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
45 self:next(cb);
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
46 end
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
47
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
48 -- Resolve DNS to target list
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
49 local dns_resolver = adns.resolver();
10121
33f287519bf6 net.resolvers.service: Fix DNS fallback
Kim Alvefur <zash@zash.se>
parents: 9691
diff changeset
50 dns_resolver:lookup(function (answer, err)
33f287519bf6 net.resolvers.service: Fix DNS fallback
Kim Alvefur <zash@zash.se>
parents: 9691
diff changeset
51 if not answer and not err then
33f287519bf6 net.resolvers.service: Fix DNS fallback
Kim Alvefur <zash@zash.se>
parents: 9691
diff changeset
52 -- net.adns returns nil if there are zero records or nxdomain
33f287519bf6 net.resolvers.service: Fix DNS fallback
Kim Alvefur <zash@zash.se>
parents: 9691
diff changeset
53 answer = {};
33f287519bf6 net.resolvers.service: Fix DNS fallback
Kim Alvefur <zash@zash.se>
parents: 9691
diff changeset
54 end
8531
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
55 if answer then
11710
26a8cc9d9eb7 net.resolvers.service: Only do DANE with secure SRV records
Kim Alvefur <zash@zash.se>
parents: 10970
diff changeset
56 if self.extra and not answer.secure then
26a8cc9d9eb7 net.resolvers.service: Only do DANE with secure SRV records
Kim Alvefur <zash@zash.se>
parents: 10970
diff changeset
57 self.extra.use_dane = false;
12129
7a68d5828f3b net.resolvers: Report DNSSEC validation errors instead of NoError
Kim Alvefur <zash@zash.se>
parents: 12025
diff changeset
58 elseif answer.bogus then
7a68d5828f3b net.resolvers: Report DNSSEC validation errors instead of NoError
Kim Alvefur <zash@zash.se>
parents: 12025
diff changeset
59 self.last_error = "Validation error in SRV lookup";
7a68d5828f3b net.resolvers: Report DNSSEC validation errors instead of NoError
Kim Alvefur <zash@zash.se>
parents: 12025
diff changeset
60 ready();
7a68d5828f3b net.resolvers: Report DNSSEC validation errors instead of NoError
Kim Alvefur <zash@zash.se>
parents: 12025
diff changeset
61 return;
11710
26a8cc9d9eb7 net.resolvers.service: Only do DANE with secure SRV records
Kim Alvefur <zash@zash.se>
parents: 10970
diff changeset
62 end
26a8cc9d9eb7 net.resolvers.service: Only do DANE with secure SRV records
Kim Alvefur <zash@zash.se>
parents: 10970
diff changeset
63
9393
e2733f504d9e net.resolvers.service: Early return on empty result set
Kim Alvefur <zash@zash.se>
parents: 9392
diff changeset
64 if #answer == 0 then
9394
bcd94cc355d3 net.resolvers.service: Add support for fallback to bare domain and default port
Kim Alvefur <zash@zash.se>
parents: 9393
diff changeset
65 if self.extra and self.extra.default_port then
9395
794eda565c69 net.resolvers.service: Rename internal variable since net.connect uses it for __tostring
Kim Alvefur <zash@zash.se>
parents: 9394
diff changeset
66 table.insert(targets, { self.hostname, self.extra.default_port, self.conn_type, self.extra });
11901
26406ce35e20 net.connect: Propagate last error message from resolvers
Kim Alvefur <zash@zash.se>
parents: 11710
diff changeset
67 else
26406ce35e20 net.connect: Propagate last error message from resolvers
Kim Alvefur <zash@zash.se>
parents: 11710
diff changeset
68 self.last_error = "zero SRV records found";
9394
bcd94cc355d3 net.resolvers.service: Add support for fallback to bare domain and default port
Kim Alvefur <zash@zash.se>
parents: 9393
diff changeset
69 end
9393
e2733f504d9e net.resolvers.service: Early return on empty result set
Kim Alvefur <zash@zash.se>
parents: 9392
diff changeset
70 ready();
e2733f504d9e net.resolvers.service: Early return on empty result set
Kim Alvefur <zash@zash.se>
parents: 9392
diff changeset
71 return;
e2733f504d9e net.resolvers.service: Early return on empty result set
Kim Alvefur <zash@zash.se>
parents: 9392
diff changeset
72 end
e2733f504d9e net.resolvers.service: Early return on empty result set
Kim Alvefur <zash@zash.se>
parents: 9392
diff changeset
73
9392
f2d71e4284b7 net.resolvers.service: Understand when service is explicitly unavailable
Kim Alvefur <zash@zash.se>
parents: 9388
diff changeset
74 if #answer == 1 and answer[1].srv.target == "." then -- No service here
11901
26406ce35e20 net.connect: Propagate last error message from resolvers
Kim Alvefur <zash@zash.se>
parents: 11710
diff changeset
75 self.last_error = "service explicitly unavailable";
9392
f2d71e4284b7 net.resolvers.service: Understand when service is explicitly unavailable
Kim Alvefur <zash@zash.se>
parents: 9388
diff changeset
76 ready();
f2d71e4284b7 net.resolvers.service: Understand when service is explicitly unavailable
Kim Alvefur <zash@zash.se>
parents: 9388
diff changeset
77 return;
f2d71e4284b7 net.resolvers.service: Understand when service is explicitly unavailable
Kim Alvefur <zash@zash.se>
parents: 9388
diff changeset
78 end
f2d71e4284b7 net.resolvers.service: Understand when service is explicitly unavailable
Kim Alvefur <zash@zash.se>
parents: 9388
diff changeset
79
9397
e09ddd061ec4 net.resolvers.service: Sort SRV records in correct direction
Kim Alvefur <zash@zash.se>
parents: 9396
diff changeset
80 table.sort(answer, function (a, b) return a.srv.priority < b.srv.priority end);
8531
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
81 for _, record in ipairs(answer) do
9388
a5d11627ce5d net.resolvers.service: net.connect resolver that uses SRV records
Kim Alvefur <zash@zash.se>
parents: 8775
diff changeset
82 table.insert(targets, { record.srv.target, record.srv.port, self.conn_type, self.extra });
8531
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
83 end
11901
26406ce35e20 net.connect: Propagate last error message from resolvers
Kim Alvefur <zash@zash.se>
parents: 11710
diff changeset
84 else
26406ce35e20 net.connect: Propagate last error message from resolvers
Kim Alvefur <zash@zash.se>
parents: 11710
diff changeset
85 self.last_error = err;
8531
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
86 end
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
87 ready();
9395
794eda565c69 net.resolvers.service: Rename internal variable since net.connect uses it for __tostring
Kim Alvefur <zash@zash.se>
parents: 9394
diff changeset
88 end, "_" .. self.service .. "._" .. self.conn_type .. "." .. self.hostname, "SRV", "IN");
8531
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
89 end
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
90
9395
794eda565c69 net.resolvers.service: Rename internal variable since net.connect uses it for __tostring
Kim Alvefur <zash@zash.se>
parents: 9394
diff changeset
91 local function new(hostname, service, conn_type, extra)
10440
1ee87b4979c2 net.resolvers.service: Pass IP literals directly to basic resolver
Kim Alvefur <zash@zash.se>
parents: 10401
diff changeset
92 local is_ip = inet_pton(hostname);
1ee87b4979c2 net.resolvers.service: Pass IP literals directly to basic resolver
Kim Alvefur <zash@zash.se>
parents: 10401
diff changeset
93 if not is_ip and hostname:sub(1,1) == '[' then
1ee87b4979c2 net.resolvers.service: Pass IP literals directly to basic resolver
Kim Alvefur <zash@zash.se>
parents: 10401
diff changeset
94 is_ip = inet_pton(hostname:sub(2,-2));
1ee87b4979c2 net.resolvers.service: Pass IP literals directly to basic resolver
Kim Alvefur <zash@zash.se>
parents: 10401
diff changeset
95 end
1ee87b4979c2 net.resolvers.service: Pass IP literals directly to basic resolver
Kim Alvefur <zash@zash.se>
parents: 10401
diff changeset
96 if is_ip and extra and extra.default_port then
1ee87b4979c2 net.resolvers.service: Pass IP literals directly to basic resolver
Kim Alvefur <zash@zash.se>
parents: 10401
diff changeset
97 return basic.new(hostname, extra.default_port, conn_type, extra);
1ee87b4979c2 net.resolvers.service: Pass IP literals directly to basic resolver
Kim Alvefur <zash@zash.se>
parents: 10401
diff changeset
98 end
1ee87b4979c2 net.resolvers.service: Pass IP literals directly to basic resolver
Kim Alvefur <zash@zash.se>
parents: 10401
diff changeset
99
8531
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
100 return setmetatable({
10384
94c9c574cd8a net.resolvers: Apply IDNA conversion to ascii for DNS lookups (fixes #1426)
Kim Alvefur <zash@zash.se>
parents: 9397
diff changeset
101 hostname = idna_to_ascii(hostname);
9388
a5d11627ce5d net.resolvers.service: net.connect resolver that uses SRV records
Kim Alvefur <zash@zash.se>
parents: 8775
diff changeset
102 service = service;
8531
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
103 conn_type = conn_type or "tcp";
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
104 extra = extra;
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
105 }, resolver_mt);
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
106 end
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
107
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
108 return {
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
109 new = new;
601681acea73 net.connect: New API for outgoing connections, based on 'service resolvers'
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
110 };