Parser.py
2.72 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
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
79
80
81
82
83
84
85
86
87
88
89
90
"""
@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: