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