示例#1
0
VOID
StSendDatagramCompletion(
    IN PTP_ADDRESS Address,
    IN PNDIS_PACKET NdisPacket,
    IN NDIS_STATUS NdisStatus
    )

/*++

Routine Description:

    This routine is called as an I/O completion handler at the time a
    StSendUIMdlFrame send request is completed.  Because this handler is only
    associated with StSendUIMdlFrame, and because StSendUIMdlFrame is only
    used with datagrams and broadcast datagrams, we know that the I/O being
    completed is a datagram.  Here we complete the in-progress datagram, and
    start-up the next one if there is one.

Arguments:

    Address - Pointer to a transport address on which the datagram
        is queued.

    NdisPacket - pointer to the NDIS packet describing this request.

Return Value:

    none.

--*/

{
    PTP_REQUEST Request;
    PLIST_ENTRY p;
    KIRQL oldirql;
    PNDIS_BUFFER HeaderBuffer;

    UNREFERENCED_PARAMETER(NdisPacket);

    StReferenceAddress ("Complete datagram", Address);

    //
    // Dequeue the current request and return it to the client.  Release
    // our hold on the send datagram queue.
    //
    // *** There may be no current request, if the one that was queued
    //     was aborted or timed out.
    //

    ACQUIRE_SPIN_LOCK (&Address->SpinLock, &oldirql);
    p = RemoveHeadList (&Address->SendDatagramQueue);

    if (p != &Address->SendDatagramQueue) {

        RELEASE_SPIN_LOCK (&Address->SpinLock, oldirql);

        Request = CONTAINING_RECORD (p, TP_REQUEST, Linkage);

        //
        // Strip off and unmap the buffers describing data and header.
        //

        NdisUnchainBufferAtFront (Address->Packet->NdisPacket, &HeaderBuffer);

        // drop the rest of the packet

        NdisReinitializePacket (Address->Packet->NdisPacket);

        NDIS_BUFFER_LINKAGE(HeaderBuffer) = (PNDIS_BUFFER)NULL;
        NdisChainBufferAtFront (Address->Packet->NdisPacket, HeaderBuffer);

        //
        // Ignore NdisStatus; datagrams always "succeed".
        //

        StCompleteRequest (Request, STATUS_SUCCESS, Request->Buffer2Length);

        ACQUIRE_SPIN_LOCK (&Address->SpinLock, &oldirql);
        Address->Flags &= ~ADDRESS_FLAGS_SEND_IN_PROGRESS;
        RELEASE_SPIN_LOCK (&Address->SpinLock, oldirql);

        //
        // Send more datagrams on the Address if possible.
        //

        StSendDatagramsOnAddress (Address);       // do more datagrams.

    } else {

        Address->Flags &= ~ADDRESS_FLAGS_SEND_IN_PROGRESS;
        RELEASE_SPIN_LOCK (&Address->SpinLock, oldirql);

    }

    StDereferenceAddress ("Complete datagram", Address);

} /* StSendDatagramCompletion */
示例#2
0
NTSTATUS
StIndicateDatagram(
    IN PDEVICE_CONTEXT DeviceContext,
    IN PTP_ADDRESS Address,
    IN PUCHAR Header,
    IN ULONG Length
)

/*++

Routine Description:

    This routine processes an incoming DATAGRAM or DATAGRAM_BROADCAST frame.
    BROADCAST and normal datagrams have the same receive logic, except
    for broadcast datagrams Address will be the broadcast address.

    When we return STATUS_MORE_PROCESSING_REQUIRED, the caller of
    this routine will continue to call us for each address for the device
    context.  When we return STATUS_SUCCESS, the caller will switch to the
    next address.  When we return any other status code, including
    STATUS_ABANDONED, the caller will stop distributing the frame.

Arguments:

    DeviceContext - Pointer to our device context.

    Address - Pointer to the transport address object.

    StHeader - Pointer to a buffer that contains the receive datagram.
        The first byte of information is the ST header.

    Length - The length of the MDL pointed to by StHeader.

Return Value:

    NTSTATUS - status of operation.

--*/

