mirror of
https://github.com/SoftEtherVPN/SoftEtherVPN.git
synced 2024-11-26 11:29:53 +03:00
ac865f04fc
* spelling: accepts * spelling: account * spelling: accept * spelling: accumulate * spelling: adapter * spelling: address * spelling: additional * spelling: aggressive * spelling: adhered * spelling: allowed * spelling: ambiguous * spelling: amount * spelling: anonymous * spelling: acquisition * spelling: assemble * spelling: associated * spelling: assigns * spelling: attach * spelling: attempt * spelling: attribute * spelling: authenticate * spelling: authentication * spelling: available * spelling: bridging * spelling: cascade * spelling: cancel * spelling: check * spelling: challenge * spelling: changing * spelling: characters * spelling: cloud * spelling: compare * spelling: communication * spelling: compatible * spelling: compatibility * spelling: completion * spelling: complete * spelling: computers * spelling: configure * spelling: configuration * spelling: conformant * spelling: connection * spelling: contains * spelling: continuously * spelling: continue * spelling: convert * spelling: counters * spelling: create * spelling: created * spelling: cumulate * spelling: currently * spelling: debugging * spelling: decryption * spelling: description * spelling: default * spelling: driver * spelling: delete * spelling: destination * spelling: disabled * spelling: different * spelling: dynamically * spelling: directory * spelling: disappeared * spelling: disable * spelling: doesn't * spelling: download * spelling: dropped * spelling: enable * spelling: established * spelling: ether * spelling: except * spelling: expired * spelling: field * spelling: following * spelling: forever * spelling: firewall * spelling: first * spelling: fragment * spelling: function * spelling: gateway * spelling: identifier * spelling: identify * spelling: incoming * spelling: information * spelling: initialize * spelling: injection * spelling: inner * spelling: instead * spelling: installation * spelling: inserted * spelling: integer * spelling: interrupt * spelling: intuitive * spelling: interval * spelling: january * spelling: keybytes * spelling: know * spelling: language * spelling: length * spelling: library * spelling: listener * spelling: maintain * spelling: modified * spelling: necessary * spelling: number * spelling: obsoleted * spelling: occurred * spelling: occurring * spelling: occur * spelling: original * spelling: omittable * spelling: omit * spelling: opening * spelling: operation * spelling: packet * spelling: parameters * spelling: pointed * spelling: popupmenuopen * spelling: privilege * spelling: product * spelling: protection * spelling: promiscuous * spelling: prompt * spelling: query * spelling: random * spelling: reconnection * spelling: revocation * spelling: received * spelling: red hat * spelling: registry * spelling: release * spelling: retrieve
427 lines
11 KiB
C
427 lines
11 KiB
C
/*
|
|
* Copyright (c) 1999 - 2005 NetGroup, Politecnico di Torino (Italy)
|
|
* Copyright (c) 2005 CACE Technologies, Davis (California)
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
*
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
* 3. Neither the name of the Politecnico di Torino, CACE Technologies
|
|
* nor the names of its contributors may be used to endorse or promote
|
|
* products derived from this software without specific prior written
|
|
* permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*
|
|
*/
|
|
|
|
#include <GlobalConst.h>
|
|
|
|
#include "stdarg.h"
|
|
#include "ntddk.h"
|
|
#include "ntiologc.h"
|
|
#include "ndis.h"
|
|
|
|
#include "debug.h"
|
|
#include "packet.h"
|
|
|
|
|
|
void *test_addr = NULL;
|
|
|
|
//-------------------------------------------------------------------
|
|
|
|
NTSTATUS
|
|
NPF_Write(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp
|
|
)
|
|
|
|
{
|
|
POPEN_INSTANCE Open;
|
|
PIO_STACK_LOCATION IrpSp;
|
|
PNDIS_PACKET pPacket;
|
|
UINT i;
|
|
NDIS_STATUS Status;
|
|
|
|
IF_LOUD(DbgPrint("NPF_Write\n");)
|
|
|
|
IrpSp = IoGetCurrentIrpStackLocation(Irp);
|
|
|
|
|
|
Open=IrpSp->FileObject->FsContext;
|
|
|
|
if( Open->Bound == FALSE )
|
|
{
|
|
// The Network adapter was removed.
|
|
EXIT_FAILURE(0);
|
|
}
|
|
|
|
NdisAcquireSpinLock(&Open->WriteLock);
|
|
if(Open->WriteInProgress)
|
|
{
|
|
// Another write operation is currently in progress
|
|
NdisReleaseSpinLock(&Open->WriteLock);
|
|
EXIT_FAILURE(0);
|
|
}
|
|
else
|
|
{
|
|
Open->WriteInProgress = TRUE;
|
|
}
|
|
|
|
NdisReleaseSpinLock(&Open->WriteLock);
|
|
|
|
IF_LOUD(DbgPrint("Max frame size = %d, packet size = %d\n", Open->MaxFrameSize, IrpSp->Parameters.Write.Length);)
|
|
|
|
|
|
if(IrpSp->Parameters.Write.Length == 0 || // Check that the buffer provided by the user is not empty
|
|
Open->MaxFrameSize == 0/* || // Check that the MaxFrameSize is correctly initialized
|
|
IrpSp->Parameters.Write.Length > Open->MaxFrameSize*/) // Check that the fame size is smaller that the MTU
|
|
{
|
|
IF_LOUD(DbgPrint("frame size out of range, send aborted\n");)
|
|
|
|
EXIT_FAILURE(0);
|
|
}
|
|
|
|
|
|
IoMarkIrpPending(Irp);
|
|
|
|
Open->Multiple_Write_Counter=Open->Nwrites;
|
|
|
|
NdisResetEvent(&Open->WriteEvent);
|
|
|
|
|
|
for(i=0;i<Open->Nwrites;i++){
|
|
|
|
// Try to get a packet from our list of free ones
|
|
NdisAllocatePacket(
|
|
&Status,
|
|
&pPacket,
|
|
Open->PacketPool
|
|
);
|
|
|
|
if (Status != NDIS_STATUS_SUCCESS) {
|
|
|
|
// No free packets
|
|
Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
|
|
IoCompleteRequest (Irp, IO_NO_INCREMENT);
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
if(Open->SkipSentPackets)
|
|
{
|
|
NdisSetPacketFlags(
|
|
pPacket,
|
|
g_SendPacketFlags);
|
|
}
|
|
|
|
// The packet hasn't a buffer that needs not to be freed after every single write
|
|
RESERVED(pPacket)->FreeBufAfterWrite = FALSE;
|
|
|
|
// Save the IRP associated with the packet
|
|
RESERVED(pPacket)->Irp=Irp;
|
|
|
|
// Attach the writes buffer to the packet
|
|
NdisChainBufferAtFront(pPacket,Irp->MdlAddress);
|
|
|
|
test_addr = MmGetMdlVirtualAddress(Irp->MdlAddress);
|
|
|
|
// Call the MAC
|
|
NdisSend(
|
|
&Status,
|
|
Open->AdapterHandle,
|
|
pPacket);
|
|
|
|
if (Status != NDIS_STATUS_PENDING) {
|
|
// The send didn't pend so call the completion handler now
|
|
NPF_SendComplete(
|
|
Open,
|
|
pPacket,
|
|
Status
|
|
);
|
|
|
|
}
|
|
|
|
if(i%100==99){
|
|
NdisWaitEvent(&Open->WriteEvent,1000);
|
|
NdisResetEvent(&Open->WriteEvent);
|
|
}
|
|
}
|
|
|
|
return(STATUS_PENDING);
|
|
}
|
|
|
|
//-------------------------------------------------------------------
|
|
|
|
INT
|
|
NPF_BufferedWrite(
|
|
IN PIRP Irp,
|
|
IN PCHAR UserBuff,
|
|
IN ULONG UserBuffSize,
|
|
BOOLEAN Sync)
|
|
{
|
|
POPEN_INSTANCE Open;
|
|
PIO_STACK_LOCATION IrpSp;
|
|
PNDIS_PACKET pPacket;
|
|
NDIS_STATUS Status;
|
|
struct sf_pkthdr *winpcap_hdr;
|
|
PMDL TmpMdl;
|
|
PCHAR EndOfUserBuff = UserBuff + UserBuffSize;
|
|
|
|
IF_LOUD(DbgPrint("NPF: BufferedWrite, UserBuff=%x, Size=%u\n", UserBuff, UserBuffSize);)
|
|
|
|
IrpSp = IoGetCurrentIrpStackLocation(Irp);
|
|
|
|
Open=IrpSp->FileObject->FsContext;
|
|
|
|
if( Open->Bound == FALSE ){
|
|
// The Network adapter was removed.
|
|
return 0;
|
|
}
|
|
|
|
// Sanity check on the user buffer
|
|
if(UserBuff == NULL)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
// Check that the MaxFrameSize is correctly initialized
|
|
if(Open->MaxFrameSize == 0)
|
|
{
|
|
IF_LOUD(DbgPrint("BufferedWrite: Open->MaxFrameSize not initialized, probably because of a problem in the OID query\n");)
|
|
|
|
return 0;
|
|
}
|
|
|
|
// Reset the event used to synchronize packet allocation
|
|
NdisResetEvent(&Open->WriteEvent);
|
|
|
|
// Reset the pending packets counter
|
|
Open->Multiple_Write_Counter = 0;
|
|
|
|
// Start from the first packet
|
|
winpcap_hdr = (struct sf_pkthdr*)UserBuff;
|
|
|
|
// Check the consistency of the user buffer
|
|
if( (PCHAR)winpcap_hdr + winpcap_hdr->caplen + sizeof(struct sf_pkthdr) > EndOfUserBuff )
|
|
{
|
|
IF_LOUD(DbgPrint("Buffered Write: bogus packet buffer\n");)
|
|
|
|
return -1;
|
|
}
|
|
|
|
//
|
|
// Main loop: send the buffer to the wire
|
|
//
|
|
while(TRUE)
|
|
{
|
|
|
|
if(winpcap_hdr->caplen ==0/* || winpcap_hdr->caplen > Open->MaxFrameSize*/)
|
|
{
|
|
// Malformed header
|
|
IF_LOUD(DbgPrint("NPF_BufferedWrite: malformed or bogus user buffer, aborting write.\n");)
|
|
|
|
return -1;
|
|
}
|
|
|
|
// Allocate an MDL to map the packet data
|
|
TmpMdl = IoAllocateMdl((PCHAR)winpcap_hdr + sizeof(struct sf_pkthdr),
|
|
winpcap_hdr->caplen,
|
|
FALSE,
|
|
FALSE,
|
|
NULL);
|
|
|
|
if (TmpMdl == NULL)
|
|
{
|
|
// Unable to map the memory: packet lost
|
|
IF_LOUD(DbgPrint("NPF_BufferedWrite: unable to allocate the MDL.\n");)
|
|
|
|
return -1;
|
|
}
|
|
|
|
MmBuildMdlForNonPagedPool(TmpMdl); // XXX can this line be removed?
|
|
|
|
// Allocate a packet from our free list
|
|
NdisAllocatePacket( &Status, &pPacket, Open->PacketPool);
|
|
|
|
if (Status != NDIS_STATUS_SUCCESS) {
|
|
// No more free packets
|
|
IF_LOUD(DbgPrint("NPF_BufferedWrite: no more free packets, returning.\n");)
|
|
|
|
NdisResetEvent(&Open->WriteEvent);
|
|
|
|
NdisWaitEvent(&Open->WriteEvent, 1000);
|
|
|
|
// Try again to allocate a packet
|
|
NdisAllocatePacket( &Status, &pPacket, Open->PacketPool);
|
|
|
|
if (Status != NDIS_STATUS_SUCCESS) {
|
|
// Second failure, report an error
|
|
IoFreeMdl(TmpMdl);
|
|
return -1;
|
|
}
|
|
|
|
// IoFreeMdl(TmpMdl);
|
|
// return (PCHAR)winpcap_hdr - UserBuff;
|
|
}
|
|
|
|
if(Open->SkipSentPackets)
|
|
{
|
|
NdisSetPacketFlags(
|
|
pPacket,
|
|
g_SendPacketFlags);
|
|
}
|
|
|
|
// The packet has a buffer that needs to be freed after every single write
|
|
RESERVED(pPacket)->FreeBufAfterWrite = TRUE;
|
|
|
|
TmpMdl->Next = NULL;
|
|
|
|
// Attach the MDL to the packet
|
|
NdisChainBufferAtFront(pPacket, TmpMdl);
|
|
|
|
// Increment the number of pending sends
|
|
InterlockedIncrement(&Open->Multiple_Write_Counter);
|
|
|
|
// Call the MAC
|
|
NdisSend( &Status, Open->AdapterHandle, pPacket);
|
|
|
|
if (Status != NDIS_STATUS_PENDING) {
|
|
// The send didn't pend so call the completion handler now
|
|
NPF_SendComplete(
|
|
Open,
|
|
pPacket,
|
|
Status
|
|
);
|
|
}
|
|
|
|
// Step to the next packet in the buffer
|
|
(PCHAR)winpcap_hdr += winpcap_hdr->caplen + sizeof(struct sf_pkthdr);
|
|
|
|
// Check if the end of the user buffer has been reached
|
|
if( (PCHAR)winpcap_hdr >= EndOfUserBuff )
|
|
{
|
|
IF_LOUD(DbgPrint("NPF_BufferedWrite: End of buffer.\n");)
|
|
|
|
// Wait the completion of pending sends
|
|
NPF_WaitEndOfBufferedWrite(Open);
|
|
|
|
return (INT)((PCHAR)winpcap_hdr - UserBuff);
|
|
}
|
|
|
|
}
|
|
|
|
return (INT)((PCHAR)winpcap_hdr - UserBuff);
|
|
}
|
|
|
|
//-------------------------------------------------------------------
|
|
|
|
VOID NPF_WaitEndOfBufferedWrite(POPEN_INSTANCE Open)
|
|
{
|
|
UINT i;
|
|
|
|
NdisResetEvent(&Open->WriteEvent);
|
|
|
|
for(i=0; Open->Multiple_Write_Counter > 0 && i < TRANSMIT_PACKETS; i++)
|
|
{
|
|
NdisWaitEvent(&Open->WriteEvent, 100);
|
|
NdisResetEvent(&Open->WriteEvent);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
//-------------------------------------------------------------------
|
|
|
|
VOID
|
|
NPF_SendComplete(
|
|
IN NDIS_HANDLE ProtocolBindingContext,
|
|
IN PNDIS_PACKET pPacket,
|
|
IN NDIS_STATUS Status
|
|
)
|
|
|
|
{
|
|
PIRP Irp;
|
|
PIO_STACK_LOCATION irpSp;
|
|
POPEN_INSTANCE Open;
|
|
PMDL TmpMdl;
|
|
|
|
IF_LOUD(DbgPrint("NPF: SendComplete, BindingContext=%d\n",ProtocolBindingContext);)
|
|
|
|
Open= (POPEN_INSTANCE)ProtocolBindingContext;
|
|
|
|
if( RESERVED(pPacket)->FreeBufAfterWrite )
|
|
{
|
|
//
|
|
// Packet sent by NPF_BufferedWrite()
|
|
//
|
|
|
|
|
|
// Free the MDL associated with the packet
|
|
NdisUnchainBufferAtFront(pPacket, &TmpMdl);
|
|
|
|
IoFreeMdl(TmpMdl);
|
|
|
|
// recyle the packet
|
|
// NdisReinitializePacket(pPacket);
|
|
|
|
NdisFreePacket(pPacket);
|
|
|
|
// Increment the number of pending sends
|
|
InterlockedDecrement(&Open->Multiple_Write_Counter);
|
|
|
|
NdisSetEvent(&Open->WriteEvent);
|
|
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Packet sent by NPF_Write()
|
|
//
|
|
|
|
if((Open->Nwrites - Open->Multiple_Write_Counter) %100 == 99)
|
|
NdisSetEvent(&Open->WriteEvent);
|
|
|
|
Open->Multiple_Write_Counter--;
|
|
|
|
if(Open->Multiple_Write_Counter == 0){
|
|
// Release the buffer and awake the application
|
|
NdisUnchainBufferAtFront(pPacket, &TmpMdl);
|
|
|
|
// Complete the request
|
|
Irp=RESERVED(pPacket)->Irp;
|
|
irpSp = IoGetCurrentIrpStackLocation(Irp);
|
|
|
|
Irp->IoStatus.Status = Status;
|
|
Irp->IoStatus.Information = irpSp->Parameters.Write.Length;
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
|
|
NdisAcquireSpinLock(&Open->WriteLock);
|
|
Open->WriteInProgress = FALSE;
|
|
NdisReleaseSpinLock(&Open->WriteLock);
|
|
}
|
|
|
|
// Put the packet back on the free list
|
|
NdisFreePacket(pPacket);
|
|
|
|
return;
|
|
}
|
|
|
|
}
|