78d11490286fb24e2021a4c549c320c63bec0087
[reactos.git] / reactos / lib / drivers / ip / network / interface.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS TCP/IP protocol driver
4 * FILE: tcpip/interface.c
5 * PURPOSE: Convenient abstraction for getting and setting information
6 * in IP_INTERFACE.
7 * PROGRAMMERS: Art Yerkes
8 * REVISIONS:
9 * CSH 01/08-2000 Created
10 */
11
12 #include "precomp.h"
13
14 NTSTATUS GetInterfaceIPv4Address( PIP_INTERFACE Interface,
15 ULONG TargetType,
16 PULONG Address ) {
17 switch( TargetType ) {
18 case ADE_UNICAST:
19 *Address = Interface->Unicast.Address.IPv4Address;
20 break;
21
22 case ADE_ADDRMASK:
23 *Address = Interface->Netmask.Address.IPv4Address;
24 break;
25
26 case ADE_BROADCAST:
27 *Address = Interface->Broadcast.Address.IPv4Address;
28 break;
29
30 case ADE_POINTOPOINT:
31 *Address = Interface->PointToPoint.Address.IPv4Address;
32 break;
33
34 default:
35 return STATUS_UNSUCCESSFUL;
36 }
37
38 return STATUS_SUCCESS;
39 }
40
41 UINT CountInterfaces() {
42 ULONG Count = 0;
43 KIRQL OldIrql;
44 IF_LIST_ITER(CurrentIF);
45
46 TcpipAcquireSpinLock(&InterfaceListLock, &OldIrql);
47
48 ForEachInterface(CurrentIF) {
49 Count++;
50 } EndFor(CurrentIF);
51
52 TcpipReleaseSpinLock(&InterfaceListLock, OldIrql);
53
54 return Count;
55 }
56
57 NTSTATUS GetInterfaceSpeed( PIP_INTERFACE Interface, PUINT Speed ) {
58 PLAN_ADAPTER IF = (PLAN_ADAPTER)Interface->Context;
59
60 *Speed = IF->Speed;
61
62 return STATUS_SUCCESS;
63 }
64
65 NTSTATUS GetInterfaceName( PIP_INTERFACE Interface,
66 PCHAR NameBuffer,
67 UINT Len ) {
68 ULONG ResultSize = 0;
69 NTSTATUS Status =
70 RtlUnicodeToMultiByteN( NameBuffer,
71 Len,
72 &ResultSize,
73 Interface->Name.Buffer,
74 Interface->Name.Length );
75
76 if( NT_SUCCESS(Status) )
77 NameBuffer[ResultSize] = 0;
78 else
79 NameBuffer[0] = 0;
80
81 return Status;
82 }
83
84 /*
85 * FUNCTION: Locates and returns an address entry using IPv4 adress as argument
86 * ARGUMENTS:
87 * Address = Raw IPv4 address
88 * RETURNS:
89 * Pointer to address entry if found, NULL if not found
90 * NOTES:
91 * If found, the address is referenced
92 */
93 BOOLEAN AddrLocateADEv4(
94 IPv4_RAW_ADDRESS MatchAddress, PIP_ADDRESS Address)
95 {
96 KIRQL OldIrql;
97 BOOLEAN Matched = FALSE;
98 IF_LIST_ITER(CurrentIF);
99
100 TcpipAcquireSpinLock(&InterfaceListLock, &OldIrql);
101
102 ForEachInterface(CurrentIF) {
103 if( AddrIsEqualIPv4( &CurrentIF->Unicast, MatchAddress ) ||
104 AddrIsEqualIPv4( &CurrentIF->Broadcast, MatchAddress ) ) {
105 Address->Type = IP_ADDRESS_V4;
106 Address->Address.IPv4Address = MatchAddress;
107 Matched = TRUE; break;
108 }
109 } EndFor(CurrentIF);
110
111 TcpipReleaseSpinLock(&InterfaceListLock, OldIrql);
112
113 return Matched;
114 }
115
116 BOOLEAN HasPrefix(
117 PIP_ADDRESS Address,
118 PIP_ADDRESS Prefix,
119 UINT Length)
120 /*
121 * FUNCTION: Determines wether an address has an given prefix
122 * ARGUMENTS:
123 * Address = Pointer to address to use
124 * Prefix = Pointer to prefix to check for
125 * Length = Length of prefix
126 * RETURNS:
127 * TRUE if the address has the prefix, FALSE if not
128 * NOTES:
129 * The two addresses must be of the same type
130 */
131 {
132 PUCHAR pAddress = (PUCHAR)&Address->Address;
133 PUCHAR pPrefix = (PUCHAR)&Prefix->Address;
134
135 TI_DbgPrint(DEBUG_ROUTER, ("Called. Address (0x%X) Prefix (0x%X) Length (%d).\n", Address, Prefix, Length));
136
137 #if 0
138 TI_DbgPrint(DEBUG_ROUTER, ("Address (%s) Prefix (%s).\n",
139 A2S(Address), A2S(Prefix)));
140 #endif
141
142 /* Check that initial integral bytes match */
143 while (Length > 8) {
144 if (*pAddress++ != *pPrefix++)
145 return FALSE;
146 Length -= 8;
147 }
148
149 /* Check any remaining bits */
150 if ((Length > 0) && ((*pAddress >> (8 - Length)) != (*pPrefix >> (8 - Length))))
151 return FALSE;
152
153 return TRUE;
154 }
155
156 static PIP_INTERFACE GetDefaultInterface(VOID)
157 {
158 KIRQL OldIrql;
159 IF_LIST_ITER(CurrentIF);
160
161 TcpipAcquireSpinLock(&InterfaceListLock, &OldIrql);
162 ForEachInterface(CurrentIF) {
163 if (CurrentIF->Context) {
164 TcpipReleaseSpinLock(&InterfaceListLock, OldIrql);
165 return CurrentIF;
166 }
167 } EndFor(CurrentIF);
168 TcpipReleaseSpinLock(&InterfaceListLock, OldIrql);
169
170 /* There are no physical interfaces on the system
171 * so we must pick the loopback interface */
172
173 return Loopback;
174 }
175
176 PIP_INTERFACE FindOnLinkInterface(PIP_ADDRESS Address)
177 /*
178 * FUNCTION: Checks all on-link prefixes to find out if an address is on-link
179 * ARGUMENTS:
180 * Address = Pointer to address to check
181 * RETURNS:
182 * Pointer to interface if address is on-link, NULL if not
183 */
184 {
185 KIRQL OldIrql;
186 IF_LIST_ITER(CurrentIF);
187
188 TI_DbgPrint(DEBUG_ROUTER, ("Called. Address (0x%X)\n", Address));
189 TI_DbgPrint(DEBUG_ROUTER, ("Address (%s)\n", A2S(Address)));
190
191 if (AddrIsUnspecified(Address))
192 return GetDefaultInterface();
193
194 TcpipAcquireSpinLock(&InterfaceListLock, &OldIrql);
195
196 ForEachInterface(CurrentIF) {
197 if (HasPrefix(Address, &CurrentIF->Unicast,
198 AddrCountPrefixBits(&CurrentIF->Netmask))) {
199 TcpipReleaseSpinLock(&InterfaceListLock, OldIrql);
200 return CurrentIF;
201 }
202 } EndFor(CurrentIF);
203
204 TcpipReleaseSpinLock(&InterfaceListLock, OldIrql);
205
206 return NULL;
207 }
208
209 NTSTATUS GetInterfaceConnectionStatus
210 ( PIP_INTERFACE Interface, PULONG Result ) {
211 NTSTATUS Status = TcpipLanGetDwordOid
212 ( Interface, OID_GEN_HARDWARE_STATUS, Result );
213 if( NT_SUCCESS(Status) ) switch( *Result ) {
214 case NdisHardwareStatusReady:
215 *Result = MIB_IF_OPER_STATUS_OPERATIONAL;
216 break;
217 case NdisHardwareStatusInitializing:
218 *Result = MIB_IF_OPER_STATUS_CONNECTING;
219 break;
220 case NdisHardwareStatusReset:
221 *Result = MIB_IF_OPER_STATUS_DISCONNECTED;
222 break;
223 case NdisHardwareStatusNotReady:
224 *Result = MIB_IF_OPER_STATUS_DISCONNECTED;
225 break;
226 case NdisHardwareStatusClosing:
227 default:
228 *Result = MIB_IF_OPER_STATUS_NON_OPERATIONAL;
229 break;
230 }
231 return Status;
232 }