:pserver:cvsanon@mok.lvcm.com:/CVS/ReactOS reactos
[reactos.git] / drivers / net / 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 #include <tcpip.h>
11 #include <info.h>
12 #include <routines.h>
13
14
15 TDI_STATUS IPTdiQueryInformationEx(
16     PTDI_REQUEST Request,
17     TDIObjectID *ID,
18     PNDIS_BUFFER Buffer,
19     PUINT BufferSize,
20     PVOID Context)
21 /*
22  * FUNCTION: Returns extended information about network layer
23  * ARGUMENTS:
24  *     Request    = Pointer to TDI request structure for the request
25  *     ID         = TDI object ID
26  *     Buffer     = Pointer to buffer with data to use. 
27  *     BufferSize = Pointer to buffer with size of Buffer. On return
28  *                  this is filled with number of bytes returned
29  *     Context    = Pointer to context buffer
30  * RETURNS:
31  *     Status of operation
32  */
33 {
34     PLIST_ENTRY CurrentIFEntry;
35     PLIST_ENTRY CurrentADEEntry;
36     PIP_INTERFACE CurrentIF;
37     PADDRESS_ENTRY CurrentADE;
38     IPADDR_ENTRY IpAddress;
39     IPSNMP_INFO SnmpInfo;
40     ULONG Temp;
41     UINT Count;
42     ULONG Entity;
43     KIRQL OldIrql;
44     UINT BufSize = *BufferSize;
45
46     /* Make return parameters consistent every time */
47     *BufferSize = 0;
48
49     Entity = ID->toi_entity.tei_entity;
50     if (Entity != CL_NL_ENTITY) {
51         /* We can't handle this entity */
52         return TDI_INVALID_PARAMETER;
53     }
54
55     if (ID->toi_entity.tei_instance != TL_INSTANCE)
56         /* We only support a single instance */
57         return TDI_INVALID_REQUEST;
58     if (ID->toi_class == INFO_CLASS_GENERIC) {
59         if (ID->toi_type == INFO_TYPE_PROVIDER && 
60             ID->toi_id == ENTITY_TYPE_ID) {
61
62             if (BufSize < sizeof(ULONG))
63                 return TDI_BUFFER_TOO_SMALL;
64             Temp = CL_NL_IP;
65
66             Count = CopyBufferToBufferChain(Buffer, 0, (PUCHAR)&Temp, sizeof(ULONG));
67
68             return TDI_SUCCESS;
69         }
70         return TDI_INVALID_PARAMETER;
71     }
72
73     if (ID->toi_class == INFO_CLASS_PROTOCOL) {
74         if (ID->toi_type != INFO_TYPE_PROVIDER)
75             return TDI_INVALID_PARAMETER;
76
77         switch (ID->toi_id) {
78         case IP_MIB_ADDRTABLE_ENTRY_ID:
79             Temp = 0;
80
81             KeAcquireSpinLock(&InterfaceListLock, &OldIrql);
82
83             CurrentIFEntry = InterfaceListHead.Flink;
84             while (CurrentIFEntry != &InterfaceListHead) {
85                     CurrentIF = CONTAINING_RECORD(CurrentIFEntry, IP_INTERFACE, ListEntry);
86
87                 if (Temp + sizeof(IPADDR_ENTRY) > BufSize) {
88                     KeReleaseSpinLock(&InterfaceListLock, OldIrql);
89                     return TDI_BUFFER_TOO_SMALL;
90                 }
91
92                 IpAddress.Addr      = 0;
93                 IpAddress.BcastAddr = 0;
94                 IpAddress.Mask      = 0;
95
96                 /* Locate the diffrent addresses and put them the right place */
97                 CurrentADEEntry = CurrentIF->ADEListHead.Flink;
98                 while (CurrentADEEntry != &CurrentIF->ADEListHead) {
99                         CurrentADE = CONTAINING_RECORD(CurrentADEEntry, ADDRESS_ENTRY, ListEntry);
100
101                     switch (CurrentADE->Type) {
102                     case ADE_UNICAST:
103                         IpAddress.Addr = CurrentADE->Address->Address.IPv4Address;
104                         break;
105                     case ADE_MULTICAST:
106                         IpAddress.BcastAddr = CurrentADE->Address->Address.IPv4Address;
107                         break;
108                     case ADE_ADDRMASK:
109                         IpAddress.Mask = CurrentADE->Address->Address.IPv4Address;
110                         break;
111                     default:
112                         /* Should not happen */
113                         TI_DbgPrint(MIN_TRACE, ("Unknown address entry type (0x%X)\n", CurrentADE->Type));
114                         break;
115                     }
116                     CurrentADEEntry = CurrentADEEntry->Flink;
117                 }
118                 /* Pack the address information into IPADDR_ENTRY structure */
119                 IpAddress.Index     = 0;
120                 IpAddress.ReasmSize = 0;
121                 IpAddress.Context   = 0;
122                 IpAddress.Pad       = 0;
123
124                 Count = CopyBufferToBufferChain(Buffer, Temp, (PUCHAR)&IpAddress, sizeof(IPADDR_ENTRY));
125
126                 Temp += sizeof(IPADDR_ENTRY);
127
128                 CurrentIFEntry = CurrentIFEntry->Flink;
129             }
130
131             KeReleaseSpinLock(&InterfaceListLock, OldIrql);
132
133             return TDI_SUCCESS;
134
135         case IP_MIB_STATS_ID:
136             if (BufSize < sizeof(IPSNMP_INFO))
137                 return TDI_BUFFER_TOO_SMALL;
138
139             RtlZeroMemory(&SnmpInfo, sizeof(IPSNMP_INFO));
140
141             /* Count number of addresses */
142             Count = 0;
143             KeAcquireSpinLock(&InterfaceListLock, &OldIrql);
144
145             CurrentIFEntry = InterfaceListHead.Flink;
146             while (CurrentIFEntry != &InterfaceListHead) {
147                     CurrentIF = CONTAINING_RECORD(CurrentIFEntry, IP_INTERFACE, ListEntry);
148                 Count++;
149                 CurrentIFEntry = CurrentIFEntry->Flink;
150             }
151
152             KeReleaseSpinLock(&InterfaceListLock, OldIrql);
153
154             SnmpInfo.NumAddr = Count;
155
156             Count = CopyBufferToBufferChain(Buffer, 0, (PUCHAR)&SnmpInfo, sizeof(IPSNMP_INFO));
157
158             return TDI_SUCCESS;
159
160         default:
161             /* We can't handle this ID */
162             return TDI_INVALID_PARAMETER;
163         }
164     }
165
166     return TDI_INVALID_PARAMETER;
167 }
168
169
170 TDI_STATUS InfoTdiQueryInformationEx(
171     PTDI_REQUEST Request,
172     TDIObjectID *ID,
173     PNDIS_BUFFER Buffer,
174     PUINT BufferSize,
175     PVOID Context)
176 /*
177  * FUNCTION: Returns extended information
178  * ARGUMENTS:
179  *     Request    = Pointer to TDI request structure for the request
180  *     ID         = TDI object ID
181  *     Buffer     = Pointer to buffer with data to use
182  *     BufferSize = Pointer to buffer with size of Buffer. On return
183  *                  this is filled with number of bytes returned
184  *     Context    = Pointer to context buffer
185  * RETURNS:
186  *     Status of operation
187  */
188 {
189     PLIST_ENTRY CurrentADFEntry;
190     PADDRESS_FILE CurrentADF;
191     ADDRESS_INFO Info;
192     KIRQL OldIrql;
193     UINT Entity;
194     UINT Count;
195     UINT Size;
196     ULONG Temp;
197     UINT Offset = 0;
198     UINT BufSize = *BufferSize;
199
200     /* Check wether it is a query for a list of entities */
201     Entity = ID->toi_entity.tei_entity;
202     if (Entity == GENERIC_ENTITY) {
203         if (ID->toi_class  != INFO_CLASS_GENERIC ||
204             ID->toi_type != INFO_TYPE_PROVIDER ||
205             ID->toi_id != ENTITY_LIST_ID)
206             return TDI_INVALID_PARAMETER;
207
208         *BufferSize = 0;
209
210         Size = EntityCount * sizeof(TDIEntityID);
211         if (BufSize < Size)
212             /* The buffer is too small to contain requested data */
213             return TDI_BUFFER_TOO_SMALL;
214
215         /* Return entity list */
216         Count = CopyBufferToBufferChain(Buffer, 0, (PUCHAR)EntityList, Size);
217
218         *BufferSize = Size;
219
220         return TDI_SUCCESS;
221     }
222
223     if ((Entity != CL_TL_ENTITY) && (Entity != CO_TL_ENTITY)) {
224         /* We can't handle this entity, pass it on */
225         return IPTdiQueryInformationEx(
226             Request, ID, Buffer, BufferSize, Context);
227     }
228
229     /* Make return parameters consistent every time */
230     *BufferSize = 0;
231
232     if (ID->toi_entity.tei_instance != TL_INSTANCE)
233         /* We only support a single instance */
234         return TDI_INVALID_REQUEST;
235
236     if (ID->toi_class == INFO_CLASS_GENERIC) {
237
238         if (ID->toi_type != INFO_TYPE_PROVIDER ||
239             ID->toi_id != ENTITY_TYPE_ID)
240             return TDI_INVALID_PARAMETER;
241
242         if (BufSize < sizeof(ULONG))
243             return TDI_BUFFER_TOO_SMALL;
244
245         if (Entity == CL_TL_ENTITY)
246             Temp = CL_TL_UDP;
247         else if (Entity == CO_TL_ENTITY)
248             Temp = CO_TL_TCP;
249         else
250             return TDI_INVALID_PARAMETER;
251
252         Count = CopyBufferToBufferChain(Buffer, 0, (PUCHAR)&Temp, sizeof(ULONG));
253
254         return TDI_SUCCESS;
255     }
256
257     if (ID->toi_class == INFO_CLASS_PROTOCOL) {
258
259         if (ID->toi_type != INFO_TYPE_PROVIDER)
260             return TDI_INVALID_PARAMETER;
261
262         switch (ID->toi_id) {
263         case UDP_MIB_STAT_ID:
264             if (Entity != CL_TL_ENTITY)
265                 return TDI_INVALID_PARAMETER;
266
267             if (BufSize < sizeof(UDPStats))
268                 return TDI_BUFFER_TOO_SMALL;
269
270             Count = CopyBufferToBufferChain(Buffer, 0, (PUCHAR)&UDPStats, sizeof(UDP_STATISTICS));
271
272             return TDI_SUCCESS;
273
274         case UDP_MIB_TABLE_ID:
275             if (Entity != CL_TL_ENTITY)
276                 return TDI_INVALID_PARAMETER;
277
278             Offset = 0;
279
280             KeAcquireSpinLock(&AddressFileListLock, &OldIrql);
281
282             CurrentADFEntry = AddressFileListHead.Flink;
283             while (CurrentADFEntry != &AddressFileListHead) {
284                     CurrentADF = CONTAINING_RECORD(CurrentADFEntry, ADDRESS_FILE, ListEntry);
285
286                 if (Offset + sizeof(ADDRESS_INFO) > BufSize) {
287                     KeReleaseSpinLock(&AddressFileListLock, OldIrql);
288                     *BufferSize = Offset;
289                     return TDI_BUFFER_OVERFLOW;
290                 }
291
292                 Info.LocalAddress = CurrentADF->ADE->Address->Address.IPv4Address;
293                 Info.LocalPort    = CurrentADF->Port;
294
295                 Count = CopyBufferToBufferChain(Buffer, Offset, (PUCHAR)&Info, sizeof(ADDRESS_INFO));
296
297                 Offset += Count;
298
299                 CurrentADFEntry = CurrentADFEntry->Flink;
300             }
301
302             KeReleaseSpinLock(&AddressFileListLock, OldIrql);
303
304             *BufferSize = Offset;
305
306             return STATUS_SUCCESS;
307
308         default:
309             /* We can't handle this ID */
310             return TDI_INVALID_PARAMETER;
311         }
312     }
313
314     return TDI_INVALID_PARAMETER;
315 }
316
317
318 TDI_STATUS InfoTdiSetInformationEx(
319     PTDI_REQUEST Request,
320     TDIObjectID *ID,
321     PVOID Buffer,
322     UINT BufferSize)
323 /*
324  * FUNCTION: Sets extended information
325  * ARGUMENTS:
326  *     Request    = Pointer to TDI request structure for the request
327  *     ID         = Pointer to TDI object ID
328  *     Buffer     = Pointer to buffer with data to use
329  *     BufferSize = Size of Buffer
330  * RETURNS:
331  *     Status of operation
332  */
333 {
334     /* FIXME: Set extended information */
335
336     return TDI_INVALID_REQUEST;
337 }
338
339 /* EOF */