D
DJ6674
Unregistered / Unconfirmed
GUEST, unregistred user!
谢谢爱元元的哥哥。
我不是做商用开发,做毕业设计而已。
我不是做商用开发,做毕业设计而已。
Copyright (c) 1997 BY Simahuapeng
Module Name:
miniport.c
--*/
#include "precomp.h"
#include "util.h"
#include "pcaenet.h"
#include "ethertype.h"
#include "DDKLBLInc.h"
#include "cons_def.h"
#pragma hdrstop
//extern FAST_MUTEX fw_mutex;
NDIS_STATUS
MPInitialize(
OUT PNDIS_STATUS OpenErrorStatus,
OUT PUINT SelectedMediumIndex,
IN PNDIS_MEDIUM MediumArray,
IN UINT MediumArraySize,
IN NDIS_HANDLE MiniportAdapterHandle,
IN NDIS_HANDLE WrapperConfigurationContext
)
/*++
Routine Description:
This is the initialize handler which gets called as a result of the BindAdapter handler
calling NdisIMInitializeDeviceInstanceEx(). The context parameter which we pass there is
the adapter structure which we retreive here. We also need to initialize the Power Management
variable.
LoadBalalncing- We keep a global list of all the passthru miniports installed and bundle
two of them together if they have the same BundleId (read from registry)
Arguments:
OpenErrorStatus Not used by us.
SelectedMediumIndex Place-holder for what media we are using
MediumArray Array of ndis media passed down to us to pick from
MediumArraySize Size of the array
MiniportAdapterHandle The handle NDIS uses to refer to us
WrapperConfigurationContext For use by NdisOpenConfiguration
Return Value:
NDIS_STATUS_SUCCESS unless something goes wrong
--*/
{
UINT i;
PADAPT pAdapt;
NDIS_STATUS Status = NDIS_STATUS_FAILURE;
NDIS_STATUS BundleStatus = NDIS_STATUS_FAILURE;
NDIS_STRING BundleUniString;
KIRQL OldIrql;
DBGPRINT("==>Passthru Initialize Miniport/n");
//
// Start off by retrieving the adapter context and storing the Miniport handle in it
//
pAdapt = NdisIMGetDeviceContext(MiniportAdapterHandle);
pAdapt->MiniportHandle = MiniportAdapterHandle;
//
// Make sure the medium saved is one of the ones being offered
//
for (i = 0; i < MediumArraySize; i++)
{
if (MediumArray[i] == pAdapt->Medium)
{
*SelectedMediumIndex = i;
break;
}
}
if (i == MediumArraySize)
{
return(NDIS_STATUS_UNSUPPORTED_MEDIA);
}
//
// Set the attributes now. The NDIS_ATTRIBUTE_DESERIALIZE is the key. This enables us
// to make up-calls to NDIS w/o having to call NdisIMSwitchToMiniport/NdisIMQueueCallBack.
// This also forces us to protect our data using spinlocks where appropriate. Also in this
// case NDIS does not queue packets on out behalf. Since this is a very simple pass-thru
// miniport, we do not have a need to protect anything. However in a general case there
// will be a need to use per-adapter spin-locks for the packet queues at the very least.
//
NdisMSetAttributesEx(MiniportAdapterHandle,
pAdapt,
0, // CheckForHangTimeInSeconds
NDIS_ATTRIBUTE_IGNORE_PACKET_TIMEOUT |
NDIS_ATTRIBUTE_IGNORE_REQUEST_TIMEOUT|
NDIS_ATTRIBUTE_INTERMEDIATE_DRIVER |
NDIS_ATTRIBUTE_DESERIALIZE |
NDIS_ATTRIBUTE_NO_HALT_ON_SUSPEND,
0);
//
// Setting up the default value for the Device State Flag as PM capable
// initialize the PM Variable, (for both miniport and the protocol) Device is ON by default
//
pAdapt->MPDeviceState=NdisDeviceStateD0;
pAdapt->PTDeviceState=NdisDeviceStateD0;
//
// Begin the Load Balancing and Bundle Identifier work here
// Default case: the miniport is the primary miniport
//
pAdapt->isSecondary = FALSE; // default - primary
pAdapt->pPrimaryAdapt = pAdapt; //default, point to self
pAdapt->pSecondaryAdapt = pAdapt; //default, point to self
//
// Set miniport as a secondary miniport, if need be
//
BundleStatus = MPBundleSearchAndSetSecondary (pAdapt);
//
// Inserting into our global Passthru pAdapt List
//
KeAcquireSpinLock (&pAdapt->SpinLock, &OldIrql);
pAdapt->Next = pAdaptList;
pAdaptList = pAdapt;
KeReleaseSpinLock (&pAdapt->SpinLock, OldIrql);
//
// We are done, In current implementation, Bundle Status does not affect the success of initialization
//
Status = NDIS_STATUS_SUCCESS;
DBGPRINT("<== Passthru Initialize Miniport/n");
return Status;
}
NDIS_STATUS
MPSend(
IN NDIS_HANDLE MiniportAdapterContext,
IN PNDIS_PACKET Packet,
IN UINT Flags
)
/*++
Routine Description:
Send handler. Just re-wrap the packet and send it below. Re-wrapping is necessary since
NDIS uses the WrapperReserved for its own use.
LBFO- All sends will be done in the secondary miniport of the bundle.
We are using the Secondary Miniport as the Send path. All sends should use that pAdapt structure.
Arguments:
MiniportAdapterContext Pointer to the adapter
Packet Packet to send
Flags Unused, passed down below
Return Value:
Return code from NdisSend
--*/
{
PADAPT pAdapt = (PADAPT)MiniportAdapterContext;
NDIS_STATUS Status;
PNDIS_PACKET MyPacket;
PRSVD Rsvd;
PVOID MediaSpecificInfo = NULL;
ULONG MediaSpecificInfoSize = 0;
//add by qsc
USHORT nEtherType, nIPhdrLen, nTCPhdrLen, nICMPhdrLen;
ULONG nNumberOfBytesRead = 0;
ULONG nIPSrcAddress, nIPSrcAddrOffset;
ULONG nIPDstAddress, nIPDstAddrOffset;
UCHAR nProtocol;
ULONG nProtocolAddrOffset;
UCHAR nMatch;
//end add
//add by df
KIRQL oldirql;
//
// According to our LBFO design, all sends will be performed on the secondary miniport
// However, the must be completed on the primary's miniport handle
//
ASSERT (pAdapt->pSecondaryAdapt);
pAdapt = pAdapt->pSecondaryAdapt;
if (IsIMDeviceStateOn (pAdapt) == FALSE)
{
return NDIS_STATUS_FAILURE;
}
//-----------------------------------------------------------add by qsc
//ExAcquireFastMutex(&fw_mutex); //add by df
//attantion
//ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
//KeRaiseIrql(DISPATCH_LEVEL, &oldirql);
nMatch=UTIL_MatchRule(Packet, DT_OUT);
//KeLowerIrql(oldirql);
//ExReleaseFastMutex(&fw_mutex); //add by df
if(nMatch==DENY)
return NDIS_STATUS_SUCCESS;
//----------------------------------------------------------------------end add
NdisAllocatePacket(&Status,
&MyPacket,
pAdapt->SendPacketPoolHandle);
if (Status == NDIS_STATUS_SUCCESS)
{
PNDIS_PACKET_EXTENSION Old, New;
Rsvd = (PRSVD)(MyPacket->ProtocolReserved);
Rsvd->OriginalPkt = Packet;
MyPacket->Private.Flags = Flags;
MyPacket->Private.Head = Packet->Private.Head;
MyPacket->Private.Tail = Packet->Private.Tail;
NdisSetPacketFlags(MyPacket, NDIS_FLAGS_DONT_LOOPBACK);
//
// Copy the OOB Offset from the original packet to the new
// packet.
//
NdisMoveMemory(NDIS_OOB_DATA_FROM_PACKET(MyPacket),
NDIS_OOB_DATA_FROM_PACKET(Packet),
sizeof(NDIS_PACKET_OOB_DATA));
//
// Copy the per packet info into the new packet
// This includes ClassificationHandle, etc.
// Make sure other stuff is not copied !!!
//
NdisIMCopySendPerPacketInfo(MyPacket, Packet);
//
// Copy the Media specific information
//
NDIS_GET_PACKET_MEDIA_SPECIFIC_INFO(Packet,
&MediaSpecificInfo,
&MediaSpecificInfoSize);
if (MediaSpecificInfo || MediaSpecificInfoSize)
{
NDIS_SET_PACKET_MEDIA_SPECIFIC_INFO(MyPacket,
MediaSpecificInfo,
MediaSpecificInfoSize);
}
NdisSend(&Status,
pAdapt->BindingHandle,
MyPacket);
if (Status != NDIS_STATUS_PENDING)
{
NdisIMCopySendCompletePerPacketInfo (Packet, MyPacket);
NdisFreePacket(MyPacket);
}
}
else
{
//
// We are out of packets. Silently drop it. Alternatively we can deal with it:
// - By keeping separate send and receive pools
// - Dynamically allocate more pools as needed and free them when not needed
//
}
return(Status);
}
VOID
MPSendPackets(
IN NDIS_HANDLE MiniportAdapterContext,
IN PPNDIS_PACKET PacketArray,
IN UINT NumberOfPackets
)
/*++
Routine Description:
Batched send-handler. TBD. Either this or the Send function can be specified but not both.
LBFO - The Send will be done on the secondary miniport of the bundle
Arguments:
MiniportAdapterContext Pointer to our adapter
PacketArray Set of packets to send
NumberOfPackets Self-explanatory
Return Value:
None
--*/
{
PADAPT pAdapt = (PADAPT)MiniportAdapterContext;
NDIS_STATUS Status;
UINT i;
PVOID MediaSpecificInfo = NULL;
UINT MediaSpecificInfoSize = 0;
//
// Route all sends to the seondary, if no secondary exists, it will point to itself
//
pAdapt = pAdapt->pSecondaryAdapt;
for (i = 0; i < NumberOfPackets; i++)
{
PRSVD Rsvd;
PNDIS_PACKET Packet, MyPacket;
Packet = PacketArray[i];
if (IsIMDeviceStateOn(pAdapt) == FALSE)
{
Status = NDIS_STATUS_FAILURE;
break;
}
NdisAllocatePacket(&Status,
&MyPacket,
pAdapt->SendPacketPoolHandle);
if (Status == NDIS_STATUS_SUCCESS)
{
PNDIS_PACKET_EXTENSION Old, New;
Rsvd = (PRSVD)(MyPacket->ProtocolReserved);
Rsvd->OriginalPkt = Packet;
MyPacket->Private.Flags = NdisGetPacketFlags(Packet);
MyPacket->Private.Head = Packet->Private.Head;
MyPacket->Private.Tail = Packet->Private.Tail;
NdisSetPacketFlags(MyPacket, NDIS_FLAGS_DONT_LOOPBACK);
//
// Copy the OOB Offset from the original packet to the new
// packet.
//
NdisMoveMemory(NDIS_OOB_DATA_FROM_PACKET(MyPacket),
NDIS_OOB_DATA_FROM_PACKET(Packet),
sizeof(NDIS_PACKET_OOB_DATA));
//
// Copy the per packet info into the new packet
// This includes ClassificationHandle, etc.
// Make sure other stuff is not copied !!!
//
NdisIMCopySendPerPacketInfo(MyPacket, Packet);
//
// Copy the Media specific information
//
NDIS_GET_PACKET_MEDIA_SPECIFIC_INFO(Packet,
&MediaSpecificInfo,
&MediaSpecificInfoSize);
if (MediaSpecificInfo || MediaSpecificInfoSize)
{
NDIS_SET_PACKET_MEDIA_SPECIFIC_INFO(MyPacket,
MediaSpecificInfo,
MediaSpecificInfoSize);
}
NdisSend(&Status,
pAdapt->BindingHandle,
MyPacket);
if (Status != NDIS_STATUS_PENDING)
{
NdisIMCopySendCompletePerPacketInfo (Packet, MyPacket);
NdisFreePacket(MyPacket);
}
}
if (Status != NDIS_STATUS_PENDING)
{
//
// We are out of packets. Silently drop it. Alternatively we can deal with it:
// - By keeping separate send and receive pools
// - Dynamically allocate more pools as needed and free them when not needed
//
NdisMSendComplete(pAdapt->pPrimaryAdapt->MiniportHandle,
Packet,
Status);
// LBFO - Complete with the prmary's miniport handle
// We should use the miniport handle that was used to call this function
}
}
}
NDIS_STATUS
MPQueryInformation(
IN NDIS_HANDLE MiniportAdapterContext,
IN NDIS_OID Oid,
IN PVOID InformationBuffer,
IN ULONG InformationBufferLength,
OUT PULONG BytesWritten,
OUT PULONG BytesNeeded
)
/*++
Routine Description:
Miniport QueryInfo handler.
In the Power Management scenario, OID_PNP_QUERY_POWER is not sent to the underlying miniport.
OID_PNP_CAPABILITES is passed as a request to the miniport below.
If the result is a success then the InformationBuffer is filled in the MPQueryPNPCapabilites.
LBFO - For present all queries are passed on to the miniports that they were requested on.
PM- If the MP is not ON (DeviceState > D0) return immediately (except for query power and set power)
If MP is ON, but the PT is not at D0, then queue the queue the request for later processing
Requests to miniports are always serialized
Arguments:
MiniportAdapterContext Pointer to the adapter structure
Oid Oid for this query
InformationBuffer Buffer for information
InformationBufferLength Size of this buffer
BytesWritten Specifies how much info is written
BytesNeeded In case the buffer is smaller than what we need, tell them how much is needed
Return Value:
Return code from the NdisRequest below.
--*/
{
PADAPT pAdapt = (PADAPT)MiniportAdapterContext;
NDIS_STATUS Status = NDIS_STATUS_FAILURE;
do
{
//
// Return Success for this OID
//
if (Oid == OID_PNP_QUERY_POWER)
{
Status=NDIS_STATUS_SUCCESS;
break;
}
//
// All other queries are failed, if the miniport is not at D0
//
if (pAdapt->MPDeviceState > NdisDeviceStateD0 || pAdapt->StandingBy == TRUE)
{
Status = NDIS_STATUS_FAILURE;
break;
}
//
// We are doing all sends on the secondary, so send all requests with Send OIDs to the Secondary
//
if (MPIsSendOID(Oid))
{
pAdapt = pAdapt->pSecondaryAdapt;
//
// Will point to itself, if there is no secondary (see initialization)
//
}
pAdapt->Request.RequestType = NdisRequestQueryInformation;
pAdapt->Request.DATA.QUERY_INFORMATION.Oid = Oid;
pAdapt->Request.DATA.QUERY_INFORMATION.InformationBuffer = InformationBuffer;
pAdapt->Request.DATA.QUERY_INFORMATION.InformationBufferLength = InformationBufferLength;
pAdapt->BytesNeeded = BytesNeeded;
pAdapt->BytesReadOrWritten = BytesWritten;
pAdapt->OutstandingRequests = TRUE;
//
// if the Protocol device state is OFF, then the IM driver cannot send the request below and must pend it
//
if (pAdapt->PTDeviceState > NdisDeviceStateD0)
{
pAdapt->QueuedRequest = TRUE;
Status = NDIS_STATUS_PENDING;
break;
}
//
// default case, most requests will be passed to the miniport below
//
NdisRequest(&Status,
pAdapt->BindingHandle,
&pAdapt->Request);
//
// If the Query was a success, pass the results back to the entity that made the request
//
if (Status == NDIS_STATUS_SUCCESS)
{
*BytesWritten = pAdapt->Request.DATA.QUERY_INFORMATION.BytesWritten;
*BytesNeeded = pAdapt->Request.DATA.QUERY_INFORMATION.BytesNeeded;
}
//
// Fill the buffer with the required values if Oid == OID_PNP_CAPABILITIES
// and the query was successful
//
if (Oid == OID_PNP_CAPABILITIES && Status == NDIS_STATUS_SUCCESS)
{
MPQueryPNPCapbilities(pAdapt,&Status);
}
if (Status != NDIS_STATUS_PENDING)
{
pAdapt->OutstandingRequests = FALSE;
}
} while (FALSE);
return(Status);
}
VOID
MPQueryPNPCapbilities(
IN OUT PADAPT pAdapt,
OUT PNDIS_STATUS pStatus
)
/*++
Routine Description:
Miniport QueryInfo OID_PNP_CAPAIBILITIES:
If the Oid == Oid_PNP_CAPABILITIES, InformationBuffer is returned with all the fields
assigned NdisDeviceStateUnspecified in the NDIS_PM_WAKE_UP_CAPABILITIES structure
OID_QUERY_POWER_STATE is returned with NDIS_STATUS_SUCCESS and should never be passed below.
Arguments:
MiniportAdapterContext Pointer to the adapter structure
Oid Oid for this query
InformationBuffer Buffer for information
InformationBufferLength Size of this buffer
BytesWritten Specifies how much info is written
BytesNeeded In case the buffer is smaller than what we need, tell them how much is needed
Return Value:
Return code from the NdisRequest below.
--*/
{
PNDIS_PNP_CAPABILITIES pPNPCapabilities;
PNDIS_PM_WAKE_UP_CAPABILITIES pPMstruct;
if (pAdapt->Request.DATA.QUERY_INFORMATION.InformationBufferLength >= sizeof(NDIS_PNP_CAPABILITIES))
{
pPNPCapabilities = (PNDIS_PNP_CAPABILITIES)(pAdapt->Request.DATA.QUERY_INFORMATION.InformationBuffer);
//
// Setting up the buffer to be returned to the Protocol above the Passthru miniport
//
pPMstruct= & pPNPCapabilities->WakeUpCapabilities;
pPMstruct->MinMagicPacketWakeUp = NdisDeviceStateUnspecified;
pPMstruct->MinPatternWakeUp = NdisDeviceStateUnspecified;
pPMstruct->MinLinkChangeWakeUp = NdisDeviceStateUnspecified;
*pAdapt->BytesReadOrWritten = sizeof(NDIS_PNP_CAPABILITIES);
*pAdapt->BytesNeeded = 0;
//
// Setting our internal flags
// Default, device is ON
//
pAdapt->MPDeviceState = NdisDeviceStateD0;
pAdapt->PTDeviceState = NdisDeviceStateD0;
*pStatus = NDIS_STATUS_SUCCESS;
}
else
{
*pAdapt->BytesNeeded= sizeof(NDIS_PNP_CAPABILITIES);
*pStatus = NDIS_STATUS_RESOURCES;
}
}
NDIS_STATUS
MPSetInformation(
IN NDIS_HANDLE MiniportAdapterContext,
IN NDIS_OID Oid,
IN PVOID InformationBuffer,
IN ULONG InformationBufferLength,
OUT PULONG BytesRead,
OUT PULONG BytesNeeded
)
/*++
Routine Description:
Miniport SetInfo handler.
In the case of OID_PNP_SET_POWER, record the power state and return the OID.
Do not pass below
If the device is suspended, do not block the SET_POWER_OID
as it is used to reactivate the Passthru miniport
PM- If the MP is not ON (DeviceState > D0) return immediately (except for 'query power' and 'set power')
If MP is ON, but the PT is not at D0, then queue the queue the request for later processing
Requests to miniports are always serialized
Arguments:
MiniportAdapterContext Pointer to the adapter structure
Oid Oid for this query
InformationBuffer Buffer for information
InformationBufferLength Size of this buffer
BytesRead Specifies how much info is read
BytesNeeded In case the buffer is smaller than what we need, tell them how much is needed
Return Value:
Return code from the NdisRequest below.
--*/
{
PADAPT pAdapt = (PADAPT)MiniportAdapterContext;
NDIS_STATUS Status;
Status = NDIS_STATUS_FAILURE;
do
{
//
// The Set Power should not be sent to the miniport below the Passthru, but is handled internally
//
if (Oid == OID_PNP_SET_POWER)
{
MPProcessSetPowerOid( &Status,
pAdapt,
InformationBuffer,
InformationBufferLength,
BytesRead,
BytesNeeded);
break;
}
//
// All other Set Information requests are failed, if the miniport is not at D0 or is transitioning to
// a device state greater than D0
//
if (pAdapt->MPDeviceState > NdisDeviceStateD0 || pAdapt->StandingBy == TRUE)
{
Status = NDIS_STATUS_FAILURE;
break;
}
// Set up the Request and return the result
pAdapt->Request.RequestType = NdisRequestSetInformation;
pAdapt->Request.DATA.SET_INFORMATION.Oid = Oid;
pAdapt->Request.DATA.SET_INFORMATION.InformationBuffer = InformationBuffer;
pAdapt->Request.DATA.SET_INFORMATION.InformationBufferLength = InformationBufferLength;
pAdapt->BytesNeeded = BytesNeeded;
pAdapt->BytesReadOrWritten = BytesRead;
pAdapt->OutstandingRequests = TRUE;
//
// if the Protocol device state is OFF, then the IM driver cannot send the request below and must pend it
//
if ( pAdapt->PTDeviceState > NdisDeviceStateD0)
{
pAdapt->QueuedRequest = TRUE;
Status = NDIS_STATUS_PENDING;
break;
}
NdisRequest(&Status,
pAdapt->BindingHandle,
&pAdapt->Request);
if (Status == NDIS_STATUS_SUCCESS)
{
*BytesRead = pAdapt->Request.DATA.SET_INFORMATION.BytesRead;
*BytesNeeded = pAdapt->Request.DATA.SET_INFORMATION.BytesNeeded;
}
if (Status != NDIS_STATUS_PENDING)
{
pAdapt->OutstandingRequests = FALSE;
}
} while (FALSE);
return(Status);
}
VOID
MPProcessSetPowerOid(
IN OUT PNDIS_STATUS pNdisStatus,
IN PADAPT pAdapt,
IN PVOID InformationBuffer,
IN ULONG InformationBufferLength,
OUT PULONG BytesRead,
OUT PULONG BytesNeeded
)
/*++
Routine Description:
This routine does all the procssing for a request with a SetPower Oid
The SampleIM miniport shoud accept the Set Power and transition to the new state
The Set Power should not be passed to the miniport below
If the IM miniport is going into a low power state, then there is no guarantee if it will ever
be asked go back to D0, before getting halted. No requests should be pended or queued.
Arguments:
IN OUT PNDIS_STATUS *pNdisStatus - Status of the operation
IN PADAPT pAdapt, - The Adapter structure
IN PVOID InformationBuffer, - The New DeviceState
IN ULONG InformationBufferLength,
OUT PULONG BytesRead, - No of bytes read
OUT PULONG BytesNeeded - No of bytes needed
Return Value:
Status - NDIS_STATUS_SUCCESS if all the wait events succeed.
--*/
{
NDIS_DEVICE_POWER_STATE NewDeviceState;
DBGPRINT ("==>MPProcessSetPowerOid");
ASSERT (InformationBuffer != NULL);
NewDeviceState = (*(PNDIS_DEVICE_POWER_STATE)InformationBuffer);
*pNdisStatus = NDIS_STATUS_FAILURE;
do
{
//
// Check for invalid length
//
if (InformationBufferLength < sizeof(NDIS_DEVICE_POWER_STATE))
{
*pNdisStatus = NDIS_STATUS_INVALID_LENGTH;
break;
}
//
// Check for invalid device state
//
if ((pAdapt->MPDeviceState > NdisDeviceStateD0) && (NewDeviceState != NdisDeviceStateD0))
{
//
// If the miniport is in a non-D0 state, the miniport can only receive a Set Power to D0
//
ASSERT (!(pAdapt->MPDeviceState > NdisDeviceStateD0) && (NewDeviceState != NdisDeviceStateD0));
*pNdisStatus = NDIS_STATUS_FAILURE;
break;
}
//
// Is the miniport transitioning from an On (D0) state to an Low Power State (>D0)
// If so, then set the StandingBy Flag - (Block all incoming requests)
//
if (pAdapt->MPDeviceState == NdisDeviceStateD0 && NewDeviceState > NdisDeviceStateD0)
{
pAdapt->StandingBy = TRUE;
}
//
// If the miniport is transitioning from a low power state to ON (D0), then clear the StandingBy flag
// All incoming requests will be pended until the physical miniport turns ON.
//
if (pAdapt->MPDeviceState > NdisDeviceStateD0 && NewDeviceState == NdisDeviceStateD0)
{
pAdapt->StandingBy = FALSE;
}
//
// Now update the state in the pAdapt structure;
//
pAdapt->MPDeviceState = NewDeviceState;
*pNdisStatus = NDIS_STATUS_SUCCESS;
} while (FALSE);
if (*pNdisStatus == NDIS_STATUS_SUCCESS)
{
*BytesRead = sizeof(NDIS_DEVICE_POWER_STATE);
*BytesNeeded = 0;
}
else
{
*BytesRead = 0;
*BytesNeeded = sizeof (NDIS_DEVICE_POWER_STATE);
}
DBGPRINT ("<==MPProcessSetPowerOid");
}
VOID
MPReturnPacket(
IN NDIS_HANDLE MiniportAdapterContext,
IN PNDIS_PACKET Packet
)
/*++
Routine Description:
Arguments:
Return Value:
--*/
{
PADAPT pAdapt = (PADAPT)MiniportAdapterContext;
PNDIS_PACKET MyPacket;
PRSVD Resvd;
Resvd = (PRSVD)(Packet->MiniportReserved);
MyPacket = Resvd->OriginalPkt;
NdisFreePacket(Packet);
NdisReturnPackets(&MyPacket, 1);
}
NDIS_STATUS
MPTransferData(
OUT PNDIS_PACKET Packet,
OUT PUINT BytesTransferred,
IN NDIS_HANDLE MiniportAdapterContext,
IN NDIS_HANDLE MiniportReceiveContext,
IN UINT ByteOffset,
IN UINT BytesToTransfer
)
/*++
Routine Description:
Miniport's transfer data handler.
Arguments:
Packet Destination packet
BytesTransferred Place-holder for how much data was copied
MiniportAdapterContext Pointer to the adapter structure
MiniportReceiveContext Context
ByteOffset Offset into the packet for copying data
BytesToTransfer How much to copy.
Return Value:
Status of transfer
--*/
{
PADAPT pAdapt = (PADAPT)MiniportAdapterContext;
NDIS_STATUS Status;
//
// Return, if the device is OFF
//
if (IsIMDeviceStateOn(pAdapt) == FALSE)
{
return NDIS_STATUS_FAILURE;
}
//
// All receives are to be done on the primary, will point to itself
//
pAdapt = pAdapt->pPrimaryAdapt;
NdisTransferData(&Status,
pAdapt->BindingHandle,
MiniportReceiveContext,
ByteOffset,
BytesToTransfer,
Packet,
BytesTransferred);
return(Status);
}
VOID
MPHalt(
IN NDIS_HANDLE MiniportAdapterContext
)
/*++
Routine Description:
Halt handler. All the hard-work for clean-up is done here.
LBFO - the current instance of the driver needs to be removed from the gloabal list
Arguments:
MiniportAdapterContext Pointer to the Adapter
Return Value:
None.
--*/
{
PADAPT pAdapt = (PADAPT)MiniportAdapterContext;
NDIS_STATUS Status;
PADAPT pCursor, *ppCursor;
PADAPT pPromoteAdapt = NULL;
KIRQL OldIrql;
DBGPRINT ("==>Passthru MPHaltMiniport/n");
//
// Remove the pAdapt from our global list
//
// Acquire the lock and keep it untill all pointers to this pAdapt have been removed
// from the linked list
//
KeAcquireSpinLock (&pAdapt->SpinLock, &OldIrql);
//
// Remove the padapt from the list
//
for (ppCursor = &pAdaptList; *ppCursor != NULL; ppCursor = &(*ppCursor)->Next)
{
if (*ppCursor == pAdapt)
{
*ppCursor = pAdapt->Next;
break;
}
}
//
// Remove all the pointers to pAdapt from our list
//
for (pCursor = pAdaptList; pCursor != NULL; pCursor = pCursor->Next)
{
//
// Now pointers in our global list might become invalid. Checking for Primary
//
if (pCursor->pPrimaryAdapt == pAdapt)
{
ASSERT (pCursor->isSecondary == TRUE);
//
// Keep a pointer to the secondary that needs to be promoted, as it is now alone
//
pPromoteAdapt = pCursor;
}
//
// Now checking for the secondary
//
if (pCursor->pSecondaryAdapt == pAdapt)
{
ASSERT(pCursor->isSecondary == FALSE); // Assert (pCursor is Primary);
//
// This is all we need to change in our internal structure, the rest of the pointers are not invalid
//
pCursor->pSecondaryAdapt = pCursor;
}
}
KeReleaseSpinLock (&pAdapt->SpinLock, OldIrql);
//
// If there is a miniport that needs to be promoted, promote it.
// Call API outside of spin lock
//
if (pPromoteAdapt != NULL)
{
MPPromoteSecondary(pPromoteAdapt);
}
//
// If we have a valid bind, close the miniport below the protocol
//
if (pAdapt->BindingHandle != NULL)
{
//
// Close the binding below. and wait for it to complete
//
NdisResetEvent(&pAdapt->Event);
NdisCloseAdapter(&Status, pAdapt->BindingHandle);
if (Status == NDIS_STATUS_PENDING)
{
NdisWaitEvent(&pAdapt->Event, 0);
Status = pAdapt->Status;
}
ASSERT (Status == NDIS_STATUS_SUCCESS);
pAdapt->BindingHandle = NULL;
}
//
// Free the resources now
//
NdisFreePacketPool(pAdapt->SendPacketPoolHandle);
NdisFreePacketPool(pAdapt->RecvPacketPoolHandle);
NdisFreeMemory(pAdapt->BundleUniString.Buffer, MAX_BUNDLEID_LENGTH,0);
NdisFreeMemory(pAdapt, sizeof(ADAPT), 0);
DBGPRINT("<==Passthru Minport Halt/n");
}
NDIS_STATUS
MPReset(
OUT PBOOLEAN AddressingReset,
IN NDIS_HANDLE MiniportAdapterContext
)
/*++
Routine Description:
Reset Handler. We just don't do anything.
Arguments:
AddressingReset To let NDIS know whether we need help from it with our reset
MiniportAdapterContext Pointer to our adapter
Return Value:
--*/
{
PADAPT pAdapt = (PADAPT)MiniportAdapterContext;
DBGPRINT("<== Passthru Miniport Reset/n"); ;
*AddressingReset = FALSE;
return(NDIS_STATUS_SUCCESS);
}
//
// The functions that do the LBFO work and bundling.
// If LBFO is turned off, then the Set Scondary API is never called and there are no bundles
//
NDIS_STATUS
MPBundleSearchAndSetSecondary(
IN PADAPT pAdapt
)
/*++
Routine Description:
Go through the list of passthru structures and and search for an instantiation with a
matching bundleid and call MPSetMiniportSecondary on that structure
Arguments:
pAdapt - Should point to the structure that belolngs to the miniport
whose bundle id will be used in the search
Return Value:
NDIS_STATUS_SUCCESS if not operation failed. This value is also returned event if
no new bundles are formed
--*/
{
NDIS_STATUS Status = NDIS_STATUS_FAILURE;
NDIS_STRING NoBundle = NDIS_STRING_CONST ("<no-bundle>");
PADAPT pCursor = NULL;
PADAPT pPrimary = NULL;
KIRQL OldIrql;
do
{
//
// If bundle == '<bundle id>' then this Passthru miniport will not be a part of any bundle
//
if (NdisEqualUnicodeString(&NoBundle, &pAdapt->BundleUniString, TRUE))
{
Status = NDIS_STATUS_SUCCESS;
break;
}
//
// If the Bundle Identifier is not present, ie. someone entered a NULL string,
// this miniport will not be part of a bundle
//
if (pAdapt->BundleUniString.Length == 0)
{
Status = NDIS_STATUS_SUCCESS;
break;
}
//
// Acquire the global pAdapt List lock
//
KeAcquireSpinLock (&pAdapt->SpinLock, &OldIrql);
//
// Searching through the global list for a Passthru with the same BundleId
//
for (pCursor = pAdaptList; pCursor != NULL; pCursor = pCursor->Next)
{
if (pCursor == pAdapt)
{
//
// Skip to next Passthru, if the cursor is pointing to me
//
continue;
}
//
// Do a case insenstive match, if matches, set current pAdapt as secondary
//
if (NdisEqualUnicodeString(&pCursor->BundleUniString, &pAdapt->BundleUniString, TRUE))
{
//
// Making sure this is a primary of a bundle
//
ASSERT (pCursor->pSecondaryAdapt == pCursor && pCursor->isSecondary == FALSE);
pPrimary = pCursor;
break;
}
}
//
// Release the lock, and also bring down our Irql
//
KeReleaseSpinLock (&pAdapt->SpinLock, OldIrql);
//
// Call our Set Secondary function, do not call at DISPATCH_LEVEL
//
if (pPrimary != NULL)
{
Status = MPSetMiniportSecondary (pAdapt, pPrimary);
ASSERT (Status == NDIS_STATUS_SUCCESS);
}
//
// We successsfully completed our search through the list, event if I did not find any bundles
//
Status = NDIS_STATUS_SUCCESS;
} while (FALSE) ;
return Status;
}
NDIS_STATUS
MPSetMiniportSecondary (
IN PADAPT Secondary,
IN PADAPT Primary
)
/*++
Routine Description:
Call the Ndis API to set the bundle and modify internal variables to keep track of the change
Arguments:
Secondary Should point to the structure that points to the Secondary miniport
Primary Should point to the structure that points to the Primary miniport
Return Value:
NDIS_STATUS_SUCCESS if there miniport was successfully made the secondary of the primary
--*/
{
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
//
// ensure that the 'to be' primary is not part of another bundle
//
ASSERT (Primary != Secondary);
ASSERT (Primary->isSecondary == 0);
ASSERT (Primary->pSecondaryAdapt == Primary);
#ifdef __LBFO
DBGPRINT ("Calling NdisMSetSecondary API on the two handles/n");
Status = NdisMSetMiniportSecondary(Secondary->MiniportHandle,
Primary->MiniportHandle);
ASSERT (Status == NDIS_STATUS_SUCCESS);
if (Status == NDIS_STATUS_SUCCESS)
{
//
// Initialize the LBFO variables, to record the current state.
//
//
Secondary->isSecondary = TRUE;
Secondary->pPrimaryAdapt = Primary;
Primary->pSecondaryAdapt = Secondary;
//
// Making sure that the other internal state variables have the correct value
//
Secondary->pSecondaryAdapt = Secondary;
Primary->pPrimaryAdapt = Primary;
Primary->isSecondary = FALSE;
}
#endif
return Status;
}
NDIS_STATUS
MPPromoteSecondary(
IN PADAPT pAdapt
)
/*++
Routine Description:
Does the Passthru book keeping to promote a
Passthru instantiation from a secondary to a primary miniport
Arguments:
pAdapt - Pointer to the internal adapter structure
Return Value:
NDIS_STATUS_SUCCESS - if success
Otherwise the return value of the NdisMPromoteMiniport API
--*/
{
NDIS_STATUS Status;
DBGPRINT ("==> MPPromoteMiniport/n");
Status = NdisMPromoteMiniport(pAdapt->MiniportHandle);
ASSERT (Status == NDIS_STATUS_SUCCESS);
if (Status == NDIS_STATUS_SUCCESS)
{
pAdapt->isSecondary = FALSE;
pAdapt->pPrimaryAdapt = pAdapt;
pAdapt->pSecondaryAdapt = pAdapt;
}
DBGPRINT ("<== MPPromoteMiniport/n");
return Status;
}
BOOLEAN
MPIsSendOID (
IN NDIS_OID Oid
)
/*++
Routine Description:
Indicates if an OID should be routed to the Send miniport. Right now, the list comprises of those OIDs which drivers
running ethernet must support (See General Objects in the DDK). In this implementation, all OIDS are Query Oids
Arguments:
Oid - The oid in question
Return Value:
True if Oid should be sent to the Send miniport
False if Oid should be sent to the Receive miniport - default
--*/
{
BOOLEAN fIsSend = FALSE; //default : it is a receive OID
switch (Oid)
{
//
// If OID needs to be sent to the Send miniport, set the boolean flag
//
case OID_GEN_TRANSMIT_BUFFER_SPACE :
case OID_GEN_TRANSMIT_BLOCK_SIZE :
case OID_GEN_MAXIMUM_TOTAL_SIZE :
//
// OIds used to collect transmission statistics
//
case OID_GEN_XMIT_OK :
case OID_GEN_XMIT_ERROR :
case OID_GEN_DIRECTED_BYTES_XMIT :
case OID_GEN_DIRECTED_FRAMES_XMIT :
case OID_GEN_MULTICAST_BYTES_XMIT :
case OID_GEN_MULTICAST_FRAMES_XMIT :
case OID_GEN_BROADCAST_BYTES_XMIT :
case OID_GEN_BROADCAST_FRAMES_XMIT :
case OID_GEN_TRANSMIT_QUEUE_LENGTH :
fIsSend = TRUE;
break;
default:
fIsSend = FALSE;
break;
}
return fIsSend;
}
/*++
Module Name:
protocol.c
--*/
#include "precomp.h"
#include "util.h"
#include "cons_def.h"
#pragma hdrstop
#define MAX_PACKET_POOL_SIZE 0x0000FFFF
#define MIN_PACKET_POOL_SIZE 0x000000FF
//extern FAST_MUTEX fw_mutex;
VOID
PtBindAdapter(
OUT PNDIS_STATUS Status,
IN NDIS_HANDLE BindContext,
IN PNDIS_STRING DeviceName,
IN PVOID SystemSpecific1,
IN PVOID SystemSpecific2
)
{
NDIS_HANDLE ConfigHandle = NULL;
PNDIS_CONFIGURATION_PARAMETER Param;
NDIS_STRING DeviceStr = NDIS_STRING_CONST("UpperBindings");
PADAPT pAdapt = NULL;
NDIS_STATUS Sts;
UINT MediumIndex;
PNDIS_CONFIGURATION_PARAMETER BundleParam;
NDIS_STRING BundleStr = NDIS_STRING_CONST("BundleId");
NDIS_STATUS BundleStatus;
DBGPRINT("==> Passthru Protocol Initialize/n");
do
{
//
// Start off by opening the config section and reading our instance which we want
// to export for this binding
//
NdisOpenProtocolConfiguration(Status,
&ConfigHandle,
SystemSpecific1);
if (*Status != NDIS_STATUS_SUCCESS)
{
break;
}
NdisReadConfiguration(Status,
&Param,
ConfigHandle,
&DeviceStr,
NdisParameterString);
if (*Status != NDIS_STATUS_SUCCESS)
{
break;
}
//
// Allocate memory for the Adapter structure. This represents both as the protocol-context
// as well as the adapter structure when the miniport is initialized.
//
NdisAllocateMemoryWithTag(&pAdapt, sizeof(ADAPT), TAG);
if (pAdapt == NULL)
{
*Status = NDIS_STATUS_RESOURCES;
break;
}
//
// Initialize the adapter structure
//
NdisZeroMemory(pAdapt, sizeof(ADAPT));
//
// Store the String used by the registry, this will be used in reading data from the registry
//
NdisAllocateMemoryWithTag( &(pAdapt->BundleUniString.Buffer), MAX_BUNDLEID_LENGTH ,TAG);
if (pAdapt->BundleUniString.Buffer == NULL)
{
*Status = NDIS_STATUS_RESOURCES;
break;
}
pAdapt->BundleUniString.MaximumLength = MAX_BUNDLEID_LENGTH ;
NdisReadConfiguration(&BundleStatus,
&BundleParam,
ConfigHandle,
&BundleStr,
NdisParameterString);
if (BundleStatus == NDIS_STATUS_SUCCESS)
{
//
// Copy the bundle identifier to our own memory
//
ASSERT(pAdapt->BundleUniString.MaximumLength >= BundleParam->ParameterData.StringData.Length);
pAdapt->BundleUniString.Length = BundleParam->ParameterData.StringData.Length;
RtlCopyUnicodeString(&pAdapt->BundleUniString, &BundleParam->ParameterData.StringData);
}
else
{
//
// We do not have a bundle id entry in the registry. To play safe we will enter
// make the escape sequence the Bundle Id, This ensures that no bundle id's are
// spuriously formed
//
NDIS_STRING NoBundle = NDIS_STRING_CONST ("<no-bundle>");
RtlCopyUnicodeString(&pAdapt->BundleUniString, &NoBundle);
}
//
// Initializing the Event and the lock
//
NdisInitializeEvent(&pAdapt->Event);
KeInitializeSpinLock(&pAdapt->SpinLock);
//
// Allocate a packet pool for sends. We need this to pass sends down. We cannot use the same
// packet descriptor that came down to our send handler
//
NdisAllocatePacketPoolEx(Status,
&pAdapt->SendPacketPoolHandle,
MIN_PACKET_POOL_SIZE,
MAX_PACKET_POOL_SIZE - MIN_PACKET_POOL_SIZE,
sizeof(RSVD));
if (*Status != NDIS_STATUS_SUCCESS)
{
break;
}
//
// Allocate a packet pool for receives. We need this to indicate receives. Same consideration
// as sends
//
NdisAllocatePacketPoolEx(Status,
&pAdapt->RecvPacketPoolHandle,
MIN_PACKET_POOL_SIZE,
MAX_PACKET_POOL_SIZE - MIN_PACKET_POOL_SIZE,
sizeof(RSVD));
if (*Status != NDIS_STATUS_SUCCESS)
{
break;
}
//
// Now open the adapter below and complete the initialization
//
NdisOpenAdapter(Status,
&Sts,
&pAdapt->BindingHandle,
&MediumIndex,
MediumArray,
sizeof(MediumArray)/sizeof(NDIS_MEDIUM),
ProtHandle,
pAdapt,
DeviceName,
0,
NULL);
if(*Status == NDIS_STATUS_PENDING)
{
NdisWaitEvent(&pAdapt->Event, 0);
*Status = pAdapt->Status;
}
if(*Status != NDIS_STATUS_SUCCESS)
{
break;
}
pAdapt->Medium = MediumArray[MediumIndex];
//
// Now ask NDIS to initialize our miniport
//
NdisIMInitializeDeviceInstanceEx(DriverHandle,
&Param->ParameterData.StringData,
pAdapt);
} while(FALSE);
if (ConfigHandle != NULL)
{
NdisCloseConfiguration(ConfigHandle);
}
if (*Status != NDIS_STATUS_SUCCESS)
{
if (pAdapt != NULL)
{
if (pAdapt->SendPacketPoolHandle != NULL)
{
NdisFreePacketPool(pAdapt->SendPacketPoolHandle);
}
if (pAdapt->RecvPacketPoolHandle != NULL)
{
NdisFreePacketPool(pAdapt->RecvPacketPoolHandle);
}
NdisFreeMemory(pAdapt, sizeof(ADAPT), 0);
}
}
DBGPRINT("<== Passthru Protocol Initialize/n");
}
VOID
PtOpenAdapterComplete(
IN NDIS_HANDLE ProtocolBindingContext,
IN NDIS_STATUS Status,
IN NDIS_STATUS OpenErrorStatus
)
{
PADAPT pAdapt =(PADAPT)ProtocolBindingContext;
DBGPRINT("==> Passthru PtOpenAdapterComplete/n");
pAdapt->Status = Status;
NdisSetEvent(&pAdapt->Event);
}
VOID
PtUnbindAdapter(
OUT PNDIS_STATUS Status,
IN NDIS_HANDLE ProtocolBindingContext,
IN NDIS_HANDLE UnbindContext
)
{
PADAPT pAdapt =(PADAPT)ProtocolBindingContext;
NDIS_HANDLE BindingHandle = pAdapt->BindingHandle;
DBGPRINT("==> Passthru PtUnbindAdapter/n");
if (pAdapt->QueuedRequest == TRUE)
{
pAdapt->QueuedRequest = FALSE;
PtRequestComplete (pAdapt,
&pAdapt->Request,
NDIS_STATUS_FAILURE );
}
//
// Call NDIS to remove our device-instance. We do most of the work inside the HaltHandler
//
// The Handle will be Null if the passthru's miniport Halt Handler has been called or
// If the IM device was never initialized
//
if(pAdapt->MiniportHandle != NULL)
{
*Status = NdisIMDeInitializeDeviceInstance(pAdapt->MiniportHandle);
if(*Status != NDIS_STATUS_SUCCESS)
{
*Status = NDIS_STATUS_FAILURE;
}
}
else
{
//
// We need to do some work here.
// Close the binding below us
// and release the memory allocated.
//
if(pAdapt->BindingHandle != NULL)
{
NdisResetEvent(&pAdapt->Event);
NdisCloseAdapter(Status, pAdapt->BindingHandle);
//
// Wait for it to complete
//
if(*Status == NDIS_STATUS_PENDING)
{
NdisWaitEvent(&pAdapt->Event, 0);
*Status = pAdapt->Status;
}
}
else
{
//
// Both Our MiniportHandle and Binding Handle should not be NULL.
//
*Status = NDIS_STATUS_FAILURE;
ASSERT(0);
}
//
// Free the memory here, if was not released earlier(by calling the HaltHandler)
//
NdisFreeMemory(pAdapt, sizeof(ADAPT), 0);
}
DBGPRINT("<==Passthru UnbindAdapter/n");
}
VOID
PtUnload(
IN PDRIVER_OBJECT DriverObject
)
{
NDIS_STATUS Status;
NdisDeregisterProtocol(&Status, ProtHandle);
}
VOID
PtCloseAdapterComplete(
IN NDIS_HANDLE ProtocolBindingContext,
IN NDIS_STATUS Status
)
{
PADAPT pAdapt =(PADAPT)ProtocolBindingContext;
pAdapt->Status = Status;
NdisSetEvent(&pAdapt->Event);
}
VOID
PtResetComplete(
IN NDIS_HANDLE ProtocolBindingContext,
IN NDIS_STATUS Status
)
{
PADAPT pAdapt =(PADAPT)ProtocolBindingContext;
//
// We never issue a reset, so we should not be here.
//
ASSERT(0);
}
VOID
PtRequestComplete(
IN NDIS_HANDLE ProtocolBindingContext,
IN PNDIS_REQUEST NdisRequest,
IN NDIS_STATUS Status
)
{
PADAPT pAdapt =(PADAPT)ProtocolBindingContext;
NDIS_OID Oid = pAdapt->Request.DATA.SET_INFORMATION.Oid ;
//
// Change to the pAdapt for which the request originated
//
if(MPIsSendOID(Oid))
{
pAdapt = pAdapt->pPrimaryAdapt;
//
// Will point to itself if there is no bundle(see initialization)
//
}
//
// Since our request is not outstanding anymore
//
pAdapt->OutstandingRequests = FALSE;
//
// Complete the Set or Query, and fill in the buffer for OID_PNP_CAPABILITIES, if need be.
//
switch(NdisRequest->RequestType)
{
case NdisRequestQueryInformation:
//
// This should not have been passsed to the miniport below us
//
ASSERT(Oid != OID_PNP_QUERY_POWER);
//
// If oid == OID_PNP_CAPABILITIES and query was successsful
// then fill the buffer with the required values
//
if(Oid == OID_PNP_CAPABILITIES && Status == NDIS_STATUS_SUCCESS)
{
MPQueryPNPCapbilities(pAdapt,&Status);
}
*pAdapt->BytesReadOrWritten = NdisRequest->DATA.QUERY_INFORMATION.BytesWritten;
*pAdapt->BytesNeeded = NdisRequest->DATA.QUERY_INFORMATION.BytesNeeded;
NdisMQueryInformationComplete(pAdapt->MiniportHandle,
Status);
break;
case NdisRequestSetInformation:
ASSERT( Oid != OID_PNP_SET_POWER);
*pAdapt->BytesReadOrWritten = NdisRequest->DATA.SET_INFORMATION.BytesRead;
*pAdapt->BytesNeeded = NdisRequest->DATA.SET_INFORMATION.BytesNeeded;
NdisMSetInformationComplete(pAdapt->MiniportHandle,
Status);
break;
default:
ASSERT(0);
break;
}
}
VOID
PtStatus(
IN NDIS_HANDLE ProtocolBindingContext,
IN NDIS_STATUS GeneralStatus,
IN PVOID StatusBuffer,
IN UINT StatusBufferSize
)
{
PADAPT pAdapt =(PADAPT)ProtocolBindingContext;
//
// If we get a status indication before our miniport is initialized, ignore it
// If the SampleIM is not ON, we do not pass on the status indication
//
if(pAdapt->MiniportHandle != NULL &&
pAdapt->MPDeviceState == NdisDeviceStateD0 &&
pAdapt->PTDeviceState == NdisDeviceStateD0 )
{
NdisMIndicateStatus(pAdapt->MiniportHandle,
GeneralStatus,
StatusBuffer,
StatusBufferSize);
}
}
VOID
PtStatusComplete(
IN NDIS_HANDLE ProtocolBindingContext
)
{
PADAPT pAdapt =(PADAPT)ProtocolBindingContext;
//
// If we get a status indication before our miniport is initialized, ignore it
//
if(pAdapt->MiniportHandle != NULL &&
pAdapt->MPDeviceState == NdisDeviceStateD0 &&
pAdapt->PTDeviceState == NdisDeviceStateD0 )
{
NdisMIndicateStatusComplete(pAdapt->MiniportHandle);
}
}
VOID
PtSendComplete(
IN NDIS_HANDLE ProtocolBindingContext,
IN PNDIS_PACKET Packet,
IN NDIS_STATUS Status
)
{
PADAPT pAdapt =(PADAPT)ProtocolBindingContext;
PNDIS_PACKET Pkt;
PRSVD Rsvd;
//
// Returning the Send on the Primary, will point to itself if there is no bundle
//
pAdapt = pAdapt->pPrimaryAdapt;
Rsvd =(PRSVD)(Packet->ProtocolReserved);
Pkt = Rsvd->OriginalPkt;
NdisIMCopySendCompletePerPacketInfo (Pkt, Packet);
NdisDprFreePacket(Packet);
NdisMSendComplete(pAdapt->MiniportHandle,
Pkt,
Status);
}
VOID
PtTransferDataComplete(
IN NDIS_HANDLE ProtocolBindingContext,
IN PNDIS_PACKET Packet,
IN NDIS_STATUS Status,
IN UINT BytesTransferred
)
{
PADAPT pAdapt =(PADAPT)ProtocolBindingContext;
//
// Returning the Send on the Primary, will point to itself if there is no LBFO
//
pAdapt = pAdapt->pPrimaryAdapt;
if(pAdapt->MiniportHandle)
{
NdisMTransferDataComplete(pAdapt->MiniportHandle,
Packet,
Status,
BytesTransferred);
}
}
NDIS_STATUS
PtReceive(
IN NDIS_HANDLE ProtocolBindingContext,
IN NDIS_HANDLE MacReceiveContext,
IN PVOID HeaderBuffer,
IN UINT HeaderBufferSize,
IN PVOID LookAheadBuffer,
IN UINT LookAheadBufferSize,
IN UINT PacketSize
)
/*++
Routine Description:
LBFO - need to use primary for all receives
Arguments:
Return Value:
--*/
{
PADAPT pAdapt =(PADAPT)ProtocolBindingContext;
PNDIS_PACKET MyPacket, Packet;
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
//add by df
KIRQL oldirql;
UCHAR nMatch;
if(!pAdapt->MiniportHandle)
{
Status = NDIS_STATUS_FAILURE;
}
else do
{
//
// We should not be getting Receives on a Secondary, this is just specific to our LBFO driver
//
if(pAdapt->isSecondary)
{
DBGPRINT("PASSTHRU GETTING RECIEVES ON SECONDARY/n");
ASSERT(0);
}
//
// If this was indicated by the miniport below as a packet, then get that packet pointer and indicate
// it as a packet as well(with appropriate status). This way the OOB stuff is accessible to the
// transport above us.
//
Packet = NdisGetReceivedPacket(pAdapt->BindingHandle, MacReceiveContext);
if(Packet != NULL)
{
//
// Get a packet off the pool and indicate that up
//
NdisDprAllocatePacket(&Status,
&MyPacket,
pAdapt->RecvPacketPoolHandle);
if(Status == NDIS_STATUS_SUCCESS)
{
MyPacket->Private.Head = Packet->Private.Head;
MyPacket->Private.Tail = Packet->Private.Tail;
//
// Get the original packet(it could be the same packet as one received or a different one
// based on # of layered MPs) and set it on the indicated packet so the OOB stuff is visible
// correctly at the top.
//
NDIS_SET_ORIGINAL_PACKET(MyPacket, NDIS_GET_ORIGINAL_PACKET(Packet));
NDIS_SET_PACKET_HEADER_SIZE(MyPacket, HeaderBufferSize);
//
// Set Packet Flags
//
NdisGetPacketFlags(MyPacket) = NdisGetPacketFlags(Packet);
//-----------------------------------------------------------add by qsc
//ExAcquireFastMutex(&fw_mutex); //add by df
//ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
//KeRaiseIrql(DISPATCH_LEVEL, &oldirql);
nMatch=UTIL_MatchRule(MyPacket, DT_IN);
//KeLowerIrql(oldirql);
//ExReleaseFastMutex(&fw_mutex); //add by df
if(nMatch==DENY)
return NDIS_STATUS_SUCCESS;
//----------------------------------------------------------------------end add
//
// Make sure the status is set to NDIS_STATUS_RESOURCES.
//
NDIS_SET_PACKET_STATUS(MyPacket, NDIS_STATUS_RESOURCES);
NdisMIndicateReceivePacket(pAdapt->MiniportHandle, &MyPacket, 1);
ASSERT(NDIS_GET_PACKET_STATUS(MyPacket) == NDIS_STATUS_RESOURCES);
NdisDprFreePacket(MyPacket);
break;
}
}
//
// Fall through if the miniport below us has either not indicated a packet or we could not
// allocate one
//
pAdapt->IndicateRcvComplete = TRUE;
switch(pAdapt->Medium)
{
case NdisMedium802_3:
NdisMEthIndicateReceive(pAdapt->MiniportHandle,
MacReceiveContext,
HeaderBuffer,
HeaderBufferSize,
LookAheadBuffer,
LookAheadBufferSize,
PacketSize);
break;
case NdisMedium802_5:
NdisMTrIndicateReceive(pAdapt->MiniportHandle,
MacReceiveContext,
HeaderBuffer,
HeaderBufferSize,
LookAheadBuffer,
LookAheadBufferSize,
PacketSize);
break;
case NdisMediumFddi:
NdisMFddiIndicateReceive(pAdapt->MiniportHandle,
MacReceiveContext,
HeaderBuffer,
HeaderBufferSize,
LookAheadBuffer,
LookAheadBufferSize,
PacketSize);
break;
default:
ASSERT(0);
break;
}
} while(FALSE);
return Status;
}
VOID
PtReceiveComplete(
IN NDIS_HANDLE ProtocolBindingContext
)
/*++
Routine Description:
Called by the adapter below us when it is done indicating a batch of received buffers.
Arguments:
ProtocolBindingContext Pointer to our adapter structure.
Return Value:
None
--*/
{
PADAPT pAdapt =(PADAPT)ProtocolBindingContext;
//
// We should not be getting Receives on a Secondary, this is just specific to our LBFO driver
//
if(pAdapt->isSecondary)
{
DBGPRINT("PASSTHRU GETTING RECEIVES ON SECONDARY/n");
ASSERT(0);
}
if((pAdapt->MiniportHandle != NULL) && pAdapt->IndicateRcvComplete)
{
switch(pAdapt->Medium)
{
case NdisMedium802_3:
NdisMEthIndicateReceiveComplete(pAdapt->MiniportHandle);
break;
case NdisMedium802_5:
NdisMTrIndicateReceiveComplete(pAdapt->MiniportHandle);
break;
case NdisMediumFddi:
NdisMFddiIndicateReceiveComplete(pAdapt->MiniportHandle);
break;
default:
ASSERT(0);
break;
}
}
pAdapt->IndicateRcvComplete = FALSE;
}
INT
PtReceivePacket(
IN NDIS_HANDLE ProtocolBindingContext,
IN PNDIS_PACKET Packet
)
/*++
Routine Description:
ReceivePacket handler. Called up by the miniport below when it supports NDIS 4.0 style receives.
Re-package the packet and hand it back to NDIS for protocols above us. The re-package part is
important since NDIS uses the WrapperReserved part of the packet for its own book-keeping. Also
the re-packaging works differently when packets flow-up or down. In the up-path(here) the protocol
reserved is owned by the protocol above. We need to use the miniport reserved here.
Arguments:
ProtocolBindingContext Pointer to our adapter structure.
Packet - Pointer to the packet
Return Value:
== 0 -> We are done with the packet
!= 0 -> We will keep the packet and call NdisReturnPackets() this many times when done.
--*/
{
PADAPT pAdapt =(PADAPT)ProtocolBindingContext;
NDIS_STATUS Status;
PNDIS_PACKET MyPacket;
PRSVD Resvd;
UCHAR nMatch;
//add by df
KIRQL oldirql;
if(!pAdapt->MiniportHandle)
{
return 0;
}
//
// We should not be getting Receives on a Secondary, this is just specific to our LBFO driver
//
if(pAdapt->isSecondary)
{
DBGPRINT("PASSTHRU GETTING RECEIVES ON SECONDARY/n");
ASSERT(0);
}
//-----------------------------------------------------------add by qsc
//ExAcquireFastMutex(&fw_mutex); //add by df
//ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
//KeRaiseIrql(DISPATCH_LEVEL, &oldirql);
nMatch=UTIL_MatchRule(Packet, DT_IN);
//KeLowerIrql(oldirql);
//ExReleaseFastMutex(&fw_mutex); //add by df
if(nMatch==DENY)
return NDIS_STATUS_SUCCESS;
//----------------------------------------------------------------------end add
//
// Get a packet off the pool and indicate that up
//
NdisDprAllocatePacket(&Status,
&MyPacket,
pAdapt->RecvPacketPoolHandle);
if(Status == NDIS_STATUS_SUCCESS)
{
Resvd =(PRSVD)(MyPacket->MiniportReserved);
Resvd->OriginalPkt = Packet;
MyPacket->Private.Head = Packet->Private.Head;
MyPacket->Private.Tail = Packet->Private.Tail;
//
// Get the original packet(it could be the same packet as one received or a different one
// based on # of layered MPs) and set it on the indicated packet so the OOB stuff is visible
// correctly at the top.
//
NDIS_SET_ORIGINAL_PACKET(MyPacket, NDIS_GET_ORIGINAL_PACKET(Packet));
//
// Set Packet Flags
//
NdisGetPacketFlags(MyPacket) = NdisGetPacketFlags(Packet);
Status = NDIS_GET_PACKET_STATUS(Packet);
NDIS_SET_PACKET_STATUS(MyPacket, Status);
NDIS_SET_PACKET_HEADER_SIZE(MyPacket, NDIS_GET_PACKET_HEADER_SIZE(Packet));
NdisMIndicateReceivePacket(pAdapt->MiniportHandle, &MyPacket, 1);
if(Status == NDIS_STATUS_RESOURCES)
{
NdisDprFreePacket(MyPacket);
}
return((Status != NDIS_STATUS_RESOURCES) ? 1 : 0);
}
else
{
//
// We are out of packets. Silently drop it. Alternatively we can deal with it:
// - By keeping separate send and receive pools
// - Dynamically allocate more pools as needed and free them when not needed
//
return(0);
}
}
NDIS_STATUS
PtPNPHandler(
IN NDIS_HANDLE ProtocolBindingContext,
IN PNET_PNP_EVENT pNetPnPEvent
)
/*++
Routine Description:
This is the Protocol PNP handlers. All PNP Related OIDS(requests) are routed to this function
If the Power of the SetPower PNP Event is received, then the new power state is copied to
the internal state of the Passthru driver. Need to complete all sends and requests before
returning from this function.
Arguments:
ProtocolBindingContext Pointer to our adapter structure.
pNetPnPEvent Pointer to a Net_PnP_Event
Return Value:
NDIS_STATUS_SUCCESS: as we do not do much here
--*/
{
PADAPT pAdapt =(PADAPT)ProtocolBindingContext;
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
DBGPRINT ("PtPnPHandler");
//
// This will happen when all entities in the system need to be notified
//
switch(pNetPnPEvent->NetEvent)
{
case NetEventSetPower :
Status = PtPnPNetEventSetPower(pAdapt, pNetPnPEvent);
break;
case NetEventReconfigure :
Status = PtPnPNetEventReconfigure(pAdapt, (PCWSTR)pNetPnPEvent->Buffer);
break;
default :
Status = NDIS_STATUS_SUCCESS;
break;
}
return Status;
}
NDIS_STATUS
PtPnPNetEventReconfigure(
IN PADAPT pAdapt,
IN PCWSTR pBundleString
)
{
NDIS_STATUS BundleStatus = NDIS_STATUS_SUCCESS;
NDIS_STRING NewBundleUniString;
if(pAdapt == NULL)
{
NdisReEnumerateProtocolBindings (ProtHandle);
return BundleStatus;
}
if (pBundleString == NULL)
{
return BundleStatus;
}
NdisInitUnicodeString( &NewBundleUniString, pBundleString);
do
{
//
// If the bundle Identifier was not changed, do not do anything
//
if(NdisEqualUnicodeString(&NewBundleUniString, &pAdapt->BundleUniString, TRUE))
{
break;
}
//
// We have a new bundle id , copy it and do the necessary bundling work
//
RtlCopyUnicodeString(&pAdapt->BundleUniString , &NewBundleUniString);
//
// If we are part of a bundle and our bundle id was changed, either the primary or the secondary
// will get promoted
// If we are the secondary of a bundle promote ourselves
//
if(pAdapt->isSecondary)
{
PADAPT pPrimaryAdapt = pAdapt->pPrimaryAdapt;
BundleStatus = MPPromoteSecondary(pAdapt);
if(BundleStatus != NDIS_STATUS_SUCCESS)
{
ASSERT(0);
break;
}
//
// resetting all the internal variables of the primary Adapter structure
//
pPrimaryAdapt->pPrimaryAdapt = pPrimaryAdapt;
pPrimaryAdapt->pSecondaryAdapt = pPrimaryAdapt;
pPrimaryAdapt->isSecondary = FALSE;
}
else
{
//
// The BundleId has changed. If we are the primary of a bundle,
// then we need to promote the secondary
//
if(pAdapt->pSecondaryAdapt != pAdapt)
{
BundleStatus = MPPromoteSecondary(pAdapt->pSecondaryAdapt);
if(BundleStatus != NDIS_STATUS_SUCCESS)
{
ASSERT(0);
break;
}
//
// resetting all our internal variables
//
pAdapt->pSecondaryAdapt = pAdapt;
pAdapt->pPrimaryAdapt = pAdapt;
pAdapt->isSecondary = FALSE ;
}
}
//
// Now we need to see if the new bundle ID makes the Passthru part of another bundle
// If so. then set the current pAdapt as the secondary
//
BundleStatus = MPBundleSearchAndSetSecondary(pAdapt);
} while(FALSE) ;
DBGPRINT("<==PtPNPNetEventReconfigure/n");
return BundleStatus;
}
NDIS_STATUS
PtPnPNetEventSetPower(
IN PADAPT pAdapt,
IN PNET_PNP_EVENT pNetPnPEvent
)
/*++
Routine Description:
Sets the PowerState to the required level. Waits for all outstanding Sends and requests to complete
Arguments:
pAdapt - Pointer to the adpater structure
pNetPnpEvent - The Net Pnp Event. this contains the new device state
Return Value:
NDIS_STATUS_SUCCESS: If the device successfully changed its power state
--*/
{
PNDIS_DEVICE_POWER_STATE pDeviceState =(PNDIS_DEVICE_POWER_STATE)(pNetPnPEvent->Buffer);
NDIS_DEVICE_POWER_STATE PrevDeviceState = pAdapt->PTDeviceState;
NDIS_STATUS Status ;
//
// Set the Internal Device State, this blocks all new sends or receives
//
pAdapt->PTDeviceState = *pDeviceState;
//
// if we are being sent to standby, block for outstanding requests and sends
//
if(*pDeviceState > NdisDeviceStateD0)
{
//
// If the physical miniport is going to standby, fail all incoming requests
//
if (PrevDeviceState == NdisDeviceStateD0)
{
pAdapt->StandingBy = TRUE;
}
while(NdisPacketPoolUsage(pAdapt->SendPacketPoolHandle) != 0)
{
//
// sleep till outstanding sends complete
//
NdisMSleep(10);
}
while(pAdapt->OutstandingRequests == TRUE)
{
//
// sleep till outstanding requests complete
//
NdisMSleep(10);
}
ASSERT(NdisPacketPoolUsage(pAdapt->SendPacketPoolHandle) == 0);
ASSERT(pAdapt->OutstandingRequests == FALSE);
}
else
{
//
// The protocol is being turned on. A pending request must be completed
//
if (pAdapt->QueuedRequest == TRUE)
{
pAdapt->QueuedRequest = FALSE;
NdisRequest(&Status,
pAdapt->BindingHandle,
&pAdapt->Request);
//
// The underlying miniport completed the request synchronously, the IM
// needs to complete the request which it had pended earlier
//
if (Status != NDIS_STATUS_PENDING)
{
PtRequestComplete(pAdapt,
&pAdapt->Request,
Status);
}
}
//
// If the physical miniport is powering up (from Low power state to D0),
// clear the flag
//
if (PrevDeviceState > NdisDeviceStateD0)
{
pAdapt->StandingBy = FALSE;
}
}
Status = NDIS_STATUS_SUCCESS;
return Status;
}
#include "precomp.h"
#include "fw_rule.h"
#include "util.h"
#include "DDKLBLInc.h"
#include "cons_def.h"
#include "fw_interface.h"
#include "driver.h"
#define DEVICE_NAME L"//Device//DOGFW"
#define DOSDEVICE_NAME L"//DosDevices//DOGFW"
#pragma hdrstop
#pragma NDIS_INIT_FUNCTION(DriverEntry)
NDIS_PHYSICAL_ADDRESS HighestAcceptableMax = NDIS_PHYSICAL_ADDRESS_CONST(-1, -1);
NDIS_HANDLE ProtHandle = NULL;
NDIS_HANDLE DriverHandle = NULL;
NDIS_MEDIUM MediumArray[3] =
{
NdisMedium802_3, // Ethernet
NdisMedium802_5, // Token-ring
NdisMediumFddi // Fddi
};
PADAPT pAdaptList=NULL;
PDEVICE_OBJECT g_DeviceObject = NULL;
NDIS_HANDLE g_NdisDeviceHandle = NULL;
struct Fw_Rules g_Rules;
struct Statistics g_stat;
struct ip g_IPHeader, *g_pIPHeader=NULL;
struct tcphdr g_TCPHeader, *g_pTCPHeader=NULL;
struct udphdr g_UDPHeader, *g_pUDPHeader=NULL;
struct icmp g_ICMPHeader, *g_pICMPHeader=NULL;
struct All_Alarms g_AllAlarm[MAX_CALL_NUM];
struct All_Logs g_AllLog[MAX_CALL_NUM];
PFILE_OBJECT g_alarmfop=NULL;
PDEVICE_EXTENSION g_alarmpdx=NULL;
PFILE_OBJECT g_logfop=NULL;
PDEVICE_EXTENSION g_logpdx=NULL;
//FAST_MUTEX fw_mutex;
extern USHORT lcall_num,acall_num;
NTSTATUS
DefaultDispatch(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
PIO_STACK_LOCATION IrpStack;
ULONG ControlCode;
ULONG InputLength, OutputLength;
IrpStack=IoGetCurrentIrpStackLocation(Irp);
ControlCode=IrpStack->Parameters.DeviceIoControl.IoControlCode;
InputLength=IrpStack->Parameters.DeviceIoControl.InputBufferLength;
OutputLength=IrpStack->Parameters.DeviceIoControl.OutputBufferLength;
Irp->IoStatus.Status=STATUS_SUCCESS;
Irp->IoStatus.Information=0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
NTSTATUS
DeviceIoDispatch(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
PIO_STACK_LOCATION IrpStack;
ULONG ControlCode;
ULONG InputLength, OutputLength;
//add by df
struct All_Rules *pallrules=NULL;
struct Proto_Restrict *pprotocol=NULL;
struct Time_Restrict *pschedule=NULL;
struct All_Alarms *pallalarm=NULL;
struct All_Logs *palllog=NULL;
struct Statistics *pstat=NULL;
PVOID chkbuf=NULL;
ULONG info=0;
NTSTATUS status;
PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
IrpStack =IoGetCurrentIrpStackLocation(Irp);
ControlCode =IrpStack->Parameters.DeviceIoControl.IoControlCode;
InputLength =IrpStack->Parameters.DeviceIoControl.InputBufferLength;
OutputLength=IrpStack->Parameters.DeviceIoControl.OutputBufferLength;
/*
KdPrint(("ControlCode=%d InputLength=%d OutputLength=%d",
ControlCode,
InputLength,
InputLength));
*/
switch(ControlCode)
{
case IOCTL_DOGFW_CTL_FW_STATUS: //char *fw_status
//KdPrint(("IOCTL_DOGFW_CTL_FW_STATUS Begin"));
//ExAcquireFastMutex(&fw_mutex);
if (InputLength < sizeof(char))
{
status = STATUS_INVALID_PARAMETER;
break;
}
g_Rules.global.fw_status=*(PCHAR)Irp->AssociatedIrp.SystemBuffer;
info=sizeof(char);
status=STATUS_SUCCESS;
//KdPrint(("IOCTL_DOGFW_CTL_FW_STATUS end"));
//ExReleaseFastMutex(&fw_mutex);
break;
case IOCTL_DOGFW_CTL_LOG: //char *log_enable
//ExAcquireFastMutex(&fw_mutex);
if (InputLength < sizeof(char))
{
status = STATUS_INVALID_PARAMETER;
break;
}
g_Rules.global.log_enable=*(PCHAR)Irp->AssociatedIrp.SystemBuffer;
info=sizeof(char);
status=STATUS_SUCCESS;
//ExReleaseFastMutex(&fw_mutex);
break;
case IOCTL_DOGFW_CTL_WARN: //char *warn_enable
//ExAcquireFastMutex(&fw_mutex);
if (InputLength < sizeof(char))
{
status = STATUS_INVALID_PARAMETER;
break;
}
g_Rules.global.warn_enable=*(PCHAR)Irp->AssociatedIrp.SystemBuffer;
info=sizeof(char);
status=STATUS_SUCCESS;
//ExReleaseFastMutex(&fw_mutex);
break;
case IOCTL_DOGFW_CTL_SCHEDULE: //struct Time_Restrict *schedule
//ExAcquireFastMutex(&fw_mutex);
if (InputLength < sizeof(struct Time_Restrict))
{
status = STATUS_INVALID_PARAMETER;
break;
}
pschedule=(struct Time_Restrict *)Irp->AssociatedIrp.SystemBuffer;
g_Rules.global.schedule.enable =pschedule->time_enable;
g_Rules.global.schedule.start_time =pschedule->start_time;
g_Rules.global.schedule.end_time =pschedule->end_time;
info=sizeof(struct Time_Restrict);
status=STATUS_SUCCESS;
//ExReleaseFastMutex(&fw_mutex);
break;
case IOCTL_DOGFW_CTL_FWMODE: //char *fw_mode
//ExAcquireFastMutex(&fw_mutex);
if (InputLength < sizeof(char))
{
status = STATUS_INVALID_PARAMETER;
break;
}
g_Rules.global.fw_mode=*(PCHAR)Irp->AssociatedIrp.SystemBuffer;
info=sizeof(char);
status=STATUS_SUCCESS;
//ExReleaseFastMutex(&fw_mutex);
break;
case IOCTL_DOGFW_CTL_PROTOCOL: //struct Proto_Restrict *protocol
//ExAcquireFastMutex(&fw_mutex);
if (InputLength < sizeof(struct Proto_Restrict))
{
status = STATUS_INVALID_PARAMETER;
break;
}
pprotocol=(struct Proto_Restrict *)Irp->AssociatedIrp.SystemBuffer;
g_Rules.tcp.enable =pprotocol->tcp_enable;
g_Rules.udp.enable =pprotocol->udp_enable;
g_Rules.icmp.enable =pprotocol->icmp_enable;
g_Rules.ip.enable =pprotocol->restip_enable;
info=sizeof(struct Proto_Restrict);
status=STATUS_SUCCESS;
//ExReleaseFastMutex(&fw_mutex);
break;
case IOCTL_DOGFW_CTL_CHKDATA:
chkbuf=(PVOID)Irp->AssociatedIrp.SystemBuffer;
UTIL_AddKeyword(chkbuf,InputLength,1);
info=InputLength;
status=STATUS_SUCCESS;
break;
case IOCTL_DOGFW_CTL_URLDATA:
chkbuf=(PVOID)Irp->AssociatedIrp.SystemBuffer;
UTIL_AddKeyword(chkbuf,InputLength,0);
info=InputLength;
status=STATUS_SUCCESS;
break;
case IOCTL_DOGFW_CTL_TCPURLDATA:
chkbuf=(PVOID)Irp->AssociatedIrp.SystemBuffer;
UTIL_AddKeyword(chkbuf,InputLength,2);
info=InputLength;
status=STATUS_SUCCESS;
break;
case IOCTL_DOGFW_CTL_DELCHKDATA:
UTIL_DelKeyword();
status=STATUS_SUCCESS;
break;
case IOCTL_DOGFW_CTL_DELURLDATA:
UTIL_DelURLWord();
status=STATUS_SUCCESS;
break;
case IOCTL_DOGFW_CTL_DELTCPURLDATA:
UTIL_DelTCPURLWord();
status=STATUS_SUCCESS;
break;
case IOCTL_DOGFW_CTL_FLUXCTRL: //struct Flux_Control *flux
status=STATUS_SUCCESS;
break;
case IOCTL_DOGFW_RULE_ADD:
status=STATUS_SUCCESS;
break;
case IOCTL_DOGFW_RULE_DEL:
status=STATUS_SUCCESS;
break;
case IOCTL_DOGFW_RULE_CHANGE:
status=STATUS_SUCCESS;
break;
case IOCTL_DOGFW_RULE_ADDALL: //struct All_Rules *all_rule
//KdPrint(("IOCTL_DOGFW_RULE_ADDALL Begin"));
//ExAcquireFastMutex(&fw_mutex);
if (InputLength < sizeof(struct All_Rules))
{
status = STATUS_INVALID_PARAMETER;
break;
}
pallrules=(struct All_Rules *)Irp->AssociatedIrp.SystemBuffer;
if (pallrules->rules_num>MAX_RULE_NUM)
{
status=STATUS_UNSUCCESSFUL; //number of rules are too much
break;
}
//if g_rules not NULL, delete all
UTIL_DelAllrules();
UTIL_AddAllrules(pallrules);
info=sizeof(struct All_Rules);
status=STATUS_SUCCESS;
//ExReleaseFastMutex(&fw_mutex);
//KdPrint(("IOCTL_DOGFW_RULE_ADDALL end"));
break;
case IOCTL_DOGFW_RULE_DELALL: //none
//KdPrint(("IOCTL_DOGFW_RULE_DELALL Begin"));
//ExAcquireFastMutex(&fw_mutex);
UTIL_DelAllrules();
status=STATUS_SUCCESS;
//KdPrint(("IOCTL_DOGFW_RULE_DELALL End"));
//ExReleaseFastMutex(&fw_mutex);
break;
case IOCTL_DOGFW_RULE_READ:
status=STATUS_SUCCESS;
break;
case IOCTL_DOGFW_STAT_READ: //see in test app sample
//ExAcquireFastMutex(&fw_mutex);
pstat=(struct Statistics *)Irp->AssociatedIrp.SystemBuffer;
memcpy((void *)pstat,(void *)&g_stat,sizeof(struct Statistics));
info=sizeof(struct Statistics);
status=STATUS_SUCCESS;
//ExReleaseFastMutex(&fw_mutex);
break;
case IOCTL_DOGFW_LOG_READ:
//ExAcquireFastMutex(&fw_mutex);
palllog=(struct All_Logs *)Irp->AssociatedIrp.SystemBuffer;
if (lcall_num==0)
memcpy((void *)palllog,(void *)&g_AllLog[2],sizeof(struct All_Logs));
else
memcpy((void *)palllog,(void *)&g_AllLog[lcall_num-1],sizeof(struct All_Logs));
info=sizeof(struct All_Logs);
status=STATUS_SUCCESS;
//ExReleaseFastMutex(&fw_mutex);
break;
case IOCTL_DOGFW_ALARM_READ:
//ExAcquireFastMutex(&fw_mutex);
pallalarm=(struct All_Alarms *)Irp->AssociatedIrp.SystemBuffer;
if (acall_num==0)
memcpy((void *)pallalarm,(void *)&g_AllAlarm[2],sizeof(struct All_Alarms));
else
memcpy((void *)pallalarm,(void *)&g_AllAlarm[acall_num-1],sizeof(struct All_Alarms));
info=sizeof(struct All_Alarms);
status=STATUS_SUCCESS;
//ExReleaseFastMutex(&fw_mutex);
break;
case IOCTL_REGISTER_ALARM_EVENT: // code == 0x8012
{
//ExAcquireFastMutex(&fw_mutex);
if (InputLength < sizeof(HANDLE))
{
status = STATUS_INVALID_PARAMETER;
break;
}
if (!RegisterEvent(pdx, IrpStack->FileObject, *(PHANDLE) Irp->AssociatedIrp.SystemBuffer, UserMode, E_ALARM))
{
status = STATUS_UNSUCCESSFUL;
break;
}
info=sizeof(HANDLE);
status=STATUS_SUCCESS;
//ExReleaseFastMutex(&fw_mutex);
break;
}
case IOCTL_REGISTER_LOG_EVENT: // code == 0x8013
{
//ExAcquireFastMutex(&fw_mutex);
if (InputLength < sizeof(HANDLE))
{
status = STATUS_INVALID_PARAMETER;
break;
}
if (!RegisterEvent(pdx, IrpStack->FileObject, *(PHANDLE) Irp->AssociatedIrp.SystemBuffer, UserMode, E_LOG))
{
status = STATUS_UNSUCCESSFUL;
break;
}
info=sizeof(HANDLE);
status=STATUS_SUCCESS;
//ExReleaseFastMutex(&fw_mutex);
break;
}
case IOCTL_DOGFW_LOG_CALLBACK: //see in test app sample
status=STATUS_SUCCESS;
break;
case IOCTL_DOGFW_ALARM_CALLBACK: //see in test app sample
default:
status=STATUS_SUCCESS;
break;
}
CompleteRequest(Irp,status,info);
return status;
}
NTSTATUS
DriverEntry(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
)
{
NDIS_STATUS Status;
NDIS_PROTOCOL_CHARACTERISTICS PChars;
NDIS_MINIPORT_CHARACTERISTICS MChars;
PNDIS_CONFIGURATION_PARAMETER Param;
NDIS_STRING Name;
NDIS_HANDLE WrapperHandle;
PDRIVER_DISPATCH MajorFunc[IRP_MJ_MAXIMUM_FUNCTION+1];
UNICODE_STRING DeviceName, DosDeviceName;
PDEVICE_EXTENSION pdx;
int i;
DbgPrint(("DriverEntry------------------------------------/n"));
RtlInitUnicodeString(&DeviceName, DEVICE_NAME);
RtlInitUnicodeString(&DosDeviceName, DOSDEVICE_NAME);
//ExInitializeFastMutex(&fw_mutex);
//
// Register the miniport with NDIS. Note that it is the miniport
// which was started as a driver and not the protocol. Also the miniport
// must be registered prior to the protocol since the protocol's BindAdapter
// handler can be initiated anytime and when it is, it must be ready to
// start driver instances.
//
NdisMInitializeWrapper(&WrapperHandle, DriverObject, RegistryPath, NULL);
NdisZeroMemory(&MChars, sizeof(NDIS_MINIPORT_CHARACTERISTICS));
MChars.MajorNdisVersion = 4;
MChars.MinorNdisVersion = 0;
MChars.InitializeHandler = MPInitialize;
MChars.QueryInformationHandler = MPQueryInformation;
MChars.SetInformationHandler = MPSetInformation;
MChars.ResetHandler = MPReset;
MChars.TransferDataHandler = MPTransferData;
MChars.HaltHandler = MPHalt;
//
// We will disable the check for hang timeout so we do not
// need a check for hang handler!
//
MChars.CheckForHangHandler = NULL;
MChars.SendHandler = MPSend;
MChars.ReturnPacketHandler = MPReturnPacket;
//
// Either the Send or the SendPackets handler should be specified.
// If SendPackets handler is specified, SendHandler is ignored
//
// MChars.SendPacketsHandler = MPSendPackets;
Status = NdisIMRegisterLayeredMiniport(WrapperHandle,
&MChars,
sizeof(MChars),
&DriverHandle);
ASSERT(Status == NDIS_STATUS_SUCCESS);
NdisMRegisterUnloadHandler(WrapperHandle, PtUnload);
//
// Now register the protocol.
//
NdisZeroMemory(&PChars, sizeof(NDIS_PROTOCOL_CHARACTERISTICS));
PChars.MajorNdisVersion = 4;
PChars.MinorNdisVersion = 0;
//
// Make sure the protocol-name matches the service-name under which this protocol is installed.
// This is needed to ensure that NDIS can correctly determine the binding and call us to bind
// to miniports below.
//
NdisInitUnicodeString(&Name, L"SFilter"); // Protocol name
PChars.Name = Name;
PChars.OpenAdapterCompleteHandler = PtOpenAdapterComplete;
PChars.CloseAdapterCompleteHandler = PtCloseAdapterComplete;
PChars.SendCompleteHandler = PtSendComplete;
PChars.TransferDataCompleteHandler = PtTransferDataComplete;
PChars.ResetCompleteHandler = PtResetComplete;
PChars.RequestCompleteHandler = PtRequestComplete;
PChars.ReceiveHandler = PtReceive;
PChars.ReceiveCompleteHandler = PtReceiveComplete;
PChars.StatusHandler = PtStatus;
PChars.StatusCompleteHandler = PtStatusComplete;
PChars.BindAdapterHandler = PtBindAdapter;
PChars.UnbindAdapterHandler = PtUnbindAdapter;
PChars.UnloadHandler = NULL;
PChars.ReceivePacketHandler = PtReceivePacket;
PChars.PnPEventHandler = PtPNPHandler;
NdisRegisterProtocol(&Status,
&ProtHandle,
&PChars,
sizeof(NDIS_PROTOCOL_CHARACTERISTICS));
ASSERT(Status == NDIS_STATUS_SUCCESS);
NdisIMAssociateMiniport(DriverHandle, ProtHandle);
for(i=0; i<=IRP_MJ_MAXIMUM_FUNCTION; i++)
MajorFunc[i]=DefaultDispatch;
MajorFunc[IRP_MJ_CREATE] = DispatchCreate;
MajorFunc[IRP_MJ_CLOSE] = DispatchClose;
MajorFunc[IRP_MJ_DEVICE_CONTROL]=DeviceIoDispatch;
NdisMRegisterDevice(
WrapperHandle,
&DeviceName,
&DosDeviceName,
MajorFunc,
&g_DeviceObject,
&g_NdisDeviceHandle
);
pdx = (PDEVICE_EXTENSION) g_DeviceObject->DeviceExtension;
pdx->DeviceObject=g_DeviceObject;
InitializeListHead(&pdx->hlist);
KeInitializeSpinLock(&pdx->lockHandles);
//IoInitializeRemoveLock(&pdx->RemoveLock, 0, 0, 0);
g_DeviceObject->Flags&= ~DO_DEVICE_INITIALIZING; //hear of ....
RtlFillMemory(&g_Rules,sizeof(g_Rules),0);
RtlFillMemory(&g_stat,sizeof(g_stat),0);
g_pIPHeader =&g_IPHeader;
g_pTCPHeader =&g_TCPHeader;
g_pUDPHeader =&g_UDPHeader;
g_pICMPHeader =&g_ICMPHeader;
g_Rules.global.pkeylist =NULL;
g_Rules.global.fw_status =FWS_ALLOWALL;
g_Rules.icmp.enable =1;
g_Rules.tcp.enable =1;
g_Rules.udp.enable =1;
g_Rules.ip.enable =1;
return(Status);
}
/////////////////////////////////////////////////////////////////////////////
//// INCLUDE FILES
#define MODULE_NAME "UTIL"
#include "precomp.h"
#include "DDKLBLInc.h"
#include "cons_def.h"
#include "fw_rule.h"
#include "PCAENET.H"
#include "fw_interface.h"
#include "driver.h"
#include <math.h>
#include <stdlib.h>
extern struct Fw_Rules g_Rules;
extern struct Statistics g_stat;
extern struct ip *g_pIPHeader;
extern struct tcphdr *g_pTCPHeader;
extern struct udphdr *g_pUDPHeader;
extern struct icmp *g_pICMPHeader;
extern struct All_Alarms g_AllAlarm[MAX_CALL_NUM];
extern struct All_Logs g_AllLog[MAX_CALL_NUM];
extern PFILE_OBJECT g_alarmfop;
extern PDEVICE_EXTENSION g_alarmpdx;
extern PFILE_OBJECT g_logfop;
extern PDEVICE_EXTENSION g_logpdx;
USHORT alarm_num=0,log_num=0,acall_num=0,lcall_num=0;
//
// Force undef of VTOOLSD For Windows 98 DDK Build
// -----------------------------------------------
// See comments in PCAIPLCE.H.
//
#ifdef NO_VTOOLSD
#undef VTOOLSD
#endif
#ifndef VTOOLSD // For Windows 98 DDK Build
//#include <vmm.h>
//#pragma VxD_LOCKED_DATA_SEG
//#pragma VxD_LOCKED_CODE_SEG
//#define isprint(c) (((c) >= 0x20) && ((c) < 0x80))
#endif
void* UTIL_AllocateMemory(unsigned int size)
{
PVOID ptr=NULL;
ptr=ExAllocatePool(NonPagedPool , size);
return ptr;
}
void UTIL_FreeMemory(void* p)
{
if (p)
ExFreePool(p);
}
/////////////////////////////////////////////////////////////////////////////
//// UTIL_ReadOnPacket
//
// Purpose
// Logical read on the packet data in a NDIS_PACKET.
//
// Parameters
//
// Return Value
//
// Remarks
// The purpose of this function is to provide a convienient mechanism to
// read packet data from an NDIS_PACKET that may have multiple chained
// NDIS_BUFFERs.
//
VOID
UTIL_ReadOnPacket(
PNDIS_PACKET Packet,
PUCHAR lpBuffer,
ULONG nNumberOfBytesToRead,
ULONG nOffset, // Byte Offset, Starting With MAC Header
PULONG lpNumberOfBytesRead
)
{
PNDIS_BUFFER CurrentBuffer;
UINT nBufferCount, TotalPacketLength;
PUCHAR VirtualAddress;
UINT CurrentLength, CurrentOffset;
UINT AmountToMove;
*lpNumberOfBytesRead = 0;
if (!nNumberOfBytesToRead)
return;
//
// Query Packet
//
NdisQueryPacket(
(PNDIS_PACKET )Packet,
(PUINT )NULL, // Physical Buffer Count
(PUINT )&nBufferCount, // Buffer Count
&CurrentBuffer, // First Buffer
&TotalPacketLength // TotalPacketLength
);
//
// Query The First Buffer
//
NdisQueryBuffer(
CurrentBuffer,
&VirtualAddress,
&CurrentLength
);
CurrentOffset = 0;
while( nOffset || nNumberOfBytesToRead )
{
while( !CurrentLength )
{
NdisGetNextBuffer(
CurrentBuffer,
&CurrentBuffer
);
// If we've reached the end of the packet. We return with what
// we've done so far (which must be shorter than requested).
if (!CurrentBuffer)
return;
NdisQueryBuffer(
CurrentBuffer,
&VirtualAddress,
&CurrentLength
);
CurrentOffset = 0;
}
if( nOffset )
{
// Compute how much data to move from this fragment
if( CurrentLength > nOffset )
CurrentOffset = nOffset;
else
CurrentOffset = CurrentLength;
nOffset -= CurrentOffset;
CurrentLength -= CurrentOffset;
}
if( nOffset )
{
CurrentLength = 0;
continue;
}
if( !CurrentLength )
{
continue;
}
// Compute how much data to move from this fragment
if (CurrentLength > nNumberOfBytesToRead)
AmountToMove = nNumberOfBytesToRead;
else
AmountToMove = CurrentLength;
// Copy the data.
NdisMoveMemory(
lpBuffer,
&VirtualAddress[ CurrentOffset ],
AmountToMove
);
// Update destination pointer
lpBuffer += AmountToMove;
// Update counters
*lpNumberOfBytesRead +=AmountToMove;
nNumberOfBytesToRead -=AmountToMove;
CurrentLength = 0;
}
}
/////////////////////////////////////////////////////////////////////////////
//// UTIL_htonl
//
// Purpose
// Converts a ULONG from host to network byte order.
//
// Parameters
//
// Return Value
//
// Remarks
// ATTENTION!!! Must revise for non-Intel (Alpha) hosts.
//
// Why isn't this function named simply "htonl"? Possible confilct with
// system implementations available on some hosts, but possibly declared
// differently...
//
ULONG UTIL_htonl( ULONG hostlong )
{
PUCHAR pBuffer;
ULONG nResult;
UCHAR c, *pResult;
pBuffer = (PUCHAR )&hostlong;
if( !pBuffer )
{
return( 0L );
}
pResult = (UCHAR * )&nResult;
c = ((UCHAR * )pBuffer)[ 0 ];
((UCHAR * )pResult)[ 0 ] = ((UCHAR * )pBuffer)[ 3 ];
((UCHAR * )pResult)[ 3 ] = c;
c = ((UCHAR * )pBuffer)[ 1 ];
((UCHAR * )pResult)[ 1 ] = ((UCHAR * )pBuffer)[ 2 ];
((UCHAR * )pResult)[ 2 ] = c;
return( nResult );
}
/////////////////////////////////////////////////////////////////////////////
//// UTIL_htons
//
// Purpose
// Converts a USHORT from host to network byte order.
//
// Parameters
//
// Return Value
//
// Remarks
// ATTENTION!!! Must revise for non-Intel (Alpha) hosts.
//
// Why isn't this function named simply "htons"? Possible confilct with
// system implementations available on some hosts, but possibly declared
// differently...
//
USHORT UTIL_htons( USHORT hostshort )
{
PUCHAR pBuffer;
USHORT nResult;
nResult = 0;
pBuffer = (PUCHAR )&hostshort;
nResult = ( (pBuffer[ 0 ] << 8) & 0xFF00 )
| ( pBuffer[ 1 ] & 0x00FF );
return( nResult );
}
/////////////////////////////////////////////////////////////////////////////
//// UTIL_ntohl
//
// Purpose
// Converts a ULONG from network to host byte order.
//
// Parameters
//
// Return Value
//
// Remarks
//
// Why isn't this function named simply "ntohl"? Possible confilct with
// system implementations available on some hosts, but possibly declared
// differently...
//
ULONG UTIL_ntohl( ULONG netlong )
{
return( UTIL_htonl( netlong ) );
}
/////////////////////////////////////////////////////////////////////////////
//// UTIL_ntohs
//
// Purpose
// Converts a USHORT from network to host byte order.
//
// Parameters
//
// Return Value
//
// Remarks
//
// Why isn't this function named simply "ntohs"? Possible confilct with
// system implementations available on some hosts, but possibly declared
// differently...
//
USHORT UTIL_ntohs( USHORT netshort )
{
return( UTIL_htons( netshort ) );
}
/////////////////////////////////////////////////////////////////////////////
//// in_cksum
//
// Purpose
// Standard Internet Protocol checksum routine.
//
// Parameters
//
// Return Value
//
// Remarks
// ICMP, IGMP, UDP and TCP all use the same checksum algorithm
//
USHORT in_cksum( PUCHAR pStartingByte, int nByteCount )
{
register ULONG sum = 0;
register PUSHORT addr = (PUSHORT )pStartingByte;
//
// Add 16-bit Words
//
while (nByteCount > 1)
{
//
// This Is The Inner Loop
//
sum += *(addr++);
nByteCount -= 2;
}
//
// Add leftover byte, if any
//
if (nByteCount > 0)
#if BIG_ENDIAN
sum += (*(PUCHAR )addr) << 8;
#else
sum += *(PUCHAR )addr;
#endif
//
// Fold 32-bit sum to 16-bit
//
while (sum >> 16)
sum = (sum & 0xffff) + (sum >> 16);
//
// Return one's compliment of final sum.
//
return (USHORT) ~sum;
}
/////////////////////////////////////////////////////////////////
//
//函数UTIL_CountPacket
//
//参数
//方向、动作
//
//返回值
//无
//
//
//备注
//统计在in、out方向上允许或禁止的包。in(0)、out(1)、allow(0)
//deny(1)
void UTIL_CountPacket (USHORT ptype,char direct,char action,int packsize)
{
/*
if 方向为in {
if 动作为允许 统计结构累计
if 动作为禁止 统计结构累计
}
if 方向为out {
if 动作为允许 统计结构累计
if 动作为禁止 统计结构累计
}
*/
if (direct==DT_IN)
{
if (action==ALLOW)
{
switch (ptype)
{
case PT_TCP:
g_stat.ip.tcp.allow_in_bytes+=packsize;
g_stat.ip.tcp.allow_in_pkts++;
break;
case PT_UDP:
g_stat.ip.udp.allow_in_bytes+=packsize;
g_stat.ip.udp.allow_in_pkts++;
break;
case PT_ICMP:
g_stat.ip.icmp.allow_in_bytes+=packsize;
g_stat.ip.icmp.allow_in_pkts++;
break;
case PT_RESTIP:
g_stat.ip.restip.allow_in_bytes+=packsize;
g_stat.ip.restip.allow_in_pkts++;
break;
default:
g_stat.notip.other_stat.allow_in_bytes+=packsize;
g_stat.notip.other_stat.allow_in_pkts++;
}
}
if (action==DENY)
{
switch (ptype)
{
case PT_TCP:
g_stat.ip.tcp.deny_in_bytes+=packsize;
g_stat.ip.tcp.deny_in_pkts++;
break;
case PT_UDP:
g_stat.ip.udp.deny_in_bytes+=packsize;
g_stat.ip.udp.deny_in_pkts++;
break;
case PT_ICMP:
g_stat.ip.icmp.deny_in_bytes+=packsize;
g_stat.ip.icmp.deny_in_pkts++;
break;
case PT_RESTIP:
g_stat.ip.restip.deny_in_bytes+=packsize;
g_stat.ip.restip.deny_in_pkts++;
break;
default:
g_stat.notip.other_stat.deny_in_bytes+=packsize;
g_stat.notip.other_stat.deny_in_pkts++;
}
}
}
if (direct==DT_OUT)
{
if (action==ALLOW)
{
switch (ptype)
{
case PT_TCP:
g_stat.ip.tcp.allow_out_bytes+=packsize;
g_stat.ip.tcp.allow_out_pkts++;
break;
case PT_UDP:
g_stat.ip.udp.allow_out_bytes+=packsize;
g_stat.ip.udp.allow_out_pkts++;
break;
case PT_ICMP:
g_stat.ip.icmp.allow_out_bytes+=packsize;
g_stat.ip.icmp.allow_out_pkts++;
break;
case PT_RESTIP:
g_stat.ip.restip.allow_out_bytes+=packsize;
g_stat.ip.restip.allow_out_pkts++;
break;
default:
g_stat.notip.other_stat.allow_out_bytes+=packsize;
g_stat.notip.other_stat.allow_out_pkts++;
}
}
if (action==DENY)
{
switch (ptype)
{
case PT_TCP:
g_stat.ip.tcp.deny_out_bytes+=packsize;
g_stat.ip.tcp.deny_out_pkts++;
break;
case PT_UDP:
g_stat.ip.udp.deny_out_bytes+=packsize;
g_stat.ip.udp.deny_out_pkts++;
break;
case PT_ICMP:
g_stat.ip.icmp.deny_out_bytes+=packsize;
g_stat.ip.icmp.deny_out_pkts++;
break;
case PT_RESTIP:
g_stat.ip.restip.deny_out_bytes+=packsize;
g_stat.ip.restip.deny_out_pkts++;
break;
default:
g_stat.notip.other_stat.deny_out_bytes+=packsize;
g_stat.notip.other_stat.deny_out_pkts++;
}
}
}
}
/////////////////////////////////////////////////////////////////
//
//函数UTIL_WriteLog
//
//参数
//USHORT ID,struct ip cur_ip
//
//返回值
//无
//
//
//备注
//在IOCTL中加入SETLOGADDRESS,传入回调函数地址,并得到当前线程号。
//在此函数中调用 _VWIN32_QueueUserApc() 调用应用程序函数。
void UTIL_TcpWriteLog(
struct Fw_Rule_Node *pTcpRule,
struct ip *piphdr,
struct tcphdr *ptcphdr
)
{
g_AllLog[lcall_num].logs[log_num].ID=pTcpRule->ID;
g_AllLog[lcall_num].log_num=log_num+1;
g_AllLog[lcall_num].protocol=PT_TCP;
memcpy((void *)&g_AllLog[lcall_num].logs[log_num].ip_pkt,(void *)piphdr,sizeof(struct ip));
memcpy((void *)&g_AllLog[lcall_num].logs[log_num].log_trans_pkt.tcp_pkt,(void *)ptcphdr,sizeof(struct tcphdr));
if ((log_num+1)>=MAX_LOG_NUM)
{
if (g_logfop && g_logpdx)
SignalEvent(g_logpdx,g_logfop);
log_num=0;
lcall_num++;
if (lcall_num>=MAX_CALL_NUM)
lcall_num=0;
}
else
{
log_num++;
}
}
/////////////////////////////////////////////////////////////////
//
//函数UTIL_Alarm
//
//参数
//USHORT ID,struct ip cur_ip
//
//返回值
//无
//
//
//备注
//在IOCTL中加入SETALARMADDRESS,传入回调函数地址,并得到当前线程号。
//在此函数中调用 _VWIN32_QueueUserApc() 调用应用程序函数。
void UTIL_TcpAlarm(
struct Fw_Rule_Node *pTcpRule,
struct ip *piphdr,
struct tcphdr *ptcphdr
)
{
g_AllAlarm[acall_num].Alarms[alarm_num].ID=pTcpRule->ID;
g_AllAlarm[acall_num].Alarms[alarm_num].protocol=PT_TCP;
g_AllAlarm[acall_num].alarm_num=alarm_num+1;
memcpy((void *)&g_AllAlarm[acall_num].Alarms[alarm_num].ip_pkt,(void *)piphdr,sizeof(struct ip));
memcpy((void *)&g_AllAlarm[acall_num].Alarms[alarm_num].alarm_trans_pkt.tcp_pkt,(void *)ptcphdr,sizeof(struct tcphdr));
if ((alarm_num+1)>=MAX_ALARM_NUM)
{
if (g_alarmfop && g_alarmpdx)
SignalEvent(g_alarmpdx,g_alarmfop);
alarm_num=0;
acall_num++;
if (acall_num>=MAX_CALL_NUM)
acall_num=0;
}
else
{
alarm_num++;
}
}
void UTIL_UdpWriteLog(
struct Fw_Rule_Node *pUdpRule,
struct ip *piphdr,
struct udphdr *pudphdr
)
{
g_AllLog[lcall_num].logs[log_num].ID=pUdpRule->ID;
g_AllLog[lcall_num].log_num=log_num+1;
g_AllLog[lcall_num].protocol=PT_UDP;
memcpy((void *)&g_AllLog[lcall_num].logs[log_num].ip_pkt,(void *)piphdr,sizeof(struct ip));
memcpy((void *)&g_AllLog[lcall_num].logs[log_num].log_trans_pkt.udp_pkt,(void *)pudphdr,sizeof(struct udphdr));
if ((log_num+1)>=MAX_LOG_NUM)
{
if (g_logfop && g_logpdx)
SignalEvent(g_logpdx,g_logfop);
log_num=0;
lcall_num++;
if (lcall_num>=MAX_CALL_NUM)
lcall_num=0;
}
else
{
log_num++;
}
}
void UTIL_UdpAlarm(
struct Fw_Rule_Node *pUdpRule,
struct ip *piphdr,
struct udphdr *pudphdr
)
{
g_AllAlarm[acall_num].Alarms[alarm_num].ID=pUdpRule->ID;
g_AllAlarm[acall_num].Alarms[alarm_num].protocol=PT_UDP;
g_AllAlarm[acall_num].alarm_num=alarm_num+1;
memcpy((void *)&g_AllAlarm[acall_num].Alarms[alarm_num].ip_pkt,(void *)piphdr,sizeof(struct ip));
memcpy((void *)&g_AllAlarm[acall_num].Alarms[alarm_num].alarm_trans_pkt.udp_pkt,(void *)pudphdr,sizeof(struct udphdr));
if ((alarm_num+1)>=MAX_ALARM_NUM)
{
if (g_alarmfop && g_alarmpdx)
SignalEvent(g_alarmpdx,g_alarmfop);
alarm_num=0;
acall_num++;
if (acall_num>=MAX_CALL_NUM)
acall_num=0;
}
else
{
alarm_num++;
}
}
void UTIL_IcmpWriteLog(
struct Fw_Rule_Node *pIcmpRule,
struct ip *piphdr,
struct icmp *picmphdr
)
{
g_AllLog[lcall_num].logs[log_num].ID=pIcmpRule->ID;
g_AllLog[lcall_num].log_num=log_num+1;
g_AllLog[lcall_num].protocol=PT_ICMP;
memcpy((void *)&g_AllLog[lcall_num].logs[log_num].ip_pkt,(void *)piphdr,sizeof(struct ip));
memcpy((void *)&g_AllLog[lcall_num].logs[log_num].log_trans_pkt.icmp_pkt,(void *)picmphdr,sizeof(struct icmp));
if ((log_num+1)>=MAX_LOG_NUM)
{
if (g_logfop && g_logpdx)
SignalEvent(g_logpdx,g_logfop);
log_num=0;
lcall_num++;
if (lcall_num>=MAX_CALL_NUM)
lcall_num=0;
}
else
{
log_num++;
}
}
void UTIL_IcmpAlarm(
struct Fw_Rule_Node *pIcmpRule,
struct ip *piphdr,
struct icmp *picmphdr
)
{
g_AllAlarm[acall_num].Alarms[alarm_num].ID=pIcmpRule->ID;
g_AllAlarm[acall_num].Alarms[alarm_num].protocol=PT_ICMP;
g_AllAlarm[acall_num].alarm_num=alarm_num+1;
memcpy((void *)&g_AllAlarm[acall_num].Alarms[alarm_num].ip_pkt,(void *)piphdr,sizeof(struct ip));
memcpy((void *)&g_AllAlarm[acall_num].Alarms[alarm_num].alarm_trans_pkt.icmp_pkt,(void *)picmphdr,sizeof(struct icmp));
if ((alarm_num+1)>=MAX_ALARM_NUM)
{
if (g_alarmfop && g_alarmpdx)
SignalEvent(g_alarmpdx,g_alarmfop);
alarm_num=0;
acall_num++;
if (acall_num>=MAX_CALL_NUM)
acall_num=0;
}
else
{
alarm_num++;
}
}
void UTIL_RestipWriteLog(
struct Fw_Rule_Node *pRestipRule,
struct ip *piphdr
)
{
g_AllLog[lcall_num].logs[log_num].ID=pRestipRule->ID;
g_AllLog[lcall_num].log_num=log_num+1;
g_AllLog[lcall_num].protocol=PT_RESTIP;
memcpy((void *)&g_AllLog[lcall_num].logs[log_num].ip_pkt,(void *)piphdr,sizeof(struct ip));
if ((log_num+1)>=MAX_LOG_NUM)
{
if (g_logfop && g_logpdx)
SignalEvent(g_logpdx,g_logfop);
log_num=0;
lcall_num++;
if (lcall_num>=MAX_CALL_NUM)
lcall_num=0;
}
else
{
log_num++;
}
}
void UTIL_RestipAlarm(
struct Fw_Rule_Node *pRestipRule,
struct ip *piphdr
)
{
g_AllAlarm[acall_num].Alarms[alarm_num].ID=pRestipRule->ID;
g_AllAlarm[acall_num].Alarms[alarm_num].protocol=PT_RESTIP;
g_AllAlarm[acall_num].alarm_num=alarm_num+1;
memcpy((void *)&g_AllAlarm[acall_num].Alarms[alarm_num].ip_pkt,(void *)piphdr,sizeof(struct ip));
if ((alarm_num+1)>=MAX_ALARM_NUM)
{
if (g_alarmfop && g_alarmpdx)
SignalEvent(g_alarmpdx,g_alarmfop);
alarm_num=0;
acall_num++;
if (acall_num>=MAX_CALL_NUM)
acall_num=0;
}
else
{
alarm_num++;
}
}
/////////////////////////////////////////////////////////////////
//
//函数UTIL_SizeupPort
//
//参数
//USHORT cur_port,char p_operator,USHORT port1,USHORT port2
//
//返回值
//TRUE,FALSE
//
//
//备注
//cur_port是否满足规则中对端口的要求
BOOLEAN UTIL_SizeupPort(
USHORT cur_port,
char p_operator,
USHORT port1,
USHORT port2
)
{
// 对端口没有特殊要求,即默认任何端口都符合
if (port1==0 && port2==0)
return TRUE;
switch (p_operator)
{
case OP_GT:
return (cur_port>port1);
case OP_LT:
return (cur_port<port1);
case OP_EQ:
return (cur_port==port1);
case OP_NE:
return (cur_port != port1);
case OP_BW:
return (cur_port>port1 && cur_port<port2);
}
return FALSE;
}
//////////////////////////////////////////////////////
//
//函数UTIL_GetCurrentTime()
//
//参数
//无
//
//返回值
//从当天零点到调用函数时的秒数
//
//
int UTIL_GetCurrentTime(void)
{
LARGE_INTEGER current;
ULONGLONG cursec=0;
ULONG sec=0;
KeQuerySystemTime(&current);
cursec=current.QuadPart/10000000;
sec=(int)(cursec%86400);
return (sec+3600*8);
}
/*-------------------------------------------------------------------
数据检查相关函数
--------------------------------------------------------------------*/
//kmp算法中求next
void UTIL_getnext(char *p,int len_p,short *next)//p为子串,len_p为子串长度
{
short i=0,j=-1;
next[0]=-1;
while (i<=len_p-1)
{
while(j>=0 && p[i]!=p[j])
{
j=next[j];
}
i++;j++;next[i]=j;
}
}
//kmp 算法
BOOLEAN UTIL_kmp(
char *data,
int datasize,
char *keyword,
int keysize,
short *next
)
{
int i=0,j=0;
while(i<=datasize-1&&j<=keysize-1)
{
while(j>=0 && data[i]!=keyword[j])
{
j=next[j];
}
i++;j++;
}
if (j==keysize) return TRUE;
else return FALSE;
}
///////////////////////////////////////////////
//查找符合端口节点的函数
//
//参数
//
//返回值
//
//备注
struct KeyList *UTIL_FindPortNode(USHORT port,int bkey)
{
struct KeyList *plistnode;
if(bkey==1)
plistnode=g_Rules.global.pkeylist;
else if(bkey == 0)
plistnode=g_Rules.global.pURLList;
else
plistnode=g_Rules.global.pTCPURLList;
while (plistnode)
{
if (port<plistnode->port)
{
plistnode=plistnode->next;
continue;
}
if (plistnode->port==port)
return plistnode;
if(port>plistnode->port)
break;
}
return NULL;
}
///////////////////////////////////////////////
//插入关键字节点的函数
//
//参数
//
//返回值
//
//备注
void UTIL_InsertKeyNode(struct KeyList *pnode,UINT id,char *key,ULONG keylen)
{
struct Keyword *keynode,*newkey;
newkey=(struct Keyword *)UTIL_AllocateMemory(sizeof(struct Keyword));
newkey->id=id;
newkey->keyword=key;
newkey->len=keylen;
newkey->overlap=(short *)UTIL_AllocateMemory((keylen+1)*sizeof(short));
UTIL_getnext(newkey->keyword,newkey->len ,newkey->overlap);
newkey->next=NULL;
keynode=pnode->pkeyword;
while(keynode->next)
{
keynode=keynode->next;
}
keynode->next=newkey;
return;
}
///////////////////////////////////////////////
//找到符合端口的插入函数
//
//参数
//
//返回值
//
//备注
void UTIL_FindRightPlace(struct KeyList **prenode,USHORT port,int bkey)
{
struct KeyList *pnode,*ppre,*pnext;
if(bkey==1)
pnode=g_Rules.global.pkeylist;
else if(bkey == 0)
pnode=g_Rules.global.pURLList;
else
pnode=g_Rules.global.pTCPURLList;
if (pnode==NULL || port<pnode->port)
{
*prenode=NULL;
return;
}
else
{
ppre=pnode;
pnext=ppre->next;
while (pnext)
{
if (port > ppre->port && port < pnext->port ) // I find it
{
*prenode=ppre;
return;
}
ppre=pnext;
pnext=ppre->next;
}
//pnext==null
*prenode=ppre;
return;
}
}
///////////////////////////////////////////////
//插入新的端口节点到端口链表末尾的函数
//
//参数
//
//返回值
//
//备注
void UTIL_InsertNewPortNode(struct KeyList *pprenode,
struct KeyList *pnewnode,
int bkey
)
{
if (pprenode==NULL)
{
if(bkey==1)
{
pnewnode->next=g_Rules.global.pkeylist;
g_Rules.global.pkeylist=pnewnode;
}
else if(bkey == 0)
{
pnewnode->next=g_Rules.global.pURLList;
g_Rules.global.pURLList=pnewnode;
}
else
{
pnewnode->next=g_Rules.global.pTCPURLList;
g_Rules.global.pTCPURLList=pnewnode;
}
}
else
{
pnewnode->next=pprenode->next;
pprenode->next=pnewnode;
}
}
///////////////////////////////////////////////
//插入端口节点函数
//
//参数
//
//返回值
//
//备注
void UTIL_UpdatePortNode(struct Interface_Keyword *pkeyhead,
char *key,
ULONG keylen,
int bkey
)
{
struct KeyList *pnode;
struct KeyList *prenode,*nextnode,*pnewport;
struct Keyword *pnewkey;
if (pnode=UTIL_FindPortNode(pkeyhead->port,bkey))
{
UTIL_InsertKeyNode(pnode,pkeyhead->id,key,keylen);
}
else
{
pnewkey=(struct Keyword *)UTIL_AllocateMemory(sizeof(struct Keyword));
pnewport=(struct KeyList *)UTIL_AllocateMemory(sizeof(struct KeyList));
pnewkey->id=pkeyhead->id;
pnewkey->keyword=key;
pnewkey->len=keylen;
pnewkey->overlap=(short *)UTIL_AllocateMemory((keylen+1)*sizeof(short));
UTIL_getnext(pnewkey->keyword,pnewkey->len ,pnewkey->overlap);
pnewkey->next=NULL;
pnewport->port=pkeyhead->port;
pnewport->pkeyword=pnewkey;
UTIL_FindRightPlace(&prenode,pnewport->port,bkey);
UTIL_InsertNewPortNode(prenode,pnewport,bkey);
}
}
///////////////////////////////////////////////
//关键字增加函数
//
//参数
//
//返回值
//
//备注
void UTIL_AddKeyword(PVOID keyword,ULONG buflen,int bkey)
{
struct Interface_Keyword *pkeyhead;
char *key;
ULONG keylen;
PVOID keybuf;
keybuf=UTIL_AllocateMemory(buflen);
memcpy(keybuf,keyword,buflen);
pkeyhead=(struct Interface_Keyword *)keybuf;
key=(char *)keybuf+sizeof(struct Interface_Keyword);
keylen=buflen-sizeof(struct Interface_Keyword);
UTIL_UpdatePortNode(pkeyhead,key,keylen,bkey);
}
///////////////////////////////////////////////
//关键字删除函数
//
//参数
//
//返回值
//
//备注
void UTIL_DelKeyword(void)
{
struct KeyList *ptr_current=NULL;
struct KeyList *ptr_next=NULL;
if (g_Rules.global.pkeylist!=NULL)
{
ptr_current=g_Rules.global.pkeylist;
ptr_next=ptr_current->next;
while (ptr_current!=NULL)
{
UTIL_FreeMemory((void *)ptr_current);
ptr_current=ptr_next;
if (ptr_current!=NULL)
ptr_next=ptr_current->next;
}
g_Rules.global.pkeylist=NULL;
}
return;
}
///////////////////////////////////////////////
//URL删除函数
//
//参数
//
//返回值
//
//备注
void UTIL_DelURLWord(void)
{
struct KeyList *ptr_current=NULL;
struct KeyList *ptr_next=NULL;
if (g_Rules.global.pURLList!=NULL)
{
ptr_current=g_Rules.global.pURLList;
ptr_next=ptr_current->next;
while (ptr_current!=NULL)
{
UTIL_FreeMemory((void *)ptr_current);
ptr_current=ptr_next;
if (ptr_current!=NULL)
ptr_next=ptr_current->next;
}
g_Rules.global.pURLList=NULL;
}
return;
}
//删除TCP
void UTIL_DelTCPURLWord(void)
{
struct KeyList *ptr_current=NULL;
struct KeyList *ptr_next=NULL;
if (g_Rules.global.pTCPURLList!=NULL)
{
ptr_current=g_Rules.global.pTCPURLList;
ptr_next=ptr_current->next;
while (ptr_current!=NULL)
{
UTIL_FreeMemory((void *)ptr_current);
ptr_current=ptr_next;
if (ptr_current!=NULL)
ptr_next=ptr_current->next;
}
g_Rules.global.pTCPURLList=NULL;
}
return;
}
///////////////////////////////////////////////
//数据检查函数
//
//参数
//data 被检查的数据
//datasize mean as name
//nSport 源端口
//nDport 目标端口
//
//返回值
//true ------被检查的数据中包含关键字
//false ------被检查的数据中不包含关键字
//
//备注
//检查包中的数据是否包含关键字
BOOLEAN UTIL_ExamineData(
char *data,
int datasize,
USHORT nSport,
USHORT nDport
)
{
struct Keyword *nextkey;
struct KeyList *nextkeylist;
BOOLEAN bDataContain;
//if 要检查数据包内容 并且 端口符合
if (g_Rules.global.pkeylist)
{
//调用数据检查函数UTIL_kmp(.....)
nextkeylist=g_Rules.global.pkeylist;
while (nextkeylist && (nextkeylist->port==nSport || nextkeylist->port==nDport))
{
nextkey=nextkeylist->pkeyword;
while(nextkey)
{
bDataContain=UTIL_kmp(
data,
datasize,
nextkey->keyword,
nextkey->len,
nextkey->overlap
);
//if 包含关键字 返回 TRUE
if (bDataContain)
{
return (TRUE);
}
nextkey=nextkey->next;
}
nextkeylist=nextkeylist->next;
}
//无关键字匹配
return FALSE;
}
return FALSE;
}
//
BOOLEAN UTIL_ExamineURL(ULONG ip_dst, ULONG ip_src)
{
struct Keyword *nextkey;
struct KeyList *nextkeylist;
BOOLEAN bDataContain;
ULONG lval;
//if 要检查数据包内容 并且 端口符合
if (g_Rules.global.pURLList)
{
//调用数据检查函数UTIL_kmp(.....)
nextkeylist=g_Rules.global.pURLList;
while (nextkeylist)
{
nextkey=nextkeylist->pkeyword;
while(nextkey)
{
lval = atol(nextkey->keyword);
if (lval == ip_dst || lval == ip_src)
return TRUE;
nextkey=nextkey->next;
}
nextkeylist=nextkeylist->next;
}
//无关键字匹配
return FALSE;
}
return FALSE;
}
//根据IP地址拦截
BOOLEAN UTIL_ExamineTCPURL(ULONG ip_dst, ULONG ip_src)
{
struct Keyword *nextkey;
struct KeyList *nextkeylist;
BOOLEAN bDataContain;
ULONG lval;
//if 要检查数据包内容 并且 端口符合
if (g_Rules.global.pTCPURLList)
{
//调用数据检查函数UTIL_kmp(.....)
nextkeylist=g_Rules.global.pTCPURLList;
while (nextkeylist)
{
nextkey=nextkeylist->pkeyword;
while(nextkey)
{
lval = atol(nextkey->keyword);
if (lval == ip_dst || lval == ip_src)
return TRUE;
nextkey=nextkey->next;
}
nextkeylist=nextkeylist->next;
}
//无关键字匹配
return FALSE;
}
return FALSE;
}
/////////////////////////////////////////////////////////////////
//
//函数UTIL_AddAllrules
//
//参数
//all_rules
//
//返回值
//是,否成功
//
//
//备注
//增加所有规则
BOOLEAN UTIL_AddAllrules(struct All_Rules *pallrules)
{
int i;
struct Fw_Rule_Node *ptcprule,*pt_in,*pt_out;
struct Fw_Rule_Node *pudprule,*pu_in,*pu_out;
struct Fw_Rule_Node *picmprule,*pi_in,*pi_out;
struct Fw_Rule_Node *prestiprule,*pr_in,*pr_out;
//KdPrint(("UTIL_AddAllrules"));
for(i=0;i<pallrules->rules_num;i++)
{
switch (pallrules->Rules[i].proto)
{
case PT_TCP:
if (pallrules->Rules[i].direct & DT_IN)
{
ptcprule=(struct Fw_Rule_Node *)UTIL_AllocateMemory(sizeof(struct Fw_Rule_Node));
ptcprule->action =pallrules->Rules[i].action;
ptcprule->s_port[0] =pallrules->Rules[i].s_port[0];
ptcprule->s_port[1] =pallrules->Rules[i].s_port[1];
ptcprule->d_port[0] =pallrules->Rules[i].d_port[0];
ptcprule->d_port[1] =pallrules->Rules[i].d_port[1];
ptcprule->sp_operator =pallrules->Rules[i].sp_operator;
ptcprule->dp_operator =pallrules->Rules[i].dp_operator;
ptcprule->direct =pallrules->Rules[i].direct;
ptcprule->ID =pallrules->Rules[i].id;
ptcprule->warn_enable =pallrules->Rules[i].warn_enable;
ptcprule->log_enable =pallrules->Rules[i].log_enable;
ptcprule->ip =pallrules->Rules[i].ip;
ptcprule->mask =pallrules->Rules[i].mask;
ptcprule->schedule.enable =pallrules->Rules[i].time.time_enable;
ptcprule->schedule.start_time=pallrules->Rules[i].time.start_time;
ptcprule->schedule.end_time =pallrules->Rules[i].time.end_time;
ptcprule->tcpflag =pallrules->Rules[i].tcpflag;
ptcprule->next =NULL;
if (g_Rules.tcp.pin==NULL) //头节点
{
g_Rules.tcp.pin=ptcprule;
pt_in=ptcprule;
}
else
{
pt_in->next=ptcprule;
pt_in=ptcprule;
}
/*
KdPrint(("in action=%u s_port=%d d_port=%d",
ptcprule->action,
ptcprule->s_port[0],
ptcprule->d_port[0]));
*/
}
if(pallrules->Rules[i].direct & DT_OUT)
{
ptcprule=(struct Fw_Rule_Node *)UTIL_AllocateMemory(sizeof(struct Fw_Rule_Node));
ptcprule->action =pallrules->Rules[i].action;
ptcprule->s_port[0] =pallrules->Rules[i].s_port[0];
ptcprule->s_port[1] =pallrules->Rules[i].s_port[1];
ptcprule->d_port[0] =pallrules->Rules[i].d_port[0];
ptcprule->d_port[1] =pallrules->Rules[i].d_port[1];
ptcprule->sp_operator =pallrules->Rules[i].sp_operator;
ptcprule->dp_operator =pallrules->Rules[i].dp_operator;
ptcprule->direct =pallrules->Rules[i].direct;
ptcprule->ID =pallrules->Rules[i].id;
ptcprule->warn_enable =pallrules->Rules[i].warn_enable;
ptcprule->log_enable =pallrules->Rules[i].log_enable;
ptcprule->ip =pallrules->Rules[i].ip;
ptcprule->mask =pallrules->Rules[i].mask;
ptcprule->schedule.enable =pallrules->Rules[i].time.time_enable;
ptcprule->schedule.start_time=pallrules->Rules[i].time.start_time;
ptcprule->schedule.end_time =pallrules->Rules[i].time.end_time;
ptcprule->tcpflag =pallrules->Rules[i].tcpflag;
ptcprule->next=NULL;
/*
KdPrint(("action=%u s_port=%d d_port=%d",
ptcprule->action,
ptcprule->s_port[0],
ptcprule->d_port[0]));
*/
if (g_Rules.tcp.pout==NULL) //头节点
{
g_Rules.tcp.pout=ptcprule;
pt_out=ptcprule;
}
else
{
pt_out->next=ptcprule;
pt_out=ptcprule;
}
}
break;
case PT_UDP:
if (pallrules->Rules[i].direct&DT_IN)
{
pudprule=(struct Fw_Rule_Node *)UTIL_AllocateMemory(sizeof(struct Fw_Rule_Node));
pudprule->action =pallrules->Rules[i].action;
pudprule->s_port[0] =pallrules->Rules[i].s_port[0];
pudprule->s_port[1] =pallrules->Rules[i].s_port[1];
pudprule->d_port[0] =pallrules->Rules[i].d_port[0];
pudprule->d_port[1] =pallrules->Rules[i].d_port[1];
pudprule->sp_operator =pallrules->Rules[i].sp_operator;
pudprule->dp_operator =pallrules->Rules[i].dp_operator;
pudprule->direct =pallrules->Rules[i].direct;
pudprule->ID =pallrules->Rules[i].id;
pudprule->warn_enable =pallrules->Rules[i].warn_enable;
pudprule->log_enable =pallrules->Rules[i].log_enable;
pudprule->ip =pallrules->Rules[i].ip;
pudprule->mask =pallrules->Rules[i].mask;
pudprule->schedule.enable =pallrules->Rules[i].time.time_enable;
pudprule->schedule.start_time=pallrules->Rules[i].time.start_time;
pudprule->schedule.end_time =pallrules->Rules[i].time.end_time;
pudprule->next =NULL;
if (g_Rules.udp.pin==NULL) //头节点
{
g_Rules.udp.pin=pudprule;
pu_in=pudprule;
}
else
{
pu_in->next=pudprule;
pu_in=pudprule;
}
}
if (pallrules->Rules[i].direct&DT_OUT)
{
pudprule=(struct Fw_Rule_Node *)UTIL_AllocateMemory(sizeof(struct Fw_Rule_Node));
pudprule->action =pallrules->Rules[i].action;
pudprule->s_port[0] =pallrules->Rules[i].s_port[0];
pudprule->s_port[1] =pallrules->Rules[i].s_port[1];
pudprule->d_port[0] =pallrules->Rules[i].d_port[0];
pudprule->d_port[1] =pallrules->Rules[i].d_port[1];
pudprule->sp_operator =pallrules->Rules[i].sp_operator;
pudprule->dp_operator =pallrules->Rules[i].dp_operator;
pudprule->direct =pallrules->Rules[i].direct;
pudprule->ID =pallrules->Rules[i].id;
pudprule->warn_enable =pallrules->Rules[i].warn_enable;
pudprule->log_enable =pallrules->Rules[i].log_enable;
pudprule->ip =pallrules->Rules[i].ip;
pudprule->mask =pallrules->Rules[i].mask;
pudprule->schedule.enable =pallrules->Rules[i].time.time_enable;
pudprule->schedule.start_time=pallrules->Rules[i].time.start_time;
pudprule->schedule.end_time =pallrules->Rules[i].time.end_time;
pudprule->next =NULL;
if (g_Rules.udp.pout==NULL) //头节点
{
g_Rules.udp.pout=pudprule;
pu_out=pudprule;
}
else
{
pu_out->next=pudprule;
pu_out=pudprule;
}
}
break;
case PT_ICMP:
if (pallrules->Rules[i].direct&DT_IN)
{
picmprule=(struct Fw_Rule_Node *)UTIL_AllocateMemory(sizeof(struct Fw_Rule_Node));
picmprule->action =pallrules->Rules[i].action;
picmprule->direct =pallrules->Rules[i].direct;
picmprule->ID =pallrules->Rules[i].id;
picmprule->warn_enable =pallrules->Rules[i].warn_enable;
picmprule->log_enable =pallrules->Rules[i].log_enable;
picmprule->ip =pallrules->Rules[i].ip;
picmprule->mask =pallrules->Rules[i].mask;
picmprule->schedule.enable =pallrules->Rules[i].time.time_enable;
picmprule->schedule.start_time=pallrules->Rules[i].time.start_time;
picmprule->schedule.end_time=pallrules->Rules[i].time.end_time;
picmprule->next =NULL;
if (g_Rules.icmp.pin==NULL) //头节点
{
g_Rules.icmp.pin=picmprule;
pi_in=picmprule;
}
else
{
pi_in->next=picmprule;
pi_in=picmprule;
}
}
if (pallrules->Rules[i].direct&DT_OUT)
{
picmprule=(struct Fw_Rule_Node *)UTIL_AllocateMemory(sizeof(struct Fw_Rule_Node));
picmprule->action =pallrules->Rules[i].action;
picmprule->direct =pallrules->Rules[i].direct;
picmprule->ID =pallrules->Rules[i].id;
picmprule->warn_enable =pallrules->Rules[i].warn_enable;
picmprule->log_enable =pallrules->Rules[i].log_enable;
picmprule->ip =pallrules->Rules[i].ip;
picmprule->mask =pallrules->Rules[i].mask;
picmprule->schedule.enable =pallrules->Rules[i].time.time_enable;
picmprule->schedule.start_time=pallrules->Rules[i].time.start_time;
picmprule->schedule.end_time=pallrules->Rules[i].time.end_time;
picmprule->next =NULL;
if (g_Rules.icmp.pout==NULL) //头节点
{
g_Rules.icmp.pout=picmprule;
pi_out=picmprule;
}
else
{
pi_out->next=picmprule;
pi_out=picmprule;
}
}
break;
case PT_RESTIP:
if (pallrules->Rules[i].direct & DT_IN)
{
prestiprule=(struct Fw_Rule_Node *)UTIL_AllocateMemory(sizeof(struct Fw_Rule_Node));
prestiprule->action =pallrules->Rules[i].action;
prestiprule->direct =pallrules->Rules[i].direct;
prestiprule->ID =pallrules->Rules[i].id;
prestiprule->warn_enable =pallrules->Rules[i].warn_enable;
prestiprule->log_enable =pallrules->Rules[i].log_enable;
prestiprule->ip =pallrules->Rules[i].ip;
prestiprule->mask =pallrules->Rules[i].mask;
prestiprule->schedule.enable=pallrules->Rules[i].time.time_enable;
prestiprule->schedule.start_time=pallrules->Rules[i].time.start_time;
prestiprule->schedule.end_time=pallrules->Rules[i].time.end_time;
prestiprule->next =NULL;
if (g_Rules.ip.pin==NULL) //头节点
{
g_Rules.ip.pin=prestiprule;
pr_in=prestiprule;
}
else
{
pr_in->next=prestiprule;
pr_in=prestiprule;
}
}
if(pallrules->Rules[i].direct & DT_OUT)
{
prestiprule=(struct Fw_Rule_Node *)UTIL_AllocateMemory(sizeof(struct Fw_Rule_Node));
prestiprule->action =pallrules->Rules[i].action;
prestiprule->direct =pallrules->Rules[i].direct;
prestiprule->ID =pallrules->Rules[i].id;
prestiprule->warn_enable =pallrules->Rules[i].warn_enable;
prestiprule->log_enable =pallrules->Rules[i].log_enable;
prestiprule->ip =pallrules->Rules[i].ip;
prestiprule->mask =pallrules->Rules[i].mask;
prestiprule->schedule.enable=pallrules->Rules[i].time.time_enable;
prestiprule->schedule.start_time=pallrules->Rules[i].time.start_time;
prestiprule->schedule.end_time=pallrules->Rules[i].time.end_time;
prestiprule->next =NULL;
if (g_Rules.ip.pout==NULL) //头节点
{
g_Rules.ip.pout=prestiprule;
pr_out=prestiprule;
}
else
{
pr_out->next=prestiprule;
pr_out=prestiprule;
}
}
break;
default:
//return FALSE; //skip not define protocol
break;
} // end of switch (protocol)
} //end of for
return TRUE;
}
/////////////////////////////////////////////////////////////////
//
//函数UTIL_DelAllrules
//
//参数
//无
//
//返回值
//是,否成功
//
//
//备注
//删除所有规则
BOOLEAN UTIL_DelAllrules(void)
{
struct Fw_Rule_Node *ptr_current=NULL;
struct Fw_Rule_Node *ptr_next=NULL;
//KdPrint(("UTIL_DelAllrules"));
//tcp in chain
if (g_Rules.tcp.pin!=NULL)
{
ptr_current=g_Rules.tcp.pin;
ptr_next=ptr_current->next;
while (ptr_current!=NULL)
{
UTIL_FreeMemory((void *)ptr_current);
ptr_current=ptr_next;
if (ptr_current!=NULL)
ptr_next=ptr_current->next;
}
g_Rules.tcp.pin=NULL;
}
//tcp out chain
if (g_Rules.tcp.pout!=NULL)
{
ptr_current=g_Rules.tcp.pout;
ptr_next=ptr_current->next;
while (ptr_current!=NULL)
{
UTIL_FreeMemory((void *)ptr_current);
ptr_current=ptr_next;
if (ptr_current!=NULL)
ptr_next=ptr_current->next;
}
g_Rules.tcp.pout=NULL;
}
//udp in chain
if (g_Rules.udp.pin!=NULL)
{
ptr_current=g_Rules.udp.pin;
ptr_next=ptr_current->next;
while (ptr_current!=NULL)
{
UTIL_FreeMemory((void *)ptr_current);
ptr_current=ptr_next;
if (ptr_current!=NULL)
ptr_next=ptr_current->next;
}
g_Rules.udp.pin=NULL;
}
//udp out chain
if (g_Rules.udp.pout!=NULL)
{
ptr_current=g_Rules.udp.pout;
ptr_next=ptr_current->next;
while (ptr_current!=NULL)
{
UTIL_FreeMemory((void *)ptr_current);
ptr_current=ptr_next;
if (ptr_current!=NULL)
ptr_next=ptr_current->next;
}
g_Rules.udp.pout=NULL;
}
//icmp in chain
if (g_Rules.icmp.pin!=NULL)
{
ptr_current=g_Rules.icmp.pin;
ptr_next=ptr_current->next;
while (ptr_current!=NULL)
{
UTIL_FreeMemory((void *)ptr_current);
ptr_current=ptr_next;
if (ptr_current!=NULL)
ptr_next=ptr_current->next;
}
g_Rules.icmp.pin=NULL;
}
//icmp out chain
if (g_Rules.icmp.pout!=NULL)
{
ptr_current=g_Rules.icmp.pout;
ptr_next=ptr_current->next;
while (ptr_current!=NULL)
{
UTIL_FreeMemory((void *)ptr_current);
ptr_current=ptr_next;
if (ptr_current!=NULL)
ptr_next=ptr_current->next;
}
g_Rules.icmp.pout=NULL;
}
//restip in chain
if (g_Rules.ip.pin!=NULL)
{
ptr_current=g_Rules.ip.pin;
ptr_next=ptr_current->next;
while (ptr_current!=NULL)
{
UTIL_FreeMemory((void *)ptr_current);
ptr_current=ptr_next;
if (ptr_current!=NULL)
ptr_next=ptr_current->next;
}
g_Rules.ip.pin=NULL;
}
//restip out chain
if (g_Rules.ip.pout!=NULL)
{
ptr_current=g_Rules.ip.pout;
ptr_next=ptr_current->next;
while (ptr_current!=NULL)
{
UTIL_FreeMemory((void *)ptr_current);
ptr_current=ptr_next;
if (ptr_current!=NULL)
ptr_next=ptr_current->next;
}
g_Rules.ip.pout=NULL;
}
return TRUE;
}
UCHAR UTIL_MatchTcpRule(struct ip *pIpHeader, struct tcphdr *pTcpHeader, UCHAR Direct)
{
UCHAR nAction=NOT_MATCH;
USHORT nSrcPort, nDstPort;
ULONG nSrcIP, nDstIP;
struct Fw_Rule *pTcpRule=NULL;
struct Fw_Rule_Node *ptr=NULL;
//KdPrint(("UTIL_MatchTcpRule"));
pTcpRule=&g_Rules.tcp;
if(!pTcpRule->enable) return DENY; //不允许TCP协议通过
if(Direct==DT_OUT)
{
nSrcIP=(ULONG)pIpHeader->ip_src.s_addr;
nDstIP=(ULONG)pIpHeader->ip_dst.s_addr;
nSrcPort=UTIL_ntohs(pTcpHeader->th_sport);
nDstPort=UTIL_ntohs(pTcpHeader->th_dport);
ptr=pTcpRule->pout;
}
else
{
nSrcIP=pIpHeader->ip_dst.s_addr;
nDstIP=pIpHeader->ip_src.s_addr;
nSrcPort=UTIL_ntohs(pTcpHeader->th_dport);
nDstPort=UTIL_ntohs(pTcpHeader->th_sport);
ptr=pTcpRule->pin;
}
//KdPrint(("UTIL_MatchTcpRule ..."));
for(; ptr!=NULL; ptr=ptr->next)
{
if(ptr->schedule.enable)
{
int cur_time=UTIL_GetCurrentTime();
// if 当前时间不在时间表范围内返回 PASS
if (cur_time<ptr->schedule.start_time ||cur_time>ptr->schedule.end_time)
{
ptr=ptr->next; //取下一个节点
continue;
}
}
if(UTIL_SizeupPort(nSrcPort, ptr->sp_operator, ptr->s_port[0], ptr->s_port[1]) &&
UTIL_SizeupPort(nDstPort, ptr->dp_operator, ptr->d_port[0], ptr->d_port[1]) &&
((ptr->ip==(nDstIP & ptr->mask))||(ptr->ip==0)))
{
//tcpflag add by df
if (ptr->tcpflag==0||ptr->tcpflag==pTcpHeader->th_flags)
{
nAction=ptr->action;
break;
}
}
}
UTIL_CountPacket(PT_TCP, Direct, nAction, (int)UTIL_ntohs(pIpHeader->ip_len));
if (nAction!=NOT_MATCH)
{
if (g_Rules.global.warn_enable && ptr->warn_enable && g_alarmfop &&g_alarmpdx)
UTIL_TcpAlarm(ptr, pIpHeader, pTcpHeader);
if (g_Rules.global.log_enable && ptr->log_enable && g_logfop && g_logpdx)
UTIL_TcpWriteLog(ptr, pIpHeader,pTcpHeader );
}
return nAction;
}
UCHAR UTIL_MatchUdpRule(struct ip *pIpHeader, struct udphdr *pUdpHeader, UCHAR Direct)
{
UCHAR nAction=NOT_MATCH;
USHORT nSrcPort, nDstPort;
ULONG nSrcIP, nDstIP;
struct Fw_Rule_Node *ptr=NULL;
if(!g_Rules.udp.enable) return DENY; //不允许UDP协议通过
if(Direct==DT_OUT)
{
nSrcIP=pIpHeader->ip_src.s_addr;
nDstIP=pIpHeader->ip_dst.s_addr;
nSrcPort=UTIL_ntohs(pUdpHeader->uh_sport);
nDstPort=UTIL_ntohs(pUdpHeader->uh_dport);
ptr=g_Rules.udp.pout;
}
else
{
nSrcIP=pIpHeader->ip_dst.s_addr;
nDstIP=pIpHeader->ip_src.s_addr;
nSrcPort=UTIL_ntohs(pUdpHeader->uh_dport);
nDstPort=UTIL_ntohs(pUdpHeader->uh_sport);
ptr=g_Rules.udp.pin;
}
for(; ptr!=NULL; ptr=ptr->next)
{
if(ptr->schedule.enable)
{
int cur_time=UTIL_GetCurrentTime();
// if 当前时间不在时间表范围内
// 返回 PASS
if (cur_time<ptr->schedule.start_time ||cur_time>ptr->schedule.end_time)
{
ptr=ptr->next; //取下一个节点
continue;
}
}
if(UTIL_SizeupPort(nSrcPort, ptr->sp_operator, ptr->s_port[0], ptr->s_port[1]) &&
UTIL_SizeupPort(nDstPort, ptr->dp_operator, ptr->d_port[0], ptr->d_port[1]) &&
((ptr->ip==(nDstIP & ptr->mask))||(ptr->ip==0)))
{
nAction=ptr->action;
break;
}
}
UTIL_CountPacket(PT_UDP, Direct, nAction, (int)UTIL_ntohs(pIpHeader->ip_len));
if (nAction!=NOT_MATCH)
{
if (g_Rules.global.warn_enable && ptr->warn_enable && g_alarmfop &&g_alarmpdx)
UTIL_UdpAlarm(ptr, pIpHeader, pUdpHeader);
if (g_Rules.global.log_enable && ptr->log_enable && g_logfop && g_logpdx)
UTIL_UdpWriteLog(ptr, pIpHeader, pUdpHeader);
}
return nAction;
}
UCHAR UTIL_MatchIcmpRule(struct ip *pIpHeader, struct icmp *pIcmpHeader, UCHAR Direct)
{
UCHAR nAction=NOT_MATCH;
ULONG nSrcIP, nDstIP;
struct Fw_Rule_Node *ptr=NULL;
if(!g_Rules.icmp.enable) return DENY; //不允许ICMP协议通过
if(Direct==DT_OUT)
{
nSrcIP=pIpHeader->ip_src.s_addr;
nDstIP=pIpHeader->ip_dst.s_addr;
ptr=g_Rules.icmp.pout;
}
else
{
nSrcIP=pIpHeader->ip_dst.s_addr;
nDstIP=pIpHeader->ip_src.s_addr;
ptr=g_Rules.icmp.pin;
}
for(; ptr!=NULL; ptr=ptr->next)
{
if(ptr->schedule.enable)
{
int cur_time=UTIL_GetCurrentTime();
// if 当前时间不在时间表范围内
// 返回 PASS
if (cur_time<ptr->schedule.start_time ||cur_time>ptr->schedule.end_time)
{
ptr=ptr->next; //取下一个节点
continue;
}
}
if((ptr->ip==(nDstIP & ptr->mask))||(ptr->ip==0))
{
nAction=ptr->action;
break;
}
}
UTIL_CountPacket(PT_ICMP, Direct, nAction, (int)UTIL_ntohs(pIpHeader->ip_len));
if (nAction!=NOT_MATCH)
{
if (g_Rules.global.warn_enable && ptr->warn_enable && g_alarmfop &&g_alarmpdx)
UTIL_IcmpAlarm(ptr, pIpHeader, pIcmpHeader);
if (g_Rules.global.log_enable && ptr->log_enable && g_logfop && g_logpdx)
UTIL_IcmpWriteLog(ptr, pIpHeader, pIcmpHeader);
}
return nAction;
}
UCHAR UTIL_MatchIpRule(struct ip *pIpHeader, UCHAR Direct)
{
UCHAR nAction=NOT_MATCH;
ULONG nSrcIP, nDstIP;
struct Fw_Rule_Node *ptr=NULL;
if(!g_Rules.ip.enable) return DENY; //不允许ICMP协议通过
if(Direct==DT_OUT)
{
nSrcIP=pIpHeader->ip_src.s_addr;
nDstIP=pIpHeader->ip_dst.s_addr;
ptr=g_Rules.ip.pout;
}
else
{
nSrcIP=pIpHeader->ip_dst.s_addr;
nDstIP=pIpHeader->ip_src.s_addr;
ptr=g_Rules.ip.pin;
}
for(; ptr!=NULL; ptr=ptr->next)
{
if(ptr->schedule.enable)
{
int cur_time=UTIL_GetCurrentTime();
// if 当前时间不在时间表范围内返回 PASS
if (cur_time<ptr->schedule.start_time ||cur_time>ptr->schedule.end_time)
{
ptr=ptr->next; //取下一个节点
continue;
}
}
if((ptr->ip==(nDstIP & ptr->mask))||(ptr->ip==0))
{
nAction=ptr->action;
break;
}
}
UTIL_CountPacket(PT_RESTIP, Direct, nAction, (int)UTIL_ntohs(pIpHeader->ip_len));
if (nAction!=NOT_MATCH)
{
if (g_Rules.global.warn_enable && ptr->warn_enable && g_alarmfop &&g_alarmpdx)
UTIL_RestipAlarm(ptr, pIpHeader);
if (g_Rules.global.log_enable && ptr->log_enable && g_logfop && g_logpdx)
UTIL_RestipWriteLog(ptr, pIpHeader);
}
return nAction;
}
UCHAR UTIL_MatchNotIpRule(PNDIS_PACKET Packet, USHORT nEtherType, UCHAR Direct)
{
return ALLOW;
}
UCHAR UTIL_MatchRule(PNDIS_PACKET Packet, UCHAR Direct)
{
ULONG nNumberOfBytesRead = 0;
UCHAR nProtocol;
USHORT nEtherType, nIPhdrLen, nIPOffset;
UCHAR nAction;
ULONG datetime=0;
ULONG datasize;
PUCHAR ppktdata=NULL;
BOOLEAN bisinclude;
//如果防火墙状态为切断所有则返回
if(g_Rules.global.fw_status==FWS_DENYALL)
{
//KdPrint(("FWS_DENYALL"));
return DENY;
}
if(g_Rules.global.fw_status==FWS_ALLOWALL)
{
//KdPrint(("FWS_ALLOWALL"));
return ALLOW;
}
//KdPrint(("UTIL_MatchRule"));
datetime=UTIL_GetCurrentTime();
if (g_Rules.global.schedule.enable)
{
//取得当前时间
int cur_time=UTIL_GetCurrentTime();
// if 当前时间不在时间表范围内 返回 PASS
if (cur_time<g_Rules.global.schedule.start_time||
cur_time>g_Rules.global.schedule.end_time)
{
return ALLOW;
}
}
UTIL_ReadOnPacket(
Packet,
(PUCHAR )&nEtherType,
sizeof( USHORT ),
MEtherType, // See PCAEnet.h
&nNumberOfBytesRead
);
//if 读出不正确,直接PASS
if(!nNumberOfBytesRead) return ALLOW;
nEtherType = UTIL_htons( nEtherType ); //将包类型转换为网络顺序
if( nEtherType == ETHERTYPE_IP ) //if 包类型是IP包
{
//read ip header
UTIL_ReadOnPacket(
Packet,
(PUCHAR )g_pIPHeader,
sizeof(*g_pIPHeader),
MHdrSize, // ATTENTION!!! Media-Dependent!!!
&nNumberOfBytesRead
);
//IP头不完整,丢弃
if(nNumberOfBytesRead<sizeof(struct ip)) return DENY;
//分片非第一片允许通过
nIPOffset=UTIL_ntohs(g_pIPHeader->ip_off);
if(((nIPOffset&IP_DF)==0) && ((nIPOffset&0x1FFF)!=0)) return ALLOW;
nIPhdrLen=g_pIPHeader->ip_hl*4;
nProtocol=g_pIPHeader->ip_p;
// 按照协议,分别进行审计
switch(nProtocol)
{
case IPPROTO_TCP:
if(UTIL_ExamineTCPURL(g_pIPHeader->ip_dst.s_addr,g_pIPHeader->ip_src.s_addr))
{
nAction=DENY;
}
else
{
UTIL_ReadOnPacket(
Packet,
(PUCHAR)g_pTCPHeader,
sizeof(*g_pTCPHeader),
MHdrSize + nIPhdrLen,
&nNumberOfBytesRead
);
//TCP头不完整,不允许通过
if(nNumberOfBytesRead<sizeof(struct tcphdr)) return DENY;
//fetch pkt data
datasize=Packet->Private.TotalLength-MHdrSize-nIPhdrLen-sizeof(struct tcphdr);
ppktdata=UTIL_AllocateMemory(datasize);
UTIL_ReadOnPacket(
Packet,
ppktdata,
datasize,
MHdrSize + nIPhdrLen+sizeof(struct tcphdr),
&nNumberOfBytesRead
);
nAction=UTIL_MatchTcpRule(g_pIPHeader, g_pTCPHeader, Direct);
//examine data
if (nAction==ALLOW)
{
//if contain keyword ,drop
bisinclude=UTIL_ExamineData(ppktdata,datasize,UTIL_ntohs(g_pTCPHeader->th_sport),UTIL_ntohs(g_pTCPHeader->th_dport));
if (bisinclude)
nAction=DENY;
}
}
break;
case IPPROTO_UDP:
if(UTIL_ExamineURL(g_pIPHeader->ip_dst.s_addr,g_pIPHeader->ip_src.s_addr))
nAction=DENY;
else{
UTIL_ReadOnPacket(
Packet,
(PUCHAR)g_pUDPHeader,
sizeof(*g_pUDPHeader),
MHdrSize + nIPhdrLen,
&nNumberOfBytesRead
);
if(nNumberOfBytesRead<sizeof(struct udphdr)) return DENY; //UDP头不完整,不允许通过
nAction=UTIL_MatchUdpRule(g_pIPHeader, g_pUDPHeader, Direct);
}
break;
case IPPROTO_ICMP:
UTIL_ReadOnPacket(
Packet,
(PUCHAR)g_pICMPHeader,
sizeof(*g_pICMPHeader),
MHdrSize + nIPhdrLen,
&nNumberOfBytesRead
);
if(nNumberOfBytesRead<4) return DENY; //ICMP头不完整,不允许通过
nAction=UTIL_MatchIcmpRule(g_pIPHeader, g_pICMPHeader, Direct);
break;
default:
nAction=UTIL_MatchIpRule(g_pIPHeader, Direct);
break;
}
if(nAction==NOT_MATCH)
{
if(g_Rules.global.fw_mode==RM_ALLOW)
{
switch(nProtocol)
{
case IPPROTO_TCP:
bisinclude=UTIL_ExamineData(ppktdata,datasize,UTIL_ntohs(g_pTCPHeader->th_sport),UTIL_ntohs(g_pTCPHeader->th_dport));
if (bisinclude)
nAction=DENY;
else
nAction=ALLOW;
break;
case IPPROTO_UDP:
nAction=ALLOW;
break;
case IPPROTO_ICMP:
nAction=ALLOW;
break;
default:
nAction=ALLOW;
break;
}
}
else
{
nAction=DENY;
}
}
if (ppktdata)
{
UTIL_FreeMemory((void *)ppktdata);
}
return nAction;
}
else
{
nAction=UTIL_MatchNotIpRule(Packet, nEtherType, Direct);
if(nAction==NOT_MATCH)
{
if(g_Rules.global.fw_mode==RM_ALLOW)
{
return ALLOW;
}
else
{
return DENY;
}
}
return nAction;
}
}