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