--- /dev/null
+/*
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS TCP/IP protocol driver
+ * FILE: datalink/loopback.c
+ * PURPOSE: Loopback adapter
+ * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
+ * REVISIONS:
+ * CSH 01/08-2000 Created
+ */
+
+#include "precomp.h"
+
+PIP_INTERFACE Loopback = NULL;
+
+VOID LoopPassiveWorker(
+ PVOID Context)
+{
+ PIP_PACKET IPPacket = Context;
+
+ /* IPReceive() takes care of the NDIS packet */
+ IPReceive(Loopback, IPPacket);
+
+ ExFreePool(IPPacket);
+}
+
+VOID LoopTransmit(
+ PVOID Context,
+ PNDIS_PACKET NdisPacket,
+ UINT Offset,
+ PVOID LinkAddress,
+ USHORT Type)
+/*
+ * FUNCTION: Transmits a packet
+ * ARGUMENTS:
+ * Context = Pointer to context information (NULL)
+ * NdisPacket = Pointer to NDIS packet to send
+ * Offset = Offset in packet where packet data starts
+ * LinkAddress = Pointer to link address
+ * Type = LAN protocol type (unused)
+ */
+{
+ PCHAR PacketBuffer;
+ UINT PacketLength;
+ PNDIS_PACKET XmitPacket;
+ NDIS_STATUS NdisStatus;
+ PIP_PACKET IPPacket;
+
+ ASSERT_KM_POINTER(NdisPacket);
+ ASSERT_KM_POINTER(PC(NdisPacket));
+ ASSERT_KM_POINTER(PC(NdisPacket)->DLComplete);
+
+ TI_DbgPrint(MAX_TRACE, ("Called (NdisPacket = %x)\n", NdisPacket));
+
+ GetDataPtr( NdisPacket, 0, &PacketBuffer, &PacketLength );
+
+ NdisStatus = AllocatePacketWithBuffer
+ ( &XmitPacket, PacketBuffer, PacketLength );
+
+ if( NT_SUCCESS(NdisStatus) ) {
+ IPPacket = ExAllocatePool(NonPagedPool, sizeof(IP_PACKET));
+ if (IPPacket)
+ {
+ IPInitializePacket(IPPacket, 0);
+
+ IPPacket->NdisPacket = XmitPacket;
+
+ GetDataPtr(IPPacket->NdisPacket,
+ 0,
+ (PCHAR*)&IPPacket->Header,
+ &IPPacket->TotalSize);
+
+ IPPacket->MappedHeader = TRUE;
+
+ if (!ChewCreate(LoopPassiveWorker, IPPacket))
+ {
+ IPPacket->Free(IPPacket);
+ ExFreePool(IPPacket);
+ NdisStatus = NDIS_STATUS_RESOURCES;
+ }
+ }
+ else
+ NdisStatus = NDIS_STATUS_RESOURCES;
+ }
+
+ (PC(NdisPacket)->DLComplete)
+ ( PC(NdisPacket)->Context, NdisPacket, NdisStatus );
+}
+
+NDIS_STATUS LoopRegisterAdapter(
+ PNDIS_STRING AdapterName,
+ PLAN_ADAPTER *Adapter)
+/*
+ * FUNCTION: Registers loopback adapter with the network layer
+ * ARGUMENTS:
+ * AdapterName = Unused
+ * Adapter = Unused
+ * RETURNS:
+ * Status of operation
+ */
+{
+ LLIP_BIND_INFO BindInfo;
+
+ TI_DbgPrint(MID_TRACE, ("Called.\n"));
+
+ /* Bind the adapter to network (IP) layer */
+ BindInfo.Context = NULL;
+ BindInfo.HeaderSize = 0;
+ BindInfo.MinFrameSize = 0;
+ BindInfo.Address = NULL;
+ BindInfo.AddressLength = 0;
+ BindInfo.Transmit = LoopTransmit;
+
+ Loopback = IPCreateInterface(&BindInfo);
+ if (!Loopback) return NDIS_STATUS_RESOURCES;
+
+ Loopback->MTU = 16384;
+
+ Loopback->Name.Buffer = L"Loopback";
+ Loopback->Name.MaximumLength = Loopback->Name.Length =
+ wcslen(Loopback->Name.Buffer) * sizeof(WCHAR);
+
+ AddrInitIPv4(&Loopback->Unicast, LOOPBACK_ADDRESS_IPv4);
+ AddrInitIPv4(&Loopback->Netmask, LOOPBACK_ADDRMASK_IPv4);
+ AddrInitIPv4(&Loopback->Broadcast, LOOPBACK_BCASTADDR_IPv4);
+
+ IPRegisterInterface(Loopback);
+
+ IPAddInterfaceRoute(Loopback);
+
+ TI_DbgPrint(MAX_TRACE, ("Leaving.\n"));
+
+ return NDIS_STATUS_SUCCESS;
+}
+
+
+NDIS_STATUS LoopUnregisterAdapter(
+ PLAN_ADAPTER Adapter)
+/*
+ * FUNCTION: Unregisters loopback adapter with the network layer
+ * ARGUMENTS:
+ * Adapter = Unused
+ * RETURNS:
+ * Status of operation
+ * NOTES:
+ * Does not care wether we have registered loopback adapter
+ */
+{
+ TI_DbgPrint(MID_TRACE, ("Called.\n"));
+
+ if (Loopback != NULL)
+ {
+ IPUnregisterInterface(Loopback);
+ IPDestroyInterface(Loopback);
+ Loopback = NULL;
+ }
+
+ TI_DbgPrint(MAX_TRACE, ("Leaving.\n"));
+
+ return NDIS_STATUS_SUCCESS;
+}