Class: Dnsruby::Message

### Home Classes Methods

### In Files

- lib/Dnsruby/message.rb

### Parent

Object

### Namespace

- CLASS Dnsruby::Message::Section
- CLASS Dnsruby::Message::SecurityLevel

### Methods

- ::decode
- ::new
- #==
- #add_question
- #add_zone
- #each_additional
- #each_answer
- #each_authority
- #each_pre
- #each_prerequisite
- #each_question
- #each_resource
- #each_section
- #each_update
- #each_zone
- #encode
- #get_exception
- #get_opt
- #rcode
- #remove_additional
- #rrset
- #rrsets
- #section_rrsets
- #set_tsig
- #signed?
- #to_s
- #tsig
- #verified?

### Files

- DNSSEC
- EVENTMACHINE
- EXAMPLES
- README

### Class/Module Index

Quicksearch

- Dnsruby
- Dnsruby::Algorithms
- Dnsruby::Classes
- Dnsruby::CodeMapper
- Dnsruby::Config
- Dnsruby::DNS
- Dnsruby::DecodeError
- Dnsruby::Dnssec
- Dnsruby::Dnssec::ValidationPolicy
- Dnsruby::EncodeError
- Dnsruby::ExtendedRCode
- Dnsruby::FormErr
- Dnsruby::Header
- Dnsruby::Hosts
- Dnsruby::IPv4
- Dnsruby::IPv6
- Dnsruby::Message
- Dnsruby::Message::Section
- Dnsruby::Message::SecurityLevel
- Dnsruby::MetaTypes
- Dnsruby::Modes
- Dnsruby::NXDomain
- Dnsruby::NXRRSet
- Dnsruby::Name
- Dnsruby::Name::Label
- Dnsruby::NotAuth
- Dnsruby::NotImp
- Dnsruby::NotZone
- Dnsruby::Nsec3HashAlgorithms
- Dnsruby::OpCode
- Dnsruby::OtherResolvError
- Dnsruby::QTypes
- Dnsruby::Question
- Dnsruby::RCode
- Dnsruby::RR
- Dnsruby::RR::ANY
- Dnsruby::RR::CERT
- Dnsruby::RR::CERT::CertificateTypes
- Dnsruby::RR::CNAME
- Dnsruby::RR::DHCID
- Dnsruby::RR::DLV
- Dnsruby::RR::DNAME
- Dnsruby::RR::DNSKEY
- Dnsruby::RR::DS
- Dnsruby::RR::DS::DigestTypes
- Dnsruby::RR::DomainName
- Dnsruby::RR::Generic
- Dnsruby::RR::HINFO
- Dnsruby::RR::HIP
- Dnsruby::RR::IN
- Dnsruby::RR::IN::A
- Dnsruby::RR::IN::AAAA
- Dnsruby::RR::IN::AFSDB
- Dnsruby::RR::IN::PX
- Dnsruby::RR::IN::SRV
- Dnsruby::RR::IN::WKS
- Dnsruby::RR::IPSECKEY
- Dnsruby::RR::ISDN
- Dnsruby::RR::KX
- Dnsruby::RR::LOC
- Dnsruby::RR::MB
- Dnsruby::RR::MG
- Dnsruby::RR::MINFO
- Dnsruby::RR::MR
- Dnsruby::RR::MX
- Dnsruby::RR::NAPTR
- Dnsruby::RR::NS
- Dnsruby::RR::NSAP
- Dnsruby::RR::NSEC
- Dnsruby::RR::NSEC3
- Dnsruby::RR::NSEC3PARAM
- Dnsruby::RR::OPT
- Dnsruby::RR::PTR
- Dnsruby::RR::RP
- Dnsruby::RR::RRSIG
- Dnsruby::RR::RT
- Dnsruby::RR::SOA
- Dnsruby::RR::SPF
- Dnsruby::RR::SSHFP
- Dnsruby::RR::SSHFP::Algorithms
- Dnsruby::RR::SSHFP::FpTypes
- Dnsruby::RR::TKEY
- Dnsruby::RR::TSIG
- Dnsruby::RR::TXT
- Dnsruby::RR::X25
- Dnsruby::RRSet
- Dnsruby::Recursor
- Dnsruby::Refused
- Dnsruby::Resolv
- Dnsruby::ResolvError
- Dnsruby::ResolvTimeout
- Dnsruby::Resolver
- Dnsruby::Resolver::EventType
- Dnsruby::SelectThread
- Dnsruby::ServFail
- Dnsruby::SingleResolver
- Dnsruby::TheLog
- Dnsruby::TsigError
- Dnsruby::TsigNotSignedResponseError
- Dnsruby::Types
- Dnsruby::Update
- Dnsruby::VerifyError
- Dnsruby::YXDomain
- Dnsruby::YXRRSet
- Dnsruby::ZoneReader
- Dnsruby::ZoneReader::ParseException
- Dnsruby::ZoneSerialError
- Dnsruby::ZoneTransfer
- Dnsruby::ZoneTransfer::Delta
- Base32

