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:



1758
1759
1760
1761
1762
1763
# File 'lib/resolv.rb', line 1758

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

Instance Method Details

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

Raises:



1783
1784
1785
1786
1787
1788
# File 'lib/resolv.rb', line 1783

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_label ⇒ Object



1875
1876
1877
1878
1879
1880
1881
1882
# File 'lib/resolv.rb', line 1875

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_labels ⇒ Object



1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
# File 'lib/resolv.rb', line 1840

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_length16 ⇒ Object



1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
# File 'lib/resolv.rb', line 1769

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_list ⇒ Object



1828
1829
1830
1831
1832
1833
1834
# File 'lib/resolv.rb', line 1828

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

#get_name ⇒ Object



1836
1837
1838
# File 'lib/resolv.rb', line 1836

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

#get_question ⇒ Object



1884
1885
1886
1887
1888
# File 'lib/resolv.rb', line 1884

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

#get_rr ⇒ Object



1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
# File 'lib/resolv.rb', line 1890

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_string ⇒ Object

Raises:



1811
1812
1813
1814
1815
1816
1817
1818
# File 'lib/resolv.rb', line 1811

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_list ⇒ Object



1820
1821
1822
1823
1824
1825
1826
# File 'lib/resolv.rb', line 1820

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

#get_unpack(template) ⇒ Object

Raises:



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

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

#inspect ⇒ Object



1765
1766
1767
# File 'lib/resolv.rb', line 1765

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