Exemple #1
0
    def _read_mptcp_prio(self, bits, size, kind):
        """Read Change Subflow Priority option.

        Structure of ``MP_PRIO`` [RFC 6824]::

                                  1                   2                   3
              0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
            +---------------+---------------+-------+-----+-+--------------+
            |     Kind      |     Length    |Subtype|     |B| AddrID (opt) |
            +---------------+---------------+-------+-----+-+--------------+

        Arguments:
            bits (str): 4-bit data (after subtype)
            size (int): length of option
            kind (Literal[30]): option kind value (Multipath TCP)

        Returns:
            DataType_TCP_Opt_REMOVE_ADDR: extracted Change Subflow Priority (``MP_PRIO``) option

        """
        temp = self._read_unpack(1) if size else None

        data = dict(
            kind=kind,
            length=size + 1,
            subtype=MPTCPOption(4),
            prio=dict(
                backup=bool(int(bits[3])),
                addr_id=temp,
            ),
        )

        return data
Exemple #2
0
    def _read_mptcp_join(self, bits, size, kind):
        """Read Join Connection option.

        Arguments:
            bits (str): 4-bit data (after subtype)
            size (int): length of option
            kind (Literal[30]): option kind value (Multipath TCP)

        Returns:
            DataType_TCP_Opt_MP_JOIN: extracted Join Connection (``MP_JOIN``) option

        """
        if self._syn and self._ack:      # MP_JOIN-SYN/ACK
            return self._read_join_synack(bits, size, kind)
        if self._syn and not self._ack:  # MP_JOIN-SYN
            return self._read_join_syn(bits, size, kind)
        if not self._syn and self._ack:  # MP_JOIN-ACK
            return self._read_join_ack(bits, size, kind)

        temp = self._read_fileng(size)   # illegal MP_JOIN occurred
        data = dict(
            kind=kind,
            length=size + 1,
            subtype=MPTCPOption(1),
            connection=None,
            join=dict(
                data=bytes(chr(int(bits[:4], base=2)), encoding='utf-8') + temp,
            ),
        )
        return data
Exemple #3
0
    def _read_mptcp_remove(self, bits, size, kind):  # pylint: disable=unused-argument
        """Read Remove Address option.

        Structure of ``REMOVE_ADDR`` [:rfc:`6824`]::

                                 1                   2                   3
             0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
            +---------------+---------------+-------+-------+---------------+
            |     Kind      |  Length = 3+n |Subtype|(resvd)|   Address ID  | ...
            +---------------+---------------+-------+-------+---------------+
                                       (followed by n-1 Address IDs, if required)

        Arguments:
            bits (str): 4-bit data (after subtype)
            size (int): length of option
            kind (Literal[30]): option kind value (Multipath TCP)

        Returns:
            DataType_TCP_Opt_REMOVE_ADDR: extracted Remove Address (``REMOVE_ADDR``) option

        """
        adid = []
        for _ in size:
            adid.append(self._read_unpack(1))

        data = dict(
            kind=kind,
            length=size + 1,
            subtype=MPTCPOption(4),
            removeaddr=dict(
                addr_id=tuple(adid),
            ),
        )

        return data
Exemple #4
0
    def _read_mptcp_fastclose(self, bits, size, kind):  # pylint: disable=unused-argument
        """Read Fast Close option.

        Structure of ``MP_FASTCLOSE`` [RFC 6824]::

                                 1                   2                   3
             0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
            +---------------+---------------+-------+-----------------------+
            |     Kind      |    Length     |Subtype|      (reserved)       |
            +---------------+---------------+-------+-----------------------+
            |                      Option Receiver's Key                    |
            |                            (64 bits)                          |
            |                                                               |
            +---------------------------------------------------------------+

        Arguments:
            bits (str): 4-bit data (after subtype)
            size (int): length of option
            kind (Literal[30]): option kind value (Multipath TCP)

        Returns:
            DataType_TCP_Opt_MP_FAIL: extracted Fast Close (``MP_FASTCLOSE``) option

        """
        resv = self._read_fileng(1)  # pylint: disable=unused-variable
        rkey = self._read_fileng(8)

        data = dict(
            kind=kind,
            length=size + 1,
            subtype=MPTCPOption(7),
            fastclose=dict(rkey=rkey, ),
        )

        return data