{
    NTSTATUS status;
    PLIST_ENTRY p, q;
    PIRP irp;
    PIO_STACK_LOCATION irpSp;
    PTP_REQUEST Request;
    ULONG IndicateBytesCopied, MdlBytesCopied;
    KIRQL oldirql;
    TA_NETBIOS_ADDRESS SourceName;
    TA_NETBIOS_ADDRESS DestinationName;
    PTDI_CONNECTION_INFORMATION remoteInformation;
    ULONG returnLength;
    PTP_ADDRESS_FILE addressFile, prevaddressFile;
    PST_HEADER StHeader;

    //
    // If this datagram wasn't big enough for a transport header, then don't
    // let the caller look at any data.
    //

    if (Length < sizeof(ST_HEADER)) {
        return STATUS_ABANDONED;
    }

    //
    // Update our statistics.
    //

    ++DeviceContext->DatagramsReceived;
    ADD_TO_LARGE_INTEGER(
        &DeviceContext->DatagramBytesReceived,
        Length - sizeof(ST_HEADER));


    //
    // Call the client's ReceiveDatagram indication handler.  He may
    // want to accept the datagram that way.
    //

    StHeader = (PST_HEADER)Header;

    TdiBuildNetbiosAddress (StHeader->Source, FALSE, &SourceName);
    TdiBuildNetbiosAddress (StHeader->Destination, FALSE, &DestinationName);


    ACQUIRE_SPIN_LOCK (&Address->SpinLock, &oldirql);

    //
    // Find the first open address file in the list.
    //

    p = Address->AddressFileDatabase.Flink;
    while (p != &Address->AddressFileDatabase) {
        addressFile = CONTAINING_RECORD (p, TP_ADDRESS_FILE, Linkage);
        if (addressFile->State != ADDRESSFILE_STATE_OPEN) {
            p = p->Flink;
            continue;
        }
        StReferenceAddressFile(addressFile);
        break;
    }

    while (p != &Address->AddressFileDatabase) {

        //
        // do we have a datagram receive request outstanding? If so, we will
        // satisfy it first.
        //
        // NOTE: We should check if this receive dataframs is for
        // a specific address.
        //

        q = RemoveHeadList (&addressFile->ReceiveDatagramQueue);
        RELEASE_SPIN_LOCK (&Address->SpinLock, oldirql);

        if (q != &addressFile->ReceiveDatagramQueue) {

            Request = CONTAINING_RECORD (q, TP_REQUEST, Linkage);

            //
            // Copy the actual user data.
            //

            MdlBytesCopied = 0;

            status = TdiCopyBufferToMdl (
                         StHeader,
                         sizeof(ST_HEADER),           // offset
                         Length - sizeof(ST_HEADER),  // length
                         Request->IoRequestPacket->MdlAddress,
                         0,
                         &MdlBytesCopied);

            irpSp = IoGetCurrentIrpStackLocation (Request->IoRequestPacket);
            remoteInformation =
                ((PTDI_REQUEST_KERNEL_RECEIVEDG)(&irpSp->Parameters))->
                ReturnDatagramInformation;
            if (remoteInformation != NULL) {
                try {
                    if (remoteInformation->RemoteAddressLength != 0) {
                        if (remoteInformation->RemoteAddressLength >=
                                sizeof (TA_NETBIOS_ADDRESS)) {

                            RtlCopyMemory (
                                (PTA_NETBIOS_ADDRESS)remoteInformation->RemoteAddress,
                                &SourceName,
                                sizeof (TA_NETBIOS_ADDRESS));

                            returnLength = sizeof(TA_NETBIOS_ADDRESS);
                            remoteInformation->RemoteAddressLength = returnLength;

                        } else {

                            RtlCopyMemory (
                                (PTA_NETBIOS_ADDRESS)remoteInformation->RemoteAddress,
                                &SourceName,
                                remoteInformation->RemoteAddressLength);

                            returnLength = remoteInformation->RemoteAddressLength;
                            remoteInformation->RemoteAddressLength = returnLength;

                        }

                    } else {

                        returnLength = 0;
                    }

                    status = STATUS_SUCCESS;

                }
                except (EXCEPTION_EXECUTE_HANDLER) {

                    returnLength = 0;
                    status = GetExceptionCode ();

                }

            }

            StCompleteRequest (Request, STATUS_SUCCESS, MdlBytesCopied);

        } else {

            //
            // no receive datagram requests; is there a kernel client?
            //

            if (addressFile->RegisteredReceiveDatagramHandler) {