[PCNET]
[reactos.git] / 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 PIP_INTERFACE AddrLocateInterface(
85 PIP_ADDRESS MatchAddress)
86 {
87 KIRQL OldIrql;
88 PIP_INTERFACE RetIF = NULL;
89 IF_LIST_ITER(CurrentIF);
90
91 TcpipAcquireSpinLock(&InterfaceListLock, &OldIrql);
92
93 ForEachInterface(CurrentIF) {
94 if( AddrIsEqual( &CurrentIF->Unicast, MatchAddress ) ||
95 AddrIsEqual( &CurrentIF->Broadcast, MatchAddress ) ) {
96 RetIF = CurrentIF;
97 break;
98 }
99 } EndFor(CurrentIF);
100
101 TcpipReleaseSpinLock(&InterfaceListLock, OldIrql);
102
103 return RetIF;
104 }
105
106 BOOLEAN HasPrefix(
107 PIP_ADDRESS Address,
108 PIP_ADDRESS Prefix,
109 UINT Length)
110 /*
111 * FUNCTION: Determines wether an address has an given prefix
112 * ARGUMENTS:
113 * Address = Pointer to address to use
114 * Prefix = Pointer to prefix to check for
115 * Length = Length of prefix
116 * RETURNS:
117 * TRUE if the address has the prefix, FALSE if not
118 * NOTES:
119 * The two addresses must be of the same type
120 */
121 {
122 PUCHAR pAddress = (PUCHAR)&Address->Address;
123 PUCHAR pPrefix = (PUCHAR)&Prefix->Address;
124
125 TI_DbgPrint(DEBUG_ROUTER, ("Called. Address (0x%X) Prefix (0x%X) Length (%d).\n", Address, Prefix, Length));
126
127 #if 0
128 TI_DbgPrint(DEBUG_ROUTER, ("Address (%s) Prefix (%s).\n",
129 A2S(Address), A2S(Prefix)));
130 #endif
131
132 /* Check that initial integral bytes match */
133 while (Length > 8) {
134 if (*pAddress++ != *pPrefix++)
135 return FALSE;
136 Length -= 8;
137 }
138
139 /* Check any remaining bits */
140 if ((Length > 0) && ((*pAddress >> (8 - Length)) != (*pPrefix >> (8 - Length))))
141 return FALSE;
142
143 return TRUE;
144 }
145
146 static PIP_INTERFACE GetDefaultInterface(VOID)
147 {
148 KIRQL OldIrql;
149 IF_LIST_ITER(CurrentIF);
150
151 TcpipAcquireSpinLock(&InterfaceListLock, &OldIrql);
152 ForEachInterface(CurrentIF) {
153 if (CurrentIF->Context) {
154 TcpipReleaseSpinLock(&InterfaceListLock, OldIrql);
155 return CurrentIF;
156 }
157 } EndFor(CurrentIF);
158 TcpipReleaseSpinLock(&InterfaceListLock, OldIrql);
159
160 /* There are no physical interfaces on the system
161 * so we must pick the loopback interface */
162
163 return Loopback;
164 }
165
166 PIP_INTERFACE FindOnLinkInterface(PIP_ADDRESS Address)
167 /*
168 * FUNCTION: Checks all on-link prefixes to find out if an address is on-link
169 * ARGUMENTS:
170 * Address = Pointer to address to check
171 * RETURNS:
172 * Pointer to interface if address is on-link, NULL if not
173 */
174 {
175 KIRQL OldIrql;
176 IF_LIST_ITER(CurrentIF);
177
178 TI_DbgPrint(DEBUG_ROUTER, ("Called. Address (0x%X)\n", Address));
179 TI_DbgPrint(DEBUG_ROUTER, ("Address (%s)\n", A2S(Address)));
180
181 if (AddrIsUnspecified(Address))
182 return GetDefaultInterface();
183
184 TcpipAcquireSpinLock(&InterfaceListLock, &OldIrql);
185
186 ForEachInterface(CurrentIF) {
187 if (HasPrefix(Address, &CurrentIF->Unicast,
188 AddrCountPrefixBits(&CurrentIF->Netmask))) {
189 TcpipReleaseSpinLock(&InterfaceListLock, OldIrql);
190 return CurrentIF;
191 }
192 } EndFor(CurrentIF);
193
194 TcpipReleaseSpinLock(&InterfaceListLock, OldIrql);
195
196 return NULL;
197 }
198
199 NTSTATUS GetInterfaceConnectionStatus(PIP_INTERFACE Interface, PULONG Result)
200 {
201 NTSTATUS Status;
202
203 /* Query OID_GEN_MEDIA_CONNECT_STATUS for connection status information */
204 Status = TcpipLanGetDwordOid(Interface, OID_GEN_MEDIA_CONNECT_STATUS, Result);
205 if (!NT_SUCCESS(Status))
206 return Status;
207
208 /* Translate the result into MIB_IF_OPER_STATUS_XXX */
209 if (*Result == NdisMediaStateConnected)
210 {
211 /* Up and running */
212 *Result = MIB_IF_OPER_STATUS_OPERATIONAL;
213 }
214 else
215 {
216 /* Down */
217 *Result = MIB_IF_OPER_STATUS_DISCONNECTED;
218 }
219
220 return STATUS_SUCCESS;
221 }