Exemple #5
0
    def _read_mptcp_fail(self, bits, size, kind):  # pylint: disable=unused-argument
        """Read Fallback option.

        Structure of ``MP_FAIL`` [:rfc:`6824`]::

                                 1                   2                   3
             0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
            +---------------+---------------+-------+----------------------+
            |     Kind      |   Length=12   |Subtype|      (reserved)      |
            +---------------+---------------+-------+----------------------+
            |                                                              |
            |                 Data Sequence Number (8 octets)              |
            |                                                              |
            +--------------------------------------------------------------+

        Arguments:
            bits (str): 4-bit data (after subtype)
            size (int): length of option
            kind (Literal[30]): option kind value (Multipath TCP)

        Returns:
            DataType_TCP_Opt_MP_FAIL: extracted Fallback (``MP_FAIL``) option

        """
        resv = self._read_fileng(1)  # pylint: disable=unused-variable
        dsn_ = self._read_unpack(8)

        data = dict(
            kind=kind,
            length=size + 1,
            subtype=MPTCPOption(6),
            fail=dict(dsn=dsn_, ),
        )

        return data
Exemple #6
0
    def _read_mptcp_add(self, bits, size, kind):
        """Read Add Address option.

        Structure of ``ADD_ADDR`` [:rfc:`6824`]::

                                 1                   2                   3
             0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
            +---------------+---------------+-------+-------+---------------+
            |     Kind      |     Length    |Subtype| IPVer |  Address ID   |
            +---------------+---------------+-------+-------+---------------+
            |          Address (IPv4 - 4 octets / IPv6 - 16 octets)         |
            +-------------------------------+-------------------------------+
            |   Port (2 octets, optional)   |
            +-------------------------------+

        Arguments:
            bits (str): 4-bit data (after subtype)
            size (int): length of option
            kind (Literal[30]): option kind value (Multipath TCP)

        Returns:
            DataType_TCP_Opt_ADD_ADDR: extracted Add Address (``ADD_ADDR``) option

        Raises:
            ProtocolError: If the option is malformed.

        """
        vers = int(bits, base=2)
        if vers == 4:
            ip_l = 4
        elif vers == 6:
            ip_l = 16
        else:
            raise ProtocolError('[MP_TCP ADD_ADDR] malformed option')

        adid = self._read_unpack(1)
        ipad = self._read_fileng(ip_l)
        pt_l = size - 1 - ip_l
        port = self._read_unpack(2) if pt_l else None

        data = dict(
            kind=kind,
            length=size + 1,
            subtype=MPTCPOption(3),
            add_addr=dict(
                ip_ver=vers,
                addrid=adid,
                addr=ipaddress.ip_address(ipad),
                port=port,
            ),
        )

        return data
Exemple #7
0
    def _read_mptcp_capable(self, bits, size, kind):
        """Read Multipath Capable option.

        Structure of ``MP_CAPABLE`` [:rfc:`6824`]::

                                 1                   2                   3
             0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
            +---------------+---------------+-------+-------+---------------+
            |     Kind      |    Length     |Subtype|Version|A|B|C|D|E|F|G|H|
            +---------------+---------------+-------+-------+---------------+
            |                   Option Sender's Key (64 bits)               |
            |                                                               |
            |                                                               |
            +---------------------------------------------------------------+
            |                  Option Receiver's Key (64 bits)              |
            |                     (if option Length == 20)                  |
            |                                                               |
            +---------------------------------------------------------------+

        Arguments:
            bits (str): 4-bit data (after subtype)
            size (int): length of option
            kind (Literal[30]): option kind value (Multipath TCP)

        Returns:
            DataType_TCP_Opt_MP_CAPABLE: extracted Multipath Capable (``MP_CAPABLE``) option

        """
        vers = int(bits, base=2)
        bins = self._read_binary(1)
        skey = self._read_unpack(8)
        rkey = self._read_unpack(8) if size == 17 else None

        data = dict(
            kind=kind,
            length=size + 1,
            subtype=MPTCPOption(0),
            capable=dict(
                version=vers,
                flags=dict(
                    req=bool(int(bins[0])),
                    ext=bool(int(bins[1])),
                    res=tuple(bool(int(bit)) for bit in bits[2:7]),
                    hsa=bool(int(bins[7])),
                ),
                skey=skey,
                rkey=rkey,
            ),
        )

        return data
