You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
90 lines
2.7 KiB
90 lines
2.7 KiB
"""
|
|
@author Georg Hopp
|
|
|
|
"""
|
|
import struct
|
|
|
|
class Parser(object):
|
|
def __init__(self):
|
|
self._ofs_names = {}
|
|
|
|
def parse(self, message, data):
|
|
self._ofs_names = {}
|
|
|
|
message._msg_id, \
|
|
message._flags, \
|
|
nqueries, \
|
|
nanswers, \
|
|
nauthorities, \
|
|
nadditionals = struct.unpack('!HHHHHH', data[0:12])
|
|
|
|
ofs = 12
|
|
ofs = self._parseQueries(message, data, ofs, nqueries)
|
|
ofs = self._parseAnswers(message, data, ofs, nanswers)
|
|
ofs = self._parseAuthorities(message, data, ofs, nauthorities)
|
|
self._parseAdditionals(message, data, ofs, nadditionals)
|
|
|
|
def _parseQueries(self, message, data, ofs, count):
|
|
while 0 < count:
|
|
name, ofs = self._decodeName(data, ofs)
|
|
typ, cls = struct.unpack('!HH', data[ofs:ofs+4])
|
|
ofs += 4
|
|
count -= 1
|
|
message._queries.append((name, typ, cls))
|
|
|
|
return ofs
|
|
|
|
def _parseAnswers(self, message, data, ofs, count):
|
|
while 0 < count:
|
|
record, ofs = self._parseResourceRecord(message, data, ofs)
|
|
count -= 1
|
|
message._answers.append(record)
|
|
|
|
return ofs
|
|
|
|
def _parseAuthorities(self, message, data, ofs, count):
|
|
while 0 < count:
|
|
record, ofs = self._parseResourceRecord(message, data, ofs)
|
|
count -= 1
|
|
message._authorities.append(record)
|
|
|
|
return ofs
|
|
|
|
def _parseAdditionals(self, message, data, ofs, count):
|
|
while 0 < count:
|
|
record, ofs = self._parseResourceRecord(message, data, ofs)
|
|
count -= 1
|
|
message._additionals.append(record)
|
|
|
|
return ofs
|
|
|
|
def _parseResourceRecord(self, message, data, ofs):
|
|
name, ofs = self._decodeName(data, ofs)
|
|
typ, cls, ttl, rrlen = struct.unpack('!HHLH', data[ofs:ofs+10])
|
|
ofs += 10
|
|
record = data[ofs:ofs+rrlen]
|
|
ofs += rrlen
|
|
|
|
return ((name, typ, cls, ttl, record), ofs)
|
|
|
|
def _decodeName(self, data, ofs):
|
|
idx = ofs
|
|
compressed = struct.unpack('!H', data[ofs:ofs+2])[0]
|
|
|
|
if compressed & int('1100000000000000', 2):
|
|
idx = compressed & int('0011111111111111', 2)
|
|
name = (self._ofs_names[idx], ofs+2)
|
|
else:
|
|
length = struct.unpack('B', data[ofs])[0]
|
|
parts = []
|
|
while 0 != length:
|
|
parts.append(data[ofs+1:ofs+1+length])
|
|
ofs += 1+length
|
|
length = struct.unpack('B', data[ofs])[0]
|
|
|
|
name = ('.'.join(parts), ofs+1)
|
|
self._ofs_names[idx] = name[0]
|
|
|
|
return name
|
|
|
|
# vim: set ft=python et ts=4 sw=4 sts=4:
|