Class: Resolv::DNS::Message::MessageDecoder

Inherits:
Object
  • Object
show all
Defined in:
lib/resolv.rb

Overview

:nodoc:

Instance Method Summary collapse

Constructor Details

#initialize(data) {|_self| ... } ⇒ MessageDecoder

Returns a new instance of MessageDecoder.

Yields:

  • (_self)

Yield Parameters:



1661
1662
1663
1664
1665
1666
# File 'lib/resolv.rb', line 1661

def initialize(data)
  @data = data
  @index = 0
  @limit = data.bytesize
  yield self
end

Instance Method Details

#get_bytes(len = @limit - @index) ⇒ Object

Raises:



1686
1687
1688
1689
1690
1691
# File 'lib/resolv.rb', line 1686

def get_bytes(len = @limit - @index)
  raise DecodeError.new("limit exceeded") if @limit < @index + len
  d = @data.byteslice(@index, len)
  @index += len
  return d
end

#get_labelObject



1778
1779
1780
1781
1782
1783
1784
1785
# File 'lib/resolv.rb', line 1778

def get_label
  return Label::Str.new(self.get_string)
rescue ArgumentError => e
  # A length octet of 64..191 is reserved rather than a label length,
  # but this decoder used to read it as one. [RFC 1035 4.1.4] Report it
  # the way the rest of a malformed message is reported.
  raise DecodeError.new(e.message)
end

#get_labelsObject



1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
# File 'lib/resolv.rb', line 1743

def get_labels
  prev_index = @index
  save_index = nil
  d = []
  # size counts the encoded form, so it starts at 1 for the root
  # label's terminating zero octet. [RFC 1035 3.1]
  size = 1
  while true
    raise DecodeError.new("limit exceeded") if @limit <= @index
    case @data.getbyte(@index)
    when 0
      @index += 1
      if save_index
        @index = save_index
      end
      return d
    when 192..255
      idx = self.get_unpack('n')[0] & 0x3fff
      if prev_index <= idx
        raise DecodeError.new("non-backward name pointer")
      end
      prev_index = idx
      if !save_index
        save_index = @index
      end
      @index = idx
    else
      l = self.get_label
      d << l
      size += 1 + l.string.bytesize
      raise DecodeError.new("name label data exceed 255 octets") if size > 255
    end
  end
end

#get_length16Object



1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
# File 'lib/resolv.rb', line 1672

def get_length16
  len, = self.get_unpack('n')
  save_limit = @limit
  @limit = @index + len
  d = yield(len)
  if @index < @limit
    raise DecodeError.new("junk exists")
  elsif @limit < @index
    raise DecodeError.new("limit exceeded")
  end
  @limit = save_limit
  return d
end

#get_listObject



1731
1732
1733
1734
1735
1736
1737
# File 'lib/resolv.rb', line 1731

def get_list
  [].tap do |values|
    while @index < @limit
      values << yield
    end
  end
end

#get_nameObject



1739
1740
1741
# File 'lib/resolv.rb', line 1739

def get_name
  return Name.new(self.get_labels)
end

#get_questionObject



1787
1788
1789
1790
1791
# File 'lib/resolv.rb', line 1787

def get_question
  name = self.get_name
  type, klass = self.get_unpack("nn")
  return name, Resource.get_class(type, klass)
end

#get_rrObject



1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
# File 'lib/resolv.rb', line 1793

def get_rr
  name = self.get_name
  type, klass, ttl = self.get_unpack('nnN')
  typeclass = Resource.get_class(type, klass)
  res = self.get_length16 do
    begin
      typeclass.decode_rdata self
    rescue => e
      raise DecodeError, e.message, e.backtrace
    end
  end
  res.instance_variable_set :@ttl, ttl
  return name, ttl, res
end

#get_stringObject

Raises:



1714
1715
1716
1717
1718
1719
1720
1721
# File 'lib/resolv.rb', line 1714

def get_string
  raise DecodeError.new("limit exceeded") if @limit <= @index
  len = @data.getbyte(@index)
  raise DecodeError.new("limit exceeded") if @limit < @index + 1 + len
  d = @data.byteslice(@index + 1, len)
  @index += 1 + len
  return d
end

#get_string_listObject



1723
1724
1725
1726
1727
1728
1729
# File 'lib/resolv.rb', line 1723

def get_string_list
  strings = []
  while @index < @limit
    strings << self.get_string
  end
  strings
end

#get_unpack(template) ⇒ Object

Raises:



1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
# File 'lib/resolv.rb', line 1693

def get_unpack(template)
  len = 0
  template.each_byte {|byte|
    byte = "%c" % byte
    case byte
    when ?c, ?C
      len += 1
    when ?n
      len += 2
    when ?N
      len += 4
    else
      raise StandardError.new("unsupported template: '#{byte.chr}' in '#{template}'")
    end
  }
  raise DecodeError.new("limit exceeded") if @limit < @index + len
  arr = @data.unpack("@#{@index}#{template}")
  @index += len
  return arr
end

#inspectObject



1668
1669
1670
# File 'lib/resolv.rb', line 1668

def inspect
  "\#<#{self.class}: #{@data.byteslice(0, @index).inspect} #{@data.byteslice(@index..-1).inspect}>"
end