Temporary workaround to prevent bochs trouble.
[reactos.git] / reactos / drivers / net / tcpip / network / ip.c
index 1ea5af9..acfebfd 100644 (file)
@@ -9,6 +9,7 @@
  */
 #include <tcpip.h>
 #include <ip.h>
+#include <tcp.h>
 #include <loopback.h>
 #include <neighbor.h>
 #include <receive.h>
@@ -29,13 +30,61 @@ KSPIN_LOCK PrefixListLock;
 UINT MaxLLHeaderSize; /* Largest maximum header size */
 UINT MinLLFrameSize;  /* Largest minimum frame size */
 BOOLEAN IPInitialized = FALSE;
+NPAGED_LOOKASIDE_LIST IPPacketList;
 
 IP_PROTOCOL_HANDLER ProtocolTable[IP_PROTOCOL_TABLE_SIZE];
 
 
+VOID FreePacket(
+    PVOID Object)
+/*
+ * FUNCTION: Frees an IP packet object
+ * ARGUMENTS:
+ *     Object = Pointer to an IP packet structure
+ */
+{
+    ExFreeToNPagedLookasideList(&IPPacketList, Object);
+}
+
+
+VOID FreeADE(
+    PVOID Object)
+/*
+ * FUNCTION: Frees an address entry object
+ * ARGUMENTS:
+ *     Object = Pointer to an address entry structure
+ */
+{
+    ExFreePool(Object);
+}
+
+
+VOID FreeNTE(
+    PVOID Object)
+/*
+ * FUNCTION: Frees a net table entry object
+ * ARGUMENTS:
+ *     Object = Pointer to an net table entry structure
+ */
+{
+    ExFreePool(Object);
+}
+
+
+VOID FreeIF(
+    PVOID Object)
+/*
+ * FUNCTION: Frees an interface object
+ * ARGUMENTS:
+ *     Object = Pointer to an interface structure
+ */
+{
+    ExFreePool(Object);
+}
+
+
 PADDRESS_ENTRY CreateADE(
-    PIP_INTERFACE IF,
-    PIP_ADDRESS Address,
+    PIP_INTERFACE IF,    PIP_ADDRESS Address,
     UCHAR Type,
     PNET_TABLE_ENTRY NTE)
 /*
@@ -60,13 +109,18 @@ PADDRESS_ENTRY CreateADE(
     TI_DbgPrint(DEBUG_IP, ("Called. IF (0x%X)  Address (0x%X)  Type (0x%X)  NTE (0x%X).\n",
         IF, Address, Type, NTE));
 
+    TI_DbgPrint(DEBUG_IP, ("Address (%s)  NTE (%s).\n",
+        A2S(Address), A2S(NTE->Address)));
+
     /* Allocate space for an ADE and set it up */
-    ADE = PoolAllocateBuffer(sizeof(ADDRESS_ENTRY));
+    ADE = ExAllocatePool(NonPagedPool, sizeof(ADDRESS_ENTRY));
     if (!ADE) {
         TI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
         return NULL;
     }
 
+    INIT_TAG(ADE, TAG('A','D','E',' '));
+    ADE->Free     = FreeADE;
     ADE->RefCount = 1;
     ADE->NTE      = NTE;
     ADE->Type     = Type;
