[REACTOS]
[reactos.git] / reactos / 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 if (ID->toi_type == INFO_TYPE_ADDRESS_OBJECT)
330 {
331 if ((EntityListContext = GetContext(ID->toi_entity)))
332 return SetAddressFileInfo(ID, EntityListContext, Buffer, BufferSize);
333 else
334 return TDI_INVALID_PARAMETER;
335 }
336
337 switch (ID->toi_id)
338 {
339 case IP_MIB_ARPTABLE_ENTRY_ID:
340 if (ID->toi_type != INFO_TYPE_PROVIDER)
341 return TDI_INVALID_PARAMETER;
342
343 if (ID->toi_entity.tei_entity == AT_ENTITY)
344 if ((EntityListContext = GetContext(ID->toi_entity)))
345 return InfoTdiSetArptableMIB(EntityListContext,
346 Buffer, BufferSize);
347 else
348 return TDI_INVALID_PARAMETER;
349 else if (ID->toi_entity.tei_entity == CL_NL_ENTITY ||
350 ID->toi_entity.tei_entity == CO_NL_ENTITY)
351 if ((EntityListContext = GetContext(ID->toi_entity)))
352 return InfoTdiSetRoute(EntityListContext, Buffer, BufferSize);
353 else
354 return TDI_INVALID_PARAMETER;
355 else
356 return TDI_INVALID_PARAMETER;
357
358 default:
359 return TDI_INVALID_REQUEST;
360 }
361
362 default:
363 return TDI_INVALID_REQUEST;
364 }
365 }