cb88a2110d3d0062d54df2c85d33911b6af64be2
[reactos.git] / drivers / network / tcpip / tcpip / ninfo.c
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 */
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
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
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
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 = (DWORD)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
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 = (DWORD)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
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 AddrInitIPv4( &Address, Route->Dest );
316 AddrInitIPv4( &Netmask, Route->Mask );
317 AddrInitIPv4( &Router, Route->Gw );
318
319 if (!Buffer || BufferSize < sizeof(IPROUTE_ENTRY))
320 return TDI_INVALID_PARAMETER;
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 }