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

fileobjs.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:        tcpip/fileobjs.c
00005  * PURPOSE:     Routines for handling file objects
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 
00014 /* List of all address file objects managed by this driver */
00015 LIST_ENTRY AddressFileListHead;
00016 KSPIN_LOCK AddressFileListLock;
00017 
00018 /* List of all connection endpoint file objects managed by this driver */
00019 LIST_ENTRY ConnectionEndpointListHead;
00020 KSPIN_LOCK ConnectionEndpointListLock;
00021 
00022 /*
00023  * FUNCTION: Searches through address file entries to find the first match
00024  * ARGUMENTS:
00025  *     Address       = IP address
00026  *     Port          = Port number
00027  *     Protocol      = Protocol number
00028  *     SearchContext = Pointer to search context
00029  * RETURNS:
00030  *     Pointer to address file, NULL if none was found
00031  */
00032 PADDRESS_FILE AddrSearchFirst(
00033     PIP_ADDRESS Address,
00034     USHORT Port,
00035     USHORT Protocol,
00036     PAF_SEARCH SearchContext)
00037 {
00038     KIRQL OldIrql;
00039     
00040     SearchContext->Address  = Address;
00041     SearchContext->Port     = Port;
00042     SearchContext->Protocol = Protocol;
00043 
00044     TcpipAcquireSpinLock(&AddressFileListLock, &OldIrql);
00045 
00046     SearchContext->Next = AddressFileListHead.Flink;
00047 
00048     if (!IsListEmpty(&AddressFileListHead))
00049         ReferenceObject(CONTAINING_RECORD(SearchContext->Next, ADDRESS_FILE, ListEntry));
00050 
00051     TcpipReleaseSpinLock(&AddressFileListLock, OldIrql);
00052 
00053     return AddrSearchNext(SearchContext);
00054 }
00055 
00056 BOOLEAN AddrIsBroadcastMatch(
00057     PIP_ADDRESS UnicastAddress,
00058     PIP_ADDRESS BroadcastAddress ) {
00059     IF_LIST_ITER(IF);
00060 
00061     ForEachInterface(IF) {
00062         if ((AddrIsUnspecified(UnicastAddress) ||
00063              AddrIsEqual(&IF->Unicast, UnicastAddress)) &&
00064             (AddrIsEqual(&IF->Broadcast, BroadcastAddress)))
00065             return TRUE;
00066     } EndFor(IF);
00067 
00068     return FALSE;
00069 }
00070 
00071 BOOLEAN AddrReceiveMatch(
00072    PIP_ADDRESS LocalAddress,
00073    PIP_ADDRESS RemoteAddress)
00074 {
00075    if (AddrIsEqual(LocalAddress, RemoteAddress))
00076    {
00077        /* Unicast address match */
00078        return TRUE;
00079    }
00080 
00081    if (AddrIsBroadcastMatch(LocalAddress, RemoteAddress))
00082    {
00083        /* Broadcast address match */
00084        return TRUE;
00085    }
00086 
00087    if (AddrIsUnspecified(LocalAddress))
00088    {
00089        /* Local address unspecified */
00090        return TRUE;
00091    }
00092 
00093    if (AddrIsUnspecified(RemoteAddress))
00094    {
00095        /* Remote address unspecified */
00096        return TRUE;
00097    }
00098 
00099    return FALSE;
00100 }
00101 
00102 /*
00103  * FUNCTION: Searches through address file entries to find next match
00104  * ARGUMENTS:
00105  *     SearchContext = Pointer to search context
00106  * RETURNS:
00107  *     Pointer to address file, NULL if none was found
00108  */
00109 PADDRESS_FILE AddrSearchNext(
00110     PAF_SEARCH SearchContext)
00111 {
00112     PLIST_ENTRY CurrentEntry;
00113     PIP_ADDRESS IPAddress;
00114     KIRQL OldIrql;
00115     PADDRESS_FILE Current = NULL;
00116     BOOLEAN Found = FALSE;
00117     
00118     TcpipAcquireSpinLock(&AddressFileListLock, &OldIrql);
00119 
00120     if (SearchContext->Next == &AddressFileListHead)
00121     {
00122         TcpipReleaseSpinLock(&AddressFileListLock, OldIrql);
00123         return NULL;
00124     }
00125 
00126     /* Remove the extra reference we added to keep this address file in memory */
00127     DereferenceObject(CONTAINING_RECORD(SearchContext->Next, ADDRESS_FILE, ListEntry));
00128 
00129     CurrentEntry = SearchContext->Next;
00130 
00131     while (CurrentEntry != &AddressFileListHead) {
00132         Current = CONTAINING_RECORD(CurrentEntry, ADDRESS_FILE, ListEntry);
00133 
00134         IPAddress = &Current->Address;
00135 
00136         TI_DbgPrint(DEBUG_ADDRFILE, ("Comparing: ((%d, %d, %s), (%d, %d, %s)).\n",
00137             WN2H(Current->Port),
00138             Current->Protocol,
00139             A2S(IPAddress),
00140             WN2H(SearchContext->Port),
00141             SearchContext->Protocol,
00142             A2S(SearchContext->Address)));
00143 
00144         /* See if this address matches the search criteria */
00145         if ((Current->Port    == SearchContext->Port) &&
00146             (Current->Protocol == SearchContext->Protocol) &&
00147             (AddrReceiveMatch(IPAddress, SearchContext->Address))) {
00148             /* We've found a match */
00149             Found = TRUE;
00150             break;
00151         }
00152         CurrentEntry = CurrentEntry->Flink;
00153     }
00154 
00155     if (Found)
00156     {
00157         SearchContext->Next = CurrentEntry->Flink;
00158 
00159         if (SearchContext->Next != &AddressFileListHead)
00160         {
00161             /* Reference the next address file to prevent the link from disappearing behind our back */
00162             ReferenceObject(CONTAINING_RECORD(SearchContext->Next, ADDRESS_FILE, ListEntry));
00163         }
00164     }
00165     else
00166         Current = NULL;
00167 
00168     TcpipReleaseSpinLock(&AddressFileListLock, OldIrql);
00169 
00170     return Current;
00171 }
00172 
00173 VOID AddrFileFree(
00174     PVOID Object)
00175 /*
00176  * FUNCTION: Frees an address file object
00177  * ARGUMENTS:
00178  *     Object = Pointer to address file object to free
00179  */
00180 {
00181   PADDRESS_FILE AddrFile = Object;
00182   KIRQL OldIrql;
00183   PDATAGRAM_RECEIVE_REQUEST ReceiveRequest;
00184   PDATAGRAM_SEND_REQUEST SendRequest;
00185   PLIST_ENTRY CurrentEntry;
00186 
00187   TI_DbgPrint(MID_TRACE, ("Called.\n"));
00188 
00189   /* We should not be associated with a connection here */
00190   ASSERT(!AddrFile->Connection);
00191 
00192   /* Remove address file from the global list */
00193   TcpipAcquireSpinLock(&AddressFileListLock, &OldIrql);
00194   RemoveEntryList(&AddrFile->ListEntry);
00195   TcpipReleaseSpinLock(&AddressFileListLock, OldIrql);
00196 
00197   /* FIXME: Kill TCP connections on this address file object */
00198 
00199   /* Return pending requests with error */
00200 
00201   TI_DbgPrint(DEBUG_ADDRFILE, ("Aborting receive requests on AddrFile at (0x%X).\n", AddrFile));
00202 
00203   /* Go through pending receive request list and cancel them all */
00204   while ((CurrentEntry = ExInterlockedRemoveHeadList(&AddrFile->ReceiveQueue, &AddrFile->Lock))) {
00205     ReceiveRequest = CONTAINING_RECORD(CurrentEntry, DATAGRAM_RECEIVE_REQUEST, ListEntry);
00206     (*ReceiveRequest->Complete)(ReceiveRequest->Context, STATUS_CANCELLED, 0);
00207     /* ExFreePoolWithTag(ReceiveRequest, DATAGRAM_RECV_TAG); FIXME: WTF? */
00208   }
00209 
00210   TI_DbgPrint(DEBUG_ADDRFILE, ("Aborting send requests on address file at (0x%X).\n", AddrFile));
00211 
00212   /* Go through pending send request list and cancel them all */
00213   while ((CurrentEntry = ExInterlockedRemoveHeadList(&AddrFile->ReceiveQueue, &AddrFile->Lock))) {
00214     SendRequest = CONTAINING_RECORD(CurrentEntry, DATAGRAM_SEND_REQUEST, ListEntry);
00215     (*SendRequest->Complete)(SendRequest->Context, STATUS_CANCELLED, 0);
00216     ExFreePoolWithTag(SendRequest, DATAGRAM_SEND_TAG);
00217   }
00218 
00219   /* Protocol specific handling */
00220   switch (AddrFile->Protocol) {
00221   case IPPROTO_TCP:
00222     if (AddrFile->Port)
00223     {
00224         TCPFreePort(AddrFile->Port);
00225     }
00226     break;
00227 
00228   case IPPROTO_UDP:
00229     UDPFreePort( AddrFile->Port );
00230     break;
00231   }
00232 
00233   RemoveEntityByContext(AddrFile);
00234 
00235   ExFreePoolWithTag(Object, ADDR_FILE_TAG);
00236 }
00237 
00238 
00239 VOID ControlChannelFree(
00240     PVOID Object)
00241 /*
00242  * FUNCTION: Frees an address file object
00243  * ARGUMENTS:
00244  *     Object = Pointer to address file object to free
00245  */
00246 {
00247     ExFreePoolWithTag(Object, CONTROL_CHANNEL_TAG);
00248 }
00249 
00250 
00251 /*
00252  * FUNCTION: Open an address file object
00253  * ARGUMENTS:
00254  *     Request  = Pointer to TDI request structure for this request
00255  *     Address  = Pointer to address to be opened
00256  *     Protocol = Protocol on which to open the address
00257  *     Options  = Pointer to option buffer
00258  * RETURNS:
00259  *     Status of operation
00260  */
00261 NTSTATUS FileOpenAddress(
00262   PTDI_REQUEST Request,
00263   PTA_IP_ADDRESS Address,
00264   USHORT Protocol,
00265   PVOID Options)
00266 {
00267   PADDRESS_FILE AddrFile;
00268 
00269   TI_DbgPrint(MID_TRACE, ("Called (Proto %d).\n", Protocol));
00270 
00271   AddrFile = ExAllocatePoolWithTag(NonPagedPool, sizeof(ADDRESS_FILE),
00272                                    ADDR_FILE_TAG);
00273   if (!AddrFile) {
00274     TI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
00275     return STATUS_INSUFFICIENT_RESOURCES;
00276   }
00277 
00278   RtlZeroMemory(AddrFile, sizeof(ADDRESS_FILE));
00279 
00280   AddrFile->RefCount = 1;
00281   AddrFile->Free = AddrFileFree;
00282 
00283   /* Set our default options */
00284   AddrFile->TTL = 128;
00285   AddrFile->DF = 0;
00286   AddrFile->BCast = 1;
00287   AddrFile->HeaderIncl = 1;
00288 
00289   /* Make sure address is a local unicast address or 0 */
00290   /* FIXME: IPv4 only */
00291   AddrFile->Family = Address->Address[0].AddressType;
00292   AddrFile->Address.Address.IPv4Address = Address->Address[0].Address[0].in_addr;
00293   AddrFile->Address.Type = IP_ADDRESS_V4;
00294 
00295   if (!AddrIsUnspecified(&AddrFile->Address) &&
00296       !AddrLocateInterface(&AddrFile->Address)) {
00297       ExFreePoolWithTag(AddrFile, ADDR_FILE_TAG);
00298       TI_DbgPrint(MIN_TRACE, ("Non-local address given (0x%X).\n", A2S(&AddrFile->Address)));
00299       return STATUS_INVALID_ADDRESS;
00300   }
00301 
00302   TI_DbgPrint(MID_TRACE, ("Opening address %s for communication (P=%d U=%d).\n",
00303     A2S(&AddrFile->Address), Protocol, IPPROTO_UDP));
00304 
00305   /* Protocol specific handling */
00306   switch (Protocol) {
00307   case IPPROTO_TCP:
00308       if (Address->Address[0].Address[0].sin_port)
00309       {
00310           /* The client specified an explicit port so we force a bind to this */
00311           AddrFile->Port = TCPAllocatePort(Address->Address[0].Address[0].sin_port);
00312           
00313           /* Check for bind success */
00314           if (AddrFile->Port == 0xffff)
00315           {
00316               ExFreePoolWithTag(AddrFile, ADDR_FILE_TAG);
00317               return STATUS_ADDRESS_ALREADY_EXISTS;
00318           }
00319           
00320           /* Sanity check */
00321           ASSERT(Address->Address[0].Address[0].sin_port == AddrFile->Port);
00322       }
00323       else if (!AddrIsUnspecified(&AddrFile->Address))
00324       {
00325           /* The client is trying to bind to a local address so allocate a port now too */
00326           AddrFile->Port = TCPAllocatePort(0);
00327           
00328           /* Check for bind success */
00329           if (AddrFile->Port == 0xffff)
00330           {
00331               ExFreePoolWithTag(AddrFile, ADDR_FILE_TAG);
00332               return STATUS_ADDRESS_ALREADY_EXISTS;
00333           }
00334       }
00335       else
00336       {
00337           /* The client wants an unspecified port with an unspecified address so we wait to see what the TCP library gives us */
00338           AddrFile->Port = 0;
00339       }
00340 
00341       AddEntity(CO_TL_ENTITY, AddrFile, CO_TL_TCP);
00342 
00343       AddrFile->Send = NULL; /* TCPSendData */
00344       break;
00345 
00346   case IPPROTO_UDP:
00347       TI_DbgPrint(MID_TRACE,("Allocating udp port\n"));
00348       AddrFile->Port =
00349       UDPAllocatePort(Address->Address[0].Address[0].sin_port);
00350 
00351       if ((Address->Address[0].Address[0].sin_port &&
00352            AddrFile->Port != Address->Address[0].Address[0].sin_port) ||
00353            AddrFile->Port == 0xffff)
00354       {
00355           ExFreePoolWithTag(AddrFile, ADDR_FILE_TAG);
00356           return STATUS_ADDRESS_ALREADY_EXISTS;
00357       }
00358 
00359       TI_DbgPrint(MID_TRACE,("Setting port %d (wanted %d)\n",
00360                              AddrFile->Port,
00361                              Address->Address[0].Address[0].sin_port));
00362 
00363       AddEntity(CL_TL_ENTITY, AddrFile, CL_TL_UDP);
00364 
00365       AddrFile->Send = UDPSendDatagram;
00366       break;
00367 
00368   case IPPROTO_ICMP:
00369     AddrFile->Port = 0;
00370     AddrFile->Send = ICMPSendDatagram;
00371 
00372     /* FIXME: Verify this */
00373     AddEntity(ER_ENTITY, AddrFile, ER_ICMP);
00374     break;
00375 
00376   default:
00377     /* Use raw IP for all other protocols */
00378     AddrFile->Port = 0;
00379     AddrFile->Send = RawIPSendDatagram;
00380 
00381     /* FIXME: Verify this */
00382     AddEntity(CL_TL_ENTITY, AddrFile, 0);
00383     break;
00384   }
00385 
00386   TI_DbgPrint(MID_TRACE, ("IP protocol number for address file object is %d.\n",
00387     Protocol));
00388 
00389   TI_DbgPrint(MID_TRACE, ("Port number for address file object is %d.\n",
00390     WN2H(AddrFile->Port)));
00391 
00392   /* Set protocol */
00393   AddrFile->Protocol = Protocol;
00394 
00395   /* Initialize receive and transmit queues */
00396   InitializeListHead(&AddrFile->ReceiveQueue);
00397   InitializeListHead(&AddrFile->TransmitQueue);
00398 
00399   /* Initialize spin lock that protects the address file object */
00400   KeInitializeSpinLock(&AddrFile->Lock);
00401 
00402   /* Return address file object */
00403   Request->Handle.AddressHandle = AddrFile;
00404 
00405   /* Add address file to global list */
00406   ExInterlockedInsertTailList(
00407     &AddressFileListHead,
00408     &AddrFile->ListEntry,
00409     &AddressFileListLock);
00410 
00411   TI_DbgPrint(MAX_TRACE, ("Leaving.\n"));
00412 
00413   return STATUS_SUCCESS;
00414 }
00415 
00416 
00417 /*
00418  * FUNCTION: Closes an address file object
00419  * ARGUMENTS:
00420  *     Request = Pointer to TDI request structure for this request
00421  * RETURNS:
00422  *     Status of operation
00423  */
00424 NTSTATUS FileCloseAddress(
00425   PTDI_REQUEST Request)
00426 {
00427   PADDRESS_FILE AddrFile = Request->Handle.AddressHandle;
00428   KIRQL OldIrql;
00429 
00430   if (!Request->Handle.AddressHandle) return STATUS_INVALID_PARAMETER;
00431 
00432   LockObject(AddrFile, &OldIrql);
00433 
00434   /* We have to close this listener because we started it */
00435   if( AddrFile->Listener )
00436   {
00437       TCPClose( AddrFile->Listener );
00438   }
00439 
00440   UnlockObject(AddrFile, OldIrql);
00441 
00442   DereferenceObject(AddrFile);
00443 
00444   TI_DbgPrint(MAX_TRACE, ("Leaving.\n"));
00445 
00446   return STATUS_SUCCESS;
00447 }
00448 
00449 
00450 /*
00451  * FUNCTION: Opens a connection file object
00452  * ARGUMENTS:
00453  *     Request       = Pointer to TDI request structure for this request
00454  *     ClientContext = Pointer to client context information
00455  * RETURNS:
00456  *     Status of operation
00457  */
00458 NTSTATUS FileOpenConnection(
00459   PTDI_REQUEST Request,
00460   PVOID ClientContext)
00461 {
00462   NTSTATUS Status;
00463   PCONNECTION_ENDPOINT Connection;
00464 
00465   TI_DbgPrint(MID_TRACE, ("Called.\n"));
00466 
00467   Connection = TCPAllocateConnectionEndpoint( ClientContext );
00468 
00469   if( !Connection ) return STATUS_NO_MEMORY;
00470 
00471   Status = TCPSocket( Connection, AF_INET, SOCK_STREAM, IPPROTO_TCP );
00472 
00473   if( !NT_SUCCESS(Status) ) {
00474       DereferenceObject( Connection );
00475       return Status;
00476   }
00477 
00478   /* Return connection endpoint file object */
00479   Request->Handle.ConnectionContext = Connection;
00480 
00481   TI_DbgPrint(MAX_TRACE, ("Leaving.\n"));
00482 
00483   return STATUS_SUCCESS;
00484 }
00485 
00486 /*
00487  * FUNCTION: Closes an connection file object
00488  * ARGUMENTS:
00489  *     Request = Pointer to TDI request structure for this request
00490  * RETURNS:
00491  *     Status of operation
00492  */
00493 NTSTATUS FileCloseConnection(
00494   PTDI_REQUEST Request)
00495 {
00496   PCONNECTION_ENDPOINT Connection;
00497 
00498   TI_DbgPrint(MID_TRACE, ("Called.\n"));
00499 
00500   Connection = Request->Handle.ConnectionContext;
00501 
00502   if (!Connection) return STATUS_INVALID_PARAMETER;
00503 
00504   TCPClose( Connection );
00505 
00506   Request->Handle.ConnectionContext = NULL;
00507 
00508   TI_DbgPrint(MAX_TRACE, ("Leaving.\n"));
00509 
00510   return STATUS_SUCCESS;
00511 }
00512 
00513 /*
00514  * FUNCTION: Opens a control channel file object
00515  * ARGUMENTS:
00516  *     Request = Pointer to TDI request structure for this request
00517  * RETURNS:
00518  *     Status of operation
00519  */
00520 NTSTATUS FileOpenControlChannel(
00521     PTDI_REQUEST Request)
00522 {
00523   PCONTROL_CHANNEL ControlChannel;
00524   TI_DbgPrint(MID_TRACE, ("Called.\n"));
00525 
00526   ControlChannel = ExAllocatePoolWithTag(NonPagedPool, sizeof(*ControlChannel),
00527                                          CONTROL_CHANNEL_TAG);
00528 
00529   if (!ControlChannel) {
00530     TI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
00531     return STATUS_INSUFFICIENT_RESOURCES;
00532   }
00533 
00534   RtlZeroMemory(ControlChannel, sizeof(CONTROL_CHANNEL));
00535 
00536   /* Make sure address is a local unicast address or 0 */
00537 
00538   /* Locate address entry. If specified address is 0, a random address is chosen */
00539 
00540   /* Initialize receive and transmit queues */
00541   InitializeListHead(&ControlChannel->ListEntry);
00542 
00543   /* Initialize spin lock that protects the address file object */
00544   KeInitializeSpinLock(&ControlChannel->Lock);
00545 
00546   ControlChannel->RefCount = 1;
00547   ControlChannel->Free = ControlChannelFree;
00548 
00549   /* Return address file object */
00550   Request->Handle.ControlChannel = ControlChannel;
00551 
00552   TI_DbgPrint(MAX_TRACE, ("Leaving.\n"));
00553 
00554   return STATUS_SUCCESS;
00555 }
00556 
00557 /*
00558  * FUNCTION: Closes a control channel file object
00559  * ARGUMENTS:
00560  *     Request = Pointer to TDI request structure for this request
00561  * RETURNS:
00562  *     Status of operation
00563  */
00564 NTSTATUS FileCloseControlChannel(
00565   PTDI_REQUEST Request)
00566 {
00567   if (!Request->Handle.ControlChannel) return STATUS_INVALID_PARAMETER;
00568 
00569   DereferenceObject((PCONTROL_CHANNEL)Request->Handle.ControlChannel);
00570 
00571   Request->Handle.ControlChannel = NULL;
00572 
00573   return STATUS_SUCCESS;
00574 }
00575 
00576 /* EOF */

Generated on Fri May 25 2012 04:26:14 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.