⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 protocol.c

📁 WinAoE is an open source GPLv3 driver for using AoE (ATA over Ethernet) on Microsoft Windows
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
  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 + -