""" @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: