Added networking code from Casper Hornstrup
[reactos.git] / reactos / 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 */