* Significant improve boot speed and debug log neatness:
[reactos.git] / reactos / 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 TDI_STATUS InfoTdiQueryGetAddrTable( PNDIS_BUFFER Buffer,
17 PUINT BufferSize ) {
18
19 TDI_STATUS Status = TDI_INVALID_REQUEST;
20 KIRQL OldIrql;
21 UINT Count = 0;
22 UINT IfCount = CountInterfaces();
23 PIPADDR_ENTRY IpAddress =
24 ExAllocatePool( NonPagedPool, sizeof( IPADDR_ENTRY ) * IfCount );
25 PIPADDR_ENTRY IpCurrent = IpAddress;
26 IF_LIST_ITER(CurrentIF);
27
28 TI_DbgPrint(DEBUG_INFO, ("Called.\n"));
29
30 TcpipAcquireSpinLock(&InterfaceListLock, &OldIrql);
31
32 ForEachInterface(CurrentIF) {
33 IpCurrent->Index = CurrentIF->Index;
34 IpCurrent->Addr = 0;
35 IpCurrent->BcastAddr = 0;
36 IpCurrent->Mask = 0;
37
38 /* Locate the diffrent addresses and put them the right place */
39 GetInterfaceIPv4Address( CurrentIF,
40 ADE_UNICAST,
41 &IpCurrent->Addr );
42 GetInterfaceIPv4Address( CurrentIF,
43 ADE_BROADCAST,
44 &IpCurrent->BcastAddr );
45 GetInterfaceIPv4Address( CurrentIF,
46 ADE_ADDRMASK,
47 &IpCurrent->Mask );
48 IpCurrent++;
49 Count++;
50 } EndFor(CurrentIF);
51 ASSERT( Count == IfCount );
52
53 TcpipReleaseSpinLock(&InterfaceListLock, OldIrql);
54
55 Status = InfoCopyOut( (PCHAR)IpAddress, sizeof(*IpAddress) * IfCount,
56 Buffer, BufferSize );
57
58 ExFreePool( IpAddress );
59
60 TI_DbgPrint(DEBUG_INFO, ("Returning %08x\n", Status));
61
62 return Status;
63 }
64
65 /* Get IPRouteEntry s for each of the routes in the system */
66 TDI_STATUS InfoTdiQueryGetRouteTable( PNDIS_BUFFER Buffer, PUINT BufferSize ) {
67 TDI_STATUS Status;
68 KIRQL OldIrql;
69 UINT RtCount = CountFIBs();
70 UINT Size = sizeof( IPROUTE_ENTRY ) * RtCount;
71 PFIB_ENTRY RCache =
72 ExAllocatePool( NonPagedPool, sizeof( FIB_ENTRY ) * RtCount ),
73 RCacheCur = RCache;
74 PIPROUTE_ENTRY RouteEntries = ExAllocatePool( NonPagedPool, Size ),
75 RtCurrent = RouteEntries;
76
77 TI_DbgPrint(DEBUG_INFO, ("Called, routes = %d, RCache = %08x\n",
78 RtCount, RCache));
79
80 if( !RCache || !RouteEntries ) {
81 if( RCache ) ExFreePool( RCache );
82 if( RouteEntries ) ExFreePool( RouteEntries );
83 return STATUS_NO_MEMORY;
84 }
85
86 RtlZeroMemory( RouteEntries, Size );
87
88 RtCount = CopyFIBs( RCache );
89
90 while( RtCurrent < RouteEntries + RtCount ) {
91 /* Copy Desitnation */
92 RtlCopyMemory( &RtCurrent->Dest,
93 &RCacheCur->NetworkAddress.Address,
94 sizeof(RtCurrent->Dest) );
95 RtlCopyMemory( &RtCurrent->Mask,
96 &RCacheCur->Netmask.Address,
97 sizeof(RtCurrent->Mask) );
98
99 if( RCacheCur->Router )
100 RtlCopyMemory( &RtCurrent->Gw,
101 &RCacheCur->Router->Address.Address,
102 sizeof(RtCurrent->Gw) );
103 else
104 RtlZeroMemory( &RtCurrent->Gw, sizeof(RtCurrent->Gw) );
105
106 RtCurrent->Metric1 = RCacheCur->Metric;
107 RtCurrent->Type = TDI_ADDRESS_TYPE_IP;
108
109 TI_DbgPrint
110 (DEBUG_INFO,
111 ("%d: NA %08x NM %08x GW %08x MT %x\n",
112 RtCurrent - RouteEntries,
113 RtCurrent->Dest,
114 RtCurrent->Mask,
115 RtCurrent->Gw,
116 RtCurrent->Metric1 ));
117
118 TcpipAcquireSpinLock(&EntityListLock, &OldIrql);
119 for( RtCurrent->Index = EntityCount;
120 RtCurrent->Index > 0 &&
121 RCacheCur->Router->Interface !=
122 EntityList[RtCurrent->Index - 1].context;
123 RtCurrent->Index-- );
124
125 RtCurrent->Index = EntityList[RtCurrent->Index - 1].tei_instance;
126 TcpipReleaseSpinLock(&EntityListLock, OldIrql);
127
128 RtCurrent++; RCacheCur++;
129 }
130
131 Status = InfoCopyOut( (PCHAR)RouteEntries, Size, Buffer, BufferSize );
132
133 ExFreePool( RouteEntries );
134 ExFreePool( RCache );
135
136 TI_DbgPrint(DEBUG_INFO, ("Returning %08x\n", Status));
137
138 return Status;
139 }
140
141 TDI_STATUS InfoTdiQueryGetIPSnmpInfo( PNDIS_BUFFER Buffer,
142 PUINT BufferSize ) {
143 IPSNMP_INFO SnmpInfo;
144 UINT IfCount = CountInterfaces();
145 UINT RouteCount = CountFIBs();
146 TDI_STATUS Status = TDI_INVALID_REQUEST;
147
148 TI_DbgPrint(DEBUG_INFO, ("Called.\n"));
149
150 RtlZeroMemory(&SnmpInfo, sizeof(IPSNMP_INFO));
151
152 SnmpInfo.NumIf = IfCount;
153 SnmpInfo.NumAddr = 1;
154 SnmpInfo.NumRoutes = RouteCount;
155
156 Status = InfoCopyOut( (PCHAR)&SnmpInfo, sizeof(SnmpInfo),
157 Buffer, BufferSize );
158
159 TI_DbgPrint(DEBUG_INFO, ("Returning %08x\n", Status));
160
161 return Status;
162 }
163
164 TDI_STATUS InfoNetworkLayerTdiQueryEx( UINT InfoClass,
165 UINT InfoType,
166 UINT InfoId,
167 PVOID Context,
168 TDIEntityID *id,
169 PNDIS_BUFFER Buffer,
170 PUINT BufferSize ) {
171 TDI_STATUS Status = TDI_INVALID_REQUEST;
172
173 TI_DbgPrint(DEBUG_INFO, ("Called.\n"));
174
175 switch( InfoClass ) {
176 case INFO_CLASS_GENERIC:
177 if( InfoType == INFO_TYPE_PROVIDER && InfoId == ENTITY_TYPE_ID ) {
178 ULONG Return = CL_NL_IP;
179 Status = InfoCopyOut( (PCHAR)&Return, sizeof(Return),
180 Buffer, BufferSize );
181 }
182 break;
183
184 case INFO_CLASS_PROTOCOL:
185 switch( InfoType ) {
186 case INFO_TYPE_PROVIDER:
187 switch( InfoId ) {
188 case IP_MIB_ADDRTABLE_ENTRY_ID:
189 Status = InfoTdiQueryGetAddrTable( Buffer, BufferSize );
190 break;
191
192 case IP_MIB_ROUTETABLE_ENTRY_ID:
193 Status = InfoTdiQueryGetRouteTable( Buffer, BufferSize );
194 break;
195
196 case IP_MIB_STATS_ID:
197 Status = InfoTdiQueryGetIPSnmpInfo( Buffer, BufferSize );
198 break;
199 }
200 break;
201 }
202 }
203
204 TI_DbgPrint(DEBUG_INFO, ("Returning %08x\n", Status));
205
206 return Status;
207 }
208
209 TDI_STATUS InfoNetworkLayerTdiSetEx( UINT InfoClass,
210 UINT InfoType,
211 UINT InfoId,
212 PVOID Context,
213 TDIEntityID *id,
214 PCHAR Buffer,
215 UINT BufferSize ) {
216 NTSTATUS Status = TDI_INVALID_REQUEST;
217 IP_ADDRESS Address;
218 IP_ADDRESS Netmask;
219 IP_ADDRESS Router;
220 PNEIGHBOR_CACHE_ENTRY NCE;
221
222 TI_DbgPrint(DEBUG_INFO,("Called\n"));
223
224 //OskitDumpBuffer( (OSK_PCHAR)Buffer, BufferSize );
225
226 if( InfoClass == INFO_CLASS_PROTOCOL &&
227 InfoType == INFO_TYPE_PROVIDER &&
228 InfoId == IP_MIB_ROUTETABLE_ENTRY_ID &&
229 id->tei_entity == CL_NL_ENTITY ) { /* Add or delete a route */
230 PIPROUTE_ENTRY Route = (PIPROUTE_ENTRY)Buffer;
231 AddrInitIPv4( &Address, Route->Dest );
232 AddrInitIPv4( &Netmask, Route->Mask );
233 AddrInitIPv4( &Router, Route->Gw );
234
235 if( Route->Type == IP_ROUTE_TYPE_ADD ) { /* Add the route */
236 TI_DbgPrint(DEBUG_INFO,("Adding route (%s)\n", A2S(&Address)));
237 /* Find the existing route this belongs to */
238 NCE = RouterGetRoute( &Router );
239 /* Really add the route */
240 if( NCE &&
241 RouterCreateRoute( &Address, &Netmask, &Router,
242 NCE->Interface, Route->Metric1 ) )
243 Status = STATUS_SUCCESS;
244 else
245 Status = STATUS_UNSUCCESSFUL;
246 } else if( Route->Type == IP_ROUTE_TYPE_DEL ) {
247 TI_DbgPrint(DEBUG_INFO,("Removing route (%s)\n", A2S(&Address)));
248 Status = RouterRemoveRoute( &Address, &Router );
249 } else Status = TDI_INVALID_REQUEST;
250 }
251
252 TI_DbgPrint(DEBUG_INFO,("Returning %x\n", Status));
253
254 return Status;
255 }