No matching classes.

# Dnsruby::Message

### Defines a DNS packet.

RFC 1035 Section 4.1, RFC 2136 Section 2, RFC 2845

### Sections

Message objects have five sections:

- The header section, a Dnsruby::Header object.

      msg.header=Header.new(...)
      header = msg.header

- The question section, an array of Dnsruby::Question objects.

      msg.add_question(Question.new(domain, type, klass))
      msg.each_question do |question|  ....   end

- The answer section, an array of Dnsruby::RR objects.

      msg.add_answer(RR.create({:name    => "a2.example.com",
                   :type    => "A", :address => "10.0.0.2"}))
      msg.each_answer {|answer| ... }

- The authority section, an array of Dnsruby::RR objects.

      msg.add_authority(rr)
      msg.each_authority {|rr| ... }

- The additional section, an array of Dnsruby::RR objects.

      msg.add_additional(rr)
      msg.each_additional {|rr| ... }

In addition, each_resource iterates the answer, additional and authority sections :

    msg.each_resource {|rr| ... }

### Packet format encoding

    Dnsruby::Message#encode
    Dnsruby::Message::decode(data)

### Additional information

security_level records the current DNSSEC status of this Message. answerfrom records the server which this Message was received from. cached records whether this response came from the cache.

### Attributes

additional[R]

The additional section, an array of Dnsruby::RR objects.

answer[R]

The answer section, an array of Dnsruby::RR objects.

answerfrom[RW]

If this Message is a response from a server, then answerfrom contains the address of the server

answerip[RW]

If this Message is a response from a server, then answerfrom contains the IP address of the server

answersize[RW]

If this Message is a response from a server, then answersize contains the size of the response

authority[R]

The authority section, an array of Dnsruby::RR objects.

cached[RW]

If the Message was returned from the cache, the cached flag will be set true. It will be false otherwise.

do_caching[RW]

do_caching is set by default. If you do not wish dnsruby to inspect the cache before sending the query, nor cache the result of the query, then set do_caching to false.

do_validation[RW]

do_validation is set by default. If you do not wish dnsruby to validate this message (on a Resolver with @dnssec==true), then set do_validation to false. This option does not affect caching, or the header options

header[RW]

The header section, a Dnsruby::Header object.

pre[R]

The answer section, an array of Dnsruby::RR objects.

prerequisite[R]

The answer section, an array of Dnsruby::RR objects.

question[R]

The question section, an array of Dnsruby::Question objects.

security_error[RW]

If there was a problem verifying this message with DNSSEC, then securiy_error will hold a description of the problem. It defaults to ""

security_level[RW]

If dnssec is set on, then each message will have the security level set To find the precise error (if any), call Dnsruby::Dnssec::validate(msg) - the resultant exception will define the error.

send_raw[RW]

Set send_raw if you wish to send and receive the response to this Message with no additional processing. In other words, if set, then Dnsruby will not touch the Header of the outgoing Message. This option does not affect caching or dnssec validation

This option should not normally be set.

tsigerror[RW]

If this message has been verified using a TSIG RR then tsigerror contains the error code returned by the TSIG verification. The error will be an RCode

tsigstart[RW]
tsigstate[RW]

Can be

- :Unsigned - the default state

- :Signed - the outgoing message has been signed

- :Verified - the incoming message has been verified by TSIG

- :Intermediate - the incoming message is an intermediate envelope in a TCP session

in which only every 100th envelope must be signed

- :Failed - the incoming response failed verification

update[R]

The authority section, an array of Dnsruby::RR objects.

zone[R]

The question section, an array of Dnsruby::Question objects.

