12 |
12 |
13 -- reference: http://tools.ietf.org/html/rfc1035 |
13 -- reference: http://tools.ietf.org/html/rfc1035 |
14 -- reference: http://tools.ietf.org/html/rfc1876 (LOC) |
14 -- reference: http://tools.ietf.org/html/rfc1876 (LOC) |
15 |
15 |
16 |
16 |
17 require 'socket' |
17 local socket = require "socket"; |
18 local ztact = require 'util.ztact' |
18 local ztact = require "util.ztact"; |
19 local require = require |
|
20 local _, windows = pcall(require, "util.windows"); |
19 local _, windows = pcall(require, "util.windows"); |
21 local is_windows = (_ and windows) or os.getenv("WINDIR"); |
20 local is_windows = (_ and windows) or os.getenv("WINDIR"); |
22 |
21 |
23 local coroutine, io, math, socket, string, table = |
22 local coroutine, io, math, string, table = |
24 coroutine, io, math, socket, string, table |
23 coroutine, io, math, string, table; |
25 |
24 |
26 local ipairs, next, pairs, print, setmetatable, tostring, assert, error, unpack = |
25 local ipairs, next, pairs, print, setmetatable, tostring, assert, error, unpack = |
27 ipairs, next, pairs, print, setmetatable, tostring, assert, error, unpack |
26 ipairs, next, pairs, print, setmetatable, tostring, assert, error, unpack; |
28 |
27 |
29 local get, set = ztact.get, ztact.set |
28 local get, set = ztact.get, ztact.set; |
30 |
29 |
31 |
30 |
32 -------------------------------------------------- module dns |
31 -------------------------------------------------- module dns |
33 module ('dns') |
32 module('dns') |
34 local dns = _M; |
33 local dns = _M; |
35 |
34 |
36 |
35 |
37 -- dns type & class codes ------------------------------ dns type & class codes |
36 -- dns type & class codes ------------------------------ dns type & class codes |
38 |
37 |
39 |
38 |
40 local append = table.insert |
39 local append = table.insert |
41 |
40 |
42 |
41 |
43 local function highbyte (i) -- - - - - - - - - - - - - - - - - - - highbyte |
42 local function highbyte(i) -- - - - - - - - - - - - - - - - - - - highbyte |
44 return (i-(i%0x100))/0x100 |
43 return (i-(i%0x100))/0x100; |
45 end |
44 end |
46 |
45 |
47 |
46 |
48 local function augment (t) -- - - - - - - - - - - - - - - - - - - - augment |
47 local function augment (t) -- - - - - - - - - - - - - - - - - - - - augment |
49 local a = {} |
48 local a = {}; |
50 for i,s in pairs (t) do a[i] = s a[s] = s a[string.lower (s)] = s end |
49 for i,s in pairs(t) do |
51 return a |
50 a[i] = s; |
52 end |
51 a[s] = s; |
|
52 a[string.lower(s)] = s; |
|
53 end |
|
54 return a; |
|
55 end |
53 |
56 |
54 |
57 |
55 local function encode (t) -- - - - - - - - - - - - - - - - - - - - - encode |
58 local function encode (t) -- - - - - - - - - - - - - - - - - - - - - encode |
56 local code = {} |
59 local code = {}; |
57 for i,s in pairs (t) do |
60 for i,s in pairs(t) do |
58 local word = string.char (highbyte (i), i %0x100) |
61 local word = string.char(highbyte(i), i%0x100); |
59 code[i] = word |
62 code[i] = word; |
60 code[s] = word |
63 code[s] = word; |
61 code[string.lower (s)] = word |
64 code[string.lower(s)] = word; |
62 end |
65 end |
63 return code |
66 return code; |
64 end |
67 end |
65 |
68 |
66 |
69 |
67 dns.types = { |
70 dns.types = { |
68 'A', 'NS', 'MD', 'MF', 'CNAME', 'SOA', 'MB', 'MG', 'MR', 'NULL', 'WKS', |
71 'A', 'NS', 'MD', 'MF', 'CNAME', 'SOA', 'MB', 'MG', 'MR', 'NULL', 'WKS', |
69 'PTR', 'HINFO', 'MINFO', 'MX', 'TXT', |
72 'PTR', 'HINFO', 'MINFO', 'MX', 'TXT', |
70 [ 28] = 'AAAA', [ 29] = 'LOC', [ 33] = 'SRV', |
73 [ 28] = 'AAAA', [ 29] = 'LOC', [ 33] = 'SRV', |
71 [252] = 'AXFR', [253] = 'MAILB', [254] = 'MAILA', [255] = '*' } |
74 [252] = 'AXFR', [253] = 'MAILB', [254] = 'MAILA', [255] = '*' }; |
72 |
75 |
73 |
76 |
74 dns.classes = { 'IN', 'CS', 'CH', 'HS', [255] = '*' } |
77 dns.classes = { 'IN', 'CS', 'CH', 'HS', [255] = '*' }; |
75 |
78 |
76 |
79 |
77 dns.type = augment (dns.types) |
80 dns.type = augment (dns.types); |
78 dns.class = augment (dns.classes) |
81 dns.class = augment (dns.classes); |
79 dns.typecode = encode (dns.types) |
82 dns.typecode = encode (dns.types); |
80 dns.classcode = encode (dns.classes) |
83 dns.classcode = encode (dns.classes); |
81 |
84 |
82 |
85 |
83 |
86 |
84 local function standardize (qname, qtype, qclass) -- - - - - - - standardize |
87 local function standardize(qname, qtype, qclass) -- - - - - - - standardize |
85 if string.byte (qname, -1) ~= 0x2E then qname = qname..'.' end |
88 if string.byte(qname, -1) ~= 0x2E then qname = qname..'.'; end |
86 qname = string.lower (qname) |
89 qname = string.lower(qname); |
87 return qname, dns.type[qtype or 'A'], dns.class[qclass or 'IN'] |
90 return qname, dns.type[qtype or 'A'], dns.class[qclass or 'IN']; |
88 end |
91 end |
89 |
92 |
90 |
93 |
91 local function prune (rrs, time, soft) -- - - - - - - - - - - - - - - prune |
94 local function prune(rrs, time, soft) -- - - - - - - - - - - - - - - prune |
92 |
95 time = time or socket.gettime(); |
93 time = time or socket.gettime () |
96 for i,rr in pairs(rrs) do |
94 for i,rr in pairs (rrs) do |
97 if rr.tod then |
95 |
98 -- rr.tod = rr.tod - 50 -- accelerated decripitude |
96 if rr.tod then |
99 rr.ttl = math.floor(rr.tod - time); |
97 -- rr.tod = rr.tod - 50 -- accelerated decripitude |
100 if rr.ttl <= 0 then |
98 rr.ttl = math.floor (rr.tod - time) |
101 table.remove(rrs, i); |
99 if rr.ttl <= 0 then |
102 return prune(rrs, time, soft); -- Re-iterate |
100 table.remove(rrs, i); |
103 end |
101 return prune(rrs, time, soft); -- Re-iterate |
104 elseif soft == 'soft' then -- What is this? I forget! |
102 end |
105 assert(rr.ttl == 0); |
103 |
106 rrs[i] = nil; |
104 elseif soft == 'soft' then -- What is this? I forget! |
107 end |
105 assert (rr.ttl == 0) |
108 end |
106 rrs[i] = nil |
109 end |
107 end end end |
|
108 |
110 |
109 |
111 |
110 -- metatables & co. ------------------------------------------ metatables & co. |
112 -- metatables & co. ------------------------------------------ metatables & co. |
111 |
113 |
112 |
114 |
113 local resolver = {} |
115 local resolver = {}; |
114 resolver.__index = resolver |
116 resolver.__index = resolver; |
115 |
117 |
116 |
118 |
117 local SRV_tostring |
119 local SRV_tostring; |
118 |
120 |
119 |
121 |
120 local rr_metatable = {} -- - - - - - - - - - - - - - - - - - - rr_metatable |
122 local rr_metatable = {}; -- - - - - - - - - - - - - - - - - - - rr_metatable |
121 function rr_metatable.__tostring (rr) |
123 function rr_metatable.__tostring(rr) |
122 local s0 = string.format ( |
124 local s0 = string.format('%2s %-5s %6i %-28s', rr.class, rr.type, rr.ttl, rr.name); |
123 '%2s %-5s %6i %-28s', rr.class, rr.type, rr.ttl, rr.name ) |
125 local s1 = ''; |
124 local s1 = '' |
126 if rr.type == 'A' then |
125 if rr.type == 'A' then s1 = ' '..rr.a |
127 s1 = ' '..rr.a; |
126 elseif rr.type == 'MX' then |
128 elseif rr.type == 'MX' then |
127 s1 = string.format (' %2i %s', rr.pref, rr.mx) |
129 s1 = string.format(' %2i %s', rr.pref, rr.mx); |
128 elseif rr.type == 'CNAME' then s1 = ' '..rr.cname |
130 elseif rr.type == 'CNAME' then |
129 elseif rr.type == 'LOC' then s1 = ' '..resolver.LOC_tostring (rr) |
131 s1 = ' '..rr.cname; |
130 elseif rr.type == 'NS' then s1 = ' '..rr.ns |
132 elseif rr.type == 'LOC' then |
131 elseif rr.type == 'SRV' then s1 = ' '..SRV_tostring (rr) |
133 s1 = ' '..resolver.LOC_tostring(rr); |
132 elseif rr.type == 'TXT' then s1 = ' '..rr.txt |
134 elseif rr.type == 'NS' then |
133 else s1 = ' <UNKNOWN RDATA TYPE>' end |
135 s1 = ' '..rr.ns; |
134 return s0..s1 |
136 elseif rr.type == 'SRV' then |
135 end |
137 s1 = ' '..SRV_tostring(rr); |
136 |
138 elseif rr.type == 'TXT' then |
137 |
139 s1 = ' '..rr.txt; |
138 local rrs_metatable = {} -- - - - - - - - - - - - - - - - - - rrs_metatable |
140 else |
139 function rrs_metatable.__tostring (rrs) |
141 s1 = ' <UNKNOWN RDATA TYPE>'; |
140 local t = {} |
142 end |
141 for i,rr in pairs (rrs) do append (t, tostring (rr)..'\n') end |
143 return s0..s1; |
142 return table.concat (t) |
144 end |
143 end |
145 |
144 |
146 |
145 |
147 local rrs_metatable = {}; -- - - - - - - - - - - - - - - - - - rrs_metatable |
146 local cache_metatable = {} -- - - - - - - - - - - - - - - - cache_metatable |
148 function rrs_metatable.__tostring(rrs) |
147 function cache_metatable.__tostring (cache) |
149 local t = {}; |
148 local time = socket.gettime () |
150 for i,rr in pairs(rrs) do |
149 local t = {} |
151 append(t, tostring(rr)..'\n'); |
150 for class,types in pairs (cache) do |
152 end |
151 for type,names in pairs (types) do |
153 return table.concat(t); |
152 for name,rrs in pairs (names) do |
154 end |
153 prune (rrs, time) |
155 |
154 append (t, tostring (rrs)) end end end |
156 |
155 return table.concat (t) |
157 local cache_metatable = {}; -- - - - - - - - - - - - - - - - cache_metatable |
156 end |
158 function cache_metatable.__tostring(cache) |
157 |
159 local time = socket.gettime(); |
158 |
160 local t = {}; |
159 function resolver:new () -- - - - - - - - - - - - - - - - - - - - - resolver |
161 for class,types in pairs(cache) do |
160 local r = { active = {}, cache = {}, unsorted = {} } |
162 for type,names in pairs(types) do |
161 setmetatable (r, resolver) |
163 for name,rrs in pairs(names) do |
162 setmetatable (r.cache, cache_metatable) |
164 prune(rrs, time); |
163 setmetatable (r.unsorted, { __mode = 'kv' }) |
165 append(t, tostring(rrs)); |
164 return r |
166 end |
165 end |
167 end |
|
168 end |
|
169 return table.concat(t); |
|
170 end |
|
171 |
|
172 |
|
173 function resolver:new() -- - - - - - - - - - - - - - - - - - - - - resolver |
|
174 local r = { active = {}, cache = {}, unsorted = {} }; |
|
175 setmetatable(r, resolver); |
|
176 setmetatable(r.cache, cache_metatable); |
|
177 setmetatable(r.unsorted, { __mode = 'kv' }); |
|
178 return r; |
|
179 end |
166 |
180 |
167 |
181 |
168 -- packet layer -------------------------------------------------- packet layer |
182 -- packet layer -------------------------------------------------- packet layer |
169 |
183 |
170 |
184 |
171 function dns.random (...) -- - - - - - - - - - - - - - - - - - - dns.random |
185 function dns.random(...) -- - - - - - - - - - - - - - - - - - - dns.random |
172 math.randomseed (10000*socket.gettime ()) |
186 math.randomseed(10000*socket.gettime()); |
173 dns.random = math.random |
187 dns.random = math.random; |
174 return dns.random (...) |
188 return dns.random(...); |
175 end |
189 end |
176 |
190 |
177 |
191 |
178 local function encodeHeader (o) -- - - - - - - - - - - - - - - encodeHeader |
192 local function encodeHeader(o) -- - - - - - - - - - - - - - - encodeHeader |
179 |
193 o = o or {}; |
180 o = o or {} |
194 o.id = o.id or dns.random(0, 0xffff); -- 16b (random) id |
181 |
195 |
182 o.id = o.id or -- 16b (random) id |
196 o.rd = o.rd or 1; -- 1b 1 recursion desired |
183 dns.random (0, 0xffff) |
197 o.tc = o.tc or 0; -- 1b 1 truncated response |
184 |
198 o.aa = o.aa or 0; -- 1b 1 authoritative response |
185 o.rd = o.rd or 1 -- 1b 1 recursion desired |
199 o.opcode = o.opcode or 0; -- 4b 0 query |
186 o.tc = o.tc or 0 -- 1b 1 truncated response |
200 -- 1 inverse query |
187 o.aa = o.aa or 0 -- 1b 1 authoritative response |
|
188 o.opcode = o.opcode or 0 -- 4b 0 query |
|
189 -- 1 inverse query |
|
190 -- 2 server status request |
201 -- 2 server status request |
191 -- 3-15 reserved |
202 -- 3-15 reserved |
192 o.qr = o.qr or 0 -- 1b 0 query, 1 response |
203 o.qr = o.qr or 0; -- 1b 0 query, 1 response |
193 |
204 |
194 o.rcode = o.rcode or 0 -- 4b 0 no error |
205 o.rcode = o.rcode or 0; -- 4b 0 no error |
195 -- 1 format error |
206 -- 1 format error |
196 -- 2 server failure |
207 -- 2 server failure |
197 -- 3 name error |
208 -- 3 name error |
198 -- 4 not implemented |
209 -- 4 not implemented |
199 -- 5 refused |
210 -- 5 refused |
200 -- 6-15 reserved |
211 -- 6-15 reserved |
201 o.z = o.z or 0 -- 3b 0 resvered |
212 o.z = o.z or 0; -- 3b 0 resvered |
202 o.ra = o.ra or 0 -- 1b 1 recursion available |
213 o.ra = o.ra or 0; -- 1b 1 recursion available |
203 |
214 |
204 o.qdcount = o.qdcount or 1 -- 16b number of question RRs |
215 o.qdcount = o.qdcount or 1; -- 16b number of question RRs |
205 o.ancount = o.ancount or 0 -- 16b number of answers RRs |
216 o.ancount = o.ancount or 0; -- 16b number of answers RRs |
206 o.nscount = o.nscount or 0 -- 16b number of nameservers RRs |
217 o.nscount = o.nscount or 0; -- 16b number of nameservers RRs |
207 o.arcount = o.arcount or 0 -- 16b number of additional RRs |
218 o.arcount = o.arcount or 0; -- 16b number of additional RRs |
208 |
219 |
209 -- string.char() rounds, so prevent roundup with -0.4999 |
220 -- string.char() rounds, so prevent roundup with -0.4999 |
210 local header = string.char ( |
221 local header = string.char( |
211 highbyte (o.id), o.id %0x100, |
222 highbyte(o.id), o.id %0x100, |
212 o.rd + 2*o.tc + 4*o.aa + 8*o.opcode + 128*o.qr, |
223 o.rd + 2*o.tc + 4*o.aa + 8*o.opcode + 128*o.qr, |
213 o.rcode + 16*o.z + 128*o.ra, |
224 o.rcode + 16*o.z + 128*o.ra, |
214 highbyte (o.qdcount), o.qdcount %0x100, |
225 highbyte(o.qdcount), o.qdcount %0x100, |
215 highbyte (o.ancount), o.ancount %0x100, |
226 highbyte(o.ancount), o.ancount %0x100, |
216 highbyte (o.nscount), o.nscount %0x100, |
227 highbyte(o.nscount), o.nscount %0x100, |
217 highbyte (o.arcount), o.arcount %0x100 ) |
228 highbyte(o.arcount), o.arcount %0x100 |
218 |
229 ); |
219 return header, o.id |
230 |
220 end |
231 return header, o.id; |
221 |
232 end |
222 |
233 |
223 local function encodeName (name) -- - - - - - - - - - - - - - - - encodeName |
234 |
224 local t = {} |
235 local function encodeName(name) -- - - - - - - - - - - - - - - - encodeName |
225 for part in string.gmatch (name, '[^.]+') do |
236 local t = {}; |
226 append (t, string.char (string.len (part))) |
237 for part in string.gmatch(name, '[^.]+') do |
227 append (t, part) |
238 append(t, string.char(string.len(part))); |
228 end |
239 append(t, part); |
229 append (t, string.char (0)) |
240 end |
230 return table.concat (t) |
241 append(t, string.char(0)); |
231 end |
242 return table.concat(t); |
232 |
243 end |
233 |
244 |
234 local function encodeQuestion (qname, qtype, qclass) -- - - - encodeQuestion |
245 |
235 qname = encodeName (qname) |
246 local function encodeQuestion(qname, qtype, qclass) -- - - - encodeQuestion |
236 qtype = dns.typecode[qtype or 'a'] |
247 qname = encodeName(qname); |
237 qclass = dns.classcode[qclass or 'in'] |
248 qtype = dns.typecode[qtype or 'a']; |
238 return qname..qtype..qclass; |
249 qclass = dns.classcode[qclass or 'in']; |
239 end |
250 return qname..qtype..qclass; |
240 |
251 end |
241 |
252 |
242 function resolver:byte (len) -- - - - - - - - - - - - - - - - - - - - - byte |
253 |
243 len = len or 1 |
254 function resolver:byte(len) -- - - - - - - - - - - - - - - - - - - - - byte |
244 local offset = self.offset |
255 len = len or 1; |
245 local last = offset + len - 1 |
256 local offset = self.offset; |
246 if last > #self.packet then |
257 local last = offset + len - 1; |
247 error (string.format ('out of bounds: %i>%i', last, #self.packet)) end |
258 if last > #self.packet then |
248 self.offset = offset + len |
259 error(string.format('out of bounds: %i>%i', last, #self.packet)); |
249 return string.byte (self.packet, offset, last) |
260 end |
250 end |
261 self.offset = offset + len; |
251 |
262 return string.byte(self.packet, offset, last); |
252 |
263 end |
253 function resolver:word () -- - - - - - - - - - - - - - - - - - - - - - word |
264 |
254 local b1, b2 = self:byte (2) |
265 |
255 return 0x100*b1 + b2 |
266 function resolver:word() -- - - - - - - - - - - - - - - - - - - - - - word |
256 end |
267 local b1, b2 = self:byte(2); |
|
268 return 0x100*b1 + b2; |
|
269 end |
257 |
270 |
258 |
271 |
259 function resolver:dword () -- - - - - - - - - - - - - - - - - - - - - dword |
272 function resolver:dword () -- - - - - - - - - - - - - - - - - - - - - dword |
260 local b1, b2, b3, b4 = self:byte (4) |
273 local b1, b2, b3, b4 = self:byte(4); |
261 --print ('dword', b1, b2, b3, b4) |
274 --print('dword', b1, b2, b3, b4); |
262 return 0x1000000*b1 + 0x10000*b2 + 0x100*b3 + b4 |
275 return 0x1000000*b1 + 0x10000*b2 + 0x100*b3 + b4; |
263 end |
276 end |
264 |
277 |
265 |
278 |
266 function resolver:sub (len) -- - - - - - - - - - - - - - - - - - - - - - sub |
279 function resolver:sub(len) -- - - - - - - - - - - - - - - - - - - - - - sub |
267 len = len or 1 |
280 len = len or 1; |
268 local s = string.sub (self.packet, self.offset, self.offset + len - 1) |
281 local s = string.sub(self.packet, self.offset, self.offset + len - 1); |
269 self.offset = self.offset + len |
282 self.offset = self.offset + len; |
270 return s |
283 return s; |
271 end |
284 end |
272 |
285 |
273 |
286 |
274 function resolver:header (force) -- - - - - - - - - - - - - - - - - - header |
287 function resolver:header(force) -- - - - - - - - - - - - - - - - - - header |
275 |
288 local id = self:word(); |
276 local id = self:word () |
289 --print(string.format(':header id %x', id)); |
277 --print (string.format (':header id %x', id)) |
290 if not self.active[id] and not force then return nil; end |
278 if not self.active[id] and not force then return nil end |
291 |
279 |
292 local h = { id = id }; |
280 local h = { id = id } |
293 |
281 |
294 local b1, b2 = self:byte(2); |
282 local b1, b2 = self:byte (2) |
295 |
283 |
296 h.rd = b1 %2; |
284 h.rd = b1 %2 |
297 h.tc = b1 /2%2; |
285 h.tc = b1 /2%2 |
298 h.aa = b1 /4%2; |
286 h.aa = b1 /4%2 |
299 h.opcode = b1 /8%16; |
287 h.opcode = b1 /8%16 |
300 h.qr = b1 /128; |
288 h.qr = b1 /128 |
301 |
289 |
302 h.rcode = b2 %16; |
290 h.rcode = b2 %16 |
303 h.z = b2 /16%8; |
291 h.z = b2 /16%8 |
304 h.ra = b2 /128; |
292 h.ra = b2 /128 |
305 |
293 |
306 h.qdcount = self:word(); |
294 h.qdcount = self:word () |
307 h.ancount = self:word(); |
295 h.ancount = self:word () |
308 h.nscount = self:word(); |
296 h.nscount = self:word () |
309 h.arcount = self:word(); |
297 h.arcount = self:word () |
310 |
298 |
311 for k,v in pairs(h) do h[k] = v-v%1; end |
299 for k,v in pairs (h) do h[k] = v-v%1 end |
312 |
300 |
313 return h; |
301 return h |
314 end |
302 end |
315 |
303 |
316 |
304 |
317 function resolver:name() -- - - - - - - - - - - - - - - - - - - - - - name |
305 function resolver:name () -- - - - - - - - - - - - - - - - - - - - - - name |
318 local remember, pointers = nil, 0; |
306 local remember, pointers = nil, 0 |
319 local len = self:byte(); |
307 local len = self:byte () |
320 local n = {}; |
308 local n = {} |
321 while len > 0 do |
309 while len > 0 do |
322 if len >= 0xc0 then -- name is "compressed" |
310 if len >= 0xc0 then -- name is "compressed" |
323 pointers = pointers + 1; |
311 pointers = pointers + 1 |
324 if pointers >= 20 then error('dns error: 20 pointers'); end; |
312 if pointers >= 20 then error ('dns error: 20 pointers') end |
325 local offset = ((len-0xc0)*0x100) + self:byte(); |
313 local offset = ((len-0xc0)*0x100) + self:byte () |
326 remember = remember or self.offset; |
314 remember = remember or self.offset |
327 self.offset = offset + 1; -- +1 for lua |
315 self.offset = offset + 1 -- +1 for lua |
328 else -- name is not compressed |
316 else -- name is not compressed |
329 append(n, self:sub(len)..'.'); |
317 append (n, self:sub (len)..'.') |
330 end |
318 end |
331 len = self:byte(); |
319 len = self:byte () |
332 end |
320 end |
333 self.offset = remember or self.offset; |
321 self.offset = remember or self.offset |
334 return table.concat(n); |
322 return table.concat (n) |
335 end |
323 end |
336 |
324 |
337 |
325 |
338 function resolver:question() -- - - - - - - - - - - - - - - - - - question |
326 function resolver:question () -- - - - - - - - - - - - - - - - - - question |
339 local q = {}; |
327 local q = {} |
340 q.name = self:name(); |
328 q.name = self:name () |
341 q.type = dns.type[self:word()]; |
329 q.type = dns.type[self:word ()] |
342 q.class = dns.class[self:word()]; |
330 q.class = dns.class[self:word ()] |
343 return q; |
331 return q |
344 end |
332 end |
345 |
333 |
346 |
334 |
347 function resolver:A(rr) -- - - - - - - - - - - - - - - - - - - - - - - - A |
335 function resolver:A (rr) -- - - - - - - - - - - - - - - - - - - - - - - - A |
348 local b1, b2, b3, b4 = self:byte(4); |
336 local b1, b2, b3, b4 = self:byte (4) |
349 rr.a = string.format('%i.%i.%i.%i', b1, b2, b3, b4); |
337 rr.a = string.format ('%i.%i.%i.%i', b1, b2, b3, b4) |
350 end |
338 end |
351 |
339 |
352 |
340 |
353 function resolver:CNAME(rr) -- - - - - - - - - - - - - - - - - - - - CNAME |
341 function resolver:CNAME (rr) -- - - - - - - - - - - - - - - - - - - - CNAME |
354 rr.cname = self:name(); |
342 rr.cname = self:name () |
355 end |
343 end |
356 |
344 |
357 |
345 |
358 function resolver:MX(rr) -- - - - - - - - - - - - - - - - - - - - - - - MX |
346 function resolver:MX (rr) -- - - - - - - - - - - - - - - - - - - - - - - MX |
359 rr.pref = self:word(); |
347 rr.pref = self:word () |
360 rr.mx = self:name(); |
348 rr.mx = self:name () |
361 end |
349 end |
362 |
350 |
363 |
351 |
364 function resolver:LOC_nibble_power() -- - - - - - - - - - LOC_nibble_power |
352 function resolver:LOC_nibble_power () -- - - - - - - - - - LOC_nibble_power |
365 local b = self:byte(); |
353 local b = self:byte () |
366 --print('nibbles', ((b-(b%0x10))/0x10), (b%0x10)); |
354 --print ('nibbles', ((b-(b%0x10))/0x10), (b%0x10)) |
367 return ((b-(b%0x10))/0x10) * (10^(b%0x10)); |
355 return ((b-(b%0x10))/0x10) * (10^(b%0x10)) |
368 end |
356 end |
369 |
357 |
370 |
358 |
371 function resolver:LOC(rr) -- - - - - - - - - - - - - - - - - - - - - - LOC |
359 function resolver:LOC (rr) -- - - - - - - - - - - - - - - - - - - - - - LOC |
372 rr.version = self:byte(); |
360 rr.version = self:byte () |
373 if rr.version == 0 then |
361 if rr.version == 0 then |
374 rr.loc = rr.loc or {}; |
362 rr.loc = rr.loc or {} |
375 rr.loc.size = self:LOC_nibble_power(); |
363 rr.loc.size = self:LOC_nibble_power () |
376 rr.loc.horiz_pre = self:LOC_nibble_power(); |
364 rr.loc.horiz_pre = self:LOC_nibble_power () |
377 rr.loc.vert_pre = self:LOC_nibble_power(); |
365 rr.loc.vert_pre = self:LOC_nibble_power () |
378 rr.loc.latitude = self:dword(); |
366 rr.loc.latitude = self:dword () |
379 rr.loc.longitude = self:dword(); |
367 rr.loc.longitude = self:dword () |
380 rr.loc.altitude = self:dword(); |
368 rr.loc.altitude = self:dword () |
381 end |
369 end end |
382 end |
370 |
383 |
371 |
384 |
372 local function LOC_tostring_degrees (f, pos, neg) -- - - - - - - - - - - - - |
385 local function LOC_tostring_degrees(f, pos, neg) -- - - - - - - - - - - - - |
373 f = f - 0x80000000 |
386 f = f - 0x80000000; |
374 if f < 0 then pos = neg f = -f end |
387 if f < 0 then pos = neg; f = -f; end |
375 local deg, min, msec |
388 local deg, min, msec; |
376 msec = f%60000 |
389 msec = f%60000; |
377 f = (f-msec)/60000 |
390 f = (f-msec)/60000; |
378 min = f%60 |
391 min = f%60; |
379 deg = (f-min)/60 |
392 deg = (f-min)/60; |
380 return string.format ('%3d %2d %2.3f %s', deg, min, msec/1000, pos) |
393 return string.format('%3d %2d %2.3f %s', deg, min, msec/1000, pos); |
381 end |
394 end |
382 |
395 |
383 |
396 |
384 function resolver.LOC_tostring (rr) -- - - - - - - - - - - - - LOC_tostring |
397 function resolver.LOC_tostring(rr) -- - - - - - - - - - - - - LOC_tostring |
385 |
398 local t = {}; |
386 local t = {} |
399 |
387 |
400 --[[ |
388 --[[ |
401 for k,name in pairs { 'size', 'horiz_pre', 'vert_pre', 'latitude', 'longitude', 'altitude' } do |
389 for k,name in pairs { 'size', 'horiz_pre', 'vert_pre', |
402 append(t, string.format('%4s%-10s: %12.0f\n', '', name, rr.loc[name])); |
390 'latitude', 'longitude', 'altitude' } do |
403 end |
391 append (t, string.format ('%4s%-10s: %12.0f\n', '', name, rr.loc[name])) |
404 --]] |
392 end |
405 |
393 --]] |
406 append(t, string.format( |
394 |
407 '%s %s %.2fm %.2fm %.2fm %.2fm', |
395 append ( t, string.format ( |
408 LOC_tostring_degrees (rr.loc.latitude, 'N', 'S'), |
396 '%s %s %.2fm %.2fm %.2fm %.2fm', |
409 LOC_tostring_degrees (rr.loc.longitude, 'E', 'W'), |
397 LOC_tostring_degrees (rr.loc.latitude, 'N', 'S'), |
410 (rr.loc.altitude - 10000000) / 100, |
398 LOC_tostring_degrees (rr.loc.longitude, 'E', 'W'), |
411 rr.loc.size / 100, |
399 (rr.loc.altitude - 10000000) / 100, |
412 rr.loc.horiz_pre / 100, |
400 rr.loc.size / 100, |
413 rr.loc.vert_pre / 100 |
401 rr.loc.horiz_pre / 100, |
414 )); |
402 rr.loc.vert_pre / 100 ) ) |
415 |
403 |
416 return table.concat(t); |
404 return table.concat (t) |
417 end |
405 end |
418 |
406 |
419 |
407 |
420 function resolver:NS(rr) -- - - - - - - - - - - - - - - - - - - - - - - NS |
408 function resolver:NS (rr) -- - - - - - - - - - - - - - - - - - - - - - - NS |
421 rr.ns = self:name(); |
409 rr.ns = self:name () |
422 end |
410 end |
423 |
411 |
424 |
412 |
425 function resolver:SOA(rr) -- - - - - - - - - - - - - - - - - - - - - - SOA |
413 function resolver:SOA (rr) -- - - - - - - - - - - - - - - - - - - - - - SOA |
426 end |
414 end |
427 |
415 |
428 |
416 |
429 function resolver:SRV(rr) -- - - - - - - - - - - - - - - - - - - - - - SRV |
417 function resolver:SRV (rr) -- - - - - - - - - - - - - - - - - - - - - - SRV |
430 rr.srv = {}; |
418 rr.srv = {} |
431 rr.srv.priority = self:word(); |
419 rr.srv.priority = self:word () |
432 rr.srv.weight = self:word(); |
420 rr.srv.weight = self:word () |
433 rr.srv.port = self:word(); |
421 rr.srv.port = self:word () |
434 rr.srv.target = self:name(); |
422 rr.srv.target = self:name () |
435 end |
423 end |
436 |
424 |
437 |
425 |
438 function SRV_tostring(rr) -- - - - - - - - - - - - - - - - - - SRV_tostring |
426 function SRV_tostring (rr) -- - - - - - - - - - - - - - - - - - SRV_tostring |
439 local s = rr.srv; |
427 local s = rr.srv |
440 return string.format( '%5d %5d %5d %s', s.priority, s.weight, s.port, s.target ); |
428 return string.format ( '%5d %5d %5d %s', |
441 end |
429 s.priority, s.weight, s.port, s.target ) |
442 |
430 end |
443 |
431 |
444 function resolver:TXT(rr) -- - - - - - - - - - - - - - - - - - - - - - TXT |
432 |
445 rr.txt = self:sub (rr.rdlength); |
433 function resolver:TXT (rr) -- - - - - - - - - - - - - - - - - - - - - - TXT |
446 end |
434 rr.txt = self:sub (rr.rdlength) |
447 |
435 end |
448 |
436 |
449 function resolver:rr() -- - - - - - - - - - - - - - - - - - - - - - - - rr |
437 |
450 local rr = {}; |
438 function resolver:rr () -- - - - - - - - - - - - - - - - - - - - - - - - rr |
451 setmetatable(rr, rr_metatable); |
439 local rr = {} |
452 rr.name = self:name(self); |
440 setmetatable (rr, rr_metatable) |
453 rr.type = dns.type[self:word()] or rr.type; |
441 rr.name = self:name (self) |
454 rr.class = dns.class[self:word()] or rr.class; |
442 rr.type = dns.type[self:word ()] or rr.type |
455 rr.ttl = 0x10000*self:word() + self:word(); |
443 rr.class = dns.class[self:word ()] or rr.class |
456 rr.rdlength = self:word(); |
444 rr.ttl = 0x10000*self:word () + self:word () |
457 |
445 rr.rdlength = self:word () |
458 if rr.ttl <= 0 then |
446 |
459 rr.tod = self.time + 30; |
447 if rr.ttl <= 0 then rr.tod = self.time + 30; |
460 else |
448 else rr.tod = self.time + rr.ttl end |
461 rr.tod = self.time + rr.ttl; |
449 |
462 end |
450 local remember = self.offset |
463 |
451 local rr_parser = self[dns.type[rr.type]] |
464 local remember = self.offset; |
452 if rr_parser then rr_parser (self, rr) end |
465 local rr_parser = self[dns.type[rr.type]]; |
453 self.offset = remember |
466 if rr_parser then rr_parser(self, rr); end |
454 rr.rdata = self:sub (rr.rdlength) |
467 self.offset = remember; |
455 return rr |
468 rr.rdata = self:sub(rr.rdlength); |
456 end |
469 return rr; |
|
470 end |
457 |
471 |
458 |
472 |
459 function resolver:rrs (count) -- - - - - - - - - - - - - - - - - - - - - rrs |
473 function resolver:rrs (count) -- - - - - - - - - - - - - - - - - - - - - rrs |
460 local rrs = {} |
474 local rrs = {}; |
461 for i = 1,count do append (rrs, self:rr ()) end |
475 for i = 1,count do append(rrs, self:rr()); end |
462 return rrs |
476 return rrs; |
463 end |
477 end |
464 |
478 |
465 |
479 |
466 function resolver:decode (packet, force) -- - - - - - - - - - - - - - decode |
480 function resolver:decode(packet, force) -- - - - - - - - - - - - - - decode |
467 |
481 self.packet, self.offset = packet, 1; |
468 self.packet, self.offset = packet, 1 |
482 local header = self:header(force); |
469 local header = self:header (force) |
483 if not header then return nil; end |
470 if not header then return nil end |
484 local response = { header = header }; |
471 local response = { header = header } |
485 |
472 |
486 response.question = {}; |
473 response.question = {} |
487 local offset = self.offset; |
474 local offset = self.offset |
488 for i = 1,response.header.qdcount do |
475 for i = 1,response.header.qdcount do |
489 append(response.question, self:question()); |
476 append (response.question, self:question ()) end |
490 end |
477 response.question.raw = string.sub (self.packet, offset, self.offset - 1) |
491 response.question.raw = string.sub(self.packet, offset, self.offset - 1); |
478 |
492 |
479 if not force then |
493 if not force then |
480 if not self.active[response.header.id] or |
494 if not self.active[response.header.id] or not self.active[response.header.id][response.question.raw] then |
481 not self.active[response.header.id][response.question.raw] then |
495 return nil; |
482 return nil end end |
496 end |
483 |
497 end |
484 response.answer = self:rrs (response.header.ancount) |
498 |
485 response.authority = self:rrs (response.header.nscount) |
499 response.answer = self:rrs(response.header.ancount); |
486 response.additional = self:rrs (response.header.arcount) |
500 response.authority = self:rrs(response.header.nscount); |
487 |
501 response.additional = self:rrs(response.header.arcount); |
488 return response |
502 |
489 end |
503 return response; |
|
504 end |
490 |
505 |
491 |
506 |
492 -- socket layer -------------------------------------------------- socket layer |
507 -- socket layer -------------------------------------------------- socket layer |
493 |
508 |
494 |
509 |
495 resolver.delays = { 1, 3 } |
510 resolver.delays = { 1, 3 }; |
496 |
511 |
497 |
512 |
498 function resolver:addnameserver (address) -- - - - - - - - - - addnameserver |
513 function resolver:addnameserver(address) -- - - - - - - - - - addnameserver |
499 self.server = self.server or {} |
514 self.server = self.server or {}; |
500 append (self.server, address) |
515 append(self.server, address); |
501 end |
516 end |
502 |
517 |
503 |
518 |
504 function resolver:setnameserver (address) -- - - - - - - - - - setnameserver |
519 function resolver:setnameserver(address) -- - - - - - - - - - setnameserver |
505 self.server = {} |
520 self.server = {}; |
506 self:addnameserver (address) |
521 self:addnameserver(address); |
507 end |
522 end |
508 |
523 |
509 |
524 |
510 function resolver:adddefaultnameservers () -- - - - - adddefaultnameservers |
525 function resolver:adddefaultnameservers() -- - - - - adddefaultnameservers |
511 if is_windows then |
526 if is_windows then |
512 if windows then |
527 if windows then |
513 for _, server in ipairs(windows.get_nameservers()) do |
528 for _, server in ipairs(windows.get_nameservers()) do |
514 self:addnameserver(server) |
529 self:addnameserver(server); |
515 end |
530 end |
516 end |
531 end |
517 if not self.server or #self.server == 0 then |
532 if not self.server or #self.server == 0 then |
518 -- TODO log warning about no nameservers, adding opendns servers as fallback |
533 -- TODO log warning about no nameservers, adding opendns servers as fallback |
519 self:addnameserver("208.67.222.222") |
534 self:addnameserver("208.67.222.222"); |
520 self:addnameserver("208.67.220.220") |
535 self:addnameserver("208.67.220.220") ; |
521 end |
536 end |
522 else -- posix |
537 else -- posix |
523 local resolv_conf = io.open("/etc/resolv.conf"); |
538 local resolv_conf = io.open("/etc/resolv.conf"); |
524 if resolv_conf then |
539 if resolv_conf then |
525 for line in resolv_conf:lines() do |
540 for line in resolv_conf:lines() do |
526 local address = line:gsub("#.*$", ""):match('^%s*nameserver%s+(%d+%.%d+%.%d+%.%d+)%s*$') |
541 local address = line:gsub("#.*$", ""):match('^%s*nameserver%s+(%d+%.%d+%.%d+%.%d+)%s*$'); |
527 if address then self:addnameserver (address) end |
542 if address then self:addnameserver(address) end |
528 end |
543 end |
529 end |
544 end |
530 if not self.server or #self.server == 0 then |
545 if not self.server or #self.server == 0 then |
531 -- TODO log warning about no nameservers, adding localhost as the default nameserver |
546 -- TODO log warning about no nameservers, adding localhost as the default nameserver |
532 self:addnameserver("127.0.0.1"); |
547 self:addnameserver("127.0.0.1"); |
533 end |
548 end |
534 end |
549 end |
535 end |
550 end |
536 |
551 |
537 |
552 |
538 function resolver:getsocket (servernum) -- - - - - - - - - - - - - getsocket |
553 function resolver:getsocket(servernum) -- - - - - - - - - - - - - getsocket |
539 |
554 self.socket = self.socket or {}; |
540 self.socket = self.socket or {} |
555 self.socketset = self.socketset or {}; |
541 self.socketset = self.socketset or {} |
556 |
542 |
557 local sock = self.socket[servernum]; |
543 local sock = self.socket[servernum] |
558 if sock then return sock; end |
544 if sock then return sock end |
559 |
545 |
560 sock = socket.udp(); |
546 sock = socket.udp () |
561 if self.socket_wrapper then sock = self.socket_wrapper(sock, self); end |
547 if self.socket_wrapper then sock = self.socket_wrapper (sock, self) end |
562 sock:settimeout(0); |
548 sock:settimeout (0) |
563 -- todo: attempt to use a random port, fallback to 0 |
549 -- todo: attempt to use a random port, fallback to 0 |
564 sock:setsockname('*', 0); |
550 sock:setsockname ('*', 0) |
565 sock:setpeername(self.server[servernum], 53); |
551 sock:setpeername (self.server[servernum], 53) |
566 self.socket[servernum] = sock; |
552 self.socket[servernum] = sock |
567 self.socketset[sock] = servernum; |
553 self.socketset[sock] = servernum |
568 return sock; |
554 return sock |
569 end |
555 end |
570 |
556 |
571 function resolver:voidsocket(sock) |
557 function resolver:voidsocket (sock) |
572 if self.socket[sock] then |
558 if self.socket[sock] then |
573 self.socketset[self.socket[sock]] = nil; |
559 self.socketset[self.socket[sock]] = nil |
574 self.socket[sock] = nil; |
560 self.socket[sock] = nil |
575 elseif self.socketset[sock] then |
561 elseif self.socketset[sock] then |
576 self.socket[self.socketset[sock]] = nil; |
562 self.socket[self.socketset[sock]] = nil |
577 self.socketset[sock] = nil; |
563 self.socketset[sock] = nil |
578 end |
564 end |
579 end |
565 end |
580 |
566 |
581 function resolver:socket_wrapper_set(func) -- - - - - - - socket_wrapper_set |
567 function resolver:socket_wrapper_set (func) -- - - - - - - socket_wrapper_set |
582 self.socket_wrapper = func; |
568 self.socket_wrapper = func |
583 end |
569 end |
|
570 |
584 |
571 |
585 |
572 function resolver:closeall () -- - - - - - - - - - - - - - - - - - closeall |
586 function resolver:closeall () -- - - - - - - - - - - - - - - - - - closeall |
573 for i,sock in ipairs (self.socket) do |
587 for i,sock in ipairs(self.socket) do |
574 self.socket[i] = nil; |
588 self.socket[i] = nil; |
575 self.socketset[sock] = nil; |
589 self.socketset[sock] = nil; |
576 sock:close(); |
590 sock:close(); |
577 end |
591 end |
578 end |
592 end |
579 |
593 |
580 |
594 |
581 function resolver:remember (rr, type) -- - - - - - - - - - - - - - remember |
595 function resolver:remember(rr, type) -- - - - - - - - - - - - - - remember |
582 |
596 --print ('remember', type, rr.class, rr.type, rr.name) |
583 --print ('remember', type, rr.class, rr.type, rr.name) |
597 |
584 |
598 if type ~= '*' then |
585 if type ~= '*' then |
599 type = rr.type; |
586 type = rr.type |
600 local all = get(self.cache, rr.class, '*', rr.name); |
587 local all = get (self.cache, rr.class, '*', rr.name) |
601 --print('remember all', all); |
588 --print ('remember all', all) |
602 if all then append(all, rr); end |
589 if all then append (all, rr) end |
603 end |
590 end |
604 |
591 |
605 self.cache = self.cache or setmetatable({}, cache_metatable); |
592 self.cache = self.cache or setmetatable ({}, cache_metatable) |
606 local rrs = get(self.cache, rr.class, type, rr.name) or |
593 local rrs = get (self.cache, rr.class, type, rr.name) or |
607 set(self.cache, rr.class, type, rr.name, setmetatable({}, rrs_metatable)); |
594 set (self.cache, rr.class, type, rr.name, setmetatable ({}, rrs_metatable)) |
608 append(rrs, rr); |
595 append (rrs, rr) |
609 |
596 |
610 if type == 'MX' then self.unsorted[rrs] = true; end |
597 if type == 'MX' then self.unsorted[rrs] = true end |
611 end |
598 end |
612 |
599 |
613 |
600 |
614 local function comp_mx(a, b) -- - - - - - - - - - - - - - - - - - - comp_mx |
601 local function comp_mx (a, b) -- - - - - - - - - - - - - - - - - - - comp_mx |
615 return (a.pref == b.pref) and (a.mx < b.mx) or (a.pref < b.pref); |
602 return (a.pref == b.pref) and (a.mx < b.mx) or (a.pref < b.pref) |
616 end |
603 end |
|
604 |
617 |
605 |
618 |
606 function resolver:peek (qname, qtype, qclass) -- - - - - - - - - - - - peek |
619 function resolver:peek (qname, qtype, qclass) -- - - - - - - - - - - - peek |
607 qname, qtype, qclass = standardize (qname, qtype, qclass) |
620 qname, qtype, qclass = standardize(qname, qtype, qclass); |
608 local rrs = get (self.cache, qclass, qtype, qname) |
621 local rrs = get(self.cache, qclass, qtype, qname); |
609 if not rrs then return nil end |
622 if not rrs then return nil; end |
610 if prune (rrs, socket.gettime ()) and qtype == '*' or not next (rrs) then |
623 if prune(rrs, socket.gettime()) and qtype == '*' or not next(rrs) then |
611 set (self.cache, qclass, qtype, qname, nil) return nil end |
624 set(self.cache, qclass, qtype, qname, nil); |
612 if self.unsorted[rrs] then table.sort (rrs, comp_mx) end |
625 return nil; |
613 return rrs |
626 end |
614 end |
627 if self.unsorted[rrs] then table.sort (rrs, comp_mx); end |
615 |
628 return rrs; |
616 |
629 end |
617 function resolver:purge (soft) -- - - - - - - - - - - - - - - - - - - purge |
630 |
618 if soft == 'soft' then |
631 |
619 self.time = socket.gettime () |
632 function resolver:purge(soft) -- - - - - - - - - - - - - - - - - - - purge |
620 for class,types in pairs (self.cache or {}) do |
633 if soft == 'soft' then |
621 for type,names in pairs (types) do |
634 self.time = socket.gettime(); |
622 for name,rrs in pairs (names) do |
635 for class,types in pairs(self.cache or {}) do |
623 prune (rrs, self.time, 'soft') |
636 for type,names in pairs(types) do |
624 end end end |
637 for name,rrs in pairs(names) do |
625 else self.cache = {} end |
638 prune(rrs, self.time, 'soft') |
626 end |
639 end |
627 |
640 end |
628 |
641 end |
629 function resolver:query (qname, qtype, qclass) -- - - - - - - - - - -- query |
642 else self.cache = {}; end |
630 |
643 end |
631 qname, qtype, qclass = standardize (qname, qtype, qclass) |
644 |
632 |
645 |
633 if not self.server then self:adddefaultnameservers () end |
646 function resolver:query(qname, qtype, qclass) -- - - - - - - - - - -- query |
634 |
647 qname, qtype, qclass = standardize(qname, qtype, qclass) |
635 local question = encodeQuestion (qname, qtype, qclass) |
648 |
636 local peek = self:peek (qname, qtype, qclass) |
649 if not self.server then self:adddefaultnameservers(); end |
637 if peek then return peek end |
650 |
638 |
651 local question = encodeQuestion(qname, qtype, qclass); |
639 local header, id = encodeHeader () |
652 local peek = self:peek (qname, qtype, qclass); |
640 --print ('query id', id, qclass, qtype, qname) |
653 if peek then return peek; end |
641 local o = { packet = header..question, |
654 |
642 server = self.best_server, |
655 local header, id = encodeHeader(); |
643 delay = 1, |
656 --print ('query id', id, qclass, qtype, qname) |
644 retry = socket.gettime () + self.delays[1] } |
657 local o = { |
|
658 packet = header..question, |
|
659 server = self.best_server, |
|
660 delay = 1, |
|
661 retry = socket.gettime() + self.delays[1] |
|
662 }; |
645 |
663 |
646 -- remember the query |
664 -- remember the query |
647 self.active[id] = self.active[id] or {} |
665 self.active[id] = self.active[id] or {}; |
648 self.active[id][question] = o |
666 self.active[id][question] = o; |
649 |
667 |
650 -- remember which coroutine wants the answer |
668 -- remember which coroutine wants the answer |
651 local co = coroutine.running () |
669 local co = coroutine.running(); |
652 if co then |
670 if co then |
653 set (self.wanted, qclass, qtype, qname, co, true) |
671 set(self.wanted, qclass, qtype, qname, co, true); |
654 --set (self.yielded, co, qclass, qtype, qname, true) |
672 --set(self.yielded, co, qclass, qtype, qname, true); |
655 end |
673 end |
656 |
674 |
657 self:getsocket (o.server):send (o.packet) |
675 self:getsocket (o.server):send (o.packet) |
658 |
|
659 end |
676 end |
660 |
677 |
661 function resolver:servfail(sock) |
678 function resolver:servfail(sock) |
662 -- Resend all queries for this server |
679 -- Resend all queries for this server |
663 |
680 |
664 local num = self.socketset[sock] |
681 local num = self.socketset[sock] |
665 |
682 |
666 -- Socket is dead now |
683 -- Socket is dead now |
667 self:voidsocket(sock); |
684 self:voidsocket(sock); |
668 |
685 |
669 -- Find all requests to the down server, and retry on the next server |
686 -- Find all requests to the down server, and retry on the next server |
670 self.time = socket.gettime () |
687 self.time = socket.gettime(); |
671 for id,queries in pairs (self.active) do |
688 for id,queries in pairs(self.active) do |
672 for question,o in pairs (queries) do |
689 for question,o in pairs(queries) do |
673 if o.server == num then -- This request was to the broken server |
690 if o.server == num then -- This request was to the broken server |
674 o.server = o.server + 1 -- Use next server |
691 o.server = o.server + 1 -- Use next server |
675 if o.server > #self.server then |
692 if o.server > #self.server then |
676 o.server = 1 |
693 o.server = 1; |
677 end |
694 end |
678 |
695 |
679 o.retries = (o.retries or 0) + 1; |
696 o.retries = (o.retries or 0) + 1; |
680 if o.retries >= #self.server then |
697 if o.retries >= #self.server then |
681 --print ('timeout') |
698 --print('timeout'); |
682 queries[question] = nil |
699 queries[question] = nil; |
683 else |
700 else |
684 local _a = self:getsocket(o.server); |
701 local _a = self:getsocket(o.server); |
685 if _a then _a:send (o.packet) end |
702 if _a then _a:send(o.packet); end |
686 end |
703 end |
687 end |
704 end |
688 end |
705 end |
689 end |
706 end |
690 |
707 |
691 if num == self.best_server then |
708 if num == self.best_server then |
692 self.best_server = self.best_server + 1 |
709 self.best_server = self.best_server + 1; |
693 if self.best_server > #self.server then |
710 if self.best_server > #self.server then |
694 -- Exhausted all servers, try first again |
711 -- Exhausted all servers, try first again |
695 self.best_server = 1 |
712 self.best_server = 1; |
696 end |
713 end |
697 end |
714 end |
698 end |
715 end |
699 |
716 |
700 function resolver:receive (rset) -- - - - - - - - - - - - - - - - - receive |
717 function resolver:receive(rset) -- - - - - - - - - - - - - - - - - receive |
701 |
718 --print('receive'); print(self.socket); |
702 --print 'receive' print (self.socket) |
719 self.time = socket.gettime(); |
703 self.time = socket.gettime () |
720 rset = rset or self.socket; |
704 rset = rset or self.socket |
721 |
705 |
722 local response; |
706 local response |
723 for i,sock in pairs(rset) do |
707 for i,sock in pairs (rset) do |
724 |
708 |
725 if self.socketset[sock] then |
709 if self.socketset[sock] then |
726 local packet = sock:receive(); |
710 local packet = sock:receive () |
727 if packet then |
711 if packet then |
728 response = self:decode(packet); |
712 |
729 if response then |
713 response = self:decode (packet) |
730 --print('received response'); |
714 if response then |
731 --self.print(response); |
715 --print 'received response' |
732 |
716 --self.print (response) |
733 for i,section in pairs({ 'answer', 'authority', 'additional' }) do |
717 |
734 for j,rr in pairs(response[section]) do |
718 for i,section in pairs { 'answer', 'authority', 'additional' } do |
735 self:remember(rr, response.question[1].type) |
719 for j,rr in pairs (response[section]) do |
736 end |
720 self:remember (rr, response.question[1].type) end end |
737 end |
721 |
738 |
722 -- retire the query |
739 -- retire the query |
723 local queries = self.active[response.header.id] |
740 local queries = self.active[response.header.id]; |
724 if queries[response.question.raw] then |
741 if queries[response.question.raw] then |
725 queries[response.question.raw] = nil end |
742 queries[response.question.raw] = nil; |
726 if not next (queries) then self.active[response.header.id] = nil end |
743 end |
727 if not next (self.active) then self:closeall () end |
744 if not next(queries) then self.active[response.header.id] = nil; end |
728 |
745 if not next(self.active) then self:closeall(); end |
729 -- was the query on the wanted list? |
746 |
730 local q = response.question |
747 -- was the query on the wanted list? |
731 local cos = get (self.wanted, q.class, q.type, q.name) |
748 local q = response.question; |
732 if cos then |
749 local cos = get(self.wanted, q.class, q.type, q.name); |
733 for co in pairs (cos) do |
750 if cos then |
734 set (self.yielded, co, q.class, q.type, q.name, nil) |
751 for co in pairs(cos) do |
735 if coroutine.status(co) == "suspended" then coroutine.resume (co) end |
752 set(self.yielded, co, q.class, q.type, q.name, nil); |
736 end |
753 if coroutine.status(co) == "suspended" then coroutine.resume(co); end |
737 set (self.wanted, q.class, q.type, q.name, nil) |
754 end |
738 end end end end end |
755 set(self.wanted, q.class, q.type, q.name, nil); |
739 |
756 end |
740 return response |
757 end |
741 end |
758 end |
|
759 end |
|
760 end |
|
761 |
|
762 return response; |
|
763 end |
742 |
764 |
743 |
765 |
744 function resolver:feed(sock, packet) |
766 function resolver:feed(sock, packet) |
745 --print 'receive' print (self.socket) |
767 --print('receive'); print(self.socket); |
746 self.time = socket.gettime () |
768 self.time = socket.gettime(); |
747 |
769 |
748 local response = self:decode (packet) |
770 local response = self:decode(packet); |
749 if response then |
771 if response then |
750 --print 'received response' |
772 --print('received response'); |
751 --self.print (response) |
773 --self.print(response); |
752 |
774 |
753 for i,section in pairs { 'answer', 'authority', 'additional' } do |
775 for i,section in pairs({ 'answer', 'authority', 'additional' }) do |
754 for j,rr in pairs (response[section]) do |
776 for j,rr in pairs(response[section]) do |
755 self:remember (rr, response.question[1].type) |
777 self:remember(rr, response.question[1].type); |
756 end |
778 end |
757 end |
779 end |
758 |
780 |
759 -- retire the query |
781 -- retire the query |
760 local queries = self.active[response.header.id] |
782 local queries = self.active[response.header.id]; |
761 if queries[response.question.raw] then |
783 if queries[response.question.raw] then |
762 queries[response.question.raw] = nil |
784 queries[response.question.raw] = nil; |
763 end |
785 end |
764 if not next (queries) then self.active[response.header.id] = nil end |
786 if not next(queries) then self.active[response.header.id] = nil; end |
765 if not next (self.active) then self:closeall () end |
787 if not next(self.active) then self:closeall(); end |
766 |
788 |
767 -- was the query on the wanted list? |
789 -- was the query on the wanted list? |
768 local q = response.question[1] |
790 local q = response.question[1]; |
769 if q then |
791 if q then |
770 local cos = get (self.wanted, q.class, q.type, q.name) |
792 local cos = get(self.wanted, q.class, q.type, q.name); |
771 if cos then |
793 if cos then |
772 for co in pairs (cos) do |
794 for co in pairs(cos) do |
773 set (self.yielded, co, q.class, q.type, q.name, nil) |
795 set(self.yielded, co, q.class, q.type, q.name, nil); |
774 if coroutine.status(co) == "suspended" then coroutine.resume (co) end |
796 if coroutine.status(co) == "suspended" then coroutine.resume(co); end |
775 end |
797 end |
776 set (self.wanted, q.class, q.type, q.name, nil) |
798 set(self.wanted, q.class, q.type, q.name, nil); |
777 end |
799 end |
778 end |
800 end |
779 end |
801 end |
780 |
802 |
781 return response |
803 return response; |
782 end |
804 end |
783 |
805 |
784 function resolver:cancel(data) |
806 function resolver:cancel(data) |
785 local cos = get (self.wanted, unpack(data, 1, 3)) |
807 local cos = get(self.wanted, unpack(data, 1, 3)); |
786 if cos then |
808 if cos then |
787 cos[data[4]] = nil; |
809 cos[data[4]] = nil; |
788 end |
810 end |
789 end |
811 end |
790 |
812 |
791 function resolver:pulse () -- - - - - - - - - - - - - - - - - - - - - pulse |
813 function resolver:pulse() -- - - - - - - - - - - - - - - - - - - - - pulse |
792 |
814 --print(':pulse'); |
793 --print ':pulse' |
815 while self:receive() do end |
794 while self:receive() do end |
816 if not next(self.active) then return nil; end |
795 if not next (self.active) then return nil end |
817 |
796 |
818 self.time = socket.gettime(); |
797 self.time = socket.gettime () |
819 for id,queries in pairs(self.active) do |
798 for id,queries in pairs (self.active) do |
820 for question,o in pairs(queries) do |
799 for question,o in pairs (queries) do |
821 if self.time >= o.retry then |
800 if self.time >= o.retry then |
822 |
801 |
823 o.server = o.server + 1; |
802 o.server = o.server + 1 |
824 if o.server > #self.server then |
803 if o.server > #self.server then |
825 o.server = 1; |
804 o.server = 1 |
826 o.delay = o.delay + 1; |
805 o.delay = o.delay + 1 |
827 end |
806 end |
828 |
807 |
829 if o.delay > #self.delays then |
808 if o.delay > #self.delays then |
830 --print('timeout'); |
809 --print ('timeout') |
831 queries[question] = nil; |
810 queries[question] = nil |
832 if not next(queries) then self.active[id] = nil; end |
811 if not next (queries) then self.active[id] = nil end |
833 if not next(self.active) then return nil; end |
812 if not next (self.active) then return nil end |
834 else |
813 else |
835 --print('retry', o.server, o.delay); |
814 --print ('retry', o.server, o.delay) |
836 local _a = self.socket[o.server]; |
815 local _a = self.socket[o.server]; |
837 if _a then _a:send(o.packet); end |
816 if _a then _a:send (o.packet) end |
838 o.retry = self.time + self.delays[o.delay]; |
817 o.retry = self.time + self.delays[o.delay] |
839 end |
818 end end end end |
840 end |
819 |
841 end |
820 if next (self.active) then return true end |
842 end |
821 return nil |
843 |
822 end |
844 if next(self.active) then return true; end |
823 |
845 return nil; |
824 |
846 end |
825 function resolver:lookup (qname, qtype, qclass) -- - - - - - - - - - lookup |
847 |
826 self:query (qname, qtype, qclass) |
848 |
827 while self:pulse () do socket.select (self.socket, nil, 4) end |
849 function resolver:lookup(qname, qtype, qclass) -- - - - - - - - - - lookup |
828 --print (self.cache) |
850 self:query (qname, qtype, qclass) |
829 return self:peek (qname, qtype, qclass) |
851 while self:pulse() do socket.select(self.socket, nil, 4); end |
830 end |
852 --print(self.cache); |
831 |
853 return self:peek(qname, qtype, qclass); |
832 function resolver:lookupex (handler, qname, qtype, qclass) -- - - - - - - - - - lookup |
854 end |
833 return self:peek (qname, qtype, qclass) or self:query (qname, qtype, qclass) |
855 |
834 end |
856 function resolver:lookupex(handler, qname, qtype, qclass) -- - - - - - - - - - lookup |
|
857 return self:peek(qname, qtype, qclass) or self:query(qname, qtype, qclass); |
|
858 end |
835 |
859 |
836 |
860 |
837 --print ---------------------------------------------------------------- print |
861 --print ---------------------------------------------------------------- print |
838 |
862 |
839 |
863 |
840 local hints = { -- - - - - - - - - - - - - - - - - - - - - - - - - - - hints |
864 local hints = { -- - - - - - - - - - - - - - - - - - - - - - - - - - - hints |
841 qr = { [0]='query', 'response' }, |
865 qr = { [0]='query', 'response' }, |
842 opcode = { [0]='query', 'inverse query', 'server status request' }, |
866 opcode = { [0]='query', 'inverse query', 'server status request' }, |
843 aa = { [0]='non-authoritative', 'authoritative' }, |
867 aa = { [0]='non-authoritative', 'authoritative' }, |
844 tc = { [0]='complete', 'truncated' }, |
868 tc = { [0]='complete', 'truncated' }, |
845 rd = { [0]='recursion not desired', 'recursion desired' }, |
869 rd = { [0]='recursion not desired', 'recursion desired' }, |
846 ra = { [0]='recursion not available', 'recursion available' }, |
870 ra = { [0]='recursion not available', 'recursion available' }, |
847 z = { [0]='(reserved)' }, |
871 z = { [0]='(reserved)' }, |
848 rcode = { [0]='no error', 'format error', 'server failure', 'name error', |
872 rcode = { [0]='no error', 'format error', 'server failure', 'name error', 'not implemented' }, |
849 'not implemented' }, |
873 |
850 |
874 type = dns.type, |
851 type = dns.type, |
875 class = dns.class |
852 class = dns.class, } |
876 }; |
853 |
877 |
854 |
878 |
855 local function hint (p, s) -- - - - - - - - - - - - - - - - - - - - - - hint |
879 local function hint(p, s) -- - - - - - - - - - - - - - - - - - - - - - hint |
856 return (hints[s] and hints[s][p[s]]) or '' end |
880 return (hints[s] and hints[s][p[s]]) or ''; |
857 |
881 end |
858 |
882 |
859 function resolver.print (response) -- - - - - - - - - - - - - resolver.print |
883 |
860 |
884 function resolver.print(response) -- - - - - - - - - - - - - resolver.print |
861 for s,s in pairs { 'id', 'qr', 'opcode', 'aa', 'tc', 'rd', 'ra', 'z', |
885 for s,s in pairs { 'id', 'qr', 'opcode', 'aa', 'tc', 'rd', 'ra', 'z', |
862 'rcode', 'qdcount', 'ancount', 'nscount', 'arcount' } do |
886 'rcode', 'qdcount', 'ancount', 'nscount', 'arcount' } do |
863 print ( string.format ('%-30s', 'header.'..s), |
887 print( string.format('%-30s', 'header.'..s), response.header[s], hint(response.header, s) ); |
864 response.header[s], hint (response.header, s) ) |
888 end |
865 end |
889 |
866 |
890 for i,question in ipairs(response.question) do |
867 for i,question in ipairs (response.question) do |
891 print(string.format ('question[%i].name ', i), question.name); |
868 print (string.format ('question[%i].name ', i), question.name) |
892 print(string.format ('question[%i].type ', i), question.type); |
869 print (string.format ('question[%i].type ', i), question.type) |
893 print(string.format ('question[%i].class ', i), question.class); |
870 print (string.format ('question[%i].class ', i), question.class) |
894 end |
871 end |
895 |
872 |
896 local common = { name=1, type=1, class=1, ttl=1, rdlength=1, rdata=1 }; |
873 local common = { name=1, type=1, class=1, ttl=1, rdlength=1, rdata=1 } |
897 local tmp; |
874 local tmp |
898 for s,s in pairs({'answer', 'authority', 'additional'}) do |
875 for s,s in pairs {'answer', 'authority', 'additional'} do |
899 for i,rr in pairs(response[s]) do |
876 for i,rr in pairs (response[s]) do |
900 for j,t in pairs({ 'name', 'type', 'class', 'ttl', 'rdlength' }) do |
877 for j,t in pairs { 'name', 'type', 'class', 'ttl', 'rdlength' } do |
901 tmp = string.format('%s[%i].%s', s, i, t); |
878 tmp = string.format ('%s[%i].%s', s, i, t) |
902 print(string.format('%-30s', tmp), rr[t], hint(rr, t)); |
879 print (string.format ('%-30s', tmp), rr[t], hint (rr, t)) |
903 end |
880 end |
904 for j,t in pairs(rr) do |
881 for j,t in pairs (rr) do |
905 if not common[j] then |
882 if not common[j] then |
906 tmp = string.format('%s[%i].%s', s, i, j); |
883 tmp = string.format ('%s[%i].%s', s, i, j) |
907 print(string.format('%-30s %s', tostring(tmp), tostring(t))); |
884 print (string.format ('%-30s %s', tostring(tmp), tostring(t))) |
908 end |
885 end end end end end |
909 end |
|
910 end |
|
911 end |
|
912 end |
886 |
913 |
887 |
914 |
888 -- module api ------------------------------------------------------ module api |
915 -- module api ------------------------------------------------------ module api |
889 |
916 |
890 |
917 |
891 local function resolve (func, ...) -- - - - - - - - - - - - - - resolver_get |
918 local function resolve(func, ...) -- - - - - - - - - - - - - - resolver_get |
892 return func (dns._resolver, ...) |
919 return func(dns._resolver, ...); |
893 end |
920 end |
894 |
921 |
895 |
922 |
896 function dns.resolver () -- - - - - - - - - - - - - - - - - - - - - resolver |
923 function dns.resolver () -- - - - - - - - - - - - - - - - - - - - - resolver |
897 |
924 -- this function seems to be redundant with resolver.new () |
898 -- this function seems to be redundant with resolver.new () |
925 |
899 |
926 local r = { active = {}, cache = {}, unsorted = {}, wanted = {}, yielded = {}, best_server = 1 }; |
900 local r = { active = {}, cache = {}, unsorted = {}, wanted = {}, yielded = {}, |
927 setmetatable (r, resolver); |
901 best_server = 1 } |
928 setmetatable (r.cache, cache_metatable); |
902 setmetatable (r, resolver) |
929 setmetatable (r.unsorted, { __mode = 'kv' }); |
903 setmetatable (r.cache, cache_metatable) |
930 return r; |
904 setmetatable (r.unsorted, { __mode = 'kv' }) |
931 end |
905 return r |
932 |
906 end |
933 |
907 |
934 function dns.lookup(...) -- - - - - - - - - - - - - - - - - - - - - lookup |
908 |
935 return resolve(resolver.lookup, ...); |
909 function dns.lookup (...) -- - - - - - - - - - - - - - - - - - - - - lookup |
936 end |
910 return resolve (resolver.lookup, ...) end |
937 |
911 |
938 |
912 |
939 function dns.purge(...) -- - - - - - - - - - - - - - - - - - - - - - purge |
913 function dns.purge (...) -- - - - - - - - - - - - - - - - - - - - - - purge |
940 return resolve(resolver.purge, ...); |
914 return resolve (resolver.purge, ...) end |
941 end |
915 |
942 |
916 function dns.peek (...) -- - - - - - - - - - - - - - - - - - - - - - - peek |
943 function dns.peek(...) -- - - - - - - - - - - - - - - - - - - - - - - peek |
917 return resolve (resolver.peek, ...) end |
944 return resolve(resolver.peek, ...); |
918 |
945 end |
919 |
946 |
920 function dns.query (...) -- - - - - - - - - - - - - - - - - - - - - - query |
947 |
921 return resolve (resolver.query, ...) end |
948 function dns.query(...) -- - - - - - - - - - - - - - - - - - - - - - query |
922 |
949 return resolve(resolver.query, ...); |
923 function dns.feed (...) -- - - - - - - - - - - - - - - - - - - - - - feed |
950 end |
924 return resolve (resolver.feed, ...) end |
951 |
|
952 function dns.feed(...) -- - - - - - - - - - - - - - - - - - - - - - feed |
|
953 return resolve(resolver.feed, ...); |
|
954 end |
925 |
955 |
926 function dns.cancel(...) -- - - - - - - - - - - - - - - - - - - - - - cancel |
956 function dns.cancel(...) -- - - - - - - - - - - - - - - - - - - - - - cancel |
927 return resolve(resolver.cancel, ...) end |
957 return resolve(resolver.cancel, ...); |
928 |
958 end |
929 function dns:socket_wrapper_set (...) -- - - - - - - - - socket_wrapper_set |
959 |
930 return resolve (resolver.socket_wrapper_set, ...) end |
960 function dns:socket_wrapper_set(...) -- - - - - - - - - socket_wrapper_set |
931 |
961 return resolve(resolver.socket_wrapper_set, ...); |
932 dns._resolver = dns.resolver () |
962 end |
933 |
963 |
934 return dns |
964 dns._resolver = dns.resolver(); |
|
965 |
|
966 return dns; |