Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenip.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/ip.c 00005 * PURPOSE: Internet Protocol module 00006 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) 00007 * REVISIONS: 00008 * CSH 01/08-2000 Created 00009 */ 00010 00011 #include "precomp.h" 00012 00013 #define __LWIP_INET_H__ 00014 #include "lwip/netifapi.h" 00015 00016 00017 LIST_ENTRY InterfaceListHead; 00018 KSPIN_LOCK InterfaceListLock; 00019 LIST_ENTRY NetTableListHead; 00020 KSPIN_LOCK NetTableListLock; 00021 BOOLEAN IPInitialized = FALSE; 00022 BOOLEAN IpWorkItemQueued = FALSE; 00023 /* Work around calling timer at Dpc level */ 00024 00025 IP_PROTOCOL_HANDLER ProtocolTable[IP_PROTOCOL_TABLE_SIZE]; 00026 00027 VOID 00028 TCPRegisterInterface(PIP_INTERFACE IF); 00029 00030 VOID 00031 TCPUnregisterInterface(PIP_INTERFACE IF); 00032 00033 VOID DeinitializePacket( 00034 PVOID Object) 00035 /* 00036 * FUNCTION: Frees buffers attached to the packet 00037 * ARGUMENTS: 00038 * Object = Pointer to an IP packet structure 00039 */ 00040 { 00041 PIP_PACKET IPPacket = Object; 00042 00043 TI_DbgPrint(MAX_TRACE, ("Freeing object: 0x%p\n", Object)); 00044 00045 /* Detect double free */ 00046 ASSERT(IPPacket->Type != 0xFF); 00047 IPPacket->Type = 0xFF; 00048 00049 /* Check if there's a packet to free */ 00050 if (IPPacket->NdisPacket != NULL) 00051 { 00052 if (IPPacket->ReturnPacket) 00053 { 00054 /* Return the packet to the miniport driver */ 00055 TI_DbgPrint(MAX_TRACE, ("Returning packet 0x%p\n", 00056 IPPacket->NdisPacket)); 00057 NdisReturnPackets(&IPPacket->NdisPacket, 1); 00058 } 00059 else 00060 { 00061 /* Free it the conventional way */ 00062 TI_DbgPrint(MAX_TRACE, ("Freeing packet 0x%p\n", 00063 IPPacket->NdisPacket)); 00064 FreeNdisPacket(IPPacket->NdisPacket); 00065 } 00066 } 00067 00068 /* Check if we have a pool-allocated header */ 00069 if (!IPPacket->MappedHeader && IPPacket->Header) 00070 { 00071 /* Free it */ 00072 TI_DbgPrint(MAX_TRACE, ("Freeing header: 0x%p\n", 00073 IPPacket->Header)); 00074 ExFreePoolWithTag(IPPacket->Header, 00075 PACKET_BUFFER_TAG); 00076 } 00077 } 00078 00079 VOID FreeIF( 00080 PVOID Object) 00081 /* 00082 * FUNCTION: Frees an interface object 00083 * ARGUMENTS: 00084 * Object = Pointer to an interface structure 00085 */ 00086 { 00087 ExFreePoolWithTag(Object, IP_INTERFACE_TAG); 00088 } 00089 00090 PIP_PACKET IPInitializePacket( 00091 PIP_PACKET IPPacket, 00092 ULONG Type) 00093 /* 00094 * FUNCTION: Creates an IP packet object 00095 * ARGUMENTS: 00096 * Type = Type of IP packet 00097 * RETURNS: 00098 * Pointer to the created IP packet. NULL if there was not enough free resources. 00099 */ 00100 { 00101 RtlZeroMemory(IPPacket, sizeof(IP_PACKET)); 00102 00103 IPPacket->Free = DeinitializePacket; 00104 IPPacket->Type = Type; 00105 00106 return IPPacket; 00107 } 00108 00109 00110 VOID NTAPI IPTimeoutDpcFn(PKDPC Dpc, 00111 PVOID DeferredContext, 00112 PVOID SystemArgument1, 00113 PVOID SystemArgument2) 00114 /* 00115 * FUNCTION: Timeout DPC 00116 * ARGUMENTS: 00117 * Dpc = Pointer to our DPC object 00118 * DeferredContext = Pointer to context information (unused) 00119 * SystemArgument1 = Unused 00120 * SystemArgument2 = Unused 00121 * NOTES: 00122 * This routine is dispatched once in a while to do maintainance jobs 00123 */ 00124 { 00125 /* Check if datagram fragments have taken too long to assemble */ 00126 IPDatagramReassemblyTimeout(); 00127 00128 /* Clean possible outdated cached neighbor addresses */ 00129 NBTimeout(); 00130 } 00131 00132 00133 VOID IPDispatchProtocol( 00134 PIP_INTERFACE Interface, 00135 PIP_PACKET IPPacket) 00136 /* 00137 * FUNCTION: IP protocol dispatcher 00138 * ARGUMENTS: 00139 * NTE = Pointer to net table entry which the packet was received on 00140 * IPPacket = Pointer to an IP packet that was received 00141 * NOTES: 00142 * This routine examines the IP header and passes the packet on to the 00143 * right upper level protocol receive handler 00144 */ 00145 { 00146 UINT Protocol; 00147 IP_ADDRESS SrcAddress; 00148 00149 switch (IPPacket->Type) { 00150 case IP_ADDRESS_V4: 00151 Protocol = ((PIPv4_HEADER)(IPPacket->Header))->Protocol; 00152 AddrInitIPv4(&SrcAddress, ((PIPv4_HEADER)(IPPacket->Header))->SrcAddr); 00153 break; 00154 case IP_ADDRESS_V6: 00155 /* FIXME: IPv6 adresses not supported */ 00156 TI_DbgPrint(MIN_TRACE, ("IPv6 datagram discarded.\n")); 00157 return; 00158 default: 00159 TI_DbgPrint(MIN_TRACE, ("Unrecognized datagram discarded.\n")); 00160 return; 00161 } 00162 00163 NBResetNeighborTimeout(&SrcAddress); 00164 00165 if (Protocol < IP_PROTOCOL_TABLE_SIZE) 00166 { 00167 /* Call the appropriate protocol handler */ 00168 (*ProtocolTable[Protocol])(Interface, IPPacket); 00169 } 00170 } 00171 00172 00173 PIP_INTERFACE IPCreateInterface( 00174 PLLIP_BIND_INFO BindInfo) 00175 /* 00176 * FUNCTION: Creates an IP interface 00177 * ARGUMENTS: 00178 * BindInfo = Pointer to link layer to IP binding information 00179 * RETURNS: 00180 * Pointer to IP_INTERFACE structure, NULL if there was 00181 * not enough free resources 00182 */ 00183 { 00184 PIP_INTERFACE IF; 00185 00186 TI_DbgPrint(DEBUG_IP, ("Called. BindInfo (0x%X).\n", BindInfo)); 00187 00188 #if DBG 00189 if (BindInfo->Address) { 00190 PUCHAR A = BindInfo->Address; 00191 TI_DbgPrint(DEBUG_IP, ("Interface address (%02X %02X %02X %02X %02X %02X).\n", 00192 A[0], A[1], A[2], A[3], A[4], A[5])); 00193 } 00194 #endif 00195 00196 IF = ExAllocatePoolWithTag(NonPagedPool, sizeof(IP_INTERFACE), 00197 IP_INTERFACE_TAG); 00198 if (!IF) { 00199 TI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n")); 00200 return NULL; 00201 } 00202 00203 RtlZeroMemory(IF, sizeof(IP_INTERFACE)); 00204 00205 IF->Free = FreeIF; 00206 IF->Context = BindInfo->Context; 00207 IF->HeaderSize = BindInfo->HeaderSize; 00208 IF->MinFrameSize = BindInfo->MinFrameSize; 00209 IF->Address = BindInfo->Address; 00210 IF->AddressLength = BindInfo->AddressLength; 00211 IF->Transmit = BindInfo->Transmit; 00212 00213 IF->Unicast.Type = IP_ADDRESS_V4; 00214 IF->PointToPoint.Type = IP_ADDRESS_V4; 00215 IF->Netmask.Type = IP_ADDRESS_V4; 00216 IF->Broadcast.Type = IP_ADDRESS_V4; 00217 00218 TcpipInitializeSpinLock(&IF->Lock); 00219 00220 IF->TCPContext = ExAllocatePool 00221 ( NonPagedPool, sizeof(struct netif)); 00222 if (!IF->TCPContext) { 00223 ExFreePoolWithTag(IF, IP_INTERFACE_TAG); 00224 return NULL; 00225 } 00226 00227 TCPRegisterInterface(IF); 00228 00229 #ifdef __NTDRIVER__ 00230 InsertTDIInterfaceEntity( IF ); 00231 #endif 00232 00233 return IF; 00234 } 00235 00236 00237 VOID IPDestroyInterface( 00238 PIP_INTERFACE IF) 00239 /* 00240 * FUNCTION: Destroys an IP interface 00241 * ARGUMENTS: 00242 * IF = Pointer to interface to destroy 00243 */ 00244 { 00245 TI_DbgPrint(DEBUG_IP, ("Called. IF (0x%X).\n", IF)); 00246 00247 #ifdef __NTDRIVER__ 00248 RemoveTDIInterfaceEntity( IF ); 00249 #endif 00250 00251 TCPUnregisterInterface(IF); 00252 00253 ExFreePool(IF->TCPContext); 00254 ExFreePoolWithTag(IF, IP_INTERFACE_TAG); 00255 } 00256 00257 VOID IPAddInterfaceRoute( PIP_INTERFACE IF ) { 00258 PNEIGHBOR_CACHE_ENTRY NCE; 00259 IP_ADDRESS NetworkAddress; 00260 00261 /* Add a permanent neighbor for this NTE */ 00262 NCE = NBAddNeighbor(IF, &IF->Unicast, 00263 IF->Address, IF->AddressLength, 00264 NUD_PERMANENT, 0); 00265 if (!NCE) { 00266 TI_DbgPrint(MIN_TRACE, ("Could not create NCE.\n")); 00267 return; 00268 } 00269 00270 AddrWidenAddress( &NetworkAddress, &IF->Unicast, &IF->Netmask ); 00271 00272 if (!RouterAddRoute(&NetworkAddress, &IF->Netmask, NCE, 1)) { 00273 TI_DbgPrint(MIN_TRACE, ("Could not add route due to insufficient resources.\n")); 00274 } 00275 00276 /* Send a gratuitous ARP packet to update the route caches of 00277 * other computers */ 00278 if (IF != Loopback) 00279 ARPTransmit(NULL, NULL, IF); 00280 00281 TCPUpdateInterfaceIPInformation(IF); 00282 } 00283 00284 BOOLEAN IPRegisterInterface( 00285 PIP_INTERFACE IF) 00286 /* 00287 * FUNCTION: Registers an IP interface with IP layer 00288 * ARGUMENTS: 00289 * IF = Pointer to interface to register 00290 * RETURNS; 00291 * TRUE if interface was successfully registered, FALSE if not 00292 */ 00293 { 00294 KIRQL OldIrql; 00295 UINT ChosenIndex = 0; 00296 BOOLEAN IndexHasBeenChosen; 00297 IF_LIST_ITER(Interface); 00298 00299 TI_DbgPrint(MID_TRACE, ("Called. IF (0x%X).\n", IF)); 00300 00301 TcpipAcquireSpinLock(&IF->Lock, &OldIrql); 00302 00303 /* Choose an index */ 00304 do { 00305 IndexHasBeenChosen = TRUE; 00306 ForEachInterface(Interface) { 00307 if( Interface->Index == ChosenIndex ) { 00308 ChosenIndex++; 00309 IndexHasBeenChosen = FALSE; 00310 } 00311 } EndFor(Interface); 00312 } while( !IndexHasBeenChosen ); 00313 00314 IF->Index = ChosenIndex; 00315 00316 /* Add interface to the global interface list */ 00317 TcpipInterlockedInsertTailList(&InterfaceListHead, 00318 &IF->ListEntry, 00319 &InterfaceListLock); 00320 00321 TcpipReleaseSpinLock(&IF->Lock, OldIrql); 00322 00323 return TRUE; 00324 } 00325 00326 VOID IPRemoveInterfaceRoute( PIP_INTERFACE IF ) { 00327 PNEIGHBOR_CACHE_ENTRY NCE; 00328 IP_ADDRESS GeneralRoute; 00329 00330 NCE = NBLocateNeighbor(&IF->Unicast); 00331 if (NCE) 00332 { 00333 TI_DbgPrint(DEBUG_IP,("Removing interface Addr %s\n", A2S(&IF->Unicast))); 00334 TI_DbgPrint(DEBUG_IP,(" Mask %s\n", A2S(&IF->Netmask))); 00335 00336 AddrWidenAddress(&GeneralRoute,&IF->Unicast,&IF->Netmask); 00337 00338 RouterRemoveRoute(&GeneralRoute, &IF->Unicast); 00339 00340 NBRemoveNeighbor(NCE); 00341 } 00342 } 00343 00344 VOID IPUnregisterInterface( 00345 PIP_INTERFACE IF) 00346 /* 00347 * FUNCTION: Unregisters an IP interface with IP layer 00348 * ARGUMENTS: 00349 * IF = Pointer to interface to unregister 00350 */ 00351 { 00352 KIRQL OldIrql3; 00353 00354 TI_DbgPrint(DEBUG_IP, ("Called. IF (0x%X).\n", IF)); 00355 00356 IPRemoveInterfaceRoute( IF ); 00357 00358 TcpipAcquireSpinLock(&InterfaceListLock, &OldIrql3); 00359 RemoveEntryList(&IF->ListEntry); 00360 TcpipReleaseSpinLock(&InterfaceListLock, OldIrql3); 00361 } 00362 00363 00364 VOID DefaultProtocolHandler( 00365 PIP_INTERFACE Interface, 00366 PIP_PACKET IPPacket) 00367 /* 00368 * FUNCTION: Default handler for Internet protocols 00369 * ARGUMENTS: 00370 * NTE = Pointer to net table entry which the packet was received on 00371 * IPPacket = Pointer to an IP packet that was received 00372 */ 00373 { 00374 TI_DbgPrint(MID_TRACE, ("[IF %x] Packet of unknown Internet protocol " 00375 "discarded.\n", Interface)); 00376 00377 Interface->Stats.InDiscardedUnknownProto++; 00378 } 00379 00380 00381 VOID IPRegisterProtocol( 00382 UINT ProtocolNumber, 00383 IP_PROTOCOL_HANDLER Handler) 00384 /* 00385 * FUNCTION: Registers a handler for an IP protocol number 00386 * ARGUMENTS: 00387 * ProtocolNumber = Internet Protocol number for which to register handler 00388 * Handler = Pointer to handler to be called when a packet is received 00389 * NOTES: 00390 * To unregister a protocol handler, call this function with Handler = NULL 00391 */ 00392 { 00393 if (ProtocolNumber >= IP_PROTOCOL_TABLE_SIZE) { 00394 TI_DbgPrint(MIN_TRACE, ("Protocol number is out of range (%d).\n", ProtocolNumber)); 00395 return; 00396 } 00397 00398 ProtocolTable[ProtocolNumber] = Handler ? Handler : DefaultProtocolHandler; 00399 } 00400 00401 00402 NTSTATUS IPStartup(PUNICODE_STRING RegistryPath) 00403 /* 00404 * FUNCTION: Initializes the IP subsystem 00405 * ARGUMENTS: 00406 * RegistryPath = Our registry node for configuration parameters 00407 * RETURNS: 00408 * Status of operation 00409 */ 00410 { 00411 UINT i; 00412 00413 TI_DbgPrint(MAX_TRACE, ("Called.\n")); 00414 00415 /* Initialize lookaside lists */ 00416 ExInitializeNPagedLookasideList( 00417 &IPDRList, /* Lookaside list */ 00418 NULL, /* Allocate routine */ 00419 NULL, /* Free routine */ 00420 0, /* Flags */ 00421 sizeof(IPDATAGRAM_REASSEMBLY), /* Size of each entry */ 00422 DATAGRAM_REASSEMBLY_TAG, /* Tag */ 00423 0); /* Depth */ 00424 00425 ExInitializeNPagedLookasideList( 00426 &IPFragmentList, /* Lookaside list */ 00427 NULL, /* Allocate routine */ 00428 NULL, /* Free routine */ 00429 0, /* Flags */ 00430 sizeof(IP_FRAGMENT), /* Size of each entry */ 00431 DATAGRAM_FRAGMENT_TAG, /* Tag */ 00432 0); /* Depth */ 00433 00434 ExInitializeNPagedLookasideList( 00435 &IPHoleList, /* Lookaside list */ 00436 NULL, /* Allocate routine */ 00437 NULL, /* Free routine */ 00438 0, /* Flags */ 00439 sizeof(IPDATAGRAM_HOLE), /* Size of each entry */ 00440 DATAGRAM_HOLE_TAG, /* Tag */ 00441 0); /* Depth */ 00442 00443 /* Start routing subsystem */ 00444 RouterStartup(); 00445 00446 /* Start neighbor cache subsystem */ 00447 NBStartup(); 00448 00449 /* Fill the protocol dispatch table with pointers 00450 to the default protocol handler */ 00451 for (i = 0; i < IP_PROTOCOL_TABLE_SIZE; i++) 00452 IPRegisterProtocol(i, DefaultProtocolHandler); 00453 00454 /* Initialize NTE list and protecting lock */ 00455 InitializeListHead(&NetTableListHead); 00456 TcpipInitializeSpinLock(&NetTableListLock); 00457 00458 /* Initialize reassembly list and protecting lock */ 00459 InitializeListHead(&ReassemblyListHead); 00460 TcpipInitializeSpinLock(&ReassemblyListLock); 00461 00462 IPInitialized = TRUE; 00463 00464 return STATUS_SUCCESS; 00465 } 00466 00467 00468 NTSTATUS IPShutdown( 00469 VOID) 00470 /* 00471 * FUNCTION: Shuts down the IP subsystem 00472 * RETURNS: 00473 * Status of operation 00474 */ 00475 { 00476 TI_DbgPrint(MAX_TRACE, ("Called.\n")); 00477 00478 if (!IPInitialized) 00479 return STATUS_SUCCESS; 00480 00481 /* Shutdown neighbor cache subsystem */ 00482 NBShutdown(); 00483 00484 /* Shutdown routing subsystem */ 00485 RouterShutdown(); 00486 00487 IPFreeReassemblyList(); 00488 00489 /* Destroy lookaside lists */ 00490 ExDeleteNPagedLookasideList(&IPHoleList); 00491 ExDeleteNPagedLookasideList(&IPDRList); 00492 ExDeleteNPagedLookasideList(&IPFragmentList); 00493 00494 IPInitialized = FALSE; 00495 00496 return STATUS_SUCCESS; 00497 } 00498 00499 /* EOF */ Generated on Sun May 27 2012 04:35:58 for ReactOS by
1.7.6.1
|