mirror of
https://github.com/cloudwu/skynet.git
synced 2026-07-22 02:53:09 +00:00
dns: parse /etc/hosts
This commit is contained in:
@@ -88,6 +88,79 @@ local CACHE = {}
|
|||||||
|
|
||||||
local dns = {}
|
local dns = {}
|
||||||
local request_pool = {}
|
local request_pool = {}
|
||||||
|
local local_hosts -- local static table lookup for hostnames
|
||||||
|
|
||||||
|
dns.DEFAULT_HOSTS = "/etc/hosts"
|
||||||
|
dns.DEFAULT_RESOLV_CONF = "/etc/resolv.conf"
|
||||||
|
|
||||||
|
-- return name type: 'ipv4', 'ipv6', or 'hostname'
|
||||||
|
local function guess_name_type(name)
|
||||||
|
if name:match("^[%d%.]+$") then
|
||||||
|
return "ipv4"
|
||||||
|
end
|
||||||
|
|
||||||
|
if name:find(":") then
|
||||||
|
return "ipv6"
|
||||||
|
end
|
||||||
|
|
||||||
|
return "hostname"
|
||||||
|
end
|
||||||
|
|
||||||
|
-- http://man7.org/linux/man-pages/man5/hosts.5.html
|
||||||
|
local function parse_hosts()
|
||||||
|
if not dns.DEFAULT_HOSTS then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local f = io.open(dns.DEFAULT_HOSTS)
|
||||||
|
if not f then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local rts = {}
|
||||||
|
for line in f:lines() do
|
||||||
|
local ip, hosts = string.match(line, "^%s*([%[%]%x%.%:]+)%s+([^#;]*)")
|
||||||
|
local family = guess_name_type(ip)
|
||||||
|
if hosts and family ~= "hostname" then
|
||||||
|
for host in hosts:gmatch("%S+") do
|
||||||
|
host = host:lower()
|
||||||
|
local rt = rts[host]
|
||||||
|
if not rt then
|
||||||
|
rt = {}
|
||||||
|
rts[host] = rt
|
||||||
|
end
|
||||||
|
|
||||||
|
if not rt[family] then
|
||||||
|
rt[family] = {}
|
||||||
|
end
|
||||||
|
table.insert(rt[family], ip)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return rts
|
||||||
|
end
|
||||||
|
|
||||||
|
-- http://man7.org/linux/man-pages/man5/resolv.conf.5.html
|
||||||
|
local function parse_resolv_conf()
|
||||||
|
if not dns.DEFAULT_RESOLV_CONF then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local f = io.open(dns.DEFAULT_RESOLV_CONF)
|
||||||
|
if not f then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local server
|
||||||
|
for line in f:lines() do
|
||||||
|
server = line:match("%s*nameserver%s+([^#;%s]+)")
|
||||||
|
if server then
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
f:close()
|
||||||
|
return server
|
||||||
|
end
|
||||||
|
|
||||||
function dns.flush()
|
function dns.flush()
|
||||||
CACHE[QTYPE.A] = setmetatable({},weak)
|
CACHE[QTYPE.A] = setmetatable({},weak)
|
||||||
@@ -290,6 +363,14 @@ local function connect_server()
|
|||||||
local fd = socket.udp(function(str, from)
|
local fd = socket.udp(function(str, from)
|
||||||
resolve(str)
|
resolve(str)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
if not dns_server.address then
|
||||||
|
dns_server.address = parse_resolv_conf()
|
||||||
|
dns_server.port = 53
|
||||||
|
end
|
||||||
|
|
||||||
|
assert(dns_server.address, "Call dns.server first")
|
||||||
|
|
||||||
local ok, err = pcall(socket.udp_connect,fd, dns_server.address, dns_server.port)
|
local ok, err = pcall(socket.udp_connect,fd, dns_server.address, dns_server.port)
|
||||||
if not ok then
|
if not ok then
|
||||||
socket.close(fd)
|
socket.close(fd)
|
||||||
@@ -326,22 +407,8 @@ local function touch_server()
|
|||||||
end
|
end
|
||||||
|
|
||||||
function dns.server(server, port)
|
function dns.server(server, port)
|
||||||
if not server then
|
|
||||||
local f = assert(io.open "/etc/resolv.conf")
|
|
||||||
for line in f:lines() do
|
|
||||||
server = line:match("%s*nameserver%s+([^%s]+)")
|
|
||||||
if server then
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
f:close()
|
|
||||||
assert(server, "Can't get nameserver")
|
|
||||||
end
|
|
||||||
assert(dns_server.fd == nil) -- only set dns.server once
|
|
||||||
dns_server.address = server
|
dns_server.address = server
|
||||||
dns_server.port = port or 53
|
dns_server.port = port or 53
|
||||||
touch_server()
|
|
||||||
return dns_server.address
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local function lookup_cache(name, qtype, ignorettl)
|
local function lookup_cache(name, qtype, ignorettl)
|
||||||
@@ -383,10 +450,30 @@ local function suspend(tid, name, qtype)
|
|||||||
return req.answers[1], req.answers
|
return req.answers[1], req.answers
|
||||||
end
|
end
|
||||||
|
|
||||||
function dns.resolve(name, ipv6)
|
-- lookup local static table
|
||||||
|
local function local_resolve(name, ipv6)
|
||||||
|
if not local_hosts then
|
||||||
|
local_hosts = parse_hosts()
|
||||||
|
end
|
||||||
|
|
||||||
|
if not local_hosts then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local family = ipv6 and "ipv6" or "ipv4"
|
||||||
|
local t = local_hosts[name]
|
||||||
|
if t then
|
||||||
|
local answers = t[family]
|
||||||
|
if answers then
|
||||||
|
return answers[1], answers
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
-- lookup dns server
|
||||||
|
local function remote_resolve(name, ipv6)
|
||||||
local qtype = ipv6 and QTYPE.AAAA or QTYPE.A
|
local qtype = ipv6 and QTYPE.AAAA or QTYPE.A
|
||||||
local name = name:lower()
|
|
||||||
assert(verify_domain_name(name) , "illegal name")
|
|
||||||
local answers = lookup_cache(name, qtype)
|
local answers = lookup_cache(name, qtype)
|
||||||
if answers then
|
if answers then
|
||||||
return answers[1], answers
|
return answers[1], answers
|
||||||
@@ -397,10 +484,31 @@ function dns.resolve(name, ipv6)
|
|||||||
qdcount = 1,
|
qdcount = 1,
|
||||||
}
|
}
|
||||||
local req = pack_header(question_header) .. pack_question(name, qtype, QCLASS.IN)
|
local req = pack_header(question_header) .. pack_question(name, qtype, QCLASS.IN)
|
||||||
assert(dns_server.address, "Call dns.server first")
|
|
||||||
touch_server()
|
touch_server()
|
||||||
socket.write(dns_server.fd, req)
|
socket.write(dns_server.fd, req)
|
||||||
return suspend(question_header.tid, name, qtype)
|
return suspend(question_header.tid, name, qtype)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function dns.resolve(name, ipv6)
|
||||||
|
local name = name:lower()
|
||||||
|
local ntype = guess_name_type(name)
|
||||||
|
if ntype ~= "hostname" then
|
||||||
|
if (ipv6 and name == "ipv4") or (not ipv6 and name == "ipv6") then
|
||||||
|
return nil, "illegal ip address"
|
||||||
|
end
|
||||||
|
return name
|
||||||
|
end
|
||||||
|
|
||||||
|
if not verify_domain_name(name) then
|
||||||
|
return nil, "illegal name"
|
||||||
|
end
|
||||||
|
|
||||||
|
local answer, answers = local_resolve(name, ipv6)
|
||||||
|
if answer then
|
||||||
|
return answer, answers
|
||||||
|
end
|
||||||
|
|
||||||
|
return remote_resolve(name, ipv6, timeout)
|
||||||
|
end
|
||||||
|
|
||||||
return dns
|
return dns
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ local resolve_list = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
skynet.start(function()
|
skynet.start(function()
|
||||||
print("nameserver:", dns.server()) -- set nameserver
|
|
||||||
-- you can specify the server like dns.server("8.8.4.4", 53)
|
-- you can specify the server like dns.server("8.8.4.4", 53)
|
||||||
for _ , name in ipairs(resolve_list) do
|
for _ , name in ipairs(resolve_list) do
|
||||||
local ip, ips = dns.resolve(name)
|
local ip, ips = dns.resolve(name)
|
||||||
|
|||||||
Reference in New Issue
Block a user