net/dns.lua

changeset 2070
72357b1c6d88
parent 2068
1e1ee53d7f6e
child 2081
b9bbb709d62e
equal deleted inserted replaced
2068:1e1ee53d7f6e 2070:72357b1c6d88
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;

mercurial