xref: /reactos/drivers/network/tcpip/tcpip/ninfo.c (revision 34593d93)
1 /*
2  * COPYRIGHT:   See COPYING in the top level directory
3  * PROJECT:     ReactOS TCP/IP protocol driver
4  * FILE:        tcpip/ninfo.c
5  * PURPOSE:     Network information
6  * PROGRAMMERS: Art Yerkes
7  * REVISIONS:
8  *   CSH 01/08-2000 Created
9  */
10 
11 #include "precomp.h"
12 
13 #define IP_ROUTE_TYPE_ADD 3
14 #define IP_ROUTE_TYPE_DEL 2
15 
16 /* Get IPRouteEntry s for each of the routes in the system */
InfoTdiQueryGetRouteTable(PIP_INTERFACE IF,PNDIS_BUFFER Buffer,PUINT BufferSize)17 TDI_STATUS InfoTdiQueryGetRouteTable( PIP_INTERFACE IF, PNDIS_BUFFER Buffer, PUINT BufferSize ) {
18     TDI_STATUS Status;
19     KIRQL OldIrql;
20     UINT RtCount = CountFIBs(IF);
21     UINT Size = sizeof( IPROUTE_ENTRY ) * RtCount;
22     PFIB_ENTRY RCache, RCacheCur;
23     PIPROUTE_ENTRY RouteEntries, RtCurrent;
24     UINT i;
25 
26     TI_DbgPrint(DEBUG_INFO, ("Called, routes = %d\n",
27 			    RtCount));
28 
29     if (RtCount == 0)
30         return InfoCopyOut(NULL, 0, NULL, BufferSize);
31 
32     RouteEntries = ExAllocatePoolWithTag( NonPagedPool, Size, ROUTE_ENTRY_TAG );
33     RtCurrent = RouteEntries;
34 
35     RCache = ExAllocatePoolWithTag( NonPagedPool, sizeof( FIB_ENTRY ) * RtCount, FIB_TAG );
36     RCacheCur = RCache;
37 
38     if( !RCache || !RouteEntries ) {
39 	if( RCache ) ExFreePoolWithTag( RCache, FIB_TAG );
40 	if( RouteEntries ) ExFreePoolWithTag( RouteEntries, ROUTE_ENTRY_TAG );
41 	return TDI_NO_RESOURCES;
42     }
43 
44     RtlZeroMemory( RouteEntries, Size );
45 
46     RtCount = CopyFIBs( IF, RCache );
47 
48     while( RtCurrent < RouteEntries + RtCount ) {
49 	ASSERT(RCacheCur->Router);
50 
51 	RtlCopyMemory( &RtCurrent->Dest,
52 		       &RCacheCur->NetworkAddress.Address,
53 		       sizeof(RtCurrent->Dest) );
54 	RtlCopyMemory( &RtCurrent->Mask,
55 		       &RCacheCur->Netmask.Address,
56 		       sizeof(RtCurrent->Mask) );
57 	RtlCopyMemory( &RtCurrent->Gw,
58 		       &RCacheCur->Router->Address.Address,
59 		       sizeof(RtCurrent->Gw) );
60 
61 	RtCurrent->Metric1 = RCacheCur->Metric;
62 	RtCurrent->Type = TDI_ADDRESS_TYPE_IP;
63 
64 	TI_DbgPrint
65 	    (DEBUG_INFO,
66 	     ("%d: NA %08x NM %08x GW %08x MT %x\n",
67 	      RtCurrent - RouteEntries,
68 	      RtCurrent->Dest,
69 	      RtCurrent->Mask,
70 	      RtCurrent->Gw,
71 	      RtCurrent->Metric1 ));
72 
73 	TcpipAcquireSpinLock(&EntityListLock, &OldIrql);
74 	for (i = 0; i < EntityCount; i++)
75              if (EntityList[i].context == IF)
76                  break;
77 
78         if (i < EntityCount)
79             RtCurrent->Index = EntityList[i].tei_instance;
80         else
81             RtCurrent->Index = 0;
82 
83 	TcpipReleaseSpinLock(&EntityListLock, OldIrql);
84 
85 	RtCurrent++; RCacheCur++;
86     }
87 
88     Status = InfoCopyOut( (PCHAR)RouteEntries, Size, Buffer, BufferSize );
89 
90     ExFreePoolWithTag( RouteEntries, ROUTE_ENTRY_TAG );
91     ExFreePoolWithTag( RCache, FIB_TAG );
92 
93     TI_DbgPrint(DEBUG_INFO, ("Returning %08x\n", Status));
94 
95     return Status;
96 }
97 
InfoTdiQueryGetAddrTable(TDIEntityID ID,PNDIS_BUFFER Buffer,PUINT BufferSize)98 TDI_STATUS InfoTdiQueryGetAddrTable(TDIEntityID ID,
99 				    PNDIS_BUFFER Buffer,
100 				    PUINT BufferSize)
101 {
102     KIRQL OldIrql;
103     PIPADDR_ENTRY IPEntry;
104     PIP_INTERFACE CurrentIF;
105     UINT i;
106 
107     TI_DbgPrint(DEBUG_INFO, ("Called.\n"));
108 
109 
110     TcpipAcquireSpinLock(&EntityListLock, &OldIrql);
111 
112     for (i = 0; i < EntityCount; i++)
113     {
114         if (EntityList[i].tei_entity == ID.tei_entity &&
115             EntityList[i].tei_instance == ID.tei_instance)
116             break;
117     }
118 
119     if (i == EntityCount)
120     {
121         TcpipReleaseSpinLock(&EntityListLock, OldIrql);
122         return TDI_INVALID_PARAMETER;
123     }
124 
125     IPEntry = ExAllocatePoolWithTag(NonPagedPool, sizeof(IPADDR_ENTRY), IP_ADDRESS_TAG);
126     if (!IPEntry)
127     {
128         TcpipReleaseSpinLock(&EntityListLock, OldIrql);
129         return TDI_NO_RESOURCES;
130     }
131 
132     CurrentIF = EntityList[i].context;
133 
134     IPEntry->Index = CurrentIF->Index;
135     GetInterfaceIPv4Address(CurrentIF,
136 			    ADE_UNICAST,
137 			    &IPEntry->Addr);
138     GetInterfaceIPv4Address(CurrentIF,
139 			    ADE_ADDRMASK,
140 			    &IPEntry->Mask);
141     GetInterfaceIPv4Address(CurrentIF,
142 			    ADE_BROADCAST,
143 			    &IPEntry->BcastAddr);
144 
145     TcpipReleaseSpinLock(&EntityListLock, OldIrql);
146 
147     InfoCopyOut((PCHAR)IPEntry, sizeof(IPADDR_ENTRY),
148 		Buffer, BufferSize);
149 
150     ExFreePoolWithTag(IPEntry, IP_ADDRESS_TAG);
151 
152     return TDI_SUCCESS;
153 }
154 
InfoTdiQueryGetIPSnmpInfo(TDIEntityID ID,PIP_INTERFACE IF,PNDIS_BUFFER Buffer,PUINT BufferSize)155 TDI_STATUS InfoTdiQueryGetIPSnmpInfo( TDIEntityID ID,
156                                       PIP_INTERFACE IF,
157 				      PNDIS_BUFFER Buffer,
158 				      PUINT BufferSize ) {
159     IPSNMPInfo SnmpInfo;
160     UINT IfCount = CountInterfaces();
161     UINT RouteCount = CountFIBs(IF);
162     TDI_STATUS Status = TDI_INVALID_REQUEST;
163 
164     TI_DbgPrint(DEBUG_INFO, ("Called.\n"));
165 
166     RtlZeroMemory(&SnmpInfo, sizeof(SnmpInfo));
167 
168     SnmpInfo.ipsi_numif = IfCount;
169     SnmpInfo.ipsi_numaddr = 1;
170     SnmpInfo.ipsi_numroutes = RouteCount;
171 
172     Status = InfoCopyOut( (PCHAR)&SnmpInfo, sizeof(SnmpInfo),
173 			  Buffer, BufferSize );
174 
175     TI_DbgPrint(DEBUG_INFO, ("Returning %08x\n", Status));
176 
177     return Status;
178 }
179 
180 #define ntohs(n) ((((n) & 0xff) << 8) | (((n) & 0xff00) >> 8))
181 
InfoTdiQueryGetConnectionTcpTable(PADDRESS_FILE AddrFile,PNDIS_BUFFER Buffer,PUINT BufferSize,TDI_TCPUDP_CLASS_INFO Class)182 TDI_STATUS InfoTdiQueryGetConnectionTcpTable(PADDRESS_FILE AddrFile,
183 				    PNDIS_BUFFER Buffer,
184 				    PUINT BufferSize,
185                     TDI_TCPUDP_CLASS_INFO Class)
186 {
187     SIZE_T Size;
188     MIB_TCPROW_OWNER_MODULE TcpRow;
189     TDI_STATUS Status = TDI_INVALID_REQUEST;
190 
191     TI_DbgPrint(DEBUG_INFO, ("Called.\n"));
192 
193     if (Class == TcpUdpClassOwnerPid)
194     {
195         Size = sizeof(MIB_TCPROW_OWNER_PID);
196     }
197     else if (Class == TcpUdpClassOwner)
198     {
199         Size = sizeof(MIB_TCPROW_OWNER_MODULE);
200     }
201     else
202     {
203         Size = sizeof(MIB_TCPROW);
204     }
205 
206     TcpRow.dwOwningPid = HandleToUlong(AddrFile->ProcessId);
207     TcpRow.liCreateTimestamp = AddrFile->CreationTime;
208 
209     if (AddrFile->Listener != NULL)
210     {
211         PADDRESS_FILE EndPoint;
212 
213         EndPoint = AddrFile->Listener->AddressFile;
214 
215         TcpRow.dwState = MIB_TCP_STATE_LISTEN;
216         TcpRow.dwLocalAddr = AddrFile->Address.Address.IPv4Address;
217         TcpRow.dwLocalPort = AddrFile->Port;
218         TcpRow.dwRemoteAddr = EndPoint->Address.Address.IPv4Address;
219         TcpRow.dwRemotePort = EndPoint->Port;
220 
221         Status = TDI_SUCCESS;
222     }
223     else if (AddrFile->Connection != NULL &&
224              AddrFile->Connection->SocketContext != NULL)
225     {
226         TA_IP_ADDRESS EndPoint;
227 
228         Status = TCPGetSockAddress(AddrFile->Connection, (PTRANSPORT_ADDRESS)&EndPoint, FALSE);
229         if (NT_SUCCESS(Status))
230         {
231             ASSERT(EndPoint.TAAddressCount >= 1);
232             ASSERT(EndPoint.Address[0].AddressLength == TDI_ADDRESS_LENGTH_IP);
233             TcpRow.dwLocalAddr = EndPoint.Address[0].Address[0].in_addr;
234             TcpRow.dwLocalPort = ntohs(EndPoint.Address[0].Address[0].sin_port);
235 
236             Status = TCPGetSockAddress(AddrFile->Connection, (PTRANSPORT_ADDRESS)&EndPoint, TRUE);
237             if (NT_SUCCESS(Status))
238             {
239                 ASSERT(EndPoint.TAAddressCount >= 1);
240                 ASSERT(EndPoint.Address[0].AddressLength == TDI_ADDRESS_LENGTH_IP);
241                 TcpRow.dwRemoteAddr = EndPoint.Address[0].Address[0].in_addr;
242                 TcpRow.dwRemotePort = ntohs(EndPoint.Address[0].Address[0].sin_port);
243 
244                 Status = TCPGetSocketStatus(AddrFile->Connection, &TcpRow.dwState);
245                 ASSERT(NT_SUCCESS(Status));
246             }
247         }
248     }
249 
250     if (NT_SUCCESS(Status))
251     {
252         if (Class == TcpUdpClassOwner)
253         {
254             RtlZeroMemory(&TcpRow.OwningModuleInfo[0], sizeof(TcpRow.OwningModuleInfo));
255             TcpRow.OwningModuleInfo[0] = (ULONG_PTR)AddrFile->SubProcessTag;
256         }
257 
258         Status = InfoCopyOut( (PCHAR)&TcpRow, Size,
259                               Buffer, BufferSize );
260     }
261 
262     TI_DbgPrint(DEBUG_INFO, ("Returning %08x\n", Status));
263 
264     return Status;
265 }
266 
InfoTdiQueryGetConnectionUdpTable(PADDRESS_FILE AddrFile,PNDIS_BUFFER Buffer,PUINT BufferSize,TDI_TCPUDP_CLASS_INFO Class)267 TDI_STATUS InfoTdiQueryGetConnectionUdpTable(PADDRESS_FILE AddrFile,
268 				    PNDIS_BUFFER Buffer,
269 				    PUINT BufferSize,
270 				    TDI_TCPUDP_CLASS_INFO Class)
271 {
272     SIZE_T Size;
273     MIB_UDPROW_OWNER_MODULE UdpRow;
274     TDI_STATUS Status = TDI_INVALID_REQUEST;
275 
276     TI_DbgPrint(DEBUG_INFO, ("Called.\n"));
277 
278     if (Class == TcpUdpClassOwnerPid)
279     {
280         Size = sizeof(MIB_UDPROW_OWNER_PID);
281     }
282     else if (Class == TcpUdpClassOwner)
283     {
284         Size = sizeof(MIB_UDPROW_OWNER_MODULE);
285     }
286     else
287     {
288         Size = sizeof(MIB_UDPROW);
289     }
290 
291     UdpRow.dwLocalAddr = AddrFile->Address.Address.IPv4Address;
292     UdpRow.dwLocalPort = AddrFile->Port;
293     UdpRow.dwOwningPid = HandleToUlong(AddrFile->ProcessId);
294     UdpRow.liCreateTimestamp = AddrFile->CreationTime;
295     UdpRow.dwFlags = 0; /* FIXME */
296     if (Class == TcpUdpClassOwner)
297     {
298         RtlZeroMemory(&UdpRow.OwningModuleInfo[0], sizeof(UdpRow.OwningModuleInfo));
299         UdpRow.OwningModuleInfo[0] = (ULONG_PTR)AddrFile->SubProcessTag;
300     }
301 
302     Status = InfoCopyOut( (PCHAR)&UdpRow,
303 			  Size, Buffer, BufferSize );
304 
305     TI_DbgPrint(DEBUG_INFO, ("Returning %08x\n", Status));
306 
307     return Status;
308 }
309 
InfoTdiSetRoute(PIP_INTERFACE IF,PVOID Buffer,UINT BufferSize)310 TDI_STATUS InfoTdiSetRoute(PIP_INTERFACE IF, PVOID Buffer, UINT BufferSize)
311 {
312     IP_ADDRESS Address, Netmask, Router;
313     PIPROUTE_ENTRY Route = Buffer;
314 
315     if (!Buffer || BufferSize < sizeof(IPROUTE_ENTRY))
316         return TDI_INVALID_PARAMETER;
317 
318     AddrInitIPv4( &Address, Route->Dest );
319     AddrInitIPv4( &Netmask, Route->Mask );
320     AddrInitIPv4( &Router,  Route->Gw );
321 
322     if (IF == Loopback)
323     {
324         DbgPrint("Failing attempt to add route to loopback adapter\n");
325         return TDI_INVALID_PARAMETER;
326     }
327 
328     if( Route->Type == IP_ROUTE_TYPE_ADD ) { /* Add the route */
329         TI_DbgPrint(DEBUG_INFO,("Adding route (%s)\n", A2S(&Address)));
330 	if (!RouterCreateRoute( &Address, &Netmask, &Router,
331 			       IF, Route->Metric1))
332 	    return TDI_NO_RESOURCES;
333 
334         return TDI_SUCCESS;
335      } else if( Route->Type == IP_ROUTE_TYPE_DEL ) {
336 	TI_DbgPrint(DEBUG_INFO,("Removing route (%s)\n", A2S(&Address)));
337 	if (NT_SUCCESS(RouterRemoveRoute( &Address, &Router )))
338             return TDI_SUCCESS;
339         else
340             return TDI_INVALID_PARAMETER;
341      }
342 
343      return TDI_INVALID_REQUEST;
344 }
345