3dbe574a634e19f556f104afba790390f222f3ff
[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
289 return TDI_INVALID_PARAMETER;
290
291 #if 0
292 case IP_INTFC_INFO_ID:
293 if (ID->toi_type != INFO_TYPE_PROVIDER)
294 return TDI_INVALID_PARAMETER;
295
296 return InfoTdiQueryGetIFInfo(Context, Buffer, BufferSize);
297 #endif
298
299 default:
300 return TDI_INVALID_REQUEST;
301 }
302
303 default:
304 return TDI_INVALID_REQUEST;
305 }
306 }
307
308 TDI_STATUS InfoTdiSetInformationEx
309 (PTDI_REQUEST Request,
310 TDIObjectID *ID,
311 PVOID Buffer,
312 UINT BufferSize)
313 /*
314 * FUNCTION: Sets extended information
315 * ARGUMENTS:
316 * Request = Pointer to TDI request structure for the request
317 * ID = Pointer to TDI object ID
318 * Buffer = Pointer to buffer with data to use
319 * BufferSize = Size of Buffer
320 * RETURNS:
321 * Status of operation
322 */
323 {
324 PVOID EntityListContext;
325
326 switch (ID->toi_class)
327 {
328 case INFO_CLASS_PROTOCOL:
329 {
330 switch (ID->toi_type)
331 {
332 case INFO_TYPE_ADDRESS_OBJECT:
333 {
334 if ((EntityListContext = GetContext(ID->toi_entity)))
335 return SetAddressFileInfo(ID, EntityListContext, Buffer, BufferSize);
336 else
337 return TDI_INVALID_PARAMETER;
338 }
339 case INFO_TYPE_CONNECTION:
340 {
341 PADDRESS_FILE AddressFile = GetContext(ID->toi_entity);
342 if (AddressFile == NULL)
343 return TDI_INVALID_PARAMETER;
344 return SetConnectionInfo(ID, AddressFile->Connection, Buffer, BufferSize);
345 }
346 case INFO_TYPE_PROVIDER:
347 {
348 switch (ID->toi_id)
349 {
350 case IP_MIB_ARPTABLE_ENTRY_ID:
351 if (ID->toi_type != INFO_TYPE_PROVIDER)
352 return TDI_INVALID_PARAMETER;
353
354 if (ID->toi_entity.tei_entity == AT_ENTITY)
355 if ((EntityListContext = GetContext(ID->toi_entity)))
356 return InfoTdiSetArptableMIB(EntityListContext, Buffer,
357 BufferSize);
358 else
359 return TDI_INVALID_PARAMETER;
360 else if (ID->toi_entity.tei_entity == CL_NL_ENTITY
361 || ID->toi_entity.tei_entity == CO_NL_ENTITY)
362 if ((EntityListContext = GetContext(ID->toi_entity)))
363 return InfoTdiSetRoute(EntityListContext, Buffer, BufferSize);
364 else
365 return TDI_INVALID_PARAMETER;
366 else
367 return TDI_INVALID_PARAMETER;
368
369 default:
370 return TDI_INVALID_REQUEST;
371 }
372 }
373 default:
374 DbgPrint("TCPIP: IOCTL_TCP_SET_INFORMATION_EX - Unrecognized information type for INFO_CLASS_PROTOCOL: %#x.\n", ID->toi_type);
375 return TDI_INVALID_PARAMETER;
376 }
377 break;
378 }
379 default:
380 DbgPrint("TCPIP: IOCTL_TCP_SET_INFORMATION_EX - Unrecognized information class %#x.\n", ID->toi_class);
381 return TDI_INVALID_REQUEST;
382 }
383 }