📄 protocol.c
字号:
/*
Copyright 2006-2008, V.
For contact information, see http://winaoe.org/
This file is part of WinAoE.
WinAoE is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
WinAoE is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with WinAoE. If not, see <http://www.gnu.org/licenses/>.
*/
#include "portable.h"
#include <ntddk.h>
#include <ndis.h>
#include <ntddndis.h>
#include "protocol.h"
#include "driver.h"
#include "aoe.h"
// in this file
VOID STDCALL ProtocolOpenAdapterComplete(IN NDIS_HANDLE ProtocolBindingContext, IN NDIS_STATUS Status, IN NDIS_STATUS OpenErrorStatus);
VOID STDCALL ProtocolCloseAdapterComplete(IN NDIS_HANDLE ProtocolBindingContext, IN NDIS_STATUS Status);
VOID STDCALL ProtocolSendComplete(IN NDIS_HANDLE ProtocolBindingContext, IN PNDIS_PACKET Packet, IN NDIS_STATUS Status);
VOID STDCALL ProtocolTransferDataComplete(IN NDIS_HANDLE ProtocolBindingContext, IN PNDIS_PACKET Packet, IN NDIS_STATUS Status, IN UINT BytesTransferred);
VOID STDCALL ProtocolResetComplete(IN NDIS_HANDLE ProtocolBindingContext, IN NDIS_STATUS Status);
VOID STDCALL ProtocolRequestComplete(IN NDIS_HANDLE ProtocolBindingContext, IN PNDIS_REQUEST NdisRequest, IN NDIS_STATUS Status);
NDIS_STATUS STDCALL ProtocolReceive(IN NDIS_HANDLE ProtocolBindingContext, IN NDIS_HANDLE MacReceiveContext, IN PVOID HeaderBuffer, IN UINT HeaderBufferSize, IN PVOID LookAheadBuffer, IN UINT LookaheadBufferSize, IN UINT PacketSize);
VOID STDCALL ProtocolReceiveComplete(IN NDIS_HANDLE ProtocolBindingContext);
VOID STDCALL ProtocolStatus(IN NDIS_HANDLE ProtocolBindingContext, IN NDIS_STATUS GeneralStatus, IN PVOID StatusBuffer, IN UINT StatusBufferSize);
VOID STDCALL ProtocolStatusComplete(IN NDIS_HANDLE ProtocolBindingContext);
VOID STDCALL ProtocolBindAdapter(OUT PNDIS_STATUS Status, IN NDIS_HANDLE BindContext, IN PNDIS_STRING DeviceName, IN PVOID SystemSpecific1, IN PVOID SystemSpecific2);
VOID STDCALL ProtocolUnbindAdapter(OUT PNDIS_STATUS Status, IN NDIS_HANDLE ProtocolBindingContext, IN NDIS_HANDLE UnbindContext);
NDIS_STATUS STDCALL ProtocolPnPEvent(IN NDIS_HANDLE ProtocolBindingContext, IN PNET_PNP_EVENT NetPnPEvent);
PCHAR STDCALL NetEventString(IN NET_PNP_EVENT_CODE NetEvent);
#ifdef _MSC_VER
#pragma pack(1)
#endif
typedef struct _HEADER {
UCHAR DestinationMac[6];
UCHAR SourceMac[6];
USHORT Protocol;
UCHAR Data[];
} __attribute__((__packed__)) HEADER, *PHEADER;
#ifdef _MSC_VER
#pragma pack()
#endif
typedef struct _BINDINGCONTEXT {
BOOLEAN Active;
UCHAR Mac[6];
UINT MTU;
NDIS_STATUS Status;
NDIS_HANDLE PacketPoolHandle;
NDIS_HANDLE BufferPoolHandle;
NDIS_HANDLE BindingHandle;
KEVENT Event;
BOOLEAN OutstandingRequest;
PWCHAR AdapterName;
PWCHAR DeviceName;
struct _BINDINGCONTEXT *Next;
} BINDINGCONTEXT, *PBINDINGCONTEXT;
KEVENT ProtocolStopEvent;
KSPIN_LOCK SpinLock;
PBINDINGCONTEXT BindingContextList = NULL;
NDIS_HANDLE ProtocolHandle = NULL;
NTSTATUS STDCALL ProtocolStart() {
NDIS_STATUS Status;
NDIS_STRING ProtocolName;
NDIS_PROTOCOL_CHARACTERISTICS ProtocolCharacteristics;
DbgPrint("ProtocolStart\n");
KeInitializeEvent(&ProtocolStopEvent, SynchronizationEvent, FALSE);
KeInitializeSpinLock(&SpinLock);
RtlInitUnicodeString(&ProtocolName, L"AoE");
NdisZeroMemory(&ProtocolCharacteristics, sizeof(NDIS_PROTOCOL_CHARACTERISTICS));
ProtocolCharacteristics.MajorNdisVersion = 5;
ProtocolCharacteristics.MinorNdisVersion = 0;
ProtocolCharacteristics.Name = ProtocolName;
ProtocolCharacteristics.OpenAdapterCompleteHandler = ProtocolOpenAdapterComplete;
ProtocolCharacteristics.CloseAdapterCompleteHandler = ProtocolCloseAdapterComplete;
ProtocolCharacteristics.SendCompleteHandler = ProtocolSendComplete;
ProtocolCharacteristics.TransferDataCompleteHandler = ProtocolTransferDataComplete;
ProtocolCharacteristics.ResetCompleteHandler = ProtocolResetComplete;
ProtocolCharacteristics.RequestCompleteHandler = ProtocolRequestComplete;
ProtocolCharacteristics.ReceiveHandler = ProtocolReceive;
ProtocolCharacteristics.ReceiveCompleteHandler = ProtocolReceiveComplete;
ProtocolCharacteristics.StatusHandler = ProtocolStatus;
ProtocolCharacteristics.StatusCompleteHandler = ProtocolStatusComplete;
ProtocolCharacteristics.BindAdapterHandler = ProtocolBindAdapter;
ProtocolCharacteristics.UnbindAdapterHandler = ProtocolUnbindAdapter;
ProtocolCharacteristics.PnPEventHandler = ProtocolPnPEvent;
NdisRegisterProtocol((PNDIS_STATUS)&Status, &ProtocolHandle, &ProtocolCharacteristics, sizeof(NDIS_PROTOCOL_CHARACTERISTICS));
return Status;
}
VOID STDCALL ProtocolStop() {
NDIS_STATUS Status;
DbgPrint("ProtocolStop\n");
KeResetEvent(&ProtocolStopEvent);
NdisDeregisterProtocol(&Status, ProtocolHandle);
if (!NT_SUCCESS(Status)) Error("NdisDeregisterProtocol", Status);
if (BindingContextList != NULL) KeWaitForSingleObject(&ProtocolStopEvent, Executive, KernelMode, FALSE, NULL);
}
BOOLEAN STDCALL ProtocolSearchNIC(IN PUCHAR Mac) {
PBINDINGCONTEXT Context = BindingContextList;
while (Context != NULL) {
if (RtlCompareMemory(Mac, Context->Mac, 6) == 6) break;
Context = Context->Next;
}
if (Context != NULL) return TRUE;
return FALSE;
}
ULONG STDCALL ProtocolGetMTU(IN PUCHAR Mac) {
PBINDINGCONTEXT Context = BindingContextList;
while (Context != NULL) {
if (RtlCompareMemory(Mac, Context->Mac, 6) == 6) break;
Context = Context->Next;
}
if (Context == NULL) return 0;
return Context->MTU;
}
BOOLEAN STDCALL ProtocolSend(IN PUCHAR SourceMac, IN PUCHAR DestinationMac, IN PUCHAR Data, IN ULONG DataSize, IN PVOID PacketContext) {
PBINDINGCONTEXT Context = BindingContextList;
NDIS_STATUS Status;
PNDIS_PACKET Packet;
PNDIS_BUFFER Buffer;
PHEADER DataBuffer;
#if defined(DEBUGALLPROTOCOLCALLS)
DbgPrint("ProtocolSend\n");
#endif
if (RtlCompareMemory(SourceMac, "\xff\xff\xff\xff\xff\xff", 6) == 6) {
while (Context != NULL) {
ProtocolSend(Context->Mac, DestinationMac, Data, DataSize, NULL);
Context = Context->Next;
}
return TRUE;
}
while (Context != NULL) {
if (RtlCompareMemory(SourceMac, Context->Mac, 6) == 6) break;
Context = Context->Next;
}
if (Context == NULL) {
DbgPrint("ProtocolSend Can't find NIC %02x:%02x:%02x:%02x:%02x:%02x\n", SourceMac[0], SourceMac[1], SourceMac[2], SourceMac[3], SourceMac[4], SourceMac[5]);
return FALSE;
}
if (DataSize > Context->MTU) {
DbgPrint("ProtocolSend Tried to send oversized packet (size: %d, MTU:)\n", DataSize, Context->MTU);
return FALSE;
}
if ((DataBuffer = (PHEADER)ExAllocatePool(NonPagedPool, (sizeof(HEADER) + DataSize))) == NULL) {
DbgPrint("ProtocolSend ExAllocatePool\n");
return FALSE;
}
RtlCopyMemory(DataBuffer->SourceMac, SourceMac, 6);
RtlCopyMemory(DataBuffer->DestinationMac, DestinationMac, 6);
DataBuffer->Protocol = htons(AOEPROTOCOLID);
RtlCopyMemory(DataBuffer->Data, Data, DataSize);
NdisAllocatePacket(&Status, &Packet, Context->PacketPoolHandle);
if (!NT_SUCCESS(Status)) {
Error("ProtocolSend NdisAllocatePacket", Status);
ExFreePool(DataBuffer);
return FALSE;
}
NdisAllocateBuffer(&Status, &Buffer, Context->BufferPoolHandle, DataBuffer, (sizeof(HEADER) + DataSize));
if (!NT_SUCCESS(Status)) {
Error("ProtocolSend NdisAllocateBuffer", Status);
NdisFreePacket(Packet);
ExFreePool(DataBuffer);
return FALSE;
}
NdisChainBufferAtFront(Packet, Buffer);
*(PVOID*)Packet->ProtocolReserved = PacketContext;
NdisSend(&Status, Context->BindingHandle, Packet);
if (Status != NDIS_STATUS_PENDING) ProtocolSendComplete(Context, Packet, Status);
return TRUE;
}
VOID STDCALL ProtocolOpenAdapterComplete(IN NDIS_HANDLE ProtocolBindingContext, IN NDIS_STATUS Status, IN NDIS_STATUS OpenErrorStatus) {
#if !defined(DEBUGMOSTPROTOCOLCALLS) && !defined(DEBUGALLPROTOCOLCALLS)
if (!NT_SUCCESS(Status))
#endif
DbgPrint("ProtocolOpenAdapterComplete: 0x%08x 0x%08x\n", Status, OpenErrorStatus);
}
VOID STDCALL ProtocolCloseAdapterComplete(IN NDIS_HANDLE ProtocolBindingContext, IN NDIS_STATUS Status) {
#if !defined(DEBUGMOSTPROTOCOLCALLS) && !defined(DEBUGALLPROTOCOLCALLS)
if (!NT_SUCCESS(Status))
#endif
Error("ProtocolCloseAdapterComplete", Status);
}
VOID STDCALL ProtocolSendComplete(IN NDIS_HANDLE ProtocolBindingContext, IN PNDIS_PACKET Packet, IN NDIS_STATUS Status) {
PNDIS_BUFFER Buffer;
PUCHAR DataBuffer;
#ifndef DEBUGALLPROTOCOLCALLS
if (!NT_SUCCESS(Status) && Status != NDIS_STATUS_NO_CABLE)
#endif
Error("ProtocolSendComplete", Status);
NdisUnchainBufferAtFront(Packet, &Buffer);
if (Buffer != NULL) {
DataBuffer = NdisBufferVirtualAddress(Buffer);
ExFreePool(DataBuffer);
NdisFreeBuffer(Buffer);
} else {
DbgPrint("ProtocolSendComplete: Buffer == NULL\n");
}
NdisFreePacket(Packet);
}
VOID STDCALL ProtocolTransferDataComplete(IN NDIS_HANDLE ProtocolBindingContext, IN PNDIS_PACKET Packet, IN NDIS_STATUS Status, IN UINT BytesTransferred) {
PNDIS_BUFFER Buffer;
PHEADER Header = NULL;
PUCHAR Data = NULL;
UINT HeaderSize, DataSize;
#ifndef DEBUGALLPROTOCOLCALLS
if (!NT_SUCCESS(Status))
#endif
Error("ProtocolTransferDataComplete", Status);
NdisUnchainBufferAtFront(Packet, &Buffer);
if (Buffer != NULL) {
NdisQueryBuffer(Buffer, &Data, &DataSize);
NdisFreeBuffer(Buffer);
} else {
DbgPrint("ProtocolTransferDataComplete Data (front) Buffer == NULL\n");
}
NdisUnchainBufferAtBack(Packet, &Buffer);
if (Buffer != NULL) {
NdisQueryBuffer(Buffer, &Header, &HeaderSize);
NdisFreeBuffer(Buffer);
} else {
DbgPrint("ProtocolTransferDataComplete Header (back) Buffer == NULL\n");
}
if (Header != NULL && Data != NULL) AoEReply(Header->SourceMac, Header->DestinationMac, Data, DataSize);
if (Header != NULL) ExFreePool(Header);
if (Data != NULL) ExFreePool(Data);
NdisFreePacket(Packet);
}
VOID STDCALL ProtocolResetComplete(IN NDIS_HANDLE ProtocolBindingContext, IN NDIS_STATUS Status) {
#if !defined(DEBUGMOSTPROTOCOLCALLS) && !defined(DEBUGALLPROTOCOLCALLS)
if (!NT_SUCCESS(Status))
#endif
Error("ProtocolResetComplete", Status);
}
VOID STDCALL ProtocolRequestComplete(IN NDIS_HANDLE ProtocolBindingContext, IN PNDIS_REQUEST NdisRequest, IN NDIS_STATUS Status) {
PBINDINGCONTEXT Context = (PBINDINGCONTEXT)ProtocolBindingContext;
#if !defined(DEBUGMOSTPROTOCOLCALLS) && !defined(DEBUGALLPROTOCOLCALLS)
if (!NT_SUCCESS(Status))
#endif
Error("ProtocolRequestComplete", Status);
Context->Status = Status;
KeSetEvent(&Context->Event, 0, FALSE);
}
NDIS_STATUS STDCALL ProtocolReceive(IN NDIS_HANDLE ProtocolBindingContext, IN NDIS_HANDLE MacReceiveContext, IN PVOID HeaderBuffer, IN UINT HeaderBufferSize, IN PVOID LookAheadBuffer, IN UINT LookaheadBufferSize, IN UINT PacketSize) {
PBINDINGCONTEXT Context = (PBINDINGCONTEXT)ProtocolBindingContext;
NDIS_STATUS Status;
PNDIS_PACKET Packet;
PNDIS_BUFFER Buffer;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -