mirror of
https://github.com/reactos/reactos.git
synced 2024-11-10 00:34:39 +00:00
265 lines
6.7 KiB
C
265 lines
6.7 KiB
C
/*
|
|
* COPYRIGHT: See COPYING in the top level directory
|
|
* PROJECT: ReactOS TCP/IP protocol driver
|
|
* FILE: tcpip/interface.c
|
|
* PURPOSE: Convenient abstraction for getting and setting information
|
|
* in IP_INTERFACE.
|
|
* PROGRAMMERS: Art Yerkes
|
|
* REVISIONS:
|
|
* CSH 01/08-2000 Created
|
|
*/
|
|
|
|
#include "precomp.h"
|
|
|
|
#include <ntifs.h>
|
|
#include <ipifcons.h>
|
|
|
|
ULONG NextDefaultAdapter = 0;
|
|
|
|
NTSTATUS GetInterfaceIPv4Address( PIP_INTERFACE Interface,
|
|
ULONG TargetType,
|
|
PULONG Address ) {
|
|
switch( TargetType ) {
|
|
case ADE_UNICAST:
|
|
*Address = Interface->Unicast.Address.IPv4Address;
|
|
break;
|
|
|
|
case ADE_ADDRMASK:
|
|
*Address = Interface->Netmask.Address.IPv4Address;
|
|
break;
|
|
|
|
case ADE_BROADCAST:
|
|
*Address = Interface->Broadcast.Address.IPv4Address;
|
|
break;
|
|
|
|
case ADE_POINTOPOINT:
|
|
*Address = Interface->PointToPoint.Address.IPv4Address;
|
|
break;
|
|
|
|
default:
|
|
return STATUS_UNSUCCESSFUL;
|
|
}
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
UINT CountInterfaces() {
|
|
ULONG Count = 0;
|
|
KIRQL OldIrql;
|
|
IF_LIST_ITER(CurrentIF);
|
|
|
|
TcpipAcquireSpinLock(&InterfaceListLock, &OldIrql);
|
|
|
|
ForEachInterface(CurrentIF) {
|
|
Count++;
|
|
} EndFor(CurrentIF);
|
|
|
|
TcpipReleaseSpinLock(&InterfaceListLock, OldIrql);
|
|
|
|
return Count;
|
|
}
|
|
|
|
NTSTATUS GetInterfaceSpeed( PIP_INTERFACE Interface, PUINT Speed ) {
|
|
PLAN_ADAPTER IF = (PLAN_ADAPTER)Interface->Context;
|
|
|
|
*Speed = IF->Speed;
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
NTSTATUS GetInterfaceName( PIP_INTERFACE Interface,
|
|
PCHAR NameBuffer,
|
|
UINT Len ) {
|
|
ULONG ResultSize = 0;
|
|
NTSTATUS Status =
|
|
RtlUnicodeToMultiByteN( NameBuffer,
|
|
Len,
|
|
&ResultSize,
|
|
Interface->Name.Buffer,
|
|
Interface->Name.Length );
|
|
|
|
if( NT_SUCCESS(Status) )
|
|
NameBuffer[ResultSize] = 0;
|
|
else
|
|
NameBuffer[0] = 0;
|
|
|
|
return Status;
|
|
}
|
|
|
|
PIP_INTERFACE AddrLocateInterface(
|
|
PIP_ADDRESS MatchAddress)
|
|
{
|
|
KIRQL OldIrql;
|
|
PIP_INTERFACE RetIF = NULL;
|
|
IF_LIST_ITER(CurrentIF);
|
|
|
|
TcpipAcquireSpinLock(&InterfaceListLock, &OldIrql);
|
|
|
|
ForEachInterface(CurrentIF) {
|
|
if( AddrIsEqual( &CurrentIF->Unicast, MatchAddress ) ||
|
|
AddrIsEqual( &CurrentIF->Broadcast, MatchAddress ) ) {
|
|
RetIF = CurrentIF;
|
|
break;
|
|
}
|
|
} EndFor(CurrentIF);
|
|
|
|
TcpipReleaseSpinLock(&InterfaceListLock, OldIrql);
|
|
|
|
return RetIF;
|
|
}
|
|
|
|
BOOLEAN HasPrefix(
|
|
PIP_ADDRESS Address,
|
|
PIP_ADDRESS Prefix,
|
|
UINT Length)
|
|
/*
|
|
* FUNCTION: Determines wether an address has an given prefix
|
|
* ARGUMENTS:
|
|
* Address = Pointer to address to use
|
|
* Prefix = Pointer to prefix to check for
|
|
* Length = Length of prefix
|
|
* RETURNS:
|
|
* TRUE if the address has the prefix, FALSE if not
|
|
* NOTES:
|
|
* The two addresses must be of the same type
|
|
*/
|
|
{
|
|
PUCHAR pAddress = (PUCHAR)&Address->Address;
|
|
PUCHAR pPrefix = (PUCHAR)&Prefix->Address;
|
|
|
|
TI_DbgPrint(DEBUG_ROUTER, ("Called. Address (0x%X) Prefix (0x%X) Length (%d).\n", Address, Prefix, Length));
|
|
|
|
#if 0
|
|
TI_DbgPrint(DEBUG_ROUTER, ("Address (%s) Prefix (%s).\n",
|
|
A2S(Address), A2S(Prefix)));
|
|
#endif
|
|
|
|
/* Don't report matches for empty prefixes */
|
|
if (Length == 0) {
|
|
return FALSE;
|
|
}
|
|
|
|
/* Check that initial integral bytes match */
|
|
while (Length > 8) {
|
|
if (*pAddress++ != *pPrefix++)
|
|
return FALSE;
|
|
Length -= 8;
|
|
}
|
|
|
|
/* Check any remaining bits */
|
|
if ((Length > 0) && ((*pAddress >> (8 - Length)) != (*pPrefix >> (8 - Length))))
|
|
return FALSE;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
PIP_INTERFACE GetDefaultInterface(VOID)
|
|
{
|
|
KIRQL OldIrql;
|
|
ULONG Index = 0;
|
|
ULONG IfStatus;
|
|
|
|
IF_LIST_ITER(CurrentIF);
|
|
|
|
TcpipAcquireSpinLock(&InterfaceListLock, &OldIrql);
|
|
/* DHCP hack: Always return the adapter without an IP address */
|
|
ForEachInterface(CurrentIF) {
|
|
if (CurrentIF->Context && AddrIsUnspecified(&CurrentIF->Unicast)) {
|
|
TcpipReleaseSpinLock(&InterfaceListLock, OldIrql);
|
|
|
|
GetInterfaceConnectionStatus(CurrentIF, &IfStatus);
|
|
if (IfStatus == MIB_IF_OPER_STATUS_OPERATIONAL) {
|
|
return CurrentIF;
|
|
}
|
|
|
|
TcpipAcquireSpinLock(&InterfaceListLock, &OldIrql);
|
|
}
|
|
} EndFor(CurrentIF);
|
|
|
|
/* Try to continue from the next adapter */
|
|
ForEachInterface(CurrentIF) {
|
|
if (CurrentIF->Context && (Index++ == NextDefaultAdapter)) {
|
|
TcpipReleaseSpinLock(&InterfaceListLock, OldIrql);
|
|
|
|
GetInterfaceConnectionStatus(CurrentIF, &IfStatus);
|
|
if (IfStatus == MIB_IF_OPER_STATUS_OPERATIONAL) {
|
|
NextDefaultAdapter++;
|
|
return CurrentIF;
|
|
}
|
|
|
|
TcpipAcquireSpinLock(&InterfaceListLock, &OldIrql);
|
|
}
|
|
} EndFor(CurrentIF);
|
|
|
|
/* No luck, so we'll choose the first adapter this time */
|
|
Index = 0;
|
|
ForEachInterface(CurrentIF) {
|
|
if (CurrentIF->Context) {
|
|
Index++;
|
|
TcpipReleaseSpinLock(&InterfaceListLock, OldIrql);
|
|
|
|
GetInterfaceConnectionStatus(CurrentIF, &IfStatus);
|
|
if (IfStatus == MIB_IF_OPER_STATUS_OPERATIONAL) {
|
|
NextDefaultAdapter = Index;
|
|
return CurrentIF;
|
|
}
|
|
|
|
TcpipAcquireSpinLock(&InterfaceListLock, &OldIrql);
|
|
}
|
|
} EndFor(CurrentIF);
|
|
|
|
/* Even that didn't work, so we'll just go with loopback */
|
|
NextDefaultAdapter = 0;
|
|
TcpipReleaseSpinLock(&InterfaceListLock, OldIrql);
|
|
|
|
/* There are no physical interfaces on the system
|
|
* so we must pick the loopback interface */
|
|
|
|
return Loopback;
|
|
}
|
|
|
|
PIP_INTERFACE FindOnLinkInterface(PIP_ADDRESS Address)
|
|
/*
|
|
* FUNCTION: Checks all on-link prefixes to find out if an address is on-link
|
|
* ARGUMENTS:
|
|
* Address = Pointer to address to check
|
|
* RETURNS:
|
|
* Pointer to interface if address is on-link, NULL if not
|
|
*/
|
|
{
|
|
KIRQL OldIrql;
|
|
IF_LIST_ITER(CurrentIF);
|
|
|
|
TI_DbgPrint(DEBUG_ROUTER, ("Called. Address (0x%X)\n", Address));
|
|
TI_DbgPrint(DEBUG_ROUTER, ("Address (%s)\n", A2S(Address)));
|
|
|
|
if (AddrIsUnspecified(Address))
|
|
return GetDefaultInterface();
|
|
|
|
TcpipAcquireSpinLock(&InterfaceListLock, &OldIrql);
|
|
|
|
ForEachInterface(CurrentIF) {
|
|
if (HasPrefix(Address, &CurrentIF->Unicast,
|
|
AddrCountPrefixBits(&CurrentIF->Netmask))) {
|
|
TcpipReleaseSpinLock(&InterfaceListLock, OldIrql);
|
|
return CurrentIF;
|
|
}
|
|
} EndFor(CurrentIF);
|
|
|
|
TcpipReleaseSpinLock(&InterfaceListLock, OldIrql);
|
|
|
|
return NULL;
|
|
}
|
|
|
|
VOID GetInterfaceConnectionStatus(PIP_INTERFACE Interface, PULONG Result)
|
|
{
|
|
PLAN_ADAPTER Adapter = Interface->Context;
|
|
|
|
/* Loopback has no adapter context */
|
|
if (Adapter == NULL || Adapter->State == LAN_STATE_STARTED) {
|
|
*Result = MIB_IF_OPER_STATUS_OPERATIONAL;
|
|
}
|
|
else {
|
|
*Result = MIB_IF_OPER_STATUS_DISCONNECTED;
|
|
}
|
|
}
|