xref: /reactos/drivers/network/tcpip/tcpip/info.c (revision 1e28d4d9)
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 
AddEntity(ULONG EntityType,PVOID Context,ULONG Flags)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 
RemoveEntityByContext(PVOID Context)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 
GetContext(TDIEntityID ID)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 
InfoCopyOut(PCHAR DataOut,UINT SizeOut,PNDIS_BUFFER ClientBuf,PUINT ClientBufSize)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 
InfoTdiQueryEntityType(TDIEntityID ID,PNDIS_BUFFER Buffer,PUINT BufferSize)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 
InfoTdiQueryListEntities(PNDIS_BUFFER Buffer,PUINT BufferSize)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
InfoTdiQueryGetATInfo(TDIEntityID ID,PIP_INTERFACE Interface,PNDIS_BUFFER Buffer,PUINT BufferSize)184 InfoTdiQueryGetATInfo(
185     TDIEntityID ID,
186     PIP_INTERFACE Interface,
187     PNDIS_BUFFER Buffer,
188     PUINT BufferSize)
189 {
190     ULONG ATInfo[2];
191     TDI_STATUS Status;
192 
193     TI_DbgPrint(DEBUG_INFO, ("Called.\n"));
194 
195     if (!Interface)
196         return TDI_INVALID_PARAMETER;
197 
198     if (*BufferSize < sizeof(ATInfo))
199         return STATUS_BUFFER_TOO_SMALL;
200 
201     /* FIXME: I have no idea what the first field should contain... */
202     ATInfo[0] = 0;
203     ATInfo[1] = Interface->Index;
204 
205     Status = InfoCopyOut((PCHAR)ATInfo,
206                          sizeof(ATInfo),
207                          Buffer,
208                          BufferSize);
209 
210     TI_DbgPrint(DEBUG_INFO, ("Returning %08x\n", Status));
211 
212     return Status;
213 }
214 
InfoTdiQueryInformationEx(PTDI_REQUEST Request,TDIObjectID * ID,PNDIS_BUFFER Buffer,PUINT BufferSize,PVOID Context)215 TDI_STATUS InfoTdiQueryInformationEx(
216   PTDI_REQUEST Request,
217   TDIObjectID *ID,
218   PNDIS_BUFFER Buffer,
219   PUINT BufferSize,
220   PVOID Context)
221 /*
222  * FUNCTION: Returns extended information
223  * ARGUMENTS:
224  *   Request    = Pointer to TDI request structure for the request
225  *   ID         = TDI object ID
226  *   Buffer     = Pointer to buffer with data to use
227  *   BufferSize = Pointer to buffer with size of Buffer. On return
228  *                this is filled with number of bytes returned
229  *   Context    = Pointer to context buffer
230  * RETURNS:
231  *   Status of operation
232  */
233 {
234     PVOID EntityListContext;
235 
236     TI_DbgPrint(DEBUG_INFO,
237 		("InfoEx Req: %x %x %x!%04x:%d\n",
238 		 ID->toi_class,
239 		 ID->toi_type,
240 		 ID->toi_id,
241 		 ID->toi_entity.tei_entity,
242 		 ID->toi_entity.tei_instance));
243 
244     switch (ID->toi_class)
245     {
246         case INFO_CLASS_GENERIC:
247            switch (ID->toi_id)
248            {
249               case ENTITY_LIST_ID:
250                  if (ID->toi_type != INFO_TYPE_PROVIDER)
251                      return TDI_INVALID_PARAMETER;
252 
253                  return InfoTdiQueryListEntities(Buffer, BufferSize);
254 
255               case ENTITY_TYPE_ID:
256                  if (ID->toi_type != INFO_TYPE_PROVIDER)
257                      return TDI_INVALID_PARAMETER;
258 
259                  return InfoTdiQueryEntityType(ID->toi_entity, Buffer, BufferSize);
260 
261               default:
262                  return TDI_INVALID_REQUEST;
263            }
264 
265         case INFO_CLASS_PROTOCOL:
266            if (ID->toi_type == INFO_TYPE_ADDRESS_OBJECT)
267            {
268                if ((EntityListContext = GetContext(ID->toi_entity)))
269                     return GetAddressFileInfo(ID, EntityListContext, Buffer, BufferSize);
270                else
271                     return TDI_INVALID_PARAMETER;
272            }
273 
274            switch (ID->toi_id)
275            {
276               case IF_MIB_STATS_ID:
277                  if (ID->toi_type != INFO_TYPE_PROVIDER)
278                      return TDI_INVALID_PARAMETER;
279 
280                  if (ID->toi_entity.tei_entity == IF_ENTITY)
281                      if ((EntityListContext = GetContext(ID->toi_entity)))
282                          return InfoTdiQueryGetInterfaceMIB(ID->toi_entity, EntityListContext, Buffer, BufferSize);
283                      else
284                          return TDI_INVALID_PARAMETER;
285                  else if (ID->toi_entity.tei_entity == CL_NL_ENTITY ||
286                           ID->toi_entity.tei_entity == CO_NL_ENTITY)
287                      if ((EntityListContext = GetContext(ID->toi_entity)))
288                          return InfoTdiQueryGetIPSnmpInfo(ID->toi_entity, EntityListContext, Buffer, BufferSize);
289                      else
290                          return TDI_INVALID_PARAMETER;
291                  else if (ID->toi_entity.tei_entity == AT_ENTITY)
292                      if ((EntityListContext = GetContext(ID->toi_entity)))
293                          return InfoTdiQueryGetATInfo(ID->toi_entity, EntityListContext, Buffer, BufferSize);
294                      else
295                          return TDI_INVALID_PARAMETER;
296                  else
297                      return TDI_INVALID_PARAMETER;
298 
299               case IP_MIB_ADDRTABLE_ENTRY_ID:
300                  if (ID->toi_type != INFO_TYPE_PROVIDER)
301                      return TDI_INVALID_PARAMETER;
302 
303                  if (ID->toi_entity.tei_entity == CL_NL_ENTITY ||
304                      ID->toi_entity.tei_entity == CO_NL_ENTITY)
305                     return InfoTdiQueryGetAddrTable(ID->toi_entity, Buffer, BufferSize);
306                 else if (ID->toi_entity.tei_entity == CO_TL_ENTITY)
307                      if ((EntityListContext = GetContext(ID->toi_entity)))
308                          return InfoTdiQueryGetConnectionTcpTable(EntityListContext, Buffer, BufferSize, TcpUdpClassOwnerPid);
309                      else
310                          return TDI_INVALID_PARAMETER;
311                 else if (ID->toi_entity.tei_entity == CL_TL_ENTITY)
312                      if ((EntityListContext = GetContext(ID->toi_entity)))
313                          return InfoTdiQueryGetConnectionUdpTable(EntityListContext, Buffer, BufferSize, TcpUdpClassOwnerPid);
314                      else
315                          return TDI_INVALID_PARAMETER;
316                 else
317                     return TDI_INVALID_PARAMETER;
318 
319               case IP_MIB_ARPTABLE_ENTRY_ID:
320                  if (ID->toi_type != INFO_TYPE_PROVIDER)
321                      return TDI_INVALID_PARAMETER;
322 
323                  if (ID->toi_entity.tei_entity == AT_ENTITY)
324                      if ((EntityListContext = GetContext(ID->toi_entity)))
325                          return InfoTdiQueryGetArptableMIB(ID->toi_entity, EntityListContext,
326                                                            Buffer, BufferSize);
327                      else
328                          return TDI_INVALID_PARAMETER;
329                  else if (ID->toi_entity.tei_entity == CO_NL_ENTITY ||
330                           ID->toi_entity.tei_entity == CL_NL_ENTITY)
331                      if ((EntityListContext = GetContext(ID->toi_entity)))
332                          return InfoTdiQueryGetRouteTable(EntityListContext, Buffer, BufferSize);
333                      else
334                          return TDI_INVALID_PARAMETER;
335                  else if (ID->toi_entity.tei_entity == CO_TL_ENTITY)
336                      if ((EntityListContext = GetContext(ID->toi_entity)))
337                          return InfoTdiQueryGetConnectionTcpTable(EntityListContext, Buffer, BufferSize, TcpUdpClassBasic);
338                      else
339                          return TDI_INVALID_PARAMETER;
340                  else if (ID->toi_entity.tei_entity == CL_TL_ENTITY)
341                      if ((EntityListContext = GetContext(ID->toi_entity)))
342                          return InfoTdiQueryGetConnectionUdpTable(EntityListContext, Buffer, BufferSize, TcpUdpClassBasic);
343                      else
344                          return TDI_INVALID_PARAMETER;
345                  else
346                      return TDI_INVALID_PARAMETER;
347 
348               case IP_SPECIFIC_MODULE_ENTRY_ID:
349                  if (ID->toi_type != INFO_TYPE_PROVIDER)
350                      return TDI_INVALID_PARAMETER;
351 
352                  if (ID->toi_entity.tei_entity == CO_TL_ENTITY)
353                      if ((EntityListContext = GetContext(ID->toi_entity)))
354                          return InfoTdiQueryGetConnectionTcpTable(EntityListContext, Buffer, BufferSize, TcpUdpClassOwner);
355                      else
356                          return TDI_INVALID_PARAMETER;
357                  else if (ID->toi_entity.tei_entity == CL_TL_ENTITY)
358                      if ((EntityListContext = GetContext(ID->toi_entity)))
359                          return InfoTdiQueryGetConnectionUdpTable(EntityListContext, Buffer, BufferSize, TcpUdpClassOwner);
360                      else
361                          return TDI_INVALID_PARAMETER;
362                  else
363                      return TDI_INVALID_PARAMETER;
364 
365 #if 0
366               case IP_INTFC_INFO_ID:
367                  if (ID->toi_type != INFO_TYPE_PROVIDER)
368                      return TDI_INVALID_PARAMETER;
369 
370                  return InfoTdiQueryGetIFInfo(Context, Buffer, BufferSize);
371 #endif
372 
373               default:
374                  return TDI_INVALID_REQUEST;
375            }
376 
377         default:
378            return TDI_INVALID_REQUEST;
379     }
380 }
381 
InfoTdiSetInformationEx(PTDI_REQUEST Request,TDIObjectID * ID,PVOID Buffer,UINT BufferSize)382 TDI_STATUS InfoTdiSetInformationEx
383 (PTDI_REQUEST Request,
384  TDIObjectID *ID,
385  PVOID Buffer,
386  UINT BufferSize)
387 /*
388  * FUNCTION: Sets extended information
389  * ARGUMENTS:
390  *   Request    = Pointer to TDI request structure for the request
391  *   ID         = Pointer to TDI object ID
392  *   Buffer     = Pointer to buffer with data to use
393  *   BufferSize = Size of Buffer
394  * RETURNS:
395  *   Status of operation
396  */
397 {
398     PVOID EntityListContext;
399 
400     switch (ID->toi_class)
401     {
402         case INFO_CLASS_PROTOCOL:
403         {
404             switch (ID->toi_type)
405             {
406                 case INFO_TYPE_ADDRESS_OBJECT:
407                 {
408                     if ((EntityListContext = GetContext(ID->toi_entity)))
409                         return SetAddressFileInfo(ID, EntityListContext, Buffer, BufferSize);
410                     else
411                         return TDI_INVALID_PARAMETER;
412                 }
413                 case INFO_TYPE_CONNECTION:
414                 {
415                     PADDRESS_FILE AddressFile = GetContext(ID->toi_entity);
416                     if (AddressFile == NULL)
417                         return TDI_INVALID_PARAMETER;
418                     return SetConnectionInfo(ID, AddressFile->Connection, Buffer, BufferSize);
419                 }
420                 case INFO_TYPE_PROVIDER:
421                 {
422                     switch (ID->toi_id)
423                     {
424                         case IP_MIB_ARPTABLE_ENTRY_ID:
425                             if (ID->toi_type != INFO_TYPE_PROVIDER)
426                                 return TDI_INVALID_PARAMETER;
427 
428                             if (ID->toi_entity.tei_entity == AT_ENTITY)
429                                 if ((EntityListContext = GetContext(ID->toi_entity)))
430                                     return InfoTdiSetArptableMIB(EntityListContext, Buffer,
431                                         BufferSize);
432                                 else
433                                     return TDI_INVALID_PARAMETER;
434                             else if (ID->toi_entity.tei_entity == CL_NL_ENTITY
435                                 || ID->toi_entity.tei_entity == CO_NL_ENTITY)
436                                 if ((EntityListContext = GetContext(ID->toi_entity)))
437                                     return InfoTdiSetRoute(EntityListContext, Buffer, BufferSize);
438                                 else
439                                     return TDI_INVALID_PARAMETER;
440                             else
441                                 return TDI_INVALID_PARAMETER;
442 
443                         default:
444                             return TDI_INVALID_REQUEST;
445                     }
446                 }
447                 default:
448                     DbgPrint("TCPIP: IOCTL_TCP_SET_INFORMATION_EX - Unrecognized information type for INFO_CLASS_PROTOCOL: %#x.\n", ID->toi_type);
449                     return TDI_INVALID_PARAMETER;
450             }
451             break;
452         }
453         default:
454             DbgPrint("TCPIP: IOCTL_TCP_SET_INFORMATION_EX - Unrecognized information class %#x.\n", ID->toi_class);
455             return TDI_INVALID_REQUEST;
456     }
457 }
458