1
0
mirror of https://github.com/SoftEtherVPN/SoftEtherVPN.git synced 2024-11-26 19:39:53 +03:00
SoftEtherVPN/src/See/Write.c
Josh Soref ac865f04fc Correct Spelling (#458)
* 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
2018-05-16 23:47:10 +02:00

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;
}
}