@@ -93,6 +147,8 @@ VOID DestroyADE(
 {
     TI_DbgPrint(DEBUG_IP, ("Called. IF (0x%X)  ADE (0x%X).\n", IF, ADE));
 
+    TI_DbgPrint(DEBUG_IP, ("ADE (%s).\n", ADE->Address));
+
     /* Unlink the address entry from the list */
     RemoveEntryList(&ADE->ListEntry);
 
@@ -111,8 +167,7 @@ VOID DestroyADE(
 #endif
 
     /* And free the ADE */
-    PoolFreeBuffer(ADE);
-    TI_DbgPrint(MIN_TRACE, ("Check.\n"));
+    FreeADE(ADE);
 }
 
 
@@ -136,7 +191,7 @@ VOID DestroyADEs(
     CurrentEntry = IF->ADEListHead.Flink;
     while (CurrentEntry != &IF->ADEListHead) {
         NextEntry = CurrentEntry->Flink;
-           Current = CONTAINING_RECORD(CurrentEntry, ADDRESS_ENTRY, ListEntry);
+           Current = CONTAINING_RECORD(CurrentEntry, ADDRESS_ENTRY, ListEntry);
         /* Destroy the ADE */
         DestroyADE(IF, Current);
         CurrentEntry = NextEntry;
@@ -144,6 +199,35 @@ VOID DestroyADEs(
 }
 
 
+PIP_PACKET IPCreatePacket(
+  ULONG Type)
+/*
+ * FUNCTION: Creates an IP packet object
+ * ARGUMENTS:
+ *     Type = Type of IP packet
+ * RETURNS:
+ *     Pointer to the created IP packet. NULL if there was not enough free resources.
+ */
+{
+  PIP_PACKET IPPacket;
+
+  IPPacket = ExAllocateFromNPagedLookasideList(&IPPacketList);
+  if (!IPPacket)
+    return NULL;
+
+    /* FIXME: Is this needed? */
+  RtlZeroMemory(IPPacket, sizeof(IP_PACKET));
+
+  INIT_TAG(IPPacket, TAG('I','P','K','T'));
+
+  IPPacket->Free     = FreePacket;
+  IPPacket->RefCount = 1;
+  IPPacket->Type     = Type;
+
+  return IPPacket;
+}
+
+
 PPREFIX_LIST_ENTRY CreatePLE(
     PIP_INTERFACE IF,
     PIP_ADDRESS Prefix,
@@ -166,13 +250,16 @@ PPREFIX_LIST_ENTRY CreatePLE(
 
     TI_DbgPrint(DEBUG_IP, ("Called. IF (0x%X)  Prefix (0x%X)  Length (%d).\n", IF, Prefix, Length));
 
+    TI_DbgPrint(DEBUG_IP, ("Prefix (%s).\n", A2S(Prefix)));
+
     /* Allocate space for an PLE and set it up */
-    PLE = PoolAllocateBuffer(sizeof(PREFIX_LIST_ENTRY));
+    PLE = ExAllocatePool(NonPagedPool, sizeof(PREFIX_LIST_ENTRY));
     if (!PLE) {
         TI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
         return NULL;
     }
 
+    INIT_TAG(PLE, TAG('P','L','E',' '));
     PLE->RefCount     = 1;
     PLE->Interface    = IF;
     PLE->Prefix       = Prefix;
@@ -197,6 +284,8 @@ VOID DestroyPLE(
 {
     TI_DbgPrint(DEBUG_IP, ("Called. PLE (0x%X).\n", PLE));
 
+    TI_DbgPrint(DEBUG_IP, ("PLE (%s).\n", PLE->Prefix));
+
     /* Unlink the prefix list entry from the list */
     RemoveEntryList(&PLE->ListEntry);
 
@@ -215,7 +304,7 @@ VOID DestroyPLE(
 #endif
 
     /* And free the PLE */
-    PoolFreeBuffer(PLE);
+    ExFreePool(PLE);
 }
 
 
@@ -238,7 +327,7 @@ VOID DestroyPLEs(
     CurrentEntry = PrefixListHead.Flink;
     while (CurrentEntry != &PrefixListHead) {
         NextEntry = CurrentEntry->Flink;
-           Current = CONTAINING_RECORD(CurrentEntry, PREFIX_LIST_ENTRY, ListEntry);
+             Current = CONTAINING_RECORD(CurrentEntry, PREFIX_LIST_ENTRY, ListEntry);
         /* Destroy the PLE */
         DestroyPLE(Current);
         CurrentEntry = NextEntry;
@@ -271,13 +360,20 @@ PNET_TABLE_ENTRY IPCreateNTE(
 
     TI_DbgPrint(DEBUG_IP, ("Called. IF (0x%X)  Address (0x%X)  PrefixLength (%d).\n", IF, Address, PrefixLength));
 
+    TI_DbgPrint(DEBUG_IP, ("Address (%s).\n", A2S(Address)));
+
     /* Allocate room for an NTE */
-    NTE = PoolAllocateBuffer(sizeof(NET_TABLE_ENTRY));
+    NTE = ExAllocatePool(NonPagedPool, sizeof(NET_TABLE_ENTRY));
     if (!NTE) {
         TI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
         return NULL;
     }
 
+    INIT_TAG(NTE, TAG('N','T','E',' '));
+    INIT_TAG(Address, TAG('A','D','R','S'));
+
+    NTE->Free = FreeNTE;
+
     NTE->Interface = IF;
 
     /* One reference is for beeing alive and one reference is for the ADE */
@@ -295,7 +391,7 @@ PNET_TABLE_ENTRY IPCreateNTE(
     ADE = CreateADE(IF, NTE->Address, ADE_UNICAST, NTE);
     if (!ADE) {
         TI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
-        PoolFreeBuffer(NTE);
+        ExFreePool(NTE);
         return NULL;
     }
 
@@ -303,7 +399,7 @@ PNET_TABLE_ENTRY IPCreateNTE(
     NTE->PLE = CreatePLE(IF, NTE->Address, PrefixLength);
     if (!NTE->PLE) {
         DestroyADE(IF, ADE);
-        PoolFreeBuffer(NTE);
+        ExFreePool(NTE);
         return NULL;
     }
 
@@ -337,6 +433,8 @@ VOID DestroyNTE(
 
     TI_DbgPrint(DEBUG_IP, ("Called. IF (0x%X)  NTE (0x%X).\n", IF, NTE));
 
+    TI_DbgPrint(DEBUG_IP, ("NTE (%s).\n", NTE->Address));
+
     /* Invalidate the prefix list entry for this NTE */
     KeAcquireSpinLock(&PrefixListLock, &OldIrql);
     DestroyPLE(NTE->PLE);
@@ -345,7 +443,13 @@ VOID DestroyNTE(
     /* Remove NTE from the interface list */
     RemoveEntryList(&NTE->IFListEntry);
     /* Remove NTE from the net table list */
+
+/* TODO: DEBUG: removed by RobD to prevent failure when testing under bochs 6 sept 2002.
+
     RemoveEntryList(&NTE->NTListEntry);
+
+ */
+
     /* Dereference the objects that are referenced */
     DereferenceObject(NTE->Address);
     DereferenceObject(NTE->Interface);
@@ -357,7 +461,7 @@ VOID DestroyNTE(
     }
 #endif
     /* And free the NTE */
-    PoolFreeBuffer(NTE);
+    ExFreePool(NTE);
 }
 
 
@@ -382,7 +486,7 @@ VOID DestroyNTEs(
     CurrentEntry = IF->NTEListHead.Flink;
     while (CurrentEntry != &IF->NTEListHead) {
         NextEntry = CurrentEntry->Flink;
-           Current = CONTAINING_RECORD(CurrentEntry, NET_TABLE_ENTRY, IFListEntry);
+             Current = CONTAINING_RECORD(CurrentEntry, NET_TABLE_ENTRY, IFListEntry);
         /* Destroy the NTE */
         DestroyNTE(IF, Current);
         CurrentEntry = NextEntry;
@@ -411,21 +515,31 @@ PNET_TABLE_ENTRY IPLocateNTEOnInterface(
     PLIST_ENTRY CurrentEntry;
     PADDRESS_ENTRY Current;
 
-    TI_DbgPrint(DEBUG_IP, ("Called. IF (0x%X)  Address (0x%X)  AddressType (0x%X).\n",
-        IF, Address, AddressType));
+//    TI_DbgPrint(DEBUG_IP, ("Called. IF (0x%X)  Address (0x%X)  AddressType (0x%X).\n",
+//        IF, Address, AddressType));
+
+//    TI_DbgPrint(DEBUG_IP, ("Address (%s)  AddressType (0x%X).\n", A2S(Address)));
 
     KeAcquireSpinLock(&IF->Lock, &OldIrql);
 
     /* Search the list and return the NTE if found */
     CurrentEntry = IF->ADEListHead.Flink;
+
+    if (CurrentEntry == &IF->ADEListHead) {
+        TI_DbgPrint(DEBUG_IP, ("NTE list is empty!!!\n"));
+    }
+
     while (CurrentEntry != &IF->ADEListHead) {
-           Current = CONTAINING_RECORD(CurrentEntry, ADDRESS_ENTRY, ListEntry);
+             Current = CONTAINING_RECORD(CurrentEntry, ADDRESS_ENTRY, ListEntry);
         if (AddrIsEqual(Address, Current->Address)) {
             ReferenceObject(Current->NTE);
             *AddressType = Current->Type;
             KeReleaseSpinLock(&IF->Lock, OldIrql);
             return Current->NTE;
         }
+        else {
+            TI_DbgPrint(DEBUG_IP, ("CurrentEntry = 0x%X != &IF->ADEListHead = 0x%X.\n", CurrentEntry, &IF->ADEListHead));
+        }
         CurrentEntry = CurrentEntry->Flink;
     }
 
@@ -455,15 +569,17 @@ PNET_TABLE_ENTRY IPLocateNTE(
     PNET_TABLE_ENTRY Current;
     PNET_TABLE_ENTRY NTE;
 
-    TI_DbgPrint(DEBUG_IP, ("Called. Address (0x%X)  AddressType (0x%X).\n",
-        Address, AddressType));
-    
+//    TI_DbgPrint(DEBUG_IP, ("Called. Address (0x%X)  AddressType (0x%X).\n",
+//        Address, AddressType));
+
+//    TI_DbgPrint(DEBUG_IP, ("Address (%s).\n", A2S(Address)));
+
     KeAcquireSpinLock(&NetTableListLock, &OldIrql);
 
     /* Search the list and return the NTE if found */
     CurrentEntry = NetTableListHead.Flink;
     while (CurrentEntry != &NetTableListHead) {
-           Current = CONTAINING_RECORD(CurrentEntry, NET_TABLE_ENTRY, NTListEntry);
+             Current = CONTAINING_RECORD(CurrentEntry, NET_TABLE_ENTRY, NTListEntry);
         NTE = IPLocateNTEOnInterface(Current->Interface, Address, AddressType);
         if (NTE) {
             ReferenceObject(NTE);
@@ -500,15 +616,17 @@ PADDRESS_ENTRY IPLocateADE(
     PIP_INTERFACE CurrentIF;
     PADDRESS_ENTRY CurrentADE;
 
-    TI_DbgPrint(DEBUG_IP, ("Called. Address (0x%X)  AddressType (0x%X).\n",
-        Address, AddressType));
+//    TI_DbgPrint(DEBUG_IP, ("Called. Address (0x%X)  AddressType (0x%X).\n",
+//        Address, AddressType));
+
+//    TI_DbgPrint(DEBUG_IP, ("Address (%s).\n", A2S(Address)));
 
     KeAcquireSpinLock(&InterfaceListLock, &OldIrql);
 
     /* Search the interface list */
     CurrentIFEntry = InterfaceListHead.Flink;
     while (CurrentIFEntry != &InterfaceListHead) {
-           CurrentIF = CONTAINING_RECORD(CurrentIFEntry, IP_INTERFACE, ListEntry);
+             CurrentIF = CONTAINING_RECORD(CurrentIFEntry, IP_INTERFACE, ListEntry);
 
         /* Search the address entry list and return the ADE if found */
         CurrentADEEntry = CurrentIF->ADEListHead.Flink;
@@ -549,9 +667,8 @@ PADDRESS_ENTRY IPGetDefaultADE(
     PLIST_ENTRY CurrentADEEntry;
     PIP_INTERFACE CurrentIF;
     PADDRESS_ENTRY CurrentADE;
-#if 0
     BOOLEAN LoopbackIsRegistered = FALSE;
-#endif
+
     TI_DbgPrint(DEBUG_IP, ("Called. AddressType (0x%X).\n", AddressType));
 
     KeAcquireSpinLock(&InterfaceListLock, &OldIrql);
@@ -559,10 +676,9 @@ PADDRESS_ENTRY IPGetDefaultADE(
     /* Search the interface list */
     CurrentIFEntry = InterfaceListHead.Flink;
     while (CurrentIFEntry != &InterfaceListHead) {
-           CurrentIF = CONTAINING_RECORD(CurrentIFEntry, IP_INTERFACE, ListEntry);
-#if 0
+             CurrentIF = CONTAINING_RECORD(CurrentIFEntry, IP_INTERFACE, ListEntry);
+
         if (CurrentIF != Loopback) {
-#endif
             /* Search the address entry list and return the first appropriate ADE found */
             CurrentADEEntry = CurrentIF->ADEListHead.Flink;
             while (CurrentADEEntry != &CurrentIF->ADEListHead) {
@@ -573,13 +689,11 @@ PADDRESS_ENTRY IPGetDefaultADE(
                     return CurrentADE;
                 }
                 CurrentADEEntry = CurrentADEEntry->Flink;
-#if 0
         } else
             LoopbackIsRegistered = TRUE;
-#endif
         CurrentIFEntry = CurrentIFEntry->Flink;
     }
-#if 0
+
     /* No address was found. Use loopback interface if available */
     if (LoopbackIsRegistered) {
         CurrentADEEntry = Loopback->ADEListHead.Flink;
@@ -593,14 +707,14 @@ PADDRESS_ENTRY IPGetDefaultADE(
             CurrentADEEntry = CurrentADEEntry->Flink;
         }
     }
-#endif
+
     KeReleaseSpinLock(&InterfaceListLock, OldIrql);
 
     return NULL;
 }
 
 
-VOID IPTimeout(
+VOID STDCALL IPTimeout(
     PKDPC Dpc,
     PVOID DeferredContext,
     PVOID SystemArgument1,
@@ -621,6 +735,9 @@ VOID IPTimeout(
 
     /* Clean possible outdated cached neighbor addresses */
     NBTimeout();
+
+    /* Call upper layer timeout routines */
+    TCPTimeout();
 }
 
 
@@ -671,21 +788,32 @@ PIP_INTERFACE IPCreateInterface(
 
     TI_DbgPrint(DEBUG_IP, ("Called. BindInfo (0x%X).\n", BindInfo));
 
-    IF = PoolAllocateBuffer(sizeof(IP_INTERFACE));
+#ifdef DBG
+    if (BindInfo->Address) {
+        PUCHAR A = BindInfo->Address;
+        TI_DbgPrint(DEBUG_IP, ("Interface address (%02X %02X %02X %02X %02X %02X).\n",
+            A[0], A[1], A[2], A[3], A[4], A[5]));
+    }
+#endif
+
+    IF = ExAllocatePool(NonPagedPool, sizeof(IP_INTERFACE));
     if (!IF) {
         TI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
         return NULL;
     }
 
-    IF->RefCount      = 1;
-    IF->Context       = BindInfo->Context;
-    IF->HeaderSize    = BindInfo->HeaderSize;
-       if (IF->HeaderSize > MaxLLHeaderSize)
-               MaxLLHeaderSize = IF->HeaderSize;
+    INIT_TAG(IF, TAG('F','A','C','E'));
+
+    IF->Free       = FreeIF;
+    IF->RefCount   = 1;
+    IF->Context    = BindInfo->Context;
+    IF->HeaderSize = BindInfo->HeaderSize;
+         if (IF->HeaderSize > MaxLLHeaderSize)
+               MaxLLHeaderSize = IF->HeaderSize;
 
-    IF->MinFrameSize  = BindInfo->MinFrameSize;
-       if (IF->MinFrameSize > MinLLFrameSize)
-               MinLLFrameSize = IF->MinFrameSize;
+    IF->MinFrameSize = BindInfo->MinFrameSize;
+         if (IF->MinFrameSize > MinLLFrameSize)
+               MinLLFrameSize = IF->MinFrameSize;
 
     IF->MTU           = BindInfo->MTU;
     IF->Address       = BindInfo->Address;
@@ -728,7 +856,7 @@ VOID IPDestroyInterface(
         TI_DbgPrint(MIN_TRACE, ("Interface at (0x%X) has (%d) references (should be 0).\n", IF, IF->RefCount));
     }
 #endif
-    PoolFreeBuffer(IF);
+    ExFreePool(IF);
 }
 
 
@@ -767,6 +895,20 @@ BOOLEAN IPRegisterInterface(
             KeReleaseSpinLock(&IF->Lock, OldIrql);
             return FALSE;
         }
+#if 1
+        /* Reference objects for forward information base */
+        ReferenceObject(Current->Address);
+        ReferenceObject(Current->PLE->Prefix);
+        ReferenceObject(Current);
+        /* NCE is already referenced */
+        if (!RouterAddRoute(Current->Address, Current->PLE->Prefix, Current, NCE, 1)) {
+            TI_DbgPrint(MIN_TRACE, ("Could not add route due to insufficient resources.\n"));
+            DereferenceObject(Current->Address);
+            DereferenceObject(Current->PLE->Prefix);
+            DereferenceObject(Current);
+            DereferenceObject(NCE);
+        }
+#else
         RCN = RouteAddRouteToDestination(Current->Address, Current, IF, NCE);
         if (!RCN) {
             TI_DbgPrint(MIN_TRACE, ("Could not create RCN.\n"));
@@ -776,7 +918,7 @@ BOOLEAN IPRegisterInterface(
         }
         /* Don't need this any more since the route cache references the NCE */
         DereferenceObject(NCE);
-
+#endif
         CurrentEntry = CurrentEntry->Flink;
     }
 
@@ -893,9 +1035,46 @@ NTSTATUS IPStartup(
 
     TI_DbgPrint(MAX_TRACE, ("Called.\n"));
 
-       MaxLLHeaderSize = 0;
+       MaxLLHeaderSize = 0;
     MinLLFrameSize  = 0;
 
+    /* Initialize lookaside lists */
+    ExInitializeNPagedLookasideList(
+      &IPDRList,                      /* Lookaside list */
+           NULL,                           /* Allocate routine */
+           NULL,                           /* Free routine */
+           0,                              /* Flags */
+           sizeof(IPDATAGRAM_REASSEMBLY),  /* Size of each entry */
+           TAG('I','P','D','R'),           /* Tag */
+           0);                             /* Depth */
+
+    ExInitializeNPagedLookasideList(
+      &IPPacketList,                  /* Lookaside list */
+           NULL,                           /* Allocate routine */
+           NULL,                           /* Free routine */
+           0,                              /* Flags */
+           sizeof(IP_PACKET),              /* Size of each entry */
+           TAG('I','P','P','K'),           /* Tag */
+           0);                             /* Depth */
+
+    ExInitializeNPagedLookasideList(
+      &IPFragmentList,                /* Lookaside list */
+           NULL,                           /* Allocate routine */
+           NULL,                           /* Free routine */
+           0,                              /* Flags */
+           sizeof(IP_FRAGMENT),            /* Size of each entry */
+           TAG('I','P','F','G'),           /* Tag */
+           0);                             /* Depth */
+
+    ExInitializeNPagedLookasideList(
+      &IPHoleList,                    /* Lookaside list */
+           NULL,                           /* Allocate routine */
+           NULL,                           /* Free routine */
+           0,                              /* Flags */
+           sizeof(IPDATAGRAM_HOLE),        /* Size of each entry */
+           TAG('I','P','H','L'),           /* Tag */
+           0);                             /* Depth */
+
     /* Start routing subsystem */
     RouterStartup();
 
@@ -971,6 +1150,12 @@ NTSTATUS IPShutdown(
     /* Clear prefix list */
     DestroyPLEs();
 
+    /* Destroy lookaside lists */
+    ExDeleteNPagedLookasideList(&IPHoleList);
+    ExDeleteNPagedLookasideList(&IPDRList);
+    ExDeleteNPagedLookasideList(&IPPacketList);
+    ExDeleteNPagedLookasideList(&IPFragmentList);
+
     IPInitialized = FALSE;
 
     return STATUS_SUCCESS;