예제 #1
0
NTSTATUS
StSendConnect(
    IN PTP_CONNECTION Connection
    )

/*++

Routine Description:

    This routine sends a CONNECT frame of the appropriate type given the
    state of the specified connection.

Arguments:

    Connection - Pointer to a transport connection object.

Return Value:

    none.

--*/

{
    NTSTATUS Status;
    PDEVICE_CONTEXT DeviceContext;
    PUCHAR SourceRouting;
    UINT SourceRoutingLength;
    UINT HeaderLength;
    PSEND_PACKET_TAG SendTag;
    PTP_PACKET Packet;
    PST_HEADER StHeader;


    DeviceContext = Connection->Provider;

    //
    // Allocate a packet from the pool.
    //

    Status = StCreatePacket (DeviceContext, &Packet);
    if (!NT_SUCCESS (Status)) {                    // couldn't make frame.
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    SendTag = (PSEND_PACKET_TAG)(Packet->NdisPacket->ProtocolReserved);
    SendTag->Type = TYPE_C_FRAME;
    SendTag->Packet = Packet;
    SendTag->Owner = (PVOID)Connection;

    //
    // Build the MAC header.
    //

    //
    // CONNECT frames go out as
    // single-route source routing.
    //

    MacReturnSingleRouteSR(
        &DeviceContext->MacInfo,
        &SourceRouting,
        &SourceRoutingLength);

    MacConstructHeader (
        &DeviceContext->MacInfo,
        Packet->Header,
        DeviceContext->MulticastAddress.Address,
        DeviceContext->LocalAddress.Address,
        sizeof(ST_HEADER),
        SourceRouting,
        SourceRoutingLength,
        &HeaderLength);


    //
    // Build the header: 'C', dest, source
    //

    StHeader = (PST_HEADER)(&Packet->Header[HeaderLength]);

    StHeader->Signature = ST_SIGNATURE;
    StHeader->Command = ST_CMD_CONNECT;
    StHeader->Flags = 0;

    RtlCopyMemory (StHeader->Destination, Connection->CalledAddress.NetbiosName, 16);
    RtlCopyMemory (StHeader->Source, Connection->AddressFile->Address->NetworkName->NetbiosName, 16);

    HeaderLength += sizeof(ST_HEADER);

    //
    // Modify the packet length and send the it.
    //

    StSetNdisPacketLength(Packet->NdisPacket, HeaderLength);

    StNdisSend (Packet);

    return STATUS_SUCCESS;
} /* StSendConnect */
예제 #2
0
VOID
NbfTdiRequestTimeoutHandler(
    IN PKDPC Dpc,
    IN PVOID DeferredContext,
    IN PVOID SystemArgument1,
    IN PVOID SystemArgument2
    )

/*++

Routine Description:

    This routine is executed as a DPC at DISPATCH_LEVEL when a request
    such as TdiSend, TdiReceive, TdiSendDatagram, TdiReceiveDatagram, etc.,
    encounters a timeout.  This routine cleans up the activity and cancels it.

Arguments:

    Dpc - Pointer to a system DPC object.

    DeferredContext - Pointer to the TP_REQUEST block representing the
        request that has timed out.

    SystemArgument1 - Not used.

    SystemArgument2 - Not used.

Return Value:

    none.

--*/

{
    KIRQL oldirql;
    PTP_REQUEST Request;
    PTP_CONNECTION Connection;
#if DBG
    LARGE_INTEGER time, difference;
#endif
    PIO_STACK_LOCATION IrpSp;
    PTDI_REQUEST_KERNEL_QUERY_INFORMATION query;
    PDEVICE_CONTEXT DeviceContext;

    Dpc, SystemArgument1, SystemArgument2; // prevent compiler warnings

    ENTER_NBF;

    Request = (PTP_REQUEST)DeferredContext;

    IF_NBFDBG (NBF_DEBUG_REQUEST) {
        NbfPrint1 ("RequestTimeoutHandler:  Entered, Request %lx\n", Request);
    }

    ACQUIRE_SPIN_LOCK (&Request->SpinLock, &oldirql);
    Request->Flags &= ~REQUEST_FLAGS_TIMER;
    if ((Request->Flags & REQUEST_FLAGS_STOPPING) == 0) {

#if DBG
        KeQuerySystemTime (&time);
        difference.QuadPart = time.QuadPart - (Request->Time).QuadPart;
        NbfPrint1 ("RequestTimeoutHandler: Request timed out, queued for %ld seconds\n",
                difference.LowPart / SECONDS);
#endif

        //
        // find reason for timeout
        //

        IrpSp = IoGetCurrentIrpStackLocation (Request->IoRequestPacket);
        if (IrpSp->MajorFunction == IRP_MJ_INTERNAL_DEVICE_CONTROL) {
            switch (IrpSp->MinorFunction) {

                //
                // none of these should time out.
                //

            case TDI_SEND:
            case TDI_ACCEPT:
            case TDI_SET_INFORMATION:
            case TDI_SET_EVENT_HANDLER:
            case TDI_SEND_DATAGRAM:
            case TDI_RECEIVE_DATAGRAM:
            case TDI_RECEIVE:

#if DBG
                NbfPrint1 ("RequestTimeoutHandler: Request: %lx Timed out, and shouldn't have!\n",
                        Request);
#endif
                ASSERT (FALSE);
                RELEASE_SPIN_LOCK (&Request->SpinLock, oldirql);
                NbfCompleteRequest (Request, STATUS_IO_TIMEOUT, 0);
                break;


            case TDI_LISTEN:
            case TDI_CONNECT:

#if DBG
                NbfPrint2 ("RequestTimeoutHandler:  %s Failed, Request: %lx\n",
                            IrpSp->MinorFunction == TDI_LISTEN ?
                                "Listen" :
                                IrpSp->MinorFunction == TDI_CONNECT ?
                                    "Connect" : "Disconnect",
                            Request);
#endif
                Connection = (PTP_CONNECTION)(Request->Context);
                RELEASE_SPIN_LOCK (&Request->SpinLock, oldirql);

                //
                // Since these requests are part of the connection
                // itself, we just stop the connection and the
                // request will get torn down then. If we get the
                // situation where the request times out before
                // it is queued to the connection, then the code
                // that is about to queue it will check the STOPPING
                // flag and complete it then.
                //
                // Don't stop the connection if an automatic connection
                // is in progress.
                //

#ifdef RASAUTODIAL

#if DBG
                DbgPrint("RequestTimeoutHandler: AUTOCONNECTING=0x%x\n", Connection->Flags2 & CONNECTION_FLAGS2_AUTOCONNECTING);
#endif
                if (!(Connection->Flags2 & CONNECTION_FLAGS2_AUTOCONNECTING))
                    NbfStopConnection (Connection, STATUS_IO_TIMEOUT);
                break;

#endif

            case TDI_DISCONNECT:

                //
                // We don't create requests for TDI_DISCONNECT any more.
                //

                ASSERT(FALSE);
                break;

            case TDI_QUERY_INFORMATION:

                DeviceContext = (PDEVICE_CONTEXT)IrpSp->FileObject->DeviceObject;
                query = (PTDI_REQUEST_KERNEL_QUERY_INFORMATION)&IrpSp->Parameters;

                IF_NBFDBG (NBF_DEBUG_DEVCTX) {
                    NbfPrint1 ("RequestTimeout: %lx:\n", DeviceContext);
                }

                //
                // Determine if the request is done, or if we should
                // requeue it.
                //

                --Request->Retries;

                if (Request->Retries > 0) {

                    RELEASE_SPIN_LOCK (&Request->SpinLock, oldirql);

                    //
                    // Send another packet out, and restart the timer.
                    //

                    if (query->QueryType == TDI_QUERY_FIND_NAME) {

                        NbfSendQueryFindName (
                            DeviceContext,
                            Request);

                    } else if (query->QueryType == TDI_QUERY_ADAPTER_STATUS) {

                        PUCHAR SingleSR;
                        UINT SingleSRLength;

                        //
                        // Send the STATUS_QUERY frames out as
                        // single-route source routing.
                        //
                        // On a second status query this should
                        // really be sent directed, but currently we
                        // don't record the address anywhere.
                        //

                        MacReturnSingleRouteSR(
                            &DeviceContext->MacInfo,
                            &SingleSR,
                            &SingleSRLength);

                        NbfSendStatusQuery (
                            DeviceContext,
                            Request,
                            &DeviceContext->NetBIOSAddress,
                            SingleSR,
                            SingleSRLength);

                    } else {

                        ASSERT (FALSE);

                    }

                } else {

                    RELEASE_SPIN_LOCK (&Request->SpinLock, oldirql);

                    //
                    // That's it, we retried enough, complete it.
                    //

                    ACQUIRE_SPIN_LOCK (&DeviceContext->SpinLock,&oldirql);
                    RemoveEntryList (&Request->Linkage);
                    RELEASE_SPIN_LOCK (&DeviceContext->SpinLock, oldirql);

                    if (Request->BytesWritten > 0) {

                        NbfCompleteRequest (Request, STATUS_SUCCESS, Request->BytesWritten);

                    } else {

                        NbfCompleteRequest (Request, STATUS_IO_TIMEOUT, Request->BytesWritten);

                    }


                }

                break;

            default:
#if DBG
                NbfPrint2 ("RequestTimeoutHandler:  Unknown Request Timed out, Request: %lx Type: %x\n",
                            Request, IrpSp->MinorFunction);
#endif
                RELEASE_SPIN_LOCK (&Request->SpinLock, oldirql);
                break;

            }   // end of switch

        } else {