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
AddEntity(ULONG EntityType,PVOID Context,ULONG Flags)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
RemoveEntityByContext(PVOID Context)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
GetContext(TDIEntityID ID)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
InfoCopyOut(PCHAR DataOut,UINT SizeOut,PNDIS_BUFFER ClientBuf,PUINT ClientBufSize)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
InfoTdiQueryEntityType(TDIEntityID ID,PNDIS_BUFFER Buffer,PUINT BufferSize)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
InfoTdiQueryListEntities(PNDIS_BUFFER Buffer,PUINT BufferSize)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
InfoTdiQueryGetATInfo(TDIEntityID ID,PIP_INTERFACE Interface,PNDIS_BUFFER Buffer,PUINT BufferSize)184 InfoTdiQueryGetATInfo(
185 TDIEntityID ID,
186 PIP_INTERFACE Interface,
187 PNDIS_BUFFER Buffer,
188 PUINT BufferSize)
189 {
190 ULONG ATInfo[2];
191 TDI_STATUS Status;
192
193 TI_DbgPrint(DEBUG_INFO, ("Called.\n"));
194
195 if (!Interface)
196 return TDI_INVALID_PARAMETER;
197
198 if (*BufferSize < sizeof(ATInfo))
199 return STATUS_BUFFER_TOO_SMALL;
200
201 /* FIXME: I have no idea what the first field should contain... */
202 ATInfo[0] = 0;
203 ATInfo[1] = Interface->Index;
204
205 Status = InfoCopyOut((PCHAR)ATInfo,
206 sizeof(ATInfo),
207 Buffer,
208 BufferSize);
209
210 TI_DbgPrint(DEBUG_INFO, ("Returning %08x\n", Status));
211
212 return Status;
213 }
214
InfoTdiQueryInformationEx(PTDI_REQUEST Request,TDIObjectID * ID,PNDIS_BUFFER Buffer,PUINT BufferSize,PVOID Context)215 TDI_STATUS InfoTdiQueryInformationEx(
216 PTDI_REQUEST Request,
217 TDIObjectID *ID,
218 PNDIS_BUFFER Buffer,
219 PUINT BufferSize,
220 PVOID Context)
221 /*
222 * FUNCTION: Returns extended information
223 * ARGUMENTS:
224 * Request = Pointer to TDI request structure for the request
225 * ID = TDI object ID
226 * Buffer = Pointer to buffer with data to use
227 * BufferSize = Pointer to buffer with size of Buffer. On return
228 * this is filled with number of bytes returned
229 * Context = Pointer to context buffer
230 * RETURNS:
231 * Status of operation
232 */
233 {
234 PVOID EntityListContext;
235
236 TI_DbgPrint(DEBUG_INFO,
237 ("InfoEx Req: %x %x %x!%04x:%d\n",
238 ID->toi_class,
239 ID->toi_type,
240 ID->toi_id,
241 ID->toi_entity.tei_entity,
242 ID->toi_entity.tei_instance));
243
244 switch (ID->toi_class)
245 {
246 case INFO_CLASS_GENERIC:
247 switch (ID->toi_id)
248 {
249 case ENTITY_LIST_ID:
250 if (ID->toi_type != INFO_TYPE_PROVIDER)
251 return TDI_INVALID_PARAMETER;
252
253 return InfoTdiQueryListEntities(Buffer, BufferSize);
254
255 case ENTITY_TYPE_ID:
256 if (ID->toi_type != INFO_TYPE_PROVIDER)
257 return TDI_INVALID_PARAMETER;
258
259 return InfoTdiQueryEntityType(ID->toi_entity, Buffer, BufferSize);
260
261 default:
262 return TDI_INVALID_REQUEST;
263 }
264
265 case INFO_CLASS_PROTOCOL:
266 if (ID->toi_type == INFO_TYPE_ADDRESS_OBJECT)
267 {
268 if ((EntityListContext = GetContext(ID->toi_entity)))
269 return GetAddressFileInfo(ID, EntityListContext, Buffer, BufferSize);
270 else
271 return TDI_INVALID_PARAMETER;
272 }
273
274 switch (ID->toi_id)
275 {
276 case IF_MIB_STATS_ID:
277 if (ID->toi_type != INFO_TYPE_PROVIDER)
278 return TDI_INVALID_PARAMETER;
279
280 if (ID->toi_entity.tei_entity == IF_ENTITY)
281 if ((EntityListContext = GetContext(ID->toi_entity)))
282 return InfoTdiQueryGetInterfaceMIB(ID->toi_entity, EntityListContext, Buffer, BufferSize);
283 else
284 return TDI_INVALID_PARAMETER;
285 else if (ID->toi_entity.tei_entity == CL_NL_ENTITY ||
286 ID->toi_entity.tei_entity == CO_NL_ENTITY)
287 if ((EntityListContext = GetContext(ID->toi_entity)))
288 return InfoTdiQueryGetIPSnmpInfo(ID->toi_entity, EntityListContext, Buffer, BufferSize);
289 else
290 return TDI_INVALID_PARAMETER;
291 else if (ID->toi_entity.tei_entity == AT_ENTITY)
292 if ((EntityListContext = GetContext(ID->toi_entity)))
293 return InfoTdiQueryGetATInfo(ID->toi_entity, EntityListContext, Buffer, BufferSize);
294 else
295 return TDI_INVALID_PARAMETER;
296 else
297 return TDI_INVALID_PARAMETER;
298
299 case IP_MIB_ADDRTABLE_ENTRY_ID:
300 if (ID->toi_type != INFO_TYPE_PROVIDER)
301 return TDI_INVALID_PARAMETER;
302
303 if (ID->toi_entity.tei_entity == CL_NL_ENTITY ||
304 ID->toi_entity.tei_entity == CO_NL_ENTITY)
305 return InfoTdiQueryGetAddrTable(ID->toi_entity, Buffer, BufferSize);
306 else if (ID->toi_entity.tei_entity == CO_TL_ENTITY)
307 if ((EntityListContext = GetContext(ID->toi_entity)))
308 return InfoTdiQueryGetConnectionTcpTable(EntityListContext, Buffer, BufferSize, TcpUdpClassOwnerPid);
309 else
310 return TDI_INVALID_PARAMETER;
311 else if (ID->toi_entity.tei_entity == CL_TL_ENTITY)
312 if ((EntityListContext = GetContext(ID->toi_entity)))
313 return InfoTdiQueryGetConnectionUdpTable(EntityListContext, Buffer, BufferSize, TcpUdpClassOwnerPid);
314 else
315 return TDI_INVALID_PARAMETER;
316 else
317 return TDI_INVALID_PARAMETER;
318
319 case IP_MIB_ARPTABLE_ENTRY_ID:
320 if (ID->toi_type != INFO_TYPE_PROVIDER)
321 return TDI_INVALID_PARAMETER;
322
323 if (ID->toi_entity.tei_entity == AT_ENTITY)
324 if ((EntityListContext = GetContext(ID->toi_entity)))
325 return InfoTdiQueryGetArptableMIB(ID->toi_entity, EntityListContext,
326 Buffer, BufferSize);
327 else
328 return TDI_INVALID_PARAMETER;
329 else if (ID->toi_entity.tei_entity == CO_NL_ENTITY ||
330 ID->toi_entity.tei_entity == CL_NL_ENTITY)
331 if ((EntityListContext = GetContext(ID->toi_entity)))
332 return InfoTdiQueryGetRouteTable(EntityListContext, Buffer, BufferSize);
333 else
334 return TDI_INVALID_PARAMETER;
335 else if (ID->toi_entity.tei_entity == CO_TL_ENTITY)
336 if ((EntityListContext = GetContext(ID->toi_entity)))
337 return InfoTdiQueryGetConnectionTcpTable(EntityListContext, Buffer, BufferSize, TcpUdpClassBasic);
338 else
339 return TDI_INVALID_PARAMETER;
340 else if (ID->toi_entity.tei_entity == CL_TL_ENTITY)
341 if ((EntityListContext = GetContext(ID->toi_entity)))
342 return InfoTdiQueryGetConnectionUdpTable(EntityListContext, Buffer, BufferSize, TcpUdpClassBasic);
343 else
344 return TDI_INVALID_PARAMETER;
345 else
346 return TDI_INVALID_PARAMETER;
347
348 case IP_SPECIFIC_MODULE_ENTRY_ID:
349 if (ID->toi_type != INFO_TYPE_PROVIDER)
350 return TDI_INVALID_PARAMETER;
351
352 if (ID->toi_entity.tei_entity == CO_TL_ENTITY)
353 if ((EntityListContext = GetContext(ID->toi_entity)))
354 return InfoTdiQueryGetConnectionTcpTable(EntityListContext, Buffer, BufferSize, TcpUdpClassOwner);
355 else
356 return TDI_INVALID_PARAMETER;
357 else if (ID->toi_entity.tei_entity == CL_TL_ENTITY)
358 if ((EntityListContext = GetContext(ID->toi_entity)))
359 return InfoTdiQueryGetConnectionUdpTable(EntityListContext, Buffer, BufferSize, TcpUdpClassOwner);
360 else
361 return TDI_INVALID_PARAMETER;
362 else
363 return TDI_INVALID_PARAMETER;
364
365 #if 0
366 case IP_INTFC_INFO_ID:
367 if (ID->toi_type != INFO_TYPE_PROVIDER)
368 return TDI_INVALID_PARAMETER;
369
370 return InfoTdiQueryGetIFInfo(Context, Buffer, BufferSize);
371 #endif
372
373 default:
374 return TDI_INVALID_REQUEST;
375 }
376
377 default:
378 return TDI_INVALID_REQUEST;
379 }
380 }
381
InfoTdiSetInformationEx(PTDI_REQUEST Request,TDIObjectID * ID,PVOID Buffer,UINT BufferSize)382 TDI_STATUS InfoTdiSetInformationEx
383 (PTDI_REQUEST Request,
384 TDIObjectID *ID,
385 PVOID Buffer,
386 UINT BufferSize)
387 /*
388 * FUNCTION: Sets extended information
389 * ARGUMENTS:
390 * Request = Pointer to TDI request structure for the request
391 * ID = Pointer to TDI object ID
392 * Buffer = Pointer to buffer with data to use
393 * BufferSize = Size of Buffer
394 * RETURNS:
395 * Status of operation
396 */
397 {
398 PVOID EntityListContext;
399
400 switch (ID->toi_class)
401 {
402 case INFO_CLASS_PROTOCOL:
403 {
404 switch (ID->toi_type)
405 {
406 case INFO_TYPE_ADDRESS_OBJECT:
407 {
408 if ((EntityListContext = GetContext(ID->toi_entity)))
409 return SetAddressFileInfo(ID, EntityListContext, Buffer, BufferSize);
410 else
411 return TDI_INVALID_PARAMETER;
412 }
413 case INFO_TYPE_CONNECTION:
414 {
415 PADDRESS_FILE AddressFile = GetContext(ID->toi_entity);
416 if (AddressFile == NULL)
417 return TDI_INVALID_PARAMETER;
418 return SetConnectionInfo(ID, AddressFile->Connection, Buffer, BufferSize);
419 }
420 case INFO_TYPE_PROVIDER:
421 {
422 switch (ID->toi_id)
423 {
424 case IP_MIB_ARPTABLE_ENTRY_ID:
425 if (ID->toi_type != INFO_TYPE_PROVIDER)
426 return TDI_INVALID_PARAMETER;
427
428 if (ID->toi_entity.tei_entity == AT_ENTITY)
429 if ((EntityListContext = GetContext(ID->toi_entity)))
430 return InfoTdiSetArptableMIB(EntityListContext, Buffer,
431 BufferSize);
432 else
433 return TDI_INVALID_PARAMETER;
434 else if (ID->toi_entity.tei_entity == CL_NL_ENTITY
435 || ID->toi_entity.tei_entity == CO_NL_ENTITY)
436 if ((EntityListContext = GetContext(ID->toi_entity)))
437 return InfoTdiSetRoute(EntityListContext, Buffer, BufferSize);
438 else
439 return TDI_INVALID_PARAMETER;
440 else
441 return TDI_INVALID_PARAMETER;
442
443 default:
444 return TDI_INVALID_REQUEST;
445 }
446 }
447 default:
448 DbgPrint("TCPIP: IOCTL_TCP_SET_INFORMATION_EX - Unrecognized information type for INFO_CLASS_PROTOCOL: %#x.\n", ID->toi_type);
449 return TDI_INVALID_PARAMETER;
450 }
451 break;
452 }
453 default:
454 DbgPrint("TCPIP: IOCTL_TCP_SET_INFORMATION_EX - Unrecognized information class %#x.\n", ID->toi_class);
455 return TDI_INVALID_REQUEST;
456 }
457 }
458