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
TCPCheckPeerForAccept(PVOID Context,PTDI_REQUEST_KERNEL Request)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 */
TCPListen(PCONNECTION_ENDPOINT Connection,UINT Backlog)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
TCPAbortListenForSocket(PCONNECTION_ENDPOINT Listener,PCONNECTION_ENDPOINT Connection)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
TCPAccept(PTDI_REQUEST Request,PCONNECTION_ENDPOINT Listener,PCONNECTION_ENDPOINT Connection,PTCP_COMPLETION_ROUTINE Complete,PVOID Context)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