Exemplo n.º 1
0
def write_empty_tunnel_packet(s: socket.socket, send_lock: threading.Lock, seq: int, mtu: int):
    m = emptym
    mlen = mtu

    put32(m.start, seq)
    seq += 1

    with send_lock:
        n = s.sendmsg([m.start[:mlen]])
    if n != mlen:
        logger.error("write: bad empty write %d of %d on TFS link", n, mlen)
    # elif TRACE:
    #     logger.debug("write: %d bytes (%s) on TFS Link", n, binascii.hexlify(m.start[:8]))

    return None, seq
Exemplo n.º 2
0
def sendmsg(
    socket: Socket,
    data: bytes,
    ancillary: List[Tuple[int, int, bytes]] = [],
    flags: int = 0,
) -> int:
    """
    Send a message on a socket.

    @param socket: The socket to send the message on.
    @param data: Bytes to write to the socket.
    @param ancillary: Extra data to send over the socket outside of the normal
        datagram or stream mechanism.  By default no ancillary data is sent.
    @param flags: Flags to affect how the message is sent.  See the C{MSG_}
        constants in the sendmsg(2) manual page.  By default no flags are set.

    @return: The return value of the underlying syscall, if it succeeds.
    """
    return socket.sendmsg([data], ancillary, flags)
Exemplo n.º 3
0
def send_ack_infos(s: socket.socket, send_lock: threading.Lock, rate: float, outq: MQueue):
    m = MBuf(MAXBUF, HDRSPACE)
    start = m.start[4:]

    periodic = Periodic(rate)
    # No sequence number
    put32(m.start, 0xFFFFFFFF)

    time.sleep(3)

    m.end = m.start[24:]
    while periodic.wait():
        # cv.acquire()
        # cv.wait()
        # cv.release()

        with outq.lock:
            # If we haven't seen any sequence (since last reset):
            if outq.startseq == 0:
                continue
            dropcnt = outq.dropcnt
            outq.dropcnt = 0
            ackstart = outq.startseq
            outq.startseq = 0
            ackend = outq.lastseq

        if dropcnt > 0xFFFFFF:
            dropcnt = 0xFFFFFF
        ns = monotonic_ns()

        # We use the 2nd bit to indicate this is an ACK this normally goes in IKEv2
        put32(start, (0x40000000 | dropcnt))
        put32(start[4:], (ns >> 32) & 0xFFFFFFFF)
        put32(start[8:], (ns & 0xFFFFFFFF))
        put32(start[12:], ackstart)
        put32(start[16:], ackend)

        with send_lock:
            n = s.sendmsg([m.start[:24]])
        if n != 24:
            logger.error("write: bad ack write %d of %d on TFS link", n, 24)
        if DEBUG:
            logger.debug("write ack: %d bytes (%s) on TFS Link", n, binascii.hexlify(m.start[4:24]))
Exemplo n.º 4
0
def write_tfs_packet(  # pylint: disable=R0912,R0913,R0914,R0915
        s: socket.socket, send_lock: threading.Lock, seq: int, mtu: int, leftover: MBuf,
        inq: MQueue, freeq: MQueue):

    # if TRACE:
    #     logger.debug("write_tfs_packet seq: %d, mtu %d", seq, mtu)

    mtuenter = mtu
    iov = []
    freem = []

    if leftover:
        if DEBUG:
            logger.debug("write_tfs_packet seq: %d, mtu %d leftover %d", seq, mtu, id(leftover))
        # This is an mbuf we didn't finish sending last time.
        m = leftover
        leftover = None
        # Set the offset to after this mbuf data.
        offset = m.len()
    else:
        # Try and get a new mbuf to embed
        m = inq.trypop()
        offset = 0
        if (DEBUG and m):  # or TRACE:
            logger.debug("write_tfs_packet: seq: %d, mtu %d m %d", seq, mtu, id(m))

    if not m:
        return write_empty_tunnel_packet(s, send_lock, seq, mtu)

    # Prepend our framing to first mbuf.
    # Would be nice but is broken. put back when we fix mbuf
    # m.prepend(8)

    assert (mtu <= mtuenter)

    # XXX create first IOV of header
    hdr = memoryview(bytearray(8))
    iov.append(hdr)
    mtu -= len(hdr)
    assert (mtu <= mtuenter)

    put32(hdr, seq)
    put16(hdr[4:], 0)
    put16(hdr[6:], offset)

    while mtu > 0:
        # We need a minimum of 6 bytes to include IPv6 length field.
        if mtu <= 6 or m is None:
            if DEBUG:
                logger.debug("write_tfs_packet: seq %d mtu %d < 6 ", seq, mtu)
            iov.append(PADBYTES[8:8 + mtu])
            assert (mtu <= mtuenter)
            mtu = 0
            break

        mlen = m.len()
        assert mlen >= 0

        if mlen > mtu:
            # Room for partial MBUF
            iov.append(m.start[:mtu])
            m.start = m.start[mtu:]
            leftover = m
            if DEBUG:
                logger.debug(
                    "write_tfs_packet: seq %d Add partial(1) MBUF mtu %d of mlen %d mtuenter %d",
                    seq, mtu, mlen, mtuenter)
            mtu = 0
            break

        # Room for full MBUF
        iov.append(m.start[:mlen])
        freem.append(m)
        m = None
        if DEBUG:
            logger.debug("write_tfs_packet: seq %d Add initial MBUF mlen %d of mtu %d mtuenter %d",
                         seq, mlen, mtu, mtuenter)
        mtu -= mlen
        if mtu > 6:
            m = inq.trypop()

    iovl = iovlen(iov)
    if iovl != mtuenter:
        logger.error("write: bad length %d of mtu %d on TFS link", iovl, mtuenter)

    with send_lock:
        n = s.sendmsg(iov)
    seq += 1  # Update sequence number now that we've written it out.

    if n != iovl:
        logger.error("write: bad write %d of %d on TFS link", n, mlen)
        if leftover:
            freem.append(leftover)
            leftover = None
    elif DEBUG:
        logger.debug("write: wrote %d bytes on TFS Link", n)

    # Free any MBufs we are done with.
    for m in freem:
        freeq.push(m, True)

    if leftover:
        assert (leftover.len() > 0)

    return leftover, seq
Exemplo n.º 5
0
 def _send_listening_fd(self, target_sock: socket.socket):
     msgs = (b'a', )
     cmsgs = ((socket.SOL_SOCKET, socket.SCM_RIGHTS,
               bytes(array.array("i", (self._socket.fileno(), )))), )
     target_sock.sendmsg(msgs, cmsgs)