Class: Dnsruby::MessageDecoder

Inherits:
Object
  • Object
show all
Defined in:
lib/dnsruby/message/decoder.rb

Overview

:nodoc: all

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

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

Returns a new instance of MessageDecoder.

Yields:

  • (_self)

Yield Parameters:



4
5
6
7
8
9
# File 'lib/dnsruby/message/decoder.rb', line 4

def initialize(data)
  @data = data
  @index = 0
  @limit = data.length
  yield self if block_given?
end

Instance Attribute Details

#indexObject (readonly)

Returns the value of attribute index.



3
4
5
# File 'lib/dnsruby/message/decoder.rb', line 3

def index
  @index
end

Instance Method Details

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



31
32
33
34
35
# File 'lib/dnsruby/message/decoder.rb', line 31

def get_bytes(len = @limit - @index)
  d = @data[@index, len]
  @index += len
  d
end

#get_labelObject



132
133
134
135
136
137
138
139
140
141
# File 'lib/dnsruby/message/decoder.rb', line 132

def get_label
  begin
    #         label = Name::Label.new(Name::decode(self.get_string))
    label = Name::Label.new(self.get_string)
    return label
      #          return Name::Label::Str.new(self.get_string)
  rescue ResolvError => e
    raise DecodeError.new(e) # Turn it into something more suitable
  end
end

#get_labels(limit = nil) ⇒ Object



103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
# File 'lib/dnsruby/message/decoder.rb', line 103

def get_labels(limit=nil)
  limit = @index if !limit || @index < limit
  d = []
  while true
    temp = @data[@index]
    if temp.class == String
      temp = temp.getbyte(0)
    end
    case temp # @data[@index]
      when 0
        @index += 1
        return d
      when 192..255
        idx = self.get_unpack('n')[0] & 0x3fff
        if limit <= idx
          raise DecodeError.new('non-backward name pointer')
        end
        save_index = @index
        @index = idx
        d += self.get_labels(limit)
        @index = save_index
        return d
      else
        d << self.get_label
    end
  end
  d
end

#get_length16Object



15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# File 'lib/dnsruby/message/decoder.rb', line 15

def get_length16
  len, = self.get_unpack('n')
  save_limit = @limit
  @limit = @index + len
  d = yield(len)
  if @index < @limit
    message = "Junk exists; limit = #{@limit}, index = #{@index}"
    raise DecodeError.new(message)
  elsif @limit < @index
    message = "Limit exceeded; limit = #{@limit}, index = #{@index}"
    raise DecodeError.new(message)
  end
  @limit = save_limit
  d
end

#get_nameObject



99
100
101
# File 'lib/dnsruby/message/decoder.rb', line 99

def get_name
  Name.new(self.get_labels)
end

#get_questionObject



143
144
145
146
147
148
# File 'lib/dnsruby/message/decoder.rb', line 143

def get_question
  name = self.get_name
  type, klass = self.get_unpack('nn')
  q = Question.new(name, type, klass)
  q
end

#get_rrObject



150
151
152
153
154
155
156
157
158
159
160
161
162
163
# File 'lib/dnsruby/message/decoder.rb', line 150

def get_rr
  name = self.get_name
  type, klass, ttl = self.get_unpack('nnN')
  klass = Classes.new(klass)
  typeclass = RR.get_class(type, klass)
  #  @TODO@ Trap decode errors here, and somehow mark the record as bad.
  #  Need some way to represent raw data only
  rec = self.get_length16 { typeclass.decode_rdata(self) }
  rec.name = name
  rec.ttl = ttl
  rec.type = type
  rec.klass = klass
  rec
end

#get_stringObject

Raises:



80
81
82
83
84
85
86
87
88
89
# File 'lib/dnsruby/message/decoder.rb', line 80

def get_string
  len = @data[@index]
  if len.class == String
    len = len.getbyte(0)
  end
  raise DecodeError.new("limit exceeded\nlimit = #{@limit}, index = #{@index}, len = #{len}\n") if @limit < @index + 1 + (len ? len : 0)
  d = @data[@index + 1, len]
  @index += 1 + len
  d
end

#get_string_listObject



91
92
93
94
95
96
97
# File 'lib/dnsruby/message/decoder.rb', line 91

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

#get_unpack(template) ⇒ Object

Raises:



37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/dnsruby/message/decoder.rb', line 37

def get_unpack(template)
  len = 0
  littlec = ?c
  bigc = ?C
  littleh = ?h
  bigh = ?H
  littlen = ?n
  bign = ?N
  star = ?*

  if (littlec.class != Fixnum)
    #  We're using Ruby 1.9 - convert the codes
    littlec = littlec.getbyte(0)
    bigc = bigc.getbyte(0)
    littleh = littleh.getbyte(0)
    bigh = bigh.getbyte(0)
    littlen = littlen.getbyte(0)
    bign = bign.getbyte(0)
    star = star.getbyte(0)
  end

  template.each_byte {|byte|
    case byte
      when littlec, bigc
        len += 1
      when littleh, bigh
        len += 1
      when littlen
        len += 2
      when bign
        len += 4
      when star
        len = @limit - @index
      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
  arr
end

#has_remainingObject



11
12
13
# File 'lib/dnsruby/message/decoder.rb', line 11

def has_remaining
  @limit - @index > 0
end