class Dnsruby::RR
Superclass for all Dnsruby resource records.
Represents a DNS RR (resource record) [RFC1035, section 3.2]
Use ::create to create a new RR record.
mx = Dnsruby::RR.create("example.com. 7200 MX 10 mailhost.example.com.") rr = Dnsruby::RR.create({:name => "example.com", :type => "MX", :ttl => 7200, :preference => 10, :exchange => "mailhost.example.com"}) s = rr.to_s # Get a String representation of the RR (in zone file format) rr_again = Dnsruby::RR.create(s)
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/resource.rb, line 650 def RR.create(*args) if (args.length == 1) && (args[0].class == String) return new_from_string(args[0]) elsif (args.length == 1) && (args[0].class == Hash) return new_from_hash(args[0]) else return new_from_data(args) end end
# File lib/Dnsruby/resource/resource.rb, line 660 def self.get_num(bytes) ret = 0 shift = (bytes.length-1) * 8 bytes.each_byte {|byte| ret += byte.to_i << shift shift -= 8 } return ret end
Return an array of all the currently implemented RR types
# File lib/Dnsruby/resource/resource.rb, line 505 def RR.implemented_rrs if (!@@implemented_rr_map) @@implemented_rr_map = ClassHash.keys.map {|k| Dnsruby::Types.to_string(k[0])} end return @@implemented_rr_map 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/resource.rb, line 350 def RR.new_from_hash(inhash) hash = inhash.clone type = hash[:type] || Types::ANY klass = hash[:klass] || Classes::IN ttl = hash[:ttl] || 0 recordclass = get_class(type, klass) record = recordclass.new record.name=hash[:name] if !(record.name.kind_of?Name) record.name = Name.create(record.name) end record.ttl=ttl record.type = type record.klass = klass hash.delete(:name) hash.delete(:type) hash.delete(:ttl) hash.delete(:klass) record.from_hash(hash) return 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/resource.rb, line 389 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, ""); if ((rrstring =~/#{@@RR_REGEX}/xo) == nil) raise Exception, "#{rrstring} did not match RR pat.\nPlease report this to the author!\n" end name = $1; ttl = $2.to_i || 0; rrclass = $3 || ''; rrtype = $4 || ''; rdata = $5 || ''; if rdata rdata.gsub!(/\s+$/o, "") end # 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 && rrclass == 'ANY') rrtype = 'ANY'; rrclass = 'IN'; elsif (rrclass=='') rrclass = 'IN'; end if (rrtype == '') rrtype = 'ANY'; end if ((rrtype == "NAPTR") || (rrtype == "TXT")) else if (rdata) rdata.gsub!("(", "") rdata.gsub!(")", "") end end if (implemented_rrs.include?(rrtype) && rdata !~/^\s*\#/o ) subclass = _get_subclass(name, rrtype, rrclass, ttl, rdata) return subclass elsif (implemented_rrs.include?(rrtype)) # A known RR type starting with \# rdata =~ /\\#\s+(\d+)\s+(.*)$/o; rdlength = $1.to_i; hexdump = $2; hexdump.gsub!(/\s*/, ""); if hexdump.length() != rdlength*2 raise Exception, "#{rdata} is inconsistent; length does not match content" end rdata = [hexdump].pack('H*'); return new_from_data(name, rrtype, rrclass, ttl, rdlength, rdata, 0) # rdata.length() - rdlength); elsif (rdata=~/\s*\\#\s+\d+\s+/o) #We are now dealing with the truly unknown. raise Exception, 'Expected RFC3597 representation of RDATA' unless rdata =~/\\#\s+(\d+)\s+(.*)$/o; rdlength = $1.to_i; hexdump = $2; hexdump.gsub!(/\s*/o, ""); if hexdump.length() != rdlength*2 raise Exception, "#{rdata} is inconsistent; length does not match content" ; end rdata = [hexdump].pack('H*'); return new_from_data(name,rrtype,rrclass,ttl,rdlength,rdata,0) # rdata.length() - rdlength); else #God knows how to handle these... subclass = _get_subclass(name, rrtype, rrclass, ttl, "") return subclass end end
Public Instance Methods
# File lib/Dnsruby/resource/resource.rb, line 220 def <=>(other) # return 1 if ((!other) || !(other.name) || !(other.type)) # return -1 if (!@name) if (@name.canonical == other.name.canonical) if (@type.code == other.type.code) return (@rdata <=> other.rdata) else return @type.code <=> other.type.code end else return @name <=> other.name end end
# File lib/Dnsruby/resource/resource.rb, line 558 def ==(other) return false unless self.class == other.class ivars = self.instance_variables s_ivars = [] ivars.each {|i| s_ivars << i.to_s} # Ruby 1.9 s_ivars.delete "@ttl" # RFC 2136 section 1.1 s_ivars.delete "@rdata" if (self.type == Types.DS) s_ivars.delete "@digest" end s_ivars.sort! ivars = other.instance_variables o_ivars = [] ivars.each {|i| o_ivars << i.to_s} # Ruby 1.9 o_ivars.delete "@ttl" # RFC 2136 section 1.1 o_ivars.delete "@rdata" if (other.type == Types.DS) o_ivars.delete "@digest" end o_ivars.sort! return s_ivars == o_ivars && s_ivars.collect {|name| self.instance_variable_get name} == o_ivars.collect {|name| other.instance_variable_get name} end
# File lib/Dnsruby/resource/resource.rb, line 280 def clone MessageDecoder.new(MessageEncoder.new {|msg| msg.put_rr(self, true)}.to_s) {|msg| r = msg.get_rr return r } end
# File lib/Dnsruby/resource/resource.rb, line 307 def init_defaults # Default to do nothing end
# File lib/Dnsruby/resource/resource.rb, line 268 def klass=(klass) if (@type != Types::OPT) @klass= Classes.new(klass) else if (klass.class == Classes) @klass = klass else @klass = Classes.new("CLASS#{klass}") end end end
# File lib/Dnsruby/resource/resource.rb, line 255 def name=(newname) if (!(newname.kind_of?Name)) @name=Name.create(newname) else @name = newname end end
Get a string representation of the data section of the RR (in zone file format)
# File lib/Dnsruby/resource/resource.rb, line 530 def rdata_to_string if (@rdata && @rdata.length > 0) return @rdata else return "no rdata" end end
# File lib/Dnsruby/resource/resource.rb, line 251 def rdlength return 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/resource.rb, line 292 def sameRRset(rec) if (@klass != rec.klass || @name.downcase != rec.name.downcase) return false end if (rec.type == Types.RRSIG) && (@type == Types.RRSIG) return rec.type_covered == self.type_covered end [rec, self].each { |rr| if (rr.type == Types::RRSIG) return ((@type == rr.type_covered) || (rec.type == rr.type_covered)) end } return (@type == rec.type) end
Returns a string representation of the RR in zone file format
# File lib/Dnsruby/resource/resource.rb, line 525 def to_s return (@name ? @name.to_s(true):"") + "\t" +(@ttl ? @ttl.to_s():"") + "\t" + (klass() ? klass.to_s():"") + "\t" + (type() ? type.to_s():"") + "\t" + rdata_to_string end
# File lib/Dnsruby/resource/resource.rb, line 263 def type=(type) @type = Types.new(type) end