### Public Class Methods

decode(m) click to toggle source

Decode the encoded message

    # File lib/Dnsruby/message.rb, line 597
    def Message.decode(m)
      o = Message.new()
      begin
        MessageDecoder.new(m) {|msg|
          o.header = Header.new(msg)
          o.header.qdcount.times {
            question = msg.get_question
            o.question << question
          }
          o.header.ancount.times {
            rr = msg.get_rr
            o.answer << rr
          }
          o.header.nscount.times {
            rr = msg.get_rr
            o.authority << rr
          }
          o.header.arcount.times { |count|
            start = msg.index
            rr = msg.get_rr
            if (rr.type == Types::TSIG)
              if (count!=o.header.arcount-1)
                Dnsruby.log.Error("Incoming message has TSIG record before last record")
                raise DecodeError.new("TSIG record present before last record")
              end
              o.tsigstart = start # needed for TSIG verification
            end
            o.additional << rr
          }
        }
      rescue DecodeError => e
        # So we got a decode error
        # However, we might have been able to fill in many parts of the message
        # So let's raise the DecodeError, but add the partially completed message
        e.partial_message = o
        raise e
      end
      return o
    end

new(*args) click to toggle source

Create a new Message. Takes optional name, type and class

type defaults to A, and klass defaults to IN

- Dnsruby::Message.new("example.com") # defaults to A, IN

- Dnsruby::Message.new("example.com", 'AAAA')

- Dnsruby::Message.new("example.com", Dnsruby::Types.PTR, "HS")

    # File lib/Dnsruby/message.rb, line 189
    def initialize(*args)
      @header = Header.new()
      #      @question = Section.new(self)
      @question = []
      @answer = Section.new(self)
      @authority = Section.new(self)
      @additional = Section.new(self)
      @tsigstate = :Unsigned
      @signing = false
      @tsigkey = nil
      @answerfrom = nil
      @answerip = nil
      @send_raw = false
      @do_validation = true
      @do_caching = true
      @security_level = SecurityLevel.UNCHECKED
      @security_error = nil
      @cached = false
      type = Types::A
      klass = Classes::IN
      if (args.length > 0)
        name = args[0]
        if (args.length > 1)
          type = Types.new(args[1])
          if (args.length > 2)
            klass = Classes.new(args[2])
          end
        end
        add_question(name, type, klass)
      end
    end

### Public Instance Methods

==(other) click to toggle source

    # File lib/Dnsruby/message.rb, line 305
    def ==(other)
      ret = false
      if (other.kind_of?Message)
        ret = @header == other.header &&
          @question[0] == other.question[0] &&
          @answer == other.answer &&
          @authority == other.authority &&
          @additional == other.additional
      end
      return ret
    end

add_question(question, type=Types.A, klass=Classes.IN) click to toggle source

Add a new Question to the Message. Takes either a Question, or a name, and an optional type and class.

- msg.add_question(Question.new("example.com", 'MX'))

- msg.add_question("example.com") # defaults to Types.A, Classes.IN

- msg.add_question("example.com", Types.LOC)

    # File lib/Dnsruby/message.rb, line 361
    def add_question(question, type=Types.A, klass=Classes.IN)
      if (!question.kind_of?Question)
        question = Question.new(question, type, klass)
      end
      @question << question
      update_counts
    end

Also aliased as: add_zone
add_zone(question, type=Types.A, klass=Classes.IN) click to toggle source
Alias for: add_question
each_additional() click to toggle source

    # File lib/Dnsruby/message.rb, line 416
    def each_additional
      @additional.each {|rec|
        yield rec
      }
    end

each_answer() click to toggle source

    # File lib/Dnsruby/message.rb, line 390
    def each_answer
      @answer.each {|rec|
        yield rec
      }
    end

Also aliased as: each_pre
each_authority() click to toggle source

    # File lib/Dnsruby/message.rb, line 403
    def each_authority
      @authority.each {|rec|
        yield rec
      }
    end

Also aliased as: each_update
each_pre() click to toggle source
Also aliased as: each_prerequisite
Alias for: each_answer
each_prerequisite() click to toggle source
Alias for: each_pre
each_question() click to toggle source

    # File lib/Dnsruby/message.rb, line 369
    def each_question
      @question.each {|rec|
        yield rec
      }
    end

