ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

receive.c
Go to the documentation of this file.
00001 /*
00002  * COPYRIGHT:   See COPYING in the top level directory
00003  * PROJECT:     ReactOS TCP/IP protocol driver
00004  * FILE:        network/receive.c
00005  * PURPOSE:     Internet Protocol receive routines
00006  * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
00007  * NOTES:       The IP datagram reassembly algorithm is taken from
00008  *              from RFC 815
00009  * REVISIONS:
00010  *   CSH 01/08-2000 Created
00011  */
00012 
00013 #include "precomp.h"
00014 
00015 LIST_ENTRY ReassemblyListHead;
00016 KSPIN_LOCK ReassemblyListLock;
00017 NPAGED_LOOKASIDE_LIST IPDRList;
00018 NPAGED_LOOKASIDE_LIST IPFragmentList;
00019 NPAGED_LOOKASIDE_LIST IPHoleList;
00020 
00021 PIPDATAGRAM_HOLE CreateHoleDescriptor(
00022   ULONG First,
00023   ULONG Last)
00024 /*
00025  * FUNCTION: Returns a pointer to a IP datagram hole descriptor
00026  * ARGUMENTS:
00027  *     First = Offset of first octet of the hole
00028  *     Last  = Offset of last octet of the hole
00029  * RETURNS:
00030  *     Pointer to descriptor, NULL if there was not enough free
00031  *     resources
00032  */
00033 {
00034     PIPDATAGRAM_HOLE Hole;
00035 
00036     TI_DbgPrint(DEBUG_IP, ("Called. First (%d)  Last (%d).\n", First, Last));
00037 
00038     Hole = ExAllocateFromNPagedLookasideList(&IPHoleList);
00039     if (!Hole) {
00040         TI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
00041         return NULL;
00042     }
00043 
00044     Hole->First = First;
00045     Hole->Last  = Last;
00046 
00047     TI_DbgPrint(DEBUG_IP, ("Returning hole descriptor at (0x%X).\n", Hole));
00048 
00049     return Hole;
00050 }
00051 
00052 
00053 VOID FreeIPDR(
00054   PIPDATAGRAM_REASSEMBLY IPDR)
00055 /*
00056  * FUNCTION: Frees an IP datagram reassembly structure
00057  * ARGUMENTS:
00058  *     IPDR = Pointer to IP datagram reassembly structure
00059  */
00060 {
00061   PLIST_ENTRY CurrentEntry;
00062   PLIST_ENTRY NextEntry;
00063   PIPDATAGRAM_HOLE CurrentH;
00064   PIP_FRAGMENT CurrentF;
00065 
00066   TI_DbgPrint(DEBUG_IP, ("Freeing IP datagram reassembly descriptor (0x%X).\n", IPDR));
00067 
00068   /* Free all descriptors */
00069   CurrentEntry = IPDR->HoleListHead.Flink;
00070   while (CurrentEntry != &IPDR->HoleListHead) {
00071     NextEntry = CurrentEntry->Flink;
00072       CurrentH = CONTAINING_RECORD(CurrentEntry, IPDATAGRAM_HOLE, ListEntry);
00073     /* Unlink it from the list */
00074     RemoveEntryList(CurrentEntry);
00075 
00076     TI_DbgPrint(DEBUG_IP, ("Freeing hole descriptor at (0x%X).\n", CurrentH));
00077 
00078     /* And free the hole descriptor */
00079     ExFreeToNPagedLookasideList(&IPHoleList, CurrentH);
00080 
00081     CurrentEntry = NextEntry;
00082   }
00083 
00084   /* Free all fragments */
00085   CurrentEntry = IPDR->FragmentListHead.Flink;
00086   while (CurrentEntry != &IPDR->FragmentListHead) {
00087     NextEntry = CurrentEntry->Flink;
00088       CurrentF = CONTAINING_RECORD(CurrentEntry, IP_FRAGMENT, ListEntry);
00089     /* Unlink it from the list */
00090     RemoveEntryList(CurrentEntry);
00091 
00092     TI_DbgPrint(DEBUG_IP, ("Freeing fragment packet at (0x%X).\n", CurrentF->Packet));
00093 
00094     /* Free the fragment data buffer */
00095     if (CurrentF->ReturnPacket)
00096     {
00097         NdisReturnPackets(&CurrentF->Packet, 1);
00098     }
00099     else
00100     {
00101         FreeNdisPacket(CurrentF->Packet);
00102     }
00103 
00104     TI_DbgPrint(DEBUG_IP, ("Freeing fragment at (0x%X).\n", CurrentF));
00105 
00106     /* And free the fragment descriptor */
00107     ExFreeToNPagedLookasideList(&IPFragmentList, CurrentF);
00108     CurrentEntry = NextEntry;
00109   }
00110 
00111   if (IPDR->IPv4Header)
00112   {
00113       TI_DbgPrint(DEBUG_IP, ("Freeing IPDR header at (0x%X).\n", IPDR->IPv4Header));
00114       ExFreePoolWithTag(IPDR->IPv4Header, PACKET_BUFFER_TAG);
00115   }
00116 
00117   TI_DbgPrint(DEBUG_IP, ("Freeing IPDR data at (0x%X).\n", IPDR));
00118 
00119   ExFreeToNPagedLookasideList(&IPDRList, IPDR);
00120 }
00121 
00122 
00123 VOID RemoveIPDR(
00124   PIPDATAGRAM_REASSEMBLY IPDR)
00125 /*
00126  * FUNCTION: Removes an IP datagram reassembly structure from the global list
00127  * ARGUMENTS:
00128  *     IPDR = Pointer to IP datagram reassembly structure
00129  */
00130 {
00131   KIRQL OldIrql;
00132 
00133   TI_DbgPrint(DEBUG_IP, ("Removing IPDR at (0x%X).\n", IPDR));
00134 
00135   TcpipAcquireSpinLock(&ReassemblyListLock, &OldIrql);
00136   RemoveEntryList(&IPDR->ListEntry);
00137   TcpipReleaseSpinLock(&ReassemblyListLock, OldIrql);
00138 }
00139 
00140 
00141 PIPDATAGRAM_REASSEMBLY GetReassemblyInfo(
00142   PIP_PACKET IPPacket)
00143 /*
00144  * FUNCTION: Returns a pointer to an IP datagram reassembly structure
00145  * ARGUMENTS:
00146  *     IPPacket = Pointer to IP packet
00147  * NOTES:
00148  *     A datagram is identified by four paramters, which are
00149  *     Source and destination address, protocol number and
00150  *     identification number
00151  */
00152 {
00153   KIRQL OldIrql;
00154   PLIST_ENTRY CurrentEntry;
00155   PIPDATAGRAM_REASSEMBLY Current;
00156   PIPv4_HEADER Header = (PIPv4_HEADER)IPPacket->Header;
00157 
00158   TI_DbgPrint(DEBUG_IP, ("Searching for IPDR for IP packet at (0x%X).\n", IPPacket));
00159 
00160   TcpipAcquireSpinLock(&ReassemblyListLock, &OldIrql);
00161 
00162   /* FIXME: Assume IPv4 */
00163 
00164   CurrentEntry = ReassemblyListHead.Flink;
00165   while (CurrentEntry != &ReassemblyListHead) {
00166       Current = CONTAINING_RECORD(CurrentEntry, IPDATAGRAM_REASSEMBLY, ListEntry);
00167     if (AddrIsEqual(&IPPacket->SrcAddr, &Current->SrcAddr) &&
00168       (Header->Id == Current->Id) &&
00169       (Header->Protocol == Current->Protocol) &&
00170       (AddrIsEqual(&IPPacket->DstAddr, &Current->DstAddr))) {
00171       TcpipReleaseSpinLock(&ReassemblyListLock, OldIrql);
00172 
00173       return Current;
00174     }
00175     CurrentEntry = CurrentEntry->Flink;
00176   }
00177 
00178   TcpipReleaseSpinLock(&ReassemblyListLock, OldIrql);
00179 
00180   return NULL;
00181 }
00182 
00183 
00184 BOOLEAN
00185 ReassembleDatagram(
00186   PIP_PACKET             IPPacket,
00187   PIPDATAGRAM_REASSEMBLY IPDR)
00188 /*
00189  * FUNCTION: Reassembles an IP datagram
00190  * ARGUMENTS:
00191  *     IPDR = Pointer to IP datagram reassembly structure
00192  * NOTES:
00193  *     This routine concatenates fragments into a complete IP datagram.
00194  *     The lock is held when this routine is called
00195  * RETURNS:
00196  *     Pointer to IP packet, NULL if there was not enough free resources
00197  * NOTES:
00198  *     At this point, header is expected to point to the IP header
00199  */
00200 {
00201   PLIST_ENTRY CurrentEntry;
00202   PIP_FRAGMENT Fragment;
00203   PCHAR Data;
00204 
00205   PAGED_CODE();
00206 
00207   TI_DbgPrint(DEBUG_IP, ("Reassembling datagram from IPDR at (0x%X).\n", IPDR));
00208   TI_DbgPrint(DEBUG_IP, ("IPDR->HeaderSize = %d\n", IPDR->HeaderSize));
00209   TI_DbgPrint(DEBUG_IP, ("IPDR->DataSize = %d\n", IPDR->DataSize));
00210 
00211   IPPacket->TotalSize  = IPDR->HeaderSize + IPDR->DataSize;
00212   IPPacket->HeaderSize = IPDR->HeaderSize;
00213 
00214   RtlCopyMemory(&IPPacket->SrcAddr, &IPDR->SrcAddr, sizeof(IP_ADDRESS));
00215   RtlCopyMemory(&IPPacket->DstAddr, &IPDR->DstAddr, sizeof(IP_ADDRESS));
00216 
00217   /* Allocate space for full IP datagram */
00218   IPPacket->Header = ExAllocatePoolWithTag(PagedPool, IPPacket->TotalSize, PACKET_BUFFER_TAG);
00219   if (!IPPacket->Header) {
00220     TI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
00221     (*IPPacket->Free)(IPPacket);
00222     return FALSE;
00223   }
00224   IPPacket->MappedHeader = FALSE;
00225 
00226   /* Copy the header into the buffer */
00227   RtlCopyMemory(IPPacket->Header, IPDR->IPv4Header, IPDR->HeaderSize);
00228 
00229   Data = (PVOID)((ULONG_PTR)IPPacket->Header + IPDR->HeaderSize);
00230   IPPacket->Data = Data;
00231 
00232   /* Copy data from all fragments into buffer */
00233   CurrentEntry = IPDR->FragmentListHead.Flink;
00234   while (CurrentEntry != &IPDR->FragmentListHead) {
00235     Fragment = CONTAINING_RECORD(CurrentEntry, IP_FRAGMENT, ListEntry);
00236 
00237     /* Copy fragment data into datagram buffer */
00238     CopyPacketToBuffer(Data + Fragment->Offset,
00239                        Fragment->Packet,
00240                        Fragment->PacketOffset,
00241                        Fragment->Size);
00242 
00243     CurrentEntry = CurrentEntry->Flink;
00244   }
00245 
00246   return TRUE;
00247 }
00248 
00249 
00250 __inline VOID Cleanup(
00251   PKSPIN_LOCK Lock,
00252   KIRQL OldIrql,
00253   PIPDATAGRAM_REASSEMBLY IPDR)
00254 /*
00255  * FUNCTION: Performs cleaning operations on errors
00256  * ARGUMENTS:
00257  *     Lock     = Pointer to spin lock to be released
00258  *     OldIrql  = Value of IRQL when spin lock was acquired
00259  *     IPDR     = Pointer to IP datagram reassembly structure to free
00260  *     Buffer   = Optional pointer to a buffer to free
00261  */
00262 {
00263   TI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
00264 
00265   TcpipReleaseSpinLock(Lock, OldIrql);
00266   RemoveIPDR(IPDR);
00267   FreeIPDR(IPDR);
00268 }
00269 
00270 
00271 VOID ProcessFragment(
00272   PIP_INTERFACE IF,
00273   PIP_PACKET IPPacket)
00274 /*
00275  * FUNCTION: Processes an IP datagram or fragment
00276  * ARGUMENTS:
00277  *     IF       = Pointer to IP interface packet was receive on
00278  *     IPPacket = Pointer to IP packet
00279  * NOTES:
00280  *     This routine reassembles fragments and, if a whole datagram can
00281  *     be assembled, passes the datagram on to the IP protocol dispatcher
00282  */
00283 {
00284   KIRQL OldIrql;
00285   PIPDATAGRAM_REASSEMBLY IPDR;
00286   PLIST_ENTRY CurrentEntry;
00287   PIPDATAGRAM_HOLE Hole, NewHole;
00288   USHORT FragFirst;
00289   USHORT FragLast;
00290   BOOLEAN MoreFragments;
00291   PIPv4_HEADER IPv4Header;
00292   IP_PACKET Datagram;
00293   PIP_FRAGMENT Fragment;
00294   BOOLEAN Success;
00295 
00296   /* FIXME: Assume IPv4 */
00297 
00298   IPv4Header = (PIPv4_HEADER)IPPacket->Header;
00299 
00300   /* Check if we already have an reassembly structure for this datagram */
00301   IPDR = GetReassemblyInfo(IPPacket);
00302   if (IPDR) {
00303     TI_DbgPrint(DEBUG_IP, ("Continueing assembly.\n"));
00304     /* We have a reassembly structure */
00305     TcpipAcquireSpinLock(&IPDR->Lock, &OldIrql);
00306       
00307     /* Reset the timeout since we received a fragment */
00308     IPDR->TimeoutCount = 0;
00309   } else {
00310     TI_DbgPrint(DEBUG_IP, ("Starting new assembly.\n"));
00311 
00312     /* We don't have a reassembly structure, create one */
00313     IPDR = ExAllocateFromNPagedLookasideList(&IPDRList);
00314     if (!IPDR)
00315       /* We don't have the resources to process this packet, discard it */
00316       return;
00317 
00318     /* Create a descriptor spanning from zero to infinity.
00319        Actually, we use a value slightly greater than the
00320        maximum number of octets an IP datagram can contain */
00321     Hole = CreateHoleDescriptor(0, 65536);
00322     if (!Hole) {
00323       /* We don't have the resources to process this packet, discard it */
00324       ExFreeToNPagedLookasideList(&IPDRList, IPDR);
00325       return;
00326     }
00327     AddrInitIPv4(&IPDR->SrcAddr, IPv4Header->SrcAddr);
00328     AddrInitIPv4(&IPDR->DstAddr, IPv4Header->DstAddr);
00329     IPDR->Id         = IPv4Header->Id;
00330     IPDR->Protocol   = IPv4Header->Protocol;
00331     IPDR->TimeoutCount = 0;
00332     InitializeListHead(&IPDR->FragmentListHead);
00333     InitializeListHead(&IPDR->HoleListHead);
00334     InsertTailList(&IPDR->HoleListHead, &Hole->ListEntry);
00335 
00336     TcpipInitializeSpinLock(&IPDR->Lock);
00337 
00338     TcpipAcquireSpinLock(&IPDR->Lock, &OldIrql);
00339 
00340     /* Update the reassembly list */
00341     TcpipInterlockedInsertTailList(
00342     &ReassemblyListHead,
00343     &IPDR->ListEntry,
00344     &ReassemblyListLock);
00345   }
00346 
00347   FragFirst     = (WN2H(IPv4Header->FlagsFragOfs) & IPv4_FRAGOFS_MASK) << 3;
00348   FragLast      = FragFirst + WN2H(IPv4Header->TotalLength);
00349   MoreFragments = (WN2H(IPv4Header->FlagsFragOfs) & IPv4_MF_MASK) > 0;
00350 
00351   CurrentEntry = IPDR->HoleListHead.Flink;
00352   for (;;) {
00353     if (CurrentEntry == &IPDR->HoleListHead)
00354         break;
00355 
00356     Hole = CONTAINING_RECORD(CurrentEntry, IPDATAGRAM_HOLE, ListEntry);
00357 
00358     TI_DbgPrint(DEBUG_IP, ("Comparing Fragment (%d,%d) to Hole (%d,%d).\n",
00359       FragFirst, FragLast, Hole->First, Hole->Last));
00360 
00361     if ((FragFirst > Hole->Last) || (FragLast < Hole->First)) {
00362       TI_DbgPrint(MID_TRACE, ("No overlap.\n"));
00363       /* The fragment does not overlap with the hole, try next
00364          descriptor in the list */
00365 
00366       CurrentEntry = CurrentEntry->Flink;
00367       continue;
00368     }
00369 
00370     /* The fragment overlap with the hole, unlink the descriptor */
00371     RemoveEntryList(CurrentEntry);
00372 
00373     if (FragFirst > Hole->First) {
00374       NewHole = CreateHoleDescriptor(Hole->First, FragFirst - 1);
00375       if (!NewHole) {
00376         /* We don't have the resources to process this packet, discard it */
00377         ExFreeToNPagedLookasideList(&IPHoleList, Hole);
00378         Cleanup(&IPDR->Lock, OldIrql, IPDR);
00379         return;
00380       }
00381 
00382       /* Put the new descriptor in the list */
00383       InsertTailList(&IPDR->HoleListHead, &NewHole->ListEntry);
00384     }
00385 
00386     if ((FragLast < Hole->Last) && MoreFragments) {
00387       NewHole = CreateHoleDescriptor(FragLast + 1, Hole->Last);
00388       if (!NewHole) {
00389         /* We don't have the resources to process this packet, discard it */
00390         ExFreeToNPagedLookasideList(&IPHoleList, Hole);
00391         Cleanup(&IPDR->Lock, OldIrql, IPDR);
00392         return;
00393       }
00394 
00395       /* Put the new hole descriptor in the list */
00396       InsertTailList(&IPDR->HoleListHead, &NewHole->ListEntry);
00397     }
00398 
00399     ExFreeToNPagedLookasideList(&IPHoleList, Hole);
00400 
00401     /* If this is the first fragment, save the IP header */
00402     if (FragFirst == 0) {
00403         IPDR->IPv4Header = ExAllocatePoolWithTag(NonPagedPool,
00404                                                  IPPacket->HeaderSize,
00405                                                  PACKET_BUFFER_TAG);
00406         if (!IPDR->IPv4Header)
00407         {
00408             Cleanup(&IPDR->Lock, OldIrql, IPDR);
00409             return;
00410         }
00411 
00412         RtlCopyMemory(IPDR->IPv4Header, IPPacket->Header, IPPacket->HeaderSize);
00413         IPDR->HeaderSize = IPPacket->HeaderSize;
00414 
00415         TI_DbgPrint(DEBUG_IP, ("First fragment found. Header buffer is at (0x%X). "
00416                                "Header size is (%d).\n", &IPDR->IPv4Header, IPPacket->HeaderSize));
00417 
00418     }
00419 
00420     /* Create a buffer, copy the data into it and put it
00421        in the fragment list */
00422 
00423     Fragment = ExAllocateFromNPagedLookasideList(&IPFragmentList);
00424     if (!Fragment) {
00425       /* We don't have the resources to process this packet, discard it */
00426       Cleanup(&IPDR->Lock, OldIrql, IPDR);
00427       return;
00428     }
00429 
00430     TI_DbgPrint(DEBUG_IP, ("Fragment descriptor allocated at (0x%X).\n", Fragment));
00431 
00432     Fragment->Size = IPPacket->TotalSize - IPPacket->HeaderSize;
00433     Fragment->Packet = IPPacket->NdisPacket;
00434     Fragment->ReturnPacket = IPPacket->ReturnPacket;
00435     Fragment->PacketOffset = IPPacket->Position + IPPacket->HeaderSize;
00436     Fragment->Offset = FragFirst;
00437 
00438     /* Disassociate the NDIS packet so it isn't freed upon return from IPReceive() */
00439     IPPacket->NdisPacket = NULL;
00440 
00441     /* If this is the last fragment, compute and save the datagram data size */
00442     if (!MoreFragments)
00443       IPDR->DataSize = FragFirst + Fragment->Size;
00444 
00445     /* Put the fragment in the list */
00446     InsertTailList(&IPDR->FragmentListHead, &Fragment->ListEntry);
00447     break;
00448   }
00449 
00450   TI_DbgPrint(DEBUG_IP, ("Done searching for hole descriptor.\n"));
00451 
00452   if (IsListEmpty(&IPDR->HoleListHead)) {
00453     /* Hole list is empty which means a complete datagram can be assembled.
00454        Assemble the datagram and pass it to an upper layer protocol */
00455 
00456     TI_DbgPrint(DEBUG_IP, ("Complete datagram received.\n"));
00457       
00458     RemoveIPDR(IPDR);
00459     TcpipReleaseSpinLock(&IPDR->Lock, OldIrql);
00460 
00461     /* FIXME: Assumes IPv4 */
00462     IPInitializePacket(&Datagram, IP_ADDRESS_V4);
00463 
00464     Success = ReassembleDatagram(&Datagram, IPDR);
00465 
00466     FreeIPDR(IPDR);
00467 
00468     if (!Success)
00469       /* Not enough free resources, discard the packet */
00470       return;
00471 
00472     DISPLAY_IP_PACKET(&Datagram);
00473 
00474     /* Give the packet to the protocol dispatcher */
00475     IPDispatchProtocol(IF, &Datagram);
00476 
00477     /* We're done with this datagram */
00478     TI_DbgPrint(MAX_TRACE, ("Freeing datagram at (0x%X).\n", Datagram));
00479     Datagram.Free(&Datagram);
00480   } else
00481     TcpipReleaseSpinLock(&IPDR->Lock, OldIrql);
00482 }
00483 
00484 
00485 VOID IPFreeReassemblyList(
00486   VOID)
00487 /*
00488  * FUNCTION: Frees all IP datagram reassembly structures in the list
00489  */
00490 {
00491   KIRQL OldIrql;
00492   PLIST_ENTRY CurrentEntry;
00493   PIPDATAGRAM_REASSEMBLY Current;
00494 
00495   TcpipAcquireSpinLock(&ReassemblyListLock, &OldIrql);
00496 
00497   CurrentEntry = ReassemblyListHead.Flink;
00498   while (CurrentEntry != &ReassemblyListHead) {
00499       Current = CONTAINING_RECORD(CurrentEntry, IPDATAGRAM_REASSEMBLY, ListEntry);
00500     /* Unlink it from the list */
00501     RemoveEntryList(CurrentEntry);
00502 
00503     /* And free the descriptor */
00504     FreeIPDR(Current);
00505 
00506     CurrentEntry = CurrentEntry->Flink;
00507   }
00508 
00509   TcpipReleaseSpinLock(&ReassemblyListLock, OldIrql);
00510 }
00511 
00512 
00513 VOID IPDatagramReassemblyTimeout(
00514   VOID)
00515 /*
00516  * FUNCTION: IP datagram reassembly timeout handler
00517  * NOTES:
00518  *     This routine is called by IPTimeout to free any resources used
00519  *     to hold IP fragments that have taken too long to reassemble
00520  */
00521 {
00522     PLIST_ENTRY CurrentEntry, NextEntry;
00523     PIPDATAGRAM_REASSEMBLY CurrentIPDR;
00524 
00525     TcpipAcquireSpinLockAtDpcLevel(&ReassemblyListLock);
00526 
00527     CurrentEntry = ReassemblyListHead.Flink;
00528     while (CurrentEntry != &ReassemblyListHead)
00529     {
00530        NextEntry = CurrentEntry->Flink;
00531        CurrentIPDR = CONTAINING_RECORD(CurrentEntry, IPDATAGRAM_REASSEMBLY, ListEntry);
00532 
00533        TcpipAcquireSpinLockAtDpcLevel(&CurrentIPDR->Lock);
00534 
00535        if (++CurrentIPDR->TimeoutCount == MAX_TIMEOUT_COUNT)
00536        {
00537            TcpipReleaseSpinLockFromDpcLevel(&CurrentIPDR->Lock);
00538            RemoveEntryList(CurrentEntry);
00539            FreeIPDR(CurrentIPDR);
00540        } 
00541        else
00542        {
00543            ASSERT(CurrentIPDR->TimeoutCount < MAX_TIMEOUT_COUNT);
00544            TcpipReleaseSpinLockFromDpcLevel(&CurrentIPDR->Lock);
00545        }
00546 
00547        CurrentEntry = NextEntry;
00548     }
00549 
00550     TcpipReleaseSpinLockFromDpcLevel(&ReassemblyListLock);
00551 }
00552 
00553 VOID IPv4Receive(PIP_INTERFACE IF, PIP_PACKET IPPacket)
00554 /*
00555  * FUNCTION: Receives an IPv4 datagram (or fragment)
00556  * ARGUMENTS:
00557  *     Context  = Pointer to context information (IP_INTERFACE)
00558  *     IPPacket = Pointer to IP packet
00559  */
00560 {
00561     UCHAR FirstByte;
00562     ULONG BytesCopied;
00563     
00564     TI_DbgPrint(DEBUG_IP, ("Received IPv4 datagram.\n"));
00565     
00566     /* Read in the first IP header byte for size information */
00567     BytesCopied = CopyPacketToBuffer((PCHAR)&FirstByte,
00568                                      IPPacket->NdisPacket,
00569                                      IPPacket->Position,
00570                                      sizeof(UCHAR));
00571     if (BytesCopied != sizeof(UCHAR))
00572     {
00573         TI_DbgPrint(MIN_TRACE, ("Failed to copy in first byte\n"));
00574         /* Discard packet */
00575         return;
00576     }
00577 
00578     IPPacket->HeaderSize = (FirstByte & 0x0F) << 2;
00579     TI_DbgPrint(DEBUG_IP, ("IPPacket->HeaderSize = %d\n", IPPacket->HeaderSize));
00580 
00581     if (IPPacket->HeaderSize > IPv4_MAX_HEADER_SIZE) {
00582         TI_DbgPrint(MIN_TRACE, ("Datagram received with incorrect header size (%d).\n",
00583           IPPacket->HeaderSize));
00584         /* Discard packet */
00585         return;
00586     }
00587 
00588     /* This is freed by IPPacket->Free() */
00589     IPPacket->Header = ExAllocatePoolWithTag(NonPagedPool,
00590                                              IPPacket->HeaderSize,
00591                                              PACKET_BUFFER_TAG);
00592     if (!IPPacket->Header)
00593     {
00594         TI_DbgPrint(MIN_TRACE, ("No resources to allocate header\n"));
00595         /* Discard packet */
00596         return;
00597     }
00598 
00599     IPPacket->MappedHeader = FALSE;
00600 
00601     BytesCopied = CopyPacketToBuffer((PCHAR)IPPacket->Header,
00602                                      IPPacket->NdisPacket,
00603                                      IPPacket->Position,
00604                                      IPPacket->HeaderSize);
00605     if (BytesCopied != IPPacket->HeaderSize)
00606     {
00607         TI_DbgPrint(MIN_TRACE, ("Failed to copy in header\n"));
00608         /* Discard packet */
00609         return;
00610     }
00611 
00612     /* Checksum IPv4 header */
00613     if (!IPv4CorrectChecksum(IPPacket->Header, IPPacket->HeaderSize)) {
00614         TI_DbgPrint(MIN_TRACE, ("Datagram received with bad checksum. Checksum field (0x%X)\n",
00615           WN2H(((PIPv4_HEADER)IPPacket->Header)->Checksum)));
00616         /* Discard packet */
00617         return;
00618     }
00619 
00620     IPPacket->TotalSize = WN2H(((PIPv4_HEADER)IPPacket->Header)->TotalLength);
00621 
00622     AddrInitIPv4(&IPPacket->SrcAddr, ((PIPv4_HEADER)IPPacket->Header)->SrcAddr);
00623     AddrInitIPv4(&IPPacket->DstAddr, ((PIPv4_HEADER)IPPacket->Header)->DstAddr);
00624     
00625     TI_DbgPrint(MID_TRACE,("IPPacket->Position = %d\n",
00626                            IPPacket->Position));
00627 
00628     /* FIXME: Possibly forward packets with multicast addresses */
00629 
00630     /* FIXME: Should we allow packets to be received on the wrong interface? */
00631     /* XXX Find out if this packet is destined for us */
00632     ProcessFragment(IF, IPPacket);
00633 }
00634 
00635 
00636 VOID IPReceive( PIP_INTERFACE IF, PIP_PACKET IPPacket )
00637 /*
00638  * FUNCTION: Receives an IP datagram (or fragment)
00639  * ARGUMENTS:
00640  *     IF       = Interface
00641  *     IPPacket = Pointer to IP packet
00642  */
00643 {
00644     UCHAR FirstByte;
00645     UINT Version, BytesCopied;
00646 
00647     /* Read in the first IP header byte for version information */
00648     BytesCopied = CopyPacketToBuffer((PCHAR)&FirstByte,
00649                                      IPPacket->NdisPacket,
00650                                      IPPacket->Position,
00651                                      sizeof(UCHAR));
00652     if (BytesCopied != sizeof(UCHAR))
00653     {
00654         TI_DbgPrint(MIN_TRACE, ("Failed to copy in first byte\n"));
00655         IPPacket->Free(IPPacket);
00656         return;
00657     }
00658 
00659     /* Check that IP header has a supported version */
00660     Version = (FirstByte >> 4);
00661 
00662     switch (Version) {
00663         case 4:
00664             IPPacket->Type = IP_ADDRESS_V4;
00665             IPv4Receive(IF, IPPacket);
00666             break;
00667         case 6:
00668             IPPacket->Type = IP_ADDRESS_V6;
00669             TI_DbgPrint(MAX_TRACE, ("Datagram of type IPv6 discarded.\n"));
00670             break;
00671         default:
00672             TI_DbgPrint(MIN_TRACE, ("Datagram has an unsupported IP version %d.\n", Version));
00673             break;
00674     }
00675 
00676     IPPacket->Free(IPPacket);
00677 }
00678 
00679 /* EOF */

Generated on Sun May 27 2012 04:35:58 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.