Esempio n. 1
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) {
Esempio n. 2
0
VOID
NbiProcessDatagram(
    IN NDIS_HANDLE MacBindingHandle,
    IN NDIS_HANDLE MacReceiveContext,
    IN PIPX_LOCAL_TARGET RemoteAddress,
    IN ULONG MacOptions,
    IN PUCHAR LookaheadBuffer,
    IN UINT LookaheadBufferSize,
    IN UINT LookaheadBufferOffset,
    IN UINT PacketSize,
    IN BOOLEAN Broadcast
    )

/*++

Routine Description:

    This routine handles datagram indications.

Arguments:

    MacBindingHandle - A handle to use when calling NdisTransferData.

    MacReceiveContext - A context to use when calling NdisTransferData.

    RemoteAddress - The local target this packet was received from.

    MacOptions - The MAC options for the underlying NDIS binding.

    LookaheadBuffer - The lookahead buffer, starting at the IPX
        header.

    LookaheadBufferSize - The length of the lookahead data.

    LookaheadBufferOffset - The offset to add when calling
        NdisTransferData.

    PacketSize - The total length of the packet, starting at the
        IPX header.

    Broadcast - TRUE if the frame was a broadcast datagram.

Return Value:

    None.

--*/

{

    PADDRESS Address;
    NDIS_STATUS NdisStatus;
    PUCHAR NetbiosName;
    NB_CONNECTIONLESS UNALIGNED * Connectionless =
                        (NB_CONNECTIONLESS UNALIGNED *)LookaheadBuffer;
    PDEVICE Device = NbiDevice;
    PSINGLE_LIST_ENTRY s;
    PNB_RECEIVE_RESERVED ReceiveReserved;
    PNB_RECEIVE_BUFFER ReceiveBuffer;
    ULONG DataOffset;
    UINT BytesTransferred;
    PNDIS_PACKET Packet;
    CTELockHandle   LockHandle;


    //
    // See if there is an address that might want this.
    //

    if (Broadcast) {
        NetbiosName = (PVOID)-1;
    } else {
        NetbiosName = (PUCHAR)Connectionless->Datagram.DestinationName;
        if (Device->AddressCounts[NetbiosName[0]] == 0) {
            return;
        }
    }

    DataOffset = sizeof(IPX_HEADER) + sizeof(NB_DATAGRAM);

#if     defined(_PNP_POWER)
    if ((PacketSize < DataOffset) ||
        (PacketSize > DataOffset + Device->CurMaxReceiveBufferSize)) {
#else
        if ((PacketSize < DataOffset) ||
            (PacketSize > DataOffset + Device->Bind.LineInfo.MaximumPacketSize)) {
#endif  _PNP_POWER

        NB_DEBUG (DATAGRAM, ("Datagram length %d discarded\n", PacketSize));
        return;
    }

    Address = NbiFindAddress (Device, NetbiosName);

    if (Address == NULL) {
        return;
    }

    //
    // We need to cache the remote name if the packet came across the router.
    // This allows this machine to get back to the RAS client which might
    // have sent this datagram. We currently dont allow broadcasts to go out
    // on the dial-in line.
    // Dont cache some of the widely used group names, that would be too much
    // to store in cache.
    //

#if 0
    if ( Connectionless->IpxHeader.TransportControl &&
         !( (Address->NetbiosAddress.NetbiosName[15] == 0x0 ) &&
            (Address->NetbiosAddress.NetbiosNameType & TDI_ADDRESS_NETBIOS_TYPE_GROUP))  &&
         !( (Address->NetbiosAddress.NetbiosName[15] == 0x01 ) &&
            (Address->NetbiosAddress.NetbiosNameType & TDI_ADDRESS_NETBIOS_TYPE_GROUP))  &&
         !( (Address->NetbiosAddress.NetbiosName[15] == 0x1E ) &&
            (Address->NetbiosAddress.NetbiosNameType & TDI_ADDRESS_NETBIOS_TYPE_GROUP))  ) {
#endif
    if ( Connectionless->IpxHeader.TransportControl &&
         ( (Address->NetbiosAddress.NetbiosName[15] == 0x1c ) &&
           (Address->NetbiosAddress.NetbiosNameType & TDI_ADDRESS_NETBIOS_TYPE_GROUP))  ) {

        PNETBIOS_CACHE CacheName;

        NB_GET_LOCK (&Device->Lock, &LockHandle);
        if ( FindInNetbiosCacheTable ( Device->NameCache,
                                       Connectionless->Datagram.SourceName,
                                       &CacheName ) != STATUS_SUCCESS ) {

            CacheName = NbiAllocateMemory (sizeof(NETBIOS_CACHE), MEMORY_CACHE, "Cache Entry");
            if (CacheName ) {
                RtlCopyMemory (CacheName->NetbiosName, Connectionless->Datagram.SourceName, 16);
                CacheName->Unique = TRUE;
                CacheName->ReferenceCount = 1;
                RtlCopyMemory (&CacheName->FirstResponse, Connectionless->IpxHeader.SourceNetwork, 12);
                CacheName->NetworksAllocated = 1;
                CacheName->NetworksUsed = 1;
                CacheName->Networks[0].Network = *(UNALIGNED ULONG *)(Connectionless->IpxHeader.SourceNetwork);
                CacheName->Networks[0].LocalTarget = *RemoteAddress;
                NB_DEBUG2 (CACHE, ("Alloc new cache from Datagram %lx for <%.16s>\n",
                                        CacheName, CacheName->NetbiosName));

                CacheName->TimeStamp = Device->CacheTimeStamp;

                InsertInNetbiosCacheTable(
                    Device->NameCache,
                    CacheName);

            }
        } else if ( CacheName->Unique ) {
            //
            // We already have an entry for this remote. We should update
            // the address. This is so that if the ras client dials-out
            // then dials-in again and gets a new address, we dont end up
            // caching the old address.
            //
            if ( !RtlEqualMemory( &CacheName->FirstResponse, Connectionless->IpxHeader.SourceNetwork, 12) ) {

                RtlCopyMemory (&CacheName->FirstResponse, Connectionless->IpxHeader.SourceNetwork, 12);
                CacheName->Networks[0].Network = *(UNALIGNED ULONG *)(Connectionless->IpxHeader.SourceNetwork);
                CacheName->Networks[0].LocalTarget = *RemoteAddress;

            }
        }
        NB_FREE_LOCK (&Device->Lock, LockHandle);
    }

    //
    // We need to allocate a packet and buffer for the transfer.
    //

    s = NbiPopReceivePacket (Device);
    if (s == NULL) {
        NbiDereferenceAddress (Address, AREF_FIND);
        return;
    }

    ReceiveReserved = CONTAINING_RECORD (s, NB_RECEIVE_RESERVED, PoolLinkage);


    s = NbiPopReceiveBuffer (Device);
    if (s == NULL) {
        ExInterlockedPushEntrySList(
            &Device->ReceivePacketList,
            &ReceiveReserved->PoolLinkage,
            &NbiGlobalPoolInterlock);
        NbiDereferenceAddress (Address, AREF_FIND);
        return;
    }

    ReceiveBuffer = CONTAINING_RECORD (s, NB_RECEIVE_BUFFER, PoolLinkage);

    Packet = CONTAINING_RECORD (ReceiveReserved, NDIS_PACKET, ProtocolReserved[0]);
    ReceiveReserved->u.RR_DG.ReceiveBuffer = ReceiveBuffer;


    //
    // Now that we have a packet and a buffer, set up the transfer.
    // The indication to the TDI clients will happen at receive
    // complete time.
    //

    NdisChainBufferAtFront (Packet, ReceiveBuffer->NdisBuffer);
    ReceiveBuffer->Address = Address;

    ReceiveReserved->Type = RECEIVE_TYPE_DATAGRAM;
    CTEAssert (!ReceiveReserved->TransferInProgress);
    ReceiveReserved->TransferInProgress = TRUE;

    TdiCopyLookaheadData(
        &ReceiveBuffer->RemoteName,
        Connectionless->Datagram.SourceName,
        16,
        (MacOptions & NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA) ? TDI_RECEIVE_COPY_LOOKAHEAD : 0);

    (*Device->Bind.TransferDataHandler) (
        &NdisStatus,
        MacBindingHandle,
        MacReceiveContext,
        LookaheadBufferOffset + DataOffset,
        PacketSize - DataOffset,
        Packet,
        &BytesTransferred);

    if (NdisStatus != NDIS_STATUS_PENDING) {
#if DBG
        if (NdisStatus == STATUS_SUCCESS) {
            CTEAssert (BytesTransferred == PacketSize - DataOffset);
        }
#endif

        NbiTransferDataComplete(
            Packet,
            NdisStatus,
            BytesTransferred);

    }

}   /* NbiProcessDatagram */


VOID
NbiIndicateDatagram(
    IN PADDRESS Address,
    IN PUCHAR RemoteName,
    IN PUCHAR Data,
    IN ULONG DataLength
    )

/*++

Routine Description:

    This routine indicates a datagram to clients on the specified
    address. It is called from NbiReceiveComplete.

Arguments:

    Address - The address the datagram was sent to.

    RemoteName - The source netbios address of the datagram.

    Data - The data.

    DataLength - The length of the data.

Return Value:

    None.

--*/

{
    PLIST_ENTRY p, q;
    PIRP Irp;
    ULONG IndicateBytesCopied;
    PREQUEST Request;
    TA_NETBIOS_ADDRESS SourceName;
    PTDI_CONNECTION_INFORMATION RemoteInformation;
    PADDRESS_FILE AddressFile, ReferencedAddressFile;
    PTDI_CONNECTION_INFORMATION DatagramInformation;
    TDI_ADDRESS_NETBIOS UNALIGNED * DatagramAddress;
    PDEVICE Device = NbiDevice;
    NB_DEFINE_LOCK_HANDLE (LockHandle)
    CTELockHandle   CancelLH;

    //
    // Update our statistics.
    //

    ++Device->Statistics.DatagramsReceived;
    ADD_TO_LARGE_INTEGER(
        &Device->Statistics.DatagramBytesReceived,
        DataLength);

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

    TdiBuildNetbiosAddress (RemoteName, FALSE, &SourceName);
    ReferencedAddressFile = NULL;

    NB_SYNC_GET_LOCK (&Address->Lock, &LockHandle);

    for (p = Address->AddressFileDatabase.Flink;
         p != &Address->AddressFileDatabase;
         p = p->Flink) {

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

        AddressFile = CONTAINING_RECORD (p, ADDRESS_FILE, Linkage);
        if (AddressFile->State != ADDRESSFILE_STATE_OPEN) {
            continue;
        }

        NbiReferenceAddressFileLock (AddressFile, AFREF_INDICATION);

        //
        // do we have a datagram receive request outstanding? If so, we will
        // satisfy it first. We run through the receive datagram queue
        // until we find a datagram with no remote address or with
        // this sender's address as its remote address.
        //

        for (q = AddressFile->ReceiveDatagramQueue.Flink;
             q != &AddressFile->ReceiveDatagramQueue;
             q = q->Flink) {

            Request = LIST_ENTRY_TO_REQUEST (q);
            DatagramInformation = ((PTDI_REQUEST_KERNEL_RECEIVEDG)
                REQUEST_PARAMETERS(Request))->ReceiveDatagramInformation;

            if (DatagramInformation &&
                (DatagramInformation->RemoteAddress) &&
                (DatagramAddress = NbiParseTdiAddress(DatagramInformation->RemoteAddress, FALSE)) &&
                (!RtlEqualMemory(
                    RemoteName,
                    DatagramAddress->NetbiosName,
                    16))) {
                continue;
            }
            break;
        }

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

            RemoveEntryList (q);
            NB_SYNC_FREE_LOCK (&Address->Lock, LockHandle);

            if (ReferencedAddressFile != NULL) {
                NbiDereferenceAddressFile (ReferencedAddressFile, AFREF_INDICATION);
            }
            ReferencedAddressFile = AddressFile;

            //
            // Do this deref now, we hold another one so it
            // will stick around.
            //

            NbiDereferenceAddressFile (AddressFile, AFREF_RCV_DGRAM);

            IndicateBytesCopied = 0;

            //
            // Fall past the else to copy the data.
            //

        } else {

            NB_SYNC_FREE_LOCK (&Address->Lock, LockHandle);

            if (ReferencedAddressFile != NULL) {
                NbiDereferenceAddressFile (ReferencedAddressFile, AFREF_INDICATION);
            }
            ReferencedAddressFile = AddressFile;

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

            if (AddressFile->RegisteredHandler[TDI_EVENT_RECEIVE_DATAGRAM]) {

                IndicateBytesCopied = 0;

                if ((*AddressFile->ReceiveDatagramHandler)(
                         AddressFile->HandlerContexts[TDI_EVENT_RECEIVE_DATAGRAM],
                         sizeof (TA_NETBIOS_ADDRESS),
                         &SourceName,
                         0,
                         NULL,
                         TDI_RECEIVE_COPY_LOOKAHEAD,
                         DataLength,      // indicated
                         DataLength,     // available
                         &IndicateBytesCopied,
                         Data,
                         &Irp) != STATUS_MORE_PROCESSING_REQUIRED) {

                    //
                    // The client did not return a request, go to the
                    // next address file.
                    //

                    NB_SYNC_GET_LOCK (&Address->Lock, &LockHandle);
                    continue;

                }

                Request = NbiAllocateRequest (Device, Irp);

                IF_NOT_ALLOCATED(Request) {
                    Irp->IoStatus.Information = 0;
                    Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
                    IoCompleteRequest (Irp, IO_NETWORK_INCREMENT);


                    NB_SYNC_GET_LOCK (&Address->Lock, &LockHandle);
                    continue;
                }

            } else {

                //
                // The client has nothing posted and no handler,
                // go on to the next address file.
                //

                NB_SYNC_GET_LOCK (&Address->Lock, &LockHandle);
                continue;

            }

        }

        //
        // We have a request; copy the actual user data.
        //
        if ( REQUEST_NDIS_BUFFER (Request) ) {

            REQUEST_STATUS(Request) =
                TdiCopyBufferToMdl (
                         Data,
                         IndicateBytesCopied,
                         DataLength - IndicateBytesCopied,
                         REQUEST_NDIS_BUFFER (Request),
                         0,
                         &REQUEST_INFORMATION (Request));

        } else {
            //
            // No buffer specified in the request
            //
            REQUEST_INFORMATION (Request) = 0;
            //
            // If there was any data to be copied, return error o/w success
            //
            REQUEST_STATUS(Request) = ( (DataLength - IndicateBytesCopied) ? STATUS_BUFFER_OVERFLOW : STATUS_SUCCESS );
        }

        //
        // Copy the addressing information.
        //

        RemoteInformation = ((PTDI_REQUEST_KERNEL_RECEIVEDG)
                REQUEST_PARAMETERS(Request))->ReturnDatagramInformation;

        if (RemoteInformation != NULL) {

            RtlCopyMemory(
                (PTA_NETBIOS_ADDRESS)RemoteInformation->RemoteAddress,
                &SourceName,
                (RemoteInformation->RemoteAddressLength < sizeof(TA_NETBIOS_ADDRESS)) ?
                    RemoteInformation->RemoteAddressLength : sizeof(TA_NETBIOS_ADDRESS));
        }


        NB_GET_CANCEL_LOCK( &CancelLH );
        IoSetCancelRoutine (Request, (PDRIVER_CANCEL)NULL);
        NB_FREE_CANCEL_LOCK( CancelLH );

        NbiCompleteRequest (Request);
        NbiFreeRequest (Device, Request);

        NB_SYNC_GET_LOCK (&Address->Lock, &LockHandle);

    }    // end of for loop through the address files
Esempio n. 3
0
NTSTATUS
IpxTdiQueryInformation(
    IN PDEVICE Device,
    IN PREQUEST Request
    )

/*++

Routine Description:

    This routine performs the TdiQueryInformation request for the transport
    provider.

Arguments:

    Request - the request for the operation.

Return Value:

    NTSTATUS - status of operation.

--*/

{
    NTSTATUS status;
    PTDI_REQUEST_KERNEL_QUERY_INFORMATION query;
    PADDRESS_FILE AddressFile;
    ULONG ElementSize, TransportAddressSize;
    PTRANSPORT_ADDRESS TransportAddress;
    TA_ADDRESS UNALIGNED * CurAddress;
    PBINDING Binding;
    union {
        struct {
            ULONG ActivityCount;
            TA_IPX_ADDRESS IpxAddress;
        } AddressInfo;
        TDI_DATAGRAM_INFO DatagramInfo;
        TDI_ADDRESS_IPX IpxAddress;
    } TempBuffer;
    UINT i;

#ifdef	_PNP_POWER
	IPX_DEFINE_LOCK_HANDLE(LockHandle1)
#endif

	//
    // what type of status do we want?
    //

    query = (PTDI_REQUEST_KERNEL_QUERY_INFORMATION)REQUEST_PARAMETERS(Request);

    switch (query->QueryType) {

    case TDI_QUERY_ADDRESS_INFO:

        //
        // The caller wants the exact address value.
        //

        AddressFile = (PADDRESS_FILE)REQUEST_OPEN_CONTEXT(Request);

        status = IpxVerifyAddressFile (AddressFile);

        if (status == STATUS_SUCCESS) {

            TempBuffer.AddressInfo.ActivityCount = 0;

            IpxBuildTdiAddress(
                &TempBuffer.AddressInfo.IpxAddress,
                Device->SourceAddress.NetworkAddress,
                Device->SourceAddress.NodeAddress,
                AddressFile->Address->Socket);

            status = TdiCopyBufferToMdl(
                &TempBuffer.AddressInfo,
                0,
                sizeof(TempBuffer.AddressInfo),
                REQUEST_NDIS_BUFFER(Request),
                0,
                &REQUEST_INFORMATION(Request));

            IpxDereferenceAddressFile (AddressFile, AFREF_VERIFY);

        }

        break;

    case TDI_QUERY_PROVIDER_INFO:

        status = TdiCopyBufferToMdl (
                    &(Device->Information),
                    0,
                    sizeof (TDI_PROVIDER_INFO),
                    REQUEST_NDIS_BUFFER(Request),
                    0,
                    &REQUEST_INFORMATION(Request));
        break;

    case TDI_QUERY_PROVIDER_STATISTICS:

        status = TdiCopyBufferToMdl (
                    &Device->Statistics,
                    0,
                    FIELD_OFFSET (TDI_PROVIDER_STATISTICS, ResourceStats[0]),
                    REQUEST_NDIS_BUFFER(Request),
                    0,
                    &REQUEST_INFORMATION(Request));
        break;

    case TDI_QUERY_DATAGRAM_INFO:

        TempBuffer.DatagramInfo.MaximumDatagramBytes = 0;
        TempBuffer.DatagramInfo.MaximumDatagramCount = 0;

        status = TdiCopyBufferToMdl (
                    &TempBuffer.DatagramInfo,
                    0,
                    sizeof(TempBuffer.DatagramInfo),
                    REQUEST_NDIS_BUFFER(Request),
                    0,
                    &REQUEST_INFORMATION(Request));
        break;

    case TDI_QUERY_DATA_LINK_ADDRESS:
    case TDI_QUERY_NETWORK_ADDRESS:

        if (query->QueryType == TDI_QUERY_DATA_LINK_ADDRESS) {
            ElementSize = (2 * sizeof(USHORT)) + 6;
        } else {
            ElementSize = (2 * sizeof(USHORT)) + sizeof(TDI_ADDRESS_IPX);
        }

        TransportAddress = IpxAllocateMemory(sizeof(int) + (ElementSize * MIN (Device->MaxBindings, Device->ValidBindings)), MEMORY_QUERY, "NetworkAddress");

        if (TransportAddress == NULL) {

            status = STATUS_INSUFFICIENT_RESOURCES;

        } else {

            TransportAddress->TAAddressCount = 0;
            TransportAddressSize = sizeof(int);
            CurAddress = (TA_ADDRESS UNALIGNED *)TransportAddress->Address;
#ifdef	_PNP_POWER
			IPX_GET_LOCK1(&Device->BindAccessLock, &LockHandle1);
            {
                ULONG   Index = MIN (Device->MaxBindings, Device->ValidBindings);

                for (i = 1; i <= Index; i++) {

                    Binding = NIC_ID_TO_BINDING(Device, i);
                    if ((Binding == NULL) ||
                        (!Binding->LineUp)) {
                        continue;
                    }

                    if (query->QueryType == TDI_QUERY_DATA_LINK_ADDRESS) {
                        CurAddress->AddressLength = 6;
                        CurAddress->AddressType = Binding->Adapter->MacInfo.RealMediumType;
                        RtlCopyMemory (CurAddress->Address, Binding->LocalAddress.NodeAddress, 6);
                    } else {
                        CurAddress->AddressLength = sizeof(TDI_ADDRESS_IPX);
                        CurAddress->AddressType = TDI_ADDRESS_TYPE_IPX;
                        RtlCopyMemory (CurAddress->Address, &Binding->LocalAddress, sizeof(TDI_ADDRESS_IPX));
                    }
                    ++TransportAddress->TAAddressCount;
                    TransportAddressSize += ElementSize;
                    CurAddress = (TA_ADDRESS UNALIGNED *)(((PUCHAR)CurAddress) + ElementSize);

                }
            }

			IPX_FREE_LOCK1(&Device->BindAccessLock, LockHandle1);
#else
            for (i = 1; i <= Device->ValidBindings; i++) {

                Binding = Device->Bindings[i];
                if ((Binding == NULL) ||
                    (!Binding->LineUp)) {
                    continue;
                }

                if (query->QueryType == TDI_QUERY_DATA_LINK_ADDRESS) {
                    CurAddress->AddressLength = 6;
                    CurAddress->AddressType = Binding->Adapter->MacInfo.RealMediumType;
                    RtlCopyMemory (CurAddress->Address, Binding->LocalAddress.NodeAddress, 6);
                } else {
                    CurAddress->AddressLength = sizeof(TDI_ADDRESS_IPX);
                    CurAddress->AddressType = TDI_ADDRESS_TYPE_IPX;
                    RtlCopyMemory (CurAddress->Address, &Binding->LocalAddress, sizeof(TDI_ADDRESS_IPX));
                }
                ++TransportAddress->TAAddressCount;
                TransportAddressSize += ElementSize;
                CurAddress = (TA_ADDRESS UNALIGNED *)(((PUCHAR)CurAddress) + ElementSize);

            }
#endif
            status = TdiCopyBufferToMdl (
                        TransportAddress,
                        0,
                        TransportAddressSize,
                        REQUEST_NDIS_BUFFER(Request),
                        0,
                        &REQUEST_INFORMATION(Request));

            CTEFreeMem (TransportAddress);

        }

        break;

    default:

        status = STATUS_INVALID_DEVICE_REQUEST;
        break;
    }

    return status;

}   /* IpxTdiQueryInformation */
Esempio n. 4
0
NTSTATUS
LpxTdiQueryInformation(
    IN PDEVICE_CONTEXT DeviceContext,
    IN PIRP Irp
    )

/*++

Routine Description:

    This routine performs the TdiQueryInformation request for the transport
    provider.

Arguments:

    Irp - the Irp for the requested operation.

Return Value:

    NTSTATUS - status of operation.

--*/

{
    NTSTATUS status;
    PIO_STACK_LOCATION irpSp;
    PTDI_REQUEST_KERNEL_QUERY_INFORMATION query;
    PTA_NETBIOS_ADDRESS broadcastAddress;
    PTDI_PROVIDER_STATISTICS ProviderStatistics;
    PTDI_CONNECTION_INFO ConnectionInfo;
    ULONG TargetBufferLength;
	LARGE_INTEGER timeout = {0,0};
    PTP_CONNECTION Connection;
    PTP_ADDRESS_FILE AddressFile;
    PTP_ADDRESS Address;
    struct {
        ULONG ActivityCount;
        TA_NETBIOS_ADDRESS TaAddressBuffer;
    } AddressInfo;
    PTRANSPORT_ADDRESS TaAddress;
    TDI_DATAGRAM_INFO DatagramInfo;
    BOOLEAN UsedConnection;
    PLIST_ENTRY p;
    KIRQL oldirql;
    ULONG BytesCopied;

    //
    // what type of status do we want?
    //

    irpSp = IoGetCurrentIrpStackLocation (Irp);

    query = (PTDI_REQUEST_KERNEL_QUERY_INFORMATION)&irpSp->Parameters;

    switch (query->QueryType) {

#if 0
    case 0x12345678:

        {
            typedef struct _LPX_CONNECTION_STATUS {
                UCHAR LocalName[16];
                UCHAR RemoteName[16];
                BOOLEAN SendActive;
                BOOLEAN ReceiveQueued;
                BOOLEAN ReceiveActive;
                BOOLEAN ReceiveWakeUp;
                ULONG Flags;
                ULONG Flags2;
            } LPX_CONNECTION_STATUS, *PLPX_CONNECTION_STATUS;

            PLPX_CONNECTION_STATUS CurStatus;
            ULONG TotalStatus;
            ULONG AllowedStatus;
            PLIST_ENRY q;

            CurStatus = MmGetSystemAddressForMdl (Irp->MdlAddress);
            TotalStatus = 0;
            AllowedStatus = MmGetMdlByteCount (Irp->MdlAddress) / sizeof(LPX_CONNECTION_STATUS);

            for (p = DeviceContext->AddressDatabase.Flink;
                 p != &DeviceContext->AddressDatabase;
                 p = p->Flink) {

                Address = CONTAINING_RECORD (p, TP_ADDRESS, Linkage);

                if ((Address->Flags & ADDRESS_FLAGS_STOPPING) != 0) {
                    continue;
                }

                for (q = Address->ConnectionDatabase.Flink;
                     q != &Address->ConnectionDatabase;
                     q = q->Flink) {

                    Connection = CONTAINING_RECORD (q, TP_CONNECTION, AddressList);

                    if ((Connection->Flags & CONNECTION_FLAGS_READY) == 0) {
                        continue;
                    }

                    if (TotalStatus >= AllowedStatus) {
                        continue;
                    }

                    RtlMoveMemory (CurStatus->LocalName, Address->NetworkName->NetbiosName, 16);
                    RtlMoveMemory (CurStatus->RemoteName, Connection->RemoteName, 16);

                    CurStatus->Flags = Connection->Flags;
                    CurStatus->Flags2 = Connection->Flags2;
                    CurStatus->SendActive = (BOOLEAN)(!IsListEmpty(&Connection->SendQueue));
                    CurStatus->ReceiveQueued = (BOOLEAN)(!IsListEmpty(&Connection->ReceiveQueue));
                    CurStatus->ReceiveActive = (BOOLEAN)((Connection->Flags & CONNECTION_FLAGS_ACTIVE_RECEIVE) != 0);
                    CurStatus->ReceiveWakeUp = (BOOLEAN)((Connection->Flags & CONNECTION_FLAGS_RECEIVE_WAKEUP) != 0);

                    ++CurStatus;
                    ++TotalStatus;

                }
            }

            Irp->IoStatus.Information = TotalStatus * sizeof(LPX_CONNECTION_STATUS);
            status = STATUS_SUCCESS;

        }

        break;
#endif

    case TDI_QUERY_CONNECTION_INFO:

        //
        // Connection info is queried on a connection,
        // verify this.
        //

        if (irpSp->FileObject->FsContext2 != (PVOID) TDI_CONNECTION_FILE) {

			ASSERT( FALSE );
            return STATUS_INVALID_CONNECTION;
        }

        Connection = irpSp->FileObject->FsContext;

        status = LpxVerifyConnectionObject (Connection);

        if (!NT_SUCCESS (status)) {

			ASSERT( FALSE );
#if DBG
            LpxPrint2 ("TdiQueryInfo: Invalid Connection %p Irp %p\n", Connection, Irp);
#endif
            return status;
        }

        ConnectionInfo = ExAllocatePoolWithTag (
                             NonPagedPool,
                             sizeof (TDI_CONNECTION_INFO),
                             LPX_MEM_TAG_TDI_CONNECTION_INFO);

        if (ConnectionInfo == NULL) {

            PANIC ("LpxQueryInfo: Cannot allocate connection info!\n");
            LpxWriteResourceErrorLog(
                DeviceContext,
                EVENT_TRANSPORT_RESOURCE_POOL,
                6,
                sizeof(TDI_CONNECTION_INFO),
                0);
            status = STATUS_INSUFFICIENT_RESOURCES;

#if __LPX__

		} else {

			LARGE_INTEGER	delay;

            RtlZeroMemory ((PVOID)ConnectionInfo, sizeof(TDI_CONNECTION_INFO));

			ConnectionInfo->Event;
			ConnectionInfo->TransmittedTsdus	= Connection->LpxSmp.NumberOfSendPackets; 
			ConnectionInfo->ReceivedTsdus		= Connection->LpxSmp.NumberofRecvPackets; 
			ConnectionInfo->TransmissionErrors	= Connection->LpxSmp.NumberOfSendRetransmission; 
			ConnectionInfo->ReceiveErrors		= Connection->LpxSmp.DropOfReceivePacket; 

			if (Connection->LpxSmp.ResponseTimeOfLargeSendRequests.QuadPart) {

				ConnectionInfo->Throughput.QuadPart	= 
					Connection->LpxSmp.BytesOfLargeSendRequests.QuadPart * 1000 * 1000 * 10 / 
					Connection->LpxSmp.ResponseTimeOfLargeSendRequests.QuadPart; 			
			
			} else if (Connection->LpxSmp.ResponseTimeOfSmallSendRequests.QuadPart) {

				ConnectionInfo->Throughput.QuadPart	= 
					Connection->LpxSmp.BytesOfSmallSendRequests.QuadPart * 1000 * 1000 * 10 / 
					Connection->LpxSmp.ResponseTimeOfSmallSendRequests.QuadPart; 			
			}			

			if (Connection->LpxSmp.NumberofSmallSendRequests) {
		
				delay.QuadPart = Connection->LpxSmp.ResponseTimeOfSmallSendRequests.QuadPart / Connection->LpxSmp.NumberofSmallSendRequests;	
				ConnectionInfo->Delay.HighPart = -1L;
				ConnectionInfo->Delay.LowPart = (ULONG) - ((LONG)(delay.LowPart));	// 100 ns
			}
			ConnectionInfo->SendBufferSize; 
			ConnectionInfo->ReceiveBufferSize; 
			ConnectionInfo->Unreliable; 

			status = TdiCopyBufferToMdl (
                            (PVOID)ConnectionInfo,
                            0L,
                            sizeof(TDI_CONNECTION_INFO),
                            Irp->MdlAddress,
                            0,
                            &BytesCopied);

            Irp->IoStatus.Information = BytesCopied;

            ExFreePool (ConnectionInfo);
		}

#endif

        LpxDereferenceConnection ("query connection info", Connection, CREF_BY_ID);

        break;
	case LPXTDI_QUERY_CONNECTION_TRANSSTAT: {
		TRANS_STAT	transStat;

		//
		// Connection info is queried on a connection,
		// verify this.
		//

		if (irpSp->FileObject->FsContext2 != (PVOID) TDI_CONNECTION_FILE) {

			ASSERT( FALSE );
			return STATUS_INVALID_CONNECTION;
		}

		Connection = irpSp->FileObject->FsContext;

		status = LpxVerifyConnectionObject (Connection);

		if (!NT_SUCCESS (status)) {

			ASSERT( FALSE );
#if DBG
			LpxPrint2 ("TdiTransStat: Invalid Connection %p Irp %p\n", Connection, Irp);
#endif
			return status;
		}

		transStat.PacketLoss = InterlockedExchange(&Connection->LpxSmp.TransportStats.PacketLoss, 0);
		transStat.Retransmits = InterlockedExchange(&Connection->LpxSmp.TransportStats.Retransmits, 0);

		status = TdiCopyBufferToMdl (
                            &transStat,
                            0L,
                            sizeof(TRANS_STAT),
                            Irp->MdlAddress,
                            0,
                            &BytesCopied);

		Irp->IoStatus.Information = BytesCopied;

		LpxDereferenceConnection ("query connection info", Connection, CREF_BY_ID);
		break;
	}
    case TDI_QUERY_ADDRESS_INFO:

        if (irpSp->FileObject->FsContext2 == (PVOID)TDI_TRANSPORT_ADDRESS_FILE) {

            AddressFile = irpSp->FileObject->FsContext;

            status = LpxVerifyAddressObject(AddressFile);

            if (!NT_SUCCESS (status)) {
#if DBG
                LpxPrint2 ("TdiQueryInfo: Invalid AddressFile %p Irp %p\n", AddressFile, Irp);
#endif
                return status;
            }

            UsedConnection = FALSE;

        } else if (irpSp->FileObject->FsContext2 == (PVOID)TDI_CONNECTION_FILE) {

            Connection = irpSp->FileObject->FsContext;

            status = LpxVerifyConnectionObject (Connection);

            if (!NT_SUCCESS (status)) {
#if DBG
                LpxPrint2 ("TdiQueryInfo: Invalid Connection %p Irp %p\n", Connection, Irp);
#endif
                return status;
            }

            AddressFile = Connection->AddressFile;

            UsedConnection = TRUE;

        } else {

            return STATUS_INVALID_ADDRESS;

        }

        Address = AddressFile->Address;
#if 0
        TdiBuildNetbiosAddress(
            Address->NetworkName->NetbiosName,
            (BOOLEAN)(Address->Flags & ADDRESS_FLAGS_GROUP ? TRUE : FALSE),
            &AddressInfo.TaAddressBuffer);
#else
		TdiBuildNetbiosAddress(
            Address->NetworkName->Node,
            FALSE,
            &AddressInfo.TaAddressBuffer);
#endif
        //
        // Count the active addresses.
        //

        AddressInfo.ActivityCount = 0;

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

        for (p = Address->AddressFileDatabase.Flink;
             p != &Address->AddressFileDatabase;
             p = p->Flink) {
            ++AddressInfo.ActivityCount;
        }

        RELEASE_SPIN_LOCK (&Address->SpinLock, oldirql);

        status = TdiCopyBufferToMdl (
                    &AddressInfo,
                    0,
                    sizeof(ULONG) + sizeof(TA_NETBIOS_ADDRESS),
                    Irp->MdlAddress,
                    0,                    
                    &BytesCopied);

        Irp->IoStatus.Information = BytesCopied;

        if (UsedConnection) {

            LpxDereferenceConnection ("query address info", Connection, CREF_BY_ID);

        } else {

            LpxDereferenceAddress ("query address info", Address, AREF_VERIFY);

        }

        break;

    case TDI_QUERY_BROADCAST_ADDRESS:

        //
        // for this provider, the broadcast address is a zero byte name,
        // contained in a Transport address structure.
        //

        broadcastAddress = ExAllocatePoolWithTag (
                                NonPagedPool,
                                sizeof (TA_NETBIOS_ADDRESS),
                                LPX_MEM_TAG_TDI_QUERY_BUFFER);
        if (broadcastAddress == NULL) {
            PANIC ("LpxQueryInfo: Cannot allocate broadcast address!\n");
            LpxWriteResourceErrorLog(
                DeviceContext,
                EVENT_TRANSPORT_RESOURCE_POOL,
                2,
                sizeof(TA_NETBIOS_ADDRESS),
                0);
            status = STATUS_INSUFFICIENT_RESOURCES;
        } else {

            broadcastAddress->TAAddressCount = 1;
            broadcastAddress->Address[0].AddressType = TDI_ADDRESS_TYPE_NETBIOS;
            broadcastAddress->Address[0].AddressLength = 0;

            Irp->IoStatus.Information =
                    sizeof (broadcastAddress->TAAddressCount) +
                    sizeof (broadcastAddress->Address[0].AddressType) +
                    sizeof (broadcastAddress->Address[0].AddressLength);

            BytesCopied = (ULONG)Irp->IoStatus.Information;

            status = TdiCopyBufferToMdl (
                            (PVOID)broadcastAddress,
                            0L,
                            BytesCopied,
                            Irp->MdlAddress,
                            0,
                            &BytesCopied);
                            
            Irp->IoStatus.Information = BytesCopied;

            ExFreePool (broadcastAddress);
        }

        break;

    case TDI_QUERY_PROVIDER_INFO:

        status = TdiCopyBufferToMdl (
                    &(DeviceContext->Information),
                    0,
                    sizeof (TDI_PROVIDER_INFO),
                    Irp->MdlAddress,
                    0,
                    &BytesCopied);

        Irp->IoStatus.Information = BytesCopied;

        break;

    case TDI_QUERY_PROVIDER_STATISTICS:

        //
        // This information is probablt available somewhere else.
        //

        LpxGetMdlChainLength (Irp->MdlAddress, &TargetBufferLength);

        if (TargetBufferLength < sizeof(TDI_PROVIDER_STATISTICS) + ((LPX_TDI_RESOURCES-1) * sizeof(TDI_PROVIDER_RESOURCE_STATS))) {

            Irp->IoStatus.Information = 0;
            status = STATUS_BUFFER_OVERFLOW;

        } else {

            ProviderStatistics = ExAllocatePoolWithTag(
                                   NonPagedPool,
                                   sizeof(TDI_PROVIDER_STATISTICS) +
                                     ((LPX_TDI_RESOURCES-1) * sizeof(TDI_PROVIDER_RESOURCE_STATS)),
                                   LPX_MEM_TAG_TDI_PROVIDER_STATS);

            if (ProviderStatistics == NULL) {

                PANIC ("LpxQueryInfo: Cannot allocate provider statistics!\n");
                LpxWriteResourceErrorLog(
                    DeviceContext,
                    EVENT_TRANSPORT_RESOURCE_POOL,
                    7,
                    sizeof(TDI_PROVIDER_STATISTICS),
                    0);
                status = STATUS_INSUFFICIENT_RESOURCES;

            } else {

                LpxStoreProviderStatistics (DeviceContext, ProviderStatistics);

                status = TdiCopyBufferToMdl (
                                (PVOID)ProviderStatistics,
                                0L,
                                sizeof(TDI_PROVIDER_STATISTICS) +
                                  ((LPX_TDI_RESOURCES-1) * sizeof(TDI_PROVIDER_RESOURCE_STATS)),
                                Irp->MdlAddress,
                                0,
                                &BytesCopied);

                Irp->IoStatus.Information = BytesCopied;

                ExFreePool (ProviderStatistics);
            }

        }

        break;

    case TDI_QUERY_SESSION_STATUS:

        status = STATUS_NOT_IMPLEMENTED;
        break;

    case TDI_QUERY_ADAPTER_STATUS:

		ASSERT( FALSE );
		status = STATUS_NOT_IMPLEMENTED;

		break;

    case TDI_QUERY_FIND_NAME:

		ASSERT( FALSE );
		status = STATUS_NOT_IMPLEMENTED;

        break;

    case TDI_QUERY_DATA_LINK_ADDRESS:
    case TDI_QUERY_NETWORK_ADDRESS:

        TaAddress = (PTRANSPORT_ADDRESS)&AddressInfo.TaAddressBuffer;
        TaAddress->TAAddressCount = 1;
        TaAddress->Address[0].AddressLength = 6;
        if (query->QueryType == TDI_QUERY_DATA_LINK_ADDRESS) {
            TaAddress->Address[0].AddressType =
                DeviceContext->MacInfo.MediumAsync ?
                    NdisMediumWan : DeviceContext->MacInfo.MediumType;
        } else {
            TaAddress->Address[0].AddressType = TDI_ADDRESS_TYPE_UNSPEC;
        }
        RtlCopyMemory (TaAddress->Address[0].Address, DeviceContext->LocalAddress.Address, 6);

        status = TdiCopyBufferToMdl (
                    &AddressInfo.TaAddressBuffer,
                    0,
                    sizeof(TRANSPORT_ADDRESS)+5,
                    Irp->MdlAddress,
                    0,
                    &BytesCopied);
                        
        Irp->IoStatus.Information = BytesCopied;
        break;

    case TDI_QUERY_DATAGRAM_INFO:

        DatagramInfo.MaximumDatagramBytes = 0;
        DatagramInfo.MaximumDatagramCount = 0;

        status = TdiCopyBufferToMdl (
                    &DatagramInfo,
                    0,
                    sizeof(DatagramInfo),
                    Irp->MdlAddress,
                    0,
                    &BytesCopied);
                        
        Irp->IoStatus.Information = BytesCopied;
        break;

    default:
        status = STATUS_INVALID_DEVICE_REQUEST;
        break;
    }

    return status;

} /* LpxTdiQueryInformation */