123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117 |
- const { create, parse } = require('dns.js')
- const { udp, net } = just
- const { loop } = just.factory
- const { readFile, isFile } = require('fs')
- const dnsServer = just.env().DNS_SERVER || '127.0.0.11'
- function parseLine (line) {
- const parts = line.split(/\s+/)
- const [address, ...hosts] = parts
- return { address, hosts }
- }
- const rxipv4 = /\d+\.\d+\.\d+\.\d+/
- const rxComment = /(\s+)?#.+/
- const rxName = /nameserver\s+(.+)/
- function readHosts () {
- const ipv4 = {}
- const ipv6 = {}
- const fileName = '/etc/hosts'
- if (!isFile(fileName)) {
- just.error(`${fileName} not found`)
- return { ipv4, ipv6 }
- }
- const hosts = readFile(fileName)
- const lines = hosts.split('\n').filter(line => line.trim())
- for (const line of lines) {
- if (line.match(rxComment)) continue
- const { address, hosts } = parseLine(line)
- if (address.match(rxipv4)) {
- for (const host of hosts) {
- ipv4[host] = address
- }
- } else {
- for (const host of hosts) {
- ipv6[host] = address
- }
- }
- }
- return { ipv4, ipv6 }
- }
- function lookupHosts (hostname) {
- const { ipv4 } = readHosts()
- return ipv4[hostname]
- }
- function readResolv () {
- const fileName = '/etc/resolv.conf'
- const results = []
- if (!isFile(fileName)) {
- just.error(`${fileName} not found`)
- return results
- }
- const resolv = readFile(fileName)
- const lines = resolv.split('\n').filter(line => line.trim())
- for (const line of lines) {
- const match = line.match(rxName)
- if (match && match.length > 1) {
- const [, ip] = match
- if (ip.match(rxipv4)) {
- results.push(ip)
- }
- }
- }
- return results
- }
- function lookup (query = 'www.google.com', onRecord = () => {}, address = dnsServer, port = 53, buf = new ArrayBuffer(65536)) {
- const ip = lookupHosts(query)
- if (ip) {
- onRecord(null, ip)
- return
- }
- const ips = readResolv()
- if (ips.length) {
- address = ips[0]
- }
- const fd = net.socket(net.AF_INET, net.SOCK_DGRAM | net.SOCK_NONBLOCK, 0)
- net.bind(fd, address, port)
- loop.add(fd, (fd, event) => {
- just.clearTimeout(timer)
- const answer = []
- const len = udp.recvmsg(fd, buf, answer)
- if (len <= 0) {
- onRecord(new Error('Bad Message Length'))
- return
- }
- const message = parse(buf, len)
- if (!message.answer.length) {
- onRecord(new Error(`Address Not Found for ${query}`))
- return
- }
- const { ip } = message.answer[0]
- const result = `${ip[0]}.${ip[1]}.${ip[2]}.${ip[3]}`
- loop.remove(fd)
- net.close(fd)
- onRecord(null, result)
- })
- const len = create(query, buf, 1)
- const rc = udp.sendmsg(fd, buf, address, port, len)
- if (rc === -1) {
- const errno = just.sys.errno()
- onRecord(new Error(`Error sending ${query} to ${address}: ${just.sys.strerror(errno)} (${errno})`))
- loop.remove(fd)
- net.close(fd)
- return
- }
- const timer = just.setTimeout(() => {
- onRecord(new Error(`Request timed out for ${query} at ${address}`))
- loop.remove(fd)
- net.close(fd)
- }, 1000)
- }
- module.exports = { lookup }
|