1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS TCP/IP protocol driver 4 * FILE: transport/tcp/accept.c 5 * PURPOSE: Transmission Control Protocol Listen/Accept code 6 * PROGRAMMERS: Art Yerkes (arty@users.sf.net) 7 * REVISIONS: 8 * arty 12/21/2004 Created 9 */ 10 11 #include "precomp.h" 12 13 #include <lwip_glue/lwip_glue.h> 14 15 extern NPAGED_LOOKASIDE_LIST TdiBucketLookasideList; 16 17 NTSTATUS TCPCheckPeerForAccept(PVOID Context, 18 PTDI_REQUEST_KERNEL Request) 19 { 20 struct tcp_pcb *newpcb = (struct tcp_pcb*)Context; 21 NTSTATUS Status; 22 PTDI_CONNECTION_INFORMATION WhoIsConnecting; 23 PTA_IP_ADDRESS RemoteAddress; 24 ip_addr_t ipaddr; 25 26 if (Request->RequestFlags & TDI_QUERY_ACCEPT) 27 DbgPrint("TDI_QUERY_ACCEPT NOT SUPPORTED!!!\n"); 28 29 WhoIsConnecting = (PTDI_CONNECTION_INFORMATION)Request->ReturnConnectionInformation; 30 RemoteAddress = (PTA_IP_ADDRESS)WhoIsConnecting->RemoteAddress; 31 32 RemoteAddress->TAAddressCount = 1; 33 RemoteAddress->Address[0].AddressLength = TDI_ADDRESS_LENGTH_IP; 34 RemoteAddress->Address[0].AddressType = TDI_ADDRESS_TYPE_IP; 35 36 Status = TCPTranslateError(LibTCPGetPeerName(newpcb, 37 &ipaddr, 38 &RemoteAddress->Address[0].Address[0].sin_port)); 39 40 RemoteAddress->Address[0].Address[0].in_addr = ipaddr.addr; 41 42 return Status; 43 } 44 45 /* This listen is on a socket we keep as internal. That socket has the same 46 * lifetime as the address file */ 47 NTSTATUS TCPListen(PCONNECTION_ENDPOINT Connection, UINT Backlog) 48 { 49 NTSTATUS Status = STATUS_SUCCESS; 50 ip_addr_t AddressToBind; 51 TA_IP_ADDRESS LocalAddress; 52 53 ASSERT(Connection); 54 55 LockObject(Connection); 56 57 ASSERT_KM_POINTER(Connection->AddressFile); 58 59 TI_DbgPrint(DEBUG_TCP,("[IP, TCPListen] Called\n")); 60 61 TI_DbgPrint(DEBUG_TCP, ("Connection->SocketContext %x\n", 62 Connection->SocketContext)); 63 64 AddressToBind.addr = Connection->AddressFile->Address.Address.IPv4Address; 65 66 Status = TCPTranslateError(LibTCPBind(Connection, 67 &AddressToBind, 68 Connection->AddressFile->Port)); 69 70 if (NT_SUCCESS(Status)) 71 { 72 /* Check if we had an unspecified port */ 73 if (!Connection->AddressFile->Port) 74 { 75 /* We did, so we need to copy back the port */ 76 Status = TCPGetSockAddress(Connection, (PTRANSPORT_ADDRESS)&LocalAddress, FALSE); 77 if (NT_SUCCESS(Status)) 78 { 79 /* Allocate the port in the port bitmap */ 80 UINT AllocatedPort = TCPAllocatePort(LocalAddress.Address[0].Address[0].sin_port); 81 /* This should never fail unless all ports are in use */ 82 if (AllocatedPort == (UINT) -1) 83 { 84 DbgPrint("ERR: No more ports available.\n"); 85 UnlockObject(Connection); 86 return STATUS_TOO_MANY_ADDRESSES; 87 } 88 Connection->AddressFile->Port = AllocatedPort; 89 } 90 } 91 } 92 93 if (NT_SUCCESS(Status)) 94 { 95 Connection->SocketContext = LibTCPListen(Connection, Backlog); 96 if (!Connection->SocketContext) 97 Status = STATUS_UNSUCCESSFUL; 98 } 99 100 UnlockObject(Connection); 101 102 TI_DbgPrint(DEBUG_TCP,("[IP, TCPListen] Leaving. Status = %x\n", Status)); 103 104 return Status; 105 } 106 107 BOOLEAN TCPAbortListenForSocket 108 ( PCONNECTION_ENDPOINT Listener, 109 PCONNECTION_ENDPOINT Connection) 110 { 111 PLIST_ENTRY ListEntry; 112 PTDI_BUCKET Bucket; 113 BOOLEAN Found = FALSE; 114 115 LockObject(Listener); 116 117 ListEntry = Listener->ListenRequest.Flink; 118 while (ListEntry != &Listener->ListenRequest) 119 { 120 Bucket = CONTAINING_RECORD(ListEntry, TDI_BUCKET, Entry); 121 122 if (Bucket->AssociatedEndpoint == Connection) 123 { 124 DereferenceObject(Bucket->AssociatedEndpoint); 125 RemoveEntryList( &Bucket->Entry ); 126 ExFreeToNPagedLookasideList(&TdiBucketLookasideList, Bucket); 127 Found = TRUE; 128 break; 129 } 130 131 ListEntry = ListEntry->Flink; 132 } 133 134 UnlockObject(Listener); 135 136 return Found; 137 } 138 139 NTSTATUS TCPAccept ( PTDI_REQUEST Request, 140 PCONNECTION_ENDPOINT Listener, 141 PCONNECTION_ENDPOINT Connection, 142 PTCP_COMPLETION_ROUTINE Complete, 143 PVOID Context ) 144 { 145 NTSTATUS Status; 146 PTDI_BUCKET Bucket; 147 148 LockObject(Listener); 149 150 Bucket = ExAllocateFromNPagedLookasideList(&TdiBucketLookasideList); 151 152 if (Bucket) 153 { 154 Bucket->AssociatedEndpoint = Connection; 155 ReferenceObject(Bucket->AssociatedEndpoint); 156 157 Bucket->Request.RequestNotifyObject = Complete; 158 Bucket->Request.RequestContext = Context; 159 InsertTailList( &Listener->ListenRequest, &Bucket->Entry ); 160 Status = STATUS_PENDING; 161 } 162 else 163 Status = STATUS_NO_MEMORY; 164 165 UnlockObject(Listener); 166 167 return Status; 168 } 169