Superclass for all Dnsruby resource records.
Represents a DNS RR (resource record) [RFC1035, section 3.2]
Use Dnsruby::RR::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)
ClassInsensitiveTypes | = | [ NS, CNAME, DNAME, DNSKEY, SOA, PTR, HINFO, MINFO, MX, TXT, ISDN, MB, MG, MR, NAPTR, NSAP, OPT, RP, RT, X25, SPF, CERT, LOC, TSIG, TKEY, ANY, RRSIG, NSEC, DS, NSEC3, NSEC3PARAM, DLV |
type | -> | rr_type |
klass | [R] | The Resource class |
name | [R] | The Resource‘s domain name |
rdata | [RW] | The Resource data section |
ttl | [RW] | The Resource Time-To-Live |
type | [R] | The Resource type |
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 604 604: def RR.create(*args) 605: if (args.length == 1) && (args[0].class == String) 606: return new_from_string(args[0]) 607: elsif (args.length == 1) && (args[0].class == Hash) 608: return new_from_hash(args[0]) 609: else 610: return new_from_data(args) 611: end 612: end
# File lib/Dnsruby/resource/resource.rb, line 614 614: def self.get_num(bytes) 615: ret = 0 616: shift = (bytes.length-1) * 8 617: bytes.each_byte {|byte| 618: ret += byte.to_i << shift 619: shift -= 8 620: } 621: return ret 622: end
Return an array of all the currently implemented RR types
# File lib/Dnsruby/resource/resource.rb, line 477 477: def RR.implemented_rrs 478: if (!@@implemented_rr_map) 479: @@implemented_rr_map = ClassHash.keys.map {|k| Dnsruby::Types.to_string(k[0])} 480: end 481: return @@implemented_rr_map 482: 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 330 330: def RR.new_from_hash(inhash) 331: hash = inhash.clone 332: type = hash[:type] || Types::ANY 333: klass = hash[:klass] || Classes::IN 334: ttl = hash[:ttl] || 0 335: recordclass = get_class(type, klass) 336: record = recordclass.new 337: record.name=hash[:name] 338: if !(record.name.kind_of?Name) 339: record.name = Name.create(record.name) 340: end 341: record.ttl=ttl 342: record.type = type 343: record.klass = klass 344: hash.delete(:name) 345: hash.delete(:type) 346: hash.delete(:ttl) 347: hash.delete(:klass) 348: record.from_hash(hash) 349: return record 350: 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 369 369: def RR.new_from_string(rrstring) 370: # strip out comments 371: # Test for non escaped ";" by means of the look-behind assertion 372: # (the backslash is escaped) 373: rrstring.gsub!(/(\?<!\\);.*/o, ""); 374: 375: if ((rrstring =~/#{@@RR_REGEX}/xo) == nil) 376: raise Exception, "#{rrstring} did not match RR pat.\nPlease report this to the author!\n" 377: end 378: 379: name = $1; 380: ttl = $2.to_i || 0; 381: rrclass = $3 || ''; 382: 383: 384: rrtype = $4 || ''; 385: rdata = $5 || ''; 386: 387: if rdata 388: rdata.gsub!(/\s+$/o, "") 389: end 390: 391: # RFC3597 tweaks 392: # This converts to known class and type if specified as TYPE### 393: if rrtype =~/^TYPE\d+/o 394: rrtype = Dnsruby::Types.typesbyval(Dnsruby::Types::typesbyname(rrtype)) 395: end 396: if rrclass =~/^CLASS\d+/o 397: rrclass = Dnsruby::Classes.classesbyval(Dnsruby::Classes::classesbyname(rrclass)) 398: end 399: 400: 401: if (rrtype=='' && rrclass && rrclass == 'ANY') 402: rrtype = 'ANY'; 403: rrclass = 'IN'; 404: elsif (rrclass=='') 405: rrclass = 'IN'; 406: end 407: 408: if (rrtype == '') 409: rrtype = 'ANY'; 410: end 411: 412: if (implemented_rrs.include?(rrtype) && rdata !~/^\s*\\#/o ) 413: subclass = _get_subclass(name, rrtype, rrclass, ttl, rdata) 414: return subclass 415: elsif (implemented_rrs.include?(rrtype)) # A known RR type starting with \# 416: rdata =~ /\\\#\s+(\d+)\s+(.*)$/o; 417: 418: rdlength = $1.to_i; 419: hexdump = $2; 420: hexdump.gsub!(/\s*/, ""); 421: 422: if hexdump.length() != rdlength*2 423: raise Exception, "#{rdata} is inconsistent; length does not match content" 424: end 425: 426: rdata = [hexdump].pack('H*'); 427: 428: return new_from_data(name, rrtype, rrclass, ttl, rdlength, rdata, 0) # rdata.length() - rdlength); 429: elsif (rdata=~/\s*\\\#\s+\d+\s+/o) 430: #We are now dealing with the truly unknown. 431: raise Exception, 'Expected RFC3597 representation of RDATA' unless rdata =~/\\\#\s+(\d+)\s+(.*)$/o; 432: 433: rdlength = $1.to_i; 434: hexdump = $2; 435: hexdump.gsub!(/\s*/o, ""); 436: 437: if hexdump.length() != rdlength*2 438: raise Exception, "#{rdata} is inconsistent; length does not match content" ; 439: end 440: 441: rdata = [hexdump].pack('H*'); 442: 443: return new_from_data(name,rrtype,rrclass,ttl,rdlength,rdata,0) # rdata.length() - rdlength); 444: else 445: #God knows how to handle these... 446: subclass = _get_subclass(name, rrtype, rrclass, ttl, "") 447: return subclass 448: end 449: end
# File lib/Dnsruby/resource/resource.rb, line 530 530: def ==(other) 531: return false unless self.class == other.class 532: ivars = self.instance_variables 533: s_ivars = [] 534: ivars.each {|i| s_ivars << i.to_s} # Ruby 1.9 535: s_ivars.sort! 536: s_ivars.delete "@ttl" # RFC 2136 section 1.1 537: s_ivars.delete "@rdata" 538: 539: ivars = other.instance_variables 540: o_ivars = [] 541: ivars.each {|i| o_ivars << i.to_s} # Ruby 1.9 542: o_ivars.sort! 543: o_ivars.delete "@ttl" # RFC 2136 section 1.1 544: o_ivars.delete "@rdata" 545: 546: return s_ivars == o_ivars && 547: s_ivars.collect {|name| self.instance_variable_get name} == 548: o_ivars.collect {|name| other.instance_variable_get name} 549: end
# File lib/Dnsruby/resource/resource.rb, line 263 263: def clone 264: MessageDecoder.new(MessageEncoder.new {|msg| 265: msg.put_rr(self, true)}.to_s) {|msg| 266: r = msg.get_rr 267: return r 268: } 269: 270: end
# File lib/Dnsruby/resource/resource.rb, line 287 287: def init_defaults 288: # Default to do nothing 289: end
# File lib/Dnsruby/resource/resource.rb, line 251 251: def klass=(klass) 252: if (@type != Types::OPT) 253: @klass= Classes.new(klass) 254: else 255: if (klass.class == Classes) 256: @klass = klass 257: else 258: @klass = Classes.new("CLASS#{klass}") 259: end 260: end 261: end
# File lib/Dnsruby/resource/resource.rb, line 238 238: def name=(newname) 239: if (!(newname.kind_of?Name)) 240: @name=Name.create(newname) 241: else 242: @name = newname 243: end 244: end
# File lib/Dnsruby/resource/resource.rb, line 234 234: def rdlength 235: return rdata.length 236: 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 275 275: def sameRRset(rec) 276: if (@klass != rec.klass || @name != rec.name) 277: return false 278: end 279: [rec, self].each { |rr| 280: if (rr.type == Types::RRSIG) 281: return ((@type == rr.type_covered) || (rec.type == rr.type_covered)) 282: end 283: } 284: return (@type == rec.type) 285: end
Returns a string representation of the RR in zone file format
# File lib/Dnsruby/resource/resource.rb, line 497 497: def to_s 498: return (@name ? @name.to_s():"") + ".\t" +(@ttl ? @ttl.to_s():"") + "\t" + (klass() ? klass.to_s():"") + "\t" + (type() ? type.to_s():"") + "\t" + rdata_to_string 499: end