[TCPIP] Implement returning TCP connections
[reactos.git] / drivers / network / tcpip / tcpip / info.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS TCP/IP protocol driver
4 * FILE: tcpip/info.c
5 * PURPOSE: TDI query and set information routines
6 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
7 * REVISIONS:
8 * CSH 01/08-2000 Created
9 */
10
11 #include "precomp.h"
12
13 #include <debug.h>
14
15 VOID AddEntity(ULONG EntityType, PVOID Context, ULONG Flags)
16 {
17 KIRQL OldIrql;
18 ULONG i, Instance = 0;
19 BOOLEAN ChoseIndex = FALSE;
20
21 TcpipAcquireSpinLock(&EntityListLock, &OldIrql);
22
23 while (!ChoseIndex)
24 {
25 ChoseIndex = TRUE;
26 for (i = 0; i < EntityCount; i++)
27 {
28 if (EntityList[i].tei_entity == EntityType &&
29 EntityList[i].tei_instance == Instance)
30 {
31 Instance++;
32 ChoseIndex = FALSE;
33 }
34 }
35 }
36
37 EntityList[EntityCount].tei_entity = EntityType;
38 EntityList[EntityCount].tei_instance = Instance;
39 EntityList[EntityCount].context = Context;
40 EntityList[EntityCount].flags = Flags;
41 EntityCount++;
42
43 TcpipReleaseSpinLock(&EntityListLock, OldIrql);
44 }
45
46 VOID RemoveEntityByContext(PVOID Context)
47 {
48 ULONG i;
49 KIRQL OldIrql;
50
51 TcpipAcquireSpinLock(&EntityListLock, &OldIrql);
52
53 for (i = 0; i < EntityCount; i++) {
54 if( EntityList[i].context == Context ) {
55 if( i != EntityCount - 1 ) {
56 memcpy( &EntityList[i],
57 &EntityList[--EntityCount],
58 sizeof(EntityList[i]) );
59 } else {
60 EntityCount--;
61 }
62 }
63 }
64
65 TcpipReleaseSpinLock(&EntityListLock, OldIrql);
66 }
67
68 PVOID GetContext(TDIEntityID ID)
69 {
70 UINT i;
71 KIRQL OldIrql;
72 PVOID Context;
73
74 TcpipAcquireSpinLock(&EntityListLock, &OldIrql);
75
76 for (i = 0; i < EntityCount; i++)
77 {
78 if (EntityList[i].tei_entity == ID.tei_entity &&
79 EntityList[i].tei_instance == ID.tei_instance)
80 break;
81 }
82
83 if (i == EntityCount)
84 {
85 TcpipReleaseSpinLock(&EntityListLock, OldIrql);
86 DbgPrint("WARNING: Unable to get context for %d %d\n", ID.tei_entity, ID.tei_instance);
87 return NULL;
88 }
89
90 Context = EntityList[i].context;
91
92 TcpipReleaseSpinLock(&EntityListLock, OldIrql);
93
94 return Context;
95 }
96
97 TDI_STATUS InfoCopyOut( PCHAR DataOut, UINT SizeOut,
98 PNDIS_BUFFER ClientBuf, PUINT ClientBufSize ) {
99 UINT RememberedCBSize = *ClientBufSize;
100 *ClientBufSize = SizeOut;
101
102 /* The driver returns success even when it couldn't fit every available
103 * byte. */
104 if( RememberedCBSize < SizeOut || !ClientBuf )
105 return TDI_SUCCESS;
106 else {
107 CopyBufferToBufferChain( ClientBuf, 0, (PCHAR)DataOut, SizeOut );
108 return TDI_SUCCESS;
109 }
110 }
111
112 TDI_STATUS InfoTdiQueryEntityType(TDIEntityID ID,
113 PNDIS_BUFFER Buffer,
114 PUINT BufferSize)
115 {
116 KIRQL OldIrql;
117 UINT i, Flags = 0;
118
119 TcpipAcquireSpinLock(&EntityListLock, &OldIrql);
120
121 for (i = 0; i < EntityCount; i++)
122 {
123 if (EntityList[i].tei_entity == ID.tei_entity &&
124 EntityList[i].tei_instance == ID.tei_instance)
125 break;
126 }
127
128 if (i == EntityCount)
129 {
130 TcpipReleaseSpinLock(&EntityListLock, OldIrql);
131 return TDI_INVALID_PARAMETER;
132 }
133
134 Flags = EntityList[i].flags;
135
136 InfoCopyOut((PCHAR)&Flags,
137 sizeof(ULONG),
138 Buffer,
139 BufferSize);
140
141 TcpipReleaseSpinLock(&EntityListLock, OldIrql);
142
143 return TDI_SUCCESS;
144 }
145
146 TDI_STATUS InfoTdiQueryListEntities(PNDIS_BUFFER Buffer,
147 PUINT BufferSize)
148 {
149 UINT Count, Size, BufSize = *BufferSize;
150 KIRQL OldIrql;
151
152 TI_DbgPrint(DEBUG_INFO,("About to copy %d TDIEntityIDs to user\n",
153 EntityCount));
154
155 TcpipAcquireSpinLock(&EntityListLock, &OldIrql);
156
157 Size = EntityCount * sizeof(TDIEntityID);
158 *BufferSize = Size;
159
160 TI_DbgPrint(DEBUG_INFO,("BufSize: %d, NeededSize: %d\n", BufSize, Size));
161
162 if (BufSize < Size || !Buffer)
163 {
164 TcpipReleaseSpinLock( &EntityListLock, OldIrql );
165 /* The buffer is too small to contain requested data, but we return
166 * success anyway, as we did everything we wanted. */
167 return TDI_SUCCESS;
168 }
169
170 /* Return entity list -- Copy only the TDIEntityID parts. */
171 for( Count = 0; Count < EntityCount; Count++ ) {
172 CopyBufferToBufferChain(Buffer,
173 Count * sizeof(TDIEntityID),
174 (PCHAR)&EntityList[Count],
175 sizeof(TDIEntityID));
176 }
177
178 TcpipReleaseSpinLock(&EntityListLock, OldIrql);
179
180 return TDI_SUCCESS;
181 }
182
183 TDI_STATUS InfoTdiQueryInformationEx(
184 PTDI_REQUEST Request,
185 TDIObjectID *ID,
186 PNDIS_BUFFER Buffer,
187 PUINT BufferSize,
188 PVOID Context)
189 /*
190 * FUNCTION: Returns extended information
191 * ARGUMENTS:
192 * Request = Pointer to TDI request structure for the request
193 * ID = TDI object ID
194 * Buffer = Pointer to buffer with data to use
195 * BufferSize = Pointer to buffer with size of Buffer. On return
196 * this is filled with number of bytes returned
197 * Context = Pointer to context buffer
198 * RETURNS:
199 * Status of operation
200 */
201 {
202 PVOID EntityListContext;
203
204 TI_DbgPrint(DEBUG_INFO,
205 ("InfoEx Req: %x %x %x!%04x:%d\n",
206 ID->toi_class,
207 ID->toi_type,
208 ID->toi_id,
209 ID->toi_entity.tei_entity,
210 ID->toi_entity.tei_instance));
211
212 switch (ID->toi_class)
213 {
214 case INFO_CLASS_GENERIC:
215 switch (ID->toi_id)
216 {
217 case ENTITY_LIST_ID:
218 if (ID->toi_type != INFO_TYPE_PROVIDER)
219 return TDI_INVALID_PARAMETER;
220
221 return InfoTdiQueryListEntities(Buffer, BufferSize);
222
223 case ENTITY_TYPE_ID:
224 if (ID->toi_type != INFO_TYPE_PROVIDER)
225 return TDI_INVALID_PARAMETER;
226
227 return InfoTdiQueryEntityType(ID->toi_entity, Buffer, BufferSize);
228
229 default:
230 return TDI_INVALID_REQUEST;
231 }
232
233 case INFO_CLASS_PROTOCOL:
234 if (ID->toi_type == INFO_TYPE_ADDRESS_OBJECT)
235 {
236 if ((EntityListContext = GetContext(ID->toi_entity)))
237 return GetAddressFileInfo(ID, EntityListContext, Buffer, BufferSize);
238 else
239 return TDI_INVALID_PARAMETER;
240 }
241
242 switch (ID->toi_id)
243 {
244 case IF_MIB_STATS_ID:
245 if (ID->toi_type != INFO_TYPE_PROVIDER)
246 return TDI_INVALID_PARAMETER;
247
248 if (ID->toi_entity.tei_entity == IF_ENTITY)
249 if ((EntityListContext = GetContext(ID->toi_entity)))
250 return InfoTdiQueryGetInterfaceMIB(ID->toi_entity, EntityListContext, Buffer, BufferSize);
251 else
252 return TDI_INVALID_PARAMETER;
253 else if (ID->toi_entity.tei_entity == CL_NL_ENTITY ||
254 ID->toi_entity.tei_entity == CO_NL_ENTITY)
255 if ((EntityListContext = GetContext(ID->toi_entity)))
256 return InfoTdiQueryGetIPSnmpInfo(ID->toi_entity, EntityListContext, Buffer, BufferSize);
257 else
258 return TDI_INVALID_PARAMETER;
259 else
260 return TDI_INVALID_PARAMETER;
261
262 case IP_MIB_ADDRTABLE_ENTRY_ID:
263 if (ID->toi_entity.tei_entity != CL_NL_ENTITY &&
264 ID->toi_entity.tei_entity != CO_NL_ENTITY)
265 return TDI_INVALID_PARAMETER;
266
267 if (ID->toi_type != INFO_TYPE_PROVIDER)
268 return TDI_INVALID_PARAMETER;
269
270 return InfoTdiQueryGetAddrTable(ID->toi_entity, Buffer, BufferSize);
271
272 case IP_MIB_ARPTABLE_ENTRY_ID:
273 if (ID->toi_type != INFO_TYPE_PROVIDER)
274 return TDI_INVALID_PARAMETER;
275
276 if (ID->toi_entity.tei_entity == AT_ENTITY)
277 if ((EntityListContext = GetContext(ID->toi_entity)))
278 return InfoTdiQueryGetArptableMIB(ID->toi_entity, EntityListContext,
279 Buffer, BufferSize);
280 else
281 return TDI_INVALID_PARAMETER;
282 else if (ID->toi_entity.tei_entity == CO_NL_ENTITY ||
283 ID->toi_entity.tei_entity == CL_NL_ENTITY)
284 if ((EntityListContext = GetContext(ID->toi_entity)))
285 return InfoTdiQueryGetRouteTable(EntityListContext, Buffer, BufferSize);
286 else
287 return TDI_INVALID_PARAMETER;
288 else if (ID->toi_entity.tei_entity == CO_TL_ENTITY)
289 if ((EntityListContext = GetContext(ID->toi_entity)))
290 return InfoTdiQueryGetConnectionTcpTable(EntityListContext, Buffer, BufferSize);
291 else
292 return TDI_INVALID_PARAMETER;
293 else
294 return TDI_INVALID_PARAMETER;
295
296 #if 0
297 case IP_INTFC_INFO_ID:
298 if (ID->toi_type != INFO_TYPE_PROVIDER)
299 return TDI_INVALID_PARAMETER;
300
301 return InfoTdiQueryGetIFInfo(Context, Buffer, BufferSize);
302 #endif
303
304 default:
305 return TDI_INVALID_REQUEST;
306 }
307
308 default:
309 return TDI_INVALID_REQUEST;
310 }
311 }
312
313 TDI_STATUS InfoTdiSetInformationEx
314 (PTDI_REQUEST Request,
315 TDIObjectID *ID,
316 PVOID Buffer,
317 UINT BufferSize)
318 /*
319 * FUNCTION: Sets extended information
320 * ARGUMENTS:
321 * Request = Pointer to TDI request structure for the request
322 * ID = Pointer to TDI object ID
323 * Buffer = Pointer to buffer with data to use
324 * BufferSize = Size of Buffer
325 * RETURNS:
326 * Status of operation
327 */
328 {
329 PVOID EntityListContext;
330
331 switch (ID->toi_class)
332 {
333 case INFO_CLASS_PROTOCOL:
334 {
335 switch (ID->toi_type)
336 {
337 case INFO_TYPE_ADDRESS_OBJECT:
338 {
339 if ((EntityListContext = GetContext(ID->toi_entity)))
340 return SetAddressFileInfo(ID, EntityListContext, Buffer, BufferSize);
341 else
342 return TDI_INVALID_PARAMETER;
343 }
344 case INFO_TYPE_CONNECTION:
345 {
346 PADDRESS_FILE AddressFile = GetContext(ID->toi_entity);
347 if (AddressFile == NULL)
348 return TDI_INVALID_PARAMETER;
349 return SetConnectionInfo(ID, AddressFile->Connection, Buffer, BufferSize);
350 }
351 case INFO_TYPE_PROVIDER:
352 {
353 switch (ID->toi_id)
354 {
355 case IP_MIB_ARPTABLE_ENTRY_ID:
356 if (ID->toi_type != INFO_TYPE_PROVIDER)
357 return TDI_INVALID_PARAMETER;
358
359 if (ID->toi_entity.tei_entity == AT_ENTITY)
360 if ((EntityListContext = GetContext(ID->toi_entity)))
361 return InfoTdiSetArptableMIB(EntityListContext, Buffer,
362 BufferSize);
363 else
364 return TDI_INVALID_PARAMETER;
365 else if (ID->toi_entity.tei_entity == CL_NL_ENTITY
366 || ID->toi_entity.tei_entity == CO_NL_ENTITY)
367 if ((EntityListContext = GetContext(ID->toi_entity)))
368 return InfoTdiSetRoute(EntityListContext, Buffer, BufferSize);
369 else
370 return TDI_INVALID_PARAMETER;
371 else
372 return TDI_INVALID_PARAMETER;
373
374 default:
375 return TDI_INVALID_REQUEST;
376 }
377 }
378 default:
379 DbgPrint("TCPIP: IOCTL_TCP_SET_INFORMATION_EX - Unrecognized information type for INFO_CLASS_PROTOCOL: %#x.\n", ID->toi_type);
380 return TDI_INVALID_PARAMETER;
381 }
382 break;
383 }
384 default:
385 DbgPrint("TCPIP: IOCTL_TCP_SET_INFORMATION_EX - Unrecognized information class %#x.\n", ID->toi_class);
386 return TDI_INVALID_REQUEST;
387 }
388 }