aboutsummaryrefslogtreecommitdiffstats
path: root/awall/host.lua
blob: 7e7a2bf843b49e81734d6e2c4907166a39843c61 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
--[[
Host address resolver for Alpine Wall
Copyright (C) 2012 Kaarle Ritvanen
Licensed under the terms of GPL2
]]--


module(..., package.seeall)

local familypatterns = {inet='%d[%.%d/]+',
			inet6='[:%x/]+',
			domain='[%a-][%.%w-]*'}

local function getfamily(addr)
   for k, v in pairs(familypatterns) do
      if string.match(addr, '^'..v..'$') then return k end
   end
   error('Malformed host specification: '..addr)
end

local dnscache = {}

function resolve(host)
   local family = getfamily(host)
   if family == 'domain' then

      if not dnscache[host] then
	 dnscache[host] = {}
	 -- TODO use default server
	 for rec in io.popen('dig @8.8.8.8 '..host..' ANY'):lines() do
	    local name, rtype, addr =
	       string.match(rec, '^('..familypatterns.domain..')\t+%d+\t+IN\t+(A+)\t+(.+)')

	    if name and string.sub(name, 1, string.len(host) + 1) == host..'.' then
	       if rtype == 'A' then family = 'inet'
	       elseif rtype == 'AAAA' then family = 'inet6'
	       else family = nil end

	       if family then
		  assert(getfamily(addr) == family)
		  table.insert(dnscache[host], {family, addr})
	       end
	    end
	 end
	 if not dnscache[host][1] then error('Invalid host name: '..host) end
      end

      return dnscache[host]
   end

   return {{family, host}}
end