Class: Async::DNS::Transaction
- Inherits:
-
Object
- Object
- Async::DNS::Transaction
- Defined in:
- lib/async/dns/transaction.rb
Overview
This class provides all details of a single DNS question and response. This is used by the DSL to provide DNS related functionality.
The main functions to complete the transaction are: #append! (evaluate a new query and append the results), #passthrough! (pass the query to an upstream server), #respond! (compute a specific response) and #fail! (fail with an error code).
Constant Summary collapse
- DEFAULT_TTL =
The default time used for responses (24 hours).
86400
Instance Attribute Summary collapse
-
#options ⇒ Object
readonly
Returns the value of attribute options.
-
#query ⇒ Object
readonly
Returns the value of attribute query.
-
#question ⇒ Object
readonly
Returns the value of attribute question.
-
#resource_class ⇒ Object
readonly
Returns the value of attribute resource_class.
-
#response ⇒ Object
readonly
Returns the value of attribute response.
- #The resource class to use for responses. This is typically used to generate a response.(resource) ⇒ Object readonly
Instance Method Summary collapse
-
#[](key) ⇒ Object
Access the options hash.
-
#add(resources, options = {}) ⇒ Object
Append a list of resources.
- #Additional options associated with the transaction.=(optionsassociatedwiththetransaction. = (value)) ⇒ Object
-
#append!(name, resource_class = nil, options = {}) ⇒ Object
Run a new query through the rules with the given name and resource type.
-
#append_question! ⇒ Object
A typical response to a DNS request includes both the question and response.
-
#fail!(rcode) ⇒ Object
This function indicates that there was a failure to resolve the given question.
- #failure!(*args) ⇒ Object deprecated Deprecated.
-
#initialize(server, query, question, resource_class, response, **options) ⇒ Transaction
constructor
Create a new transaction with the given server, query, question, resource class, response, and options.
-
#name ⇒ Object
The name of the question, which is typically the requested hostname.
-
#passthrough(resolver, name: self.name, resource_class: self.resource_class) ⇒ Object
Use the given resolver to respond to the question.
-
#passthrough!(resolver, force: false, **options, &block) ⇒ Object
Use the given resolver to respond to the question.
-
#process ⇒ Object
A helper method to process the transaction on the given server.
-
#respond!(*args) ⇒ Object
The last argument can optionally be a hash of
options. - #The incoming query.=(incomingquery. = (value)) ⇒ Object
- #The question to answer.=(questiontoanswer. = (value)) ⇒ Object
- #The response to the query.=(responsetothequery. = (value)) ⇒ Object
-
#to_s ⇒ Object
Shows the question name and resource class.
Constructor Details
#initialize(server, query, question, resource_class, response, **options) ⇒ Transaction
Create a new transaction with the given server, query, question, resource class, response, and options.
23 24 25 26 27 28 29 30 31 |
# File 'lib/async/dns/transaction.rb', line 23 def initialize(server, query, question, resource_class, response, **) @server = server @query = query @question = question @resource_class = resource_class @response = response @options = end |
Instance Attribute Details
#options ⇒ Object (readonly)
Returns the value of attribute options.
46 47 48 |
# File 'lib/async/dns/transaction.rb', line 46 def @options end |
#query ⇒ Object (readonly)
Returns the value of attribute query.
37 38 39 |
# File 'lib/async/dns/transaction.rb', line 37 def query @query end |
#question ⇒ Object (readonly)
Returns the value of attribute question.
40 41 42 |
# File 'lib/async/dns/transaction.rb', line 40 def question @question end |
#resource_class ⇒ Object (readonly)
Returns the value of attribute resource_class.
34 35 36 |
# File 'lib/async/dns/transaction.rb', line 34 def resource_class @resource_class end |
#response ⇒ Object (readonly)
Returns the value of attribute response.
43 44 45 |
# File 'lib/async/dns/transaction.rb', line 43 def response @response end |
#The resource class to use for responses. This is typically used to generate a response.(resource) ⇒ Object (readonly)
34 |
# File 'lib/async/dns/transaction.rb', line 34 attr :resource_class |
Instance Method Details
#[](key) ⇒ Object
Access the options hash.
51 52 53 |
# File 'lib/async/dns/transaction.rb', line 51 def [] key @options[key] end |
#add(resources, options = {}) ⇒ Object
Append a list of resources.
By default resources are appended to the answers section, but this can be changed by setting options[:section] to either :authority or :additional.
The time-to-live (TTL) of the resources can be specified using options[:ttl] and defaults to DEFAULT_TTL.
132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 |
# File 'lib/async/dns/transaction.rb', line 132 def add(resources, = {}) # Use the default options if provided: = .merge(@options) ttl = [:ttl] || DEFAULT_TTL name = [:name] || @question.to_s + "." section = ([:section] || "answer").to_sym method = "add_#{section}".to_sym resources.each do |resource| @server.logger.debug {"#{method}: #{resource.inspect} #{resource.class::TypeValue} #{resource.class::ClassValue}"} @response.send(method, name, ttl, resource) end end |
#Additional options associated with the transaction.=(optionsassociatedwiththetransaction. = (value)) ⇒ Object
46 |
# File 'lib/async/dns/transaction.rb', line 46 attr :options |
#append!(name, resource_class = nil, options = {}) ⇒ 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 transaction’s response.
66 67 68 |
# File 'lib/async/dns/transaction.rb', line 66 def append!(name, resource_class = nil, = {}) Transaction.new(@server, @query, name, resource_class || @resource_class, @response, **).process end |
#append_question! ⇒ Object
A typical response to a DNS request includes both the question and response. This helper appends the question unless it looks like the user is already managing that aspect of the response.
187 188 189 190 191 |
# File 'lib/async/dns/transaction.rb', line 187 def append_question! if @response.question.size == 0 @response.add_question(@question, @resource_class) end end |
#fail!(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 [RFC2929](www.rfc-editor.org/rfc/rfc2929.txt) for more information about DNS error codes (specifically, page 3).
**This function will complete deferred transactions.**
164 165 166 167 168 169 170 171 172 |
# File 'lib/async/dns/transaction.rb', line 164 def fail!(rcode) append_question! if rcode.kind_of? Symbol @response.rcode = Resolv::DNS::RCode.const_get(rcode) else @response.rcode = rcode.to_i end end |
#failure!(*args) ⇒ Object
175 176 177 178 179 |
# File 'lib/async/dns/transaction.rb', line 175 def failure!(*args) @server.logger.warn "failure! is deprecated, use fail! instead" fail!(*args) end |
#name ⇒ Object
The name of the question, which is typically the requested hostname.
56 57 58 |
# File 'lib/async/dns/transaction.rb', line 56 def name @question.to_s end |
#passthrough(resolver, name: self.name, resource_class: self.resource_class) ⇒ Object
Use the given resolver to respond to the question.
A block must be supplied, and provided a valid response is received from the upstream server, this function yields with the reply and reply_name.
If options[:name] is provided, this overrides the default query name sent to the upstream server. The same logic applies to options[:resource_class].
101 102 103 |
# File 'lib/async/dns/transaction.rb', line 101 def passthrough(resolver, name: self.name, resource_class: self.resource_class) resolver.query(name, resource_class) end |
#passthrough!(resolver, force: false, **options, &block) ⇒ Object
Use the given resolver to respond to the question. Uses passthrough to do the lookup and merges the result.
If a block is supplied, this function yields with the response message if successful. This could be used, for example, to update a cache or modify the reply.
If recursion is not requested, the result is ‘fail!(:Refused)`. This check is ignored if an explicit options[:name] or options[:force] is given.
If the resolver can’t reach upstream servers, ‘fail!(:ServFail)` is invoked.
77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 |
# File 'lib/async/dns/transaction.rb', line 77 def passthrough!(resolver, force: false, **, &block) if @query.rd || force || [:name] response = passthrough(resolver, **) if response yield response if block_given? # Recursion is available and is being used: # See issue #26 for more details. @response.ra = 1 @response.merge!(response) else fail!(:ServFail) end else fail!(:Refused) end end |
#process ⇒ Object
A helper method to process the transaction on the given server. Unless the transaction is deferred, it will #succeed on completion.
182 183 184 |
# File 'lib/async/dns/transaction.rb', line 182 def process @server.process(name, @resource_class, self) end |
#respond!(*args) ⇒ Object
The last argument can optionally be a hash of options. If options[:resource_class] is provided, it overrides the default resource class of transaction. Additional options are passed to #append!.
See Resolv::DNS::Resource for more information about the various resource_classes available (www.ruby-doc.org/stdlib/libdoc/resolv/rdoc/index.html).
112 113 114 115 116 117 118 119 120 121 122 123 124 125 |
# File 'lib/async/dns/transaction.rb', line 112 def respond!(*args) append_question! = args.last.kind_of?(Hash) ? args.pop : {} resource_class = [:resource_class] || @resource_class if resource_class == nil raise ArgumentError.new("Could not instantiate resource #{resource_class}!") end resource = resource_class.new(*args) add([resource], ) end |
#The incoming query.=(incomingquery. = (value)) ⇒ Object
37 |
# File 'lib/async/dns/transaction.rb', line 37 attr :query |
#The question to answer.=(questiontoanswer. = (value)) ⇒ Object
40 |
# File 'lib/async/dns/transaction.rb', line 40 attr :question |
#The response to the query.=(responsetothequery. = (value)) ⇒ Object
43 |
# File 'lib/async/dns/transaction.rb', line 43 attr :response |
#to_s ⇒ Object
Shows the question name and resource class. Suitable for debugging purposes.
61 62 63 |
# File 'lib/async/dns/transaction.rb', line 61 def to_s "#{name} #{@resource_class.name}" end |