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