Module: Async::DNS::System

Defined in:
lib/async/dns/system.rb

Overview

This module encapsulates system dependent name lookup functionality.

Defined Under Namespace

Classes: Hosts, Resource

Constant Summary collapse

RESOLV_CONF =
"/etc/resolv.conf"
HOSTS =
"/etc/hosts"
DEFAULT_TIMEOUT =
5.0

Class Method Summary collapse

Class Method Details

.hosts_pathObject

Get the path to the hosts file.



21
22
23
24
25
26
27
# File 'lib/async/dns/system.rb', line 21

def self.hosts_path
  if RUBY_PLATFORM =~ /mswin32|mingw|bccwin/
    Win32::Resolv.get_hosts_path
  else
    HOSTS
  end
end

.ipv6?Boolean

Returns:

  • (Boolean)


30
31
32
33
34
35
36
37
38
# File 'lib/async/dns/system.rb', line 30

def self.ipv6?
  begin
    list = Socket.ip_address_list
  rescue NotImplementedError
    return true
  end
  
  list.any? {|a| a.ipv6? && !a.ipv6_loopback? && !a.ipv6_linklocal? }
end

.parse_resolv_configuration(path) ⇒ Object

Parse the ‘resolv.conf` file and return a list of nameservers.



119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
# File 'lib/async/dns/system.rb', line 119

def self.parse_resolv_configuration(path)
  nameservers = []
  search = nil
  ndots = 1
  edns = nil
  timeout = DEFAULT_TIMEOUT
  
  File.open(path) do |file|
    file.each do |line|
      # Remove any comments:
      line.sub!(/[#;].*/, "")
      
      # Extract resolv.conf command:
      keyword, *arguments = line.split(/\s+/)
      
      case keyword
      when "nameserver"
        nameservers.concat(arguments)
      when "domain", "search"
        search = arguments
      when "options"
        arguments.each do |argument|
          key, value = argument.split(":", 2)
          
          case key
          when "ndots"
            ndots = value.to_i
          when "edns0"
            edns = 0
          when "timeout"
            timeout = value.to_f
          end
        end
      end
    end
  end
  
  return {
    nameservers: nameservers,
    search: search,
    ndots: ndots,
    edns: edns,
    timeout: timeout,
  }
end

.resolver(**options) ⇒ Object

Get a list of standard nameserver connections which can be used for querying any standard servers that the system has been configured with. There is no equivalent facility to use the ‘hosts` file at present.



166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
# File 'lib/async/dns/system.rb', line 166

def self.resolver(**options)
  nameservers = []
  
  if File.exist? RESOLV_CONF
    options.update(parse_resolv_configuration(RESOLV_CONF))
    nameservers = options.delete(:nameservers)
  elsif defined?(Win32::Resolv) and RUBY_PLATFORM =~ /mswin32|cygwin|mingw|bccwin/
    search, nameservers = Win32::Resolv.get_resolv_info
    options.update(search: search)
  end
  
  if search = options[:search]
    unless search.include?(".")
      search << nil
    end
  else
    options[:search] = [nil]
  end
  
  if hosts = Hosts.local
    cache = options.fetch(:cache) do
      options[:cache] = Cache.new
    end
    
    hosts.each do |name, addresses|
      addresses.each do |address|
        resource = Resource.new(address, nil)
        case address
        when Resolv::IPv4
          cache.store(name, Resolv::DNS::Resource::IN::A, resource)
        when Resolv::IPv6
          cache.store(name, Resolv::DNS::Resource::IN::AAAA, resource)
        end
      end
    end
  end
  
  timeout = options.delete(:timeout) || DEFAULT_TIMEOUT
  endpoint = Endpoint.for(nameservers, timeout: timeout)
  
  if block_given?
    yield endpoint, **options
  else
    return Resolver.new(endpoint, **options)
  end
end