This function extracts the source/destination address of a 6LoWPAN
    from its upper Dot15d4Data (802.15.4 data) layer.

    params:
     - source: if True, the address is the source one. Otherwise, it is the
               destination.
    returns: the packed & processed address

def _extract_dot15d4address(pkt, source=True):
    """This function extracts the source/destination address of a 6LoWPAN
    from its upper Dot15d4Data (802.15.4 data) layer.

    params:
     - source: if True, the address is the source one. Otherwise, it is the
               destination.
    returns: the packed & processed address
    """
    underlayer = pkt.underlayer
    while underlayer is not None and not isinstance(underlayer, Dot15d4Data):  # noqa: E501
        underlayer = underlayer.underlayer
    if type(underlayer) == Dot15d4Data:
        addr = underlayer.src_addr if source else underlayer.dest_addr
        if underlayer.underlayer.fcf_destaddrmode == 3:
            tmp_ip = LINK_LOCAL_PREFIX[0:8] + struct.pack(">Q", addr)  # noqa: E501
            # Turn off the bit 7.
            tmp_ip = tmp_ip[0:8] + struct.pack("B", (orb(tmp_ip[8]) ^ 0x2)) + tmp_ip[9:16]  # noqa: E501
        elif underlayer.underlayer.fcf_destaddrmode == 2:
            tmp_ip = LINK_LOCAL_PREFIX[0:8] + \
                b"\x00\x00\x00\xff\xfe\x00" + \
                struct.pack(">Q", addr)[6:]
        return tmp_ip
    else:
        # Most of the times, it's necessary the IEEE 802.15.4 data to extract this address  # noqa: E501
        raise Exception('Unimplemented: IP Header is contained into IEEE 802.15.4 frame, in this case it\'s not available.')