Also aliased as: each_zone
each_resource() click to toggle source

Calls each_answer, each_authority, each_additional

    # File lib/Dnsruby/message.rb, line 428
    def each_resource
      each_answer {|rec| yield rec}
      each_authority {|rec| yield rec}
      each_additional {|rec| yield rec}
    end

each_section() click to toggle source

Yields each section (question, answer, authority, additional)

    # File lib/Dnsruby/message.rb, line 423
    def each_section
      [@answer, @authority, @additional].each {|section| yield section}
    end

each_update() click to toggle source
Alias for: each_authority
each_zone() click to toggle source
Alias for: each_question
encode() click to toggle source

Return the encoded form of the message

    If there is a TSIG record present and the record has not been signed
    then sign it

    # File lib/Dnsruby/message.rb, line 575
    def encode
      if ((@tsigkey) && @tsigstate == :Unsigned && !@signing)
        @signing = true
        sign!
        @signing = false
      end
      return MessageEncoder.new {|msg|
        header = @header
        header.encode(msg)
        @question.each {|q|
          msg.put_name(q.qname)
          msg.put_pack('nn', q.qtype.code, q.qclass.code)
        }
        [@answer, @authority, @additional].each {|rr|
          rr.each { |r|
            msg.put_rr(r)
          }
        }
      }.to_s
    end

get_exception() click to toggle source

    # File lib/Dnsruby/message.rb, line 277
    def get_exception
      exception = nil
      if (rcode==RCode.NXDOMAIN)
        exception = NXDomain.new
      elsif (rcode==RCode.SERVFAIL)
        exception = ServFail.new
      elsif (rcode==RCode.FORMERR)
        exception = FormErr.new
      elsif (rcode==RCode.NOTIMP)
        exception = NotImp.new
      elsif (rcode==RCode.REFUSED)
        exception = Refused.new
      elsif (rcode==RCode.NOTZONE)
        exception = NotZone.new
      elsif (rcode==RCode.NOTAUTH)
        exception = NotAuth.new
      elsif (rcode==RCode.NXRRSET)
        exception = NXRRSet.new
      elsif (rcode==RCode.YXRRSET)
        exception = YXRRSet.new
      elsif (rcode==RCode.YXDOMAIN)
        exception = YXDomain.new
      elsif (rcode >= RCode.BADSIG && rcode <= RCode.BADALG)
        return VerifyError.new # @TODO@
      end
      return exception
    end

get_opt() click to toggle source

    # File lib/Dnsruby/message.rb, line 475
    def get_opt
      each_additional do |r|
        if (r.type == Types::OPT)
          return r
        end
      end
      return nil
    end

rcode() click to toggle source

    # File lib/Dnsruby/message.rb, line 484
    def rcode
      rcode = @header.get_header_rcode
      opt = get_opt
      if (opt != nil)
        rcode = rcode.code + (opt.xrcode.code << 4)
        rcode = RCode.new(rcode)
      end
      return rcode;
    end

remove_additional() click to toggle source

    # File lib/Dnsruby/message.rb, line 317
    def remove_additional
      @additional = Section.new(self)
      @header.arcount = 0
    end

rrset(name, type, klass = Classes::IN) click to toggle source

Return the first rrset of the specified attributes in the message

    # File lib/Dnsruby/message.rb, line 323
    def rrset(name, type, klass = Classes::IN)
      [@answer, @authority, @additional].each do |section|
        if ((rrset = section.rrset(name, type, klass)).length > 0)
          return rrset
        end
      end
      return RRSet.new
    end

rrsets(type, klass=Classes::IN) click to toggle source

Return the rrsets of the specified type in the message

    # File lib/Dnsruby/message.rb, line 333
    def rrsets(type, klass=Classes::IN)
      rrsetss = []
      [@answer, @authority, @additional].each do |section|
        if ((rrsets = section.rrsets(type, klass)).length > 0)
          rrsets.each {|rrset|
            rrsetss.push(rrset)
          }
        end
      end
      return rrsetss
    end

section_rrsets(type = nil, include_opt = false) click to toggle source

Return a hash, with the section as key, and the RRSets in that section as the data : {section => section_rrs}

    # File lib/Dnsruby/message.rb, line 347
    def section_rrsets(type = nil, include_opt = false)
      ret = {}
      ["answer", "authority", "additional"].each do |section|
        ret[section] = self.send(section).rrsets(type, include_opt)
      end
      return ret
    end

