Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenreceive.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
1.7.6.1
|