class Dnsruby::RR
Attributes
The Resource class
The Resource's domain name
The Resource data section
The Resource type
The Resource Time-To-Live
The Resource type
Public Class Methods
Create a new RR
from the arguments, which can be either a String or a Hash. See new_from_string
and new_from_hash
for details
a = Dnsruby::RR.create('foo.example.com. 86400 A 10.1.2.3') mx = Dnsruby::RR.create('example.com. 7200 MX 10 mailhost.example.com.') cname = Dnsruby::RR.create('www.example.com 300 IN CNAME www1.example.com') txt = Dnsruby::RR.create('baz.example.com 3600 HS TXT 'text record'') rr = Dnsruby::RR.create({:name => 'example.com'}) rr = Dnsruby::RR.create({:name => 'example.com', :type => 'MX', :ttl => 10, :preference => 5, :exchange => 'mx1.example.com'})
# File lib/dnsruby/resource/RR.rb, line 399 def RR.create(*args) case args[0] when String new_from_string(args[0]) when Hash new_from_hash(args[0]) else new_from_data(args) end end
# File lib/dnsruby/resource/RR.rb, line 410 def self.get_num(bytes) ret = 0 shift = (bytes.length - 1) * 8 bytes.each_byte do |byte| ret += byte.to_i << shift shift -= 8 end ret end
Return an array of all the currently implemented RR
types
# File lib/dnsruby/resource/RR.rb, line 274 def RR.implemented_rrs @@implemented_rr_map ||= ClassHash.keys.map { |key| Dnsruby::Types.to_string(key[0]) } end
Create a new RR
from the hash. The name is required; all other fields are optional. Type defaults to ANY
and the Class defaults to IN
. The TTL defaults to 0.
If the type is specified, then it is necessary to provide ALL of the resource record fields which are specific to that record; i.e. for an MX
record, you would need to specify the exchange and the preference
require 'Dnsruby' rr = Dnsruby::RR.new_from_hash({:name => "example.com"}) rr = Dnsruby::RR.new_from_hash({:name => "example.com", :type => Types.MX, :ttl => 10, :preference => 5, :exchange => "mx1.example.com"})
# File lib/dnsruby/resource/RR.rb, line 141 def RR.new_from_hash(inhash) hash = inhash.clone type = hash[:type] || Types::ANY klass = Classes.new(hash[:klass] || Classes::IN) ttl = hash[:ttl] || 0 record_class = get_class(type, klass) record = record_class.new record.name = hash[:name] unless record.name.kind_of?(Name) record.name = Name.create(record.name) end record.ttl = ttl record.type = type record.klass = Classes.new(klass) hash.delete(:name) hash.delete(:type) hash.delete(:ttl) hash.delete(:klass) record.from_hash(hash) record end
Returns a Dnsruby::RR
object of the appropriate type and initialized from the string passed by the user. The format of the string is that used in zone files, and is compatible with the string returned by Net::DNS::RR.inspect
The name and RR
type are required; all other information is optional. If omitted, the TTL defaults to 0 and the RR
class defaults to IN
.
All names must be fully qualified. The trailing dot (.) is optional.
a = Dnsruby::RR.new_from_string("foo.example.com. 86400 A 10.1.2.3") mx = Dnsruby::RR.new_from_string("example.com. 7200 MX 10 mailhost.example.com.") cname = Dnsruby::RR.new_from_string("www.example.com 300 IN CNAME www1.example.com") txt = Dnsruby::RR.new_from_string('baz.example.com 3600 HS TXT "text record"')
# File lib/dnsruby/resource/RR.rb, line 180 def RR.new_from_string(rrstring) # strip out comments # Test for non escaped ";" by means of the look-behind assertion # (the backslash is escaped) rrstring = rrstring.gsub(/(\?<!\\);.*/o, '') matches = (/#{@@RR_REGEX}/xo).match(rrstring) unless matches raise "#{rrstring} did not match RR pattern. Please report this to the author!" end name = matches[1] ttl = matches[2].to_i || 0 rrclass = matches[3] || '' rrtype = matches[4] || '' rdata = matches[5] || '' rdata.gsub!(/\s+$/o, '') if rdata # RFC3597 tweaks # This converts to known class and type if specified as TYPE### if rrtype =~/^TYPE\d+/o rrtype = Dnsruby::Types.typesbyval(Dnsruby::Types::typesbyname(rrtype)) end if rrclass =~/^CLASS\d+/o rrclass = Dnsruby::Classes.classesbyval(Dnsruby::Classes::classesbyname(rrclass)) end if rrtype == '' && rrclass == 'ANY' rrtype = 'ANY' rrclass = 'IN' elsif rrclass == '' rrclass = 'IN' end if rrtype == '' rrtype = 'ANY' end unless %w(NAPTR TXT).include?(rrtype) if rdata rdata.gsub!('(', '') rdata.gsub!(')', '') end end test_length = ->(hexdump, rdlength) do if hexdump.length != rdlength * 2 raise "#{rdata} is inconsistent; length should be #{rdlength * 2} but is #{hexdump.length}." end end pack_rdata = ->(regex) do rdata =~ regex matches = regex.match(rdata) rdlength = matches[1].to_i hexdump = matches[2].gsub(/\s*/, '') test_length.(hexdump, rdlength) packed_rdata = [hexdump].pack('H*') [packed_rdata, rdlength] end if implemented_rrs.include?(rrtype) && rdata !~/^\s*\\#/o return _get_subclass(name, rrtype, rrclass, ttl, rdata) elsif implemented_rrs.include?(rrtype) # A known RR type starting with \# packed_rdata, rdlength = pack_rdata.(/\\#\s+(\d+)\s+(.*)$/o) return new_from_data(name, rrtype, rrclass, ttl, rdlength, packed_rdata, 0) # rdata.length() - rdlength); elsif rdata =~ /\s*\\#\s+\d+\s+/o regex = /\\#\s+(\d+)\s+(.*)$/o # We are now dealing with the truly unknown. raise 'Expected RFC3597 representation of RDATA' unless rdata =~ regex packed_rdata, rdlength = pack_rdata.(regex) return new_from_data(name, rrtype, rrclass, ttl, rdlength, packed_rdata, 0) # rdata.length() - rdlength); else # God knows how to handle these... return _get_subclass(name, rrtype, rrclass, ttl, '') end end
Public Instance Methods
# File lib/dnsruby/resource/RR.rb, line 23 def <=>(other) # return 1 if ((!other) || !(other.name) || !(other.type)) # return -1 if (!@name) if @name.canonical == other.name.canonical @type.code != other.type.code ? (@type.code <=> other.type.code) : (@rdata <=> other.rdata) else @name <=> other.name end end
# File lib/dnsruby/resource/RR.rb, line 322 def ==(other) return false unless self.class == other.class ivars_to_compare = ->(object) do ivars = object.instance_variables.map { |var| var.to_s } ivars.delete '@ttl' # RFC 2136 section 1.1 ivars.delete '@rdata' if self.type == Types.DS ivars.delete '@digest' end ivars.sort end get_instance_var_values = ->(object, ivar_names) do ivar_names.map { |ivar_name| object.instance_variable_get(ivar_name) } end self_ivars = ivars_to_compare.(self) other_ivars = ivars_to_compare.(other) return false unless self_ivars == other_ivars self_values = get_instance_var_values.(self, self_ivars) other_values = get_instance_var_values.(other, other_ivars) self_values == other_values end
# File lib/dnsruby/resource/RR.rb, line 75 def clone encoded = MessageEncoder.new { |encoder| encoder.put_rr(self, true) }.to_s MessageDecoder.new(encoded).get_rr end
# File lib/dnsruby/resource/RR.rb, line 98 def init_defaults # Default to do nothing end
# File lib/dnsruby/resource/RR.rb, line 67 def klass=(klass) if @type != Types::OPT @klass = Classes.new(klass) else @klass = klass.is_a?(Classes) ? klass : Classes.new("CLASS#{klass}") end end
# File lib/dnsruby/resource/RR.rb, line 58 def name=(new_name) @name = new_name.kind_of?(Name) ? new_name : Name.create(new_name) end
Get a string representation of the data section of the RR
(in zone file format)
# File lib/dnsruby/resource/RR.rb, line 298 def rdata_to_string (@rdata && @rdata.length > 0) ? @rdata : 'no rdata' end
# File lib/dnsruby/resource/RR.rb, line 54 def rdlength rdata.length end
Determines if two Records could be part of the same RRset. This compares the name, type, and class of the Records; the ttl and rdata are not compared.
# File lib/dnsruby/resource/RR.rb, line 84 def sameRRset(rec) if @klass != rec.klass || @name.downcase != rec.name.downcase return false elsif (rec.type == Types.RRSIG) && (@type == Types.RRSIG) return rec.type_covered == self.type_covered end [rec, self].each do |rr| if rr.type == Types::RRSIG return (@type == rr.type_covered) || (rec.type == rr.type_covered) end end @type == rec.type end
Returns a string representation of the RR
in zone file format
# File lib/dnsruby/resource/RR.rb, line 292 def to_s s = name ? (name.to_s(true) + "\t") : '' s << [ttl, klass, type, rdata_to_string].map(&:to_s).join("\t") end
# File lib/dnsruby/resource/RR.rb, line 62 def type=(type) @type = Types.new(type) end