Exemple #8
0
    def _read_join_synack(self, bits, size, kind):
        """Read Join Connection option for Responding SYN/ACK.

        Structure of ``MP_JOIN-SYN/ACK`` [:rfc:`6824`]::

                                 1                   2                   3
             0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
            +---------------+---------------+-------+-----+-+---------------+
            |     Kind      |  Length = 16  |Subtype|     |B|   Address ID  |
            +---------------+---------------+-------+-----+-+---------------+
            |                                                               |
            |                Sender's Truncated HMAC (64 bits)              |
            |                                                               |
            +---------------------------------------------------------------+
            |                Sender's Random Number (32 bits)               |
            +---------------------------------------------------------------+

        Arguments:
            bits (str): 4-bit data (after subtype)
            size (int): length of option
            kind (Literal[30]): option kind value (Multipath TCP)

        Returns:
            DataType_TCP_Opt_MP_JOIN_SYNACK: extracted Join Connection (``MP_JOIN-SYN/ACK``)
            option for Responding SYN/ACK

        """
        adid = self._read_unpack(1)
        hmac = self._read_fileng(8)
        srno = self._read_unpack(4)

        data = dict(
            kind=kind,
            length=size + 1,
            subtype=MPTCPOption(1),
            connection='SYN/ACK',
            join=dict(
                synack=dict(
                    backup=bool(int(bits[3])),
                    addr_id=adid,
                    hmac=hmac,
                    rand_num=srno,
                ),
            ),
        )

        return data
Exemple #9
0
    def _read_join_syn(self, bits, size, kind):
        """Read Join Connection option for Initial SYN.

        Structure of ``MP_JOIN-SYN`` [:rfc:`6824`]::

                                 1                   2                   3
             0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
            +---------------+---------------+-------+-----+-+---------------+
            |     Kind      |  Length = 12  |Subtype|     |B|   Address ID  |
            +---------------+---------------+-------+-----+-+---------------+
            |                   Receiver's Token (32 bits)                  |
            +---------------------------------------------------------------+
            |                Sender's Random Number (32 bits)               |
            +---------------------------------------------------------------+

        Arguments:
            bits (str): 4-bit data (after subtype)
            size (int): length of option
            kind (Literal[30]): option kind value (Multipath TCP)

        Returns:
            DataType_TCP_Opt_MP_JOIN_SYN: extracted Join Connection (``MP_JOIN-SYN``) option for Initial SYN

        """
        adid = self._read_unpack(1)
        rtkn = self._read_unpack(4)
        srno = self._read_unpack(4)

        data = dict(
            kind=kind,
            length=size + 1,
            subtype=MPTCPOption(1),
            connection='SYN',
            join=dict(
                syn=dict(
                    backup=bool(int(bits[3])),
                    addr_id=adid,
                    token=rtkn,
                    rand_num=srno,
                ),
            ),
        )

        return data
Exemple #10
0
    def _read_join_ack(self, bits, size, kind):  # pylint: disable=unused-argument
        """Read Join Connection option for Third ACK.

        Structure of ``MP_JOIN-ACK`` [:rfc:`6824`]::

                                 1                   2                   3
             0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
            +---------------+---------------+-------+-----------------------+
            |     Kind      |  Length = 24  |Subtype|      (reserved)       |
            +---------------+---------------+-------+-----------------------+
            |                                                               |
            |                                                               |
            |                   Sender's HMAC (160 bits)                    |
            |                                                               |
            |                                                               |
            +---------------------------------------------------------------+

        Arguments:
            bits (str): 4-bit data (after subtype)
            size (int): length of option
            kind (Literal[30]): option kind value (Multipath TCP)

        Returns:
            DataType_TCP_Opt_MP_JOIN_ACK: extracted Join Connection (``MP_JOIN-ACK``)
            option for Third ACK

        """
        temp = self._read_fileng(20)

        data = dict(
            kind=kind,
            length=size + 1,
            subtype=MPTCPOption(1),
            connection='ACK',
            join=dict(
                ack=dict(
                    hmac=temp,
                ),
            ),
        )

        return data
