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

ip.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 doxygen 1.7.6.1

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