Class: ReDNS::Resolver

Inherits:
Object
  • Object
show all
Defined in:
lib/redns/resolver.rb

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options = { }) {|_self| ... } ⇒ Resolver

Instance Methods =====================================================

Yields:

  • (_self)

Yield Parameters:



48
49
50
51
52
53
54
55
56
# File 'lib/redns/resolver.rb', line 48

def initialize(options = { }, &block)
	@servers = self.class.servers.dup
	@responses = { }
	
	@socket = UDPSocket.new
	ReDNS::Support.io_set_nonblock(@socket)
	
	yield(self) if (block)
end

Class Method Details

.in_resolv_confObject

Class Methods ========================================================



14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# File 'lib/redns/resolver.rb', line 14

def self.in_resolv_conf
	list = [ ]
	
	File.open("/etc/resolv.conf") do |fh|
		list = fh.readlines.collect { |l| l.chomp }.collect { |l| l.sub(/#.*/, '') }
		
		list.reject!{ |l| !l.sub!(/^\s*nameserver\s+/, '') }
	end
	
	list

rescue Errno::ENOENT
  # /etc/resolv.conf may not be present on misconfigured or offline systems
  [ ]
end

.serversObject



30
31
32
# File 'lib/redns/resolver.rb', line 30

def self.servers
	@servers ||= in_resolv_conf
end

.servers=(list) ⇒ Object



34
35
36
# File 'lib/redns/resolver.rb', line 34

def self.servers=(list)
	@servers = list
end

.timeoutObject



38
39
40
# File 'lib/redns/resolver.rb', line 38

def self.timeout
	@timeout
end

.timeout=(secs) ⇒ Object



42
43
44
# File 'lib/redns/resolver.rb', line 42

def self.timeout=(secs)
	@timeout = secs
end

Instance Method Details

#a_for(name) ⇒ Object



94
95
96
# File 'lib/redns/resolver.rb', line 94

def a_for(name)
	simple_query(:a, name)
end

#bulk_query(type, names) ⇒ Object



67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/redns/resolver.rb', line 67

def bulk_query(type, names)
	results = { }
	ids = [ ]
	
	message ||= ReDNS::Message.new
	q = (message.questions[0] ||= ReDNS::Question.new)
	q.qtype = type
	
	names.each do |name|
		q.name = name.to_s
		message.increment_id!
		ids.push(message.id)
		
		send_message(message)
	end
	
	wait_for_responses do |response, addr|
		results[response.questions[0].name.to_s] = response

		ids.delete(response.id)
			
		return results if (ids.empty?)
	end
	
	results
end

#mx_for(name) ⇒ Object



106
107
108
# File 'lib/redns/resolver.rb', line 106

def mx_for(name)
	simple_query(:mx, name)
end

#ns_for(name) ⇒ Object



98
99
100
101
102
103
104
# File 'lib/redns/resolver.rb', line 98

def ns_for(name)
	if (name.match(/^(\d+\.\d+\.\d+)\.\d+$/))
		return simple_query(:ns, ReDNS::Support.addr_to_arpa($1))
	end
	
	simple_query(:ns, name)
end

#ptr_for(name) ⇒ Object



110
111
112
# File 'lib/redns/resolver.rb', line 110

def ptr_for(name)
	simple_query(:ptr, ReDNS::Support.addr_to_arpa(name))
end

#ptr_for_list(name) ⇒ Object



114
115
116
117
118
# File 'lib/redns/resolver.rb', line 114

def ptr_for_list(name)
	ips = [ ips ].flatten
	
	bulk_query(:ptr, ips.collect { |ip| ReDNS::Support.addr_to_arpa(ip) })
end

#query(message = nil, server = nil, async = false) {|| ... } ⇒ Object

Yields:

  • ()


157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
# File 'lib/redns/resolver.rb', line 157

def query(message = nil, server = nil, async = false, &block)
	# FUTURE: Fix the duplication here and in query_async

	message ||= ReDNS::Message.new
	message.questions[0] ||= ReDNS::Question.new
	
	yield(message.questions[0]) if (block)
	
	send_message(message, server)
	
	unless (async)
		wait_for_responses do |r, addr|
			return r if (r.id == message.id)
		end
	end
end

#random_serverObject



149
150
151
# File 'lib/redns/resolver.rb', line 149

def random_server
	@servers[rand(@servers.length)]
end

#response_for(id) ⇒ Object



174
175
176
# File 'lib/redns/resolver.rb', line 174

def response_for(id)
	@responses[id]
end

#responsesObject



178
179
180
# File 'lib/redns/resolver.rb', line 178

def responses
	@responses
end

#reverse_addresses(ips) ⇒ Object



124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
# File 'lib/redns/resolver.rb', line 124

def reverse_addresses(ips)
	map = ips.inject({ }) do |h, ip|
		h[ReDNS::Support.addr_to_arpa(ip)] = ip
		h
	end
	
	list = bulk_query(:ptr, map.keys)
	
	list.values.inject({ }) do |h, r|
		if (ip = map[r.questions[0].name.to_s])
		  h[ip] = (r.answers[0] and r.answers[0].rdata.to_s)
	  end
	  
		h
	end
end

#send_message(message, server = nil) ⇒ Object



153
154
155
# File 'lib/redns/resolver.rb', line 153

def send_message(message, server = nil)
	@socket.send(message.serialize.to_s, 0, (server or random_server), 53)
end

#serversObject



141
142
143
# File 'lib/redns/resolver.rb', line 141

def servers
	@servers
end

#servers=(list) ⇒ Object



145
146
147
# File 'lib/redns/resolver.rb', line 145

def servers=(list)
	@servers = list
end

#simple_query(type, name) ⇒ Object



58
59
60
61
62
63
64
65
# File 'lib/redns/resolver.rb', line 58

def simple_query(type, name)
	r = query do |q|
		q.qtype = type
		q.name = name.to_s
	end
	
	expand_answers(r)
end

#soa_for(name) ⇒ Object



120
121
122
# File 'lib/redns/resolver.rb', line 120

def soa_for(name)
	simple_query(:soa, name)
end

#timeoutObject



182
183
184
# File 'lib/redns/resolver.rb', line 182

def timeout
	@timeout or self.class.timeout
end

#timeout=(secs) ⇒ Object



186
187
188
# File 'lib/redns/resolver.rb', line 186

def timeout=(secs)
	@timeout = secs
end

#wait(_timeout = nil, &block) ⇒ Object



190
191
192
# File 'lib/redns/resolver.rb', line 190

def wait(_timeout = nil, &block)
	wait_for_response(nil, _timeout, &block)
end

#wait_for_responses(_timeout = nil, &block) ⇒ Object



194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
# File 'lib/redns/resolver.rb', line 194

def wait_for_responses(_timeout = nil, &block)
	start = Time.now

	_timeout ||= timeout
	left = _timeout - Time.now.to_f + start.to_f

	while (left > 0)
		if (ready = IO.select([ @socket ], nil, nil, left))
			ready[0].each do |socket|
				data = socket.recvfrom(1524)
		
				r = ReDNS::Message.new(ReDNS::Buffer.new(data[0]))
				
				yield(r, data[1]) if (block)

				@responses[r.id] = [ r, data[1] ]
			end
		end

		left = _timeout - Time.now.to_f + start.to_f
	end
end