Class: RubyDNS::Transaction

Inherits:
Object
  • Object
show all
Defined in:
lib/rubydns/transaction.rb

Overview

This class provides all details of a single DNS question and answer. This is used by the DSL to provide DNS related functionality.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(server, query, question, resource_class, answer) ⇒ Transaction

Returns a new instance of Transaction.



26
27
28
29
30
31
32
33
34
# File 'lib/rubydns/transaction.rb', line 26

def initialize(server, query, question, resource_class, answer)
  @server = server
  @query = query
  @question = question
  @resource_class = resource_class
  @answer = answer
  
  @question_appended = false
end

Instance Attribute Details

#answerObject (readonly)

The current full answer to the incoming query.



47
48
49
# File 'lib/rubydns/transaction.rb', line 47

def answer
  @answer
end

#queryObject (readonly)

The incoming query which is a set of questions.



41
42
43
# File 'lib/rubydns/transaction.rb', line 41

def query
  @query
end

#questionObject (readonly)

The question that this transaction represents.



44
45
46
# File 'lib/rubydns/transaction.rb', line 44

def question
  @question
end

#resource_classObject (readonly)

The resource_class that was requested. This is typically used to generate a response.



38
39
40
# File 'lib/rubydns/transaction.rb', line 38

def resource_class
  @resource_class
end

Instance Method Details

#append!(*resources) ⇒ Object

Append a given set of resources to the answer. The last argument can optionally be a hash of options.

options[:ttl]

Specify the TTL for the resource

options[:name]

Override the name (question) of the response.

This function can be used to supply multiple responses to a given question. For example, each argument is expected to be an instantiated resource from Resolv::DNS::Resource module.



155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
# File 'lib/rubydns/transaction.rb', line 155

def append! (*resources)
  append_question!

  options = resources.last.kind_of?(Hash) ? resources.pop.dup : {}
  options[:ttl] ||= 16000
  options[:name] ||= @question.to_s + "."

  resources.each do |resource|
    @server.logger.debug "add_answer: #{resource.inspect} #{resource.class::TypeValue} #{resource.class::ClassValue}"
    @answer.add_answer(options[:name], options[:ttl], resource)
  end

  # Raise an exception if there was something wrong with the resource
  @answer.encode

  true
end

#append_query!(name, resource_class = nil) ⇒ Object

Run a new query through the rules with the given name and resource type. The results of this query are appended to the current transactions answer.



61
62
63
# File 'lib/rubydns/transaction.rb', line 61

def append_query!(name, resource_class = nil)
  Transaction.new(@server, @query, name, resource_class || @resource_class, @answer).process
end

#append_question!Object



202
203
204
205
206
# File 'lib/rubydns/transaction.rb', line 202

def append_question!
  if @answer.question.size == 0
    @answer.add_question(@question, @resource_class) unless @question_appended
  end
end

#failure!(rcode) ⇒ Object

This function indicates that there was a failure to resolve the given question. The single argument must be an integer error code, typically given by the constants in Resolv::DNS::RCode.

The easiest way to use this function it to simply supply a symbol. Here is a list of the most commonly used ones:

:NoError

No error occurred.

:FormErr:: The incoming data was not formatted correctly.

:ServFail

The operation caused a server failure (internal error, etc).

:NXDomain

Non-eXistant Domain (domain record does not exist).

:NotImp

The operation requested is not implemented.

:Refused

The operation was refused by the server.

:NotAuth

The server is not authoritive for the zone.

See www.rfc-editor.org/rfc/rfc2929.txt for more information about DNS error codes (specifically, page 3).



190
191
192
193
194
195
196
197
198
199
200
# File 'lib/rubydns/transaction.rb', line 190

def failure! (rcode)
  append_question!

  if rcode.kind_of? Symbol
    @answer.rcode = Resolv::DNS::RCode.const_get(rcode)
  else
    @answer.rcode = rcode.to_i
  end

  true
end

#nameObject

Return the name of the question, which is typically the requested hostname.



50
51
52
# File 'lib/rubydns/transaction.rb', line 50

def name
  @question.to_s
end

#passthrough(resolver, options = {}, &block) ⇒ Object

Use the given resolver to respond to the question. If recursion is not requested, the result is failure!(:Refused). If the resolver does not respond, the result is failure!(:NXDomain)

If a block is supplied, this function yields with the reply and reply_name if successful. This block is responsible for doing something useful with the reply, such as merging it or conditionally discarding it.

A second argument, options, provides some control over the passthrough process. :force => true, ensures that the query will occur even if recursion is not requested.



98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/rubydns/transaction.rb', line 98

def passthrough (resolver, options = {}, &block)
  if @query.rd || options[:force]
    reply, reply_name = resolver.query(name, resource_class)
    
    if reply
      yield reply, reply_name
    else
      failure!(:NXDomain)
    end
  else
    failure!(:Refused)
  end
  
  true
end

#passthrough!(resolver, options = {}, &block) ⇒ Object

Use the given resolver to respond to the question. The default functionality is implemented by passthrough, and if a reply is received, it will be merged with the answer for this transaction.

If a block is supplied, this function yields with the reply and reply_name if successful. This could be used, for example, to update a cache or modify the reply.



76
77
78
79
80
81
82
83
84
85
86
# File 'lib/rubydns/transaction.rb', line 76

def passthrough! (resolver, options = {}, &block)
  passthrough(resolver, options) do |reply, reply_name|
    if block_given?
      yield reply, reply_name
    end
    
    @answer.merge!(reply)
  end
  
  true
end

#processObject



65
66
67
# File 'lib/rubydns/transaction.rb', line 65

def process
  @server.process(name, @resource_class, self)
end

#respond!(*data) ⇒ Object

Respond to the given query with a resource record. The arguments to this function depend on the resource_class requested. The last argument can optionally be a hash of options.

options[:resource_class]

Override the default resource_class

options[:ttl]

Specify the TTL for the resource

options[:name]

Override the name (question) of the response.

for A records

respond!("1.2.3.4")

for MX records

respond!("mail.blah.com", 10)

This function instantiates the resource class with the supplied arguments, and then passes it to append!.

See Resolv::DNS::Resource for more information about the various resource_classs available. www.ruby-doc.org/stdlib/libdoc/resolv/rdoc/index.html



131
132
133
134
135
136
137
138
139
140
141
142
143
144
# File 'lib/rubydns/transaction.rb', line 131

def respond! (*data)
  options = data.last.kind_of?(Hash) ? data.pop : {}
  resource_class = options[:resource_class] || @resource_class
  
  if resource_class == nil
    raise ArgumentError, "Could not instantiate resource #{resource_class}!"
  end
  
  @server.logger.info "Resource class: #{resource_class.inspect}"
  resource = resource_class.new(*data)
  @server.logger.info "Resource: #{resource.inspect}"
  
  append!(resource, options)
end

#to_sObject

Suitable for debugging purposes



55
56
57
# File 'lib/rubydns/transaction.rb', line 55

def to_s
  "#{name} #{@resource_class.name}"
end