set_tsig(*args) click to toggle source

Sets the TSIG to sign this message with. Can either be a Dnsruby::RR::TSIG object, or it can be a (name, key) tuple, or it can be a hash which takes Dnsruby::RR::TSIG attributes (e.g. name, key, fudge, etc.)

    # File lib/Dnsruby/message.rb, line 447
    def set_tsig(*args)
      if (args.length == 1)
        if (args[0].instance_of?RR::TSIG)
          @tsigkey = args[0]
        elsif (args[0].instance_of?Hash)
          @tsigkey = RR.create({:type=>'TSIG', :klass=>'ANY'}.merge(args[0]))
        else
          raise ArgumentError.new("Wrong type of argument to Dnsruby::Message#set_tsig - should be TSIG or Hash")
        end
      elsif (args.length == 2)
        @tsigkey = RR.create({:type=>'TSIG', :klass=>'ANY', :name=>args[0], :key=>args[1]})
      else
        raise ArgumentError.new("Wrong number of arguments to Dnsruby::Message#set_tsig")
      end
    end

signed?() click to toggle source

Was this message signed by a TSIG?

    # File lib/Dnsruby/message.rb, line 464
    def signed?
      return (@tsigstate == :Signed ||
          @tsigstate == :Verified ||
          @tsigstate == :Failed)
    end

to_s() click to toggle source

    # File lib/Dnsruby/message.rb, line 494
    def to_s
      retval = "";

      if (@answerfrom != nil && @answerfrom != "")
        retval = retval + ";; Answer received from #{@answerfrom} (#{@answersize} bytes)\n;;\n";
      end
      retval = retval + ";; Security Level : #{@security_level.string}\n"

      retval = retval + ";; HEADER SECTION\n"
      # OPT pseudosection? EDNS flags, udpsize
      opt = get_opt
      if (!opt)
        retval = retval + @header.to_s
      else
        retval = retval + @header.to_s_with_rcode(rcode())
      end
      retval = retval + "\n"

      if (opt)
        retval = retval + opt.to_s
        retval = retval + "\n"
      end

      section = (@header.opcode == OpCode.UPDATE) ? "ZONE" : "QUESTION";
      retval = retval +  ";; #{section} SECTION (#{@header.qdcount}  record#{@header.qdcount == 1 ? '' : 's'})\n";
      each_question { |qr|
        retval = retval + ";; #{qr.to_s}\n";
      }

      if (@answer.size > 0)
        retval = retval + "\n";
        section = (@header.opcode == OpCode.UPDATE) ? "PREREQUISITE" : "ANSWER";
        retval = retval + ";; #{section} SECTION (#{@header.ancount}  record#{@header.ancount == 1 ? '' : 's'})\n";
        each_answer { |rr|
          retval = retval + rr.to_s + "\n";
        }
      end

      if (@authority.size > 0)
        retval = retval + "\n";
        section = (@header.opcode == OpCode.UPDATE) ? "UPDATE" : "AUTHORITY";
        retval = retval + ";; #{section} SECTION (#{@header.nscount}  record#{@header.nscount == 1 ? '' : 's'})\n";
        each_authority { |rr|
          retval = retval + rr.to_s + "\n";
        }
      end

      if ((@additional.size > 0 && !opt) || (@additional.size > 1))
        retval = retval + "\n";
        retval = retval + ";; ADDITIONAL SECTION (#{@header.arcount}  record#{@header.arcount == 1 ? '' : 's'})\n";
        each_additional { |rr|
          if (rr.type != Types::OPT)
            retval = retval + rr.to_s+ "\n"
          end
        }
      end

      return retval;
    end

tsig() click to toggle source

Returns the TSIG record from the ADDITIONAL section, if one is present.

    # File lib/Dnsruby/message.rb, line 435
    def tsig
      if (@additional.last)
        if (@additional.last.rr_type == Types.TSIG)
          return @additional.last
        end
      end
      return nil
    end

verified?() click to toggle source

If this message was signed by a TSIG, was the TSIG verified?

    # File lib/Dnsruby/message.rb, line 471
    def verified?
      return (@tsigstate == :Verified)
    end

[Validate]

Generated with the Darkfish Rdoc Generator 2.