예제 #1
0
  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
예제 #2
0
  def __init__(self, qname, qtype: int, qclass: int):
    """
    :param qname: question subject
    :param qtype: question type
    :param qclass: question class
    :return:
    """
    if isinstance(qname, str) and qtype == 1:
      qname = qname.split(".")

    self._qname = qname
    self._qtype = int(qtype)
    self._qclass = qclass
    self._qtype_str = QuestionTypes.get(qtype).qname
예제 #3
0
  def raw(self, offset):
    """
    :param offset: offset from begin of the message for the name label
    :return:
    """
    body = b""

    if offset < 1:
      offset = 0

    body += struct.pack(u16bit, 0b1100000000000000 + offset)  # 16 bytes record, type 11, start 2 bytes
    body += struct.pack(u16bit, self._type)
    body += struct.pack(u16bit, self._class)
    body += struct.pack(u32bit, self._ttl)
    ipdata, size = QuestionTypes.pack(self._rtype, self._data)

    if ipdata is None:
      return None

    body += struct.pack(u16bit, size)
    body += ipdata
    return body
예제 #4
0

def unpack_a_response(data: bytes) -> list:
  ret = [-1] * 4
  for i in range(0, 4):
    octet, data = bread(data, 1, data_fx=lambda x: int.from_bytes(x, byteorder="big"))
    ret[i] = octet

  return ret


def unpack_ptr_response(data: bytes) -> str:
  size = -1
  _str = []
  while size != 0:  # ToDo: add check if packet is malformed and no zero flag at the end
    size, data = bread(data, 1, data_fx=lambda x: int.from_bytes(x, byteorder="big"))
    if size != 0:
      lbl, data = bread(data, size)
      try:
        _str.append(lbl.decode(encoding="utf-8"))
      except UnicodeDecodeError:
        _str.append("<invalid format>")

  return ".".join(_str)


# register packer/unpacker
QuestionTypes.set_fx("A", pack_a_response, unpack_a_response)
QuestionTypes.set_fx("PTR", pack_ptr_response, unpack_ptr_response)
QuestionTypes.set_fx("NS", pack_ptr_response, unpack_ptr_response)