Пример #1
0
    def _read_mode_ts(self, size, kind):
        """Read Time Stamp option.

        Structure of Timestamp (TS) option [:rfc:`791`]::

            +--------+--------+--------+--------+
            |01000100| length | pointer|oflw|flg|
            +--------+--------+--------+--------+
            |         internet address          |
            +--------+--------+--------+--------+
            |             timestamp             |
            +--------+--------+--------+--------+
            |                 .                 |
                              .
                              .

        Arguments:
            size (int): length of option
            kind (Literal[68]): option kind value (TS)

        Returns:
            DataType_Opt_TimeStamp: extracted Time Stamp option

        Raises:
            ProtocolError: If the option is malformed.

        """
        if size > 40 or size < 4:
            raise ProtocolError(f'{self.alias}: [OptNo {kind}] invalid format')

        _tptr = self._read_unpack(1)
        _oflg = self._read_binary(1)
        _oflw = int(_oflg[:4], base=2)
        _flag = int(_oflg[4:], base=2)

        if _tptr < 5:
            raise ProtocolError(f'{self.alias}: [OptNo {kind}] invalid format')

        data = dict(
            kind=kind,
            type=self._read_opt_type(kind),
            length=size,
            pointer=_tptr,
            overflow=_oflw,
            flag=_flag,
        )

        endpoint = min(_tptr, size)
        if _flag == 0:
            if (size - 4) % 4 != 0:
                raise ProtocolError(
                    f'{self.alias}: [OptNo {kind}] invalid format')
            counter = 5
            timestamp = list()
            while counter < endpoint:
                counter += 4
                time = self._read_unpack(4, lilendian=True)
                timestamp.append(datetime.datetime.fromtimestamp(time))
            data['timestamp'] = timestamp or None
        elif _flag in (1, 3):
            if (size - 4) % 8 != 0:
                raise ProtocolError(
                    f'{self.alias}: [OptNo {kind}] invalid format')
            counter = 5
            ipaddress = list()  # pylint: disable=redefined-outer-name
            timestamp = list()
            while counter < endpoint:
                counter += 8
                ipaddress.append(self._read_ipv4_addr())
                time = self._read_unpack(4, lilendian=True)
                timestamp.append(datetime.datetime.fromtimestamp(time))
            data['ip'] = tuple(ipaddress) or None
            data['timestamp'] = tuple(timestamp) or None
        else:
            data['data'] = self._read_fileng(size - 4) or None

        return data
Пример #2
0
    def _read_mode_ts(self, size, kind):
        """Read Time Stamp option.

        Positional arguments:
            * size - int, length of option
            * kind - int, 68 (TS)

        Returns:
            * dict -- extracted Time Stamp (TS) option

        Structure of Timestamp (TS) option [RFC 791]:
            +--------+--------+--------+--------+
            |01000100| length | pointer|oflw|flg|
            +--------+--------+--------+--------+
            |         internet address          |
            +--------+--------+--------+--------+
            |             timestamp             |
            +--------+--------+--------+--------+
            |                 .                 |
                              .
                              .

            Octets      Bits        Name                    Description
              0           0     ip.ts.kind              Kind (25)
              0           0     ip.ts.type.copy         Copied Flag (0)
              0           1     ip.ts.type.class        Option Class (0)
              0           3     ip.ts.type.number       Option Number (25)
              1           8     ip.ts.length            Length (≤40)
              2          16     ip.ts.pointer           Pointer (≥5)
              3          24     ip.ts.overflow          Overflow Octets
              3          28     ip.ts.flag              Flag
              4          32     ip.ts.ip                Internet Address
              8          64     ip.ts.timestamp         Timestamp

        """
        if size > 40 or size < 4:
            raise ProtocolError(f'{self.alias}: [Optno {kind}] invalid format')

        _tptr = self._read_unpack(1)
        _oflg = self._read_binary(1)
        _oflw = int(_oflg[:4], base=2)
        _flag = int(_oflg[4:], base=2)

        if _tptr < 5:
            raise ProtocolError(f'{self.alias}: [Optno {kind}] invalid format')

        data = dict(
            kind=kind,
            type=self._read_opt_type(kind),
            length=size,
            pointer=_tptr,
            overflow=_oflw,
            flag=_flag,
        )

        endpoint = min(_tptr, size)
        if _flag == 0:
            if (size - 4) % 4 != 0:
                raise ProtocolError(
                    f'{self.alias}: [Optno {kind}] invalid format')
            counter = 5
            timestamp = list()
            while counter < endpoint:
                counter += 4
                time = self._read_unpack(4, lilendian=True)
                timestamp.append(datetime.datetime.fromtimestamp(time))
            data['timestamp'] = timestamp or None
        elif _flag == 1 or _flag == 3:
            if (size - 4) % 8 != 0:
                raise ProtocolError(
                    f'{self.alias}: [Optno {kind}] invalid format')
            counter = 5
            ipaddress = list()
            timestamp = list()
            while counter < endpoint:
                counter += 8
                ipaddress.append(self._read_ipv4_addr())
                time = self._read_unpack(4, lilendian=True)
                timestamp.append(datetime.datetime.fromtimestamp(time))
            data['ip'] = ipaddress or None
            data['timestamp'] = timestamp or None
        else:
            data['data'] = self._read_fileng(size - 4) or None

        return data