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