Merge Tobias->trunk
[prosody.git] / net / dns.lua
index d40174dfe9e8979283a60c96b44d38fdbdbe3328..23a453aa82e1c49be9e269655240f7238f43e463 100644 (file)
@@ -2,8 +2,6 @@
 -- This file is included with Prosody IM. It has modifications,
 -- which are hereby placed in the public domain.
 
--- public domain 20080404 lua@ztact.com
-
 
 -- todo: quick (default) header generation
 -- todo: nxdomain, error handling
@@ -15,7 +13,6 @@
 
 
 local socket = require "socket";
-local ztact = require "util.ztact";
 local timer = require "util.timer";
 
 local _, windows = pcall(require, "util.windows");
@@ -24,9 +21,50 @@ local is_windows = (_ and windows) or os.getenv("WINDIR");
 local coroutine, io, math, string, table =
       coroutine, io, math, string, table;
 
-local ipairs, next, pairs, print, setmetatable, tostring, assert, error, unpack =
-      ipairs, next, pairs, print, setmetatable, tostring, assert, error, unpack;
+local ipairs, next, pairs, print, setmetatable, tostring, assert, error, unpack, select, type=
+      ipairs, next, pairs, print, setmetatable, tostring, assert, error, unpack, select, type;
 
+local ztact = { -- public domain 20080404 lua@ztact.com
+       get = function(parent, ...)
+               local len = select('#', ...);
+               for i=1,len do
+                       parent = parent[select(i, ...)];
+                       if parent == nil then break; end
+               end
+               return parent;
+       end;
+       set = function(parent, ...)
+               local len = select('#', ...);
+               local key, value = select(len-1, ...);
+               local cutpoint, cutkey;
+
+               for i=1,len-2 do
+                       local key = select (i, ...)
+                       local child = parent[key]
+
+                       if value == nil then
+                               if child == nil then
+                                       return;
+                               elseif next(child, next(child)) then
+                                       cutpoint = nil; cutkey = nil;
+                               elseif cutpoint == nil then
+                                       cutpoint = parent; cutkey = key;
+                               end
+                       elseif child == nil then
+                               child = {};
+                               parent[key] = child;
+                       end
+                       parent = child
+               end
+
+               if value == nil and cutpoint then
+                       cutpoint[cutkey] = nil;
+               else
+                       parent[key] = value;
+                       return value;
+               end
+       end;
+};
 local get, set = ztact.get, ztact.set;
 
 local default_timeout = 15;
@@ -122,29 +160,24 @@ resolver.timeout = default_timeout;
 
 local SRV_tostring;
 
+local function default_rr_tostring(rr)
+       local rr_val = rr.type and rr[rr.type:lower()];
+       if type(rr_val) ~= "string" then
+               return "<UNKNOWN RDATA TYPE>";
+       end
+       return rr_val;
+end
+
+local special_tostrings = {
+       LOC = resolver.LOC_tostring;
+       MX = function (rr) return string.format('%2i %s', rr.pref, rr.mx); end;
+       SRV = SRV_tostring;
+};
 
 local rr_metatable = {};   -- - - - - - - - - - - - - - - - - - -  rr_metatable
 function rr_metatable.__tostring(rr)
-       local s0 = string.format('%2s %-5s %6i %-28s', rr.class, rr.type, rr.ttl, rr.name);
-       local s1 = '';
-       if rr.type == 'A' then
-               s1 = ' '..rr.a;
-       elseif rr.type == 'MX' then
-               s1 = string.format(' %2i %s', rr.pref, rr.mx);
-       elseif rr.type == 'CNAME' then
-               s1 = ' '..rr.cname;
-       elseif rr.type == 'LOC' then
-               s1 = ' '..resolver.LOC_tostring(rr);
-       elseif rr.type == 'NS' then
-               s1 = ' '..rr.ns;
-       elseif rr.type == 'SRV' then
-               s1 = ' '..SRV_tostring(rr);
-       elseif rr.type == 'TXT' then
-               s1 = ' '..rr.txt;
-       else
-               s1 = ' <UNKNOWN RDATA TYPE>';
-       end
-       return s0..s1;
+       local rr_string = (special_tostrings[rr.type] or default_rr_tostring)(rr);
+       return string.format('%2s %-5s %6i %-28s %s', rr.class, rr.type, rr.ttl, rr.name, rr_string);
 end
 
 
@@ -531,7 +564,7 @@ end
 
 function resolver:adddefaultnameservers()    -- - - - -  adddefaultnameservers
        if is_windows then
-               if windows then
+               if windows and windows.get_nameservers then
                        for _, server in ipairs(windows.get_nameservers()) do
                                self:addnameserver(server);
                        end
@@ -901,6 +934,9 @@ function resolver:lookupex(handler, qname, qtype, qclass)    -- - - - - - - - -
        return self:peek(qname, qtype, qclass) or self:query(qname, qtype, qclass);
 end
 
+function resolver:tohostname(ip)
+       return dns.lookup(ip:gsub("(%d+)%.(%d+)%.(%d+)%.(%d+)", "%4.%3.%2.%1.in-addr.arpa."), "PTR");
+end
 
 --print ---------------------------------------------------------------- print
 
@@ -976,6 +1012,10 @@ function dns.lookup(...)    -- - - - - - - - - - - - - - - - - - - - -  lookup
        return _resolver:lookup(...);
 end
 
+function dns.tohostname(...)
+       return _resolver:tohostname(...);
+end
+
 function dns.purge(...)    -- - - - - - - - - - - - - - - - - - - - - -  purge
        return _resolver:purge(...);
 end