Exemple #11
0
    def _read_mode_mptcp(self, size, kind):
        """Read Multipath TCP option.

        Structure of ``MP-TCP`` [:rfc:`6824`]::

                                 1                   2                   3
             0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
            +---------------+---------------+-------+-----------------------+
            |     Kind      |    Length     |Subtype|                       |
            +---------------+---------------+-------+                       |
            |                     Subtype-specific data                     |
            |                       (variable length)                       |
            +---------------------------------------------------------------+

        Arguments:
            size (int): length of option
            kind (Literal[30]): option kind value (Multipath TCP)

        Returns:
            DataType_TCP_Opt_MPTCP: extracted Multipath TCP (``MP-TCP``) option

        """
        bins = self._read_binary(1)
        subt = int(bins[:4], base=2)  # subtype number
        bits = bins[4:]  # 4-bit data
        dlen = size - 1  # length of remaining data

        # fetch subtype-specific data
        func = mptcp_opt.get(subt)
        if func is None:  # if subtype not exist, directly read all data
            temp = self._read_fileng(dlen)
            data = dict(
                kind=kind,
                length=size,
                subtype=MPTCPOption.get(subt),
                data=bytes(chr(int(bits[:4], base=2)), encoding='utf-8') +
                temp,
            )
        else:  # fetch corresponding subtype data dict
            data = func(self, bits, dlen, kind)
        return data
Exemple #12
0
    def _read_mptcp_dss(self, bits, size, kind):
        """Read Data Sequence Signal (Data ACK and Data Sequence Mapping) option.

        Structure of ``DSS`` [:rfc:`6824`]::

                                 1                   2                   3
             0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
            +---------------+---------------+-------+----------------------+
            |     Kind      |    Length     |Subtype| (reserved) |F|m|M|a|A|
            +---------------+---------------+-------+----------------------+
            |                                                              |
            |           Data ACK (4 or 8 octets, depending on flags)       |
            |                                                              |
            +--------------------------------------------------------------+
            |                                                              |
            |   Data sequence number (4 or 8 octets, depending on flags)   |
            |                                                              |
            +--------------------------------------------------------------+
            |              Subflow Sequence Number (4 octets)              |
            +-------------------------------+------------------------------+
            |  Data-Level Length (2 octets) |      Checksum (2 octets)     |
            +-------------------------------+------------------------------+

        Arguments:
            bits (str): 4-bit data (after subtype)
            size (int): length of option
            kind (Literal[30]): option kind value (Multipath TCP)

        Returns:
            DataType_TCP_Opt_DSS: extracted Data Sequence Signal (``DSS``) option

        """
        bits = self._read_binary(1)
        mflg = 8 if int(bits[4]) else 4
        Mflg = bool(int(bits[5]))
        aflg = 8 if int(bits[6]) else 4
        Aflg = bool(int(bits[7]))
        ack_ = self._read_unpack(aflg) if Aflg else None
        dsn_ = self._read_unpack(mflg) if Mflg else None
        ssn_ = self._read_unpack(4) if Mflg else None
        dll_ = self._read_unpack(2) if Mflg else None
        chk_ = self._read_fileng(2) if Mflg else None

        data = dict(
            kind=kind,
            length=size + 1,
            subtype=MPTCPOption(2),
            dss=dict(
                flags=dict(
                    fin=bool(int(bits[3])),
                    dsn_len=mflg,
                    data_pre=Mflg,
                    ack_len=aflg,
                    ack_pre=Aflg,
                ),
                ack=ack_,
                dsn=dsn_,
                ssn=ssn_,
                dl_len=dll_,
                checksum=chk_,
            ),
        )

        return data