Class: Nesser::Unpacker

Inherits:
Object
  • Object
show all
Defined in:
lib/nesser/packets/unpacker.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(data) ⇒ Unpacker

Returns a new instance of Unpacker.



31
32
33
34
# File 'lib/nesser/packets/unpacker.rb', line 31

def initialize(data)
  @data = data
  @offset = 0
end

Instance Attribute Details

#dataObject

Returns the value of attribute data.



23
24
25
# File 'lib/nesser/packets/unpacker.rb', line 23

def data
  @data
end

#offsetObject

Returns the value of attribute offset.



23
24
25
# File 'lib/nesser/packets/unpacker.rb', line 23

def offset
  @offset
end

Instance Method Details

#to_sObject



158
159
160
# File 'lib/nesser/packets/unpacker.rb', line 158

def to_s()
  return HexHelper::to_s(@data, offset: @offset)
end

#unpack(format) ⇒ Object



54
55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/nesser/packets/unpacker.rb', line 54

def unpack(format)
  if @offset >= @data.length
    raise(DnsException, "DNS packet was invalid!")
  end

  results = @data[@offset..-1].unpack(format + "a*")
  remaining = results.pop
  @offset = @data.length - remaining.length

  _verify_results(results)

  return *results
end

#unpack_name(depth: 0) ⇒ Object



120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
# File 'lib/nesser/packets/unpacker.rb', line 120

def unpack_name(depth:0)
  segments = []

  if depth > MAX_RECURSION_DEPTH
    raise(DnsException, "It looks like this packet contains recursive pointers!")
  end

  loop do
    # If no offset is given, just eat data from the normal source
    len = unpack_one("C")

    # Stop at the null terminator
    if len == 0
      break
    end

    # Handle "pointer" records by updating the offset
    if (len & 0xc0) == 0xc0
      # If the first two bits are 1 (ie, 0xC0), the next
      # 10 bits are an offset, so we have to mask out the first two bits
      # with 0x3F (00111111)
      offset = ((len << 8) | unpack_one("C")) & 0x3FFF

      _with_offset(offset) do
        segments << unpack_name(depth:depth+1).split(/\./)
      end

      break
    end

    # It's normal, just unpack what we need to!
    segments << unpack("a#{len}")
  end

  return segments.join('.')
end

#unpack_one(format) ⇒ Object



76
77
78
79
80
81
82
83
84
85
# File 'lib/nesser/packets/unpacker.rb', line 76

def unpack_one(format)
  results = unpack(format)

  _verify_results(results)
  if results.length != 1
    raise(DnsException, "unpack_one() was passed a bad format string")
  end

  return results.pop()
end