def parse(bytedata: bytes) -> tuple: """ :param bytedata data, from the dns packet stream :return: tuple(AnswerItem, rest of bytedata) :rtype AnswerItem, bytes """ name_field, bytedata = bread(bytedata, 2) name_field = int.from_bytes(name_field, byteorder="big") # 0bXY00000000000000 - X: 1 Y: 1 -> 11, X:0 Y:1 -> 1, X:1 Y:0 -> 10 name_type = 10 * ((name_field >> 15) & 0b1) + ((name_field >> 14) & 0b1) name_offset = name_field & 0b001111111111111 assert name_type == 11 _type, bytedata = bread(bytedata, 2) _type = int.from_bytes(_type, byteorder="big") _class, bytedata = bread(bytedata, 2) _class = int.from_bytes(_class, byteorder="big") _ttl, bytedata = bread(bytedata, 4) _ttl = int.from_bytes(_ttl, byteorder="big") rdlen, bytedata = bread(bytedata, 2) rdlen = int.from_bytes(rdlen, byteorder="big") rddata, bytedata = bread(bytedata, rdlen) rddata = QuestionTypes.unpack(_type, rddata) return AnswerItem(QuestionItem(name_offset, _type, _class), _type, rddata, _ttl), bytedata
def parse(bytedata: bytes) -> tuple: """ :param bytedata data, from the dns packet stream :return: tuple(QuestionItem, rest of bytedata) :rtype QuestionItem, bytes """ domain = [] count = -1 while count != 0: count, bytedata = bread(bytedata, 1) count = int.from_bytes(count, byteorder="big") if count != 0: domain_part, bytedata = bread(bytedata, count) domain.append(domain_part.decode()) qtype, bytedata = bread(bytedata, 2) qtype = int.from_bytes(qtype, byteorder="big") qclass, bytedata = bread(bytedata, 2) qclass = int.from_bytes(qclass, byteorder="big") return QuestionItem(domain, qtype, qclass), bytedata
def __init__(self, _msg=None): """ :type _msg byte :param _msg Get byte array as input and form structured data """ if _msg is None: self.message_id = generate_message_id() self.header = Header() self.question_section = [] self.answer_section = [] self.authority_section = [] self.additional_section = [] return offset = 0 # parse data packet self.message_id, _msg, offset = bread(_msg, 2, offset) _pack1, _msg, offset = bread(_msg, 2, offset, data_fx=lambda x: int.from_bytes(x, byteorder="big")) # declare sections _size, _msg, offset = bread(_msg, 2, offset, data_fx=lambda x: int.from_bytes(x, byteorder="big")) self.question_section = [None] * _size # required to store question section offsets for answer_section "name" question_offset_grid = [None] * _size _size, _msg, offset = bread(_msg, 2, offset, data_fx=lambda x: int.from_bytes(x, byteorder="big")) self.answer_section = [None] * _size _size, _msg, offset = bread(_msg, 2, offset, data_fx=lambda x: int.from_bytes(x, byteorder="big")) self.authority_section = [None] * _size _size, _msg, offset = bread(_msg, 2, offset, data_fx=lambda x: int.from_bytes(x, byteorder="big")) self.additional_section = [None] * _size # decode header section self.header = Header(_pack1) # decode Question section for i in range(0, len(self.question_section)): la = len(_msg) item, _msg = QuestionItem.parse(_msg) lb = len(_msg) question_offset_grid[i] = offset self.question_section[i] = item offset += la - lb # decode Answer section for i in range(0, len(self.answer_section)): la = len(_msg) item, _msg = AnswerItem.parse(_msg) lb = len(_msg) # here we will get answer name from the offset loffset = item.name for x in range(0, len(question_offset_grid)): if question_offset_grid[x] <= loffset: item.name = self.question_section[x].qname self.answer_section[i] = item offset += la - lb # decode Authority section for i in range(0, len(self.authority_section)): la = len(_msg) item, _msg = AnswerItem.parse(_msg) lb = len(_msg) # here we will get answer name from the offset loffset = item.name for x in range(0, len(question_offset_grid)): if question_offset_grid[x] <= loffset: item.name = self.question_section[x].qname self.authority_section[i] = item offset += la - lb